diff --git a/src/debug/runReporter.ts b/src/debug/runReporter.ts index b42b36716..c574d30a5 100644 --- a/src/debug/runReporter.ts +++ b/src/debug/runReporter.ts @@ -97,12 +97,15 @@ async function runReporter() { result = findResult; for (const innerMap in result) { - if (result[innerMap][SYM_PROXY_INNER_GET] != null && result[innerMap][SYM_PROXY_INNER_VALUE] == null) { - throw new Error("Webpack Find Fail"); - } else if (result[innerMap][SYM_LAZY_COMPONENT_INNER] != null && result[innerMap][SYM_LAZY_COMPONENT_INNER]() == null) { + if ( + (result[innerMap][SYM_PROXY_INNER_GET] != null && result[innerMap][SYM_PROXY_INNER_VALUE] == null) || + (result[innerMap][SYM_LAZY_COMPONENT_INNER] != null && result[innerMap][SYM_LAZY_COMPONENT_INNER]() == null) + ) { throw new Error("Webpack Find Fail"); } } + + break; } // This can happen if a `find` was immediately found @@ -125,9 +128,10 @@ async function runReporter() { if (args[0].$$vencordProps != null) { if (["find", "findComponent", "waitFor"].includes(searchType)) { filterName = args[0].$$vencordProps[0]; + parsedArgs = args[0].$$vencordProps.slice(1); + } else { + parsedArgs = args[0].$$vencordProps; } - - parsedArgs = args[0].$$vencordProps.slice(1); } function stringifyCodeFilter(code: string | RegExp | Webpack.CodeFilter) { diff --git a/src/plugins/_core/noTrack.ts b/src/plugins/_core/noTrack.ts index d030c6577..887ce3a68 100644 --- a/src/plugins/_core/noTrack.ts +++ b/src/plugins/_core/noTrack.ts @@ -93,7 +93,7 @@ export default definePlugin({ // Ensure this is most likely the Sentry WebpackInstance. // Function.g is a very generic property and is not uncommon for another WebpackInstance (or even a React component: ) to include it const { stack } = new Error(); - if (!(stack?.includes("discord.com") || stack?.includes("discordapp.com")) || !String(this).includes("exports:{}") || this.c != null) { + if (!stack?.includes("/assets/") || !String(this).includes("exports:{}") || this.c != null) { return; } diff --git a/src/plugins/clientTheme/index.tsx b/src/plugins/clientTheme/index.tsx index b12798ac3..19bc6747e 100644 --- a/src/plugins/clientTheme/index.tsx +++ b/src/plugins/clientTheme/index.tsx @@ -37,14 +37,14 @@ function setTheme(theme: string) { } const ThemeStore = findStore("ThemeStore"); -const NitroThemeStore = findStore("ClientThemesBackgroundStore"); +const ClientThemesBackgroundStore = findStore("ClientThemesBackgroundStore"); function ThemeSettings() { const theme = useStateFromStores([ThemeStore], () => ThemeStore.theme); const isLightTheme = theme === "light"; const oppositeTheme = isLightTheme ? "dark" : "light"; - const nitroTheme = useStateFromStores([NitroThemeStore], () => NitroThemeStore.gradientPreset); + const nitroTheme = useStateFromStores([ClientThemesBackgroundStore], () => ClientThemesBackgroundStore.gradientPreset); const nitroThemeEnabled = nitroTheme !== undefined; const selectedLuminance = relativeLuminance(settings.store.color); diff --git a/src/plugins/consoleShortcuts/index.ts b/src/plugins/consoleShortcuts/index.ts index f73559c89..16c7e0e23 100644 --- a/src/plugins/consoleShortcuts/index.ts +++ b/src/plugins/consoleShortcuts/index.ts @@ -94,8 +94,8 @@ function makeShortcuts() { findAllByProps: (...props: string[]) => cacheFindAll(filters.byProps(...props)), findByCode: newFindWrapper(filters.byCode), findAllByCode: (code: string) => cacheFindAll(filters.byCode(code)), - findComponentByCode: newFindWrapper(filters.byComponentCode), - findAllComponentsByCode: (...code: string[]) => cacheFindAll(filters.byComponentCode(...code)), + findComponentByCode: newFindWrapper(filters.componentByCode), + findAllComponentsByCode: (...code: string[]) => cacheFindAll(filters.componentByCode(...code)), findExportedComponent: (...props: string[]) => findByProps(...props)[props[0]], findStore: newFindWrapper(filters.byStoreName), findByFactoryCode: newFindWrapper(filters.byFactoryCode), diff --git a/src/plugins/decor/ui/components/index.ts b/src/plugins/decor/ui/components/index.ts index b73ad7564..a0c05cd69 100644 --- a/src/plugins/decor/ui/components/index.ts +++ b/src/plugins/decor/ui/components/index.ts @@ -19,9 +19,7 @@ type DecorationGridItemComponent = ComponentType DecorationGridItem = v; -export const AvatarDecorationModalPreview = findComponentByCode(".shopPreviewBanner", component => { - return React.memo(component); -}); +export const AvatarDecorationModalPreview = findComponentByCode(".shopPreviewBanner", component => React.memo(component)); type DecorationGridDecorationComponent = React.ComponentType & { avatarDecoration: AvatarDecoration; diff --git a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx index 05c601257..24339be3a 100644 --- a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx @@ -20,7 +20,7 @@ import { AvatarDecorationModalPreview } from "../components"; const FileUpload = findComponentByCode("fileUploadInput,"); const { HelpMessage, HelpMessageTypes } = mapMangledModule('POSITIVE=3]="POSITIVE', { - HelpMessage: filters.byComponentCode(".iconDiv,", "messageType"), + HelpMessage: filters.componentByCode(".iconDiv,", "messageType"), HelpMessageTypes: filters.byProps("POSITIVE", "WARNING"), }); diff --git a/src/plugins/devCompanion.dev/index.tsx b/src/plugins/devCompanion.dev/index.tsx index 7842655ba..3781e5ca4 100644 --- a/src/plugins/devCompanion.dev/index.tsx +++ b/src/plugins/devCompanion.dev/index.tsx @@ -216,7 +216,7 @@ function initWs(isManual = false) { results = Object.keys(search(parsedArgs[0])); break; case "ComponentByCode": - results = cacheFindAll(filters.byComponentCode(...parsedArgs)); + results = cacheFindAll(filters.componentByCode(...parsedArgs)); break; default: return reply("Unknown Find Type " + type); diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index beda7aab9..2c6cb0f40 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -30,7 +30,7 @@ import type { Message } from "discord-types/general"; import { applyPalette, GIFEncoder, quantize } from "gifenc"; import type { ReactElement, ReactNode } from "react"; -const StickerStore = findStore("StickersStore") as { +const StickersStore = findStore("StickersStore") as { getPremiumPacks(): StickerPack[]; getAllGuildStickers(): Map; getStickerById(id: string): Sticker | undefined; @@ -566,8 +566,8 @@ export default definePlugin({ const gifMatch = child.props.href.match(fakeNitroGifStickerRegex); if (gifMatch) { - // There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickerStore contains the id of the fake sticker - if (StickerStore.getStickerById(gifMatch[1])) return null; + // There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickersStore contains the id of the fake sticker + if (StickersStore.getStickerById(gifMatch[1])) return null; } } @@ -655,7 +655,7 @@ export default definePlugin({ url = new URL(item); } catch { } - const stickerName = StickerStore.getStickerById(imgMatch[1])?.name ?? url?.searchParams.get("name") ?? "FakeNitroSticker"; + const stickerName = StickersStore.getStickerById(imgMatch[1])?.name ?? url?.searchParams.get("name") ?? "FakeNitroSticker"; stickers.push({ format_type: 1, id: imgMatch[1], @@ -668,9 +668,9 @@ export default definePlugin({ const gifMatch = item.match(fakeNitroGifStickerRegex); if (gifMatch) { - if (!StickerStore.getStickerById(gifMatch[1])) continue; + if (!StickersStore.getStickerById(gifMatch[1])) continue; - const stickerName = StickerStore.getStickerById(gifMatch[1])?.name ?? "FakeNitroSticker"; + const stickerName = StickersStore.getStickerById(gifMatch[1])?.name ?? "FakeNitroSticker"; stickers.push({ format_type: 2, id: gifMatch[1], @@ -703,8 +703,8 @@ export default definePlugin({ const gifMatch = embed.url!.match(fakeNitroGifStickerRegex); if (gifMatch) { - // There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickerStore contains the id of the fake sticker - if (StickerStore.getStickerById(gifMatch[1])) return true; + // There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickersStore contains the id of the fake sticker + if (StickersStore.getStickerById(gifMatch[1])) return true; } } @@ -721,8 +721,8 @@ export default definePlugin({ const match = attachment.url.match(fakeNitroGifStickerRegex); if (match) { - // There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickerStore contains the id of the fake sticker - if (StickerStore.getStickerById(match[1])) return false; + // There is no way to differentiate a regular gif attachment from a fake nitro animated sticker, so we check if the StickersStore contains the id of the fake sticker + if (StickersStore.getStickerById(match[1])) return false; } return true; @@ -878,7 +878,7 @@ export default definePlugin({ if (!s.enableStickerBypass) break stickerBypass; - const sticker = StickerStore.getStickerById(extra.stickers?.[0]!); + const sticker = StickersStore.getStickerById(extra.stickers?.[0]!); if (!sticker) break stickerBypass; diff --git a/src/plugins/lastfm/index.tsx b/src/plugins/lastfm/index.tsx index 5076fc5e6..35667cb66 100644 --- a/src/plugins/lastfm/index.tsx +++ b/src/plugins/lastfm/index.tsx @@ -21,7 +21,7 @@ import { Link } from "@components/Link"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; -import { findByProps } from "@webpack"; +import { findStore } from "@webpack"; import { ApplicationAssetUtils, FluxDispatcher, Forms } from "@webpack/common"; interface ActivityAssets { @@ -86,7 +86,7 @@ const placeholderId = "2a96cbd8b46e442fc41c2b86b821562f"; const logger = new Logger("LastFMRichPresence"); -const presenceStore = findByProps("getLocalPresence"); +const SelfPresenceStore = findStore("SelfPresenceStore"); async function getApplicationAsset(key: string): Promise { return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0]; @@ -275,7 +275,7 @@ export default definePlugin({ async getActivity(): Promise { if (settings.store.hideWithSpotify) { - for (const activity of presenceStore.getActivities()) { + for (const activity of SelfPresenceStore.getActivities()) { if (activity.type === ActivityType.LISTENING && activity.application_id !== applicationId) { // there is already music status because of Spotify or richerCider (probably more) return null; diff --git a/src/plugins/messageClickActions/index.ts b/src/plugins/messageClickActions/index.ts index 61bf79029..832c0f09d 100644 --- a/src/plugins/messageClickActions/index.ts +++ b/src/plugins/messageClickActions/index.ts @@ -20,11 +20,11 @@ import { addClickListener, removeClickListener } from "@api/MessageEvents"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByProps } from "@webpack"; +import { findByProps, findStore } from "@webpack"; import { FluxDispatcher, PermissionsBits, PermissionStore, UserStore } from "@webpack/common"; const MessageActions = findByProps("deleteMessage", "startEditMessage"); -const EditStore = findByProps("isEditing", "isEditingAny"); +const EditMessageStore = findStore("EditMessageStore"); let isDeletePressed = false; const keydown = (e: KeyboardEvent) => e.key === "Backspace" && (isDeletePressed = true); @@ -74,7 +74,7 @@ export default definePlugin({ if (msg.deleted === true) return; if (isMe) { - if (!settings.store.enableDoubleClickToEdit || EditStore.isEditing(channel.id, msg.id)) return; + if (!settings.store.enableDoubleClickToEdit || EditMessageStore.isEditing(channel.id, msg.id)) return; MessageActions.startEditMessage(channel.id, msg.id, msg.content); event.preventDefault(); diff --git a/src/plugins/noBlockedMessages/index.ts b/src/plugins/noBlockedMessages/index.ts index 8a6ec9de3..16863f7d4 100644 --- a/src/plugins/noBlockedMessages/index.ts +++ b/src/plugins/noBlockedMessages/index.ts @@ -21,9 +21,9 @@ import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { findByProps } from "@webpack"; -import { Message } from "discord-types/general"; +import { RelationshipStore } from "@webpack/common"; -const RelationshipStore = findByProps("getRelationships", "isBlocked"); +import { Message } from "discord-types/general"; const settings = definePluginSettings({ ignoreBlockedMessages: { diff --git a/src/plugins/noPendingCount/index.ts b/src/plugins/noPendingCount/index.ts index e4afddccf..6f6dfa865 100644 --- a/src/plugins/noPendingCount/index.ts +++ b/src/plugins/noPendingCount/index.ts @@ -19,9 +19,9 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByProps } from "@webpack"; +import { findStore } from "@webpack"; -const MessageRequestStore = findByProps("getMessageRequestsCount"); +const MessageRequestStore = findStore("MessageRequestStore"); const settings = definePluginSettings({ hideFriendRequestsCount: { diff --git a/src/plugins/petpet/index.ts b/src/plugins/petpet/index.ts index 5b7d12cd3..3d726caec 100644 --- a/src/plugins/petpet/index.ts +++ b/src/plugins/petpet/index.ts @@ -20,7 +20,7 @@ import { ApplicationCommandInputType, ApplicationCommandOptionType, Argument, Co import { Devs } from "@utils/constants"; import { makeLazy } from "@utils/lazy"; import definePlugin from "@utils/types"; -import { findByProps } from "@webpack"; +import { findStore } from "@webpack"; import { DraftType, UploadHandler, UploadManager, UserUtils } from "@webpack/common"; import { applyPalette, GIFEncoder, quantize } from "gifenc"; @@ -35,7 +35,7 @@ const getFrames = makeLazy(() => Promise.all( )) ); -const UploadStore = findByProps("getUploads"); +const UploadAttachmentStore = findStore("UploadAttachmentStore"); function loadImage(source: File | string) { const isFile = source instanceof File; @@ -58,7 +58,7 @@ async function resolveImage(options: Argument[], ctx: CommandContext, noServerPf for (const opt of options) { switch (opt.name) { case "image": - const upload = UploadStore.getUpload(ctx.channel.id, opt.name, DraftType.SlashCommand); + const upload = UploadAttachmentStore.getUpload(ctx.channel.id, opt.name, DraftType.SlashCommand); if (upload) { if (!upload.isImage) { UploadManager.clearAll(ctx.channel.id, DraftType.SlashCommand); diff --git a/src/plugins/previewMessage/index.tsx b/src/plugins/previewMessage/index.tsx index 132a8fde0..6c438caf1 100644 --- a/src/plugins/previewMessage/index.tsx +++ b/src/plugins/previewMessage/index.tsx @@ -20,15 +20,14 @@ import { addChatBarButton, ChatBarButton, removeChatBarButton } from "@api/ChatB import { generateId, sendBotMessage } from "@api/Commands"; import { Devs } from "@utils/constants"; import definePlugin, { StartAt } from "@utils/types"; -import { findByProps } from "@webpack"; +import { findStore } from "@webpack"; import { DraftStore, DraftType, SelectedChannelStore, UserStore, useStateFromStores } from "@webpack/common"; import { MessageAttachment } from "discord-types/general"; -const UploadStore = findByProps("getUploads"); +const UploadAttachmentStore = findStore("UploadAttachmentStore"); const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.ChannelMessage); - const getImageBox = (url: string): Promise<{ width: number, height: number; } | null> => new Promise(res => { const img = new Image(); @@ -44,7 +43,7 @@ const getImageBox = (url: string): Promise<{ width: number, height: number; } | const getAttachments = async (channelId: string) => await Promise.all( - UploadStore.getUploads(channelId, DraftType.ChannelMessage) + UploadAttachmentStore.getUploads(channelId, DraftType.ChannelMessage) .map(async (upload: any) => { const { isImage, filename, spoiler, item: { file } } = upload; const url = URL.createObjectURL(file); @@ -79,7 +78,7 @@ const PreviewButton: ChatBarButton = ({ isMainChat, isEmpty, type: { attachments if (!isMainChat) return null; - const hasAttachments = attachments && UploadStore.getUploads(channelId, DraftType.ChannelMessage).length > 0; + const hasAttachments = attachments && UploadAttachmentStore.getUploads(channelId, DraftType.ChannelMessage).length > 0; const hasContent = !isEmpty && draft?.length > 0; if (!hasContent && !hasAttachments) return null; diff --git a/src/plugins/quickReply/index.ts b/src/plugins/quickReply/index.ts index a6b6d1dc3..e93349a70 100644 --- a/src/plugins/quickReply/index.ts +++ b/src/plugins/quickReply/index.ts @@ -20,11 +20,10 @@ import { definePluginSettings, Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByProps } from "@webpack"; -import { ChannelStore, FluxDispatcher as Dispatcher, MessageStore, PermissionsBits, PermissionStore, SelectedChannelStore, UserStore } from "@webpack/common"; +import { ChannelStore, FluxDispatcher as Dispatcher, MessageStore, PermissionsBits, PermissionStore, RelationshipStore, SelectedChannelStore, UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; const Kangaroo = findByProps("jumpToMessage"); -const RelationshipStore = findByProps("getRelationships", "isBlocked"); const isMac = navigator.platform.includes("Mac"); // bruh let replyIdx = -1; diff --git a/src/plugins/reviewDB/auth.tsx b/src/plugins/reviewDB/auth.tsx index 6edc1c4b1..4cacf279e 100644 --- a/src/plugins/reviewDB/auth.tsx +++ b/src/plugins/reviewDB/auth.tsx @@ -8,14 +8,12 @@ import { DataStore } from "@api/index"; import { Logger } from "@utils/Logger"; import { openModal } from "@utils/modal"; import { findExportedComponent } from "@webpack"; -import { showToast, Toasts, UserStore } from "@webpack/common"; +import { OAuth2AuthorizeModal, showToast, Toasts, UserStore } from "@webpack/common"; import { ReviewDBAuth } from "./entities"; const DATA_STORE_KEY = "rdb-auth"; -const OAuth2AuthorizeModal = findExportedComponent("OAuth2AuthorizeModal"); - export let Auth: ReviewDBAuth = {}; export async function initAuth() { diff --git a/src/plugins/seeSummaries/index.tsx b/src/plugins/seeSummaries/index.tsx index a08393194..bba66bd1f 100644 --- a/src/plugins/seeSummaries/index.tsx +++ b/src/plugins/seeSummaries/index.tsx @@ -8,10 +8,10 @@ import { DataStore } from "@api/index"; import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByCode, findByProps } from "@webpack"; +import { findByCode, findStore } from "@webpack"; import { ChannelStore, GuildStore } from "@webpack/common"; -const SummaryStore = findByProps("allSummaries", "findSummary"); +const SummaryStore = findStore("SummaryStore"); const createSummaryFromServer = findByCode(".people)),startId:", ".type}"); const settings = definePluginSettings({ diff --git a/src/plugins/spotifyControls/SpotifyStore.ts b/src/plugins/spotifyControls/SpotifyStore.ts index a148d73f3..8ee9724f2 100644 --- a/src/plugins/spotifyControls/SpotifyStore.ts +++ b/src/plugins/spotifyControls/SpotifyStore.ts @@ -20,8 +20,7 @@ import { proxyLazy } from "@utils/lazy"; import { findByProps, webpackDependantLazy } from "@webpack"; import { Flux, FluxDispatcher } from "@webpack/common"; -// Avoid circular dependency -const SpotifyControls = proxyLazy(() => require(".")) as typeof import("."); +import { settings } from "."; export interface Track { id: string; @@ -91,7 +90,7 @@ export const SpotifyStore = webpackDependantLazy(() => { public isSettingPosition = false; public openExternal(path: string) { - const url = SpotifyControls.settings.store.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp") + const url = settings.store.useSpotifyUris || Vencord.Plugins.isPluginEnabled("OpenInApp") ? "spotify:" + path.replaceAll("/", (_, idx) => idx === 0 ? "" : ":") : "https://open.spotify.com" + path; diff --git a/src/plugins/spotifyShareCommands/index.ts b/src/plugins/spotifyShareCommands/index.ts index bdb7dfa7f..c263a0145 100644 --- a/src/plugins/spotifyShareCommands/index.ts +++ b/src/plugins/spotifyShareCommands/index.ts @@ -19,7 +19,7 @@ import { ApplicationCommandInputType, sendBotMessage } from "@api/Commands"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByProps } from "@webpack"; +import { findStore } from "@webpack"; import { FluxDispatcher, MessageActions } from "@webpack/common"; interface Album { @@ -52,8 +52,8 @@ interface Track { name: string; } -const Spotify = findByProps("getPlayerState"); -const PendingReplyStore = findByProps("getPendingReply"); +const SpotifyStore = findStore("SpotifyStore"); +const PendingReplyStore = findStore("PendingReplyStore"); function sendMessage(channelId, message) { message = { @@ -84,7 +84,7 @@ export default definePlugin({ inputType: ApplicationCommandInputType.BUILT_IN, options: [], execute: (_, ctx) => { - const track: Track | null = Spotify.getTrack(); + const track: Track | null = SpotifyStore.getTrack(); if (track === null) { sendBotMessage(ctx.channel.id, { content: "You're not listening to any music." @@ -103,7 +103,7 @@ export default definePlugin({ inputType: ApplicationCommandInputType.BUILT_IN, options: [], execute: (_, ctx) => { - const track: Track | null = Spotify.getTrack(); + const track: Track | null = SpotifyStore.getTrack(); if (track === null) { sendBotMessage(ctx.channel.id, { content: "You're not listening to any music." @@ -121,7 +121,7 @@ export default definePlugin({ inputType: ApplicationCommandInputType.BUILT_IN, options: [], execute: (_, ctx) => { - const track: Track | null = Spotify.getTrack(); + const track: Track | null = SpotifyStore.getTrack(); if (track === null) { sendBotMessage(ctx.channel.id, { content: "You're not listening to any music." diff --git a/src/plugins/vcNarrator/index.tsx b/src/plugins/vcNarrator/index.tsx index 46a86aee6..59c13b722 100644 --- a/src/plugins/vcNarrator/index.tsx +++ b/src/plugins/vcNarrator/index.tsx @@ -24,7 +24,7 @@ import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { wordsToTitle } from "@utils/text"; import definePlugin, { OptionType, ReporterTestable } from "@utils/types"; -import { findByProps } from "@webpack"; +import { findStore } from "@webpack"; import { Button, ChannelStore, Forms, GuildMemberStore, SelectedChannelStore, SelectedGuildStore, useMemo, UserStore } from "@webpack/common"; interface VoiceState { @@ -37,7 +37,7 @@ interface VoiceState { selfMute: boolean; } -const VoiceStateStore = findByProps("getVoiceStatesForChannel", "getCurrentClientVoiceChannelId"); +const VoiceStateStore = findStore("VoiceStateStore"); // Mute/Deaf for other people than you is commented out, because otherwise someone can spam it and it will be annoying // Filtering out events is not as simple as just dropping duplicates, as otherwise mute, unmute, mute would diff --git a/src/webpack/api.tsx b/src/webpack/api.tsx index 62591e6f5..43855bfee 100644 --- a/src/webpack/api.tsx +++ b/src/webpack/api.tsx @@ -113,7 +113,7 @@ export const filters = { return filter; }, - byComponentCode: (...code: CodeFilter): FilterFn => { + componentByCode: (...code: CodeFilter): FilterFn => { const byCodeFilter = filters.byCode(...code); const filter: FilterFn = m => { let inner = m; @@ -129,7 +129,7 @@ export const filters = { return false; }; - filter.$$vencordProps = ["byComponentCode", ...code]; + filter.$$vencordProps = ["componentByCode", ...code]; filter.$$vencordIsComponentFilter = true; return filter; }, @@ -232,7 +232,7 @@ export function waitFor(filter: FilterFn, callback: ModCallbackFn, { isIndirect * * @param filter A function that takes an export or module exports and returns a boolean * @param parse A function that takes the find result as its first argument and returns something to use as the proxy inner value. Useful if you want to use a value from the find result, instead of all of it. Defaults to the find result itself - * @returns A proxy that has the parse function return value as its true value, or the plain parse function return value if it was called immediately. + * @returns A proxy that has the parse function return value as its true value, or the plain parse function return value, if it was called immediately. */ export function find(filter: FilterFn, parse: (module: ModuleExports) => ModuleExports = m => m, { isIndirect = false }: { isIndirect?: boolean; } = {}) { if (typeof filter !== "function") @@ -306,7 +306,7 @@ export function findExportedComponent(...props: PropsFil } /** - * Find the first component in an export that includes all the given code. + * Find the first exported component which when its code is stringified includes all the given code. * * @example findComponentByCode(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR") * @example findComponentByCode(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)", ColorPicker => React.memo(ColorPicker)) @@ -319,7 +319,7 @@ export function findComponentByCode(...code: CodeFilter const parse = (typeof code.at(-1) === "function" ? code.pop() : m => m) as (component: ModuleExports) => LazyComponentType; const newCode = code as CodeFilter; - const ComponentResult = findComponent(filters.byComponentCode(...newCode), parse, { isIndirect: true }); + const ComponentResult = findComponent(filters.componentByCode(...newCode), parse, { isIndirect: true }); if (IS_REPORTER) { webpackSearchHistory.push(["findComponentByCode", [ComponentResult, ...newCode]]); @@ -369,7 +369,7 @@ export function findByPropsAndExtract(...props: PropsFilter | [...Props } /** - * Find the first export that includes all the given code. + * Find the first exported function which when stringified includes all the given code. * * @param code A list of code to search each export for * @param parse A function that takes the find result as its first argument and returns something. Useful if you want to use a value from the find result, instead of all of it. Defaults to the find result itself @@ -403,7 +403,7 @@ export function findStore(name: StoreNameFilter) { } /** - * Find the module exports of the first module which the factory includes all the given code. + * Find the module exports of the first module which the factory when stringified includes all the given code. * * @param code A list of code to search each factory for * @param parse A function that takes the find result as its first argument and returns something. Useful if you want to use a value from the find result, instead of all of it. Defaults to the find result itself @@ -422,7 +422,7 @@ export function findByFactoryCode(...code: CodeFilter | [...CodeFilter, } /** - * Find the module exports of the first module which the factory includes all the given code, + * Find the module exports of the first module which the factory when stringified includes all the given code, * then map them into an easily usable object via the specified mappers. * * IMPORTANT: You can destructure the properties of the returned object at top level as long as the property filter does not return a primitive value export. @@ -465,6 +465,8 @@ export function mapMangledModule(code: string | RegExp | waitFor(factoryFilter, exports => { callbackCalled = true; + if (typeof exports !== "object") return; + for (const exportKey in exports) { const exportValue = exports[exportKey]; if (exportValue == null) continue; @@ -507,7 +509,7 @@ export function mapMangledModule(code: string | RegExp | } /** - * Find the first module factory that includes all the given code. + * Find the first module factory which when stringified includes all the given code. */ export function findModuleFactory(...code: CodeFilter) { const filter = filters.byFactoryCode(...code); diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index bd2fc4640..c792294e4 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -120,7 +120,7 @@ export const UserUtils: t.UserUtils = { export const UploadManager = findByProps("clearAll", "addFile"); export const UploadHandler: t.UploadHandler = { - promptToUpload: findByCode(".ATTACHMENT_TOO_MANY_ERROR_TITLE,") as (files: File[], channel: Channel, draftType: Number) => void + promptToUpload: findByCode(".ATTACHMENT_TOO_MANY_ERROR_TITLE,") }; export const ApplicationAssetUtils = findByProps("fetchAssetIds", "getAssetImage"); diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index fa6213e3d..b50108db7 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -50,7 +50,7 @@ define(Function.prototype, "m", { // We may also catch Discord bundled libs, React Devtools or other extensions WebpackInstance here. // This ensures we actually got the right ones const { stack } = new Error(); - if (!(stack?.includes("discord.com") || stack?.includes("discordapp.com")) || (stack != null ? /at \d+? \(/.test(stack) : true) || !String(this).includes("exports:{}")) { + if (!stack?.includes("/assets/") || stack?.match(/at \d+? \(/) || !String(this).includes("exports:{}")) { return; } @@ -68,7 +68,7 @@ define(Function.prototype, "m", { define(this, "p", { value: bundlePath }); clearTimeout(setterTimeout); - if (window.GLOBAL_ENV?.PUBLIC_PATH != null && bundlePath !== window.GLOBAL_ENV.PUBLIC_PATH) return; + if (bundlePath !== "/assets/") return; logger.info("Main Webpack found" + interpolateIfDefined` in ${fileName}` + ", initializing internal references to WebpackRequire"); _initWebpack(this); @@ -117,7 +117,7 @@ const moduleFactoriesHandler: ProxyHandler = { // Same thing as get has: (target, p) => { return false; - } + }, */ // The set trap for patching or defining getters for the module factories when new module factories are loaded @@ -207,12 +207,12 @@ function defineModulesFactoryGetter(id: PropertyKey, factory: WrappedModuleFacto return (factory = wrapAndPatchFactory(id, factory)); }, - set(v: AnyModuleFactory) { + set(newFactory: AnyModuleFactory) { if (factory.$$vencordOriginal != null) { - factory.toString = v.toString.bind(v); - factory.$$vencordOriginal = v; + factory.toString = newFactory.toString.bind(v); + factory.$$vencordOriginal = newFactory; } else { - factory = v; + factory = newFactory; } } }); @@ -229,141 +229,139 @@ function defineModulesFactoryGetter(id: PropertyKey, factory: WrappedModuleFacto function wrapAndPatchFactory(id: PropertyKey, originalFactory: AnyModuleFactory) { const patchedFactory = patchFactory(id, originalFactory); - // The patched factory wrapper, define it in an object to preserve the name after minification - const wrappedFactory: WrappedModuleFactory = { - PatchedFactory(...args: Parameters) { - // Restore the original factory in all the module factories objects. We want to make sure the original factory is restored properly, no matter what is the Webpack instance - for (const wreq of allWebpackInstances) { - define(wreq.m, id, { value: wrappedFactory.$$vencordOriginal }); - } + const wrappedFactory: WrappedModuleFactory = function (...args) { + // Restore the original factory in all the module factories objects. We want to make sure the original factory is restored properly, no matter what is the Webpack instance + for (const wreq of allWebpackInstances) { + define(wreq.m, id, { value: wrappedFactory.$$vencordOriginal }); + } - // eslint-disable-next-line prefer-const - let [module, exports, require] = args; + // eslint-disable-next-line prefer-const + let [module, exports, require] = args; - if (wreq == null) { - if (!wreqFallbackApplied) { - wreqFallbackApplied = true; + if (wreq == null) { + if (!wreqFallbackApplied) { + wreqFallbackApplied = true; - // Make sure the require argument is actually the WebpackRequire function - if (typeof require === "function" && require.m != null) { - const { stack } = new Error(); - const webpackInstanceFileName = stack?.match(/\/assets\/(.+?\.js)/)?.[1]; - logger.warn( - "WebpackRequire was not initialized, falling back to WebpackRequire passed to the first called patched module factory (" + - `id: ${String(id)}` + interpolateIfDefined`, WebpackInstance origin: ${webpackInstanceFileName}` + - ")" - ); - _initWebpack(require as WebpackRequire); - } else if (IS_DEV) { - logger.error("WebpackRequire was not initialized, running modules without patches instead."); - } - } + // Make sure the require argument is actually the WebpackRequire function + if (typeof require === "function" && require.m != null) { + const { stack } = new Error(); + const webpackInstanceFileName = stack?.match(/\/assets\/(.+?\.js)/)?.[1]; - if (IS_DEV) { + logger.warn( + "WebpackRequire was not initialized, falling back to WebpackRequire passed to the first called patched module factory (" + + `id: ${String(id)}` + interpolateIfDefined`, WebpackInstance origin: ${webpackInstanceFileName}` + + ")" + ); + + _initWebpack(require as WebpackRequire); + } else if (IS_DEV) { + logger.error("WebpackRequire was not initialized, running modules without patches instead."); return wrappedFactory.$$vencordOriginal!.apply(this, args); } - } - - let factoryReturn: unknown; - try { - // Call the patched factory - factoryReturn = patchedFactory.apply(this, args); - } catch (err) { - // Just re-throw Discord errors - if (patchedFactory === originalFactory) { - throw err; - } - - logger.error("Error in patched module factory:\n", err); + } else if (IS_DEV) { return wrappedFactory.$$vencordOriginal!.apply(this, args); } + } - exports = module.exports; - if (exports == null) return; + let factoryReturn: unknown; + try { + // Call the patched factory + factoryReturn = patchedFactory.apply(this, args); + } catch (err) { + // Just re-throw Discord errors + if (patchedFactory === originalFactory) { + throw err; + } - // There are (at the time of writing) 11 modules exporting the window - // Make these non enumerable to improve webpack search performance - if (typeof require === "function" && require.c != null) { - let foundWindow = false; + logger.error("Error in patched module factory:\n", err); + return wrappedFactory.$$vencordOriginal!.apply(this, args); + } - if (exports === window) { + exports = module.exports; + if (exports == null) return; + + // There are (at the time of writing) 11 modules exporting the window + // Make these non enumerable to improve webpack search performance + if (typeof require === "function" && require.c != null) { + let foundWindow = false; + + if (exports === window) { + foundWindow = true; + } else if (typeof exports === "object") { + if (exports.default === window) { foundWindow = true; - } else if (typeof exports === "object") { - if (exports.default === window) { - foundWindow = true; - } else { - for (const exportKey in exports) if (exportKey.length <= 3) { - if (exports[exportKey] === window) { - foundWindow = true; - } + } else { + for (const exportKey in exports) if (exportKey.length <= 3) { + if (exports[exportKey] === window) { + foundWindow = true; } } } - - if (foundWindow) { - Object.defineProperty(require.c, id, { - value: require.c[id], - enumerable: false, - configurable: true, - writable: true - }); - - return factoryReturn; - } } - for (const callback of moduleListeners) { - try { - callback(exports, { id, factory: wrappedFactory.$$vencordOriginal! }); - } catch (err) { - logger.error("Error in Webpack module listener:\n", err, callback); - } + if (foundWindow) { + Object.defineProperty(require.c, id, { + value: require.c[id], + enumerable: false, + configurable: true, + writable: true + }); + + return factoryReturn; } + } - for (const [filter, callback] of waitForSubscriptions) { - try { - if (filter.$$vencordIsFactoryFilter) { - if (filter(wrappedFactory.$$vencordOriginal!)) { - waitForSubscriptions.delete(filter); - callback(exports, { id, exportKey: null, factory: wrappedFactory.$$vencordOriginal! }); - } + for (const callback of moduleListeners) { + try { + callback(exports, { id, factory: wrappedFactory.$$vencordOriginal! }); + } catch (err) { + logger.error("Error in Webpack module listener:\n", err, callback); + } + } - continue; - } - - if (filter(exports)) { + for (const [filter, callback] of waitForSubscriptions) { + try { + if (filter.$$vencordIsFactoryFilter) { + if (filter(wrappedFactory.$$vencordOriginal!)) { waitForSubscriptions.delete(filter); callback(exports, { id, exportKey: null, factory: wrappedFactory.$$vencordOriginal! }); - continue; } - if (typeof exports !== "object") { - continue; - } - - if (exports.default != null && filter(exports.default)) { - waitForSubscriptions.delete(filter); - callback(exports.default, { id, exportKey: "default", factory: wrappedFactory.$$vencordOriginal! }); - continue; - } - - for (const exportKey in exports) if (exportKey.length <= 3) { - const exportValue = exports[exportKey]; - - if (exportValue != null && filter(exportValue)) { - waitForSubscriptions.delete(filter); - callback(exportValue, { id, exportKey, factory: wrappedFactory.$$vencordOriginal! }); - break; - } - } - } catch (err) { - logger.error("Error while firing callback for Webpack waitFor subscription:\n", err, filter, callback); + continue; } - } - return factoryReturn; + if (filter(exports)) { + waitForSubscriptions.delete(filter); + callback(exports, { id, exportKey: null, factory: wrappedFactory.$$vencordOriginal! }); + continue; + } + + if (typeof exports !== "object") { + continue; + } + + if (exports.default != null && filter(exports.default)) { + waitForSubscriptions.delete(filter); + callback(exports.default, { id, exportKey: "default", factory: wrappedFactory.$$vencordOriginal! }); + continue; + } + + for (const exportKey in exports) if (exportKey.length <= 3) { + const exportValue = exports[exportKey]; + + if (exportValue != null && filter(exportValue)) { + waitForSubscriptions.delete(filter); + callback(exportValue, { id, exportKey, factory: wrappedFactory.$$vencordOriginal! }); + break; + } + } + } catch (err) { + logger.error("Error while firing callback for Webpack waitFor subscription:\n", err, filter, callback); + } } - }.PatchedFactory; + + return factoryReturn; + }; wrappedFactory.toString = originalFactory.toString.bind(originalFactory); wrappedFactory.$$vencordOriginal = originalFactory;