Advertisement
Guest User

Untitled

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