Discord Status Animator (Manual edit/Non-UI)

Automatically changes your Discord status

目前為 2021-06-15 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Discord Status Animator (Manual edit/Non-UI)
  3. // @namespace https://github.com/Hakorr/discord-status-animator
  4. // @run-at document-start
  5. // @version 1.5
  6. // @description Automatically changes your Discord status
  7. // @author HKR
  8. // @match https://discord.com/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. //Welcome! Don't be scared by the code, I was too lazy to do an UI for this.
  14. //All you have to edit is the statusanimation function's code (Around the line 40)
  15. var name = "Status Animator";
  16. var version = "V1.5";
  17. var run = true;
  18.  
  19. //A Cookie will be made with this name, feel free to edit it
  20. //DO NOT SHARE THIS COOKIE WITH ANYONE AS IT'S YOUR DISCORD TOKEN
  21. var cookie_name = "DoNotShareThisToken";
  22. var delete_cookie_after_a_week = true;
  23. //Your status will be changed to these after you close the Discord tab
  24. var default_status_text = "";
  25. var default_status_emoji = "";
  26. var default_status_state = "online";
  27. //Animation blocks////////////////
  28. /* Timeouts are in milliseconds! You can type "random" on the emoji section to randomize it!
  29. - await delay(ms);
  30. - await blank();
  31. - await setstate("state");
  32. -> states = invisible, dnd, idle, online
  33. - await setemoji("emoji");
  34. - await settext("text");
  35. - await status(emoji,text,state);
  36. -> states = invisible, dnd, idle, online
  37. - await typewriter("emoji","text",timeout,reversed);
  38. - await glitch("emoji","text",times,timeout);
  39. - await glitchtype("emoji","text",timeout,glitch_rate,reversed);
  40. - await sentence("emoji","text",timeout);
  41. - await blink("emoji","text",timeout,times);
  42. - await count("emoji","prefix",count_to,"suffix",timeout,reversed);
  43. */async function statusanimation() {
  44. ////////////////////////////////////
  45. //This is your animation code///////
  46.  
  47. await status("👐","This","online");
  48. await delay(500);
  49.  
  50. await status("👀","Is","dnd");
  51. await delay(500);
  52.  
  53. await status("😶","a test...","idle");
  54. await delay(500);
  55.  
  56. await status("","","online");
  57. await delay(500);
  58.  
  59. await typewriter("⌨️","It's just a test!",100);
  60. await typewriter("It's just a test!",100,true);
  61. await delay(500);
  62.  
  63. await glitch("random","I am just testing this!",25,100);
  64.  
  65. await glitchtype("I am just testing this!",50,5);
  66. await glitchtype("🥳","I am just testing this!",50,5,true);
  67. await delay(1000);
  68.  
  69. await sentence("🙈","This is a test!",500);
  70. await delay(500);
  71.  
  72. await blink("👁️","Just testing...",1000,5);
  73. await delay(5000);
  74. await count("I've tested this ",10," times!",500,false);
  75. await count("⏱️","(",10," Seconds) Until detonation",100,true);
  76. await status("💥","Boom!!!","dnd");
  77. await delay(100);
  78. await setstate("idle");
  79. await delay(100);
  80. await setstate("dnd");
  81. await delay(100);
  82. await setstate("idle");
  83. await delay(100);
  84. await setstate("dnd");
  85. await delay(1000);
  86. await settext("Finished!");
  87. await delay(1000);
  88. await blank();
  89. await delay(5000);
  90. /////////////////////////////
  91. //This loops the animation
  92. if (run) statusanimation(); }
  93. //Do not edit after this line (If you don't know what you're doing)
  94. ///////////////////////////////////////////////////////////////////
  95.  
  96. function random_emoji() {
  97. var emojis = [
  98. '😄','😃','😀','😊','☺','😉','😍','😘','😚','😗','😙','😜','😝','😛','😳','😁','😔','😌','😒','😞','😣','😢','😂','😭','😪','😥','😰','😅','😓','😩','😫','😨','😱','😠','😡','😤','😖','😆','😋','😷','😎','😴','😵','😲','😟','😦','😧','😈','👿','😮','😬','😐','😕','😯','😶','😇','😏','😑','👲','👳','👮','👷','💂','👶','👦','👧','👨','👩','👴','👵','👱','👼','👸','😺','😸','😻','😽','😼','🙀','😿','😹','😾','👹','👺','🙈','🙉','🙊','💀','👽','💩','🔥','✨','🌟','💫','💥','💢','💦','💧','💤','💨','👂','👀','👃','👅','👄','👍','👎','👌','👊','✊','✌','👋','✋','👐','👆','👇','👉','👈','🙌','🙏','☝','👏','💪','🚶','🏃','💃','👫','👪','👬','👭','💏','💑','👯','🙆','🙅','💁','🙋','💆','💇','💅','👰','🙎','🙍','🙇','🎩','👑','👒','👟','👞','👡','👠','👢','👕','👔','👚','👗','🎽','👖','👘','👙','💼','👜','👝','👛','👓','🎀','🌂','💄','💛','💙','💜','💚','❤','💔','💗','💓','💕','💖','💞','💘','💌','💋','💍','💎','👤','👥','💬','👣','💭','🐶','🐺','🐱','🐭','🐹','🐰','🐸','🐯','🐨','🐻','🐷','🐽','🐮','🐗','🐵','🐒','🐴','🐑','🐘','🐼','🐧','🐦','🐤','🐥','🐣','🐔','🐍','🐢','🐛','🐝','🐜','🐞','🐌','🐙','🐚','🐠','🐟','🐬','🐳','🐋','🐄','🐏','🐀','🐃','🐅','🐇','🐉','🐎','🐐','🐓','🐕','🐖','🐁','🐂','🐲','🐡','🐊','🐫','🐪','🐆','🐈','🐩','🐾','💐','🌸','🌷','🍀','🌹','🌻','🌺','🍁','🍃','🍂','🌿','🌾','🍄','🌵','🌴','🌲','🌳','🌰','🌱','🌼','🌐','🌞','🌝','🌚','🌑','🌒','🌓','🌔','🌕','🌖','🌗','🌘','🌜','🌛','🌙','🌍','🌎','🌏','🌋','🌌','🌠','⭐','☀','⛅','☁','⚡','☔','❄','⛄','🌀','🌁','🌈','🌊','🎍','💝','🎎','🎒','🎓','🎏','🎆','🎇','🎐','🎑','🎃','👻','🎅','🎄','🎁','🎋','🎉','🎊','🎈','🎌','🔮','🎥','📷','📹','📼','💿','📀','💽','💾','💻','📱','☎','📞','📟','📠','📡','📺','📻','🔊','🔉','🔈','🔇','🔔','🔕','📢','📣','⏳','⌛','⏰','⌚','🔓','🔒','🔏','🔐','🔑','🔎','💡','🔦','🔆','🔅','🔌','🔋','🔍','🛁','🛀','🚿','🚽','🔧','🔩','🔨','🚪','🚬','💣','🔫','🔪','💊','💉','💰','💴','💵','💷','💶','💳','💸','📲','📧','📥','📤','✉','📩','📨','📯','📫','📪','📬','📭','📮','📦','📝','📄','📃','📑','📊','📈','📉','📜','📋','📅','📆','📇','📁','📂','✂','📌','📎','✒','✏','📏','📐','📕','📗','📘','📙','📓','📔','📒','📚','📖','🔖','📛','🔬','🔭','📰','🎨','🎬','🎤','🎧','🎼','🎵','🎶','🎹','🎻','🎺','🎷','🎸','👾','🎮','🃏','🎴','🀄','🎲','🎯','🏈','🏀','⚽','⚾','🎾','🎱','🏉','🎳','⛳','🚵','🚴','🏁','🏇','🏆','🎿','🏂','🏊','🏄','🎣','☕','🍵','🍶','🍼','🍺','🍻','🍸','🍹','🍷','🍴','🍕','🍔','🍟','🍗','🍖','🍝','🍛','🍤','🍱','🍣','🍥','🍙','🍘','🍚','🍜','🍲','🍢','🍡','🍳','🍞','🍩','🍮','🍦','🍨','🍧','🎂','🍰','🍪','🍫','🍬','🍭','🍯','🍎','🍏','🍊','🍋','🍒','🍇','🍉','🍓','🍑','🍈','🍌','🍐','🍍','🍠','🍆','🍅','🌽','🏠','🏡','🏫','🏢','🏣','🏥','🏦','🏪','🏩','🏨','💒','⛪','🏬','🏤','🌇','🌆','🏯','🏰','⛺','🏭','🗼','🗾','🗻','🌄','🌅','🌃','🗽','🌉','🎠','🎡','⛲','🎢','🚢','⛵','🚤','🚣','⚓','🚀','✈','💺','🚁','🚂','🚊','🚉','🚞','🚆','🚄','🚅','🚈','🚇','🚝','🚋','🚃','🚎','🚌','🚍','🚙','🚘','🚗','🚕','🚖','🚛','🚚','🚨','🚓','🚔','🚒','🚑','🚐','🚲','🚡','🚟','🚠','🚜','💈','🚏','🎫','🚦','🚥','⚠','🚧','🔰','⛽','🏮','🎰','♨','🗿','🎪','🎭','📍','🚩','⬆','⬇','⬅','➡','🔠','🔡','🔤','↗','↖','↘','↙','↔','↕','🔄','◀','▶','🔼','🔽','↩','↪','ℹ','⏪','⏩','⏫','⏬','⤵','⤴','🆗','🔀','🔁','🔂','🆕','🆙','🆒','🆓','🆖','📶','🎦','🈁','🈯','🈳','🈵','🈴','🈲','🉐','🈹','🈺','🈶','🈚','🚻','🚹','🚺','🚼','🚾','🚰','🚮','🅿','♿','🚭','🈷','🈸','🈂','Ⓜ','🛂','🛄','🛅','🛃','🉑','㊙','㊗','🆑','🆘','🆔','🚫','🔞','📵','🚯','🚱','🚳','🚷','🚸','⛔','✳','❇','❎','✅','✴','💟','🆚','📳','📴','🅰','🅱','🆎','🅾','💠','➿','♻','♈','♉','♊','♋','♌','♍','♎','♏','♐','♑','♒','♓','⛎','🔯','🏧','💹','💲','💱','©','®','™','〽','〰','🔝','🔚','🔙','🔛','🔜','❌','⭕','❗','❓','❕','❔','🔃','🕛','🕧','🕐','🕜','🕑','🕝','🕒','🕞','🕓','🕟','🕔','🕠','🕕','🕖','🕗','🕘','🕙','🕚','🕡','🕢','🕣','🕤','🕥','🕦','✖','➕','➖','➗','♠','♥','♣','♦','💮','💯','✔','☑','🔘','🔗','➰','🔱','🔲','🔳','◼','◻','◾','◽','▪','▫','🔺','⬜','⬛','⚫','⚪','🔴','🔵','🔻','🔶','🔷','🔸','🔹'
  99. ];
  100. return emojis[Math.floor(Math.random() * emojis.length)];
  101. }
  102. //Output XX/XX/XX @ XX:XX:XX
  103. function getDateTime() {
  104. var currentdate = new Date();
  105. if(currentdate.getMinutes() > 9) var fixed_minutes = currentdate.getMinutes();
  106. else var fixed_minutes = "0" + currentdate.getMinutes();
  107. if(currentdate.getSeconds() > 9) var fixed_seconds = currentdate.getSeconds();
  108. else var fixed_seconds = "0" + currentdate.getSeconds();
  109.  
  110. var datetime = currentdate.getDate() + "/" + (currentdate.getMonth()+1) + "/" + currentdate.getFullYear() + " @ " + currentdate.getHours() + ":" + fixed_minutes + ":" + fixed_seconds;
  111.  
  112. return datetime;
  113. }
  114. //Output: XX:XX:XX
  115. function getExactTime() {
  116. var currentdate = new Date();
  117. if(currentdate.getMinutes() > 9) var fixed_minutes = currentdate.getMinutes();
  118. else var fixed_minutes = "0" + currentdate.getMinutes();
  119. if(currentdate.getSeconds() > 9) var fixed_seconds = currentdate.getSeconds();
  120. else var fixed_seconds = "0" + currentdate.getSeconds();
  121.  
  122. var datetime = currentdate.getHours() + ":" + fixed_minutes + ":" + fixed_seconds;
  123.  
  124. return datetime;
  125. }
  126. //Output: X:XX
  127. function getTime() {
  128. var currentdate = new Date();
  129. if(currentdate.getMinutes() > 9) var fixed_minutes = currentdate.getMinutes();
  130. else var fixed_minutes = "0" + currentdate.getMinutes();
  131.  
  132. var datetime = currentdate.getHours() + ":" + fixed_minutes;
  133.  
  134. return datetime;
  135. }
  136. //Simple delay function for animation
  137. function delay(t) {
  138. return new Promise(function(resolve) {
  139. setTimeout(resolve, t)
  140. });
  141. }
  142. //Typewriter effect
  143. async function typewriter(emoji,text,timeout,reversed) {
  144. //Repeat for each letter
  145. for(var i = 1; i <= text.length; i++) {
  146. //Cut the text
  147. if(!reversed) var substring_text = text.substring(0,i);
  148. else var substring_text = text.substring(0,text.length - i);
  149. //Set the status to the cutted text
  150. if(emoji != "random") await status(emoji,substring_text);
  151. else await status(random_emoji(),substring_text);
  152. //Wait a selected amount of time until writing the next letter
  153. await delay(timeout);
  154. }
  155. return;
  156. }
  157.  
  158. //Glitch effect
  159. async function glitch(emoji,text,times,timeout) {
  160. //Repeat for each letter
  161. for(var i = 1; i < times; i++) {
  162. //Shuffle the text
  163. var glitch_text = shuffle(text)
  164. //Set the status to the cutted text
  165. if(emoji != "random") await status(emoji,glitch_text);
  166. else await status(random_emoji(),glitch_text);
  167. //Wait a selected amount of time until writing the next letter
  168. await delay(timeout);
  169. }
  170. return;
  171. }
  172. //Glitchtype effect
  173. async function glitchtype(emoji,text,timeout,glitch_rate,reversed) {
  174. //Repeat for each letter
  175. for(var i = 1; i <= text.length; i++) {
  176. //Cut the text
  177. if(!reversed) var substring_text = text.substring(0,i);
  178. else var substring_text = text.substring(0,text.length - i);
  179. //Glitch rest of the text
  180. if(!reversed) var glitch_text = shuffle(text.substring(i));
  181. else var glitch_text = shuffle(text.substring(text.length - i));
  182. //Set the status to the cutted text + glitched text
  183. if(emoji != "random") await status(emoji,substring_text + glitch_text);
  184. else await status(random_emoji(),substring_text + glitch_text);
  185. //Wait a selected amount of time until writing the next letter
  186. await delay(timeout);
  187. for(var a = 0; a < glitch_rate; a++) {
  188. //Glitch rest of the text
  189. if(!reversed) var glitch_text = shuffle(text.substring(i));
  190. else var glitch_text = shuffle(text.substring(text.length - i));
  191. //Set the status to the cutted text + glitched text
  192. await status(emoji,substring_text + glitch_text);
  193. //Wait a selected amount of time until writing the next glitched characterset at the end of the string
  194. await delay(timeout/2);
  195. }
  196. }
  197. return;
  198. }
  199. async function sentence(emoji,text,timeout) {
  200. //Split sentence into words
  201. var words = text.split(" ");
  202. //Repeat for each word
  203. for(var i = 0; i < words.length; i++) {
  204. //Set status to array's word
  205. if(emoji != "random") await status(emoji,words[i]);
  206. else await status(random_emoji(),words[i]);
  207. //Wait a selected amount of time until writing the next letter
  208. await delay(timeout);
  209. }
  210. return;
  211. }
  212. async function blink(emoji,text,timeout,times) {
  213. for(var i = 0; i < times; i++) {
  214. if(emoji != "random") await status(emoji,text);
  215. else await status(random_emoji(),text);
  216. await delay(timeout);
  217. await blank();
  218. await delay(timeout);
  219. }
  220. return;
  221. }
  222. async function blank() {
  223. //Could just send blank status as {"custom_status":null}, but that behaves weirdly.
  224. await status("","");
  225. return;
  226. }
  227. async function count(emoji,prefix,count_to,suffix,timeout,reversed) {
  228. for(var i = 0; i < count_to; i++) {
  229. if(!reversed) {
  230. var recalculated_count = i + 1;
  231. var final_string = prefix + recalculated_count + suffix;
  232. }
  233. else {
  234. var recalculated_count = count_to - i;
  235. var final_string = prefix + recalculated_count + suffix;
  236. }
  237. if(emoji != "random") await status(emoji,final_string);
  238. else await status(random_emoji(),final_string);
  239. await delay(timeout);
  240. }
  241. return;
  242. }
  243. //codespeedy.com/shuffle-characters-of-a-string-in-javascript/
  244. function getRandomInt(n) {
  245. return Math.floor(Math.random() * n);
  246. }
  247. //codespeedy.com/shuffle-characters-of-a-string-in-javascript/
  248. function shuffle(s) {
  249. var arr = s.split(''); // Convert String to array
  250. var n = arr.length; // Length of the array
  251.  
  252. for(var i=0 ; i<n-1 ; ++i) {
  253. var j = getRandomInt(n); // Get random of [0, n-1]
  254.  
  255. var temp = arr[i]; // Swap arr[i] and arr[j]
  256. arr[i] = arr[j];
  257. arr[j] = temp;
  258. }
  259.  
  260. s = arr.join(''); // Convert Array to string
  261. return s; // Return shuffled string
  262. }
  263. //Function to read the saved cookie
  264. window.getCookie = function(name) {
  265. var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
  266. if (match) return match[2];
  267. }
  268. //Set the Discord Token as a Cookie for future use of the script
  269. //If there is no Token cookie
  270. if(document.cookie.indexOf(cookie_name + "=") == -1) {
  271. //Ask user if they want to refresh the page to get the token
  272. if(confirm("\"" + cookie_name + "\" cookie not found. Refreshing Discord to get it.\n\n- " + name + " " + version)) {
  273. //Load the page again and create a new element which will have the token in its localStorage
  274. location.reload();
  275. var i = document.createElement('iframe');
  276. document.body.appendChild(i);
  277. //Get Token from localStorage
  278. var token = i.contentWindow.localStorage.token
  279. token = token.slice(1, -1);
  280. //Delete cookie after a week or not
  281. if(delete_cookie_after_a_week)
  282. document.cookie = cookie_name + "=" + token + "; secure=true; max-age=604800; path=/";
  283. else
  284. document.cookie = cookie_name + "=" + token + "; secure=true; path=/";
  285.  
  286. } else throw new Error("[Not an actually uncaught] User stopped the Status Animator. \n\nNo cookie was found and user decided not to continue.");
  287. }
  288. var status_text = "";
  289. var status_emoji = "";
  290. var status_state = "";
  291. //Function that changes the status variables (Saves up a bit space)
  292. async function status(emoji,text,state) {
  293. if(run) {
  294. status_text = text;
  295. status_emoji = emoji;
  296. status_state = state;
  297. await setstatus();
  298. return;
  299. }
  300. }
  301. //Get Discord Token from saved Cookie
  302. var token = getCookie(cookie_name);
  303.  
  304. //HTTP Request's URL address
  305. var url = "https://discord.com/api/v9/users/@me/settings";
  306. //Function that handles the HTTP request for the status change
  307. async function setstatus() {
  308.  
  309. var request = new XMLHttpRequest();
  310. request.open("PATCH", url);
  311. request.setRequestHeader("Accept", "*/*" );
  312. request.setRequestHeader("Content-Type", "application/json");
  313. request.setRequestHeader("Authorization", token);
  314. request.send(JSON.stringify({"custom_status":{"text":status_text,"emoji_name":status_emoji}}));
  315.  
  316. //If the request failed
  317. request.onreadystatechange = () => {
  318. if (request.status != 200) {
  319. run = false;
  320. throw new Error("[Not an actually uncaught] Failed to update status. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
  321. }
  322. };
  323. if(status_state == "invisible" || status_state == "dnd" || status_state == "idle" || status_state == "online") {
  324. var request2 = new XMLHttpRequest();
  325. request2.open("PATCH", url);
  326. request2.setRequestHeader("Accept", "*/*" );
  327. request2.setRequestHeader("Content-Type", "application/json");
  328. request2.setRequestHeader("Authorization", token);
  329. request2.send(JSON.stringify({"status":status_state}));
  330. //If the request failed
  331. request2.onreadystatechange = () => {
  332. if (request2.status != 200) {
  333. run = false;
  334. throw new Error("[Not an actually uncaught] Failed to update status. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
  335. }
  336. };
  337. }
  338. return;
  339. }
  340. async function setstate(text) {
  341. if(run) {
  342. status_state = text;
  343. if(status_state == "invisible" || status_state == "dnd" || status_state == "idle" || status_state == "online") {
  344. var request = new XMLHttpRequest();
  345. request.open("PATCH", url);
  346. request.setRequestHeader("Accept", "*/*" );
  347. request.setRequestHeader("Content-Type", "application/json");
  348. request.setRequestHeader("Authorization", token);
  349. request.send(JSON.stringify({"status":status_state}));
  350. //If the request failed
  351. request.onreadystatechange = () => {
  352. if (request.status != 200) {
  353. run = false;
  354. throw new Error("[Not an actually uncaught] Failed to update state. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
  355. }
  356. };
  357. }
  358.  
  359. return;
  360. }
  361. }
  362. async function setemoji(emoji) {
  363. if(run) {
  364. status_emoji = emoji;
  365. var request = new XMLHttpRequest();
  366. request.open("PATCH", url);
  367. request.setRequestHeader("Accept", "*/*" );
  368. request.setRequestHeader("Content-Type", "application/json");
  369. request.setRequestHeader("Authorization", token);
  370. request.send(JSON.stringify({"custom_status":{"emoji_name":status_emoji}}));
  371.  
  372. //If the request failed
  373. request.onreadystatechange = () => {
  374. if (request.status != 200) {
  375. run = false;
  376. throw new Error("[Not an actually uncaught] Failed to update emoji. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
  377. }
  378. };
  379.  
  380. return;
  381. }
  382. }
  383. async function settext(text) {
  384. if(run) {
  385. status_text = text;
  386. var request = new XMLHttpRequest();
  387. request.open("PATCH", url);
  388. request.setRequestHeader("Accept", "*/*" );
  389. request.setRequestHeader("Content-Type", "application/json");
  390. request.setRequestHeader("Authorization", token);
  391. request.send(JSON.stringify({"custom_status":{"text":status_text}}));
  392.  
  393. //If the request failed
  394. request.onreadystatechange = () => {
  395. if (request.status != 200) {
  396. run = false;
  397. throw new Error("[Not an actually uncaught] Failed to update text. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
  398. }
  399. };
  400.  
  401. return;
  402. }
  403. }
  404. //Start the animation for the first time
  405. if (run) statusanimation();
  406. //Edit (Clear by default) status before exiting
  407. window.onbeforeunload = function () {
  408. run = false;
  409. status_text = default_status_text;
  410. status_emoji = default_status_emoji;
  411. if(status_state == "invisible" || status_state == "dnd" || status_state == "idle" || status_state == "online")
  412. status_state = default_status_state;
  413. setstatus();
  414. return "";
  415. };
  416. })();