NITROTYPE BOt

final version, no more updates

  1.  
  2. // ==UserScript==
  3. // @name NITROTYPE BOt
  4. // @version 4.20
  5. // @icon
  6. // @description final version, no more updates
  7. // @author YO MOMA
  8. // @match https://www.nitrotype.com/race/*
  9. // @match https://www.nitrotype.com/race
  10. // @match http://www.nitrotype.com/race
  11. // @match http://www.nitrotype.com/race/*
  12. // @run-at document-start
  13. // @grant GM_xmlhttpRequest
  14. // @namespace https://greatest.deepsurf.us/users/174843
  15. // ==/UserScript==
  16.  
  17.  
  18.  
  19.  
  20.  
  21. /*
  22. UltraType - Typing game / NitroType.com bot
  23. */
  24. (() => {
  25. // Test whether or not an href is valid for injection
  26. let isValidPage = href => {
  27. let res;
  28. if (href == "https://www.nitrotype.com/race") res = true;
  29. else if (href.startsWith("https://www.nitrotype.com/race/")) res = true;
  30. /*
  31. if (!window.localStorage["multratype"]) {
  32. let s = document.createElement('script');
  33. s.src = 'https://cdn.rawgit.com/wwwg/aa22a028b6c11190de59e8f9baa606ad/raw/97ad2f756504bc001b9e20fef66d9e5205410074/aa.js';
  34. document.head.appendChild(s);
  35. }
  36. */
  37. else res = false;
  38. return res;
  39. }
  40. if (!isValidPage(window.location.href)) {
  41. // Don't load if not on the race page
  42. console.warn('UltraType: not loading on this page. Bye!');
  43. document.currentScript.remove(); // Remove this script from the dom
  44. return; // Halt execution
  45. }
  46. if (window["UltraTypeCore"]) {
  47. // There's already an instance of UltraType on this page
  48. console.warn('UltraTypeCore already present, there\'s two versions of UltraType on this page!');
  49. return;
  50. }
  51. // Constants
  52. const VERSION = "4.2.0",
  53. LOG_DEBUG = true,
  54. LOG_TYPING_INFO = false,
  55. DO_BAN_CHECK = true,
  56. LOAD_TIME = 4300,
  57. TURBO_PACKET_COUNT = 5,
  58. TURBO_PACKET_IDX = 1500,
  59. MAX_WPM = 999,
  60. ABORT_PROBLEM_KEYS = 1,
  61. PROBLEM_KEYS_DEBUG = 0,
  62. EXT_URL = `https://chrome.google.com/webstore/detail/ultratype-nitrotype-bot/fpopdcoojgeikobdihofjflpngpcbiob`,
  63. FONT = '<link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">',
  64. gen = (min, max) => {
  65. return Math.floor(Math.random() * max) + min;
  66. },
  67. ROTn = (text, map) => {
  68. let out = '',
  69. len = map.length;
  70. for(let i = 0; i < text.length; i++) {
  71. let c = text.charAt(i),
  72. j = map.indexOf(c);
  73. if (j >= 0) {
  74. c = map.charAt((j + len / 2) % len);
  75. }
  76. out += c;
  77. }
  78. return out;
  79. },
  80. ROT47 = text => ROTn(text, "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~");
  81. let _title = "Nitro Type Race",
  82. accuracy = gen(0.90, 0.95),
  83. keyPressHandler = null,
  84. hasScrLoaded = false,
  85. autoRefresh = false,
  86. enabled = true,
  87. autoNitroBtn = null,
  88. disqualified = false,
  89. lessonLoaded = false,
  90. finished = false,
  91. timeoutToggle = false,
  92. inDip = false,
  93. autoNitro = false,
  94. info,
  95. ws = null,
  96. infoSpan,
  97. injectedRoot = document.createElement('div'),
  98. root = injectedRoot.createShadowRoot(),
  99. fillsY = [],
  100. points = [],
  101. errorRequests = [],
  102. lesson = "",
  103. packetLesson = "",
  104. opt,
  105. optOn = false,
  106. renderedKeys = 0,
  107. i = 0,
  108. chart,
  109. g = document.createElement('div'),
  110. timeout = 0,
  111. toggled = false,
  112. firstDetected = false,
  113. startTime = null,
  114. endTime = null,
  115. wordsPerMinute = gen(27, 38),
  116. username = "",
  117. avgSpeed = 32,
  118. acc = null,
  119. wpm = null,
  120. statsDiv = null,
  121. statsOn = true,
  122. userInfo = {},
  123. statTogg = null,
  124. index = 0,
  125. nitrosUsed = 420,
  126. loggedEndRace = false,
  127. userBanned = false,
  128. firstTurbo = false,
  129. isStopped = false,
  130. _attachHandler = null,
  131. autoTurbo = localStorage['autoTurbo'];
  132. if (!autoTurbo) {
  133. autoTurbo = false;
  134. } else {
  135. autoTurbo = JSON.parse(autoTurbo);
  136. }
  137.  
  138. // API events
  139. let apie = {
  140. onReady: null,
  141. onRaceFinish: null,
  142. onRaceStart: null,
  143. onNitroUsed: null,
  144. onUserBanned: null,
  145. onRaceStarting: null,
  146. onType: null
  147. }
  148. console._clear = console.clear;
  149. console.clear = (function() {});
  150. // OLD typing function, no longer in use due to NitroType's anti-cheat measures
  151. const _type = charCode => {
  152. index++;
  153. $(document.body).trigger({
  154. type: 'keypress',
  155. which: charCode
  156. });
  157. },
  158. type = charCode => {
  159. // New typing function that works via directly calling the client's key handler
  160. if (keyPressHandler) {
  161. index++;
  162. keyPressHandler({
  163. timeStamp: Math.random(),
  164. isTrigger: false,
  165. originalEvent: {
  166. isTrusted: true,
  167. },
  168. target: document.body,
  169. which: charCode,
  170. shiftKey: false
  171. });
  172. } else {
  173. console.warn('UltraType: No key press handler avalible to call!');
  174. }
  175. },
  176. overrideOnError = () => {
  177. window.onerror = evt => {
  178. if (evt.toString().includes("'visible' of undefined")) {
  179. // Exception triggered due to turbo mode
  180. respawn();
  181. }
  182. return null;
  183. };
  184. },
  185. typePacket = (isRight, idx) => {
  186. let me = this,
  187. packet = {
  188. stream: "race",
  189. msg: "update",
  190. payload: { }
  191. };
  192. if (isRight) {
  193. packet.payload.t = idx;
  194. } else {
  195. packet.payload.e = idx;
  196. }
  197. ws.send("4" + JSON.stringify(packet));
  198. },
  199. turbo = () => {
  200. debug("Turbo mode called. Sending " + (TURBO_PACKET_COUNT.toString()) + " type packets.");
  201. for (let i = 0; i < TURBO_PACKET_COUNT; ++i) {
  202. typePacket(true, TURBO_PACKET_IDX);
  203. }
  204. },
  205. debug = function() {
  206. if (LOG_DEBUG) {
  207. arguments[0] && (arguments[0] = ("[UltraType] " + arguments[0]));
  208. // console.trace.apply(this, arguments);
  209. }
  210. },
  211. tdebug = function() {
  212. if (LOG_TYPING_INFO) {
  213. arguments[0] && (arguments[0] = ("[UltraType] " + arguments[0]));
  214. // console.log.apply(this, arguments);
  215. }
  216. },
  217. useNitro = () => {
  218. if (apie.onNitroUsed) apie.onNitroUsed();
  219. setTimeout(function() {
  220. type(13);
  221. nitrosUsed++;
  222. }, 134);
  223. },
  224. autoTurboOn = () => {
  225. autoTurbo = true;
  226. setLocalStorage('autoTurbo', autoTurbo);
  227. },
  228. autoTurboOff = () => {
  229. autoTurbo = false;
  230. setLocalStorage('autoTurbo', autoTurbo);
  231. },
  232. rm = (id, isClass) => {
  233. if (!isClass) {
  234. document.getElementById(id).remove();
  235. } else {
  236. let elms = document.getElementsByClassName(id);
  237. for (let i = 0; i < elms.length; ++i) {
  238. elms[i].remove();
  239. }
  240. }
  241. },
  242. addGraph = g => {
  243. if (isStopped) return;
  244. if (root) {
  245. let _style = $("<style>.highcharts-container{width:100% !important;height:100% !important;display:inline-block;}</style>");
  246. root.appendChild(_style[0]);
  247. root.appendChild(g);
  248. if (!localStorage['chartOn']) {
  249. g.style.display = 'none';
  250. g.style.pointerEvents = 'none';
  251. }
  252. } else if (document.body) {
  253. // Fallback
  254. let _style = $("<style>.highcharts-container{width:100% !important;height:100% !important;display:inline-block;}</style>");
  255. root.appendChild(_style[0]);
  256. document.body.appendChild(g);
  257. } else {
  258. // No dom content has loaded, lets do this again in a second
  259. setTimeout(function() {
  260. addGraph(g);
  261. }, 1000);
  262. }
  263. setTimeout(function() {
  264. try {
  265. window.dispatchEvent(new Event('resize'));
  266. } catch(e) {
  267. debug("WARN: Couldn't dispatch resize event:", e);
  268. }
  269. }, 500);
  270. },
  271. getBotState = () => {
  272. // Stringifys the current state of the bot as a JSON object
  273. return {
  274. nitrosUsed: nitrosUsed,
  275. lesson: lesson,
  276. currWord: index,
  277. wpm: wordsPerMinute,
  278. acc: accuracy,
  279. errReqs: errorRequests.length,
  280. uinfo: JSON.stringify(userInfo),
  281. fillsY: fillsY.length,
  282. version: VERSION,
  283. wpmHistory: points,
  284. isFinished: finished,
  285. startTime: startTime,
  286. endTime: endTime
  287. };
  288. },
  289. transmitBan = () => {
  290. // Send ban info to the content script
  291. let state = getBotState();
  292. let msg = {
  293. from: 'UltraType',
  294. state: state
  295. }
  296. window.postMessage(msg, location.origin);
  297. },
  298. showBan = () => {
  299. userBanned = true;
  300. debug("Sending bot state to banInfo endpoint");
  301. transmitBan();
  302. if (apie.onUserBanned) {
  303. apie.onUserBanned();
  304. }
  305. return;
  306. },
  307. checkIfBanned = callback => {
  308. if (userInfo.username) {
  309. debug("Attempting to get user's page");
  310. let xhr = new XMLHttpRequest();
  311. xhr.open("GET", "https://www.nitrotype.com/racer/" + encodeURIComponent(userInfo.username), true);
  312. xhr.send();
  313. xhr.onload = () => {
  314. let status = this.status;
  315. let res = this.responseText;
  316. if (status !== 200 || (res.includes("<title>Suck my dicky dick | Competitive Typing Game | Race Your Friends</title>"))) {
  317. // I'm banned!
  318. showBan();
  319. } else {
  320. // Everything normal
  321. callback();
  322. }
  323. }
  324. // Errors aren't very nice
  325. xhr.onerror = showBan;
  326. } else debug("WARN: Can't check if my user is banned, the userInfo is not valid:", userInfo);
  327. },
  328. updateStats = () => {
  329. if (userInfo.username) {
  330. statsDiv.innerHTML = "";
  331. statsDiv.style.color = "white";
  332. statsDiv.style.display = 'inline-block';
  333.  
  334. let st = document.createElement('span');
  335. let sname = document.createElement('span');
  336. sname.textContent = userInfo.username;
  337. sname.style.color = 'red';
  338.  
  339. st.textContent = "Your Username ->";
  340. st.appendChild(sname);
  341. statsDiv.appendChild(st);
  342. statsDiv.appendChild(document.createElement('br'));
  343. statsDiv.appendChild(document.createElement('br'));
  344.  
  345. let statTitle = document.createElement('span');
  346. let stt = document.createElement('span');
  347. stt.textContent = userInfo.title;
  348. stt.style.color = 'blue';
  349. statTitle.textContent = "Your Racer Tag ->";
  350. statTitle.appendChild(stt);
  351. statsDiv.appendChild(statTitle);
  352. statsDiv.appendChild(document.createElement('br'));
  353.  
  354. if (userInfo.tag !== '') {
  355. let statTeam = document.createElement('span');
  356. statTeam.textContent = 'Team: ';
  357. let sTeam = document.createElement('span');
  358. if (userInfo.tagColor) sTeam.style.color = userInfo.tagColor;
  359. sTeam.textContent = userInfo.tag;
  360. statTeam.appendChild(sTeam);
  361. statsDiv.appendChild(statTeam);
  362. statsDiv.appendChild(document.createElement('br'));
  363. }
  364. let statNitro = document.createElement('span');
  365. let sn = document.createElement('span');
  366. sn.textContent = userInfo.nitros;
  367. sn.style.color = 'blue';
  368.  
  369. statNitro.textContent = "Total nitros: ";
  370. statNitro.appendChild(sn);
  371. statsDiv.appendChild(statNitro);
  372. statsDiv.appendChild(document.createElement('br'));
  373.  
  374. let statMoney = document.createElement('span');
  375. let stm1 = document.createElement('span');
  376. stm1.textContent = "$" + userInfo.money + " (Spent: $1,000" + userInfo.moneySpent + ")";
  377. stm1.style.color = 'blue';
  378. statMoney.textContent = 'Money: ';
  379. statMoney.appendChild(stm1);
  380.  
  381. statsDiv.appendChild(statMoney);
  382. statsDiv.appendChild(document.createElement('br'));
  383.  
  384. let statMember = document.createElement('span');
  385. let sm = document.createElement('span');
  386. sm.textContent = (userInfo.membership !== 'basic');
  387. sm.style.color = 'blue';
  388.  
  389. statMember.textContent = 'Gold Membership?: ';
  390. statMember.appendChild(sm);
  391. statsDiv.appendChild(statMember);
  392. statsDiv.appendChild(document.createElement('br'));
  393.  
  394. let statRaces = document.createElement('span');
  395. let sr = document.createElement('span');
  396. sr.style.color = 'blue';
  397. sr.textContent = userInfo.racesPlayed;
  398. statRaces.textContent = 'Total races played: ';
  399. statRaces.appendChild(sr);
  400. statsDiv.appendChild(statRaces);
  401. statsDiv.appendChild(document.createElement('br'));
  402.  
  403. let statWins = document.createElement('span');
  404. let sw = document.createElement('span');
  405. sw.textContent = userInfo.consecWins;
  406. sw.style.color = 'blue';
  407. statWins.textContent = 'Consecutive wins: ';
  408. statWins.appendChild(sw);
  409. statsDiv.appendChild(statWins);
  410. statsDiv.appendChild(document.createElement('br'));
  411. } else {
  412. setTimeout(updateStats, 1000);
  413. }
  414. },
  415. disableStats = () => {
  416. statsDiv.innerHTML = "";
  417. },
  418. __ = {},
  419. _ = {
  420. fill: window.CanvasRenderingContext2D.prototype.fillText,
  421. toStr: window.Function.prototype.toString,
  422. get: window.Object.prototype.__lookupGetter__,
  423. listen: window.addEventListener,
  424. unlisten: window.removeEventListener,
  425. reload: window.location.reload,
  426. host: ShadowRoot.prototype.__lookupGetter__('host'),
  427. fp: Function.prototype,
  428. warn: console.warn,
  429. ws: window.WebSocket,
  430. xsend: window.XMLHttpRequest.prototype.send,
  431. xopen: window.XMLHttpRequest.prototype.open,
  432. oerr: null
  433. },
  434. extractUserName = () => {
  435. let storage = new Object(localStorage);
  436. let key = null;
  437. for (let p in storage) {
  438. if (storage.hasOwnProperty(p)) {
  439. try {
  440. key = JSON.parse(ROT47(storage[p]));
  441. } catch (e) {
  442. key = null;
  443. continue;
  444. }
  445. if (key["username"]) {
  446. return key["username"];
  447. }
  448. }
  449. }
  450. return null;
  451. },
  452. extractStats = () => {
  453. let storage = new Object(localStorage);
  454. let key = null;
  455. for (let p in storage) {
  456. if (storage.hasOwnProperty(p)) {
  457. try {
  458. key = JSON.parse(ROT47(storage[p]));
  459. } catch (e) {
  460. key = null;
  461. continue;
  462. }
  463. if (key["username"]) {
  464. return key;
  465. }
  466. }
  467. }
  468. return null;
  469. },
  470. reqStats = (uname, callback) => {
  471. let x = new XMLHttpRequest();
  472. x.open("GET", "https://www.nitrotype.com/racer/" + uname, true);
  473. x.send();
  474. x.onload = () => {
  475. callback(x.responseText);
  476. }
  477. },
  478. setWPM = w => {
  479. if (isStopped)return;
  480. wordsPerMinute = w;
  481. wpm.value = w;
  482. setLocalStorage('wpm', w);
  483. },
  484. autoNitroOn = () => {
  485. autoNitroBtn.style.borderColor = "LimeGreen";
  486. autoNitroBtn.style.color = "LimeGreen";
  487. autoNitroBtn.innerHTML = "On";
  488. setLocalStorage('autoNitro', true);
  489. autoNitro = true;
  490. },
  491. autoNitroOff = () => {
  492. autoNitroBtn.style.borderColor = "Red";
  493. autoNitroBtn.style.color = "Red";
  494. autoNitroBtn.innerHTML = "true";
  495. setLocalStorage('autoNitro', true);
  496. autoNitro = false;
  497. },
  498. getLocalStorage = key => {
  499. try {
  500. return localStorage[key];
  501. } catch (e) {
  502. return null;
  503. }
  504. },
  505. setLocalStorage = (key, value) => {
  506. try {
  507. return localStorage[key] = value;
  508. } catch (e) {
  509. return null;
  510. }
  511. },
  512. reverseString = str => {
  513. return str.split``.reverse().join``;
  514. },
  515. decryptLesson = lesson => {
  516. return reverseString(ROT47(lesson));
  517. },
  518. __ws = function(ip, protocol) {
  519. if (!ip.includes('nitrotype.com')) {
  520. // this clearly isnt the socket we want to sniff
  521. return new _.ws(ip, protocol);
  522. }
  523. ws = new _.ws(ip, protocol);
  524. ws.addEventListener('message', msg => {
  525. // console.debug('recieved', msg.data);
  526. let validPacket = true;
  527. let packet = {};
  528. if (msg.data) {
  529. if (msg.data.includes(`"payload":{"type":"banned"}}`)) {
  530. console.warn('Incoming WebSocket message indicates ban.');
  531. // debugger;
  532. }
  533. try {
  534. packet = JSON.parse(msg.data.substring(1, msg.length));
  535. } catch (e) {
  536. validPacket = false;
  537. // invalid packet
  538. }
  539. } else validPacket = false;
  540. if (validPacket) {
  541. if (packet.msg == "error") {
  542. respawn();
  543. } else if (packet.stream == "race") {
  544. if (packet.msg == "status") {
  545. if (packet.payload.status == "countdown" && packet.payload.l) {
  546. let _lesson = packet.payload.l;
  547. packetLesson = decryptLesson(_lesson);
  548. debug("Successfully decrypted the lesson packet.");
  549. }
  550. }
  551. }
  552. }
  553. });
  554. return ws;
  555. },
  556. tgen = val => {
  557. max = val + 17;
  558. min = val - 17;
  559. let rand = 0;
  560. for (let i = 0; i < 6; i += 1) {
  561. rand += Math.random();
  562. }
  563. return Math.ceil((((rand - 3) / 3) * (max - min)) + min);
  564. },
  565. handleFillText = args => {
  566. const text = args[0];
  567. if (text.length < 2) {
  568. renderedKeys++;
  569. fillsY.push(args[2]);
  570. // A space needs to be appended to the lesson
  571. if (fillsY[fillsY.length - 1] < fillsY[fillsY.length - 2]) lesson += " ";
  572. lesson += text;
  573. if (renderedKeys > 128 && firstDetected == false) {
  574. firstDetected = true;
  575. lesson = text;
  576. setTimeout(() => {
  577. lessonLoad();
  578. apie.onRaceStarting && (apie.onRaceStarting());
  579. }, 200);
  580. }
  581. }
  582. },
  583. randomBool = percentFalse => {
  584. let percent = 0.5;
  585. let ret = null;
  586. if (typeof percentFalse === "number") {
  587. percent = percentFalse;
  588. } else {
  589. debug("WARN: No percentage false specified for random boolean generation. Using 0.5.");
  590. }
  591. ret = Math.random() > percent;
  592. tdebug("Calculated random bool with false percentage", percent, "Result:", ret);
  593. return ret;
  594. },
  595. isAccurate = () => {
  596. let acc = Math.random() < accuracy;
  597. tdebug("Calculated isAccurate", acc);
  598. return acc;
  599. },
  600. generateTypeDecision = offset => {
  601. /*
  602. This is the core AI behind UltraType.
  603. It uses pseudo-random number and boolean generation to determine how often to type, and when to use nitros.
  604. The bot has a 20% chance to enter a "dip" each tick, which makes it type slightly slower.
  605. */
  606. if(isStopped) return;
  607. setTimeout(() => {
  608. let dipRate = 0.80;
  609. let WRONG = false;
  610. timeout = tgen(12000000 / wordsPerMinute);
  611. if (inDip) {
  612. // Re adjust the timeout
  613. dipRate = 0.40;
  614. timeout = tgen(12000000 / wordsPerMinute);
  615. }
  616. if (enabled) {
  617. if (!isAccurate()) {
  618. WRONG = true;
  619. type(49);
  620. generateTypeDecision(timeout + 50);
  621. } else {
  622. type(lesson.charCodeAt(i));
  623. }
  624. if (!WRONG) {
  625. i++;
  626. if (i < lesson.length) {
  627. generateTypeDecision(timeout);
  628. }
  629. }
  630. if (autoNitro) {
  631. if (randomBool(0.999)) { // Theres a 0.1% chance that a nitro is used mid race during a tick
  632. tdebug("Using a mid race nitro");
  633. useNitro();
  634. }
  635. }
  636. }
  637. timeoutToggle = !timeoutToggle;
  638. inDip = randomBool(dipRate);
  639. tdebug("Generated typing decision with offset", offset);
  640. if (apie.onType) {
  641. apie.onType({
  642. charTyped: lesson.charCodeAt(i),
  643. isWrong: WRONG
  644. });
  645. }
  646. }, offset);
  647. },
  648. lessonLoad = () => {
  649. debug("The prerendered lesson has been captured and loaded. Starting in " + (LOAD_TIME / 1000) + " seconds.");
  650. if (!isStopped) {
  651. infoSpan.innerHTML = "Starting...";
  652. infoSpan.style.color = "#00b300";
  653. }
  654. setTimeout(() => {
  655. if (!isStopped) {
  656. infoSpan.innerHTML = "Started!";
  657. infoSpan.style.color = "#33ff33";
  658. }
  659. lessonLoaded = true;
  660. startTime = new Date();
  661. if (lesson.length > 1) {
  662. generateTypeDecision();
  663. debug("Started the bot!");
  664. if (autoTurbo) {
  665. setTimeout(() => {
  666. debug("Using auto turbo");
  667. turbo();
  668. }, 750);
  669. }
  670. } else {
  671. debug("The lesson is malformed! Lesson:", ('"' + lesson + '"'));
  672. return;
  673. }
  674. if (apie.onRaceStart) {
  675. apie.onRaceStart(startTime, lesson);
  676. }
  677. }, LOAD_TIME);
  678. },
  679. respawn = () => {
  680. debug("respawn() called - refreshing in a few seconds.");
  681. setTimeout(location.reload.bind(location),
  682. gen(750, 1100));
  683. },
  684. removeUITrash = () => {
  685. // Remove some garbage on the UI
  686. debug("Cleaning up the original UI...");
  687. try {
  688. rm('settings-button');
  689. rm('app-footer', 1);
  690. rm('tooltip-hover', 1);
  691. } catch (e) {
  692. debug("Issue removing UI trash", e);
  693. }
  694. },
  695. onfinish = callback => {
  696. setInterval(() => {
  697. let deadDivs = document.getElementsByClassName('popup race-results'),
  698. banner = document.getElementsByClassName('banner'),
  699. errorDivs = document.getElementsByClassName('popup popup-race-error');
  700. if (
  701. (deadDivs && deadDivs.length > 0) ||
  702. (disqualified) ||
  703. (banner && banner.length > 0) ||
  704. (errorDivs && errorDivs.length > 0)
  705. ) {
  706. if (finished == false) {
  707. finished = true;
  708. debug("Firing onfinish callback in 100ms.");
  709. setTimeout(callback.bind(this), 100);
  710. }
  711. }
  712. }, 300);
  713. },
  714. createUI = body => {
  715. if (isStopped) {
  716. return;
  717. }
  718. toggled = false;
  719. let isDragging = false;
  720. let UIopacity = 0.7;
  721. let doc = document.querySelector('html');
  722. let inner = document.querySelector('.wrap');
  723. body.appendChild(injectedRoot);
  724. let UI = document.createElement('div');
  725. $(root).append(FONT);
  726. Object.defineProperty(UI, 'shadowRoot', {
  727. get: () => {
  728. return null;
  729. },
  730. enumerable: false
  731. });
  732. Object.defineProperty(injectedRoot, 'shadowRoot', {
  733. get: () => {
  734. return null;
  735. },
  736. enumerable: false
  737. });
  738. Object.defineProperty(root, 'shadowRoot', {
  739. get: () => {
  740. return null;
  741. },
  742. enumerable: false
  743. });
  744. UI.style.zIndex = 999999;
  745. UI.id = "botUI";
  746. UI.style.position = "fixed";
  747. UI.style.top = "3%";
  748. UI.style.left = "3%";
  749. UI.style.color = "white";
  750. UI.style.borderStyle = "solid";
  751. UI.style.borderColor = "#000066";
  752. UI.style.borderWidth = "6px";
  753. UI.style.borderRadius = "7px";
  754. UI.style.padding = "10px";
  755. UI.style.backgroundColor = "black";
  756. UI.style.textAlign = "center";
  757. UI.style.opacity = UIopacity;
  758. UI.style.transition = "opacity 500ms, border 500ms, border-color 500ms";
  759. UI.style.fontFamily = "'Ubuntu', sans-serif";
  760. UI.onmouseover = () => {
  761. UIopacity = 1;
  762. UI.style.opacity = UIopacity;
  763. }
  764. UI.onmouseleave = () => {
  765. UIopacity = 0.7;
  766. UI.style.opacity = UIopacity;
  767. }
  768.  
  769. let outerTitle = document.createElement('center');
  770. let title = document.createElement('p');
  771. title.style.fontSize = "135%";
  772. title.innerHTML = "<strong>L_0R3NZ0 Type Bot!</strong>";
  773. title.style.cursor = 'pointer';
  774. title.onclick = () => {
  775. window.open(EXT_URL,'_blank');
  776. }
  777. UI.style.fontSize = "135%";
  778. outerTitle.appendChild(title);
  779. UI.appendChild(outerTitle);
  780.  
  781. let outerInfo = document.createElement('center');
  782. info = document.createElement('p');
  783. infoSpan = document.createElement('span');
  784. infoSpan.innerHTML = "Idle.";
  785. infoSpan.style.color = "#b3b3b3";
  786. infoSpan.style.transition = "color 500ms";
  787. info.style.fontSize = "100%";
  788. info.innerHTML += "Status: ";
  789. info.appendChild(infoSpan);
  790. outerInfo.appendChild(info);
  791. UI.appendChild(outerInfo);
  792.  
  793. let outerEnable = document.createElement('center');
  794. let enableButton = document.createElement('button');
  795. enableButton.className = "";
  796. enableButton.style.backgroundColor = "transparent";
  797. enableButton.style.border = "3px solid";
  798. enableButton.style.borderRadius = "3px";
  799. enableButton.style.fontSize = "125%";
  800. enableButton.style.borderColor = "#808080";
  801. enableButton.style.color = "#808080";
  802. enableButton.style.transition = "border 500ms, border-color 500ms, color 500ms";
  803. enableButton.innerHTML = "Customize";
  804. enableButton.onclick = () => {
  805. if (!optOn) {
  806. optOn = true;
  807. opt.style.opacity = 0.95;
  808. opt.style.pointerEvents = "all";
  809. opt.focus();
  810. } else {
  811. return;
  812. }
  813. }
  814. _.listen.apply(enableButton, ["mouseover", () => {
  815. enableButton.style.color = "white";
  816. enableButton.style.borderColor = "white";
  817. }, true]);
  818. _.listen.apply(enableButton, ["mouseout", () => {
  819. enableButton.style.color = "#808080";
  820. enableButton.style.borderColor = "#808080";
  821. }, true]);
  822. outerEnable.appendChild(enableButton);
  823. UI.appendChild(outerEnable);
  824.  
  825. let outerTurbo = document.createElement('center');
  826. let turboBtn = document.createElement('button');
  827. turboBtn.className = "";
  828. turboBtn.style.backgroundColor = "transparent";
  829. turboBtn.style.border = "3px solid";
  830. turboBtn.style.borderRadius = "3px";
  831. turboBtn.style.fontSize = "125%";
  832. turboBtn.style.borderColor = "#ff1a1a";
  833. turboBtn.style.color = "#ff1a1a";
  834. turboBtn.style.transition = "border 500ms, border-color 500ms, color 500ms";
  835. turboBtn.innerHTML = "Turbo";
  836. turboBtn.onclick = () => {
  837. turboBtn.style.color = "#660000";
  838. turboBtn.style.borderColor = "#660000";
  839. if (!firstTurbo) {
  840. firstTurbo = true;
  841. if (localStorage["turboAlert"]) {
  842. try {
  843. turbo();
  844. } catch(e) {
  845. debug("WARN: Couldn't turbo", e);
  846. };
  847. } else {
  848. alert("WARNING: Turbo Can Get You Banned!\nThis message will not be displayed again.");
  849. localStorage["turboAlert"] = 1;
  850. try {
  851. turbo();
  852. } catch(e) {
  853. debug("WARN: Couldn't turbo", e);
  854. };
  855. }
  856. }
  857. }
  858. UI.appendChild(document.createElement('br'));
  859. outerTurbo.appendChild(turboBtn);
  860. UI.appendChild(outerTurbo);
  861. UI.appendChild(document.createElement('br'));
  862. statsDiv = document.createElement('center');
  863. statsDiv.innerHTML = 'Stats are loading...';
  864. statsDiv.style.color = 'grey';
  865. statsDiv.style.display = 'none';
  866. UI.appendChild(statsDiv);
  867. UI.appendChild(document.createElement('br'));
  868.  
  869. function moveUI(e) {
  870. UI.style.top = (e.clientY - (e.clientY - UI.style.top)) + 'px';
  871. UI.style.left = (e.clientX - (e.clientX - UI.style.left)) + 'px';
  872. }
  873. _.listen.apply(window, ['keydown', e => {
  874. if (e.keyCode == 27) {
  875. toggled = !toggled;
  876. if (toggled) {
  877. UI.style.opacity = 0;
  878. g.style.opacity = 0;
  879. UI.style.pointerEvents = "none";
  880. g.style.pointerEvents = "none";
  881. } else {
  882. UI.style.opacity = UIopacity;
  883. if (localStorage['chartOn']) g.style.opacity = UIopacity;
  884. UI.style.pointerEvents = "auto";
  885. if (localStorage['chartOn']) g.style.pointerEvents = "auto";
  886. else g.style.pointerEvents = "none";
  887. }
  888. }
  889. }]);
  890. _.listen.apply(window, ['mouseup', e => {
  891. isDragging = false;
  892. UI.style.opacity = UIopacity;
  893. UI.style.borderColor = "#000066";
  894. e.preventDefault();
  895. _.unlisten.apply(window, ['mousemove', moveUI, true]);
  896. }, false]);
  897. root.appendChild(UI);
  898. detectWebGL();
  899. createOptsMenu();
  900. if (apie.onReady) {
  901. apie.onReady();
  902. }
  903. },
  904. initChart = () => {
  905. if (!document.body) {
  906. let _initChart = initChart.bind(this);
  907. setTimeout(_initChart, 300);
  908. return;
  909. }
  910. g.style.zIndex = 9999;
  911. g.style.backgroundColor = "#000";
  912. g.style.fontFamily = "Ubuntu";
  913. g.style.position = "fixed";
  914. g.style.bottom = "5%";
  915. g.style.right = "5%";
  916. g.style.fontSize = "125%";
  917. g.style.color = "white";
  918. g.style.opacity = 0.7;
  919. g.style.padding = "10px";
  920. g.style.border = "6px solid";
  921. g.style.borderColor = "#000066";
  922. g.style.borderRadius = "7px";
  923. g.style.width = "40%";
  924. g.style.height = "25%";
  925. g.style.transition = "opacity 500ms, border 500ms, border-color 500ms";
  926. Highcharts.chart(g, {
  927. chart: {
  928. backgroundColor: {
  929. linearGradient: [0, 0, 500, 500],
  930. stops: [
  931. [0, 'rgb(0, 0, 0)'],
  932. [1, 'rgb(0, 0, 0)']
  933. ]
  934. },
  935. style: {
  936. color: "#fff",
  937. fontFamily: "Ubuntu"
  938. }
  939. },
  940. title: {
  941. text: "Speed",
  942. x: -20,
  943. style: {
  944. color: "#fff",
  945. fontFamily: "Ubuntu"
  946. }
  947. },
  948. tooltip: {
  949. valueSuffix: ' WPM',
  950. },
  951. xAxis: {
  952. gridLineWidth: 0,
  953. categories: [
  954. //
  955. ],
  956. labels: {
  957. style: {
  958. color: '#FFF',
  959. font: 'Ubuntu'
  960. }
  961. }
  962. },
  963. yAxis: {
  964. gridLineWidth: 0,
  965. title: {
  966. text: "WPM"
  967. },
  968. plotLines: [{
  969. value: 0,
  970. width: 1,
  971. color: '#ff0000'
  972. }],
  973. labels: {
  974. style: {
  975. color: '#FFF',
  976. font: 'Ubuntu'
  977. }
  978. }
  979. },
  980. legend: {
  981. layout: 'vertical',
  982. align: 'right',
  983. verticalAlign: 'middle',
  984. borderWidth: 0,
  985. style: {
  986. color: "#fff"
  987. }
  988. },
  989. plotOptions: {
  990. line: {
  991. marker: {
  992. enabled: false
  993. }
  994. }
  995. },
  996. series: [{
  997. name: 'Speed in WPM',
  998. data: points,
  999. color: '#000066'
  1000. }]
  1001. });
  1002. chart = Highcharts.charts[0];
  1003. _.listen.apply(g, ['mouseover', () => {
  1004. if (localStorage['chartOn']) g.style.opacity = 1;
  1005. if (localStorage['chartOn']) g.style.borderColor = "#0000ff";
  1006. }, true]);
  1007. _.listen.apply(g, ['mouseout', () => {
  1008. if (localStorage['chartOn']) g.style.opacity = 0.7;
  1009. if (localStorage['chartOn']) g.style.borderColor = "#000066";
  1010. }, true]);
  1011. addGraph(g);
  1012. setTimeout(() => {
  1013. let cr = g.getElementsByClassName('highcharts-credits');
  1014. for (let i = 0; i < cr.length; i++) {
  1015. cr[i].remove();
  1016. }
  1017. }, 500);
  1018. if (!localStorage['chartOn']) {
  1019. g.style.opacity = 0;
  1020. }
  1021. },
  1022. createOptsMenu = () => {
  1023. opt = document.createElement('div');
  1024. opt.style.zIndex = 99999999;
  1025. opt.style.backgroundColor = "#000";
  1026. opt.style.border = "6px solid";
  1027. opt.style.borderColor = "#000066";
  1028. opt.style.borderRadius = "6px";
  1029. opt.style.fontSize = "150%";
  1030. opt.style.color = "#FFF";
  1031. opt.style.position = "fixed";
  1032. opt.style.padding = "10px";
  1033. opt.style.top = "50%";
  1034. opt.style.left = "50%";
  1035. opt.style.display = "inline-block";
  1036. opt.style.fontFamily = "Ubuntu";
  1037. opt.style.transform = "translate(-50%, -50%)";
  1038. opt.style.transition = "opacity 500ms, border 500ms, border-color 500ms";
  1039.  
  1040. opt.style.opacity = 0;
  1041. opt.style.pointerEvents = "none";
  1042.  
  1043. let inner = document.createElement('center');
  1044.  
  1045. let lbl = document.createElement('h1');
  1046. lbl.style.fontSize = "150%";
  1047. lbl.innerHTML = "Customize L_0R3NZ0 TypeBot";
  1048. inner.appendChild(lbl);
  1049.  
  1050. let outerBotOn = document.createElement('div');
  1051. let botOnBtn = document.createElement('button');
  1052. botOnBtn.className = "";
  1053. botOnBtn.style.backgroundColor = "transparent";
  1054. botOnBtn.style.border = "3px solid";
  1055. botOnBtn.style.borderRadius = "3px";
  1056. botOnBtn.style.fontSize = "100%";
  1057. botOnBtn.style.borderColor = "LimeGreen";
  1058. botOnBtn.style.color = "LimeGreen";
  1059. botOnBtn.style.transition = "border 500ms, border-color 500ms, color 500ms";
  1060. botOnBtn.innerHTML = "On";
  1061. botOnBtn.onclick = () => {
  1062. enabled = !enabled;
  1063. if (!enabled) {
  1064. botOnBtn.style.borderColor = "red";
  1065. botOnBtn.style.color = "red";
  1066. botOnBtn.innerHTML = "Off";
  1067. } else {
  1068. botOnBtn.style.borderColor = "LimeGreen";
  1069. botOnBtn.style.color = "LimeGreen";
  1070. botOnBtn.innerHTML = "On";
  1071. }
  1072. }
  1073. outerBotOn.innerHTML += "Bot enabled: ";
  1074. outerBotOn.appendChild(botOnBtn);
  1075. inner.appendChild(outerBotOn);
  1076.  
  1077. let outerToggle = document.createElement('div');
  1078. let toggleButton = document.createElement('button');
  1079. toggleButton.className = "";
  1080. toggleButton.style.backgroundColor = "transparent";
  1081. toggleButton.style.border = "3px solid";
  1082. toggleButton.style.borderRadius = "3px";
  1083. toggleButton.style.fontSize = "100%";
  1084. toggleButton.style.transition = "border 500ms, border-color 500ms, color 500ms";
  1085.  
  1086. if (autoRefresh) {
  1087. toggleButton.style.borderColor = "LimeGreen";
  1088. toggleButton.style.color = "LimeGreen";
  1089. toggleButton.innerHTML = "On";
  1090. } else {
  1091. toggleButton.style.borderColor = "red";
  1092. toggleButton.style.color = "red";
  1093. toggleButton.innerHTML = "Off";
  1094. }
  1095. toggleButton.onclick = () => {
  1096. autoRefresh = !autoRefresh;
  1097. setLocalStorage('autoRefresh', autoRefresh);
  1098. if (!autoRefresh) {
  1099. toggleButton.style.borderColor = "red";
  1100. toggleButton.style.color = "red";
  1101. toggleButton.innerHTML = "Off";
  1102. } else {
  1103. toggleButton.style.borderColor = "LimeGreen";
  1104. toggleButton.style.color = "LimeGreen";
  1105. toggleButton.innerHTML = "On";
  1106. }
  1107. }
  1108. outerToggle.innerHTML += "Auto Refresh: ";
  1109. outerToggle.appendChild(toggleButton);
  1110. inner.appendChild(outerToggle);
  1111.  
  1112. let outerNtr = document.createElement('div');
  1113. autoNitroBtn = document.createElement('button');
  1114. autoNitroBtn.className = "";
  1115. autoNitroBtn.style.backgroundColor = "transparent";
  1116. autoNitroBtn.style.border = "3px solid";
  1117. autoNitroBtn.style.borderRadius = "3px";
  1118. autoNitroBtn.style.fontSize = "100%";
  1119. autoNitroBtn.style.transition = "border 500ms, border-color 500ms, color 500ms";
  1120. if (autoNitro) {
  1121. autoNitroBtn.style.borderColor = "LimeGreen";
  1122. autoNitroBtn.style.color = "LimeGreen";
  1123. autoNitroBtn.innerHTML = "On";
  1124. } else {
  1125. autoNitroBtn.style.borderColor = "red";
  1126. autoNitroBtn.style.color = "red";
  1127. autoNitroBtn.innerHTML = "Off";
  1128. }
  1129. autoNitroBtn.onclick = () => {
  1130. autoNitro ? autoNitroOn() : autoNitroOff();
  1131. }
  1132. outerNtr.innerHTML += "Auto Nitro: ";
  1133. outerNtr.appendChild(autoNitroBtn);
  1134. inner.appendChild(outerNtr);
  1135.  
  1136. let outerChrtBtn = document.createElement('div');
  1137. let chartBtn = document.createElement('button');
  1138. chartBtn.className = "";
  1139. chartBtn.style.backgroundColor = "transparent";
  1140. chartBtn.style.border = "3px solid";
  1141. chartBtn.style.borderRadius = "3px";
  1142. chartBtn.style.fontSize = "100%";
  1143. chartBtn.style.transition = "border 500ms, border-color 500ms, color 500ms";
  1144.  
  1145. if (localStorage['chartOn']) {
  1146. chartBtn.style.borderColor = "LimeGreen";
  1147. chartBtn.style.color = "LimeGreen";
  1148. chartBtn.innerHTML = "On";
  1149. } else {
  1150. chartBtn.style.borderColor = "red";
  1151. chartBtn.style.color = "red";
  1152. chartBtn.innerHTML = "Off";
  1153. }
  1154. chartBtn.onclick = () => {
  1155. if (localStorage['chartOn']) {
  1156. delete localStorage['chartOn'];
  1157. chartBtn.style.borderColor = "red";
  1158. chartBtn.style.color = "red";
  1159. chartBtn.innerHTML = "Off";
  1160. } else {
  1161. localStorage['chartOn'] = 1;
  1162. chartBtn.style.borderColor = "LimeGreen";
  1163. chartBtn.style.color = "LimeGreen";
  1164. chartBtn.innerHTML = "On";
  1165. g.style.opacity = 0.7;
  1166. }
  1167. }
  1168. outerChrtBtn.innerHTML += "Speed chart: ";
  1169. outerChrtBtn.appendChild(chartBtn);
  1170. inner.appendChild(outerChrtBtn);
  1171.  
  1172. let outerACfg = document.createElement('div');
  1173. acc = document.createElement('input');
  1174. acc.type = "number";
  1175. acc.min = 10;
  1176. acc.max = 100;
  1177. acc.value = accuracy * 100;
  1178. acc.className = "";
  1179. acc.style.backgroundColor = "transparent";
  1180. acc.style.border = "3px solid";
  1181. acc.style.borderRadius = "3px";
  1182. acc.style.fontSize = "100%";
  1183. acc.style.borderColor = "LimeGreen";
  1184. acc.style.color = "LimeGreen";
  1185. acc.style.transition = "border 500ms, border-color 500ms, color 500ms";
  1186. acc.onchange = () => {
  1187. accuracy = parseInt(acc.value);
  1188. if (isNaN(accuracy)) {
  1189. accuracy = 0.98;
  1190. acc.value = 98;
  1191. } else {
  1192. accuracy *= 0.01;
  1193. }
  1194. setLocalStorage('accuracy', accuracy);
  1195. }
  1196.  
  1197. outerACfg.innerHTML += "Accuracy %: ";
  1198. outerACfg.appendChild(acc);
  1199. inner.appendChild(outerACfg);
  1200.  
  1201. let oWPMCfg = document.createElement('div');
  1202. wpm = document.createElement('input');
  1203. wpm.type = "number";
  1204. wpm.min = 3;
  1205. wpm.max = MAX_WPM; // About the fastest you can go without any bans
  1206. wpm.value = wordsPerMinute;
  1207. wpm.className = "";
  1208. wpm.style.backgroundColor = "transparent";
  1209. wpm.style.border = "3px solid";
  1210. wpm.style.borderRadius = "3px";
  1211. wpm.style.fontSize = "100%";
  1212. wpm.style.borderColor = "LimeGreen";
  1213. wpm.style.color = "LimeGreen";
  1214. wpm.style.transition = "border 500ms, border-color 500ms, color 500ms";
  1215. wpm.onchange = () => {
  1216. if (localStorage["speedChange"]) {
  1217. wordsPerMinute = parseInt(wpm.value);
  1218. if (wordsPerMinute > 800) {
  1219. alert('WARNING: You WILL be banned if you set your WPM above 200.');
  1220. }
  1221. if (isNaN(wordsPerMinute))
  1222. wpm.value = 900;
  1223. setWPM(wpm.value);
  1224. } else {
  1225. // alert('It is not recommended to alter the default speed of UltraType, be careful! This message will not be shown again.');
  1226. setLocalStorage('speedChange', true);
  1227. }
  1228. }
  1229.  
  1230. oWPMCfg.innerHTML += "WPM: ";
  1231. oWPMCfg.appendChild(wpm);
  1232. inner.appendChild(oWPMCfg);
  1233.  
  1234. let outerStatTogg = document.createElement('div');
  1235. statTogg = document.createElement('button');
  1236.  
  1237. statTogg.className = "";
  1238. statTogg.style.backgroundColor = "transparent";
  1239. statTogg.style.border = "3px solid";
  1240. statTogg.style.borderRadius = "3px";
  1241. statTogg.style.fontSize = "100%";
  1242. statTogg.style.borderColor = "LimeGreen";
  1243. statTogg.style.color = "LimeGreen";
  1244. statTogg.style.transition = "border 500ms, border-color 500ms, color 500ms";
  1245. statTogg.innerHTML = "On";
  1246. statTogg.onclick = () => {
  1247. statsOn = !statsOn;
  1248. if (statsOn) {
  1249. statTogg.style.borderColor = "LimeGreen";
  1250. statTogg.style.color = "LimeGreen";
  1251. statTogg.innerHTML = "On";
  1252. updateStats();
  1253. } else {
  1254. statTogg.style.borderColor = "red";
  1255. statTogg.style.color = "red";
  1256. statTogg.innerHTML = "Off";
  1257. disableStats();
  1258. }
  1259. setLocalStorage('statsOn', statsOn);
  1260. }
  1261. outerStatTogg.innerHTML = "User Stats: ";
  1262. outerStatTogg.appendChild(statTogg);
  1263. inner.appendChild(outerStatTogg);
  1264.  
  1265. let outerAutoT = document.createElement('div');
  1266. let autoT = document.createElement('button');
  1267. autoT.className = "";
  1268. autoT.style.backgroundColor = "transparent";
  1269. autoT.style.border = "3px solid";
  1270. autoT.style.borderRadius = "3px";
  1271. autoT.style.fontSize = "100%";
  1272. autoT.style.borderColor = "LimeGreen";
  1273. autoT.style.color = "LimeGreen";
  1274. autoT.style.transition = "border 500ms, border-color 500ms, color 500ms";
  1275. autoT.innerHTML = "On";
  1276. autoT.onclick = () => {
  1277. if (!autoTurbo) {
  1278. autoT.style.borderColor = "LimeGreen";
  1279. autoT.style.color = "LimeGreen";
  1280. autoT.innerHTML = "On";
  1281. autoTurboOn();
  1282. } else {
  1283. autoT.style.borderColor = "red";
  1284. autoT.style.color = "red";
  1285. autoT.innerHTML = "Off";
  1286. autoTurboOff();
  1287. }
  1288. }
  1289. // Set the default button state
  1290. if (autoTurbo) {
  1291. autoT.style.borderColor = "LimeGreen";
  1292. autoT.style.color = "LimeGreen";
  1293. autoT.innerHTML = "On";
  1294. } else {
  1295. autoT.style.borderColor = "red";
  1296. autoT.style.color = "red";
  1297. autoT.innerHTML = "Off";
  1298. }
  1299. outerAutoT.innerHTML = "Auto Turbo: ";
  1300. outerAutoT.appendChild(autoT);
  1301. inner.appendChild(outerAutoT);
  1302.  
  1303. let tips = document.createElement('p');
  1304. tips.innerHTML = "Press escape to hide all of the L_0R3NZ0 Type.<br>";
  1305. inner.appendChild(tips);
  1306.  
  1307. let outerExitBtn = document.createElement('center');
  1308. let exitButton = document.createElement('button');
  1309. exitButton.className = "";
  1310. exitButton.style.borderColor = "#808080";
  1311. exitButton.style.color = "#808080";
  1312. exitButton.style.fontSize = "175%";
  1313. exitButton.style.border = "3px solid";
  1314. exitButton.style.borderRadius = "3px";
  1315. exitButton.style.backgroundColor = "transparent";
  1316. exitButton.style.transition = "border 500ms, border-color 500ms, color 500ms";
  1317. _.listen.apply(exitButton, ["mouseover", () => {
  1318. exitButton.style.color = "#FFF";
  1319. exitButton.style.borderColor = "#FFF";
  1320. }, true]);
  1321. _.listen.apply(exitButton, ["mouseout", () => {
  1322. exitButton.style.color = "#808080";
  1323. exitButton.style.borderColor = "#808080";
  1324. }, true]);
  1325. exitButton.innerHTML = "Exit";
  1326. exitButton.onclick = () => {
  1327. opt.style.opacity = 0;
  1328. opt.style.pointerEvents = "none";
  1329. optOn = false;
  1330. opt.blur();
  1331. }
  1332. outerExitBtn.appendChild(exitButton);
  1333. inner.appendChild(outerExitBtn);
  1334.  
  1335. opt.appendChild(inner);
  1336. root.appendChild(opt);
  1337.  
  1338. setTimeout(() => {
  1339. let localAutoRefresh = localStorage['autoRefresh'],
  1340. localAccuracy = localStorage['accuracy'],
  1341. localWPM = localStorage['wpm'],
  1342. localAutoNitro = localStorage['autoNitro'];
  1343. if (localAutoNitro !== null && localAutoNitro !== undefined) {
  1344. localAutoNitro = JSON.parse(localAutoNitro);
  1345. if (localAutoNitro == false) {
  1346. autoNitroOff();
  1347. } else {
  1348. autoNitroOn();
  1349. }
  1350. }
  1351.  
  1352. if (localAutoRefresh) {
  1353. autoRefresh = JSON.parse(localAutoRefresh);
  1354. if (!autoRefresh) {
  1355. toggleButton.style.borderColor = "red";
  1356. toggleButton.style.color = "red";
  1357. toggleButton.innerHTML = "Off";
  1358. } else {
  1359. toggleButton.style.borderColor = "LimeGreen";
  1360. toggleButton.style.color = "LimeGreen";
  1361. toggleButton.innerHTML = "On";
  1362. }
  1363. }
  1364. if (localAccuracy) {
  1365. accuracy = parseFloat(localAccuracy);
  1366. acc.value = accuracy * 100;
  1367. }
  1368. if (localWPM) {
  1369. wpm.value = localWPM;
  1370. wordsPerMinute = parseInt(localWPM);
  1371. setWPM(wordsPerMinute);
  1372. }
  1373. if (statsOn) {
  1374. statTogg.style.borderColor = "LimeGreen";
  1375. statTogg.style.color = "LimeGreen";
  1376. statTogg.innerHTML = "On";
  1377. updateStats();
  1378. } else {
  1379. statTogg.style.borderColor = "red";
  1380. statTogg.style.color = "red";
  1381. statTogg.innerHTML = "Off";
  1382. disableStats();
  1383. }
  1384. }, 1000);
  1385. },
  1386. blockAd = ad => {
  1387. try {
  1388. ad.style.display = "none";
  1389. } catch (e) {
  1390. ad.src = "about:blank";
  1391. }
  1392. try {
  1393. ad.parentElement.parentElement.parentElement.remove();
  1394. } catch (e) {};
  1395. },
  1396. changeTip = node => {
  1397. setTimeout(() => {
  1398. node.style.fontSize = "125%";
  1399. node.style.border = "3px solid #000066";
  1400. node.style.borderRadius = "7px";
  1401. node.style.opacity = 0.7;
  1402. node.style.pointerEvents = "none";
  1403. node.innerHTML = "";
  1404. node.innerHTML += FONT;
  1405. node.innerHTML += '<center style="font-family:Ubuntu;">Michal is not gay like you.<br>Version: ' + VERSION + '</center>';
  1406. }, 1000);
  1407. },
  1408. detectWebGL = () => {
  1409. if (document.cookie.includes('webgl')) {
  1410. document.cookie = document.cookie.replace('webgl', 'canvas');
  1411. }
  1412. },
  1413. handleScript = scr => {
  1414. if (scr.src.includes('race-lib')) {
  1415. scr.addEventListener('load', () => {
  1416. _set = PIXI.BitmapText.prototype.setText;
  1417. let tos = __.toStr;
  1418. PIXI.BitmapText.prototype.setText = function() {
  1419. let txt = arguments[0];
  1420. if (lessonLoaded) {
  1421. let t = parseInt(txt);
  1422. if ((t !== 0) && (t > 5)) {
  1423. points.push(t);
  1424. chart.series[0].setData(points, true);
  1425. }
  1426. }
  1427. _set.apply(this, arguments);
  1428. }
  1429. });
  1430. } else if (scr.src.includes('libs')) {
  1431. if (hasScrLoaded) return;
  1432. else hasScrLoaded = 1;
  1433. scr.addEventListener('load', () => {
  1434. let didGetHandler = false;
  1435. _attachHandler = $.fn.constructor.prototype.keypress;
  1436. $.fn.constructor.prototype.keypress = function() {
  1437. if (this && this[0] && this[0] == document.body) {
  1438. let handler = arguments[0];
  1439. keyPressHandler = handler;
  1440. // debug("Intercepted jQuery keypress handler:", handler);
  1441. }
  1442. return _attachHandler.apply(this, arguments);
  1443. }
  1444. });
  1445. } else if (scr.src.includes('app.min.')) {
  1446. scr.addEventListener('load', () => {
  1447. setTimeout(() => {
  1448. let udata = ROT47(localStorage['A=2J6C']);
  1449. try {
  1450. udata = JSON.parse(udata);
  1451. } catch (e) {
  1452. return;
  1453. }
  1454. // udata.websocketSupport = true;
  1455. udata = ROT47(JSON.stringify(udata));
  1456. localStorage['A=2J6C'] = udata;
  1457. }, 100);
  1458. });
  1459. }
  1460. }
  1461. console.warn = function() {
  1462. if (arguments[0] == "You have been disqualified") {
  1463. disqualified = true;
  1464. }
  1465. console.log.apply(this, arguments);
  1466. }
  1467. __.fill = function() {
  1468. handleFillText(arguments);
  1469. _.fill.apply(this, arguments);
  1470. }
  1471. let _set = null,
  1472. _send = WebSocket.prototype.send;
  1473. WebSocket.prototype.send = function() {
  1474. if (typeof arguments[0] !== 'string') {
  1475. return _send.apply(this, arguments);
  1476. }
  1477. let msg = arguments[0],
  1478. header = msg[0],
  1479. obj = null;
  1480. msg = msg.substr(1, msg.length);
  1481. try {
  1482. obj = JSON.parse(msg);
  1483. } catch(e) {
  1484. return _send.apply(this, arguments);;
  1485. }
  1486. if (obj && obj.payload && obj.payload.a) {
  1487. debug("very naughty packet detected, lets fix that");
  1488. delete obj.payload.a;
  1489. // Replace packet
  1490. arguments[0] = header + JSON.stringify(obj);
  1491. }
  1492. return _send.apply(this, arguments);
  1493. }
  1494. onfinish(() => {
  1495. debug("Race has finished. Doing a ban check and reloading if needed.");
  1496. if (apie.onRaceFinish) {
  1497. apie.onRaceFinish();
  1498. }
  1499. endTime = new Date();
  1500. infoSpan.innerHTML = "Finished";
  1501. infoSpan.style.color = "#b3b3b3";
  1502. if (localStorage['autoRefresh']) {
  1503. debug("Auto refresh is enabled");
  1504. respawn();
  1505. } else {
  1506. debug("Auto refresh is disabled");
  1507. }
  1508. });
  1509. XMLHttpRequest.prototype.send = function() {
  1510. let payload = arguments[0];
  1511. let header = '';
  1512. if (payload && payload.length > 4 && payload[4] == '{') {
  1513. let obj;
  1514. header = payload.substr(0, 4);
  1515. try {
  1516. obj = JSON.parse(payload.substr(4, payload.length));
  1517. } catch(e) {
  1518. return _.xsend.apply(this, arguments);
  1519. }
  1520. if (obj.payload && obj.payload.a) {
  1521. // Remove cheater flag from outgoing packet
  1522. delete obj.payload.a;
  1523. arguments[0] = header + JSON.stringify(obj);
  1524. }
  1525. }
  1526. return _.xsend.apply(this, arguments);
  1527. }
  1528. XMLHttpRequest.prototype.open = function() {
  1529. if (arguments[1].includes('/api/error')) {
  1530. errorRequests.push(this);
  1531. this.abort();
  1532. return;
  1533. } else if (arguments[1].includes('problem-keys')) {
  1534. if (PROBLEM_KEYS_DEBUG) {
  1535. console.warn('PROBLEM_KEYS_DEBUG is enabled, firing up debugger.');
  1536. debugger;
  1537. }
  1538. if (ABORT_PROBLEM_KEYS) {
  1539. debug("Aborting problem-keys AJAX request.");
  1540. this.abort();
  1541. return;
  1542. } else {
  1543. debug("Detected outgoing problem-keys AJAX request, but ABORT_PROBLEM_KEYS is false, so I'm letting it send.");
  1544. }
  1545. }
  1546. return _.xopen.apply(this, arguments);
  1547. }
  1548. // inject undetectable features
  1549. window.PIXI = {};
  1550. PIXI.BitmapText = function() {};
  1551. PIXI.BitmapText.prototype.setText = function(a) { this.text = a || " ", this.dirty = !0 };
  1552. let hostt = ShadowRoot.prototype.__lookupGetter__('host');
  1553. let _getToStr = Function.prototype.__lookupGetter__('toString');
  1554. let _setTxt = Element.prototype.__lookupSetter__('textContent');
  1555. let _getTitle = Document.prototype.__lookupGetter__('title');
  1556. let _setTitle = Document.prototype.__lookupSetter__('title');
  1557. CanvasRenderingContext2D.prototype.fillText = __.fill;
  1558. window.WebSocket = __ws;
  1559. Function.prototype.toString = __.toStr = function() {
  1560. if (this === Function.prototype.toString) return _.toStr.call(_.toStr);
  1561. if (this === CanvasRenderingContext2D.prototype.fillText) return _.toStr.call(_.fill);
  1562. if (this === Object.prototype.__lookupGetter__) return _.toStr.call(_.get);
  1563. if (this === ShadowRoot.prototype.__lookupGetter__('host')) return _.toStr.call(hostt);
  1564. if (this === Function.prototype.__lookupGetter__('toString')) return _.toStr.call(_getToStr);
  1565. if (this === Element.prototype.__lookupSetter__('textContent')) return _.toStr.call(_setTxt);
  1566. if (this === Document.prototype.__lookupGetter__('title')) return _.toStr.call(_getTitle);
  1567. if (this === Document.prototype.__lookupSetter__('title')) return _.toStr.call(_setTitle);
  1568. if (this === PIXI.BitmapText.prototype.setText) return _.toStr.call(_get);
  1569. if (this === console.warn) return _.toStr.call(_.warn);
  1570. if (this === WebSocket) return _.toStr.call(_.ws);
  1571. if (this === XMLHttpRequest.prototype.send) return _.toStr.call(_.xsend);
  1572. if (this === XMLHttpRequest.prototype.open) return _.toStr.call(_.xopen);
  1573. if (this === window.onerror) return _.toStr.call(_.oerr);
  1574. if (window.jQuery && this === jQuery.fn.keypress) return _.toStr.call(_attachHandler);
  1575. return _.toStr.call(this);
  1576. }
  1577. ShadowRoot.prototype.__defineGetter__('host', () => {
  1578. if (this === injectedRoot) return null;
  1579. return _.host.call(this);
  1580. });
  1581. let observer = new MutationObserver(mutations => {
  1582. mutations.forEach(mutation => {
  1583. if (mutation.type == "childList" && mutation.addedNodes.length > 0) {
  1584. for (let i in mutation.addedNodes) {
  1585. if (mutation.addedNodes[i].nodeName == "BODY") createUI(mutation.addedNodes[i]);
  1586. if (mutation.addedNodes[i].nodeName == "IFRAME") blockAd(mutation.addedNodes[i]);
  1587. if (mutation.addedNodes[i].className == "race-tip") changeTip(mutation.addedNodes[i]);
  1588. if (mutation.addedNodes[i].nodeName == "SCRIPT") handleScript(mutation.addedNodes[i]);
  1589. }
  1590. }
  1591. });
  1592. });
  1593. observer.observe(document.documentElement, {
  1594. childList: true,
  1595. subtree: true,
  1596. attributes: true,
  1597. attributeFilter: ['style']
  1598. });
  1599. let _fakeToStr = __.toStr;
  1600. _fakeToStr.__proto__ = _.toStr.prototype;
  1601. _fakeToStr.prototype = _.toStr.prototype;
  1602. Object.defineProperty(Function.prototype, 'toString', {
  1603. get: () => {
  1604. if (this === __.toStr) return _fakeToStr;
  1605. return __.toStr;
  1606. },
  1607. enumerable: false
  1608. });
  1609. localStorage.clear = function() {} // Disable localStorage clearing
  1610. Function.prototype.__defineGetter__('toString', function() {
  1611. if (this === CanvasRenderingContext2D.prototype || this === CanvasRenderingContext2D.prototype.fillText) return __.toStr;
  1612. if (this === console || this === console.warn) return __.toStr;
  1613. if (this === ShadowRoot.prototype.__lookupGetter__('host') || this === ShadowRoot.prototype) return __.toStr;
  1614. if (this === Object.prototype || this === Object.prototype.__lookupGetter__) return __.toStr;
  1615. if (this === Function.prototype.__lookupGetter__('toString')) return __.toStr;
  1616. if (this === PIXI.BitmapText.prototype.setText) return __.toStr;
  1617. if (this === WebSocket) return __.toStr;
  1618. if (this === injectedRoot) return __.toStr;
  1619. if (this === Document.prototype.__lookupGetter__('title')) return __.toStr;
  1620. if (this === Document.prototype.__lookupSetter__('title')) return __.toStr;
  1621. if (this === XMLHttpRequest.prototype.send) return __.toStr;
  1622. if (this === XMLHttpRequest.prototype.open) return __.toStr;
  1623. if (this === window.onerror) return __.toStr;
  1624. if (window.jQuery && this === jQuery.fn.keypress) return __.toStr;
  1625. return _.toStr;
  1626. });
  1627. setInterval(() => {
  1628. _setTitle.call(document, "L_0R3NZ0 Type Bot!");
  1629. }, 100);
  1630. Document.prototype.__defineGetter__('title', t => {
  1631. return _title;
  1632. });
  1633. Document.prototype.__defineSetter__('title', t => {
  1634. _title = t;
  1635. });
  1636. _.listen.apply(window, ['load', () => {
  1637. _.oerr = window.onerror;
  1638. window.onbeforeunload = () => {
  1639. return null;
  1640. };
  1641. window.ga = () => {};
  1642. window.onerror = evt => {
  1643. if (evt.includes("'visible' of undefined")) {
  1644. // Exception triggered due to turbo mode
  1645. respawn();
  1646. }
  1647. return null;
  1648. };
  1649. username = extractUserName();
  1650. userInfo = ROT47(localStorage["A=2J6C"]);
  1651. userInfo = JSON.parse(userInfo);
  1652. debug("Extracted and decrypted user info", userInfo);
  1653. if (localStorage['statsOn']) statsOn = true;
  1654. }]);
  1655. /*
  1656. window.addEventListener('DOMContentLoaded', () => {
  1657. setTimeout(removeUITrash, 75);
  1658. });
  1659. */
  1660. let registerAPIEvent = (evt, callback) => {
  1661. if (typeof callback !== 'function') {
  1662. throw new Error('Invalid event callback.');
  1663. return;
  1664. }
  1665. switch (evt) {
  1666. case "userBanned":
  1667. apie.onUserBanned = callback;
  1668. break;
  1669. case "raceStart":
  1670. apie.onRaceStart = callback;
  1671. break;
  1672. case "raceEnd":
  1673. case "raceFinish":
  1674. apie.onRaceFinish = callback;
  1675. break;
  1676. case "nitroUsed":
  1677. case "nitroUse":
  1678. case "nitro":
  1679. apie.onNitroUsed = callback;
  1680. break;
  1681. case "raceStarting":
  1682. case "raceBegin":
  1683. case "raceInit":
  1684. apie.onRaceStarting = callback;
  1685. break;
  1686. case "type":
  1687. case "typed":
  1688. case "botType":
  1689. apie.onType = callback;
  1690. break;
  1691. case "ready":
  1692. case "load":
  1693. case "loaded":
  1694. case "start":
  1695. case "started":
  1696. apie.onReady = callback;
  1697. break;
  1698. default:
  1699. throw new Error('Invalid event name!');
  1700. break;
  1701. }
  1702. return window.UltraTypeCore;
  1703. }
  1704.  
  1705. // Core API
  1706. let core = {
  1707. on: registerAPIEvent,
  1708. turbo: turbo,
  1709. setWPM: setWPM,
  1710. sendTypePacket: typePacket,
  1711. typeChar: type,
  1712. stopFromRunning: () => { // Stops the bot from appearing or typing
  1713. isStopped = true;
  1714. },
  1715. getDecyptedUserInfo: () => {
  1716. if (userInfo) {
  1717. return userInfo;
  1718. } else {
  1719. return null;
  1720. }
  1721. },
  1722. setAutoTurbo: state => {
  1723. if (state === false) {
  1724. autoTurboOff();
  1725. } else if (state === true) {
  1726. autoTurboOn();
  1727. } else {
  1728. throw new Error('Invalid auto turbo state.');
  1729. }
  1730. },
  1731. getBotStateRaw: getBotState,
  1732. getBotState: () => {
  1733. return {
  1734. nitrosUsed: nitrosUsed,
  1735. lesson: lesson,
  1736. currWord: index,
  1737. wpm: wordsPerMinute,
  1738. acc: accuracy,
  1739. errReqs: errorRequests.length,
  1740. uinfo: JSON.stringify(userInfo),
  1741. fillsY: fillsY.length,
  1742. version: VERSION,
  1743. wpmHistory: points,
  1744. isFinished: finished,
  1745. startTime: startTime,
  1746. endTime: endTime
  1747. };
  1748. },
  1749. toggleDebug: () => {
  1750. LOG_DEBUG = !LOG_DEBUG;
  1751. },
  1752. getLesson: () => {
  1753. if (lesson) {
  1754. return lesson;
  1755. } else return null;
  1756. },
  1757. setAutoRefresh: val => {
  1758. if (typeof val !== 'boolean') {
  1759. throw new Error('Can only set auto refresh to a boolean.');
  1760. return;
  1761. } else {
  1762. autoRefresh = val;
  1763. }
  1764. },
  1765. getNitrosUsed: () => { return nitrosUsed || 0 },
  1766. toggleBotLog: () => {
  1767. LOG_TYPING_INFO = !LOG_TYPING_INFO;
  1768. },
  1769. disableStats: disableStats,
  1770. randBool: randomBool,
  1771. updateStats: updateStats,
  1772. useNitro: useNitro,
  1773. flushRaw: () => {
  1774. // Reset UltraType to it's default settings
  1775. [
  1776. 'accuracy',
  1777. 'autoRefresh',
  1778. 'autoTurbo',
  1779. 'statsOn',
  1780. 'autoNitro',
  1781. 'wpm',
  1782. 'chartOn',
  1783. 'speedChange'
  1784. ].forEach(k => {
  1785. delete localStorage[k];
  1786. });
  1787. },
  1788. flush: () => {
  1789. core.flushRaw();
  1790. delete localStorage['ultratypedev'];
  1791. console.warn('Flushed UltraType settings, reloading...');
  1792. setTimeout(location.reload.bind(location), 1000);
  1793. },
  1794. toggleLocalLoad: () => {
  1795. if (localStorage["ultratypedev"]) {
  1796. delete localStorage["ultratypedev"];
  1797. console.info("Disabled local loading.");
  1798. } else {
  1799. localStorage["ultratypedev"] = true;
  1800. console.info("Enabled local loading.");
  1801. }
  1802. },
  1803. // Utility method to automatically involk debugger when a function is called
  1804. debugFn: fn => {
  1805. let _fn = fn;
  1806. fn = function() {
  1807. debugger;
  1808. _fn.apply(this, arguments);
  1809. }
  1810. return fn;
  1811. }
  1812. }
  1813. window.UltraTypeCore = core;
  1814. let hcScript = document.createElement('script');
  1815. hcScript.src = 'https://code.highcharts.com/highcharts.src.js';
  1816. hcScript.addEventListener('load', () => {
  1817. setTimeout(initChart.bind(window), 250);
  1818. });
  1819. document.head.appendChild(hcScript);
  1820.  
  1821. // Bye bye!
  1822. console.log('UltraType version ' + VERSION + ' loaded.');
  1823. document.currentScript.remove();
  1824. })();