// ==UserScript==
// @name Human-Typer by Warrior
// @description Simulate human typing in Google Docs and Slides with customizable settings such as typing speed, errors, and breaks.
// @version 1.3
// @namespace http://yournamespace.com/human-typer
// @match *://docs.google.com/document/*
// @match *://docs.google.com/presentation/*
// @include *://docs.google.com/document/*
// @include *://docs.google.com/presentation/*
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// Function to create a button on the Google Docs/Slides toolbar
function createButton() {
const toolbar = document.querySelector('.docs-titlebar-right');
if (!toolbar) {
return;
}
const button = document.createElement("button");
button.textContent = "Human-Typer";
button.style.marginLeft = "10px";
button.style.backgroundColor = "#000";
button.style.color = "#fff";
button.style.border = "none";
button.style.padding = "8px 12px";
button.style.borderRadius = "4px";
button.style.cursor = "pointer";
button.id = "human-typer-button";
// Add event listener to show UI overlay when button is clicked
button.addEventListener("click", showUIOverlay);
toolbar.appendChild(button);
}
// Function to create and display the UI overlay for user customization
function showUIOverlay() {
// Check if an overlay already exists; if so, remove it
const existingOverlay = document.getElementById("human-typer-overlay");
if (existingOverlay) {
document.body.removeChild(existingOverlay);
return;
}
// Create an overlay div for user input and customization options
const overlay = document.createElement("div");
overlay.id = "human-typer-overlay";
overlay.style.position = "fixed";
overlay.style.bottom = "10px";
overlay.style.right = "10px";
overlay.style.backgroundColor = "rgba(255, 255, 255, 0.9)";
overlay.style.padding = "20px";
overlay.style.border = "1px solid #ccc";
overlay.style.borderRadius = "8px";
overlay.style.boxShadow = "0px 2px 8px rgba(0, 0, 0, 0.1)";
overlay.style.zIndex = "10000";
// Create input field for text input
const textInput = document.createElement("textarea");
textInput.rows = "4";
textInput.placeholder = "Enter text to type...";
textInput.style.width = "100%";
textInput.style.marginBottom = "10px";
textInput.style.padding = "8px";
textInput.style.border = "1px solid #ccc";
textInput.style.borderRadius = "4px";
// Create dropdown for typing speed selection
const speedLabel = document.createElement("p");
speedLabel.textContent = "Typing Speed:";
const speedSelect = document.createElement("select");
speedSelect.options.add(new Option("Fast", "fast"));
speedSelect.options.add(new Option("Medium", "medium"));
speedSelect.options.add(new Option("Normal", "normal"));
speedSelect.options.add(new Option("Slow", "slow"));
speedSelect.style.marginBottom = "10px";
// Create input for number of typing errors
const errorLabel = document.createElement("p");
errorLabel.textContent = "Number of Typing Errors:";
const errorInput = document.createElement("input");
errorInput.type = "number";
errorInput.min = "0";
errorInput.value = "0";
errorInput.style.width = "100%";
errorInput.style.marginBottom = "10px";
errorInput.style.padding = "8px";
errorInput.style.border = "1px solid #ccc";
errorInput.style.borderRadius = "4px";
// Create input for the number of breaks
const breakLabel = document.createElement("p");
breakLabel.textContent = "Number of Breaks:";
const breakInput = document.createElement("input");
breakInput.type = "number";
breakInput.min = "0";
breakInput.value = "0";
breakInput.style.width = "100%";
breakInput.style.marginBottom = "10px";
breakInput.style.padding = "8px";
breakInput.style.border = "1px solid #ccc";
breakInput.style.borderRadius = "4px";
// Create input for the duration of each break in minutes
const breakDurationLabel = document.createElement("p");
breakDurationLabel.textContent = "Duration of Each Break (minutes):";
const breakDurationInput = document.createElement("input");
breakDurationInput.type = "number";
breakDurationInput.min = "0";
breakDurationInput.value = "0";
breakDurationInput.style.width = "100%";
breakDurationInput.style.marginBottom = "10px";
breakDurationInput.style.padding = "8px";
breakDurationInput.style.border = "1px solid #ccc";
breakDurationInput.style.borderRadius = "4px";
// Create a button to start typing
const startButton = document.createElement("button");
startButton.textContent = "Start Typing";
startButton.style.padding = "8px 16px";
startButton.style.backgroundColor = "#1a73e8";
startButton.style.color = "#fff";
startButton.style.border = "none";
startButton.style.borderRadius = "4px";
startButton.style.cursor = "pointer";
// Append elements to the overlay
overlay.appendChild(textInput);
overlay.appendChild(speedLabel);
overlay.appendChild(speedSelect);
overlay.appendChild(errorLabel);
overlay.appendChild(errorInput);
overlay.appendChild(breakLabel);
overlay.appendChild(breakInput);
overlay.appendChild(breakDurationLabel);
overlay.appendChild(breakDurationInput);
overlay.appendChild(startButton);
// Append the overlay to the body
document.body.appendChild(overlay);
// Add an event listener to the start button
startButton.addEventListener("click", () => {
// Get user input values from the overlay
const text = textInput.value.trim();
const speed = speedSelect.value;
const numErrors = parseInt(errorInput.value);
const numBreaks = parseInt(breakInput.value);
const breakDuration = parseInt(breakDurationInput.value);
// Remove the overlay from the page
document.body.removeChild(overlay);
// Call function to start typing with user-defined options
startTyping(text, speed, numErrors, numBreaks, breakDuration);
});
}
// Function to simulate typing with errors and breaks
function startTyping(text, speed, numErrors, numBreaks, breakDuration) {
// Select the active element in the iframe to simulate typing
const inputElement = document.querySelector(".docs-texteventtarget-iframe").contentDocument.activeElement;
// Define speed settings based on user choice
const speedSettings = {
fast: { lowerBound: 50, upperBound: 150 },
medium: { lowerBound: 60, upperBound: 220 },
normal: { lowerBound: 70, upperBound: 200 },
slow: { lowerBound: 80, upperBound: 250 }
};
// Get the lower and upper bounds for the chosen typing speed
const lowerBound = speedSettings[speed].lowerBound;
const upperBound = speedSettings[speed].upperBound;
let currentErrorCount = 0; // Track current error count
let currentBreakCount = 0; // Track current break count
// Calculate interval for breaks based on the number of breaks
let breakInterval = numBreaks > 0 ? Math.floor(text.length / numBreaks) : text.length;
// Convert break duration from minutes to milliseconds
let breakTime = breakDuration * 60 * 1000;
// Function to type a character with optional errors and delay
async function typeCharacter(character, delay) {
return new Promise((resolve) => {
if (currentErrorCount < numErrors && Math.random() < 0.05) {
// Introduce a random typing error
inputElement.value += character;
inputElement.value = inputElement.value.slice(0, -2);
currentErrorCount++;
} else {
inputElement.value += character;
}
setTimeout(resolve, delay);
});
}
// Function to type the text with the defined speed, errors, and breaks
async function typeText(text) {
for (let i = 0; i < text.length; i++) {
// Generate a random delay based on the chosen speed
const delay = Math.floor(Math.random() * (upperBound - lowerBound + 1)) + lowerBound;
// Check if it's time to take a break
if (currentBreakCount < numBreaks && i > 0 && i % breakInterval === 0) {
// Take a break
await new Promise((resolve) => setTimeout(resolve, breakTime));
currentBreakCount++;
}
// Type the current character with a delay
await typeCharacter(text[i], delay);
}
}
// Start typing the text
typeText(text);
}
// Create the button on the toolbar
createButton();
})();