Human-Typer for Google Docs/Slides

Simulate human typing in Google Docs and Google Slides with customizable options.

目前为 2024-09-07 提交的版本。查看 最新版本

// ==UserScript==
// @name         Human-Typer for Google Docs/Slides
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Simulate human typing in Google Docs and Google Slides with customizable options.
// @author       Your Name
// @match        https://docs.google.com/*
// @match        https://slides.google.com/*
// @grant        none
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// ==/UserScript==

(function() {
    'use strict';

    // Constants
    const TYPING_SPEEDS = {
        fast: [50, 100],
        medium: [100, 200],
        normal: [200, 300],
        slow: [300, 500]
    };

    let settings = {
        text: "",
        speed: "normal",
        errorRate: 0,
        breakTime: 1, // minutes
        breakCount: 1
    };

    function addButton() {
        const toolbar = document.querySelector('.docs-titlebar');
        if (toolbar && !document.querySelector('#human-typer-button')) {
            const button = document.createElement('button');
            button.id = 'human-typer-button';
            button.textContent = 'Human-Typer';
            button.style.margin = '0 10px';
            button.onclick = openSettingsOverlay;
            toolbar.appendChild(button);
        }
    }

    function openSettingsOverlay() {
        if (document.querySelector('#human-typer-overlay')) return;

        const overlay = document.createElement('div');
        overlay.id = 'human-typer-overlay';
        overlay.style.position = 'fixed';
        overlay.style.top = '50px';
        overlay.style.right = '50px';
        overlay.style.backgroundColor = '#fff';
        overlay.style.border = '1px solid #ccc';
        overlay.style.padding = '20px';
        overlay.style.zIndex = 1000;

        overlay.innerHTML = `
            <h3>Human-Typer Settings</h3>
            <label for="ht-text">Text:</label><br>
            <textarea id="ht-text" rows="4" cols="30"></textarea><br><br>
            <label for="ht-speed">Typing Speed:</label><br>
            <select id="ht-speed">
                <option value="fast">Fast</option>
                <option value="medium">Medium</option>
                <option value="normal" selected>Normal</option>
                <option value="slow">Slow</option>
            </select><br><br>
            <label for="ht-error-rate">Error Rate (%):</label><br>
            <input type="number" id="ht-error-rate" min="0" max="20" value="0"><br><br>
            <label for="ht-break-time">Break Time (minutes):</label><br>
            <input type="number" id="ht-break-time" min="0" value="1"><br><br>
            <label for="ht-break-count">Break Count:</label><br>
            <input type="number" id="ht-break-count" min="0" value="1"><br><br>
            <button id="ht-start-typing">Start Typing</button>
            <button id="ht-close">Close</button>
        `;

        document.body.appendChild(overlay);
        document.getElementById('ht-text').value = settings.text;
        document.getElementById('ht-speed').value = settings.speed;
        document.getElementById('ht-error-rate').value = settings.errorRate;
        document.getElementById('ht-break-time').value = settings.breakTime;
        document.getElementById('ht-break-count').value = settings.breakCount;

        document.getElementById('ht-start-typing').onclick = startTyping;
        document.getElementById('ht-close').onclick = () => overlay.remove();
    }

    function startTyping() {
        settings.text = document.getElementById('ht-text').value;
        settings.speed = document.getElementById('ht-speed').value;
        settings.errorRate = parseInt(document.getElementById('ht-error-rate').value, 10);
        settings.breakTime = parseInt(document.getElementById('ht-break-time').value, 10) * 60000; // convert to ms
        settings.breakCount = parseInt(document.getElementById('ht-break-count').value, 10);

        document.getElementById('human-typer-overlay').remove();
        typeText();
    }

    function typeText() {
        const typingArea = document.activeElement;
        const text = settings.text.split('');
        const [minDelay, maxDelay] = TYPING_SPEEDS[settings.speed];
        const totalBreaks = settings.breakCount;
        let breakInterval = settings.breakTime / totalBreaks;
        let currentBreak = 0;

        function typeNextChar() {
            if (text.length === 0) return;

            let char = text.shift();
            if (Math.random() * 100 < settings.errorRate) {
                char = String.fromCharCode(Math.random() * (126 - 33) + 33); // Random char
            }
            typingArea.focus();
            typingArea.dispatchEvent(new KeyboardEvent('keydown', { key: char }));
            typingArea.dispatchEvent(new KeyboardEvent('keypress', { key: char }));
            typingArea.dispatchEvent(new KeyboardEvent('keyup', { key: char }));
            typingArea.textContent += char;

            let delay = Math.floor(Math.random() * (maxDelay - minDelay + 1)) + minDelay;
            setTimeout(() => {
                if (text.length === 0 && currentBreak < totalBreaks) {
                    currentBreak++;
                    setTimeout(typeNextChar, breakInterval);
                } else {
                    typeNextChar();
                }
            }, delay);
        }

        typeNextChar();
    }

    window.addEventListener('load', addButton);
})();