LonKeyDotae / BREAK OUT

// ==UserScript==
// @name         BREAK OUT
// @namespace    http://tampermonkey.net/
// @version      2025-10-16-working
// @description  Configure and automate Google Takeout form interactions with mobile debugging
// @author       You
// @match        https://takeout.google.com/manage
// @icon         https://www.google.com/s2/favicons?sz=64&domain=google.com
// @grant        unsafeWindow
// @grant        GM.notification
// @grant        GM.registerMenuCommand
// @license MIT
// ==/UserScript==

(function() {
    'use strict';
    
    // CONFIGURATION - Edit these elements to match what you want to click
    const elementsToClick = [
        {
            "element": "<div class=\"VfPpkd-Jh9lGc\"></div>",
            "delay": 5,
            "description": "Main button"
        },
        {
            "element": "<button class=\"VfPpkd-LgbsSe\"></button>",
            "delay": 3,
            "description": "Confirmation button"
        }
    ];
    
    const TIMEOUT_SECONDS = 15;
    
    // Banner management
    let currentBanner = null;
    let debugLog = [];
    
    function logDebug(message) {
        debugLog.push(message);
        console.log(message);
    }
    
    function createDebugBanner(message, color = '#00ff00', showLog = false) {
        if (currentBanner) {
            currentBanner.remove();
        }
        const banner = document.createElement('div');
        banner.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            background: black;
            color: ${color};
            padding: 20px;
            font-size: 18px;
            font-weight: bold;
            z-index: 999999;
            text-align: center;
            font-family: monospace;
            border-bottom: 3px solid ${color};
            max-height: 200px;
            overflow-y: auto;
        `;
        
        if (showLog && debugLog.length > 0) {
            const logText = debugLog.slice(-5).join('\n');
            banner.innerHTML = `<div style="font-size: 14px; margin-bottom: 10px;">${logText.replace(/\n/g, '<br>')}</div><div>${message}</div>`;
        } else {
            banner.textContent = message;
        }
        
        document.body.appendChild(banner);
        currentBanner = banner;
        return banner;
    }
    
    function updateBanner(message, color) {
        if (currentBanner) {
            currentBanner.textContent = message;
            currentBanner.style.color = color;
            currentBanner.style.borderBottomColor = color;
        } else {
            createDebugBanner(message, color);
        }
    }
    
    // Show initial load message
    createDebugBanner('🚀 BREAK OUT LOADED - Ready to automate clicks', '#00ff00');
    
    console.log('=================================');
    console.log('BREAK OUT SCRIPT LOADED');
    console.log('=================================');
    
    // Function to extract selector from HTML string
    function extractSelector(htmlString) {
        const classMatch = htmlString.match(/class=["']([^"']+)["']/);
        if (classMatch) {
            const classes = classMatch[1].split(' ').map(c => `.${c}`).join('');
            return classes;
        }
        
        const tagMatch = htmlString.match(/<(\w+)/);
        return tagMatch ? tagMatch[1] : null;
    }
    
    // Function to highlight element
    function highlightElement(element) {
        element.style.outline = '3px solid red';
        element.style.backgroundColor = 'rgba(255, 255, 0, 0.3)';
        element.style.transition = 'all 0.3s ease';
    }
    
    // Function to remove highlight
    function removeHighlight(element) {
        element.style.outline = '';
        element.style.backgroundColor = '';
    }
    
    // Function to wait/delay
    function wait(seconds) {
        return new Promise(resolve => setTimeout(resolve, seconds * 1000));
    }
    
    // Wait for element to appear in the DOM
    function waitForElement(selector, timeout) {
        return new Promise((resolve, reject) => {
            if (document.querySelector(selector)) {
                return resolve(document.querySelector(selector));
            }

            const observer = new MutationObserver(() => {
                if (document.querySelector(selector)) {
                    observer.disconnect();
                    resolve(document.querySelector(selector));
                }
            });

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

            setTimeout(() => {
                observer.disconnect();
                reject(new Error(`Timeout waiting for element: ${selector}`));
            }, timeout * 1000);
        });
    }
    
    // Main function to process clicks sequentially
    async function processClicks() {
        console.log('🚀 Starting click sequence');
        updateBanner('🚀 Starting click sequence...', '#00ffff');
        
        for (let i = 0; i < elementsToClick.length; i++) {
            const item = elementsToClick[i];
            const description = item.description || `Item ${i + 1}`;
            
            console.log(`Processing: ${description}`);
            
            const selector = extractSelector(item.element);
            
            if (!selector) {
                console.log(`Could not extract selector from: ${item.element}`);
                updateBanner(`⚠️ Could not extract selector for: ${description}`, '#ff9900');
                await wait(2);
                continue;
            }
            
            try {
                updateBanner(`⏳ Looking for: ${description}`, '#ffff00');
                logDebug(`Looking for selector: ${selector}`);
                
                const element = await waitForElement(selector, TIMEOUT_SECONDS);
                
                logDebug(`✅ Found element: ${selector}`);
                logDebug(`Element tag: ${element.tagName}, classes: ${element.className}`);
                updateBanner(`✅ Found ${description} - waiting ${item.delay}s`, '#00ff00', true);
                
                highlightElement(element);
                await wait(item.delay);
                
                // Try multiple click methods to ensure compatibility
                updateBanner(`🖱️ Attempting click on: ${description}`, '#ffff00');
                console.log(`Attempting multiple click methods on: ${selector}`);
                
                // Method 1: Try the element's onclick attribute if it exists
                if (element.onclick) {
                    console.log('Method 1: Invoking onclick attribute');
                    element.onclick.call(element);
                }
                
                // Method 2: Try href for javascript: links
                if (element.href && element.href.startsWith('javascript:')) {
                    console.log('Method 2: Following javascript: link');
                    unsafeWindow.location.assign(element.getAttribute('href'));
                }
                
                // Method 3: Dispatch MouseEvent in unsafeWindow context
                console.log('Method 3: Dispatching MouseEvent in unsafeWindow context');
                const mousedownEvt = unsafeWindow.document.createEvent("MouseEvents");
                mousedownEvt.initMouseEvent("mousedown", true, true, unsafeWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                element.dispatchEvent(mousedownEvt);
                
                await wait(0.1);
                
                const mouseupEvt = unsafeWindow.document.createEvent("MouseEvents");
                mouseupEvt.initMouseEvent("mouseup", true, true, unsafeWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                element.dispatchEvent(mouseupEvt);
                
                await wait(0.1);
                
                const clickEvt = unsafeWindow.document.createEvent("MouseEvents");
                clickEvt.initMouseEvent("click", true, true, unsafeWindow, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                element.dispatchEvent(clickEvt);
                
                // Method 4: Simple click() as fallback
                console.log('Method 4: Simple click() fallback');
                element.click();
                
                console.log(`All click methods attempted for: ${selector}`);
                updateBanner(`✅ Clicked: ${description}`, '#00ff00');
                
                removeHighlight(element);
                await wait(1);
                
            } catch (error) {
                console.error(`Error with element ${selector}: ${error.message}`);
                updateBanner(`❌ Failed to find: ${description}`, '#ff0000');
                await wait(3);
            }
        }
        
        console.log('All clicks completed');
        updateBanner('✨ All clicks completed successfully!', '#00ff00');
        
        setTimeout(() => {
            if (currentBanner) {
                currentBanner.remove();
                currentBanner = null;
            }
        }, 5000);
    }
    
    // Create control panel button
    function createControlPanel() {
        const panel = document.createElement('div');
        panel.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: black;
            color: white;
            padding: 15px;
            border-radius: 8px;
            z-index: 999998;
            font-family: monospace;
            border: 2px solid #00ff00;
        `;
        
        const title = document.createElement('div');
        title.textContent = '🎮 BREAK OUT Controls';
        title.style.cssText = 'font-weight: bold; margin-bottom: 10px; color: #00ff00;';
        panel.appendChild(title);
        
        const startButton = document.createElement('button');
        startButton.textContent = '🚀 Start Click Sequence';
        startButton.style.cssText = `
            background: #00ff00;
            color: black;
            border: none;
            padding: 10px 15px;
            border-radius: 4px;
            cursor: pointer;
            font-weight: bold;
            width: 100%;
            margin-bottom: 5px;
        `;
        startButton.onclick = processClicks;
        panel.appendChild(startButton);
        
        const closeButton = document.createElement('button');
        closeButton.textContent = '❌ Close';
        closeButton.style.cssText = `
            background: #ff0000;
            color: white;
            border: none;
            padding: 5px 10px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
            width: 100%;
        `;
        closeButton.onclick = () => panel.remove();
        panel.appendChild(closeButton);
        
        document.body.appendChild(panel);
    }
    
    // Wait for page to be fully loaded
    window.addEventListener('load', function() {
        updateBanner('✅ Page loaded - Click button in bottom-right to start', '#00ff00');
        createControlPanel();
        console.log('Control panel created');
        
        // Hide banner after 5 seconds
        setTimeout(() => {
            if (currentBanner) {
                currentBanner.remove();
                currentBanner = null;
            }
        }, 5000);
    });
    
    // Inject Eruda for mobile debugging
    setTimeout(function() {
        const script = document.createElement('script');
        script.src = 'https://cdn.jsdelivr.net/npm/eruda';
        document.body.appendChild(script);
        script.onload = function() {
            eruda.init();
            console.log('Eruda console initialized - tap icon in corner');
        };
    }, 2000);
    
})();