MonkeyType AutoTyper Bot

A Bot that automatically types for you in MokeyType.

目前为 2023-05-06 提交的版本。查看 最新版本

// ==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.0
// @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 randomChar = String.fromCharCode(random(97, 122));
  pressKey(randomChar);
}

  // 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);
  }
}
  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;
}

})();