Human Typer (Ultimate Fix)

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

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==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.');
    }

})();