-
-
Save mx-989/fa077e1e5e8bafa14b697e5bfeac211b to your computer and use it in GitHub Desktop.
Complete Recent Discord Quest - Batch Complete All Accepted Quests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | |
| const supportedTasks = ["WATCH_VIDEO", "PLAY_ON_DESKTOP", "STREAM_ON_DESKTOP", "PLAY_ACTIVITY", "WATCH_VIDEO_ON_MOBILE"] | |
| let isApp = typeof DiscordNative !== "undefined" | |
| let startQuestLoop = function (retryCount = 0) { | |
| let quests = [...QuestsStore.quests.values()].filter(x => x.userStatus?.enrolledAt && !x.userStatus?.completedAt && new Date(x.config.expiresAt).getTime() > Date.now() && supportedTasks.find(y => Object.keys((x.config.taskConfig ?? x.config.taskConfigV2).tasks).includes(y))) | |
| if (quests.length === 0) { | |
| if (retryCount >= 1) { | |
| console.log("No accepted quests found after retry. Script ended.") | |
| return | |
| } | |
| console.log("No accepted quests found. Checking again in 30 seconds...") | |
| setTimeout(() => startQuestLoop(retryCount + 1), 30000) | |
| return | |
| } | |
| console.log(`Found ${quests.length} quest(s) to complete.`) | |
| let doJob = function () { | |
| const quest = quests.pop() | |
| if (!quest) { | |
| console.log("All quests in current batch completed. Restarting quest check...") | |
| setTimeout(() => startQuestLoop(), 5000) | |
| return | |
| } | |
| 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 = supportedTasks.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!") | |
| doJob() | |
| } | |
| 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) | |
| doJob() | |
| } | |
| } | |
| 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) | |
| doJob() | |
| } | |
| } | |
| 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!") | |
| doJob() | |
| } | |
| fn() | |
| } | |
| } | |
| doJob() | |
| } | |
| startQuestLoop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment