Skip to content

Instantly share code, notes, and snippets.

@aamiaa
Last active February 27, 2025 22:50
Show Gist options
  • Save aamiaa/204cd9d42013ded9faf646fae7f89fbb to your computer and use it in GitHub Desktop.
Save aamiaa/204cd9d42013ded9faf646fae7f89fbb to your computer and use it in GitHub Desktop.
Complete Recent Discord Quest

Complete Recent Discord Quest

Note

This does not works in browser for non-video, non-activity quests! For stream/play quests use the desktop app!

Note

When doing stream quests, you need at least 1 other account in the vc!

How to use this script:

  1. Accept a quest under Discover -> Quests
  2. Press Ctrl+Shift+I to open DevTools
  3. Go to the Console tab
  4. Paste the following code and hit enter:
Click to expand
delete window.$;
let wpRequire;
window.webpackChunkdiscord_app.push([[ Math.random() ], {}, (req) => { wpRequire = req; }]);

let ApplicationStreamingStore = Object.values(wpRequire.c).find(x => x?.exports?.Z?.__proto__?.getStreamerActiveStreamMetadata).exports.Z;
let RunningGameStore = Object.values(wpRequire.c).find(x => x?.exports?.ZP?.getRunningGames).exports.ZP;
let QuestsStore = Object.values(wpRequire.c).find(x => x?.exports?.Z?.__proto__?.getQuest).exports.Z;
let ChannelStore = Object.values(wpRequire.c).find(x => x?.exports?.Z?.__proto__?.getAllThreadsForParent).exports.Z;
let GuildChannelStore = Object.values(wpRequire.c).find(x => x?.exports?.ZP?.getSFWDefaultChannel).exports.ZP;
let FluxDispatcher = Object.values(wpRequire.c).find(x => x?.exports?.Z?.__proto__?.flushWaitQueue).exports.Z;
let api = Object.values(wpRequire.c).find(x => x?.exports?.tn?.get).exports.tn;

let quest = [...QuestsStore.quests.values()].find(x => x.id !== "1248385850622869556" && x.userStatus?.enrolledAt && !x.userStatus?.completedAt && new Date(x.config.expiresAt).getTime() > Date.now())
let isApp = navigator.userAgent.includes("Electron/")
if(!quest) {
	console.log("You don't have any uncompleted quests!")
} else {
	const pid = Math.floor(Math.random() * 30000) + 1000
	
	const applicationId = quest.config.application.id
	const applicationName = quest.config.application.name
	const taskName = ["WATCH_VIDEO", "PLAY_ON_DESKTOP", "STREAM_ON_DESKTOP", "PLAY_ACTIVITY"].find(x => quest.config.taskConfig.tasks[x] != null)
	const secondsNeeded = quest.config.taskConfig.tasks[taskName].target
	const secondsDone = quest.userStatus?.progress?.[taskName]?.value ?? 0

	if(taskName === "WATCH_VIDEO") {
		const tolerance = 2, speed = 10
		const diff = Math.floor((Date.now() - new Date(quest.userStatus.enrolledAt).getTime())/1000)
		const startingPoint = Math.min(Math.max(Math.ceil(secondsDone), diff), secondsNeeded)
		let fn = async () => {
			for(let i=startingPoint;i<=secondsNeeded;i+=speed) {
				try {
					await api.post({url: `/quests/${quest.id}/video-progress`, body: {timestamp: Math.min(secondsNeeded, i + Math.random())}})
				} catch(ex) {
					console.log("Failed to send increment of", i, ex.message)
				}
				await new Promise(resolve => setTimeout(resolve, tolerance * 1000))
			}
			if((secondsNeeded-secondsDone)%speed !== 0) {
				await api.post({url: `/quests/${quest.id}/video-progress`, body: {timestamp: secondsNeeded}})
			}
			console.log("Quest completed!")
		}
		fn()
		console.log(`Spoofing video for ${applicationName}. Wait for ${Math.ceil((secondsNeeded - startingPoint)/speed*tolerance)} more seconds.`)
	} else if(taskName === "PLAY_ON_DESKTOP") {
		if(!isApp) {
			console.log("This no longer works in browser for non-video quests. Use the desktop app to complete the", applicationName, "quest!")
		}
		
		api.get({url: `/applications/public?application_ids=${applicationId}`}).then(res => {
			const appData = res.body[0]
			const exeName = appData.executables.find(x => x.os === "win32").name.replace(">","")
			
			const games = RunningGameStore.getRunningGames()
			const fakeGame = {
				cmdLine: `C:\\Program Files\\${appData.name}\\${exeName}`,
				exeName,
				exePath: `c:/program files/${appData.name.toLowerCase()}/${exeName}`,
				hidden: false,
				isLauncher: false,
				id: applicationId,
				name: appData.name,
				pid: pid,
				pidPath: [pid],
				processName: appData.name,
				start: Date.now(),
			}
			games.push(fakeGame)
			FluxDispatcher.dispatch({type: "RUNNING_GAMES_CHANGE", removed: [], added: [fakeGame], games: games})
			
			let fn = data => {
				let progress = quest.config.configVersion === 1 ? data.userStatus.streamProgressSeconds : Math.floor(data.userStatus.progress.PLAY_ON_DESKTOP.value)
				console.log(`Quest progress: ${progress}/${secondsNeeded}`)
				
				if(progress >= secondsNeeded) {
					console.log("Quest completed!")
					
					const idx = games.indexOf(fakeGame)
					if(idx > -1) {
						games.splice(idx, 1)
						FluxDispatcher.dispatch({type: "RUNNING_GAMES_CHANGE", removed: [fakeGame], added: [], games: []})
					}
					FluxDispatcher.unsubscribe("QUESTS_SEND_HEARTBEAT_SUCCESS", fn)
				}
			}
			FluxDispatcher.subscribe("QUESTS_SEND_HEARTBEAT_SUCCESS", fn)
			
			console.log(`Spoofed your game to ${applicationName}. Wait for ${Math.ceil((secondsNeeded - secondsDone) / 60)} more minutes.`)
		})
	} else if(taskName === "STREAM_ON_DESKTOP") {
		if(!isApp) {
			console.log("This no longer works in browser for non-video quests. Use the desktop app to complete the", applicationName, "quest!")
		}
		
		let realFunc = ApplicationStreamingStore.getStreamerActiveStreamMetadata
		ApplicationStreamingStore.getStreamerActiveStreamMetadata = () => ({
			id: applicationId,
			pid,
			sourceName: null
		})
		
		let fn = data => {
			let progress = quest.config.configVersion === 1 ? data.userStatus.streamProgressSeconds : Math.floor(data.userStatus.progress.STREAM_ON_DESKTOP.value)
			console.log(`Quest progress: ${progress}/${secondsNeeded}`)
			
			if(progress >= secondsNeeded) {
				console.log("Quest completed!")
				
				ApplicationStreamingStore.getStreamerActiveStreamMetadata = realFunc
				FluxDispatcher.unsubscribe("QUESTS_SEND_HEARTBEAT_SUCCESS", fn)
			}
		}
		FluxDispatcher.subscribe("QUESTS_SEND_HEARTBEAT_SUCCESS", fn)
		
		console.log(`Spoofed your stream to ${applicationName}. Stream any window in vc for ${Math.ceil((secondsNeeded - secondsDone) / 60)} more minutes.`)
		console.log("Remember that you need at least 1 other person to be in the vc!")
	} else if(taskName === "PLAY_ACTIVITY") {
		const channelId = ChannelStore.getSortedPrivateChannels()[0]?.id ?? Object.values(GuildChannelStore.getAllGuilds()).find(x => x != null && x.VOCAL.length > 0).VOCAL[0].channel.id
		const streamKey = `call:${channelId}:1`
		
		let fn = async () => {
			console.log("Completing quest", applicationName, "-", quest.config.messages.questName)
			
			while(true) {
				const res = await api.post({url: `/quests/${quest.id}/heartbeat`, body: {stream_key: streamKey, terminal: false}})
				const progress = res.body.progress.PLAY_ACTIVITY.value
				console.log(`Quest progress: ${progress}/${secondsNeeded}`)
				
				await new Promise(resolve => setTimeout(resolve, 20 * 1000))
				
				if(progress >= secondsNeeded) {
					await api.post({url: `/quests/${quest.id}/heartbeat`, body: {stream_key: streamKey, terminal: true}})
					break
				}
			}
			
			console.log("Quest completed!")
		}
		fn()
	}
}
  1. Follow the printed instructions depending on what type of quest you have
    • If your quest says to "play" the game, you can just wait and do nothing
    • If your quest says to "stream" the game, join a vc with a friend or alt and stream any window
  2. Wait for 15 minutes
  3. You can now claim the reward in User Settings -> Gift Inventory!

You can track the progress by looking at the Quest progress: prints in the Console tab, or by reopening the Gift Inventory tab in settings.

FAQ

Q: Ctrl + Shift + I doesn't work

A: Either download the ptb client, or use this to enable DevTools on stable

Q: I get an error saying "Unauthorized"

A: Discord has patched the script from working in browsers. Use the desktop app, or alternatively find some extension which lets you change your User-Agent and append the string Electron/ anywhere in it.

They have also started checking how many people are in the vc, so make sure you join it on at least 1 other account.

Q: I get a syntax error/unexpected token error

A: Make sure your browser isn't auto-translating this website before copying the script. Turn off any translator extensions and try again.

Q: I get the error Cannot read properties of undefined (reading 'nativeModules')

A: You're on a modded client which is a browser wrapper (i.e. Vesktop). Use an actual desktop app.

Q: I get a different error

A: Make sure you're copy/pasting the script correctly and that you've have done all the steps.

Q: Can you make the script auto accept the quest/reward?

A: No. Both of those actions may show a captcha, so automating them is not a good idea. Just do the two clicks yourself.


Side note: Please don't post your "fixed" or "improved" versions of the script in the comments. It creates unnecessary confusion, often doesn't fix anything, and sometimes puts other people's accounts at risk. I might redact/delete such comments without notice. Thank you for understanding.

@Xenarth
Copy link

Xenarth commented Feb 18, 2025

What do i do when i get an error saying "Uncaught TypeError: QuestsStore.quests.values is not a function or its return value is not iterable at :13:36"

You want my code?

If you have vouches for it :)

2i6drj67VwjgtTdJKUph

sorry, where do i put this?

Click Here Create your game account on this link and then redeem it

Ohh, i'm trying to get the overwatch code rn haha

Get this one before someone redeems it

@aamiaa
Copy link
Author

aamiaa commented Feb 18, 2025

Fixed

@lozadakerbin268
Copy link

Fixed

thx

@Trubbel
Copy link

Trubbel commented Feb 19, 2025

Overwatch 2: 5 Loot Boxes
5SB8-DDN9-9BCGR-KXRN-9D8B

@thepro-3418
Copy link

Overwatch 2: 5 Loot Boxes
D9Q6-FV6K-PMFSN-V3J8-5GKQ

@Trubbel
Copy link

Trubbel commented Feb 20, 2025

Overwatch 2: 5 Loot Boxes #2
HK4H-DWLF-9S9J6-8D6J-CR5F

@UserStudios1
Copy link

Overwatch 2: 5 Loot Boxes K63W-LD94-JXFGJ-FW59-KD4K

@Kotoezhh
Copy link

Overwatch 2: 5 Loot Boxes
9VQQ-6N6M-XLHL4-VRBR-SXXW

@thepro-3418
Copy link

THE FIRST DESCENDANT Quest Discord Collection Bundle! 9WMUG47KFK
PC Player Quest 14 Day Trial! X2Y9X-72VKT-3YQJY-JKMWY-FQWCZ
COD: Black Ops 6 Quest 0Y7K-64Z46-8BX9
BLACK HAWK DOWN Quest a Spray Paint & Premium Armament Pack Cf5gkb0011tqrMcqF3ga

@mesalytic
Copy link

[Overwatch 2] 5 Loot Boxes: C9JN-KBNN-XTL5F-4TMT-DQD4

@mesalytic
Copy link

[Delta Force] Spray Paint & Premium Armament Pack: Cf5gkb00191t2cz3e5GA

@mario638
Copy link

[Overwatch 2] 5 Loot Boxes: C8GF-SWSC-CT8JQ-WP9D-JMSQ
You can't claim if you claimed before

@Trubbel
Copy link

Trubbel commented Feb 21, 2025

Delta Force: Spray Paint & Premium Armament Pack
Cf5gkb001dFi7OzxGWLg

@adelkoses
Copy link

6T7UA6FA3VBV - for Zaneless Zone Zero, i was still holding onto it, if anyone needs it take it if its even available

@thepro-3418
Copy link

Who still uses this method to do the fortnite decoration quest?

me

@ThanhTrucOwO
Copy link

Thanks It's working

@Guggs0408
Copy link

"VM921:11 Uncaught TypeError: QuestsStore.quests.values is not a function or its return value is not iterable
at :11:36"
I encounter this error when i paste the code in console. It used to work perfectly fine before but now I don't know why it gives this error.
Any solution to this?

@aamiaa
Copy link
Author

aamiaa commented Feb 22, 2025

Yes, the solution is to copy the latest version of the script instead of using an outdated one

@Cats1337
Copy link

How difficult do you think it would be to turn this into a Plugin or into a quick/simple "get raw.github" type thing so people don't have to update their code every time and can just use a single line?

@aamiaa
Copy link
Author

aamiaa commented Feb 22, 2025

How difficult do you think it would be to turn this into a Plugin or into a quick/simple "get raw.github" type thing so people don't have to update their code every time and can just use a single line?

Making it a plugin would require to update it too often (vencord takes a few days to merge dev branch into main for example).

Making it fetch and eval the code would put you at risk because I could change the underlying code to be malicious at any time and you'd never know. Obviously I wouldn't do that, but it's still a risk.

@Cleboost
Copy link

Cleboost commented Feb 23, 2025

@aamiaa,
you should do a raw on a commit, so that people know the code and don't change it. if people don't trust you, they can always take the script manually.

I had fun using your code and making gui :)

https://gist.github.com/user-attachments/assets/afefffe1-249d-4f60-b126-2faa77b3f2a2
image

@perqy
Copy link

perqy commented Feb 23, 2025

Delta force Spray pack Cf5gkb001p2USNar1xqy

@Cats1337
Copy link

@aamiaa, you should do a raw on a commit, so that people know the code and don't change it. if people don't trust you, they can always take the script manually.

I had fun using your code and making gui :)

https://gist.github.com/user-attachments/assets/afefffe1-249d-4f60-b126-2faa77b3f2a2 image

Yeah a simple fetch() is what I was thinking, but couldn't remember the name of

@Trubbel
Copy link

Trubbel commented Feb 24, 2025

Seekers of Skyveil: Grassland Strix Skin
22ceb-NPWNS

@thepro-3418
Copy link

Seekers of Skyveil: Grassland Strix Skin 2mcvN-WuHvk

@JTDMedia
Copy link

i like how people just put their quest codes that they don't need here

@UserStudios1
Copy link

Delta Force Spray Paint & Premium Armament Pack: Cf5gkb002cmerUg3g5Ip

@OmarSherif06
Copy link

Seekers of Skyveil: Grassland Strix Skin 3vGYD-JTnaz

@Viiruzz
Copy link

Viiruzz commented Feb 27, 2025

Seekers of Skyveil: Grassland Strix Skin 4jnRx-qW6KE

@Viiruzz
Copy link

Viiruzz commented Feb 27, 2025

Overwatch 2: 5 Loot Boxes 59H3-CBMH-96CWH-J4KH-9G6X

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