前言
Discord 最近新出了一個徽章,只要完成 Discord 出的任務就能拿到合作遊戲的遊戲內獎勵和展示在 Discord 個人資料上的任務徽章,但不是每個人都花 70~90 GB 的硬碟空間裝和 GTA5 差不多大小的牆國抄襲遊戲 還原神作 ,所以我們可以用一段程式碼來欺騙 Discord,讓系統以為你正在直播原神給朋友以完成任務。
教學
1. 到 Discord 設定
裡的 禮物庫存
,可以看到多了個 任務
的部分,要求你直播 15 分鐘的原神給朋友看。
2. 按下 接受任務
後進任一伺服器的語音頻道,以防萬一可以請一位朋友或自己的小帳一起加入語音頻道,不然可能會失效。接著直播隨便一個視窗,任何視窗都行,重點是有開直播就好,我這邊是直播瀏覽器。
3. 都準備好後直接 Ctrl + Shift + i,可以看到右半邊跳出了開發者工具,其中的警告可以都忽略,不用太擔心。
4. 接著按到 Console
標籤,將下圖下方的程式碼貼上來後 Enter。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| let wpRequire; window.webpackChunkdiscord_app.push([[ Math.random() ], {}, (req) => { wpRequire = req; }]);
let ApplicationStreamingStore, RunningGameStore, QuestsStore, ExperimentStore, FluxDispatcher, api if(window.GLOBAL_ENV.SENTRY_TAGS.buildId === "366c746173a6ca0a801e9f4a4d7b6745e6de45d4") { ApplicationStreamingStore = Object.values(wpRequire.c).find(x => x?.exports?.default?.getStreamerActiveStreamMetadata).exports.default; RunningGameStore = Object.values(wpRequire.c).find(x => x?.exports?.default?.getRunningGames).exports.default; QuestsStore = Object.values(wpRequire.c).find(x => x?.exports?.default?.getQuest).exports.default; ExperimentStore = Object.values(wpRequire.c).find(x => x?.exports?.default?.getGuildExperiments).exports.default; FluxDispatcher = Object.values(wpRequire.c).find(x => x?.exports?.default?.flushWaitQueue).exports.default; api = Object.values(wpRequire.c).find(x => x?.exports?.getAPIBaseURL).exports.HTTP; } else { ApplicationStreamingStore = Object.values(wpRequire.c).find(x => x?.exports?.Z?.getStreamerActiveStreamMetadata).exports.Z; RunningGameStore = Object.values(wpRequire.c).find(x => x?.exports?.ZP?.getRunningGames).exports.ZP; QuestsStore = Object.values(wpRequire.c).find(x => x?.exports?.Z?.getQuest).exports.Z; ExperimentStore = Object.values(wpRequire.c).find(x => x?.exports?.Z?.getGuildExperiments).exports.Z; FluxDispatcher = Object.values(wpRequire.c).find(x => x?.exports?.Z?.flushWaitQueue).exports.Z; api = Object.values(wpRequire.c).find(x => x?.exports?.tn?.get).exports.tn; }
let quest = [...QuestsStore.quests.values()].find(x => x.userStatus?.enrolledAt && !x.userStatus?.completedAt && new Date(x.config.expiresAt).getTime() > Date.now()) let isApp = navigator.userAgent.includes("Electron/") if(!isApp) { console.log("This no longer works in browser. Use the desktop app!") } else if(!quest) { console.log("You don't have any uncompleted quests!") } else { const pid = Math.floor(Math.random() * 30000) + 1000 let applicationId, applicationName, secondsNeeded, secondsDone, canPlay if(quest.config.configVersion === 1) { applicationId = quest.config.applicationId applicationName = quest.config.applicationName secondsNeeded = quest.config.streamDurationRequirementMinutes * 60 secondsDone = quest.userStatus?.streamProgressSeconds ?? 0 canPlay = quest.config.variants.includes(2) } else if(quest.config.configVersion === 2) { applicationId = quest.config.application.id applicationName = quest.config.application.name canPlay = ExperimentStore.getUserExperimentBucket("2024-04_quest_playtime_task") > 0 && quest.config.taskConfig.tasks["PLAY_ON_DESKTOP"] const taskName = canPlay ? "PLAY_ON_DESKTOP" : "STREAM_ON_DESKTOP" secondsNeeded = quest.config.taskConfig.tasks[taskName].target secondsDone = quest.userStatus?.progress?.[taskName]?.value ?? 0 }
if(canPlay) { 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 { 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!") } }
|
5. 可以在控制台看到 Quest progress: XX/XXX
,代表任務進度正在跑了,也可以回到 禮物庫存
確認下進度有沒有加,接著直播別關掛著 15 分鐘即可。
15 分鐘後回到 Discord,可以看到任務完成了,獎勵也成功解鎖了,而 Discord 的個人檔案上也多了個任務徽章。
補充
如果在第 4 步 Enter 後跳出了下圖的警告,輸入 allow pasting
即可繼續。