Discord Status Animator (Manual edit/Non-UI)

Automatically changes your Discord status

اعتبارا من 15-06-2021. شاهد أحدث إصدار.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

ستحتاج إلى تثبيت إضافة مثل Stylus لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتتمكن من تثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

(لدي بالفعل مثبت أنماط للمستخدم، دعني أقم بتثبيته!)

// ==UserScript==
// @name         Discord Status Animator (Manual edit/Non-UI)
// @namespace    https://github.com/Hakorr/discord-status-animator
// @run-at       document-start
// @version      1.5
// @description  Automatically changes your Discord status
// @author       HKR
// @match        https://discord.com/*
// @grant        none
// ==/UserScript==

(function() {
	//Welcome! Don't be scared by the code, I was too lazy to do an UI for this.
	//All you have to edit is the statusanimation function's code (Around the line 40)
	
	var name = "Status Animator";
	var version = "V1.5";
	var run = true;

	//A Cookie will be made with this name, feel free to edit it
	//DO NOT SHARE THIS COOKIE WITH ANYONE AS IT'S YOUR DISCORD TOKEN
	var cookie_name = "DoNotShareThisToken";
	var delete_cookie_after_a_week = true;
	
	//Your status will be changed to these after you close the Discord tab
	var default_status_text = "";
	var default_status_emoji = "";
	var default_status_state = "online";
	
	//Animation blocks////////////////
	/* Timeouts are in milliseconds! You can type "random" on the emoji section to randomize it!
	
	 - await delay(ms);
	
	 - await blank();
	 
	 - await setstate("state");
		-> states = invisible, dnd, idle, online
		
	 - await setemoji("emoji");
	 
	 - await settext("text");
		
	 - await status(emoji,text,state);
		-> states = invisible, dnd, idle, online
		
	 - await typewriter("emoji","text",timeout,reversed);
	 
	 - await glitch("emoji","text",times,timeout);
	 
	 - await glitchtype("emoji","text",timeout,glitch_rate,reversed);
	 
	 - await sentence("emoji","text",timeout);
	 
	 - await blink("emoji","text",timeout,times);
	 
	 - await count("emoji","prefix",count_to,"suffix",timeout,reversed);
	
	*/async function statusanimation() {
	////////////////////////////////////
	//This is your animation code///////

	await status("👐","This","online");
	await delay(500);

	await status("👀","Is","dnd");
	await delay(500);

	await status("😶","a test...","idle");
	await delay(500);

	await status("","","online");
	await delay(500);

	await typewriter("⌨️","It's just a test!",100);
	await typewriter("It's just a test!",100,true);
	await delay(500);

	await glitch("random","I am just testing this!",25,100);

	await glitchtype("I am just testing this!",50,5);
	await glitchtype("🥳","I am just testing this!",50,5,true);
	await delay(1000);

	await sentence("🙈","This is a test!",500);
	await delay(500);

	await blink("👁️","Just testing...",1000,5);
	await delay(5000);
	
	await count("I've tested this ",10," times!",500,false);
	await count("⏱️","(",10," Seconds) Until detonation",100,true);
	await status("💥","Boom!!!","dnd");
	await delay(100);
	await setstate("idle");
	await delay(100);
	await setstate("dnd");
	await delay(100);
	await setstate("idle");
	await delay(100);
	await setstate("dnd");
	
	await delay(1000);
	await settext("Finished!");
	await delay(1000);
	await blank();
	await delay(5000);
		
	/////////////////////////////
	//This loops the animation
	if (run) statusanimation(); }
	
	//Do not edit after this line (If you don't know what you're doing)
	///////////////////////////////////////////////////////////////////

	function random_emoji() {
		
		var emojis = [
			'😄','😃','😀','😊','☺','😉','😍','😘','😚','😗','😙','😜','😝','😛','😳','😁','😔','😌','😒','😞','😣','😢','😂','😭','😪','😥','😰','😅','😓','😩','😫','😨','😱','😠','😡','😤','😖','😆','😋','😷','😎','😴','😵','😲','😟','😦','😧','😈','👿','😮','😬','😐','😕','😯','😶','😇','😏','😑','👲','👳','👮','👷','💂','👶','👦','👧','👨','👩','👴','👵','👱','👼','👸','😺','😸','😻','😽','😼','🙀','😿','😹','😾','👹','👺','🙈','🙉','🙊','💀','👽','💩','🔥','✨','🌟','💫','💥','💢','💦','💧','💤','💨','👂','👀','👃','👅','👄','👍','👎','👌','👊','✊','✌','👋','✋','👐','👆','👇','👉','👈','🙌','🙏','☝','👏','💪','🚶','🏃','💃','👫','👪','👬','👭','💏','💑','👯','🙆','🙅','💁','🙋','💆','💇','💅','👰','🙎','🙍','🙇','🎩','👑','👒','👟','👞','👡','👠','👢','👕','👔','👚','👗','🎽','👖','👘','👙','💼','👜','👝','👛','👓','🎀','🌂','💄','💛','💙','💜','💚','❤','💔','💗','💓','💕','💖','💞','💘','💌','💋','💍','💎','👤','👥','💬','👣','💭','🐶','🐺','🐱','🐭','🐹','🐰','🐸','🐯','🐨','🐻','🐷','🐽','🐮','🐗','🐵','🐒','🐴','🐑','🐘','🐼','🐧','🐦','🐤','🐥','🐣','🐔','🐍','🐢','🐛','🐝','🐜','🐞','🐌','🐙','🐚','🐠','🐟','🐬','🐳','🐋','🐄','🐏','🐀','🐃','🐅','🐇','🐉','🐎','🐐','🐓','🐕','🐖','🐁','🐂','🐲','🐡','🐊','🐫','🐪','🐆','🐈','🐩','🐾','💐','🌸','🌷','🍀','🌹','🌻','🌺','🍁','🍃','🍂','🌿','🌾','🍄','🌵','🌴','🌲','🌳','🌰','🌱','🌼','🌐','🌞','🌝','🌚','🌑','🌒','🌓','🌔','🌕','🌖','🌗','🌘','🌜','🌛','🌙','🌍','🌎','🌏','🌋','🌌','🌠','⭐','☀','⛅','☁','⚡','☔','❄','⛄','🌀','🌁','🌈','🌊','🎍','💝','🎎','🎒','🎓','🎏','🎆','🎇','🎐','🎑','🎃','👻','🎅','🎄','🎁','🎋','🎉','🎊','🎈','🎌','🔮','🎥','📷','📹','📼','💿','📀','💽','💾','💻','📱','☎','📞','📟','📠','📡','📺','📻','🔊','🔉','🔈','🔇','🔔','🔕','📢','📣','⏳','⌛','⏰','⌚','🔓','🔒','🔏','🔐','🔑','🔎','💡','🔦','🔆','🔅','🔌','🔋','🔍','🛁','🛀','🚿','🚽','🔧','🔩','🔨','🚪','🚬','💣','🔫','🔪','💊','💉','💰','💴','💵','💷','💶','💳','💸','📲','📧','📥','📤','✉','📩','📨','📯','📫','📪','📬','📭','📮','📦','📝','📄','📃','📑','📊','📈','📉','📜','📋','📅','📆','📇','📁','📂','✂','📌','📎','✒','✏','📏','📐','📕','📗','📘','📙','📓','📔','📒','📚','📖','🔖','📛','🔬','🔭','📰','🎨','🎬','🎤','🎧','🎼','🎵','🎶','🎹','🎻','🎺','🎷','🎸','👾','🎮','🃏','🎴','🀄','🎲','🎯','🏈','🏀','⚽','⚾','🎾','🎱','🏉','🎳','⛳','🚵','🚴','🏁','🏇','🏆','🎿','🏂','🏊','🏄','🎣','☕','🍵','🍶','🍼','🍺','🍻','🍸','🍹','🍷','🍴','🍕','🍔','🍟','🍗','🍖','🍝','🍛','🍤','🍱','🍣','🍥','🍙','🍘','🍚','🍜','🍲','🍢','🍡','🍳','🍞','🍩','🍮','🍦','🍨','🍧','🎂','🍰','🍪','🍫','🍬','🍭','🍯','🍎','🍏','🍊','🍋','🍒','🍇','🍉','🍓','🍑','🍈','🍌','🍐','🍍','🍠','🍆','🍅','🌽','🏠','🏡','🏫','🏢','🏣','🏥','🏦','🏪','🏩','🏨','💒','⛪','🏬','🏤','🌇','🌆','🏯','🏰','⛺','🏭','🗼','🗾','🗻','🌄','🌅','🌃','🗽','🌉','🎠','🎡','⛲','🎢','🚢','⛵','🚤','🚣','⚓','🚀','✈','💺','🚁','🚂','🚊','🚉','🚞','🚆','🚄','🚅','🚈','🚇','🚝','🚋','🚃','🚎','🚌','🚍','🚙','🚘','🚗','🚕','🚖','🚛','🚚','🚨','🚓','🚔','🚒','🚑','🚐','🚲','🚡','🚟','🚠','🚜','💈','🚏','🎫','🚦','🚥','⚠','🚧','🔰','⛽','🏮','🎰','♨','🗿','🎪','🎭','📍','🚩','⬆','⬇','⬅','➡','🔠','🔡','🔤','↗','↖','↘','↙','↔','↕','🔄','◀','▶','🔼','🔽','↩','↪','ℹ','⏪','⏩','⏫','⏬','⤵','⤴','🆗','🔀','🔁','🔂','🆕','🆙','🆒','🆓','🆖','📶','🎦','🈁','🈯','🈳','🈵','🈴','🈲','🉐','🈹','🈺','🈶','🈚','🚻','🚹','🚺','🚼','🚾','🚰','🚮','🅿','♿','🚭','🈷','🈸','🈂','Ⓜ','🛂','🛄','🛅','🛃','🉑','㊙','㊗','🆑','🆘','🆔','🚫','🔞','📵','🚯','🚱','🚳','🚷','🚸','⛔','✳','❇','❎','✅','✴','💟','🆚','📳','📴','🅰','🅱','🆎','🅾','💠','➿','♻','♈','♉','♊','♋','♌','♍','♎','♏','♐','♑','♒','♓','⛎','🔯','🏧','💹','💲','💱','©','®','™','〽','〰','🔝','🔚','🔙','🔛','🔜','❌','⭕','❗','❓','❕','❔','🔃','🕛','🕧','🕐','🕜','🕑','🕝','🕒','🕞','🕓','🕟','🕔','🕠','🕕','🕖','🕗','🕘','🕙','🕚','🕡','🕢','🕣','🕤','🕥','🕦','✖','➕','➖','➗','♠','♥','♣','♦','💮','💯','✔','☑','🔘','🔗','➰','🔱','🔲','🔳','◼','◻','◾','◽','▪','▫','🔺','⬜','⬛','⚫','⚪','🔴','🔵','🔻','🔶','🔷','🔸','🔹'
		];
		
		return emojis[Math.floor(Math.random() * emojis.length)];
	}
	
	//Output XX/XX/XX @ XX:XX:XX
	function getDateTime() {
		var currentdate = new Date(); 
		
		  if(currentdate.getMinutes() > 9) var fixed_minutes = currentdate.getMinutes();
		  else var fixed_minutes = "0" + currentdate.getMinutes();
		  if(currentdate.getSeconds() > 9) var fixed_seconds = currentdate.getSeconds(); 
		  else var fixed_seconds = "0" + currentdate.getSeconds();

		  var datetime =  currentdate.getDate() + "/" + (currentdate.getMonth()+1) + "/" + currentdate.getFullYear() + " @ "  + currentdate.getHours() + ":" + fixed_minutes + ":" + fixed_seconds;

		return datetime;
	}
  
	//Output: XX:XX:XX
	function getExactTime() {
		var currentdate = new Date(); 
		
		  if(currentdate.getMinutes() > 9) var fixed_minutes = currentdate.getMinutes();
		  else var fixed_minutes = "0" + currentdate.getMinutes();
		  if(currentdate.getSeconds() > 9) var fixed_seconds = currentdate.getSeconds(); 
		  else var fixed_seconds = "0" + currentdate.getSeconds();

		  var datetime = currentdate.getHours() + ":" + fixed_minutes + ":" + fixed_seconds;

		return datetime;
	}
  
	//Output: X:XX
	function getTime() {
		var currentdate = new Date(); 
		
		  if(currentdate.getMinutes() > 9) var fixed_minutes = currentdate.getMinutes();
		  else var fixed_minutes = "0" + currentdate.getMinutes();

		  var datetime = currentdate.getHours() + ":" + fixed_minutes;

		return datetime;
	}
  
	//Simple delay function for animation
	function delay(t) {
		return new Promise(function(resolve) {
		  setTimeout(resolve, t)
		});
	}
	
	//Typewriter effect
	async function typewriter(emoji,text,timeout,reversed) {
		//Repeat for each letter
		for(var i = 1; i <= text.length; i++) {
			//Cut the text
			if(!reversed) var substring_text = text.substring(0,i);
			else var substring_text = text.substring(0,text.length - i);
			
			//Set the status to the cutted text
			if(emoji != "random") await status(emoji,substring_text);
			else await status(random_emoji(),substring_text);
			
			//Wait a selected amount of time until writing the next letter
			await delay(timeout);
		}
		
		return;
	}

	//Glitch effect
	async function glitch(emoji,text,times,timeout) {
		//Repeat for each letter
		for(var i = 1; i < times; i++) {
			//Shuffle the text
			var glitch_text = shuffle(text)
			
			//Set the status to the cutted text
			if(emoji != "random") await status(emoji,glitch_text);
			else await status(random_emoji(),glitch_text);
			
			//Wait a selected amount of time until writing the next letter
			await delay(timeout);
		}
		
		return;
	}
	
	//Glitchtype effect
	async function glitchtype(emoji,text,timeout,glitch_rate,reversed) {
			//Repeat for each letter
			for(var i = 1; i <= text.length; i++) {
				//Cut the text
				if(!reversed) var substring_text = text.substring(0,i);
				else var substring_text = text.substring(0,text.length - i);
				
				//Glitch rest of the text
				if(!reversed) var glitch_text = shuffle(text.substring(i));
				else var glitch_text = shuffle(text.substring(text.length - i));
				
				//Set the status to the cutted text + glitched text
				if(emoji != "random") await status(emoji,substring_text + glitch_text);
				else await status(random_emoji(),substring_text + glitch_text);
				
				//Wait a selected amount of time until writing the next letter
				await delay(timeout);
				
				for(var a = 0; a < glitch_rate; a++) {
					//Glitch rest of the text
					if(!reversed) var glitch_text = shuffle(text.substring(i));
					else var glitch_text = shuffle(text.substring(text.length - i));
					
					//Set the status to the cutted text + glitched text
					await status(emoji,substring_text + glitch_text);
					
					//Wait a selected amount of time until writing the next glitched characterset at the end of the string
					await delay(timeout/2);
				}
			}
			
		return;
	}
	
	async function sentence(emoji,text,timeout) {
		//Split sentence into words	
		var words = text.split(" ");
		
			//Repeat for each word
			for(var i = 0; i < words.length; i++) {
				//Set status to array's word
				if(emoji != "random") await status(emoji,words[i]);
				else await status(random_emoji(),words[i]);
				
				//Wait a selected amount of time until writing the next letter
				await delay(timeout);
			}
			
		return;
	}
	
	async function blink(emoji,text,timeout,times) {
		for(var i = 0; i < times; i++) {
			if(emoji != "random") await status(emoji,text);
			else await status(random_emoji(),text);
			await delay(timeout);
			await blank();
			await delay(timeout);
		}
		
		return;
	}
	
	async function blank() {
		//Could just send blank status as {"custom_status":null}, but that behaves weirdly.
		await status("","");
		
		return;
	}
	
	async function count(emoji,prefix,count_to,suffix,timeout,reversed) {
		for(var i = 0; i < count_to; i++) {
			if(!reversed) {
				var recalculated_count = i + 1;
				var final_string = prefix + recalculated_count + suffix;
			}				
			else {
				var recalculated_count = count_to - i;
				var final_string = prefix + recalculated_count + suffix;
			}
			if(emoji != "random") await status(emoji,final_string);
			else await status(random_emoji(),final_string);
			
			await delay(timeout);
		}
		return;
	}
	
	
	//codespeedy.com/shuffle-characters-of-a-string-in-javascript/
	function getRandomInt(n) {
		return Math.floor(Math.random() * n);
	}
	
	//codespeedy.com/shuffle-characters-of-a-string-in-javascript/
	function shuffle(s) {
		var arr = s.split('');           // Convert String to array
		var n = arr.length;              // Length of the array

		for(var i=0 ; i<n-1 ; ++i) {
			var j = getRandomInt(n);       // Get random of [0, n-1]

			var temp = arr[i];             // Swap arr[i] and arr[j]
			arr[i] = arr[j];
			arr[j] = temp;
		}

		s = arr.join('');                // Convert Array to string
		return s;                        // Return shuffled string
	}
	
	//Function to read the saved cookie
	window.getCookie = function(name) {
		var match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
		if (match) return match[2];
	}
	
	//Set the Discord Token as a Cookie for future use of the script
	//If there is no Token cookie
	if(document.cookie.indexOf(cookie_name + "=") == -1) {
		//Ask user if they want to refresh the page to get the token
		if(confirm("\"" + cookie_name + "\" cookie not found. Refreshing Discord to get it.\n\n- " + name + " " + version)) {
			
			//Load the page again and create a new element which will have the token in its localStorage
			location.reload();
			var i = document.createElement('iframe');
			document.body.appendChild(i);
			
			//Get Token from localStorage
			var token = i.contentWindow.localStorage.token
			token = token.slice(1, -1);
			
			//Delete cookie after a week or not
			if(delete_cookie_after_a_week) 
				document.cookie = cookie_name + "=" + token + "; secure=true; max-age=604800; path=/";
			else
				document.cookie = cookie_name + "=" + token + "; secure=true; path=/";

		} else throw new Error("[Not an actually uncaught] User stopped the Status Animator. \n\nNo cookie was found and user decided not to continue.");
	}
	
	var status_text = "";
	var status_emoji = "";
	var status_state = "";
	//Function that changes the status variables (Saves up a bit space)
	async function status(emoji,text,state) {
		if(run) {
			status_text = text;
			status_emoji = emoji;
			status_state = state;
			
			await setstatus();
			
			return;
		}
	}
	
	//Get Discord Token from saved Cookie
	var token = getCookie(cookie_name);

	//HTTP Request's URL address
	var url = "https://discord.com/api/v9/users/@me/settings";
	
	//Function that handles the HTTP request for the status change
	async function setstatus() {

		var request = new XMLHttpRequest(); 
		request.open("PATCH", url); 
		request.setRequestHeader("Accept", "*/*" ); 
		request.setRequestHeader("Content-Type", "application/json"); 
		request.setRequestHeader("Authorization", token);
		request.send(JSON.stringify({"custom_status":{"text":status_text,"emoji_name":status_emoji}}));

		//If the request failed
		request.onreadystatechange = () => {
			if (request.status != 200) {
				run = false; 
				throw new Error("[Not an actually uncaught] Failed to update status. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
			}
		};
			
		
		if(status_state == "invisible" || status_state == "dnd" || status_state == "idle" || status_state == "online") {
			var request2 = new XMLHttpRequest(); 
			request2.open("PATCH", url); 
			request2.setRequestHeader("Accept", "*/*" ); 
			request2.setRequestHeader("Content-Type", "application/json"); 
			request2.setRequestHeader("Authorization", token);
			request2.send(JSON.stringify({"status":status_state}));
			
			//If the request failed
			request2.onreadystatechange = () => {
				if (request2.status != 200) {
					run = false; 
					throw new Error("[Not an actually uncaught] Failed to update status. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
				}
			};
		}
		
		return;
	}
	
	async function setstate(text) {
		if(run) {
			status_state = text;
			
			if(status_state == "invisible" || status_state == "dnd" || status_state == "idle" || status_state == "online") {
				var request = new XMLHttpRequest(); 
				request.open("PATCH", url); 
				request.setRequestHeader("Accept", "*/*" ); 
				request.setRequestHeader("Content-Type", "application/json"); 
				request.setRequestHeader("Authorization", token);
				request.send(JSON.stringify({"status":status_state}));
				
				//If the request failed
				request.onreadystatechange = () => {
					if (request.status != 200) {
						run = false; 
						throw new Error("[Not an actually uncaught] Failed to update state. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
					}
				};
			}

			return;
		}
	}
	
	async function setemoji(emoji) {
		if(run) {
			status_emoji = emoji;
			
			var request = new XMLHttpRequest(); 
			request.open("PATCH", url); 
			request.setRequestHeader("Accept", "*/*" ); 
			request.setRequestHeader("Content-Type", "application/json"); 
			request.setRequestHeader("Authorization", token);
			request.send(JSON.stringify({"custom_status":{"emoji_name":status_emoji}}));

			//If the request failed
			request.onreadystatechange = () => {
				if (request.status != 200) {
					run = false; 
					throw new Error("[Not an actually uncaught] Failed to update emoji. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
				}
			};

			return;
		}
	}
	
	async function settext(text) {
		if(run) {
			status_text = text;
			
			var request = new XMLHttpRequest(); 
			request.open("PATCH", url); 
			request.setRequestHeader("Accept", "*/*" ); 
			request.setRequestHeader("Content-Type", "application/json"); 
			request.setRequestHeader("Authorization", token);
			request.send(JSON.stringify({"custom_status":{"text":status_text}}));

			//If the request failed
			request.onreadystatechange = () => {
				if (request.status != 200) {
					run = false; 
					throw new Error("[Not an actually uncaught] Failed to update text. \n\nThe HTTP request failed. Most likely because the authorization token is incorrect.");
				}
			};

			return;
		}
	}
		
	//Start the animation for the first time
	if (run) statusanimation();
	
	//Edit (Clear by default) status before exiting
	window.onbeforeunload = function () {
		run = false;
		
		status_text = default_status_text;
		status_emoji = default_status_emoji;
		
		if(status_state == "invisible" || status_state == "dnd" || status_state == "idle" || status_state == "online")
		status_state = default_status_state;
	
		setstatus();
		
		return "";
	};
})();