Skip to content

Instantly share code, notes, and snippets.

@luluwaffless
Forked from aamiaa/CompleteDiscordQuest.md
Last active November 7, 2025 01:26
Show Gist options
  • Select an option

  • Save luluwaffless/a1d9479c28a4d31b3bf880ad26e7482b to your computer and use it in GitHub Desktop.

Select an option

Save luluwaffless/a1d9479c28a4d31b3bf880ad26e7482b to your computer and use it in GitHub Desktop.
Complete Discord Quests
/*
* This is a fork by luluwaffless (https://github.com/luluwaffless) of
* CompleteDiscordQuest by aamiaa (https://gist.github.com/aamiaa/) with
* support for finishing all uncompleted quests without having to re-run
* the script multiple times. All rights to Amia. Make sure to read the
* document of the original repository if you need help.
* Revision: https://gist.githubusercontent.com/aamiaa/204cd9d42013ded9faf646fae7f89fbb/raw/4912415839790240d49c1d2553e940f0c65f95d5/CompleteDiscordQuest.md
*/
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 isApp = typeof DiscordNative !== "undefined";
const sleep = s => new Promise(r => setTimeout(r, s * 1000));
const completeQuest = quest => new Promise(async (r) => {
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;
console.log(`Spoofing video for ${questName}.`);
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 sleep(interval);
};
if (!completed) await api.post({ url: `/quests/${quest.id}/video-progress`, body: { timestamp: secondsNeeded } });
console.log("Quest completed!");
r("Success");
} 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!");
r("Unavailable on browser");
} else {
const res = await api.get({ url: `/applications/public?application_ids=${applicationId}` });
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!");
r("Success");
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!");
r("Unavailable on browser");
} 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!");
r("Success");
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 voice chat for ${Math.ceil((secondsNeeded - secondsDone) / 60)} more minutes.\nBe aware that you need another person to be in the voice chat in order to progress!`);
};
} 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`;
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 sleep(20);
if (progress >= secondsNeeded) {
await api.post({ url: `/quests/${quest.id}/heartbeat`, body: { stream_key: streamKey, terminal: true } });
break;
};
};
console.log("Quest completed!");
r("Success");
};
});
let quests = [...QuestsStore.quests.values()].filter(x => x.id !== "1412491570820812933" && x.userStatus?.enrolledAt && !x.userStatus?.completedAt && new Date(x.config.expiresAt).getTime() > Date.now());
if (quests.length === 0) {
console.log("You don't have any uncompleted quests!");
} else {
(async () => {
console.log(`${quests.length} uncompleted quest${quests.length !== 1 ? "s" : ""} detected!`);
const results = {};
for (let i = 0; i < quests.length; i++) {
const quest = quests[i];
console.log(`Starting quest #${i + 1}...`)
const result = await completeQuest(quest);
if (!results[result]) results[result] = 0;
results[result] += 1;
console.log(`Finished quest #${i + 1}! (${i + 1}/${quests.length} | ${Math.floor(((i + 1) / quests.length) * 1000) / 10}%)`);
};
console.log(`Finished all ${quests.length} quests! Results:\n${Object.keys(results).map(key => `${key}: ${results[key]}`).join('\n')}`);
})();
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment