NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==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);
})();