From 75fa0ff708f343e78642b16e31a0ef71f62ec3ec Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 2 May 2024 23:18:12 -0300 Subject: [PATCH 001/361] Immediate finds --- scripts/generateReport.ts | 57 +- src/api/ChatButtons.tsx | 5 +- src/api/Commands/commandHelpers.ts | 4 +- src/api/Notices.ts | 5 +- src/components/CodeBlock.tsx | 4 +- src/components/PluginSettings/PluginModal.tsx | 6 +- src/components/PluginSettings/index.tsx | 6 +- src/components/Switch.tsx | 4 +- src/components/VencordSettings/ThemesTab.tsx | 13 +- src/plugins/anonymiseFileNames/index.tsx | 6 +- src/plugins/arRPC.web/index.tsx | 4 +- src/plugins/betterFolders/FolderSideBar.tsx | 8 +- src/plugins/betterFolders/index.tsx | 10 +- src/plugins/betterNotes/index.tsx | 4 +- src/plugins/betterRoleContext/index.tsx | 4 +- src/plugins/betterSessions/index.tsx | 12 +- src/plugins/betterSettings/index.tsx | 4 +- .../biggerStreamPreview/webpack/stores.ts | 6 +- src/plugins/clientTheme/index.tsx | 10 +- src/plugins/consoleShortcuts/index.ts | 12 +- src/plugins/crashHandler/index.ts | 21 +- src/plugins/customRPC/index.tsx | 8 +- src/plugins/decor/index.tsx | 4 +- .../decor/ui/components/DecorSection.tsx | 4 +- .../decor/ui/components/SectionedGridList.tsx | 4 +- src/plugins/decor/ui/components/index.ts | 5 +- src/plugins/decor/ui/index.ts | 4 +- .../decor/ui/modals/ChangeDecorationModal.tsx | 4 +- .../decor/ui/modals/CreateDecorationModal.tsx | 6 +- src/plugins/devCompanion.dev/index.tsx | 12 +- src/plugins/emoteCloner/index.tsx | 6 +- src/plugins/experiments/index.tsx | 4 +- src/plugins/fakeNitro/index.tsx | 14 +- src/plugins/favGifSearch/index.tsx | 6 +- src/plugins/friendInvites/index.ts | 6 +- src/plugins/friendsSince/index.tsx | 12 +- src/plugins/gameActivityToggle/index.tsx | 4 +- src/plugins/gifPaste/index.ts | 4 +- src/plugins/greetStickerPicker/index.tsx | 4 +- src/plugins/ignoreActivities/index.tsx | 4 +- .../imageZoom/components/Magnifier.tsx | 2 +- src/plugins/implicitRelationships/index.ts | 4 +- src/plugins/lastfm/index.tsx | 4 +- src/plugins/memberCount/index.tsx | 6 +- src/plugins/messageClickActions/index.ts | 6 +- src/plugins/messageLinkEmbeds/index.tsx | 12 +- src/plugins/messageLogger/index.tsx | 4 +- src/plugins/moreUserTags/index.tsx | 6 +- src/plugins/mutualGroupDMs/index.tsx | 10 +- src/plugins/newGuildSettings/index.tsx | 10 +- src/plugins/noBlockedMessages/index.ts | 4 +- src/plugins/noPendingCount/index.ts | 4 +- src/plugins/pauseInvitesForever/index.tsx | 6 +- .../components/UserPermissions.tsx | 15 +- src/plugins/petpet/index.ts | 4 +- .../pinDms/components/CreateCategoryModal.tsx | 6 +- src/plugins/pinDms/index.tsx | 6 +- src/plugins/pinDms/settings.ts | 94 +++ src/plugins/platformIndicators/index.tsx | 6 +- src/plugins/previewMessage/index.tsx | 4 +- .../components/PronounsChatComponent.tsx | 4 +- src/plugins/quickReply/index.ts | 4 +- src/plugins/resurrectHome/index.tsx | 4 +- src/plugins/revealAllSpoilers/index.ts | 6 +- src/plugins/reviewDB/auth.tsx | 4 +- .../reviewDB/components/MessageButton.tsx | 4 +- .../reviewDB/components/ReviewComponent.tsx | 274 ++++---- .../reviewDB/components/ReviewsView.tsx | 10 +- src/plugins/searchReply/index.tsx | 4 +- .../serverProfile/GuildProfileModal.tsx | 6 +- .../previewExample.tsx | 2 +- src/plugins/showConnections/VerifiedIcon.tsx | 6 +- src/plugins/showConnections/index.tsx | 12 +- .../components/HiddenChannelLockScreen.tsx | 14 +- src/plugins/showHiddenChannels/index.tsx | 4 +- src/plugins/spotifyControls/SpotifyStore.ts | 10 +- src/plugins/spotifyShareCommands/index.ts | 6 +- .../startupTimings/StartupTimingPage.tsx | 4 +- src/plugins/typingIndicator/index.tsx | 10 +- .../components/VoiceChannelSection.tsx | 6 +- src/plugins/userVoiceShow/index.tsx | 4 +- src/plugins/vcNarrator/index.tsx | 4 +- src/plugins/vencordToolbox/index.tsx | 4 +- src/plugins/voiceMessages/VoicePreview.tsx | 4 +- src/plugins/voiceMessages/index.tsx | 8 +- src/plugins/webContextMenus.web/index.ts | 4 +- src/plugins/webKeybinds.web/index.ts | 4 +- src/plugins/whoReacted/index.tsx | 7 +- src/plugins/xsOverlay.desktop/index.ts | 4 +- src/utils/discord.tsx | 4 +- src/utils/index.ts | 1 + src/utils/lazy.ts | 138 ++-- src/utils/lazyReact.tsx | 18 +- src/utils/modal.tsx | 31 +- src/utils/proxyInner.ts | 91 +++ src/webpack/common/classes.ts | 6 +- src/webpack/common/components.ts | 15 +- src/webpack/common/internal.tsx | 44 -- src/webpack/common/menu.ts | 8 +- src/webpack/common/react.ts | 6 +- src/webpack/common/settingsStores.ts | 8 +- src/webpack/common/stores.ts | 58 +- src/webpack/common/types/components.d.ts | 10 +- src/webpack/common/utils.ts | 65 +- src/webpack/patchWebpack.ts | 12 +- src/webpack/webpack.ts | 535 --------------- src/webpack/webpack.tsx | 609 ++++++++++++++++++ 107 files changed, 1400 insertions(+), 1229 deletions(-) create mode 100644 src/plugins/pinDms/settings.ts create mode 100644 src/utils/proxyInner.ts delete mode 100644 src/webpack/common/internal.tsx delete mode 100644 src/webpack/webpack.ts create mode 100644 src/webpack/webpack.tsx diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 912f38eda..8108e5436 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -400,7 +400,7 @@ async function runtime(token: string) { } Vencord.Webpack.waitFor( - "loginToken", + Vencord.Webpack.filters.byProps("loginToken"), m => { console.log("[PUP_DEBUG]", "Logging in with token..."); m.loginToken(token); @@ -471,39 +471,62 @@ async function runtime(token: string) { } } - for (const [searchType, args] of Vencord.Webpack.lazyWebpackSearchHistory) { - let method = searchType; + for (const [searchType, args] of [...Vencord.Webpack.webpackSearchHistory]) { + let method = searchType as string; - if (searchType === "findComponent") method = "find"; - if (searchType === "findExportedComponent") method = "findByProps"; - if (searchType === "waitFor" || searchType === "waitForComponent") { - if (typeof args[0] === "string") method = "findByProps"; - else method = "find"; - } - if (searchType === "waitForStore") method = "findStore"; + if (searchType === "waitFor") method = "cacheFind"; try { let result: any; - if (method === "proxyLazyWebpack" || method === "LazyComponentWebpack") { + if (method === "webpackDependantLazy" || method === "webpackDependantLazyComponent") { const [factory] = args; result = factory(); + if (result != null && "$$vencordGetter" in result) result = result.$$vencordGetter(); } else if (method === "extractAndLoadChunks") { const [code, matcher] = args; const module = Vencord.Webpack.findModuleFactory(...code); - if (module) result = module.toString().match(canonicalizeMatch(matcher)); + if (module) result = module.toString().match(Vencord.Util.canonicalizeMatch(matcher)); } else { - // @ts-ignore result = Vencord.Webpack[method](...args); + + // If the result is our Proxy or ComponentWrapper, this means the search failed + if (result != null && result[Vencord.Util.proxyInnerGet] != null) result = undefined; + if (result != null && "$$vencordGetter" in result) result = undefined; } - if (result == null || ("$$vencordInternal" in result && result.$$vencordInternal() == null)) throw "a rock at ben shapiro"; + if (result == null) throw "find failed"; } catch (e) { let logMessage = searchType; - if (method === "find" || method === "proxyLazyWebpack" || method === "LazyComponentWebpack") logMessage += `(${args[0].toString().slice(0, 147)}...)`; - else if (method === "extractAndLoadChunks") logMessage += `([${args[0].map(arg => `"${arg}"`).join(", ")}], ${args[1].toString()})`; - else logMessage += `(${args.map(arg => `"${arg}"`).join(", ")})`; + + let filterName = ""; + let parsedArgs = args; + if ("$$vencordProps" in args[0]) { + if ( + searchType === "find" || + searchType === "findComponent" || + searchType === "waitFor" + ) { + filterName = args[0].$$vencordProps[0]; + } + + parsedArgs = args[0].$$vencordProps.slice(1); + } + + if ( + parsedArgs === args && searchType === "waitFor" || + searchType === "find" || + searchType === "findComponent" || + searchType === "webpackDependantLazy" || + searchType === "webpackDependantLazyComponent" + ) { + logMessage += `(${parsedArgs[0].toString().slice(0, 147)}...)`; + } else if (searchType === "extractAndLoadChunks") { + logMessage += `([${parsedArgs[0].map((arg: any) => `"${arg}"`).join(", ")}], ${parsedArgs[1].toString()})`; + } else { + logMessage += `(${filterName.length ? `${filterName}(` : ""}${parsedArgs.map(arg => `"${arg}"`).join(", ")})${filterName.length ? ")" : ""}`; + } console.log("[PUP_WEBPACK_FIND_FAIL]", logMessage); } diff --git a/src/api/ChatButtons.tsx b/src/api/ChatButtons.tsx index fcb76fffc..b44ee29ad 100644 --- a/src/api/ChatButtons.tsx +++ b/src/api/ChatButtons.tsx @@ -8,13 +8,12 @@ import "./ChatButton.css"; import ErrorBoundary from "@components/ErrorBoundary"; import { Logger } from "@utils/Logger"; -import { waitFor } from "@webpack"; +import { findByProps } from "@webpack"; import { Button, ButtonLooks, ButtonWrapperClasses, Tooltip } from "@webpack/common"; import { Channel } from "discord-types/general"; import { HTMLProps, MouseEventHandler, ReactNode } from "react"; -let ChannelTextAreaClasses: Record<"button" | "buttonContainer", string>; -waitFor(["buttonContainer", "channelTextArea"], m => ChannelTextAreaClasses = m); +const ChannelTextAreaClasses = findByProps>("buttonContainer", "channelTextArea"); export interface ChatBarProps { channel: Channel; diff --git a/src/api/Commands/commandHelpers.ts b/src/api/Commands/commandHelpers.ts index dc5ecfd67..759bb0e3c 100644 --- a/src/api/Commands/commandHelpers.ts +++ b/src/api/Commands/commandHelpers.ts @@ -17,14 +17,14 @@ */ import { mergeDefaults } from "@utils/misc"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { MessageActions, SnowflakeUtils } from "@webpack/common"; import { Message } from "discord-types/general"; import type { PartialDeep } from "type-fest"; import { Argument } from "./types"; -const MessageCreator = findByPropsLazy("createBotMessage"); +const MessageCreator = findByProps("createBotMessage"); export function generateId() { return `-${SnowflakeUtils.fromTimestamp(Date.now())}`; diff --git a/src/api/Notices.ts b/src/api/Notices.ts index 6d20087a7..7652d55a6 100644 --- a/src/api/Notices.ts +++ b/src/api/Notices.ts @@ -16,10 +16,9 @@ * along with this program. If not, see . */ -import { waitFor } from "@webpack"; +import { find } from "@webpack"; -let NoticesModule: any; -waitFor(m => m.show && m.dismiss && !m.suppressAll, m => NoticesModule = m); +const NoticesModule = find(m => m.show && m.dismiss && !m.suppressAll, m => m); export const noticesQueue = [] as any[]; export let currentNotice: any = null; diff --git a/src/components/CodeBlock.tsx b/src/components/CodeBlock.tsx index 41c5ef0c1..03ec96fc1 100644 --- a/src/components/CodeBlock.tsx +++ b/src/components/CodeBlock.tsx @@ -4,10 +4,10 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Parser } from "@webpack/common"; -const CodeContainerClasses = findByPropsLazy("markup", "codeContainer"); +const CodeContainerClasses = findByProps("markup", "codeContainer"); /** * Renders code in a Discord codeblock diff --git a/src/components/PluginSettings/PluginModal.tsx b/src/components/PluginSettings/PluginModal.tsx index 34de43c2d..f62da7632 100644 --- a/src/components/PluginSettings/PluginModal.tsx +++ b/src/components/PluginSettings/PluginModal.tsx @@ -25,7 +25,7 @@ import { Margins } from "@utils/margins"; import { classes, isObjectEmpty } from "@utils/misc"; import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize } from "@utils/modal"; import { OptionType, Plugin } from "@utils/types"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByProps,findComponentByCode } from "@webpack"; import { Button, Clickable, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, UserUtils } from "@webpack/common"; import { User } from "discord-types/general"; import { Constructor } from "type-fest"; @@ -41,8 +41,8 @@ import { } from "./components"; import { openContributorModal } from "./ContributorModal"; -const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); -const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar"); +const UserSummaryItem = findComponentByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"); +const AvatarStyles = findByProps("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar"); const UserRecord: Constructor> = proxyLazy(() => UserStore.getCurrentUser().constructor) as any; interface PluginModalProps extends ModalProps { diff --git a/src/components/PluginSettings/index.tsx b/src/components/PluginSettings/index.tsx index 33a472c1a..eff1b4359 100644 --- a/src/components/PluginSettings/index.tsx +++ b/src/components/PluginSettings/index.tsx @@ -33,7 +33,7 @@ import { classes, isObjectEmpty } from "@utils/misc"; import { openModalLazy } from "@utils/modal"; import { useAwaiter } from "@utils/react"; import { Plugin } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Alerts, Button, Card, Forms, lodash, Parser, React, Select, Text, TextInput, Toasts, Tooltip } from "@webpack/common"; import Plugins from "~plugins"; @@ -44,8 +44,8 @@ import { startDependenciesRecursive, startPlugin, stopPlugin } from "../../plugi const cl = classNameFactory("vc-plugins-"); const logger = new Logger("PluginSettings", "#a6d189"); -const InputStyles = findByPropsLazy("inputDefault", "inputWrapper"); -const ButtonClasses = findByPropsLazy("button", "disabled", "enabled"); +const InputStyles = findByProps("inputDefault", "inputWrapper"); +const ButtonClasses = findByProps("button", "disabled", "enabled"); function showErrorToast(message: string) { diff --git a/src/components/Switch.tsx b/src/components/Switch.tsx index 10904e141..4e72054dd 100644 --- a/src/components/Switch.tsx +++ b/src/components/Switch.tsx @@ -19,7 +19,7 @@ import "./Switch.css"; import { classes } from "@utils/misc"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; interface SwitchProps { checked: boolean; @@ -29,7 +29,7 @@ interface SwitchProps { const SWITCH_ON = "var(--green-360)"; const SWITCH_OFF = "var(--primary-400)"; -const SwitchClasses = findByPropsLazy("slider", "input", "container"); +const SwitchClasses = findByProps("slider", "input", "container"); export function Switch({ checked, onChange, disabled }: SwitchProps) { return ( diff --git a/src/components/VencordSettings/ThemesTab.tsx b/src/components/VencordSettings/ThemesTab.tsx index 2eb91cb82..8c5943fcc 100644 --- a/src/components/VencordSettings/ThemesTab.tsx +++ b/src/components/VencordSettings/ThemesTab.tsx @@ -29,23 +29,22 @@ import { classes } from "@utils/misc"; import { openModal } from "@utils/modal"; import { showItemInFolder } from "@utils/native"; import { useAwaiter } from "@utils/react"; -import { findByPropsLazy, findLazy } from "@webpack"; +import { find, findComponent } from "@webpack"; import { Button, Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common"; -import type { ComponentType, Ref, SyntheticEvent } from "react"; +import type { Ref, SyntheticEvent } from "react"; import { AddonCard } from "./AddonCard"; import { SettingsTab, wrapTab } from "./shared"; -type FileInput = ComponentType<{ +type FileInputProps = { ref: Ref; onChange: (e: SyntheticEvent) => void; multiple?: boolean; filters?: { name?: string; extensions: string[]; }[]; -}>; +}; -const InviteActions = findByPropsLazy("resolveInvite"); -const FileInput: FileInput = findLazy(m => m.prototype?.activateUploadDialogue && m.prototype.setRef); -const TextAreaProps = findLazy(m => typeof m.textarea === "string"); +const FileInput = findComponent(m => m.prototype?.activateUploadDialogue && m.prototype.setRef); +const TextAreaProps = find(m => typeof m.textarea === "string"); const cl = classNameFactory("vc-settings-theme-"); diff --git a/src/plugins/anonymiseFileNames/index.tsx b/src/plugins/anonymiseFileNames/index.tsx index b424b7a59..de8cb0fb2 100644 --- a/src/plugins/anonymiseFileNames/index.tsx +++ b/src/plugins/anonymiseFileNames/index.tsx @@ -21,12 +21,12 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByCodeLazy, findByPropsLazy } from "@webpack"; +import { findByCode, findByProps } from "@webpack"; type AnonUpload = Upload & { anonymise?: boolean; }; -const ActionBarIcon = findByCodeLazy(".actionBarIcon)"); -const UploadDraft = findByPropsLazy("popFirstFile", "update"); +const ActionBarIcon = findByCode(".actionBarIcon)"); +const UploadDraft = findByProps("popFirstFile", "update"); const enum Methods { Random, diff --git a/src/plugins/arRPC.web/index.tsx b/src/plugins/arRPC.web/index.tsx index 423dce9b5..1a21e757f 100644 --- a/src/plugins/arRPC.web/index.tsx +++ b/src/plugins/arRPC.web/index.tsx @@ -20,10 +20,10 @@ import { popNotice, showNotice } from "@api/Notices"; import { Link } from "@components/Link"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { ApplicationAssetUtils, FluxDispatcher, Forms, Toasts } from "@webpack/common"; -const RpcUtils = findByPropsLazy("fetchApplicationsRPC", "getRemoteIconURL"); +const RpcUtils = findByProps("fetchApplicationsRPC", "getRemoteIconURL"); async function lookupAsset(applicationId: string, key: string): Promise { return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0]; diff --git a/src/plugins/betterFolders/FolderSideBar.tsx b/src/plugins/betterFolders/FolderSideBar.tsx index 53d24ed93..05f7833b0 100644 --- a/src/plugins/betterFolders/FolderSideBar.tsx +++ b/src/plugins/betterFolders/FolderSideBar.tsx @@ -17,15 +17,15 @@ */ import ErrorBoundary from "@components/ErrorBoundary"; -import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; +import { findByProps, findComponentByCode, findStore } from "@webpack"; import { useStateFromStores } from "@webpack/common"; import type { CSSProperties } from "react"; import { ExpandedGuildFolderStore, settings } from "."; -const ChannelRTCStore = findStoreLazy("ChannelRTCStore"); -const Animations = findByPropsLazy("a", "animated", "useTransition"); -const GuildsBar = findComponentByCodeLazy('("guildsnav")'); +const ChannelRTCStore = findStore("ChannelRTCStore"); +const Animations = findByProps("a", "animated", "useTransition"); +const GuildsBar = findComponentByCode('("guildsnav")'); export default ErrorBoundary.wrap(guildsBarProps => { const expandedFolders = useStateFromStores([ExpandedGuildFolderStore], () => ExpandedGuildFolderStore.getExpandedFolders()); diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 70e4070cd..81d9c122d 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -19,7 +19,7 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy, findStoreLazy } from "@webpack"; +import { findByProps, findStore } from "@webpack"; import { FluxDispatcher, i18n } from "@webpack/common"; import FolderSideBar from "./FolderSideBar"; @@ -30,10 +30,10 @@ enum FolderIconDisplay { MoreThanOneFolderExpanded } -const { GuildsTree } = findByPropsLazy("GuildsTree"); -const SortedGuildStore = findStoreLazy("SortedGuildStore"); -export const ExpandedGuildFolderStore = findStoreLazy("ExpandedGuildFolderStore"); -const FolderUtils = findByPropsLazy("move", "toggleGuildFolderExpand"); +const { GuildsTree } = findByProps("GuildsTree"); +const SortedGuildStore = findStore("SortedGuildStore"); +export const ExpandedGuildFolderStore = findStore("ExpandedGuildFolderStore"); +const FolderUtils = findByProps("move", "toggleGuildFolderExpand"); let lastGuildId = null as string | null; let dispatchingFoldersClose = false; diff --git a/src/plugins/betterNotes/index.tsx b/src/plugins/betterNotes/index.tsx index 2183d98e2..76c971018 100644 --- a/src/plugins/betterNotes/index.tsx +++ b/src/plugins/betterNotes/index.tsx @@ -20,9 +20,9 @@ import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import { canonicalizeMatch } from "@utils/patches"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; -const UserPopoutSectionCssClasses = findByPropsLazy("section", "lastSection"); +const UserPopoutSectionCssClasses = findByProps("section", "lastSection"); export default definePlugin({ name: "BetterNotesBox", diff --git a/src/plugins/betterRoleContext/index.tsx b/src/plugins/betterRoleContext/index.tsx index 3db3494f9..d52a127b0 100644 --- a/src/plugins/betterRoleContext/index.tsx +++ b/src/plugins/betterRoleContext/index.tsx @@ -7,10 +7,10 @@ import { Devs } from "@utils/constants"; import { getCurrentGuild } from "@utils/discord"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Clipboard, GuildStore, Menu, PermissionStore, TextAndImagesSettingsStores } from "@webpack/common"; -const GuildSettingsActions = findByPropsLazy("open", "selectRole", "updateGuild"); +const GuildSettingsActions = findByProps("open", "selectRole", "updateGuild"); function PencilIcon() { return ( diff --git a/src/plugins/betterSessions/index.tsx b/src/plugins/betterSessions/index.tsx index 539508f80..7fdaff971 100644 --- a/src/plugins/betterSessions/index.tsx +++ b/src/plugins/betterSessions/index.tsx @@ -21,20 +21,20 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy, findExportedComponentLazy, findStoreLazy } from "@webpack"; +import { findByProps, findExportedComponent, findStore } from "@webpack"; import { React, RestAPI, Tooltip } from "@webpack/common"; import { RenameButton } from "./components/RenameButton"; import { Session, SessionInfo } from "./types"; import { fetchNamesFromDataStore, getDefaultName, GetOsColor, GetPlatformIcon, savedSessionsCache, saveSessionsToDataStore } from "./utils"; -const AuthSessionsStore = findStoreLazy("AuthSessionsStore"); -const UserSettingsModal = findByPropsLazy("saveAccountChanges", "open"); +const AuthSessionsStore = findStore("AuthSessionsStore"); +const UserSettingsModal = findByProps("saveAccountChanges", "open"); -const TimestampClasses = findByPropsLazy("timestampTooltip", "blockquoteContainer"); -const SessionIconClasses = findByPropsLazy("sessionIcon"); +const TimestampClasses = findByProps("timestampTooltip", "blockquoteContainer"); +const SessionIconClasses = findByProps("sessionIcon"); -const BlobMask = findExportedComponentLazy("BlobMask"); +const BlobMask = findExportedComponent("BlobMask"); const settings = definePluginSettings({ backgroundCheck: { diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 7d81c6f5c..ed246ae06 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -9,14 +9,14 @@ import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { ComponentDispatch, FocusLock, i18n, Menu, useEffect, useRef } from "@webpack/common"; import type { HTMLAttributes, ReactElement } from "react"; type SettingsEntry = { section: string, label: string; }; const cl = classNameFactory(""); -const Classes = findByPropsLazy("animating", "baseLayer", "bg", "layer", "layers"); +const Classes = findByProps("animating", "baseLayer", "bg", "layer", "layers"); const settings = definePluginSettings({ disableFade: { diff --git a/src/plugins/biggerStreamPreview/webpack/stores.ts b/src/plugins/biggerStreamPreview/webpack/stores.ts index ba5227baa..805c8622e 100644 --- a/src/plugins/biggerStreamPreview/webpack/stores.ts +++ b/src/plugins/biggerStreamPreview/webpack/stores.ts @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -import { findStoreLazy } from "@webpack"; +import { findStore } from "@webpack"; import * as t from "./types/stores"; -export const ApplicationStreamPreviewStore: t.ApplicationStreamPreviewStore = findStoreLazy("ApplicationStreamPreviewStore"); -export const ApplicationStreamingStore: t.ApplicationStreamingStore = findStoreLazy("ApplicationStreamingStore"); +export const ApplicationStreamPreviewStore: t.ApplicationStreamPreviewStore = findStore("ApplicationStreamPreviewStore"); +export const ApplicationStreamingStore: t.ApplicationStreamingStore = findStore("ApplicationStreamingStore"); diff --git a/src/plugins/clientTheme/index.tsx b/src/plugins/clientTheme/index.tsx index 4e07daf42..34e0e74f9 100644 --- a/src/plugins/clientTheme/index.tsx +++ b/src/plugins/clientTheme/index.tsx @@ -11,10 +11,10 @@ import { Devs } from "@utils/constants"; import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import definePlugin, { OptionType, StartAt } from "@utils/types"; -import { findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; +import { findByProps, findComponentByCode, findStore } from "@webpack"; import { Button, Forms, useStateFromStores } from "@webpack/common"; -const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); +const ColorPicker = findComponentByCode(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); const colorPresets = [ "#1E1514", "#172019", "#13171B", "#1C1C28", "#402D2D", @@ -30,14 +30,14 @@ function onPickColor(color: number) { updateColorVars(hexColor); } -const { saveClientTheme } = findByPropsLazy("saveClientTheme"); +const { saveClientTheme } = findByProps("saveClientTheme"); function setTheme(theme: string) { saveClientTheme({ theme }); } -const ThemeStore = findStoreLazy("ThemeStore"); -const NitroThemeStore = findStoreLazy("ClientThemesBackgroundStore"); +const ThemeStore = findStore("ThemeStore"); +const NitroThemeStore = findStore("ClientThemesBackgroundStore"); function ThemeSettings() { const theme = useStateFromStores([ThemeStore], () => ThemeStore.theme); diff --git a/src/plugins/consoleShortcuts/index.ts b/src/plugins/consoleShortcuts/index.ts index e25e7cb30..5db4d4478 100644 --- a/src/plugins/consoleShortcuts/index.ts +++ b/src/plugins/consoleShortcuts/index.ts @@ -21,7 +21,7 @@ import { relaunch } from "@utils/native"; import { canonicalizeMatch, canonicalizeReplace, canonicalizeReplacement } from "@utils/patches"; import definePlugin from "@utils/types"; import * as Webpack from "@webpack"; -import { extract, filters, findAll, search } from "@webpack"; +import { cacheFindAll, extract, filters, search } from "@webpack"; import { React, ReactDOM } from "@webpack/common"; import type { ComponentType } from "react"; @@ -42,7 +42,7 @@ export default definePlugin({ const cacheKey = String(filterProps); if (cache.has(cacheKey)) return cache.get(cacheKey); - const matches = findAll(filterFactory(...filterProps)); + const matches = cacheFindAll(filterFactory(...filterProps)); const result = (() => { switch (matches.length) { @@ -73,13 +73,13 @@ export default definePlugin({ wpex: extract, wpexs: (code: string) => extract(Webpack.findModuleId(code)!), find, - findAll, + findAll: cacheFindAll, findByProps, - findAllByProps: (...props: string[]) => findAll(filters.byProps(...props)), + findAllByProps: (...props: string[]) => cacheFindAll(filters.byProps(...props)), findByCode: newFindWrapper(filters.byCode), - findAllByCode: (code: string) => findAll(filters.byCode(code)), + findAllByCode: (code: string) => cacheFindAll(filters.byCode(code)), findComponentByCode: newFindWrapper(filters.componentByCode), - findAllComponentsByCode: (...code: string[]) => findAll(filters.componentByCode(...code)), + findAllComponentsByCode: (...code: string[]) => cacheFindAll(filters.componentByCode(...code)), findExportedComponent: (...props: string[]) => findByProps(...props)[props[0]], findStore: newFindWrapper(filters.byStoreName), PluginsApi: Vencord.Plugins, diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index f8c76d7f7..d1995e1c0 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -23,25 +23,14 @@ import { Logger } from "@utils/Logger"; import { closeAllModals } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; import { maybePromptToUpdate } from "@utils/updater"; -import { filters, findBulk, proxyLazyWebpack } from "@webpack"; +import { findByProps } from "@webpack"; import { FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common"; const CrashHandlerLogger = new Logger("CrashHandler"); -const { ModalStack, DraftManager, DraftType, closeExpressionPicker } = proxyLazyWebpack(() => { - const modules = findBulk( - filters.byProps("pushLazy", "popAll"), - filters.byProps("clearDraft", "saveDraft"), - filters.byProps("DraftType"), - filters.byProps("closeExpressionPicker", "openExpressionPicker"), - ); - - return { - ModalStack: modules[0], - DraftManager: modules[1], - DraftType: modules[2]?.DraftType, - closeExpressionPicker: modules[3]?.closeExpressionPicker, - }; -}); +const ModalStack = findByProps("pushLazy", "popAll"); +const DraftManager = findByProps("clearDraft", "saveDraft"); +const { DraftType } = findByProps("DraftType"); +const { closeExpressionPicker } = findByProps("closeExpressionPicker", "openExpressionPicker"); const settings = definePluginSettings({ attemptToPreventCrashes: { diff --git a/src/plugins/customRPC/index.tsx b/src/plugins/customRPC/index.tsx index 334372e38..5eef82e43 100644 --- a/src/plugins/customRPC/index.tsx +++ b/src/plugins/customRPC/index.tsx @@ -22,12 +22,12 @@ import { Devs } from "@utils/constants"; import { isTruthy } from "@utils/guards"; import { useAwaiter } from "@utils/react"; import definePlugin, { OptionType } from "@utils/types"; -import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByCode, findByProps, findComponentByCode } from "@webpack"; import { ApplicationAssetUtils, FluxDispatcher, Forms, GuildStore, React, SelectedChannelStore, SelectedGuildStore, UserStore } from "@webpack/common"; -const useProfileThemeStyle = findByCodeLazy("profileThemeStyle:", "--profile-gradient-primary-color"); -const ActivityComponent = findComponentByCodeLazy("onOpenGameProfile"); -const ActivityClassName = findByPropsLazy("activity", "buttonColor"); +const useProfileThemeStyle = findByCode("profileThemeStyle:", "--profile-gradient-primary-color"); +const ActivityComponent = findComponentByCode("onOpenGameProfile"); +const ActivityClassName = findByProps("activity", "buttonColor"); async function getApplicationAsset(key: string): Promise { if (/https?:\/\/(cdn|media)\.discordapp\.(com|net)\/attachments\//.test(key)) return "mp:" + key.replace(/https?:\/\/(cdn|media)\.discordapp\.(com|net)\//, ""); diff --git a/src/plugins/decor/index.tsx b/src/plugins/decor/index.tsx index 5b2b6d0f0..b01d5d05c 100644 --- a/src/plugins/decor/index.tsx +++ b/src/plugins/decor/index.tsx @@ -9,7 +9,7 @@ import "./ui/styles.css"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { UserStore } from "@webpack/common"; import { CDN_URL, RAW_SKU_ID, SKU_ID } from "./lib/constants"; @@ -20,7 +20,7 @@ import { settings } from "./settings"; import { setDecorationGridDecoration, setDecorationGridItem } from "./ui/components"; import DecorSection from "./ui/components/DecorSection"; -const { isAnimatedAvatarDecoration } = findByPropsLazy("isAnimatedAvatarDecoration"); +const { isAnimatedAvatarDecoration } = findByProps("isAnimatedAvatarDecoration"); export interface AvatarDecoration { asset: string; skuId: string; diff --git a/src/plugins/decor/ui/components/DecorSection.tsx b/src/plugins/decor/ui/components/DecorSection.tsx index f11a87a53..8e454ea03 100644 --- a/src/plugins/decor/ui/components/DecorSection.tsx +++ b/src/plugins/decor/ui/components/DecorSection.tsx @@ -5,7 +5,7 @@ */ import { Flex } from "@components/Flex"; -import { findByCodeLazy } from "@webpack"; +import { findByCode } from "@webpack"; import { Button, useEffect } from "@webpack/common"; import { useAuthorizationStore } from "../../lib/stores/AuthorizationStore"; @@ -13,7 +13,7 @@ import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDeco import { cl } from "../"; import { openChangeDecorationModal } from "../modals/ChangeDecorationModal"; -const CustomizationSection = findByCodeLazy(".customizationSectionBackground"); +const CustomizationSection = findByCode(".customizationSectionBackground"); interface DecorSectionProps { hideTitle?: boolean; diff --git a/src/plugins/decor/ui/components/SectionedGridList.tsx b/src/plugins/decor/ui/components/SectionedGridList.tsx index 9a6ec1b8d..315448c64 100644 --- a/src/plugins/decor/ui/components/SectionedGridList.tsx +++ b/src/plugins/decor/ui/components/SectionedGridList.tsx @@ -5,13 +5,13 @@ */ import { classes } from "@utils/misc"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { React } from "@webpack/common"; import { cl } from "../"; import Grid, { GridProps } from "./Grid"; -const ScrollerClasses = findByPropsLazy("managedReactiveScroller"); +const ScrollerClasses = findByProps("managedReactiveScroller"); type Section = SectionT & { items: Array; diff --git a/src/plugins/decor/ui/components/index.ts b/src/plugins/decor/ui/components/index.ts index 8fe41fc92..8bc7f296d 100644 --- a/src/plugins/decor/ui/components/index.ts +++ b/src/plugins/decor/ui/components/index.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { findComponentByCode, LazyComponentWebpack } from "@webpack"; +import { filters, findComponent } from "@webpack"; import { React } from "@webpack/common"; import type { ComponentType, HTMLProps, PropsWithChildren } from "react"; @@ -18,8 +18,7 @@ type DecorationGridItemComponent = ComponentType DecorationGridItem = v; -export const AvatarDecorationModalPreview = LazyComponentWebpack(() => { - const component = findComponentByCode(".shopPreviewBanner"); +export const AvatarDecorationModalPreview = findComponent(filters.componentByCode(".shopPreviewBanner"), component => { return React.memo(component); }); diff --git a/src/plugins/decor/ui/index.ts b/src/plugins/decor/ui/index.ts index 0ead602e2..b3fd3f246 100644 --- a/src/plugins/decor/ui/index.ts +++ b/src/plugins/decor/ui/index.ts @@ -5,10 +5,10 @@ */ import { classNameFactory } from "@api/Styles"; -import { extractAndLoadChunksLazy, findByPropsLazy } from "@webpack"; +import { extractAndLoadChunksLazy, findByProps } from "@webpack"; export const cl = classNameFactory("vc-decor-"); -export const DecorationModalStyles = findByPropsLazy("modalFooterShopButton"); +export const DecorationModalStyles = findByProps("modalFooterShopButton"); export const requireAvatarDecorationModal = extractAndLoadChunksLazy(["openAvatarDecorationModal:"]); export const requireCreateStickerModal = extractAndLoadChunksLazy(["stickerInspected]:"]); diff --git a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx index 5fbe165ce..2e8e6a75c 100644 --- a/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/ChangeDecorationModal.tsx @@ -10,7 +10,7 @@ import { openInviteModal } from "@utils/discord"; import { Margins } from "@utils/margins"; import { classes } from "@utils/misc"; import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; -import { findComponentByCodeLazy } from "@webpack"; +import { findComponentByCode } from "@webpack"; import { Alerts, Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Parser, Text, Tooltip, useEffect, UserStore, UserUtils, useState } from "@webpack/common"; import { User } from "discord-types/general"; @@ -29,7 +29,7 @@ import SectionedGridList from "../components/SectionedGridList"; import { openCreateDecorationModal } from "./CreateDecorationModal"; import { openGuidelinesModal } from "./GuidelinesModal"; -const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); +const UserSummaryItem = findComponentByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"); function usePresets() { const [presets, setPresets] = useState([]); diff --git a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx index 0dcf855ef..8bd0ce9bf 100644 --- a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx +++ b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx @@ -9,7 +9,7 @@ import { Link } from "@components/Link"; import { openInviteModal } from "@utils/discord"; import { Margins } from "@utils/margins"; import { closeAllModals, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByProps, findComponentByCode } from "@webpack"; import { Button, FluxDispatcher, Forms, GuildStore, NavigationRouter, Text, TextInput, useEffect, useMemo, UserStore, useState } from "@webpack/common"; import { GUILD_ID, INVITE_KEY, RAW_SKU_ID } from "../../lib/constants"; @@ -17,9 +17,9 @@ import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDeco import { cl, DecorationModalStyles, requireAvatarDecorationModal, requireCreateStickerModal } from "../"; import { AvatarDecorationModalPreview } from "../components"; -const FileUpload = findComponentByCodeLazy("fileUploadInput,"); +const FileUpload = findComponentByCode("fileUploadInput,"); -const { default: HelpMessage, HelpMessageTypes } = findByPropsLazy("HelpMessageTypes"); +const { default: HelpMessage, HelpMessageTypes } = findByProps("HelpMessageTypes"); function useObjectURL(object: Blob | MediaSource | null) { const [url, setUrl] = useState(null); diff --git a/src/plugins/devCompanion.dev/index.tsx b/src/plugins/devCompanion.dev/index.tsx index 25fd563e4..9caddee45 100644 --- a/src/plugins/devCompanion.dev/index.tsx +++ b/src/plugins/devCompanion.dev/index.tsx @@ -22,7 +22,7 @@ import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; import { canonicalizeMatch, canonicalizeReplace } from "@utils/patches"; import definePlugin, { OptionType } from "@utils/types"; -import { filters, findAll, search } from "@webpack"; +import { cacheFind, filters, search } from "@webpack"; const PORT = 8485; const NAV_ID = "dev-companion-reconnect"; @@ -201,22 +201,22 @@ function initWs(isManual = false) { let results: any[]; switch (type.replace("find", "").replace("Lazy", "")) { case "": - results = findAll(parsedArgs[0]); + results = cacheFind(parsedArgs[0]); break; case "ByProps": - results = findAll(filters.byProps(...parsedArgs)); + results = cacheFind(filters.byProps(...parsedArgs)); break; case "Store": - results = findAll(filters.byStoreName(parsedArgs[0])); + results = cacheFind(filters.byStoreName(parsedArgs[0])); break; case "ByCode": - results = findAll(filters.byCode(...parsedArgs)); + results = cacheFind(filters.byCode(...parsedArgs)); break; case "ModuleId": results = Object.keys(search(parsedArgs[0])); break; case "ComponentByCode": - results = findAll(filters.componentByCode(...parsedArgs)); + results = cacheFind(filters.componentByCode(...parsedArgs)); break; default: return reply("Unknown Find Type " + type); diff --git a/src/plugins/emoteCloner/index.tsx b/src/plugins/emoteCloner/index.tsx index cd9890a80..2c95317b2 100644 --- a/src/plugins/emoteCloner/index.tsx +++ b/src/plugins/emoteCloner/index.tsx @@ -23,12 +23,12 @@ import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal"; import definePlugin from "@utils/types"; -import { findByPropsLazy, findStoreLazy } from "@webpack"; +import { findByProps, findStore } from "@webpack"; import { EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, Toasts, Tooltip, UserStore } from "@webpack/common"; import { Promisable } from "type-fest"; -const StickersStore = findStoreLazy("StickersStore"); -const EmojiManager = findByPropsLazy("fetchEmoji", "uploadEmoji", "deleteEmoji"); +const StickersStore = findStore("StickersStore"); +const EmojiManager = findByProps("fetchEmoji", "uploadEmoji", "deleteEmoji"); interface Sticker { t: "Sticker"; diff --git a/src/plugins/experiments/index.tsx b/src/plugins/experiments/index.tsx index 344638828..c10a41a5b 100644 --- a/src/plugins/experiments/index.tsx +++ b/src/plugins/experiments/index.tsx @@ -22,10 +22,10 @@ import { ErrorCard } from "@components/ErrorCard"; import { Devs } from "@utils/constants"; import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Forms, React } from "@webpack/common"; -const KbdStyles = findByPropsLazy("key", "removeBuildOverride"); +const KbdStyles = findByProps("key", "removeBuildOverride"); const settings = definePluginSettings({ enableIsStaff: { diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index adf1f70fb..1e26b3a2e 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -23,7 +23,7 @@ import { ApngBlendOp, ApngDisposeOp, importApngJs } from "@utils/dependencies"; import { getCurrentGuild } from "@utils/discord"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy, findStoreLazy, proxyLazyWebpack } from "@webpack"; +import { findByProps, findStore, webpackDependantLazy } from "@webpack"; import { Alerts, ChannelStore, EmojiStore, FluxDispatcher, Forms, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common"; import type { CustomEmoji } from "@webpack/types"; import type { Message } from "discord-types/general"; @@ -31,14 +31,14 @@ import { applyPalette, GIFEncoder, quantize } from "gifenc"; import type { ReactElement, ReactNode } from "react"; const DRAFT_TYPE = 0; -const StickerStore = findStoreLazy("StickersStore") as { +const StickerStore = findStore("StickersStore") as { getPremiumPacks(): StickerPack[]; getAllGuildStickers(): Map; getStickerById(id: string): Sticker | undefined; }; -const UserSettingsProtoStore = findStoreLazy("UserSettingsProtoStore"); -const ProtoUtils = findByPropsLazy("BINARY_READ_OPTIONS"); +const UserSettingsProtoStore = findStore("UserSettingsProtoStore"); +const ProtoUtils = findByProps("BINARY_READ_OPTIONS"); function searchProtoClassField(localName: string, protoClass: any) { const field = protoClass?.fields?.find((field: any) => field.localName === localName); @@ -48,9 +48,9 @@ function searchProtoClassField(localName: string, protoClass: any) { return fieldGetter?.(); } -const PreloadedUserSettingsActionCreators = proxyLazyWebpack(() => UserSettingsActionCreators.PreloadedUserSettingsActionCreators); -const AppearanceSettingsActionCreators = proxyLazyWebpack(() => searchProtoClassField("appearance", PreloadedUserSettingsActionCreators.ProtoClass)); -const ClientThemeSettingsActionsCreators = proxyLazyWebpack(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators)); +const PreloadedUserSettingsActionCreators = webpackDependantLazy(() => UserSettingsActionCreators.PreloadedUserSettingsActionCreators); +const AppearanceSettingsActionCreators = webpackDependantLazy(() => searchProtoClassField("appearance", PreloadedUserSettingsActionCreators.ProtoClass)); +const ClientThemeSettingsActionsCreators = webpackDependantLazy(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators)); const enum EmojiIntentions { diff --git a/src/plugins/favGifSearch/index.tsx b/src/plugins/favGifSearch/index.tsx index d71f56795..f1af5b043 100644 --- a/src/plugins/favGifSearch/index.tsx +++ b/src/plugins/favGifSearch/index.tsx @@ -20,7 +20,7 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { useCallback, useEffect, useRef, useState } from "@webpack/common"; interface SearchBarComponentProps { @@ -35,7 +35,7 @@ interface SearchBarComponentProps { } type TSearchBarComponent = - React.FC & { Sizes: Record<"SMALL" | "MEDIUM" | "LARGE", string>; }; + React.ComponentType & { Sizes: Record<"SMALL" | "MEDIUM" | "LARGE", string>; }; interface Gif { format: number; @@ -60,7 +60,7 @@ interface Instance { } -const containerClasses: { searchBar: string; } = findByPropsLazy("searchBar", "searchBarFullRow"); +const containerClasses: { searchBar: string; } = findByProps("searchBar", "searchBarFullRow"); export const settings = definePluginSettings({ searchOption: { diff --git a/src/plugins/friendInvites/index.ts b/src/plugins/friendInvites/index.ts index e5ff447ed..eb293b663 100644 --- a/src/plugins/friendInvites/index.ts +++ b/src/plugins/friendInvites/index.ts @@ -19,11 +19,11 @@ import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { RestAPI, UserStore } from "@webpack/common"; -const FriendInvites = findByPropsLazy("createFriendInvite"); -const { uuid4 } = findByPropsLazy("uuid4"); +const FriendInvites = findByProps("createFriendInvite"); +const { uuid4 } = findByProps("uuid4"); export default definePlugin({ name: "FriendInvites", diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx index fb431b52b..1c19eeeca 100644 --- a/src/plugins/friendsSince/index.tsx +++ b/src/plugins/friendsSince/index.tsx @@ -8,14 +8,14 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getCurrentChannel } from "@utils/discord"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Heading, React, RelationshipStore, Text } from "@webpack/common"; -const container = findByPropsLazy("memberSinceWrapper"); -const { getCreatedAtDate } = findByPropsLazy("getCreatedAtDate"); -const clydeMoreInfo = findByPropsLazy("clydeMoreInfo"); -const locale = findByPropsLazy("getLocale"); -const lastSection = findByPropsLazy("lastSection"); +const container = findByProps("memberSinceWrapper"); +const { getCreatedAtDate } = findByProps("getCreatedAtDate"); +const clydeMoreInfo = findByProps("clydeMoreInfo"); +const locale = findByProps("getLocale"); +const lastSection = findByProps("lastSection"); export default definePlugin({ name: "FriendsSince", diff --git a/src/plugins/gameActivityToggle/index.tsx b/src/plugins/gameActivityToggle/index.tsx index 51feb9165..6ecdf4e1f 100644 --- a/src/plugins/gameActivityToggle/index.tsx +++ b/src/plugins/gameActivityToggle/index.tsx @@ -21,12 +21,12 @@ import { disableStyle, enableStyle } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findComponentByCodeLazy } from "@webpack"; +import { findComponentByCode } from "@webpack"; import { StatusSettingsStores } from "@webpack/common"; import style from "./style.css?managed"; -const Button = findComponentByCodeLazy("Button.Sizes.NONE,disabled:"); +const Button = findComponentByCode("Button.Sizes.NONE,disabled:"); function makeIcon(showCurrentGame?: boolean) { const { oldIcon } = settings.use(["oldIcon"]); diff --git a/src/plugins/gifPaste/index.ts b/src/plugins/gifPaste/index.ts index 5553bf847..fd1eb0dae 100644 --- a/src/plugins/gifPaste/index.ts +++ b/src/plugins/gifPaste/index.ts @@ -19,9 +19,9 @@ import { Devs } from "@utils/constants"; import { insertTextIntoChatInputBox } from "@utils/discord"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; -const { closeExpressionPicker } = findByPropsLazy("closeExpressionPicker"); +const { closeExpressionPicker } = findByProps("closeExpressionPicker"); export default definePlugin({ name: "GifPaste", diff --git a/src/plugins/greetStickerPicker/index.tsx b/src/plugins/greetStickerPicker/index.tsx index 73bb5125e..608e97d07 100644 --- a/src/plugins/greetStickerPicker/index.tsx +++ b/src/plugins/greetStickerPicker/index.tsx @@ -19,7 +19,7 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { ContextMenuApi, FluxDispatcher, Menu, MessageActions } from "@webpack/common"; import { Channel, Message } from "discord-types/general"; @@ -49,7 +49,7 @@ const settings = definePluginSettings({ unholyMultiGreetEnabled?: boolean; }>(); -const { WELCOME_STICKERS } = findByPropsLazy("WELCOME_STICKERS"); +const { WELCOME_STICKERS } = findByProps("WELCOME_STICKERS"); function greet(channel: Channel, message: Message, stickers: string[]) { const options = MessageActions.getSendMessageOptionsForReply({ diff --git a/src/plugins/ignoreActivities/index.tsx b/src/plugins/ignoreActivities/index.tsx index e2262129d..adddb0adf 100644 --- a/src/plugins/ignoreActivities/index.tsx +++ b/src/plugins/ignoreActivities/index.tsx @@ -11,7 +11,7 @@ import { Flex } from "@components/Flex"; import { Devs } from "@utils/constants"; import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; -import { findStoreLazy } from "@webpack"; +import { findStore } from "@webpack"; import { Button, Forms, showToast, StatusSettingsStores, TextInput, Toasts, Tooltip, useEffect, useState } from "webpack/common"; const enum ActivitiesTypes { @@ -25,7 +25,7 @@ interface IgnoredActivity { type: ActivitiesTypes; } -const RunningGameStore = findStoreLazy("RunningGameStore"); +const RunningGameStore = findStore("RunningGameStore"); function ToggleIcon(activity: IgnoredActivity, tooltipText: string, path: string, fill: string) { return ( diff --git a/src/plugins/imageZoom/components/Magnifier.tsx b/src/plugins/imageZoom/components/Magnifier.tsx index 816717350..f2bd79688 100644 --- a/src/plugins/imageZoom/components/Magnifier.tsx +++ b/src/plugins/imageZoom/components/Magnifier.tsx @@ -36,7 +36,7 @@ export interface MagnifierProps { const cl = classNameFactory("vc-imgzoom-"); -export const Magnifier: React.FC = ({ instance, size: initialSize, zoom: initalZoom }) => { +export const Magnifier: React.ComponentType = ({ instance, size: initialSize, zoom: initalZoom }) => { const [ready, setReady] = useState(false); const [lensPosition, setLensPosition] = useState({ x: 0, y: 0 }); diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index be17e0fe4..07ddc855e 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -19,11 +19,11 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByProps, findStoreLazy } from "@webpack"; +import { findByProps, findStore } from "@webpack"; import { ChannelStore, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common"; import { Settings } from "Vencord"; -const UserAffinitiesStore = findStoreLazy("UserAffinitiesStore"); +const UserAffinitiesStore = findStore("UserAffinitiesStore"); interface UserAffinity { user_id: string; diff --git a/src/plugins/lastfm/index.tsx b/src/plugins/lastfm/index.tsx index 5dfec8a32..01aae2c16 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 { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { ApplicationAssetUtils, FluxDispatcher, Forms } from "@webpack/common"; interface ActivityAssets { @@ -85,7 +85,7 @@ const placeholderId = "2a96cbd8b46e442fc41c2b86b821562f"; const logger = new Logger("LastFMRichPresence"); -const presenceStore = findByPropsLazy("getLocalPresence"); +const presenceStore = findByProps("getLocalPresence"); async function getApplicationAsset(key: string): Promise { return (await ApplicationAssetUtils.fetchAssetIds(applicationId, [key]))[0]; diff --git a/src/plugins/memberCount/index.tsx b/src/plugins/memberCount/index.tsx index 92e9a2057..98e672b61 100644 --- a/src/plugins/memberCount/index.tsx +++ b/src/plugins/memberCount/index.tsx @@ -23,13 +23,13 @@ import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findStoreLazy } from "@webpack"; +import { findStore } from "@webpack"; import { FluxStore } from "@webpack/types"; import { MemberCount } from "./MemberCount"; -export const GuildMemberCountStore = findStoreLazy("GuildMemberCountStore") as FluxStore & { getMemberCount(guildId: string): number | null; }; -export const ChannelMemberStore = findStoreLazy("ChannelMemberStore") as FluxStore & { +export const GuildMemberCountStore = findStore("GuildMemberCountStore") as FluxStore & { getMemberCount(guildId: string): number | null; }; +export const ChannelMemberStore = findStore("ChannelMemberStore") as FluxStore & { getProps(guildId: string, channelId: string): { groups: { count: number; id: string; }[]; }; }; diff --git a/src/plugins/messageClickActions/index.ts b/src/plugins/messageClickActions/index.ts index 052c33f61..f254428e9 100644 --- a/src/plugins/messageClickActions/index.ts +++ b/src/plugins/messageClickActions/index.ts @@ -20,7 +20,7 @@ import { addClickListener, removeClickListener } from "@api/MessageEvents"; import { definePluginSettings, Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { FluxDispatcher, PermissionsBits, PermissionStore, UserStore } from "@webpack/common"; let isDeletePressed = false; @@ -60,8 +60,8 @@ export default definePlugin({ settings, start() { - const MessageActions = findByPropsLazy("deleteMessage", "startEditMessage"); - const EditStore = findByPropsLazy("isEditing", "isEditingAny"); + const MessageActions = findByProps("deleteMessage", "startEditMessage"); + const EditStore = findByProps("isEditing", "isEditingAny"); document.addEventListener("keydown", keydown); document.addEventListener("keyup", keyup); diff --git a/src/plugins/messageLinkEmbeds/index.tsx b/src/plugins/messageLinkEmbeds/index.tsx index 2a5f88282..29da765e2 100644 --- a/src/plugins/messageLinkEmbeds/index.tsx +++ b/src/plugins/messageLinkEmbeds/index.tsx @@ -23,7 +23,7 @@ import { Devs } from "@utils/constants.js"; import { classes } from "@utils/misc"; import { Queue } from "@utils/Queue"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByProps,findComponentByCode } from "@webpack"; import { Button, ChannelStore, @@ -46,12 +46,12 @@ const messageCache = new Map(); -const Embed = findComponentByCodeLazy(".inlineMediaEmbed"); -const AutoModEmbed = findComponentByCodeLazy(".withFooter]:", "childrenMessageContent:"); -const ChannelMessage = findComponentByCodeLazy("renderSimpleAccessories)"); +const Embed = findComponentByCode(".inlineMediaEmbed"); +const AutoModEmbed = findComponentByCode(".withFooter]:", "childrenMessageContent:"); +const ChannelMessage = findComponentByCode("renderSimpleAccessories)"); -const SearchResultClasses = findByPropsLazy("message", "searchResult"); -const EmbedClasses = findByPropsLazy("embedAuthorIcon", "embedAuthor", "embedAuthor"); +const SearchResultClasses = findByProps("message", "searchResult"); +const EmbedClasses = findByProps("embedAuthorIcon", "embedAuthor", "embedAuthor"); const messageLinkRegex = /(? m.Types?.[0] === "BOT") as RC<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; +const Tag = find(m => m.Types?.[0] === "BOT") as RC<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot(); diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index 1753fefbc..aed1876ad 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -19,15 +19,15 @@ import { Devs } from "@utils/constants"; import { isNonNullish } from "@utils/guards"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Avatar, ChannelStore, Clickable, IconUtils, RelationshipStore, ScrollerThin, UserStore } from "@webpack/common"; import { Channel, User } from "discord-types/general"; -const SelectedChannelActionCreators = findByPropsLazy("selectPrivateChannel"); -const UserUtils = findByPropsLazy("getGlobalName"); +const SelectedChannelActionCreators = findByProps("selectPrivateChannel"); +const UserUtils = findByProps("getGlobalName"); -const ProfileListClasses = findByPropsLazy("emptyIconFriends", "emptyIconGuilds"); -const GuildLabelClasses = findByPropsLazy("guildNick", "guildAvatarWithoutIcon"); +const ProfileListClasses = findByProps("emptyIconFriends", "emptyIconGuilds"); +const GuildLabelClasses = findByProps("guildNick", "guildAvatarWithoutIcon"); function getGroupDMName(channel: Channel) { return channel.name || diff --git a/src/plugins/newGuildSettings/index.tsx b/src/plugins/newGuildSettings/index.tsx index ff6f1c261..39fda260c 100644 --- a/src/plugins/newGuildSettings/index.tsx +++ b/src/plugins/newGuildSettings/index.tsx @@ -16,14 +16,14 @@ * along with this program. If not, see . */ -import { definePluginSettings,migratePluginSettings } from "@api/Settings"; +import { definePluginSettings, migratePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; -const { updateGuildNotificationSettings } = findByPropsLazy("updateGuildNotificationSettings"); -const { toggleShowAllChannels } = findByPropsLazy("toggleShowAllChannels"); -const { isOptInEnabledForGuild } = findByPropsLazy("isOptInEnabledForGuild"); +const { updateGuildNotificationSettings } = findByProps("updateGuildNotificationSettings"); +const { toggleShowAllChannels } = findByProps("toggleShowAllChannels"); +const { isOptInEnabledForGuild } = findByProps("isOptInEnabledForGuild"); const settings = definePluginSettings({ guild: { diff --git a/src/plugins/noBlockedMessages/index.ts b/src/plugins/noBlockedMessages/index.ts index 427f725ca..5a3f9797e 100644 --- a/src/plugins/noBlockedMessages/index.ts +++ b/src/plugins/noBlockedMessages/index.ts @@ -19,9 +19,9 @@ import { Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; -const RelationshipStore = findByPropsLazy("getRelationships", "isBlocked"); +const RelationshipStore = findByProps("getRelationships", "isBlocked"); export default definePlugin({ name: "NoBlockedMessages", diff --git a/src/plugins/noPendingCount/index.ts b/src/plugins/noPendingCount/index.ts index 29458df9d..7fd988b98 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 { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; -const MessageRequestStore = findByPropsLazy("getMessageRequestsCount"); +const MessageRequestStore = findByProps("getMessageRequestsCount"); const settings = definePluginSettings({ hideFriendRequestsCount: { diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx index 81f18fd6e..74cbca7dc 100644 --- a/src/plugins/pauseInvitesForever/index.tsx +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -18,11 +18,11 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { GuildStore, RestAPI } from "@webpack/common"; -const Messages = findByPropsLazy("GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION"); -const { InvitesDisabledExperiment } = findByPropsLazy("InvitesDisabledExperiment"); +const Messages = findByProps("GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION"); +const { InvitesDisabledExperiment } = findByProps("InvitesDisabledExperiment"); export default definePlugin({ name: "PauseInvitesForever", diff --git a/src/plugins/permissionsViewer/components/UserPermissions.tsx b/src/plugins/permissionsViewer/components/UserPermissions.tsx index bcd6bdf07..a8f5cf667 100644 --- a/src/plugins/permissionsViewer/components/UserPermissions.tsx +++ b/src/plugins/permissionsViewer/components/UserPermissions.tsx @@ -18,8 +18,9 @@ import ErrorBoundary from "@components/ErrorBoundary"; import ExpandableHeader from "@components/ExpandableHeader"; +import { proxyLazy } from "@utils/lazy"; import { classes } from "@utils/misc"; -import { filters, findBulk, proxyLazyWebpack } from "@webpack"; +import { findByProps } from "@webpack"; import { i18n, PermissionsBits, Text, Tooltip, useMemo, UserStore } from "@webpack/common"; import type { Guild, GuildMember } from "discord-types/general"; @@ -35,13 +36,11 @@ interface UserPermission { type UserPermissions = Array; -const Classes = proxyLazyWebpack(() => - Object.assign({}, ...findBulk( - filters.byProps("roles", "rolePill", "rolePillBorder"), - filters.byProps("roleCircle", "dotBorderBase", "dotBorderColor"), - filters.byProps("roleNameOverflow", "root", "roleName", "roleRemoveButton") - )) -) as Record<"roles" | "rolePill" | "rolePillBorder" | "desaturateUserColors" | "flex" | "alignCenter" | "justifyCenter" | "svg" | "background" | "dot" | "dotBorderColor" | "roleCircle" | "dotBorderBase" | "flex" | "alignCenter" | "justifyCenter" | "wrap" | "root" | "role" | "roleRemoveButton" | "roleDot" | "roleFlowerStar" | "roleRemoveIcon" | "roleRemoveIconFocused" | "roleVerifiedIcon" | "roleName" | "roleNameOverflow" | "actionButton" | "overflowButton" | "addButton" | "addButtonIcon" | "overflowRolesPopout" | "overflowRolesPopoutArrowWrapper" | "overflowRolesPopoutArrow" | "popoutBottom" | "popoutTop" | "overflowRolesPopoutHeader" | "overflowRolesPopoutHeaderIcon" | "overflowRolesPopoutHeaderText" | "roleIcon", string>; +const RoleClasses1 = findByProps("roles", "rolePill", "rolePillBorder"); +const RoleClasses2 = findByProps("roleCircle", "dotBorderBase", "dotBorderColor"); +const RoleClasses3 = findByProps("roleNameOverflow", "root", "roleName", "roleRemoveButton"); + +const Classes = proxyLazy(() => Object.assign({}, RoleClasses1, RoleClasses2, RoleClasses3)); function UserPermissionsComponent({ guild, guildMember, showBorder }: { guild: Guild; guildMember: GuildMember; showBorder: boolean; }) { const stns = settings.use(["permissionsSortOrder"]); diff --git a/src/plugins/petpet/index.ts b/src/plugins/petpet/index.ts index 3f9743255..b6fb5d5fc 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 { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { UploadHandler, UserUtils } from "@webpack/common"; import { applyPalette, GIFEncoder, quantize } from "gifenc"; @@ -36,7 +36,7 @@ const getFrames = makeLazy(() => Promise.all( )) ); -const UploadStore = findByPropsLazy("getUploads"); +const UploadStore = findByProps("getUploads"); function loadImage(source: File | string) { const isFile = source instanceof File; diff --git a/src/plugins/pinDms/components/CreateCategoryModal.tsx b/src/plugins/pinDms/components/CreateCategoryModal.tsx index 06e1c3568..ea73ec724 100644 --- a/src/plugins/pinDms/components/CreateCategoryModal.tsx +++ b/src/plugins/pinDms/components/CreateCategoryModal.tsx @@ -6,7 +6,7 @@ import { classNameFactory } from "@api/Styles"; import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModalLazy } from "@utils/modal"; -import { extractAndLoadChunksLazy, findComponentByCodeLazy } from "@webpack"; +import { extractAndLoadChunksLazy, findComponentByCode } from "@webpack"; import { Button, Forms, Text, TextInput, Toasts, useEffect, useState } from "@webpack/common"; import { DEFAULT_COLOR, SWATCHES } from "../constants"; @@ -30,8 +30,8 @@ interface ColorPickerWithSwatchesProps { renderCustomButton?: () => React.ReactNode; } -const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); -const ColorPickerWithSwatches = findComponentByCodeLazy("presets,", "customColor:"); +const ColorPicker = findComponentByCode(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); +const ColorPickerWithSwatches = findComponentByCode("presets,", "customColor:"); export const requireSettingsMenu = extractAndLoadChunksLazy(['name:"UserSettings"'], /createPromise:.{0,20}Promise\.all\((\[\i\.\i\(".+?"\).+?\])\).then\(\i\.bind\(\i,"(.+?)"\)\).{0,50}"UserSettings"/); diff --git a/src/plugins/pinDms/index.tsx b/src/plugins/pinDms/index.tsx index 010b5506c..26bfe894b 100644 --- a/src/plugins/pinDms/index.tsx +++ b/src/plugins/pinDms/index.tsx @@ -11,7 +11,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { classes } from "@utils/misc"; import definePlugin, { OptionType, StartAt } from "@utils/types"; -import { findByPropsLazy, findStoreLazy } from "@webpack"; +import { findByProps, findStore } from "@webpack"; import { ContextMenuApi, FluxDispatcher, Menu, React } from "@webpack/common"; import { Channel } from "discord-types/general"; @@ -27,9 +27,9 @@ interface ChannelComponentProps { } -const headerClasses = findByPropsLazy("privateChannelsHeaderContainer"); +const headerClasses = findByProps("privateChannelsHeaderContainer"); -export const PrivateChannelSortStore = findStoreLazy("PrivateChannelSortStore") as { getPrivateChannelIds: () => string[]; }; +export const PrivateChannelSortStore = findStore("PrivateChannelSortStore") as { getPrivateChannelIds: () => string[]; }; export let instance: any; export const forceUpdate = () => instance?.props?._forceUpdate?.(); diff --git a/src/plugins/pinDms/settings.ts b/src/plugins/pinDms/settings.ts new file mode 100644 index 000000000..386b662d1 --- /dev/null +++ b/src/plugins/pinDms/settings.ts @@ -0,0 +1,94 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2023 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +import { definePluginSettings, Settings, useSettings } from "@api/Settings"; +import { OptionType } from "@utils/types"; +import { findStore } from "@webpack"; + +export const enum PinOrder { + LastMessage, + Custom +} + +export const settings = definePluginSettings({ + pinOrder: { + type: OptionType.SELECT, + description: "Which order should pinned DMs be displayed in?", + options: [ + { label: "Most recent message", value: PinOrder.LastMessage, default: true }, + { label: "Custom (right click channels to reorder)", value: PinOrder.Custom } + ] + } +}); + +const PrivateChannelSortStore = findStore("PrivateChannelSortStore"); + +export let snapshotArray: string[]; +let snapshot: Set | undefined; + +const getArray = () => (Settings.plugins.PinDMs.pinnedDMs || void 0)?.split(",") as string[] | undefined; +const save = (pins: string[]) => { + snapshot = void 0; + Settings.plugins.PinDMs.pinnedDMs = pins.join(","); +}; +const takeSnapshot = () => { + snapshotArray = getArray() ?? []; + return snapshot = new Set(snapshotArray); +}; +const requireSnapshot = () => snapshot ?? takeSnapshot(); + +export function usePinnedDms() { + useSettings(["plugins.PinDMs.pinnedDMs"]); + + return requireSnapshot(); +} + +export function isPinned(id: string) { + return requireSnapshot().has(id); +} + +export function togglePin(id: string) { + const snapshot = requireSnapshot(); + if (!snapshot.delete(id)) { + snapshot.add(id); + } + + save([...snapshot]); +} + +export function sortedSnapshot() { + requireSnapshot(); + if (settings.store.pinOrder === PinOrder.LastMessage) + return PrivateChannelSortStore.getPrivateChannelIds().filter(isPinned); + + return snapshotArray; +} + +export function getPinAt(idx: number) { + return sortedSnapshot()[idx]; +} + +export function movePin(id: string, direction: -1 | 1) { + const pins = getArray()!; + const a = pins.indexOf(id); + const b = a + direction; + + [pins[a], pins[b]] = [pins[b], pins[a]]; + + save(pins); +} diff --git a/src/plugins/platformIndicators/index.tsx b/src/plugins/platformIndicators/index.tsx index 9fae9adfa..7293d7cff 100644 --- a/src/plugins/platformIndicators/index.tsx +++ b/src/plugins/platformIndicators/index.tsx @@ -23,11 +23,11 @@ import { Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy, findStoreLazy } from "@webpack"; +import { findByProps, findStore } from "@webpack"; import { PresenceStore, Tooltip, UserStore } from "@webpack/common"; import { User } from "discord-types/general"; -const SessionsStore = findStoreLazy("SessionsStore"); +const SessionsStore = findStore("SessionsStore"); function Icon(path: string, opts?: { viewBox?: string; width?: number; height?: number; }) { return ({ color, tooltip, small }: { color: string; tooltip: string; small: boolean; }) => ( @@ -55,7 +55,7 @@ const Icons = { }; type Platform = keyof typeof Icons; -const StatusUtils = findByPropsLazy("useStatusFillColor", "StatusTypes"); +const StatusUtils = findByProps("useStatusFillColor", "StatusTypes"); const PlatformIcon = ({ platform, status, small }: { platform: Platform, status: string; small: boolean; }) => { const tooltip = platform[0].toUpperCase() + platform.slice(1); diff --git a/src/plugins/previewMessage/index.tsx b/src/plugins/previewMessage/index.tsx index fe6b227a5..132a8fde0 100644 --- a/src/plugins/previewMessage/index.tsx +++ b/src/plugins/previewMessage/index.tsx @@ -20,11 +20,11 @@ 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 { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { DraftStore, DraftType, SelectedChannelStore, UserStore, useStateFromStores } from "@webpack/common"; import { MessageAttachment } from "discord-types/general"; -const UploadStore = findByPropsLazy("getUploads"); +const UploadStore = findByProps("getUploads"); const getDraft = (channelId: string) => DraftStore.getDraft(channelId, DraftType.ChannelMessage); diff --git a/src/plugins/pronoundb/components/PronounsChatComponent.tsx b/src/plugins/pronoundb/components/PronounsChatComponent.tsx index 64fac18ba..5164f0d0e 100644 --- a/src/plugins/pronoundb/components/PronounsChatComponent.tsx +++ b/src/plugins/pronoundb/components/PronounsChatComponent.tsx @@ -18,14 +18,14 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { classes } from "@utils/misc"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; import { useFormattedPronouns } from "../pronoundbUtils"; import { settings } from "../settings"; -const styles: Record = findByPropsLazy("timestampInline"); +const styles: Record = findByProps("timestampInline"); const AUTO_MODERATION_ACTION = 24; diff --git a/src/plugins/quickReply/index.ts b/src/plugins/quickReply/index.ts index 620e1a33f..468bb40a5 100644 --- a/src/plugins/quickReply/index.ts +++ b/src/plugins/quickReply/index.ts @@ -19,11 +19,11 @@ import { definePluginSettings, Settings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { ChannelStore, FluxDispatcher as Dispatcher, MessageStore, PermissionsBits, PermissionStore, SelectedChannelStore, UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; -const Kangaroo = findByPropsLazy("jumpToMessage"); +const Kangaroo = findByProps("jumpToMessage"); const isMac = navigator.platform.includes("Mac"); // bruh let replyIdx = -1; diff --git a/src/plugins/resurrectHome/index.tsx b/src/plugins/resurrectHome/index.tsx index 2042ed9c7..596c33a4c 100644 --- a/src/plugins/resurrectHome/index.tsx +++ b/src/plugins/resurrectHome/index.tsx @@ -21,10 +21,10 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Button, Menu, Tooltip, useEffect, useState } from "@webpack/common"; -const ChannelRowClasses = findByPropsLazy("modeConnected", "modeLocked", "icon"); +const ChannelRowClasses = findByProps("modeConnected", "modeLocked", "icon"); let currentShouldViewServerHome = false; const shouldViewServerHomeStates = new Set>>(); diff --git a/src/plugins/revealAllSpoilers/index.ts b/src/plugins/revealAllSpoilers/index.ts index e728181aa..896571b09 100644 --- a/src/plugins/revealAllSpoilers/index.ts +++ b/src/plugins/revealAllSpoilers/index.ts @@ -18,10 +18,10 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; -const SpoilerClasses = findByPropsLazy("spoilerContent"); -const MessagesClasses = findByPropsLazy("messagesWrapper", "messages"); +const SpoilerClasses = findByProps("spoilerContent"); +const MessagesClasses = findByProps("messagesWrapper", "messages"); export default definePlugin({ name: "RevealAllSpoilers", diff --git a/src/plugins/reviewDB/auth.tsx b/src/plugins/reviewDB/auth.tsx index 4cd81f2ea..7f3898b4e 100644 --- a/src/plugins/reviewDB/auth.tsx +++ b/src/plugins/reviewDB/auth.tsx @@ -7,14 +7,14 @@ import { DataStore } from "@api/index"; import { Logger } from "@utils/Logger"; import { openModal } from "@utils/modal"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { showToast, Toasts, UserStore } from "@webpack/common"; import { ReviewDBAuth } from "./entities"; const DATA_STORE_KEY = "rdb-auth"; -const { OAuth2AuthorizeModal } = findByPropsLazy("OAuth2AuthorizeModal"); +const { OAuth2AuthorizeModal } = findByProps("OAuth2AuthorizeModal"); export let Auth: ReviewDBAuth = {}; diff --git a/src/plugins/reviewDB/components/MessageButton.tsx b/src/plugins/reviewDB/components/MessageButton.tsx index 9b0b4be1a..5c84303c7 100644 --- a/src/plugins/reviewDB/components/MessageButton.tsx +++ b/src/plugins/reviewDB/components/MessageButton.tsx @@ -18,10 +18,10 @@ import { DeleteIcon } from "@components/Icons"; import { classes } from "@utils/misc"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Tooltip } from "@webpack/common"; -const iconClasses = findByPropsLazy("button", "wrapper", "disabled", "separator"); +const iconClasses = findByProps("button", "wrapper", "disabled", "separator"); export function DeleteButton({ onClick }: { onClick(): void; }) { return ( diff --git a/src/plugins/reviewDB/components/ReviewComponent.tsx b/src/plugins/reviewDB/components/ReviewComponent.tsx index 20b298ccb..1526543ad 100644 --- a/src/plugins/reviewDB/components/ReviewComponent.tsx +++ b/src/plugins/reviewDB/components/ReviewComponent.tsx @@ -18,8 +18,7 @@ import { openUserProfile } from "@utils/discord"; import { classes } from "@utils/misc"; -import { LazyComponent } from "@utils/react"; -import { filters, findBulk } from "@webpack"; +import { findByProps } from "@webpack"; import { Alerts, Parser, Timestamp, useState } from "@webpack/common"; import { Auth, getToken } from "../auth"; @@ -31,161 +30,150 @@ import { openBlockModal } from "./BlockedUserModal"; import { BlockButton, DeleteButton, ReportButton } from "./MessageButton"; import ReviewBadge from "./ReviewBadge"; -export default LazyComponent(() => { - // this is terrible, blame mantika - const p = filters.byProps; - const [ - { cozyMessage, buttons, message, buttonsInner, groupStart }, - { container, isHeader }, - { avatar, clickable, username, wrapper, cozy }, - buttonClasses, - botTag - ] = findBulk( - p("cozyMessage"), - p("container", "isHeader"), - p("avatar", "zalgo"), - p("button", "wrapper", "selected"), - p("botTag", "botTagRegular") - ); +const { cozyMessage, message, groupStart, buttons, buttonsInner } = findByProps("cozyMessage"); +const { container, isHeader } = findByProps("container", "isHeader"); +const { wrapper, cozy, avatar, clickable, username } = findByProps("avatar", "zalgo"); +const buttonClasses = findByProps("button", "wrapper", "selected"); +const botTag = findByProps("botTag", "botTagRegular"); - const dateFormat = new Intl.DateTimeFormat(); +const dateFormat = new Intl.DateTimeFormat(); - return function ReviewComponent({ review, refetch, profileId }: { review: Review; refetch(): void; profileId: string; }) { - const [showAll, setShowAll] = useState(false); +export default function ReviewComponent({ review, refetch, profileId }: { review: Review; refetch(): void; profileId: string; }) { + const [showAll, setShowAll] = useState(false); - function openModal() { - openUserProfile(review.sender.discordID); - } + function openModal() { + openUserProfile(review.sender.discordID); + } - function delReview() { - Alerts.show({ - title: "Are you sure?", - body: "Do you really want to delete this review?", - confirmText: "Delete", - cancelText: "Nevermind", - onConfirm: async () => { - if (!(await getToken())) { - return showToast("You must be logged in to delete reviews."); - } else { - deleteReview(review.id).then(res => { - if (res) { - refetch(); - } - }); - } + function delReview() { + Alerts.show({ + title: "Are you sure?", + body: "Do you really want to delete this review?", + confirmText: "Delete", + cancelText: "Nevermind", + onConfirm: async () => { + if (!(await getToken())) { + return showToast("You must be logged in to delete reviews."); + } else { + deleteReview(review.id).then(res => { + if (res) { + refetch(); + } + }); } - }); - } + } + }); + } - function reportRev() { - Alerts.show({ - title: "Are you sure?", - body: "Do you really you want to report this review?", - confirmText: "Report", - cancelText: "Nevermind", - // confirmColor: "red", this just adds a class name and breaks the submit button guh - onConfirm: async () => { - if (!(await getToken())) { - return showToast("You must be logged in to report reviews."); - } else { - reportReview(review.id); - } + function reportRev() { + Alerts.show({ + title: "Are you sure?", + body: "Do you really you want to report this review?", + confirmText: "Report", + cancelText: "Nevermind", + // confirmColor: "red", this just adds a class name and breaks the submit button guh + onConfirm: async () => { + if (!(await getToken())) { + return showToast("You must be logged in to report reviews."); + } else { + reportReview(review.id); } - }); - } + } + }); + } - const isAuthorBlocked = Auth?.user?.blockedUsers?.includes(review.sender.discordID) ?? false; + const isAuthorBlocked = Auth?.user?.blockedUsers?.includes(review.sender.discordID) ?? false; - function blockReviewSender() { - if (isAuthorBlocked) - return unblockUser(review.sender.discordID); + function blockReviewSender() { + if (isAuthorBlocked) + return unblockUser(review.sender.discordID); - Alerts.show({ - title: "Are you sure?", - body: "Do you really you want to block this user? They will be unable to leave further reviews on your profile. You can unblock users in the plugin settings.", - confirmText: "Block", - cancelText: "Nevermind", - // confirmColor: "red", this just adds a class name and breaks the submit button guh - onConfirm: async () => { - if (!(await getToken())) { - return showToast("You must be logged in to block users."); - } else { - blockUser(review.sender.discordID); - } + Alerts.show({ + title: "Are you sure?", + body: "Do you really you want to block this user? They will be unable to leave further reviews on your profile. You can unblock users in the plugin settings.", + confirmText: "Block", + cancelText: "Nevermind", + // confirmColor: "red", this just adds a class name and breaks the submit button guh + onConfirm: async () => { + if (!(await getToken())) { + return showToast("You must be logged in to block users."); + } else { + blockUser(review.sender.discordID); } - }); - } + } + }); + } - return ( -
+ return ( +
- -
+ +
+ openModal()} + > + {review.sender.username} + + + {review.type === ReviewType.System && ( openModal()} - > - {review.sender.username} - - - {review.type === ReviewType.System && ( - - - System - + className={classes(botTag.botTagVerified, botTag.botTagRegular, botTag.botTag, botTag.px, botTag.rem)} + style={{ marginLeft: "4px" }}> + + System - )} -
- {isAuthorBlocked && ( - openBlockModal()} - /> - )} - {review.sender.badges.map(badge => )} - - { - !settings.store.hideTimestamps && review.type !== ReviewType.System && ( - - {dateFormat.format(review.timestamp * 1000)} - ) - } - -
- {(review.comment.length > 200 && !showAll) - ? [Parser.parseGuildEventDescription(review.comment.substring(0, 200)), "...",
, ( setShowAll(true)}>Read more)] - : Parser.parseGuildEventDescription(review.comment)} -
- - {review.id !== 0 && ( -
-
- {canReportReview(review) && } - {canBlockReviewAuthor(profileId, review) && } - {canDeleteReview(profileId, review) && } -
-
+ )}
- ); - }; -}); + {isAuthorBlocked && ( + openBlockModal()} + /> + )} + {review.sender.badges.map(badge => )} + + { + !settings.store.hideTimestamps && review.type !== ReviewType.System && ( + + {dateFormat.format(review.timestamp * 1000)} + ) + } + +
+ {(review.comment.length > 200 && !showAll) + ? [Parser.parseGuildEventDescription(review.comment.substring(0, 200)), "...",
, ( setShowAll(true)}>Read more)] + : Parser.parseGuildEventDescription(review.comment)} +
+ + {review.id !== 0 && ( +
+
+ {canReportReview(review) && } + {canBlockReviewAuthor(profileId, review) && } + {canDeleteReview(profileId, review) && } +
+
+ )} +
+ ); +} + diff --git a/src/plugins/reviewDB/components/ReviewsView.tsx b/src/plugins/reviewDB/components/ReviewsView.tsx index a705bc80a..d4829f0ad 100644 --- a/src/plugins/reviewDB/components/ReviewsView.tsx +++ b/src/plugins/reviewDB/components/ReviewsView.tsx @@ -17,7 +17,7 @@ */ import { useAwaiter, useForceUpdater } from "@utils/react"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByProps, findComponentByCode } from "@webpack"; import { Forms, React, RelationshipStore, useRef, UserStore } from "@webpack/common"; import { Auth, authorize } from "../auth"; @@ -28,11 +28,11 @@ import { cl, showToast } from "../utils"; import ReviewComponent from "./ReviewComponent"; -const { Editor, Transforms } = findByPropsLazy("Editor", "Transforms"); -const { ChatInputTypes } = findByPropsLazy("ChatInputTypes"); +const { Editor, Transforms } = findByProps("Editor", "Transforms"); +const { ChatInputTypes } = findByProps("ChatInputTypes"); -const InputComponent = findComponentByCodeLazy("default.CHANNEL_TEXT_AREA", "input"); -const { createChannelRecordFromServer } = findByPropsLazy("createChannelRecordFromServer"); +const InputComponent = findComponentByCode("default.CHANNEL_TEXT_AREA", "input"); +const { createChannelRecordFromServer } = findByProps("createChannelRecordFromServer"); interface UserProps { discordId: string; diff --git a/src/plugins/searchReply/index.tsx b/src/plugins/searchReply/index.tsx index 35b197874..354eba80b 100644 --- a/src/plugins/searchReply/index.tsx +++ b/src/plugins/searchReply/index.tsx @@ -20,12 +20,12 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/Co import { ReplyIcon } from "@components/Icons"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { ChannelStore, i18n, Menu, PermissionsBits, PermissionStore, SelectedChannelStore } from "@webpack/common"; import { Message } from "discord-types/general"; -const messageUtils = findByPropsLazy("replyToMessage"); +const messageUtils = findByProps("replyToMessage"); const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { message }: { message: Message; }) => { // make sure the message is in the selected channel diff --git a/src/plugins/serverProfile/GuildProfileModal.tsx b/src/plugins/serverProfile/GuildProfileModal.tsx index 8e6f60518..0621df8db 100644 --- a/src/plugins/serverProfile/GuildProfileModal.tsx +++ b/src/plugins/serverProfile/GuildProfileModal.tsx @@ -11,12 +11,12 @@ import { openImageModal, openUserProfile } from "@utils/discord"; import { classes } from "@utils/misc"; import { ModalRoot, ModalSize, openModal } from "@utils/modal"; import { useAwaiter } from "@utils/react"; -import { findByPropsLazy, findExportedComponentLazy } from "@webpack"; +import { findByProps,findExportedComponent } from "@webpack"; import { FluxDispatcher, Forms, GuildChannelStore, GuildMemberStore, GuildStore, IconUtils, Parser, PresenceStore, RelationshipStore, ScrollerThin, SnowflakeUtils, TabBar, Timestamp, useEffect, UserStore, UserUtils, useState, useStateFromStores } from "@webpack/common"; import { Guild, User } from "discord-types/general"; -const IconClasses = findByPropsLazy("icon", "acronym", "childWrapper"); -const FriendRow = findExportedComponentLazy("FriendRow"); +const IconClasses = findByProps("icon", "acronym", "childWrapper"); +const FriendRow = findExportedComponent("FriendRow"); const cl = classNameFactory("vc-gp-"); diff --git a/src/plugins/shikiCodeblocks.desktop/previewExample.tsx b/src/plugins/shikiCodeblocks.desktop/previewExample.tsx index 508153b4b..48853ec8c 100644 --- a/src/plugins/shikiCodeblocks.desktop/previewExample.tsx +++ b/src/plugins/shikiCodeblocks.desktop/previewExample.tsx @@ -4,7 +4,7 @@ import React from "react"; const handleClick = async () => console.log((await import("@webpack/common")).Clipboard.copy("\u200b")); -export const Example: React.FC<{ +export const Example: React.ComponentType<{ real: boolean, shigged?: number, }> = ({ real, shigged }) => <> diff --git a/src/plugins/showConnections/VerifiedIcon.tsx b/src/plugins/showConnections/VerifiedIcon.tsx index ffdf21e63..ec435b438 100644 --- a/src/plugins/showConnections/VerifiedIcon.tsx +++ b/src/plugins/showConnections/VerifiedIcon.tsx @@ -16,11 +16,11 @@ * along with this program. If not, see . */ -import { findComponentByCodeLazy, findLazy } from "@webpack"; +import { find, findComponentByCode } from "@webpack"; import { i18n, useToken } from "@webpack/common"; -const ColorMap = findLazy(m => m.colors?.INTERACTIVE_MUTED?.css); -const VerifiedIconComponent = findComponentByCodeLazy(".CONNECTIONS_ROLE_OFFICIAL_ICON_TOOLTIP"); +const ColorMap = find(m => m.colors?.INTERACTIVE_MUTED?.css); +const VerifiedIconComponent = findComponentByCode(".CONNECTIONS_ROLE_OFFICIAL_ICON_TOOLTIP"); export function VerifiedIcon() { const color = useToken(ColorMap.colors.INTERACTIVE_MUTED).hex(); diff --git a/src/plugins/showConnections/index.tsx b/src/plugins/showConnections/index.tsx index d70c09315..cc26725a3 100644 --- a/src/plugins/showConnections/index.tsx +++ b/src/plugins/showConnections/index.tsx @@ -25,17 +25,17 @@ import { CopyIcon, LinkIcon } from "@components/Icons"; import { Devs } from "@utils/constants"; import { copyWithToast } from "@utils/misc"; import definePlugin, { OptionType } from "@utils/types"; -import { findByCodeLazy, findByPropsLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; +import { findByCode, findByProps, findComponentByCode, findStore } from "@webpack"; import { Text, Tooltip, UserProfileStore } from "@webpack/common"; import { User } from "discord-types/general"; import { VerifiedIcon } from "./VerifiedIcon"; -const Section = findComponentByCodeLazy(".lastSection", "children:"); -const ThemeStore = findStoreLazy("ThemeStore"); -const platformHooks: { useLegacyPlatformType(platform: string): string; } = findByPropsLazy("useLegacyPlatformType"); -const platforms: { get(type: string): ConnectionPlatform; } = findByPropsLazy("isSupported", "getByUrl"); -const getProfileThemeProps = findByCodeLazy(".getPreviewThemeColors", "primaryColor:"); +const Section = findComponentByCode(".lastSection", "children:"); +const ThemeStore = findStore("ThemeStore"); +const platformHooks: { useLegacyPlatformType(platform: string): string; } = findByProps("useLegacyPlatformType"); +const platforms: { get(type: string): ConnectionPlatform; } = findByProps("isSupported", "getByUrl"); +const getProfileThemeProps = findByCode(".getPreviewThemeColors", "primaryColor:"); const enum Spacing { COMPACT, diff --git a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx index a8f5735e7..e7d7fdb6b 100644 --- a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx +++ b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx @@ -19,7 +19,7 @@ import { Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { formatDuration } from "@utils/text"; -import { findByPropsLazy, findComponentByCodeLazy, findComponentLazy } from "@webpack"; +import { findByProps,findComponent, findComponentByCode } from "@webpack"; import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, Parser, PermissionsBits, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip, useEffect, useState } from "@webpack/common"; import type { Channel } from "discord-types/general"; @@ -78,10 +78,10 @@ const enum ChannelFlags { } -const ChatScrollClasses = findByPropsLazy("auto", "content", "scrollerBase"); -const ChatClasses = findByPropsLazy("chat", "content", "noChat", "chatContent"); -const ChannelBeginHeader = findComponentByCodeLazy(".Messages.ROLE_REQUIRED_SINGLE_USER_MESSAGE"); -const TagComponent = findComponentLazy(m => { +const ChatScrollClasses = findByProps("auto", "content", "scrollerBase"); +const ChatClasses = findByProps("chat", "content", "noChat", "chatContent"); +const ChannelBeginHeader = findComponentByCode(".Messages.ROLE_REQUIRED_SINGLE_USER_MESSAGE"); +const TagComponent = findComponent(m => { if (typeof m !== "function") return false; const code = Function.prototype.toString.call(m); @@ -89,8 +89,8 @@ const TagComponent = findComponentLazy(m => { return code.includes(".Messages.FORUM_TAG_A11Y_FILTER_BY_TAG") && !code.includes("increasedActivityPill"); }); -const EmojiParser = findByPropsLazy("convertSurrogateToName"); -const EmojiUtils = findByPropsLazy("getURL", "getEmojiColors"); +const EmojiParser = findByProps("convertSurrogateToName"); +const EmojiUtils = findByProps("getURL", "getEmojiColors"); const ChannelTypesToChannelNames = { [ChannelTypes.GUILD_TEXT]: "text", diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index 09aa2302a..be9ea3aff 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -23,13 +23,13 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { canonicalizeMatch } from "@utils/patches"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { ChannelStore, PermissionsBits, PermissionStore, Tooltip } from "@webpack/common"; import type { Channel, Role } from "discord-types/general"; import HiddenChannelLockScreen from "./components/HiddenChannelLockScreen"; -const ChannelListClasses = findByPropsLazy("modeMuted", "modeSelected", "unread", "icon"); +const ChannelListClasses = findByProps("modeMuted", "modeSelected", "unread", "icon"); const enum ShowMode { LockIcon, diff --git a/src/plugins/spotifyControls/SpotifyStore.ts b/src/plugins/spotifyControls/SpotifyStore.ts index b3cd0b282..cb441f370 100644 --- a/src/plugins/spotifyControls/SpotifyStore.ts +++ b/src/plugins/spotifyControls/SpotifyStore.ts @@ -17,7 +17,7 @@ */ import { Settings } from "@api/Settings"; -import { findByProps, proxyLazyWebpack } from "@webpack"; +import { findByProps, webpackDependantLazy } from "@webpack"; import { Flux, FluxDispatcher } from "@webpack/common"; export interface Track { @@ -64,14 +64,14 @@ interface Device { type Repeat = "off" | "track" | "context"; +const SpotifySocket = findByProps("getActiveSocketAndDevice"); +const SpotifyUtils = findByProps("SpotifyAPI"); + // Don't wanna run before Flux and Dispatcher are ready! -export const SpotifyStore = proxyLazyWebpack(() => { +export const SpotifyStore = webpackDependantLazy(() => { // For some reason ts hates extends Flux.Store const { Store } = Flux; - const SpotifySocket = findByProps("getActiveSocketAndDevice"); - const SpotifyUtils = findByProps("SpotifyAPI"); - const API_BASE = "https://api.spotify.com/v1/me/player"; class SpotifyStore extends Store { diff --git a/src/plugins/spotifyShareCommands/index.ts b/src/plugins/spotifyShareCommands/index.ts index a3b82dc20..bdb7dfa7f 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 { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { FluxDispatcher, MessageActions } from "@webpack/common"; interface Album { @@ -52,8 +52,8 @@ interface Track { name: string; } -const Spotify = findByPropsLazy("getPlayerState"); -const PendingReplyStore = findByPropsLazy("getPendingReply"); +const Spotify = findByProps("getPlayerState"); +const PendingReplyStore = findByProps("getPendingReply"); function sendMessage(channelId, message) { message = { diff --git a/src/plugins/startupTimings/StartupTimingPage.tsx b/src/plugins/startupTimings/StartupTimingPage.tsx index c8cf51da2..d70e44ff2 100644 --- a/src/plugins/startupTimings/StartupTimingPage.tsx +++ b/src/plugins/startupTimings/StartupTimingPage.tsx @@ -18,7 +18,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Forms, React } from "@webpack/common"; interface AppStartPerformance { @@ -45,7 +45,7 @@ interface Log { delta?: number; } -const AppStartPerformance = findByPropsLazy("markWithDelta", "markAndLog", "markAt") as AppStartPerformance; +const AppStartPerformance = findByProps("markWithDelta", "markAndLog", "markAt") as AppStartPerformance; interface TimerItemProps extends Log { instance: { diff --git a/src/plugins/typingIndicator/index.tsx b/src/plugins/typingIndicator/index.tsx index 6df3f4b80..858f18699 100644 --- a/src/plugins/typingIndicator/index.tsx +++ b/src/plugins/typingIndicator/index.tsx @@ -22,16 +22,16 @@ import { definePluginSettings, Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findComponentByCodeLazy, findExportedComponentLazy, findStoreLazy } from "@webpack"; +import { findComponentByCode, findExportedComponent, findStore } from "@webpack"; import { ChannelStore, GuildMemberStore, i18n, RelationshipStore, SelectedChannelStore, Tooltip, UserStore, useStateFromStores } from "@webpack/common"; import { buildSeveralUsers } from "../typingTweaks"; -const ThreeDots = findExportedComponentLazy("Dots", "AnimatedDots"); -const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); +const ThreeDots = findExportedComponent("Dots", "AnimatedDots"); +const UserSummaryItem = findComponentByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"); -const TypingStore = findStoreLazy("TypingStore"); -const UserGuildSettingsStore = findStoreLazy("UserGuildSettingsStore"); +const TypingStore = findStore("TypingStore"); +const UserGuildSettingsStore = findStore("UserGuildSettingsStore"); const enum IndicatorMode { Dots = 1 << 0, diff --git a/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx b/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx index c1bcbd657..c7f9bdd8a 100644 --- a/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx +++ b/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx @@ -18,12 +18,12 @@ import "./VoiceChannelSection.css"; -import { findByCodeLazy, findByPropsLazy } from "@webpack"; +import { findByCode,findByProps } from "@webpack"; import { Button, Forms, PermissionStore, Toasts } from "@webpack/common"; import { Channel } from "discord-types/general"; -const ChannelActions = findByPropsLazy("selectChannel", "selectVoiceChannel"); -const UserPopoutSection = findByCodeLazy(".lastSection", "children:"); +const ChannelActions = findByProps("selectChannel", "selectVoiceChannel"); +const UserPopoutSection = findByCode(".lastSection", "children:"); const CONNECT = 1n << 20n; diff --git a/src/plugins/userVoiceShow/index.tsx b/src/plugins/userVoiceShow/index.tsx index feba28316..090a4fe4e 100644 --- a/src/plugins/userVoiceShow/index.tsx +++ b/src/plugins/userVoiceShow/index.tsx @@ -20,13 +20,13 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findStoreLazy } from "@webpack"; +import { findStore } from "@webpack"; import { ChannelStore, GuildStore, UserStore } from "@webpack/common"; import { User } from "discord-types/general"; import { VoiceChannelSection } from "./components/VoiceChannelSection"; -const VoiceStateStore = findStoreLazy("VoiceStateStore"); +const VoiceStateStore = findStore("VoiceStateStore"); const settings = definePluginSettings({ showInUserProfileModal: { diff --git a/src/plugins/vcNarrator/index.tsx b/src/plugins/vcNarrator/index.tsx index ac629e749..be6c093a5 100644 --- a/src/plugins/vcNarrator/index.tsx +++ b/src/plugins/vcNarrator/index.tsx @@ -23,7 +23,7 @@ import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { wordsToTitle } from "@utils/text"; import definePlugin, { OptionType, PluginOptionsItem } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Button, ChannelStore, Forms, GuildMemberStore, SelectedChannelStore, SelectedGuildStore, useMemo, UserStore } from "@webpack/common"; interface VoiceState { @@ -36,7 +36,7 @@ interface VoiceState { selfMute: boolean; } -const VoiceStateStore = findByPropsLazy("getVoiceStatesForChannel", "getCurrentClientVoiceChannelId"); +const VoiceStateStore = findByProps("getVoiceStatesForChannel", "getCurrentClientVoiceChannelId"); // 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/plugins/vencordToolbox/index.tsx b/src/plugins/vencordToolbox/index.tsx index 00805fbd3..b894845e5 100644 --- a/src/plugins/vencordToolbox/index.tsx +++ b/src/plugins/vencordToolbox/index.tsx @@ -23,11 +23,11 @@ import { Settings, useSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findExportedComponentLazy } from "@webpack"; +import { findExportedComponent } from "@webpack"; import { Menu, Popout, useState } from "@webpack/common"; import type { ReactNode } from "react"; -const HeaderBarIcon = findExportedComponentLazy("Icon", "Divider"); +const HeaderBarIcon = findExportedComponent("Icon", "Divider"); function VencordPopout(onClose: () => void) { const { useQuickCss } = useSettings(["useQuickCss"]); diff --git a/src/plugins/voiceMessages/VoicePreview.tsx b/src/plugins/voiceMessages/VoicePreview.tsx index 9c77d8329..24cf6359a 100644 --- a/src/plugins/voiceMessages/VoicePreview.tsx +++ b/src/plugins/voiceMessages/VoicePreview.tsx @@ -17,7 +17,7 @@ */ import { useTimer } from "@utils/react"; -import { findComponentByCodeLazy } from "@webpack"; +import { findComponentByCode } from "@webpack"; import { cl } from "./utils"; @@ -25,7 +25,7 @@ interface VoiceMessageProps { src: string; waveform: string; } -const VoiceMessage = findComponentByCodeLazy("waveform:", "onVolumeChange"); +const VoiceMessage = findComponentByCode("waveform:", "onVolumeChange"); export type VoicePreviewOptions = { src?: string; diff --git a/src/plugins/voiceMessages/index.tsx b/src/plugins/voiceMessages/index.tsx index 2f232f341..c67ccc333 100644 --- a/src/plugins/voiceMessages/index.tsx +++ b/src/plugins/voiceMessages/index.tsx @@ -27,7 +27,7 @@ import { ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, openModa import { useAwaiter } from "@utils/react"; import definePlugin from "@utils/types"; import { chooseFile } from "@utils/web"; -import { findByPropsLazy, findStoreLazy } from "@webpack"; +import { findByProps, findStore } from "@webpack"; import { Button, Card, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; import { ComponentType } from "react"; @@ -37,9 +37,9 @@ import { cl } from "./utils"; import { VoicePreview } from "./VoicePreview"; import { VoiceRecorderWeb } from "./WebRecorder"; -const CloudUtils = findByPropsLazy("CloudUpload"); -const PendingReplyStore = findStoreLazy("PendingReplyStore"); -const OptionClasses = findByPropsLazy("optionName", "optionIcon", "optionLabel"); +const CloudUtils = findByProps("CloudUpload"); +const PendingReplyStore = findStore("PendingReplyStore"); +const OptionClasses = findByProps("optionName", "optionIcon", "optionLabel"); export type VoiceRecorder = ComponentType<{ setAudioBlob(blob: Blob): void; diff --git a/src/plugins/webContextMenus.web/index.ts b/src/plugins/webContextMenus.web/index.ts index ac4689036..e68592379 100644 --- a/src/plugins/webContextMenus.web/index.ts +++ b/src/plugins/webContextMenus.web/index.ts @@ -20,10 +20,10 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { saveFile } from "@utils/web"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { Clipboard, ComponentDispatch } from "@webpack/common"; -const ctxMenuCallbacks = findByPropsLazy("contextMenuCallbackNative"); +const ctxMenuCallbacks = findByProps("contextMenuCallbackNative"); async function fetchImage(url: string) { const res = await fetch(url); diff --git a/src/plugins/webKeybinds.web/index.ts b/src/plugins/webKeybinds.web/index.ts index 12d485aac..d229dcd99 100644 --- a/src/plugins/webKeybinds.web/index.ts +++ b/src/plugins/webKeybinds.web/index.ts @@ -18,10 +18,10 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { ComponentDispatch, FluxDispatcher, NavigationRouter, SelectedGuildStore, SettingsRouter } from "@webpack/common"; -const KeyBinds = findByPropsLazy("JUMP_TO_GUILD", "SERVER_NEXT"); +const KeyBinds = findByProps("JUMP_TO_GUILD", "SERVER_NEXT"); export default definePlugin({ name: "WebKeybinds", diff --git a/src/plugins/whoReacted/index.tsx b/src/plugins/whoReacted/index.tsx index b3728c215..a4f3248ba 100644 --- a/src/plugins/whoReacted/index.tsx +++ b/src/plugins/whoReacted/index.tsx @@ -22,14 +22,15 @@ import { sleep } from "@utils/misc"; import { Queue } from "@utils/Queue"; import { useForceUpdater } from "@utils/react"; import definePlugin from "@utils/types"; -import { findByPropsLazy, findComponentByCodeLazy } from "@webpack"; +import { findByProps, findComponentByCode } from "@webpack"; import { ChannelStore, FluxDispatcher, React, RestAPI, Tooltip } from "@webpack/common"; import { CustomEmoji } from "@webpack/types"; import { Message, ReactionEmoji, User } from "discord-types/general"; -const UserSummaryItem = findComponentByCodeLazy("defaultRenderUser", "showDefaultAvatarsForNullUsers"); -const AvatarStyles = findByPropsLazy("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar"); +const UserSummaryItem = findComponentByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"); +const AvatarStyles = findByProps("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar"); let Scroll: any = null; + const queue = new Queue(); let reactions: Record; diff --git a/src/plugins/xsOverlay.desktop/index.ts b/src/plugins/xsOverlay.desktop/index.ts index 763f6a782..fbda6861c 100644 --- a/src/plugins/xsOverlay.desktop/index.ts +++ b/src/plugins/xsOverlay.desktop/index.ts @@ -9,7 +9,7 @@ import { makeRange } from "@components/PluginSettings/components"; import { Devs } from "@utils/constants"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType, PluginNative } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import { ChannelStore, GuildStore, UserStore } from "@webpack/common"; import type { Channel, Embed, GuildMember, MessageAttachment, User } from "discord-types/general"; @@ -71,7 +71,7 @@ interface Call { ringing: string[]; } -const MuteStore = findByPropsLazy("isSuppressEveryoneEnabled"); +const MuteStore = findByProps("isSuppressEveryoneEnabled"); const XSLog = new Logger("XSOverlay"); const settings = definePluginSettings({ diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index 74e1aefe8..0cbf3ce72 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -20,7 +20,7 @@ import { MessageObject } from "@api/MessageEvents"; import { ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Guild, Message, User } from "discord-types/general"; -import { ImageModal, ModalRoot, ModalSize, openModal } from "./modal"; +import { ImageModal, ImageModalProps, ModalRoot, ModalSize, openModal } from "./modal"; /** * Open the invite modal @@ -108,7 +108,7 @@ export function sendMessage( return MessageActions.sendMessage(channelId, messageData, waitForChannelReady, extra); } -export function openImageModal(url: string, props?: Partial>): string { +export function openImageModal(url: string, props?: Partial): string { return openModal(modalProps => ( . -*/ + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ export function makeLazy(factory: () => T, attempts = 5): () => T { let tries = 0; @@ -22,8 +10,9 @@ export function makeLazy(factory: () => T, attempts = 5): () => T { return () => { if (!cache && attempts > tries++) { cache = factory(); - if (!cache && attempts === tries) - console.error("Lazy factory failed:", factory); + if (!cache && attempts === tries) { + console.error(`Lazy factory failed:\n${factory}`); + } } return cache; }; @@ -33,94 +22,81 @@ export function makeLazy(factory: () => T, attempts = 5): () => T { // will always return the function default for them. const unconfigurable = ["arguments", "caller", "prototype"]; -const handler: ProxyHandler = {}; +const handler: ProxyHandler = { + ...Object.fromEntries(Object.getOwnPropertyNames(Reflect).map(propName => + [propName, (target: any, ...args: any[]) => Reflect[propName](target[proxyLazyGet](), ...args)] + )), + ownKeys: target => { + const keys = Reflect.ownKeys(target[proxyLazyGet]()); + for (const key of unconfigurable) { + if (!keys.includes(key)) keys.push(key); + } + return keys; + }, + getOwnPropertyDescriptor: (target, p) => { + if (typeof p === "string" && unconfigurable.includes(p)) + return Reflect.getOwnPropertyDescriptor(target, p); -const kGET = Symbol.for("vencord.lazy.get"); -const kCACHE = Symbol.for("vencord.lazy.cached"); - -for (const method of [ - "apply", - "construct", - "defineProperty", - "deleteProperty", - "getOwnPropertyDescriptor", - "getPrototypeOf", - "has", - "isExtensible", - "ownKeys", - "preventExtensions", - "set", - "setPrototypeOf" -]) { - handler[method] = - (target: any, ...args: any[]) => Reflect[method](target[kGET](), ...args); -} - -handler.ownKeys = target => { - const v = target[kGET](); - const keys = Reflect.ownKeys(v); - for (const key of unconfigurable) { - if (!keys.includes(key)) keys.push(key); + const descriptor = Reflect.getOwnPropertyDescriptor(target[proxyLazyGet](), p); + if (descriptor) Object.defineProperty(target, p, descriptor); + return descriptor; } - return keys; }; -handler.getOwnPropertyDescriptor = (target, p) => { - if (typeof p === "string" && unconfigurable.includes(p)) - return Reflect.getOwnPropertyDescriptor(target, p); - - const descriptor = Reflect.getOwnPropertyDescriptor(target[kGET](), p); - - if (descriptor) Object.defineProperty(target, p, descriptor); - return descriptor; -}; +const proxyLazyGet = Symbol.for("vencord.lazy.get"); +const proxyLazyCache = Symbol.for("vencord.lazy.cached"); /** - * Wraps the result of {@link makeLazy} in a Proxy you can consume as if it wasn't lazy. - * On first property access, the lazy is evaluated - * @param factory lazy factory - * @param attempts how many times to try to evaluate the lazy before giving up - * @returns Proxy - * - * Note that the example below exists already as an api, see {@link findByPropsLazy} - * @example const mod = proxyLazy(() => findByProps("blah")); console.log(mod.blah); + * Wraps the result of factory in a Proxy you can consume as if it wasn't lazy. + * On first property access, the factory is evaluated + * @param factory Factory returning the result + * @param attempts How many times to try to evaluate the factory before giving up + * @returns Result of factory function */ -export function proxyLazy(factory: () => T, attempts = 5, isChild = false): T { - let isSameTick = true; - if (!isChild) - setTimeout(() => isSameTick = false, 0); +export function proxyLazy(factory: () => T, attempts = 5, isChild = false): T { + const get = makeLazy(factory, attempts); - let tries = 0; + let isSameTick = true; + if (!isChild) setTimeout(() => isSameTick = false, 0); + + let failed = false; const proxyDummy = Object.assign(function () { }, { - [kCACHE]: void 0 as T | undefined, - [kGET]() { - if (!proxyDummy[kCACHE] && attempts > tries++) { - proxyDummy[kCACHE] = factory(); - if (!proxyDummy[kCACHE] && attempts === tries) - console.error("Lazy factory failed:", factory); + [proxyLazyGet]() { + if (!proxyDummy[proxyLazyCache] && !failed) { + proxyDummy[proxyLazyCache] = get(); + + if (!proxyDummy[proxyLazyCache]) { + failed = true; + throw new Error(`proxyLazy factory failed:\n${factory}`); + } } - return proxyDummy[kCACHE]; - } + + return proxyDummy[proxyLazyCache]; + }, + [proxyLazyCache]: void 0 as T | undefined }); return new Proxy(proxyDummy, { ...handler, get(target, p, receiver) { - // if we're still in the same tick, it means the lazy was immediately used. + // If we're still in the same tick, it means the lazy was immediately used. // thus, we lazy proxy the get access to make things like destructuring work as expected // meow here will also be a lazy // `const { meow } = findByPropsLazy("meow");` - if (!isChild && isSameTick) + if (!isChild && isSameTick) { return proxyLazy( - () => Reflect.get(target[kGET](), p, receiver), + () => Reflect.get(target[proxyLazyGet](), p, receiver), attempts, true ); - const lazyTarget = target[kGET](); + } + + const lazyTarget = target[proxyLazyGet](); if (typeof lazyTarget === "object" || typeof lazyTarget === "function") { return Reflect.get(lazyTarget, p, receiver); } + throw new Error("proxyLazy called on a primitive value"); } - }) as any; + }) as T; } diff --git a/src/utils/lazyReact.tsx b/src/utils/lazyReact.tsx index 4896a0581..0e929aa98 100644 --- a/src/utils/lazyReact.tsx +++ b/src/utils/lazyReact.tsx @@ -8,22 +8,32 @@ import { ComponentType } from "react"; import { makeLazy } from "./lazy"; -const NoopComponent = () => null; +export const NoopComponent = () => null; /** * A lazy component. The factory method is called on first render. - * @param factory Function returning a Component + * @param factory Function returning a component * @param attempts How many times to try to get the component before giving up * @returns Result of factory function */ export function LazyComponent(factory: () => React.ComponentType, attempts = 5) { const get = makeLazy(factory, attempts); + + let failed = false; const LazyComponent = (props: T) => { - const Component = get() ?? NoopComponent; + const Component = get() ?? (() => { + if (!failed) { + failed = true; + console.error(`LazyComponent factory failed:\n${factory}`); + } + + return NoopComponent; + })(); + return ; }; - LazyComponent.$$vencordInternal = get; + LazyComponent.$$vencordGetter = get; return LazyComponent as ComponentType; } diff --git a/src/utils/modal.tsx b/src/utils/modal.tsx index b4d0f59fb..4c9962563 100644 --- a/src/utils/modal.tsx +++ b/src/utils/modal.tsx @@ -16,10 +16,9 @@ * along with this program. If not, see . */ -import { findByPropsLazy, findExportedComponentLazy } from "@webpack"; +import { filters, find, findByProps, findExportedComponent } from "@webpack"; import type { ComponentType, PropsWithChildren, ReactNode, Ref } from "react"; -import { LazyComponent } from "./react"; export const enum ModalSize { SMALL = "small", @@ -49,7 +48,7 @@ export interface ModalOptions { type RenderFunction = (props: ModalProps) => ReactNode; -export const Modals = findByPropsLazy("ModalRoot", "ModalCloseButton") as { +type Modals = { ModalRoot: ComponentType; }; -export type ImageModal = ComponentType<{ + +export let ModalRoot: Modals["ModalRoot"]; +export let ModalHeader: Modals["ModalHeader"]; +export let ModalContent: Modals["ModalContent"]; +export let ModalFooter: Modals["ModalFooter"]; +export let ModalCloseButton: Modals["ModalCloseButton"]; + +export const Modals = find(filters.byProps("ModalRoot", "ModalCloseButton"), m => { + ({ ModalRoot, ModalHeader, ModalContent, ModalFooter, ModalCloseButton } = m); + return m; +}); + +export type ImageModalProps = { className?: string; src: string; placeholder: string; @@ -116,17 +127,11 @@ export type ImageModal = ComponentType<{ shouldAnimate?: boolean; onClose?(): void; shouldHideMediaOptions?: boolean; -}>; +}; -export const ImageModal = findExportedComponentLazy("ImageModal") as ImageModal; +export const ImageModal = findExportedComponent("ImageModal"); -export const ModalRoot = LazyComponent(() => Modals.ModalRoot); -export const ModalHeader = LazyComponent(() => Modals.ModalHeader); -export const ModalContent = LazyComponent(() => Modals.ModalContent); -export const ModalFooter = LazyComponent(() => Modals.ModalFooter); -export const ModalCloseButton = LazyComponent(() => Modals.ModalCloseButton); - -const ModalAPI = findByPropsLazy("openModalLazy"); +const ModalAPI = findByProps("openModalLazy"); /** * Wait for the render promise to resolve, then open a modal with it. diff --git a/src/utils/proxyInner.ts b/src/utils/proxyInner.ts new file mode 100644 index 000000000..7f818d0d5 --- /dev/null +++ b/src/utils/proxyInner.ts @@ -0,0 +1,91 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +export const proxyInnerGet = Symbol.for("vencord.proxyInner.get"); +export const proxyInnerValue = Symbol.for("vencord.proxyInner.innerValue"); + +// Proxies demand that these properties be unmodified, so proxyInner +// will always return the function default for them. +const unconfigurable = ["arguments", "caller", "prototype"]; + +const handler: ProxyHandler = { + ...Object.fromEntries(Object.getOwnPropertyNames(Reflect).map(propName => + [propName, (target: any, ...args: any[]) => Reflect[propName](target[proxyInnerGet](), ...args)] + )), + ownKeys: target => { + const keys = Reflect.ownKeys(target[proxyInnerGet]()); + for (const key of unconfigurable) { + if (!keys.includes(key)) keys.push(key); + } + return keys; + }, + getOwnPropertyDescriptor: (target, p) => { + if (typeof p === "string" && unconfigurable.includes(p)) + return Reflect.getOwnPropertyDescriptor(target, p); + + const descriptor = Reflect.getOwnPropertyDescriptor(target[proxyInnerGet](), p); + if (descriptor) Object.defineProperty(target, p, descriptor); + return descriptor; + } +}; + +/** + * A proxy which has an inner value that can be set later. + * When a property is accessed, the proxy looks for the property value in its inner value, and errors if it's not set. + * @param err The error to throw when the inner value is not set + * @returns A proxy which will act like the inner value when accessed + */ +export function proxyInner(err = new Error("Proxy inner value is undefined, setInnerValue was never called."), isChild = false): [proxy: T, setInnerValue: (innerValue: T) => void] { + let isSameTick = true; + if (!isChild) setTimeout(() => isSameTick = false, 0); + + const proxyDummy = Object.assign(function () { }, { + [proxyInnerGet]: function () { + if (proxyDummy[proxyInnerValue] == null) { + throw err; + } + + return proxyDummy[proxyInnerValue]; + }, + [proxyInnerValue]: void 0 as T | undefined + }); + + const recursiveSetInnerValues = [] as Array<(innerValue: T) => void>; + + function setInnerValue(innerValue: T) { + proxyDummy[proxyInnerValue] = innerValue; + recursiveSetInnerValues.forEach(setInnerValue => setInnerValue(innerValue)); + } + + return [new Proxy(proxyDummy, { + ...handler, + get(target, p, receiver) { + if (p === proxyInnerValue) return target[proxyInnerValue]; + if (p === proxyInnerGet) return target[proxyInnerGet]; + + // If we're still in the same tick, it means the proxy was immediately used. + // thus, we proxy the get access to make things like destructuring work as expected + // meow here will also be a proxy + // `const { meow } = findByProps("meow");` + if (!isChild && isSameTick) { + const [recursiveProxy, recursiveSetInnerValue] = proxyInner(err, true); + recursiveSetInnerValues.push((innerValue: T) => { + recursiveSetInnerValue(Reflect.get(innerValue as object, p, receiver)); + }); + + return recursiveProxy; + } + + const innerTarget = target[proxyInnerGet](); + if (typeof innerTarget === "object" || typeof innerTarget === "function") { + return Reflect.get(innerTarget, p, receiver); + } + + throw new Error("proxyInner called on a primitive value"); + + } + }) as T, setInnerValue]; +} diff --git a/src/webpack/common/classes.ts b/src/webpack/common/classes.ts index ca3d75f57..7a9eee949 100644 --- a/src/webpack/common/classes.ts +++ b/src/webpack/common/classes.ts @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -import { findByPropsLazy, findLazy } from "@webpack"; +import { find, findByProps } from "@webpack"; import * as t from "./types/classes"; -export const ModalImageClasses: t.ImageModalClasses = findLazy(m => m.image && m.modal && !m.applicationIcon); -export const ButtonWrapperClasses: t.ButtonWrapperClasses = findByPropsLazy("buttonWrapper", "buttonContent"); +export const ModalImageClasses: t.ImageModalClasses = find(m => m.image && m.modal && !m.applicationIcon); +export const ButtonWrapperClasses: t.ButtonWrapperClasses = findByProps("buttonWrapper", "buttonContent"); diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index 46f843ce6..cdf12d997 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -17,9 +17,8 @@ */ // eslint-disable-next-line path-alias/no-relative -import { filters, findByPropsLazy, waitFor } from "@webpack"; +import { filters, findComponent, findExportedComponent, waitFor } from "@webpack"; -import { waitForComponent } from "./internal"; import * as t from "./types/components"; export let Forms = {} as { @@ -53,13 +52,14 @@ export let FocusLock: t.FocusLock; /** css colour resolver stuff, no clue what exactly this does, just copied usage from Discord */ export let useToken: t.useToken; -export const MaskedLink = waitForComponent("MaskedLink", filters.componentByCode("MASKED_LINK)")); -export const Timestamp = waitForComponent("Timestamp", filters.byCode(".Messages.MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL.format")); -export const Flex = waitForComponent("Flex", ["Justify", "Align", "Wrap"]); +export const MaskedLink = findComponent(filters.componentByCode("MASKED_LINK)")); +export const Timestamp = findComponent(filters.componentByCode(".Messages.MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL.format")); +export const Flex = findComponent(filters.byProps("Justify", "Align", "Wrap")); -export const { OAuth2AuthorizeModal } = findByPropsLazy("OAuth2AuthorizeModal"); +export const OAuth2AuthorizeModal = findExportedComponent("OAuth2AuthorizeModal"); -waitFor(["FormItem", "Button"], m => { +waitFor(filters.byProps("FormItem", "Button"), m => { + Forms = m; ({ useToken, Card, @@ -83,5 +83,4 @@ waitFor(["FormItem", "Button"], m => { FocusLock, Heading } = m); - Forms = m; }); diff --git a/src/webpack/common/internal.tsx b/src/webpack/common/internal.tsx deleted file mode 100644 index 9a89af362..000000000 --- a/src/webpack/common/internal.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -import { LazyComponent } from "@utils/react"; - -// eslint-disable-next-line path-alias/no-relative -import { FilterFn, filters, lazyWebpackSearchHistory, waitFor } from "../webpack"; - -export function waitForComponent = React.ComponentType & Record>(name: string, filter: FilterFn | string | string[]): T { - if (IS_DEV) lazyWebpackSearchHistory.push(["waitForComponent", Array.isArray(filter) ? filter : [filter]]); - - let myValue: T = function () { - throw new Error(`Vencord could not find the ${name} Component`); - } as any; - - const lazyComponent = LazyComponent(() => myValue) as T; - waitFor(filter, (v: any) => { - myValue = v; - Object.assign(lazyComponent, v); - }, { isIndirect: true }); - - return lazyComponent; -} - -export function waitForStore(name: string, cb: (v: any) => void) { - if (IS_DEV) lazyWebpackSearchHistory.push(["waitForStore", [name]]); - - waitFor(filters.byStoreName(name), cb, { isIndirect: true }); -} diff --git a/src/webpack/common/menu.ts b/src/webpack/common/menu.ts index 9a4a3a799..a722cf242 100644 --- a/src/webpack/common/menu.ts +++ b/src/webpack/common/menu.ts @@ -17,12 +17,10 @@ */ // eslint-disable-next-line path-alias/no-relative -import { findByPropsLazy, waitFor } from "../webpack"; +import { findByProps } from "../webpack"; import type * as t from "./types/menu"; -export let Menu = {} as t.Menu; +export const Menu = findByProps("MenuItem", "MenuSliderControl"); -waitFor(["MenuItem", "MenuSliderControl"], m => Menu = m); - -export const ContextMenuApi: t.ContextMenuApi = findByPropsLazy("closeContextMenu", "openContextMenu"); +export const ContextMenuApi = findByProps("closeContextMenu", "openContextMenu"); diff --git a/src/webpack/common/react.ts b/src/webpack/common/react.ts index 17196132d..f71517f2c 100644 --- a/src/webpack/common/react.ts +++ b/src/webpack/common/react.ts @@ -17,7 +17,7 @@ */ // eslint-disable-next-line path-alias/no-relative -import { findByPropsLazy, waitFor } from "../webpack"; +import { filters, findByProps,waitFor } from "../webpack"; export let React: typeof import("react"); export let useState: typeof React.useState; @@ -27,9 +27,9 @@ export let useRef: typeof React.useRef; export let useReducer: typeof React.useReducer; export let useCallback: typeof React.useCallback; -export const ReactDOM: typeof import("react-dom") & typeof import("react-dom/client") = findByPropsLazy("createPortal", "render"); +export const ReactDOM = findByProps("createPortal", "render"); -waitFor("useState", m => { +waitFor(filters.byProps("useState"), m => { React = m; ({ useEffect, useState, useMemo, useRef, useReducer, useCallback } = React); }); diff --git a/src/webpack/common/settingsStores.ts b/src/webpack/common/settingsStores.ts index 4a48efda6..e4da26b31 100644 --- a/src/webpack/common/settingsStores.ts +++ b/src/webpack/common/settingsStores.ts @@ -4,12 +4,12 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { findByPropsLazy } from "@webpack"; +import { findByProps } from "@webpack"; import * as t from "./types/settingsStores"; -export const TextAndImagesSettingsStores = findByPropsLazy("MessageDisplayCompact") as Record; -export const StatusSettingsStores = findByPropsLazy("ShowCurrentGame") as Record; +export const TextAndImagesSettingsStores = findByProps("MessageDisplayCompact") as Record; +export const StatusSettingsStores = findByProps("ShowCurrentGame") as Record; -export const UserSettingsActionCreators = findByPropsLazy("PreloadedUserSettingsActionCreators"); +export const UserSettingsActionCreators = findByProps("PreloadedUserSettingsActionCreators"); diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 2f9786bc5..5ab4651e8 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -19,11 +19,10 @@ import type * as Stores from "discord-types/stores"; // eslint-disable-next-line path-alias/no-relative -import { findByPropsLazy } from "../webpack"; -import { waitForStore } from "./internal"; +import { findByProps, findStore } from "../webpack"; import * as t from "./types/stores"; -export const Flux: t.Flux = findByPropsLazy("connectStores"); +export const Flux: t.Flux = findByProps("connectStores"); export type GenericStore = t.FluxStore & Record; @@ -34,32 +33,32 @@ export enum DraftType { ApplicationLauncherCommand = 3 } -export let MessageStore: Omit & { +export const MessageStore = findStore("MessageStore") as Omit & { getMessages(chanId: string): any; }; // this is not actually a FluxStore -export const PrivateChannelsStore = findByPropsLazy("openPrivateChannel"); -export let PermissionStore: GenericStore; -export let GuildChannelStore: GenericStore; -export let ReadStateStore: GenericStore; -export let PresenceStore: GenericStore; +export const PrivateChannelsStore = findByProps("openPrivateChannel"); +export const PermissionStore: GenericStore = findStore("PermissionStore"); +export const GuildChannelStore: GenericStore = findStore("GuildChannelStore"); +export const ReadStateStore: GenericStore = findStore("ReadStateStore"); +export const PresenceStore: GenericStore = findStore("PresenceStore"); -export let GuildStore: t.GuildStore; -export let UserStore: Stores.UserStore & t.FluxStore; -export let UserProfileStore: GenericStore; -export let SelectedChannelStore: Stores.SelectedChannelStore & t.FluxStore; -export let SelectedGuildStore: t.FluxStore & Record; -export let ChannelStore: Stores.ChannelStore & t.FluxStore; -export let GuildMemberStore: Stores.GuildMemberStore & t.FluxStore; -export let RelationshipStore: Stores.RelationshipStore & t.FluxStore & { +export const GuildStore: t.GuildStore = findStore("GuildStore"); +export const UserStore: Stores.UserStore & t.FluxStore = findStore("UserStore"); +export const UserProfileStore: GenericStore = findStore("UserProfileStore"); +export const SelectedChannelStore: Stores.SelectedChannelStore & t.FluxStore = findStore("SelectedChannelStore"); +export const SelectedGuildStore: t.FluxStore & Record = findStore("SelectedGuildStore"); +export const ChannelStore: Stores.ChannelStore & t.FluxStore = findStore("ChannelStore"); +export const GuildMemberStore: Stores.GuildMemberStore & t.FluxStore = findStore("GuildMemberStore"); +export const RelationshipStore = findStore("RelationshipStore") as Stores.RelationshipStore & t.FluxStore & { /** Get the date (as a string) that the relationship was created */ getSince(userId: string): string; }; -export let EmojiStore: t.EmojiStore; -export let WindowStore: t.WindowStore; -export let DraftStore: t.DraftStore; +export const EmojiStore: t.EmojiStore = findStore("EmojiStore"); +export const WindowStore: t.WindowStore = findStore("WindowStore"); +export const DraftStore: t.DraftStore = findStore("DraftStore"); /** * React hook that returns stateful data for one or more stores @@ -80,21 +79,4 @@ export const { useStateFromStores }: { isEqual?: (old: T, newer: T) => boolean ) => T; } - = findByPropsLazy("useStateFromStores"); - -waitForStore("DraftStore", s => DraftStore = s); -waitForStore("UserStore", s => UserStore = s); -waitForStore("UserProfileStore", m => UserProfileStore = m); -waitForStore("ChannelStore", m => ChannelStore = m); -waitForStore("SelectedChannelStore", m => SelectedChannelStore = m); -waitForStore("SelectedGuildStore", m => SelectedGuildStore = m); -waitForStore("GuildStore", m => GuildStore = m); -waitForStore("GuildMemberStore", m => GuildMemberStore = m); -waitForStore("RelationshipStore", m => RelationshipStore = m); -waitForStore("PermissionStore", m => PermissionStore = m); -waitForStore("PresenceStore", m => PresenceStore = m); -waitForStore("ReadStateStore", m => ReadStateStore = m); -waitForStore("GuildChannelStore", m => GuildChannelStore = m); -waitForStore("MessageStore", m => MessageStore = m); -waitForStore("WindowStore", m => WindowStore = m); -waitForStore("EmojiStore", m => EmojiStore = m); + = findByProps("useStateFromStores"); diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index c51264370..c772c8994 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -153,7 +153,7 @@ export type Switch = ComponentType>; -export type Timestamp = ComponentType>; +}>; export type TextInput = ComponentType>; // TODO - type maybe idk probably not that useful other than the constants -export type Flex = ComponentType> & { +export type FlexProps = PropsWithChildren & { Align: Record<"START" | "END" | "CENTER" | "STRETCH" | "BASELINE", string>; Direction: Record<"VERTICAL" | "HORIZONTAL" | "HORIZONTAL_REVERSE", string>; Justify: Record<"START" | "END" | "CENTER" | "BETWEEN" | "AROUND", string>; @@ -399,7 +399,7 @@ export type Paginator = ComponentType<{ hideMaxPage?: boolean; }>; -export type MaskedLink = ComponentType>; +}>; export type ScrollerThin = ComponentType { - FluxDispatcher = m; +export const FluxDispatcher = find(filters.byProps("dispatch", "subscribe"), m => { // Non import call to avoid circular dependency Vencord.Plugins.subscribeAllPluginsFluxEvents(m); @@ -34,31 +31,25 @@ waitFor(["dispatch", "subscribe"], m => { _resolveReady(); }; m.subscribe("CONNECTION_OPEN", cb); + + return m; }); -export let ComponentDispatch; -waitFor(["ComponentDispatch", "ComponentDispatcher"], m => ComponentDispatch = m.ComponentDispatch); +export const { ComponentDispatch } = findByProps("ComponentDispatch", "ComponentDispatcher"); +export const RestAPI = find(filters.byProps("getAPIBaseURL"), m => m.HTTP ?? m); +export const moment = findByProps("parseTwoDigitYear"); -export const RestAPI: t.RestAPI = proxyLazyWebpack(() => { - const mod = findByProps("getAPIBaseURL"); - return mod.HTTP ?? mod; -}); -export const moment: typeof import("moment") = findByPropsLazy("parseTwoDigitYear"); +export const hljs = findByProps("highlight", "registerLanguage"); -export const hljs: typeof import("highlight.js") = findByPropsLazy("highlight", "registerLanguage"); +export const lodash = findByProps("debounce", "cloneDeep"); -export const lodash: typeof import("lodash") = findByPropsLazy("debounce", "cloneDeep"); +export const i18n = find(m => m.Messages?.["en-US"]); -export const i18n: t.i18n = findLazy(m => m.Messages?.["en-US"]); +export const SnowflakeUtils = findByProps("fromTimestamp", "extractTimestamp"); -export let SnowflakeUtils: t.SnowflakeUtils; -waitFor(["fromTimestamp", "extractTimestamp"], m => SnowflakeUtils = m); - -export let Parser: t.Parser; -waitFor("parseTopic", m => Parser = m); -export let Alerts: t.Alerts; -waitFor(["show", "close"], m => Alerts = m); +export const Parser = findByProps("parseTopic"); +export const Alerts = findByProps("show", "close"); const ToastType = { MESSAGE: 0, @@ -100,12 +91,11 @@ export const Toasts = { }; // This is the same module but this is easier -waitFor("showToast", m => { +waitFor(filters.byCode("showToast"), m => { Toasts.show = m.showToast; Toasts.pop = m.popToast; }); - /** * Show a simple toast. If you need more options, use Toasts.show manually */ @@ -117,31 +107,30 @@ export function showToast(message: string, type = ToastType.MESSAGE) { }); } -export const UserUtils = findByPropsLazy("getUser", "fetchCurrentUser") as { getUser: (id: string) => Promise; }; -export const UploadHandler = findByPropsLazy("showUploadFileSizeExceededError", "promptToUpload") as { +export const UserUtils = findByProps("getUser", "fetchCurrentUser") as { getUser: (id: string) => Promise; }; +export const UploadHandler = findByProps("showUploadFileSizeExceededError", "promptToUpload") as { promptToUpload: (files: File[], channel: Channel, draftType: Number) => void; }; -export const ApplicationAssetUtils = findByPropsLazy("fetchAssetIds", "getAssetImage") as { +export const ApplicationAssetUtils = findByProps("fetchAssetIds", "getAssetImage") as { fetchAssetIds: (applicationId: string, e: string[]) => Promise; }; -export const Clipboard: t.Clipboard = findByPropsLazy("SUPPORTS_COPY", "copy"); +export const Clipboard = findByProps("SUPPORTS_COPY", "copy"); -export const NavigationRouter: t.NavigationRouter = findByPropsLazy("transitionTo", "replaceWith", "transitionToGuild"); +export const NavigationRouter = findByProps("transitionTo", "replaceWith", "transitionToGuild"); -export let SettingsRouter: any; -waitFor(["open", "saveAccountChanges"], m => SettingsRouter = m); +export const SettingsRouter = findByProps("open", "saveAccountChanges"); -export const { Permissions: PermissionsBits } = findLazy(m => typeof m.Permissions?.ADMINISTRATOR === "bigint") as { Permissions: t.PermissionsBits; }; +export const { Permissions: PermissionsBits } = find(m => typeof m.Permissions?.ADMINISTRATOR === "bigint") as { Permissions: t.PermissionsBits; }; -export const zustandCreate: typeof import("zustand").default = findByCodeLazy("will be removed in v4"); +export const zustandCreate = findByCode("will be removed in v4"); const persistFilter = filters.byCode("[zustand persist middleware]"); -export const { persist: zustandPersist }: typeof import("zustand/middleware") = findLazy(m => m.persist && persistFilter(m.persist)); +export const { persist: zustandPersist } = find(m => m.persist && persistFilter(m.persist)); -export const MessageActions = findByPropsLazy("editMessage", "sendMessage"); -export const UserProfileActions = findByPropsLazy("openUserProfileModal", "closeUserProfileModal"); -export const InviteActions = findByPropsLazy("resolveInvite"); +export const MessageActions = findByProps("editMessage", "sendMessage"); +export const UserProfileActions = findByProps("openUserProfileModal", "closeUserProfileModal"); +export const InviteActions = findByProps("resolveInvite"); -export const IconUtils: t.IconUtils = findByPropsLazy("getGuildBannerURL", "getUserAvatarURL"); +export const IconUtils = findByProps("getGuildBannerURL", "getUserAvatarURL"); diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index d2b569e8d..913db621b 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -24,7 +24,7 @@ import { WebpackInstance } from "discord-types/other"; import { traceFunction } from "../debug/Tracer"; import { patches } from "../plugins"; -import { _initWebpack, beforeInitListeners, factoryListeners, moduleListeners, subscriptions, wreq } from "."; +import { _initWebpack, beforeInitListeners, factoryListeners, moduleListeners, waitForSubscriptions, wreq } from "."; const logger = new Logger("WebpackInterceptor", "#8caaee"); const initCallbackRegex = canonicalizeMatch(/{return \i\(".+?"\)}/); @@ -216,14 +216,14 @@ function patchFactories(factories: Record. -*/ - -import { proxyLazy } from "@utils/lazy"; -import { LazyComponent } from "@utils/lazyReact"; -import { Logger } from "@utils/Logger"; -import { canonicalizeMatch } from "@utils/patches"; -import type { WebpackInstance } from "discord-types/other"; - -import { traceFunction } from "../debug/Tracer"; - -const logger = new Logger("Webpack"); - -export let _resolveReady: () => void; -/** - * Fired once a gateway connection to Discord has been established. - * This indicates that the core webpack modules have been initialised - */ -export const onceReady = new Promise(r => _resolveReady = r); - -export let wreq: WebpackInstance; -export let cache: WebpackInstance["c"]; - -export type FilterFn = (mod: any) => boolean; - -export const filters = { - byProps: (...props: string[]): FilterFn => - props.length === 1 - ? m => m[props[0]] !== void 0 - : m => props.every(p => m[p] !== void 0), - - byCode: (...code: string[]): FilterFn => m => { - if (typeof m !== "function") return false; - const s = Function.prototype.toString.call(m); - for (const c of code) { - if (!s.includes(c)) return false; - } - return true; - }, - byStoreName: (name: string): FilterFn => m => - m.constructor?.displayName === name, - - componentByCode: (...code: string[]): FilterFn => { - const filter = filters.byCode(...code); - return m => { - if (filter(m)) return true; - if (!m.$$typeof) return false; - if (m.type && m.type.render) return filter(m.type.render); // memo + forwardRef - if (m.type) return filter(m.type); // memos - if (m.render) return filter(m.render); // forwardRefs - return false; - }; - } -}; - -export type CallbackFn = (mod: any, id: string) => void; - -export const subscriptions = new Map(); -export const moduleListeners = new Set(); -export const factoryListeners = new Set<(factory: (module: any, exports: any, require: WebpackInstance) => void) => void>(); -export const beforeInitListeners = new Set<(wreq: WebpackInstance) => void>(); - -export function _initWebpack(webpackRequire: WebpackInstance) { - wreq = webpackRequire; - cache = webpackRequire.c; -} - -let devToolsOpen = false; -if (IS_DEV && IS_DISCORD_DESKTOP) { - // At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed - setTimeout(() => { - DiscordNative/* just to make sure */?.window.setDevtoolsCallbacks(() => devToolsOpen = true, () => devToolsOpen = false); - }, 0); -} - -export function handleModuleNotFound(method: string, ...filter: unknown[]) { - const err = new Error(`webpack.${method} found no module`); - logger.error(err, "Filter:", filter); - - // Strict behaviour in DevBuilds to fail early and make sure the issue is found - if (IS_DEV && !devToolsOpen) - throw err; -} - -/** - * Find the first module that matches the filter - */ -export const find = traceFunction("find", function find(filter: FilterFn, { isIndirect = false, isWaitFor = false }: { isIndirect?: boolean; isWaitFor?: boolean; } = {}) { - if (typeof filter !== "function") - throw new Error("Invalid filter. Expected a function got " + typeof filter); - - for (const key in cache) { - const mod = cache[key]; - if (!mod?.exports || mod.exports === window) continue; - - if (filter(mod.exports)) { - return isWaitFor ? [mod.exports, key] : mod.exports; - } - - if (mod.exports.default && mod.exports.default !== window && filter(mod.exports.default)) { - const found = mod.exports.default; - return isWaitFor ? [found, key] : found; - } - } - - if (!isIndirect) { - handleModuleNotFound("find", filter); - } - - return isWaitFor ? [null, null] : null; -}); - -export function findAll(filter: FilterFn) { - if (typeof filter !== "function") - throw new Error("Invalid filter. Expected a function got " + typeof filter); - - const ret = [] as any[]; - for (const key in cache) { - const mod = cache[key]; - if (!mod?.exports) continue; - - if (filter(mod.exports)) - ret.push(mod.exports); - - if (mod.exports.default && filter(mod.exports.default)) - ret.push(mod.exports.default); - } - - return ret; -} - -/** - * Same as {@link find} but in bulk - * @param filterFns Array of filters. Please note that this array will be modified in place, so if you still - * need it afterwards, pass a copy. - * @returns Array of results in the same order as the passed filters - */ -export const findBulk = traceFunction("findBulk", function findBulk(...filterFns: FilterFn[]) { - if (!Array.isArray(filterFns)) - throw new Error("Invalid filters. Expected function[] got " + typeof filterFns); - - const { length } = filterFns; - - if (length === 0) - throw new Error("Expected at least two filters."); - - if (length === 1) { - if (IS_DEV) { - throw new Error("bulk called with only one filter. Use find"); - } - return find(filterFns[0]); - } - - const filters = filterFns as Array; - - let found = 0; - const results = Array(length); - - outer: - for (const key in cache) { - const mod = cache[key]; - if (!mod?.exports) continue; - - for (let j = 0; j < length; j++) { - const filter = filters[j]; - // Already done - if (filter === undefined) continue; - - if (filter(mod.exports)) { - results[j] = mod.exports; - filters[j] = undefined; - if (++found === length) break outer; - break; - } - - if (mod.exports.default && filter(mod.exports.default)) { - results[j] = mod.exports.default; - filters[j] = undefined; - if (++found === length) break outer; - break; - } - } - } - - if (found !== length) { - const err = new Error(`Got ${length} filters, but only found ${found} modules!`); - if (IS_DEV) { - if (!devToolsOpen) - // Strict behaviour in DevBuilds to fail early and make sure the issue is found - throw err; - } else { - logger.warn(err); - } - } - - return results; -}); - -/** - * Find the id of the first module factory that includes all the given code - * @returns string or null - */ -export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) { - outer: - for (const id in wreq.m) { - const str = wreq.m[id].toString(); - - for (const c of code) { - if (!str.includes(c)) continue outer; - } - return id; - } - - const err = new Error("Didn't find module with code(s):\n" + code.join("\n")); - if (IS_DEV) { - if (!devToolsOpen) - // Strict behaviour in DevBuilds to fail early and make sure the issue is found - throw err; - } else { - logger.warn(err); - } - - return null; -}); - -/** - * Find the first module factory that includes all the given code - * @returns The module factory or null - */ -export function findModuleFactory(...code: string[]) { - const id = findModuleId(...code); - if (!id) return null; - - return wreq.m[id]; -} - -export const lazyWebpackSearchHistory = [] as Array<["find" | "findByProps" | "findByCode" | "findStore" | "findComponent" | "findComponentByCode" | "findExportedComponent" | "waitFor" | "waitForComponent" | "waitForStore" | "proxyLazyWebpack" | "LazyComponentWebpack" | "extractAndLoadChunks", any[]]>; - -/** - * This is just a wrapper around {@link proxyLazy} to make our reporter test for your webpack finds. - * - * Wraps the result of {@link makeLazy} in a Proxy you can consume as if it wasn't lazy. - * On first property access, the lazy is evaluated - * @param factory lazy factory - * @param attempts how many times to try to evaluate the lazy before giving up - * @returns Proxy - * - * Note that the example below exists already as an api, see {@link findByPropsLazy} - * @example const mod = proxyLazy(() => findByProps("blah")); console.log(mod.blah); - */ -export function proxyLazyWebpack(factory: () => any, attempts?: number) { - if (IS_DEV) lazyWebpackSearchHistory.push(["proxyLazyWebpack", [factory]]); - - return proxyLazy(factory, attempts); -} - -/** - * This is just a wrapper around {@link LazyComponent} to make our reporter test for your webpack finds. - * - * A lazy component. The factory method is called on first render. - * @param factory Function returning a Component - * @param attempts How many times to try to get the component before giving up - * @returns Result of factory function - */ -export function LazyComponentWebpack(factory: () => any, attempts?: number) { - if (IS_DEV) lazyWebpackSearchHistory.push(["LazyComponentWebpack", [factory]]); - - return LazyComponent(factory, attempts); -} - -/** - * Find the first module that matches the filter, lazily - */ -export function findLazy(filter: FilterFn) { - if (IS_DEV) lazyWebpackSearchHistory.push(["find", [filter]]); - - return proxyLazy(() => find(filter)); -} - -/** - * Find the first module that has the specified properties - */ -export function findByProps(...props: string[]) { - const res = find(filters.byProps(...props), { isIndirect: true }); - if (!res) - handleModuleNotFound("findByProps", ...props); - return res; -} - -/** - * Find the first module that has the specified properties, lazily - */ -export function findByPropsLazy(...props: string[]) { - if (IS_DEV) lazyWebpackSearchHistory.push(["findByProps", props]); - - return proxyLazy(() => findByProps(...props)); -} - -/** - * Find the first function that includes all the given code - */ -export function findByCode(...code: string[]) { - const res = find(filters.byCode(...code), { isIndirect: true }); - if (!res) - handleModuleNotFound("findByCode", ...code); - return res; -} - -/** - * Find the first function that includes all the given code, lazily - */ -export function findByCodeLazy(...code: string[]) { - if (IS_DEV) lazyWebpackSearchHistory.push(["findByCode", code]); - - return proxyLazy(() => findByCode(...code)); -} - -/** - * Find a store by its displayName - */ -export function findStore(name: string) { - const res = find(filters.byStoreName(name), { isIndirect: true }); - if (!res) - handleModuleNotFound("findStore", name); - return res; -} - -/** - * Find a store by its displayName, lazily - */ -export function findStoreLazy(name: string) { - if (IS_DEV) lazyWebpackSearchHistory.push(["findStore", [name]]); - - return proxyLazy(() => findStore(name)); -} - -/** - * Finds the component which includes all the given code. Checks for plain components, memos and forwardRefs - */ -export function findComponentByCode(...code: string[]) { - const res = find(filters.componentByCode(...code), { isIndirect: true }); - if (!res) - handleModuleNotFound("findComponentByCode", ...code); - return res; -} - -/** - * Finds the first component that matches the filter, lazily. - */ -export function findComponentLazy(filter: FilterFn) { - if (IS_DEV) lazyWebpackSearchHistory.push(["findComponent", [filter]]); - - - return LazyComponent(() => { - const res = find(filter, { isIndirect: true }); - if (!res) - handleModuleNotFound("findComponent", filter); - return res; - }); -} - -/** - * Finds the first component that includes all the given code, lazily - */ -export function findComponentByCodeLazy(...code: string[]) { - if (IS_DEV) lazyWebpackSearchHistory.push(["findComponentByCode", code]); - - return LazyComponent(() => { - const res = find(filters.componentByCode(...code), { isIndirect: true }); - if (!res) - handleModuleNotFound("findComponentByCode", ...code); - return res; - }); -} - -/** - * Finds the first component that is exported by the first prop name, lazily - */ -export function findExportedComponentLazy(...props: string[]) { - if (IS_DEV) lazyWebpackSearchHistory.push(["findExportedComponent", props]); - - return LazyComponent(() => { - const res = find(filters.byProps(...props), { isIndirect: true }); - if (!res) - handleModuleNotFound("findExportedComponent", ...props); - return res[props[0]]; - }); -} - -const DefaultExtractAndLoadChunksRegex = /(?:Promise\.all\((\[\i\.\i\(".+?"\).+?\])\)|Promise\.resolve\(\)).then\(\i\.bind\(\i,"(.+?)"\)\)/; - -/** - * Extract and load chunks using their entry point - * @param code An array of all the code the module factory containing the lazy chunk loading must include - * @param matcher A RegExp that returns the chunk ids array as the first capture group and the entry point id as the second. Defaults to a matcher that captures the lazy chunk loading found in the module factory - * @returns A promise that resolves when the chunks were loaded - */ -export async function extractAndLoadChunks(code: string[], matcher: RegExp = DefaultExtractAndLoadChunksRegex) { - const module = findModuleFactory(...code); - if (!module) { - const err = new Error("extractAndLoadChunks: Couldn't find module factory"); - logger.warn(err, "Code:", code, "Matcher:", matcher); - - return; - } - - const match = module.toString().match(canonicalizeMatch(matcher)); - if (!match) { - const err = new Error("extractAndLoadChunks: Couldn't find chunk loading in module factory code"); - logger.warn(err, "Code:", code, "Matcher:", matcher); - - // Strict behaviour in DevBuilds to fail early and make sure the issue is found - if (IS_DEV && !devToolsOpen) - throw err; - - return; - } - - const [, rawChunkIds, entryPointId] = match; - if (Number.isNaN(entryPointId)) { - const err = new Error("extractAndLoadChunks: Matcher didn't return a capturing group with the chunk ids array, or the entry point id returned as the second group wasn't a number"); - logger.warn(err, "Code:", code, "Matcher:", matcher); - - // Strict behaviour in DevBuilds to fail early and make sure the issue is found - if (IS_DEV && !devToolsOpen) - throw err; - - return; - } - - if (rawChunkIds) { - const chunkIds = Array.from(rawChunkIds.matchAll(/\("(.+?)"\)/g)).map((m: any) => m[1]); - await Promise.all(chunkIds.map(id => wreq.e(id))); - } - - wreq(entryPointId); -} - -/** - * This is just a wrapper around {@link extractAndLoadChunks} to make our reporter test for your webpack finds. - * - * Extract and load chunks using their entry point - * @param code An array of all the code the module factory containing the lazy chunk loading must include - * @param matcher A RegExp that returns the chunk ids array as the first capture group and the entry point id as the second. Defaults to a matcher that captures the lazy chunk loading found in the module factory - * @returns A function that returns a promise that resolves when the chunks were loaded, on first call - */ -export function extractAndLoadChunksLazy(code: string[], matcher = DefaultExtractAndLoadChunksRegex) { - if (IS_DEV) lazyWebpackSearchHistory.push(["extractAndLoadChunks", [code, matcher]]); - - return () => extractAndLoadChunks(code, matcher); -} - -/** - * Wait for a module that matches the provided filter to be registered, - * then call the callback with the module as the first argument - */ -export function waitFor(filter: string | string[] | FilterFn, callback: CallbackFn, { isIndirect = false }: { isIndirect?: boolean; } = {}) { - if (IS_DEV && !isIndirect) lazyWebpackSearchHistory.push(["waitFor", Array.isArray(filter) ? filter : [filter]]); - - if (typeof filter === "string") - filter = filters.byProps(filter); - else if (Array.isArray(filter)) - filter = filters.byProps(...filter); - else if (typeof filter !== "function") - throw new Error("filter must be a string, string[] or function, got " + typeof filter); - - if (cache != null) { - const [existing, id] = find(filter, { isIndirect: true, isWaitFor: true }); - if (existing) return void callback(existing, id); - } - - subscriptions.set(filter, callback); -} - -/** - * Search modules by keyword. This searches the factory methods, - * meaning you can search all sorts of things, displayName, methodName, strings somewhere in the code, etc - * @param filters One or more strings or regexes - * @returns Mapping of found modules - */ -export function search(...filters: Array) { - const results = {} as Record; - const factories = wreq.m; - outer: - for (const id in factories) { - const factory = factories[id].original ?? factories[id]; - const str: string = factory.toString(); - for (const filter of filters) { - if (typeof filter === "string" && !str.includes(filter)) continue outer; - if (filter instanceof RegExp && !filter.test(str)) continue outer; - } - results[id] = factory; - } - - return results; -} - -/** - * Extract a specific module by id into its own Source File. This has no effect on - * the code, it is only useful to be able to look at a specific module without having - * to view a massive file. extract then returns the extracted module so you can jump to it. - * As mentioned above, note that this extracted module is not actually used, - * so putting breakpoints or similar will have no effect. - * @param id The id of the module to extract - */ -export function extract(id: string | number) { - const mod = wreq.m[id] as Function; - if (!mod) return null; - - const code = ` -// [EXTRACTED] WebpackModule${id} -// WARNING: This module was extracted to be more easily readable. -// This module is NOT ACTUALLY USED! This means putting breakpoints will have NO EFFECT!! - -0,${mod.toString()} -//# sourceURL=ExtractedWebpackModule${id} -`; - const extracted = (0, eval)(code); - return extracted as Function; -} diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx new file mode 100644 index 000000000..73f7c5c73 --- /dev/null +++ b/src/webpack/webpack.tsx @@ -0,0 +1,609 @@ +/* + * Vencord, a modification for Discord's desktop app + * Copyright (c) 2022 Vendicated and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +import { proxyLazy } from "@utils/lazy"; +import { LazyComponent } from "@utils/lazyReact"; +import { Logger } from "@utils/Logger"; +import { canonicalizeMatch } from "@utils/patches"; +import { proxyInner, proxyInnerValue } from "@utils/proxyInner"; +import type { WebpackInstance } from "discord-types/other"; + +import { traceFunction } from "../debug/Tracer"; + +const logger = new Logger("Webpack"); + +export let _resolveReady: () => void; +/** + * Fired once a gateway connection to Discord has been established. + * This indicates that the core webpack modules have been initialised + */ +export const onceReady = new Promise(r => _resolveReady = r); + +export let wreq: WebpackInstance; +export let cache: WebpackInstance["c"]; + +export type FilterFn = (mod: any) => boolean; + +export const filters = { + byProps: (...props: string[]): FilterFn => { + const filter = props.length === 1 + ? m => m?.[props[0]] !== void 0 + : m => props.every(p => m?.[p] !== void 0); + + // @ts-ignore + filter.$$vencordProps = ["byProps", ...props]; + return filter; + }, + + byCode: (...code: string[]): FilterFn => { + const filter = m => { + if (typeof m !== "function") return false; + const s = Function.prototype.toString.call(m); + for (const c of code) { + if (!s.includes(c)) return false; + } + return true; + }; + + filter.$$vencordProps = ["byCode", ...code]; + return filter; + }, + + byStoreName: (name: string): FilterFn => { + const filter = m => m?.constructor?.displayName === name; + + filter.$$vencordProps = ["byStoreName", name]; + return filter; + }, + + componentByCode: (...code: string[]): FilterFn => { + const filter = filters.byCode(...code); + const wrapper = m => { + if (filter(m)) return true; + if (!m?.$$typeof) return false; + if (m?.type && m.type.render) return filter(m.type.render); // memo + forwardRef + if (m?.type) return filter(m.type); // memos + if (m?.render) return filter(m.render); // forwardRefs + return false; + }; + + wrapper.$$vencordProps = ["componentByCode", ...code]; + return wrapper; + } +}; + +export type ModCallbackFn = (mod: any) => void; +export type ModCallbackFnWithId = (mod: any, id: string) => void; + +export const waitForSubscriptions = new Map(); +export const moduleListeners = new Set(); +export const factoryListeners = new Set<(factory: (module: any, exports: any, require: WebpackInstance) => void) => void>(); +export const beforeInitListeners = new Set<(wreq: WebpackInstance) => void>(); + +export function _initWebpack(webpackRequire: WebpackInstance) { + wreq = webpackRequire; + cache = webpackRequire.c; +} + +let devToolsOpen = false; +if (IS_DEV && IS_DISCORD_DESKTOP) { + // At this point in time, DiscordNative has not been exposed yet, so setImmediate is needed + setTimeout(() => { + DiscordNative/* just to make sure */?.window.setDevtoolsCallbacks(() => devToolsOpen = true, () => devToolsOpen = false); + }, 0); +} + +export const webpackSearchHistory = [] as Array<["waitFor" | "find" | "findComponent" | "findExportedComponent" | "findComponentByCode" | "findByProps" | "findByCode" | "findStore" | "extractAndLoadChunks" | "webpackDependantLazy" | "webpackDependantLazyComponent", any[]]>; + +function printFilter(filter: FilterFn) { + if ("$$vencordProps" in filter) { + const props = filter.$$vencordProps as string[]; + return `${props[0]}(${props.slice(1).map(arg => `"${arg}"`).join(", ")})`; + } + + return filter.toString(); +} + +/** + * Wait for the first module that matches the provided filter to be required, + * then call the callback with the module as the first argument. + * + * If the module is already required, the callback will be called immediately. + * @param filter A function that takes a module and returns a boolean + * @param callback A function that takes the found module as its first argument + */ +export function waitFor(filter: FilterFn, callback: ModCallbackFn, { isIndirect = false }: { isIndirect?: boolean; } = {}) { + if (typeof filter !== "function") + throw new Error("Invalid filter. Expected a function got " + typeof filter); + if (typeof callback !== "function") + throw new Error("Invalid callback. Expected a function got " + typeof callback); + + if (IS_DEV && !isIndirect) webpackSearchHistory.push(["waitFor", [filter]]); + + if (cache != null) { + const existing = cacheFind(filter); + if (existing) return callback(existing); + } + + waitForSubscriptions.set(filter, callback); +} + +/** + * Find the first module that matches the filter. + * + * The way this works internally is: + * Wait for the first module that matches the provided filter to be required, + * then call the callback with the module as the first argument. + * + * If the module is already required, the callback will be called immediately. + * + * The callback must return a value that will be used as the proxy inner value. + * + * If no callback is specified, the default callback will assign the proxy inner value to all the module + * @param filter A function that takes a module and returns a boolean + * @param callback A function that takes the found module as its first argument and returns to use as the proxy inner value + * @returns A proxy that has the callback return value as its true value, or the callback return value if the callback was called when the function was called + */ +export function find(filter: FilterFn, callback: (mod: any) => any = m => m, { isIndirect = false }: { isIndirect?: boolean; } = {}) { + if (typeof filter !== "function") + throw new Error("Invalid filter. Expected a function got " + typeof filter); + if (typeof callback !== "function") + throw new Error("Invalid callback. Expected a function got " + typeof callback); + + if (IS_DEV && !isIndirect) webpackSearchHistory.push(["find", [filter]]); + + const [proxy, setInnerValue] = proxyInner(new Error(`Webpack find matched no module. Filter: ${printFilter(filter)}`)); + waitFor(filter, mod => setInnerValue(callback(mod)), { isIndirect: true }); + + if (proxy[proxyInnerValue] != null) return proxy[proxyInnerValue] as T; + + return proxy; +} + +/** + * Find the first component that matches the filter. + * @param filter A function that takes a module and returns a boolean + * @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component + * @returns The component if found, or a noop component + */ +export function findComponent(filter: FilterFn, parse: (component: any) => React.ComponentType = m => m, { isIndirect = false }: { isIndirect?: boolean; } = {}) { + if (typeof filter !== "function") + throw new Error("Invalid filter. Expected a function got " + typeof filter); + if (typeof parse !== "function") + throw new Error("Invalid component parse. Expected a function got " + typeof parse); + + if (IS_DEV && !isIndirect) webpackSearchHistory.push(["findComponent", [filter]]); + + let noMatchLogged = false; + const NoopComponent = (() => { + if (!noMatchLogged) { + noMatchLogged = true; + logger.error(`Webpack find matched no module. Filter: ${printFilter(filter)}`); + } + + return null; + }) as React.ComponentType; + + let InnerComponent = NoopComponent; + + const WrapperComponent = (props: T) => { + return ; + }; + + WrapperComponent.$$vencordGetter = () => InnerComponent; + + waitFor(filter, (v: any) => { + const parsedComponent = parse(v); + InnerComponent = parsedComponent; + Object.assign(InnerComponent, parsedComponent); + }, { isIndirect: true }); + + if (InnerComponent !== NoopComponent) return InnerComponent; + + return WrapperComponent; +} + +/** + * Find the first component that is exported by the first prop name. + * + * @example findExportedComponent("FriendRow") + * @example findExportedComponent("FriendRow", "Friend", FriendRow => React.memo(FriendRow)) + * + * @param props A list of prop names to search the exports for + * @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component + * @returns The component if found, or a noop component + */ +export function findExportedComponent(...props: string[] | [...string[], (component: any) => React.ComponentType]) { + const parse = (typeof props.at(-1) === "function" ? props.pop() : m => m) as (component: any) => React.ComponentType; + const newProps = props as string[]; + + const filter = filters.byProps(...newProps); + + if (IS_DEV) webpackSearchHistory.push(["findExportedComponent", props]); + + let noMatchLogged = false; + const NoopComponent = (() => { + if (!noMatchLogged) { + noMatchLogged = true; + logger.error(`Webpack find matched no module. Filter: ${printFilter(filter)}`); + } + + return null; + }) as React.ComponentType; + + let InnerComponent = NoopComponent; + + const WrapperComponent = (props: T) => { + return ; + }; + + WrapperComponent.$$vencordGetter = () => InnerComponent; + + waitFor(filter, (v: any) => { + const parsedComponent = parse(v[newProps[0]]); + InnerComponent = parsedComponent; + Object.assign(InnerComponent, parsedComponent); + }, { isIndirect: true }); + + if (InnerComponent !== NoopComponent) return InnerComponent; + + return WrapperComponent as React.ComponentType; +} + +/** + * Find the first component that 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)) + * + * @param code A list of code to search each export for + * @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component + * @returns The component if found, or a noop component + */ +export function findComponentByCode(...code: string[] | [...string[], (component: any) => React.ComponentType]) { + const parse = (typeof code.at(-1) === "function" ? code.pop() : m => m) as (component: any) => React.ComponentType; + const newCode = code as string[]; + + if (IS_DEV) webpackSearchHistory.push(["findComponentByCode", code]); + + return findComponent(filters.componentByCode(...newCode), parse, { isIndirect: true }); +} + +/** + * Find the first module or default export that includes all the given props + * + * @param props A list of props to search the exports for + */ +export function findByProps(...props: string[]) { + if (IS_DEV) webpackSearchHistory.push(["findByProps", props]); + + return find(filters.byProps(...props), m => m, { isIndirect: true }); +} + +/** + * Find the first export that includes all the given code + * + * @param code A list of code to search each export for + */ +export function findByCode(...code: string[]) { + if (IS_DEV) webpackSearchHistory.push(["findByCode", code]); + + return find(filters.byCode(...code), m => m, { isIndirect: true }); +} + +/** + * Find a store by its name + * + * @param name The store name + */ +export function findStore(name: string) { + if (IS_DEV) webpackSearchHistory.push(["findStore", [name]]); + + return find(filters.byStoreName(name), m => m, { isIndirect: true }); +} + +/** + * Find the first already required module that matches the filter. + * @param filter A function that takes a module and returns a boolean + * @returns The found module or null + */ +export const cacheFind = traceFunction("find", function find(filter: FilterFn) { + if (typeof filter !== "function") + throw new Error("Invalid filter. Expected a function got " + typeof filter); + + for (const key in cache) { + const mod = cache[key]; + if (!mod?.exports || mod.exports === window) continue; + + if (filter(mod.exports)) { + return mod.exports; + } + + if (mod.exports.default && filter(mod.exports.default)) { + return mod.exports.default; + } + } + + return null; +}); + + +export function cacheFindAll(filter: FilterFn) { + if (typeof filter !== "function") + throw new Error("Invalid filter. Expected a function got " + typeof filter); + + const ret = [] as any[]; + for (const key in cache) { + const mod = cache[key]; + if (!mod?.exports) continue; + + if (filter(mod.exports)) { + ret.push(mod.exports); + } + + if (mod.exports.default && filter(mod.exports.default)) { + ret.push(mod.exports.default); + } + } + + return ret; +} + +/** + * Same as {@link cacheFind} but in bulk + * @param filterFns Array of filters. Please note that this array will be modified in place, so if you still + * need it afterwards, pass a copy. + * @returns Array of results in the same order as the passed filters + */ +export const cacheFindBulk = traceFunction("findBulk", function findBulk(...filterFns: FilterFn[]) { + if (!Array.isArray(filterFns)) + throw new Error("Invalid filters. Expected function[] got " + typeof filterFns); + + const { length } = filterFns; + + if (length === 0) + throw new Error("Expected at least two filters."); + + if (length === 1) { + if (IS_DEV) { + throw new Error("bulk called with only one filter. Use find"); + } + + return cacheFind(filterFns[0]); + } + + let found = 0; + const results = Array(length); + + outer: + for (const key in cache) { + const mod = cache[key]; + if (!mod?.exports) continue; + + for (let j = 0; j < length; j++) { + const filter = filterFns[j]; + + if (filter(mod.exports)) { + results[j] = mod.exports; + filterFns.splice(j--, 1); + if (++found === length) break outer; + break; + } + + if (mod.exports.default && filter(mod.exports.default)) { + results[j] = mod.exports.default; + filterFns.splice(j--, 1); + if (++found === length) break outer; + break; + } + } + } + + if (found !== length) { + const err = new Error(`Got ${length} filters, but only found ${found} modules!`); + + if (!IS_DEV) { + logger.warn(err); + return results; + } + + if (!devToolsOpen) { + throw err; // Strict behaviour in DevBuilds to fail early and make sure the issue is found + } + } + + return results; +}); + +/** + * Find the id of the first module factory that includes all the given code + * @returns string or null + */ +export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) { + outer: + for (const id in wreq.m) { + const str = wreq.m[id].toString(); + + for (const c of code) { + if (!str.includes(c)) continue outer; + } + return id; + } + + const err = new Error("Didn't find module with code(s):\n" + code.join("\n")); + if (!IS_DEV) { + logger.warn(err); + return null; + } + + if (!devToolsOpen) { + throw err; // Strict behaviour in DevBuilds to fail early and make sure the issue is found + } + + return null; +}); + +/** + * Find the first module factory that includes all the given code + * @returns The module factory or null + */ +export function findModuleFactory(...code: string[]) { + const id = findModuleId(...code); + if (!id) return null; + + return wreq.m[id]; +} + +/** + * This is just a wrapper around {@link proxyLazy} to make our reporter test for your webpack finds. + * + * Wraps the result of factory in a Proxy you can consume as if it wasn't lazy. + * On first property access, the factory is evaluated + * @param factory Factory returning the result + * @param attempts How many times to try to evaluate the factory before giving up + * @returns Result of factory function + */ +export function webpackDependantLazy(factory: () => any, attempts?: number) { + if (IS_DEV) webpackSearchHistory.push(["webpackDependantLazy", [factory]]); + + return proxyLazy(factory, attempts); +} + +/** + * This is just a wrapper around {@link LazyComponent} to make our reporter test for your webpack finds. + * + * A lazy component. The factory method is called on first render. + * @param factory Function returning a Component + * @param attempts How many times to try to get the component before giving up + * @returns Result of factory function + */ +export function webpackDependantLazyComponent(factory: () => any, attempts?: number) { + if (IS_DEV) webpackSearchHistory.push(["webpackDependantLazyComponent", [factory]]); + + return LazyComponent(factory, attempts); +} + +const DefaultExtractAndLoadChunksRegex = /(?:Promise\.all\((\[\i\.\i\(".+?"\).+?\])\)|Promise\.resolve\(\)).then\(\i\.bind\(\i,"(.+?)"\)\)/; + +/** + * Extract and load chunks using their entry point + * @param code An array of all the code the module factory containing the lazy chunk loading must include + * @param matcher A RegExp that returns the chunk ids array as the first capture group and the entry point id as the second. Defaults to a matcher that captures the lazy chunk loading found in the module factory + * @returns A promise that resolves when the chunks were loaded + */ +export async function extractAndLoadChunks(code: string[], matcher: RegExp = DefaultExtractAndLoadChunksRegex) { + const module = findModuleFactory(...code); + if (!module) { + const err = new Error("extractAndLoadChunks: Couldn't find module factory"); + logger.warn(err, "Code:", code, "Matcher:", matcher); + + return; + } + + const match = module.toString().match(canonicalizeMatch(matcher)); + if (!match) { + const err = new Error("extractAndLoadChunks: Couldn't find chunk loading in module factory code"); + logger.warn(err, "Code:", code, "Matcher:", matcher); + + // Strict behaviour in DevBuilds to fail early and make sure the issue is found + if (IS_DEV && !devToolsOpen) + throw err; + + return; + } + + const [, rawChunkIds, entryPointId] = match; + if (Number.isNaN(entryPointId)) { + const err = new Error("extractAndLoadChunks: Matcher didn't return a capturing group with the chunk ids array, or the entry point id returned as the second group wasn't a number"); + logger.warn(err, "Code:", code, "Matcher:", matcher); + + // Strict behaviour in DevBuilds to fail early and make sure the issue is found + if (IS_DEV && !devToolsOpen) + throw err; + + return; + } + + if (rawChunkIds) { + const chunkIds = Array.from(rawChunkIds.matchAll(/\("(.+?)"\)/g)).map((m: any) => m[1]); + await Promise.all(chunkIds.map(id => wreq.e(id))); + } + + wreq(entryPointId); +} + +/** + * This is just a wrapper around {@link extractAndLoadChunks} to make our reporter test for your webpack finds. + * + * Extract and load chunks using their entry point + * @param code An array of all the code the module factory containing the lazy chunk loading must include + * @param matcher A RegExp that returns the chunk ids array as the first capture group and the entry point id as the second. Defaults to a matcher that captures the lazy chunk loading found in the module factory + * @returns A function that returns a promise that resolves when the chunks were loaded, on first call + */ +export function extractAndLoadChunksLazy(code: string[], matcher = DefaultExtractAndLoadChunksRegex) { + if (IS_DEV) webpackSearchHistory.push(["extractAndLoadChunks", [code, matcher]]); + + return () => extractAndLoadChunks(code, matcher); +} + +/** + * Search modules by keyword. This searches the factory methods, + * meaning you can search all sorts of things, displayName, methodName, strings somewhere in the code, etc + * @param filters One or more strings or regexes + * @returns Mapping of found modules + */ +export function search(...filters: Array) { + const results = {} as Record; + const factories = wreq.m; + outer: + for (const id in factories) { + const factory = factories[id]; + const str: string = factory.toString(); + for (const filter of filters) { + if (typeof filter === "string" && !str.includes(filter)) continue outer; + if (filter instanceof RegExp && !filter.test(str)) continue outer; + } + results[id] = factory; + } + + return results; +} + +/** + * Extract a specific module by id into its own Source File. This has no effect on + * the code, it is only useful to be able to look at a specific module without having + * to view a massive file. extract then returns the extracted module so you can jump to it. + * As mentioned above, note that this extracted module is not actually used, + * so putting breakpoints or similar will have no effect. + * @param id The id of the module to extract + */ +export function extract(id: string | number) { + const mod = wreq.m[id] as Function; + if (!mod) return null; + + const code = ` +// [EXTRACTED] WebpackModule${id} +// WARNING: This module was extracted to be more easily readable. +// This module is NOT ACTUALLY USED! This means putting breakpoints will have NO EFFECT!! + +0,${mod.toString()} +//# sourceURL=ExtractedWebpackModule${id} +`; + const extracted = (0, eval)(code); + return extracted as Function; +} From cd5e0aeec1bf71a13647b3f4a28af880feba64de Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 2 May 2024 23:42:42 -0300 Subject: [PATCH 002/361] throw a rock at ben shapiro --- scripts/generateReport.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 8108e5436..2af192ff3 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -482,21 +482,32 @@ async function runtime(token: string) { if (method === "webpackDependantLazy" || method === "webpackDependantLazyComponent") { const [factory] = args; result = factory(); - if (result != null && "$$vencordGetter" in result) result = result.$$vencordGetter(); + + if (result != null && "$$vencordGetter" in result) { + result = result.$$vencordGetter(); + } } else if (method === "extractAndLoadChunks") { const [code, matcher] = args; const module = Vencord.Webpack.findModuleFactory(...code); - if (module) result = module.toString().match(Vencord.Util.canonicalizeMatch(matcher)); + if (module) { + result = module.toString().match(Vencord.Util.canonicalizeMatch(matcher)); + } } else { result = Vencord.Webpack[method](...args); // If the result is our Proxy or ComponentWrapper, this means the search failed - if (result != null && result[Vencord.Util.proxyInnerGet] != null) result = undefined; - if (result != null && "$$vencordGetter" in result) result = undefined; + if ( + result != null && + (result[Vencord.Util.proxyInnerGet] != null || "$$vencordGetter" in result) + ) { + result = undefined; + } } - if (result == null) throw "find failed"; + if (result == null) { + throw "a rock at ben shapiro"; + } } catch (e) { let logMessage = searchType; From a29115ba78d42d89f6eebe25f32836ed2f44a788 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 01:21:52 -0300 Subject: [PATCH 003/361] Fix ReviewDB --- .../reviewDB/components/ReviewComponent.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/plugins/reviewDB/components/ReviewComponent.tsx b/src/plugins/reviewDB/components/ReviewComponent.tsx index 1526543ad..87bf38c52 100644 --- a/src/plugins/reviewDB/components/ReviewComponent.tsx +++ b/src/plugins/reviewDB/components/ReviewComponent.tsx @@ -30,11 +30,11 @@ import { openBlockModal } from "./BlockedUserModal"; import { BlockButton, DeleteButton, ReportButton } from "./MessageButton"; import ReviewBadge from "./ReviewBadge"; -const { cozyMessage, message, groupStart, buttons, buttonsInner } = findByProps("cozyMessage"); -const { container, isHeader } = findByProps("container", "isHeader"); -const { wrapper, cozy, avatar, clickable, username } = findByProps("avatar", "zalgo"); +const messageClasses = findByProps("cozyMessage"); +const containerClasses = findByProps("container", "isHeader"); +const avatarClasses = findByProps("avatar", "zalgo"); const buttonClasses = findByProps("button", "wrapper", "selected"); -const botTag = findByProps("botTag", "botTagRegular"); +const botTagClasses = findByProps("botTag", "botTagRegular"); const dateFormat = new Intl.DateTimeFormat(); @@ -105,7 +105,7 @@ export default function ReviewComponent({ review, refetch, profileId }: { review } return ( -
openModal()} > @@ -130,9 +130,9 @@ export default function ReviewComponent({ review, refetch, profileId }: { review {review.type === ReviewType.System && ( - + System @@ -163,10 +163,10 @@ export default function ReviewComponent({ review, refetch, profileId }: { review
{review.id !== 0 && ( -
-
+
{canReportReview(review) && } {canBlockReviewAuthor(profileId, review) && } {canDeleteReview(profileId, review) && } From f1dd39885b7775fa3be9a0eb2b0eedaa7dd2b2df Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 01:50:50 -0300 Subject: [PATCH 004/361] Clean up commons --- src/utils/modal.tsx | 1 - src/utils/react.tsx | 2 -- src/webpack/common/classes.ts | 8 ++++---- src/webpack/common/components.ts | 22 ++++++++++---------- src/webpack/common/menu.ts | 1 - src/webpack/common/react.ts | 10 +++++----- src/webpack/common/settingsStores.ts | 9 ++++----- src/webpack/common/stores.ts | 30 ++++++++++++++-------------- src/webpack/common/utils.ts | 1 - 9 files changed, 38 insertions(+), 46 deletions(-) diff --git a/src/utils/modal.tsx b/src/utils/modal.tsx index 4c9962563..800dcc092 100644 --- a/src/utils/modal.tsx +++ b/src/utils/modal.tsx @@ -19,7 +19,6 @@ import { filters, find, findByProps, findExportedComponent } from "@webpack"; import type { ComponentType, PropsWithChildren, ReactNode, Ref } from "react"; - export const enum ModalSize { SMALL = "small", MEDIUM = "medium", diff --git a/src/utils/react.tsx b/src/utils/react.tsx index f31549f19..abae97c53 100644 --- a/src/utils/react.tsx +++ b/src/utils/react.tsx @@ -22,8 +22,6 @@ import { checkIntersecting } from "./misc"; export * from "./lazyReact"; -export const NoopComponent = () => null; - /** * Check if an element is on screen * @param intersectOnly If `true`, will only update the state when the element comes into view diff --git a/src/webpack/common/classes.ts b/src/webpack/common/classes.ts index 7a9eee949..ea41bd693 100644 --- a/src/webpack/common/classes.ts +++ b/src/webpack/common/classes.ts @@ -16,9 +16,9 @@ * along with this program. If not, see . */ -import { find, findByProps } from "@webpack"; - +// eslint-disable-next-line path-alias/no-relative +import { find, findByProps } from "../webpack"; import * as t from "./types/classes"; -export const ModalImageClasses: t.ImageModalClasses = find(m => m.image && m.modal && !m.applicationIcon); -export const ButtonWrapperClasses: t.ButtonWrapperClasses = findByProps("buttonWrapper", "buttonContent"); +export const ModalImageClasses = find(m => m.image && m.modal && !m.applicationIcon); +export const ButtonWrapperClasses = findByProps("buttonWrapper", "buttonContent"); diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index cdf12d997..94f5389bd 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -17,17 +17,9 @@ */ // eslint-disable-next-line path-alias/no-relative -import { filters, findComponent, findExportedComponent, waitFor } from "@webpack"; - +import { filters, find, findComponent, findExportedComponent } from "../webpack"; import * as t from "./types/components"; -export let Forms = {} as { - FormTitle: t.FormTitle, - FormSection: t.FormSection, - FormDivider: t.FormDivider, - FormText: t.FormText, -}; - export let Card: t.Card; export let Button: t.Button; export let Switch: t.Switch; @@ -58,8 +50,7 @@ export const Flex = findComponent(filters.byProps("Justify", "Align export const OAuth2AuthorizeModal = findExportedComponent("OAuth2AuthorizeModal"); -waitFor(filters.byProps("FormItem", "Button"), m => { - Forms = m; +export const Forms = find(filters.byProps("FormItem", "Button"), m => { ({ useToken, Card, @@ -83,4 +74,11 @@ waitFor(filters.byProps("FormItem", "Button"), m => { FocusLock, Heading } = m); -}); + + return m; +}) as { + FormTitle: t.FormTitle, + FormSection: t.FormSection, + FormDivider: t.FormDivider, + FormText: t.FormText, +}; diff --git a/src/webpack/common/menu.ts b/src/webpack/common/menu.ts index a722cf242..aada18f58 100644 --- a/src/webpack/common/menu.ts +++ b/src/webpack/common/menu.ts @@ -23,4 +23,3 @@ import type * as t from "./types/menu"; export const Menu = findByProps("MenuItem", "MenuSliderControl"); export const ContextMenuApi = findByProps("closeContextMenu", "openContextMenu"); - diff --git a/src/webpack/common/react.ts b/src/webpack/common/react.ts index f71517f2c..4a66c4817 100644 --- a/src/webpack/common/react.ts +++ b/src/webpack/common/react.ts @@ -17,9 +17,8 @@ */ // eslint-disable-next-line path-alias/no-relative -import { filters, findByProps,waitFor } from "../webpack"; +import { filters, find, findByProps } from "../webpack"; -export let React: typeof import("react"); export let useState: typeof React.useState; export let useEffect: typeof React.useEffect; export let useMemo: typeof React.useMemo; @@ -29,7 +28,8 @@ export let useCallback: typeof React.useCallback; export const ReactDOM = findByProps("createPortal", "render"); -waitFor(filters.byProps("useState"), m => { - React = m; - ({ useEffect, useState, useMemo, useRef, useReducer, useCallback } = React); +export const React = find(filters.byProps("useState"), m => { + ({ useEffect, useState, useMemo, useRef, useReducer, useCallback } = m); + + return m; }); diff --git a/src/webpack/common/settingsStores.ts b/src/webpack/common/settingsStores.ts index e4da26b31..326a09019 100644 --- a/src/webpack/common/settingsStores.ts +++ b/src/webpack/common/settingsStores.ts @@ -4,12 +4,11 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { findByProps } from "@webpack"; - +// eslint-disable-next-line path-alias/no-relative +import { findByProps } from "../webpack"; import * as t from "./types/settingsStores"; - -export const TextAndImagesSettingsStores = findByProps("MessageDisplayCompact") as Record; -export const StatusSettingsStores = findByProps("ShowCurrentGame") as Record; +export const TextAndImagesSettingsStores = findByProps>("MessageDisplayCompact"); +export const StatusSettingsStores = findByProps>("ShowCurrentGame"); export const UserSettingsActionCreators = findByProps("PreloadedUserSettingsActionCreators"); diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 5ab4651e8..d7e7cd60a 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -22,7 +22,7 @@ import type * as Stores from "discord-types/stores"; import { findByProps, findStore } from "../webpack"; import * as t from "./types/stores"; -export const Flux: t.Flux = findByProps("connectStores"); +export const Flux = findByProps("connectStores"); export type GenericStore = t.FluxStore & Record; @@ -39,26 +39,26 @@ export const MessageStore = findStore("MessageStore") as Omit("PermissionStore"); +export const GuildChannelStore = findStore("GuildChannelStore"); +export const ReadStateStore = findStore("ReadStateStore"); +export const PresenceStore = findStore("PresenceStore"); -export const GuildStore: t.GuildStore = findStore("GuildStore"); -export const UserStore: Stores.UserStore & t.FluxStore = findStore("UserStore"); -export const UserProfileStore: GenericStore = findStore("UserProfileStore"); -export const SelectedChannelStore: Stores.SelectedChannelStore & t.FluxStore = findStore("SelectedChannelStore"); -export const SelectedGuildStore: t.FluxStore & Record = findStore("SelectedGuildStore"); -export const ChannelStore: Stores.ChannelStore & t.FluxStore = findStore("ChannelStore"); -export const GuildMemberStore: Stores.GuildMemberStore & t.FluxStore = findStore("GuildMemberStore"); +export const GuildStore = findStore("GuildStore"); +export const UserStore = findStore("UserStore"); +export const UserProfileStore = findStore("UserProfileStore"); +export const SelectedChannelStore = findStore("SelectedChannelStore"); +export const SelectedGuildStore = findStore("SelectedGuildStore"); +export const ChannelStore = findStore("ChannelStore"); +export const GuildMemberStore = findStore("GuildMemberStore"); export const RelationshipStore = findStore("RelationshipStore") as Stores.RelationshipStore & t.FluxStore & { /** Get the date (as a string) that the relationship was created */ getSince(userId: string): string; }; -export const EmojiStore: t.EmojiStore = findStore("EmojiStore"); -export const WindowStore: t.WindowStore = findStore("WindowStore"); -export const DraftStore: t.DraftStore = findStore("DraftStore"); +export const EmojiStore = findStore("EmojiStore"); +export const WindowStore = findStore("WindowStore"); +export const DraftStore = findStore("DraftStore"); /** * React hook that returns stateful data for one or more stores diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 3f50c3054..07fd2f7df 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -90,7 +90,6 @@ export const Toasts = { } }; -// This is the same module but this is easier waitFor(filters.byCode("showToast"), m => { Toasts.show = m.showToast; Toasts.pop = m.popToast; From 770078f23635fdba0b56eee57390dcb2b970a0f6 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 04:49:14 -0300 Subject: [PATCH 005/361] More things --- src/components/PluginSettings/PluginModal.tsx | 2 +- src/plugins/messageLinkEmbeds/index.tsx | 2 +- src/plugins/moreUserTags/index.tsx | 3 +- src/plugins/pinDms/settings.ts | 94 ------------------- .../serverProfile/GuildProfileModal.tsx | 2 +- .../components/HiddenChannelLockScreen.tsx | 2 +- .../components/VoiceChannelSection.tsx | 2 +- src/plugins/whoReacted/index.tsx | 2 +- src/utils/modal.tsx | 1 + src/webpack/patchWebpack.ts | 2 +- 10 files changed, 9 insertions(+), 103 deletions(-) delete mode 100644 src/plugins/pinDms/settings.ts diff --git a/src/components/PluginSettings/PluginModal.tsx b/src/components/PluginSettings/PluginModal.tsx index f62da7632..e8f2ac425 100644 --- a/src/components/PluginSettings/PluginModal.tsx +++ b/src/components/PluginSettings/PluginModal.tsx @@ -25,7 +25,7 @@ import { Margins } from "@utils/margins"; import { classes, isObjectEmpty } from "@utils/misc"; import { ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalProps, ModalRoot, ModalSize } from "@utils/modal"; import { OptionType, Plugin } from "@utils/types"; -import { findByProps,findComponentByCode } from "@webpack"; +import { findByProps, findComponentByCode } from "@webpack"; import { Button, Clickable, FluxDispatcher, Forms, React, Text, Tooltip, UserStore, UserUtils } from "@webpack/common"; import { User } from "discord-types/general"; import { Constructor } from "type-fest"; diff --git a/src/plugins/messageLinkEmbeds/index.tsx b/src/plugins/messageLinkEmbeds/index.tsx index 29da765e2..2d525bd34 100644 --- a/src/plugins/messageLinkEmbeds/index.tsx +++ b/src/plugins/messageLinkEmbeds/index.tsx @@ -23,7 +23,7 @@ import { Devs } from "@utils/constants.js"; import { classes } from "@utils/misc"; import { Queue } from "@utils/Queue"; import definePlugin, { OptionType } from "@utils/types"; -import { findByProps,findComponentByCode } from "@webpack"; +import { findByProps, findComponentByCode } from "@webpack"; import { Button, ChannelStore, diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 0ea8c098d..d28beeb39 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -23,7 +23,6 @@ import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; import { find, findByProps } from "@webpack"; import { Card, ChannelStore, Forms, GuildStore, PermissionsBits, Switch, TextInput, Tooltip, useState } from "@webpack/common"; -import { RC } from "@webpack/types"; import { Channel, Message, User } from "discord-types/general"; type PermissionName = "CREATE_INSTANT_INVITE" | "KICK_MEMBERS" | "BAN_MEMBERS" | "ADMINISTRATOR" | "MANAGE_CHANNELS" | "MANAGE_GUILD" | "CHANGE_NICKNAME" | "MANAGE_NICKNAMES" | "MANAGE_ROLES" | "MANAGE_WEBHOOKS" | "MANAGE_GUILD_EXPRESSIONS" | "CREATE_GUILD_EXPRESSIONS" | "VIEW_AUDIT_LOG" | "VIEW_CHANNEL" | "VIEW_GUILD_ANALYTICS" | "VIEW_CREATOR_MONETIZATION_ANALYTICS" | "MODERATE_MEMBERS" | "SEND_MESSAGES" | "SEND_TTS_MESSAGES" | "MANAGE_MESSAGES" | "EMBED_LINKS" | "ATTACH_FILES" | "READ_MESSAGE_HISTORY" | "MENTION_EVERYONE" | "USE_EXTERNAL_EMOJIS" | "ADD_REACTIONS" | "USE_APPLICATION_COMMANDS" | "MANAGE_THREADS" | "CREATE_PUBLIC_THREADS" | "CREATE_PRIVATE_THREADS" | "USE_EXTERNAL_STICKERS" | "SEND_MESSAGES_IN_THREADS" | "CONNECT" | "SPEAK" | "MUTE_MEMBERS" | "DEAFEN_MEMBERS" | "MOVE_MEMBERS" | "USE_VAD" | "PRIORITY_SPEAKER" | "STREAM" | "USE_EMBEDDED_ACTIVITIES" | "USE_SOUNDBOARD" | "USE_EXTERNAL_SOUNDS" | "REQUEST_TO_SPEAK" | "MANAGE_EVENTS" | "CREATE_EVENTS"; @@ -58,7 +57,7 @@ const PermissionUtil = findByProps("computePermissions", "canEveryoneRole") as { computePermissions({ ...args }): bigint; }; -const Tag = find(m => m.Types?.[0] === "BOT") as RC<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; +const Tag = find(m => m.Types?.[0] === "BOT") as React.ComponentType<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot(); diff --git a/src/plugins/pinDms/settings.ts b/src/plugins/pinDms/settings.ts deleted file mode 100644 index 386b662d1..000000000 --- a/src/plugins/pinDms/settings.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2023 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -import { definePluginSettings, Settings, useSettings } from "@api/Settings"; -import { OptionType } from "@utils/types"; -import { findStore } from "@webpack"; - -export const enum PinOrder { - LastMessage, - Custom -} - -export const settings = definePluginSettings({ - pinOrder: { - type: OptionType.SELECT, - description: "Which order should pinned DMs be displayed in?", - options: [ - { label: "Most recent message", value: PinOrder.LastMessage, default: true }, - { label: "Custom (right click channels to reorder)", value: PinOrder.Custom } - ] - } -}); - -const PrivateChannelSortStore = findStore("PrivateChannelSortStore"); - -export let snapshotArray: string[]; -let snapshot: Set | undefined; - -const getArray = () => (Settings.plugins.PinDMs.pinnedDMs || void 0)?.split(",") as string[] | undefined; -const save = (pins: string[]) => { - snapshot = void 0; - Settings.plugins.PinDMs.pinnedDMs = pins.join(","); -}; -const takeSnapshot = () => { - snapshotArray = getArray() ?? []; - return snapshot = new Set(snapshotArray); -}; -const requireSnapshot = () => snapshot ?? takeSnapshot(); - -export function usePinnedDms() { - useSettings(["plugins.PinDMs.pinnedDMs"]); - - return requireSnapshot(); -} - -export function isPinned(id: string) { - return requireSnapshot().has(id); -} - -export function togglePin(id: string) { - const snapshot = requireSnapshot(); - if (!snapshot.delete(id)) { - snapshot.add(id); - } - - save([...snapshot]); -} - -export function sortedSnapshot() { - requireSnapshot(); - if (settings.store.pinOrder === PinOrder.LastMessage) - return PrivateChannelSortStore.getPrivateChannelIds().filter(isPinned); - - return snapshotArray; -} - -export function getPinAt(idx: number) { - return sortedSnapshot()[idx]; -} - -export function movePin(id: string, direction: -1 | 1) { - const pins = getArray()!; - const a = pins.indexOf(id); - const b = a + direction; - - [pins[a], pins[b]] = [pins[b], pins[a]]; - - save(pins); -} diff --git a/src/plugins/serverProfile/GuildProfileModal.tsx b/src/plugins/serverProfile/GuildProfileModal.tsx index 0621df8db..4e4b926e7 100644 --- a/src/plugins/serverProfile/GuildProfileModal.tsx +++ b/src/plugins/serverProfile/GuildProfileModal.tsx @@ -11,7 +11,7 @@ import { openImageModal, openUserProfile } from "@utils/discord"; import { classes } from "@utils/misc"; import { ModalRoot, ModalSize, openModal } from "@utils/modal"; import { useAwaiter } from "@utils/react"; -import { findByProps,findExportedComponent } from "@webpack"; +import { findByProps, findExportedComponent } from "@webpack"; import { FluxDispatcher, Forms, GuildChannelStore, GuildMemberStore, GuildStore, IconUtils, Parser, PresenceStore, RelationshipStore, ScrollerThin, SnowflakeUtils, TabBar, Timestamp, useEffect, UserStore, UserUtils, useState, useStateFromStores } from "@webpack/common"; import { Guild, User } from "discord-types/general"; diff --git a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx index e7d7fdb6b..e0194b0e8 100644 --- a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx +++ b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx @@ -19,7 +19,7 @@ import { Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { formatDuration } from "@utils/text"; -import { findByProps,findComponent, findComponentByCode } from "@webpack"; +import { findByProps, findComponent, findComponentByCode } from "@webpack"; import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, Parser, PermissionsBits, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip, useEffect, useState } from "@webpack/common"; import type { Channel } from "discord-types/general"; diff --git a/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx b/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx index c7f9bdd8a..661a68320 100644 --- a/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx +++ b/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx @@ -18,7 +18,7 @@ import "./VoiceChannelSection.css"; -import { findByCode,findByProps } from "@webpack"; +import { findByCode, findByProps } from "@webpack"; import { Button, Forms, PermissionStore, Toasts } from "@webpack/common"; import { Channel } from "discord-types/general"; diff --git a/src/plugins/whoReacted/index.tsx b/src/plugins/whoReacted/index.tsx index a4f3248ba..c890d58d8 100644 --- a/src/plugins/whoReacted/index.tsx +++ b/src/plugins/whoReacted/index.tsx @@ -29,8 +29,8 @@ import { Message, ReactionEmoji, User } from "discord-types/general"; const UserSummaryItem = findComponentByCode("defaultRenderUser", "showDefaultAvatarsForNullUsers"); const AvatarStyles = findByProps("moreUsers", "emptyUser", "avatarContainer", "clickableAvatar"); -let Scroll: any = null; +let Scroll: any = null; const queue = new Queue(); let reactions: Record; diff --git a/src/utils/modal.tsx b/src/utils/modal.tsx index 800dcc092..3007b5c72 100644 --- a/src/utils/modal.tsx +++ b/src/utils/modal.tsx @@ -108,6 +108,7 @@ export let ModalCloseButton: Modals["ModalCloseButton"]; export const Modals = find(filters.byProps("ModalRoot", "ModalCloseButton"), m => { ({ ModalRoot, ModalHeader, ModalContent, ModalFooter, ModalCloseButton } = m); + return m; }); diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index 913db621b..1d6048a6c 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -226,7 +226,7 @@ function patchFactories(factories: Record string, original: any, (...args: any[]): void; }; From bdb693302a7cc107b8b762686c005f64bb12f302 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 05:19:35 -0300 Subject: [PATCH 006/361] Copy Array -> Use for loop with len --- scripts/generateReport.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 2af192ff3..9875fb749 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -471,9 +471,13 @@ async function runtime(token: string) { } } - for (const [searchType, args] of [...Vencord.Webpack.webpackSearchHistory]) { - let method = searchType as string; + // Must evaluate the len outside of the loop, as the array will be modified by the find methods called inside of it + // This will avoid an infinite loop + const len = Vencord.Webpack.webpackSearchHistory.length; + for (let i = 0; i < len; i++) { + const [searchType, args] = Vencord.Webpack.webpackSearchHistory[i]; + let method = searchType as string; if (searchType === "waitFor") method = "cacheFind"; try { From 901d803ba9d9b98ea7b35a5501b81e7ab59436db Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 05:35:53 -0300 Subject: [PATCH 007/361] Make it less breaking: Add old methods back but mark as deprecated --- src/webpack/webpack.tsx | 80 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index 73f7c5c73..4e7143ad1 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -498,6 +498,86 @@ export function webpackDependantLazyComponent(factory: ( return LazyComponent(factory, attempts); } +/** + * @deprecated Use {@link webpackDependantLazy} instead + * This is just a wrapper around {@link proxyLazy} to make our reporter test for your webpack finds. + * + * Wraps the result of factory in a Proxy you can consume as if it wasn't lazy. + * On first property access, the factory is evaluated + * @param factory Factory returning the result + * @param attempts How many times to try to evaluate the factory before giving up + * @returns Result of factory function + */ +export const proxyLazyWebpack = webpackDependantLazy; + +/** + * @deprecated Use {@link webpackDependantLazyComponent} instead + * This is just a wrapper around {@link LazyComponent} to make our reporter test for your webpack finds. + * + * A lazy component. The factory method is called on first render. + * @param factory Function returning a Component + * @param attempts How many times to try to get the component before giving up + * @returns Result of factory function + */ +export const LazyComponentWebpack = webpackDependantLazyComponent; + +/** + * @deprecated Use {@link find} instead + * Find the first module that matches the filter, lazily + */ +export const findLazy = find; + +/** + * @deprecated Use {@link findByProps} instead + * Find the first module that has the specified properties, lazily + */ +export const findByPropsLazy = findByProps; + + +/** + * @deprecated Use {@link findByCode} instead + * Find the first function that includes all the given code, lazily + */ +export const findByCodeLazy = findByCode; + +/** + * @deprecated Use {@link findStore} instead + * Find a store by its displayName, lazily + */ +export const findStoreLazy = findStore; + +/** + * @deprecated Use {@link findComponent} instead + * Finds the first component that matches the filter, lazily. + */ +export const findComponentLazy = findComponent; + +/** + * @deprecated Use {@link findComponentByCode} instead + * Finds the first component that includes all the given code, lazily + */ +export const findComponentByCodeLazy = findComponentByCode; + +/** + * @deprecated Use {@link findExportedComponent} instead + * Finds the first component that is exported by the first prop name, lazily + */ +export const findExportedComponentLazy = findExportedComponent; + +/** + * @deprecated Use {@link cacheFindAll} instead + */ +export const findAll = cacheFindAll; + +/** + * @deprecated Use {@link cacheFindBulk} instead + * Same as {@link cacheFind} but in bulk + * @param filterFns Array of filters. Please note that this array will be modified in place, so if you still + * need it afterwards, pass a copy. + * @returns Array of results in the same order as the passed filters + */ +export const findBulk = cacheFindBulk; + const DefaultExtractAndLoadChunksRegex = /(?:Promise\.all\((\[\i\.\i\(".+?"\).+?\])\)|Promise\.resolve\(\)).then\(\i\.bind\(\i,"(.+?)"\)\)/; /** From 9ece4dddd3412174af8f5b3b98d9e570039d3816 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 19:39:21 -0300 Subject: [PATCH 008/361] Better deprecation comments --- src/webpack/webpack.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index 4e7143ad1..b09ba456e 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -500,6 +500,7 @@ export function webpackDependantLazyComponent(factory: ( /** * @deprecated Use {@link webpackDependantLazy} instead + * * This is just a wrapper around {@link proxyLazy} to make our reporter test for your webpack finds. * * Wraps the result of factory in a Proxy you can consume as if it wasn't lazy. @@ -512,6 +513,7 @@ export const proxyLazyWebpack = webpackDependantLazy; /** * @deprecated Use {@link webpackDependantLazyComponent} instead + * * This is just a wrapper around {@link LazyComponent} to make our reporter test for your webpack finds. * * A lazy component. The factory method is called on first render. @@ -523,12 +525,14 @@ export const LazyComponentWebpack = webpackDependantLazyComponent; /** * @deprecated Use {@link find} instead + * * Find the first module that matches the filter, lazily */ export const findLazy = find; /** * @deprecated Use {@link findByProps} instead + * * Find the first module that has the specified properties, lazily */ export const findByPropsLazy = findByProps; @@ -536,30 +540,35 @@ export const findByPropsLazy = findByProps; /** * @deprecated Use {@link findByCode} instead + * * Find the first function that includes all the given code, lazily */ export const findByCodeLazy = findByCode; /** * @deprecated Use {@link findStore} instead + * * Find a store by its displayName, lazily */ export const findStoreLazy = findStore; /** * @deprecated Use {@link findComponent} instead + * * Finds the first component that matches the filter, lazily. */ export const findComponentLazy = findComponent; /** * @deprecated Use {@link findComponentByCode} instead + * * Finds the first component that includes all the given code, lazily */ export const findComponentByCodeLazy = findComponentByCode; /** * @deprecated Use {@link findExportedComponent} instead + * * Finds the first component that is exported by the first prop name, lazily */ export const findExportedComponentLazy = findExportedComponent; @@ -571,6 +580,7 @@ export const findAll = cacheFindAll; /** * @deprecated Use {@link cacheFindBulk} instead + * * Same as {@link cacheFind} but in bulk * @param filterFns Array of filters. Please note that this array will be modified in place, so if you still * need it afterwards, pass a copy. From ac85b3508bd62d08428de578e55b433645af1824 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Fri, 3 May 2024 20:11:52 -0300 Subject: [PATCH 009/361] Comment proxyInner better --- src/utils/proxyInner.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/utils/proxyInner.ts b/src/utils/proxyInner.ts index 7f818d0d5..ef41f1fe0 100644 --- a/src/utils/proxyInner.ts +++ b/src/utils/proxyInner.ts @@ -53,8 +53,11 @@ export function proxyInner(err = new Error("Proxy inner value is undefi [proxyInnerValue]: void 0 as T | undefined }); + // Values destructured in the same tick the proxy was created will push their setInnerValue here const recursiveSetInnerValues = [] as Array<(innerValue: T) => void>; + // Once we set the parent inner value, we will call the setInnerValue functions of the destructured values, + // for them to get the proper value from the parent and use as their inner instead function setInnerValue(innerValue: T) { proxyDummy[proxyInnerValue] = innerValue; recursiveSetInnerValues.forEach(setInnerValue => setInnerValue(innerValue)); @@ -72,7 +75,9 @@ export function proxyInner(err = new Error("Proxy inner value is undefi // `const { meow } = findByProps("meow");` if (!isChild && isSameTick) { const [recursiveProxy, recursiveSetInnerValue] = proxyInner(err, true); + recursiveSetInnerValues.push((innerValue: T) => { + // Set the inner value of the destructured value as the prop value p of the parent recursiveSetInnerValue(Reflect.get(innerValue as object, p, receiver)); }); From 70103e81119ad41f1e26d384ed0f60a7ae14e241 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 4 May 2024 17:49:20 -0300 Subject: [PATCH 010/361] Add better explanation for destructuring primitives --- src/utils/lazy.ts | 2 +- src/utils/proxyInner.ts | 15 ++++++++++----- src/webpack/webpack.tsx | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/utils/lazy.ts b/src/utils/lazy.ts index 5fa1a8689..97e6f3e81 100644 --- a/src/utils/lazy.ts +++ b/src/utils/lazy.ts @@ -96,7 +96,7 @@ export function proxyLazy(factory: () => T, attempts = 5, isChild = fal return Reflect.get(lazyTarget, p, receiver); } - throw new Error("proxyLazy called on a primitive value"); + throw new Error("proxyLazy called on a primitive value. This can happen if you try to destructure a primitive at the same tick as the proxy was created."); } }) as T; } diff --git a/src/utils/proxyInner.ts b/src/utils/proxyInner.ts index ef41f1fe0..698363c71 100644 --- a/src/utils/proxyInner.ts +++ b/src/utils/proxyInner.ts @@ -35,17 +35,22 @@ const handler: ProxyHandler = { /** * A proxy which has an inner value that can be set later. * When a property is accessed, the proxy looks for the property value in its inner value, and errors if it's not set. - * @param err The error to throw when the inner value is not set + * @param err The error message to throw when the inner value is not set + * @param primitiveErr The error message to throw when the inner value is a primitive * @returns A proxy which will act like the inner value when accessed */ -export function proxyInner(err = new Error("Proxy inner value is undefined, setInnerValue was never called."), isChild = false): [proxy: T, setInnerValue: (innerValue: T) => void] { +export function proxyInner( + errMsg = "Proxy inner value is undefined, setInnerValue was never called.", + primitiveErrMsg = "proxyInner called on a primitive value. This can happen if you try to destructure a primitive at the same tick as the proxy was created.", + isChild = false +): [proxy: T, setInnerValue: (innerValue: T) => void] { let isSameTick = true; if (!isChild) setTimeout(() => isSameTick = false, 0); const proxyDummy = Object.assign(function () { }, { [proxyInnerGet]: function () { if (proxyDummy[proxyInnerValue] == null) { - throw err; + throw new Error(errMsg); } return proxyDummy[proxyInnerValue]; @@ -74,7 +79,7 @@ export function proxyInner(err = new Error("Proxy inner value is undefi // meow here will also be a proxy // `const { meow } = findByProps("meow");` if (!isChild && isSameTick) { - const [recursiveProxy, recursiveSetInnerValue] = proxyInner(err, true); + const [recursiveProxy, recursiveSetInnerValue] = proxyInner(errMsg, primitiveErrMsg, true); recursiveSetInnerValues.push((innerValue: T) => { // Set the inner value of the destructured value as the prop value p of the parent @@ -89,7 +94,7 @@ export function proxyInner(err = new Error("Proxy inner value is undefi return Reflect.get(innerTarget, p, receiver); } - throw new Error("proxyInner called on a primitive value"); + throw new Error(primitiveErrMsg); } }) as T, setInnerValue]; diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index b09ba456e..23b3e0992 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -167,7 +167,7 @@ export function find(filter: FilterFn, callback: (mod: any) => any = m if (IS_DEV && !isIndirect) webpackSearchHistory.push(["find", [filter]]); - const [proxy, setInnerValue] = proxyInner(new Error(`Webpack find matched no module. Filter: ${printFilter(filter)}`)); + const [proxy, setInnerValue] = proxyInner(`Webpack find matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value. This can happen if you try to destructure a primitive in the top level definition of the find."); waitFor(filter, mod => setInnerValue(callback(mod)), { isIndirect: true }); if (proxy[proxyInnerValue] != null) return proxy[proxyInnerValue] as T; From cfefdbc7a7c72ebde860f78fc5f7520d7f76a50b Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 4 May 2024 20:56:32 -0300 Subject: [PATCH 011/361] Improve proxyLazy --- src/utils/lazy.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/utils/lazy.ts b/src/utils/lazy.ts index 97e6f3e81..4a8557d0f 100644 --- a/src/utils/lazy.ts +++ b/src/utils/lazy.ts @@ -7,15 +7,20 @@ export function makeLazy(factory: () => T, attempts = 5): () => T { let tries = 0; let cache: T; - return () => { + + const getter = () => { if (!cache && attempts > tries++) { cache = factory(); if (!cache && attempts === tries) { - console.error(`Lazy factory failed:\n${factory}`); + console.error(`Lazy factory failed:\n\n${factory}`); } } return cache; }; + + getter.$$vencordLazyFailed = () => tries >= attempts; + + return getter; } // Proxies demand that these properties be unmodified, so proxyLazy @@ -54,20 +59,20 @@ const proxyLazyCache = Symbol.for("vencord.lazy.cached"); * @returns Result of factory function */ export function proxyLazy(factory: () => T, attempts = 5, isChild = false): T { - const get = makeLazy(factory, attempts); + const get = makeLazy(factory, attempts) as any; let isSameTick = true; if (!isChild) setTimeout(() => isSameTick = false, 0); - let failed = false; const proxyDummy = Object.assign(function () { }, { [proxyLazyGet]() { - if (!proxyDummy[proxyLazyCache] && !failed) { - proxyDummy[proxyLazyCache] = get(); + if (!proxyDummy[proxyLazyCache]) { + if (!get.$$vencordLazyFailed()) { + proxyDummy[proxyLazyCache] = get(); + } if (!proxyDummy[proxyLazyCache]) { - failed = true; - throw new Error(`proxyLazy factory failed:\n${factory}`); + throw new Error(`proxyLazy factory failed:\n\n${factory}`); } } From b3819228eddd276ae88d14faa63aa5304d6ac518 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 4 May 2024 23:15:33 -0300 Subject: [PATCH 012/361] Resolve PluginSettings circular deps better --- src/components/PluginSettings/index.tsx | 5 +++-- src/plugins/_api/badges/index.tsx | 8 ++------ src/plugins/_core/settings.tsx | 23 +++++++++++++++-------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/components/PluginSettings/index.tsx b/src/components/PluginSettings/index.tsx index 33a472c1a..e6b2cf1fb 100644 --- a/src/components/PluginSettings/index.tsx +++ b/src/components/PluginSettings/index.tsx @@ -27,6 +27,7 @@ import PluginModal from "@components/PluginSettings/PluginModal"; import { AddonCard } from "@components/VencordSettings/AddonCard"; import { SettingsTab } from "@components/VencordSettings/shared"; import { ChangeList } from "@utils/ChangeList"; +import { proxyLazy } from "@utils/lazy"; import { Logger } from "@utils/Logger"; import { Margins } from "@utils/margins"; import { classes, isObjectEmpty } from "@utils/misc"; @@ -38,8 +39,8 @@ import { Alerts, Button, Card, Forms, lodash, Parser, React, Select, Text, TextI import Plugins from "~plugins"; -import { startDependenciesRecursive, startPlugin, stopPlugin } from "../../plugins"; - +// Avoid circular dependency +const { startDependenciesRecursive, startPlugin, stopPlugin } = proxyLazy(() => require("../../plugins")); const cl = classNameFactory("vc-plugins-"); const logger = new Logger("PluginSettings", "#a6d189"); diff --git a/src/plugins/_api/badges/index.tsx b/src/plugins/_api/badges/index.tsx index 5493d4b6a..bbccf0a11 100644 --- a/src/plugins/_api/badges/index.tsx +++ b/src/plugins/_api/badges/index.tsx @@ -23,6 +23,7 @@ import DonateButton from "@components/DonateButton"; import ErrorBoundary from "@components/ErrorBoundary"; import { Flex } from "@components/Flex"; import { Heart } from "@components/Heart"; +import { openContributorModal } from "@components/PluginSettings/ContributorModal"; import { Devs } from "@utils/constants"; import { Margins } from "@utils/margins"; import { isPluginDev } from "@utils/misc"; @@ -37,12 +38,7 @@ const ContributorBadge: ProfileBadge = { image: CONTRIBUTOR_BADGE, position: BadgePosition.START, shouldShow: ({ user }) => isPluginDev(user.id), - onClick(_, { user }) { - // circular import shenanigans - const { openContributorModal } = require("@components/PluginSettings/ContributorModal") as typeof import("@components/PluginSettings/ContributorModal"); - // setImmediate is needed to run on later tick to workaround limitation in proxyLazy - setImmediate(() => openContributorModal(user)); - } + onClick: (_, { user }) => openContributorModal(user) }; let DonorBadges = {} as Record>>; diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 1aea0d6ee..772ee9b64 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -17,6 +17,13 @@ */ import { Settings } from "@api/Settings"; +import BackupAndRestoreTab from "@components/VencordSettings/BackupAndRestoreTab"; +import CloudTab from "@components/VencordSettings/CloudTab"; +import PatchHelperTab from "@components/VencordSettings/PatchHelperTab"; +import PluginsTab from "@components/VencordSettings/PluginsTab"; +import ThemesTab from "@components/VencordSettings/ThemesTab"; +import UpdaterTab from "@components/VencordSettings/UpdaterTab"; +import VencordTab from "@components/VencordSettings/VencordTab"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { React } from "@webpack/common"; @@ -36,7 +43,7 @@ export default definePlugin({ match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, replace: (m, component, props) => { props = props.replace(/children:\[.+\]/, ""); - return `${m},Vencord.Plugins.plugins.Settings.makeInfoElements(${component}, ${props})`; + return `${m},$self.makeInfoElements(${component}, ${props})`; } } ] @@ -77,43 +84,43 @@ export default definePlugin({ { section: "VencordSettings", label: "Vencord", - element: require("@components/VencordSettings/VencordTab").default, + element: VencordTab, className: "vc-settings" }, { section: "VencordPlugins", label: "Plugins", - element: require("@components/VencordSettings/PluginsTab").default, + element: PluginsTab, className: "vc-plugins" }, { section: "VencordThemes", label: "Themes", - element: require("@components/VencordSettings/ThemesTab").default, + element: ThemesTab, className: "vc-themes" }, !IS_UPDATER_DISABLED && { section: "VencordUpdater", label: "Updater", - element: require("@components/VencordSettings/UpdaterTab").default, + element: UpdaterTab, className: "vc-updater" }, { section: "VencordCloud", label: "Cloud", - element: require("@components/VencordSettings/CloudTab").default, + element: CloudTab, className: "vc-cloud" }, { section: "VencordSettingsSync", label: "Backup & Restore", - element: require("@components/VencordSettings/BackupAndRestoreTab").default, + element: BackupAndRestoreTab, className: "vc-backup-restore" }, IS_DEV && { section: "VencordPatchHelper", label: "Patch Helper", - element: require("@components/VencordSettings/PatchHelperTab").default, + element: PatchHelperTab, className: "vc-patch-helper" }, ...this.customSections.map(func => func(SectionTypes)), From bc68bc0312b438df391c896ef71fdda9f5204fe2 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 4 May 2024 23:15:46 -0300 Subject: [PATCH 013/361] ImplicitRelationships: Properly test find --- src/plugins/implicitRelationships/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index 15165d64a..4faad2a9d 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -19,11 +19,12 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByProps, findStoreLazy } from "@webpack"; +import { findByPropsLazy, findStoreLazy } from "@webpack"; import { ChannelStore, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common"; import { Settings } from "Vencord"; const UserAffinitiesStore = findStoreLazy("UserAffinitiesStore"); +const { FriendsSections } = findByPropsLazy("FriendsSections"); interface UserAffinity { user_id: string; @@ -181,7 +182,6 @@ export default definePlugin({ }, start() { - const { FriendsSections } = findByProps("FriendsSections"); FriendsSections.IMPLICIT = "IMPLICIT"; } }); From 043675f3f8e70d41484b8af11c9f475995ad5801 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 4 May 2024 23:56:02 -0300 Subject: [PATCH 014/361] Forgot to change this --- src/utils/lazyReact.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/utils/lazyReact.tsx b/src/utils/lazyReact.tsx index 0e929aa98..14654406a 100644 --- a/src/utils/lazyReact.tsx +++ b/src/utils/lazyReact.tsx @@ -19,16 +19,20 @@ export const NoopComponent = () => null; export function LazyComponent(factory: () => React.ComponentType, attempts = 5) { const get = makeLazy(factory, attempts); - let failed = false; const LazyComponent = (props: T) => { - const Component = get() ?? (() => { - if (!failed) { - failed = true; - console.error(`LazyComponent factory failed:\n${factory}`); - } + let Component = (() => { + console.error(`LazyComponent factory failed:\n\n${factory}`); return NoopComponent; - })(); + })() as React.ComponentType; + + // @ts-ignore + if (!get.$$vencordLazyFailed()) { + const result = get(); + if (result != null) { + Component = result; + } + } return ; }; From b98544ed1f93579dd04ab681de9fb8de17b8dc17 Mon Sep 17 00:00:00 2001 From: Fafa <87046111+Faf4a@users.noreply.github.com> Date: Sun, 5 May 2024 06:42:15 +0200 Subject: [PATCH 015/361] ReviewDB: Fix context menus being added to folders (#2416) --- src/plugins/reviewDB/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx index bcd0f163f..e73bce82c 100644 --- a/src/plugins/reviewDB/index.tsx +++ b/src/plugins/reviewDB/index.tsx @@ -36,6 +36,7 @@ import { settings } from "./settings"; import { showToast } from "./utils"; const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => { + if (!guild) return; children.push( Date: Sun, 5 May 2024 02:52:41 -0300 Subject: [PATCH 016/361] Fix wrongfully logging LazyComponent factory failed --- src/utils/lazy.ts | 6 +++--- src/utils/lazyReact.tsx | 8 +++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/utils/lazy.ts b/src/utils/lazy.ts index 4a8557d0f..a98e56f45 100644 --- a/src/utils/lazy.ts +++ b/src/utils/lazy.ts @@ -9,16 +9,16 @@ export function makeLazy(factory: () => T, attempts = 5): () => T { let cache: T; const getter = () => { - if (!cache && attempts > tries++) { + if (!cache && attempts > tries) { cache = factory(); - if (!cache && attempts === tries) { + if (!cache && attempts === ++tries) { console.error(`Lazy factory failed:\n\n${factory}`); } } return cache; }; - getter.$$vencordLazyFailed = () => tries >= attempts; + getter.$$vencordLazyFailed = () => tries === attempts; return getter; } diff --git a/src/utils/lazyReact.tsx b/src/utils/lazyReact.tsx index 14654406a..f7f6b0ff0 100644 --- a/src/utils/lazyReact.tsx +++ b/src/utils/lazyReact.tsx @@ -23,15 +23,13 @@ export function LazyComponent(factory: () => React.Compo let Component = (() => { console.error(`LazyComponent factory failed:\n\n${factory}`); - return NoopComponent; - })() as React.ComponentType; + return null; + }) as React.ComponentType; // @ts-ignore if (!get.$$vencordLazyFailed()) { const result = get(); - if (result != null) { - Component = result; - } + if (result != null) Component = result; } return ; From 49e78793c5b66de116dc9a5b470345d5f888df12 Mon Sep 17 00:00:00 2001 From: Sqaaakoi Date: Sun, 5 May 2024 20:15:01 +1200 Subject: [PATCH 017/361] ImageLink: Fix embed showing in gifs (#2417) --- src/plugins/imageLink/index.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/plugins/imageLink/index.ts b/src/plugins/imageLink/index.ts index 73a977fa9..5e8dd23e9 100644 --- a/src/plugins/imageLink/index.ts +++ b/src/plugins/imageLink/index.ts @@ -10,15 +10,15 @@ import definePlugin from "@utils/types"; export default definePlugin({ name: "ImageLink", description: "Never hide image links in messages, even if it's the only content", - authors: [Devs.Kyuuhachi], + authors: [Devs.Kyuuhachi, Devs.Sqaaakoi], patches: [ { - find: "isEmbedInline:function()", + find: "unknownUserMentionPlaceholder:", replacement: { - match: /(?<=isEmbedInline:function\(\)\{return )\i(?=\})/, - replace: "()=>false", - }, - }, - ], + match: /\(0,\i\.isEmbedInline\)\(\i\)/, + replace: "false", + } + } + ] }); From 886071af4d5a76db5012ed411f2875e0298fa8a2 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Mon, 6 May 2024 23:22:36 -0300 Subject: [PATCH 018/361] Clean up Webpack ComponentWrapper --- src/webpack/webpack.tsx | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index 23b3e0992..f8945c28b 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -189,20 +189,16 @@ export function findComponent(filter: FilterFn, parse: ( if (IS_DEV && !isIndirect) webpackSearchHistory.push(["findComponent", [filter]]); - let noMatchLogged = false; - const NoopComponent = (() => { - if (!noMatchLogged) { - noMatchLogged = true; + let InnerComponent = null as null | React.ComponentType; + + let findFailedLogged = false; + const WrapperComponent = (props: T) => { + if (InnerComponent === null && !findFailedLogged) { + findFailedLogged = true; logger.error(`Webpack find matched no module. Filter: ${printFilter(filter)}`); } - return null; - }) as React.ComponentType; - - let InnerComponent = NoopComponent; - - const WrapperComponent = (props: T) => { - return ; + return InnerComponent && ; }; WrapperComponent.$$vencordGetter = () => InnerComponent; @@ -213,7 +209,7 @@ export function findComponent(filter: FilterFn, parse: ( Object.assign(InnerComponent, parsedComponent); }, { isIndirect: true }); - if (InnerComponent !== NoopComponent) return InnerComponent; + if (InnerComponent !== null) return InnerComponent; return WrapperComponent; } @@ -236,20 +232,16 @@ export function findExportedComponent(...props: string[] if (IS_DEV) webpackSearchHistory.push(["findExportedComponent", props]); - let noMatchLogged = false; - const NoopComponent = (() => { - if (!noMatchLogged) { - noMatchLogged = true; + let InnerComponent = null as null | React.ComponentType; + + let findFailedLogged = false; + const WrapperComponent = (props: T) => { + if (InnerComponent === null && !findFailedLogged) { + findFailedLogged = true; logger.error(`Webpack find matched no module. Filter: ${printFilter(filter)}`); } - return null; - }) as React.ComponentType; - - let InnerComponent = NoopComponent; - - const WrapperComponent = (props: T) => { - return ; + return InnerComponent && ; }; WrapperComponent.$$vencordGetter = () => InnerComponent; @@ -260,7 +252,7 @@ export function findExportedComponent(...props: string[] Object.assign(InnerComponent, parsedComponent); }, { isIndirect: true }); - if (InnerComponent !== NoopComponent) return InnerComponent; + if (InnerComponent !== null) return InnerComponent; return WrapperComponent as React.ComponentType; } From 4a89fadedd75ba2b5931581b3dbe240eb3b92e42 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 01:13:46 -0300 Subject: [PATCH 019/361] Make Webpack finds not need to re-search --- scripts/generateReport.ts | 70 +++++++++++++++++----------------- src/utils/lazy.ts | 14 ++++--- src/utils/lazyReact.tsx | 36 +++++++++--------- src/utils/react.tsx | 2 + src/webpack/webpack.tsx | 79 +++++++++++++++++++++++++++++---------- 5 files changed, 123 insertions(+), 78 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 9875fb749..d53cbb48f 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -471,26 +471,19 @@ async function runtime(token: string) { } } - // Must evaluate the len outside of the loop, as the array will be modified by the find methods called inside of it - // This will avoid an infinite loop - const len = Vencord.Webpack.webpackSearchHistory.length; - for (let i = 0; i < len; i++) { - const [searchType, args] = Vencord.Webpack.webpackSearchHistory[i]; + const WEBPACK_SEARCH_HISTORY_WITH_FILTER_NAME_PROP = ["find", "findComponent", "waitFor"]; - let method = searchType as string; - if (searchType === "waitFor") method = "cacheFind"; + // eslint-disable-next-line prefer-const + for (let [searchType, args] of Vencord.Webpack.webpackSearchHistory) { + args = [...args]; try { - let result: any; + let result = null as any; - if (method === "webpackDependantLazy" || method === "webpackDependantLazyComponent") { + if (searchType === "webpackDependantLazy" || searchType === "webpackDependantLazyComponent") { const [factory] = args; result = factory(); - - if (result != null && "$$vencordGetter" in result) { - result = result.$$vencordGetter(); - } - } else if (method === "extractAndLoadChunks") { + } else if (searchType === "extractAndLoadChunks") { const [code, matcher] = args; const module = Vencord.Webpack.findModuleFactory(...code); @@ -498,14 +491,20 @@ async function runtime(token: string) { result = module.toString().match(Vencord.Util.canonicalizeMatch(matcher)); } } else { - result = Vencord.Webpack[method](...args); + result = args.shift(); - // If the result is our Proxy or ComponentWrapper, this means the search failed - if ( - result != null && - (result[Vencord.Util.proxyInnerGet] != null || "$$vencordGetter" in result) - ) { - result = undefined; + if (result != null) { + if (result.$$vencordCallbackCalled != null && !result.$$vencordCallbackCalled()) { + result = null; + } + + if (result[Vencord.Util.proxyInnerGet] != null) { + result = result[Vencord.Util.proxyInnerValue]; + } + + if (result.$$vencordInner != null) { + result = result.$$vencordInner(); + } } } @@ -517,28 +516,27 @@ async function runtime(token: string) { let filterName = ""; let parsedArgs = args; - if ("$$vencordProps" in args[0]) { - if ( - searchType === "find" || - searchType === "findComponent" || - searchType === "waitFor" - ) { - filterName = args[0].$$vencordProps[0]; + + if (args[0].$$vencordProps != null) { + if (WEBPACK_SEARCH_HISTORY_WITH_FILTER_NAME_PROP.includes(searchType)) { + filterName = args[0].$$vencordProps.shift(); } - parsedArgs = args[0].$$vencordProps.slice(1); + parsedArgs = args[0].$$vencordProps; } + // if parsedArgs is the same as args, it means vencordProps of the filter was not available (like in normal filter functions), + // so log the filter function instead if ( - parsedArgs === args && searchType === "waitFor" || - searchType === "find" || - searchType === "findComponent" || - searchType === "webpackDependantLazy" || - searchType === "webpackDependantLazyComponent" + parsedArgs === args && (searchType === "waitFor" || + searchType === "find" || + searchType === "findComponent" || + searchType === "webpackDependantLazy" || + searchType === "webpackDependantLazyComponent") ) { - logMessage += `(${parsedArgs[0].toString().slice(0, 147)}...)`; + logMessage += `(${args[0].toString().slice(0, 147)}...)`; } else if (searchType === "extractAndLoadChunks") { - logMessage += `([${parsedArgs[0].map((arg: any) => `"${arg}"`).join(", ")}], ${parsedArgs[1].toString()})`; + logMessage += `([${args[0].map((arg: any) => `"${arg}"`).join(", ")}], ${args[1].toString()})`; } else { logMessage += `(${filterName.length ? `${filterName}(` : ""}${parsedArgs.map(arg => `"${arg}"`).join(", ")})${filterName.length ? ")" : ""}`; } diff --git a/src/utils/lazy.ts b/src/utils/lazy.ts index a98e56f45..4edc56d0d 100644 --- a/src/utils/lazy.ts +++ b/src/utils/lazy.ts @@ -4,17 +4,18 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -export function makeLazy(factory: () => T, attempts = 5): () => T { +export function makeLazy(factory: () => T, attempts = 5, { isIndirect = false }: { isIndirect?: boolean; } = {}): () => T { let tries = 0; let cache: T; const getter = () => { if (!cache && attempts > tries) { cache = factory(); - if (!cache && attempts === ++tries) { + if (!cache && attempts === ++tries && !isIndirect) { console.error(`Lazy factory failed:\n\n${factory}`); } } + return cache; }; @@ -48,8 +49,8 @@ const handler: ProxyHandler = { } }; -const proxyLazyGet = Symbol.for("vencord.lazy.get"); -const proxyLazyCache = Symbol.for("vencord.lazy.cached"); +export const proxyLazyGet = Symbol.for("vencord.lazy.get"); +export const proxyLazyCache = Symbol.for("vencord.lazy.cached"); /** * Wraps the result of factory in a Proxy you can consume as if it wasn't lazy. @@ -59,7 +60,7 @@ const proxyLazyCache = Symbol.for("vencord.lazy.cached"); * @returns Result of factory function */ export function proxyLazy(factory: () => T, attempts = 5, isChild = false): T { - const get = makeLazy(factory, attempts) as any; + const get = makeLazy(factory, attempts, { isIndirect: true }) as any; let isSameTick = true; if (!isChild) setTimeout(() => isSameTick = false, 0); @@ -84,6 +85,9 @@ export function proxyLazy(factory: () => T, attempts = 5, isChild = fal return new Proxy(proxyDummy, { ...handler, get(target, p, receiver) { + if (p === proxyLazyGet) return target[proxyLazyGet]; + if (p === proxyLazyCache) return target[proxyLazyCache]; + // If we're still in the same tick, it means the lazy was immediately used. // thus, we lazy proxy the get access to make things like destructuring work as expected // meow here will also be a lazy diff --git a/src/utils/lazyReact.tsx b/src/utils/lazyReact.tsx index f7f6b0ff0..acc538ce1 100644 --- a/src/utils/lazyReact.tsx +++ b/src/utils/lazyReact.tsx @@ -4,12 +4,8 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { ComponentType } from "react"; - import { makeLazy } from "./lazy"; -export const NoopComponent = () => null; - /** * A lazy component. The factory method is called on first render. * @param factory Function returning a component @@ -17,25 +13,31 @@ export const NoopComponent = () => null; * @returns Result of factory function */ export function LazyComponent(factory: () => React.ComponentType, attempts = 5) { - const get = makeLazy(factory, attempts); + const get = makeLazy(factory, attempts, { isIndirect: true }); + let InnerComponent = null as React.ComponentType | null; + + let lazyFailedLogged = false; const LazyComponent = (props: T) => { - let Component = (() => { - console.error(`LazyComponent factory failed:\n\n${factory}`); - - return null; - }) as React.ComponentType; - // @ts-ignore if (!get.$$vencordLazyFailed()) { - const result = get(); - if (result != null) Component = result; + const ResultComponent = get(); + if (ResultComponent != null) { + InnerComponent = ResultComponent; + } } - return ; + if (InnerComponent === null && !lazyFailedLogged) { + // @ts-ignore + if (get.$$vencordLazyFailed()) { + lazyFailedLogged = true; + } + + console.error(`LazyComponent factory failed:\n\n${factory}`); + } + + return InnerComponent && ; }; - LazyComponent.$$vencordGetter = get; - - return LazyComponent as ComponentType; + return LazyComponent as React.ComponentType; } diff --git a/src/utils/react.tsx b/src/utils/react.tsx index abae97c53..f31549f19 100644 --- a/src/utils/react.tsx +++ b/src/utils/react.tsx @@ -22,6 +22,8 @@ import { checkIntersecting } from "./misc"; export * from "./lazyReact"; +export const NoopComponent = () => null; + /** * Check if an element is on screen * @param intersectOnly If `true`, will only update the state when the element comes into view diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index f8945c28b..ce0d41b99 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -133,7 +133,22 @@ export function waitFor(filter: FilterFn, callback: ModCallbackFn, { isIndirect if (typeof callback !== "function") throw new Error("Invalid callback. Expected a function got " + typeof callback); - if (IS_DEV && !isIndirect) webpackSearchHistory.push(["waitFor", [filter]]); + if (IS_DEV && !isIndirect) { + const originalCallback = callback; + + let callbackCalled = false; + callback = function () { + callbackCalled = true; + + // @ts-ignore + originalCallback(...arguments); + }; + + // @ts-ignore + callback.$$vencordCallbackCalled = () => callbackCalled; + + webpackSearchHistory.push(["waitFor", [callback, filter]]); + } if (cache != null) { const existing = cacheFind(filter); @@ -165,11 +180,13 @@ export function find(filter: FilterFn, callback: (mod: any) => any = m if (typeof callback !== "function") throw new Error("Invalid callback. Expected a function got " + typeof callback); - if (IS_DEV && !isIndirect) webpackSearchHistory.push(["find", [filter]]); - const [proxy, setInnerValue] = proxyInner(`Webpack find matched no module. Filter: ${printFilter(filter)}`, "Webpack find with proxy called on a primitive value. This can happen if you try to destructure a primitive in the top level definition of the find."); waitFor(filter, mod => setInnerValue(callback(mod)), { isIndirect: true }); + if (IS_DEV && !isIndirect) { + webpackSearchHistory.push(["find", [proxy, filter]]); + } + if (proxy[proxyInnerValue] != null) return proxy[proxyInnerValue] as T; return proxy; @@ -187,9 +204,7 @@ export function findComponent(filter: FilterFn, parse: ( if (typeof parse !== "function") throw new Error("Invalid component parse. Expected a function got " + typeof parse); - if (IS_DEV && !isIndirect) webpackSearchHistory.push(["findComponent", [filter]]); - - let InnerComponent = null as null | React.ComponentType; + let InnerComponent = null as React.ComponentType | null; let findFailedLogged = false; const WrapperComponent = (props: T) => { @@ -201,14 +216,20 @@ export function findComponent(filter: FilterFn, parse: ( return InnerComponent && ; }; - WrapperComponent.$$vencordGetter = () => InnerComponent; - waitFor(filter, (v: any) => { const parsedComponent = parse(v); InnerComponent = parsedComponent; Object.assign(InnerComponent, parsedComponent); }, { isIndirect: true }); + if (IS_DEV) { + WrapperComponent.$$vencordInner = () => InnerComponent; + + if (!isIndirect) { + webpackSearchHistory.push(["findComponent", [WrapperComponent, filter]]); + } + } + if (InnerComponent !== null) return InnerComponent; return WrapperComponent; @@ -230,9 +251,7 @@ export function findExportedComponent(...props: string[] const filter = filters.byProps(...newProps); - if (IS_DEV) webpackSearchHistory.push(["findExportedComponent", props]); - - let InnerComponent = null as null | React.ComponentType; + let InnerComponent = null as React.ComponentType | null; let findFailedLogged = false; const WrapperComponent = (props: T) => { @@ -244,7 +263,6 @@ export function findExportedComponent(...props: string[] return InnerComponent && ; }; - WrapperComponent.$$vencordGetter = () => InnerComponent; waitFor(filter, (v: any) => { const parsedComponent = parse(v[newProps[0]]); @@ -252,6 +270,11 @@ export function findExportedComponent(...props: string[] Object.assign(InnerComponent, parsedComponent); }, { isIndirect: true }); + if (IS_DEV) { + WrapperComponent.$$vencordInner = () => InnerComponent; + webpackSearchHistory.push(["findExportedComponent", [WrapperComponent, ...props]]); + } + if (InnerComponent !== null) return InnerComponent; return WrapperComponent as React.ComponentType; @@ -271,9 +294,13 @@ export function findComponentByCode(...code: string[] | const parse = (typeof code.at(-1) === "function" ? code.pop() : m => m) as (component: any) => React.ComponentType; const newCode = code as string[]; - if (IS_DEV) webpackSearchHistory.push(["findComponentByCode", code]); + const ComponentResult = findComponent(filters.componentByCode(...newCode), parse, { isIndirect: true }); - return findComponent(filters.componentByCode(...newCode), parse, { isIndirect: true }); + if (IS_DEV) { + webpackSearchHistory.push(["findComponentByCode", [ComponentResult, ...code]]); + } + + return ComponentResult; } /** @@ -282,9 +309,13 @@ export function findComponentByCode(...code: string[] | * @param props A list of props to search the exports for */ export function findByProps(...props: string[]) { - if (IS_DEV) webpackSearchHistory.push(["findByProps", props]); + const result = find(filters.byProps(...props), m => m, { isIndirect: true }); - return find(filters.byProps(...props), m => m, { isIndirect: true }); + if (IS_DEV) { + webpackSearchHistory.push(["findByProps", [result, ...props]]); + } + + return result; } /** @@ -293,9 +324,13 @@ export function findByProps(...props: string[]) { * @param code A list of code to search each export for */ export function findByCode(...code: string[]) { - if (IS_DEV) webpackSearchHistory.push(["findByCode", code]); + const result = find(filters.byCode(...code), m => m, { isIndirect: true }); - return find(filters.byCode(...code), m => m, { isIndirect: true }); + if (IS_DEV) { + webpackSearchHistory.push(["findByCode", [result, ...code]]); + } + + return result; } /** @@ -304,9 +339,13 @@ export function findByCode(...code: string[]) { * @param name The store name */ export function findStore(name: string) { - if (IS_DEV) webpackSearchHistory.push(["findStore", [name]]); + const result = find(filters.byStoreName(name), m => m, { isIndirect: true }); - return find(filters.byStoreName(name), m => m, { isIndirect: true }); + if (IS_DEV) { + webpackSearchHistory.push(["findStore", [result, name]]); + } + + return result; } /** From d97596a16a0865e9d19b9250717444518d70f48a Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 02:38:12 -0300 Subject: [PATCH 020/361] e --- scripts/generateReport.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index d53cbb48f..865c5cb38 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -534,9 +534,9 @@ async function runtime(token: string) { searchType === "webpackDependantLazy" || searchType === "webpackDependantLazyComponent") ) { - logMessage += `(${args[0].toString().slice(0, 147)}...)`; + logMessage += `(${parsedArgs[0].toString().slice(0, 147)}...)`; } else if (searchType === "extractAndLoadChunks") { - logMessage += `([${args[0].map((arg: any) => `"${arg}"`).join(", ")}], ${args[1].toString()})`; + logMessage += `([${parsedArgs[0].map((arg: any) => `"${arg}"`).join(", ")}], ${parsedArgs[1].toString()})`; } else { logMessage += `(${filterName.length ? `${filterName}(` : ""}${parsedArgs.map(arg => `"${arg}"`).join(", ")})${filterName.length ? ")" : ""}`; } From 6e0064c5fc11457a365ea027af91b8c580fb3d8e Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 02:57:17 -0300 Subject: [PATCH 021/361] give a name to the proxy dummy function, for better logs in the console --- src/utils/lazy.ts | 2 +- src/utils/proxyInner.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/lazy.ts b/src/utils/lazy.ts index 4edc56d0d..664d4e114 100644 --- a/src/utils/lazy.ts +++ b/src/utils/lazy.ts @@ -65,7 +65,7 @@ export function proxyLazy(factory: () => T, attempts = 5, isChild = fal let isSameTick = true; if (!isChild) setTimeout(() => isSameTick = false, 0); - const proxyDummy = Object.assign(function () { }, { + const proxyDummy = Object.assign(function ProxyDummy() { }, { [proxyLazyGet]() { if (!proxyDummy[proxyLazyCache]) { if (!get.$$vencordLazyFailed()) { diff --git a/src/utils/proxyInner.ts b/src/utils/proxyInner.ts index 698363c71..24018a1d6 100644 --- a/src/utils/proxyInner.ts +++ b/src/utils/proxyInner.ts @@ -47,7 +47,7 @@ export function proxyInner( let isSameTick = true; if (!isChild) setTimeout(() => isSameTick = false, 0); - const proxyDummy = Object.assign(function () { }, { + const proxyDummy = Object.assign(function ProxyDummy() { }, { [proxyInnerGet]: function () { if (proxyDummy[proxyInnerValue] == null) { throw new Error(errMsg); From 65b64400247180cd07707fe69bb93864c7eba912 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 03:01:45 -0300 Subject: [PATCH 022/361] Clean up --- scripts/generateReport.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 865c5cb38..0f5c2d8af 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -471,8 +471,6 @@ async function runtime(token: string) { } } - const WEBPACK_SEARCH_HISTORY_WITH_FILTER_NAME_PROP = ["find", "findComponent", "waitFor"]; - // eslint-disable-next-line prefer-const for (let [searchType, args] of Vencord.Webpack.webpackSearchHistory) { args = [...args]; @@ -518,7 +516,7 @@ async function runtime(token: string) { let parsedArgs = args; if (args[0].$$vencordProps != null) { - if (WEBPACK_SEARCH_HISTORY_WITH_FILTER_NAME_PROP.includes(searchType)) { + if (["find", "findComponent", "waitFor"].includes(searchType)) { filterName = args[0].$$vencordProps.shift(); } @@ -528,11 +526,8 @@ async function runtime(token: string) { // if parsedArgs is the same as args, it means vencordProps of the filter was not available (like in normal filter functions), // so log the filter function instead if ( - parsedArgs === args && (searchType === "waitFor" || - searchType === "find" || - searchType === "findComponent" || - searchType === "webpackDependantLazy" || - searchType === "webpackDependantLazyComponent") + parsedArgs === args && + ["waitFor", "find", "findComponent", "webpackDependantLazy", "webpackDependantLazyComponent"].includes(searchType) ) { logMessage += `(${parsedArgs[0].toString().slice(0, 147)}...)`; } else if (searchType === "extractAndLoadChunks") { From a1fefcf27adfeb34efccf92058e5688c33784d22 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 03:07:03 -0300 Subject: [PATCH 023/361] Cant modify this array because we only clone 1 level deep --- scripts/generateReport.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 0f5c2d8af..2d72d5df9 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -517,10 +517,10 @@ async function runtime(token: string) { if (args[0].$$vencordProps != null) { if (["find", "findComponent", "waitFor"].includes(searchType)) { - filterName = args[0].$$vencordProps.shift(); + filterName = args[0].$$vencordProps[0]; } - parsedArgs = args[0].$$vencordProps; + parsedArgs = args[0].$$vencordProps.slice(1); } // if parsedArgs is the same as args, it means vencordProps of the filter was not available (like in normal filter functions), From f04bd8a7adb819baf9454dcd1f12d4a0e38832db Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 06:13:38 -0300 Subject: [PATCH 024/361] useStateFromStores: Document 3rd param and fix JSDoc --- src/webpack/common/stores.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 2f9786bc5..b5b3a0e73 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -16,10 +16,11 @@ * along with this program. If not, see . */ +import { proxyLazy } from "@utils/lazy"; import type * as Stores from "discord-types/stores"; // eslint-disable-next-line path-alias/no-relative -import { findByPropsLazy } from "../webpack"; +import { findByProps, findByPropsLazy } from "../webpack"; import { waitForStore } from "./internal"; import * as t from "./types/stores"; @@ -67,20 +68,17 @@ export let DraftStore: t.DraftStore; * * @param stores The stores to listen to * @param mapper A function that returns the data you need - * @param idk some thing, idk just pass null + * @param dependencies An array of reactive values which the hook depends on. Use this if your mapper or equality function depends on the value of another hook * @param isEqual A custom comparator for the data returned by mapper * * @example const user = useStateFromStores([UserStore], () => UserStore.getCurrentUser(), null, (old, current) => old.id === current.id); */ -export const { useStateFromStores }: { - useStateFromStores: ( - stores: t.FluxStore[], - mapper: () => T, - idk?: any, - isEqual?: (old: T, newer: T) => boolean - ) => T; -} - = findByPropsLazy("useStateFromStores"); +export const useStateFromStores = proxyLazy(() => findByProps("useStateFromStores").useStateFromStores) as ( + stores: t.FluxStore[], + mapper: () => T, + dependencies?: any, + isEqual?: (old: T, newer: T) => boolean +) => T; waitForStore("DraftStore", s => DraftStore = s); waitForStore("UserStore", s => UserStore = s); From c65e1f88d23cac2dd0d26782f29f28a4742e251e Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 06:28:43 -0300 Subject: [PATCH 025/361] Improve description of some finds --- src/webpack/webpack.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index b305d8d2c..1547df507 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -281,7 +281,7 @@ export function findExportedComponent(...props: string[] } /** - * Find the first component that includes all the given code. + * Find the first component in a default export that 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 findByProps(...props: string[]) { } /** - * Find the first export that includes all the given code. + * Find the first default export that includes all the given code. * * @param code A list of code to search each export for */ From b77b654df1ed3a84c9b6d5657c66bfd1ab19636f Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 06:30:24 -0300 Subject: [PATCH 026/361] I should have done this in the dev branch but it's whatever now --- src/webpack/common/stores.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 1abfbf7a0..58cbece30 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -74,6 +74,6 @@ export const DraftStore = findStore("DraftStore"); export const useStateFromStores = find(filters.byProps("useStateFromStores"), m => m.useStateFromStores) as ( stores: t.FluxStore[], mapper: () => T, - dependencies?: any, + dependencies?: any[], isEqual?: (old: T, newer: T) => boolean ) => T; From 8873391496661f3a670245ac1d0cf117e1eaef10 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 06:33:07 -0300 Subject: [PATCH 027/361] Fix the lint :) --- src/webpack/common/stores.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 58cbece30..b40b7bf2a 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -74,6 +74,6 @@ export const DraftStore = findStore("DraftStore"); export const useStateFromStores = find(filters.byProps("useStateFromStores"), m => m.useStateFromStores) as ( stores: t.FluxStore[], mapper: () => T, - dependencies?: any[], + dependencies?: any[] | null, isEqual?: (old: T, newer: T) => boolean ) => T; From 511ec1b129a683282a79904a670401e6df573988 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 21:33:05 -0300 Subject: [PATCH 028/361] Add warn for using deprecated method --- src/webpack/webpack.tsx | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index 1547df507..f26b6be9f 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -529,6 +529,13 @@ export function webpackDependantLazyComponent(factory: ( return LazyComponent(factory, attempts); } +function deprecatedRedirect any>(oldMethod: string, newMethod: string, redirect: T): T { + return ((...args: Parameters) => { + logger.warn(`Method ${oldMethod} is deprecated. Use ${newMethod} instead. For more information read https://github.com/Vendicated/Vencord/pull/2409#issue-2277161516`); + return redirect(...args); + }) as T; +} + /** * @deprecated Use {@link webpackDependantLazy} instead * @@ -540,7 +547,7 @@ export function webpackDependantLazyComponent(factory: ( * @param attempts How many times to try to evaluate the factory before giving up * @returns Result of factory function */ -export const proxyLazyWebpack = webpackDependantLazy; +export const proxyLazyWebpack = deprecatedRedirect("proxyLazyWebpack", "webpackDependantLazy", webpackDependantLazy); /** * @deprecated Use {@link webpackDependantLazyComponent} instead @@ -552,21 +559,21 @@ export const proxyLazyWebpack = webpackDependantLazy; * @param attempts How many times to try to get the component before giving up * @returns Result of factory function */ -export const LazyComponentWebpack = webpackDependantLazyComponent; +export const LazyComponentWebpack = deprecatedRedirect("LazyComponentWebpack", "webpackDependantLazyComponent", webpackDependantLazyComponent); /** * @deprecated Use {@link find} instead * * Find the first module that matches the filter, lazily */ -export const findLazy = find; +export const findLazy = deprecatedRedirect("findLazy", "find", find); /** * @deprecated Use {@link findByProps} instead * * Find the first module that has the specified properties, lazily */ -export const findByPropsLazy = findByProps; +export const findByPropsLazy = deprecatedRedirect("findByPropsLazy", "findByProps", findByProps); /** @@ -574,40 +581,40 @@ export const findByPropsLazy = findByProps; * * Find the first function that includes all the given code, lazily */ -export const findByCodeLazy = findByCode; +export const findByCodeLazy = deprecatedRedirect("findByCodeLazy", "findByCode", findByCode); /** * @deprecated Use {@link findStore} instead * * Find a store by its displayName, lazily */ -export const findStoreLazy = findStore; +export const findStoreLazy = deprecatedRedirect("findStoreLazy", "findStore", findStore); /** * @deprecated Use {@link findComponent} instead * * Finds the first component that matches the filter, lazily. */ -export const findComponentLazy = findComponent; +export const findComponentLazy = deprecatedRedirect("findComponentLazy", "findComponent", findComponent); /** * @deprecated Use {@link findComponentByCode} instead * * Finds the first component that includes all the given code, lazily */ -export const findComponentByCodeLazy = findComponentByCode; +export const findComponentByCodeLazy = deprecatedRedirect("findComponentByCodeLazy", "findComponentByCode", findComponentByCode); /** * @deprecated Use {@link findExportedComponent} instead * * Finds the first component that is exported by the first prop name, lazily */ -export const findExportedComponentLazy = findExportedComponent; +export const findExportedComponentLazy = deprecatedRedirect("findExportedComponentLazy", "findExportedComponent", findExportedComponent); /** * @deprecated Use {@link cacheFindAll} instead */ -export const findAll = cacheFindAll; +export const findAll = deprecatedRedirect("findAll", "cacheFindAll", cacheFindAll); /** * @deprecated Use {@link cacheFindBulk} instead @@ -617,7 +624,7 @@ export const findAll = cacheFindAll; * need it afterwards, pass a copy. * @returns Array of results in the same order as the passed filters */ -export const findBulk = cacheFindBulk; +export const findBulk = deprecatedRedirect("findBulk", "cacheFindBulk", cacheFindBulk); const DefaultExtractAndLoadChunksRegex = /(?:Promise\.all\((\[\i\.\i\(".+?"\).+?\])\)|Promise\.resolve\(\)).then\(\i\.bind\(\i,"(.+?)"\)\)/; From f1e2d5572a18d1eaa401cd6e00fa997c013c75d9 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 21:44:26 -0300 Subject: [PATCH 029/361] Update these license headers because I forgot in the other pr --- src/webpack/patchWebpack.ts | 20 ++++---------------- src/webpack/webpack.tsx | 20 ++++---------------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts index 816930714..cb43fffc4 100644 --- a/src/webpack/patchWebpack.ts +++ b/src/webpack/patchWebpack.ts @@ -1,20 +1,8 @@ /* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ import { WEBPACK_CHUNK } from "@utils/constants"; import { Logger } from "@utils/Logger"; diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index f26b6be9f..6c0222a0e 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -1,20 +1,8 @@ /* - * Vencord, a modification for Discord's desktop app - * Copyright (c) 2022 Vendicated and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ import { proxyLazy } from "@utils/lazy"; import { LazyComponent } from "@utils/lazyReact"; From 8b6620ca2fef39d8bfed6a31885688c7016148b7 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 22:06:45 -0300 Subject: [PATCH 030/361] Update FluxEvents and Permissions --- src/webpack/common/types/fluxEvents.d.ts | 4 +- src/webpack/common/types/utils.d.ts | 81 ++++++++++++------------ 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/webpack/common/types/fluxEvents.d.ts b/src/webpack/common/types/fluxEvents.d.ts index 36bcb2cde..906ea76bd 100644 --- a/src/webpack/common/types/fluxEvents.d.ts +++ b/src/webpack/common/types/fluxEvents.d.ts @@ -36,5 +36,5 @@ function makeFluxEventList() { } */ -// 46kb worth of events ??????? -export type FluxEvents = "ACCESSIBILITY_COLORBLIND_TOGGLE" | "ACCESSIBILITY_DARK_SIDEBAR_TOGGLE" | "ACCESSIBILITY_DESATURATE_ROLES_TOGGLE" | "ACCESSIBILITY_DETECTION_MODAL_SEEN" | "ACCESSIBILITY_FORCED_COLORS_MODAL_SEEN" | "ACCESSIBILITY_KEYBOARD_MODE_DISABLE" | "ACCESSIBILITY_KEYBOARD_MODE_ENABLE" | "ACCESSIBILITY_LOW_CONTRAST_TOGGLE" | "ACCESSIBILITY_RESET_TO_DEFAULT" | "ACCESSIBILITY_SET_ALWAYS_SHOW_LINK_DECORATIONS" | "ACCESSIBILITY_SET_FONT_SIZE" | "ACCESSIBILITY_SET_MESSAGE_GROUP_SPACING" | "ACCESSIBILITY_SET_PREFERS_REDUCED_MOTION" | "ACCESSIBILITY_SET_ROLE_STYLE" | "ACCESSIBILITY_SET_SATURATION" | "ACCESSIBILITY_SET_SYNC_FORCED_COLORS" | "ACCESSIBILITY_SET_ZOOM" | "ACCESSIBILITY_SUBMIT_BUTTON_TOGGLE" | "ACCESSIBILITY_SUPPORT_CHANGED" | "ACCESSIBILITY_SYNC_PROFILE_THEME_WITH_USER_THEME_TOGGLE" | "ACCESSIBILITY_SYSTEM_COLOR_PREFERENCES_CHANGED" | "ACCESSIBILITY_SYSTEM_PREFERS_CONTRAST_CHANGED" | "ACCESSIBILITY_SYSTEM_PREFERS_REDUCED_MOTION_CHANGED" | "ACK_APPROVED_GUILD_JOIN_REQUEST" | "ACTIVE_CHANNELS_FETCH_FAILURE" | "ACTIVE_CHANNELS_FETCH_START" | "ACTIVE_CHANNELS_FETCH_SUCCESS" | "ACTIVE_OUTBOUND_PROMOTIONS_FETCH" | "ACTIVE_OUTBOUND_PROMOTIONS_FETCH_FAIL" | "ACTIVE_OUTBOUND_PROMOTIONS_FETCH_SUCCESS" | "ACTIVITY_INVITE_EDUCATION_DISMISS" | "ACTIVITY_INVITE_MODAL_CLOSE" | "ACTIVITY_INVITE_MODAL_OPEN" | "ACTIVITY_JOIN" | "ACTIVITY_JOIN_FAILED" | "ACTIVITY_JOIN_LOADING" | "ACTIVITY_LAUNCH_FAIL" | "ACTIVITY_METADATA_UPDATE" | "ACTIVITY_PIP_MODE_UPDATE" | "ACTIVITY_PLAY" | "ACTIVITY_SCREEN_ORIENTATION_UPDATE" | "ACTIVITY_START" | "ACTIVITY_SYNC" | "ACTIVITY_SYNC_STOP" | "ACTIVITY_UPDATE_FAIL" | "ACTIVITY_UPDATE_START" | "ACTIVITY_UPDATE_SUCCESS" | "ADD_STICKER_PREVIEW" | "ADMIN_ONBOARDING_GUIDE_HIDE" | "AFK" | "AGE_GATE_FAILURE_MODAL_OPEN" | "AGE_GATE_LOGOUT_UNDERAGE_NEW_USER" | "AGE_GATE_MODAL_CLOSE" | "AGE_GATE_MODAL_OPEN" | "AGE_GATE_SUCCESS_MODAL_OPEN" | "ALLOW_SPAM_MESSAGES_FOR_USER" | "APPLICATIONS_FETCH" | "APPLICATIONS_FETCH_FAIL" | "APPLICATIONS_FETCH_SUCCESS" | "APPLICATION_ACTIVITY_STATISTICS_FETCH_FAIL" | "APPLICATION_ACTIVITY_STATISTICS_FETCH_START" | "APPLICATION_ACTIVITY_STATISTICS_FETCH_SUCCESS" | "APPLICATION_BRANCHES_FETCH_FAIL" | "APPLICATION_BRANCHES_FETCH_SUCCESS" | "APPLICATION_BUILD_FETCH_START" | "APPLICATION_BUILD_FETCH_SUCCESS" | "APPLICATION_BUILD_NOT_FOUND" | "APPLICATION_BUILD_SIZE_FETCH_FAIL" | "APPLICATION_BUILD_SIZE_FETCH_START" | "APPLICATION_BUILD_SIZE_FETCH_SUCCESS" | "APPLICATION_COMMANDS_FETCH" | "APPLICATION_COMMANDS_FETCH_FOR_APPLICATION" | "APPLICATION_COMMAND_AUTOCOMPLETE_REQUEST" | "APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE" | "APPLICATION_COMMAND_FETCH" | "APPLICATION_COMMAND_REGISTRY_UPDATE" | "APPLICATION_COMMAND_SEARCH_STORE_QUERY" | "APPLICATION_COMMAND_SEARCH_STORE_UI_UPDATE" | "APPLICATION_COMMAND_SEARCH_STORE_UPDATE" | "APPLICATION_COMMAND_SET_ACTIVE_COMMAND" | "APPLICATION_COMMAND_SET_PREFERRED_COMMAND" | "APPLICATION_COMMAND_UPDATE_CHANNEL_STATE" | "APPLICATION_COMMAND_UPDATE_OPTIONS" | "APPLICATION_COMMAND_USED" | "APPLICATION_FETCH" | "APPLICATION_FETCH_FAIL" | "APPLICATION_FETCH_SUCCESS" | "APPLICATION_STORE_ACCEPT_EULA" | "APPLICATION_STORE_ACCEPT_STORE_TERMS" | "APPLICATION_STORE_CLEAR_DATA" | "APPLICATION_STORE_DIRECTORY_FETCH_SUCCESS" | "APPLICATION_STORE_DIRECTORY_MUTE" | "APPLICATION_STORE_DIRECTORY_UNMUTE" | "APPLICATION_STORE_LOCATION_CHANGE" | "APPLICATION_STORE_MATURE_AGREE" | "APPLICATION_STORE_RESET_NAVIGATION" | "APPLICATION_SUBSCRIPTIONS_CHANNEL_NOTICE_DISMISSED" | "APPLICATION_SUBSCRIPTIONS_FETCH_ENTITLEMENTS" | "APPLICATION_SUBSCRIPTIONS_FETCH_ENTITLEMENTS_FAILURE" | "APPLICATION_SUBSCRIPTIONS_FETCH_ENTITLEMENTS_SUCCESS" | "APPLICATION_SUBSCRIPTIONS_FETCH_LISTINGS" | "APPLICATION_SUBSCRIPTIONS_FETCH_LISTINGS_FAILURE" | "APPLICATION_SUBSCRIPTIONS_FETCH_LISTINGS_SUCCESS" | "APPLICATION_SUBSCRIPTIONS_FETCH_LISTING_FOR_PLAN_SUCCESS" | "APPLIED_BOOSTS_COOLDOWN_FETCH_SUCCESS" | "APPLIED_GUILD_BOOST_COUNT_UPDATE" | "APP_STATE_UPDATE" | "APP_VIEW_SET_HOME_LINK" | "AUDIO_INPUT_DETECTED" | "AUDIO_RESET" | "AUDIO_SET_ATTENUATION" | "AUDIO_SET_AUTOMATIC_GAIN_CONTROL" | "AUDIO_SET_DEBUG_LOGGING" | "AUDIO_SET_DISPLAY_SILENCE_WARNING" | "AUDIO_SET_ECHO_CANCELLATION" | "AUDIO_SET_INPUT_DEVICE" | "AUDIO_SET_INPUT_VOLUME" | "AUDIO_SET_LOCAL_PAN" | "AUDIO_SET_LOCAL_VIDEO_DISABLED" | "AUDIO_SET_LOCAL_VOLUME" | "AUDIO_SET_LOOPBACK" | "AUDIO_SET_MODE" | "AUDIO_SET_NOISE_CANCELLATION" | "AUDIO_SET_NOISE_SUPPRESSION" | "AUDIO_SET_OUTPUT_DEVICE" | "AUDIO_SET_OUTPUT_VOLUME" | "AUDIO_SET_QOS" | "AUDIO_SET_SUBSYSTEM" | "AUDIO_SET_TEMPORARY_SELF_MUTE" | "AUDIO_TOGGLE_LOCAL_MUTE" | "AUDIO_TOGGLE_SELF_DEAF" | "AUDIO_TOGGLE_SELF_MUTE" | "AUDIO_VOLUME_CHANGE" | "AUDIT_LOG_FETCH_FAIL" | "AUDIT_LOG_FETCH_NEXT_PAGE_FAIL" | "AUDIT_LOG_FETCH_NEXT_PAGE_START" | "AUDIT_LOG_FETCH_NEXT_PAGE_SUCCESS" | "AUDIT_LOG_FETCH_START" | "AUDIT_LOG_FETCH_SUCCESS" | "AUDIT_LOG_FILTER_BY_ACTION" | "AUDIT_LOG_FILTER_BY_USER" | "AUTH_INVITE_UPDATE" | "AUTH_SESSION_CHANGE" | "AUTO_MODERATION_MENTION_RAID_DETECTION" | "AUTO_MODERATION_MENTION_RAID_NOTICE_DISMISS" | "BILLING_IP_COUNTRY_CODE_FAILURE" | "BILLING_IP_COUNTRY_CODE_FETCH_START" | "BILLING_LOCALIZED_PRICING_PROMO_FAILURE" | "BILLING_MOST_RECENT_SUBSCRIPTION_FETCH_SUCCESS" | "BILLING_PAYMENTS_FETCH_SUCCESS" | "BILLING_PAYMENT_FETCH_SUCCESS" | "BILLING_PAYMENT_SOURCES_FETCH_FAIL" | "BILLING_PAYMENT_SOURCES_FETCH_START" | "BILLING_PAYMENT_SOURCES_FETCH_SUCCESS" | "BILLING_PAYMENT_SOURCE_CREATE_FAIL" | "BILLING_PAYMENT_SOURCE_CREATE_START" | "BILLING_PAYMENT_SOURCE_CREATE_SUCCESS" | "BILLING_PAYMENT_SOURCE_REMOVE_CLEAR_ERROR" | "BILLING_PAYMENT_SOURCE_REMOVE_FAIL" | "BILLING_PAYMENT_SOURCE_REMOVE_START" | "BILLING_PAYMENT_SOURCE_REMOVE_SUCCESS" | "BILLING_PAYMENT_SOURCE_UPDATE_CLEAR_ERROR" | "BILLING_PAYMENT_SOURCE_UPDATE_FAIL" | "BILLING_PAYMENT_SOURCE_UPDATE_START" | "BILLING_PAYMENT_SOURCE_UPDATE_SUCCESS" | "BILLING_POPUP_BRIDGE_CALLBACK" | "BILLING_POPUP_BRIDGE_STATE_UPDATE" | "BILLING_PURCHASE_TOKEN_AUTH_CLEAR_STATE" | "BILLING_SET_IP_COUNTRY_CODE" | "BILLING_SET_LOCALIZED_PRICING_PROMO" | "BILLING_SUBSCRIPTION_CANCEL_FAIL" | "BILLING_SUBSCRIPTION_CANCEL_START" | "BILLING_SUBSCRIPTION_CANCEL_SUCCESS" | "BILLING_SUBSCRIPTION_FETCH_FAIL" | "BILLING_SUBSCRIPTION_FETCH_START" | "BILLING_SUBSCRIPTION_FETCH_SUCCESS" | "BILLING_SUBSCRIPTION_RESET" | "BILLING_SUBSCRIPTION_UPDATE_FAIL" | "BILLING_SUBSCRIPTION_UPDATE_START" | "BILLING_SUBSCRIPTION_UPDATE_SUCCESS" | "BILLING_USER_PREMIUM_LIKELIHOOD_FETCH" | "BILLING_USER_PREMIUM_LIKELIHOOD_FETCH_ERROR" | "BILLING_USER_PREMIUM_LIKELIHOOD_FETCH_SUCCESS" | "BILLING_USER_TRIAL_OFFER_ACKNOWLEDGED_SUCCESS" | "BILLING_USER_TRIAL_OFFER_FETCH_SUCCESS" | "BLOCKED_DOMAIN_LIST_FETCHED" | "BOOSTED_GUILD_GRACE_PERIOD_NOTICE_DISMISS" | "BRAINTREE_CREATE_CLIENT_SUCCESS" | "BRAINTREE_CREATE_PAYPAL_CLIENT_SUCCESS" | "BRAINTREE_CREATE_VENMO_CLIENT_SUCCESS" | "BRAINTREE_TEARDOWN_PAYPAL_CLIENT" | "BRAINTREE_TEARDOWN_VENMO_CLIENT" | "BRAINTREE_TOKENIZE_PAYPAL_START" | "BRAINTREE_TOKENIZE_PAYPAL_SUCCESS" | "BRAINTREE_TOKENIZE_VENMO_START" | "BRAINTREE_TOKENIZE_VENMO_SUCCESS" | "BROWSER_HANDOFF_BEGIN" | "BROWSER_HANDOFF_FROM_APP" | "BROWSER_HANDOFF_SET_USER" | "BROWSER_HANDOFF_UNAVAILABLE" | "BUILD_OVERRIDE_RESOLVED" | "BULK_ACK" | "BULK_CLEAR_RECENTS" | "BURST_REACTION_ADD" | "BURST_REACTION_ANIMATION_ADD" | "BURST_REACTION_EFFECT_CLEAR" | "BURST_REACTION_EFFECT_PLAY" | "BURST_REACTION_REMOVE" | "CACHE_LOADED" | "CACHE_LOADED_LAZY" | "CALL_CHAT_TOASTS_SET_ENABLED" | "CALL_CONNECT" | "CALL_CREATE" | "CALL_DELETE" | "CALL_ENQUEUE_RING" | "CALL_UPDATE" | "CANDIDATE_GAMES_CHANGE" | "CATEGORY_COLLAPSE" | "CATEGORY_COLLAPSE_ALL" | "CATEGORY_EXPAND" | "CATEGORY_EXPAND_ALL" | "CERTIFIED_DEVICES_SET" | "CHANGE_LOG_CLOSE" | "CHANGE_LOG_FETCH_SUCCESS" | "CHANGE_LOG_LOCK" | "CHANGE_LOG_OPEN" | "CHANGE_LOG_SET_OVERRIDE" | "CHANGE_LOG_UNLOCK" | "CHANNEL_ACK" | "CHANNEL_CALL_POPOUT_WINDOW_OPEN" | "CHANNEL_COLLAPSE" | "CHANNEL_CREATE" | "CHANNEL_DELETE" | "CHANNEL_FOLLOWER_CREATED" | "CHANNEL_FOLLOWER_STATS_FETCH_FAILURE" | "CHANNEL_FOLLOWER_STATS_FETCH_SUCCESS" | "CHANNEL_FOLLOWING_PUBLISH_BUMP_DISMISSED" | "CHANNEL_FOLLOWING_PUBLISH_BUMP_HIDE_PERMANENTLY" | "CHANNEL_HIGHLIGHTS_FETCH_START" | "CHANNEL_HIGHLIGHTS_FETCH_SUCCESS" | "CHANNEL_LOCAL_ACK" | "CHANNEL_MESSAGE_PREVIEW_LOAD_MESSAGES" | "CHANNEL_PINS_ACK" | "CHANNEL_PINS_UPDATE" | "CHANNEL_PRELOAD" | "CHANNEL_RECIPIENT_ADD" | "CHANNEL_RECIPIENT_REMOVE" | "CHANNEL_RTC_ACTIVE_CHANNELS" | "CHANNEL_RTC_SELECT_PARTICIPANT" | "CHANNEL_RTC_UPDATE_CHAT_OPEN" | "CHANNEL_RTC_UPDATE_LAYOUT" | "CHANNEL_RTC_UPDATE_PARTICIPANTS_OPEN" | "CHANNEL_RTC_UPDATE_STAGE_MUSIC_MUTED" | "CHANNEL_RTC_UPDATE_STAGE_STREAM_SIZE" | "CHANNEL_RTC_UPDATE_STAGE_VIDEO_LIMIT_BOOST_UPSELL_DISMISSED" | "CHANNEL_RTC_UPDATE_VOICE_PARTICIPANTS_HIDDEN" | "CHANNEL_SELECT" | "CHANNEL_SETTINGS_CLOSE" | "CHANNEL_SETTINGS_INIT" | "CHANNEL_SETTINGS_LOADED_INVITES" | "CHANNEL_SETTINGS_OPEN" | "CHANNEL_SETTINGS_OVERWRITE_SELECT" | "CHANNEL_SETTINGS_PERMISSIONS_INIT" | "CHANNEL_SETTINGS_PERMISSIONS_SAVE_SUCCESS" | "CHANNEL_SETTINGS_PERMISSIONS_SELECT_PERMISSION" | "CHANNEL_SETTINGS_PERMISSIONS_SET_ADVANCED_MODE" | "CHANNEL_SETTINGS_PERMISSIONS_SUBMITTING" | "CHANNEL_SETTINGS_PERMISSIONS_UPDATE_PERMISSION" | "CHANNEL_SETTINGS_SET_SECTION" | "CHANNEL_SETTINGS_SUBMIT" | "CHANNEL_SETTINGS_SUBMIT_FAILURE" | "CHANNEL_SETTINGS_SUBMIT_SUCCESS" | "CHANNEL_SETTINGS_UPDATE" | "CHANNEL_TOGGLE_MEMBERS_SECTION" | "CHANNEL_UPDATES" | "CHECKING_FOR_UPDATES" | "CHECK_LAUNCHABLE_GAME" | "CLEAR_AUTHENTICATION_ERRORS" | "CLEAR_CACHES" | "CLEAR_GUILD_CACHE" | "CLEAR_INTERACTION_MODAL_STATE" | "CLEAR_MESSAGES" | "CLEAR_OLDEST_UNREAD_MESSAGE" | "CLEAR_PENDING_CHANNEL_AND_ROLE_UPDATES" | "CLEAR_REMOTE_DISCONNECT_VOICE_CHANNEL_ID" | "CLEAR_STICKER_PREVIEW" | "CLIENT_THEMES_EDITOR_CLOSE" | "CLIENT_THEMES_EDITOR_OPEN" | "CLIPS_CLEAR_CLIPS_SESSION" | "CLIPS_SAVE_CLIP" | "CLIPS_SETTINGS_UPDATE" | "COMMANDS_MIGRATION_NOTICE_DISMISSED" | "COMMANDS_MIGRATION_OVERVIEW_TOOLTIP_DISMISSED" | "COMMANDS_MIGRATION_TOGGLE_TOOLTIP_DISMISSED" | "COMMANDS_MIGRATION_UPDATE_SUCCESS" | "CONNECTED_DEVICE_IGNORE" | "CONNECTED_DEVICE_NEVER_SHOW_MODAL" | "CONNECTED_DEVICE_SET" | "CONNECTIONS_GRID_MODAL_HIDE" | "CONNECTIONS_GRID_MODAL_SHOW" | "CONNECTION_CLOSED" | "CONNECTION_OPEN" | "CONNECTION_OPEN_SUPPLEMENTAL" | "CONNECTION_RESUMED" | "CONSOLE_COMMAND_UPDATE" | "CONTEXT_MENU_CLOSE" | "CONTEXT_MENU_OPEN" | "CREATE_PENDING_REPLY" | "CURRENT_BUILD_OVERRIDE_RESOLVED" | "CURRENT_USER_UPDATE" | "DECAY_READ_STATES" | "DELETED_ENTITY_IDS" | "DELETE_PENDING_REPLY" | "DETECTED_OFF_PLATFORM_PREMIUM_PERKS_DISMISS" | "DEVELOPER_ACTIVITY_SHELF_FETCH_FAIL" | "DEVELOPER_ACTIVITY_SHELF_FETCH_START" | "DEVELOPER_ACTIVITY_SHELF_FETCH_SUCCESS" | "DEVELOPER_ACTIVITY_SHELF_MARK_ACTIVITY_USED" | "DEVELOPER_ACTIVITY_SHELF_SET_ACTIVITY_URL_OVERRIDE" | "DEVELOPER_ACTIVITY_SHELF_TOGGLE_ENABLED" | "DEVELOPER_ACTIVITY_SHELF_TOGGLE_USE_ACTIVITY_URL_OVERRIDE" | "DEVELOPER_OPTIONS_UPDATE_SETTINGS" | "DEVELOPER_TEST_MODE_AUTHORIZATION_FAIL" | "DEVELOPER_TEST_MODE_AUTHORIZATION_START" | "DEVELOPER_TEST_MODE_AUTHORIZATION_SUCCESS" | "DEVELOPER_TEST_MODE_RESET" | "DEVELOPER_TEST_MODE_RESET_ERROR" | "DEV_TOOLS_SETTINGS_UPDATE" | "DISABLE_AUTOMATIC_ACK" | "DISCOVER_CHECKLIST_FETCH_FAILURE" | "DISCOVER_CHECKLIST_FETCH_START" | "DISCOVER_CHECKLIST_FETCH_SUCCESS" | "DISCOVER_GUILDS_FETCH_FAILURE" | "DISCOVER_GUILDS_FETCH_START" | "DISCOVER_GUILDS_FETCH_SUCCESS" | "DISMISS_FAVORITE_SUGGESTION" | "DISMISS_NITRODUCTION_TOOLTIP" | "DISPATCH_APPLICATION_ADD_TO_INSTALLATIONS" | "DISPATCH_APPLICATION_CANCEL" | "DISPATCH_APPLICATION_ERROR" | "DISPATCH_APPLICATION_INSTALL" | "DISPATCH_APPLICATION_INSTALL_SCRIPTS_PROGRESS_UPDATE" | "DISPATCH_APPLICATION_LAUNCH_SETUP_COMPLETE" | "DISPATCH_APPLICATION_LAUNCH_SETUP_START" | "DISPATCH_APPLICATION_MOVE_UP" | "DISPATCH_APPLICATION_REMOVE_FINISHED" | "DISPATCH_APPLICATION_REPAIR" | "DISPATCH_APPLICATION_STATE_UPDATE" | "DISPATCH_APPLICATION_UNINSTALL" | "DISPATCH_APPLICATION_UPDATE" | "DISPLAYED_INVITE_SHOW" | "DOMAIN_MIGRATION_FAILURE" | "DOMAIN_MIGRATION_SKIP" | "DOMAIN_MIGRATION_START" | "DRAFT_CHANGE" | "DRAFT_CLEAR" | "DRAFT_SAVE" | "DRAWER_CLOSE" | "DRAWER_OPEN" | "DRAWER_SELECT_TAB" | "DROPS_ELIGIBILITY_FETCH_SUCCESS" | "DROPS_ENROLLED_USER_FETCH_SUCCESS" | "DROPS_HEARTBEAT_FAILURE" | "DROPS_HEARTBEAT_SUCCESS" | "DROPS_PLATFORM_AVAILABILITY_SUCCESS" | "DROPS_USER_STATUS_FETCH_SUCCESS" | "EMAIL_SETTINGS_FETCH_SUCCESS" | "EMAIL_SETTINGS_UPDATE" | "EMAIL_SETTINGS_UPDATE_SUCCESS" | "EMBEDDED_ACTIVITY_CLOSE" | "EMBEDDED_ACTIVITY_DEFERRED_OPEN" | "EMBEDDED_ACTIVITY_DISCONNECT" | "EMBEDDED_ACTIVITY_DISMISS_FREE_INDICATOR" | "EMBEDDED_ACTIVITY_FETCH_SHELF" | "EMBEDDED_ACTIVITY_FETCH_SHELF_FAIL" | "EMBEDDED_ACTIVITY_FETCH_SHELF_SUCCESS" | "EMBEDDED_ACTIVITY_FREE_ACTIVITY_UPDATE" | "EMBEDDED_ACTIVITY_INBOUND_UPDATE" | "EMBEDDED_ACTIVITY_LAUNCH_FAIL" | "EMBEDDED_ACTIVITY_LAUNCH_START" | "EMBEDDED_ACTIVITY_LAUNCH_SUCCESS" | "EMBEDDED_ACTIVITY_OPEN" | "EMBEDDED_ACTIVITY_SET_CONFIG" | "EMBEDDED_ACTIVITY_SET_ORIENTATION_LOCK_STATE" | "EMOJI_DELETE" | "EMOJI_FETCH_FAILURE" | "EMOJI_FETCH_SUCCESS" | "EMOJI_TRACK_USAGE" | "EMOJI_UPLOAD_START" | "EMOJI_UPLOAD_STOP" | "ENABLE_AUTOMATIC_ACK" | "ENTITLEMENTS_FETCH_FOR_USER_SUCCESS" | "ENTITLEMENTS_GIFTABLE_FETCH_SUCCESS" | "ENTITLEMENT_CREATE" | "ENTITLEMENT_DELETE" | "ENTITLEMENT_FETCH_APPLICATION_FAIL" | "ENTITLEMENT_FETCH_APPLICATION_START" | "ENTITLEMENT_FETCH_APPLICATION_SUCCESS" | "ENTITLEMENT_UPDATE" | "EVENT_DIRECTORY_FETCH_FAILURE" | "EVENT_DIRECTORY_FETCH_START" | "EVENT_DIRECTORY_FETCH_SUCCESS" | "EXPERIMENTS_FETCH" | "EXPERIMENTS_FETCH_FAILURE" | "EXPERIMENTS_FETCH_SUCCESS" | "EXPERIMENT_OVERRIDE_BUCKET" | "EXPERIMENT_REGISTER_LEGACY" | "EXPERIMENT_TRIGGER" | "FETCH_AUTH_SESSIONS_SUCCESS" | "FETCH_GUILD_EVENTS_FOR_GUILD" | "FINGERPRINT" | "FORCE_INVISIBLE" | "FORGOT_PASSWORD_REQUEST" | "FORGOT_PASSWORD_SENT" | "FORUM_SEARCH_CLEAR" | "FORUM_SEARCH_FAILURE" | "FORUM_SEARCH_QUERY_UPDATED" | "FORUM_SEARCH_START" | "FORUM_SEARCH_SUCCESS" | "FORUM_UNREADS" | "FRIENDS_SET_INITIAL_SECTION" | "FRIENDS_SET_SECTION" | "FRIEND_INVITES_FETCH_REQUEST" | "FRIEND_INVITES_FETCH_RESPONSE" | "FRIEND_INVITE_CREATE_FAILURE" | "FRIEND_INVITE_CREATE_REQUEST" | "FRIEND_INVITE_CREATE_SUCCESS" | "FRIEND_INVITE_REVOKE_REQUEST" | "FRIEND_INVITE_REVOKE_SUCCESS" | "FRIEND_SUGGESTION_CREATE" | "FRIEND_SUGGESTION_DELETE" | "GAMES_DATABASE_FETCH" | "GAMES_DATABASE_FETCH_FAIL" | "GAMES_DATABASE_UPDATE" | "GAME_CLOUD_SYNC_COMPLETE" | "GAME_CLOUD_SYNC_CONFLICT" | "GAME_CLOUD_SYNC_ERROR" | "GAME_CLOUD_SYNC_START" | "GAME_CLOUD_SYNC_UPDATE" | "GAME_CONSOLE_FETCH_DEVICES_FAIL" | "GAME_CONSOLE_FETCH_DEVICES_START" | "GAME_CONSOLE_FETCH_DEVICES_SUCCESS" | "GAME_ICON_UPDATE" | "GAME_LAUNCHABLE_UPDATE" | "GAME_LAUNCH_FAIL" | "GAME_LAUNCH_START" | "GAME_LAUNCH_SUCCESS" | "GENERIC_PUSH_NOTIFICATION_SENT" | "GIFT_CODES_FETCH" | "GIFT_CODES_FETCH_FAILURE" | "GIFT_CODES_FETCH_SUCCESS" | "GIFT_CODE_CREATE" | "GIFT_CODE_CREATE_SUCCESS" | "GIFT_CODE_REDEEM" | "GIFT_CODE_REDEEM_FAILURE" | "GIFT_CODE_REDEEM_SUCCESS" | "GIFT_CODE_RESOLVE" | "GIFT_CODE_RESOLVE_FAILURE" | "GIFT_CODE_RESOLVE_SUCCESS" | "GIFT_CODE_REVOKE_SUCCESS" | "GIFT_CODE_UPDATE" | "GIF_PICKER_INITIALIZE" | "GIF_PICKER_QUERY" | "GIF_PICKER_QUERY_FAILURE" | "GIF_PICKER_QUERY_SUCCESS" | "GIF_PICKER_SUGGESTIONS_SUCCESS" | "GIF_PICKER_TRENDING_FETCH_SUCCESS" | "GIF_PICKER_TRENDING_SEARCH_TERMS_SUCCESS" | "GUILD_ACK" | "GUILD_ANALYTICS_ENGAGEMENT_OVERVIEW_FETCH_FAILURE" | "GUILD_ANALYTICS_ENGAGEMENT_OVERVIEW_FETCH_SUCCESS" | "GUILD_ANALYTICS_GROWTH_ACTIVATION_OVERVIEW_FETCH_FAILURE" | "GUILD_ANALYTICS_GROWTH_ACTIVATION_OVERVIEW_FETCH_SUCCESS" | "GUILD_ANALYTICS_GROWTH_ACTIVATION_RETENTION_FETCH_FAILURE" | "GUILD_ANALYTICS_GROWTH_ACTIVATION_RETENTION_FETCH_SUCCESS" | "GUILD_ANALYTICS_MEMBER_INSIGHTS_FETCH_SUCCESS" | "GUILD_APPLICATIONS_FETCH_SUCCESS" | "GUILD_APPLICATION_COMMAND_INDEX_UPDATE" | "GUILD_APPLIED_BOOSTS_FETCH_SUCCESS" | "GUILD_APPLY_BOOST_FAIL" | "GUILD_APPLY_BOOST_START" | "GUILD_APPLY_BOOST_SUCCESS" | "GUILD_BAN_ADD" | "GUILD_BAN_REMOVE" | "GUILD_BOOST_SLOTS_FETCH_SUCCESS" | "GUILD_BOOST_SLOT_CREATE" | "GUILD_BOOST_SLOT_UPDATE" | "GUILD_BOOST_SLOT_UPDATE_SUCCESS" | "GUILD_CREATE" | "GUILD_DELETE" | "GUILD_DIRECTORY_ADMIN_ENTRIES_FETCH_SUCCESS" | "GUILD_DIRECTORY_CACHED_SEARCH" | "GUILD_DIRECTORY_CATEGORY_SELECT" | "GUILD_DIRECTORY_COUNTS_FETCH_SUCCESS" | "GUILD_DIRECTORY_ENTRY_CREATE" | "GUILD_DIRECTORY_ENTRY_DELETE" | "GUILD_DIRECTORY_ENTRY_UPDATE" | "GUILD_DIRECTORY_FETCH_FAILURE" | "GUILD_DIRECTORY_FETCH_START" | "GUILD_DIRECTORY_FETCH_SUCCESS" | "GUILD_DIRECTORY_SEARCH_CLEAR" | "GUILD_DIRECTORY_SEARCH_FAILURE" | "GUILD_DIRECTORY_SEARCH_START" | "GUILD_DIRECTORY_SEARCH_SUCCESS" | "GUILD_DISCOVERY_CATEGORY_ADD" | "GUILD_DISCOVERY_CATEGORY_DELETE" | "GUILD_DISCOVERY_CATEGORY_FETCH_SUCCESS" | "GUILD_DISCOVERY_CATEGORY_UPDATE_FAIL" | "GUILD_DISCOVERY_CLEAR_SEARCH" | "GUILD_DISCOVERY_CLEAR_SEEN_GUILDS" | "GUILD_DISCOVERY_FETCH_FAILURE" | "GUILD_DISCOVERY_FETCH_START" | "GUILD_DISCOVERY_FETCH_SUCCESS" | "GUILD_DISCOVERY_GUILD_SEEN" | "GUILD_DISCOVERY_METADATA_FETCH_FAIL" | "GUILD_DISCOVERY_POPULAR_FETCH_FAILURE" | "GUILD_DISCOVERY_POPULAR_FETCH_START" | "GUILD_DISCOVERY_POPULAR_FETCH_SUCCESS" | "GUILD_DISCOVERY_SEARCH_COUNTS_FAIL" | "GUILD_DISCOVERY_SEARCH_FETCH_FAILURE" | "GUILD_DISCOVERY_SEARCH_FETCH_START" | "GUILD_DISCOVERY_SEARCH_FETCH_SUCCESS" | "GUILD_DISCOVERY_SEARCH_INIT" | "GUILD_DISCOVERY_SEARCH_UPDATE_COUNTS" | "GUILD_DISCOVERY_SELECT_CATEGORY" | "GUILD_DISCOVERY_SLUG_FETCH_SUCCESS" | "GUILD_EMOJIS_UPDATE" | "GUILD_FEATURE_ACK" | "GUILD_FEED_FEATURED_ITEMS_FETCH_FAILURE" | "GUILD_FEED_FEATURED_ITEMS_FETCH_SUCCESS" | "GUILD_FEED_FEATURE_ITEM" | "GUILD_FEED_FETCH_FAILURE" | "GUILD_FEED_FETCH_FRESH_START" | "GUILD_FEED_FETCH_PAGE_START" | "GUILD_FEED_FETCH_SUCCESS" | "GUILD_FEED_ITEM_HIDE" | "GUILD_FEED_ITEM_READ_ACK" | "GUILD_FEED_ITEM_REMOVE" | "GUILD_FEED_ITEM_UNHIDE" | "GUILD_FEED_UNFEATURE_ITEM" | "GUILD_FOLDER_COLLAPSE" | "GUILD_HOME_ENSURE_HOME_SESSION" | "GUILD_HOME_SET_SCROLL_POSITION" | "GUILD_HOME_SET_SOURCE" | "GUILD_IDENTITY_SETTINGS_CLEAR_ERRORS" | "GUILD_IDENTITY_SETTINGS_CLOSE" | "GUILD_IDENTITY_SETTINGS_INIT" | "GUILD_IDENTITY_SETTINGS_RESET_ALL_PENDING" | "GUILD_IDENTITY_SETTINGS_RESET_AND_CLOSE_FORM" | "GUILD_IDENTITY_SETTINGS_RESET_PENDING_MEMBER_CHANGES" | "GUILD_IDENTITY_SETTINGS_RESET_PENDING_PROFILE_CHANGES" | "GUILD_IDENTITY_SETTINGS_SET_DISABLE_SUBMIT" | "GUILD_IDENTITY_SETTINGS_SET_GUILD" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_AVATAR" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_BANNER" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_BIO" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_NICKNAME" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_PRONOUNS" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_THEME_COLORS" | "GUILD_IDENTITY_SETTINGS_SUBMIT" | "GUILD_IDENTITY_SETTINGS_SUBMIT_FAILURE" | "GUILD_IDENTITY_SETTINGS_SUBMIT_SUCCESS" | "GUILD_INTEGRATIONS_UPDATE" | "GUILD_JOIN" | "GUILD_JOIN_REQUESTS_BULK_ACTION" | "GUILD_JOIN_REQUESTS_FETCH_FAILURE" | "GUILD_JOIN_REQUESTS_FETCH_START" | "GUILD_JOIN_REQUESTS_FETCH_SUCCESS" | "GUILD_JOIN_REQUESTS_SET_APPLICATION_STATUS" | "GUILD_JOIN_REQUESTS_SET_SELECTED" | "GUILD_JOIN_REQUESTS_SET_SORT_ORDER" | "GUILD_JOIN_REQUEST_CREATE" | "GUILD_JOIN_REQUEST_DELETE" | "GUILD_JOIN_REQUEST_UPDATE" | "GUILD_MEMBERS_CHUNK" | "GUILD_MEMBERS_REQUEST" | "GUILD_MEMBER_ADD" | "GUILD_MEMBER_LIST_UPDATE" | "GUILD_MEMBER_PROFILE_UPDATE" | "GUILD_MEMBER_REMOVE" | "GUILD_MEMBER_UPDATE" | "GUILD_MEMBER_UPDATE_LOCAL" | "GUILD_MOVE" | "GUILD_MOVE_BY_ID" | "GUILD_NSFW_AGREE" | "GUILD_ONBOARDING_COMPLETE" | "GUILD_ONBOARDING_PROMPTS_FETCH_FAILURE" | "GUILD_ONBOARDING_PROMPTS_FETCH_START" | "GUILD_ONBOARDING_PROMPTS_FETCH_SUCCESS" | "GUILD_ONBOARDING_PROMPTS_LOCAL_UPDATE" | "GUILD_ONBOARDING_SELECT_OPTION" | "GUILD_ONBOARDING_SET_STEP" | "GUILD_ONBOARDING_START" | "GUILD_ONBOARDING_UPDATE_RESPONSES_SUCCESS" | "GUILD_POPOUT_FETCH_FAILURE" | "GUILD_POPOUT_FETCH_START" | "GUILD_POPOUT_FETCH_SUCCESS" | "GUILD_PROGRESS_COMPLETED_SEEN" | "GUILD_PROGRESS_DISMISS" | "GUILD_PROGRESS_INITIALIZE" | "GUILD_PROMPT_VIEWED" | "GUILD_RECOMMENDATION_FETCH" | "GUILD_RECOMMENDATION_FETCH_FAILURE" | "GUILD_RECOMMENDATION_FETCH_SUCCESS" | "GUILD_ROLE_CONNECTIONS_CONFIGURATIONS_FETCH_SUCCESS" | "GUILD_ROLE_CONNECTION_ELIGIBILITY_FETCH_SUCCESS" | "GUILD_ROLE_CREATE" | "GUILD_ROLE_DELETE" | "GUILD_ROLE_MEMBER_ADD" | "GUILD_ROLE_MEMBER_BULK_ADD" | "GUILD_ROLE_MEMBER_COUNT_FETCH_SUCCESS" | "GUILD_ROLE_MEMBER_COUNT_UPDATE" | "GUILD_ROLE_MEMBER_REMOVE" | "GUILD_ROLE_SUBSCRIPTIONS_CREATE_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_DELETE_GROUP_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_DELETE_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTINGS" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTINGS_FAILURE" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTINGS_SUCCESS" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTING_FOR_PLAN" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTING_FOR_PLAN_SUCCESS" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_RESTRICTIONS" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_RESTRICTIONS_ABORTED" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_RESTRICTIONS_FAILURE" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_RESTRICTIONS_SUCCESS" | "GUILD_ROLE_SUBSCRIPTIONS_UPDATE_GROUP_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_UPDATE_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_UPDATE_SUBSCRIPTIONS_SETTINGS" | "GUILD_ROLE_SUBSCRIPTIONS_UPDATE_SUBSCRIPTION_TRIAL" | "GUILD_ROLE_UPDATE" | "GUILD_SCHEDULED_EVENT_CREATE" | "GUILD_SCHEDULED_EVENT_DELETE" | "GUILD_SCHEDULED_EVENT_RSVPS_FETCH_SUCESS" | "GUILD_SCHEDULED_EVENT_UPDATE" | "GUILD_SCHEDULED_EVENT_USERS_FETCH_SUCCESS" | "GUILD_SCHEDULED_EVENT_USER_ADD" | "GUILD_SCHEDULED_EVENT_USER_REMOVE" | "GUILD_SETTINGS_CANCEL_CHANGES" | "GUILD_SETTINGS_CLOSE" | "GUILD_SETTINGS_DEFAULT_CHANNELS_RESET" | "GUILD_SETTINGS_DEFAULT_CHANNELS_SAVE_FAILED" | "GUILD_SETTINGS_DEFAULT_CHANNELS_SAVE_SUCCESS" | "GUILD_SETTINGS_DEFAULT_CHANNELS_SUBMIT" | "GUILD_SETTINGS_DEFAULT_CHANNELS_TOGGLE" | "GUILD_SETTINGS_INIT" | "GUILD_SETTINGS_LOADED_BANS" | "GUILD_SETTINGS_LOADED_INTEGRATIONS" | "GUILD_SETTINGS_LOADED_INTEGRATIONS_WITH_COMMANDS" | "GUILD_SETTINGS_LOADED_INVITES" | "GUILD_SETTINGS_ONBOARDING_EDUCATION_UPSELL_DISMISSED" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_EDIT" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_ERRORS" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_RESET" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_SAVE_FAILED" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_SAVE_SUCCESS" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_SUBMIT" | "GUILD_SETTINGS_ONBOARDING_STEP" | "GUILD_SETTINGS_OPEN" | "GUILD_SETTINGS_ROLES_CLEAR_PERMISSIONS" | "GUILD_SETTINGS_ROLES_EDIT_SECTION_UPDATE" | "GUILD_SETTINGS_ROLES_INIT" | "GUILD_SETTINGS_ROLES_SAVE_FAIL" | "GUILD_SETTINGS_ROLES_SAVE_SUCCESS" | "GUILD_SETTINGS_ROLES_SORT_UPDATE" | "GUILD_SETTINGS_ROLES_SUBMITTING" | "GUILD_SETTINGS_ROLES_UPDATE_COLOR" | "GUILD_SETTINGS_ROLES_UPDATE_DESCRIPTION" | "GUILD_SETTINGS_ROLES_UPDATE_NAME" | "GUILD_SETTINGS_ROLES_UPDATE_PERMISSIONS" | "GUILD_SETTINGS_ROLES_UPDATE_PERMISSION_SET" | "GUILD_SETTINGS_ROLES_UPDATE_ROLE_CONNECTION_CONFIGURATIONS" | "GUILD_SETTINGS_ROLES_UPDATE_ROLE_ICON" | "GUILD_SETTINGS_ROLES_UPDATE_SETTINGS" | "GUILD_SETTINGS_ROLE_SELECT" | "GUILD_SETTINGS_SAVE_ROUTE_STACK" | "GUILD_SETTINGS_SET_MFA_SUCCESS" | "GUILD_SETTINGS_SET_SEARCH_QUERY" | "GUILD_SETTINGS_SET_SECTION" | "GUILD_SETTINGS_SET_VANITY_URL" | "GUILD_SETTINGS_SET_WIDGET" | "GUILD_SETTINGS_SUBMIT" | "GUILD_SETTINGS_SUBMIT_FAILURE" | "GUILD_SETTINGS_SUBMIT_SUCCESS" | "GUILD_SETTINGS_UPDATE" | "GUILD_SETTINGS_VANITY_URL_CLOSE" | "GUILD_SETTINGS_VANITY_URL_ERROR" | "GUILD_SETTINGS_VANITY_URL_RESET" | "GUILD_SETTINGS_VANITY_URL_SET" | "GUILD_SOUNDBOARD_DELETE_SUCCESS" | "GUILD_SOUNDBOARD_FETCH" | "GUILD_SOUNDBOARD_FETCH_FAILURE" | "GUILD_SOUNDBOARD_FETCH_SUCCESS" | "GUILD_SOUNDBOARD_SOUND_PLAY_END" | "GUILD_SOUNDBOARD_SOUND_PLAY_START" | "GUILD_SOUNDBOARD_UPDATE_SUCCESS" | "GUILD_SOUNDBOARD_UPLOAD_SUCCESS" | "GUILD_STICKERS_CREATE_SUCCESS" | "GUILD_STICKERS_FETCH_SUCCESS" | "GUILD_STICKERS_UPDATE" | "GUILD_STOP_LURKING" | "GUILD_STOP_LURKING_FAILURE" | "GUILD_SUBSCRIPTIONS" | "GUILD_SUBSCRIPTIONS_CHANNEL" | "GUILD_SUBSCRIPTIONS_FLUSH" | "GUILD_SUBSCRIPTIONS_MEMBERS_ADD" | "GUILD_SUBSCRIPTIONS_MEMBERS_REMOVE" | "GUILD_TEMPLATE_ACCEPT" | "GUILD_TEMPLATE_ACCEPT_FAILURE" | "GUILD_TEMPLATE_ACCEPT_SUCCESS" | "GUILD_TEMPLATE_CREATE_SUCCESS" | "GUILD_TEMPLATE_DELETE_SUCCESS" | "GUILD_TEMPLATE_DIRTY_TOOLTIP_HIDE" | "GUILD_TEMPLATE_DIRTY_TOOLTIP_REFRESH" | "GUILD_TEMPLATE_LOAD_FOR_GUILD_SUCCESS" | "GUILD_TEMPLATE_MODAL_HIDE" | "GUILD_TEMPLATE_MODAL_SHOW" | "GUILD_TEMPLATE_PROMOTION_TOOLTIP_HIDE" | "GUILD_TEMPLATE_RESOLVE" | "GUILD_TEMPLATE_RESOLVE_FAILURE" | "GUILD_TEMPLATE_RESOLVE_SUCCESS" | "GUILD_TEMPLATE_SYNC_SUCCESS" | "GUILD_TOGGLE_COLLAPSE_MUTED" | "GUILD_TOP_READ_CHANNELS_FETCH_SUCCESS" | "GUILD_UNAPPLY_BOOST_FAIL" | "GUILD_UNAPPLY_BOOST_START" | "GUILD_UNAPPLY_BOOST_SUCCESS" | "GUILD_UNAVAILABLE" | "GUILD_UNREADS_SET_LAST_CLEARED" | "GUILD_UPDATE" | "GUILD_UPDATE_DISCOVERY_METADATA" | "GUILD_UPDATE_DISCOVERY_METADATA_FAIL" | "GUILD_UPDATE_DISCOVERY_METADATA_FROM_SERVER" | "GUILD_VERIFICATION_CHECK" | "HIDE_ACTION_SHEET" | "HIDE_ACTION_SHEET_QUICK_SWITCHER" | "HIDE_KEYBOARD_SHORTCUTS" | "HIDE_SPAM_MESSAGES_FOR_USER" | "HOTSPOT_HIDE" | "HOTSPOT_OVERRIDE_CLEAR" | "HOTSPOT_OVERRIDE_SET" | "HYPESQUAD_ONLINE_MEMBERSHIP_JOIN_SUCCESS" | "HYPESQUAD_ONLINE_MEMBERSHIP_LEAVE_SUCCESS" | "I18N_LOAD_ERROR" | "I18N_LOAD_START" | "I18N_LOAD_SUCCESS" | "IDLE" | "IMPERSONATE_STOP" | "IMPERSONATE_UPDATE" | "INBOX_OPEN" | "INCOMING_CALL_MOVE" | "INSTALLATION_LOCATION_ADD" | "INSTALLATION_LOCATION_FETCH_METADATA" | "INSTALLATION_LOCATION_REMOVE" | "INSTALLATION_LOCATION_UPDATE" | "INSTANT_INVITE_CREATE" | "INSTANT_INVITE_CREATE_FAILURE" | "INSTANT_INVITE_CREATE_SUCCESS" | "INSTANT_INVITE_REVOKE_SUCCESS" | "INTEGRATION_PERMISSION_SETTINGS_APPLICATION_PERMISSIONS_FETCH_FAILURE" | "INTEGRATION_PERMISSION_SETTINGS_CLEAR" | "INTEGRATION_PERMISSION_SETTINGS_COMMANDS_FETCH_FAILURE" | "INTEGRATION_PERMISSION_SETTINGS_COMMANDS_FETCH_SUCCESS" | "INTEGRATION_PERMISSION_SETTINGS_COMMAND_UPDATE" | "INTEGRATION_PERMISSION_SETTINGS_EDIT" | "INTEGRATION_PERMISSION_SETTINGS_INIT" | "INTEGRATION_PERMISSION_SETTINGS_RESET" | "INTEGRATION_QUERY" | "INTEGRATION_QUERY_FAILURE" | "INTEGRATION_QUERY_SUCCESS" | "INTEGRATION_SETTINGS_INIT" | "INTEGRATION_SETTINGS_SAVE_FAILURE" | "INTEGRATION_SETTINGS_SAVE_SUCCESS" | "INTEGRATION_SETTINGS_SET_SECTION" | "INTEGRATION_SETTINGS_START_EDITING_COMMAND" | "INTEGRATION_SETTINGS_START_EDITING_INTEGRATION" | "INTEGRATION_SETTINGS_START_EDITING_WEBHOOK" | "INTEGRATION_SETTINGS_STOP_EDITING_COMMAND" | "INTEGRATION_SETTINGS_STOP_EDITING_INTEGRATION" | "INTEGRATION_SETTINGS_STOP_EDITING_WEBHOOK" | "INTEGRATION_SETTINGS_SUBMITTING" | "INTEGRATION_SETTINGS_UPDATE_INTEGRATION" | "INTEGRATION_SETTINGS_UPDATE_WEBHOOK" | "INTERACTION_CREATE" | "INTERACTION_FAILURE" | "INTERACTION_MODAL_CREATE" | "INTERACTION_QUEUE" | "INTERACTION_SUCCESS" | "INVITE_ACCEPT" | "INVITE_ACCEPT_FAILURE" | "INVITE_ACCEPT_SUCCESS" | "INVITE_APP_NOT_OPENED" | "INVITE_APP_OPENED" | "INVITE_APP_OPENING" | "INVITE_MODAL_CLOSE" | "INVITE_MODAL_ERROR" | "INVITE_MODAL_OPEN" | "INVITE_RESOLVE" | "INVITE_RESOLVE_FAILURE" | "INVITE_RESOLVE_SUCCESS" | "KEYBINDS_ADD_KEYBIND" | "KEYBINDS_DELETE_KEYBIND" | "KEYBINDS_ENABLE_ALL_KEYBINDS" | "KEYBINDS_REGISTER_GLOBAL_KEYBIND_ACTIONS" | "KEYBINDS_SET_KEYBIND" | "KEYBOARD_NAVIGATION_EXPLAINER_MODAL_SEEN" | "LAYER_POP" | "LAYER_POP_ALL" | "LAYER_PUSH" | "LAYOUT_CREATE" | "LAYOUT_CREATE_WIDGETS" | "LAYOUT_DELETE_ALL_WIDGETS" | "LAYOUT_DELETE_WIDGET" | "LAYOUT_SET_PINNED" | "LAYOUT_SET_TOP_WIDGET" | "LAYOUT_UPDATE_WIDGET" | "LIBRARY_APPLICATIONS_TEST_MODE_ENABLED" | "LIBRARY_APPLICATION_ACTIVE_BRANCH_UPDATE" | "LIBRARY_APPLICATION_ACTIVE_LAUNCH_OPTION_UPDATE" | "LIBRARY_APPLICATION_FILTER_UPDATE" | "LIBRARY_APPLICATION_FLAGS_UPDATE_START" | "LIBRARY_APPLICATION_FLAGS_UPDATE_SUCCESS" | "LIBRARY_APPLICATION_UPDATE" | "LIBRARY_FETCH_SUCCESS" | "LIBRARY_TABLE_ACTIVE_ROW_ID_UPDATE" | "LIBRARY_TABLE_SORT_UPDATE" | "LIVE_CHANNEL_NOTICE_HIDE" | "LOAD_ARCHIVED_THREADS" | "LOAD_ARCHIVED_THREADS_FAIL" | "LOAD_ARCHIVED_THREADS_SUCCESS" | "LOAD_FORUM_POSTS" | "LOAD_FRIEND_SUGGESTIONS_FAILURE" | "LOAD_FRIEND_SUGGESTIONS_SUCCESS" | "LOAD_GUILD_AFFINITIES_SUCCESS" | "LOAD_MESSAGES" | "LOAD_MESSAGES_AROUND_SUCCESS" | "LOAD_MESSAGES_FAILURE" | "LOAD_MESSAGES_SUCCESS" | "LOAD_MESSAGES_SUCCESS_CACHED" | "LOAD_MESSAGE_INTERACTION_DATA_SUCCESS" | "LOAD_MESSAGE_REQUESTS_SUPPLEMENTAL_DATA_ERROR" | "LOAD_MESSAGE_REQUESTS_SUPPLEMENTAL_DATA_SUCCESS" | "LOAD_NOTIFICATION_CENTER_ITEMS" | "LOAD_NOTIFICATION_CENTER_ITEMS_FAILURE" | "LOAD_NOTIFICATION_CENTER_ITEMS_SUCCESS" | "LOAD_PINNED_MESSAGES" | "LOAD_PINNED_MESSAGES_FAILURE" | "LOAD_PINNED_MESSAGES_SUCCESS" | "LOAD_RECENT_MENTIONS" | "LOAD_RECENT_MENTIONS_FAILURE" | "LOAD_RECENT_MENTIONS_SUCCESS" | "LOAD_REGIONS" | "LOAD_RELATIONSHIPS_FAILURE" | "LOAD_RELATIONSHIPS_SUCCESS" | "LOAD_THREADS_SUCCESS" | "LOAD_USER_AFFINITIES" | "LOAD_USER_AFFINITIES_FAILURE" | "LOAD_USER_AFFINITIES_SUCCESS" | "LOBBY_CONNECT" | "LOBBY_CREATE" | "LOBBY_DELETE" | "LOBBY_DISCONNECT" | "LOBBY_MEMBER_CONNECT" | "LOBBY_MEMBER_DISCONNECT" | "LOBBY_MEMBER_UPDATE" | "LOBBY_MESSAGE" | "LOBBY_UPDATE" | "LOBBY_VOICE_CONNECT" | "LOBBY_VOICE_DISCONNECT" | "LOBBY_VOICE_SERVER_UPDATE" | "LOBBY_VOICE_STATE_UPDATE" | "LOCAL_ACTIVITY_UPDATE" | "LOGIN" | "LOGIN_ACCOUNT_DISABLED" | "LOGIN_ACCOUNT_SCHEDULED_FOR_DELETION" | "LOGIN_ATTEMPTED" | "LOGIN_FAILURE" | "LOGIN_MFA" | "LOGIN_MFA_FAILURE" | "LOGIN_MFA_SMS" | "LOGIN_MFA_SMS_FAILURE" | "LOGIN_MFA_SMS_REQUEST_SUCCESS" | "LOGIN_MFA_STEP" | "LOGIN_MFA_WEBAUTHN" | "LOGIN_MFA_WEBAUTHN_TO_TOTP" | "LOGIN_PASSWORD_RECOVERY_PHONE_VERIFICATION" | "LOGIN_PHONE_IP_AUTHORIZATION_REQUIRED" | "LOGIN_RESET" | "LOGIN_STATUS_RESET" | "LOGIN_SUCCESS" | "LOGOUT" | "LOGOUT_AUTH_SESSIONS_SUCCESS" | "MASKED_LINK_ADD_TRUSTED_DOMAIN" | "MASKED_LINK_ADD_TRUSTED_PROTOCOL" | "MAX_MEMBER_COUNT_NOTICE_DISMISS" | "MEDIA_ENGINE_APPLY_MEDIA_FILTER_SETTINGS" | "MEDIA_ENGINE_APPLY_MEDIA_FILTER_SETTINGS_ERROR" | "MEDIA_ENGINE_APPLY_MEDIA_FILTER_SETTINGS_START" | "MEDIA_ENGINE_DEVICES" | "MEDIA_ENGINE_ENABLE_SOUNDSHARE" | "MEDIA_ENGINE_INTERACTION_REQUIRED" | "MEDIA_ENGINE_NOISE_CANCELLATION_ERROR_RESET" | "MEDIA_ENGINE_PERMISSION" | "MEDIA_ENGINE_SET_AEC_DUMP" | "MEDIA_ENGINE_SET_AUDIO_ENABLED" | "MEDIA_ENGINE_SET_AV1" | "MEDIA_ENGINE_SET_DESKTOP_SOURCE" | "MEDIA_ENGINE_SET_EXPERIMENTAL_ENCODERS" | "MEDIA_ENGINE_SET_EXPERIMENTAL_SOUNDSHARE" | "MEDIA_ENGINE_SET_HARDWARE_H264" | "MEDIA_ENGINE_SET_OPEN_H264" | "MEDIA_ENGINE_SET_VIDEO_DEVICE" | "MEDIA_ENGINE_SET_VIDEO_ENABLED" | "MEDIA_ENGINE_SET_VIDEO_HOOK" | "MEDIA_ENGINE_SOUNDSHARE_FAILED" | "MEDIA_ENGINE_SOUNDSHARE_TRANSMITTING" | "MEDIA_ENGINE_VIDEO_SOURCE_QUALITY_CHANGED" | "MEDIA_ENGINE_VIDEO_STATE_CHANGED" | "MEMBER_VERIFICATION_FORM_FETCH_FAIL" | "MEMBER_VERIFICATION_FORM_UPDATE" | "MENTION_MODAL_CLOSE" | "MENTION_MODAL_OPEN" | "MESSAGE_ACK" | "MESSAGE_CREATE" | "MESSAGE_DELETE" | "MESSAGE_DELETE_BULK" | "MESSAGE_EDIT_FAILED_AUTOMOD" | "MESSAGE_END_EDIT" | "MESSAGE_LENGTH_UPSELL" | "MESSAGE_REACTION_ADD" | "MESSAGE_REACTION_ADD_USERS" | "MESSAGE_REACTION_REMOVE" | "MESSAGE_REACTION_REMOVE_ALL" | "MESSAGE_REACTION_REMOVE_EMOJI" | "MESSAGE_REQUEST_ACCEPT_OPTIMISTIC" | "MESSAGE_REVEAL" | "MESSAGE_SEND_FAILED" | "MESSAGE_SEND_FAILED_AUTOMOD" | "MESSAGE_START_EDIT" | "MESSAGE_TODO_ADD" | "MESSAGE_TODO_CLEANUP" | "MESSAGE_TODO_COMPLETE" | "MESSAGE_UPDATE" | "MESSAGE_UPDATE_EDIT" | "MFA_CLEAR_BACKUP_CODES" | "MFA_DISABLE_SUCCESS" | "MFA_ENABLE_SUCCESS" | "MFA_SEND_VERIFICATION_KEY" | "MFA_SMS_TOGGLE" | "MFA_SMS_TOGGLE_COMPLETE" | "MFA_VIEW_BACKUP_CODES" | "MFA_WEBAUTHN_CREDENTIALS_LOADED" | "MFA_WEBAUTHN_CREDENTIALS_LOADING" | "MFA_WEBAUTHN_CREDENTIAL_CREATE" | "MFA_WEBAUTHN_CREDENTIAL_DELETE" | "MOBILE_WEB_SIDEBAR_CLOSE" | "MOBILE_WEB_SIDEBAR_OPEN" | "MODAL_POP" | "MODAL_PUSH" | "MULTI_ACCOUNT_INVALIDATE_PUSH_SYNC_TOKENS" | "MULTI_ACCOUNT_MOBILE_EXPERIMENT_UPDATE" | "MULTI_ACCOUNT_MOVE_ACCOUNT" | "MULTI_ACCOUNT_REMOVE_ACCOUNT" | "MULTI_ACCOUNT_UPDATE_PUSH_SYNC_TOKEN" | "MULTI_ACCOUNT_VALIDATE_TOKEN_FAILURE" | "MULTI_ACCOUNT_VALIDATE_TOKEN_REQUEST" | "MULTI_ACCOUNT_VALIDATE_TOKEN_SUCCESS" | "MUTUAL_FRIENDS_FETCH_FAILURE" | "MUTUAL_FRIENDS_FETCH_START" | "MUTUAL_FRIENDS_FETCH_SUCCESS" | "NEWLY_ADDED_EMOJI_SEEN_ACKNOWLEDGED" | "NEWLY_ADDED_EMOJI_SEEN_PENDING" | "NEWLY_ADDED_EMOJI_SEEN_UPDATED" | "NEW_PAYMENT_SOURCE_ADDRESS_INFO_UPDATE" | "NEW_PAYMENT_SOURCE_CARD_INFO_UPDATE" | "NEW_PAYMENT_SOURCE_CLEAR_ERROR" | "NEW_PAYMENT_SOURCE_STRIPE_PAYMENT_REQUEST_UPDATE" | "NITRODUCTION_PERSISTENT_ONBOARDING_TOGGLE_COLLAPSE" | "NOTICE_DISABLE" | "NOTICE_DISMISS" | "NOTICE_SHOW" | "NOTIFICATIONS_SET_DESKTOP_TYPE" | "NOTIFICATIONS_SET_DISABLED_SOUNDS" | "NOTIFICATIONS_SET_DISABLE_UNREAD_BADGE" | "NOTIFICATIONS_SET_NOTIFY_MESSAGES_IN_SELECTED_CHANNEL" | "NOTIFICATIONS_SET_PERMISSION_STATE" | "NOTIFICATIONS_SET_TASKBAR_FLASH" | "NOTIFICATIONS_SET_TTS_TYPE" | "NOTIFICATIONS_TOGGLE_ALL_DISABLED" | "NOTIFICATION_CENTER_ITEMS_ACK" | "NOTIFICATION_CENTER_ITEMS_ACK_FAILURE" | "NOTIFICATION_CENTER_ITEMS_LOCAL_ACK" | "NOTIFICATION_CENTER_ITEM_COMPLETED" | "NOTIFICATION_CENTER_ITEM_CREATE" | "NOTIFICATION_CENTER_ITEM_DELETE" | "NOTIFICATION_CENTER_ITEM_DELETE_FAILURE" | "NOTIFICATION_CENTER_SET_ACTIVE" | "NOTIFICATION_CENTER_SET_TAB" | "NOTIFICATION_CLICK" | "NOTIFICATION_CREATE" | "NOW_PLAYING_MOUNTED" | "NOW_PLAYING_UNMOUNTED" | "NUF_COMPLETE" | "NUF_NEW_USER" | "OAUTH2_TOKEN_REVOKE" | "ONLINE_GUILD_MEMBER_COUNT_UPDATE" | "OUTBOUND_PROMOTIONS_SEEN" | "OUTBOUND_PROMOTION_NOTICE_DISMISS" | "OVERLAY_ACTIVATE_REGION" | "OVERLAY_CALL_PRIVATE_CHANNEL" | "OVERLAY_CRASHED" | "OVERLAY_DEACTIVATE_ALL_REGIONS" | "OVERLAY_DISABLE_EXTERNAL_LINK_ALERT" | "OVERLAY_FOCUSED" | "OVERLAY_GAMES_CHANGE" | "OVERLAY_INCOMPATIBLE_APP" | "OVERLAY_INITIALIZE" | "OVERLAY_JOIN_GAME" | "OVERLAY_READY" | "OVERLAY_SELECT_CALL" | "OVERLAY_SELECT_CHANNEL" | "OVERLAY_SET_AVATAR_SIZE_MODE" | "OVERLAY_SET_DISPLAY_NAME_MODE" | "OVERLAY_SET_DISPLAY_USER_MODE" | "OVERLAY_SET_ENABLED" | "OVERLAY_SET_INPUT_LOCKED" | "OVERLAY_SET_NOTIFICATION_POSITION_MODE" | "OVERLAY_SET_NOT_IDLE" | "OVERLAY_SET_PREVIEW_IN_GAME_MODE" | "OVERLAY_SET_TEXT_CHAT_NOTIFICATION_MODE" | "OVERLAY_SET_TEXT_WIDGET_OPACITY" | "OVERLAY_SET_UI_LOCKED" | "OVERLAY_START_SESSION" | "PARTNER_REQUIREMENTS_FETCH_FAILURE" | "PARTNER_REQUIREMENTS_FETCH_START" | "PARTNER_REQUIREMENTS_FETCH_SUCCESS" | "PASSIVE_UPDATE_V1" | "PASSWORD_UPDATED" | "PAYMENT_AUTHENTICATION_CLEAR_ERROR" | "PAYMENT_AUTHENTICATION_ERROR" | "PAYMENT_UPDATE" | "PERMISSION_CLEAR_ELEVATED_PROCESS" | "PERMISSION_CLEAR_PTT_ADMIN_WARNING" | "PERMISSION_CLEAR_SUPPRESS_WARNING" | "PERMISSION_CLEAR_VAD_WARNING" | "PERMISSION_CONTINUE_NONELEVATED_PROCESS" | "PERMISSION_REQUEST_ELEVATED_PROCESS" | "PHONE_SET_COUNTRY_CODE" | "PICTURE_IN_PICTURE_CLOSE" | "PICTURE_IN_PICTURE_HIDE" | "PICTURE_IN_PICTURE_MOVE" | "PICTURE_IN_PICTURE_OPEN" | "PICTURE_IN_PICTURE_SHOW" | "PICTURE_IN_PICTURE_UPDATE_RECT" | "PICTURE_IN_PICTURE_UPDATE_SELECTED_WINDOW" | "POGGERMODE_ACHIEVEMENT_UNLOCK" | "POGGERMODE_SETTINGS_UPDATE" | "POGGERMODE_TEMPORARILY_DISABLED" | "POGGERMODE_UPDATE_COMBO" | "POGGERMODE_UPDATE_MESSAGE_COMBO" | "POPOUT_WINDOW_CLOSE" | "POPOUT_WINDOW_OPEN" | "POPOUT_WINDOW_SET_ALWAYS_ON_TOP" | "POST_CONNECTION_OPEN" | "PREMIUM_PAYMENT_ERROR_CLEAR" | "PREMIUM_PAYMENT_MODAL_CLOSE" | "PREMIUM_PAYMENT_MODAL_OPEN" | "PREMIUM_PAYMENT_SUBSCRIBE_FAIL" | "PREMIUM_PAYMENT_SUBSCRIBE_START" | "PREMIUM_PAYMENT_SUBSCRIBE_SUCCESS" | "PREMIUM_PAYMENT_UPDATE_FAIL" | "PREMIUM_PAYMENT_UPDATE_SUCCESS" | "PREMIUM_REQUIRED_MODAL_CLOSE" | "PREMIUM_REQUIRED_MODAL_OPEN" | "PRESENCES_REPLACE" | "PRESENCE_UPDATES" | "PRIVATE_CHANNEL_RECIPIENTS_ADD_USER" | "PRIVATE_CHANNEL_RECIPIENTS_INVITE_CLOSE" | "PRIVATE_CHANNEL_RECIPIENTS_INVITE_OPEN" | "PRIVATE_CHANNEL_RECIPIENTS_INVITE_QUERY" | "PRIVATE_CHANNEL_RECIPIENTS_INVITE_SELECT" | "PRIVATE_CHANNEL_RECIPIENTS_REMOVE_USER" | "PROFILE_CUSTOMIZATION_OPEN_PREVIEW_MODAL" | "PROFILE_PANEL_TOGGLE_SECTION" | "PUBLIC_UPSELL_NOTICE_DISMISS" | "PURCHASE_CONFIRMATION_MODAL_CLOSE" | "PURCHASE_CONFIRMATION_MODAL_OPEN" | "PUSH_NOTIFICATION_CLICK" | "QUEUE_INTERACTION_COMPONENT_STATE" | "QUICKSWITCHER_HIDE" | "QUICKSWITCHER_SEARCH" | "QUICKSWITCHER_SELECT" | "QUICKSWITCHER_SHOW" | "QUICKSWITCHER_SWITCH_TO" | "RECENT_MENTION_DELETE" | "REGISTER" | "REGISTER_FAILURE" | "REGISTER_SAVE_FORM" | "REGISTER_SUCCESS" | "RELATIONSHIP_ADD" | "RELATIONSHIP_REMOVE" | "RELATIONSHIP_UPDATE" | "REMOTE_COMMAND" | "REMOTE_SESSION_CONNECT" | "REMOTE_SESSION_DISCONNECT" | "REMOVE_AUTOMOD_MESSAGE_NOTICE" | "REQUEST_FORUM_UNREADS" | "RESET_ALL_NITRODUCTION_TOOLTIPS" | "RESET_HAS_COMPLETED_STEP" | "RESET_NOTIFICATION_CENTER" | "RESET_PAYMENT_ID" | "RESORT_THREADS" | "RPC_APP_AUTHENTICATED" | "RPC_APP_CONNECTED" | "RPC_APP_DISCONNECTED" | "RPC_NOTIFICATION_CREATE" | "RPC_SERVER_READY" | "RTC_CONNECTION_LOSS_RATE" | "RTC_CONNECTION_PING" | "RTC_CONNECTION_STATE" | "RTC_CONNECTION_UPDATE_ID" | "RTC_CONNECTION_VIDEO" | "RTC_DEBUG_MODAL_CLOSE" | "RTC_DEBUG_MODAL_OPEN" | "RTC_DEBUG_MODAL_OPEN_REPLAY" | "RTC_DEBUG_MODAL_OPEN_REPLAY_AT_PATH" | "RTC_DEBUG_MODAL_SET_SECTION" | "RTC_DEBUG_MODAL_UPDATE" | "RTC_DEBUG_MODAL_UPDATE_VIDEO_OUTPUT" | "RTC_DEBUG_POPOUT_WINDOW_OPEN" | "RTC_DEBUG_SET_RECORDING_FLAG" | "RTC_LATENCY_TEST_COMPLETE" | "RUNNING_GAMES_CHANGE" | "RUNNING_GAME_ADD_OVERRIDE" | "RUNNING_GAME_DELETE_ENTRY" | "RUNNING_GAME_EDIT_NAME" | "RUNNING_GAME_TOGGLE_OVERLAY" | "RUNNING_STREAMER_TOOLS_CHANGE" | "SAVE_LAST_NON_VOICE_ROUTE" | "SAVE_LAST_ROUTE" | "SEARCH_AUTOCOMPLETE_QUERY_UPDATE" | "SEARCH_CLEAR_HISTORY" | "SEARCH_EDITOR_STATE_CHANGE" | "SEARCH_EDITOR_STATE_CLEAR" | "SEARCH_ENSURE_SEARCH_STATE" | "SEARCH_FINISH" | "SEARCH_INDEXING" | "SEARCH_MODAL_CLOSE" | "SEARCH_MODAL_OPEN" | "SEARCH_SET_SHOW_BLOCKED_RESULTS" | "SEARCH_START" | "SELECTIVELY_SYNCED_USER_SETTINGS_UPDATE" | "SELF_PRESENCE_STORE_UPDATE" | "SESSIONS_REPLACE" | "SET_CHANNEL_BITRATE" | "SET_CHANNEL_VIDEO_QUALITY_MODE" | "SET_CONSENT_REQUIRED" | "SET_GUILD_FOLDER_EXPANDED" | "SET_HAS_COMPLETED_STEP" | "SET_INTERACTION_COMPONENT_STATE" | "SET_LOCATION_METADATA" | "SET_LOGIN_CREDENTIALS" | "SET_NATIVE_PERMISSION" | "SET_PENDING_REPLY_SHOULD_MENTION" | "SET_RECENT_MENTIONS_FILTER" | "SET_RECENT_MENTIONS_STALE" | "SET_SOUNDPACK" | "SET_TTS_SPEECH_RATE" | "SET_VAD_PERMISSION" | "SHOW_ACTION_SHEET" | "SHOW_ACTION_SHEET_QUICK_SWITCHER" | "SHOW_KEYBOARD_SHORTCUTS" | "SIDEBAR_CLOSE" | "SIDEBAR_CREATE_THREAD" | "SIDEBAR_VIEW_CHANNEL" | "SKUS_FETCH_SUCCESS" | "SKU_FETCH_FAIL" | "SKU_FETCH_START" | "SKU_FETCH_SUCCESS" | "SKU_PURCHASE_CLEAR_ERROR" | "SKU_PURCHASE_FAIL" | "SKU_PURCHASE_MODAL_CLOSE" | "SKU_PURCHASE_MODAL_OPEN" | "SKU_PURCHASE_PREVIEW_FETCH_SUCCESS" | "SKU_PURCHASE_SHOW_CONFIRMATION_STEP" | "SKU_PURCHASE_START" | "SKU_PURCHASE_SUCCESS" | "SKU_PURCHASE_UPDATE_IS_GIFT" | "SLOWMODE_RESET_COOLDOWN" | "SLOWMODE_SET_COOLDOWN" | "SOUNDBOARD_ADD_FAVORITE_SOUND" | "SOUNDBOARD_REMOVE_FAVORITE_SOUND" | "SPEAKING" | "SPEAKING_MESSAGE" | "SPEAK_MESSAGE" | "SPEAK_TEXT" | "SPELLCHECK_LEARN_WORD" | "SPELLCHECK_TOGGLE" | "SPOTIFY_ACCOUNT_ACCESS_TOKEN" | "SPOTIFY_ACCOUNT_ACCESS_TOKEN_REVOKE" | "SPOTIFY_PLAYER_PAUSE" | "SPOTIFY_PLAYER_PLAY" | "SPOTIFY_PLAYER_STATE" | "SPOTIFY_PROFILE_UPDATE" | "SPOTIFY_SET_ACTIVE_DEVICE" | "SPOTIFY_SET_DEVICES" | "SPOTIFY_SET_PROTOCOL_REGISTERED" | "STAGE_INSTANCE_CREATE" | "STAGE_INSTANCE_DELETE" | "STAGE_INSTANCE_UPDATE" | "START_SESSION" | "STATUS_PAGE_INCIDENT" | "STATUS_PAGE_SCHEDULED_MAINTENANCE" | "STATUS_PAGE_SCHEDULED_MAINTENANCE_ACK" | "STICKER_FETCH_SUCCESS" | "STICKER_PACKS_FETCH_START" | "STICKER_PACKS_FETCH_SUCCESS" | "STICKER_PACK_FETCH_SUCCESS" | "STICKER_TRACK_USAGE" | "STOP_SPEAKING" | "STORE_APPLICATION_INTERACTION_FAKE_USER" | "STORE_LISTINGS_FETCH_SUCCESS" | "STORE_LISTING_FETCH_SUCCESS" | "STREAMER_MODE_UPDATE" | "STREAMING_UPDATE" | "STREAM_CLOSE" | "STREAM_CREATE" | "STREAM_DELETE" | "STREAM_LAYOUT_UPDATE" | "STREAM_PREVIEW_FETCH_FAIL" | "STREAM_PREVIEW_FETCH_START" | "STREAM_PREVIEW_FETCH_SUCCESS" | "STREAM_SERVER_UPDATE" | "STREAM_SET_PAUSED" | "STREAM_START" | "STREAM_STATS_UPDATE" | "STREAM_STOP" | "STREAM_TIMED_OUT" | "STREAM_UPDATE" | "STREAM_UPDATE_SELF_HIDDEN" | "STREAM_UPDATE_SETTINGS" | "STREAM_WATCH" | "STRIPE_TOKEN_FAILURE" | "SUBSCRIPTION_PLANS_FETCH" | "SUBSCRIPTION_PLANS_FETCH_FAILURE" | "SUBSCRIPTION_PLANS_FETCH_SUCCESS" | "SUBSCRIPTION_PLANS_RESET" | "SURVEY_FETCHED" | "SURVEY_HIDE" | "SURVEY_OVERRIDE" | "SYSTEM_THEME_CHANGE" | "THERMAL_STATE_CHANGE" | "THREAD_CREATE" | "THREAD_CREATE_LOCAL" | "THREAD_DELETE" | "THREAD_LIST_SYNC" | "THREAD_MEMBERS_UPDATE" | "THREAD_MEMBER_LIST_UPDATE" | "THREAD_MEMBER_LOCAL_UPDATE" | "THREAD_MEMBER_UPDATE" | "THREAD_SETTINGS_DRAFT_CHANGE" | "THREAD_UPDATE" | "TOGGLE_GUILD_FOLDER_EXPAND" | "TOP_EMOJIS_FETCH" | "TOP_EMOJIS_FETCH_SUCCESS" | "TRUNCATE_MENTIONS" | "TRUNCATE_MESSAGES" | "TUTORIAL_INDICATOR_DISMISS" | "TUTORIAL_INDICATOR_HIDE" | "TUTORIAL_INDICATOR_SHOW" | "TUTORIAL_INDICATOR_SUPPRESS_ALL" | "TYPING_START" | "TYPING_START_LOCAL" | "TYPING_STOP" | "TYPING_STOP_LOCAL" | "UNSYNCED_USER_SETTINGS_UPDATE" | "UNVERIFIED_GAME_UPDATE" | "UPDATE_APP_COLORS" | "UPDATE_AVAILABLE" | "UPDATE_CHANNEL_DIMENSIONS" | "UPDATE_CHANNEL_LIST_DIMENSIONS" | "UPDATE_CONSENTS" | "UPDATE_DOWNLOADED" | "UPDATE_ERROR" | "UPDATE_GUILD_LIST_DIMENSIONS" | "UPDATE_HAS_FLOW_START_EVENT_BEEN_EMITTED" | "UPDATE_MANUALLY" | "UPDATE_NOT_AVAILABLE" | "UPDATE_TOKEN" | "UPLOAD_ATTACHMENT_ADD_FILES" | "UPLOAD_ATTACHMENT_CLEAR_ALL_FILES" | "UPLOAD_ATTACHMENT_POP_FILE" | "UPLOAD_ATTACHMENT_REMOVE_FILE" | "UPLOAD_ATTACHMENT_REMOVE_FILES" | "UPLOAD_ATTACHMENT_SET_FILE" | "UPLOAD_ATTACHMENT_SET_UPLOADS" | "UPLOAD_ATTACHMENT_UPDATE_FILE" | "UPLOAD_CANCEL_REQUEST" | "UPLOAD_COMPLETE" | "UPLOAD_COMPRESSION_PROGRESS" | "UPLOAD_FAIL" | "UPLOAD_PROGRESS" | "UPLOAD_RESTORE_FAILED_UPLOAD" | "UPLOAD_START" | "USER_ACHIEVEMENT_UPDATE" | "USER_ACTIVITY_STATISTICS_FETCH_SUCCESS" | "USER_APPLIED_BOOSTS_FETCH_SUCCESS" | "USER_AUTHORIZED_APPS_UPDATE" | "USER_CONNECTIONS_INTEGRATION_JOINING" | "USER_CONNECTIONS_UPDATE" | "USER_CONNECTION_UPDATE" | "USER_GUILD_JOIN_REQUEST_UPDATE" | "USER_GUILD_SETTINGS_CHANNEL_UPDATE" | "USER_GUILD_SETTINGS_CHANNEL_UPDATE_BULK" | "USER_GUILD_SETTINGS_FULL_UPDATE" | "USER_GUILD_SETTINGS_GUILD_AND_CHANNELS_UPDATE" | "USER_GUILD_SETTINGS_GUILD_UPDATE" | "USER_GUILD_SETTINGS_REMOVE_PENDING_CHANNEL_UPDATES" | "USER_JOIN_REQUEST_GUILDS_FETCH" | "USER_NON_CHANNEL_ACK" | "USER_NOTE_LOADED" | "USER_NOTE_LOAD_START" | "USER_NOTE_UPDATE" | "USER_PAYMENT_CLIENT_ADD" | "USER_PROFILE_ACCESSIBILITY_TOOLTIP_VIEWED" | "USER_PROFILE_FETCH_FAILURE" | "USER_PROFILE_FETCH_START" | "USER_PROFILE_FETCH_SUCCESS" | "USER_PROFILE_MODAL_CLOSE" | "USER_PROFILE_MODAL_OPEN" | "USER_PROFILE_UPDATE_SUCCESS" | "USER_REQUIRED_ACTION_UPDATE" | "USER_SETTINGS_ACCOUNT_CLOSE" | "USER_SETTINGS_ACCOUNT_INIT" | "USER_SETTINGS_ACCOUNT_RESET_AND_CLOSE_FORM" | "USER_SETTINGS_ACCOUNT_SET_DISABLE_SUBMIT" | "USER_SETTINGS_ACCOUNT_SET_PENDING_ACCENT_COLOR" | "USER_SETTINGS_ACCOUNT_SET_PENDING_AVATAR" | "USER_SETTINGS_ACCOUNT_SET_PENDING_AVATAR_DECORATION" | "USER_SETTINGS_ACCOUNT_SET_PENDING_BANNER" | "USER_SETTINGS_ACCOUNT_SET_PENDING_BIO" | "USER_SETTINGS_ACCOUNT_SET_PENDING_PRONOUNS" | "USER_SETTINGS_ACCOUNT_SET_PENDING_THEME_COLORS" | "USER_SETTINGS_ACCOUNT_SET_TRY_IT_OUT_AVATAR" | "USER_SETTINGS_ACCOUNT_SET_TRY_IT_OUT_BANNER" | "USER_SETTINGS_ACCOUNT_SET_TRY_IT_OUT_THEME_COLORS" | "USER_SETTINGS_ACCOUNT_SUBMIT" | "USER_SETTINGS_ACCOUNT_SUBMIT_FAILURE" | "USER_SETTINGS_ACCOUNT_SUBMIT_SUCCESS" | "USER_SETTINGS_CLEAR_ERRORS" | "USER_SETTINGS_LOCALE_OVERRIDE" | "USER_SETTINGS_MODAL_CLEAR_SCROLL_POSITION" | "USER_SETTINGS_MODAL_CLEAR_SUBSECTION" | "USER_SETTINGS_MODAL_CLOSE" | "USER_SETTINGS_MODAL_INIT" | "USER_SETTINGS_MODAL_OPEN" | "USER_SETTINGS_MODAL_RESET" | "USER_SETTINGS_MODAL_SET_SECTION" | "USER_SETTINGS_MODAL_SUBMIT" | "USER_SETTINGS_MODAL_SUBMIT_COMPLETE" | "USER_SETTINGS_MODAL_SUBMIT_FAILURE" | "USER_SETTINGS_MODAL_UPDATE_ACCOUNT" | "USER_SETTINGS_OVERRIDE_APPLY" | "USER_SETTINGS_OVERRIDE_CLEAR" | "USER_SETTINGS_PROTO_ENQUEUE_UPDATE" | "USER_SETTINGS_PROTO_LOAD_IF_NECESSARY" | "USER_SETTINGS_PROTO_UPDATE" | "USER_SETTINGS_PROTO_UPDATE_EDIT_INFO" | "USER_SETTINGS_RESET_ALL_PENDING" | "USER_SETTINGS_RESET_ALL_TRY_IT_OUT" | "USER_SETTINGS_RESET_PENDING_ACCOUNT_CHANGES" | "USER_SETTINGS_RESET_PENDING_PROFILE_CHANGES" | "USER_SETTINGS_THEME_OVERRIDE" | "USER_UPDATE" | "VERIFY_FAILURE" | "VERIFY_SUCCESS" | "VIDEO_FILTER_ASSETS_FETCH_SUCCESS" | "VIDEO_FILTER_ASSET_DELETE_SUCCESS" | "VIDEO_FILTER_ASSET_UPLOAD_SUCCESS" | "VIDEO_SAVE_LAST_USED_BACKGROUND_OPTION" | "VIEW_HISTORY_MARK_VIEW" | "VOICE_CATEGORY_COLLAPSE" | "VOICE_CATEGORY_EXPAND" | "VOICE_CHANNEL_EFFECT_CLEAR" | "VOICE_CHANNEL_EFFECT_RECENT_EMOJI" | "VOICE_CHANNEL_EFFECT_SEND" | "VOICE_CHANNEL_EFFECT_SENT_LOCAL" | "VOICE_CHANNEL_EFFECT_TOGGLE_ANIMATION_TYPE" | "VOICE_CHANNEL_EFFECT_UPDATE_TIME_STAMP" | "VOICE_CHANNEL_SELECT" | "VOICE_SERVER_UPDATE" | "VOICE_STATE_UPDATES" | "WAIT_FOR_REMOTE_SESSION" | "WEBHOOKS_FETCHING" | "WEBHOOKS_UPDATE" | "WEBHOOK_CREATE" | "WEBHOOK_DELETE" | "WEBHOOK_UPDATE" | "WELCOME_SCREEN_FETCH_FAIL" | "WELCOME_SCREEN_FETCH_START" | "WELCOME_SCREEN_FETCH_SUCCESS" | "WELCOME_SCREEN_SETTINGS_CLEAR" | "WELCOME_SCREEN_SETTINGS_RESET" | "WELCOME_SCREEN_SETTINGS_UPDATE" | "WELCOME_SCREEN_SUBMIT" | "WELCOME_SCREEN_SUBMIT_FAILURE" | "WELCOME_SCREEN_SUBMIT_SUCCESS" | "WELCOME_SCREEN_UPDATE" | "WELCOME_SCREEN_VIEW" | "WINDOW_FOCUS" | "WINDOW_FULLSCREEN_CHANGE" | "WINDOW_HIDDEN" | "WINDOW_INIT" | "WINDOW_RESIZED" | "WINDOW_UNLOAD"; +// 57kb worth of events ??????? +export type FluxEvents = "ACCESSIBILITY_COLORBLIND_TOGGLE" | "ACCESSIBILITY_DARK_SIDEBAR_TOGGLE" | "ACCESSIBILITY_DESATURATE_ROLES_TOGGLE" | "ACCESSIBILITY_FORCED_COLORS_MODAL_SEEN" | "ACCESSIBILITY_KEYBOARD_MODE_DISABLE" | "ACCESSIBILITY_KEYBOARD_MODE_ENABLE" | "ACCESSIBILITY_LOW_CONTRAST_TOGGLE" | "ACCESSIBILITY_RESET_TO_DEFAULT" | "ACCESSIBILITY_SET_ALWAYS_SHOW_LINK_DECORATIONS" | "ACCESSIBILITY_SET_CONTRAST" | "ACCESSIBILITY_SET_FONT_SIZE" | "ACCESSIBILITY_SET_MESSAGE_GROUP_SPACING" | "ACCESSIBILITY_SET_PREFERS_REDUCED_MOTION" | "ACCESSIBILITY_SET_ROLE_STYLE" | "ACCESSIBILITY_SET_SATURATION" | "ACCESSIBILITY_SET_SYNC_FORCED_COLORS" | "ACCESSIBILITY_SET_ZOOM" | "ACCESSIBILITY_SUBMIT_BUTTON_TOGGLE" | "ACCESSIBILITY_SYNC_PROFILE_THEME_WITH_USER_THEME_TOGGLE" | "ACCESSIBILITY_SYSTEM_COLOR_PREFERENCES_CHANGED" | "ACCESSIBILITY_SYSTEM_PREFERS_CONTRAST_CHANGED" | "ACCESSIBILITY_SYSTEM_PREFERS_CROSSFADES_CHANGED" | "ACCESSIBILITY_SYSTEM_PREFERS_REDUCED_MOTION_CHANGED" | "ACCESSIBILITY_TOGGLE_DISABLE_VOICE_BACKGROUNDS" | "ACKNOWLEDGE_CHANNEL_SAFETY_WARNING_TOOLTIP" | "ACK_APPROVED_GUILD_JOIN_REQUEST" | "ACTIVE_BOGO_PROMOTION_FETCH" | "ACTIVE_BOGO_PROMOTION_FETCH_FAIL" | "ACTIVE_BOGO_PROMOTION_FETCH_SUCCESS" | "ACTIVE_CHANNELS_FETCH_FAILURE" | "ACTIVE_CHANNELS_FETCH_START" | "ACTIVE_CHANNELS_FETCH_SUCCESS" | "ACTIVE_OUTBOUND_PROMOTIONS_FETCH" | "ACTIVE_OUTBOUND_PROMOTIONS_FETCH_FAIL" | "ACTIVE_OUTBOUND_PROMOTIONS_FETCH_SUCCESS" | "ACTIVITIES_WHATS_NEW_ACKNOWLEDGE_SECTION" | "ACTIVITIES_WHATS_NEW_MARK_OPENED_SECTION" | "ACTIVITY_INVITE_EDUCATION_DISMISS" | "ACTIVITY_INVITE_MODAL_CLOSE" | "ACTIVITY_INVITE_MODAL_OPEN" | "ACTIVITY_JOIN" | "ACTIVITY_JOIN_FAILED" | "ACTIVITY_JOIN_LOADING" | "ACTIVITY_LAUNCH_FAIL" | "ACTIVITY_LAYOUT_MODE_UPDATE" | "ACTIVITY_METADATA_UPDATE" | "ACTIVITY_PLAY" | "ACTIVITY_SCREEN_ORIENTATION_UPDATE" | "ACTIVITY_START" | "ACTIVITY_SYNC" | "ACTIVITY_SYNC_STOP" | "ACTIVITY_UPDATE_FAIL" | "ACTIVITY_UPDATE_START" | "ACTIVITY_UPDATE_SUCCESS" | "ADD_STICKER_PREVIEW" | "ADMIN_ONBOARDING_GUIDE_HIDE" | "ADYEN_CASH_APP_PAY_SUBMIT_SUCCESS" | "ADYEN_CREATE_CASH_APP_PAY_COMPONENT_SUCCESS" | "ADYEN_CREATE_CLIENT_SUCCESS" | "ADYEN_TEARDOWN_CLIENT" | "AFK" | "AGE_GATE_FAILURE_MODAL_OPEN" | "AGE_GATE_LOGOUT_UNDERAGE_NEW_USER" | "AGE_GATE_MODAL_CLOSE" | "AGE_GATE_MODAL_OPEN" | "AGE_GATE_SUCCESS_MODAL_OPEN" | "APPLICATIONS_FETCH" | "APPLICATIONS_FETCH_FAIL" | "APPLICATIONS_FETCH_SUCCESS" | "APPLICATIONS_SHELF_FETCH_FAIL" | "APPLICATIONS_SHELF_FETCH_START" | "APPLICATIONS_SHELF_FETCH_SUCCESS" | "APPLICATION_ACTIVITY_STATISTICS_FETCH_FAIL" | "APPLICATION_ACTIVITY_STATISTICS_FETCH_START" | "APPLICATION_ACTIVITY_STATISTICS_FETCH_SUCCESS" | "APPLICATION_ASSETS_FETCH" | "APPLICATION_ASSETS_FETCH_SUCCESS" | "APPLICATION_ASSETS_UPDATE" | "APPLICATION_BRANCHES_FETCH_FAIL" | "APPLICATION_BRANCHES_FETCH_SUCCESS" | "APPLICATION_BUILD_FETCH_START" | "APPLICATION_BUILD_FETCH_SUCCESS" | "APPLICATION_BUILD_NOT_FOUND" | "APPLICATION_BUILD_SIZE_FETCH_FAIL" | "APPLICATION_BUILD_SIZE_FETCH_START" | "APPLICATION_BUILD_SIZE_FETCH_SUCCESS" | "APPLICATION_COMMAND_AUTOCOMPLETE_REQUEST" | "APPLICATION_COMMAND_AUTOCOMPLETE_RESPONSE" | "APPLICATION_COMMAND_EXECUTE_BAD_VERSION" | "APPLICATION_COMMAND_INDEX_FETCH_FAILURE" | "APPLICATION_COMMAND_INDEX_FETCH_REQUEST" | "APPLICATION_COMMAND_INDEX_FETCH_SUCCESS" | "APPLICATION_COMMAND_SET_ACTIVE_COMMAND" | "APPLICATION_COMMAND_SET_PREFERRED_COMMAND" | "APPLICATION_COMMAND_UPDATE_CHANNEL_STATE" | "APPLICATION_COMMAND_UPDATE_OPTIONS" | "APPLICATION_COMMAND_USED" | "APPLICATION_DIRECTORY_FETCH_APPLICATION" | "APPLICATION_DIRECTORY_FETCH_APPLICATION_FAILURE" | "APPLICATION_DIRECTORY_FETCH_APPLICATION_SUCCESS" | "APPLICATION_DIRECTORY_FETCH_CATEGORIES_SUCCESS" | "APPLICATION_DIRECTORY_FETCH_COLLECTIONS" | "APPLICATION_DIRECTORY_FETCH_COLLECTIONS_FAILURE" | "APPLICATION_DIRECTORY_FETCH_COLLECTIONS_SUCCESS" | "APPLICATION_DIRECTORY_FETCH_SEARCH" | "APPLICATION_DIRECTORY_FETCH_SEARCH_FAILURE" | "APPLICATION_DIRECTORY_FETCH_SEARCH_SUCCESS" | "APPLICATION_DIRECTORY_FETCH_SIMILAR_APPLICATIONS" | "APPLICATION_DIRECTORY_FETCH_SIMILAR_APPLICATIONS_FAILURE" | "APPLICATION_DIRECTORY_FETCH_SIMILAR_APPLICATIONS_SUCCESS" | "APPLICATION_FETCH" | "APPLICATION_FETCH_FAIL" | "APPLICATION_FETCH_SUCCESS" | "APPLICATION_STORE_ACCEPT_EULA" | "APPLICATION_STORE_ACCEPT_STORE_TERMS" | "APPLICATION_STORE_CLEAR_DATA" | "APPLICATION_STORE_LOCATION_CHANGE" | "APPLICATION_STORE_MATURE_AGREE" | "APPLICATION_STORE_RESET_NAVIGATION" | "APPLICATION_SUBSCRIPTIONS_CHANNEL_NOTICE_DISMISSED" | "APPLICATION_SUBSCRIPTIONS_FETCH_ENTITLEMENTS" | "APPLICATION_SUBSCRIPTIONS_FETCH_ENTITLEMENTS_FAILURE" | "APPLICATION_SUBSCRIPTIONS_FETCH_ENTITLEMENTS_SUCCESS" | "APPLICATION_SUBSCRIPTIONS_FETCH_LISTINGS" | "APPLICATION_SUBSCRIPTIONS_FETCH_LISTINGS_FAILURE" | "APPLICATION_SUBSCRIPTIONS_FETCH_LISTINGS_SUCCESS" | "APPLICATION_SUBSCRIPTIONS_FETCH_LISTING_FOR_PLAN_SUCCESS" | "APPLIED_BOOSTS_COOLDOWN_FETCH_SUCCESS" | "APPLIED_GUILD_BOOST_COUNT_UPDATE" | "APP_ICON_EDITOR_CLOSE" | "APP_ICON_EDITOR_OPEN" | "APP_ICON_TRACK_IMPRESSION" | "APP_ICON_UPDATED" | "APP_LAUNCHER_DISMISS_APP_DETAIL" | "APP_LAUNCHER_DISMISS_POPUP" | "APP_LAUNCHER_SET_ACTIVE_COMMAND" | "APP_LAUNCHER_SHOW_APP_DETAIL" | "APP_LAUNCHER_SHOW_POPUP" | "APP_STATE_UPDATE" | "APP_VIEW_SET_HOME_LINK" | "AUDIO_INPUT_DETECTED" | "AUDIO_RESET" | "AUDIO_SET_ATTENUATION" | "AUDIO_SET_AUTOMATIC_GAIN_CONTROL" | "AUDIO_SET_DEBUG_LOGGING" | "AUDIO_SET_DISPLAY_SILENCE_WARNING" | "AUDIO_SET_ECHO_CANCELLATION" | "AUDIO_SET_INPUT_DEVICE" | "AUDIO_SET_INPUT_VOLUME" | "AUDIO_SET_LOCAL_PAN" | "AUDIO_SET_LOCAL_VIDEO_DISABLED" | "AUDIO_SET_LOCAL_VOLUME" | "AUDIO_SET_LOOPBACK" | "AUDIO_SET_MODE" | "AUDIO_SET_NOISE_CANCELLATION" | "AUDIO_SET_NOISE_SUPPRESSION" | "AUDIO_SET_OUTPUT_DEVICE" | "AUDIO_SET_OUTPUT_VOLUME" | "AUDIO_SET_QOS" | "AUDIO_SET_SELF_MUTE" | "AUDIO_SET_SUBSYSTEM" | "AUDIO_SET_TEMPORARY_SELF_MUTE" | "AUDIO_TOGGLE_LOCAL_MUTE" | "AUDIO_TOGGLE_LOCAL_SOUNDBOARD_MUTE" | "AUDIO_TOGGLE_SELF_DEAF" | "AUDIO_TOGGLE_SELF_MUTE" | "AUDIO_VOLUME_CHANGE" | "AUDIT_LOG_FETCH_FAIL" | "AUDIT_LOG_FETCH_NEXT_PAGE_FAIL" | "AUDIT_LOG_FETCH_NEXT_PAGE_START" | "AUDIT_LOG_FETCH_NEXT_PAGE_SUCCESS" | "AUDIT_LOG_FETCH_START" | "AUDIT_LOG_FETCH_SUCCESS" | "AUDIT_LOG_FILTER_BY_ACTION" | "AUDIT_LOG_FILTER_BY_TARGET" | "AUDIT_LOG_FILTER_BY_USER" | "AUTHENTICATOR_CREATE" | "AUTHENTICATOR_DELETE" | "AUTHENTICATOR_UPDATE" | "AUTH_INVITE_UPDATE" | "AUTH_SESSION_CHANGE" | "AUTO_MODERATION_MENTION_RAID_DETECTION" | "AUTO_MODERATION_MENTION_RAID_NOTICE_DISMISS" | "BACKGROUND_SYNC" | "BACKGROUND_SYNC_CHANNEL_MESSAGES" | "BILLING_ANNUAL_USER_OFFER_FETCH_FAIL" | "BILLING_ANNUAL_USER_OFFER_FETCH_SUCCESS" | "BILLING_CREATE_REFERRAL_PREVIEW_FAIL" | "BILLING_CREATE_REFERRAL_PREVIEW_START" | "BILLING_CREATE_REFERRAL_PREVIEW_SUCCESS" | "BILLING_CREATE_REFERRAL_SUCCESS" | "BILLING_IP_COUNTRY_CODE_FAILURE" | "BILLING_IP_COUNTRY_CODE_FETCH_START" | "BILLING_LOCALIZED_PRICING_PROMO_FAILURE" | "BILLING_MOST_RECENT_SUBSCRIPTION_FETCH_SUCCESS" | "BILLING_NITRO_AFFINITY_FETCHED" | "BILLING_NITRO_AFFINITY_FETCH_SUCCEEDED" | "BILLING_PAYMENTS_FETCH_SUCCESS" | "BILLING_PAYMENT_FETCH_SUCCESS" | "BILLING_PAYMENT_SOURCES_FETCH_FAIL" | "BILLING_PAYMENT_SOURCES_FETCH_START" | "BILLING_PAYMENT_SOURCES_FETCH_SUCCESS" | "BILLING_PAYMENT_SOURCE_CREATE_FAIL" | "BILLING_PAYMENT_SOURCE_CREATE_START" | "BILLING_PAYMENT_SOURCE_CREATE_SUCCESS" | "BILLING_PAYMENT_SOURCE_REMOVE_CLEAR_ERROR" | "BILLING_PAYMENT_SOURCE_REMOVE_FAIL" | "BILLING_PAYMENT_SOURCE_REMOVE_START" | "BILLING_PAYMENT_SOURCE_REMOVE_SUCCESS" | "BILLING_PAYMENT_SOURCE_UPDATE_CLEAR_ERROR" | "BILLING_PAYMENT_SOURCE_UPDATE_FAIL" | "BILLING_PAYMENT_SOURCE_UPDATE_START" | "BILLING_PAYMENT_SOURCE_UPDATE_SUCCESS" | "BILLING_PERKS_RELEVANCE_FETCH_FAIL" | "BILLING_PERKS_RELEVANCE_FETCH_START" | "BILLING_PERKS_RELEVANCE_FETCH_SUCCESS" | "BILLING_POPUP_BRIDGE_CALLBACK" | "BILLING_POPUP_BRIDGE_STATE_UPDATE" | "BILLING_PREVIOUS_PREMIUM_SUBSCRIPTION_FETCH_SUCCESS" | "BILLING_PURCHASE_TOKEN_AUTH_CLEAR_STATE" | "BILLING_REFERRALS_REMAINING_FETCH_FAIL" | "BILLING_REFERRALS_REMAINING_FETCH_START" | "BILLING_REFERRALS_REMAINING_FETCH_SUCCESS" | "BILLING_REFERRAL_RESOLVE_FAIL" | "BILLING_REFERRAL_RESOLVE_SUCCESS" | "BILLING_REFERRAL_TRIAL_OFFER_UPDATE" | "BILLING_SET_IP_COUNTRY_CODE" | "BILLING_SET_LOCALIZED_PRICING_PROMO" | "BILLING_SUBSCRIPTION_CANCEL_FAIL" | "BILLING_SUBSCRIPTION_CANCEL_START" | "BILLING_SUBSCRIPTION_CANCEL_SUCCESS" | "BILLING_SUBSCRIPTION_FETCH_FAIL" | "BILLING_SUBSCRIPTION_FETCH_START" | "BILLING_SUBSCRIPTION_FETCH_SUCCESS" | "BILLING_SUBSCRIPTION_RESET" | "BILLING_SUBSCRIPTION_UPDATE_FAIL" | "BILLING_SUBSCRIPTION_UPDATE_START" | "BILLING_SUBSCRIPTION_UPDATE_SUCCESS" | "BILLING_USER_OFFER_ACKNOWLEDGED_SUCCESS" | "BILLING_USER_OFFER_FETCH_FAIL" | "BILLING_USER_OFFER_FETCH_SUCCESS" | "BILLING_USER_PREMIUM_LIKELIHOOD_FETCH" | "BILLING_USER_PREMIUM_LIKELIHOOD_FETCH_ERROR" | "BILLING_USER_PREMIUM_LIKELIHOOD_FETCH_SUCCESS" | "BILLING_USER_TRIAL_OFFER_ACKNOWLEDGED_SUCCESS" | "BILLING_USER_TRIAL_OFFER_FETCH_SUCCESS" | "BLOCKED_DOMAIN_LIST_FETCHED" | "BOOSTED_GUILD_GRACE_PERIOD_NOTICE_DISMISS" | "BRAINTREE_CREATE_CLIENT_SUCCESS" | "BRAINTREE_CREATE_PAYPAL_CLIENT_SUCCESS" | "BRAINTREE_CREATE_VENMO_CLIENT_SUCCESS" | "BRAINTREE_TEARDOWN_PAYPAL_CLIENT" | "BRAINTREE_TEARDOWN_VENMO_CLIENT" | "BRAINTREE_TOKENIZE_PAYPAL_FAIL" | "BRAINTREE_TOKENIZE_PAYPAL_START" | "BRAINTREE_TOKENIZE_PAYPAL_SUCCESS" | "BRAINTREE_TOKENIZE_VENMO_FAIL" | "BRAINTREE_TOKENIZE_VENMO_START" | "BRAINTREE_TOKENIZE_VENMO_SUCCESS" | "BROADCASTER_BUCKETS_RECEIVED" | "BROADCAST_START" | "BROADCAST_STOP" | "BROADCAST_VIEWERS_UPDATE" | "BROWSER_HANDOFF_BEGIN" | "BROWSER_HANDOFF_FROM_APP" | "BROWSER_HANDOFF_SET_USER" | "BROWSER_HANDOFF_UNAVAILABLE" | "BUILD_OVERRIDE_RESOLVED" | "BULK_ACK" | "BULK_CLEAR_RECENTS" | "BURST_REACTION_ANIMATION_ADD" | "BURST_REACTION_EFFECT_CLEAR" | "BURST_REACTION_EFFECT_PLAY" | "BURST_REACTION_PICKER_ANIMATION_ADD" | "BURST_REACTION_PICKER_ANIMATION_CLEAR" | "CACHED_EMOJIS_LOADED" | "CACHED_STICKERS_LOADED" | "CACHE_LOADED" | "CACHE_LOADED_LAZY" | "CACHE_LOADED_LAZY_NO_CACHE" | "CALL_CHAT_TOASTS_SET_ENABLED" | "CALL_CONNECT" | "CALL_CONNECT_MULTIPLE" | "CALL_CREATE" | "CALL_DELETE" | "CALL_ENQUEUE_RING" | "CALL_UPDATE" | "CANDIDATE_GAMES_CHANGE" | "CATEGORY_COLLAPSE" | "CATEGORY_COLLAPSE_ALL" | "CATEGORY_EXPAND" | "CATEGORY_EXPAND_ALL" | "CERTIFIED_DEVICES_SET" | "CHANGE_LOG_FETCH_FAILED" | "CHANGE_LOG_FETCH_SUCCESS" | "CHANGE_LOG_LOCK" | "CHANGE_LOG_MARK_SEEN" | "CHANGE_LOG_SET_CONFIG" | "CHANGE_LOG_SET_OVERRIDE" | "CHANGE_LOG_UNLOCK" | "CHANNEL_ACK" | "CHANNEL_CALL_POPOUT_WINDOW_OPEN" | "CHANNEL_COLLAPSE" | "CHANNEL_CREATE" | "CHANNEL_DELETE" | "CHANNEL_FOLLOWER_CREATED" | "CHANNEL_FOLLOWER_STATS_FETCH_FAILURE" | "CHANNEL_FOLLOWER_STATS_FETCH_SUCCESS" | "CHANNEL_FOLLOWING_PUBLISH_BUMP_DISMISSED" | "CHANNEL_FOLLOWING_PUBLISH_BUMP_HIDE_PERMANENTLY" | "CHANNEL_LOCAL_ACK" | "CHANNEL_MUTE_EXPIRED" | "CHANNEL_PINS_ACK" | "CHANNEL_PINS_UPDATE" | "CHANNEL_PRELOAD" | "CHANNEL_RECIPIENT_ADD" | "CHANNEL_RECIPIENT_REMOVE" | "CHANNEL_RTC_ACTIVE_CHANNELS" | "CHANNEL_RTC_SELECT_PARTICIPANT" | "CHANNEL_RTC_UPDATE_CHAT_OPEN" | "CHANNEL_RTC_UPDATE_LAYOUT" | "CHANNEL_RTC_UPDATE_PARTICIPANTS_OPEN" | "CHANNEL_RTC_UPDATE_STAGE_STREAM_SIZE" | "CHANNEL_RTC_UPDATE_STAGE_VIDEO_LIMIT_BOOST_UPSELL_DISMISSED" | "CHANNEL_RTC_UPDATE_VOICE_PARTICIPANTS_HIDDEN" | "CHANNEL_SAFETY_WARNING_FEEDBACK" | "CHANNEL_SELECT" | "CHANNEL_SETTINGS_CLOSE" | "CHANNEL_SETTINGS_INIT" | "CHANNEL_SETTINGS_LOADED_INVITES" | "CHANNEL_SETTINGS_OPEN" | "CHANNEL_SETTINGS_OVERWRITE_SELECT" | "CHANNEL_SETTINGS_PERMISSIONS_INIT" | "CHANNEL_SETTINGS_PERMISSIONS_SAVE_SUCCESS" | "CHANNEL_SETTINGS_PERMISSIONS_SELECT_PERMISSION" | "CHANNEL_SETTINGS_PERMISSIONS_SET_ADVANCED_MODE" | "CHANNEL_SETTINGS_PERMISSIONS_SUBMITTING" | "CHANNEL_SETTINGS_PERMISSIONS_UPDATE_PERMISSION" | "CHANNEL_SETTINGS_SET_SECTION" | "CHANNEL_SETTINGS_SUBMIT" | "CHANNEL_SETTINGS_SUBMIT_FAILURE" | "CHANNEL_SETTINGS_SUBMIT_SUCCESS" | "CHANNEL_SETTINGS_UPDATE" | "CHANNEL_STATUSES" | "CHANNEL_TOGGLE_MEMBERS_SECTION" | "CHANNEL_TOGGLE_SUMMARIES_SECTION" | "CHANNEL_UPDATES" | "CHECKING_FOR_UPDATES" | "CHECK_LAUNCHABLE_GAME" | "CLAN_SETTINGS_FETCH_START" | "CLAN_SETTINGS_FETCH_SUCCESS" | "CLAN_SETTINGS_SUBMIT" | "CLAN_SETTINGS_SUBMIT_ERROR" | "CLAN_SETTINGS_SUBMIT_SUCCESS" | "CLAN_SETTINGS_UPDATE" | "CLAN_SETUP_ERROR" | "CLAN_SETUP_RESET" | "CLAN_SETUP_SUBMIT" | "CLAN_SETUP_SUCCESS" | "CLAN_SETUP_UPDATE" | "CLEAR_AUTHENTICATION_ERRORS" | "CLEAR_CACHES" | "CLEAR_CHANNEL_SAFETY_WARNINGS" | "CLEAR_CONVERSATION_SUMMARIES" | "CLEAR_HANG_STATUS" | "CLEAR_INTERACTION_MODAL_STATE" | "CLEAR_LAST_SESSION_VOICE_CHANNEL_ID" | "CLEAR_MENTIONS" | "CLEAR_MESSAGES" | "CLEAR_OLDEST_UNREAD_MESSAGE" | "CLEAR_PENDING_CHANNEL_AND_ROLE_UPDATES" | "CLEAR_REMOTE_DISCONNECT_VOICE_CHANNEL_ID" | "CLEAR_STICKER_PREVIEW" | "CLIENT_THEMES_EDITOR_CLOSE" | "CLIENT_THEMES_EDITOR_OPEN" | "CLIPS_CLASSIFY_HARDWARE" | "CLIPS_CLEAR_CLIPS_SESSION" | "CLIPS_CLEAR_NEW_CLIP_IDS" | "CLIPS_DELETE_CLIP" | "CLIPS_DISMISS_EDUCATION" | "CLIPS_INIT" | "CLIPS_INIT_FAILURE" | "CLIPS_LOAD_DIRECTORY_SUCCESS" | "CLIPS_RESTART" | "CLIPS_SAVE_ANIMATION_END" | "CLIPS_SAVE_CLIP" | "CLIPS_SAVE_CLIP_ERROR" | "CLIPS_SAVE_CLIP_PLACEHOLDER" | "CLIPS_SAVE_CLIP_PLACEHOLDER_ERROR" | "CLIPS_SAVE_CLIP_START" | "CLIPS_SETTINGS_UPDATE" | "CLIPS_SHOW_CALL_WARNING" | "CLIPS_UPDATE_METADATA" | "CLOSE_SUSPENDED_USER" | "COLLECTIBLES_CATEGORIES_FETCH" | "COLLECTIBLES_CATEGORIES_FETCH_FAILURE" | "COLLECTIBLES_CATEGORIES_FETCH_SUCCESS" | "COLLECTIBLES_CATEGORY_ITEMS_VIEWED" | "COLLECTIBLES_CLAIM" | "COLLECTIBLES_CLAIM_FAILURE" | "COLLECTIBLES_CLAIM_SUCCESS" | "COLLECTIBLES_PRODUCT_DETAILS_OPEN" | "COLLECTIBLES_PRODUCT_FETCH" | "COLLECTIBLES_PRODUCT_FETCH_FAILURE" | "COLLECTIBLES_PRODUCT_FETCH_SUCCESS" | "COLLECTIBLES_PURCHASES_FETCH" | "COLLECTIBLES_PURCHASES_FETCH_FAILURE" | "COLLECTIBLES_PURCHASES_FETCH_SUCCESS" | "COLLECTIBLES_SHOP_CLOSE" | "COLLECTIBLES_SHOP_OPEN" | "COMMANDS_MIGRATION_NOTICE_DISMISSED" | "COMMANDS_MIGRATION_OVERVIEW_TOOLTIP_DISMISSED" | "COMMANDS_MIGRATION_TOGGLE_TOOLTIP_DISMISSED" | "COMMANDS_MIGRATION_UPDATE_SUCCESS" | "COMPLETE_NEW_MEMBER_ACTION" | "COMPLETE_SIGN_UP" | "CONNECTED_DEVICE_IGNORE" | "CONNECTED_DEVICE_NEVER_SHOW_MODAL" | "CONNECTED_DEVICE_SET" | "CONNECTIONS_GRID_MODAL_HIDE" | "CONNECTIONS_GRID_MODAL_SHOW" | "CONNECTION_CLOSED" | "CONNECTION_INTERRUPTED" | "CONNECTION_OPEN" | "CONNECTION_OPEN_SUPPLEMENTAL" | "CONNECTION_RESUMED" | "CONSOLE_COMMAND_UPDATE" | "CONTENT_INVENTORY_CLEAR_FEED" | "CONTENT_INVENTORY_SET_FEED" | "CONTENT_INVENTORY_TOGGLE_FEED_HIDDEN" | "CONTENT_INVENTORY_TOGGLE_REPLY_MODE" | "CONTEXT_MENU_CLOSE" | "CONTEXT_MENU_OPEN" | "CONVERSATION_SUMMARY_UPDATE" | "CREATE_PENDING_REPLY" | "CREATE_REFERRALS_SUCCESS" | "CREATE_SHALLOW_PENDING_REPLY" | "CREATOR_MONETIZATION_NAG_ACTIVATE_ELIGIBLITY_FETCH_SUCCESS" | "CREATOR_MONETIZATION_PRICE_TIERS_FETCH" | "CREATOR_MONETIZATION_PRICE_TIERS_FETCH_FAILURE" | "CREATOR_MONETIZATION_PRICE_TIERS_FETCH_SUCCESS" | "CURRENT_BUILD_OVERRIDE_RESOLVED" | "CURRENT_USER_UPDATE" | "DCF_DAILY_CAP_OVERRIDE" | "DCF_HANDLE_DC_DISMISSED" | "DCF_HANDLE_DC_SHOWN" | "DCF_RESET" | "DECAY_READ_STATES" | "DELETED_ENTITY_IDS" | "DELETE_PENDING_REPLY" | "DELETE_SUMMARY" | "DETECTABLE_GAME_SUPPLEMENTAL_FETCH" | "DETECTABLE_GAME_SUPPLEMENTAL_FETCH_FAILURE" | "DETECTABLE_GAME_SUPPLEMENTAL_FETCH_SUCCESS" | "DETECTED_OFF_PLATFORM_PREMIUM_PERKS_DISMISS" | "DEVELOPER_ACTIVITY_SHELF_FETCH_FAIL" | "DEVELOPER_ACTIVITY_SHELF_FETCH_START" | "DEVELOPER_ACTIVITY_SHELF_FETCH_SUCCESS" | "DEVELOPER_ACTIVITY_SHELF_MARK_ACTIVITY_USED" | "DEVELOPER_ACTIVITY_SHELF_SET_ACTIVITY_URL_OVERRIDE" | "DEVELOPER_ACTIVITY_SHELF_TOGGLE_USE_ACTIVITY_URL_OVERRIDE" | "DEVELOPER_ACTIVITY_SHELF_UPDATE_FILTER" | "DEVELOPER_OPTIONS_UPDATE_SETTINGS" | "DEVELOPER_TEST_MODE_AUTHORIZATION_FAIL" | "DEVELOPER_TEST_MODE_AUTHORIZATION_START" | "DEVELOPER_TEST_MODE_AUTHORIZATION_SUCCESS" | "DEVELOPER_TEST_MODE_RESET" | "DEVELOPER_TEST_MODE_RESET_ERROR" | "DEV_TOOLS_DESIGN_TOGGLE_SET" | "DEV_TOOLS_DESIGN_TOGGLE_WEB_SET" | "DEV_TOOLS_DEV_SETTING_SET" | "DEV_TOOLS_SETTINGS_UPDATE" | "DISABLE_AUTOMATIC_ACK" | "DISCOVER_CHECKLIST_FETCH_FAILURE" | "DISCOVER_CHECKLIST_FETCH_START" | "DISCOVER_CHECKLIST_FETCH_SUCCESS" | "DISCOVER_GUILDS_FETCH_FAILURE" | "DISCOVER_GUILDS_FETCH_START" | "DISCOVER_GUILDS_FETCH_SUCCESS" | "DISMISS_CHANNEL_SAFETY_WARNINGS" | "DISMISS_FAVORITE_SUGGESTION" | "DISMISS_MEDIA_POST_SHARE_PROMPT" | "DISMISS_SIGN_UP" | "DISPATCH_APPLICATION_ADD_TO_INSTALLATIONS" | "DISPATCH_APPLICATION_CANCEL" | "DISPATCH_APPLICATION_ERROR" | "DISPATCH_APPLICATION_INSTALL" | "DISPATCH_APPLICATION_INSTALL_SCRIPTS_PROGRESS_UPDATE" | "DISPATCH_APPLICATION_LAUNCH_SETUP_COMPLETE" | "DISPATCH_APPLICATION_LAUNCH_SETUP_START" | "DISPATCH_APPLICATION_MOVE_UP" | "DISPATCH_APPLICATION_REMOVE_FINISHED" | "DISPATCH_APPLICATION_REPAIR" | "DISPATCH_APPLICATION_STATE_UPDATE" | "DISPATCH_APPLICATION_UNINSTALL" | "DISPATCH_APPLICATION_UPDATE" | "DISPLAYED_INVITE_SHOW" | "DOMAIN_MIGRATION_FAILURE" | "DOMAIN_MIGRATION_SKIP" | "DOMAIN_MIGRATION_START" | "DRAFT_CHANGE" | "DRAFT_CLEAR" | "DRAFT_SAVE" | "DRAWER_CLOSE" | "DRAWER_OPEN" | "DRAWER_SELECT_TAB" | "DROPS_ELIGIBILITY_FETCH_SUCCESS" | "DROPS_ENROLLED_USER_FETCH_SUCCESS" | "DROPS_FETCH_PROGRESS_FAILURE" | "DROPS_FETCH_PROGRESS_SUCCESS" | "DROPS_HEARTBEAT_FAILURE" | "DROPS_HEARTBEAT_SUCCESS" | "DROPS_PLATFORM_AVAILABILITY_SUCCESS" | "DROPS_UNENROLL_USER" | "DROPS_USER_STATUS_FETCH_FAILURE" | "DROPS_USER_STATUS_FETCH_SUCCESS" | "EMAIL_SETTINGS_FETCH_SUCCESS" | "EMAIL_SETTINGS_UPDATE" | "EMAIL_SETTINGS_UPDATE_SUCCESS" | "EMBEDDED_ACTIVITY_CLOSE" | "EMBEDDED_ACTIVITY_DEFERRED_OPEN" | "EMBEDDED_ACTIVITY_DISCONNECT" | "EMBEDDED_ACTIVITY_DISMISS_NEW_INDICATOR" | "EMBEDDED_ACTIVITY_FETCH_SHELF" | "EMBEDDED_ACTIVITY_FETCH_SHELF_FAIL" | "EMBEDDED_ACTIVITY_FETCH_SHELF_SUCCESS" | "EMBEDDED_ACTIVITY_LAUNCH_FAIL" | "EMBEDDED_ACTIVITY_LAUNCH_START" | "EMBEDDED_ACTIVITY_LAUNCH_SUCCESS" | "EMBEDDED_ACTIVITY_OPEN" | "EMBEDDED_ACTIVITY_SET_CONFIG" | "EMBEDDED_ACTIVITY_SET_FOCUSED_LAYOUT" | "EMBEDDED_ACTIVITY_SET_ORIENTATION_LOCK_STATE" | "EMBEDDED_ACTIVITY_SET_PANEL_MODE" | "EMBEDDED_ACTIVITY_UPDATE" | "EMBEDDED_ACTIVITY_UPDATE_V2" | "EMOJI_AUTOSUGGESTION_UPDATE" | "EMOJI_CAPTIONS_FETCH" | "EMOJI_CAPTIONS_FETCH_ERROR" | "EMOJI_CAPTIONS_FETCH_SUCCESS" | "EMOJI_DELETE" | "EMOJI_FETCH_FAILURE" | "EMOJI_FETCH_SUCCESS" | "EMOJI_TRACK_USAGE" | "EMOJI_UPLOAD_START" | "EMOJI_UPLOAD_STOP" | "ENABLE_AUTOMATIC_ACK" | "ENABLE_GUILD_SIGN_UP" | "ENABLE_USER_SIGN_UP" | "ENTITLEMENTS_FETCH_FOR_USER_FAIL" | "ENTITLEMENTS_FETCH_FOR_USER_START" | "ENTITLEMENTS_FETCH_FOR_USER_SUCCESS" | "ENTITLEMENTS_GIFTABLE_FETCH_SUCCESS" | "ENTITLEMENT_CREATE" | "ENTITLEMENT_DELETE" | "ENTITLEMENT_FETCH_APPLICATION_FAIL" | "ENTITLEMENT_FETCH_APPLICATION_START" | "ENTITLEMENT_FETCH_APPLICATION_SUCCESS" | "ENTITLEMENT_UPDATE" | "EVENT_DIRECTORY_FETCH_FAILURE" | "EVENT_DIRECTORY_FETCH_START" | "EVENT_DIRECTORY_FETCH_SUCCESS" | "EXPERIMENTS_FETCH" | "EXPERIMENTS_FETCH_FAILURE" | "EXPERIMENTS_FETCH_SUCCESS" | "EXPERIMENT_OVERRIDE_BUCKET" | "EXPERIMENT_REGISTER_LEGACY" | "FAMILY_CENTER_FETCH_START" | "FAMILY_CENTER_HANDLE_TAB_SELECT" | "FAMILY_CENTER_INITIAL_LOAD" | "FAMILY_CENTER_LINKED_USERS_FETCH_SUCCESS" | "FAMILY_CENTER_LINK_CODE_FETCH_SUCCESS" | "FAMILY_CENTER_REQUEST_LINK_REMOVE_SUCCESS" | "FAMILY_CENTER_REQUEST_LINK_SUCCESS" | "FAMILY_CENTER_REQUEST_LINK_UPDATE_SUCCESS" | "FAMILY_CENTER_TEEN_ACTIVITY_FETCH_SUCCESS" | "FAMILY_CENTER_TEEN_ACTIVITY_MORE_FETCH_SUCCESS" | "FETCH_AUTH_SESSIONS_SUCCESS" | "FETCH_CLAN_DISCOVERY_SEARCH_RESULT_SUCCESS" | "FETCH_GUILD_EVENT" | "FETCH_GUILD_EVENTS_FOR_GUILD" | "FETCH_GUILD_MEMBER_SUPPLEMENTAL_SUCCESS" | "FETCH_INTEGRATION_APPLICATION_IDS_FOR_MY_GUILDS" | "FETCH_INTEGRATION_APPLICATION_IDS_FOR_MY_GUILDS_FAILURE" | "FETCH_INTEGRATION_APPLICATION_IDS_FOR_MY_GUILDS_SUCCESS" | "FETCH_PRIVATE_CHANNEL_INTEGRATIONS_FAIL" | "FETCH_PRIVATE_CHANNEL_INTEGRATIONS_START" | "FETCH_PRIVATE_CHANNEL_INTEGRATIONS_SUCCESS" | "FETCH_STATIC_CLAN_LIST_SUCCESS" | "FINGERPRINT" | "FORCE_INVISIBLE" | "FORGOT_PASSWORD_REQUEST" | "FORGOT_PASSWORD_SENT" | "FORUM_SEARCH_CLEAR" | "FORUM_SEARCH_FAILURE" | "FORUM_SEARCH_QUERY_UPDATED" | "FORUM_SEARCH_START" | "FORUM_SEARCH_SUCCESS" | "FORUM_UNREADS" | "FRIENDS_SET_INITIAL_SECTION" | "FRIENDS_SET_SECTION" | "FRIEND_INVITES_FETCH_REQUEST" | "FRIEND_INVITES_FETCH_RESPONSE" | "FRIEND_INVITE_CREATE_FAILURE" | "FRIEND_INVITE_CREATE_REQUEST" | "FRIEND_INVITE_CREATE_SUCCESS" | "FRIEND_INVITE_REVOKE_REQUEST" | "FRIEND_INVITE_REVOKE_SUCCESS" | "FRIEND_SUGGESTION_CREATE" | "FRIEND_SUGGESTION_DELETE" | "GAMES_DATABASE_FETCH" | "GAMES_DATABASE_FETCH_FAIL" | "GAMES_DATABASE_UPDATE" | "GAME_CLOUD_SYNC_COMPLETE" | "GAME_CLOUD_SYNC_CONFLICT" | "GAME_CLOUD_SYNC_ERROR" | "GAME_CLOUD_SYNC_START" | "GAME_CLOUD_SYNC_UPDATE" | "GAME_CONSOLE_FETCH_DEVICES_FAIL" | "GAME_CONSOLE_FETCH_DEVICES_START" | "GAME_CONSOLE_FETCH_DEVICES_SUCCESS" | "GAME_CONSOLE_SELECT_DEVICE" | "GAME_DETECTION_WATCH_CANDIDATE_GAMES_START" | "GAME_ICON_UPDATE" | "GAME_INVITE_CLEAR_UNSEEN" | "GAME_INVITE_CREATE" | "GAME_INVITE_DELETE" | "GAME_INVITE_DELETE_MANY" | "GAME_INVITE_UPDATE_STATUS" | "GAME_LAUNCHABLE_UPDATE" | "GAME_LAUNCH_FAIL" | "GAME_LAUNCH_START" | "GAME_LAUNCH_SUCCESS" | "GENERIC_PUSH_NOTIFICATION_SENT" | "GIFT_CODES_FETCH" | "GIFT_CODES_FETCH_FAILURE" | "GIFT_CODES_FETCH_SUCCESS" | "GIFT_CODE_CREATE" | "GIFT_CODE_CREATE_SUCCESS" | "GIFT_CODE_REDEEM" | "GIFT_CODE_REDEEM_FAILURE" | "GIFT_CODE_REDEEM_SUCCESS" | "GIFT_CODE_RESOLVE" | "GIFT_CODE_RESOLVE_FAILURE" | "GIFT_CODE_RESOLVE_SUCCESS" | "GIFT_CODE_REVOKE_SUCCESS" | "GIFT_CODE_UPDATE" | "GIF_PICKER_INITIALIZE" | "GIF_PICKER_QUERY" | "GIF_PICKER_QUERY_FAILURE" | "GIF_PICKER_QUERY_SUCCESS" | "GIF_PICKER_SUGGESTIONS_SUCCESS" | "GIF_PICKER_TRENDING_FETCH_SUCCESS" | "GIF_PICKER_TRENDING_SEARCH_TERMS_SUCCESS" | "GUILD_ACK" | "GUILD_ANALYTICS_ENGAGEMENT_OVERVIEW_FETCH_FAILURE" | "GUILD_ANALYTICS_ENGAGEMENT_OVERVIEW_FETCH_SUCCESS" | "GUILD_ANALYTICS_GROWTH_ACTIVATION_OVERVIEW_FETCH_FAILURE" | "GUILD_ANALYTICS_GROWTH_ACTIVATION_OVERVIEW_FETCH_SUCCESS" | "GUILD_ANALYTICS_GROWTH_ACTIVATION_RETENTION_FETCH_FAILURE" | "GUILD_ANALYTICS_GROWTH_ACTIVATION_RETENTION_FETCH_SUCCESS" | "GUILD_ANALYTICS_MEMBER_INSIGHTS_FETCH_SUCCESS" | "GUILD_APPLICATIONS_FETCH_SUCCESS" | "GUILD_APPLICATION_COMMAND_INDEX_UPDATE" | "GUILD_APPLIED_BOOSTS_FETCH_SUCCESS" | "GUILD_APPLY_BOOST_FAIL" | "GUILD_APPLY_BOOST_START" | "GUILD_APPLY_BOOST_SUCCESS" | "GUILD_BAN_ADD" | "GUILD_BAN_REMOVE" | "GUILD_BOOST_SLOTS_FETCH_SUCCESS" | "GUILD_BOOST_SLOT_CREATE" | "GUILD_BOOST_SLOT_UPDATE" | "GUILD_BOOST_SLOT_UPDATE_SUCCESS" | "GUILD_CREATE" | "GUILD_DELETE" | "GUILD_DIRECTORY_ADMIN_ENTRIES_FETCH_SUCCESS" | "GUILD_DIRECTORY_CACHED_SEARCH" | "GUILD_DIRECTORY_CATEGORY_SELECT" | "GUILD_DIRECTORY_COUNTS_FETCH_SUCCESS" | "GUILD_DIRECTORY_ENTRY_CREATE" | "GUILD_DIRECTORY_ENTRY_DELETE" | "GUILD_DIRECTORY_ENTRY_UPDATE" | "GUILD_DIRECTORY_FETCH_FAILURE" | "GUILD_DIRECTORY_FETCH_START" | "GUILD_DIRECTORY_FETCH_SUCCESS" | "GUILD_DIRECTORY_SEARCH_CLEAR" | "GUILD_DIRECTORY_SEARCH_FAILURE" | "GUILD_DIRECTORY_SEARCH_START" | "GUILD_DIRECTORY_SEARCH_SUCCESS" | "GUILD_DISCOVERY_CATEGORY_ADD" | "GUILD_DISCOVERY_CATEGORY_DELETE" | "GUILD_DISCOVERY_CATEGORY_FETCH_SUCCESS" | "GUILD_DISCOVERY_CATEGORY_UPDATE_FAIL" | "GUILD_DISCOVERY_CLEAR_SEARCH" | "GUILD_DISCOVERY_CLEAR_SEEN_GUILDS" | "GUILD_DISCOVERY_FETCH_FAILURE" | "GUILD_DISCOVERY_FETCH_START" | "GUILD_DISCOVERY_FETCH_SUCCESS" | "GUILD_DISCOVERY_GUILD_SEEN" | "GUILD_DISCOVERY_METADATA_FETCH_FAIL" | "GUILD_DISCOVERY_POPULAR_FETCH_FAILURE" | "GUILD_DISCOVERY_POPULAR_FETCH_START" | "GUILD_DISCOVERY_POPULAR_FETCH_SUCCESS" | "GUILD_DISCOVERY_SEARCH_COUNTS_FAIL" | "GUILD_DISCOVERY_SEARCH_FETCH_FAILURE" | "GUILD_DISCOVERY_SEARCH_FETCH_START" | "GUILD_DISCOVERY_SEARCH_FETCH_SUCCESS" | "GUILD_DISCOVERY_SEARCH_INIT" | "GUILD_DISCOVERY_SEARCH_UPDATE_COUNTS" | "GUILD_DISCOVERY_SELECT_CATEGORY" | "GUILD_DISCOVERY_SLUG_FETCH_FAIL" | "GUILD_DISCOVERY_SLUG_FETCH_SUCCESS" | "GUILD_EMOJIS_UPDATE" | "GUILD_FEATURE_ACK" | "GUILD_FEED_FEATURED_ITEMS_FETCH_FAILURE" | "GUILD_FEED_FEATURED_ITEMS_FETCH_SUCCESS" | "GUILD_FEED_FEATURE_ITEM" | "GUILD_FEED_FETCH_FAILURE" | "GUILD_FEED_FETCH_FRESH_START" | "GUILD_FEED_FETCH_PAGE_START" | "GUILD_FEED_FETCH_SUCCESS" | "GUILD_FEED_ITEM_HIDE" | "GUILD_FEED_ITEM_REMOVE" | "GUILD_FEED_ITEM_UNHIDE" | "GUILD_FEED_UNFEATURE_ITEM" | "GUILD_FOLDER_COLLAPSE" | "GUILD_FOLDER_CREATE_LOCAL" | "GUILD_FOLDER_DELETE_LOCAL" | "GUILD_FOLDER_EDIT_LOCAL" | "GUILD_GEO_RESTRICTED" | "GUILD_HOME_ENSURE_HOME_SESSION" | "GUILD_HOME_SETTINGS_FETCH_FAIL" | "GUILD_HOME_SETTINGS_FETCH_START" | "GUILD_HOME_SETTINGS_FETCH_SUCCESS" | "GUILD_HOME_SETTINGS_TOGGLE_ENABLED" | "GUILD_HOME_SETTINGS_UPDATE_FAIL" | "GUILD_HOME_SETTINGS_UPDATE_START" | "GUILD_HOME_SETTINGS_UPDATE_SUCCESS" | "GUILD_HOME_SET_SCROLL_POSITION" | "GUILD_HOME_SET_SOURCE" | "GUILD_IDENTITY_SETTINGS_CLEAR_ERRORS" | "GUILD_IDENTITY_SETTINGS_CLOSE" | "GUILD_IDENTITY_SETTINGS_INIT" | "GUILD_IDENTITY_SETTINGS_RESET_ALL_PENDING" | "GUILD_IDENTITY_SETTINGS_RESET_AND_CLOSE_FORM" | "GUILD_IDENTITY_SETTINGS_RESET_PENDING_MEMBER_CHANGES" | "GUILD_IDENTITY_SETTINGS_RESET_PENDING_PROFILE_CHANGES" | "GUILD_IDENTITY_SETTINGS_SET_GUILD" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_AVATAR" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_AVATAR_DECORATION" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_BANNER" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_BIO" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_NICKNAME" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_PROFILE_EFFECT_ID" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_PRONOUNS" | "GUILD_IDENTITY_SETTINGS_SET_PENDING_THEME_COLORS" | "GUILD_IDENTITY_SETTINGS_SUBMIT" | "GUILD_IDENTITY_SETTINGS_SUBMIT_FAILURE" | "GUILD_IDENTITY_SETTINGS_SUBMIT_SUCCESS" | "GUILD_INTEGRATIONS_UPDATE" | "GUILD_JOIN" | "GUILD_JOIN_REQUESTS_BULK_ACTION" | "GUILD_JOIN_REQUESTS_FETCH_FAILURE" | "GUILD_JOIN_REQUESTS_FETCH_START" | "GUILD_JOIN_REQUESTS_FETCH_SUCCESS" | "GUILD_JOIN_REQUESTS_SET_APPLICATION_TAB" | "GUILD_JOIN_REQUESTS_SET_SELECTED" | "GUILD_JOIN_REQUESTS_SET_SORT_ORDER" | "GUILD_JOIN_REQUEST_BY_ID_FETCH_SUCCESS" | "GUILD_JOIN_REQUEST_CREATE" | "GUILD_JOIN_REQUEST_DELETE" | "GUILD_JOIN_REQUEST_UPDATE" | "GUILD_MEMBERS_CHUNK_BATCH" | "GUILD_MEMBERS_REQUEST" | "GUILD_MEMBER_ADD" | "GUILD_MEMBER_LIST_UPDATE" | "GUILD_MEMBER_PROFILE_UPDATE" | "GUILD_MEMBER_REMOVE" | "GUILD_MEMBER_UPDATE" | "GUILD_MEMBER_UPDATE_LOCAL" | "GUILD_MOVE_BY_ID" | "GUILD_MUTE_EXPIRED" | "GUILD_NEW_MEMBER_ACTIONS_DELETE_SUCCESS" | "GUILD_NEW_MEMBER_ACTIONS_FETCH_FAIL" | "GUILD_NEW_MEMBER_ACTIONS_FETCH_START" | "GUILD_NEW_MEMBER_ACTIONS_FETCH_SUCCESS" | "GUILD_NEW_MEMBER_ACTION_UPDATE_SUCCESS" | "GUILD_NSFW_AGREE" | "GUILD_ONBOARDING_COMPLETE" | "GUILD_ONBOARDING_PROMPTS_FETCH_FAILURE" | "GUILD_ONBOARDING_PROMPTS_FETCH_START" | "GUILD_ONBOARDING_PROMPTS_FETCH_SUCCESS" | "GUILD_ONBOARDING_PROMPTS_LOCAL_UPDATE" | "GUILD_ONBOARDING_SELECT_OPTION" | "GUILD_ONBOARDING_SET_STEP" | "GUILD_ONBOARDING_START" | "GUILD_ONBOARDING_UPDATE_RESPONSES_SUCCESS" | "GUILD_POPOUT_FETCH_FAILURE" | "GUILD_POPOUT_FETCH_START" | "GUILD_POPOUT_FETCH_SUCCESS" | "GUILD_PRODUCTS_FETCH" | "GUILD_PRODUCTS_FETCH_FAILURE" | "GUILD_PRODUCTS_FETCH_SUCCESS" | "GUILD_PRODUCT_CREATE" | "GUILD_PRODUCT_DELETE" | "GUILD_PRODUCT_FETCH" | "GUILD_PRODUCT_FETCH_FAILURE" | "GUILD_PRODUCT_FETCH_SUCCESS" | "GUILD_PRODUCT_UPDATE" | "GUILD_PROGRESS_COMPLETED_SEEN" | "GUILD_PROGRESS_DISMISS" | "GUILD_PROGRESS_INITIALIZE" | "GUILD_PROMPT_VIEWED" | "GUILD_RECOMMENDATION_FETCH" | "GUILD_RECOMMENDATION_FETCH_FAILURE" | "GUILD_RECOMMENDATION_FETCH_SUCCESS" | "GUILD_RESOURCE_CHANNEL_UPDATE_SUCCESS" | "GUILD_ROLE_CONNECTIONS_CONFIGURATIONS_FETCH_SUCCESS" | "GUILD_ROLE_CONNECTION_ELIGIBILITY_FETCH_SUCCESS" | "GUILD_ROLE_CREATE" | "GUILD_ROLE_DELETE" | "GUILD_ROLE_MEMBER_ADD" | "GUILD_ROLE_MEMBER_BULK_ADD" | "GUILD_ROLE_MEMBER_COUNT_FETCH_SUCCESS" | "GUILD_ROLE_MEMBER_COUNT_UPDATE" | "GUILD_ROLE_MEMBER_REMOVE" | "GUILD_ROLE_SUBSCRIPTIONS_CREATE_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_DELETE_GROUP_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_DELETE_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTINGS" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTINGS_FAILURE" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTINGS_SUCCESS" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTING_FOR_PLAN" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_LISTING_FOR_PLAN_SUCCESS" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_RESTRICTIONS" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_RESTRICTIONS_ABORTED" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_RESTRICTIONS_FAILURE" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_RESTRICTIONS_SUCCESS" | "GUILD_ROLE_SUBSCRIPTIONS_FETCH_TEMPLATES" | "GUILD_ROLE_SUBSCRIPTIONS_STASH_TEMPLATE_CHANNELS" | "GUILD_ROLE_SUBSCRIPTIONS_UPDATE_GROUP_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_UPDATE_LISTING" | "GUILD_ROLE_SUBSCRIPTIONS_UPDATE_SUBSCRIPTIONS_SETTINGS" | "GUILD_ROLE_SUBSCRIPTIONS_UPDATE_SUBSCRIPTION_TRIAL" | "GUILD_ROLE_UPDATE" | "GUILD_SCHEDULED_EVENT_CREATE" | "GUILD_SCHEDULED_EVENT_DELETE" | "GUILD_SCHEDULED_EVENT_EXCEPTIONS_DELETE" | "GUILD_SCHEDULED_EVENT_EXCEPTION_CREATE" | "GUILD_SCHEDULED_EVENT_EXCEPTION_DELETE" | "GUILD_SCHEDULED_EVENT_EXCEPTION_UPDATE" | "GUILD_SCHEDULED_EVENT_RSVPS_FETCH_SUCESS" | "GUILD_SCHEDULED_EVENT_UPDATE" | "GUILD_SCHEDULED_EVENT_USERS_FETCH_SUCCESS" | "GUILD_SCHEDULED_EVENT_USER_ADD" | "GUILD_SCHEDULED_EVENT_USER_COUNTS_FETCH_SUCCESS" | "GUILD_SCHEDULED_EVENT_USER_REMOVE" | "GUILD_SEARCH_RECENT_MEMBERS" | "GUILD_SETTINGS_CANCEL_CHANGES" | "GUILD_SETTINGS_CLOSE" | "GUILD_SETTINGS_DEFAULT_CHANNELS_RESET" | "GUILD_SETTINGS_DEFAULT_CHANNELS_SAVE_FAILED" | "GUILD_SETTINGS_DEFAULT_CHANNELS_SAVE_SUCCESS" | "GUILD_SETTINGS_DEFAULT_CHANNELS_SUBMIT" | "GUILD_SETTINGS_DEFAULT_CHANNELS_TOGGLE" | "GUILD_SETTINGS_INIT" | "GUILD_SETTINGS_LOADED_BANS" | "GUILD_SETTINGS_LOADED_BANS_BATCH" | "GUILD_SETTINGS_LOADED_INTEGRATIONS" | "GUILD_SETTINGS_LOADED_INVITES" | "GUILD_SETTINGS_ONBOARDING_ADD_NEW_MEMBER_ACTION" | "GUILD_SETTINGS_ONBOARDING_ADD_RESOURCE_CHANNEL" | "GUILD_SETTINGS_ONBOARDING_DELETE_NEW_MEMBER_ACTION" | "GUILD_SETTINGS_ONBOARDING_DELETE_RESOURCE_CHANNEL" | "GUILD_SETTINGS_ONBOARDING_DISMISS_RESOURCE_CHANNEL_SUGGESTION" | "GUILD_SETTINGS_ONBOARDING_EDUCATION_UPSELL_DISMISSED" | "GUILD_SETTINGS_ONBOARDING_HOME_SETTINGS_RESET" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_EDIT" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_ERRORS" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_RESET" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_SAVE_FAILED" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_SAVE_SUCCESS" | "GUILD_SETTINGS_ONBOARDING_PROMPTS_SUBMIT" | "GUILD_SETTINGS_ONBOARDING_REORDER_NEW_MEMBER_ACTION" | "GUILD_SETTINGS_ONBOARDING_REORDER_RESOURCE_CHANNEL" | "GUILD_SETTINGS_ONBOARDING_SET_MODE" | "GUILD_SETTINGS_ONBOARDING_STEP" | "GUILD_SETTINGS_ONBOARDING_UPDATE_NEW_MEMBER_ACTION" | "GUILD_SETTINGS_ONBOARDING_UPDATE_NEW_MEMBER_ACTION_ICON_DATA" | "GUILD_SETTINGS_ONBOARDING_UPDATE_RESOURCE_CHANNEL" | "GUILD_SETTINGS_ONBOARDING_UPDATE_WELCOME_MESSAGE" | "GUILD_SETTINGS_OPEN" | "GUILD_SETTINGS_ROLES_CLEAR_PERMISSIONS" | "GUILD_SETTINGS_ROLES_EDIT_SECTION_UPDATE" | "GUILD_SETTINGS_ROLES_INIT" | "GUILD_SETTINGS_ROLES_SAVE_FAIL" | "GUILD_SETTINGS_ROLES_SAVE_SUCCESS" | "GUILD_SETTINGS_ROLES_SORT_UPDATE" | "GUILD_SETTINGS_ROLES_SUBMITTING" | "GUILD_SETTINGS_ROLES_UPDATE_COLOR" | "GUILD_SETTINGS_ROLES_UPDATE_DESCRIPTION" | "GUILD_SETTINGS_ROLES_UPDATE_NAME" | "GUILD_SETTINGS_ROLES_UPDATE_PERMISSIONS" | "GUILD_SETTINGS_ROLES_UPDATE_PERMISSION_SET" | "GUILD_SETTINGS_ROLES_UPDATE_ROLE_CONNECTION_CONFIGURATIONS" | "GUILD_SETTINGS_ROLES_UPDATE_ROLE_ICON" | "GUILD_SETTINGS_ROLES_UPDATE_SETTINGS" | "GUILD_SETTINGS_ROLE_SELECT" | "GUILD_SETTINGS_SAFETY_PAGE" | "GUILD_SETTINGS_SAFETY_SET_SUBSECTION" | "GUILD_SETTINGS_SAVE_ROUTE_STACK" | "GUILD_SETTINGS_SET_MFA_SUCCESS" | "GUILD_SETTINGS_SET_SEARCH_QUERY" | "GUILD_SETTINGS_SET_SECTION" | "GUILD_SETTINGS_SET_VANITY_URL" | "GUILD_SETTINGS_SET_WIDGET" | "GUILD_SETTINGS_SUBMIT" | "GUILD_SETTINGS_SUBMIT_FAILURE" | "GUILD_SETTINGS_SUBMIT_SUCCESS" | "GUILD_SETTINGS_UPDATE" | "GUILD_SETTINGS_VANITY_URL_CLOSE" | "GUILD_SETTINGS_VANITY_URL_ERROR" | "GUILD_SETTINGS_VANITY_URL_RESET" | "GUILD_SETTINGS_VANITY_URL_SET" | "GUILD_SOUNDBOARD_FETCH" | "GUILD_SOUNDBOARD_SOUNDS_UPDATE" | "GUILD_SOUNDBOARD_SOUND_CREATE" | "GUILD_SOUNDBOARD_SOUND_DELETE" | "GUILD_SOUNDBOARD_SOUND_PLAY_END" | "GUILD_SOUNDBOARD_SOUND_PLAY_LOCALLY" | "GUILD_SOUNDBOARD_SOUND_PLAY_START" | "GUILD_SOUNDBOARD_SOUND_UPDATE" | "GUILD_STICKERS_CREATE_SUCCESS" | "GUILD_STICKERS_FETCH_SUCCESS" | "GUILD_STICKERS_UPDATE" | "GUILD_STOP_LURKING" | "GUILD_STOP_LURKING_FAILURE" | "GUILD_SUBSCRIPTIONS" | "GUILD_SUBSCRIPTIONS_ADD_MEMBER_UPDATES" | "GUILD_SUBSCRIPTIONS_CHANNEL" | "GUILD_SUBSCRIPTIONS_FLUSH" | "GUILD_SUBSCRIPTIONS_MEMBERS_ADD" | "GUILD_SUBSCRIPTIONS_MEMBERS_REMOVE" | "GUILD_SUBSCRIPTIONS_REMOVE_MEMBER_UPDATES" | "GUILD_TEMPLATE_ACCEPT" | "GUILD_TEMPLATE_ACCEPT_FAILURE" | "GUILD_TEMPLATE_ACCEPT_SUCCESS" | "GUILD_TEMPLATE_CREATE_SUCCESS" | "GUILD_TEMPLATE_DELETE_SUCCESS" | "GUILD_TEMPLATE_DIRTY_TOOLTIP_HIDE" | "GUILD_TEMPLATE_DIRTY_TOOLTIP_REFRESH" | "GUILD_TEMPLATE_LOAD_FOR_GUILD_SUCCESS" | "GUILD_TEMPLATE_MODAL_HIDE" | "GUILD_TEMPLATE_MODAL_SHOW" | "GUILD_TEMPLATE_PROMOTION_TOOLTIP_HIDE" | "GUILD_TEMPLATE_RESOLVE" | "GUILD_TEMPLATE_RESOLVE_FAILURE" | "GUILD_TEMPLATE_RESOLVE_SUCCESS" | "GUILD_TEMPLATE_SYNC_SUCCESS" | "GUILD_TOGGLE_COLLAPSE_MUTED" | "GUILD_TOP_READ_CHANNELS_FETCH_SUCCESS" | "GUILD_UNAPPLY_BOOST_FAIL" | "GUILD_UNAPPLY_BOOST_START" | "GUILD_UNAPPLY_BOOST_SUCCESS" | "GUILD_UNAVAILABLE" | "GUILD_UPDATE" | "GUILD_UPDATE_DISCOVERY_METADATA" | "GUILD_UPDATE_DISCOVERY_METADATA_FAIL" | "GUILD_UPDATE_DISCOVERY_METADATA_FROM_SERVER" | "GUILD_VERIFICATION_CHECK" | "HABITUAL_DND_CLEAR" | "HIDE_ACTION_SHEET" | "HIDE_ACTION_SHEET_QUICK_SWITCHER" | "HIDE_KEYBOARD_SHORTCUTS" | "HIGH_FIVE_COMPLETE" | "HIGH_FIVE_COMPLETE_CLEAR" | "HIGH_FIVE_QUEUE" | "HIGH_FIVE_REMOVE" | "HIGH_FIVE_SET_ENABLED" | "HOTSPOT_HIDE" | "HOTSPOT_OVERRIDE_CLEAR" | "HOTSPOT_OVERRIDE_SET" | "HYPESQUAD_ONLINE_MEMBERSHIP_JOIN_SUCCESS" | "HYPESQUAD_ONLINE_MEMBERSHIP_LEAVE_SUCCESS" | "I18N_LOAD_ERROR" | "I18N_LOAD_START" | "I18N_LOAD_SUCCESS" | "IDLE" | "IMPERSONATE_STOP" | "IMPERSONATE_UPDATE" | "INBOX_OPEN" | "INCOMING_CALL_MOVE" | "INITIALIZE_MEMBER_SAFETY_STORE" | "INSTALLATION_LOCATION_ADD" | "INSTALLATION_LOCATION_FETCH_METADATA" | "INSTALLATION_LOCATION_REMOVE" | "INSTALLATION_LOCATION_UPDATE" | "INSTANT_INVITE_CLEAR" | "INSTANT_INVITE_CREATE" | "INSTANT_INVITE_CREATE_FAILURE" | "INSTANT_INVITE_CREATE_SUCCESS" | "INSTANT_INVITE_REVOKE_SUCCESS" | "INTEGRATION_CREATE" | "INTEGRATION_DELETE" | "INTEGRATION_PERMISSION_SETTINGS_APPLICATION_PERMISSIONS_FETCH_FAILURE" | "INTEGRATION_PERMISSION_SETTINGS_CLEAR" | "INTEGRATION_PERMISSION_SETTINGS_COMMANDS_FETCH_FAILURE" | "INTEGRATION_PERMISSION_SETTINGS_COMMANDS_FETCH_SUCCESS" | "INTEGRATION_PERMISSION_SETTINGS_COMMAND_UPDATE" | "INTEGRATION_PERMISSION_SETTINGS_EDIT" | "INTEGRATION_PERMISSION_SETTINGS_INIT" | "INTEGRATION_PERMISSION_SETTINGS_RESET" | "INTEGRATION_QUERY" | "INTEGRATION_QUERY_FAILURE" | "INTEGRATION_QUERY_SUCCESS" | "INTEGRATION_SETTINGS_INIT" | "INTEGRATION_SETTINGS_SAVE_FAILURE" | "INTEGRATION_SETTINGS_SAVE_SUCCESS" | "INTEGRATION_SETTINGS_SET_SECTION" | "INTEGRATION_SETTINGS_START_EDITING_COMMAND" | "INTEGRATION_SETTINGS_START_EDITING_INTEGRATION" | "INTEGRATION_SETTINGS_START_EDITING_WEBHOOK" | "INTEGRATION_SETTINGS_STOP_EDITING_COMMAND" | "INTEGRATION_SETTINGS_STOP_EDITING_INTEGRATION" | "INTEGRATION_SETTINGS_STOP_EDITING_WEBHOOK" | "INTEGRATION_SETTINGS_SUBMITTING" | "INTEGRATION_SETTINGS_UPDATE_INTEGRATION" | "INTEGRATION_SETTINGS_UPDATE_WEBHOOK" | "INTERACTION_CREATE" | "INTERACTION_FAILURE" | "INTERACTION_IFRAME_MODAL_CLOSE" | "INTERACTION_IFRAME_MODAL_CREATE" | "INTERACTION_IFRAME_MODAL_KEY_CREATE" | "INTERACTION_MODAL_CREATE" | "INTERACTION_QUEUE" | "INTERACTION_SUCCESS" | "INVITE_ACCEPT" | "INVITE_ACCEPT_FAILURE" | "INVITE_ACCEPT_SUCCESS" | "INVITE_APP_NOT_OPENED" | "INVITE_APP_OPENED" | "INVITE_APP_OPENING" | "INVITE_MODAL_CLOSE" | "INVITE_MODAL_ERROR" | "INVITE_MODAL_OPEN" | "INVITE_RESOLVE" | "INVITE_RESOLVE_FAILURE" | "INVITE_RESOLVE_SUCCESS" | "KEYBINDS_ADD_KEYBIND" | "KEYBINDS_DELETE_KEYBIND" | "KEYBINDS_ENABLE_ALL_KEYBINDS" | "KEYBINDS_REGISTER_GLOBAL_KEYBIND_ACTIONS" | "KEYBINDS_SET_KEYBIND" | "KEYBOARD_NAVIGATION_EXPLAINER_MODAL_SEEN" | "LAYER_POP" | "LAYER_POP_ALL" | "LAYER_PUSH" | "LAYOUT_CREATE" | "LAYOUT_CREATE_WIDGETS" | "LAYOUT_DELETE_ALL_WIDGETS" | "LAYOUT_DELETE_WIDGET" | "LAYOUT_SET_PINNED" | "LAYOUT_SET_TOP_WIDGET" | "LAYOUT_UPDATE_WIDGET" | "LIBRARY_APPLICATIONS_TEST_MODE_ENABLED" | "LIBRARY_APPLICATION_ACTIVE_BRANCH_UPDATE" | "LIBRARY_APPLICATION_ACTIVE_LAUNCH_OPTION_UPDATE" | "LIBRARY_APPLICATION_FILTER_UPDATE" | "LIBRARY_APPLICATION_FLAGS_UPDATE_START" | "LIBRARY_APPLICATION_FLAGS_UPDATE_SUCCESS" | "LIBRARY_APPLICATION_UPDATE" | "LIBRARY_FETCH_SUCCESS" | "LIBRARY_TABLE_ACTIVE_ROW_ID_UPDATE" | "LIBRARY_TABLE_SORT_UPDATE" | "LIGHTNING_CHECKOUT_CLOSE" | "LIGHTNING_CHECKOUT_OPEN" | "LIVE_CHANNEL_NOTICE_HIDE" | "LOAD_ARCHIVED_THREADS" | "LOAD_ARCHIVED_THREADS_FAIL" | "LOAD_ARCHIVED_THREADS_SUCCESS" | "LOAD_CHANNELS" | "LOAD_FORUM_POSTS" | "LOAD_FRIEND_SUGGESTIONS_FAILURE" | "LOAD_FRIEND_SUGGESTIONS_SUCCESS" | "LOAD_GUILD_AFFINITIES_SUCCESS" | "LOAD_MESSAGES" | "LOAD_MESSAGES_AROUND_SUCCESS" | "LOAD_MESSAGES_FAILURE" | "LOAD_MESSAGES_SUCCESS" | "LOAD_MESSAGES_SUCCESS_CACHED" | "LOAD_MESSAGE_INTERACTION_DATA_SUCCESS" | "LOAD_MESSAGE_REQUESTS_SUPPLEMENTAL_DATA_ERROR" | "LOAD_MESSAGE_REQUESTS_SUPPLEMENTAL_DATA_SUCCESS" | "LOAD_NOTIFICATION_CENTER_ITEMS" | "LOAD_NOTIFICATION_CENTER_ITEMS_FAILURE" | "LOAD_NOTIFICATION_CENTER_ITEMS_SUCCESS" | "LOAD_PINNED_MESSAGES" | "LOAD_PINNED_MESSAGES_FAILURE" | "LOAD_PINNED_MESSAGES_SUCCESS" | "LOAD_RECENT_MENTIONS" | "LOAD_RECENT_MENTIONS_FAILURE" | "LOAD_RECENT_MENTIONS_SUCCESS" | "LOAD_REGIONS" | "LOAD_RELATIONSHIPS_FAILURE" | "LOAD_RELATIONSHIPS_SUCCESS" | "LOAD_THREADS_SUCCESS" | "LOAD_USER_AFFINITIES" | "LOAD_USER_AFFINITIES_FAILURE" | "LOAD_USER_AFFINITIES_SUCCESS" | "LOCAL_ACTIVITY_UPDATE" | "LOCAL_MESSAGES_LOADED" | "LOCAL_MESSAGE_CREATE" | "LOGIN" | "LOGIN_ACCOUNT_DISABLED" | "LOGIN_ACCOUNT_SCHEDULED_FOR_DELETION" | "LOGIN_ATTEMPTED" | "LOGIN_FAILURE" | "LOGIN_MFA" | "LOGIN_MFA_FAILURE" | "LOGIN_MFA_SMS" | "LOGIN_MFA_SMS_FAILURE" | "LOGIN_MFA_SMS_REQUEST_SUCCESS" | "LOGIN_MFA_STEP" | "LOGIN_PASSWORD_RECOVERY_PHONE_VERIFICATION" | "LOGIN_PHONE_IP_AUTHORIZATION_REQUIRED" | "LOGIN_RESET" | "LOGIN_STATUS_RESET" | "LOGIN_SUCCESS" | "LOGIN_SUSPENDED_USER" | "LOGOUT" | "LOGOUT_AUTH_SESSIONS_SUCCESS" | "MASKED_LINK_ADD_TRUSTED_DOMAIN" | "MASKED_LINK_ADD_TRUSTED_PROTOCOL" | "MAX_MEMBER_COUNT_NOTICE_DISMISS" | "MEDIA_ENGINE_APPLY_MEDIA_FILTER_SETTINGS" | "MEDIA_ENGINE_APPLY_MEDIA_FILTER_SETTINGS_ERROR" | "MEDIA_ENGINE_APPLY_MEDIA_FILTER_SETTINGS_START" | "MEDIA_ENGINE_DEVICES" | "MEDIA_ENGINE_INTERACTION_REQUIRED" | "MEDIA_ENGINE_NOISE_CANCELLATION_ERROR_RESET" | "MEDIA_ENGINE_PERMISSION" | "MEDIA_ENGINE_SET_AEC_DUMP" | "MEDIA_ENGINE_SET_AUDIO_ENABLED" | "MEDIA_ENGINE_SET_EXPERIMENTAL_ENCODERS" | "MEDIA_ENGINE_SET_EXPERIMENTAL_SOUNDSHARE" | "MEDIA_ENGINE_SET_GO_LIVE_SOURCE" | "MEDIA_ENGINE_SET_HARDWARE_H264" | "MEDIA_ENGINE_SET_OPEN_H264" | "MEDIA_ENGINE_SET_VIDEO_DEVICE" | "MEDIA_ENGINE_SET_VIDEO_ENABLED" | "MEDIA_ENGINE_SET_VIDEO_HOOK" | "MEDIA_ENGINE_SOUNDSHARE_FAILED" | "MEDIA_ENGINE_SOUNDSHARE_TRANSMITTING" | "MEDIA_ENGINE_VIDEO_SOURCE_QUALITY_CHANGED" | "MEDIA_ENGINE_VIDEO_STATE_CHANGED" | "MEDIA_POST_EMBED_FETCH" | "MEDIA_POST_EMBED_FETCH_FAILURE" | "MEDIA_POST_EMBED_FETCH_SUCCESS" | "MEDIA_SESSION_JOINED" | "MEMBER_SAFETY_GUILD_MEMBER_SEARCH_SUCCESS" | "MEMBER_SAFETY_GUILD_MEMBER_UPDATE_BATCH" | "MEMBER_SAFETY_NEW_MEMBER_TIMESTAMP_REFRESH" | "MEMBER_SAFETY_PAGINATION_TOKEN_UPDATE" | "MEMBER_SAFETY_PAGINATION_UPDATE" | "MEMBER_SAFETY_SEARCH_STATE_UPDATE" | "MEMBER_VERIFICATION_FORM_FETCH_FAIL" | "MEMBER_VERIFICATION_FORM_UPDATE" | "MENTION_MODAL_CLOSE" | "MENTION_MODAL_OPEN" | "MESSAGE_ACK" | "MESSAGE_ACKED" | "MESSAGE_CREATE" | "MESSAGE_DELETE" | "MESSAGE_DELETE_BULK" | "MESSAGE_EDIT_FAILED_AUTOMOD" | "MESSAGE_END_EDIT" | "MESSAGE_EXPLICIT_CONTENT_FP_CREATE" | "MESSAGE_EXPLICIT_CONTENT_FP_SUBMIT" | "MESSAGE_EXPLICIT_CONTENT_SCAN_TIMEOUT" | "MESSAGE_LENGTH_UPSELL" | "MESSAGE_NOTIFICATION_SHOWN" | "MESSAGE_PREVIEWS_LOADED" | "MESSAGE_PREVIEWS_LOCALLY_LOADED" | "MESSAGE_REACTION_ADD" | "MESSAGE_REACTION_ADD_MANY" | "MESSAGE_REACTION_ADD_USERS" | "MESSAGE_REACTION_REMOVE" | "MESSAGE_REACTION_REMOVE_ALL" | "MESSAGE_REACTION_REMOVE_EMOJI" | "MESSAGE_REMINDER_NOTIFIED" | "MESSAGE_REMINDER_TOGGLE" | "MESSAGE_REQUEST_ACCEPT_OPTIMISTIC" | "MESSAGE_REVEAL" | "MESSAGE_SEND_FAILED" | "MESSAGE_SEND_FAILED_AUTOMOD" | "MESSAGE_START_EDIT" | "MESSAGE_UPDATE" | "MESSAGE_UPDATE_EDIT" | "MFA_CLEAR_BACKUP_CODES" | "MFA_DISABLE_SUCCESS" | "MFA_ENABLE_EMAIL_TOKEN" | "MFA_ENABLE_SUCCESS" | "MFA_SEEN_BACKUP_CODE_PROMPT" | "MFA_SEND_VERIFICATION_KEY" | "MFA_SMS_TOGGLE" | "MFA_SMS_TOGGLE_COMPLETE" | "MFA_VIEW_BACKUP_CODES" | "MFA_WEBAUTHN_CREDENTIALS_LOADED" | "MFA_WEBAUTHN_CREDENTIALS_LOADING" | "MOBILE_NATIVE_UPDATE_CHECK_FINISHED" | "MOBILE_WEB_SIDEBAR_CLOSE" | "MOBILE_WEB_SIDEBAR_OPEN" | "MODAL_POP" | "MODAL_PUSH" | "MOD_VIEW_SEARCH_FINISH" | "MULTI_ACCOUNT_INVALIDATE_PUSH_SYNC_TOKENS" | "MULTI_ACCOUNT_MOBILE_EXPERIMENT_UPDATE" | "MULTI_ACCOUNT_MOVE_ACCOUNT" | "MULTI_ACCOUNT_REMOVE_ACCOUNT" | "MULTI_ACCOUNT_UPDATE_PUSH_SYNC_TOKEN" | "MULTI_ACCOUNT_VALIDATE_TOKEN_FAILURE" | "MULTI_ACCOUNT_VALIDATE_TOKEN_REQUEST" | "MULTI_ACCOUNT_VALIDATE_TOKEN_SUCCESS" | "MUTUAL_FRIENDS_FETCH_FAILURE" | "MUTUAL_FRIENDS_FETCH_START" | "MUTUAL_FRIENDS_FETCH_SUCCESS" | "NEWLY_ADDED_EMOJI_SEEN_ACKNOWLEDGED" | "NEWLY_ADDED_EMOJI_SEEN_PENDING" | "NEWLY_ADDED_EMOJI_SEEN_UPDATED" | "NEW_PAYMENT_SOURCE_ADDRESS_INFO_UPDATE" | "NEW_PAYMENT_SOURCE_CARD_INFO_UPDATE" | "NEW_PAYMENT_SOURCE_CLEAR_ERROR" | "NEW_PAYMENT_SOURCE_STRIPE_PAYMENT_REQUEST_UPDATE" | "NOTICE_DISABLE" | "NOTICE_DISMISS" | "NOTICE_SHOW" | "NOTIFICATIONS_SET_DESKTOP_TYPE" | "NOTIFICATIONS_SET_DISABLED_SOUNDS" | "NOTIFICATIONS_SET_DISABLE_UNREAD_BADGE" | "NOTIFICATIONS_SET_NOTIFY_MESSAGES_IN_SELECTED_CHANNEL" | "NOTIFICATIONS_SET_PERMISSION_STATE" | "NOTIFICATIONS_SET_TASKBAR_FLASH" | "NOTIFICATIONS_SET_TTS_TYPE" | "NOTIFICATIONS_TOGGLE_ALL_DISABLED" | "NOTIFICATION_CENTER_CLEAR_GUILD_MENTIONS" | "NOTIFICATION_CENTER_ITEMS_ACK" | "NOTIFICATION_CENTER_ITEMS_ACK_FAILURE" | "NOTIFICATION_CENTER_ITEMS_LOCAL_ACK" | "NOTIFICATION_CENTER_ITEM_COMPLETED" | "NOTIFICATION_CENTER_ITEM_CREATE" | "NOTIFICATION_CENTER_ITEM_DELETE" | "NOTIFICATION_CENTER_ITEM_DELETE_FAILURE" | "NOTIFICATION_CENTER_REFRESH" | "NOTIFICATION_CENTER_SET_ACTIVE" | "NOTIFICATION_CENTER_SET_TAB" | "NOTIFICATION_CENTER_TAB_FOCUSED" | "NOTIFICATION_CLICK" | "NOTIFICATION_CREATE" | "NOTIFICATION_SETTINGS_UPDATE" | "NOW_PLAYING_MOUNTED" | "NOW_PLAYING_UNMOUNTED" | "NUF_COMPLETE" | "NUF_NEW_USER" | "OAUTH2_TOKEN_REVOKE" | "ONLINE_GUILD_MEMBER_COUNT_UPDATE" | "OUTBOUND_PROMOTIONS_SEEN" | "OUTBOUND_PROMOTION_NOTICE_DISMISS" | "OVERLAY_ACTIVATE_REGION" | "OVERLAY_CALL_PRIVATE_CHANNEL" | "OVERLAY_CRASHED" | "OVERLAY_DEACTIVATE_ALL_REGIONS" | "OVERLAY_DISABLE_EXTERNAL_LINK_ALERT" | "OVERLAY_FOCUSED" | "OVERLAY_INCOMPATIBLE_APP" | "OVERLAY_INITIALIZE" | "OVERLAY_JOIN_GAME" | "OVERLAY_MESSAGE_EVENT_ACTION" | "OVERLAY_NOTIFICATION_EVENT" | "OVERLAY_NOTIFY_READY_TO_SHOW" | "OVERLAY_READY" | "OVERLAY_SELECT_CALL" | "OVERLAY_SELECT_CHANNEL" | "OVERLAY_SET_ASSOCIATED_GAME" | "OVERLAY_SET_AVATAR_SIZE_MODE" | "OVERLAY_SET_CLICK_ZONES" | "OVERLAY_SET_DISPLAY_NAME_MODE" | "OVERLAY_SET_DISPLAY_USER_MODE" | "OVERLAY_SET_ENABLED" | "OVERLAY_SET_INPUT_LOCKED" | "OVERLAY_SET_NOTIFICATION_POSITION_MODE" | "OVERLAY_SET_NOT_IDLE" | "OVERLAY_SET_PREVIEW_IN_GAME_MODE" | "OVERLAY_SET_SHOW_KEYBIND_INDICATORS" | "OVERLAY_SET_TEXT_CHAT_NOTIFICATION_MODE" | "OVERLAY_SET_TEXT_WIDGET_OPACITY" | "OVERLAY_SET_UI_LOCKED" | "OVERLAY_SOUNDBOARD_SOUNDS_FETCH_REQUEST" | "OVERLAY_START_SESSION" | "OVERLAY_SUCCESSFULLY_SHOWN" | "OVERLAY_WIDGET_CHANGED" | "PASSIVE_UPDATE_V1" | "PASSWORD_UPDATED" | "PAYMENT_AUTHENTICATION_CLEAR_ERROR" | "PAYMENT_AUTHENTICATION_ERROR" | "PAYMENT_UPDATE" | "PERMISSION_CLEAR_ELEVATED_PROCESS" | "PERMISSION_CLEAR_PTT_ADMIN_WARNING" | "PERMISSION_CLEAR_SUPPRESS_WARNING" | "PERMISSION_CLEAR_VAD_WARNING" | "PERMISSION_CONTINUE_NONELEVATED_PROCESS" | "PERMISSION_REQUEST_ELEVATED_PROCESS" | "PHONE_SET_COUNTRY_CODE" | "PICTURE_IN_PICTURE_CLOSE" | "PICTURE_IN_PICTURE_HIDE" | "PICTURE_IN_PICTURE_MOVE" | "PICTURE_IN_PICTURE_OPEN" | "PICTURE_IN_PICTURE_SHOW" | "PICTURE_IN_PICTURE_UPDATE_RECT" | "PICTURE_IN_PICTURE_UPDATE_SELECTED_WINDOW" | "POGGERMODE_ACHIEVEMENT_UNLOCK" | "POGGERMODE_SETTINGS_UPDATE" | "POGGERMODE_TEMPORARILY_DISABLED" | "POGGERMODE_UPDATE_COMBO" | "POGGERMODE_UPDATE_MESSAGE_COMBO" | "POPOUT_WINDOW_CLOSE" | "POPOUT_WINDOW_OPEN" | "POPOUT_WINDOW_SET_ALWAYS_ON_TOP" | "POST_CONNECTION_OPEN" | "PREMIUM_MARKETING_DATA_READY" | "PREMIUM_MARKETING_PREVIEW" | "PREMIUM_PAYMENT_ERROR_CLEAR" | "PREMIUM_PAYMENT_MODAL_CLOSE" | "PREMIUM_PAYMENT_MODAL_OPEN" | "PREMIUM_PAYMENT_SUBSCRIBE_FAIL" | "PREMIUM_PAYMENT_SUBSCRIBE_START" | "PREMIUM_PAYMENT_SUBSCRIBE_SUCCESS" | "PREMIUM_PAYMENT_UPDATE_FAIL" | "PREMIUM_PAYMENT_UPDATE_SUCCESS" | "PREMIUM_PERKS_DEMOS_FETCH_FAILURE" | "PREMIUM_PERKS_DEMOS_FETCH_SUCCESS" | "PREMIUM_PERKS_DEMO_ACTIVATE_FAILURE" | "PREMIUM_PERKS_DEMO_ACTIVATE_SUCCESS" | "PREMIUM_PERKS_DEMO_COMPLETE" | "PREMIUM_PERKS_DEMO_OVERRIDE" | "PREMIUM_REQUIRED_MODAL_CLOSE" | "PREMIUM_REQUIRED_MODAL_OPEN" | "PRESENCES_REPLACE" | "PRESENCE_UPDATES" | "PRIVATE_CHANNEL_INTEGRATION_CREATE" | "PRIVATE_CHANNEL_INTEGRATION_DELETE" | "PRIVATE_CHANNEL_INTEGRATION_UPDATE" | "PRIVATE_CHANNEL_RECIPIENTS_ADD_USER" | "PRIVATE_CHANNEL_RECIPIENTS_INVITE_CLOSE" | "PRIVATE_CHANNEL_RECIPIENTS_INVITE_OPEN" | "PRIVATE_CHANNEL_RECIPIENTS_INVITE_QUERY" | "PRIVATE_CHANNEL_RECIPIENTS_INVITE_SELECT" | "PRIVATE_CHANNEL_RECIPIENTS_REMOVE_USER" | "PROFILE_CUSTOMIZATION_OPEN_PREVIEW_MODAL" | "PROFILE_EFFECTS_SET_TRY_IT_OUT" | "PROFILE_PANEL_TOGGLE_SECTION" | "PROXY_BLOCKED_REQUEST" | "PUBLIC_UPSELL_NOTICE_DISMISS" | "PURCHASED_ITEMS_FESTIVITY_FETCH_WOW_MOMENT_MEDIA_SUCCESS" | "PURCHASED_ITEMS_FESTIVITY_IS_FETCHING_WOW_MOMENT_MEDIA" | "PURCHASED_ITEMS_FESTIVITY_SET_CAN_PLAY_WOW_MOMENT" | "PURCHASE_CONFIRMATION_MODAL_CLOSE" | "PURCHASE_CONFIRMATION_MODAL_OPEN" | "PUSH_NOTIFICATION_CLICK" | "QUESTS_CLAIM_REWARD_BEGIN" | "QUESTS_CLAIM_REWARD_CODE_BEGIN" | "QUESTS_CLAIM_REWARD_CODE_FAILURE" | "QUESTS_CLAIM_REWARD_CODE_SUCCESS" | "QUESTS_CLAIM_REWARD_FAILURE" | "QUESTS_CLAIM_REWARD_SUCCESS" | "QUESTS_DISMISS_CONTENT_BEGIN" | "QUESTS_DISMISS_CONTENT_FAILURE" | "QUESTS_DISMISS_CONTENT_SUCCESS" | "QUESTS_DISMISS_PROGRESS_TRACKING_FAILURE_NOTICE" | "QUESTS_ENROLL_BEGIN" | "QUESTS_ENROLL_FAILURE" | "QUESTS_ENROLL_SUCCESS" | "QUESTS_FETCH_CURRENT_QUESTS_BEGIN" | "QUESTS_FETCH_CURRENT_QUESTS_FAILURE" | "QUESTS_FETCH_CURRENT_QUESTS_SUCCESS" | "QUESTS_FETCH_REWARD_CODE_BEGIN" | "QUESTS_FETCH_REWARD_CODE_FAILURE" | "QUESTS_FETCH_REWARD_CODE_SUCCESS" | "QUESTS_OPTIMISTIC_PROGRESS_UPDATE" | "QUESTS_PREVIEW_UPDATE_SUCCESS" | "QUESTS_SEND_HEARTBEAT_FAILURE" | "QUESTS_SEND_HEARTBEAT_SUCCESS" | "QUEUE_INTERACTION_COMPONENT_STATE" | "QUICKSWITCHER_HIDE" | "QUICKSWITCHER_SEARCH" | "QUICKSWITCHER_SELECT" | "QUICKSWITCHER_SHOW" | "QUICKSWITCHER_SWITCH_TO" | "RECEIVE_CHANNEL_AFFINITIES" | "RECEIVE_CHANNEL_SUMMARIES" | "RECEIVE_CHANNEL_SUMMARIES_BULK" | "RECEIVE_CHANNEL_SUMMARY" | "RECENT_MENTION_DELETE" | "RECOMPUTE_READ_STATES" | "REFERRALS_FETCH_ELIGIBLE_USER_FAIL" | "REFERRALS_FETCH_ELIGIBLE_USER_START" | "REFERRALS_FETCH_ELIGIBLE_USER_SUCCESS" | "REGISTER" | "REGISTER_FAILURE" | "REGISTER_SAVE_FORM" | "REGISTER_SUCCESS" | "RELATIONSHIP_ADD" | "RELATIONSHIP_PENDING_INCOMING_REMOVED" | "RELATIONSHIP_REMOVE" | "RELATIONSHIP_UPDATE" | "REMOTE_COMMAND" | "REMOTE_SESSION_CONNECT" | "REMOTE_SESSION_DISCONNECT" | "REMOVE_AUTOMOD_MESSAGE_NOTICE" | "REQUEST_CHANNEL_AFFINITIES" | "REQUEST_CHANNEL_SUMMARIES" | "REQUEST_CHANNEL_SUMMARIES_BULK" | "REQUEST_CHANNEL_SUMMARY" | "REQUEST_FORUM_UNREADS" | "REQUEST_SOUNDBOARD_SOUNDS" | "RESET_NOTIFICATION_CENTER" | "RESET_PAYMENT_ID" | "RESET_PREVIEW_CLIENT_THEME" | "RESET_SOCKET" | "RESORT_THREADS" | "RPC_APP_AUTHENTICATED" | "RPC_APP_CONNECTED" | "RPC_APP_DISCONNECTED" | "RPC_NOTIFICATION_CREATE" | "RPC_SERVER_READY" | "RTC_CONNECTION_FLAGS" | "RTC_CONNECTION_LOSS_RATE" | "RTC_CONNECTION_PING" | "RTC_CONNECTION_PLATFORM" | "RTC_CONNECTION_STATE" | "RTC_CONNECTION_UPDATE_ID" | "RTC_CONNECTION_USER_CREATE" | "RTC_CONNECTION_VIDEO" | "RTC_DEBUG_MODAL_CLOSE" | "RTC_DEBUG_MODAL_OPEN" | "RTC_DEBUG_MODAL_OPEN_REPLAY" | "RTC_DEBUG_MODAL_OPEN_REPLAY_AT_PATH" | "RTC_DEBUG_MODAL_SET_SECTION" | "RTC_DEBUG_MODAL_UPDATE" | "RTC_DEBUG_MODAL_UPDATE_VIDEO_OUTPUT" | "RTC_DEBUG_POPOUT_WINDOW_OPEN" | "RTC_DEBUG_SET_RECORDING_FLAG" | "RTC_LATENCY_TEST_COMPLETE" | "RTC_SPEED_TEST_START_TEST" | "RTC_SPEED_TEST_STOP_TEST" | "RUNNING_GAMES_CHANGE" | "RUNNING_GAME_ADD_OVERRIDE" | "RUNNING_GAME_DELETE_ENTRY" | "RUNNING_GAME_EDIT_NAME" | "RUNNING_GAME_TOGGLE_DETECTION" | "RUNNING_GAME_TOGGLE_OVERLAY" | "RUNNING_STREAMER_TOOLS_CHANGE" | "SAFETY_HUB_APPEAL_CLOSE" | "SAFETY_HUB_APPEAL_OPEN" | "SAFETY_HUB_APPEAL_SIGNAL_CUSTOM_INPUT_CHANGE" | "SAFETY_HUB_APPEAL_SIGNAL_SELECT" | "SAFETY_HUB_FETCH_CLASSIFICATION_FAILURE" | "SAFETY_HUB_FETCH_CLASSIFICATION_START" | "SAFETY_HUB_FETCH_CLASSIFICATION_SUCCESS" | "SAFETY_HUB_FETCH_FAILURE" | "SAFETY_HUB_FETCH_START" | "SAFETY_HUB_FETCH_SUCCESS" | "SAFETY_HUB_REQUEST_REVIEW_FAILURE" | "SAFETY_HUB_REQUEST_REVIEW_START" | "SAFETY_HUB_REQUEST_REVIEW_SUCCESS" | "SAVED_MESSAGES_UPDATE" | "SAVE_LAST_NON_VOICE_ROUTE" | "SAVE_LAST_ROUTE" | "SEARCH_ADD_HISTORY" | "SEARCH_AUTOCOMPLETE_QUERY_UPDATE" | "SEARCH_CLEAR_HISTORY" | "SEARCH_EDITOR_STATE_CHANGE" | "SEARCH_EDITOR_STATE_CLEAR" | "SEARCH_ENSURE_SEARCH_STATE" | "SEARCH_FINISH" | "SEARCH_INDEXING" | "SEARCH_MODAL_CLOSE" | "SEARCH_MODAL_OPEN" | "SEARCH_REMOVE_HISTORY" | "SEARCH_SCREEN_OPEN" | "SEARCH_SET_SHOW_BLOCKED_RESULTS" | "SEARCH_START" | "SELECTIVELY_SYNCED_USER_SETTINGS_UPDATE" | "SELECT_HOME_RESOURCE_CHANNEL" | "SELECT_NEW_MEMBER_ACTION_CHANNEL" | "SELF_PRESENCE_STORE_UPDATE" | "SESSIONS_REPLACE" | "SET_CHANNEL_BITRATE" | "SET_CHANNEL_VIDEO_QUALITY_MODE" | "SET_CONSENT_REQUIRED" | "SET_CREATED_AT_OVERRIDE" | "SET_GUILD_FOLDER_EXPANDED" | "SET_HIGHLIGHTED_SUMMARY" | "SET_INTERACTION_COMPONENT_STATE" | "SET_LOCATION_METADATA" | "SET_LOGIN_CREDENTIALS" | "SET_NATIVE_PERMISSION" | "SET_PENDING_REPLY_SHOULD_MENTION" | "SET_PREMIUM_TYPE_OVERRIDE" | "SET_RECENTLY_ACTIVE_COLLAPSED" | "SET_RECENT_MENTIONS_FILTER" | "SET_RECENT_MENTIONS_STALE" | "SET_SELECTED_SUMMARY" | "SET_SOUNDPACK" | "SET_STREAM_APP_INTENT" | "SET_SUMMARY_FEEDBACK" | "SET_TTS_SPEECH_RATE" | "SET_VAD_PERMISSION" | "SHARED_CANVAS_CLEAR_DRAWABLES" | "SHARED_CANVAS_DRAW_LINE_POINT" | "SHARED_CANVAS_SET_DRAW_MODE" | "SHARED_CANVAS_UPDATE_EMOJI_HOSE" | "SHARED_CANVAS_UPDATE_LINE_POINTS" | "SHOW_ACTION_SHEET" | "SHOW_ACTION_SHEET_QUICK_SWITCHER" | "SHOW_KEYBOARD_SHORTCUTS" | "SIDEBAR_CLOSE" | "SIDEBAR_CLOSE_GUILD" | "SIDEBAR_CREATE_THREAD" | "SIDEBAR_VIEW_CHANNEL" | "SIDEBAR_VIEW_GUILD" | "SKUS_FETCH_SUCCESS" | "SKU_FETCH_FAIL" | "SKU_FETCH_START" | "SKU_FETCH_SUCCESS" | "SKU_PURCHASE_AWAIT_CONFIRMATION" | "SKU_PURCHASE_CLEAR_ERROR" | "SKU_PURCHASE_FAIL" | "SKU_PURCHASE_MODAL_CLOSE" | "SKU_PURCHASE_MODAL_OPEN" | "SKU_PURCHASE_PREVIEW_FETCH" | "SKU_PURCHASE_PREVIEW_FETCH_FAILURE" | "SKU_PURCHASE_PREVIEW_FETCH_SUCCESS" | "SKU_PURCHASE_SHOW_CONFIRMATION_STEP" | "SKU_PURCHASE_START" | "SKU_PURCHASE_SUCCESS" | "SKU_PURCHASE_UPDATE_IS_GIFT" | "SLOWMODE_RESET_COOLDOWN" | "SLOWMODE_SET_COOLDOWN" | "SOUNDBOARD_FETCH_DEFAULT_SOUNDS" | "SOUNDBOARD_FETCH_DEFAULT_SOUNDS_SUCCESS" | "SOUNDBOARD_MUTE_JOIN_SOUND" | "SOUNDBOARD_SET_OVERLAY_ENABLED" | "SOUNDBOARD_SOUNDS_RECEIVED" | "SPEAKING" | "SPEAKING_MESSAGE" | "SPEAK_MESSAGE" | "SPEAK_TEXT" | "SPEED_TEST_CREATE" | "SPEED_TEST_DELETE" | "SPEED_TEST_SERVER_UPDATE" | "SPELLCHECK_LEARN_WORD" | "SPELLCHECK_TOGGLE" | "SPELLCHECK_UNLEARN_WORD" | "SPOTIFY_ACCOUNT_ACCESS_TOKEN" | "SPOTIFY_ACCOUNT_ACCESS_TOKEN_REVOKE" | "SPOTIFY_NEW_TRACK" | "SPOTIFY_PLAYER_PAUSE" | "SPOTIFY_PLAYER_PLAY" | "SPOTIFY_PLAYER_STATE" | "SPOTIFY_PROFILE_UPDATE" | "SPOTIFY_SET_ACTIVE_DEVICE" | "SPOTIFY_SET_DEVICES" | "SPOTIFY_SET_PROTOCOL_REGISTERED" | "STAGE_INSTANCE_CREATE" | "STAGE_INSTANCE_DELETE" | "STAGE_INSTANCE_UPDATE" | "STAGE_MUSIC_MUTE" | "STAGE_MUSIC_PLAY" | "START_BROADCAST_STREAM" | "START_SESSION" | "STATUS_PAGE_INCIDENT" | "STATUS_PAGE_SCHEDULED_MAINTENANCE" | "STATUS_PAGE_SCHEDULED_MAINTENANCE_ACK" | "STICKER_FETCH_SUCCESS" | "STICKER_PACKS_FETCH_START" | "STICKER_PACKS_FETCH_SUCCESS" | "STICKER_PACK_FETCH_SUCCESS" | "STICKER_TRACK_USAGE" | "STOP_SPEAKING" | "STORE_LISTINGS_FETCH_SUCCESS" | "STORE_LISTING_FETCH_SUCCESS" | "STREAMER_MODE_UPDATE" | "STREAMING_UPDATE" | "STREAM_CLOSE" | "STREAM_CREATE" | "STREAM_DELETE" | "STREAM_LAYOUT_UPDATE" | "STREAM_PREVIEW_FETCH_FAIL" | "STREAM_PREVIEW_FETCH_START" | "STREAM_PREVIEW_FETCH_SUCCESS" | "STREAM_SERVER_UPDATE" | "STREAM_SET_PAUSED" | "STREAM_START" | "STREAM_STATS_UPDATE" | "STREAM_STOP" | "STREAM_TIMED_OUT" | "STREAM_UPDATE" | "STREAM_UPDATE_SELF_HIDDEN" | "STREAM_UPDATE_SETTINGS" | "STREAM_WATCH" | "STRIPE_TOKEN_FAILURE" | "SUBSCRIPTION_PLANS_FETCH" | "SUBSCRIPTION_PLANS_FETCH_FAILURE" | "SUBSCRIPTION_PLANS_FETCH_SUCCESS" | "SUBSCRIPTION_PLANS_RESET" | "SURVEY_FETCHED" | "SURVEY_HIDE" | "SURVEY_OVERRIDE" | "SURVEY_SEEN" | "SYSTEM_THEME_CHANGE" | "THERMAL_STATE_CHANGE" | "THREAD_CREATE" | "THREAD_CREATE_LOCAL" | "THREAD_DELETE" | "THREAD_LIST_SYNC" | "THREAD_MEMBERS_UPDATE" | "THREAD_MEMBER_LIST_UPDATE" | "THREAD_MEMBER_LOCAL_UPDATE" | "THREAD_MEMBER_UPDATE" | "THREAD_SETTINGS_DRAFT_CHANGE" | "THREAD_UPDATE" | "TOGGLE_GUILD_FOLDER_EXPAND" | "TOGGLE_OVERLAY_CANVAS" | "TOGGLE_TOPICS_BAR" | "TOP_EMOJIS_FETCH" | "TOP_EMOJIS_FETCH_SUCCESS" | "TRUNCATE_MENTIONS" | "TRUNCATE_MESSAGES" | "TRY_ACK" | "TUTORIAL_INDICATOR_DISMISS" | "TUTORIAL_INDICATOR_HIDE" | "TUTORIAL_INDICATOR_SHOW" | "TUTORIAL_INDICATOR_SUPPRESS_ALL" | "TYPING_START" | "TYPING_START_LOCAL" | "TYPING_STOP" | "TYPING_STOP_LOCAL" | "UNREAD_SETTING_NOTICE_CHANNEL_VISIT" | "UNREAD_SETTING_NOTICE_RENDERED" | "UNSYNCED_USER_SETTINGS_UPDATE" | "UNVERIFIED_GAME_UPDATE" | "UPCOMING_GUILD_EVENT_NOTICE_HIDE" | "UPCOMING_GUILD_EVENT_NOTICE_SEEN" | "UPDATE_AVAILABLE" | "UPDATE_BACKGROUND_GRADIENT_PRESET" | "UPDATE_CHANNEL_DIMENSIONS" | "UPDATE_CHANNEL_LIST_DIMENSIONS" | "UPDATE_CHANNEL_LIST_SUBTITLES" | "UPDATE_CLIENT_PREMIUM_TYPE" | "UPDATE_CONSENTS" | "UPDATE_DOWNLOADED" | "UPDATE_ERROR" | "UPDATE_GUILD_LIST_DIMENSIONS" | "UPDATE_HANG_STATUS" | "UPDATE_HANG_STATUS_CUSTOM" | "UPDATE_MANUALLY" | "UPDATE_MOBILE_PENDING_THEME_INDEX" | "UPDATE_NOT_AVAILABLE" | "UPDATE_TOKEN" | "UPDATE_VISIBLE_MESSAGES" | "UPLOAD_ATTACHMENT_ADD_FILES" | "UPLOAD_ATTACHMENT_CLEAR_ALL_FILES" | "UPLOAD_ATTACHMENT_POP_FILE" | "UPLOAD_ATTACHMENT_REMOVE_FILE" | "UPLOAD_ATTACHMENT_REMOVE_FILES" | "UPLOAD_ATTACHMENT_SET_FILE" | "UPLOAD_ATTACHMENT_SET_UPLOADS" | "UPLOAD_ATTACHMENT_UPDATE_FILE" | "UPLOAD_CANCEL_REQUEST" | "UPLOAD_COMPLETE" | "UPLOAD_COMPRESSION_PROGRESS" | "UPLOAD_FAIL" | "UPLOAD_FILE_UPDATE" | "UPLOAD_ITEM_CANCEL_REQUEST" | "UPLOAD_PROGRESS" | "UPLOAD_RESTORE_FAILED_UPLOAD" | "UPLOAD_START" | "USER_ACHIEVEMENT_UPDATE" | "USER_ACTIVITY_STATISTICS_FETCH_SUCCESS" | "USER_APPLICATION_REMOVE" | "USER_APPLICATION_UPDATE" | "USER_APPLIED_BOOSTS_FETCH_START" | "USER_APPLIED_BOOSTS_FETCH_SUCCESS" | "USER_AUTHORIZED_APPS_UPDATE" | "USER_CONNECTIONS_INTEGRATION_JOINING" | "USER_CONNECTIONS_INTEGRATION_JOINING_ERROR" | "USER_CONNECTIONS_UPDATE" | "USER_CONNECTION_UPDATE" | "USER_GUILD_JOIN_REQUEST_UPDATE" | "USER_GUILD_SETTINGS_CHANNEL_UPDATE" | "USER_GUILD_SETTINGS_CHANNEL_UPDATE_BULK" | "USER_GUILD_SETTINGS_FULL_UPDATE" | "USER_GUILD_SETTINGS_GUILD_AND_CHANNELS_UPDATE" | "USER_GUILD_SETTINGS_GUILD_UPDATE" | "USER_GUILD_SETTINGS_REMOVE_PENDING_CHANNEL_UPDATES" | "USER_JOIN_REQUEST_GUILDS_FETCH" | "USER_NON_CHANNEL_ACK" | "USER_NOTE_LOADED" | "USER_NOTE_LOAD_START" | "USER_NOTE_UPDATE" | "USER_PAYMENT_BROWSER_CHECKOUT_DONE" | "USER_PAYMENT_BROWSER_CHECKOUT_STARTED" | "USER_PAYMENT_CLIENT_ADD" | "USER_PROFILE_ACCESSIBILITY_TOOLTIP_VIEWED" | "USER_PROFILE_EFFECTS_FETCH" | "USER_PROFILE_EFFECTS_FETCH_FAILURE" | "USER_PROFILE_EFFECTS_FETCH_SUCCESS" | "USER_PROFILE_FETCH_FAILURE" | "USER_PROFILE_FETCH_START" | "USER_PROFILE_FETCH_SUCCESS" | "USER_PROFILE_MODAL_CLOSE" | "USER_PROFILE_MODAL_OPEN" | "USER_PROFILE_UPDATE_FAILURE" | "USER_PROFILE_UPDATE_START" | "USER_PROFILE_UPDATE_SUCCESS" | "USER_RECENT_GAMES_FETCH_ERROR" | "USER_RECENT_GAMES_FETCH_START" | "USER_RECENT_GAMES_FETCH_SUCCESS" | "USER_RECENT_GAMES_UPDATE_LOCAL" | "USER_REQUIRED_ACTION_UPDATE" | "USER_SETTINGS_ACCOUNT_CLOSE" | "USER_SETTINGS_ACCOUNT_INIT" | "USER_SETTINGS_ACCOUNT_RESET_AND_CLOSE_FORM" | "USER_SETTINGS_ACCOUNT_SET_PENDING_ACCENT_COLOR" | "USER_SETTINGS_ACCOUNT_SET_PENDING_AVATAR" | "USER_SETTINGS_ACCOUNT_SET_PENDING_AVATAR_DECORATION" | "USER_SETTINGS_ACCOUNT_SET_PENDING_BANNER" | "USER_SETTINGS_ACCOUNT_SET_PENDING_BIO" | "USER_SETTINGS_ACCOUNT_SET_PENDING_GLOBAL_NAME" | "USER_SETTINGS_ACCOUNT_SET_PENDING_PROFILE_EFFECT_ID" | "USER_SETTINGS_ACCOUNT_SET_PENDING_PRONOUNS" | "USER_SETTINGS_ACCOUNT_SET_PENDING_THEME_COLORS" | "USER_SETTINGS_ACCOUNT_SET_SINGLE_TRY_IT_OUT_COLLECTIBLES_ITEM" | "USER_SETTINGS_ACCOUNT_SET_TRY_IT_OUT_AVATAR" | "USER_SETTINGS_ACCOUNT_SET_TRY_IT_OUT_AVATAR_DECORATION" | "USER_SETTINGS_ACCOUNT_SET_TRY_IT_OUT_BANNER" | "USER_SETTINGS_ACCOUNT_SET_TRY_IT_OUT_PROFILE_EFFECT_ID" | "USER_SETTINGS_ACCOUNT_SET_TRY_IT_OUT_THEME_COLORS" | "USER_SETTINGS_ACCOUNT_SUBMIT" | "USER_SETTINGS_ACCOUNT_SUBMIT_FAILURE" | "USER_SETTINGS_ACCOUNT_SUBMIT_SUCCESS" | "USER_SETTINGS_CLEAR_ERRORS" | "USER_SETTINGS_LOCALE_OVERRIDE" | "USER_SETTINGS_MODAL_CLEAR_SCROLL_POSITION" | "USER_SETTINGS_MODAL_CLEAR_SUBSECTION" | "USER_SETTINGS_MODAL_CLOSE" | "USER_SETTINGS_MODAL_INIT" | "USER_SETTINGS_MODAL_OPEN" | "USER_SETTINGS_MODAL_RESET" | "USER_SETTINGS_MODAL_SET_SECTION" | "USER_SETTINGS_MODAL_SUBMIT" | "USER_SETTINGS_MODAL_SUBMIT_COMPLETE" | "USER_SETTINGS_MODAL_SUBMIT_FAILURE" | "USER_SETTINGS_MODAL_UPDATE_ACCOUNT" | "USER_SETTINGS_OVERRIDE_APPLY" | "USER_SETTINGS_OVERRIDE_CLEAR" | "USER_SETTINGS_PROTO_ENQUEUE_UPDATE" | "USER_SETTINGS_PROTO_LOAD_IF_NECESSARY" | "USER_SETTINGS_PROTO_UPDATE" | "USER_SETTINGS_PROTO_UPDATE_EDIT_INFO" | "USER_SETTINGS_RESET_ALL_PENDING" | "USER_SETTINGS_RESET_ALL_TRY_IT_OUT" | "USER_SETTINGS_RESET_PENDING_ACCOUNT_CHANGES" | "USER_SETTINGS_RESET_PENDING_AVATAR_DECORATION" | "USER_SETTINGS_RESET_PENDING_PROFILE_CHANGES" | "USER_SOUNDBOARD_SET_VOLUME" | "USER_TENURE_REWARD_STATUS_DELETE" | "USER_TENURE_REWARD_STATUS_RESET" | "USER_TENURE_REWARD_SYNC_START" | "USER_TENURE_REWARD_SYNC_SUCCESS" | "USER_UPDATE" | "VERIFY_FAILURE" | "VERIFY_SUCCESS" | "VIDEO_FILTER_ASSETS_FETCH_SUCCESS" | "VIDEO_FILTER_ASSET_DELETE_SUCCESS" | "VIDEO_FILTER_ASSET_UPLOAD_SUCCESS" | "VIDEO_SAVE_LAST_USED_BACKGROUND_OPTION" | "VIEW_HISTORY_MARK_VIEW" | "VOICE_BACKGROUND_UPDATE" | "VOICE_CATEGORY_COLLAPSE" | "VOICE_CATEGORY_EXPAND" | "VOICE_CHANNEL_EFFECT_CLEAR" | "VOICE_CHANNEL_EFFECT_RECENT_EMOJI" | "VOICE_CHANNEL_EFFECT_SEND" | "VOICE_CHANNEL_EFFECT_SENT_LOCAL" | "VOICE_CHANNEL_EFFECT_TOGGLE_ANIMATION_TYPE" | "VOICE_CHANNEL_EFFECT_UPDATE_TIME_STAMP" | "VOICE_CHANNEL_SELECT" | "VOICE_CHANNEL_STATUS_UPDATE" | "VOICE_SERVER_UPDATE" | "VOICE_STATE_UPDATES" | "WAIT_FOR_REMOTE_SESSION" | "WEBHOOKS_FETCHING" | "WEBHOOKS_UPDATE" | "WEBHOOK_CREATE" | "WEBHOOK_DELETE" | "WEBHOOK_UPDATE" | "WELCOME_SCREEN_FETCH_FAIL" | "WELCOME_SCREEN_FETCH_START" | "WELCOME_SCREEN_FETCH_SUCCESS" | "WELCOME_SCREEN_SETTINGS_CLEAR" | "WELCOME_SCREEN_SETTINGS_RESET" | "WELCOME_SCREEN_SETTINGS_UPDATE" | "WELCOME_SCREEN_SUBMIT" | "WELCOME_SCREEN_SUBMIT_FAILURE" | "WELCOME_SCREEN_SUBMIT_SUCCESS" | "WELCOME_SCREEN_UPDATE" | "WELCOME_SCREEN_VIEW" | "WINDOW_FOCUS" | "WINDOW_FULLSCREEN_CHANGE" | "WINDOW_HIDDEN" | "WINDOW_INIT" | "WINDOW_RESIZED" | "WINDOW_UNLOAD" | "WINDOW_VISIBILITY_CHANGE" | "WRITE_CACHES"; diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts index 39af843c5..16fe6e2dd 100644 --- a/src/webpack/common/types/utils.d.ts +++ b/src/webpack/common/types/utils.d.ts @@ -83,53 +83,56 @@ interface RestRequestData { export type RestAPI = Record<"delete" | "get" | "patch" | "post" | "put", (data: RestRequestData) => Promise>; -export type Permissions = "CREATE_INSTANT_INVITE" - | "KICK_MEMBERS" - | "BAN_MEMBERS" +export type Permissions = "ADD_REACTIONS" | "ADMINISTRATOR" - | "MANAGE_CHANNELS" - | "MANAGE_GUILD" + | "ATTACH_FILES" + | "BAN_MEMBERS" | "CHANGE_NICKNAME" + | "CONNECT" + | "CREATE_EVENTS" + | "CREATE_GUILD_EXPRESSIONS" + | "CREATE_INSTANT_INVITE" + | "CREATE_PRIVATE_THREADS" + | "CREATE_PUBLIC_THREADS" + | "DEAFEN_MEMBERS" + | "EMBED_LINKS" + | "KICK_MEMBERS" + | "MANAGE_CHANNELS" + | "MANAGE_EVENTS" + | "MANAGE_GUILD" + | "MANAGE_GUILD_EXPRESSIONS" + | "MANAGE_MESSAGES" | "MANAGE_NICKNAMES" | "MANAGE_ROLES" + | "MANAGE_THREADS" | "MANAGE_WEBHOOKS" - | "MANAGE_GUILD_EXPRESSIONS" - | "CREATE_GUILD_EXPRESSIONS" + | "MENTION_EVERYONE" + | "MODERATE_MEMBERS" + | "MOVE_MEMBERS" + | "MUTE_MEMBERS" + | "PRIORITY_SPEAKER" + | "READ_MESSAGE_HISTORY" + | "REQUEST_TO_SPEAK" + | "SEND_MESSAGES" + | "SEND_MESSAGES_IN_THREADS" + | "SEND_POLLS" + | "SEND_TTS_MESSAGES" + | "SEND_VOICE_MESSAGES" + | "SET_VOICE_CHANNEL_STATUS" + | "SPEAK" + | "STREAM" + | "USE_APPLICATION_COMMANDS" + | "USE_CLYDE_AI" + | "USE_EMBEDDED_ACTIVITIES" + | "USE_EXTERNAL_EMOJIS" + | "USE_EXTERNAL_SOUNDS" + | "USE_EXTERNAL_STICKERS" + | "USE_SOUNDBOARD" + | "USE_VAD" | "VIEW_AUDIT_LOG" | "VIEW_CHANNEL" - | "VIEW_GUILD_ANALYTICS" | "VIEW_CREATOR_MONETIZATION_ANALYTICS" - | "MODERATE_MEMBERS" - | "SEND_MESSAGES" - | "SEND_TTS_MESSAGES" - | "MANAGE_MESSAGES" - | "EMBED_LINKS" - | "ATTACH_FILES" - | "READ_MESSAGE_HISTORY" - | "MENTION_EVERYONE" - | "USE_EXTERNAL_EMOJIS" - | "ADD_REACTIONS" - | "USE_APPLICATION_COMMANDS" - | "MANAGE_THREADS" - | "CREATE_PUBLIC_THREADS" - | "CREATE_PRIVATE_THREADS" - | "USE_EXTERNAL_STICKERS" - | "SEND_MESSAGES_IN_THREADS" - | "SEND_VOICE_MESSAGES" - | "CONNECT" - | "SPEAK" - | "MUTE_MEMBERS" - | "DEAFEN_MEMBERS" - | "MOVE_MEMBERS" - | "USE_VAD" - | "PRIORITY_SPEAKER" - | "STREAM" - | "USE_EMBEDDED_ACTIVITIES" - | "USE_SOUNDBOARD" - | "USE_EXTERNAL_SOUNDS" - | "REQUEST_TO_SPEAK" - | "MANAGE_EVENTS" - | "CREATE_EVENTS"; + | "VIEW_GUILD_ANALYTICS"; export type PermissionsBits = Record; From c2e12e2827d629365f834c54f903788be37db58d Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 22:10:05 -0300 Subject: [PATCH 031/361] why not --- src/webpack/common/types/stores.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index d6bf3aaf3..8fcff338a 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -186,6 +186,6 @@ export class GuildStore extends FluxStore { export type useStateFromStores = ( stores: t.FluxStore[], mapper: () => T, - dependencies?: any, + dependencies?: any[] | null, isEqual?: (old: T, newer: T) => boolean ) => T; From 3b7f1be9a2eb81f28e18094a62710aa2637ec5f3 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 7 May 2024 22:23:44 -0300 Subject: [PATCH 032/361] i18nMessages: Keep language codes only --- src/webpack/common/types/i18nMessages.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webpack/common/types/i18nMessages.ts b/src/webpack/common/types/i18nMessages.ts index fdf677fc0..d18d801fd 100644 --- a/src/webpack/common/types/i18nMessages.ts +++ b/src/webpack/common/types/i18nMessages.ts @@ -19,6 +19,6 @@ import { LiteralUnion } from "type-fest"; export type i18nMessages = LiteralUnion< - "TITLE_BAR_CLOSE_WINDOW" | "TITLE_BAR_MAXIMIZE_WINDOW" | "TITLE_BAR_MINIMIZE_WINDOW" | "en-US" | "en-GB" | "zh-CN" | "zh-TW" | "cs" | "da" | "nl" | "fr" | "de" | "el" | "hu" | "it" | "ja" | "ko" | "pl" | "pt-BR" | "ru" | "es-ES" | "sv-SE" | "tr" | "bg" | "uk" | "fi" | "no" | "hr" | "ro" | "lt" | "th" | "vi" | "hi" | "KEYBIND_DESCRIPTION_MODAL_NAVIGATE_SERVERS" | "KEYBIND_DESCRIPTION_MODAL_NAVIGATE_CHANNELS" | "KEYBIND_DESCRIPTION_MODAL_NAVIGATE_BACK_FORWARD" | "KEYBIND_DESCRIPTION_MODAL_UNREAD_CHANNELS" | "KEYBIND_DESCRIPTION_MODAL_UNREAD_MENTION_CHANNELS" | "KEYBIND_DESCRIPTION_MODAL_NAVIGATE_TO_CALL" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_PREVIOUS_GUILD" | "KEYBIND_DESCRIPTION_MODAL_QUICKSWITCHER" | "KEYBIND_DESCRIPTION_MODAL_CREATE_GUILD" | "DND_OPERATION_LABEL_START" | "DND_OPERATION_LABEL_MOVE" | "DND_OPERATION_LABEL_DROP" | "DND_OPERATION_LABEL_CANCEL" | "KEYBIND_DESCRIPTION_MODAL_MARK_SERVER_READ" | "KEYBIND_DESCRIPTION_MODAL_MARK_CHANNEL_READ" | "KEYBIND_DESCRIPTION_MODAL_CREATE_DM_GROUP" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_PINS" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_INBOX" | "KEYBIND_DESCRIPTION_MODAL_MARK_TOP_INBOX_CHANNEL_READ" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_USERS" | "KEYBIND_DESCRIPTION_MODAL_SEARCH_EMOJIS" | "KEYBIND_DESCRIPTION_MODAL_SEARCH_GIFS" | "KEYBIND_DESCRIPTION_MODAL_SEARCH_STICKERS" | "KEYBIND_DESCRIPTION_MODAL_SCROLL_CHAT" | "KEYBIND_DESCRIPTION_MODAL_JUMP_TO_FIRST_UNREAD" | "KEYBIND_DESCRIPTION_MODAL_FOCUS_TEXT_AREA" | "KEYBIND_DESCRIPTION_MODAL_UPLOAD_FILE" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_MUTE" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_DEAFEN" | "KEYBIND_DESCRIPTION_MODAL_CALL_ACCEPT" | "KEYBIND_DESCRIPTION_MODAL_CALL_DECLINE" | "KEYBIND_DESCRIPTION_MODAL_CALL_START" | "KEYBIND_DESCRIPTION_MODAL_TOGGLE_HELP" | "KEYBIND_DESCRIPTION_MODAL_SEARCH" | "KEYBIND_DESCRIPTION_MODAL_EASTER_EGG" | "EDIT_MESSAGE" | "DELETE_MESSAGE" | "PIN_MESSAGE" | "ADD_REACTION" | "MESSAGE_ACTION_REPLY" | "COPY_TEXT" | "MARK_UNREAD" | "GUILDS_BAR_A11Y_LABEL" | "SERVERS" | "NEW" | "ADD_A_SERVER" | "GUILD_DISCOVERY_TOOLTIP" | "ACCOUNT_A11Y_LABEL" | "GUILD_SIDEBAR_A11Y_LABEL" | "UNKNOWN_USER" | "LOADING" | "LOADING_DID_YOU_KNOW" | "CONNECTING_PROBLEMS_CTA" | "TWEET_US" | "SERVER_STATUS" | "NOTIFICATION_CENTER_INCOMING_FRIEND_REQUEST" | "COMMAND_SHRUG_MESSAGE_DESCRIPTION" | "DIRECT_MESSAGES" | "GUILD_TOOLTIP_A11Y_LABEL" | "FAVORITES_GUILD_NAME" | "MEMBER_VERIFICATION_FOLDER_NAME" | "DND_DROP_ABOVE" | "DND_DROP_COMBINE" | "GUILD_FOLDER_TOOLTIP_A11Y_LABEL" | "DND_END_OF_LIST" | "GUILD_SIDEBAR_ACTIONS_BUTTON" | "PREMIUM_GUILD_TIER_3" | "PREMIUM_GUILD_SUBSCRIPTION_SUBSCRIBER_COUNT_TOOLTIP" | "CHANNELS" | "NEW_UNREADS" | "NEW_MENTIONS" | "UNMUTE" | "MUTE" | "DEAFEN" | "SET_STATUS" | "LABEL_WITH_ONLINE_STATUS" | "STATUS_ONLINE" | "USER_SETTINGS" | "CHANNEL_HEADER_BAR_A11Y_LABEL" | "TEXT_CHANNEL" | "UPLOAD_TO" | "UPLOAD_AREA_HELP" | "THREADS" | "NOTIFICATION_SETTINGS" | "PINNED_MESSAGES" | "MEMBER_LIST_SHOWN" | "SEARCH" | "SEARCH_CLEAR" | "INBOX" | "HELP" | "TEXTAREA_PLACEHOLDER" | "TEXTAREA_TEXT_CHANNEL_A11Y_LABEL" | "CHANNEL_A11Y_LABEL" | "CHANNEL_CHAT_HEADING" | "CHANNEL_MESSAGES_A11Y_LABEL" | "CHANNEL_MESSAGES_A11Y_DESCRIPTION" | "CHAT_ATTACH_UPLOAD_A_FILE" | "CHAT_ATTACH_UPLOAD_TEXT_AS_FILE" | "CREATE_THREAD" | "CHAT_ATTACH_USE_SLASH_COMMAND" | "CHAT_ATTACH_UPLOAD_OR_INVITE" | "PREMIUM_GIFT_BUTTON_TOOLTIP" | "PREMIUM_GIFT_BUTTON_LABEL" | "GIF_BUTTON_LABEL" | "STICKER_BUTTON_LABEL" | "SELECT_EMOJI" | "CHARACTER_COUNT_CLOSE_TO_LIMIT" | "MEMBERS_LIST_LANDMARK_LABEL" | "MEMBERS" | "PREMIUM_GUILD_SUBSCRIPTIONS_GOAL" | "PREMIUM_GUILD_TIER_3_SHORT" | "PREMIUM_GUILD_SUBSCRIPTIONS_PROGRESS_BAR_BLURB" | "PREMIUM_GUILD_SUBSCRIPTIONS_PROGRESS_BAR_COMPLETED_BLURB" | "PREMIUM_GUILD_SUBSCRIPTIONS_NUDGE_TOOLTIP_COMPLETE" | "PREMIUM_GUILD_SUBSCRIPTIONS_PROGRESS_BAR_TADA_ICON_ALT_TEXT" | "GUILD_EVENTS" | "GUILD_SIDEBAR_DEFAULT_CHANNEL_A11Y_LABEL" | "CHANNEL_TOOLTIP_TEXT_LIMITED" | "CREATE_INSTANT_INVITE" | "EDIT_CHANNEL" | "CHANNEL_TOOLTIP_TEXT" | "CATEGORY_A11Y_LABEL" | "CREATE_CHANNEL" | "CHANNEL_TOOLTIP_RULES" | "GUILD_SIDEBAR_ANNOUNCEMENT_CHANNEL_A11Y_LABEL" | "CHANNEL_TOOLTIP_ANNOUNCEMENTS" | "GUILD_SIDEBAR_STAGE_CHANNEL_A11Y_LABEL" | "OPEN_CHAT" | "CHANNEL_TOOLTIP_STAGE_LIMITED" | "CHANNEL_TOOLTIP_TEXT_ACTIVE_THREADS" | "THREAD_GROUP_A11Y_LABEL" | "GUILD_SIDEBAR_THREAD_A11Y_LABEL" | "GUILD_SIDEBAR_VOICE_CHANNEL_A11Y_LABEL" | "GUILD_SIDEBAR_CHANNEL_A11Y_LABEL_UNREAD" | "GUILD_SIDEBAR_VOICE_CHANNEL_A11Y_LABEL_USERS" | "CHANNEL_TOOLTIP_VOICE" | "STATUS_UNKNOWN" | "MESSAGE_A11Y_ROLE_DESCRIPTION" | "ROLE_ICON_ALT_TEXT" | "CHANNEL_MESSAGE_REPLY_A11Y_LABEL" | "IMAGE" | "MESSAGE_EDITED" | "MESSAGE_EDITED_TIMESTAMP_A11Y_LABEL" | "EMOJI_TOOLTIP_CLICK_CTA" | "REMOVE_MESSAGE_ATTACHMENT" | "VERIFIED_BOT_TOOLTIP" | "SUPPRESS_ALL_EMBEDS" | "CHANNEL_MEMBERS_A11Y_LABEL" | "GUILD_OWNER" | "PREMIUM_GUILD_SUBSCRIPTION_TOOLTIP" | "STATUS_ONLINE_MOBILE" | "STATUS_IDLE" | "STREAMING" | "LISTENING_TO" | "WATCHING" | "COMPETING" | "PLAYING_GAME" | "STATUS_DND" | "CHAT_ATTACH_INVITE_TO_LISTEN" | "ACTIVITY_PANEL_GO_LIVE_STREAM_GAME" | "SEARCH_ANSWER_HAS_LINK" | "SEARCH_ANSWER_HAS_EMBED" | "SEARCH_ANSWER_HAS_ATTACHMENT" | "SEARCH_ANSWER_HAS_VIDEO" | "SEARCH_ANSWER_HAS_IMAGE" | "SEARCH_ANSWER_HAS_SOUND" | "SEARCH_ANSWER_HAS_STICKER" | "SEARCH_FILTER_FROM" | "SEARCH_FILTER_MENTIONS" | "SEARCH_FILTER_HAS" | "SEARCH_FILTER_FILE_TYPE" | "SEARCH_FILTER_FILE_NAME" | "SEARCH_FILTER_BEFORE" | "SEARCH_FILTER_ON" | "SEARCH_FILTER_DURING" | "SEARCH_FILTER_AFTER" | "SEARCH_FILTER_IN" | "SEARCH_FILTER_PINNED" | "MESSAGE_UTILITIES_A11Y_LABEL" | "EDIT" | "MORE" | "SEARCH_SHORTCUT_TODAY" | "SEARCH_SHORTCUT_YESTERDAY" | "SEARCH_SHORTCUT_WEEK" | "SEARCH_SHORTCUT_MONTH" | "SEARCH_SHORTCUT_YEAR" | "SEARCH_GROUP_HEADER_SEARCH_OPTIONS" | "SEARCH_GROUP_HEADER_HISTORY" | "LEARN_MORE" | "SEARCH_ANSWER_FROM" | "SEARCH_ANSWER_MENTIONS" | "SEARCH_ANSWER_HAS" | "SEARCH_ANSWER_DATE" | "SEARCH_ANSWER_IN" | "SEARCH_ANSWER_BOOLEAN" | "SEARCH_CLEAR_HISTORY" | "SEARCH_FROM_SUGGESTIONS" | "MEMBER_LIST_HIDDEN" | "SEARCH_RESULTS_SECTION_LABEL" | "SEARCH_NEWEST_SHORT" | "SEARCH_OLDEST_SHORT" | "SEARCH_MOST_RELEVANT_SHORT" | "SEARCHING" | "TOTAL_RESULTS" | "JUMP" | "REPLY_QUOTE_MESSAGE_NOT_LOADED" | "COPY_MESSAGE_LINK" | "COPY_ID" | "MESSAGE_ACTIONS_MENU_LABEL" | "ACTIVE_THREADS_POPOUT_HEADER" | "ACTIVE_THREADS_POPOUT_LINK" | "THREAD_BROWSER_TIMESTAMP_MINUTES" | "THREAD_BROWSER_TIMESTAMP_HOURS" | "THREAD_BROWSER_TIMESTAMP_DAYS" | "THREAD_BROWSER_TIMESTAMP_MORE_THAN_MONTH" | "OPEN_CHANNEL_TOPIC" | "VIDEO" | "REPLY_QUOTE_NO_TEXT_CONTENT" | "PLAY" | "NEW_MEMBER_BADGE_TOOLTIP_TEXT" | "USER_SETTINGS_MY_ACCOUNT" | "USER_SETTINGS_PROFILES" | "PRIVACY_AND_SAFETY" | "AUTHORIZED_APPS" | "AUTH_SESSIONS" | "CONNECTIONS" | "CLIPS" | "FRIEND_REQUESTS" | "BILLING_SETTINGS" | "PREMIUM" | "PREMIUM_GUILD_SUBSCRIPTION_TITLE" | "SUBSCRIPTIONS_TITLE" | "GIFT_INVENTORY" | "BILLING" | "APP_SETTINGS" | "APPEARANCE" | "ACCESSIBILITY" | "VOICE_AND_VIDEO" | "POGGERMODE" | "TEXT_AND_IMAGES" | "NOTIFICATIONS" | "KEYBINDS" | "LANGUAGE" | "USER_SETTINGS_WINDOWS_SETTINGS" | "USER_SETTINGS_LINUX_SETTINGS" | "STREAMER_MODE" | "SETTINGS_ADVANCED" | "ACTIVITY_SETTINGS" | "ACTIVITY_PRIVACY" | "REGISTERED_GAMES" | "OVERLAY" | "WHATS_NEW" | "USER_SETTINGS_HYPESQUAD" | "LOGOUT" | "BETA" | "USER_SETTINGS_ACCOUNT_PASSWORD_AND_AUTHENTICATION" | "CHANGE_PASSWORD" | "USER_SETTINGS_EDIT_USER_PROFILE" | "ACTIONS" | "HYPESQUAD_ONLINE_BADGE_TOOLTIP" | "HYPESQUAD_HOUSE_1" | "ACTIVE_DEVELOPER_BADGE_TOOLTIP" | "PROFILE_USER_BADGES" | "USER_SETTINGS_LABEL_USERNAME" | "USER_SETTINGS_ACCOUNT_EDIT_USERNAME_A11Y_LABEL" | "USER_SETTINGS_ACCOUNT_EDIT_EMAIL_A11Y_LABEL" | "USER_SETTINGS_ACCOUNT_REVEAL_EMAIL_A11Y_LABEL" | "USER_SETTINGS_ACCOUNT_HIDE_EMAIL_A11Y_LABEL" | "USER_SETTINGS_LABEL_EMAIL" | "REVEAL" | "USER_SETTINGS_ACCOUNT_REVEAL_PHONE_A11Y_LABEL" | "USER_SETTINGS_ACCOUNT_HIDE_PHONE_A11Y_LABEL" | "USER_SETTINGS_LABEL_PHONE_NUMBER" | "USER_SETTINGS_ACCOUNT_REMOVE_PHONE_A11Y_LABEL" | "REMOVE" | "USER_SETTINGS_ACCOUNT_EDIT_PHONE_A11Y_LABEL" | "TWO_FA_VIEW_BACKUP_CODES" | "TWO_FA_ENABLED" | "TWO_FA_DESCRIPTION" | "TWO_FA_DISABLED_FOR_SERVER_SUBSCRIPTION_MOD" | "MFA_SMS_AUTH_CURRENT_PHONE" | "MFA_SMS_PHONE_NUMBER_REVEAL" | "MFA_SMS_ENABLE" | "CHANGE_PHONE_NUMBER" | "MFA_SMS_AUTH" | "MFA_SMS_AUTH_SALES_PITCH" | "TWO_FA_REMOVE" | "USER_SETTINGS_ACCOUNT_REMOVAL_SECTION" | "USER_SETTINGS_ACCOUNT_REMOVAL_DESCRIPTION" | "DISABLE_ACCOUNT" | "DELETE_ACCOUNT" | "CLOSE" | "PREMIUM_BADGE_TOOLTIP" | "SELECT" | "REPLYING_TO" | "SUPER_REACTION_NITRO_TOOLTIP" | "YOURE_VIEWING_OLDER_MESSAGES" | "JUMP_TO_PRESENT" | "REACT_WITH_COUNT_A11Y_LABEL" | "SEARCH_NO_RESULTS" | "GUILD_SIDEBAR_CHANNEL_A11Y_LABEL_LIMIT" | "COPY_LINK" | "DELETE" | "GUILD_SIDEBAR_DEFAULT_CHANNEL_A11Y_LABEL_WITH_MENTIONS" | "NEW_MESSAGES" | "NEW_MESSAGES_PILL" | "JUMP_TO_LAST_UNREAD_MESSAGE" | "MARK_AS_READ", + "bg" | "cs" | "da" | "de" | "el" | "en" | "en-GB" | "en-US" | "es-419" | "es-ES" | "fi" | "fr" | "hi" | "hr" | "hu" | "it" | "ja" | "ko" | "lt" | "nl" | "no" | "pl" | "pt-BR" | "ro" | "ru" | "sv-SE" | "th" | "tr" | "uk" | "vi" | "zh-CN" | "zh-TW", string >; From 4cc6789b5b346ad91fefba7a2dc05245e06f6f84 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 8 May 2024 00:25:34 -0300 Subject: [PATCH 033/361] misc fixes --- src/api/Styles.ts | 4 ++-- src/plugins/fakeNitro/index.tsx | 1 - src/utils/lazy.ts | 2 +- src/webpack/webpack.tsx | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/api/Styles.ts b/src/api/Styles.ts index 6b0ac2cdf..023299c17 100644 --- a/src/api/Styles.ts +++ b/src/api/Styles.ts @@ -89,8 +89,8 @@ export const isStyleEnabled = (name: string) => requireStyle(name).dom?.isConnec * // -- plugin.ts -- * import pluginStyle from "./plugin.css?managed"; * import { setStyleVars } from "@api/Styles"; - * import { findByPropsLazy } from "@webpack"; - * const classNames = findByPropsLazy("thin", "scrollerBase"); // { thin: "thin-31rlnD scrollerBase-_bVAAt", ... } + * import { findByProps } from "@webpack"; + * const classNames = findByProps("thin", "scrollerBase"); // { thin: "thin-31rlnD scrollerBase-_bVAAt", ... } * * // Inside some plugin method like "start()" * setStyleClassNames(pluginStyle, classNames); diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index cf7f7adaf..43134d775 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -52,7 +52,6 @@ const PreloadedUserSettingsActionCreators = webpackDependantLazy(() => UserSetti const AppearanceSettingsActionCreators = webpackDependantLazy(() => searchProtoClassField("appearance", PreloadedUserSettingsActionCreators.ProtoClass)); const ClientThemeSettingsActionsCreators = webpackDependantLazy(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators)); - const enum EmojiIntentions { REACTION = 0, STATUS = 1, diff --git a/src/utils/lazy.ts b/src/utils/lazy.ts index 664d4e114..554649f18 100644 --- a/src/utils/lazy.ts +++ b/src/utils/lazy.ts @@ -91,7 +91,7 @@ export function proxyLazy(factory: () => T, attempts = 5, isChild = fal // If we're still in the same tick, it means the lazy was immediately used. // thus, we lazy proxy the get access to make things like destructuring work as expected // meow here will also be a lazy - // `const { meow } = findByPropsLazy("meow");` + // `const { meow } = proxyLazy(() => ({ meow: [] }));` if (!isChild && isSameTick) { return proxyLazy( () => Reflect.get(target[proxyLazyGet](), p, receiver), diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index 6c0222a0e..666f82a09 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -341,7 +341,7 @@ export function findStore(name: string) { * @param filter A function that takes a module and returns a boolean * @returns The found module or null */ -export const cacheFind = traceFunction("find", function find(filter: FilterFn) { +export const cacheFind = traceFunction("cacheFind", function cacheFind(filter: FilterFn) { if (typeof filter !== "function") throw new Error("Invalid filter. Expected a function got " + typeof filter); @@ -389,7 +389,7 @@ export function cacheFindAll(filter: FilterFn) { * need it afterwards, pass a copy. * @returns Array of results in the same order as the passed filters */ -export const cacheFindBulk = traceFunction("findBulk", function findBulk(...filterFns: FilterFn[]) { +export const cacheFindBulk = traceFunction("cacheFindBulk", function cacheFindBulk(...filterFns: FilterFn[]) { if (!Array.isArray(filterFns)) throw new Error("Invalid filters. Expected function[] got " + typeof filterFns); From fa948e863933ba3b839087c1bdc9ad60d91cd550 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 8 May 2024 04:48:48 -0300 Subject: [PATCH 034/361] Clean up all finds; Make common components NoopComponents by default I went through every single find and made sure every component find is using the proper method --- src/api/Notices.ts | 2 +- src/components/VencordSettings/ThemesTab.tsx | 4 +- src/plugins/anonymiseFileNames/index.tsx | 4 +- .../decor/ui/components/DecorSection.tsx | 4 +- src/plugins/decor/ui/components/index.ts | 5 ++- src/plugins/moreUserTags/index.tsx | 10 ++--- src/plugins/pauseInvitesForever/index.tsx | 5 +-- src/plugins/reviewDB/auth.tsx | 4 +- .../components/HiddenChannelLockScreen.tsx | 10 +---- .../components/VoiceChannelSection.tsx | 4 +- src/utils/modal.tsx | 12 +++--- src/webpack/common/components.ts | 40 ++++++++++--------- src/webpack/common/stores.ts | 2 +- src/webpack/common/types/components.d.ts | 7 ++++ src/webpack/common/utils.ts | 6 +-- 15 files changed, 61 insertions(+), 58 deletions(-) diff --git a/src/api/Notices.ts b/src/api/Notices.ts index 7652d55a6..b98063914 100644 --- a/src/api/Notices.ts +++ b/src/api/Notices.ts @@ -18,7 +18,7 @@ import { find } from "@webpack"; -const NoticesModule = find(m => m.show && m.dismiss && !m.suppressAll, m => m); +const NoticesModule = find(m => m.show && m.dismiss && !m.suppressAll); export const noticesQueue = [] as any[]; export let currentNotice: any = null; diff --git a/src/components/VencordSettings/ThemesTab.tsx b/src/components/VencordSettings/ThemesTab.tsx index 8c5943fcc..27e077fdc 100644 --- a/src/components/VencordSettings/ThemesTab.tsx +++ b/src/components/VencordSettings/ThemesTab.tsx @@ -29,7 +29,7 @@ import { classes } from "@utils/misc"; import { openModal } from "@utils/modal"; import { showItemInFolder } from "@utils/native"; import { useAwaiter } from "@utils/react"; -import { find, findComponent } from "@webpack"; +import { findByProps, findComponent } from "@webpack"; import { Button, Card, Forms, React, showToast, TabBar, TextArea, useEffect, useRef, useState } from "@webpack/common"; import type { Ref, SyntheticEvent } from "react"; @@ -44,7 +44,7 @@ type FileInputProps = { }; const FileInput = findComponent(m => m.prototype?.activateUploadDialogue && m.prototype.setRef); -const TextAreaProps = find(m => typeof m.textarea === "string"); +const TextAreaProps = findByProps("textarea"); const cl = classNameFactory("vc-settings-theme-"); diff --git a/src/plugins/anonymiseFileNames/index.tsx b/src/plugins/anonymiseFileNames/index.tsx index de8cb0fb2..93efa2491 100644 --- a/src/plugins/anonymiseFileNames/index.tsx +++ b/src/plugins/anonymiseFileNames/index.tsx @@ -21,11 +21,11 @@ import { definePluginSettings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByCode, findByProps } from "@webpack"; +import { findByProps, findComponentByCode } from "@webpack"; type AnonUpload = Upload & { anonymise?: boolean; }; -const ActionBarIcon = findByCode(".actionBarIcon)"); +const ActionBarIcon = findComponentByCode(".actionBarIcon)"); const UploadDraft = findByProps("popFirstFile", "update"); const enum Methods { diff --git a/src/plugins/decor/ui/components/DecorSection.tsx b/src/plugins/decor/ui/components/DecorSection.tsx index 8e454ea03..6be02f0b4 100644 --- a/src/plugins/decor/ui/components/DecorSection.tsx +++ b/src/plugins/decor/ui/components/DecorSection.tsx @@ -5,7 +5,7 @@ */ import { Flex } from "@components/Flex"; -import { findByCode } from "@webpack"; +import { findComponentByCode } from "@webpack"; import { Button, useEffect } from "@webpack/common"; import { useAuthorizationStore } from "../../lib/stores/AuthorizationStore"; @@ -13,7 +13,7 @@ import { useCurrentUserDecorationsStore } from "../../lib/stores/CurrentUserDeco import { cl } from "../"; import { openChangeDecorationModal } from "../modals/ChangeDecorationModal"; -const CustomizationSection = findByCode(".customizationSectionBackground"); +const CustomizationSection = findComponentByCode(".customizationSectionBackground"); interface DecorSectionProps { hideTitle?: boolean; diff --git a/src/plugins/decor/ui/components/index.ts b/src/plugins/decor/ui/components/index.ts index 8bc7f296d..be66fc6d4 100644 --- a/src/plugins/decor/ui/components/index.ts +++ b/src/plugins/decor/ui/components/index.ts @@ -4,6 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { NoopComponent } from "@utils/react"; import { filters, findComponent } from "@webpack"; import { React } from "@webpack/common"; import type { ComponentType, HTMLProps, PropsWithChildren } from "react"; @@ -15,7 +16,7 @@ type DecorationGridItemComponent = ComponentType; -export let DecorationGridItem: DecorationGridItemComponent; +export let DecorationGridItem: DecorationGridItemComponent = NoopComponent; export const setDecorationGridItem = v => DecorationGridItem = v; export const AvatarDecorationModalPreview = findComponent(filters.componentByCode(".shopPreviewBanner"), component => { @@ -28,5 +29,5 @@ type DecorationGridDecorationComponent = React.ComponentType; -export let DecorationGridDecoration: DecorationGridDecorationComponent; +export let DecorationGridDecoration: DecorationGridDecorationComponent = NoopComponent; export const setDecorationGridDecoration = v => DecorationGridDecoration = v; diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 762b09ce3..3728b4404 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -21,19 +21,17 @@ import { Flex } from "@components/Flex"; import { Devs } from "@utils/constants"; import { Margins } from "@utils/margins"; import definePlugin, { OptionType } from "@utils/types"; -import { find, findByProps } from "@webpack"; -import { Card, ChannelStore, Forms, GuildStore, PermissionsBits, Switch, TextInput, Tooltip, useState } from "@webpack/common"; +import { findByProps, findComponentByCode } from "@webpack"; +import { Card, ChannelStore, Forms, GuildStore, PermissionsBits, Switch, TextInput, Tooltip, useState, UtilTypes } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; -type PermissionName = "CREATE_INSTANT_INVITE" | "KICK_MEMBERS" | "BAN_MEMBERS" | "ADMINISTRATOR" | "MANAGE_CHANNELS" | "MANAGE_GUILD" | "CHANGE_NICKNAME" | "MANAGE_NICKNAMES" | "MANAGE_ROLES" | "MANAGE_WEBHOOKS" | "MANAGE_GUILD_EXPRESSIONS" | "CREATE_GUILD_EXPRESSIONS" | "VIEW_AUDIT_LOG" | "VIEW_CHANNEL" | "VIEW_GUILD_ANALYTICS" | "VIEW_CREATOR_MONETIZATION_ANALYTICS" | "MODERATE_MEMBERS" | "SEND_MESSAGES" | "SEND_TTS_MESSAGES" | "MANAGE_MESSAGES" | "EMBED_LINKS" | "ATTACH_FILES" | "READ_MESSAGE_HISTORY" | "MENTION_EVERYONE" | "USE_EXTERNAL_EMOJIS" | "ADD_REACTIONS" | "USE_APPLICATION_COMMANDS" | "MANAGE_THREADS" | "CREATE_PUBLIC_THREADS" | "CREATE_PRIVATE_THREADS" | "USE_EXTERNAL_STICKERS" | "SEND_MESSAGES_IN_THREADS" | "CONNECT" | "SPEAK" | "MUTE_MEMBERS" | "DEAFEN_MEMBERS" | "MOVE_MEMBERS" | "USE_VAD" | "PRIORITY_SPEAKER" | "STREAM" | "USE_EMBEDDED_ACTIVITIES" | "USE_SOUNDBOARD" | "USE_EXTERNAL_SOUNDS" | "REQUEST_TO_SPEAK" | "MANAGE_EVENTS" | "CREATE_EVENTS"; - interface Tag { // name used for identifying, must be alphanumeric + underscores name: string; // name shown on the tag itself, can be anything probably; automatically uppercase'd displayName: string; description: string; - permissions?: PermissionName[]; + permissions?: UtilTypes.Permissions[]; condition?(message: Message | null, user: User, channel: Channel): boolean; } @@ -57,7 +55,7 @@ const PermissionUtil = findByProps("computePermissions", "canEveryoneRole") as { computePermissions({ ...args }): bigint; }; -const Tag = find(m => m.Types?.[0] === "BOT") as React.ComponentType<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; +const Tag = findComponentByCode(".DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP,") as React.ComponentType<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot(); diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx index 74cbca7dc..5db8faf2f 100644 --- a/src/plugins/pauseInvitesForever/index.tsx +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -19,9 +19,8 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { findByProps } from "@webpack"; -import { GuildStore, RestAPI } from "@webpack/common"; +import { GuildStore, i18n, RestAPI } from "@webpack/common"; -const Messages = findByProps("GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION"); const { InvitesDisabledExperiment } = findByProps("InvitesDisabledExperiment"); export default definePlugin({ @@ -63,7 +62,7 @@ export default definePlugin({ renderInvitesLabel(guildId: string, setChecked: Function) { return (
- {Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} + {i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} {this.showDisableInvites(guildId) && { setChecked(true); this.disableInvites(guildId); diff --git a/src/plugins/reviewDB/auth.tsx b/src/plugins/reviewDB/auth.tsx index 7f3898b4e..6edc1c4b1 100644 --- a/src/plugins/reviewDB/auth.tsx +++ b/src/plugins/reviewDB/auth.tsx @@ -7,14 +7,14 @@ import { DataStore } from "@api/index"; import { Logger } from "@utils/Logger"; import { openModal } from "@utils/modal"; -import { findByProps } from "@webpack"; +import { findExportedComponent } from "@webpack"; import { showToast, Toasts, UserStore } from "@webpack/common"; import { ReviewDBAuth } from "./entities"; const DATA_STORE_KEY = "rdb-auth"; -const { OAuth2AuthorizeModal } = findByProps("OAuth2AuthorizeModal"); +const OAuth2AuthorizeModal = findExportedComponent("OAuth2AuthorizeModal"); export let Auth: ReviewDBAuth = {}; diff --git a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx index e0194b0e8..8cc19b48f 100644 --- a/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx +++ b/src/plugins/showHiddenChannels/components/HiddenChannelLockScreen.tsx @@ -19,7 +19,7 @@ import { Settings } from "@api/Settings"; import ErrorBoundary from "@components/ErrorBoundary"; import { formatDuration } from "@utils/text"; -import { findByProps, findComponent, findComponentByCode } from "@webpack"; +import { findByProps, findComponentByCode } from "@webpack"; import { EmojiStore, FluxDispatcher, GuildMemberStore, GuildStore, Parser, PermissionsBits, PermissionStore, SnowflakeUtils, Text, Timestamp, Tooltip, useEffect, useState } from "@webpack/common"; import type { Channel } from "discord-types/general"; @@ -81,13 +81,7 @@ const enum ChannelFlags { const ChatScrollClasses = findByProps("auto", "content", "scrollerBase"); const ChatClasses = findByProps("chat", "content", "noChat", "chatContent"); const ChannelBeginHeader = findComponentByCode(".Messages.ROLE_REQUIRED_SINGLE_USER_MESSAGE"); -const TagComponent = findComponent(m => { - if (typeof m !== "function") return false; - - const code = Function.prototype.toString.call(m); - // Get the component which doesn't include increasedActivity - return code.includes(".Messages.FORUM_TAG_A11Y_FILTER_BY_TAG") && !code.includes("increasedActivityPill"); -}); +const TagComponent = findComponentByCode(".Messages.FORUM_TAG_A11Y_FILTER_BY_TAG"); const EmojiParser = findByProps("convertSurrogateToName"); const EmojiUtils = findByProps("getURL", "getEmojiColors"); diff --git a/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx b/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx index 661a68320..ce428181a 100644 --- a/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx +++ b/src/plugins/userVoiceShow/components/VoiceChannelSection.tsx @@ -18,12 +18,12 @@ import "./VoiceChannelSection.css"; -import { findByCode, findByProps } from "@webpack"; +import { findByProps, findComponentByCode } from "@webpack"; import { Button, Forms, PermissionStore, Toasts } from "@webpack/common"; import { Channel } from "discord-types/general"; const ChannelActions = findByProps("selectChannel", "selectVoiceChannel"); -const UserPopoutSection = findByCode(".lastSection", "children:"); +const UserPopoutSection = findComponentByCode(".lastSection", "children:"); const CONNECT = 1n << 20n; diff --git a/src/utils/modal.tsx b/src/utils/modal.tsx index 3007b5c72..d98ca02df 100644 --- a/src/utils/modal.tsx +++ b/src/utils/modal.tsx @@ -19,6 +19,8 @@ import { filters, find, findByProps, findExportedComponent } from "@webpack"; import type { ComponentType, PropsWithChildren, ReactNode, Ref } from "react"; +import { NoopComponent } from "./react"; + export const enum ModalSize { SMALL = "small", MEDIUM = "medium", @@ -100,11 +102,11 @@ type Modals = { }; -export let ModalRoot: Modals["ModalRoot"]; -export let ModalHeader: Modals["ModalHeader"]; -export let ModalContent: Modals["ModalContent"]; -export let ModalFooter: Modals["ModalFooter"]; -export let ModalCloseButton: Modals["ModalCloseButton"]; +export let ModalRoot: Modals["ModalRoot"] = NoopComponent; +export let ModalHeader: Modals["ModalHeader"] = NoopComponent; +export let ModalContent: Modals["ModalContent"] = NoopComponent; +export let ModalFooter: Modals["ModalFooter"] = NoopComponent; +export let ModalCloseButton: Modals["ModalCloseButton"] = NoopComponent; export const Modals = find(filters.byProps("ModalRoot", "ModalCloseButton"), m => { ({ ModalRoot, ModalHeader, ModalContent, ModalFooter, ModalCloseButton } = m); diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index 94f5389bd..774fa29bb 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -16,30 +16,32 @@ * along with this program. If not, see . */ +import { NoopComponent } from "@utils/react"; + // eslint-disable-next-line path-alias/no-relative import { filters, find, findComponent, findExportedComponent } from "../webpack"; import * as t from "./types/components"; -export let Card: t.Card; -export let Button: t.Button; -export let Switch: t.Switch; -export let Tooltip: t.Tooltip; -export let TextInput: t.TextInput; -export let TextArea: t.TextArea; -export let Text: t.Text; -export let Heading: t.Heading; -export let Select: t.Select; -export let SearchableSelect: t.SearchableSelect; -export let Slider: t.Slider; +export let Card: t.Card = NoopComponent as any; +export let Button: t.Button = NoopComponent as any; +export let Switch: t.Switch = NoopComponent; +export let Tooltip: t.Tooltip = NoopComponent as any; +export let TextInput: t.TextInput = NoopComponent as any; +export let TextArea: t.TextArea = NoopComponent; +export let Text: t.Text = NoopComponent; +export let Heading: t.Heading = NoopComponent; +export let Select: t.Select = NoopComponent; +export let SearchableSelect: t.SearchableSelect = NoopComponent; +export let Slider: t.Slider = NoopComponent; export let ButtonLooks: t.ButtonLooks; -export let Popout: t.Popout; -export let Dialog: t.Dialog; -export let TabBar: any; -export let Paginator: t.Paginator; -export let ScrollerThin: t.ScrollerThin; -export let Clickable: t.Clickable; -export let Avatar: t.Avatar; -export let FocusLock: t.FocusLock; +export let Popout: t.Popout = NoopComponent as any; +export let Dialog: t.Dialog = NoopComponent; +export let TabBar: t.TabBar = NoopComponent as any; +export let Paginator: t.Paginator = NoopComponent; +export let ScrollerThin: t.ScrollerThin = NoopComponent; +export let Clickable: t.Clickable = NoopComponent; +export let Avatar: t.Avatar = NoopComponent; +export let FocusLock: t.FocusLock = NoopComponent; // token lagger real /** css colour resolver stuff, no clue what exactly this does, just copied usage from Discord */ export let useToken: t.useToken; diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 71c7989ef..ce1638b60 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -37,7 +37,7 @@ export const MessageStore = findStore("MessageStore") as Omit("PermissionStore"); export const GuildChannelStore = findStore("GuildChannelStore"); diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index c772c8994..e82851aa4 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -377,6 +377,13 @@ export type Popout = ComponentType<{ export type Dialog = ComponentType>; +export type TabBar = ComponentType> & { + Header: ComponentType>; + Item: ComponentType>; + Separator: ComponentType>; + Panel: ComponentType>; +}; + type Resolve = (data: { theme: "light" | "dark", saturation: number; }) => { hex(): string; hsl(): string; diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 8f18f1ed9..54b3637b5 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -35,7 +35,7 @@ export const FluxDispatcher = find(filters.byProps("dispatch", return m; }); -export const { ComponentDispatch } = findByProps("ComponentDispatch", "ComponentDispatcher"); +export const ComponentDispatch = find(filters.byProps("ComponentDispatch", "ComponentDispatcher"), m => m.ComponentDispatch); export const Constants = findByProps("Endpoints"); @@ -123,12 +123,12 @@ export const NavigationRouter = findByProps("transitionTo", export const SettingsRouter = findByProps("open", "saveAccountChanges"); -export const { Permissions: PermissionsBits } = find(m => typeof m.Permissions?.ADMINISTRATOR === "bigint") as { Permissions: t.PermissionsBits; }; +export const PermissionsBits = find(m => typeof m.Permissions?.ADMINISTRATOR === "bigint", m => m.Permissions); export const zustandCreate = findByCode("will be removed in v4"); const persistFilter = filters.byCode("[zustand persist middleware]"); -export const { persist: zustandPersist } = find(m => m.persist && persistFilter(m.persist)); +export const zustandPersist = find(m => m.persist && persistFilter(m.persist), m => m.persist); export const MessageActions = findByProps("editMessage", "sendMessage"); export const UserProfileActions = findByProps("openUserProfileModal", "closeUserProfileModal"); From f70cc5205c039c44c254d0afe5be473970c85cb4 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 8 May 2024 06:16:00 -0300 Subject: [PATCH 035/361] Reporter Bad Webpack Finds logs cleanups --- scripts/generateReport.ts | 16 ++++++++++++++-- src/webpack/webpack.tsx | 2 +- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 2d72d5df9..67b833c61 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -529,9 +529,21 @@ async function runtime(token: string) { parsedArgs === args && ["waitFor", "find", "findComponent", "webpackDependantLazy", "webpackDependantLazyComponent"].includes(searchType) ) { - logMessage += `(${parsedArgs[0].toString().slice(0, 147)}...)`; + let filter = parsedArgs[0].toString(); + if (filter.length > 150) { + filter = filter.slice(0, 147) + "..."; + } + + logMessage += `(${filter})`; } else if (searchType === "extractAndLoadChunks") { - logMessage += `([${parsedArgs[0].map((arg: any) => `"${arg}"`).join(", ")}], ${parsedArgs[1].toString()})`; + let regexStr: string; + if (parsedArgs[1] === Vencord.Webpack.DefaultExtractAndLoadChunksRegex) { + regexStr = "DefaultExtractAndLoadChunksRegex"; + } else { + regexStr = parsedArgs[1].toString(); + } + + logMessage += `([${parsedArgs[0].map((arg: any) => `"${arg}"`).join(", ")}], ${regexStr})`; } else { logMessage += `(${filterName.length ? `${filterName}(` : ""}${parsedArgs.map(arg => `"${arg}"`).join(", ")})${filterName.length ? ")" : ""}`; } diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index 666f82a09..d3a3577cb 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -614,7 +614,7 @@ export const findAll = deprecatedRedirect("findAll", "cacheFindAll", cacheFindAl */ export const findBulk = deprecatedRedirect("findBulk", "cacheFindBulk", cacheFindBulk); -const DefaultExtractAndLoadChunksRegex = /(?:Promise\.all\((\[\i\.\i\(".+?"\).+?\])\)|Promise\.resolve\(\)).then\(\i\.bind\(\i,"(.+?)"\)\)/; +export const DefaultExtractAndLoadChunksRegex = /(?:Promise\.all\((\[\i\.\i\(".+?"\).+?\])\)|Promise\.resolve\(\)).then\(\i\.bind\(\i,"(.+?)"\)\)/; /** * Extract and load chunks using their entry point. From 035e2add0b26c0d8cdd61c8450a37c992de805f7 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 8 May 2024 06:44:18 -0300 Subject: [PATCH 036/361] Fix MoreUserTags freezing the client --- src/plugins/moreUserTags/index.tsx | 17 ++++++------- src/utils/lazyReact.tsx | 8 +++++++ src/webpack/webpack.tsx | 38 ++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 3728b4404..b48f6ccfc 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -55,7 +55,8 @@ const PermissionUtil = findByProps("computePermissions", "canEveryoneRole") as { computePermissions({ ...args }): bigint; }; -const Tag = findComponentByCode(".DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP,") as React.ComponentType<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; +const Tag = findComponentByCode(".DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP,") as React.ComponentType<{ type?: number, className?: string, useRemSizes?: boolean; }>; +const { BotTagTypes } = findByProps("BotTagTypes"); const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot(); @@ -116,7 +117,7 @@ function SettingsComponent(props: { setValue(v: any): void; }) { onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} > - {t.displayName} Tag + {t.displayName} Tag
)} @@ -316,7 +317,7 @@ export default definePlugin({ return obj; }, - isOPTag: (tag: number) => tag === Tag.Types.ORIGINAL_POSTER || tags.some(t => tag === Tag.Types[`${t.name}-OP`]), + isOPTag: (tag: number) => tag === BotTagTypes.ORIGINAL_POSTER || tags.some(t => tag === BotTagTypes[`${t.name}-OP`]), getTagText(passedTagName: string, strings: Record) { if (!passedTagName) return strings.APP_TAG; @@ -349,9 +350,9 @@ export default definePlugin({ if (!user) return null; if (location === "chat" && user.id === "1") - return Tag.Types.OFFICIAL; + return BotTagTypes.OFFICIAL; if (user.isClyde()) - return Tag.Types.AI; + return BotTagTypes.AI; let type = typeof origType === "number" ? origType : null; @@ -370,11 +371,11 @@ export default definePlugin({ (tag.condition?.(message!, user, channel)) ) { if (channel.isForumPost() && channel.ownerId === user.id) - type = Tag.Types[`${tag.name}-OP`]; + type = BotTagTypes[`${tag.name}-OP`]; else if (user.bot && !isWebhook(message!, user) && !settings.dontShowBotTag) - type = Tag.Types[`${tag.name}-BOT`]; + type = BotTagTypes[`${tag.name}-BOT`]; else - type = Tag.Types[tag.name]; + type = BotTagTypes[tag.name]; break; } } diff --git a/src/utils/lazyReact.tsx b/src/utils/lazyReact.tsx index acc538ce1..719ce4262 100644 --- a/src/utils/lazyReact.tsx +++ b/src/utils/lazyReact.tsx @@ -8,6 +8,14 @@ import { makeLazy } from "./lazy"; /** * A lazy component. The factory method is called on first render. + * + * IMPORTANT: You cannot access properties set on the lazy component using this method. + * + * Example of how you cannot access the properties set on the component: + * ``` + * const Component = LazyComponent(...); + * console.log(Component.Types); // This will not work + * ```` * @param factory Function returning a component * @param attempts How many times to try to get the component before giving up * @returns Result of factory function diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index d3a3577cb..158faf348 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -182,6 +182,14 @@ export function find(filter: FilterFn, callback: (mod: any) => any = m /** * Find the first component that matches the filter. + * + * IMPORTANT: You cannot access properties set on the found component using this method. You should instead try to obtain the property using a non component find instead. + * + * Example of how you cannot access the properties set on the component: + * ``` + * const Component = findComponent(...); + * console.log(Component.Types); // This will not work + * ```` * @param filter A function that takes a module and returns a boolean * @param parse A function that takes the found component as its first argument and returns a component. Useful if you want to wrap the found component in something. Defaults to the original component * @returns The component if found, or a noop component @@ -226,6 +234,13 @@ export function findComponent(filter: FilterFn, parse: ( /** * Find the first component that is exported by the first prop name. * + * IMPORTANT: You cannot access properties set on the found component using this method. You should instead try to obtain the property using a non component find instead. + * + * Example of how you cannot access the properties set on the component: + * ``` + * const Component = findExportedComponent(...); + * console.log(Component.Types); // This will not work + * ```` * @example findExportedComponent("FriendRow") * @example findExportedComponent("FriendRow", "Friend", FriendRow => React.memo(FriendRow)) * @@ -271,6 +286,13 @@ export function findExportedComponent(...props: string[] /** * Find the first component in a default export that includes all the given code. * + * IMPORTANT: You cannot access properties set on the found component using this method. You should instead try to obtain the property using a non component find instead. + * + * Example of how you cannot access the properties set on the component: + * ``` + * const Component = findComponentByCode(...); + * console.log(Component.Types); // This will not work + * ```` * @example findComponentByCode(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR") * @example findComponentByCode(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)", ColorPicker => React.memo(ColorPicker)) * @@ -507,6 +529,14 @@ export function webpackDependantLazy(factory: () => any, attempts?: num * This is just a wrapper around {@link LazyComponent} to make our reporter test for your webpack finds. * * A lazy component. The factory method is called on first render. + * + * IMPORTANT: You cannot access properties set on the lazy component using this method. + * + * Example of how you cannot access the properties set on the component: + * ``` + * const Component = webpackDependantLazyComponent(...); + * console.log(Component.Types); // This will not work + * ```` * @param factory Function returning a Component * @param attempts How many times to try to get the component before giving up * @returns Result of factory function @@ -543,6 +573,14 @@ export const proxyLazyWebpack = deprecatedRedirect("proxyLazyWebpack", "webpackD * This is just a wrapper around {@link LazyComponent} to make our reporter test for your webpack finds. * * A lazy component. The factory method is called on first render. + * + * IMPORTANT: You cannot access properties set on the lazy component using this method. + * + * Example of how you cannot access the properties set on the component: + * ``` + * const Component = LazyComponentWebpack(...); + * console.log(Component.Types); // This will not work + * ```` * @param factory Function returning a Component * @param attempts How many times to try to get the component before giving up * @returns Result of factory function From b7c1b495af5e25bd139738f520d25b464156b070 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 8 May 2024 18:37:27 -0300 Subject: [PATCH 037/361] CrashHandler: Increment timeout for trying to recover --- src/plugins/crashHandler/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index f8c76d7f7..10053021f 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -104,7 +104,7 @@ export default definePlugin({ shouldAttemptRecover = false; // This is enough to avoid a crash loop - setTimeout(() => shouldAttemptRecover = true, 500); + setTimeout(() => shouldAttemptRecover = true, 1000); } catch { } try { From fb8f00137c8f4068249e5523e69de3abb9558a34 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Wed, 8 May 2024 18:51:47 -0300 Subject: [PATCH 038/361] I'm dumb --- src/plugins/betterSettings/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 5657b9809..39a57445a 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -134,7 +134,7 @@ export default definePlugin({ // not in children Layer(props: LayerProps) { try { - if (FocusLock === NoopComponent || FocusLock[proxyInnerValue] == null || ComponentDispatch[proxyInnerValue] == null) + if (FocusLock === NoopComponent || ComponentDispatch[proxyInnerValue] == null) throw new Error("Failed to fetch some webpack modules"); return Layer(props); From 546c5105b23557f0bcecfb5afe608d43fca768ce Mon Sep 17 00:00:00 2001 From: Vendicated Date: Thu, 9 May 2024 03:12:11 +0200 Subject: [PATCH 039/361] im the dumbest dumdum --- src/plugins/betterSettings/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index c9bf070fa..a4c739edb 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -133,6 +133,7 @@ export default definePlugin({ Layer(props: LayerProps) { if (!FocusLock || !ComponentDispatch) { new Logger("BetterSettings").error("Failed to find some components"); + return props.children; } return ; From bd88625d254376783fb27ab15d105dc5f35e9b24 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 9 May 2024 00:44:04 -0300 Subject: [PATCH 040/361] ErrorBoundary some more components --- src/plugins/betterNotes/index.tsx | 5 ++++- .../imageZoom/components/Magnifier.tsx | 5 +++-- src/plugins/mutualGroupDMs/index.tsx | 5 +++-- src/plugins/pauseInvitesForever/index.tsx | 20 ++++++++++--------- .../readAllNotificationsButton/index.tsx | 3 ++- src/plugins/showMeYourName/index.tsx | 11 +++++----- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/plugins/betterNotes/index.tsx b/src/plugins/betterNotes/index.tsx index 2183d98e2..5ebca1f8b 100644 --- a/src/plugins/betterNotes/index.tsx +++ b/src/plugins/betterNotes/index.tsx @@ -17,6 +17,7 @@ */ import { Settings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { canonicalizeMatch } from "@utils/patches"; import definePlugin, { OptionType } from "@utils/types"; @@ -83,7 +84,9 @@ export default definePlugin({ patchPadding(lastSection: any) { if (!lastSection) return; return ( -
+ +
+
); } }); diff --git a/src/plugins/imageZoom/components/Magnifier.tsx b/src/plugins/imageZoom/components/Magnifier.tsx index 816717350..aadd0903a 100644 --- a/src/plugins/imageZoom/components/Magnifier.tsx +++ b/src/plugins/imageZoom/components/Magnifier.tsx @@ -17,6 +17,7 @@ */ import { classNameFactory } from "@api/Styles"; +import ErrorBoundary from "@components/ErrorBoundary"; import { FluxDispatcher, React, useRef, useState } from "@webpack/common"; import { ELEMENT_ID } from "../constants"; @@ -36,7 +37,7 @@ export interface MagnifierProps { const cl = classNameFactory("vc-imgzoom-"); -export const Magnifier: React.FC = ({ instance, size: initialSize, zoom: initalZoom }) => { +export const Magnifier = ErrorBoundary.wrap(({ instance, size: initialSize, zoom: initalZoom }) => { const [ready, setReady] = useState(false); const [lensPosition, setLensPosition] = useState({ x: 0, y: 0 }); @@ -199,4 +200,4 @@ export const Magnifier: React.FC = ({ instance, size: initialSiz )}
); -}; +}, { noop: true }); diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index 1753fefbc..e787fefb4 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { isNonNullish } from "@utils/guards"; import definePlugin from "@utils/types"; @@ -60,7 +61,7 @@ export default definePlugin({ } ], - renderMutualGDMs(user: User, onClose: () => void) { + renderMutualGDMs: ErrorBoundary.wrap((user: User, onClose: () => void) => { const entries = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).map(c => ( ); - } + }) }); diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx index 81f18fd6e..1e71a4ed1 100644 --- a/src/plugins/pauseInvitesForever/index.tsx +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -16,12 +16,12 @@ * along with this program. If not, see . */ +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { GuildStore, RestAPI } from "@webpack/common"; +import { GuildStore, i18n, RestAPI } from "@webpack/common"; -const Messages = findByPropsLazy("GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION"); const { InvitesDisabledExperiment } = findByPropsLazy("InvitesDisabledExperiment"); export default definePlugin({ @@ -62,13 +62,15 @@ export default definePlugin({ renderInvitesLabel(guildId: string, setChecked: Function) { return ( - + +
+ {i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} + {this.showDisableInvites(guildId) && { + setChecked(true); + this.disableInvites(guildId); + }}> Pause Indefinitely.} +
+
); } }); diff --git a/src/plugins/readAllNotificationsButton/index.tsx b/src/plugins/readAllNotificationsButton/index.tsx index ae66e11a4..3bf53f993 100644 --- a/src/plugins/readAllNotificationsButton/index.tsx +++ b/src/plugins/readAllNotificationsButton/index.tsx @@ -19,6 +19,7 @@ import "./style.css"; import { addServerListElement, removeServerListElement, ServerListRenderPosition } from "@api/ServerList"; +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { Button, FluxDispatcher, GuildChannelStore, GuildStore, React, ReadStateStore } from "@webpack/common"; @@ -64,7 +65,7 @@ export default definePlugin({ authors: [Devs.kemo], dependencies: ["ServerListAPI"], - renderReadAllButton: () => , + renderReadAllButton: ErrorBoundary.wrap(ReadAllButton, { noop: true }), start() { addServerListElement(ServerListRenderPosition.Above, this.renderReadAllButton); diff --git a/src/plugins/showMeYourName/index.tsx b/src/plugins/showMeYourName/index.tsx index a9db1af9a..7908e5591 100644 --- a/src/plugins/showMeYourName/index.tsx +++ b/src/plugins/showMeYourName/index.tsx @@ -7,6 +7,7 @@ import "./styles.css"; import { definePluginSettings } from "@api/Settings"; +import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { Message, User } from "discord-types/general"; @@ -56,7 +57,7 @@ export default definePlugin({ ], settings, - renderUsername: ({ author, message, isRepliedMessage, withMentionPrefix, userOverride }: UsernameProps) => { + renderUsername: ErrorBoundary.wrap(({ author, message, isRepliedMessage, withMentionPrefix, userOverride }: UsernameProps) => { try { const user = userOverride ?? message.author; let { username } = user; @@ -66,14 +67,14 @@ export default definePlugin({ const { nick } = author; const prefix = withMentionPrefix ? "@" : ""; if (username === nick || isRepliedMessage && !settings.store.inReplies) - return prefix + nick; + return <>prefix + nick; if (settings.store.mode === "user-nick") return <>{prefix}{username} {nick}; if (settings.store.mode === "nick-user") return <>{prefix}{nick} {username}; - return prefix + username; + return <>prefix + username; } catch { - return author?.nick; + return <>author?.nick; } - }, + }, { noop: true }), }); From 33a5f30ae44104cb68561a50b8cb660f660c56a0 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Thu, 9 May 2024 02:59:08 -0300 Subject: [PATCH 041/361] ShowMeYourName: Fix regression caused by adding ErrorBoundary --- src/plugins/showMeYourName/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/showMeYourName/index.tsx b/src/plugins/showMeYourName/index.tsx index 7908e5591..7ba245da5 100644 --- a/src/plugins/showMeYourName/index.tsx +++ b/src/plugins/showMeYourName/index.tsx @@ -67,14 +67,14 @@ export default definePlugin({ const { nick } = author; const prefix = withMentionPrefix ? "@" : ""; if (username === nick || isRepliedMessage && !settings.store.inReplies) - return <>prefix + nick; + return <>{prefix}{nick}; if (settings.store.mode === "user-nick") return <>{prefix}{username} {nick}; if (settings.store.mode === "nick-user") return <>{prefix}{nick} {username}; - return <>prefix + username; + return <>{prefix}{username}; } catch { - return <>author?.nick; + return <>{author?.nick}; } }, { noop: true }), }); From b043d8abb749a92ecb652e0682d4723d0c70ecc5 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 11 May 2024 01:11:57 -0300 Subject: [PATCH 042/361] Clarify more what the find methods return --- scripts/generateReport.ts | 16 ++++++++-------- src/utils/lazy.ts | 17 ++++++++++++----- src/utils/proxyInner.ts | 13 ++++++++++--- src/utils/types.ts | 2 ++ src/webpack/webpack.tsx | 19 ++++++++++--------- 5 files changed, 42 insertions(+), 25 deletions(-) diff --git a/scripts/generateReport.ts b/scripts/generateReport.ts index 67b833c61..bb7ea9e7f 100644 --- a/scripts/generateReport.ts +++ b/scripts/generateReport.ts @@ -489,19 +489,19 @@ async function runtime(token: string) { result = module.toString().match(Vencord.Util.canonicalizeMatch(matcher)); } } else { - result = args.shift(); + const findResult = args.shift(); - if (result != null) { - if (result.$$vencordCallbackCalled != null && !result.$$vencordCallbackCalled()) { - result = null; + if (findResult != null) { + if (findResult.$$vencordCallbackCalled != null && findResult.$$vencordCallbackCalled()) { + result = findResult; } - if (result[Vencord.Util.proxyInnerGet] != null) { - result = result[Vencord.Util.proxyInnerValue]; + if (findResult[Vencord.Util.proxyInnerGet] != null) { + result = findResult[Vencord.Util.proxyInnerValue]; } - if (result.$$vencordInner != null) { - result = result.$$vencordInner(); + if (findResult.$$vencordInner != null) { + result = findResult.$$vencordInner(); } } } diff --git a/src/utils/lazy.ts b/src/utils/lazy.ts index 554649f18..582aa650c 100644 --- a/src/utils/lazy.ts +++ b/src/utils/lazy.ts @@ -4,6 +4,16 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { AnyObject } from "./types"; + +export type ProxyLazy = T & { + [proxyLazyGet]: () => T; + [proxyLazyCache]: T | undefined; +}; + +export const proxyLazyGet = Symbol.for("vencord.lazy.get"); +export const proxyLazyCache = Symbol.for("vencord.lazy.cached"); + export function makeLazy(factory: () => T, attempts = 5, { isIndirect = false }: { isIndirect?: boolean; } = {}): () => T { let tries = 0; let cache: T; @@ -49,9 +59,6 @@ const handler: ProxyHandler = { } }; -export const proxyLazyGet = Symbol.for("vencord.lazy.get"); -export const proxyLazyCache = Symbol.for("vencord.lazy.cached"); - /** * Wraps the result of factory in a Proxy you can consume as if it wasn't lazy. * On first property access, the factory is evaluated @@ -59,7 +66,7 @@ export const proxyLazyCache = Symbol.for("vencord.lazy.cached"); * @param attempts How many times to try to evaluate the factory before giving up * @returns Result of factory function */ -export function proxyLazy(factory: () => T, attempts = 5, isChild = false): T { +export function proxyLazy(factory: () => T, attempts = 5, isChild = false): ProxyLazy { const get = makeLazy(factory, attempts, { isIndirect: true }) as any; let isSameTick = true; @@ -107,5 +114,5 @@ export function proxyLazy(factory: () => T, attempts = 5, isChild = fal throw new Error("proxyLazy called on a primitive value. This can happen if you try to destructure a primitive at the same tick as the proxy was created."); } - }) as T; + }); } diff --git a/src/utils/proxyInner.ts b/src/utils/proxyInner.ts index 24018a1d6..f78aaf32f 100644 --- a/src/utils/proxyInner.ts +++ b/src/utils/proxyInner.ts @@ -4,6 +4,13 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { AnyObject } from "./types"; + +export type ProxyInner = T & { + [proxyInnerGet]?: () => T; + [proxyInnerValue]?: T | undefined; +}; + export const proxyInnerGet = Symbol.for("vencord.proxyInner.get"); export const proxyInnerValue = Symbol.for("vencord.proxyInner.innerValue"); @@ -39,11 +46,11 @@ const handler: ProxyHandler = { * @param primitiveErr The error message to throw when the inner value is a primitive * @returns A proxy which will act like the inner value when accessed */ -export function proxyInner( +export function proxyInner( errMsg = "Proxy inner value is undefined, setInnerValue was never called.", primitiveErrMsg = "proxyInner called on a primitive value. This can happen if you try to destructure a primitive at the same tick as the proxy was created.", isChild = false -): [proxy: T, setInnerValue: (innerValue: T) => void] { +): [proxy: ProxyInner, setInnerValue: (innerValue: T) => void] { let isSameTick = true; if (!isChild) setTimeout(() => isSameTick = false, 0); @@ -97,5 +104,5 @@ export function proxyInner( throw new Error(primitiveErrMsg); } - }) as T, setInnerValue]; + }), setInnerValue]; } diff --git a/src/utils/types.ts b/src/utils/types.ts index bec7cb0b3..e4401b31f 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -335,3 +335,5 @@ export type PluginNative Return extends Promise ? Return : Promise : never; }; + +export type AnyObject = Record & ((...args: any[]) => any); diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index 158faf348..5ea4e038a 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -8,7 +8,8 @@ import { proxyLazy } from "@utils/lazy"; import { LazyComponent } from "@utils/lazyReact"; import { Logger } from "@utils/Logger"; import { canonicalizeMatch } from "@utils/patches"; -import { proxyInner, proxyInnerValue } from "@utils/proxyInner"; +import { ProxyInner, proxyInner, proxyInnerValue } from "@utils/proxyInner"; +import { AnyObject } from "@utils/types"; import type { WebpackInstance } from "discord-types/other"; import { traceFunction } from "../debug/Tracer"; @@ -162,7 +163,7 @@ export function waitFor(filter: FilterFn, callback: ModCallbackFn, { isIndirect * @param callback A function that takes the found module as its first argument and returns something to use as the proxy inner value. Useful if you want to use a value from the module, instead of all of it. Defaults to the module itself * @returns A proxy that has the callback return value as its true value, or the callback return value if the callback was called when the function was called */ -export function find(filter: FilterFn, callback: (mod: any) => any = m => m, { isIndirect = false }: { isIndirect?: boolean; } = {}) { +export function find(filter: FilterFn, callback: (mod: any) => any = m => m, { isIndirect = false }: { isIndirect?: boolean; } = {}) { if (typeof filter !== "function") throw new Error("Invalid filter. Expected a function got " + typeof filter); if (typeof callback !== "function") @@ -175,7 +176,7 @@ export function find(filter: FilterFn, callback: (mod: any) => any = m webpackSearchHistory.push(["find", [proxy, filter]]); } - if (proxy[proxyInnerValue] != null) return proxy[proxyInnerValue] as T; + if (proxy[proxyInnerValue] != null) return proxy[proxyInnerValue] as ProxyInner; return proxy; } @@ -228,7 +229,7 @@ export function findComponent(filter: FilterFn, parse: ( if (InnerComponent !== null) return InnerComponent; - return WrapperComponent; + return WrapperComponent as React.ComponentType; } /** @@ -318,7 +319,7 @@ export function findComponentByCode(...code: string[] | * * @param props A list of props to search the exports for */ -export function findByProps(...props: string[]) { +export function findByProps(...props: string[]) { const result = find(filters.byProps(...props), m => m, { isIndirect: true }); if (IS_DEV) { @@ -333,7 +334,7 @@ export function findByProps(...props: string[]) { * * @param code A list of code to search each export for */ -export function findByCode(...code: string[]) { +export function findByCode(...code: string[]) { const result = find(filters.byCode(...code), m => m, { isIndirect: true }); if (IS_DEV) { @@ -348,7 +349,7 @@ export function findByCode(...code: string[]) { * * @param name The store name */ -export function findStore(name: string) { +export function findStore(name: string) { const result = find(filters.byStoreName(name), m => m, { isIndirect: true }); if (IS_DEV) { @@ -425,7 +426,7 @@ export const cacheFindBulk = traceFunction("cacheFindBulk", function cacheFindBu throw new Error("bulk called with only one filter. Use find"); } - return cacheFind(filterFns[0]); + return [cacheFind(filterFns[0])]; } let found = 0; @@ -519,7 +520,7 @@ export function findModuleFactory(...code: string[]) { * @param attempts How many times to try to evaluate the factory before giving up * @returns Result of factory function */ -export function webpackDependantLazy(factory: () => any, attempts?: number) { +export function webpackDependantLazy(factory: () => T, attempts?: number) { if (IS_DEV) webpackSearchHistory.push(["webpackDependantLazy", [factory]]); return proxyLazy(factory, attempts); From 5edff4a3c5605bfeaeff0023b2583cd22d28072d Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 11 May 2024 05:19:12 -0300 Subject: [PATCH 043/361] types --- src/utils/modal.tsx | 2 +- src/webpack/common/react.ts | 2 +- src/webpack/common/utils.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/modal.tsx b/src/utils/modal.tsx index d98ca02df..59e522c86 100644 --- a/src/utils/modal.tsx +++ b/src/utils/modal.tsx @@ -108,7 +108,7 @@ export let ModalContent: Modals["ModalContent"] = NoopComponent; export let ModalFooter: Modals["ModalFooter"] = NoopComponent; export let ModalCloseButton: Modals["ModalCloseButton"] = NoopComponent; -export const Modals = find(filters.byProps("ModalRoot", "ModalCloseButton"), m => { +export const Modals = find(filters.byProps("ModalRoot", "ModalCloseButton"), (m: Modals) => { ({ ModalRoot, ModalHeader, ModalContent, ModalFooter, ModalCloseButton } = m); return m; diff --git a/src/webpack/common/react.ts b/src/webpack/common/react.ts index 4a66c4817..6109290ec 100644 --- a/src/webpack/common/react.ts +++ b/src/webpack/common/react.ts @@ -28,7 +28,7 @@ export let useCallback: typeof React.useCallback; export const ReactDOM = findByProps("createPortal", "render"); -export const React = find(filters.byProps("useState"), m => { +export const React = find(filters.byProps("useState"), (m: typeof import("react")) => { ({ useEffect, useState, useMemo, useRef, useReducer, useCallback } = m); return m; diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 54b3637b5..6b78ace91 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -22,7 +22,7 @@ import type { Channel, User } from "discord-types/general"; import { _resolveReady, filters, find, findByCode, findByProps, waitFor } from "../webpack"; import type * as t from "./types/utils"; -export const FluxDispatcher = find(filters.byProps("dispatch", "subscribe"), m => { +export const FluxDispatcher = find(filters.byProps("dispatch", "subscribe"), (m: t.FluxDispatcher) => { // Non import call to avoid circular dependency Vencord.Plugins.subscribeAllPluginsFluxEvents(m); From 1b64419ef1405492a353e01c46400f834749c0f8 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 11 May 2024 05:44:52 -0300 Subject: [PATCH 044/361] Make commons have proper ProxyInner typing --- src/webpack/common/components.ts | 11 ++--------- src/webpack/common/stores.ts | 20 ++++++-------------- src/webpack/common/types/components.d.ts | 7 +++++++ src/webpack/common/types/stores.d.ts | 15 +++++++++++++++ src/webpack/common/types/utils.d.ts | 15 ++++++++++++++- src/webpack/common/utils.ts | 12 +++--------- 6 files changed, 47 insertions(+), 33 deletions(-) diff --git a/src/webpack/common/components.ts b/src/webpack/common/components.ts index 774fa29bb..adb5a9974 100644 --- a/src/webpack/common/components.ts +++ b/src/webpack/common/components.ts @@ -42,8 +42,6 @@ export let ScrollerThin: t.ScrollerThin = NoopComponent; export let Clickable: t.Clickable = NoopComponent; export let Avatar: t.Avatar = NoopComponent; export let FocusLock: t.FocusLock = NoopComponent; -// token lagger real -/** css colour resolver stuff, no clue what exactly this does, just copied usage from Discord */ export let useToken: t.useToken; export const MaskedLink = findComponent(filters.componentByCode("MASKED_LINK)")); @@ -52,7 +50,7 @@ export const Flex = findComponent(filters.byProps("Justify", "Align export const OAuth2AuthorizeModal = findExportedComponent("OAuth2AuthorizeModal"); -export const Forms = find(filters.byProps("FormItem", "Button"), m => { +export const Forms = find(filters.byProps("FormItem", "Button"), m => { ({ useToken, Card, @@ -78,9 +76,4 @@ export const Forms = find(filters.byProps("FormItem", "Button"), m => { } = m); return m; -}) as { - FormTitle: t.FormTitle, - FormSection: t.FormSection, - FormDivider: t.FormDivider, - FormText: t.FormText, -}; +}); diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index ce1638b60..311d1c66e 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -16,8 +16,6 @@ * along with this program. If not, see . */ -import type * as Stores from "discord-types/stores"; - // eslint-disable-next-line path-alias/no-relative import { filters, find, findByProps, findStore } from "../webpack"; import * as t from "./types/stores"; @@ -33,28 +31,22 @@ export enum DraftType { ApplicationLauncherCommand = 3 } -export const MessageStore = findStore("MessageStore") as Omit & { - getMessages(chanId: string): any; -}; - // This is not actually a FluxStore export const PrivateChannelsStore = findByProps("openPrivateChannel"); export const PermissionStore = findStore("PermissionStore"); export const GuildChannelStore = findStore("GuildChannelStore"); export const ReadStateStore = findStore("ReadStateStore"); export const PresenceStore = findStore("PresenceStore"); +export const MessageStore = findStore("MessageStore"); export const GuildStore = findStore("GuildStore"); -export const UserStore = findStore("UserStore"); +export const UserStore = findStore("UserStore"); export const UserProfileStore = findStore("UserProfileStore"); -export const SelectedChannelStore = findStore("SelectedChannelStore"); +export const SelectedChannelStore = findStore("SelectedChannelStore"); export const SelectedGuildStore = findStore("SelectedGuildStore"); -export const ChannelStore = findStore("ChannelStore"); -export const GuildMemberStore = findStore("GuildMemberStore"); -export const RelationshipStore = findStore("RelationshipStore") as Stores.RelationshipStore & t.FluxStore & { - /** Get the date (as a string) that the relationship was created */ - getSince(userId: string): string; -}; +export const ChannelStore = findStore("ChannelStore"); +export const GuildMemberStore = findStore("GuildMemberStore"); +export const RelationshipStore = findStore("RelationshipStore"); export const EmojiStore = findStore("EmojiStore"); export const WindowStore = findStore("WindowStore"); diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index e82851aa4..1fcdddd0a 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -68,6 +68,13 @@ export type FormText = ComponentType & TextProps> & { Types: FormTextTypes; }; +type Forms = { + FormTitle: t.FormTitle, + FormSection: t.FormSection, + FormDivider: t.FormDivider, + FormText: t.FormText, +}; + export type Tooltip = ComponentType<{ text: ReactNode; children: FunctionComponent<{ diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index 8fcff338a..5095eb004 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -18,6 +18,7 @@ import { DraftType } from "@webpack/common"; import { Channel, Guild, Role } from "discord-types/general"; +import type * as Stores from "discord-types/stores"; import { FluxDispatcher, FluxEvents } from "./utils"; @@ -183,6 +184,20 @@ export class GuildStore extends FluxStore { getAllGuildRoles(): Record>; } +type MessageStore = t.FluxStore & Omit & { + getMessages(channelId: string): any; +}; + +type UserStore = t.FluxStore & Stores.UserStore; +type SelectedChannelStore = t.FluxStore & Stores.SelectedChannelStore; +type ChannelStore = t.FluxStore & Stores.ChannelStore; +type GuildMemberStore = t.FluxStore & Stores.GuildMemberStore; + +type RelationshipStore = t.FluxStore & Stores.RelationshipStore & { + /** Get the date (as a string) that the relationship was created */ + getSince(userId: string): string; +}; + export type useStateFromStores = ( stores: t.FluxStore[], mapper: () => T, diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts index 16fe6e2dd..03317131d 100644 --- a/src/webpack/common/types/utils.d.ts +++ b/src/webpack/common/types/utils.d.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Guild, GuildMember } from "discord-types/general"; +import { Channel, Guild, GuildMember, User } from "discord-types/general"; import type { ReactNode } from "react"; import type { FluxEvents } from "./fluxEvents"; @@ -227,3 +227,16 @@ export interface IconUtils { getApplicationIconSource: any; getAnimatableSourceWithFallback: any; } + +export interface UserUtils { + getUser: (id: string) => Promise; +} + +export interface UploadHandler { + promptToUpload: (files: File[], channel: Channel, draftType: Number) => void; +} + +export interface ApplicationAssetUtils { + fetchAssetIds: (applicationId: string, e: string[]) => Promise; +} + diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index 6b78ace91..f8340e2b1 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -16,8 +16,6 @@ * along with this program. If not, see . */ -import type { Channel, User } from "discord-types/general"; - // eslint-disable-next-line path-alias/no-relative import { _resolveReady, filters, find, findByCode, findByProps, waitFor } from "../webpack"; import type * as t from "./types/utils"; @@ -108,14 +106,10 @@ export function showToast(message: string, type = ToastType.MESSAGE) { }); } -export const UserUtils = findByProps("getUser", "fetchCurrentUser") as { getUser: (id: string) => Promise; }; -export const UploadHandler = findByProps("showUploadFileSizeExceededError", "promptToUpload") as { - promptToUpload: (files: File[], channel: Channel, draftType: Number) => void; -}; +export const UserUtils = findByProps("getUser", "fetchCurrentUser"); +export const UploadHandler = findByProps("showUploadFileSizeExceededError", "promptToUpload"); -export const ApplicationAssetUtils = findByProps("fetchAssetIds", "getAssetImage") as { - fetchAssetIds: (applicationId: string, e: string[]) => Promise; -}; +export const ApplicationAssetUtils = findByProps("fetchAssetIds", "getAssetImage"); export const Clipboard = findByProps("SUPPORTS_COPY", "copy"); From 09a6a9bf859e7d98febd9208a647b37e57691236 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 11 May 2024 05:47:53 -0300 Subject: [PATCH 045/361] wtf? --- src/webpack/common/types/components.d.ts | 2 +- src/webpack/common/types/stores.d.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/webpack/common/types/components.d.ts b/src/webpack/common/types/components.d.ts index 1fcdddd0a..c27168749 100644 --- a/src/webpack/common/types/components.d.ts +++ b/src/webpack/common/types/components.d.ts @@ -68,7 +68,7 @@ export type FormText = ComponentType & TextProps> & { Types: FormTextTypes; }; -type Forms = { +export type Forms = { FormTitle: t.FormTitle, FormSection: t.FormSection, FormDivider: t.FormDivider, diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index 5095eb004..146386d2e 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -184,14 +184,14 @@ export class GuildStore extends FluxStore { getAllGuildRoles(): Record>; } -type MessageStore = t.FluxStore & Omit & { +export type MessageStore = t.FluxStore & Omit & { getMessages(channelId: string): any; }; -type UserStore = t.FluxStore & Stores.UserStore; -type SelectedChannelStore = t.FluxStore & Stores.SelectedChannelStore; -type ChannelStore = t.FluxStore & Stores.ChannelStore; -type GuildMemberStore = t.FluxStore & Stores.GuildMemberStore; +export type UserStore = t.FluxStore & Stores.UserStore; +export type SelectedChannelStore = t.FluxStore & Stores.SelectedChannelStore; +export type ChannelStore = t.FluxStore & Stores.ChannelStore; +export type GuildMemberStore = t.FluxStore & Stores.GuildMemberStore; type RelationshipStore = t.FluxStore & Stores.RelationshipStore & { /** Get the date (as a string) that the relationship was created */ From e11d651e33c0c0a391f2c2f0e6e23259e4a6a51d Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 11 May 2024 05:51:18 -0300 Subject: [PATCH 046/361] work --- src/webpack/common/types/stores.d.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index 146386d2e..47816a380 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -184,22 +184,22 @@ export class GuildStore extends FluxStore { getAllGuildRoles(): Record>; } -export type MessageStore = t.FluxStore & Omit & { +export type MessageStore = FluxStore & Omit & { getMessages(channelId: string): any; }; -export type UserStore = t.FluxStore & Stores.UserStore; -export type SelectedChannelStore = t.FluxStore & Stores.SelectedChannelStore; -export type ChannelStore = t.FluxStore & Stores.ChannelStore; -export type GuildMemberStore = t.FluxStore & Stores.GuildMemberStore; +export type UserStore = FluxStore & Stores.UserStore; +export type SelectedChannelStore = FluxStore & Stores.SelectedChannelStore; +export type ChannelStore = FluxStore & Stores.ChannelStore; +export type GuildMemberStore = FluxStore & Stores.GuildMemberStore; -type RelationshipStore = t.FluxStore & Stores.RelationshipStore & { +export type RelationshipStore = FluxStore & Stores.RelationshipStore & { /** Get the date (as a string) that the relationship was created */ getSince(userId: string): string; }; export type useStateFromStores = ( - stores: t.FluxStore[], + stores: FluxStore[], mapper: () => T, dependencies?: any[] | null, isEqual?: (old: T, newer: T) => boolean From 5676f45781666e7db6fd5c0ca77a29c385111bd0 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 11 May 2024 05:56:26 -0300 Subject: [PATCH 047/361] whatever --- src/webpack/common/types/stores.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index 47816a380..4aa3bedf1 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -199,7 +199,7 @@ export type RelationshipStore = FluxStore & Stores.RelationshipStore & { }; export type useStateFromStores = ( - stores: FluxStore[], + stores: any[], mapper: () => T, dependencies?: any[] | null, isEqual?: (old: T, newer: T) => boolean From f6e484034c64033d9af3ac7c3eec157757fe3df4 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Sat, 11 May 2024 06:05:20 -0300 Subject: [PATCH 048/361] more pog --- src/webpack/common/types/stores.d.ts | 3 +-- src/webpack/webpack.tsx | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index 4aa3bedf1..ec52d1627 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -39,7 +39,6 @@ export class FluxStore { registerActionHandlers: GenericFunction; syncWith: GenericFunction; waitFor: GenericFunction; - __getLocalVars(): Record; } export interface Flux { @@ -199,7 +198,7 @@ export type RelationshipStore = FluxStore & Stores.RelationshipStore & { }; export type useStateFromStores = ( - stores: any[], + stores: FluxStore[], mapper: () => T, dependencies?: any[] | null, isEqual?: (old: T, newer: T) => boolean diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index 5ea4e038a..0000ce6c1 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -13,6 +13,7 @@ import { AnyObject } from "@utils/types"; import type { WebpackInstance } from "discord-types/other"; import { traceFunction } from "../debug/Tracer"; +import { GenericStore } from "./common"; const logger = new Logger("Webpack"); @@ -349,7 +350,7 @@ export function findByCode(...code: string[]) { * * @param name The store name */ -export function findStore(name: string) { +export function findStore(name: string) { const result = find(filters.byStoreName(name), m => m, { isIndirect: true }); if (IS_DEV) { From 7d91dea822e3b09769cafc59c215c9c0ba17284c Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Mon, 13 May 2024 23:15:16 -0300 Subject: [PATCH 049/361] Merge branch 'dev' into immediate-finds --- src/plugins/betterNotes/index.tsx | 12 ++- src/plugins/betterSessions/index.tsx | 4 +- src/plugins/emoteCloner/index.tsx | 11 +-- src/plugins/fakeNitro/index.tsx | 13 ++++ src/plugins/friendInvites/index.ts | 4 +- src/plugins/invisibleChat.desktop/index.tsx | 4 +- src/plugins/messageLinkEmbeds/index.tsx | 3 +- .../messageLogger/deleteStyleOverlay.css | 2 +- src/plugins/messageLogger/deleteStyleText.css | 8 +- src/plugins/mutualGroupDMs/index.tsx | 4 +- src/plugins/pauseInvitesForever/index.tsx | 73 ++++++++++--------- src/plugins/unsuppressEmbeds/index.tsx | 4 +- src/plugins/validUser/index.tsx | 2 +- src/plugins/voiceMessages/index.tsx | 4 +- src/plugins/whoReacted/index.tsx | 4 +- src/utils/constants.ts | 4 + src/utils/discord.tsx | 4 +- 17 files changed, 89 insertions(+), 71 deletions(-) diff --git a/src/plugins/betterNotes/index.tsx b/src/plugins/betterNotes/index.tsx index c83994869..6309146c6 100644 --- a/src/plugins/betterNotes/index.tsx +++ b/src/plugins/betterNotes/index.tsx @@ -61,7 +61,7 @@ export default definePlugin({ find: ".popularApplicationCommandIds,", replacement: { match: /lastSection:(!?\i)}\),/, - replace: "$&$self.patchPadding($1)," + replace: "$&$self.patchPadding({lastSection:$1})," } } ], @@ -81,12 +81,10 @@ export default definePlugin({ } }, - patchPadding(lastSection: any) { - if (!lastSection) return; + patchPadding: ErrorBoundary.wrap(({ lastSection }) => { + if (!lastSection) return null; return ( - -
-
+
); - } + }) }); diff --git a/src/plugins/betterSessions/index.tsx b/src/plugins/betterSessions/index.tsx index 7fdaff971..4692872a0 100644 --- a/src/plugins/betterSessions/index.tsx +++ b/src/plugins/betterSessions/index.tsx @@ -22,7 +22,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByProps, findExportedComponent, findStore } from "@webpack"; -import { React, RestAPI, Tooltip } from "@webpack/common"; +import { Constants, React, RestAPI, Tooltip } from "@webpack/common"; import { RenameButton } from "./components/RenameButton"; import { Session, SessionInfo } from "./types"; @@ -168,7 +168,7 @@ export default definePlugin({ async checkNewSessions() { const data = await RestAPI.get({ - url: "/auth/sessions" + url: Constants.Endpoints.AUTH_SESSIONS }); for (const session of data.body.user_sessions) { diff --git a/src/plugins/emoteCloner/index.tsx b/src/plugins/emoteCloner/index.tsx index 2c95317b2..4321b8146 100644 --- a/src/plugins/emoteCloner/index.tsx +++ b/src/plugins/emoteCloner/index.tsx @@ -24,7 +24,7 @@ import { Margins } from "@utils/margins"; import { ModalContent, ModalHeader, ModalRoot, openModalLazy } from "@utils/modal"; import definePlugin from "@utils/types"; import { findByProps, findStore } from "@webpack"; -import { EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, Toasts, Tooltip, UserStore } from "@webpack/common"; +import { Constants, EmojiStore, FluxDispatcher, Forms, GuildStore, Menu, PermissionsBits, PermissionStore, React, RestAPI, Toasts, Tooltip, UserStore } from "@webpack/common"; import { Promisable } from "type-fest"; const StickersStore = findStore("StickersStore"); @@ -64,7 +64,7 @@ async function fetchSticker(id: string) { if (cached) return cached; const { body } = await RestAPI.get({ - url: `/stickers/${id}` + url: Constants.Endpoints.STICKER(id) }); FluxDispatcher.dispatch({ @@ -83,7 +83,7 @@ async function cloneSticker(guildId: string, sticker: Sticker) { data.append("file", await fetchBlob(getUrl(sticker))); const { body } = await RestAPI.post({ - url: `/guilds/${guildId}/stickers`, + url: Constants.Endpoints.GUILD_STICKER_PACKS(guildId), body: data, }); @@ -322,8 +322,9 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, props) = switch (favoriteableType) { case "emoji": const match = props.message.content.match(RegExp(`|https://cdn\\.discordapp\\.com/emojis/${favoriteableId}\\.`)); - if (!match) return; - const name = match[1] ?? "FakeNitroEmoji"; + const reaction = props.message.reactions.find(reaction => reaction.emoji.id === favoriteableId); + if (!match && !reaction) return; + const name = (match && match[1]) ?? reaction?.emoji.name ?? "FakeNitroEmoji"; return buildMenuItem("Emoji", () => ({ id: favoriteableId, diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 829b046fd..112c18ace 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -39,6 +39,7 @@ const StickerStore = findStore("StickersStore") as { const UserSettingsProtoStore = findStore("UserSettingsProtoStore"); const ProtoUtils = findByProps("BINARY_READ_OPTIONS"); +const RoleSubscriptionEmojiUtils = findByProps("isUnusableRoleSubscriptionEmoji"); function searchProtoClassField(localName: string, protoClass: any) { const field = protoClass?.fields?.find((field: any) => field.localName === localName); @@ -407,6 +408,15 @@ export default definePlugin({ match: /canUseCustomNotificationSounds:function\(\i\){/, replace: "$&return true;" } + }, + // Allows the usage of subscription-locked emojis + { + find: "isUnusableRoleSubscriptionEmoji:function", + replacement: { + match: /isUnusableRoleSubscriptionEmoji:function/, + // replace the original export with a func that always returns false and alias the original + replace: "isUnusableRoleSubscriptionEmoji:()=>()=>false,isUnusableRoleSubscriptionEmojiOriginal:function" + } } ], @@ -803,6 +813,9 @@ export default definePlugin({ if (e.require_colons === false) return true; if (e.available === false) return false; + const isUnusableRoleSubEmoji = RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmojiOriginal ?? RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmoji; + if (isUnusableRoleSubEmoji(e, this.guildId)) return false; + if (this.canUseEmotes) return e.guildId === this.guildId || hasExternalEmojiPerms(channelId); else diff --git a/src/plugins/friendInvites/index.ts b/src/plugins/friendInvites/index.ts index eb293b663..41755cca7 100644 --- a/src/plugins/friendInvites/index.ts +++ b/src/plugins/friendInvites/index.ts @@ -20,7 +20,7 @@ import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { findByProps } from "@webpack"; -import { RestAPI, UserStore } from "@webpack/common"; +import { Constants, RestAPI, UserStore } from "@webpack/common"; const FriendInvites = findByProps("createFriendInvite"); const { uuid4 } = findByProps("uuid4"); @@ -58,7 +58,7 @@ export default definePlugin({ if (uses === 1) { const random = uuid4(); const { body: { invite_suggestions } } = await RestAPI.post({ - url: "/friend-finder/find-friends", + url: Constants.Endpoints.FRIEND_FINDER, body: { modified_contacts: { [random]: [1, "", ""] diff --git a/src/plugins/invisibleChat.desktop/index.tsx b/src/plugins/invisibleChat.desktop/index.tsx index fcb0af712..3dfe51e77 100644 --- a/src/plugins/invisibleChat.desktop/index.tsx +++ b/src/plugins/invisibleChat.desktop/index.tsx @@ -23,7 +23,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getStegCloak } from "@utils/dependencies"; import definePlugin, { OptionType } from "@utils/types"; -import { ChannelStore, FluxDispatcher, RestAPI, Tooltip } from "@webpack/common"; +import { ChannelStore, Constants, FluxDispatcher, RestAPI, Tooltip } from "@webpack/common"; import { Message } from "discord-types/general"; import { buildDecModal } from "./components/DecryptionModal"; @@ -153,7 +153,7 @@ export default definePlugin({ // Gets the Embed of a Link async getEmbed(url: URL): Promise { const { body } = await RestAPI.post({ - url: "/unfurler/embed-urls", + url: Constants.Endpoints.UNFURL_EMBED_URLS, body: { urls: [url] } diff --git a/src/plugins/messageLinkEmbeds/index.tsx b/src/plugins/messageLinkEmbeds/index.tsx index 2d525bd34..e4f334528 100644 --- a/src/plugins/messageLinkEmbeds/index.tsx +++ b/src/plugins/messageLinkEmbeds/index.tsx @@ -27,6 +27,7 @@ import { findByProps, findComponentByCode } from "@webpack"; import { Button, ChannelStore, + Constants, FluxDispatcher, GuildStore, IconUtils, @@ -132,7 +133,7 @@ async function fetchMessage(channelID: string, messageID: string) { messageCache.set(messageID, { fetched: false }); const res = await RestAPI.get({ - url: `/channels/${channelID}/messages`, + url: Constants.Endpoints.MESSAGES(channelID), query: { limit: 1, around: messageID diff --git a/src/plugins/messageLogger/deleteStyleOverlay.css b/src/plugins/messageLogger/deleteStyleOverlay.css index 3778e80b3..59e4ac666 100644 --- a/src/plugins/messageLogger/deleteStyleOverlay.css +++ b/src/plugins/messageLogger/deleteStyleOverlay.css @@ -1,3 +1,3 @@ .messagelogger-deleted { - background-color: rgba(240 71 71 / 15%) !important; + background-color: hsla(var(--red-430-hsl, 0 85% 61%) / 15%) !important; } diff --git a/src/plugins/messageLogger/deleteStyleText.css b/src/plugins/messageLogger/deleteStyleText.css index 8fb8bf129..3477ef229 100644 --- a/src/plugins/messageLogger/deleteStyleText.css +++ b/src/plugins/messageLogger/deleteStyleText.css @@ -1,19 +1,19 @@ /* Message content highlighting */ .messagelogger-deleted [class*="contents"] > :is(div, h1, h2, h3, p) { - color: #f04747 !important; + color: var(--status-danger, #f04747) !important; } /* Bot "thinking" text highlighting */ .messagelogger-deleted [class*="colorStandard"] { - color: #f04747 !important; + color: var(--status-danger, #f04747) !important; } /* Embed highlighting */ .messagelogger-deleted article :is(div, span, h1, h2, h3, p) { - color: #f04747 !important; + color: var(--status-danger, #f04747) !important; } .messagelogger-deleted a { - color: #be3535 !important; + color: var(--red-460, #be3535) !important; text-decoration: underline; } diff --git a/src/plugins/mutualGroupDMs/index.tsx b/src/plugins/mutualGroupDMs/index.tsx index df4deaa49..31f7ea273 100644 --- a/src/plugins/mutualGroupDMs/index.tsx +++ b/src/plugins/mutualGroupDMs/index.tsx @@ -56,12 +56,12 @@ export default definePlugin({ find: ".UserProfileSections.USER_INFO_CONNECTIONS:", replacement: { match: /(?<={user:(\i),onClose:(\i)}\);)(?=case \i\.\i\.MUTUAL_FRIENDS)/, - replace: "case \"MUTUAL_GDMS\":return $self.renderMutualGDMs($1,$2);" + replace: "case \"MUTUAL_GDMS\":return $self.renderMutualGDMs({user: $1, onClose: $2});" } } ], - renderMutualGDMs: ErrorBoundary.wrap((user: User, onClose: () => void) => { + renderMutualGDMs: ErrorBoundary.wrap(({ user, onClose }: { user: User, onClose: () => void; }) => { const entries = ChannelStore.getSortedPrivateChannels().filter(c => c.isGroupDM() && c.recipients.includes(user.id)).map(c => ( { return ( - -
- {i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} - {this.showDisableInvites(guildId) && { - setChecked(true); - this.disableInvites(guildId); - }}> Pause Indefinitely.} -
-
+
+ {i18n.Messages.GUILD_INVITE_DISABLE_ACTION_SHEET_DESCRIPTION} + {showDisableInvites(guildId) && { + setChecked(true); + disableInvites(guildId); + }}> Pause Indefinitely.} +
); - } + }) }); diff --git a/src/plugins/unsuppressEmbeds/index.tsx b/src/plugins/unsuppressEmbeds/index.tsx index 0e87201c6..16debf711 100644 --- a/src/plugins/unsuppressEmbeds/index.tsx +++ b/src/plugins/unsuppressEmbeds/index.tsx @@ -20,7 +20,7 @@ import { findGroupChildrenByChildId, NavContextMenuPatchCallback } from "@api/Co import { ImageInvisible, ImageVisible } from "@components/Icons"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { Menu, PermissionsBits, PermissionStore, RestAPI, UserStore } from "@webpack/common"; +import { Constants, Menu, PermissionsBits, PermissionStore, RestAPI, UserStore } from "@webpack/common"; const EMBED_SUPPRESSED = 1 << 2; @@ -44,7 +44,7 @@ const messageContextMenuPatch: NavContextMenuPatchCallback = (children, { channe icon={isEmbedSuppressed ? ImageVisible : ImageInvisible} action={() => RestAPI.patch({ - url: `/channels/${channel.id}/messages/${messageId}`, + url: Constants.Endpoints.MESSAGE(channel.id, messageId), body: { flags: isEmbedSuppressed ? flags & ~EMBED_SUPPRESSED : flags | EMBED_SUPPRESSED } }) } diff --git a/src/plugins/validUser/index.tsx b/src/plugins/validUser/index.tsx index 64b734f53..4825cdaa3 100644 --- a/src/plugins/validUser/index.tsx +++ b/src/plugins/validUser/index.tsx @@ -75,7 +75,7 @@ async function getUser(id: string) { if (userObj) return userObj; - const user: any = await RestAPI.get({ url: `/users/${id}` }).then(response => { + const user: any = await RestAPI.get({ url: Constants.Endpoints.USER(id) }).then(response => { FluxDispatcher.dispatch({ type: "USER_UPDATE", user: response.body, diff --git a/src/plugins/voiceMessages/index.tsx b/src/plugins/voiceMessages/index.tsx index c67ccc333..93766808c 100644 --- a/src/plugins/voiceMessages/index.tsx +++ b/src/plugins/voiceMessages/index.tsx @@ -28,7 +28,7 @@ import { useAwaiter } from "@utils/react"; import definePlugin from "@utils/types"; import { chooseFile } from "@utils/web"; import { findByProps, findStore } from "@webpack"; -import { Button, Card, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; +import { Button, Card, Constants, FluxDispatcher, Forms, lodash, Menu, MessageActions, PermissionsBits, PermissionStore, RestAPI, SelectedChannelStore, showToast, SnowflakeUtils, Toasts, useEffect, useState } from "@webpack/common"; import { ComponentType } from "react"; import { VoiceRecorderDesktop } from "./DesktopRecorder"; @@ -98,7 +98,7 @@ function sendAudio(blob: Blob, meta: AudioMetadata) { upload.on("complete", () => { RestAPI.post({ - url: `/channels/${channelId}/messages`, + url: Constants.Endpoints.MESSAGES(channelId), body: { flags: 1 << 13, channel_id: channelId, diff --git a/src/plugins/whoReacted/index.tsx b/src/plugins/whoReacted/index.tsx index c890d58d8..f6d2864aa 100644 --- a/src/plugins/whoReacted/index.tsx +++ b/src/plugins/whoReacted/index.tsx @@ -23,7 +23,7 @@ import { Queue } from "@utils/Queue"; import { useForceUpdater } from "@utils/react"; import definePlugin from "@utils/types"; import { findByProps, findComponentByCode } from "@webpack"; -import { ChannelStore, FluxDispatcher, React, RestAPI, Tooltip } from "@webpack/common"; +import { ChannelStore, Constants, FluxDispatcher, React, RestAPI, Tooltip } from "@webpack/common"; import { CustomEmoji } from "@webpack/types"; import { Message, ReactionEmoji, User } from "discord-types/general"; @@ -37,7 +37,7 @@ let reactions: Record; function fetchReactions(msg: Message, emoji: ReactionEmoji, type: number) { const key = emoji.name + (emoji.id ? `:${emoji.id}` : ""); return RestAPI.get({ - url: `/channels/${msg.channel_id}/messages/${msg.id}/reactions/${key}`, + url: Constants.Endpoints.REACTIONS(msg.channel_id, msg.id, key), query: { limit: 100, type diff --git a/src/utils/constants.ts b/src/utils/constants.ts index c1e2cea2c..e446a27b6 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -473,6 +473,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ ImBanana: { name: "Im_Banana", id: 635250116688871425n + }, + xocherry: { + name: "xocherry", + id: 221288171013406720n } } satisfies Record); diff --git a/src/utils/discord.tsx b/src/utils/discord.tsx index 0cbf3ce72..c1e9a430d 100644 --- a/src/utils/discord.tsx +++ b/src/utils/discord.tsx @@ -17,7 +17,7 @@ */ import { MessageObject } from "@api/MessageEvents"; -import { ChannelStore, ComponentDispatch, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; +import { ChannelStore, ComponentDispatch, Constants, FluxDispatcher, GuildStore, InviteActions, MaskedLink, MessageActions, ModalImageClasses, PrivateChannelsStore, RestAPI, SelectedChannelStore, SelectedGuildStore, UserProfileActions, UserProfileStore, UserSettingsActionCreators, UserUtils } from "@webpack/common"; import { Guild, Message, User } from "discord-types/general"; import { ImageModal, ImageModalProps, ModalRoot, ModalSize, openModal } from "./modal"; @@ -162,7 +162,7 @@ export async function fetchUserProfile(id: string, options?: FetchUserProfileOpt FluxDispatcher.dispatch({ type: "USER_PROFILE_FETCH_START", userId: id }); const { body } = await RestAPI.get({ - url: `/users/${id}/profile`, + url: Constants.Endpoints.USER_PROFILE(id), query: { with_mutual_guilds: false, with_mutual_friends_count: false, From c007fc74788cddcaf6a0aabe61acdf66a082bbcf Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 14 May 2024 18:52:35 +0200 Subject: [PATCH 050/361] fix settings ui on canary --- src/plugins/_core/settings.tsx | 112 ++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 37 deletions(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 772ee9b64..0a6aea8b9 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -26,7 +26,7 @@ import UpdaterTab from "@components/VencordSettings/UpdaterTab"; import VencordTab from "@components/VencordSettings/VencordTab"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { React } from "@webpack/common"; +import { i18n, React } from "@webpack/common"; import gitHash from "~git-hash"; @@ -36,41 +36,55 @@ export default definePlugin({ authors: [Devs.Ven, Devs.Megu], required: true, - patches: [{ - find: ".versionHash", - replacement: [ - { - match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, - replace: (m, component, props) => { - props = props.replace(/children:\[.+\]/, ""); - return `${m},$self.makeInfoElements(${component}, ${props})`; + patches: [ + { + find: ".versionHash", + replacement: [ + { + match: /\[\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^{}}]+\{.{0,20}.versionHash,.+?\})\)," "/, + replace: (m, component, props) => { + props = props.replace(/children:\[.+\]/, ""); + return `${m},$self.makeInfoElements(${component}, ${props})`; + } } + ] + }, + // Discord Stable + // FIXME: remove once change merged to stable + { + find: "Messages.ACTIVITY_SETTINGS", + replacement: { + get match() { + switch (Settings.plugins.Settings.settingsLocation) { + case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS/; + case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS/; + case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS/; + case "belowActivity": return /(?<=\{section:(\i\.\i)\.DIVIDER},)\{section:"changelog"/; + case "bottom": return /\{section:(\i\.\i)\.CUSTOM,\s*element:.+?}/; + case "aboveActivity": + default: + return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS/; + } + }, + replace: "...$self.makeSettingsCategories($1),$&" + } + }, + // Discord Canary + { + find: "Messages.ACTIVITY_SETTINGS", + replacement: { + match: /(?<=section:(.{0,50})\.DIVIDER\}\))([,;])(?=.{0,200}(\i)\.push.{0,100}label:(\i)\.header)/, + replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}` + } + }, + { + find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", + replacement: { + match: /(?<=function\((\i),\i\)\{)(?=let \i=Object.values\(\i.UserSettingsSections\).*?(\i)\.default\.open\()/, + replace: "$2.default.open($1);return;" } - ] - }, { - find: "Messages.ACTIVITY_SETTINGS", - replacement: { - get match() { - switch (Settings.plugins.Settings.settingsLocation) { - case "top": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.USER_SETTINGS/; - case "aboveNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.BILLING_SETTINGS/; - case "belowNitro": return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.APP_SETTINGS/; - case "belowActivity": return /(?<=\{section:(\i\.\i)\.DIVIDER},)\{section:"changelog"/; - case "bottom": return /\{section:(\i\.\i)\.CUSTOM,\s*element:.+?}/; - case "aboveActivity": - default: - return /\{section:(\i\.\i)\.HEADER,\s*label:(\i)\.\i\.Messages\.ACTIVITY_SETTINGS/; - } - }, - replace: "...$self.makeSettingsCategories($1),$&" } - }, { - find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", - replacement: { - match: /(?<=function\((\i),\i\)\{)(?=let \i=Object.values\(\i.UserSettingsSections\).*?(\i)\.default\.open\()/, - replace: "$2.default.open($1);return;" - } - }], + ], customSections: [] as ((SectionTypes: Record) => any)[], @@ -130,19 +144,43 @@ export default definePlugin({ ].filter(Boolean); }, + isRightSpot({ header, settings }: { header?: string; settings?: string[]; }) { + const firstChild = settings?.[0]; + // lowest two elements... sanity backup + if (firstChild === "LOGOUT" || firstChild === "SOCIAL_LINKS") return true; + + const { settingsLocation } = Settings.plugins.Settings; + + if (settingsLocation === "bottom") return firstChild === "LOGOUT"; + if (settingsLocation === "belowActivity") return firstChild === "CHANGELOG"; + + const names = { + top: i18n.Messages.USER_SETTINGS, + aboveNitro: i18n.Messages.BILLING_SETTINGS, + belowNitro: i18n.Messages.APP_SETTINGS, + aboveActivity: i18n.Messages.ACTIVITY_SETTINGS + }; + return header === names[settingsLocation]; + }, + + addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: Record) { + if (!this.isRightSpot(element)) return; + + elements.push(...this.makeSettingsCategories(sectionTypes)); + }, + options: { settingsLocation: { type: OptionType.SELECT, description: "Where to put the Vencord settings section", options: [ { label: "At the very top", value: "top" }, - { label: "Above the Nitro section", value: "aboveNitro" }, + { label: "Above the Nitro section", value: "aboveNitro", default: true }, { label: "Below the Nitro section", value: "belowNitro" }, - { label: "Above Activity Settings", value: "aboveActivity", default: true }, + { label: "Above Activity Settings", value: "aboveActivity" }, { label: "Below Activity Settings", value: "belowActivity" }, { label: "At the very bottom", value: "bottom" }, - ], - restartNeeded: true + ] }, }, From 4209bfd3aad4b13ed79f02365f633edb2e586465 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 14 May 2024 18:54:00 +0200 Subject: [PATCH 051/361] bump to v1.8.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e5845987..95f98a8ba 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.8.3", + "version": "1.8.4", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { From 5ba5eca1a1c4e163dfdce29052cd2c0faa69a8d8 Mon Sep 17 00:00:00 2001 From: Vendicated Date: Tue, 14 May 2024 21:18:43 +0200 Subject: [PATCH 052/361] fix Vencord Settings section being added multiple times --- src/plugins/_core/settings.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 0a6aea8b9..b09af2c05 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -154,6 +154,8 @@ export default definePlugin({ if (settingsLocation === "bottom") return firstChild === "LOGOUT"; if (settingsLocation === "belowActivity") return firstChild === "CHANGELOG"; + if (!header) return; + const names = { top: i18n.Messages.USER_SETTINGS, aboveNitro: i18n.Messages.BILLING_SETTINGS, @@ -163,8 +165,12 @@ export default definePlugin({ return header === names[settingsLocation]; }, + patchedSettings: new WeakSet(), + addSettings(elements: any[], element: { header?: string; settings: string[]; }, sectionTypes: Record) { - if (!this.isRightSpot(element)) return; + if (this.patchedSettings.has(elements) || !this.isRightSpot(element)) return; + + this.patchedSettings.add(elements); elements.push(...this.makeSettingsCategories(sectionTypes)); }, From 7169dfe61a60595bcd11b9cbdb84506ff6e90801 Mon Sep 17 00:00:00 2001 From: Board <26598490+BoardTM@users.noreply.github.com> Date: Wed, 15 May 2024 01:07:33 +0200 Subject: [PATCH 053/361] ThemeAttributes: add larger avatar url variables to avatars (#2449) Co-authored-by: vee --- src/plugins/themeAttributes/README.md | 10 ++++++++- src/plugins/themeAttributes/index.ts | 30 ++++++++++++++++++++++++++- src/utils/constants.ts | 4 ++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/plugins/themeAttributes/README.md b/src/plugins/themeAttributes/README.md index 87cb803c5..89001aae4 100644 --- a/src/plugins/themeAttributes/README.md +++ b/src/plugins/themeAttributes/README.md @@ -1,6 +1,6 @@ # ThemeAttributes -This plugin adds data attributes to various elements inside Discord +This plugin adds data attributes and CSS variables to various elements inside Discord This allows themes to more easily theme those elements or even do things that otherwise wouldn't be possible @@ -19,3 +19,11 @@ This allows themes to more easily theme those elements or even do things that ot - `data-is-self` is a boolean indicating whether this is the current user's message ![image](https://github.com/Vendicated/Vencord/assets/45497981/34bd5053-3381-402f-82b2-9c812cc7e122) + +## CSS Variables + +### Avatars + +`--avatar-url-` contains a URL for the users avatar with the size attribute adjusted for the resolutions `128, 256, 512, 1024, 2048, 4096`. + +![image](https://github.com/Vendicated/Vencord/assets/26598490/192ddac0-c827-472f-9933-fa99ff36f723) diff --git a/src/plugins/themeAttributes/index.ts b/src/plugins/themeAttributes/index.ts index b8ceac621..b80844546 100644 --- a/src/plugins/themeAttributes/index.ts +++ b/src/plugins/themeAttributes/index.ts @@ -9,10 +9,11 @@ import definePlugin from "@utils/types"; import { UserStore } from "@webpack/common"; import { Message } from "discord-types/general"; + export default definePlugin({ name: "ThemeAttributes", description: "Adds data attributes to various elements for theming purposes", - authors: [Devs.Ven], + authors: [Devs.Ven, Devs.Board], patches: [ // Add data-tab-id to all tab bar items @@ -32,9 +33,36 @@ export default definePlugin({ match: /\.messageListItem(?=,"aria)/, replace: "$&,...$self.getMessageProps(arguments[0])" } + }, + + // add --avatar-url- css variable to avatar img elements + // popout profiles + { + find: ".LABEL_WITH_ONLINE_STATUS", + replacement: { + match: /src:null!=\i\?(\i).{1,50}"aria-hidden":!0/, + replace: "$&,style:$self.getAvatarStyles($1)" + } + }, + // chat avatars + { + find: "showCommunicationDisabledStyles", + replacement: { + match: /src:(\i),"aria-hidden":!0/, + replace: "$&,style:$self.getAvatarStyles($1)" + } } ], + getAvatarStyles(src: string) { + return Object.fromEntries( + [128, 256, 512, 1024, 2048, 4096].map(size => [ + `--avatar-url-${size}`, + `url(${src.replace(/\d+$/, String(size))})` + ]) + ); + }, + getMessageProps(props: { message: Message; }) { const author = props.message?.author; const authorId = author?.id; diff --git a/src/utils/constants.ts b/src/utils/constants.ts index e446a27b6..69c18cd56 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -382,6 +382,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "ant0n", id: 145224646868860928n }, + Board: { + name: "BoardTM", + id: 285475344817848320n, + }, philipbry: { name: "philipbry", id: 554994003318276106n From 2596bf09903ad32990466004b4b2c5392d8048cf Mon Sep 17 00:00:00 2001 From: Ulysses Zhan Date: Tue, 14 May 2024 16:18:30 -0700 Subject: [PATCH 054/361] new plugin NoServerEmoji ~ hides server emojis from autocomplete (#1787) Co-authored-by: vee --- src/plugins/noServerEmojis/index.ts | 50 +++++++++++++++++++++++++++++ src/utils/constants.ts | 4 +++ 2 files changed, 54 insertions(+) create mode 100644 src/plugins/noServerEmojis/index.ts diff --git a/src/plugins/noServerEmojis/index.ts b/src/plugins/noServerEmojis/index.ts new file mode 100644 index 000000000..ed843769c --- /dev/null +++ b/src/plugins/noServerEmojis/index.ts @@ -0,0 +1,50 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; + +const settings = definePluginSettings({ + shownEmojis: { + description: "The types of emojis to show in the autocomplete menu.", + type: OptionType.SELECT, + default: "onlyUnicode", + options: [ + { label: "Only unicode emojis", value: "onlyUnicode" }, + { label: "Unicode emojis and server emojis from current server", value: "currentServer" }, + { label: "Unicode emojis and all server emojis (Discord default)", value: "all" } + ] + } +}); + +export default definePlugin({ + name: "NoServerEmojis", + authors: [Devs.UlyssesZhan], + description: "Do not show server emojis in the autocomplete menu.", + settings, + patches: [ + { + find: "}searchWithoutFetchingLatest(", + replacement: { + match: /searchWithoutFetchingLatest.{20,300}get\((\i).{10,40}?reduce\(\((\i),(\i)\)=>\{/, + replace: "$& if ($self.shouldSkip($1, $3)) return $2;" + } + } + ], + shouldSkip(guildId: string, emoji: any) { + if (emoji.type !== "GUILD_EMOJI") { + return false; + } + if (settings.store.shownEmojis === "onlyUnicode") { + return true; + } + if (settings.store.shownEmojis === "currentServer") { + return emoji.guildId !== guildId; + } + return false; + } +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 69c18cd56..21d891900 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -378,6 +378,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "ProffDea", id: 609329952180928513n }, + UlyssesZhan: { + name: "UlyssesZhan", + id: 586808226058862623n + }, ant0n: { name: "ant0n", id: 145224646868860928n From dc73b89b299b57e00c569a24091ec8b9af53932c Mon Sep 17 00:00:00 2001 From: Ulysses Zhan Date: Tue, 14 May 2024 16:21:00 -0700 Subject: [PATCH 055/361] new plugin CtrlEnterSend (#1794) Co-authored-by: vee --- src/plugins/ctrlEnterSend/index.ts | 68 ++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/plugins/ctrlEnterSend/index.ts diff --git a/src/plugins/ctrlEnterSend/index.ts b/src/plugins/ctrlEnterSend/index.ts new file mode 100644 index 000000000..4b9dd8e06 --- /dev/null +++ b/src/plugins/ctrlEnterSend/index.ts @@ -0,0 +1,68 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2023 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { definePluginSettings } from "@api/Settings"; +import { Devs } from "@utils/constants"; +import definePlugin, { OptionType } from "@utils/types"; + +export default definePlugin({ + name: "CtrlEnterSend", + authors: [Devs.UlyssesZhan], + description: "Use Ctrl+Enter to send messages (customizable)", + settings: definePluginSettings({ + submitRule: { + description: "The way to send a message", + type: OptionType.SELECT, + options: [ + { + label: "Ctrl+Enter (Enter or Shift+Enter for new line)", + value: "ctrl+enter" + }, + { + label: "Shift+Enter (Enter for new line)", + value: "shift+enter" + }, + { + label: "Enter (Shift+Enter for new line; Discord default)", + value: "enter" + } + ], + default: "ctrl+enter" + }, + sendMessageInTheMiddleOfACodeBlock: { + description: "Whether to send a message in the middle of a code block", + type: OptionType.BOOLEAN, + default: true, + } + }), + patches: [ + { + find: "KeyboardKeys.ENTER&&(!", + replacement: { + match: /(?<=(\i)\.which===\i\.KeyboardKeys.ENTER&&).{0,100}(\(0,\i\.hasOpenPlainTextCodeBlock\)\(\i\)).{0,100}(?=&&\(\i\.preventDefault)/, + replace: "$self.shouldSubmit($1, $2)" + } + } + ], + shouldSubmit(event: KeyboardEvent, codeblock: boolean): boolean { + let result = false; + switch (this.settings.store.submitRule) { + case "shift+enter": + result = event.shiftKey; + break; + case "ctrl+enter": + result = event.ctrlKey; + break; + case "enter": + result = !event.shiftKey && !event.ctrlKey; + break; + } + if (!this.settings.store.sendMessageInTheMiddleOfACodeBlock) { + result &&= !codeblock; + } + return result; + } +}); From 82f9e36e5ae7a54482f34a54db26763ed72d2134 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 14 May 2024 23:53:41 -0300 Subject: [PATCH 056/361] Merge remote-tracking branch 'upstream/dev' into immediate-finds --- src/main/utils/constants.ts | 1 + src/plugins/crashHandler/index.ts | 10 ++- src/plugins/fakeNitro/index.tsx | 5 +- src/plugins/openInApp/index.ts | 21 +++++- src/plugins/petpet/index.ts | 17 +++-- src/plugins/validReply/README.md | 7 ++ src/plugins/validReply/index.ts | 106 +++++++++++++++++++++++++++ src/utils/constants.ts | 6 +- src/webpack/common/stores.ts | 7 +- src/webpack/common/types/stores.d.ts | 9 +++ src/webpack/common/utils.ts | 2 + src/webpack/webpack.tsx | 2 +- 12 files changed, 172 insertions(+), 21 deletions(-) create mode 100644 src/plugins/validReply/README.md create mode 100644 src/plugins/validReply/index.ts diff --git a/src/main/utils/constants.ts b/src/main/utils/constants.ts index 6c076c328..9513da51c 100644 --- a/src/main/utils/constants.ts +++ b/src/main/utils/constants.ts @@ -35,6 +35,7 @@ export const ALLOWED_PROTOCOLS = [ "steam:", "spotify:", "com.epicgames.launcher:", + "tidal:" ]; export const IS_VANILLA = /* @__PURE__ */ process.argv.includes("--vanilla"); diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index 7d5e7c6db..da82ca29d 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -24,12 +24,11 @@ import { closeAllModals } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; import { maybePromptToUpdate } from "@utils/updater"; import { findByProps } from "@webpack"; -import { FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common"; +import { DraftType, FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common"; const CrashHandlerLogger = new Logger("CrashHandler"); const ModalStack = findByProps("pushLazy", "popAll"); const DraftManager = findByProps("clearDraft", "saveDraft"); -const { DraftType } = findByProps("DraftType"); const { closeExpressionPicker } = findByProps("closeExpressionPicker", "openExpressionPicker"); const settings = definePluginSettings({ @@ -126,8 +125,11 @@ export default definePlugin({ try { const channelId = SelectedChannelStore.getChannelId(); - DraftManager.clearDraft(channelId, DraftType.ChannelMessage); - DraftManager.clearDraft(channelId, DraftType.FirstThreadMessage); + for (const key in DraftType) { + if (!Number.isNaN(Number(key))) continue; + + DraftManager.clearDraft(channelId, DraftType[key]); + } } catch (err) { CrashHandlerLogger.debug("Failed to clear drafts.", err); } diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index 112c18ace..492446c5e 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -24,13 +24,12 @@ import { getCurrentGuild } from "@utils/discord"; import { Logger } from "@utils/Logger"; import definePlugin, { OptionType } from "@utils/types"; import { findByProps, findStore, webpackDependantLazy } from "@webpack"; -import { Alerts, ChannelStore, EmojiStore, FluxDispatcher, Forms, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common"; +import { Alerts, ChannelStore, DraftType, EmojiStore, FluxDispatcher, Forms, IconUtils, lodash, Parser, PermissionsBits, PermissionStore, UploadHandler, UserSettingsActionCreators, UserStore } from "@webpack/common"; import type { CustomEmoji } from "@webpack/types"; import type { Message } from "discord-types/general"; import { applyPalette, GIFEncoder, quantize } from "gifenc"; import type { ReactElement, ReactNode } from "react"; -const DRAFT_TYPE = 0; const StickerStore = findStore("StickersStore") as { getPremiumPacks(): StickerPack[]; getAllGuildStickers(): Map; @@ -806,7 +805,7 @@ export default definePlugin({ gif.finish(); const file = new File([gif.bytesView()], `${stickerId}.gif`, { type: "image/gif" }); - UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DRAFT_TYPE); + UploadHandler.promptToUpload([file], ChannelStore.getChannel(channelId), DraftType.ChannelMessage); }, canUseEmote(e: CustomEmoji, channelId: string) { diff --git a/src/plugins/openInApp/index.ts b/src/plugins/openInApp/index.ts index 0835c0612..83da5f3c3 100644 --- a/src/plugins/openInApp/index.ts +++ b/src/plugins/openInApp/index.ts @@ -26,6 +26,7 @@ const ShortUrlMatcher = /^https:\/\/(spotify\.link|s\.team)\/.+$/; const SpotifyMatcher = /^https:\/\/open\.spotify\.com\/(track|album|artist|playlist|user|episode)\/(.+)(?:\?.+?)?$/; const SteamMatcher = /^https:\/\/(steamcommunity\.com|(?:help|store)\.steampowered\.com)\/.+$/; const EpicMatcher = /^https:\/\/store\.epicgames\.com\/(.+)$/; +const TidalMatcher = /^https:\/\/tidal\.com\/browse\/(track|album|artist|playlist|user|video|mix)\/(.+)(?:\?.+?)?$/; const settings = definePluginSettings({ spotify: { @@ -42,6 +43,11 @@ const settings = definePluginSettings({ type: OptionType.BOOLEAN, description: "Open Epic Games links in the Epic Games Launcher", default: true, + }, + tidal: { + type: OptionType.BOOLEAN, + description: "Open Tidal links in the Tidal app", + default: true, } }); @@ -49,7 +55,7 @@ const Native = VencordNative.pluginHelpers.OpenInApp as PluginNative UploadHandler.promptToUpload([file], cmdCtx.channel, DRAFT_TYPE), 10); + setTimeout(() => UploadHandler.promptToUpload([file], cmdCtx.channel, DraftType.ChannelMessage), 10); }, }, ] diff --git a/src/plugins/validReply/README.md b/src/plugins/validReply/README.md new file mode 100644 index 000000000..49e313cf5 --- /dev/null +++ b/src/plugins/validReply/README.md @@ -0,0 +1,7 @@ +# ValidReply + +Fixes referenced (replied to) messages showing as "Message could not be loaded". + +Hover the text to load the message! + +![](https://github.com/Vendicated/Vencord/assets/45801973/d3286acf-e822-4b7f-a4e7-8ced18f581af) diff --git a/src/plugins/validReply/index.ts b/src/plugins/validReply/index.ts new file mode 100644 index 000000000..948596ed8 --- /dev/null +++ b/src/plugins/validReply/index.ts @@ -0,0 +1,106 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2024 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import { Devs } from "@utils/constants"; +import definePlugin from "@utils/types"; +import { findByProps } from "@webpack"; +import { FluxDispatcher, RestAPI } from "@webpack/common"; +import { Message, User } from "discord-types/general"; +import { Channel } from "discord-types/general/index.js"; + +const enum ReferencedMessageState { + Loaded, + NotLoaded, + Deleted +} + +interface Reply { + baseAuthor: User, + baseMessage: Message; + channel: Channel; + referencedMessage: { state: ReferencedMessageState; }; + compact: boolean; + isReplyAuthorBlocked: boolean; +} + +const fetching = new Map(); +let ReplyStore: any; + +const { createMessageRecord } = findByProps("createMessageRecord"); + +export default definePlugin({ + name: "ValidReply", + description: 'Fixes "Message could not be loaded" upon hovering over the reply', + authors: [Devs.newwares], + patches: [ + { + find: "Messages.REPLY_QUOTE_MESSAGE_NOT_LOADED", + replacement: { + match: /Messages\.REPLY_QUOTE_MESSAGE_NOT_LOADED/, + replace: "$&,onMouseEnter:()=>$self.fetchReply(arguments[0])" + } + }, + { + find: "ReferencedMessageStore", + replacement: { + match: /constructor\(\)\{\i\(this,"_channelCaches",new Map\)/, + replace: "$&;$self.setReplyStore(this);" + } + } + ], + + setReplyStore(store: any) { + ReplyStore = store; + }, + + async fetchReply(reply: Reply) { + const { channel_id: channelId, message_id: messageId } = reply.baseMessage.messageReference!; + + if (fetching.has(messageId)) { + return; + } + fetching.set(messageId, channelId); + + RestAPI.get({ + url: `/channels/${channelId}/messages`, + query: { + limit: 1, + around: messageId + }, + retries: 2 + }) + .then(res => { + const reply: Message | undefined = res?.body?.[0]; + if (!reply) return; + + if (reply.id !== messageId) { + ReplyStore.set(channelId, messageId, { + state: ReferencedMessageState.Deleted + }); + + FluxDispatcher.dispatch({ + type: "MESSAGE_DELETE", + channelId: channelId, + message: messageId + }); + } else { + ReplyStore.set(reply.channel_id, reply.id, { + state: ReferencedMessageState.Loaded, + message: createMessageRecord(reply) + }); + + FluxDispatcher.dispatch({ + type: "MESSAGE_UPDATE", + message: reply + }); + } + }) + .catch(() => { }) + .finally(() => { + fetching.delete(messageId); + }); + } +}); diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 21d891900..a77edf7d5 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -485,7 +485,11 @@ export const Devs = /* #__PURE__*/ Object.freeze({ xocherry: { name: "xocherry", id: 221288171013406720n - } + }, + ScattrdBlade: { + name: "ScattrdBlade", + id: 678007540608532491n + }, } satisfies Record); // iife so #__PURE__ works correctly diff --git a/src/webpack/common/stores.ts b/src/webpack/common/stores.ts index 311d1c66e..f0cce76ce 100644 --- a/src/webpack/common/stores.ts +++ b/src/webpack/common/stores.ts @@ -24,12 +24,7 @@ export const Flux = findByProps("connectStores"); export type GenericStore = t.FluxStore & Record; -export enum DraftType { - ChannelMessage = 0, - ThreadSettings = 1, - FirstThreadMessage = 2, - ApplicationLauncherCommand = 3 -} +export const { DraftType }: { DraftType: typeof t.DraftType; } = findByPropsLazy("DraftType"); // This is not actually a FluxStore export const PrivateChannelsStore = findByProps("openPrivateChannel"); diff --git a/src/webpack/common/types/stores.d.ts b/src/webpack/common/types/stores.d.ts index ec52d1627..d19b046b7 100644 --- a/src/webpack/common/types/stores.d.ts +++ b/src/webpack/common/types/stores.d.ts @@ -173,6 +173,15 @@ export class DraftStore extends FluxStore { getThreadSettings(channelId: string): any | null; } +export enum DraftType { + ChannelMessage, + ThreadSettings, + FirstThreadMessage, + ApplicationLauncherCommand, + Poll, + SlashCommand, +} + export class GuildStore extends FluxStore { getGuild(guildId: string): Guild; getGuildCount(): number; diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index f8340e2b1..c2984dc85 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -107,6 +107,8 @@ export function showToast(message: string, type = ToastType.MESSAGE) { } export const UserUtils = findByProps("getUser", "fetchCurrentUser"); + +export const UploadManager = findByProps("clearAll", "addFile"); export const UploadHandler = findByProps("showUploadFileSizeExceededError", "promptToUpload"); export const ApplicationAssetUtils = findByProps("fetchAssetIds", "getAssetImage"); diff --git a/src/webpack/webpack.tsx b/src/webpack/webpack.tsx index 0000ce6c1..567623c55 100644 --- a/src/webpack/webpack.tsx +++ b/src/webpack/webpack.tsx @@ -684,7 +684,7 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = Def } const [, rawChunkIds, entryPointId] = match; - if (Number.isNaN(entryPointId)) { + if (Number.isNaN(Number(entryPointId))) { const err = new Error("extractAndLoadChunks: Matcher didn't return a capturing group with the chunk ids array, or the entry point id returned as the second group wasn't a number"); logger.warn(err, "Code:", code, "Matcher:", matcher); From c72099fc396cbb3aafc927df32b557bb668f62ae Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 14 May 2024 23:57:43 -0300 Subject: [PATCH 057/361] feat: Allow finds to use regex (#2452) --- .../VencordSettings/PatchHelperTab.tsx | 44 ++++++++++++++----- src/utils/types.ts | 8 +++- src/webpack/patchWebpack.ts | 7 ++- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/components/VencordSettings/PatchHelperTab.tsx b/src/components/VencordSettings/PatchHelperTab.tsx index 064c872ab..9e2980e7e 100644 --- a/src/components/VencordSettings/PatchHelperTab.tsx +++ b/src/components/VencordSettings/PatchHelperTab.tsx @@ -180,7 +180,8 @@ function ReplacementInput({ replacement, setReplacement, replacementError }) { return ( <> - replacement + {/* FormTitle adds a class if className is not set, so we set it to an empty string to prevent that */} + replacement {!isFunc && (
- Cheat Sheet + Cheat Sheet {Object.entries({ "\\i": "Special regex escape sequence that matches identifiers (varnames, classnames, etc.)", "$$": "Insert a $", @@ -220,11 +221,12 @@ function ReplacementInput({ replacement, setReplacement, replacementError }) { interface FullPatchInputProps { setFind(v: string): void; + setParsedFind(v: string | RegExp): void; setMatch(v: string): void; setReplacement(v: string | ReplaceFn): void; } -function FullPatchInput({ setFind, setMatch, setReplacement }: FullPatchInputProps) { +function FullPatchInput({ setFind, setParsedFind, setMatch, setReplacement }: FullPatchInputProps) { const [fullPatch, setFullPatch] = React.useState(""); const [fullPatchError, setFullPatchError] = React.useState(""); @@ -233,6 +235,7 @@ function FullPatchInput({ setFind, setMatch, setReplacement }: FullPatchInputPro setFullPatchError(""); setFind(""); + setParsedFind(""); setMatch(""); setReplacement(""); return; @@ -256,7 +259,8 @@ function FullPatchInput({ setFind, setMatch, setReplacement }: FullPatchInputPro if (!parsed.replacement.match) throw new Error("No 'replacement.match' field"); if (!parsed.replacement.replace) throw new Error("No 'replacement.replace' field"); - setFind(parsed.find); + setFind(parsed.find instanceof RegExp ? parsed.find.toString() : parsed.find); + setParsedFind(parsed.find); setMatch(parsed.replacement.match instanceof RegExp ? parsed.replacement.match.source : parsed.replacement.match); setReplacement(parsed.replacement.replace); setFullPatchError(""); @@ -266,7 +270,7 @@ function FullPatchInput({ setFind, setMatch, setReplacement }: FullPatchInputPro } return <> - Paste your full JSON patch here to fill out the fields + Paste your full JSON patch here to fill out the fields