Untitled

 avatar
unknown
plain_text
a month ago
6.6 kB
4
Indexable
(function() {
    // --------------------- State Tracking ---------------------
    let isRunning = true;
    const processedMessages = new Set();

    // --------------------- Overlay Implementation ---------------------
    function createOverlay() {
        const overlay = document.createElement('div');
        overlay.id = 'automation-overlay';
        Object.assign(overlay.style, {
            position: 'fixed', top: '0', left: '0', width: '100%', height: '100%',
            backgroundColor: 'rgba(255, 255, 255, 0.8)', display: 'flex',
            flexDirection: 'column', justifyContent: 'center', alignItems: 'center',
            zIndex: '9999', cursor: 'not-allowed'
        });

        const message = document.createElement('div');
        message.innerText = 'Unsending messages - Keep this window visible - Details in DevConsole!';
        Object.assign(message.style, { fontSize: '24px', marginBottom: '20px', textAlign: 'center', color: '#333' });

        const killButton = document.createElement('button');
        killButton.innerText = 'Stop script?';
        Object.assign(killButton.style, {
            padding: '10px 20px', fontSize: '16px', cursor: 'pointer', border: 'none',
            borderRadius: '5px', backgroundColor: '#ff4d4d', color: '#fff'
        });

        killButton.addEventListener('click', () => {
            console.warn('Script terminated by user.');
            isRunning = false;
            overlay.remove();
        });

        overlay.append(message, killButton);
        document.body.appendChild(overlay);
    }

    createOverlay();

    // --------------------- Utility Functions ---------------------
    const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

    function simulateClick(element) {
        if (element) {
            element.dispatchEvent(new MouseEvent('click', { view: window, bubbles: true, cancelable: true }));
        }
    }

    function isUserMessage(messageElement) {
        return [/You sent/i, /You replied/i].some(pattern => pattern.test(messageElement.innerText));
    }

    function findScrollableContainer() {
        return document.querySelector('.x1n2onr6 .x78zum5.xdt5ytf[data-scope="messages_table"][role="gridcell"]')?.parentElement;
    }

    function isInViewport(element) {
        const rect = element.getBoundingClientRect();
        return rect.top >= 0 && rect.bottom <= window.innerHeight;
    }

    function checkViewProfile() {
        return [...document.querySelectorAll('a')].some(el => el.textContent.trim() === 'View profile' && isInViewport(el));
    }

    async function waitForElementToDisappear(element, timeoutMs = 60000) {
        const start = Date.now();
        while (document.contains(element) && isRunning) {
            if (Date.now() - start > timeoutMs) throw new Error('Element did not disappear in time.');
            await delay(1000);
        }
    }

    async function waitForMoreButton(messageElement) {
        let elapsed = 0, timeout = 10000;
        while (elapsed < timeout && isRunning) {
            const moreButton = messageElement.querySelector(`[aria-label="More"]`);
            if (moreButton) {
                simulateClick(moreButton);
                await delay(1000);
                return true;
            }
            elapsed += 100;
            await delay(100);
        }
        console.warn(`"More" button not found in ${timeout / 1000} seconds.`);
        return false;
    }

    async function findAndClickUnsendSvg() {
        let elapsed = 0, timeout = 10000;
        while (elapsed < timeout && isRunning) {
            const unsendButton = [...document.querySelectorAll('svg[aria-label="Unsend"]')]
                .find(svg => svg.offsetWidth || svg.offsetHeight || svg.getClientRects().length);
            
            if (unsendButton) {
                simulateClick(unsendButton.closest('button') || unsendButton);
                await delay(1000);
                return true;
            }
            elapsed += 100;
            await delay(100);
        }
        console.warn('Unsend button not found.');
        return false;
    }

    function clickConfirmUnsend() {
        const checkInterval = setInterval(() => {
            if (!isRunning) return clearInterval(checkInterval);

            const confirmButton = [...document.querySelectorAll('*')].find(el =>
                el.textContent.includes('Unsend') && el.tabIndex === 0);

            if (confirmButton) {
                simulateClick(confirmButton);
                clearInterval(checkInterval);
            }
        }, 100);
    }

    async function scrollByDistance(container, distance) {
        if (!container) throw new Error('Scrollable container not found.');
        container.scrollBy({ top: distance, behavior: 'smooth' });
        await delay(1000);
    }

    // --------------------- Main Processing Function ---------------------
    async function processMessages() {
        let scrollableContainer = findScrollableContainer();
        if (!scrollableContainer) return console.log('Chat container not found. Exiting script.');

        while (isRunning) {
            console.log('--- New Scroll Cycle ---');

            const messages = [...document.querySelectorAll('.x1n2onr6 .x78zum5.xdt5ytf[data-scope="messages_table"][role="gridcell"]')].reverse();
            for (let msg of messages) {
                if (!isRunning || processedMessages.has(msg) || !isUserMessage(msg)) continue;

                processedMessages.add(msg);
                msg.scrollIntoView({ behavior: 'smooth', block: 'center' });
                await delay(1000);

                if (await waitForMoreButton(msg) && (await findAndClickUnsendSvg())) {
                    clickConfirmUnsend();
                    try {
                        await waitForElementToDisappear(msg);
                    } catch {
                        console.warn('Rate limit detected. Waiting 3 minutes.');
                        await delay(180000);
                    }
                } else {
                    console.warn('Retrying after scrolling down.');
                    await scrollByDistance(scrollableContainer, 1000);
                }
            }

            if (checkViewProfile()) break;

            try {
                await scrollByDistance(scrollableContainer, -100);
            } catch (error) {
                console.error(error);
                break;
            }
        }

        console.log('Script terminated.');
    }

    processMessages();
})();
Editor is loading...
Leave a Comment