您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Nitrotype Bot with GUI & variance sliders, also Mostly a Troll Hack TW: GETS YOU BANNED Theres no way currently to make a script that works using tampermonkey.
// ==UserScript== // @license MIT // @description Nitrotype Bot with GUI & variance sliders, also Mostly a Troll Hack TW: GETS YOU BANNED Theres no way currently to make a script that works using tampermonkey. // @name Nitro Type Bot // @namespace https://www.youtube.com/@InternetTyper // @match https://www.nitrotype.com/* // @author Internet Typer // @run-at document-start // @grant none // @version 1.0.2 // ==/UserScript== (() => { 'use strict'; function isRacePage() { return location.pathname.startsWith('/race'); } const sockets = []; const nativeWebSocket = window.WebSocket; window.WebSocket = function (...args) { const socket = new nativeWebSocket(...args); sockets.push(socket); return socket; }; function sleep(s) { return new Promise(resolve => setTimeout(resolve, s * 1000)); } function loadNum(key, def) { const val = sessionStorage.getItem(key); return val !== null ? parseInt(val) : def; } function saveNum(key, val) { sessionStorage.setItem(key, val.toString()); } function loadBool(key, def) { const val = sessionStorage.getItem(key); return val === null ? def : val === 'true'; } function saveBool(key, val) { sessionStorage.setItem(key, val ? 'true' : 'false'); } function loadStr(key, def) { const val = sessionStorage.getItem(key); return val !== null ? val : def; } function saveStr(key, val) { sessionStorage.setItem(key, val); } const keys = { enabled: 'ntbot_enabled', baseWpm: 'ntbot_wpm', baseAcc: 'ntbot_acc', wpmVar: 'ntbot_wpm_var', accVar: 'ntbot_acc_var', color: 'ntbot_color' }; const defaults = { enabled: true, baseWpm: 200, baseAcc: 100, wpmVar: 10, accVar: 5, color: '#0f0' }; let enabled = loadBool(keys.enabled, defaults.enabled); let baseWpm = loadNum(keys.baseWpm, defaults.baseWpm); let baseAcc = loadNum(keys.baseAcc, defaults.baseAcc); let wpmVar = loadNum(keys.wpmVar, defaults.wpmVar); let accVar = loadNum(keys.accVar, defaults.accVar); let color = loadStr(keys.color, defaults.color); function createGUI() { if (document.getElementById('ntbot_gui')) return; const style = document.createElement('style'); style.textContent = ` #ntbot_gui { position: fixed; top: 10px; right: 10px; background: #111; color: white; padding: 10px 15px; border-radius: 8px; font-family: Arial, sans-serif; font-size: 14px; width: 280px; box-shadow: 0 0 15px ${color}; z-index: 99999; user-select: none; } #ntbot_gui h2 { margin: 0 0 10px 0; font-size: 18px; cursor: pointer; } #ntbot_gui .section { margin-bottom: 12px; } #ntbot_gui label { display: block; margin-bottom: 4px; font-weight: bold; } #ntbot_gui input[type="number"], #ntbot_gui input[type="range"], #ntbot_gui input[type="color"] { width: 100%; font-size: 14px; padding: 4px; border-radius: 4px; border: none; background: white; color: black; } #ntbot_gui .small-text { font-size: 11px; color: #aaa; margin-top: 2px; } #ntbot_gui button.toggle-btn { background: ${color}; border: none; padding: 6px 10px; border-radius: 4px; cursor: pointer; font-weight: bold; color: #000; width: 100%; margin-top: 8px; } #ntbot_gui .variance-value { text-align: right; font-size: 12px; color: ${color}; margin-top: -16px; margin-bottom: 6px; user-select: none; } #ntbot_credits { font-size: 12px; text-align: center; margin-top: 10px; color: #ccc; } #ntbot_credits .highlight { font-size: 14px; color: ${color}; font-weight: bold; } #ntbot_credits a { color: ${color}; text-decoration: none; } `; document.head.appendChild(style); const gui = document.createElement('div'); gui.id = 'ntbot_gui'; gui.innerHTML = ` <h2 id="ntbot_toggle">Nitrotype Bot ▲</h2> <div class="collapse-content"> <div class="section"> <label for="ntbot_enabled">Enable Bot</label> <button id="ntbot_enabled" class="toggle-btn">${enabled ? 'ON' : 'OFF'}</button> </div> <div class="section"> <label for="ntbot_wpm_input">Base WPM</label> <input type="number" id="ntbot_wpm_input" min="1" max="3600" value="${baseWpm}" /> </div> <div class="variance-value" id="wpm_var_val">${wpmVar} WPM variance</div> <input type="range" id="ntbot_wpm_var" min="0" max="50" step="1" value="${wpmVar}" /> <div class="section" style="margin-top:12px;"> <label for="ntbot_acc_input">Base Accuracy (%)</label> <input type="number" id="ntbot_acc_input" min="1" max="100" value="${baseAcc}" /> </div> <div class="variance-value" id="acc_var_val">${accVar} accuracy variance</div> <input type="range" id="ntbot_acc_var" min="0" max="20" step="1" value="${accVar}" /> <div class="section"> <label for="ntbot_color_picker">Highlight Color</label> <input type="color" id="ntbot_color_picker" value="${color}" /> </div> <div id="ntbot_credits"> Credit: RedHawk and adl212 and<br> <a class="highlight" href="https://www.youtube.com/@InternetTyper" target="_blank">@InternetTyper on YouTube</a> </div> </div> `; document.body.appendChild(gui); gui.querySelector('#ntbot_toggle').addEventListener('click', () => { gui.classList.toggle('collapsed'); gui.querySelector('#ntbot_toggle').textContent = gui.classList.contains('collapsed') ? 'Nitrotype Bot ▼' : 'Nitrotype Bot ▲'; }); const enableBtn = gui.querySelector('#ntbot_enabled'); enableBtn.addEventListener('click', () => { enabled = !enabled; saveBool(keys.enabled, enabled); enableBtn.textContent = enabled ? 'ON' : 'OFF'; enableBtn.style.background = enabled ? color : '#555'; }); enableBtn.style.background = enabled ? color : '#555'; gui.querySelector('#ntbot_wpm_input').addEventListener('change', e => { let val = parseInt(e.target.value); if (isNaN(val) || val < 1) val = 1; if (val > 3600) val = 3600; baseWpm = val; saveNum(keys.baseWpm, baseWpm); e.target.value = baseWpm; }); gui.querySelector('#ntbot_wpm_var').addEventListener('input', e => { wpmVar = parseInt(e.target.value); saveNum(keys.wpmVar, wpmVar); gui.querySelector('#wpm_var_val').textContent = `${wpmVar} WPM variance`; }); gui.querySelector('#ntbot_acc_input').addEventListener('change', e => { let val = parseInt(e.target.value); if (isNaN(val) || val < 1) val = 1; if (val > 100) val = 100; baseAcc = val; saveNum(keys.baseAcc, baseAcc); e.target.value = baseAcc; }); gui.querySelector('#ntbot_acc_var').addEventListener('input', e => { accVar = parseInt(e.target.value); saveNum(keys.accVar, accVar); gui.querySelector('#acc_var_val').textContent = `${accVar} accuracy variance`; }); gui.querySelector('#ntbot_color_picker').addEventListener('change', e => { color = e.target.value; saveStr(keys.color, color); location.reload(); }); } async function main(ws, event) { if (!enabled || !isRacePage()) return; const message = event.data; const scan_for_text = msg => { try { const parsed = JSON.parse(msg.slice(1)); if (parsed && parsed.payload && typeof parsed.payload.l === 'string') { return parsed.payload.l; } } catch (e) {} return null; }; const text = scan_for_text(message); if (typeof text !== 'string') return; function randrange(min, max) { if (max <= min) return min; return Math.floor(Math.random() * (max - min + 1)) + min; } const words = text.split(' '); const fullText = words.join(' '); const numChars = fullText.length; let charDelays = []; for (let i = 0; i < numChars; i++) { const wpm = Math.max(1, Math.min(3600, baseWpm + randrange(-wpmVar, wpmVar))); const cpm = wpm * 5; const charDelay = 60 * 1000 / cpm; charDelays.push(charDelay); } await sleep(4.3); ws.send('4{"stream":"race","msg":"update","payload":{"t":1,"f":0}}'); let t = 2; let e = 1; for (let i = 0; i < fullText.length; i++) { ws.send(`4{"stream":"race","msg":"update","payload":{"t":${t},"f":${e}}}`); await sleep(charDelays[i] / 1000); t++; } } createGUI(); const hookInterval = setInterval(() => { if (sockets.length > 0) { const ws = sockets[0]; if (!ws._ntbot_hooked) { ws._ntbot_hooked = true; ws.addEventListener('message', event => main(ws, event)); clearInterval(hookInterval); } } }, 500); })();