// ==UserScript==
// @name MonkeyType AutoTyper Bot
// @author longkidkoolstar
// @description A Bot that automatically types for you in MokeyType.
// @icon https://th.bing.com/th/id/R.c8397fb766c4397fea8a8b499c15a453?rik=aROX42RoH7HhXw&pid=ImgRaw&r=0
// @version 2.1
// @match *://monkeytype.com/*
// @run-at document-start
// @grant none
// @license MIT
// @namespace https://greasyfork.org/users/1000020
// ==/UserScript==
/* jshint esversion:6 */
(function () {
"use strict";
// Minimum and maximum delay (ms)
let MIN_DELAY = 100;
let MAX_DELAY = 333;
const TOGGLE_KEY = "ArrowRight";
const log = console.log;
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
let toggle = false;
function canType() {
const typingTest = document.getElementById("typingTest");
const isHidden = typingTest.classList.contains("hidden");
if (isHidden) toggle = false;
return toggle && !isHidden;
}
function getNextCharacter() {
const currentWord = document.querySelector(".word.active");
for (const letter of currentWord.children) {
if (letter.className === "") return letter.textContent;
}
return " ";
}
const InputEvents = {};
function pressKey(key) {
const wordsInput = document.getElementById("wordsInput");
const KeyboardEvent = Object.assign({}, DEFAULT_INPUT_OPTIONS, {
target: wordsInput,
data: key,
});
const InputEvent = Object.assign({}, DEFAULT_KEY_OPTIONS, {
target: wordsInput,
key: key,
});
wordsInput.value += key;
InputEvents.beforeinput(InputEvent);
InputEvents.input(InputEvent);
InputEvents.keyup(KeyboardEvent);
}
function typeCharacter() {
if (!canType()) {
log("STOPPED TYPING TEST");
return;
}
const nextChar = getNextCharacter();
let delay;
// Check which section is currently displayed
const basicSection = document.getElementById("basicSection");
if (basicSection.style.display === "") { // Basic section is displayed
delay = 60000 / (document.getElementById("wpmSlider").value * 5);
} else { // Advanced section is displayed
delay = random(MIN_DELAY, MAX_DELAY);
}
const accuracy = document.getElementById("accuracySlider").value;
// introduce some random errors
if (Math.random() > accuracy) {
// skip this character
setTimeout(typeCharacter, delay);
return;
} else if (Math.random() > accuracy) {
// repeat this character
pressKey(nextChar);
} else if (Math.random() > accuracy) {
// insert a random incorrect character
const adjacentKey = getAdjacentKey(nextChar);
pressKey(adjacentKey);
}
// press the next character
pressKey(nextChar);
// introduce a pause between words
if (nextChar === " ") {
const pauseDelay = document.getElementById("pauseDelaySlider").value;
setTimeout(typeCharacter, pauseDelay);
} else {
setTimeout(typeCharacter, delay);
}
}
function getAdjacentKey(key) {
// Define the adjacent keys for each key
const adjacentKeys = {
"q": ["w", "a"],
"w": ["q", "e", "a", "s"],
"e": ["w", "r", "s", "d"],
"r": ["e", "t", "d", "f"],
"t": ["r", "y", "f", "g"],
"y": ["t", "u", "g", "h"],
"u": ["y", "i", "h", "j"],
"i": ["u", "o", "j", "k"],
"o": ["i", "p", "k", "l"],
"p": ["o", "l"],
"a": ["q", "w", "s", "z"],
"s": ["w", "e", "a", "d", "z", "x"],
"d": ["e", "r", "s", "f", "x", "c"],
"f": ["r", "t", "d", "g", "c", "v"],
"g": ["t", "y", "f", "h", "v", "b"],
"h": ["y", "u", "g", "j", "b", "n"],
"j": ["u", "i", "h", "k", "n", "m"],
"k": ["i", "o", "j", "l", "m"],
"l": ["o", "p", "k"],
"z": ["a", "s", "x"],
"x": ["s", "d", "z", "c"],
"c": ["d", "f", "x", "v"],
"v": ["f", "g", "c", "b"],
"b": ["g", "h", "v", "n"],
"n": ["h", "j", "b", "m"],
"m": ["j", "k", "n"]
};
// Handle space character separately
if (key === " ") {
return " ";
}
// Get the adjacent keys for the given key
const keys = adjacentKeys[key.toLowerCase()];
// Randomly select an adjacent key
const randomIndex = Math.floor(Math.random() * keys.length);
return keys[randomIndex];
}
window.addEventListener("keydown", function (event) {
if (event.code === TOGGLE_KEY) {
event.preventDefault();
if (event.repeat) return;
toggle = !toggle;
if (toggle) {
log("STARTED TYPING TEST");
typeCharacter();
}
}
});
// Intercept when JQuery attached an addEventListener to the Input element
function hook(element) {
element.addEventListener = new Proxy(element.addEventListener, {
apply(target, _this, args) {
const [type, listener, ...options] = args;
if (_this.id === "wordsInput") {
InputEvents[type] = listener;
}
return target.apply(_this, args);
},
});
}
hook(HTMLInputElement.prototype);
const DEFAULT_KEY_OPTIONS = {
key: "",
code: "",
keyCode: 0,
which: 0,
isTrusted: true,
altKey: false,
bubbles: true,
cancelBubble: false,
cancelable: true,
charCode: 0,
composed: true,
ctrlKey: false,
currentTarget: null,
defaultPrevented: false,
detail: 0,
eventPhase: 0,
isComposing: false,
location: 0,
metaKey: false,
path: null,
repeat: false,
returnValue: true,
shiftKey: false,
srcElement: null,
target: null,
timeStamp: 6338.5,
type: "",
view: window,
};
const DEFAULT_INPUT_OPTIONS = {
isTrusted: true,
bubbles: true,
cancelBubble: false,
cancelable: false,
composed: true,
data: "",
dataTransfer: null,
defaultPrevented: false,
detail: 0,
eventPhase: 0,
inputType: "insertText",
isComposing: false,
path: null,
returnValue: true,
sourceCapabilities: null,
srcElement: null,
target: null,
currentTarget: null,
timeStamp: 11543,
type: "input",
view: null,
which: 0,
};
// Add GUI to change min and max delay
const gui = document.createElement("div");
gui.style.position = "fixed";
gui.style.bottom = "30%";
gui.style.right = "0";
gui.style.transform = "translateY(50%)";
gui.style.padding = "5px";
gui.style.background = "rgba(0, 0, 0, 0.6)";
gui.style.color = "white";
gui.style.fontFamily = "sans-serif";
gui.style.fontSize = "12px";
gui.style.zIndex = "9999"; // set z-index to a high value
gui.innerHTML = `
<div style="display: flex; flex-direction: column;">
<div style="margin-bottom: 10px;">
<button id="resetButton">Reset to Default</button>
</div>
<div style="display: flex; flex-direction: column;">
<div style="margin-bottom: 10px;">
<button id="basicButton">Basic</button>
<button id="advancedButton">Advanced</button>
</div>
<div id="basicSection">
<div style="margin-bottom: 5px;">
WPM: <input type="range" id="wpmSlider" value="50" min="10" max="100" step="5" style="width: 100px;">
<span id="wpmValue">50</span>
</div>
</div>
<div id="advancedSection" style="display: none;">
<div style="margin-bottom: 5px;">
Min Delay: <input type="range" id="minDelaySlider" value="${MIN_DELAY}" min="0" max="1000" step="10" style="width: 100px;">
<span id="minDelayValue">${MIN_DELAY}ms</span>
</div>
<div style="margin-bottom: 5px;">
Max Delay: <input type="range" id="maxDelaySlider" value="${MAX_DELAY}" min="0" max="1000" step="10" style="width: 100px;">
<span id="maxDelayValue">${MAX_DELAY}ms</span>
</div>
<div>
Pause Delay: <input type="range" id="pauseDelaySlider" value="${MAX_DELAY}" min="0" max="1000" step="10" style="width: 100px;">
<span id="pauseDelayValue">${MAX_DELAY}ms</span>
</div>
</div>
</div>
<div style="margin-bottom: 5px;">
Accuracy: <input type="range" id="accuracySlider" value="0.1" min="0" max="1" step="0.01" style="width: 100px;">
<span id="accuracyValue">0.1</span>
</div>
`;
document.body.appendChild(gui);
// Add event listeners to toggle the visibility of each section
const basicButton = document.getElementById("basicButton");
const basicSection = document.getElementById("basicSection");
basicButton.addEventListener("click", function() {
basicSection.style.display = "";
advancedSection.style.display = "none";
});
const advancedButton = document.getElementById("advancedButton");
const advancedSection = document.getElementById("advancedSection");
advancedButton.addEventListener("click", function() {
basicSection.style.display = "none";
advancedSection.style.display = "";
});
// Add event listeners to the sliders
const wpmSlider = document.getElementById("wpmSlider");
const wpmValue = document.getElementById("wpmValue");
wpmSlider.addEventListener("input", function() {
wpmValue.textContent = wpmSlider.value;
});
const minDelaySlider = document.getElementById("minDelaySlider");
const minDelayValue = document.getElementById("minDelayValue");
minDelaySlider.addEventListener("input", function() {
MIN_DELAY = parseInt(minDelaySlider.value);
minDelayValue.textContent = `${MIN_DELAY}ms`;
});
const maxDelaySlider = document.getElementById("maxDelaySlider");
const maxDelayValue = document.getElementById("maxDelayValue");
maxDelaySlider.addEventListener("input", function() {
MAX_DELAY = parseInt(maxDelaySlider.value);
maxDelayValue.textContent = `${MAX_DELAY}ms`;
});
const pauseDelaySlider = document.getElementById("pauseDelaySlider");
const pauseDelayValue = document.getElementById("pauseDelayValue");
pauseDelaySlider.addEventListener("input", function() {
pauseDelayValue.textContent = `${pauseDelaySlider.value}ms`;
});
const accuracySlider = document.getElementById("accuracySlider");
const accuracyValue = document.getElementById("accuracyValue");
accuracySlider.addEventListener("input", function() {
accuracyValue.textContent = accuracySlider.value;
});
const resetButton = document.getElementById("resetButton");
resetButton.addEventListener("click", function() {
wpmSlider.value = 40;
minDelaySlider.value = 100;
maxDelaySlider.value = 333;
pauseDelaySlider.value = 100;
accuracySlider.value = 95;
wpmValue.textContent = wpmSlider.value;
minDelayValue.textContent = `${minDelaySlider.value}ms`;
maxDelayValue.textContent = `${maxDelaySlider.value}ms`;
pauseDelayValue.textContent = `${pauseDelaySlider.value}ms`;
accuracyValue.textContent = accuracySlider.value;
// Save default values to localStorage
localStorage.setItem('wpmSliderValue', wpmSlider.value);
localStorage.setItem('minDelaySliderValue', minDelaySlider.value);
localStorage.setItem('maxDelaySliderValue', maxDelaySlider.value);
localStorage.setItem('pauseDelaySliderValue', pauseDelaySlider.value);
localStorage.setItem('accuracySliderValue', accuracySlider.value);
});
function saveSliderValues() {
localStorage.setItem('wpmSliderValue', wpmSlider.value);
localStorage.setItem('minDelaySliderValue', minDelaySlider.value);
localStorage.setItem('maxDelaySliderValue', maxDelaySlider.value);
localStorage.setItem('pauseDelaySliderValue', pauseDelaySlider.value);
localStorage.setItem('accuracySliderValue', accuracySlider.value);
}
wpmSlider.addEventListener('input', function() {
wpmValue.textContent = wpmSlider.value;
saveSliderValues();
});
minDelaySlider.addEventListener('input', function() {
MIN_DELAY = parseInt(minDelaySlider.value);
minDelayValue.textContent = `${MIN_DELAY}ms`;
saveSliderValues();
});
maxDelaySlider.addEventListener('input', function() {
MAX_DELAY = parseInt(maxDelaySlider.value);
maxDelayValue.textContent = `${MAX_DELAY}ms`;
saveSliderValues();
});
pauseDelaySlider.addEventListener('input', function() {
pauseDelayValue.textContent = `${pauseDelaySlider.value}ms`;
saveSliderValues();
});
accuracySlider.addEventListener('input', function() {
accuracyValue.textContent = accuracySlider.value;
saveSliderValues();
});
// Retrieve slider values from localStorage
if (localStorage.getItem('wpmSliderValue')) {
wpmSlider.value = localStorage.getItem('wpmSliderValue');
wpmValue.textContent = wpmSlider.value;
}
if (localStorage.getItem('minDelaySliderValue')) {
minDelaySlider.value = localStorage.getItem('minDelaySliderValue');
MIN_DELAY = parseInt(minDelaySlider.value);
minDelayValue.textContent = `${MIN_DELAY}ms`;
}
if (localStorage.getItem('maxDelaySliderValue')) {
maxDelaySlider.value = localStorage.getItem('maxDelaySliderValue');
MAX_DELAY = parseInt(maxDelaySlider.value);
maxDelayValue.textContent = `${MAX_DELAY}ms`;
}
if (localStorage.getItem('pauseDelaySliderValue')) {
pauseDelaySlider.value = localStorage.getItem('pauseDelaySliderValue');
pauseDelayValue.textContent = `${pauseDelaySlider.value}ms`;
}
if (localStorage.getItem('accuracySliderValue')) {
accuracySlider.value = localStorage.getItem('accuracySliderValue');
accuracyValue.textContent = accuracySlider.value;
}
})();