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 1.5
  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 = "10%";
  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="basicButton">Basic</button>
  205. <button id="advancedButton">Advanced</button>
  206. </div>
  207. <div id="basicSection">
  208. <div style="margin-bottom: 5px;">
  209. WPM: <input type="range" id="wpmSlider" value="50" min="10" max="100" step="5" style="width: 100px;">
  210. <span id="wpmValue">50</span>
  211. </div>
  212. </div>
  213. <div id="advancedSection" style="display: none;">
  214. <div style="margin-bottom: 5px;">
  215. Min Delay: <input type="range" id="minDelaySlider" value="${MIN_DELAY}" min="0" max="1000" step="10" style="width: 100px;">
  216. <span id="minDelayValue">${MIN_DELAY}ms</span>
  217. </div>
  218. <div style="margin-bottom: 5px;">
  219. Max Delay: <input type="range" id="maxDelaySlider" value="${MAX_DELAY}" min="0" max="1000" step="10" style="width: 100px;">
  220. <span id="maxDelayValue">${MAX_DELAY}ms</span>
  221. </div>
  222. <div>
  223. Pause Delay: <input type="range" id="pauseDelaySlider" value="${MAX_DELAY}" min="0" max="1000" step="10" style="width: 100px;">
  224. <span id="pauseDelayValue">${MAX_DELAY}ms</span>
  225. </div>
  226. </div>
  227. </div>
  228. <div style="margin-bottom: 5px;">
  229. Accuracy: <input type="range" id="accuracySlider" value="0.1" min="0" max="1" step="0.1" style="width: 100px;">
  230. <span id="accuracyValue">0.1</span>
  231. </div>
  232. `;
  233. document.body.appendChild(gui);
  234.  
  235. // Add event listeners to toggle the visibility of each section
  236. const basicButton = document.getElementById("basicButton");
  237. const basicSection = document.getElementById("basicSection");
  238. basicButton.addEventListener("click", function() {
  239. basicSection.style.display = "";
  240. advancedSection.style.display = "none";
  241. });
  242.  
  243. const advancedButton = document.getElementById("advancedButton");
  244. const advancedSection = document.getElementById("advancedSection");
  245. advancedButton.addEventListener("click", function() {
  246. basicSection.style.display = "none";
  247. advancedSection.style.display = "";
  248. });
  249.  
  250. // Add event listeners to the sliders
  251. const wpmSlider = document.getElementById("wpmSlider");
  252. const wpmValue = document.getElementById("wpmValue");
  253. wpmSlider.addEventListener("input", function() {
  254. wpmValue.textContent = wpmSlider.value;
  255. });
  256.  
  257. const minDelaySlider = document.getElementById("minDelaySlider");
  258. const minDelayValue = document.getElementById("minDelayValue");
  259. minDelaySlider.addEventListener("input", function() {
  260. MIN_DELAY = parseInt(minDelaySlider.value);
  261. minDelayValue.textContent = `${MIN_DELAY}ms`;
  262. });
  263.  
  264. const maxDelaySlider = document.getElementById("maxDelaySlider");
  265. const maxDelayValue = document.getElementById("maxDelayValue");
  266. maxDelaySlider.addEventListener("input", function() {
  267. MAX_DELAY = parseInt(maxDelaySlider.value);
  268. maxDelayValue.textContent = `${MAX_DELAY}ms`;
  269. });
  270.  
  271. const pauseDelaySlider = document.getElementById("pauseDelaySlider");
  272. const pauseDelayValue = document.getElementById("pauseDelayValue");
  273. pauseDelaySlider.addEventListener("input", function() {
  274. pauseDelayValue.textContent = `${pauseDelaySlider.value}ms`;
  275. });
  276.  
  277. const accuracySlider = document.getElementById("accuracySlider");
  278. const accuracyValue = document.getElementById("accuracyValue");
  279. accuracySlider.addEventListener("input", function() {
  280. accuracyValue.textContent = accuracySlider.value;
  281. });
  282.  
  283. })();