Greasy Fork is available in English.

Telegram Chat Manager - Deleted Annoying Joined Chat (by AFU IT)

Auto-delete contact joined Telegram chats.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Telegram Chat Manager - Deleted Annoying Joined Chat (by AFU IT)
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Auto-delete contact joined Telegram chats.
// @author       AFU IT
// @telegram     https://t.me/afuituserscript
// @match        https://web.telegram.org/k*
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    let isRunning = false;
    let shouldStop = false;
    let isExpanded = false;
    let autoDeleteEnabled = true;

    // Wait for page to load
    function waitForElement(selector, callback) {
        const observer = new MutationObserver((mutations, obs) => {
            const element = document.querySelector(selector);
            if (element) {
                obs.disconnect();
                callback(element);
            }
        });
        observer.observe(document, {
            childList: true,
            subtree: true
        });
    }

    // Navigate to Telegram's notification settings automatically
    function openTelegramNotificationSettings() {
        logStatus('🔧 Opening Telegram notification settings...');

        // Step 1: Click hamburger menu
        const menuButton = document.querySelector('.btn-icon.rp.btn-menu-toggle') ||
                          document.querySelector('.sidebar-header .btn-icon') ||
                          document.querySelector('[data-testid="hamburger-menu"]');

        if (menuButton) {
            menuButton.click();
            logStatus('📱 Opened main menu');

            setTimeout(() => {
                // Step 2: Click Settings
                const settingsButton = Array.from(document.querySelectorAll('.btn-menu-item .i18n')).find(el =>
                    el.textContent.includes('Settings')
                ) || Array.from(document.querySelectorAll('.btn-menu-item-text')).find(el =>
                    el.textContent.includes('Settings')
                );

                if (settingsButton) {
                    settingsButton.closest('.btn-menu-item').click();
                    logStatus('⚙️ Opened Settings');

                    setTimeout(() => {
                        // Step 3: Click Notifications and Sounds
                        const notificationsButton = Array.from(document.querySelectorAll('.row-title .i18n')).find(el =>
                            el.textContent.includes('Notifications and Sounds') || el.textContent.includes('Notifications')
                        );

                        if (notificationsButton) {
                            notificationsButton.closest('.row').click();
                            logStatus('🔔 Opened Notifications settings');
                        } else {
                            logStatus('❌ Could not find Notifications option');
                        }
                    }, 800);
                } else {
                    logStatus('❌ Could not find Settings option');
                }
            }, 500);
        } else {
            logStatus('❌ Could not find menu button');
        }
    }

    function logStatus(message) {
        const statusLog = document.getElementById('status-log');
        if (statusLog) {
            const timestamp = new Date().toLocaleTimeString();
            statusLog.innerHTML += `<div style="margin-bottom: 2px; opacity: 0.9;">[${timestamp}] ${message}</div>`;
            statusLog.scrollTop = statusLog.scrollHeight;
        }
        console.log(message);
    }

    // Create compact round control panel
    function createControlPanel() {
        const panel = document.createElement('div');
        panel.id = 'telegram-manager-panel';
        panel.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            z-index: 10000;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        `;

        panel.innerHTML = `
            <!-- Round Toggle Button -->
            <div id="round-toggle" style="
                width: 56px;
                height: 56px;
                background: linear-gradient(135deg, #ff4757, #ff3742);
                border-radius: 50%;
                display: flex;
                align-items: center;
                justify-content: center;
                cursor: pointer;
                box-shadow: 0 4px 16px rgba(255, 71, 87, 0.4);
                transition: all 0.3s ease;
                backdrop-filter: blur(10px);
                border: 2px solid rgba(255, 255, 255, 0.2);
                position: relative;
            ">
                <span style="font-size: 24px;">🧹</span>
                <div id="status-indicator" style="
                    position: absolute;
                    top: -2px;
                    right: -2px;
                    width: 16px;
                    height: 16px;
                    background: #2ed573;
                    border-radius: 50%;
                    border: 2px solid white;
                    transition: all 0.3s ease;
                "></div>
            </div>

            <!-- Overlay Panel -->
            <div id="overlay-panel" style="
                position: absolute;
                top: 0;
                right: 0;
                background: rgba(30, 30, 30, 0.85);
                backdrop-filter: blur(20px);
                border: 1px solid rgba(255, 255, 255, 0.1);
                padding: 20px;
                border-radius: 16px;
                min-width: 320px;
                transform: scale(0) translateX(20px);
                transform-origin: top right;
                transition: all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
                opacity: 0;
                pointer-events: none;
                box-shadow: 0 8px 32px rgba(0, 0, 0, 0.6);
                display: flex;
                flex-direction: column;
                height: auto;
            ">
                <!-- Header -->
                <div style="font-weight: 600; margin-bottom: 16px; color: #ffffff; font-size: 16px; display: flex; align-items: center; gap: 8px;">
                    <span>🧹</span>
                    <span>Chat Cleaner</span>
                    <div id="close-overlay" style="
                        margin-left: auto;
                        width: 24px;
                        height: 24px;
                        border-radius: 50%;
                        background: rgba(255, 255, 255, 0.1);
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        cursor: pointer;
                        font-size: 14px;
                        transition: background 0.2s ease;
                    ">×</div>
                </div>

                <!-- Main Buttons -->
                <button id="delete-joined-chats" class="tg-button tg-button-danger" style="width: 100%; margin-bottom: 12px;">
                    <span class="tg-button-icon">🗑️</span>
                    <span>Clean "Joined" Chats</span>
                </button>

                <button id="stop-process" class="tg-button tg-button-warning" style="width: 100%; display: none; margin-bottom: 12px;">
                    <span class="tg-button-icon">⏹️</span>
                    <span>Stop Process</span>
                </button>

                <div id="status-log" style="
                    font-size: 11px;
                    max-height: 120px;
                    overflow-y: auto;
                    background: rgba(0, 0, 0, 0.3);
                    padding: 10px;
                    border-radius: 8px;
                    color: #cccccc;
                    line-height: 1.4;
                    border: 1px solid rgba(255, 255, 255, 0.1);
                    margin-bottom: 16px;
                ">
                    Ready to clean chats silently...
                </div>

                <!-- Bottom Settings Button -->
                <div id="bottom-container" style="
                    margin-top: auto;
                    background: rgba(255, 255, 255, 0.05);
                    border: 1px solid rgba(255, 255, 255, 0.1);
                    border-radius: 12px;
                    padding: 16px;
                ">
                    <!-- Settings Button -->
                    <button id="open-settings-btn" style="
                        background: rgba(139, 92, 246, 0.2);
                        border: 1px solid #8b5cf6;
                        color: #8b5cf6;
                        padding: 12px;
                        border-radius: 8px;
                        font-size: 13px;
                        cursor: pointer;
                        transition: all 0.2s ease;
                        width: 100%;
                        font-weight: 500;
                    ">
                        ⚙️ Open Telegram Settings
                    </button>
                </div>
            </div>
        `;

        // Add styles
        const style = document.createElement('style');
        style.textContent = `
            .tg-button {
                background: #0088cc;
                color: white;
                border: none;
                border-radius: 8px;
                padding: 10px 14px;
                font-size: 13px;
                font-weight: 500;
                cursor: pointer;
                display: flex;
                align-items: center;
                justify-content: center;
                gap: 6px;
                transition: all 0.2s ease;
                font-family: inherit;
                position: relative;
                overflow: hidden;
                box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
            }

            .tg-button:hover {
                transform: translateY(-1px);
                box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
            }

            .tg-button:active {
                transform: translateY(0);
            }

            .tg-button-danger {
                background: linear-gradient(135deg, #ff4757, #ff3742);
            }

            .tg-button-danger:hover {
                background: linear-gradient(135deg, #ff3742, #ff2f3a);
                box-shadow: 0 4px 16px rgba(255, 71, 87, 0.4);
            }

            .tg-button-danger:disabled {
                background: #666;
                cursor: not-allowed;
                transform: none;
                box-shadow: none;
            }

            .tg-button-warning {
                background: linear-gradient(135deg, #ffa502, #ff9500);
            }

            .tg-button-warning:hover {
                background: linear-gradient(135deg, #ff9500, #ff8c00);
                box-shadow: 0 4px 16px rgba(255, 165, 2, 0.4);
            }

            .tg-button-icon {
                font-size: 14px;
            }

            #round-toggle:hover {
                transform: scale(1.1);
                box-shadow: 0 6px 20px rgba(255, 71, 87, 0.6);
            }

            #round-toggle:active {
                transform: scale(0.95);
            }

            #close-overlay:hover {
                background: rgba(255, 255, 255, 0.2) !important;
            }

            #open-settings-btn:hover {
                background: rgba(139, 92, 246, 0.3) !important;
                transform: translateY(-1px);
            }

            #status-log::-webkit-scrollbar {
                width: 4px;
            }

            #status-log::-webkit-scrollbar-track {
                background: rgba(255, 255, 255, 0.1);
                border-radius: 2px;
            }

            #status-log::-webkit-scrollbar-thumb {
                background: rgba(255, 255, 255, 0.3);
                border-radius: 2px;
            }

            /* Hide all UI elements during silent operation */
            .silent-mode .btn-menu.contextmenu,
            .silent-mode .popup-delete-chat,
            .silent-mode .popup {
                display: none !important;
                visibility: hidden !important;
                opacity: 0 !important;
                pointer-events: none !important;
            }
        `;
        document.head.appendChild(style);

        document.body.appendChild(panel);

        // Add event listeners for toggle functionality
        setupToggleListeners();

        return panel;
    }

    function setupToggleListeners() {
        const roundToggle = document.getElementById('round-toggle');
        const overlayPanel = document.getElementById('overlay-panel');
        const closeOverlay = document.getElementById('close-overlay');
        const openSettingsBtn = document.getElementById('open-settings-btn');

        roundToggle.addEventListener('click', toggleOverlay);
        closeOverlay.addEventListener('click', hideOverlay);
        openSettingsBtn.addEventListener('click', openTelegramNotificationSettings);

        // Close overlay when clicking outside
        document.addEventListener('click', (e) => {
            if (isExpanded && !document.getElementById('telegram-manager-panel').contains(e.target)) {
                hideOverlay();
            }
        });
    }

    function toggleOverlay() {
        if (isExpanded) {
            hideOverlay();
        } else {
            showOverlay();
        }
    }

    function showOverlay() {
        const overlayPanel = document.getElementById('overlay-panel');
        const roundToggle = document.getElementById('round-toggle');

        isExpanded = true;
        overlayPanel.style.transform = 'scale(1) translateX(0)';
        overlayPanel.style.opacity = '1';
        overlayPanel.style.pointerEvents = 'auto';

        roundToggle.style.opacity = '0.3';
    }

    function hideOverlay() {
        const overlayPanel = document.getElementById('overlay-panel');
        const roundToggle = document.getElementById('round-toggle');

        isExpanded = false;
        overlayPanel.style.transform = 'scale(0) translateX(20px)';
        overlayPanel.style.opacity = '0';
        overlayPanel.style.pointerEvents = 'none';

        roundToggle.style.opacity = '1';
    }

    // Hide all UI elements (context menus, popups, etc.)
    function hideAllUIElements() {
        const contextMenus = document.querySelectorAll('.btn-menu.contextmenu, .contextmenu');
        contextMenus.forEach(menu => {
            menu.style.display = 'none';
            menu.style.visibility = 'hidden';
            menu.style.opacity = '0';
            menu.style.pointerEvents = 'none';
        });

        const popups = document.querySelectorAll('.popup-delete-chat, .popup');
        popups.forEach(popup => {
            popup.style.display = 'none';
            popup.style.visibility = 'hidden';
            popup.style.opacity = '0';
            popup.style.pointerEvents = 'none';
        });
    }

    // Monitor and hide all UI elements immediately
    function startSilentUIHandler() {
        document.body.classList.add('silent-mode');

        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                mutation.addedNodes.forEach((node) => {
                    if (node.nodeType === 1) {
                        if (node.classList && (node.classList.contains('btn-menu') || node.classList.contains('contextmenu'))) {
                            hideUIElement(node);
                            handleContextMenuSilently(node);
                        }
                        else if (node.classList && node.classList.contains('popup-delete-chat')) {
                            hideUIElement(node);
                            handlePopupSilently(node);
                        }
                        else if (node.querySelector) {
                            const contextMenu = node.querySelector('.btn-menu.contextmenu, .contextmenu');
                            if (contextMenu) {
                                hideUIElement(contextMenu);
                                handleContextMenuSilently(contextMenu);
                            }

                            const popup = node.querySelector('.popup-delete-chat');
                            if (popup) {
                                hideUIElement(popup);
                                handlePopupSilently(popup);
                            }
                        }
                    }
                });
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        setInterval(() => {
            hideAllUIElements();

            const contextMenu = document.querySelector('.btn-menu.contextmenu.active');
            if (contextMenu) {
                handleContextMenuSilently(contextMenu);
            }

            const popup = document.querySelector('.popup-delete-chat.active');
            if (popup) {
                handlePopupSilently(popup);
            }
        }, 50);
    }

    function hideUIElement(element) {
        if (element && element.style) {
            element.style.display = 'none';
            element.style.visibility = 'hidden';
            element.style.opacity = '0';
            element.style.pointerEvents = 'none';
            element.style.zIndex = '-9999';
        }
    }

    function handleContextMenuSilently(contextMenu) {
        if (!contextMenu) return;

        hideUIElement(contextMenu);

        setTimeout(() => {
            const deleteOption = contextMenu.querySelector('.btn-menu-item.danger');
            if (deleteOption) {
                deleteOption.click();
                logStatus('🔇 Context menu handled silently');
            }
        }, 10);
    }

    function handlePopupSilently(popup) {
        if (!popup) return;

        hideUIElement(popup);

        setTimeout(() => {
            const checkbox = popup.querySelector('.checkbox-field-input');
            if (checkbox && !checkbox.checked) {
                checkbox.checked = true;
                checkbox.dispatchEvent(new Event('change', { bubbles: true }));
            }

            const deleteButton = popup.querySelector('.popup-button.btn.danger');
            if (deleteButton) {
                deleteButton.click();
                logStatus('✅ Chat deleted silently');
            }
        }, 10);
    }

    // Enhanced silent delete function
    async function silentDeleteChat(chatElement) {
        return new Promise((resolve) => {
            const peerId = chatElement.dataset.peerId;

            if (window.appImManager && window.appImManager.deleteDialog) {
                try {
                    window.appImManager.deleteDialog(peerId, true, true);
                    logStatus(`🔇 API deleted chat ${peerId}`);
                    resolve(true);
                    return;
                } catch (e) {
                    // Fallback to UI method
                }
            }

            const rect = chatElement.getBoundingClientRect();

            chatElement.dispatchEvent(new MouseEvent('contextmenu', {
                bubbles: true,
                cancelable: true,
                view: window,
                clientX: rect.left + rect.width / 2,
                clientY: rect.top + rect.height / 2
            }));

            setTimeout(() => resolve(true), 200);
        });
    }

    // Main deletion function
    async function deleteJoinedTelegramChats() {
        if (isRunning) {
            logStatus('⚠️ Process already running');
            return;
        }

        isRunning = true;
        shouldStop = false;

        const deleteBtn = document.getElementById('delete-joined-chats');
        const stopBtn = document.getElementById('stop-process');
        const roundToggle = document.getElementById('round-toggle');

        deleteBtn.style.display = 'none';
        stopBtn.style.display = 'block';

        // Change round button to indicate running state
        roundToggle.innerHTML = '<span style="font-size: 24px;">⚡</span>';
        roundToggle.style.background = 'linear-gradient(135deg, #ffa502, #ff9500)';

        startSilentUIHandler();

        const chatItems = document.querySelectorAll('.chatlist-chat');
        let deletedCount = 0;
        let foundCount = 0;

        logStatus(`🔍 Scanning ${chatItems.length} chats for "joined Telegram" messages...`);

        for (let i = 0; i < chatItems.length && !shouldStop; i++) {
            const chat = chatItems[i];
            const joinedSpans = chat.querySelectorAll('span.i18n');
            let hasJoinedMessage = false;

            joinedSpans.forEach(span => {
                if (span.textContent.includes('joined Telegram')) {
                    hasJoinedMessage = true;
                    const peerName = span.querySelector('.peer-title')?.textContent || 'Unknown';
                    logStatus(`📱 Found: ${peerName} joined Telegram`);
                }
            });

            if (hasJoinedMessage && !shouldStop) {
                foundCount++;
                logStatus(`🗑️ Silently deleting chat ${foundCount}...`);

                const success = await silentDeleteChat(chat);
                if (success) {
                    deletedCount++;
                }

                await new Promise(resolve => setTimeout(resolve, 150));
            }
        }

        // Reset UI
        isRunning = false;
        document.body.classList.remove('silent-mode');
        deleteBtn.style.display = 'block';
        stopBtn.style.display = 'none';

        // Reset round button
        roundToggle.innerHTML = '<span style="font-size: 24px;">🧹</span>';
        roundToggle.style.background = 'linear-gradient(135deg, #ff4757, #ff3742)';

        if (shouldStop) {
            logStatus(`⏹️ Process stopped by user. Deleted ${deletedCount} of ${foundCount} found chats`);
        } else {
            logStatus(`✅ Process complete! Found ${foundCount} "joined Telegram" chats, successfully deleted ${deletedCount}`);
        }
    }

    function stopProcess() {
        shouldStop = true;
        document.body.classList.remove('silent-mode');
        logStatus('🛑 Stopping process...');
    }

    // Initialize the script
    function init() {
        waitForElement('.chatlist-container, #column-left', () => {
            const panel = createControlPanel();

            document.getElementById('delete-joined-chats').addEventListener('click', deleteJoinedTelegramChats);
            document.getElementById('stop-process').addEventListener('click', stopProcess);

            logStatus('🚀 Simplified Chat Cleaner loaded');
            logStatus('⚙️ Use "Open Telegram Settings" to access notifications');
        });
    }

    // Start the script
    init();
})();