Greasy Fork

Greasy Fork is available in English.

Facebook Activity Auto Deleter (2025) - Improved

Automatically deletes Facebook activity log entries, confirms popups, and scrolls. Includes GUI toggle. Starts paused. Permanently skips problematic items.

当前为 2025-04-06 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Facebook Activity Auto Deleter (2025) - Improved
// @namespace    http://greasyfork.icu/en/users/1454546-shawnfrost13
// @version      5
// @description  Automatically deletes Facebook activity log entries, confirms popups, and scrolls. Includes GUI toggle. Starts paused. Permanently skips problematic items.
// @author       shawnfrost13 (improved by Claude)
// @license      MIT
// @match        https://www.facebook.com/*/allactivity*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
    'use strict';

    console.log("🔥 FB Auto Deleter 4.03 loaded");

    let isRunning = false;
    let deletionCount = 0;
    let failureCount = 0;
    let skipNext = false;
    // Track problematic items to permanently skip them
    const problemItems = new Set();

    function getRandomDelay(min = 1100, max = 2100) {
        return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    function logStatus(text) {
        let el = document.getElementById('fb-auto-delete-status');
        if (!el) {
            el = document.createElement('div');
            el.id = 'fb-auto-delete-status';
            el.style.position = 'fixed';
            el.style.bottom = '50px';
            el.style.right = '10px';
            el.style.background = '#111';
            el.style.color = 'lime';
            el.style.padding = '10px';
            el.style.borderRadius = '10px';
            el.style.fontFamily = 'monospace';
            el.style.zIndex = '9999';
            document.body.appendChild(el);
        }
        el.textContent = `🧹 ${text}`;
    }

    function createToggleButton() {
        const toggle = document.createElement('button');
        toggle.textContent = '▶️ Start Deleter';
        toggle.style.position = 'fixed';
        toggle.style.bottom = '95px';
        toggle.style.right = '10px';
        toggle.style.zIndex = '10000';
        toggle.style.padding = '8px 12px';
        toggle.style.background = '#222';
        toggle.style.color = '#fff';
        toggle.style.border = '1px solid lime';
        toggle.style.borderRadius = '8px';
        toggle.style.cursor = 'pointer';
        toggle.style.fontFamily = 'monospace';
        toggle.addEventListener('click', () => {
            isRunning = !isRunning;
            toggle.textContent = isRunning ? '⏸️ Pause Deleter' : '▶️ Start Deleter';
            if (isRunning) deleteNext();
            logStatus(isRunning ? 'Script running...' : 'Script paused');
        });
        document.body.appendChild(toggle);
        
        // Add statistics display
        const stats = document.createElement('div');
        stats.id = 'fb-auto-delete-stats';
        stats.style.position = 'fixed';
        stats.style.bottom = '140px';
        stats.style.right = '10px';
        stats.style.background = '#111';
        stats.style.color = 'white';
        stats.style.padding = '8px';
        stats.style.borderRadius = '8px';
        stats.style.fontFamily = 'monospace';
        stats.style.zIndex = '10000';
        stats.style.fontSize = '12px';
        stats.style.textAlign = 'right';
        document.body.appendChild(stats);
        
        // Update stats every second
        setInterval(() => {
            if (stats) {
                stats.innerHTML = `
                <div>Items Deleted: <span style="color:lime">${deletionCount}</span></div>
                <div>Problem Items: <span style="color:orange">${problemItems.size}</span></div>
                `;
            }
        }, 1000);
    }

    function findMenuButtons() {
        return Array.from(document.querySelectorAll('[role="button"]')).filter(btn => {
            const label = btn.getAttribute('aria-label') || '';
            return (
                btn.offsetParent !== null &&
                (label.toLowerCase().includes("activity options") ||
                    label.toLowerCase().includes("action options"))
            );
        });
    }

    function getItemSignature(element) {
        // Create a unique signature for an item based on its content and position
        if (!element) return null;
        
        // Find the parent container of the menu button
        let container = element.closest('[data-visualcompletion="ignore-dynamic"]');
        if (!container) {
            container = element.parentElement;
            if (!container) return null;
        }
        
        // Extract text content and position info to create a signature
        const textContent = container.textContent.slice(0, 100).replace(/\s+/g, ' ').trim();
        const position = Array.from(container.parentElement.children).indexOf(container);
        
        return `${textContent}-${position}`;
    }

    function closeAllErrorPopups() {
        // Close "Something went wrong" popups
        const popups = Array.from(document.querySelectorAll('[role="alert"]'));
        let found = false;
        
        popups.forEach(popup => {
            if (popup.innerText.includes("Something went wrong")) {
                const closeBtn = popup.querySelector('[aria-label="Close"], [aria-label="Dismiss"]');
                if (closeBtn) {
                    closeBtn.click();
                    found = true;
                    console.log("🚫 Closed error popup");
                }
            }
        });
        
        // Also try to find the bottom notification popups
        const bottomPopups = Array.from(document.querySelectorAll('[role="status"]'));
        bottomPopups.forEach(popup => {
            if (popup.innerText.includes("Something went wrong") || popup.innerText.includes("try again")) {
                const closeBtn = popup.querySelector('div[role="button"]');
                if (closeBtn) {
                    closeBtn.click();
                    found = true;
                    console.log("🚫 Closed bottom notification popup");
                }
            }
        });
        
        return found;
    }

    function autoConfirmPopups() {
        const dialogs = Array.from(document.querySelectorAll('[role="dialog"], [role="alertdialog"]'));
        dialogs.forEach(dialog => {
            const deleteBtn = Array.from(dialog.querySelectorAll('div[role="button"], button'))
                .find(btn =>
                    btn.offsetParent !== null &&
                    btn.innerText.trim().toLowerCase() === "delete"
                );
            if (deleteBtn) {
                console.log("✅ Auto-confirming DELETE dialog");
                deleteBtn.click();
                logStatus("Auto-confirmed delete popup");
            }
        });
    }

    function autoScrollAndRetry() {
        console.log("🔄 Scrolling to load more activity...");
        logStatus("Scrolling to load more items...");
        window.scrollTo({
            top: document.body.scrollHeight,
            behavior: 'smooth'
        });
        setTimeout(() => deleteNext(), 2500);
    }

    function deleteNext() {
        if (!isRunning) return;

        // Clean up any lingering UI elements
        closeAllErrorPopups();
        autoConfirmPopups();

        const buttons = findMenuButtons();

        if (buttons.length === 0) {
            logStatus('No deletable buttons found. Trying to scroll...');
            autoScrollAndRetry();
            return;
        }

        if (skipNext) {
            console.log("⏭️ Skipping next item due to earlier failure.");
            skipNext = false;
            if (buttons.length > 0) {
                const itemToSkip = buttons[0];
                const signature = getItemSignature(itemToSkip);
                if (signature) {
                    problemItems.add(signature);
                    console.log(`🔒 Permanently marking item as problematic: ${signature.substring(0, 30)}...`);
                }
                buttons.shift(); // remove the first one
            }
        }

        // Filter out any buttons that belong to already identified problem items
        const filteredButtons = buttons.filter(btn => {
            const signature = getItemSignature(btn);
            return !problemItems.has(signature);
        });

        const btn = filteredButtons[0];
        if (!btn) {
            // If no valid buttons after filtering, scroll and retry
            autoScrollAndRetry();
            return;
        }

        btn.scrollIntoView({ behavior: 'smooth', block: 'center' });
        btn.click();
        logStatus(`Opened menu for item #${deletionCount + 1}`);
        console.log(`📂 Opened menu for item #${deletionCount + 1}`);

        setTimeout(() => {
            const menuItems = Array.from(document.querySelectorAll('[role="menuitem"]'));
            const deleteOption = menuItems.find(el =>
                el.innerText.includes("Move to Recycle bin") ||
                el.innerText.includes("Delete") ||
                el.innerText.includes("Remove") ||
                el.innerText.includes("Unlike") ||
                el.innerText.includes("Remove reaction") ||
                el.innerText.includes("Remove tag")
            );

            if (deleteOption) {
                deleteOption.click();
                logStatus(`Clicked delete on item #${deletionCount + 1}`);
                console.log(`🗑️ Attempted delete on item #${deletionCount + 1}`);

                setTimeout(() => {
                    // First close any error popups that might have appeared
                    const failed = closeAllErrorPopups();
                    
                    if (failed) {
                        failureCount++;
                        console.log("❌ Deletion failed. Failure count: " + failureCount);
                        logStatus("Deletion failed, retrying...");
                        if (failureCount >= 2) {
                            skipNext = true;
                            failureCount = 0;
                        }
                        setTimeout(deleteNext, getRandomDelay());
                    } else {
                        failureCount = 0;
                        deletionCount++;
                        logStatus(`✅ Deleted item #${deletionCount}`);
                        setTimeout(deleteNext, getRandomDelay());
                    }
                }, 1800);
            } else {
                // If no delete option, mark the item as problematic
                const signature = getItemSignature(btn);
                if (signature) {
                    problemItems.add(signature);
                    console.log(`🔒 Marking item as problematic: ${signature.substring(0, 30)}...`);
                }
                
                logStatus(`No delete option found. Skipping...`);
                console.log("⚠️ No delete option found.");
                
                // Click somewhere else to close the menu
                document.body.click();
                
                setTimeout(deleteNext, getRandomDelay());
            }
        }, 1300);
    }

    // Initial setup
    createToggleButton();
    setInterval(autoConfirmPopups, 1000); // scan for popups every second
    setInterval(closeAllErrorPopups, 1500); // scan for error popups more frequently
})();