Skip to content

Instantly share code, notes, and snippets.

@vanyle
Last active April 4, 2025 14:10
Show Gist options
  • Save vanyle/edbdd0c28a0150af3b905b99a4c48f00 to your computer and use it in GitHub Desktop.
Save vanyle/edbdd0c28a0150af3b905b99a4c48f00 to your computer and use it in GitHub Desktop.
Modding the Discord client

Modding the discord client

Disclaimer: Modding the discord client is against Discord's term of service. I'm not responsible if any action is taken against you.

Why modding ?

Modding the client will allow you to customize to:

  • change the appearance of the discord client
  • have script to automaticaly send messages at specific times
  • log messages from a chat into a local file

This guide will explain how to inject js code into the discord client and send messages. I'm assuming you know you to write javascript code and are using Windows. Most of this will also work on Linux and Mac but the directories will not be the same

How to mod discord ?

First install npm and asar

npm can be installed from here: https://nodejs.org/en/ (it's bundled with nodejs)

asar can when be installed with npm install asar -g

Then go to the following directory: %LocalAppData%/Discord/app-<some version>/modules/discord_desktop_core-<number>/discord_desktop_core/ You will find a file named core.asar

asar files work find of like zip files. You should make a backup of the file as we are going to modify it.

To unpack the file, run asar extract core.asar unpacked This will create an unpacked folder. Inside, search for app/mainScreen.js. This is the js file we will edit to inject js code into Discord.

I suggest adding the following lines (but you could add anything else depending on the feature you want):

At line ~350, inside the object mainWindowOptions.webPreferences add the property: nodeIntegration: true. This will allow you to access node js functions from inside discord to write files for example.

At line ~440, in the scope of launchMainAppWindow, add:

const fs = require('fs');
mainWindow.webContents.on('dom-ready', () => {
  setTimeout(() => {
    mainWindow.webContents.executeJavaScript(fs.readFileSync('C:/discord.js') + "");
  }, 3000);
});

This will load the file located at C:/discord.js into the discord client. You can change this path to any path convenient to you.

You will then need to repack this code into the asar file. To do this, run:

asar pack unpacked core.asar

This will override the core.asar file so making a backup is important here.

When, create the js file at C:/discord.js and add the following inside: (You can customize this to do other stuff)

// Discord requires a authorization token to send messages.
// We will fetch this token by listening to request discord makes
let authTokenObtained = false;
let insideChannelRequest = false;
let authToken = "";
let xsuperToken = "";

// We override the default AJAX request to listen to the requests discord makes.
var proxied1 = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function() {
	console.log(arguments[1]);
	if(arguments[1].startsWith('https://discordapp.com/api/v6/channels')){
		if(!authTokenObtained){
			insideChannelRequest = true;
		}
		(function(url){
			setTimeout(function(){ // wait for the ui to update.
				let elements = document.getElementsByTagName('h3');
       				// We update the UI to display the channel name.
				if(elements.length >= 1 && elements[0].style.userSelect !== "text"){ // add channel URL to name
					elements[0].style.userSelect = "text";
					elements[0].innerHTML += " | "+url.substring("https://discordapp.com/api/v6/channels".length);
				}
			},1000);
		})(arguments[1]);
	}
	return proxied1.apply(this, [].slice.call(arguments));
};

let proxied2 = window.XMLHttpRequest.prototype.setRequestHeader;
window.XMLHttpRequest.prototype.setRequestHeader = function() {
	if(insideChannelRequest && !authTokenObtained && arguments[0] === "Authorization"){
		authToken = arguments[1];
		authTokenObtained = true;
		console.log("Token Obtained.");
	}
	if(insideChannelRequest && arguments[0] == "X-Super-Properties"){
		xsuperToken = arguments[1];
		console.log("X-Super-Properties updated.")
	}
	// console.log( arguments );
	return proxied2.apply(this, [].slice.call(arguments));
};

// We can now define a sendMessage function that behaves exactly like discord:
function sendMessage(msg,channel){
	if(!authTokenObtained){
		console.log("Unable to send message without authToken.");
		console.log("Try typing something in a chat to obtain the token.");
	}
	channel_url = `https://discordapp.com/api/v6/channels/${channel}/messages`;

	request = new XMLHttpRequest();
	request.withCredentials = true;
	request.open("POST", channel_url);
	request.setRequestHeader("Content-Type", "application/json");
	request.setRequestHeader("Authorization", authToken);
	request.setRequestHeader("X-Super-Properties", xsuperToken);
	request.send(JSON.stringify({ content: msg, tts: false }));
}

Now, once you reload discord, you can see the channel id name of somebody next to their username. Also, when opening the console (with Ctrl+Shift+I) inside discord, you can run: sendMessage("<your message here>","<the channel id here>"); which will send a message in the corresponding channel.

You can use the same stuff to listen to incomming messages (you override the AJAX request callbacks to get access to the messages fetched by discord) You can also edit the discord.js file to change the css. The code above already does that to make usernames selectable.

Now, you can write in the console something like for example:

setTimeout(function(){
  sendMessage("I'm still online, I am not afk","<the channel id>");
},1000 * 60 * 60);

to send a message in one hour. You can get creative and do all sort of stuff with this.

This concludes this guide. Have fun.

@vanyle
Copy link
Author

vanyle commented Aug 19, 2021

Yup, this gist is a year old and the overall file structure of Discord changed since (the method names might not even be the same).

I might update it to reflect those changes. Moreover, you might not even need to unpack the asar file now (maybe editing the index.js file inside the directory with the core works, I haven't tested this.)

@PatriotZest
Copy link

PatriotZest commented Aug 20, 2021

@vanyle how can I change the appearance of the discord client? If you cannot tell here please respond on my discord Patriot Zest#0001 Not able to figure how to do so

@PatriotZest
Copy link

Just looked at it right now. All the discord_desktop_core/index.js file contains is this.
module.exports = require('./core.asar');
So I believe you still have to unpack the asar file.

yes you have to

@cat-marin
Copy link

cat-marin commented Sep 20, 2021

Yeah, line numbers have already changed.

Can confirm this still works, I was able to inject Undiscord into the desktop app on linux

update: turned it into a BD plugin for those who want to do the same thing i did but easier: here's the link

@Trebossalol
Copy link

Hi, is there a way to require node modules inside injected code ?

@vanyle
Copy link
Author

vanyle commented Oct 10, 2021

Yes, you can ! You just need to do an npm install in the folder of the injected file and require your modules from this file.
You'll need to set nodeIntegration to true for this to work.

@Stanlyhalo
Copy link

Sending a message doesn't work :\ Anyone figured it out? I have the same issue as @TheGloriousDuck .

@Trebossalol
Copy link

Sending a message doesn't work :\ Anyone figured it out? I have the same issue as @TheGloriousDuck .

Yes, i debugged it and the variable insideChannelRequest Was always false. This resulted in not obtaining the auth token. Fix it by setting that variable to true by default.
But remember, you can only post to channels not DMs.

@Paradox-77
Copy link

Any idea if this still works?

@Trebossalol
Copy link

Does still work

@Paradox-77
Copy link

Paradox-77 commented Jan 9, 2022

The dom-ready event never seems to trigger for me, any idea why?
I have placed it at the end of the the launchMainAppWindow function

@Trebossalol
Copy link

Just follow the instruction, that'll work. When it works, you can edit stuff.
Oh and btw, if you want the authtoken collected in the variable, that won't work for some reason (at least I experienced that), but if you set the variable insideChannelRequest by default to true you will get the authtoken at some point after sending a message. Happy hacking

@whoisShepherd
Copy link

Is there any documentation for the different kinds of requests that can be made? I'm trying to alter the discord.js file to change my current status.

@Paradox-77
Copy link

The CSP (Content Security Policy) allows you to access the discord API. You should have no problem doing that.

@whoisShepherd
Copy link

I looked through the CSP API, but I wasn't able to find a way to set a custom status using a XMLHttpRequest. How would I modify

        request = new XMLHttpRequest();
	request.withCredentials = true;
	request.open("POST", channel_url);
	request.setRequestHeader("Content-Type", "application/json");
	request.setRequestHeader("Authorization", authToken);
	request.setRequestHeader("X-Super-Properties", xsuperToken);
	request.send(JSON.stringify({ content: msg, tts: false }));

To change my status instead of sending a message?

@goesbyabhi
Copy link

Just follow the instruction, that'll work. When it works, you can edit stuff. Oh and btw, if you want the authtoken collected in the variable, that won't work for some reason (at least I experienced that), but if you set the variable insideChannelRequest by default to true you will get the authtoken at some point after sending a message. Happy hacking

Is it still working for you?

@Trebossalol
Copy link

Just follow the instruction, that'll work. When it works, you can edit stuff. Oh and btw, if you want the authtoken collected in the variable, that won't work for some reason (at least I experienced that), but if you set the variable insideChannelRequest by default to true you will get the authtoken at some point after sending a message. Happy hacking

Is it still working for you?

Yes it is still working for me, and I don't think discord will patch this anytime. But I am sorry I can not provide any help with this.

@goesbyabhi
Copy link

Just follow the instruction, that'll work. When it works, you can edit stuff. Oh and btw, if you want the authtoken collected in the variable, that won't work for some reason (at least I experienced that), but if you set the variable insideChannelRequest by default to true you will get the authtoken at some point after sending a message. Happy hacking

Is it still working for you?

Yes it is still working for me, and I don't think discord will patch this anytime. But I am sorry I can not provide any help with this.

No it's dwdw i figured it out

@kumina-dev
Copy link

Hello, I got an error saying "A fatal Javascript error occured"
"TypeError: Cannot read property 'webContents' of null"

@kumina-dev
Copy link

Hello, I got an error saying "A fatal Javascript error occured" "TypeError: Cannot read property 'webContents' of null"

Got it fixed by rearranging the code in mainScreen.js

@dec04
Copy link

dec04 commented May 27, 2022

Hello. core.asar is electron wrapper and app.asar is app front? I understand correctly?

@dec04
Copy link

dec04 commented May 27, 2022

How i can send request to another domain, not discord? I get cors error, when i try to send request to another domain, like google . com

@aindrigo
Copy link

aindrigo commented Jun 9, 2022

why doesn't require or import work? i enabled nodeIntegration and it did nothing

@vwv-source
Copy link

Could anyone help? require doesn't work and i can't write files even after enabling nodeIntegration

@dec04
Copy link

dec04 commented Oct 5, 2022

For me, import or require dont work, after enable nodeIntegration: true

@ProxxDev2
Copy link

I keep getting this error, please help.
image

@ProxxDev2
Copy link

nevermind i fixed it

@dec04
Copy link

dec04 commented Oct 5, 2022

what fix? you can share with us?

@ProxxDev2
Copy link

@dec04 I removed the dom-ready thing and it works, by the way i put it out of the if platform linux thing scope

@FunWithAlbiYT
Copy link

FunWithAlbiYT commented Oct 22, 2022

Make sure to put the code that runs the code from discord.js at line ~470
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment