Human Typer (Ultimate Fix)

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

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

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

})();