Instantly share code, notes, and snippets.
Forked fromaamiaa/CompleteDiscordQuest.md
Last activeSeptember 26, 2025 03:25
Save aliceric27/cd89939281a7dcbb9d90500dcc7ff9a9 to your computer and use it in GitHub Desktop.
Complete Recent Discord Quest
Note
對於非影片、非活動的任務,此腳本無法在瀏覽器中運作!對於直播/遊玩類型的任務,請使用桌面版應用程式!
Note
執行直播任務時,語音頻道中需要至少有另一個帳號!
如何使用此腳本:
- 在「探索」(伺服器列表中)->「任務」中接受一個任務
- 按下Ctrl+Shift+I 開啟開發者工具
- 前往 Console (主控台) 標籤頁
- 貼上以下程式碼並按下 Enter:
點擊展開
deletewindow.$;letwpRequire=webpackChunkdiscord_app.push([[Symbol()],{},r=>r]);webpackChunkdiscord_app.pop();// -----------[ 模組定義 ] -----------letApplicationStreamingStore=Object.values(wpRequire.c).find(x=>x?.exports?.Z?.__proto__?.getStreamerActiveStreamMetadata).exports.Z;letRunningGameStore=Object.values(wpRequire.c).find(x=>x?.exports?.ZP?.getRunningGames).exports.ZP;letQuestsStore=Object.values(wpRequire.c).find(x=>x?.exports?.Z?.__proto__?.getQuest).exports.Z;letChannelStore=Object.values(wpRequire.c).find(x=>x?.exports?.Z?.__proto__?.getAllThreadsForParent).exports.Z;letGuildChannelStore=Object.values(wpRequire.c).find(x=>x?.exports?.ZP?.getSFWDefaultChannel).exports.ZP;letFluxDispatcher=Object.values(wpRequire.c).find(x=>x?.exports?.Z?.__proto__?.flushWaitQueue).exports.Z;letapi=Object.values(wpRequire.c).find(x=>x?.exports?.tn?.get).exports.tn;// -----------[ 主函式 ] -----------asyncfunctioncompleteAllQuests(){constisApp=typeofDiscordNative!=="undefined";while(true){// 在每次迴圈開始時,重新獲取最新的任務列表constquest=[...QuestsStore.quests.values()].find(x=>x.id!=="1248385850622869556"&&// 排除特定任務x.userStatus?.enrolledAt&&!x.userStatus?.completedAt&&newDate(x.config.expiresAt).getTime()>Date.now());if(!quest){console.log("所有可用的任務都已完成!腳本結束。");break;// 當找不到可執行的任務時,跳出迴圈}console.log(`找到新任務:${quest.config.messages.questName}`);constpid=Math.floor(Math.random()*30000)+1000;constapplicationId=quest.config.application.id;constapplicationName=quest.config.application.name;consttaskConfig=quest.config.taskConfig??quest.config.taskConfigV2;consttaskName=["WATCH_VIDEO","PLAY_ON_DESKTOP","STREAM_ON_DESKTOP","PLAY_ACTIVITY","WATCH_VIDEO_ON_MOBILE"].find(x=>taskConfig.tasks[x]!=null);constsecondsNeeded=taskConfig.tasks[taskName].target;letsecondsDone=quest.userStatus?.progress?.[taskName]?.value??0;try{switch(taskName){case"WATCH_VIDEO":case"WATCH_VIDEO_ON_MOBILE":console.log(`開始處理影片任務:${quest.config.messages.questName}`);awaitcompleteVideoQuest(quest,secondsNeeded);break;case"PLAY_ON_DESKTOP":if(!isApp){console.log("非影片任務需要使用 Discord 桌面版應用程式。");return;// 結束整個函式}console.log(`開始模擬遊戲任務:${applicationName}`);awaitcompletePlayOnDesktopQuest(quest,applicationId,applicationName,secondsNeeded,secondsDone,pid);break;case"STREAM_ON_DESKTOP":if(!isApp){console.log("非影片任務需要使用 Discord 桌面版應用程式。");return;// 結束整個函式}console.log(`開始模擬直播任務:${applicationName}`);awaitcompleteStreamOnDesktopQuest(quest,applicationId,applicationName,secondsNeeded,secondsDone,pid);break;case"PLAY_ACTIVITY":console.log(`開始處理活動任務:${quest.config.messages.questName}`);awaitcompleteActivityQuest(quest,secondsNeeded);break;}console.log(`任務${quest.config.messages.questName} 已完成!正在尋找下一個任務...`);// 等待幾秒鐘,讓 Discord 狀態更新awaitnewPromise(resolve=>setTimeout(resolve,5000));}catch(error){console.error(`執行任務${quest.config.messages.questName} 時發生錯誤:`,error);console.log("等待10秒後重試...");awaitnewPromise(resolve=>setTimeout(resolve,10000));}}}// -----------[ 各類任務的處理函式 ] -----------asyncfunctioncompleteVideoQuest(quest,secondsNeeded){constmaxFuture=10,speed=7,interval=1;constenrolledAt=newDate(quest.userStatus.enrolledAt).getTime();letsecondsDone=quest.userStatus?.progress?.WATCH_VIDEO?.value??0;letcompleted=false;while(secondsDone<secondsNeeded){constmaxAllowed=Math.floor((Date.now()-enrolledAt)/1000)+maxFuture;constdiff=maxAllowed-secondsDone;consttimestamp=secondsDone+speed;if(diff>=speed){constres=awaitapi.post({url:`/quests/${quest.id}/video-progress`,body:{timestamp:Math.min(secondsNeeded,timestamp+Math.random())}});if(res.body.completed_at)completed=true;secondsDone=Math.min(secondsNeeded,timestamp);}if(completed)break;awaitnewPromise(resolve=>setTimeout(resolve,interval*1000));}if(!completed){awaitapi.post({url:`/quests/${quest.id}/video-progress`,body:{timestamp:secondsNeeded}});}}functioncompletePlayOnDesktopQuest(quest,applicationId,applicationName,secondsNeeded,secondsDone,pid){returnnewPromise(async(resolve,reject)=>{try{constres=awaitapi.get({url:`/applications/public?application_ids=${applicationId}`});constappData=res.body[0];constexeName=appData.executables.find(x=>x.os==="win32").name.replace(">","");constfakeGame={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(),};constrealGames=RunningGameStore.getRunningGames();constfakeGames=[fakeGame];constrealGetRunningGames=RunningGameStore.getRunningGames;constrealGetGameForPID=RunningGameStore.getGameForPID;RunningGameStore.getRunningGames=()=>fakeGames;RunningGameStore.getGameForPID=(p)=>fakeGames.find(x=>x.pid===p);FluxDispatcher.dispatch({type:"RUNNING_GAMES_CHANGE",removed:realGames,added:[fakeGame],games:fakeGames});constcleanup=()=>{RunningGameStore.getRunningGames=realGetRunningGames;RunningGameStore.getGameForPID=realGetGameForPID;FluxDispatcher.dispatch({type:"RUNNING_GAMES_CHANGE",removed:[fakeGame],added:[],games:[]});FluxDispatcher.unsubscribe("QUESTS_SEND_HEARTBEAT_SUCCESS",onHeartbeat);};constonHeartbeat=(data)=>{if(data.questId!==quest.id)return;constprogress=Math.floor(data.userStatus.progress.PLAY_ON_DESKTOP.value);console.log(`遊戲進度:${progress}/${secondsNeeded}`);if(progress>=secondsNeeded){cleanup();resolve();}};FluxDispatcher.subscribe("QUESTS_SEND_HEARTBEAT_SUCCESS",onHeartbeat);console.log(`已模擬遊戲${applicationName}。預計需要等待${Math.ceil((secondsNeeded-secondsDone)/60)} 分鐘。`);}catch(error){reject(error);}});}functioncompleteStreamOnDesktopQuest(quest,applicationId,applicationName,secondsNeeded,secondsDone,pid){returnnewPromise((resolve)=>{letrealFunc=ApplicationStreamingStore.getStreamerActiveStreamMetadata;ApplicationStreamingStore.getStreamerActiveStreamMetadata=()=>({id:applicationId, pid,sourceName:null});constcleanup=()=>{ApplicationStreamingStore.getStreamerActiveStreamMetadata=realFunc;FluxDispatcher.unsubscribe("QUESTS_SEND_HEARTBEAT_SUCCESS",onHeartbeat);};constonHeartbeat=(data)=>{if(data.questId!==quest.id)return;constprogress=Math.floor(data.userStatus.progress.STREAM_ON_DESKTOP.value);console.log(`直播進度:${progress}/${secondsNeeded}`);if(progress>=secondsNeeded){cleanup();resolve();}};FluxDispatcher.subscribe("QUESTS_SEND_HEARTBEAT_SUCCESS",onHeartbeat);console.log(`已模擬在${applicationName} 中直播。請在語音頻道中直播任何視窗,並確保有至少一位觀眾。`);console.log(`預計需要${Math.ceil((secondsNeeded-secondsDone)/60)} 分鐘。`);});}asyncfunctioncompleteActivityQuest(quest,secondsNeeded){constchannelId=ChannelStore.getSortedPrivateChannels()[0]?.id??Object.values(GuildChannelStore.getAllGuilds()).find(x=>x!=null&&x.VOCAL.length>0).VOCAL[0].channel.id;conststreamKey=`call:${channelId}:1`;letprogress=0;while(progress<secondsNeeded){constres=awaitapi.post({url:`/quests/${quest.id}/heartbeat`,body:{stream_key:streamKey,terminal:false}});progress=res.body.progress.PLAY_ACTIVITY.value;console.log(`活動進度:${progress}/${secondsNeeded}`);if(progress>=secondsNeeded)break;awaitnewPromise(resolve=>setTimeout(resolve,20*1000));}awaitapi.post({url:`/quests/${quest.id}/heartbeat`,body:{stream_key:streamKey,terminal:true}});}// -----------[ 啟動腳本 ] -----------completeAllQuests();
- 根據您的任務類型,遵循主控台中顯示的指示
- 如果您的任務要求「遊玩」遊戲,您只需等待,不需進行任何操作
- 如果您的任務要求「直播」遊戲,請與朋友或分身帳號加入一個語音頻道,並直播任何一個視窗
- 等待所有任務完成(全自動檢測目前所有已接取任務)
- 您現在可以到「使用者設定」->「禮物庫」中領取獎勵了!
問:Ctrl +Shift +I 沒有作用
答:您可以下載PTB 用戶端,或使用這個方法來在穩定版中啟用開發者工具。
或參考Discord多開管理器
問:Ctrl +V 沒有作用
答:你需要先手動輸入allow pasting 並Enter送出
問:我收到「未經授權 (Unauthorized)」的錯誤訊息
答:Discord 已經修補了此腳本在瀏覽器中的漏洞。請使用 Discord 桌面版應用程式。
他們也開始檢查語音頻道中的人數,所以請確保至少有另一個帳號加入頻道。
問:我收到語法錯誤/非預期符記 (syntax error/unexpected token) 的錯誤訊息
答:在複製腳本前,請確保您的瀏覽器沒有自動翻譯此網頁。關閉任何翻譯擴充功能後再試一次。
問:我遇到其他錯誤
答:請確保您正確地複製/貼上腳本,並且已完成所有步驟。
問:可以讓腳本自動接受任務/領取獎勵嗎?
答:不行。這兩個操作都有可能觸發人機驗證 (captcha),所以自動化並不是個好主意。請您親自點擊那兩下。
問:您可以將獨立的腳本上傳到一個 repo,然後讓這個 gist 的程式碼變成一行 fetch() 嗎?
答:不行。這樣做會讓您置於風險之中,因為我 (或任何能存取我帳號的人) 可以隨時將底層的程式碼改成惡意代碼,然後再用 force-push 的方式抹去紀錄,您將永遠不會知道。
此專案透過CompleteDiscordQuest.md 重新修改
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment