Activates via Alt+V. Pause: Ctrl+Shift+Alt. Kill: Ctrl+Shift+Alt+Space. Console: exit
// ==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.');
}
})();