MonkeyType AutoTyper Bot

A Bot that automatically types for you in MokeyType.

当前为 2023-05-06 提交的版本,查看 最新版本

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