Greasy Fork is available in English.

MonkeyType AutoTyper Bot

A Bot that automatically types for you in MokeyType.

Pasang skrip ini?
Sugesti pemilik skrip

Kamu mungkin juga suka Vocabulary.com Answer Bot.

Pasang skrip ini
  1. // ==UserScript==
  2. // @name MonkeyType AutoTyper Bot
  3. // @author longkidkoolstar
  4. // @description A Bot that automatically types for you in MokeyType.
  5. // @icon https://th.bing.com/th/id/R.c8397fb766c4397fea8a8b499c15a453?rik=aROX42RoH7HhXw&pid=ImgRaw&r=0
  6. // @version 2.1
  7. // @match *://monkeytype.com/*
  8. // @run-at document-start
  9. // @grant none
  10. // @license MIT
  11. // @namespace https://greatest.deepsurf.us/users/1000020
  12. // ==/UserScript==
  13. /* jshint esversion:6 */
  14.  
  15. (function () {
  16. "use strict";
  17. // Minimum and maximum delay (ms)
  18. let MIN_DELAY = 100;
  19. let MAX_DELAY = 333;
  20. const TOGGLE_KEY = "ArrowRight";
  21. const log = console.log;
  22. function random(min, max) {
  23. return Math.floor(Math.random() * (max - min + 1) + min);
  24. }
  25. let toggle = false;
  26. function canType() {
  27. const typingTest = document.getElementById("typingTest");
  28. const isHidden = typingTest.classList.contains("hidden");
  29. if (isHidden) toggle = false;
  30. return toggle && !isHidden;
  31. }
  32. function getNextCharacter() {
  33. const currentWord = document.querySelector(".word.active");
  34. for (const letter of currentWord.children) {
  35. if (letter.className === "") return letter.textContent;
  36. }
  37. return " ";
  38. }
  39. const InputEvents = {};
  40. function pressKey(key) {
  41. const wordsInput = document.getElementById("wordsInput");
  42. const KeyboardEvent = Object.assign({}, DEFAULT_INPUT_OPTIONS, {
  43. target: wordsInput,
  44. data: key,
  45. });
  46. const InputEvent = Object.assign({}, DEFAULT_KEY_OPTIONS, {
  47. target: wordsInput,
  48. key: key,
  49. });
  50. wordsInput.value += key;
  51. InputEvents.beforeinput(InputEvent);
  52. InputEvents.input(InputEvent);
  53. InputEvents.keyup(KeyboardEvent);
  54. }
  55. function typeCharacter() {
  56. if (!canType()) {
  57. log("STOPPED TYPING TEST");
  58. return;
  59. }
  60. const nextChar = getNextCharacter();
  61. let delay;
  62. // Check which section is currently displayed
  63. const basicSection = document.getElementById("basicSection");
  64. if (basicSection.style.display === "") { // Basic section is displayed
  65. delay = 60000 / (document.getElementById("wpmSlider").value * 5);
  66. } else { // Advanced section is displayed
  67. delay = random(MIN_DELAY, MAX_DELAY);
  68. }
  69. const accuracy = document.getElementById("accuracySlider").value;
  70. // introduce some random errors
  71. if (Math.random() > accuracy) {
  72. // skip this character
  73. setTimeout(typeCharacter, delay);
  74. return;
  75. } else if (Math.random() > accuracy) {
  76. // repeat this character
  77. pressKey(nextChar);
  78. } else if (Math.random() > accuracy) {
  79. // insert a random incorrect character
  80. const adjacentKey = getAdjacentKey(nextChar);
  81. pressKey(adjacentKey);
  82. }
  83. // press the next character
  84. pressKey(nextChar);
  85. // introduce a pause between words
  86. if (nextChar === " ") {
  87. const pauseDelay = document.getElementById("pauseDelaySlider").value;
  88. setTimeout(typeCharacter, pauseDelay);
  89. } else {
  90. setTimeout(typeCharacter, delay);
  91. }
  92. }
  93. function getAdjacentKey(key) {
  94. // Define the adjacent keys for each key
  95. const adjacentKeys = {
  96. "q": ["w", "a"],
  97. "w": ["q", "e", "a", "s"],
  98. "e": ["w", "r", "s", "d"],
  99. "r": ["e", "t", "d", "f"],
  100. "t": ["r", "y", "f", "g"],
  101. "y": ["t", "u", "g", "h"],
  102. "u": ["y", "i", "h", "j"],
  103. "i": ["u", "o", "j", "k"],
  104. "o": ["i", "p", "k", "l"],
  105. "p": ["o", "l"],
  106. "a": ["q", "w", "s", "z"],
  107. "s": ["w", "e", "a", "d", "z", "x"],
  108. "d": ["e", "r", "s", "f", "x", "c"],
  109. "f": ["r", "t", "d", "g", "c", "v"],
  110. "g": ["t", "y", "f", "h", "v", "b"],
  111. "h": ["y", "u", "g", "j", "b", "n"],
  112. "j": ["u", "i", "h", "k", "n", "m"],
  113. "k": ["i", "o", "j", "l", "m"],
  114. "l": ["o", "p", "k"],
  115. "z": ["a", "s", "x"],
  116. "x": ["s", "d", "z", "c"],
  117. "c": ["d", "f", "x", "v"],
  118. "v": ["f", "g", "c", "b"],
  119. "b": ["g", "h", "v", "n"],
  120. "n": ["h", "j", "b", "m"],
  121. "m": ["j", "k", "n"]
  122. };
  123. // Handle space character separately
  124. if (key === " ") {
  125. return " ";
  126. }
  127. // Get the adjacent keys for the given key
  128. const keys = adjacentKeys[key.toLowerCase()];
  129. // Randomly select an adjacent key
  130. const randomIndex = Math.floor(Math.random() * keys.length);
  131. return keys[randomIndex];
  132. }
  133. window.addEventListener("keydown", function (event) {
  134. if (event.code === TOGGLE_KEY) {
  135. event.preventDefault();
  136. if (event.repeat) return;
  137. toggle = !toggle;
  138. if (toggle) {
  139. log("STARTED TYPING TEST");
  140. typeCharacter();
  141. }
  142. }
  143. });
  144. // Intercept when JQuery attached an addEventListener to the Input element
  145. function hook(element) {
  146. element.addEventListener = new Proxy(element.addEventListener, {
  147. apply(target, _this, args) {
  148. const [type, listener, ...options] = args;
  149. if (_this.id === "wordsInput") {
  150. InputEvents[type] = listener;
  151. }
  152. return target.apply(_this, args);
  153. },
  154. });
  155. }
  156. hook(HTMLInputElement.prototype);
  157. const DEFAULT_KEY_OPTIONS = {
  158. key: "",
  159. code: "",
  160. keyCode: 0,
  161. which: 0,
  162. isTrusted: true,
  163. altKey: false,
  164. bubbles: true,
  165. cancelBubble: false,
  166. cancelable: true,
  167. charCode: 0,
  168. composed: true,
  169. ctrlKey: false,
  170. currentTarget: null,
  171. defaultPrevented: false,
  172. detail: 0,
  173. eventPhase: 0,
  174. isComposing: false,
  175. location: 0,
  176. metaKey: false,
  177. path: null,
  178. repeat: false,
  179. returnValue: true,
  180. shiftKey: false,
  181. srcElement: null,
  182. target: null,
  183. timeStamp: 6338.5,
  184. type: "",
  185. view: window,
  186. };
  187. const DEFAULT_INPUT_OPTIONS = {
  188. isTrusted: true,
  189. bubbles: true,
  190. cancelBubble: false,
  191. cancelable: false,
  192. composed: true,
  193. data: "",
  194. dataTransfer: null,
  195. defaultPrevented: false,
  196. detail: 0,
  197. eventPhase: 0,
  198. inputType: "insertText",
  199. isComposing: false,
  200. path: null,
  201. returnValue: true,
  202. sourceCapabilities: null,
  203. srcElement: null,
  204. target: null,
  205. currentTarget: null,
  206. timeStamp: 11543,
  207. type: "input",
  208. view: null,
  209. which: 0,
  210. };
  211. // Add GUI to change min and max delay
  212. const gui = document.createElement("div");
  213. gui.style.position = "fixed";
  214. gui.style.bottom = "30%";
  215. gui.style.right = "0";
  216. gui.style.transform = "translateY(50%)";
  217. gui.style.padding = "5px";
  218. gui.style.background = "rgba(0, 0, 0, 0.6)";
  219. gui.style.color = "white";
  220. gui.style.fontFamily = "sans-serif";
  221. gui.style.fontSize = "12px";
  222. gui.style.zIndex = "9999"; // set z-index to a high value
  223. gui.innerHTML = `
  224. <div style="display: flex; flex-direction: column;">
  225. <div style="margin-bottom: 10px;">
  226. <button id="resetButton">Reset to Default</button>
  227. </div>
  228. <div style="display: flex; flex-direction: column;">
  229. <div style="margin-bottom: 10px;">
  230. <button id="basicButton">Basic</button>
  231. <button id="advancedButton">Advanced</button>
  232. </div>
  233. <div id="basicSection">
  234. <div style="margin-bottom: 5px;">
  235. WPM: <input type="range" id="wpmSlider" value="50" min="10" max="100" step="5" style="width: 100px;">
  236. <span id="wpmValue">50</span>
  237. </div>
  238. </div>
  239. <div id="advancedSection" style="display: none;">
  240. <div style="margin-bottom: 5px;">
  241. Min Delay: <input type="range" id="minDelaySlider" value="${MIN_DELAY}" min="0" max="1000" step="10" style="width: 100px;">
  242. <span id="minDelayValue">${MIN_DELAY}ms</span>
  243. </div>
  244. <div style="margin-bottom: 5px;">
  245. Max Delay: <input type="range" id="maxDelaySlider" value="${MAX_DELAY}" min="0" max="1000" step="10" style="width: 100px;">
  246. <span id="maxDelayValue">${MAX_DELAY}ms</span>
  247. </div>
  248. <div>
  249. Pause Delay: <input type="range" id="pauseDelaySlider" value="${MAX_DELAY}" min="0" max="1000" step="10" style="width: 100px;">
  250. <span id="pauseDelayValue">${MAX_DELAY}ms</span>
  251. </div>
  252. </div>
  253. </div>
  254. <div style="margin-bottom: 5px;">
  255. Accuracy: <input type="range" id="accuracySlider" value="0.1" min="0" max="1" step="0.01" style="width: 100px;">
  256. <span id="accuracyValue">0.1</span>
  257. </div>
  258. `;
  259. document.body.appendChild(gui);
  260. // Add event listeners to toggle the visibility of each section
  261. const basicButton = document.getElementById("basicButton");
  262. const basicSection = document.getElementById("basicSection");
  263. basicButton.addEventListener("click", function() {
  264. basicSection.style.display = "";
  265. advancedSection.style.display = "none";
  266. });
  267. const advancedButton = document.getElementById("advancedButton");
  268. const advancedSection = document.getElementById("advancedSection");
  269. advancedButton.addEventListener("click", function() {
  270. basicSection.style.display = "none";
  271. advancedSection.style.display = "";
  272. });
  273. // Add event listeners to the sliders
  274. const wpmSlider = document.getElementById("wpmSlider");
  275. const wpmValue = document.getElementById("wpmValue");
  276. wpmSlider.addEventListener("input", function() {
  277. wpmValue.textContent = wpmSlider.value;
  278. });
  279. const minDelaySlider = document.getElementById("minDelaySlider");
  280. const minDelayValue = document.getElementById("minDelayValue");
  281. minDelaySlider.addEventListener("input", function() {
  282. MIN_DELAY = parseInt(minDelaySlider.value);
  283. minDelayValue.textContent = `${MIN_DELAY}ms`;
  284. });
  285. const maxDelaySlider = document.getElementById("maxDelaySlider");
  286. const maxDelayValue = document.getElementById("maxDelayValue");
  287. maxDelaySlider.addEventListener("input", function() {
  288. MAX_DELAY = parseInt(maxDelaySlider.value);
  289. maxDelayValue.textContent = `${MAX_DELAY}ms`;
  290. });
  291. const pauseDelaySlider = document.getElementById("pauseDelaySlider");
  292. const pauseDelayValue = document.getElementById("pauseDelayValue");
  293. pauseDelaySlider.addEventListener("input", function() {
  294. pauseDelayValue.textContent = `${pauseDelaySlider.value}ms`;
  295. });
  296. const accuracySlider = document.getElementById("accuracySlider");
  297. const accuracyValue = document.getElementById("accuracyValue");
  298. accuracySlider.addEventListener("input", function() {
  299. accuracyValue.textContent = accuracySlider.value;
  300. });
  301. const resetButton = document.getElementById("resetButton");
  302. resetButton.addEventListener("click", function() {
  303. wpmSlider.value = 40;
  304. minDelaySlider.value = 100;
  305. maxDelaySlider.value = 333;
  306. pauseDelaySlider.value = 100;
  307. accuracySlider.value = 95;
  308. wpmValue.textContent = wpmSlider.value;
  309. minDelayValue.textContent = `${minDelaySlider.value}ms`;
  310. maxDelayValue.textContent = `${maxDelaySlider.value}ms`;
  311. pauseDelayValue.textContent = `${pauseDelaySlider.value}ms`;
  312. accuracyValue.textContent = accuracySlider.value;
  313. // Save default values to localStorage
  314. localStorage.setItem('wpmSliderValue', wpmSlider.value);
  315. localStorage.setItem('minDelaySliderValue', minDelaySlider.value);
  316. localStorage.setItem('maxDelaySliderValue', maxDelaySlider.value);
  317. localStorage.setItem('pauseDelaySliderValue', pauseDelaySlider.value);
  318. localStorage.setItem('accuracySliderValue', accuracySlider.value);
  319. });
  320. function saveSliderValues() {
  321. localStorage.setItem('wpmSliderValue', wpmSlider.value);
  322. localStorage.setItem('minDelaySliderValue', minDelaySlider.value);
  323. localStorage.setItem('maxDelaySliderValue', maxDelaySlider.value);
  324. localStorage.setItem('pauseDelaySliderValue', pauseDelaySlider.value);
  325. localStorage.setItem('accuracySliderValue', accuracySlider.value);
  326. }
  327. wpmSlider.addEventListener('input', function() {
  328. wpmValue.textContent = wpmSlider.value;
  329. saveSliderValues();
  330. });
  331. minDelaySlider.addEventListener('input', function() {
  332. MIN_DELAY = parseInt(minDelaySlider.value);
  333. minDelayValue.textContent = `${MIN_DELAY}ms`;
  334. saveSliderValues();
  335. });
  336. maxDelaySlider.addEventListener('input', function() {
  337. MAX_DELAY = parseInt(maxDelaySlider.value);
  338. maxDelayValue.textContent = `${MAX_DELAY}ms`;
  339. saveSliderValues();
  340. });
  341. pauseDelaySlider.addEventListener('input', function() {
  342. pauseDelayValue.textContent = `${pauseDelaySlider.value}ms`;
  343. saveSliderValues();
  344. });
  345. accuracySlider.addEventListener('input', function() {
  346. accuracyValue.textContent = accuracySlider.value;
  347. saveSliderValues();
  348. });
  349. // Retrieve slider values from localStorage
  350. if (localStorage.getItem('wpmSliderValue')) {
  351. wpmSlider.value = localStorage.getItem('wpmSliderValue');
  352. wpmValue.textContent = wpmSlider.value;
  353. }
  354. if (localStorage.getItem('minDelaySliderValue')) {
  355. minDelaySlider.value = localStorage.getItem('minDelaySliderValue');
  356. MIN_DELAY = parseInt(minDelaySlider.value);
  357. minDelayValue.textContent = `${MIN_DELAY}ms`;
  358. }
  359. if (localStorage.getItem('maxDelaySliderValue')) {
  360. maxDelaySlider.value = localStorage.getItem('maxDelaySliderValue');
  361. MAX_DELAY = parseInt(maxDelaySlider.value);
  362. maxDelayValue.textContent = `${MAX_DELAY}ms`;
  363. }
  364. if (localStorage.getItem('pauseDelaySliderValue')) {
  365. pauseDelaySlider.value = localStorage.getItem('pauseDelaySliderValue');
  366. pauseDelayValue.textContent = `${pauseDelaySlider.value}ms`;
  367. }
  368. if (localStorage.getItem('accuracySliderValue')) {
  369. accuracySlider.value = localStorage.getItem('accuracySliderValue');
  370. accuracyValue.textContent = accuracySlider.value;
  371. }
  372. })();