File size: 4,824 Bytes
364eb96 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | (function () {
console.log("%c Monkeytype Cheat Initiated (Persistent Mode) ", "background: #222; color: #bada55; font-size: 20px");
const keyMap = {
' ': { code: 'Space', keyCode: 32 },
'\n': { code: 'Enter', keyCode: 13 },
};
let isArmed = false;
function typeChar(char) {
const target = document.activeElement || document.body;
let key = char;
let code, keyCode;
if (keyMap[char]) {
code = keyMap[char].code;
keyCode = keyMap[char].keyCode;
} else {
code = `Key${char.toUpperCase()}`;
keyCode = char.toUpperCase().charCodeAt(0);
}
const eventOptions = {
key: key,
code: code,
keyCode: keyCode,
which: keyCode,
bubbles: true,
cancelable: true,
isTrusted: true
};
target.dispatchEvent(new KeyboardEvent('keydown', eventOptions));
target.dispatchEvent(new KeyboardEvent('keypress', eventOptions));
const inputEvent = new InputEvent('input', {
data: char,
inputType: 'insertText',
bubbles: true,
cancelable: true
});
target.dispatchEvent(inputEvent);
target.dispatchEvent(new KeyboardEvent('keyup', eventOptions));
}
function getDelay() {
return 100 + (Math.random() * 60 - 30);
}
async function cheat(textToType) {
console.log(`Typing ${textToType.length} chars...`);
for (let i = 0; i < textToType.length; i++) {
// Check if test was reset mid-run
if (!document.querySelector('#words .word.active')) {
console.log("Test reset detected. Stopping current run.");
return;
}
typeChar(textToType[i]);
await new Promise(r => setTimeout(r, getDelay()));
}
}
function getFullText() {
const words = document.querySelectorAll('#words .word');
let fullBuffer = "";
words.forEach((word, index) => {
const letters = word.querySelectorAll('letter');
letters.forEach(l => fullBuffer += l.textContent);
if (index < words.length - 1) fullBuffer += " ";
});
return fullBuffer;
}
const triggerHandler = (e) => {
if (!isArmed) return;
if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
const targetText = getFullText();
if (!targetText) return;
const firstChar = targetText[0];
if (firstChar && e.key === firstChar) {
isArmed = false; // Disarm to prevent double trigger
const remainingText = targetText.substring(1);
console.log("Triggered! Starting...");
setTimeout(() => cheat(remainingText), 150);
}
}
};
function armCheat() {
// Debounce slightly to ensure DOM is ready
setTimeout(() => {
const text = getFullText();
if (text.length > 0) {
isArmed = true;
console.log("Cheat RE-ARMED. Waiting for first key...");
} else {
console.log("Training ended or no words found.");
}
}, 500);
}
// LISTENER: Watch for Keydown (Trigger)
// We add this ONCE and keep it capable of firing whenever 'isArmed' is true.
window.addEventListener('keydown', triggerHandler);
// MUTATION OBSERVER: Watch for "Restart Test"
// When #words changes (new words added), we re-arm.
const wordsContainer = document.querySelector('#words');
if (wordsContainer) {
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
// If words are added/removed, it means test reset/changed
if (mutation.type === 'childList') {
// Check if we have new words
const words = document.querySelectorAll('#words .word');
if (words.length > 5) { // Arbitrary threshold to ensure it's a real set of words
armCheat();
// We break to avoid calling armCheat multiple times per batch update
break;
}
}
}
});
observer.observe(wordsContainer, { childList: true });
console.log("Observer attached. Auto-restart enabled.");
// Initial Arm
armCheat();
} else {
console.error("Container #words not found. Is the page loaded?");
}
})(); |