Human-Typer by Warrior

Simulate human typing in Google Docs and Slides with customizable settings such as typing speed, errors, and breaks.

目前為 2024-04-27 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Human-Typer by Warrior
  3. // @description Simulate human typing in Google Docs and Slides with customizable settings such as typing speed, errors, and breaks.
  4. // @version 1.2
  5. // @namespace http://yournamespace.com/human-typer
  6. // @match *://docs.google.com/document/*
  7. // @match *://docs.google.com/presentation/*
  8. // @include *://docs.google.com/document/*
  9. // @include *://docs.google.com/presentation/*
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13.  
  14. (function() {
  15. 'use strict';
  16.  
  17. // Check if the URL indicates the current page is a Google Docs or Google Slides page
  18. if (window.location.href.includes("docs.google.com/document/d") || window.location.href.includes("docs.google.com/presentation/d")) {
  19. // Create a black button on the toolbar next to the "Help" button
  20. const toolbar = document.querySelector('.docs-material .docs-titlebar-right');
  21. if (toolbar) {
  22. const blackButton = document.createElement("div");
  23. blackButton.textContent = "Human-Typer";
  24. blackButton.style.backgroundColor = "black";
  25. blackButton.style.color = "white";
  26. blackButton.style.padding = "10px 20px";
  27. blackButton.style.borderRadius = "5px";
  28. blackButton.style.cursor = "pointer";
  29. blackButton.style.marginLeft = "10px"; // Add margin to separate from other toolbar items
  30. blackButton.id = "human-typer-button";
  31. toolbar.appendChild(blackButton);
  32.  
  33. // Function to create and display the UI overlay
  34. function showUIOverlay() {
  35. const overlay = document.createElement("div");
  36. overlay.id = "human-typer-overlay";
  37. overlay.style.position = "fixed";
  38. overlay.style.bottom = "10px";
  39. overlay.style.right = "10px";
  40. overlay.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
  41. overlay.style.padding = "15px";
  42. overlay.style.borderRadius = "8px";
  43. overlay.style.boxShadow = "0px 2px 10px rgba(0, 0, 0, 0.1)";
  44. overlay.style.zIndex = "9999";
  45. overlay.style.display = "flex";
  46. overlay.style.flexDirection = "column";
  47. overlay.style.width = "250px";
  48.  
  49. // Text input field for user input
  50. const textInput = document.createElement("textarea");
  51. textInput.rows = "4";
  52. textInput.placeholder = "Enter text to type...";
  53. textInput.style.marginBottom = "10px";
  54. textInput.style.width = "100%";
  55. textInput.style.padding = "8px";
  56. textInput.style.border = "1px solid #ccc";
  57. textInput.style.borderRadius = "4px";
  58.  
  59. // Typing speed customization
  60. const speedLabel = document.createElement("p");
  61. speedLabel.textContent = "Typing speed:";
  62. const speedSelect = document.createElement("select");
  63. speedSelect.options.add(new Option("Fast", "fast"));
  64. speedSelect.options.add(new Option("Medium", "medium"));
  65. speedSelect.options.add(new Option("Normal", "normal"));
  66. speedSelect.options.add(new Option("Slow", "slow"));
  67.  
  68. // Typing error customization
  69. const errorLabel = document.createElement("p");
  70. errorLabel.textContent = "Number of typing errors:";
  71. const errorInput = document.createElement("input");
  72. errorInput.type = "number";
  73. errorInput.min = "0";
  74. errorInput.value = "0";
  75.  
  76. // Break time customization
  77. const breakLabel = document.createElement("p");
  78. breakLabel.textContent = "Number of breaks:";
  79. const breakInput = document.createElement("input");
  80. breakInput.type = "number";
  81. breakInput.min = "0";
  82. breakInput.value = "0";
  83.  
  84. const breakDurationLabel = document.createElement("p");
  85. breakDurationLabel.textContent = "Duration of each break (minutes):";
  86. const breakDurationInput = document.createElement("input");
  87. breakDurationInput.type = "number";
  88. breakDurationInput.min = "0";
  89. breakDurationInput.value = "0";
  90.  
  91. // Confirm button to start typing
  92. const confirmButton = document.createElement("button");
  93. confirmButton.textContent = "Start Typing";
  94. confirmButton.style.padding = "8px 16px";
  95. confirmButton.style.backgroundColor = "#1a73e8";
  96. confirmButton.style.color = "white";
  97. confirmButton.style.border = "none";
  98. confirmButton.style.borderRadius = "4px";
  99. confirmButton.style.cursor = "pointer";
  100.  
  101. // Append elements to the overlay
  102. overlay.appendChild(textInput);
  103. overlay.appendChild(speedLabel);
  104. overlay.appendChild(speedSelect);
  105. overlay.appendChild(errorLabel);
  106. overlay.appendChild(errorInput);
  107. overlay.appendChild(breakLabel);
  108. overlay.appendChild(breakInput);
  109. overlay.appendChild(breakDurationLabel);
  110. overlay.appendChild(breakDurationInput);
  111. overlay.appendChild(confirmButton);
  112.  
  113. // Append the overlay to the body
  114. document.body.appendChild(overlay);
  115.  
  116. // Event listener for the confirm button
  117. confirmButton.addEventListener("click", () => {
  118. const text = textInput.value.trim();
  119. const speed = speedSelect.value;
  120. const numErrors = parseInt(errorInput.value);
  121. const numBreaks = parseInt(breakInput.value);
  122. const breakDuration = parseInt(breakDurationInput.value);
  123.  
  124. // If text is empty, do nothing
  125. if (!text) return;
  126.  
  127. // Remove the overlay from the page
  128. document.body.removeChild(overlay);
  129.  
  130. // Call function to start typing
  131. startTyping(text, speed, numErrors, numBreaks, breakDuration);
  132. });
  133. }
  134.  
  135. // Event listener for the black button
  136. blackButton.addEventListener("click", () => {
  137. // Show the UI overlay when the black button is clicked
  138. showUIOverlay();
  139. });
  140.  
  141. // Function to simulate typing with errors and breaks
  142. function startTyping(text, speed, numErrors, numBreaks, breakDuration) {
  143. const inputElement = document.querySelector(".docs-texteventtarget-iframe").contentDocument.activeElement;
  144. const speedSettings = {
  145. fast: { lowerBound: 50, upperBound: 150 },
  146. medium: { lowerBound: 60, upperBound: 220 },
  147. normal: { lowerBound: 70, upperBound: 200 },
  148. slow: { lowerBound: 80, upperBound: 250 }
  149. };
  150.  
  151. const lowerBound = speedSettings[speed].lowerBound;
  152. const upperBound = speedSettings[speed].upperBound;
  153.  
  154. let currentErrorCount = 0;
  155. let currentBreakCount = 0;
  156. let breakInterval = Math.floor(text.length / numBreaks);
  157. let breakTime = breakDuration * 60 * 1000; // Convert break duration from minutes to milliseconds
  158.  
  159. async function typeCharacter(character, delay) {
  160. return new Promise((resolve) => {
  161. if (currentErrorCount < numErrors && Math.random() < 0.05) {
  162. // Introduce a random typing error
  163. inputElement.value += character;
  164. inputElement.value = inputElement.value.slice(0, -2);
  165. currentErrorCount++;
  166. } else {
  167. inputElement.value += character;
  168. }
  169.  
  170. setTimeout(resolve, delay);
  171. });
  172. }
  173.  
  174. async function typeText(text) {
  175. for (let i = 0; i < text.length; i++) {
  176. const delay = Math.floor(Math.random() * (upperBound - lowerBound + 1)) + lowerBound;
  177.  
  178. if (currentBreakCount < numBreaks && i > 0 && i % breakInterval === 0) {
  179. // Take a break
  180. await new Promise((resolve) => setTimeout(resolve, breakTime));
  181. currentBreakCount++;
  182. }
  183.  
  184. await typeCharacter(text[i], delay);
  185. }
  186. }
  187.  
  188. // Start typing the text
  189. typeText(text);
  190. }
  191. }
  192. }
  193. })();