Automatizador de Tarefas com Cooldown

Cria um botão para iniciar um ciclo de cliques com um cooldown aleatório entre 5 e 6 horas.

// ==UserScript==
// @name         Automatizador de Tarefas com Cooldown
// @namespace    http://tampermonkey.net/
// @version      1.6 // Versão Atualizada com Botão de Forçar
// @description  Cria um botão para iniciar um ciclo de cliques com um cooldown aleatório entre 5 e 6 horas.
// @author       Você
// @match        https://degenidle.com/game
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        window.onurlchange
// ==/UserScript==

(function() {
    'use strict';

    // ==================================================================================
    // ÁREA DE CONFIGURAÇÃO - COMPLETA!
    // ==================================================================================
    const RESET_SKILL_SELECTOR = 'button[title="Restart Task"]';
    const CHANGE_CHARACTER_SELECTOR = 'button:has(img[alt="Cecilia"])';
    const PRIMARY_CHARACTER_SELECTOR = 'button:has(img[alt="tlsBR420"])';
    // ==================================================================================

    let isRunning = GM_getValue('isRunning', false);
    let cooldownEndTime = GM_getValue('cooldownEndTime', 0);

    // --- Criação da Interface do Usuário (Painel de Controle) ---
    const panel = document.createElement('div');
    panel.style.position = 'fixed';
    panel.style.bottom = '20px';
    panel.style.right = '20px';
    panel.style.backgroundColor = '#282c34';
    panel.style.color = 'white';
    panel.style.padding = '15px';
    panel.style.borderRadius = '8px';
    panel.style.zIndex = '9999';
    panel.style.fontFamily = 'Arial, sans-serif';
    panel.style.boxShadow = '0 4px 8px rgba(0,0,0,0.3)';
    document.body.appendChild(panel);

    const title = document.createElement('h3');
    title.innerText = 'Painel de Automação';
    title.style.margin = '0 0 10px 0';
    title.style.textAlign = 'center';
    panel.appendChild(title);

    const toggleButton = document.createElement('button');
    toggleButton.style.width = '100%';
    toggleButton.style.padding = '10px';
    toggleButton.style.border = 'none';
    toggleButton.style.borderRadius = '5px';
    toggleButton.style.cursor = 'pointer';
    panel.appendChild(toggleButton);

    // NOVO BOTÃO DE FORÇAR
    const forceButton = document.createElement('button');
    forceButton.innerText = 'Forçar Ação (Ignorar CD)';
    forceButton.style.width = '100%';
    forceButton.style.padding = '8px';
    forceButton.style.marginTop = '8px';
    forceButton.style.border = 'none';
    forceButton.style.borderRadius = '5px';
    forceButton.style.cursor = 'pointer';
    forceButton.style.backgroundColor = '#f39c12'; // Laranja
    forceButton.style.color = 'white';
    panel.appendChild(forceButton);
    // FIM DO NOVO BOTÃO

    const statusDisplay = document.createElement('p');
    statusDisplay.style.marginTop = '10px';
    statusDisplay.style.textAlign = 'center';
    statusDisplay.style.fontSize = '14px';
    statusDisplay.style.minHeight = '20px';
    panel.appendChild(statusDisplay);

    // --- Funções Principais ---

    /**
     * Tenta encontrar um elemento e, se encontrar, clica nele.
     * @param {string} selector - O seletor CSS do elemento.
     * @returns {Promise<boolean>} - True se o clique foi bem-sucedido, false caso contrário.
     */
    async function clickElement(selector) {
        const element = document.querySelector(selector);
        if (element) {
            console.log(`[Automatizador] Clicando em: ${selector}`);
            element.click();
            return true;
        } else {
            console.error(`[Automatizador] ERRO: Elemento não encontrado com o seletor: ${selector}`);
            return false;
        }
    }

    /**
     * Pausa a execução por um determinado tempo.
     * @param {number} ms - Tempo em milissegundos.
     */
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    /**
     * Executa a sequência de ações.
     */
    async function performActions() {
        if (!isRunning) return; // Garantir que não roda se for parado no meio

        console.log('[Automatizador] Iniciando sequência de ações...');
        statusDisplay.innerText = 'Executando ações...';

        // 1. Clica no botão de resetar skill (Personagem 1)
        let success = await clickElement(RESET_SKILL_SELECTOR);
        if (!success) {
            stopScript('Erro: botão de reset (1º clique) não encontrado.');
            return;
        }
        await sleep(1500);

        // 2. Clica no ícone de trocar personagem (Troca para Personagem 2)
        success = await clickElement(CHANGE_CHARACTER_SELECTOR);
        if (!success) {
            stopScript('Erro: ícone de troca não encontrado.');
            return;
        }
        await sleep(1500);

        // 3. Clica novamente no botão de resetar skill (Personagem 2)
        success = await clickElement(RESET_SKILL_SELECTOR);
        if (!success) {
            stopScript('Erro: botão de reset (2º clique) não encontrado.');
            return;
        }
        await sleep(1500);

        // 4. Clica no personagem principal para voltar (Personagem 1: tlsBR420)
        success = await clickElement(PRIMARY_CHARACTER_SELECTOR);
        if (!success) {
            console.warn('[Automatizador] Aviso: Não conseguiu voltar para o Personagem 1 (tlsBR420).');
        }
        await sleep(1000);

        console.log('[Automatizador] Sequência concluída. Iniciando cooldown.');
        setCooldown();
    }

    /**
     * Define o tempo de cooldown aleatório e salva o estado.
     */
    function setCooldown() {
        const minHours = 5;
        const maxHours = 6;
        const cooldownTime = Math.random() * (maxHours - minHours) * 3600 * 1000 + (minHours * 3600 * 1000);

        cooldownEndTime = Date.now() + cooldownTime;
        GM_setValue('cooldownEndTime', cooldownEndTime);
        console.log(`[Automatizador] Próxima execução em: ${new Date(cooldownEndTime).toLocaleTimeString()}`);
    }

    /**
     * Atualiza o botão e o status na tela.
     */
    function updateUI() {
        if (isRunning) {
            toggleButton.innerText = 'Parar Automação';
            toggleButton.style.backgroundColor = '#e74c3c';
            toggleButton.style.color = 'white';
            forceButton.style.display = 'block'; // Mostra o botão de forçar

            const now = Date.now();
            if (now < cooldownEndTime) {
                const remaining = cooldownEndTime - now;
                const hours = Math.floor(remaining / 3600000);
                const minutes = Math.floor((remaining % 3600000) / 60000);
                const seconds = Math.floor((remaining % 60000) / 1000);
                statusDisplay.innerText = `Cooldown: ${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
            } else {
                statusDisplay.innerText = 'Aguardando para executar...';
            }
        } else {
            toggleButton.innerText = 'Iniciar Automação';
            toggleButton.style.backgroundColor = '#2ecc71';
            toggleButton.style.color = 'white';
            forceButton.style.display = 'none'; // Esconde o botão de forçar
            statusDisplay.innerText = 'Inativo. Clique para começar.';
        }
    }

    function stopScript(reason = '') {
        isRunning = false;
        GM_setValue('isRunning', false);
        console.log(`[Automatizador] Script parado. ${reason}`);
        updateUI();
        if (reason) {
            statusDisplay.innerText = `Parado! ${reason}`;
        }
    }

    // --- Lógica Principal (Loop) ---
    function mainLoop() {
        if (!isRunning) {
            return;
        }

        const now = Date.now();
        if (now >= cooldownEndTime) {
            performActions();
        }
    }

    // Adiciona o listener de clique ao botão
    toggleButton.addEventListener('click', () => {
        isRunning = !isRunning;
        GM_setValue('isRunning', isRunning);

        if (isRunning) {
            console.log('[Automatizador] Script iniciado pelo usuário.');

            // Lógica para rodar IMEDIATAMENTE se o cooldown expirou ou é a primeira vez.
            if (Date.now() >= cooldownEndTime) {
                console.log('[Automatizador] Cooldown expirado ou primeiro uso. Executando ações imediatamente.');
                performActions(); // Execução instantânea!
            } else {
                console.log('[Automatizador] Script iniciado, mas o cooldown ainda está ativo. Aguardando...');
            }
        } else {
            stopScript();
        }
        updateUI();
    });

    // Adiciona o listener para o botão de forçar execução
    forceButton.addEventListener('click', () => {
        // 1. Zera o cooldown.
        cooldownEndTime = Date.now();
        GM_setValue('cooldownEndTime', cooldownEndTime);

        // 2. Garante que está rodando.
        if (!isRunning) {
            isRunning = true;
            GM_setValue('isRunning', true);
        }

        // 3. Executa a ação imediatamente.
        console.warn('[Automatizador] Execução forçada pelo usuário. Cooldown resetado.');
        performActions();
        updateUI();
    });

    // Inicia o script
    updateUI();
    setInterval(updateUI, 1000);
    setInterval(mainLoop, 5000);
})();