MonkeyType AutoTyper Bot

Combines the working V6.2 engine with V6.6 features and anti-cheat bypass.

Du musst eine Erweiterung wie Tampermonkey, Greasemonkey oder Violentmonkey installieren, um dieses Skript zu installieren.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

Sie müssten eine Skript Manager Erweiterung installieren damit sie dieses Skript installieren können

(Ich habe schon ein Skript Manager, Lass mich es installieren!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         MonkeyType AutoTyper Bot
// @namespace    https://greasyfork.org/users/1546585
// @version      6.9
// @description  Combines the working V6.2 engine with V6.6 features and anti-cheat bypass.
// @author       greedism
// @match        *://monkeytype.com/*
// @run-at       document-end
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    "use strict";

    class AutoTyper {
        constructor() {
            this.isTyping = false;
            this.timeoutId = null;
            this.isHidden = false;
            this.wpmHistory = [];
            this.stats = { charsTyped: 0, errors: 0, startTime: null };
            
            this.loadSettings();
            this.init();
        }

        loadSettings() {
            // grab saved stuff, or use defaults if first time
            const sWpm = localStorage.getItem('mt-bot-wpm');
            const sAcc = localStorage.getItem('mt-bot-acc');
            const sDelay = localStorage.getItem('mt-bot-delay');
            
            this.config = {
                accuracy: sAcc ? parseFloat(sAcc) : 0.97,
                wpm: sWpm ? parseInt(sWpm) : 80,
                startDelay: sDelay ? parseInt(sDelay) : 500,
                humanMode: true
            };
        }

        init() {
            this.createGUI();
            this.makeDraggable(document.getElementById('monkeytype-autotyper-gui'));
            console.log("MT-Bot: Engine V6.9 Ready.");
        }

        getNextCharacter() {
            const word = document.querySelector(".word.active");
            if (!word) return " ";
            // loop through letters to find the one without a status class
            const letters = word.children;
            for (let i = 0; i < letters.length; i++) {
                if (letters[i].className === "" || letters[i].classList.contains("letter")) {
                    return letters[i].textContent;
                }
            }
            return " ";
        }

        pressKey(k) {
            const input = document.getElementById("wordsInput");
            if (!input) return;

            const evInit = {
                key: k,
                code: k === " " ? "Space" : `Key${k.toUpperCase()}`,
                bubbles: true,
                cancelable: true,
                composed: true,
                which: k.charCodeAt(0),
                keyCode: k.charCodeAt(0)
            };

            input.dispatchEvent(new KeyboardEvent('keydown', evInit));
            
            // update the hidden input field so monkeytype sees it
            if (k !== " ") {
                input.value += k;
            } else {
                input.value = "";
            }

            input.dispatchEvent(new InputEvent('input', { 
                inputType: 'insertText', 
                data: k, 
                bubbles: true 
            }));
            
            input.dispatchEvent(new KeyboardEvent('keyup', evInit));
        }

        getHumanDelay(base, char) {
            const sd = base * 0.25;
            const u1 = Math.random();
            const u2 = Math.random();
            // normal distribution randomizer
            const z = Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(2.0 * Math.PI * u2);
            let d = base + z * sd;

            // Speed up common bigrams - feels more like a real typist
            const common = ['th', 'he', 'in', 'er', 'an', 're', 'on', 'at', 'nd'];
            if (common.includes((this.lastChar || '') + char)) {
                d *= 0.62; 
            }

            // Random micro-pause (distraction/stumble simulation)
            if (Math.random() < 0.012) {
                d += (Math.random() * 250) + 150;
            }

            // Fatigue logic: slow down slightly as the test goes on
            const fatigue = 1 + (this.stats.charsTyped / 2200); 
            d *= fatigue;

            if (char === " ") d += (Math.random() * 140) + 45;

            this.lastChar = char;
            return Math.max(d, 24); 
        }

        typeCharacter() {
            if (!this.canType()) { this.stopTyping(); return; }
            
            const char = this.getNextCharacter();
            this.stats.charsTyped++;

            // Mistake Simulation
            if (Math.random() > this.config.accuracy) {
                this.stats.errors++;
                const chars = "abcdefghijklmnopqrstuvwxyz";
                const wrong = chars.charAt(Math.floor(Math.random() * chars.length));
                
                this.pressKey(wrong);
                
                // human-like reaction time to realize a mistake happened
                this.timeoutId = setTimeout(() => {
                    this.pressKey("Backspace");
                    this.timeoutId = setTimeout(() => this.typeCharacter(), this.getHumanDelay(115, char));
                }, 90 + Math.random() * 110);
                return;
            } else {
                this.pressKey(char);
            }

            let bDelay = (60000 / (this.config.wpm * 5));
            let finalD = this.config.humanMode ? this.getHumanDelay(bDelay, char) : bDelay;

            this.updateStats();
            this.timeoutId = setTimeout(() => this.typeCharacter(), finalD);
        }

        toggleTyping() {
            const btn = document.getElementById('mainStartBtn');
            if (!this.isTyping) {
                this.updateStatusText('Preparing...', '#e2b714');
                setTimeout(() => {
                    this.isTyping = true;
                    this.wpmHistory = [];
                    this.stats = { charsTyped: 0, errors: 0, startTime: Date.now() };
                    btn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3"><rect x="4" y="4" width="16" height="16" rx="2"></rect></svg> STOP`;
                    btn.style.color = "#ff4444";
                    this.typeCharacter();
                }, this.config.startDelay);
            } else {
                this.stopTyping();
            }
        }

        stopTyping() {
            this.isTyping = false;
            clearTimeout(this.timeoutId);
            const btn = document.getElementById('mainStartBtn');
            if (btn) {
                btn.innerHTML = `<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg> START`;
                btn.style.color = "#fff";
            }
            this.updateStatusText('Ready', '#444');
        }

        updateStats() {
            const diff = (Date.now() - this.stats.startTime) / 1000;
            const wpm = Math.round((this.stats.charsTyped / 5) / (diff / 60)) || 0;
            document.getElementById('w-val').innerText = wpm;
            
            if (Math.floor(diff) > this.wpmHistory.length) {
                this.wpmHistory.push(wpm);
                if (this.wpmHistory.length > 25) this.wpmHistory.shift();
                this.drawGraph();
            }
            this.updateStatusText('<span class="pulse">●</span> Typing...', '#fff');
        }

        drawGraph() {
            const svg = document.getElementById('wpm-graph');
            if (!svg || this.wpmHistory.length < 2) return;
            const max = Math.max(...this.wpmHistory, 150);
            const pts = this.wpmHistory.map((w, i) => `${(i / (this.wpmHistory.length - 1)) * 240},${40 - (w / max) * 40}`).join(' ');
            svg.innerHTML = `<polyline points="${pts}" fill="none" stroke="#e2b714" stroke-width="2" stroke-linejoin="round" />`;
        }

        updateStatusText(t, c) { 
            const s = document.getElementById('status');
            if (s) { s.innerHTML = t; s.style.color = c; }
        }

        canType() { return !!document.querySelector('.word.active'); }

        makeDraggable(el) {
            let p1 = 0, p2 = 0, p3 = 0, p4 = 0;
            const h = document.getElementById('gui-header');
            h.onmousedown = (e) => {
                if (e.target.tagName === 'BUTTON' || e.target.tagName === 'INPUT') return;
                p3 = e.clientX; p4 = e.clientY;
                document.onmouseup = () => { document.onmouseup = null; document.onmousemove = null; };
                document.onmousemove = (ev) => {
                    p1 = p3 - ev.clientX; p2 = p4 - ev.clientY;
                    p3 = ev.clientX; p4 = ev.clientY;
                    el.style.top = (el.offsetTop - p2) + "px"; 
                    el.style.left = (el.offsetLeft - p1) + "px";
                    el.style.bottom = "auto"; el.style.right = "auto";
                };
            };
        }

        createGUI() {
            const gui = document.createElement('div');
            gui.id = 'monkeytype-autotyper-gui';
            gui.style.cssText = `position:fixed;top:100px;right:20px;width:280px;background:rgba(10,10,10,0.98);border:1px solid #222;border-radius:12px;color:#fff;font-family:'Lexend Deca',sans-serif;z-index:100000;backdrop-filter:blur(10px);box-shadow:0 10px 40px #000;`;

            gui.innerHTML = `
                <div id="gui-header" style="padding:12px;background:#111;border-radius:12px 12px 0 0;cursor:move;display:flex;justify-content:space-between;border-bottom:1px solid #222;font-size:11px;color:#e2b714;font-weight:bold;align-items:center;">
                    <span>MONKEY BOT STEALTH V6.9</span>
                    <button id="hideBtn" style="background:none;border:none;color:#444;cursor:pointer;font-size:9px;">HIDE</button>
                </div>
                <div style="padding:15px;">
                    <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:15px;">
                        <div class="stat-card">WPM <b id="w-val">0</b></div>
                        <div class="stat-card">ACC <b id="a-val">${Math.round(this.config.accuracy*100)}%</b></div>
                    </div>
                    
                    <div class="ctrl">
                        <label>Target WPM: <span id="v-wpm">${this.config.wpm}</span></label>
                        <input type="range" id="s-wpm" min="10" max="350" value="${this.config.wpm}">
                    </div>

                    <div class="ctrl">
                        <label>Start Delay:</label>
                        <div style="display:flex;gap:5px;margin-top:5px;">
                            <button class="d-btn ${this.config.startDelay === 0 ? 'active' : ''}" data-ms="0">Instant</button>
                            <button class="d-btn ${this.config.startDelay === 500 ? 'active' : ''}" data-ms="500">Normal</button>
                            <button class="d-btn ${this.config.startDelay === 2000 ? 'active' : ''}" data-ms="2000">Slow</button>
                        </div>
                    </div>

                    <button id="mainStartBtn"><svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg> START</button>
                    
                    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px;">
                        <button id="exportBtn" class="sec-btn">EXPORT</button>
                        <button id="importBtn" class="sec-btn">IMPORT</button>
                    </div>

                    <div style="background:#000; border: 1px solid #111; border-radius: 8px; height: 40px; margin-top: 15px; position:relative; overflow:hidden;">
                        <svg id="wpm-graph" width="240" height="40" style="position:absolute;left:5px;"></svg>
                    </div>

                    <div id="status" style="text-align:center;font-size:10px;color:#444;margin-top:10px;">Ready</div>
                </div>
                <style>
                    .stat-card { background:#000; padding:10px; border-radius:8px; border:1px solid #1a1a1a; text-align:center; font-size:10px; color:#555; }
                    .stat-card b { display:block; font-size:16px; color:#fff; }
                    .ctrl { margin-bottom:12px; }
                    .ctrl label { font-size:10px; color:#888; display:flex; justify-content:space-between; }
                    .ctrl label span { color:#e2b714; }
                    input[type=range] { width:100%; accent-color:#e2b714; }
                    #mainStartBtn { width:100%; background:#111; color:#fff; border:1px solid #333; padding:10px; border-radius:8px; font-weight:bold; cursor:pointer; display:flex; align-items:center; justify-content:center; gap:8px; }
                    .sec-btn { background:#080808; border:1px solid #222; color:#666; padding:6px; border-radius:6px; cursor:pointer; font-size:9px; font-weight:bold; }
                    .d-btn { flex:1; background:#111; border:1px solid #222; color:#555; font-size:9px; padding:6px; border-radius:4px; cursor:pointer; }
                    .d-btn.active { border-color:#e2b714; color:#fff; }
                    .pulse { color:#ff4444; animation: blink 1s infinite; }
                    @keyframes blink { 50% { opacity: 0; } }
                </style>
            `;

            const tab = document.createElement('div');
            tab.id = 'mt-restore-tab'; 
            tab.innerHTML = 'BOT';
            tab.style.cssText = `position:fixed;top:50%;right:0;transform:translateY(-50%);background:#e2b714;color:#000;padding:15px 8px;border-radius:10px 0 0 10px;cursor:pointer;font-size:10px;font-weight:900;writing-mode:vertical-rl;display:none;z-index:100000;`;

            document.body.appendChild(gui);
            document.body.appendChild(tab);

            // Click handlers
            document.getElementById('mainStartBtn').onclick = () => this.toggleTyping();
            document.getElementById('hideBtn').onclick = () => { gui.style.display='none'; tab.style.display='flex'; };
            tab.onclick = () => { gui.style.display='block'; tab.style.display='none'; };
            document.getElementById('exportBtn').onclick = () => this.exportConfig();
            document.getElementById('importBtn').onclick = () => this.importConfig();
            
            document.getElementById('s-wpm').oninput = (e) => {
                this.config.wpm = e.target.value;
                document.getElementById('v-wpm').innerText = e.target.value;
                localStorage.setItem('mt-bot-wpm', e.target.value);
            };

            document.querySelectorAll('.d-btn').forEach(btn => {
                btn.onclick = () => {
                    this.config.startDelay = parseInt(btn.dataset.ms);
                    document.querySelectorAll('.d-btn').forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    localStorage.setItem('mt-bot-delay', btn.dataset.ms);
                };
            });
        }

        exportConfig() {
            const data = JSON.stringify({ wpm: this.config.wpm, acc: this.config.accuracy });
            navigator.clipboard.writeText(data).then(() => {
                this.updateStatusText('Copied!', '#e2b714');
            });
        }

        importConfig() {
            const raw = prompt("Paste JSON Config:");
            if (raw) {
                try {
                    const parsed = JSON.parse(raw);
                    this.config.wpm = parsed.wpm; 
                    this.config.accuracy = parsed.acc;
                    localStorage.setItem('mt-bot-wpm', parsed.wpm); 
                    localStorage.setItem('mt-bot-acc', parsed.acc);
                    location.reload();
                } catch(e) { alert("Invalid JSON!"); }
            }
        }
    }

    // Startup
    new AutoTyper();
})();