MonkeyType-lightning / mnk_lightning_v3.js
algorembrant's picture
Upload 41 files
364eb96 verified
// MnkLightning v3 - Browser-Based Human Typer
// Merges logic from Python script and JS injector into a single userscript/console script.
(function () {
console.log("%c MnkLightning v3 Active ", "background: #222; color: #00ff00; font-size: 16px");
// === CONFIGURATION ===
const CONFIG = {
min_wpm: 100,
max_wpm: 140,
// Key Hold Time (Seconds)
min_key_hold: 0.01,
max_key_hold: 0.04,
// Imperfection Rates (0.0 to 1.0)
wrong_char_rate: 0.005,
adjacent_key_rate: 0.005,
double_letter_rate: 0.001,
skip_letter_rate: 0.001,
hesitation_rate: 0.02,
burst_rate: 0.08,
insane_burst_rate: 0.001,
// Timing Multipliers
hesitation_multiplier: 2.5,
burst_speed_multiplier: 0.6,
post_mistake_pause: 0.4,
word_start_slowdown: 1.2,
};
// QWERTY Adjacency Map
const ADJACENT_KEYS = {
'a': 'qwsz', 'b': 'vghn', 'c': 'xdfv', 'd': 'serfcx', 'e': 'wsdr',
'f': 'drtgvc', 'g': 'ftyhbv', 'h': 'gyujnb', 'i': 'ujko', 'j': 'huikmn',
'k': 'jiolm', 'l': 'kop', 'm': 'njk', 'n': 'bhjm', 'o': 'iklp',
'p': 'ol', 'q': 'wa', 'r': 'edft', 's': 'awedxz', 't': 'rfgy',
'u': 'yhji', 'v': 'cfgb', 'w': 'qase', 'x': 'zsdc', 'y': 'tghu',
'z': 'asx'
};
// Global State
let isTyping = false;
let abortTyping = false;
// === HELPERS ===
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const randomUniform = (min, max) => Math.random() * (max - min) + min;
const randomInt = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
const randomChoice = (arr) => arr[Math.floor(Math.random() * arr.length)];
const randomChar = () => "abcdefghijklmnopqrstuvwxyz"[Math.floor(Math.random() * 26)];
function getKeystrokeDelay(wpm, inBurst = false) {
const cpm = wpm * 5;
let baseDelay = 60 / cpm;
if (inBurst) {
baseDelay *= CONFIG.burst_speed_multiplier;
}
const variance = baseDelay * 0.20;
const noise = randomUniform(-variance, variance);
return Math.max(0.005, baseDelay + noise) * 1000;
}
function getAdjacentKey(char) {
const charLower = char.toLowerCase();
if (ADJACENT_KEYS[charLower]) {
const adj = randomChoice(ADJACENT_KEYS[charLower]);
return char === char.toUpperCase() ? adj.toUpperCase() : adj;
}
return char;
}
// === INPUT SIMULATION ===
const CODE_MAP = {
' ': 'Space',
'Enter': 'Enter',
'Backspace': 'Backspace',
'Escape': 'Escape',
',': 'Comma',
'.': 'Period',
'/': 'Slash',
';': 'Semicolon',
"'": 'Quote',
'[': 'BracketLeft',
']': 'BracketRight',
'\\': 'Backslash',
'-': 'Minus',
'=': 'Equal',
'`': 'Backquote',
'1': 'Digit1', '2': 'Digit2', '3': 'Digit3', '4': 'Digit4', '5': 'Digit5',
'6': 'Digit6', '7': 'Digit7', '8': 'Digit8', '9': 'Digit9', '0': 'Digit0'
};
function dispatchKey(key, type) {
let code;
// 1. Check strict map
if (CODE_MAP[key]) {
code = CODE_MAP[key];
}
// 2. Letters
else if (key.length === 1 && /[a-zA-Z]/.test(key)) {
code = `Key${key.toUpperCase()}`;
}
// 3. Fallback for shifted punctuation
else if (key === '!') code = 'Digit1';
else if (key === '@') code = 'Digit2';
else if (key === '#') code = 'Digit3';
else if (key === '$') code = 'Digit4';
else if (key === '%') code = 'Digit5';
else if (key === '^') code = 'Digit6';
else if (key === '&') code = 'Digit7';
else if (key === '*') code = 'Digit8';
else if (key === '(') code = 'Digit9';
else if (key === ')') code = 'Digit0';
else if (key === '_') code = 'Minus';
else if (key === '+') code = 'Equal';
else if (key === '{') code = 'BracketLeft';
else if (key === '}') code = 'BracketRight';
else if (key === '|') code = 'Backslash';
else if (key === ':') code = 'Semicolon';
else if (key === '"') code = 'Quote';
else if (key === '<') code = 'Comma';
else if (key === '>') code = 'Period';
else if (key === '?') code = 'Slash';
else if (key === '~') code = 'Backquote';
else {
code = key;
}
const event = new KeyboardEvent(type, {
key: key,
code: code,
bubbles: true,
cancelable: true,
view: window,
which: key.charCodeAt(0),
keyCode: key.charCodeAt(0)
});
const target = document.activeElement || document.body;
target.dispatchEvent(event);
}
async function typeChar(char) {
dispatchKey(char, 'keydown');
dispatchKey(char, 'keypress');
const holdTime = randomUniform(CONFIG.min_key_hold, CONFIG.max_key_hold) * 1000;
await sleep(holdTime);
dispatchKey(char, 'keyup');
}
async function simulateBackspace(count = 1) {
for (let i = 0; i < count; i++) {
dispatchKey('Backspace', 'keydown');
await sleep(randomUniform(CONFIG.min_key_hold, CONFIG.max_key_hold) * 1000);
dispatchKey('Backspace', 'keyup');
await sleep(randomUniform(50, 100));
}
}
// === CORE LOGIC ===
function getVisibleText() {
const words = document.querySelectorAll('.word');
if (words.length === 0) return null;
let text = "";
words.forEach((word) => {
word.querySelectorAll('letter').forEach(letter => {
text += letter.textContent;
});
text += " ";
});
return text.trim();
}
async function startTyping() {
if (isTyping) return;
const text = getVisibleText();
if (!text) {
console.error("MnkLightning: No text found! Are you in a test?");
return;
}
// Try to focus the game area if possible
const gameWords = document.getElementById('words');
if (gameWords) {
gameWords.click(); // Hack to ensure focus
}
isTyping = true;
abortTyping = false;
const wpm = randomInt(CONFIG.min_wpm, CONFIG.max_wpm);
console.log(`MnkLightning: Starting... Target WPM: ${wpm}, Length: ${text.length}`);
let idx = 0;
let burstRemaining = 0;
try {
while (idx < text.length) {
if (abortTyping) break;
const char = text[idx];
let delay = getKeystrokeDelay(wpm, burstRemaining > 0);
if (burstRemaining > 0) burstRemaining--;
// === IMPERFECTIONS ===
if (Math.random() < CONFIG.hesitation_rate) {
delay *= CONFIG.hesitation_multiplier;
}
if (burstRemaining === 0 && Math.random() < CONFIG.burst_rate) {
burstRemaining = 5;
}
// Insane Burst
if (Math.random() < CONFIG.insane_burst_rate) {
const burstLen = randomInt(4, 5);
for (let i = 0; i < burstLen; i++) {
if (idx >= text.length || abortTyping) break;
dispatchKey(text[idx], 'keydown');
dispatchKey(text[idx], 'keyup');
idx++;
await sleep(2);
}
continue;
}
// Mistakes
if (Math.random() < CONFIG.wrong_char_rate && /[a-zA-Z0-9]/.test(char)) {
const wrong = randomChar();
await typeChar(wrong);
await sleep(delay * 2);
await simulateBackspace(1);
await sleep(delay);
}
await typeChar(char);
idx++;
if (char === ' ') {
delay *= CONFIG.word_start_slowdown;
}
await sleep(delay);
}
} catch (e) {
console.error(e);
}
console.log("MnkLightning: Finished.");
isTyping = false;
}
// === LISTENERS ===
window.addEventListener('keydown', (e) => {
if (e.key === 'Insert') {
e.preventDefault();
if (isTyping) {
console.log("MnkLightning: Already running!");
return;
}
startTyping();
}
if (e.key === 'Escape') {
abortTyping = true;
if (isTyping) {
console.log("MnkLightning: Aborting...");
isTyping = false;
}
}
});
})();