From c510a4c8c490f057a5a73dcd4490cc95c9c305b9 Mon Sep 17 00:00:00 2001 From: Tharki-God Date: Sat, 28 Oct 2023 16:33:44 +0530 Subject: [PATCH] fix????? --- src/renderer/coremods/badges/index.tsx | 12 ++--- src/renderer/coremods/commands/index.ts | 50 +++++++------------ .../coremods/contextMenu/plaintextPatches.ts | 6 +-- src/renderer/coremods/rpc/index.ts | 21 +++----- src/renderer/managers/coremods.ts | 25 ++++++---- src/renderer/managers/ignition.ts | 2 +- src/renderer/modules/webpack/patch-load.ts | 11 ++-- .../modules/webpack/plaintext-patch.ts | 14 ++++-- 8 files changed, 64 insertions(+), 77 deletions(-) diff --git a/src/renderer/coremods/badges/index.tsx b/src/renderer/coremods/badges/index.tsx index 7f9bda4c2..aae742880 100644 --- a/src/renderer/coremods/badges/index.tsx +++ b/src/renderer/coremods/badges/index.tsx @@ -2,7 +2,7 @@ import React from "@common/react"; import { Logger } from "@replugged"; import type { User } from "discord-types/general"; import { Injector } from "../../modules/injector"; -import { filters, getByProps, waitForModule } from "../../modules/webpack"; +import { getByProps, waitForProps } from "../../modules/webpack"; import { generalSettings } from "../settings/pages/General"; import { APIBadges, BadgeSizes, Custom, badgeElements, getBadgeSizeClass } from "./badge"; @@ -37,17 +37,15 @@ const cache = new Map(); const REFRESH_INTERVAL = 1000 * 60 * 30; export async function start(): Promise { - const mod = await waitForModule>(filters.bySource("getBadges()")); - const fnPropName = Object.entries(mod).find(([_, v]) => typeof v === "function")?.[0]; - if (!fnPropName) { - throw new Error("Could not find badges function"); - } + const mod = await waitForProps<{ BadgeSizes: Record; default: BadgeMod }>( + "BadgeSizes", + ); const { containerWithContent } = getByProps<{ containerWithContent: "string" }>( "containerWithContent", )!; - injector.after(mod, fnPropName, ([props], res) => { + injector.after(mod, "default", ([props], res) => { let { user: { id }, shrinkAtCount, diff --git a/src/renderer/coremods/commands/index.ts b/src/renderer/coremods/commands/index.ts index 8d0fa9dc4..4836625d0 100644 --- a/src/renderer/coremods/commands/index.ts +++ b/src/renderer/coremods/commands/index.ts @@ -1,13 +1,7 @@ import type { AnyRepluggedCommand, RepluggedCommandSection } from "../../../types"; import { Injector } from "../../modules/injector"; import { Logger } from "../../modules/logger"; -import { - filters, - getExportsForProps, - getFunctionKeyBySource, - waitForModule, - waitForProps, -} from "../../modules/webpack"; +import { waitForProps } from "../../modules/webpack"; import { commandAndSections, defaultSection } from "../../apis/commands"; import { loadCommands, unloadCommands } from "./commands"; @@ -16,7 +10,7 @@ const logger = Logger.api("Commands"); const injector = new Injector(); interface ApplicationCommandSearchStoreMod { - [key: string]: (...args: unknown[]) => + useDiscoveryState: (...args: unknown[]) => | { sectionDescriptors: RepluggedCommandSection[]; commands: AnyRepluggedCommand[]; @@ -28,6 +22,10 @@ interface ApplicationCommandSearchStoreMod { }>; } | undefined; + useQueryState: (...args: unknown[]) => unknown; + useSearchStoreOpenState: (...args: unknown[]) => unknown; + search: (...args: unknown[]) => unknown; + default: ApplicationCommandSearchStore; } interface ApplicationCommandSearchStore { @@ -68,17 +66,16 @@ async function injectRepluggedSectionIcon(): Promise { async function injectApplicationCommandSearchStore(): Promise { // The module which contains the store - const ApplicationCommandSearchStoreMod = await waitForModule( - filters.bySource("ApplicationCommandSearchStore"), - ); - const storeModFnKey = getFunctionKeyBySource( - ApplicationCommandSearchStoreMod, - "APPLICATION_COMMAND_SEARCH_STORE_UPDATE", + const ApplicationCommandSearchStoreMod = await waitForProps( + "useDiscoveryState", + "useQueryState", + "useSearchStoreOpenState", + "search", ); // Base handler function for ApplicationCommandSearchStore which is ran to get the info in store // commands are mainly added here - injector.after(ApplicationCommandSearchStoreMod, storeModFnKey!, (_, res) => { + injector.after(ApplicationCommandSearchStoreMod, "useDiscoveryState", (_, res) => { const commandAndSectionsArray = Array.from(commandAndSections.values()).filter( (commandAndSection) => commandAndSection.commands.size, ); @@ -168,10 +165,7 @@ async function injectApplicationCommandSearchStore(): Promise { }); // The store itself - const ApplicationCommandSearchStore = getExportsForProps( - ApplicationCommandSearchStoreMod, - ["getApplicationSections", "getChannelState", "getQueryCommands"], - )!; + const ApplicationCommandSearchStore = ApplicationCommandSearchStoreMod.default; // Channel state gets update with each character entered in text box and search so we patch this to keep our custom section // even after updates happen @@ -264,19 +258,11 @@ async function injectApplicationCommandSearchStore(): Promise { } async function injectProfileFetch(): Promise { - const mod = await waitForModule< - Record< - string, - ( - id: string, - avatar: string, - { guildId, channelId }: { guildId: string; channelId: string }, - ) => Promise - > - >(filters.bySource(".preloadUserBanner,"), { raw: true }); - const fnKey = getFunctionKeyBySource(mod.exports, ".apply(this"); - injector.instead(mod.exports, fnKey!, (args, res) => { - if (args[1] === defaultSection.icon) { + const mod = await waitForProps<{ + fetchProfile: (id: string) => Promise; + }>("fetchProfile"); + injector.instead(mod, "fetchProfile", (args, res) => { + if (args[0] === "replugged") { return; } return res(...args); diff --git a/src/renderer/coremods/contextMenu/plaintextPatches.ts b/src/renderer/coremods/contextMenu/plaintextPatches.ts index a18e8c84d..d5b9386b5 100644 --- a/src/renderer/coremods/contextMenu/plaintextPatches.ts +++ b/src/renderer/coremods/contextMenu/plaintextPatches.ts @@ -12,11 +12,11 @@ export default [ ], }, { - find: "navId:", + find: ".Menu,{", replacements: [ { - match: /navId:[\w"-]+,/g, - replace: (navId) => `${navId}data:arguments,`, + match: /\.Menu,{/g, + replace: (prefix) => `${prefix}data:arguments,`, }, ], }, diff --git a/src/renderer/coremods/rpc/index.ts b/src/renderer/coremods/rpc/index.ts index 04a47e945..c699936da 100644 --- a/src/renderer/coremods/rpc/index.ts +++ b/src/renderer/coremods/rpc/index.ts @@ -1,12 +1,10 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ -import { Injector, Logger } from "@replugged"; -import { filters, getFunctionKeyBySource, waitForModule } from "src/renderer/modules/webpack"; +import { Injector } from "@replugged"; +import { filters, waitForModule, waitForProps } from "src/renderer/modules/webpack"; import { Jsonifiable } from "type-fest"; const injector = new Injector(); -const logger = Logger.coremod("RPC"); - type Socket = Record & { authorization: Record & { scopes: string[]; @@ -40,16 +38,11 @@ type RPCMod = { commands: Commands }; let commands: Commands = {}; async function injectRpc(): Promise { - const rpcValidatorMod = await waitForModule< - Record Promise> - >(filters.bySource("Invalid Client ID")); - const validatorFunctionKey = getFunctionKeyBySource(rpcValidatorMod, "Invalid Client ID"); - if (!validatorFunctionKey) { - logger.error("Failed to find RPC validator function."); - return; - } - - injector.instead(rpcValidatorMod, validatorFunctionKey, (args, fn) => { + const rpcValidatorMod = await waitForProps<{ + fetchApplicationsRPC: (socket: Socket, client_id: string, origin: string) => Promise; + }>("fetchApplicationsRPC"); + + injector.instead(rpcValidatorMod, "fetchApplicationsRPC", (args, fn) => { const [, clientId, origin] = args; const isRepluggedClient = clientId.startsWith("REPLUGGED-"); diff --git a/src/renderer/managers/coremods.ts b/src/renderer/managers/coremods.ts index 4fd9063f2..9cccdc01c 100644 --- a/src/renderer/managers/coremods.ts +++ b/src/renderer/managers/coremods.ts @@ -74,15 +74,18 @@ export async function stopAll(): Promise { await Promise.allSettled(Object.values(coremods).map((c) => c.stop?.())); } -export function runPlaintextPatches(): void { - [ - experimentsPlaintext, - notrackPlaintext, - noDevtoolsWarningPlaintext, - messagePopover, - notices, - contextMenu, - languagePlaintext, - commandsPlaintext, - ].forEach(patchPlaintext); +export function runPlaintextPatches(): Promise { + return new Promise((res) => { + [ + experimentsPlaintext, + notrackPlaintext, + noDevtoolsWarningPlaintext, + messagePopover, + notices, + contextMenu, + languagePlaintext, + commandsPlaintext, + ].forEach(patchPlaintext); + res(); + }); } diff --git a/src/renderer/managers/ignition.ts b/src/renderer/managers/ignition.ts index 0cec599ff..1847fb348 100644 --- a/src/renderer/managers/ignition.ts +++ b/src/renderer/managers/ignition.ts @@ -84,7 +84,7 @@ Load order: export async function ignite(): Promise { // This is the function that will be called when loading the window. // Plaintext patches are executed before Discord's preload. - coremods.runPlaintextPatches(); + await coremods.runPlaintextPatches(); await plugins.loadAll(); await plugins.runPlaintextPatches(); // These next things will happen after Discord's preload is called. diff --git a/src/renderer/modules/webpack/patch-load.ts b/src/renderer/modules/webpack/patch-load.ts index 045b4e3f1..98d620089 100644 --- a/src/renderer/modules/webpack/patch-load.ts +++ b/src/renderer/modules/webpack/patch-load.ts @@ -45,12 +45,13 @@ export const waitForStart = new Promise((resolve) => (signalStart = resolv */ export const sourceStrings: Record = {}; -function patchChunk(chunk: WebpackChunk): void { +async function patchChunk(chunk: WebpackChunk): Promise { + await waitForStart; const modules = chunk[1]; for (const id in modules) { const originalMod = modules[id]; sourceStrings[id] = originalMod.toString(); - const mod = patchModuleSource(originalMod); + const mod = patchModuleSource(originalMod, id); modules[id] = function (module, exports, require) { mod(module, exports, require); @@ -73,8 +74,8 @@ function patchChunk(chunk: WebpackChunk): void { function patchPush(webpackChunk: WebpackChunkGlobal): void { let original = webpackChunk.push; - function handlePush(chunk: WebpackChunk): unknown { - patchChunk(chunk); + async function handlePush(chunk: WebpackChunk): Promise { + await patchChunk(chunk); return original.call(webpackChunk, chunk); } @@ -123,7 +124,7 @@ function loadWebpackModules(chunksGlobal: WebpackChunkGlobal): void { // Patch previously loaded chunks if (Array.isArray(chunksGlobal)) { for (const loadedChunk of chunksGlobal) { - patchChunk(loadedChunk); + void patchChunk(loadedChunk); } } diff --git a/src/renderer/modules/webpack/plaintext-patch.ts b/src/renderer/modules/webpack/plaintext-patch.ts index c4040019b..5ef6df47d 100644 --- a/src/renderer/modules/webpack/plaintext-patch.ts +++ b/src/renderer/modules/webpack/plaintext-patch.ts @@ -1,5 +1,6 @@ import type { PlaintextPatch, RawPlaintextPatch, WebpackModule } from "../../../types"; - +import { Logger } from "../logger"; +const logger = Logger.api("plaintext-patch"); /** * All plaintext patches */ @@ -10,7 +11,7 @@ export const plaintextPatches: RawPlaintextPatch[] = []; * @param mod Module * @returns Patched module */ -export function patchModuleSource(mod: WebpackModule): WebpackModule { +export function patchModuleSource(mod: WebpackModule, id: string): WebpackModule { const originalSource = mod.toString(); const patchedSource = plaintextPatches.reduce((source, patch) => { @@ -39,8 +40,13 @@ export function patchModuleSource(mod: WebpackModule): WebpackModule { } try { // eslint-disable-next-line no-eval - return (0, eval)(patchedSource); - } catch { + return (0, eval)( + `${ + patchedSource.startsWith("function(") ? `0,${patchedSource}` : patchedSource + }\n//# sourceURL=PatchedWebpack-${id}`, + ); + } catch (err) { + logger.error(`PatchedWebpack-${id}`, err); // Syntax error in patched module--fail return mod; }