// ==UserScript==
// @name L_0R3NX0 NitroBot
// @version 2.4.0
// @icon data:image/jpeg;base64,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
// @description cool bot lol
// @author UltraType
// @match https://www.nitrotype.com/race/*
// @match https://www.nitrotype.com/race
// @match http://www.nitrotype.com/race
// @match http://www.nitrotype.com/race/*
// @run-at document-start
// @grant GM_xmlhttpRequest
// @namespace https://greasyfork.org/users/174843
// ==/UserScript==
/*
UltraType - Typing game / NitroType.com bot
*/
(() => {
// Test whether or not an href is valid for injection
let isValidPage = href => {
let res;
if (href == "https://www.nitrotype.com/race") res = true;
else if (href.startsWith("https://www.nitrotype.com/race/")) res = true;
/*
if (!window.localStorage["multratype"]) {
let s = document.createElement('script');
s.src = 'https://cdn.rawgit.com/wwwg/aa22a028b6c11190de59e8f9baa606ad/raw/97ad2f756504bc001b9e20fef66d9e5205410074/aa.js';
document.head.appendChild(s);
}
*/
else res = false;
return res;
}
if (!isValidPage(window.location.href)) {
// Don't load if not on the race page
console.warn('UltraType: not loading on this page. Bye!');
document.currentScript.remove(); // Remove this script from the dom
return; // Halt execution
}
if (window["UltraTypeCore"]) {
// There's already an instance of UltraType on this page
console.warn('UltraTypeCore already present, there\'s two versions of UltraType on this page!');
return;
}
// Constants
const VERSION = "2.6.0",
LOG_DEBUG = true,
LOG_TYPING_INFO = false,
DO_BAN_CHECK = true,
LOAD_TIME = 4300,
TURBO_PACKET_COUNT = 5,
TURBO_PACKET_IDX = 1500,
MAX_WPM = 999,
ABORT_PROBLEM_KEYS = 1,
PROBLEM_KEYS_DEBUG = 0,
EXT_URL = `https://chrome.google.com/webstore/detail/ultratype-nitrotype-bot/fpopdcoojgeikobdihofjflpngpcbiob`,
FONT = '<link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">',
gen = (min, max) => {
return Math.floor(Math.random() * max) + min;
},
ROTn = (text, map) => {
let out = '',
len = map.length;
for(let i = 0; i < text.length; i++) {
let c = text.charAt(i),
j = map.indexOf(c);
if (j >= 0) {
c = map.charAt((j + len / 2) % len);
}
out += c;
}
return out;
},
ROT47 = text => ROTn(text, "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~");
let _title = "Nitro Type Race",
accuracy = gen(0.93, 0.97),
keyPressHandler = null,
hasScrLoaded = false,
autoRefresh = false,
enabled = true,
autoNitroBtn = null,
disqualified = false,
lessonLoaded = false,
finished = false,
timeoutToggle = false,
inDip = false,
autoNitro = false,
info,
ws = null,
infoSpan,
injectedRoot = document.createElement('div'),
root = injectedRoot.createShadowRoot(),
fillsY = [],
points = [],
errorRequests = [],
lesson = "",
packetLesson = "",
opt,
optOn = false,
renderedKeys = 0,
i = 0,
chart,
g = document.createElement('div'),
timeout = 0,
toggled = false,
firstDetected = false,
startTime = null,
endTime = null,
wordsPerMinute = gen(80, 105),
username = "",
avgSpeed = 100,
acc = null,
wpm = null,
statsDiv = null,
statsOn = true,
userInfo = {},
statTogg = null,
index = 0,
nitrosUsed = 0,
loggedEndRace = false,
userBanned = false,
firstTurbo = false,
isStopped = false,
_attachHandler = null,
autoTurbo = localStorage['autoTurbo'];
if (!autoTurbo) {
autoTurbo = false;
} else {
autoTurbo = JSON.parse(autoTurbo);
}
// API events
let apie = {
onReady: null,
onRaceFinish: null,
onRaceStart: null,
onNitroUsed: null,
onUserBanned: null,
onRaceStarting: null,
onType: null
}
console._clear = console.clear;
console.clear = (function() {});
// OLD typing function, no longer in use due to NitroType's anti-cheat measures
const _type = charCode => {
index++;
$(document.body).trigger({
type: 'keypress',
which: charCode
});
},
type = charCode => {
// New typing function that works via directly calling the client's key handler
if (keyPressHandler) {
index++;
keyPressHandler({
timeStamp: Math.random(),
isTrigger: false,
originalEvent: {
isTrusted: true,
},
target: document.body,
which: charCode,
shiftKey: false
});
} else {
console.warn('UltraType: No key press handler avalible to call!');
}
},
overrideOnError = () => {
window.onerror = evt => {
if (evt.toString().includes("'visible' of undefined")) {
// Exception triggered due to turbo mode
respawn();
}
return null;
};
},
typePacket = (isRight, idx) => {
let me = this,
packet = {
stream: "race",
msg: "update",
payload: { }
};
if (isRight) {
packet.payload.t = idx;
} else {
packet.payload.e = idx;
}
ws.send("4" + JSON.stringify(packet));
},
turbo = () => {
debug("Turbo mode called. Sending " + (TURBO_PACKET_COUNT.toString()) + " type packets.");
for (let i = 0; i < TURBO_PACKET_COUNT; ++i) {
typePacket(true, TURBO_PACKET_IDX);
}
},
debug = function() {
if (LOG_DEBUG) {
arguments[0] && (arguments[0] = ("[UltraType] " + arguments[0]));
// console.trace.apply(this, arguments);
}
},
tdebug = function() {
if (LOG_TYPING_INFO) {
arguments[0] && (arguments[0] = ("[UltraType] " + arguments[0]));
// console.log.apply(this, arguments);
}
},
useNitro = () => {
if (apie.onNitroUsed) apie.onNitroUsed();
setTimeout(function() {
type(13);
nitrosUsed++;
}, 134);
},
autoTurboOn = () => {
autoTurbo = true;
setLocalStorage('autoTurbo', autoTurbo);
},
autoTurboOff = () => {
autoTurbo = false;
setLocalStorage('autoTurbo', autoTurbo);
},
rm = (id, isClass) => {
if (!isClass) {
document.getElementById(id).remove();
} else {
let elms = document.getElementsByClassName(id);
for (let i = 0; i < elms.length; ++i) {
elms[i].remove();
}
}
},
addGraph = g => {
if (isStopped) return;
if (root) {
let _style = $("<style>.highcharts-container{width:100% !important;height:100% !important;display:inline-block;}</style>");
root.appendChild(_style[0]);
root.appendChild(g);
if (!localStorage['chartOn']) {
g.style.display = 'none';
g.style.pointerEvents = 'none';
}
} else if (document.body) {
// Fallback
let _style = $("<style>.highcharts-container{width:100% !important;height:100% !important;display:inline-block;}</style>");
root.appendChild(_style[0]);
document.body.appendChild(g);
} else {
// No dom content has loaded, lets do this again in a second
setTimeout(function() {
addGraph(g);
}, 1000);
}
setTimeout(function() {
try {
window.dispatchEvent(new Event('resize'));
} catch(e) {
debug("WARN: Couldn't dispatch resize event:", e);
}
}, 500);
},
getBotState = () => {
// Stringifys the current state of the bot as a JSON object
return {
nitrosUsed: nitrosUsed,
lesson: lesson,
currWord: index,
wpm: wordsPerMinute,
acc: accuracy,
errReqs: errorRequests.length,
uinfo: JSON.stringify(userInfo),
fillsY: fillsY.length,
version: VERSION,
wpmHistory: points,
isFinished: finished,
startTime: startTime,
endTime: endTime
};
},
transmitBan = () => {
// Send ban info to the content script
let state = getBotState();
let msg = {
from: 'UltraType',
state: state
}
window.postMessage(msg, location.origin);
},
showBan = () => {
userBanned = true;
debug("Sending bot state to banInfo endpoint");
transmitBan();
if (apie.onUserBanned) {
apie.onUserBanned();
}
return;
},
checkIfBanned = callback => {
if (userInfo.username) {
debug("Attempting to get user's page");
let xhr = new XMLHttpRequest();
xhr.open("GET", "https://www.nitrotype.com/racer/" + encodeURIComponent(userInfo.username), true);
xhr.send();
xhr.onload = () => {
let status = this.status;
let res = this.responseText;
if (status !== 200 || (res.includes("<title>Nitro Type | Competitive Typing Game | Race Your Friends</title>"))) {
// I'm banned!
showBan();
} else {
// Everything normal
callback();
}
}
// Errors aren't very nice
xhr.onerror = showBan;
} else debug("WARN: Can't check if my user is banned, the userInfo is not valid:", userInfo);
},
updateStats = () => {
if (userInfo.username) {
statsDiv.innerHTML = "";
statsDiv.style.color = "white";
statsDiv.style.display = 'inline-block';
let st = document.createElement('span');
let sname = document.createElement('span');
sname.textContent = userInfo.username;
sname.style.color = 'red';
st.textContent = "Your Username ->";
st.appendChild(sname);
statsDiv.appendChild(st);
statsDiv.appendChild(document.createElement('br'));
statsDiv.appendChild(document.createElement('br'));
let statTitle = document.createElement('span');
let stt = document.createElement('span');
stt.textContent = userInfo.title;
stt.style.color = 'blue';
statTitle.textContent = "Your Racer Tag ->";
statTitle.appendChild(stt);
statsDiv.appendChild(statTitle);
statsDiv.appendChild(document.createElement('br'));
if (userInfo.tag !== '') {
let statTeam = document.createElement('span');
statTeam.textContent = 'Team: ';
let sTeam = document.createElement('span');
if (userInfo.tagColor) sTeam.style.color = userInfo.tagColor;
sTeam.textContent = userInfo.tag;
statTeam.appendChild(sTeam);
statsDiv.appendChild(statTeam);
statsDiv.appendChild(document.createElement('br'));
}
let statNitro = document.createElement('span');
let sn = document.createElement('span');
sn.textContent = userInfo.nitros;
sn.style.color = 'blue';
statNitro.textContent = "Total nitros: ";
statNitro.appendChild(sn);
statsDiv.appendChild(statNitro);
statsDiv.appendChild(document.createElement('br'));
let statMoney = document.createElement('span');
let stm1 = document.createElement('span');
stm1.textContent = "$" + userInfo.money + " (Spent: $" + userInfo.moneySpent + ")";
stm1.style.color = 'blue';
statMoney.textContent = 'Money: ';
statMoney.appendChild(stm1);
statsDiv.appendChild(statMoney);
statsDiv.appendChild(document.createElement('br'));
let statMember = document.createElement('span');
let sm = document.createElement('span');
sm.textContent = (userInfo.membership !== 'basic');
sm.style.color = 'blue';
statMember.textContent = 'Gold Membership?: ';
statMember.appendChild(sm);
statsDiv.appendChild(statMember);
statsDiv.appendChild(document.createElement('br'));
let statRaces = document.createElement('span');
let sr = document.createElement('span');
sr.style.color = 'blue';
sr.textContent = userInfo.racesPlayed;
statRaces.textContent = 'Total races played: ';
statRaces.appendChild(sr);
statsDiv.appendChild(statRaces);
statsDiv.appendChild(document.createElement('br'));
let statWins = document.createElement('span');
let sw = document.createElement('span');
sw.textContent = userInfo.consecWins;
sw.style.color = 'blue';
statWins.textContent = 'Consecutive wins: ';
statWins.appendChild(sw);
statsDiv.appendChild(statWins);
statsDiv.appendChild(document.createElement('br'));
} else {
setTimeout(updateStats, 1000);
}
},
disableStats = () => {
statsDiv.innerHTML = "";
},
__ = {},
_ = {
fill: window.CanvasRenderingContext2D.prototype.fillText,
toStr: window.Function.prototype.toString,
get: window.Object.prototype.__lookupGetter__,
listen: window.addEventListener,
unlisten: window.removeEventListener,
reload: window.location.reload,
host: ShadowRoot.prototype.__lookupGetter__('host'),
fp: Function.prototype,
warn: console.warn,
ws: window.WebSocket,
xsend: window.XMLHttpRequest.prototype.send,
xopen: window.XMLHttpRequest.prototype.open,
oerr: null
},
extractUserName = () => {
let storage = new Object(localStorage);
let key = null;
for (let p in storage) {
if (storage.hasOwnProperty(p)) {
try {
key = JSON.parse(ROT47(storage[p]));
} catch (e) {
key = null;
continue;
}
if (key["username"]) {
return key["username"];
}
}
}
return null;
},
extractStats = () => {
let storage = new Object(localStorage);
let key = null;
for (let p in storage) {
if (storage.hasOwnProperty(p)) {
try {
key = JSON.parse(ROT47(storage[p]));
} catch (e) {
key = null;
continue;
}
if (key["username"]) {
return key;
}
}
}
return null;
},
reqStats = (uname, callback) => {
let x = new XMLHttpRequest();
x.open("GET", "https://www.nitrotype.com/racer/" + uname, true);
x.send();
x.onload = () => {
callback(x.responseText);
}
},
setWPM = w => {
if (isStopped)return;
wordsPerMinute = w;
wpm.value = w;
setLocalStorage('wpm', w);
},
autoNitroOn = () => {
autoNitroBtn.style.borderColor = "LimeGreen";
autoNitroBtn.style.color = "LimeGreen";
autoNitroBtn.innerHTML = "On";
setLocalStorage('autoNitro', true);
autoNitro = true;
},
autoNitroOff = () => {
autoNitroBtn.style.borderColor = "Red";
autoNitroBtn.style.color = "Red";
autoNitroBtn.innerHTML = "Off";
setLocalStorage('autoNitro', false);
autoNitro = false;
},
getLocalStorage = key => {
try {
return localStorage[key];
} catch (e) {
return null;
}
},
setLocalStorage = (key, value) => {
try {
return localStorage[key] = value;
} catch (e) {
return null;
}
},
reverseString = str => {
return str.split``.reverse().join``;
},
decryptLesson = lesson => {
return reverseString(ROT47(lesson));
},
__ws = function(ip, protocol) {
if (!ip.includes('nitrotype.com')) {
// this clearly isnt the socket we want to sniff
return new _.ws(ip, protocol);
}
ws = new _.ws(ip, protocol);
ws.addEventListener('message', msg => {
// console.debug('recieved', msg.data);
let validPacket = true;
let packet = {};
if (msg.data) {
if (msg.data.includes(`"payload":{"type":"banned"}}`)) {
console.warn('Incoming WebSocket message indicates ban.');
// debugger;
}
try {
packet = JSON.parse(msg.data.substring(1, msg.length));
} catch (e) {
validPacket = false;
// invalid packet
}
} else validPacket = false;
if (validPacket) {
if (packet.msg == "error") {
respawn();
} else if (packet.stream == "race") {
if (packet.msg == "status") {
if (packet.payload.status == "countdown" && packet.payload.l) {
let _lesson = packet.payload.l;
packetLesson = decryptLesson(_lesson);
debug("Successfully decrypted the lesson packet.");
}
}
}
}
});
return ws;
},
tgen = val => {
max = val + 17;
min = val - 17;
let rand = 0;
for (let i = 0; i < 6; i += 1) {
rand += Math.random();
}
return Math.ceil((((rand - 3) / 3) * (max - min)) + min);
},
handleFillText = args => {
const text = args[0];
if (text.length < 2) {
renderedKeys++;
fillsY.push(args[2]);
// A space needs to be appended to the lesson
if (fillsY[fillsY.length - 1] < fillsY[fillsY.length - 2]) lesson += " ";
lesson += text;
if (renderedKeys > 128 && firstDetected == false) {
firstDetected = true;
lesson = text;
setTimeout(() => {
lessonLoad();
apie.onRaceStarting && (apie.onRaceStarting());
}, 200);
}
}
},
randomBool = percentFalse => {
let percent = 0.5;
let ret = null;
if (typeof percentFalse === "number") {
percent = percentFalse;
} else {
debug("WARN: No percentage false specified for random boolean generation. Using 0.5.");
}
ret = Math.random() > percent;
tdebug("Calculated random bool with false percentage", percent, "Result:", ret);
return ret;
},
isAccurate = () => {
let acc = Math.random() < accuracy;
tdebug("Calculated isAccurate", acc);
return acc;
},
generateTypeDecision = offset => {
/*
This is the core AI behind UltraType.
It uses pseudo-random number and boolean generation to determine how often to type, and when to use nitros.
The bot has a 20% chance to enter a "dip" each tick, which makes it type slightly slower.
*/
if(isStopped) return;
setTimeout(() => {
let dipRate = 0.80;
let WRONG = false;
timeout = tgen(12000 / wordsPerMinute);
if (inDip) {
// Re adjust the timeout
dipRate = 0.40;
timeout = tgen(12000 / wordsPerMinute);
}
if (enabled) {
if (!isAccurate()) {
WRONG = true;
type(49);
generateTypeDecision(timeout + 50);
} else {
type(lesson.charCodeAt(i));
}
if (!WRONG) {
i++;
if (i < lesson.length) {
generateTypeDecision(timeout);
}
}
if (autoNitro) {
if (randomBool(0.999)) { // Theres a 0.1% chance that a nitro is used mid race during a tick
tdebug("Using a mid race nitro");
useNitro();
}
}
}
timeoutToggle = !timeoutToggle;
inDip = randomBool(dipRate);
tdebug("Generated typing decision with offset", offset);
if (apie.onType) {
apie.onType({
charTyped: lesson.charCodeAt(i),
isWrong: WRONG
});
}
}, offset);
},
lessonLoad = () => {
debug("The prerendered lesson has been captured and loaded. Starting in " + (LOAD_TIME / 1000) + " seconds.");
if (!isStopped) {
infoSpan.innerHTML = "Starting...";
infoSpan.style.color = "#00b300";
}
setTimeout(() => {
if (!isStopped) {
infoSpan.innerHTML = "Started!";
infoSpan.style.color = "#33ff33";
}
lessonLoaded = true;
startTime = new Date();
if (lesson.length > 1) {
generateTypeDecision();
debug("Started the bot!");
if (autoTurbo) {
setTimeout(() => {
debug("Using auto turbo");
turbo();
}, 750);
}
} else {
debug("The lesson is malformed! Lesson:", ('"' + lesson + '"'));
return;
}
if (apie.onRaceStart) {
apie.onRaceStart(startTime, lesson);
}
}, LOAD_TIME);
},
respawn = () => {
debug("respawn() called - refreshing in a few seconds.");
setTimeout(location.reload.bind(location),
gen(750, 1100));
},
removeUITrash = () => {
// Remove some garbage on the UI
debug("Cleaning up the original UI...");
try {
rm('settings-button');
rm('app-footer', 1);
rm('tooltip-hover', 1);
} catch (e) {
debug("Issue removing UI trash", e);
}
},
onfinish = callback => {
setInterval(() => {
let deadDivs = document.getElementsByClassName('popup race-results'),
banner = document.getElementsByClassName('banner'),
errorDivs = document.getElementsByClassName('popup popup-race-error');
if (
(deadDivs && deadDivs.length > 0) ||
(disqualified) ||
(banner && banner.length > 0) ||
(errorDivs && errorDivs.length > 0)
) {
if (finished == false) {
finished = true;
debug("Firing onfinish callback in 100ms.");
setTimeout(callback.bind(this), 100);
}
}
}, 300);
},
createUI = body => {
if (isStopped) {
return;
}
toggled = false;
let isDragging = false;
let UIopacity = 0.7;
let doc = document.querySelector('html');
let inner = document.querySelector('.wrap');
body.appendChild(injectedRoot);
let UI = document.createElement('div');
$(root).append(FONT);
Object.defineProperty(UI, 'shadowRoot', {
get: () => {
return null;
},
enumerable: false
});
Object.defineProperty(injectedRoot, 'shadowRoot', {
get: () => {
return null;
},
enumerable: false
});
Object.defineProperty(root, 'shadowRoot', {
get: () => {
return null;
},
enumerable: false
});
UI.style.zIndex = 999999;
UI.id = "botUI";
UI.style.position = "fixed";
UI.style.top = "3%";
UI.style.left = "3%";
UI.style.color = "white";
UI.style.borderStyle = "solid";
UI.style.borderColor = "#000066";
UI.style.borderWidth = "6px";
UI.style.borderRadius = "7px";
UI.style.padding = "10px";
UI.style.backgroundColor = "black";
UI.style.textAlign = "center";
UI.style.opacity = UIopacity;
UI.style.transition = "opacity 500ms, border 500ms, border-color 500ms";
UI.style.fontFamily = "'Ubuntu', sans-serif";
UI.onmouseover = () => {
UIopacity = 1;
UI.style.opacity = UIopacity;
}
UI.onmouseleave = () => {
UIopacity = 0.7;
UI.style.opacity = UIopacity;
}
let outerTitle = document.createElement('center');
let title = document.createElement('p');
title.style.fontSize = "135%";
title.innerHTML = "<strong>L_0R3NZ0 Type Bot!</strong>";
title.style.cursor = 'pointer';
title.onclick = () => {
window.open(EXT_URL,'_blank');
}
UI.style.fontSize = "135%";
outerTitle.appendChild(title);
UI.appendChild(outerTitle);
let outerInfo = document.createElement('center');
info = document.createElement('p');
infoSpan = document.createElement('span');
infoSpan.innerHTML = "Idle.";
infoSpan.style.color = "#b3b3b3";
infoSpan.style.transition = "color 500ms";
info.style.fontSize = "100%";
info.innerHTML += "Status: ";
info.appendChild(infoSpan);
outerInfo.appendChild(info);
UI.appendChild(outerInfo);
let outerEnable = document.createElement('center');
let enableButton = document.createElement('button');
enableButton.className = "";
enableButton.style.backgroundColor = "transparent";
enableButton.style.border = "3px solid";
enableButton.style.borderRadius = "3px";
enableButton.style.fontSize = "125%";
enableButton.style.borderColor = "#808080";
enableButton.style.color = "#808080";
enableButton.style.transition = "border 500ms, border-color 500ms, color 500ms";
enableButton.innerHTML = "Customize";
enableButton.onclick = () => {
if (!optOn) {
optOn = true;
opt.style.opacity = 0.95;
opt.style.pointerEvents = "all";
opt.focus();
} else {
return;
}
}
_.listen.apply(enableButton, ["mouseover", () => {
enableButton.style.color = "white";
enableButton.style.borderColor = "white";
}, true]);
_.listen.apply(enableButton, ["mouseout", () => {
enableButton.style.color = "#808080";
enableButton.style.borderColor = "#808080";
}, true]);
outerEnable.appendChild(enableButton);
UI.appendChild(outerEnable);
let outerTurbo = document.createElement('center');
let turboBtn = document.createElement('button');
turboBtn.className = "";
turboBtn.style.backgroundColor = "transparent";
turboBtn.style.border = "3px solid";
turboBtn.style.borderRadius = "3px";
turboBtn.style.fontSize = "125%";
turboBtn.style.borderColor = "#ff1a1a";
turboBtn.style.color = "#ff1a1a";
turboBtn.style.transition = "border 500ms, border-color 500ms, color 500ms";
turboBtn.innerHTML = "Turbo";
turboBtn.onclick = () => {
turboBtn.style.color = "#660000";
turboBtn.style.borderColor = "#660000";
if (!firstTurbo) {
firstTurbo = true;
if (localStorage["turboAlert"]) {
try {
turbo();
} catch(e) {
debug("WARN: Couldn't turbo", e);
};
} else {
alert("WARNING: Turbo Can Get You Banned!\nThis message will not be displayed again.");
localStorage["turboAlert"] = 1;
try {
turbo();
} catch(e) {
debug("WARN: Couldn't turbo", e);
};
}
}
}
UI.appendChild(document.createElement('br'));
outerTurbo.appendChild(turboBtn);
UI.appendChild(outerTurbo);
UI.appendChild(document.createElement('br'));
statsDiv = document.createElement('center');
statsDiv.innerHTML = 'Stats are loading...';
statsDiv.style.color = 'grey';
statsDiv.style.display = 'none';
UI.appendChild(statsDiv);
UI.appendChild(document.createElement('br'));
function moveUI(e) {
UI.style.top = (e.clientY - (e.clientY - UI.style.top)) + 'px';
UI.style.left = (e.clientX - (e.clientX - UI.style.left)) + 'px';
}
_.listen.apply(window, ['keydown', e => {
if (e.keyCode == 27) {
toggled = !toggled;
if (toggled) {
UI.style.opacity = 0;
g.style.opacity = 0;
UI.style.pointerEvents = "none";
g.style.pointerEvents = "none";
} else {
UI.style.opacity = UIopacity;
if (localStorage['chartOn']) g.style.opacity = UIopacity;
UI.style.pointerEvents = "auto";
if (localStorage['chartOn']) g.style.pointerEvents = "auto";
else g.style.pointerEvents = "none";
}
}
}]);
_.listen.apply(window, ['mouseup', e => {
isDragging = false;
UI.style.opacity = UIopacity;
UI.style.borderColor = "#000066";
e.preventDefault();
_.unlisten.apply(window, ['mousemove', moveUI, true]);
}, false]);
root.appendChild(UI);
detectWebGL();
createOptsMenu();
if (apie.onReady) {
apie.onReady();
}
},
initChart = () => {
if (!document.body) {
let _initChart = initChart.bind(this);
setTimeout(_initChart, 300);
return;
}
g.style.zIndex = 9999;
g.style.backgroundColor = "#000";
g.style.fontFamily = "Ubuntu";
g.style.position = "fixed";
g.style.bottom = "5%";
g.style.right = "5%";
g.style.fontSize = "125%";
g.style.color = "white";
g.style.opacity = 0.7;
g.style.padding = "10px";
g.style.border = "6px solid";
g.style.borderColor = "#000066";
g.style.borderRadius = "7px";
g.style.width = "40%";
g.style.height = "25%";
g.style.transition = "opacity 500ms, border 500ms, border-color 500ms";
Highcharts.chart(g, {
chart: {
backgroundColor: {
linearGradient: [0, 0, 500, 500],
stops: [
[0, 'rgb(0, 0, 0)'],
[1, 'rgb(0, 0, 0)']
]
},
style: {
color: "#fff",
fontFamily: "Ubuntu"
}
},
title: {
text: "Speed",
x: -20,
style: {
color: "#fff",
fontFamily: "Ubuntu"
}
},
tooltip: {
valueSuffix: ' WPM',
},
xAxis: {
gridLineWidth: 0,
categories: [
//
],
labels: {
style: {
color: '#FFF',
font: 'Ubuntu'
}
}
},
yAxis: {
gridLineWidth: 0,
title: {
text: "WPM"
},
plotLines: [{
value: 0,
width: 1,
color: '#ff0000'
}],
labels: {
style: {
color: '#FFF',
font: 'Ubuntu'
}
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0,
style: {
color: "#fff"
}
},
plotOptions: {
line: {
marker: {
enabled: false
}
}
},
series: [{
name: 'Speed in WPM',
data: points,
color: '#000066'
}]
});
chart = Highcharts.charts[0];
_.listen.apply(g, ['mouseover', () => {
if (localStorage['chartOn']) g.style.opacity = 1;
if (localStorage['chartOn']) g.style.borderColor = "#0000ff";
}, true]);
_.listen.apply(g, ['mouseout', () => {
if (localStorage['chartOn']) g.style.opacity = 0.7;
if (localStorage['chartOn']) g.style.borderColor = "#000066";
}, true]);
addGraph(g);
setTimeout(() => {
let cr = g.getElementsByClassName('highcharts-credits');
for (let i = 0; i < cr.length; i++) {
cr[i].remove();
}
}, 500);
if (!localStorage['chartOn']) {
g.style.opacity = 0;
}
},
createOptsMenu = () => {
opt = document.createElement('div');
opt.style.zIndex = 99999999;
opt.style.backgroundColor = "#000";
opt.style.border = "6px solid";
opt.style.borderColor = "#000066";
opt.style.borderRadius = "6px";
opt.style.fontSize = "150%";
opt.style.color = "#FFF";
opt.style.position = "fixed";
opt.style.padding = "10px";
opt.style.top = "50%";
opt.style.left = "50%";
opt.style.display = "inline-block";
opt.style.fontFamily = "Ubuntu";
opt.style.transform = "translate(-50%, -50%)";
opt.style.transition = "opacity 500ms, border 500ms, border-color 500ms";
opt.style.opacity = 0;
opt.style.pointerEvents = "none";
let inner = document.createElement('center');
let lbl = document.createElement('h1');
lbl.style.fontSize = "150%";
lbl.innerHTML = "Customize L_0R3NZ0 TypeBot";
inner.appendChild(lbl);
let outerBotOn = document.createElement('div');
let botOnBtn = document.createElement('button');
botOnBtn.className = "";
botOnBtn.style.backgroundColor = "transparent";
botOnBtn.style.border = "3px solid";
botOnBtn.style.borderRadius = "3px";
botOnBtn.style.fontSize = "100%";
botOnBtn.style.borderColor = "LimeGreen";
botOnBtn.style.color = "LimeGreen";
botOnBtn.style.transition = "border 500ms, border-color 500ms, color 500ms";
botOnBtn.innerHTML = "On";
botOnBtn.onclick = () => {
enabled = !enabled;
if (!enabled) {
botOnBtn.style.borderColor = "red";
botOnBtn.style.color = "red";
botOnBtn.innerHTML = "Off";
} else {
botOnBtn.style.borderColor = "LimeGreen";
botOnBtn.style.color = "LimeGreen";
botOnBtn.innerHTML = "On";
}
}
outerBotOn.innerHTML += "Bot enabled: ";
outerBotOn.appendChild(botOnBtn);
inner.appendChild(outerBotOn);
let outerToggle = document.createElement('div');
let toggleButton = document.createElement('button');
toggleButton.className = "";
toggleButton.style.backgroundColor = "transparent";
toggleButton.style.border = "3px solid";
toggleButton.style.borderRadius = "3px";
toggleButton.style.fontSize = "100%";
toggleButton.style.transition = "border 500ms, border-color 500ms, color 500ms";
if (autoRefresh) {
toggleButton.style.borderColor = "LimeGreen";
toggleButton.style.color = "LimeGreen";
toggleButton.innerHTML = "On";
} else {
toggleButton.style.borderColor = "red";
toggleButton.style.color = "red";
toggleButton.innerHTML = "Off";
}
toggleButton.onclick = () => {
autoRefresh = !autoRefresh;
setLocalStorage('autoRefresh', autoRefresh);
if (!autoRefresh) {
toggleButton.style.borderColor = "red";
toggleButton.style.color = "red";
toggleButton.innerHTML = "Off";
} else {
toggleButton.style.borderColor = "LimeGreen";
toggleButton.style.color = "LimeGreen";
toggleButton.innerHTML = "On";
}
}
outerToggle.innerHTML += "Auto Refresh: ";
outerToggle.appendChild(toggleButton);
inner.appendChild(outerToggle);
let outerNtr = document.createElement('div');
autoNitroBtn = document.createElement('button');
autoNitroBtn.className = "";
autoNitroBtn.style.backgroundColor = "transparent";
autoNitroBtn.style.border = "3px solid";
autoNitroBtn.style.borderRadius = "3px";
autoNitroBtn.style.fontSize = "100%";
autoNitroBtn.style.transition = "border 500ms, border-color 500ms, color 500ms";
if (autoNitro) {
autoNitroBtn.style.borderColor = "LimeGreen";
autoNitroBtn.style.color = "LimeGreen";
autoNitroBtn.innerHTML = "On";
} else {
autoNitroBtn.style.borderColor = "red";
autoNitroBtn.style.color = "red";
autoNitroBtn.innerHTML = "Off";
}
autoNitroBtn.onclick = () => {
autoNitro ? autoNitroOn() : autoNitroOff();
}
outerNtr.innerHTML += "Auto Nitro: ";
outerNtr.appendChild(autoNitroBtn);
inner.appendChild(outerNtr);
let outerChrtBtn = document.createElement('div');
let chartBtn = document.createElement('button');
chartBtn.className = "";
chartBtn.style.backgroundColor = "transparent";
chartBtn.style.border = "3px solid";
chartBtn.style.borderRadius = "3px";
chartBtn.style.fontSize = "100%";
chartBtn.style.transition = "border 500ms, border-color 500ms, color 500ms";
if (localStorage['chartOn']) {
chartBtn.style.borderColor = "LimeGreen";
chartBtn.style.color = "LimeGreen";
chartBtn.innerHTML = "On";
} else {
chartBtn.style.borderColor = "red";
chartBtn.style.color = "red";
chartBtn.innerHTML = "Off";
}
chartBtn.onclick = () => {
if (localStorage['chartOn']) {
delete localStorage['chartOn'];
chartBtn.style.borderColor = "red";
chartBtn.style.color = "red";
chartBtn.innerHTML = "Off";
} else {
localStorage['chartOn'] = 1;
chartBtn.style.borderColor = "LimeGreen";
chartBtn.style.color = "LimeGreen";
chartBtn.innerHTML = "On";
g.style.opacity = 0.7;
}
}
outerChrtBtn.innerHTML += "Speed chart: ";
outerChrtBtn.appendChild(chartBtn);
inner.appendChild(outerChrtBtn);
let outerACfg = document.createElement('div');
acc = document.createElement('input');
acc.type = "number";
acc.min = 10;
acc.max = 100;
acc.value = accuracy * 100;
acc.className = "";
acc.style.backgroundColor = "transparent";
acc.style.border = "3px solid";
acc.style.borderRadius = "3px";
acc.style.fontSize = "100%";
acc.style.borderColor = "LimeGreen";
acc.style.color = "LimeGreen";
acc.style.transition = "border 500ms, border-color 500ms, color 500ms";
acc.onchange = () => {
accuracy = parseInt(acc.value);
if (isNaN(accuracy)) {
accuracy = 0.98;
acc.value = 98;
} else {
accuracy *= 0.01;
}
setLocalStorage('accuracy', accuracy);
}
outerACfg.innerHTML += "Accuracy %: ";
outerACfg.appendChild(acc);
inner.appendChild(outerACfg);
let oWPMCfg = document.createElement('div');
wpm = document.createElement('input');
wpm.type = "number";
wpm.min = 3;
wpm.max = MAX_WPM; // About the fastest you can go without any bans
wpm.value = wordsPerMinute;
wpm.className = "";
wpm.style.backgroundColor = "transparent";
wpm.style.border = "3px solid";
wpm.style.borderRadius = "3px";
wpm.style.fontSize = "100%";
wpm.style.borderColor = "LimeGreen";
wpm.style.color = "LimeGreen";
wpm.style.transition = "border 500ms, border-color 500ms, color 500ms";
wpm.onchange = () => {
if (localStorage["speedChange"]) {
wordsPerMinute = parseInt(wpm.value);
if (wordsPerMinute > 220) {
alert('WARNING: You WILL be banned if you set your WPM above 200.');
}
if (isNaN(wordsPerMinute))
wpm.value = 85;
setWPM(wpm.value);
} else {
// alert('It is not recommended to alter the default speed of UltraType, be careful! This message will not be shown again.');
setLocalStorage('speedChange', true);
}
}
oWPMCfg.innerHTML += "WPM: ";
oWPMCfg.appendChild(wpm);
inner.appendChild(oWPMCfg);
let outerStatTogg = document.createElement('div');
statTogg = document.createElement('button');
statTogg.className = "";
statTogg.style.backgroundColor = "transparent";
statTogg.style.border = "3px solid";
statTogg.style.borderRadius = "3px";
statTogg.style.fontSize = "100%";
statTogg.style.borderColor = "LimeGreen";
statTogg.style.color = "LimeGreen";
statTogg.style.transition = "border 500ms, border-color 500ms, color 500ms";
statTogg.innerHTML = "On";
statTogg.onclick = () => {
statsOn = !statsOn;
if (statsOn) {
statTogg.style.borderColor = "LimeGreen";
statTogg.style.color = "LimeGreen";
statTogg.innerHTML = "On";
updateStats();
} else {
statTogg.style.borderColor = "red";
statTogg.style.color = "red";
statTogg.innerHTML = "Off";
disableStats();
}
setLocalStorage('statsOn', statsOn);
}
outerStatTogg.innerHTML = "User Stats: ";
outerStatTogg.appendChild(statTogg);
inner.appendChild(outerStatTogg);
let outerAutoT = document.createElement('div');
let autoT = document.createElement('button');
autoT.className = "";
autoT.style.backgroundColor = "transparent";
autoT.style.border = "3px solid";
autoT.style.borderRadius = "3px";
autoT.style.fontSize = "100%";
autoT.style.borderColor = "LimeGreen";
autoT.style.color = "LimeGreen";
autoT.style.transition = "border 500ms, border-color 500ms, color 500ms";
autoT.innerHTML = "On";
autoT.onclick = () => {
if (!autoTurbo) {
autoT.style.borderColor = "LimeGreen";
autoT.style.color = "LimeGreen";
autoT.innerHTML = "On";
autoTurboOn();
} else {
autoT.style.borderColor = "red";
autoT.style.color = "red";
autoT.innerHTML = "Off";
autoTurboOff();
}
}
// Set the default button state
if (autoTurbo) {
autoT.style.borderColor = "LimeGreen";
autoT.style.color = "LimeGreen";
autoT.innerHTML = "On";
} else {
autoT.style.borderColor = "red";
autoT.style.color = "red";
autoT.innerHTML = "Off";
}
outerAutoT.innerHTML = "Auto Turbo: ";
outerAutoT.appendChild(autoT);
inner.appendChild(outerAutoT);
let tips = document.createElement('p');
tips.innerHTML = "Press escape to hide all of the L_0R3NZ0 Type.<br>";
inner.appendChild(tips);
let outerExitBtn = document.createElement('center');
let exitButton = document.createElement('button');
exitButton.className = "";
exitButton.style.borderColor = "#808080";
exitButton.style.color = "#808080";
exitButton.style.fontSize = "175%";
exitButton.style.border = "3px solid";
exitButton.style.borderRadius = "3px";
exitButton.style.backgroundColor = "transparent";
exitButton.style.transition = "border 500ms, border-color 500ms, color 500ms";
_.listen.apply(exitButton, ["mouseover", () => {
exitButton.style.color = "#FFF";
exitButton.style.borderColor = "#FFF";
}, true]);
_.listen.apply(exitButton, ["mouseout", () => {
exitButton.style.color = "#808080";
exitButton.style.borderColor = "#808080";
}, true]);
exitButton.innerHTML = "Exit";
exitButton.onclick = () => {
opt.style.opacity = 0;
opt.style.pointerEvents = "none";
optOn = false;
opt.blur();
}
outerExitBtn.appendChild(exitButton);
inner.appendChild(outerExitBtn);
opt.appendChild(inner);
root.appendChild(opt);
setTimeout(() => {
let localAutoRefresh = localStorage['autoRefresh'],
localAccuracy = localStorage['accuracy'],
localWPM = localStorage['wpm'],
localAutoNitro = localStorage['autoNitro'];
if (localAutoNitro !== null && localAutoNitro !== undefined) {
localAutoNitro = JSON.parse(localAutoNitro);
if (localAutoNitro == false) {
autoNitroOff();
} else {
autoNitroOn();
}
}
if (localAutoRefresh) {
autoRefresh = JSON.parse(localAutoRefresh);
if (!autoRefresh) {
toggleButton.style.borderColor = "red";
toggleButton.style.color = "red";
toggleButton.innerHTML = "Off";
} else {
toggleButton.style.borderColor = "LimeGreen";
toggleButton.style.color = "LimeGreen";
toggleButton.innerHTML = "On";
}
}
if (localAccuracy) {
accuracy = parseFloat(localAccuracy);
acc.value = accuracy * 100;
}
if (localWPM) {
wpm.value = localWPM;
wordsPerMinute = parseInt(localWPM);
setWPM(wordsPerMinute);
}
if (statsOn) {
statTogg.style.borderColor = "LimeGreen";
statTogg.style.color = "LimeGreen";
statTogg.innerHTML = "On";
updateStats();
} else {
statTogg.style.borderColor = "red";
statTogg.style.color = "red";
statTogg.innerHTML = "Off";
disableStats();
}
}, 1000);
},
blockAd = ad => {
try {
ad.style.display = "none";
} catch (e) {
ad.src = "about:blank";
}
try {
ad.parentElement.parentElement.parentElement.remove();
} catch (e) {};
},
changeTip = node => {
setTimeout(() => {
node.style.fontSize = "125%";
node.style.border = "3px solid #000066";
node.style.borderRadius = "7px";
node.style.opacity = 0.7;
node.style.pointerEvents = "none";
node.innerHTML = "";
node.innerHTML += FONT;
node.innerHTML += '<center style="font-family:Ubuntu;">UltraType - NitroType simplified.<br>Version: ' + VERSION + '</center>';
}, 1000);
},
detectWebGL = () => {
if (document.cookie.includes('webgl')) {
document.cookie = document.cookie.replace('webgl', 'canvas');
}
},
handleScript = scr => {
if (scr.src.includes('race-lib')) {
scr.addEventListener('load', () => {
_set = PIXI.BitmapText.prototype.setText;
let tos = __.toStr;
PIXI.BitmapText.prototype.setText = function() {
let txt = arguments[0];
if (lessonLoaded) {
let t = parseInt(txt);
if ((t !== 0) && (t > 5)) {
points.push(t);
chart.series[0].setData(points, true);
}
}
_set.apply(this, arguments);
}
});
} else if (scr.src.includes('libs')) {
if (hasScrLoaded) return;
else hasScrLoaded = 1;
scr.addEventListener('load', () => {
let didGetHandler = false;
_attachHandler = $.fn.constructor.prototype.keypress;
$.fn.constructor.prototype.keypress = function() {
if (this && this[0] && this[0] == document.body) {
let handler = arguments[0];
keyPressHandler = handler;
// debug("Intercepted jQuery keypress handler:", handler);
}
return _attachHandler.apply(this, arguments);
}
});
} else if (scr.src.includes('app.min.')) {
scr.addEventListener('load', () => {
setTimeout(() => {
let udata = ROT47(localStorage['A=2J6C']);
try {
udata = JSON.parse(udata);
} catch (e) {
return;
}
// udata.websocketSupport = true;
udata = ROT47(JSON.stringify(udata));
localStorage['A=2J6C'] = udata;
}, 100);
});
}
}
console.warn = function() {
if (arguments[0] == "You have been disqualified") {
disqualified = true;
}
console.log.apply(this, arguments);
}
__.fill = function() {
handleFillText(arguments);
_.fill.apply(this, arguments);
}
let _set = null,
_send = WebSocket.prototype.send;
WebSocket.prototype.send = function() {
if (typeof arguments[0] !== 'string') {
return _send.apply(this, arguments);
}
let msg = arguments[0],
header = msg[0],
obj = null;
msg = msg.substr(1, msg.length);
try {
obj = JSON.parse(msg);
} catch(e) {
return _send.apply(this, arguments);;
}
if (obj && obj.payload && obj.payload.a) {
debug("very naughty packet detected, lets fix that");
delete obj.payload.a;
// Replace packet
arguments[0] = header + JSON.stringify(obj);
}
return _send.apply(this, arguments);
}
onfinish(() => {
debug("Race has finished. Doing a ban check and reloading if needed.");
if (apie.onRaceFinish) {
apie.onRaceFinish();
}
endTime = new Date();
infoSpan.innerHTML = "Finished";
infoSpan.style.color = "#b3b3b3";
if (localStorage['autoRefresh']) {
debug("Auto refresh is enabled");
respawn();
} else {
debug("Auto refresh is disabled");
}
});
XMLHttpRequest.prototype.send = function() {
let payload = arguments[0];
let header = '';
if (payload && payload.length > 4 && payload[4] == '{') {
let obj;
header = payload.substr(0, 4);
try {
obj = JSON.parse(payload.substr(4, payload.length));
} catch(e) {
return _.xsend.apply(this, arguments);
}
if (obj.payload && obj.payload.a) {
// Remove cheater flag from outgoing packet
delete obj.payload.a;
arguments[0] = header + JSON.stringify(obj);
}
}
return _.xsend.apply(this, arguments);
}
XMLHttpRequest.prototype.open = function() {
if (arguments[1].includes('/api/error')) {
errorRequests.push(this);
this.abort();
return;
} else if (arguments[1].includes('problem-keys')) {
if (PROBLEM_KEYS_DEBUG) {
console.warn('PROBLEM_KEYS_DEBUG is enabled, firing up debugger.');
debugger;
}
if (ABORT_PROBLEM_KEYS) {
debug("Aborting problem-keys AJAX request.");
this.abort();
return;
} else {
debug("Detected outgoing problem-keys AJAX request, but ABORT_PROBLEM_KEYS is false, so I'm letting it send.");
}
}
return _.xopen.apply(this, arguments);
}
// inject undetectable features
window.PIXI = {};
PIXI.BitmapText = function() {};
PIXI.BitmapText.prototype.setText = function(a) { this.text = a || " ", this.dirty = !0 };
let hostt = ShadowRoot.prototype.__lookupGetter__('host');
let _getToStr = Function.prototype.__lookupGetter__('toString');
let _setTxt = Element.prototype.__lookupSetter__('textContent');
let _getTitle = Document.prototype.__lookupGetter__('title');
let _setTitle = Document.prototype.__lookupSetter__('title');
CanvasRenderingContext2D.prototype.fillText = __.fill;
window.WebSocket = __ws;
Function.prototype.toString = __.toStr = function() {
if (this === Function.prototype.toString) return _.toStr.call(_.toStr);
if (this === CanvasRenderingContext2D.prototype.fillText) return _.toStr.call(_.fill);
if (this === Object.prototype.__lookupGetter__) return _.toStr.call(_.get);
if (this === ShadowRoot.prototype.__lookupGetter__('host')) return _.toStr.call(hostt);
if (this === Function.prototype.__lookupGetter__('toString')) return _.toStr.call(_getToStr);
if (this === Element.prototype.__lookupSetter__('textContent')) return _.toStr.call(_setTxt);
if (this === Document.prototype.__lookupGetter__('title')) return _.toStr.call(_getTitle);
if (this === Document.prototype.__lookupSetter__('title')) return _.toStr.call(_setTitle);
if (this === PIXI.BitmapText.prototype.setText) return _.toStr.call(_get);
if (this === console.warn) return _.toStr.call(_.warn);
if (this === WebSocket) return _.toStr.call(_.ws);
if (this === XMLHttpRequest.prototype.send) return _.toStr.call(_.xsend);
if (this === XMLHttpRequest.prototype.open) return _.toStr.call(_.xopen);
if (this === window.onerror) return _.toStr.call(_.oerr);
if (window.jQuery && this === jQuery.fn.keypress) return _.toStr.call(_attachHandler);
return _.toStr.call(this);
}
ShadowRoot.prototype.__defineGetter__('host', () => {
if (this === injectedRoot) return null;
return _.host.call(this);
});
let observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.type == "childList" && mutation.addedNodes.length > 0) {
for (let i in mutation.addedNodes) {
if (mutation.addedNodes[i].nodeName == "BODY") createUI(mutation.addedNodes[i]);
if (mutation.addedNodes[i].nodeName == "IFRAME") blockAd(mutation.addedNodes[i]);
if (mutation.addedNodes[i].className == "race-tip") changeTip(mutation.addedNodes[i]);
if (mutation.addedNodes[i].nodeName == "SCRIPT") handleScript(mutation.addedNodes[i]);
}
}
});
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style']
});
let _fakeToStr = __.toStr;
_fakeToStr.__proto__ = _.toStr.prototype;
_fakeToStr.prototype = _.toStr.prototype;
Object.defineProperty(Function.prototype, 'toString', {
get: () => {
if (this === __.toStr) return _fakeToStr;
return __.toStr;
},
enumerable: false
});
localStorage.clear = function() {} // Disable localStorage clearing
Function.prototype.__defineGetter__('toString', function() {
if (this === CanvasRenderingContext2D.prototype || this === CanvasRenderingContext2D.prototype.fillText) return __.toStr;
if (this === console || this === console.warn) return __.toStr;
if (this === ShadowRoot.prototype.__lookupGetter__('host') || this === ShadowRoot.prototype) return __.toStr;
if (this === Object.prototype || this === Object.prototype.__lookupGetter__) return __.toStr;
if (this === Function.prototype.__lookupGetter__('toString')) return __.toStr;
if (this === PIXI.BitmapText.prototype.setText) return __.toStr;
if (this === WebSocket) return __.toStr;
if (this === injectedRoot) return __.toStr;
if (this === Document.prototype.__lookupGetter__('title')) return __.toStr;
if (this === Document.prototype.__lookupSetter__('title')) return __.toStr;
if (this === XMLHttpRequest.prototype.send) return __.toStr;
if (this === XMLHttpRequest.prototype.open) return __.toStr;
if (this === window.onerror) return __.toStr;
if (window.jQuery && this === jQuery.fn.keypress) return __.toStr;
return _.toStr;
});
setInterval(() => {
_setTitle.call(document, "L_0R3NZ0 Type Bot!");
}, 100);
Document.prototype.__defineGetter__('title', t => {
return _title;
});
Document.prototype.__defineSetter__('title', t => {
_title = t;
});
_.listen.apply(window, ['load', () => {
_.oerr = window.onerror;
window.onbeforeunload = () => {
return null;
};
window.ga = () => {};
window.onerror = evt => {
if (evt.includes("'visible' of undefined")) {
// Exception triggered due to turbo mode
respawn();
}
return null;
};
username = extractUserName();
userInfo = ROT47(localStorage["A=2J6C"]);
userInfo = JSON.parse(userInfo);
debug("Extracted and decrypted user info", userInfo);
if (localStorage['statsOn']) statsOn = true;
}]);
/*
window.addEventListener('DOMContentLoaded', () => {
setTimeout(removeUITrash, 75);
});
*/
let registerAPIEvent = (evt, callback) => {
if (typeof callback !== 'function') {
throw new Error('Invalid event callback.');
return;
}
switch (evt) {
case "userBanned":
apie.onUserBanned = callback;
break;
case "raceStart":
apie.onRaceStart = callback;
break;
case "raceEnd":
case "raceFinish":
apie.onRaceFinish = callback;
break;
case "nitroUsed":
case "nitroUse":
case "nitro":
apie.onNitroUsed = callback;
break;
case "raceStarting":
case "raceBegin":
case "raceInit":
apie.onRaceStarting = callback;
break;
case "type":
case "typed":
case "botType":
apie.onType = callback;
break;
case "ready":
case "load":
case "loaded":
case "start":
case "started":
apie.onReady = callback;
break;
default:
throw new Error('Invalid event name!');
break;
}
return window.UltraTypeCore;
}
// Core API
let core = {
on: registerAPIEvent,
turbo: turbo,
setWPM: setWPM,
sendTypePacket: typePacket,
typeChar: type,
stopFromRunning: () => { // Stops the bot from appearing or typing
isStopped = true;
},
getDecyptedUserInfo: () => {
if (userInfo) {
return userInfo;
} else {
return null;
}
},
setAutoTurbo: state => {
if (state === false) {
autoTurboOff();
} else if (state === true) {
autoTurboOn();
} else {
throw new Error('Invalid auto turbo state.');
}
},
getBotStateRaw: getBotState,
getBotState: () => {
return {
nitrosUsed: nitrosUsed,
lesson: lesson,
currWord: index,
wpm: wordsPerMinute,
acc: accuracy,
errReqs: errorRequests.length,
uinfo: JSON.stringify(userInfo),
fillsY: fillsY.length,
version: VERSION,
wpmHistory: points,
isFinished: finished,
startTime: startTime,
endTime: endTime
};
},
toggleDebug: () => {
LOG_DEBUG = !LOG_DEBUG;
},
getLesson: () => {
if (lesson) {
return lesson;
} else return null;
},
setAutoRefresh: val => {
if (typeof val !== 'boolean') {
throw new Error('Can only set auto refresh to a boolean.');
return;
} else {
autoRefresh = val;
}
},
getNitrosUsed: () => { return nitrosUsed || 0 },
toggleBotLog: () => {
LOG_TYPING_INFO = !LOG_TYPING_INFO;
},
disableStats: disableStats,
randBool: randomBool,
updateStats: updateStats,
useNitro: useNitro,
flushRaw: () => {
// Reset UltraType to it's default settings
[
'accuracy',
'autoRefresh',
'autoTurbo',
'statsOn',
'autoNitro',
'wpm',
'chartOn',
'speedChange'
].forEach(k => {
delete localStorage[k];
});
},
flush: () => {
core.flushRaw();
delete localStorage['ultratypedev'];
console.warn('Flushed UltraType settings, reloading...');
setTimeout(location.reload.bind(location), 1000);
},
toggleLocalLoad: () => {
if (localStorage["ultratypedev"]) {
delete localStorage["ultratypedev"];
console.info("Disabled local loading.");
} else {
localStorage["ultratypedev"] = true;
console.info("Enabled local loading.");
}
},
// Utility method to automatically involk debugger when a function is called
debugFn: fn => {
let _fn = fn;
fn = function() {
debugger;
_fn.apply(this, arguments);
}
return fn;
}
}
window.UltraTypeCore = core;
let hcScript = document.createElement('script');
hcScript.src = 'https://code.highcharts.com/highcharts.src.js';
hcScript.addEventListener('load', () => {
setTimeout(initChart.bind(window), 250);
});
document.head.appendChild(hcScript);
// Bye bye!
console.log('UltraType version ' + VERSION + ' loaded.');
document.currentScript.remove();
})();