## 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 User Settings -> Gift Inventory 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 ```js delete window.$; let wpRequire = webpackChunkdiscord_app.push([[Symbol()], {}, r => r]); webpackChunkdiscord_app.pop(); 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 = typeof DiscordNative !== "undefined" 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 questName = quest.config.messages.questName const taskConfig = quest.config.taskConfig ?? quest.config.taskConfigV2 const taskName = ["WATCH_VIDEO", "PLAY_ON_DESKTOP", "STREAM_ON_DESKTOP", "PLAY_ACTIVITY", "WATCH_VIDEO_ON_MOBILE"].find(x => taskConfig.tasks[x] != null) const secondsNeeded = taskConfig.tasks[taskName].target let secondsDone = quest.userStatus?.progress?.[taskName]?.value ?? 0 if(taskName === "WATCH_VIDEO" || taskName === "WATCH_VIDEO_ON_MOBILE") { const maxFuture = 10, speed = 7, interval = 1 const enrolledAt = new Date(quest.userStatus.enrolledAt).getTime() let completed = false let fn = async () => { while(true) { const maxAllowed = Math.floor((Date.now() - enrolledAt)/1000) + maxFuture const diff = maxAllowed - secondsDone const timestamp = secondsDone + speed if(diff >= speed) { const res = await api.post({url: `/quests/${quest.id}/video-progress`, body: {timestamp: Math.min(secondsNeeded, timestamp + Math.random())}}) completed = res.body.completed_at != null secondsDone = Math.min(secondsNeeded, timestamp) } if(timestamp >= secondsNeeded) { break } await new Promise(resolve => setTimeout(resolve, interval * 1000)) } if(!completed) { await api.post({url: `/quests/${quest.id}/video-progress`, body: {timestamp: secondsNeeded}}) } console.log("Quest completed!") } fn() console.log(`Spoofing video for ${questName}.`) } else if(taskName === "PLAY_ON_DESKTOP") { if(!isApp) { console.log("This no longer works in browser for non-video quests. Use the discord desktop app to complete the", questName, "quest!") } else { 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 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(), } const realGames = RunningGameStore.getRunningGames() const fakeGames = [fakeGame] const realGetRunningGames = RunningGameStore.getRunningGames const realGetGameForPID = RunningGameStore.getGameForPID RunningGameStore.getRunningGames = () => fakeGames RunningGameStore.getGameForPID = (pid) => fakeGames.find(x => x.pid === pid) FluxDispatcher.dispatch({type: "RUNNING_GAMES_CHANGE", removed: realGames, added: [fakeGame], games: fakeGames}) 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!") RunningGameStore.getRunningGames = realGetRunningGames RunningGameStore.getGameForPID = realGetGameForPID 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 discord desktop app to complete the", questName, "quest!") } else { 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", questName, "-", 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() } } ```
5. 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 7. Wait for 15 minutes 8. 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](https://discord.com/api/downloads/distributions/app/installers/latest?channel=ptb&platform=win&arch=x64), or use [this](https://www.reddit.com/r/discordapp/comments/sc61n3/comment/hu4fw5x/) 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.