您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
This script automatically finds messages sent by bots in Tango.me chats and lets you delete them in bulk. It adds an easy-to-use button to the Tango chat interface. Clicking the button shows a list of bot-related chats, which you can delete with a single confirmation. A progress indicator appears during deletion, and you’ll be notified about how many chats were deleted or failed to delete. The script offers a simple and user-friendly experience for quick chat cleanup.
// ==UserScript== // @name Tango Delete AI Bot Messages // @name:tr Tango Bot Mesajlarını Sil // @namespace https://tomyris.dev -// @author [email protected] // @icon https://tango.me/favicons/favicon-48x48.png // @version 1.0 // @description This script automatically finds messages sent by bots in Tango.me chats and lets you delete them in bulk. It adds an easy-to-use button to the Tango chat interface. Clicking the button shows a list of bot-related chats, which you can delete with a single confirmation. A progress indicator appears during deletion, and you’ll be notified about how many chats were deleted or failed to delete. The script offers a simple and user-friendly experience for quick chat cleanup. // @description:tr Bu script, Tango.me platformundaki sohbetlerde botlar tarafından gönderilen mesajları otomatik olarak bulur ve topluca silmenizi sağlar. Tango’nun sohbet ekranına kullanımı kolay bir buton ekler. Butona tıkladığınızda, bot mesajı içeren sohbetler listelenir ve onayınızla silinir. Silme işlemi sırasında bir ilerleme ekranı gösterilir; işlem bittiğinde kaç sohbetin silindiği veya silinemediği bildirilir. Kullanıcı dostu bir arayüzle, işlemleri hızlı ve kolay bir şekilde yapabilirsiniz. // @match https://tango.me/* // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; const BASE_URL = "https://gateway.tango.me"; const targetDiv = "#root > div._3vw1h > div > header > nav"; // SweetAlert2 CDN const script = document.createElement('script'); script.src = 'https://cdn.jsdelivr.net/npm/sweetalert2@11'; document.head.appendChild(script); // --- Butonu ekle --- function addButton() { if (document.querySelector("#deleteBotMessagesBtn")) return; // class="ixxi2" olan aside elementini bul const targetElement = document.querySelector(targetDiv); if (!targetElement) { console.error("Hedef element (aside.ixxi2) bulunamadı!"); return; } const btn = document.createElement("button"); btn.id = "deleteBotMessagesBtn"; btn.setAttribute("data-testid", "delete-bot-messages-btn"); btn.setAttribute("class","J6Ncy"); btn.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="none" viewBox="0 0 32 32"> <path fill="#fff" fill-rule="evenodd" d="M16 8a4 4 0 0 0-4 4v2h-2a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8a2 2 0 0 0-2-2h-2v-2a4 4 0 0 0-4-4zm-2 2a2 2 0 1 1 4 0v2h-4v-2zm-2 6h8v8h-8v-8zm4 2a1 1 0 1 0 0 2 1 1 0 0 0 0-2z" clip-rule="evenodd"></path> </svg>Delete Bot ! `; btn.title = "Bot Mesajlarını Sil"; // Tooltip için btn.onclick = showDeleteConfirmation; // Butonu aside elementinin üstüne ekle targetElement.append(btn); } // --- AI_CHAT_BOT conversation_id’lerini ve isimleri al --- async function getBotConversationIds() { const resp = await fetch(`${BASE_URL}/proxycador/api/public/v1/chats/v1/conversations/get`, { method: "POST", credentials: "include", headers: { "accept": "application/json", "accept-language": "tr,en;q=0.9,en-GB;q=0.8,en-US;q=0.7", "content-type": "application/json", "origin": "https://tango.me", "referer": "https://tango.me/", "sec-ch-ua": '"Not;A=Brand";v="99", "Microsoft Edge";v="139", "Chromium";v="139"', "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": '"Windows"', "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-site", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0", }, body: JSON.stringify({ direction: "FORWARD", last_update_request_timestamp: 0, limit_conversations: 100, limit_messages_per_conversation: 1, include_group_members: true, include_messages: true, include_group_info: true, include_account_info: true }) }); const data = await resp.json(); const conversations = data.conversations || []; return conversations .filter(conv => conv.messages && conv.messages.some(msg => msg.message_source === "AI_CHAT_BOT")) .map(conv => ({ id: conv.conversation.conversation_id, name: conv.conversation.account_info ? conv.conversation.account_info.first_name : "Bilinmeyen Kullanıcı" })); } // --- Silme işlemi --- async function deleteConversations(ids) { if (!ids.length) { Swal.fire({ icon: 'info', title: 'Bilgi', text: 'Silinecek bot mesajı bulunamadı ✅', confirmButtonText: 'Tamam' }); return; } // Yükleme ekranını göster Swal.fire({ title: 'Sohbetler Siliniyor...', text: 'Lütfen bekleyin, bot sohbetleri siliniyor.', allowOutsideClick: false, allowEscapeKey: false, showConfirmButton: false, didOpen: () => { Swal.showLoading(); } }); let successCount = 0; let failCount = 0; for (const id of ids) { try { const resp = await fetch(`${BASE_URL}/tc2/v2/conversations/delete`, { method: "POST", credentials: "include", headers: { "accept": "application/json", "content-type": "application/json" }, body: JSON.stringify({ peer_ids: [id] }) }); if (resp.ok) { successCount++; console.log(`Sohbet ${id} silindi.`); } else { failCount++; console.error(`Sohbet ${id} silinirken hata oluştu.`); } } catch (err) { failCount++; console.error(`Sohbet ${id} silinirken hata:`, err); } } // Yükleme ekranını kapat Swal.close(); if (successCount > 0) { alert(`Toplam ${successCount} bot sohbeti silindi 🚀${failCount > 0 ? `\n${failCount} silme işlemi başarısız oldu ❌` : ''}`); } else { alert("Hiçbir bot sohbeti silinemedi ❌"); } } // --- Silme onay modalı --- async function showDeleteConfirmation() { try { const conversations = await getBotConversationIds(); if (conversations.length === 0) { Swal.fire({ icon: 'info', title: 'Bilgi', text: 'Silinecek bot mesajı bulunamadı ✅', confirmButtonText: 'Tamam' }); return; } // Modal içeriği için HTML oluştur const content = ` <div style="text-align: left; max-height: 300px; overflow-y: auto;"> <h3>Silinecek Bot Sohbetleri:</h3> <ul style="list-style-type: none; padding: 0;"> ${conversations.map(conv => ` <li> <strong>${conv.name}</strong> (ID: <a href="https://tango.me/chat/${conv.id}" target="_blank" style="color: #1e90ff; text-decoration: underline;">${conv.id}</a>) </li> `).join('')} </ul> </div> `; Swal.fire({ title: 'Bot Mesajlarını Sil', html: content, icon: 'warning', showCancelButton: true, confirmButtonText: 'Sil', cancelButtonText: 'İptal', confirmButtonColor: '#e63946', cancelButtonColor: '#3085d6' }).then(async (result) => { if (result.isConfirmed) { const ids = conversations.map(conv => conv.id); await deleteConversations(ids); } }); } catch (err) { console.error("Hata:", err); Swal.fire({ icon: 'error', title: 'Hata', text: 'Bir hata oluştu ❌', confirmButtonText: 'Tamam' }); } } // --- Sayfa tamamen yüklendiğinde ve aside.ixxi2 mevcut olduğunda butonu ekle --- function waitForPageLoadAndElement() { // MutationObserver ile aside.ixxi2 elementini izle const observer = new MutationObserver((mutations, obs) => { const targetElement = document.querySelector(targetDiv); if (targetElement) { addButton(); obs.disconnect(); // Element bulunduğunda gözlemciyi durdur } }); observer.observe(document.body, { childList: true, subtree: true }); // Ekstra güvenlik için window.onload ile tüm kaynakların yüklendiğinden emin ol window.onload = () => { const targetElement = document.querySelector(targetDiv); if (targetElement) { addButton(); observer.disconnect(); } }; // Belirli bir süre sonra hala element bulunmazsa hata yaz setTimeout(() => { if (!document.querySelector(targetDiv)) { console.error("Timeout: element bulunamadı!"); observer.disconnect(); } }, 10000); // 10 saniye timeout } // Sayfa yüklenmesini bekle ve gözlemciyi başlat if (document.readyState === 'complete') { waitForPageLoadAndElement(); } else { window.addEventListener('load', waitForPageLoadAndElement); } })();