Now Reading
Reverse Engineering Discord’s Celebration Mode

Reverse Engineering Discord’s Celebration Mode

2022-11-08 11:42:56

If you have not seen but, Discord added a ‘Celebration Mode’ as a result of they’re celebrating their seventh birthday. When a good friend satisfied me to allow it, I did the primary few challenges, however rapidly seen that they’re actually repetitive.

So I did the one affordable factor: Automate it. My good friend used puppeteer to automate the duties, however I made a decision to undergo their supply code and discover the code that handles these achievements.

While you’ve solely bought a UI, it is at all times onerous to know the place to begin. There are a bunch of locations to look. Since Discord makes use of Electron we are able to both look via the recordsdata on disk or within the browser. We would solely go for the primary choice, if we all know that the function can solely be accessed on the desktop utility. An instance for that will be the Discord overlay. However for the reason that occasion mode additionally works within the browser, we are able to begin there.

After inspecting the HTML components for the occasion mode, I could not see any references to any JavaScript capabilities. I additionally checked the networking tab, however there have been no outgoing or incoming requests. Lastly, I checked the console however there was additionally no output.

Since all our makes an attempt did not deliver us nearer to determining how the occasion mode works, let’s attempt one thing else. Discord has an asset folder with all their bundled code. The bundler compiles all of the JavaScript recordsdata, minifies and generally even obfuscates them. Fortunately, these are simply minified, so we are able to right-click on the belongings folder and search all of the recordsdata in it.

assets-folder

We will now seek for sure key phrases and see what comes up. I attempted key phrases like occasion, combo, confetti and located the in accordance file fairly rapidly.

There are a bunch of references, that simply include mappings like these. They don’t seem to be actually helpful to us, as a result of they’re simply mapping sure variables to their HTML identifiers.

440313: e=>{
	e.exports = {
		combo: "combo-2aK5O7",
		comboValue: "comboValue-1MDc9T",
		comboNameplate: "comboNameplate-2LHfRI",
		comboMultiplier: "comboMultiplier-YkNec8",
		comboSquare: "comboSquare-12yWYj",
		left: "left-2uQTLJ",
		proper: "right-1c_YIP",
		confettiIcon: "confettiIcon-1nMd5V",
		tip: "tip-WcKlNf",
		messageComboScore: "messageComboScore-1cWPCc",
		comboScore: "comboScore-38MG6A"
	}
}

However there’s additionally one other file (78a38cf0ea7963a0711a.js), that handles the occasion mode logic. Simply by trying on the strings and variable names, we are able to already guess what it is doing. For instance, what do you suppose this code does?

!perform(e) {
	e[e.ENABLE_POGGERMODE = 0] = "ENABLE_POGGERMODE";
	e[e.DISABLE_POGGERMODE = 1] = "DISABLE_POGGERMODE";
	e[e.PING_SOMEONE = 2] = "PING_SOMEONE";
	e[e.PING_ME = 3] = "PING_ME";
	e[e.COMBO_MULTI_LEVEL_1 = 4] = "COMBO_MULTI_LEVEL_1";
	e[e.COMBO_MULTI_LEVEL_2 = 5] = "COMBO_MULTI_LEVEL_2";
	e[e.COMBO_MULTI_LEVEL_3 = 6] = "COMBO_MULTI_LEVEL_3";
	e[e.COMBO_MULTI_LEVEL_4 = 7] = "COMBO_MULTI_LEVEL_4";
	e[e.TOTAL_SCORE_LEVEL_1 = 8] = "TOTAL_SCORE_LEVEL_1";
	e[e.TOTAL_SCORE_LEVEL_2 = 9] = "TOTAL_SCORE_LEVEL_2";
	e[e.TOTAL_SCORE_LEVEL_3 = 10] = "TOTAL_SCORE_LEVEL_3";
	e[e.TOTAL_SCORE_LEVEL_4 = 11] = "TOTAL_SCORE_LEVEL_4";
	e[e.TOTAL_SCORE_LEVEL_5 = 12] = "TOTAL_SCORE_LEVEL_5";
	e[e.VISITOR_100 = 13] = "VISITOR_100";
	e[e.CUSTOMIZE_CONFETTI = 14] = "CUSTOMIZE_CONFETTI";
	e[e.MORE = 15] = "MORE";
	e[e.COMBO_VALUE_LEVEL_1 = 16] = "COMBO_VALUE_LEVEL_1";
	e[e.COMBO_VALUE_LEVEL_2 = 17] = "COMBO_VALUE_LEVEL_2";
	e[e.COMBO_VALUE_LEVEL_3 = 18] = "COMBO_VALUE_LEVEL_3";
	e[e.COMBO_VALUE_LEVEL_4 = 19] = "COMBO_VALUE_LEVEL_4"
}(o || (t.PoggermodeAchievementId = o = {}));

If you recognize what achievements there are, you may instantly acknowledge that that is the array that shops some information about them. And when scrolling down a bit of, you may discover precisely 19 blocks of code that every one look considerably like this:

a[o.DISABLE_POGGERMODE] = {
	id: o.DISABLE_POGGERMODE,
	title: perform() {
		return s.default.Messages.POGGERMODE_ACHIEVEMENT_DISABLE_POGGERMODE_NAME
	},
	description: perform() {
		return s.default.Messages.POGGERMODE_ACHIEVEMENT_DISABLE_POGGERMODE_DESCRIPTION
	},
	rarity: i.UNCOMMON,
	hideDescriptionUntilUnlock: !1
},

There’s even one legendary achievement that has an occasion handler. Are you able to guess which video they’re opening?

 a[o.VISITOR_100] = {
	id: o.VISITOR_100,
	title: perform() {
		return s.default.Messages.POGGERMODE_ACHIEVEMENT_VISITOR_100_NAME
	},
	description: perform() {
		return s.default.Messages.POGGERMODE_ACHIEVEMENT_VISITOR_100_DESCRIPTION
	},
	rarity: i.LEGENDARY,
	hideDescriptionUntilUnlock: !0,
	onAction: perform() {
		window.open("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "_blank")
	}
},

So now we all know the place the achievement logic is situated, can we determine whether or not it is saved? I initially did some achievements by hand on the Desktop consumer, however once I opened the browser consumer, all of them had been gone. Since there have been additionally no outgoing or incoming requests when trying on the networking, we may be sure that the information is simply saved regionally.

You may now both undergo the file and seek for references to storage APIs or look via LocalStorage. Since there’s not that many choices, the PoggermodeAchievementStore key may stand out. While you have a look at the saved worth, you may clearly see the unlocked achievements. Good! local-storage-value

See Also

Now that we all know the place the achievements are saved, we are able to simply modify it. I needed to put in writing a easy JavaScript program for that, however for no matter purpose, window.localStorage wasn’t outlined. So as a substitute of losing extra time to discover a workaround, I made a decision to manually substitute it.

Since we already discovered the achievement array, we all know that there is 19 of them. We will simply write it out like this and substitute the worth. The dateUnlocked worth is a epoch timestamp. You may create your individual timestamp on this website.

{
    "_state": {
        "unlockedAchievements": {
            "0": {
                "achievementId": 0,
                "dateUnlocked": -19975457838000
            },
            "1": {
                "achievementId": 1,
                "dateUnlocked": -19975457838000
            },
            "2": {
                "achievementId": 2,
                "dateUnlocked": -19975457838000
            },
            // Skipped...
            "18": {
                "achievementId": 18,
                "dateUnlocked": -19975457838000
            },
            "19": {
                "achievementId": 19,
                "dateUnlocked": -19975457838000
            }
        }
    },
    "_version": 0
}

After reloading the consumer, we bought all of the achievements. Now I can brag to all of you about how cool I’m. 🙂 unlocked-achievements

This was solely a small challenge, however we nonetheless realized quite a bit. We now know the way we are able to begin reversing web sites or Electron purposes. I am utilizing Firefox for all my private searching, however I made a decision to spin up Chrome as a result of I understand how good their DevTools are. So be sure that to use the precise software for the job.


I am a giant fan of structured procrastination and learning new things by starting a project. So when you catch your self procrastinating or losing time, attempt to flip it right into a enjoyable facet challenge.

In any case, it’s by no means a waste of time to study one thing new.

Source Link

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top