Human Typer (Ultimate Fix)

Activates via Alt+V. Pause: Ctrl+Shift+Alt. Kill: Ctrl+Shift+Alt+Space. Console: exit

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         Human Typer (Ultimate Fix)
// @namespace    http://tampermonkey.net/
// @version      8.0
// @description  Activates via Alt+V. Pause: Ctrl+Shift+Alt. Kill: Ctrl+Shift+Alt+Space. Console: exit
// @author       You
// @match        *://*/*
// @grant        none
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    // --- 1. DEFINE CONSOLE COMMAND AT THE VERY TOP ---
    // This ensures "exit" is ALWAYS defined in the console, even if the rest of the script breaks.
    window.exit = function() {
        clearTimeout(window.__ht_timeout);
        window.__ht_typing = false;
        window.__ht_paused = false;
        window.__ht_target = null;
        console.log('[HumanTyper] 🛑 SCRIPT EXITED.');
    };
    
    console.log('[HumanTyper] Script loaded. Type "exit" in the console to kill it.');

    // --- 2. ANTI-DOUBLE-SCRIPT LOCK ---
    if (window.__humanTyperMutex) {
        console.log('[HumanTyper] Duplicate script detected. Shutting down duplicate.');
        return; 
    }
    window.__humanTyperMutex = true;

    const LOG_PREFIX = '[HumanTyper]';
    const LOG = console.log.bind(console, LOG_PREFIX);

    // Using window.__ht_ variables so the window.exit() function can see and kill them
    window.__ht_typing = false;
    window.__ht_paused = false;
    let textToType = "";
    let currentIndex = 0;
    window.__ht_timeout = null;
    window.__ht_target = null; 

    // --- 3. Intercept Alt+V (New Activation) ---
    document.addEventListener('keydown', async function(e) {
        // Check for Alt+V (and ensure Ctrl/Shift are NOT held)
        if (e.altKey && !e.ctrlKey && !e.shiftKey && e.code === 'KeyV') {
            
            // CRITICAL FIX: stopImmediatePropagation stops Chrome from stealing focus to open the "View" menu
            e.preventDefault(); 
            e.stopPropagation();
            e.stopImmediatePropagation(); 

            if (window.__ht_typing) return;

            LOG('Alt+V detected. Reading clipboard...');

            let txt = '';
            try {
                if (navigator.clipboard && navigator.clipboard.readText) {
                    txt = await navigator.clipboard.readText();
                }
            } catch (err) {
                console.error(LOG_PREFIX, 'Failed to read clipboard.', err);
                console.error(LOG_PREFIX, 'NOTE: If you are testing on a local HTTP:// website, Chrome blocks clipboard access. It MUST be on HTTPS://');
                return;
            }

            if (!txt) {
                LOG('Clipboard is empty.');
                return;
            }

            window.__ht_target = document.activeElement;
            
            if (!window.__ht_target || !(window.__ht_target.isContentEditable || window.__ht_target.tagName === 'INPUT' || window.__ht_target.tagName === 'TEXTAREA')) {
                LOG('Please focus on a text box before pressing Alt+V.');
                return;
            }

            textToType = txt;
            currentIndex = 0;
            window.__ht_typing = true;
            window.__ht_paused = false;
            
            LOG(`Starting typing (${textToType.length} chars)...`);
            typeNextChar();
        }
    }, true); // 'true' means capture phase (runs before the website)

    // --- 4. Intercept Ctrl+Shift+Alt (Pause) & Ctrl+Shift+Alt+Space (Kill Switch) ---
    document.addEventListener('keydown', function(e) {
        if (e.ctrlKey && e.shiftKey && e.altKey) {
            if (e.repeat) return; 
            e.preventDefault();

            // --- KILL SWITCH LOGIC ---
            if (e.code === 'Space') {
                clearTimeout(window.__ht_timeout);
                window.__ht_typing = false;
                window.__ht_paused = false;
                currentIndex = 0;
                textToType = "";
                window.__ht_target = null;
                LOG('🛑 SCRIPT COMPLETELY STOPPED & RESET.');
                return; 
            }

            // --- PAUSE/RESUME LOGIC ---
            if (!window.__ht_typing) return;

            window.__ht_paused = !window.__ht_paused;

            if (window.__ht_paused) {
                clearTimeout(window.__ht_timeout);
                LOG('⏸️ PAUSED');
            } else {
                LOG('▶️ RESUMED');
                typeNextChar(); 
            }
        }
    }, true);

    // --- 5. Foolproof Typing Logic ---
    function typeNextChar() {
        if (!window.__ht_typing || window.__ht_paused) return;
        
        if (!window.__ht_target || !document.body.contains(window.__ht_target)) {
            LOG('Target text box was removed from the page. Stopping.');
            window.__ht_typing = false;
            return;
        }

        if (currentIndex >= textToType.length) {
            window.__ht_typing = false;
            LOG('Typing loop finished. Running verification...');
            verifyOutput(); 
            return;
        }

        // FORCE FOCUS: Keep typing even if invisible or scrolled away
        if (document.activeElement !== window.__ht_target) {
            window.__ht_target.focus();
        }

        const charToType = textToType[currentIndex];

        if (window.__ht_target.tagName === 'INPUT' || window.__ht_target.tagName === 'TEXTAREA') {
            const prototype = window.__ht_target.tagName === 'TEXTAREA' ? window.HTMLTextAreaElement.prototype : window.HTMLInputElement.prototype;
            const nativeSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;
            
            const start = window.__ht_target.selectionStart;
            const end = window.__ht_target.selectionEnd;
            const newVal = window.__ht_target.value.substring(0, start) + charToType + window.__ht_target.value.substring(end);
            
            nativeSetter.call(window.__ht_target, newVal);
            window.__ht_target.selectionStart = window.__ht_target.selectionEnd = start + 1;
            window.__ht_target.dispatchEvent(new Event('input', { bubbles: true }));
            
        } else if (window.__ht_target.isContentEditable) {
            document.execCommand('insertHTML', false, charToType);
        }

        currentIndex++;
        
        const humanDelay = Math.floor(Math.random() * 30) + 15; 
        window.__ht_timeout = setTimeout(typeNextChar, humanDelay);
    }

    // --- 6. Verification Subroutine ---
    function verifyOutput() {
        if (!window.__ht_target) return;

        let currentText = "";

        if (window.__ht_target.tagName === 'INPUT' || window.__ht_target.tagName === 'TEXTAREA') {
            currentText = window.__ht_target.value;
        } else if (window.__ht_target.isContentEditable) {
            currentText = window.__ht_target.innerText;
        }

        if (currentText === textToType) {
            LOG('✅ VERIFICATION PASSED: Output is 100% identical to clipboard.');
            return;
        }

        LOG('⚠️ MISMATCH DETECTED: Force-correcting text to match clipboard...');
        forceExactText(window.__ht_target, textToType);
    }

    function forceExactText(el, text) {
        el.focus();
        
        if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') {
            const prototype = el.tagName === 'TEXTAREA' ? window.HTMLTextAreaElement.prototype : window.HTMLInputElement.prototype;
            const nativeSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;
            
            nativeSetter.call(el, text);
            el.selectionStart = el.selectionEnd = text.length;
            el.dispatchEvent(new Event('input', { bubbles: true }));
            el.dispatchEvent(new Event('change', { bubbles: true }));
        } else if (el.isContentEditable) {
            const selection = window.getSelection();
            const range = document.createRange();
            range.selectNodeContents(el);
            selection.removeAllRanges();
            selection.addRange(range);
            
            document.execCommand('insertText', false, text);
        }
        
        LOG('✅ FIX APPLIED: Text force-corrected to match clipboard.');
    }

})();