Gartic.io Anonim Menu

Press F2 to open and close the menu

  1. // ==UserScript==
  2. // @name Gartic.io Anonim Menu
  3. // @namespace https://greasyfork.org/
  4. // @version 2024-01-18
  5. // @description Press F2 to open and close the menu
  6. // @author anonimbiri
  7. // @match https://gartic.io/*
  8. // @icon https://www.google.com/s2/favicons?sz=64&domain=gartic.io
  9. // @require https://update.greasyfork.org/scripts/482771/1321969/Malayala%20Kit.js
  10. // @grant none
  11. // ==/UserScript==
  12. const AnonimbiriAPI = {
  13. ws: null,
  14. isGame: false,
  15. playerId: null,
  16. unlimitedKick: false,
  17. autoSkip: false,
  18. antiAfk: false,
  19. noCooldown: false,
  20. autoGuessing: false,
  21. hint: null,
  22. wordListURL: null,
  23. wordList: [],
  24. hotkey: new KeyboardEvent('keyup', {
  25. key: "F2",
  26. keyCode: 113,
  27. ctrlKey: false,
  28. altKey: false,
  29. shiftKey: false
  30. }),
  31. debug: false,
  32. };
  33. var toastManager = new MalayalaKit.ToastManager();
  34. const kit = new MalayalaKit.CreateMenu({
  35. title: "Anonim Menu",
  36. icon: "",
  37. size: { width: 500, height: 400 },
  38. position: { top: 50, left: 50 },
  39. hotkey: AnonimbiriAPI.hotkey,
  40. });
  41. const general = new MalayalaKit.Tab("General");
  42. general.addSwitch({
  43. label: "Unlimited Kick",
  44. value: false,
  45. onchange: (value) => {
  46. AnonimbiriAPI.unlimitedKick = value;
  47. toastManager.showToast({ message: 'Unlimited Kick is ' + (value ? 'ON' : 'OFF'), type: 'info' });
  48. },
  49. });
  50. general.addSwitch({
  51. label: "Auto Skip",
  52. value: false,
  53. onchange: (value) => {
  54. AnonimbiriAPI.autoSkip = value;
  55. toastManager.showToast({ message: 'Auto Skip is ' + (value ? 'ON' : 'OFF'), type: 'info' });
  56. },
  57. });
  58. general.addSwitch({
  59. label: "Anti Afk",
  60. value: false,
  61. onchange: (value) => {
  62. AnonimbiriAPI.antiAfk = value;
  63. toastManager.showToast({ message: 'Anti Afk is ' + (value ? 'ON' : 'OFF'), type: 'info' });
  64. },
  65. });
  66. general.addSwitch({
  67. label: "No Cooldown For Room Change",
  68. value: false,
  69. onchange: (value) => {
  70. AnonimbiriAPI.noCooldown = value;
  71. toastManager.showToast({ message: 'No Cooldown For Room Change is ' + (value ? 'ON' : 'OFF'), type: 'info' });
  72. },
  73. });
  74. general.addHotkey({
  75. label: "Menu Hotkey",
  76. style: "border",
  77. value: AnonimbiriAPI.hotkey,
  78. onlistener: function (event) {
  79. AnonimbiriAPI.hotkey = event;
  80. toastManager.showToast({ message: 'Menu Opening Hotkey Set To ' + event.key, type: 'info' });
  81. }
  82. });
  83. kit.addTab(general);
  84. const guess = new MalayalaKit.Tab("Guess");
  85. guess.addSwitch({
  86. label: "Auto Guessing",
  87. value: false,
  88. onchange: (value) => {
  89. AnonimbiriAPI.autoGuessing = value;
  90. toastManager.showToast({ message: 'Auto Guessing is ' + (value ? 'ON' : 'OFF'), type: 'info' });
  91. },
  92. });
  93. guess.addInput({
  94. label: "Word List",
  95. placeholder: "wordList.txt",
  96. type: "text",
  97. value: AnonimbiriAPI.wordListURL,
  98. onchange: (value) => {
  99. AnonimbiriAPI.wordListURL = value;
  100. fetch(AnonimbiriAPI.wordListURL)
  101. .then(response => response.text())
  102. .then(data => {
  103. AnonimbiriAPI.wordList = data.split('\n').map(word => word.trim().toLowerCase());
  104. }).catch(error => AnonimbiriAPI.debug && console.error('Error:', error));
  105. },
  106. });
  107. kit.addTab(guess);
  108. let fakeWinText = "anonimbiri";
  109. const local = new MalayalaKit.Tab("Local");
  110. local.addInput({
  111. label: "Fake Win text",
  112. placeholder: "Enter Fake Win text",
  113. type: "text",
  114. value: fakeWinText,
  115. onchange: (value) => {
  116. fakeWinText = value;
  117. },
  118. });
  119. local.addButton({
  120. label: "Send Fake Win",
  121. style: "border",
  122. buttonLabel: "Send Fake Win",
  123. onclick: () => {
  124. const event = new MessageEvent("message", {
  125. data: `42["26","${fakeWinText}",10,11,10000]`,
  126. });
  127. AnonimbiriAPI.ws.dispatchEvent(event);
  128. },
  129. });
  130. kit.addTab(local);
  131. let intervalId = null;
  132. let spamText = "anonimbiri";
  133. const spam = new MalayalaKit.Tab("Spam");
  134. spam.addSwitch({
  135. label: "Spam",
  136. value: false,
  137. onchange: (value) => {
  138. if (value) {
  139. intervalId = setInterval(() => {
  140. const randomIndex = Math.floor(Math.random() * (spamText.length + 1));
  141. const newText = spamText.replace(/(‎{${randomIndex}})/, '$1.');
  142. AnonimbiriAPI.ws.send(`42[11,${AnonimbiriAPI.playerId},"${newText}"]`);
  143. }, 800);
  144. } else {
  145. clearInterval(intervalId);
  146. }
  147. toastManager.showToast({ message: 'Spam Has ' + (value ? 'Started' : 'Heen Stopped'), type: 'info' });
  148. },
  149. });
  150. spam.addInput({
  151. label: "Spam text",
  152. placeholder: "Enter Spam text",
  153. type: "text",
  154. value: spamText,
  155. onchange: (value) => {
  156. spamText = value;
  157. },
  158. });
  159. kit.addTab(spam);
  160. let intervalHint = null;
  161. let index = 0;
  162. window.WebSocket = class extends WebSocket {
  163. constructor(...args) {
  164. super(...args);
  165. AnonimbiriAPI.ws = this;
  166. this.addEventListener("message", (e) => {
  167. AnonimbiriAPI.debug && console.log("%c<--- Received data:", "color: pink", e.data);
  168. const messageData = JSON.parse(e.data.slice(2));
  169. if (messageData[0] === "45" && AnonimbiriAPI.unlimitedKick) {
  170. const OriginalDate = window.Date;
  171. window.Date = class extends Date {
  172. static now() {
  173. return super.now() * 2123;
  174. }
  175. };
  176. setTimeout(() => {
  177. window.Date = OriginalDate;
  178. }, 2000);
  179. return;
  180. } else if (messageData[0] === "5") {
  181. AnonimbiriAPI.isGame = true;
  182. AnonimbiriAPI.playerId = messageData[2];
  183. } else if (messageData[0] === "16" && AnonimbiriAPI.autoSkip) {
  184. AnonimbiriAPI.ws.send(`42[25,${AnonimbiriAPI.playerId}]`);
  185. } else if (messageData[0] === "34") {
  186. AnonimbiriAPI.ws.send(`42[30,${AnonimbiriAPI.playerId}]`);
  187. AnonimbiriAPI.ws.send(`42[30,${AnonimbiriAPI.playerId}]`);
  188. AnonimbiriAPI.ws.send(`42[30,${AnonimbiriAPI.playerId}]`);
  189. } else if (messageData[0] === "19" && AnonimbiriAPI.antiAfk) {
  190. window.Date = class extends Date {
  191. static now() {
  192. return super.now() / 2123;
  193. }
  194. };
  195. } else if (messageData[0] === "23") {
  196. !AnonimbiriAPI.debug && console.clear();
  197. const nickElements = document.querySelectorAll('.nick');
  198. nickElements.forEach((nickElement) => {
  199. const nickName = nickElement.innerText;
  200. if (
  201. nickName.startsWith('‎') &&
  202. !nickElement.parentElement.querySelector('.cheater') &&
  203. !nickElement.parentElement.parentElement.classList.contains('you')
  204. ) {
  205. const newElement = document.createElement('span');
  206. newElement.classList.add('cheater');
  207. newElement.style = 'color:pink; font-weight: bold; font-family: "Lucida Console", "Courier New", monospace;';
  208. newElement.innerText = `🎮 Cheater`;
  209. nickElement.parentElement.appendChild(newElement);
  210. }
  211. });
  212. } else if (messageData[0] ==="30") {
  213. AnonimbiriAPI.hint = messageData[1].join('');
  214. if(!AnonimbiriAPI.autoGuessing && !AnonimbiriAPI.hint && intervalHint) return;
  215. setInterval(() => {
  216. const hints = guessWord(AnonimbiriAPI.hint);
  217. if (index < hints.length) AnonimbiriAPI.ws.send(`42[13,${AnonimbiriAPI.playerId},"${hints[index++]}"]`), AnonimbiriAPI.wordList.splice(AnonimbiriAPI.wordList.indexOf(hints[index++]), 1);
  218. else clearInterval(intervalHint);
  219. }, 1000);
  220. } else if (messageData[0] ==="19" && intervalHint) {
  221. AnonimbiriAPI.hint = null;
  222. clearInterval(intervalHint);
  223. fetch(AnonimbiriAPI.wordListURL)
  224. .then(response => response.text())
  225. .then(data => {
  226. AnonimbiriAPI.wordList = data.split('\n').map(word => word.trim().toLowerCase());
  227. }).catch(error => AnonimbiriAPI.debug && console.error('Error:', error));
  228. } else if (messageData[0] ==="13" && AnonimbiriAPI.wordList.length !== 0) {
  229. const index = AnonimbiriAPI.wordList.indexOf(messageData[1].toLowerCase());
  230. index !== -1 && AnonimbiriAPI.wordList.splice(index, 1)
  231. }
  232. });
  233. }
  234. send(data) {
  235. AnonimbiriAPI.debug && console.log("%c---> Sent data:", "color: pink", data);
  236. const newData = JSON.parse(data.slice(2));
  237. if (newData[1] && newData[1].nick) {
  238. newData[1].nick = `‎${newData[1].nick}`;
  239. data = data.slice(0, 2) + JSON.stringify(newData);
  240. super.send(data);
  241. } else if (newData[0] === "46") {
  242. } else {
  243. super.send(data);
  244. }
  245. }
  246. };
  247. function guessWord(guessedPattern) {
  248. if (!guessedPattern) return;
  249. const wordList = AnonimbiriAPI.wordList.map(word => word.toLowerCase());
  250. const length = guessedPattern.length;
  251. const possibleWords = [];
  252. for (let i = 0; i < wordList.length; i++) {
  253. const word = wordList[i];
  254. if (word.length === length) {
  255. let match = true;
  256. for (let j = 0; j < length; j++) {
  257. if (guessedPattern[j] !== '_' && guessedPattern[j] !== word[j]) {
  258. match = false;
  259. break;
  260. }
  261. }
  262. if (match) {
  263. possibleWords.push(word);
  264. }
  265. }
  266. }
  267. return possibleWords;
  268. }
  269. // I'll just leave it here that such a method exists and works
  270. /*function requestText (url) {
  271. return fetch(url).then((d) => {return d.text()})
  272. }
  273. function requestBuffer (url) {
  274. return fetch(url).then((d) => {return d.arrayBuffer()})
  275. }
  276. Node.prototype.appendChild = new Proxy(Node.prototype.appendChild, {
  277. apply: async function (target, thisArg, [element]) {
  278. if (element.tagName === "SCRIPT" && element.src.includes('room')) {
  279. let text = await requestText(element.src);
  280. text = text.replace(/this\._lang\.violatingRules/g, '"dememe"'); // this is the wrong code lol
  281. let blob = new Blob([text]);
  282. element.src = URL.createObjectURL(blob);
  283. }
  284. return Reflect.apply(target, thisArg, [element]);
  285. }
  286. });*/
  287. const observer = new MutationObserver(() => {
  288. const input = document.querySelector('input[name="chat"]');
  289. input?.disabled && input.querySelector('input[name="chat"]').replaceWith(
  290. Object.assign(document.createElement('input'), {
  291. type: 'text',
  292. name: 'chat',
  293. className: 'mousetrap',
  294. placeholder: '🔓 Chat Unlocked',
  295. autocomplete: 'off',
  296. autocorrect: 'off',
  297. autocapitalize: 'off',
  298. maxLength: 100,
  299. value: '',
  300. })
  301. );
  302. if (document.querySelector('#popUp') && AnonimbiriAPI.noCooldown) {
  303. const OriginalDate = window.Date;
  304. window.Date = class extends Date {
  305. static now() {
  306. return super.now() * 2123;
  307. }
  308. };
  309. setTimeout(() => {
  310. window.Date = class extends Date {
  311. static now() {
  312. return super.now() / 2123;
  313. }
  314. };
  315. }, 500);
  316. document.querySelector('.ic-playHome').click();
  317. }
  318. });
  319. observer.observe(document.body, { childList: true, subtree: false });
  320. const keyupEvent = (e) => {
  321. if (e.keyCode === 13) {
  322. const chatInput = document.querySelector('input[name="chat"]');
  323. AnonimbiriAPI.ws.send(`42[11,${AnonimbiriAPI.playerId},"${chatInput.value}"]`);
  324. chatInput.value = '';
  325. }
  326. };
  327. window.addEventListener('keyup', keyupEvent);
  328. window.AnonimbiriAPI = AnonimbiriAPI;
  329. kit.render();