diff --git a/package.json b/package.json index 1bc01bac..e80c3970 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "vencord", "private": "true", - "version": "1.8.9", + "version": "1.9.0", "description": "The cutest Discord client mod", "homepage": "https://github.com/Vendicated/Vencord#readme", "bugs": { diff --git a/src/debug/loadLazyChunks.ts b/src/debug/loadLazyChunks.ts index 0aeae732..64c3e0ea 100644 --- a/src/debug/loadLazyChunks.ts +++ b/src/debug/loadLazyChunks.ts @@ -25,7 +25,7 @@ export async function loadLazyChunks() { // True if resolved, false otherwise const chunksSearchPromises = [] as Array<() => boolean>; - const LazyChunkRegex = canonicalizeMatch(/(?:(?:Promise\.all\(\[)?(\i\.e\("[^)]+?"\)[^\]]*?)(?:\]\))?)\.then\(\i\.bind\(\i,"([^)]+?)"\)\)/g); + const LazyChunkRegex = canonicalizeMatch(/(?:(?:Promise\.all\(\[)?(\i\.e\("?[^)]+?"?\)[^\]]*?)(?:\]\))?)\.then\(\i\.bind\(\i,"?([^)]+?)"?\)\)/g); async function searchAndLoadLazyChunks(factoryCode: string) { const lazyChunks = factoryCode.matchAll(LazyChunkRegex); diff --git a/src/plugins/_api/messageEvents.ts b/src/plugins/_api/messageEvents.ts index 2f31398c..0347d544 100644 --- a/src/plugins/_api/messageEvents.ts +++ b/src/plugins/_api/messageEvents.ts @@ -35,11 +35,11 @@ export default definePlugin({ } }, { - find: ".handleSendMessage", + find: ".handleSendMessage,onResize", replacement: { // props.chatInputType...then((function(isMessageValid)... var parsedMessage = b.c.parse(channel,... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply); // Lookbehind: validateMessage)({openWarningPopout:..., type: i.props.chatInputType, content: t, stickers: r, ...}).then((function(isMessageValid) - match: /(type:this\.props\.chatInputType.+?\.then\()(\i=>\{.+?let (\i)=\i\.\i\.parse\((\i),.+?let (\i)=\i\.\i\.\i\(\i\);)(?<=\)\(({.+?})\)\.then.+?)/, + match: /(type:this\.props\.chatInputType.+?\.then\()(\i=>\{.+?let (\i)=\i\.\i\.parse\((\i),.+?let (\i)=\i\.\i\.getSendMessageOptionsForReply\(\i\);)(?<=\)\(({.+?})\)\.then.+?)/, // props.chatInputType...then((async function(isMessageValid)... var replyOptions = f.g.getSendMessageOptionsForReply(pendingReply); if(await Vencord.api...) return { shoudClear:true, shouldRefocus:true }; replace: (_, rest1, rest2, parsedMessage, channel, replyOptions, extra) => "" + `${rest1}async ${rest2}` + diff --git a/src/plugins/_core/settings.tsx b/src/plugins/_core/settings.tsx index 85300862..50cd6f04 100644 --- a/src/plugins/_core/settings.tsx +++ b/src/plugins/_core/settings.tsx @@ -84,13 +84,6 @@ export default definePlugin({ replace: (_, sectionTypes, commaOrSemi, elements, element) => `${commaOrSemi} $self.addSettings(${elements}, ${element}, ${sectionTypes}) ${commaOrSemi}` } }, - { - find: "useDefaultUserSettingsSections:function", - replacement: { - match: /(?<=useDefaultUserSettingsSections:function\(\){return )(\i)\}/, - replace: "$self.wrapSettingsHook($1)}" - } - }, { find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", replacement: { diff --git a/src/plugins/alwaysTrust/index.ts b/src/plugins/alwaysTrust/index.ts index b195e8eb..7484a619 100644 --- a/src/plugins/alwaysTrust/index.ts +++ b/src/plugins/alwaysTrust/index.ts @@ -49,7 +49,7 @@ export default definePlugin({ predicate: () => settings.store.domain }, { - find: "isSuspiciousDownload:", + find: "bitbucket.org", replacement: { match: /function \i\(\i\){(?=.{0,60}\.parse\(\i\))/, replace: "$&return null;" diff --git a/src/plugins/banger/index.ts b/src/plugins/banger/index.ts index 11ced3bd..7e0d2df7 100644 --- a/src/plugins/banger/index.ts +++ b/src/plugins/banger/index.ts @@ -27,7 +27,7 @@ export default definePlugin({ { find: "BAN_CONFIRM_TITLE.", replacement: { - match: /src:\i\(\d+\)/g, + match: /src:\i\("?\d+"?\)/g, replace: "src: Vencord.Settings.plugins.BANger.source" } } diff --git a/src/plugins/betterFolders/index.tsx b/src/plugins/betterFolders/index.tsx index 59e55111..d0e8cf34 100644 --- a/src/plugins/betterFolders/index.tsx +++ b/src/plugins/betterFolders/index.tsx @@ -144,8 +144,8 @@ export default definePlugin({ replacement: [ { // Modify the expanded state to instead return the list of expanded folders - match: /(\i\).{0,20}=>)(\i\.\i)\.isFolderExpanded\(\i\)/, - replace: (_, rest, ExpandedGuildFolderStore) => `${rest}${ExpandedGuildFolderStore}.getExpandedFolders()`, + match: /(\],\(\)=>)(\i\.\i)\.isFolderExpanded\(\i\)\)/, + replace: (_, rest, ExpandedGuildFolderStore) => `${rest}${ExpandedGuildFolderStore}.getExpandedFolders())`, }, { // Modify the expanded prop to use the boolean if the above patch fails, or check if the folder is expanded from the list if it succeeds diff --git a/src/plugins/betterSettings/index.tsx b/src/plugins/betterSettings/index.tsx index 6d8d9855..6a3ded3c 100644 --- a/src/plugins/betterSettings/index.tsx +++ b/src/plugins/betterSettings/index.tsx @@ -88,7 +88,7 @@ export default definePlugin({ predicate: () => settings.store.disableFade }, { // Lazy-load contents - match: /createPromise:\(\)=>([^:}]*?),webpackId:\d+,name:(?!="CollectiblesShop")"[^"]+"/g, + match: /createPromise:\(\)=>([^:}]*?),webpackId:"?\d+"?,name:(?!="CollectiblesShop")"[^"]+"/g, replace: "$&,_:$1", predicate: () => settings.store.eagerLoad } @@ -111,7 +111,7 @@ export default definePlugin({ { // Load menu TOC eagerly find: "Messages.USER_SETTINGS_WITH_BUILD_OVERRIDE.format", replacement: { - match: /(\i)\(this,"handleOpenSettingsContextMenu",.{0,100}?\i\.\i\).{0,100}?(await Promise\.all[^};]*?\)\)).*?,(?=\1\(this)/, + match: /(\i)\(this,"handleOpenSettingsContextMenu",.{0,100}?null!=\i&&.{0,100}?(await Promise\.all[^};]*?\)\)).*?,(?=\1\(this)/, replace: "$&(async ()=>$2)()," }, predicate: () => settings.store.eagerLoad @@ -119,8 +119,8 @@ export default definePlugin({ { // Settings cog context menu find: "Messages.USER_SETTINGS_ACTIONS_MENU_LABEL", replacement: { - match: /\(0,\i.\i\)\(\)(?=\.filter\(\i=>\{let\{section:\i\}=)/, - replace: "$self.wrapMenu($&)" + match: /(EXPERIMENTS:.+?)(\(0,\i.\i\)\(\))(?=\.filter\(\i=>\{let\{section:\i\}=)/, + replace: "$1$self.wrapMenu($2)" } } ], diff --git a/src/plugins/clientTheme/index.tsx b/src/plugins/clientTheme/index.tsx index 4e07daf4..b36a2cb8 100644 --- a/src/plugins/clientTheme/index.tsx +++ b/src/plugins/clientTheme/index.tsx @@ -11,7 +11,7 @@ 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 { findByCodeLazy, findComponentByCodeLazy, findStoreLazy } from "@webpack"; import { Button, Forms, useStateFromStores } from "@webpack/common"; const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); @@ -30,7 +30,7 @@ function onPickColor(color: number) { updateColorVars(hexColor); } -const { saveClientTheme } = findByPropsLazy("saveClientTheme"); +const saveClientTheme = findByCodeLazy('type:"UNSYNCED_USER_SETTINGS_UPDATE",settings:{useSystemTheme:"system"==='); function setTheme(theme: string) { saveClientTheme({ theme }); diff --git a/src/plugins/crashHandler/index.ts b/src/plugins/crashHandler/index.ts index 3297ca30..ab881e60 100644 --- a/src/plugins/crashHandler/index.ts +++ b/src/plugins/crashHandler/index.ts @@ -24,20 +24,19 @@ import { closeAllModals } from "@utils/modal"; import definePlugin, { OptionType } from "@utils/types"; import { maybePromptToUpdate } from "@utils/updater"; import { filters, findBulk, proxyLazyWebpack } from "@webpack"; -import { DraftType, FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common"; +import { DraftType, ExpressionPickerStore, FluxDispatcher, NavigationRouter, SelectedChannelStore } from "@webpack/common"; const CrashHandlerLogger = new Logger("CrashHandler"); -const { ModalStack, DraftManager, closeExpressionPicker } = proxyLazyWebpack(() => { - const [ModalStack, DraftManager, ExpressionManager] = findBulk( +const { ModalStack, DraftManager } = proxyLazyWebpack(() => { + const [ModalStack, DraftManager] = findBulk( filters.byProps("pushLazy", "popAll"), filters.byProps("clearDraft", "saveDraft"), - filters.byProps("closeExpressionPicker", "openExpressionPicker"),); + ); return { ModalStack, - DraftManager, - closeExpressionPicker: ExpressionManager?.closeExpressionPicker, + DraftManager }; }); @@ -144,7 +143,7 @@ export default definePlugin({ CrashHandlerLogger.debug("Failed to clear drafts.", err); } try { - closeExpressionPicker(); + ExpressionPickerStore.closeExpressionPicker(); } catch (err) { CrashHandlerLogger.debug("Failed to close expression picker.", err); diff --git a/src/plugins/decor/ui/index.ts b/src/plugins/decor/ui/index.ts index 0ead602e..c7846364 100644 --- a/src/plugins/decor/ui/index.ts +++ b/src/plugins/decor/ui/index.ts @@ -10,5 +10,5 @@ import { extractAndLoadChunksLazy, findByPropsLazy } from "@webpack"; export const cl = classNameFactory("vc-decor-"); export const DecorationModalStyles = findByPropsLazy("modalFooterShopButton"); -export const requireAvatarDecorationModal = extractAndLoadChunksLazy(["openAvatarDecorationModal:"]); +export const requireAvatarDecorationModal = extractAndLoadChunksLazy([".COLLECTIBLES_SHOP_FULLSCREEN&&"]); export const requireCreateStickerModal = extractAndLoadChunksLazy(["stickerInspected]:"]); diff --git a/src/plugins/decor/ui/modals/CreateDecorationModal.tsx b/src/plugins/decor/ui/modals/CreateDecorationModal.tsx index 0dcf855e..f5596f39 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 { filters, findComponentByCodeLazy, mapMangledModuleLazy } 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"; @@ -19,7 +19,10 @@ import { AvatarDecorationModalPreview } from "../components"; const FileUpload = findComponentByCodeLazy("fileUploadInput,"); -const { default: HelpMessage, HelpMessageTypes } = findByPropsLazy("HelpMessageTypes"); +const { HelpMessage, HelpMessageTypes } = mapMangledModuleLazy('POSITIVE=3]="POSITIVE', { + HelpMessageTypes: filters.byProps("POSITIVE", "WARNING"), + HelpMessage: filters.byCode(".iconDiv") +}); function useObjectURL(object: Blob | MediaSource | null) { const [url, setUrl] = useState(null); diff --git a/src/plugins/emoteCloner/index.tsx b/src/plugins/emoteCloner/index.tsx index b456c351..6dd3eb30 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 { findByCodeLazy, findStoreLazy } from "@webpack"; import { Constants, 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 uploadEmoji = findByCodeLazy(".GUILD_EMOJIS(", "EMOJI_UPLOAD_START"); interface Sticker { t: "Sticker"; @@ -106,7 +106,7 @@ async function cloneEmoji(guildId: string, emoji: Emoji) { reader.readAsDataURL(data); }); - return EmojiManager.uploadEmoji({ + return uploadEmoji({ guildId, name: emoji.name.split("~")[0], image: dataUrl diff --git a/src/plugins/experiments/index.tsx b/src/plugins/experiments/index.tsx index 9cb22521..4cf8439b 100644 --- a/src/plugins/experiments/index.tsx +++ b/src/plugins/experiments/index.tsx @@ -28,7 +28,7 @@ import { Forms, React } from "@webpack/common"; import hideBugReport from "./hideBugReport.css?managed"; -const KbdStyles = findByPropsLazy("key", "removeBuildOverride"); +const KbdStyles = findByPropsLazy("key", "combo"); const settings = definePluginSettings({ toolbarDevMenu: { @@ -106,9 +106,11 @@ export default definePlugin({ More Information You can open Discord's DevTools via {" "} - {modKey} +{" "} - {altKey} +{" "} - O{" "} +
+ {modKey} +{" "} + {altKey} +{" "} + O{" "} +
); diff --git a/src/plugins/fakeNitro/index.tsx b/src/plugins/fakeNitro/index.tsx index cdf74d15..76c8f364 100644 --- a/src/plugins/fakeNitro/index.tsx +++ b/src/plugins/fakeNitro/index.tsx @@ -37,8 +37,8 @@ const StickerStore = findStoreLazy("StickersStore") as { }; const UserSettingsProtoStore = findStoreLazy("UserSettingsProtoStore"); -const ProtoUtils = findByPropsLazy("BINARY_READ_OPTIONS"); -const RoleSubscriptionEmojiUtils = findByPropsLazy("isUnusableRoleSubscriptionEmoji"); + +const BINARY_READ_OPTIONS = findByPropsLazy("readerFactory"); function searchProtoClassField(localName: string, protoClass: any) { const field = protoClass?.fields?.find((field: any) => field.localName === localName); @@ -49,7 +49,7 @@ function searchProtoClassField(localName: string, protoClass: any) { } const PreloadedUserSettingsActionCreators = proxyLazyWebpack(() => UserSettingsActionCreators.PreloadedUserSettingsActionCreators); -const AppearanceSettingsActionCreators = proxyLazyWebpack(() => searchProtoClassField("appearance", PreloadedUserSettingsActionCreators.ProtoClass)); +const AppearanceSettingsActionCreators = proxyLazyWebpack(() => searchProtoClassField("appearance", PreloadedUserSettingsActionCreators)); const ClientThemeSettingsActionsCreators = proxyLazyWebpack(() => searchProtoClassField("clientThemeSettings", AppearanceSettingsActionCreators)); @@ -234,15 +234,16 @@ export default definePlugin({ } ] }, + // FIXME // Allows the usage of subscription-locked emojis - { - find: "isUnusableRoleSubscriptionEmoji:function", + /* { + find: ".getUserIsAdmin(", replacement: { - match: /isUnusableRoleSubscriptionEmoji:function/, + match: /(?=.+?\.getUserIsAdmin\((?<=function (\i)\(\i,\i\){.+?))(\i):function\(\){return \1}/, // Replace the original export with a func that always returns false and alias the original - replace: "isUnusableRoleSubscriptionEmoji:()=>()=>false,isUnusableRoleSubscriptionEmojiOriginal:function" + replace: "$2:()=>()=>false,isUnusableRoleSubscriptionEmojiOriginal:function(){return $1}" } - }, + }, */ // Allow stickers to be sent everywhere { find: "canUseCustomStickersEverywhere:function", @@ -361,7 +362,7 @@ export default definePlugin({ replacement: [ { // Export the renderable sticker to be used in the fake nitro sticker notice - match: /let{renderableSticker:(\i).{0,250}isGuildSticker.+?channel:\i,/, + match: /let{renderableSticker:(\i).{0,270}sticker:\i,channel:\i,/, replace: (m, renderableSticker) => `${m}fakeNitroRenderableSticker:${renderableSticker},` }, { @@ -472,12 +473,12 @@ export default definePlugin({ const premiumType = UserStore?.getCurrentUser()?.premiumType ?? 0; if (premiumType === 2 || backgroundGradientPresetId == null) return original(); - if (!PreloadedUserSettingsActionCreators || !AppearanceSettingsActionCreators || !ClientThemeSettingsActionsCreators || !ProtoUtils) return; + if (!PreloadedUserSettingsActionCreators || !AppearanceSettingsActionCreators || !ClientThemeSettingsActionsCreators || !BINARY_READ_OPTIONS) return; const currentAppearanceSettings = PreloadedUserSettingsActionCreators.getCurrentValue().appearance; const newAppearanceProto = currentAppearanceSettings != null - ? AppearanceSettingsActionCreators.fromBinary(AppearanceSettingsActionCreators.toBinary(currentAppearanceSettings), ProtoUtils.BINARY_READ_OPTIONS) + ? AppearanceSettingsActionCreators.fromBinary(AppearanceSettingsActionCreators.toBinary(currentAppearanceSettings), BINARY_READ_OPTIONS) : AppearanceSettingsActionCreators.create(); newAppearanceProto.theme = theme; @@ -816,8 +817,9 @@ export default definePlugin({ if (e.type === 0) return true; if (e.available === false) return false; - const isUnusableRoleSubEmoji = RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmojiOriginal ?? RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmoji; - if (isUnusableRoleSubEmoji(e, this.guildId)) return false; + // FIXME + /* const isUnusableRoleSubEmoji = isUnusableRoleSubscriptionEmojiOriginal ?? RoleSubscriptionEmojiUtils.isUnusableRoleSubscriptionEmoji; + if (isUnusableRoleSubEmoji(e, this.guildId)) return false; */ if (this.canUseEmotes) return e.guildId === this.guildId || hasExternalEmojiPerms(channelId); diff --git a/src/plugins/fakeProfileThemes/index.tsx b/src/plugins/fakeProfileThemes/index.tsx index 7a6bda9a..31fc71a9 100644 --- a/src/plugins/fakeProfileThemes/index.tsx +++ b/src/plugins/fakeProfileThemes/index.tsx @@ -111,7 +111,7 @@ interface ProfileModalProps { const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); const ProfileModal = findComponentByCodeLazy('"ProfileCustomizationPreview"'); -const requireColorPicker = extractAndLoadChunksLazy(["USER_SETTINGS_PROFILE_COLOR_DEFAULT_BUTTON.format"], /createPromise:\(\)=>\i\.\i\("(.+?)"\).then\(\i\.bind\(\i,"(.+?)"\)\)/); +const requireColorPicker = extractAndLoadChunksLazy(["USER_SETTINGS_PROFILE_COLOR_DEFAULT_BUTTON.format"], /createPromise:\(\)=>\i\.\i\("?(.+?)"?\).then\(\i\.bind\(\i,"?(.+?)"?\)\)/); export default definePlugin({ name: "FakeProfileThemes", diff --git a/src/plugins/forceOwnerCrown/index.ts b/src/plugins/forceOwnerCrown/index.ts index 15b1f6f5..771583fe 100644 --- a/src/plugins/forceOwnerCrown/index.ts +++ b/src/plugins/forceOwnerCrown/index.ts @@ -27,7 +27,7 @@ export default definePlugin({ authors: [Devs.D3SOX, Devs.Nickyux], patches: [ { - find: "AVATAR_DECORATION_PADDING:", + find: ".PREMIUM_GUILD_SUBSCRIPTION_TOOLTIP", replacement: { match: /,isOwner:(\i),/, replace: ",_isOwner:$1=$self.isGuildOwner(e)," diff --git a/src/plugins/friendInvites/index.ts b/src/plugins/friendInvites/index.ts index 47e312c3..20c615d6 100644 --- a/src/plugins/friendInvites/index.ts +++ b/src/plugins/friendInvites/index.ts @@ -16,14 +16,12 @@ * along with this program. If not, see . */ -import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands"; +import { ApplicationCommandInputType, sendBotMessage } from "@api/Commands"; import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; -import { Constants, RestAPI, UserStore } from "@webpack/common"; const FriendInvites = findByPropsLazy("createFriendInvite"); -const { uuid4 } = findByPropsLazy("uuid4"); export default definePlugin({ name: "FriendInvites", @@ -35,47 +33,9 @@ export default definePlugin({ name: "create friend invite", description: "Generates a friend invite link.", inputType: ApplicationCommandInputType.BOT, - options: [{ - name: "Uses", - description: "How many uses?", - choices: [ - { label: "1", name: "1", value: "1" }, - { label: "5", name: "5", value: "5" } - ], - required: false, - type: ApplicationCommandOptionType.INTEGER - }], execute: async (args, ctx) => { - const uses = findOption(args, "Uses", 5); - - if (uses === 1 && !UserStore.getCurrentUser().phone) - return sendBotMessage(ctx.channel.id, { - content: "You need to have a phone number connected to your account to create a friend invite with 1 use!" - }); - - let invite: any; - if (uses === 1) { - const random = uuid4(); - const { body: { invite_suggestions } } = await RestAPI.post({ - url: Constants.Endpoints.FRIEND_FINDER, - body: { - modified_contacts: { - [random]: [1, "", ""] - }, - phone_contact_methods_count: 1 - } - }); - invite = await FriendInvites.createFriendInvite({ - code: invite_suggestions[0][3], - recipient_phone_number_or_email: random, - contact_visibility: 1, - filter_visibilities: [], - filtered_invite_suggestions_index: 1 - }); - } else { - invite = await FriendInvites.createFriendInvite(); - } + const invite = await FriendInvites.createFriendInvite(); sendBotMessage(ctx.channel.id, { content: ` diff --git a/src/plugins/friendsSince/index.tsx b/src/plugins/friendsSince/index.tsx index 6c354278..b290a445 100644 --- a/src/plugins/friendsSince/index.tsx +++ b/src/plugins/friendsSince/index.tsx @@ -4,21 +4,23 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import { classNameFactory } from "@api/Styles"; import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { getCurrentChannel } from "@utils/discord"; import { Logger } from "@utils/Logger"; import { classes } from "@utils/misc"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByCodeLazy, findByPropsLazy } from "@webpack"; import { Heading, React, RelationshipStore, Text } from "@webpack/common"; const container = findByPropsLazy("memberSinceWrapper"); -const { getCreatedAtDate } = findByPropsLazy("getCreatedAtDate"); -const clydeMoreInfo = findByPropsLazy("clydeMoreInfo"); +const getCreatedAtDate = findByCodeLazy('month:"short",day:"numeric"'); const locale = findByPropsLazy("getLocale"); const lastSection = findByPropsLazy("lastSection"); +const cl = classNameFactory("vc-friendssince-"); + export default definePlugin({ name: "FriendsSince", description: "Shows when you became friends with someone in the user popout", @@ -28,7 +30,7 @@ export default definePlugin({ { find: ".USER_PROFILE}};return", replacement: { - match: /\i.\i,\{userId:(\i.id).{0,30}}\)/, + match: /,{userId:(\i.id).{0,30}}\)/, replace: "$&,$self.friendsSince({ userId: $1 })" } }, @@ -36,7 +38,7 @@ export default definePlugin({ { find: ".PROFILE_PANEL,", replacement: { - match: /\i.\i,\{userId:([^,]+?)}\)/, + match: /,{userId:([^,]+?)}\)/, replace: "$&,$self.friendsSince({ userId: $1 })" } }, @@ -69,7 +71,7 @@ export default definePlugin({ return (
- + Friends Since @@ -86,7 +88,7 @@ export default definePlugin({ )} - + {getCreatedAtDate(friendsSince, locale.getLocale())}
diff --git a/src/plugins/friendsSince/styles.css b/src/plugins/friendsSince/styles.css new file mode 100644 index 00000000..9f73db0b --- /dev/null +++ b/src/plugins/friendsSince/styles.css @@ -0,0 +1,12 @@ +/* copy pasted from discord */ + +.vc-friendssince-title { + display: flex; + font-weight: 700; + margin-bottom: 6px +} + +.vc-friendssince-body { + font-size: 14px; + line-height: 18px +} diff --git a/src/plugins/gifPaste/index.ts b/src/plugins/gifPaste/index.ts index 5553bf84..b2b4305d 100644 --- a/src/plugins/gifPaste/index.ts +++ b/src/plugins/gifPaste/index.ts @@ -19,9 +19,7 @@ import { Devs } from "@utils/constants"; import { insertTextIntoChatInputBox } from "@utils/discord"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; - -const { closeExpressionPicker } = findByPropsLazy("closeExpressionPicker"); +import { ExpressionPickerStore } from "@webpack/common"; export default definePlugin({ name: "GifPaste", @@ -39,7 +37,7 @@ export default definePlugin({ handleSelect(gif?: { url: string; }) { if (gif) { insertTextIntoChatInputBox(gif.url + " "); - closeExpressionPicker(); + ExpressionPickerStore.closeExpressionPicker(); } } }); diff --git a/src/plugins/greetStickerPicker/index.tsx b/src/plugins/greetStickerPicker/index.tsx index 73bb5125..438fa40c 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 { findLazy } 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 = findLazy(m => Array.isArray(m) && m[0]?.name === "Wave"); function greet(channel: Channel, message: Message, stickers: string[]) { const options = MessageActions.getSendMessageOptionsForReply({ diff --git a/src/plugins/imageLink/index.ts b/src/plugins/imageLink/index.ts index 5e8dd23e..08d3a024 100644 --- a/src/plugins/imageLink/index.ts +++ b/src/plugins/imageLink/index.ts @@ -16,7 +16,8 @@ export default definePlugin({ { find: "unknownUserMentionPlaceholder:", replacement: { - match: /\(0,\i\.isEmbedInline\)\(\i\)/, + // SimpleEmbedTypes.has(embed.type) && isEmbedInline(embed) + match: /\i\.has\(\i\.type\)&&\(0,\i\.\i\)\(\i\)/, replace: "false", } } diff --git a/src/plugins/implicitRelationships/index.ts b/src/plugins/implicitRelationships/index.ts index 4faad2a9..7fefb39b 100644 --- a/src/plugins/implicitRelationships/index.ts +++ b/src/plugins/implicitRelationships/index.ts @@ -19,17 +19,11 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy, findStoreLazy } from "@webpack"; -import { ChannelStore, FluxDispatcher, GuildStore, RelationshipStore, SnowflakeUtils, UserStore } from "@webpack/common"; +import { findStoreLazy } from "@webpack"; +import { ChannelStore, Constants, 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; - affinity: number; -} export default definePlugin({ name: "ImplicitRelationships", @@ -70,7 +64,7 @@ export default definePlugin({ }, // Piggyback relationship fetch { - find: ".fetchRelationships()", + find: '"FriendsStore', replacement: { match: /(\i\.\i)\.fetchRelationships\(\)/, // This relationship fetch is actually completely useless, but whatevs @@ -182,6 +176,6 @@ export default definePlugin({ }, start() { - FriendsSections.IMPLICIT = "IMPLICIT"; + Constants.FriendsSections.IMPLICIT = "IMPLICIT"; } }); diff --git a/src/plugins/index.ts b/src/plugins/index.ts index b731899d..45e182b8 100644 --- a/src/plugins/index.ts +++ b/src/plugins/index.ts @@ -44,7 +44,6 @@ const pluginsValues = Object.values(Plugins); const settings = Settings.plugins; const forceDisabled = new Set([ - "ShowHiddenChannels", "MoreUserTags" ]); export function isPluginEnabled(p: string) { diff --git a/src/plugins/maskedLinkPaste/index.ts b/src/plugins/maskedLinkPaste/index.ts index 72931208..bcd622ed 100644 --- a/src/plugins/maskedLinkPaste/index.ts +++ b/src/plugins/maskedLinkPaste/index.ts @@ -10,7 +10,7 @@ import { findByPropsLazy } from "@webpack"; const linkRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/; -const { SlateTransforms } = findByPropsLazy("SlateTransforms"); +const SlateTransforms = findByPropsLazy("insertText", "selectCommandOption"); export default definePlugin({ name: "MaskedLinkPaste", diff --git a/src/plugins/newGuildSettings/index.tsx b/src/plugins/newGuildSettings/index.tsx index d5c3d920..f1c29f25 100644 --- a/src/plugins/newGuildSettings/index.tsx +++ b/src/plugins/newGuildSettings/index.tsx @@ -19,11 +19,11 @@ import { definePluginSettings, migratePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByCodeLazy, findByPropsLazy } from "@webpack"; const { updateGuildNotificationSettings } = findByPropsLazy("updateGuildNotificationSettings"); const { toggleShowAllChannels } = findByPropsLazy("toggleShowAllChannels"); -const { isOptInEnabledForGuild } = findByPropsLazy("isOptInEnabledForGuild"); +const isOptInEnabledForGuild = findByCodeLazy(".COMMUNITY)||", ".isOptInEnabled("); const settings = definePluginSettings({ guild: { diff --git a/src/plugins/pauseInvitesForever/index.tsx b/src/plugins/pauseInvitesForever/index.tsx index 332297b6..3f1ce6bf 100644 --- a/src/plugins/pauseInvitesForever/index.tsx +++ b/src/plugins/pauseInvitesForever/index.tsx @@ -56,8 +56,8 @@ export default definePlugin({ replace: "children: $self.renderInvitesLabel({guildId:arguments[0].guildId,setChecked})", }, { - match: /(\i\.\i\)\(\i\),\[\i,(\i)\]=\i\.useState\(\i\))/, - replace: "$1,setChecked=$2" + match: /\.INVITES_DISABLED\)(?=.+?\.Messages\.INVITES_PERMANENTLY_DISABLED_TIP.+?checked:(\i)).+?\[\1,(\i)\]=\i.useState\(\i\)/, + replace: "$&,setChecked=$2" } ] } diff --git a/src/plugins/permissionFreeWill/index.ts b/src/plugins/permissionFreeWill/index.ts index 70a85868..96e110b6 100644 --- a/src/plugins/permissionFreeWill/index.ts +++ b/src/plugins/permissionFreeWill/index.ts @@ -6,6 +6,7 @@ import { definePluginSettings } from "@api/Settings"; import { Devs } from "@utils/constants"; +import { canonicalizeMatch } from "@utils/patches"; import definePlugin, { OptionType } from "@utils/types"; const settings = definePluginSettings({ @@ -31,7 +32,7 @@ export default definePlugin({ patches: [ // Permission lockout, just set the check to true { - find: ".showPermissionLockoutModal(", + find: ".STAGE_CHANNEL_CANNOT_OVERWRITE_PERMISSION", replacement: [ { match: /case"DENY":.{0,50}if\((?=\i\.\i\.can)/, @@ -45,9 +46,8 @@ export default definePlugin({ find: ".ONBOARDING_CHANNEL_THRESHOLD_WARNING", replacement: [ { - // are we java yet? - match: /(?<=(?:isDefaultChannelThresholdMetAfterDelete|checkDefaultChannelThresholdMetAfterChannelPermissionDeny):function\(\)\{)return \i(?=\})/g, - replace: "return () => true" + match: /{(\i:function\(\){return \i},?){2}}/, + replace: m => m.replaceAll(canonicalizeMatch(/return \i/g), "return ()=>Promise.resolve(true)") } ], predicate: () => settings.store.onboarding diff --git a/src/plugins/pinDms/components/CreateCategoryModal.tsx b/src/plugins/pinDms/components/CreateCategoryModal.tsx index 123bc838..2f1d4d1d 100644 --- a/src/plugins/pinDms/components/CreateCategoryModal.tsx +++ b/src/plugins/pinDms/components/CreateCategoryModal.tsx @@ -33,7 +33,7 @@ interface ColorPickerWithSwatchesProps { const ColorPicker = findComponentByCodeLazy(".Messages.USER_SETTINGS_PROFILE_COLOR_SELECT_COLOR", ".BACKGROUND_PRIMARY)"); const ColorPickerWithSwatches = findExportedComponentLazy("ColorPicker", "CustomColorPicker"); -export const requireSettingsMenu = extractAndLoadChunksLazy(['name:"UserSettings"'], /createPromise:.{0,20}Promise\.all\((\[\i\.\i\(".+?"\).+?\])\).then\(\i\.bind\(\i,"(.+?)"\)\).{0,50}"UserSettings"/); +export const requireSettingsMenu = extractAndLoadChunksLazy(['name:"UserSettings"'], /createPromise:.{0,20}Promise\.all\((\[\i\.\i\("?.+?"?\).+?\])\).then\(\i\.bind\(\i,"?(.+?)"?\)\).{0,50}"UserSettings"/); const cl = classNameFactory("vc-pindms-modal-"); diff --git a/src/plugins/revealAllSpoilers/index.ts b/src/plugins/revealAllSpoilers/index.ts index e728181a..98e8423c 100644 --- a/src/plugins/revealAllSpoilers/index.ts +++ b/src/plugins/revealAllSpoilers/index.ts @@ -21,7 +21,7 @@ import definePlugin from "@utils/types"; import { findByPropsLazy } from "@webpack"; const SpoilerClasses = findByPropsLazy("spoilerContent"); -const MessagesClasses = findByPropsLazy("messagesWrapper", "messages"); +const MessagesClasses = findByPropsLazy("messagesWrapper"); export default definePlugin({ name: "RevealAllSpoilers", diff --git a/src/plugins/reviewDB/components/ReviewComponent.tsx b/src/plugins/reviewDB/components/ReviewComponent.tsx index 8faec9f4..31eab29f 100644 --- a/src/plugins/reviewDB/components/ReviewComponent.tsx +++ b/src/plugins/reviewDB/components/ReviewComponent.tsx @@ -142,7 +142,7 @@ export default LazyComponent(() => { {review.type === ReviewType.System && ( System diff --git a/src/plugins/seeSummaries/index.tsx b/src/plugins/seeSummaries/index.tsx index f1cdd785..4ce8c4af 100644 --- a/src/plugins/seeSummaries/index.tsx +++ b/src/plugins/seeSummaries/index.tsx @@ -57,7 +57,7 @@ export default definePlugin({ { find: "SUMMARIZEABLE.has", replacement: { - match: /\i\.hasFeature\(.{0,10}\.SUMMARIES_ENABLED\w+?\)/g, + match: /\i\.hasFeature\(\i\.\i\.SUMMARIES_ENABLED\w+?\)/g, replace: "true" } }, diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index 48342cae..b0668673 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -116,14 +116,14 @@ export default definePlugin({ }, // Prevent Discord from trying to connect to hidden stage channels { - find: ".MAX_STAGE_VOICE_USER_LIMIT})", + find: ".AUDIENCE),{isSubscriptionGated", replacement: { match: /!(\i)\.isRoleSubscriptionTemplatePreviewChannel\(\)/, replace: (m, channel) => `${m}&&!$self.isHiddenChannel(${channel})` } }, { - find: "ChannelItemEditButton:function(){", + find: 'tutorialId:"instant-invite"', replacement: [ // Render null instead of the buttons if the channel is hidden ...[ @@ -195,7 +195,7 @@ export default definePlugin({ // Hide the new version of unreads box for hidden channels find: '="ChannelListUnreadsStore",', replacement: { - match: /(?=&&\(0,\i\.getHasImportantUnread\)\((\i)\))/g, // Global because Discord has multiple methods like that in the same module + match: /(?<=\.id\)\))(?=&&\(0,\i\.\i\)\((\i)\))/, replace: (_, channel) => `&&!$self.isHiddenChannel(${channel})` } }, @@ -203,15 +203,15 @@ export default definePlugin({ // Make the old version of unreads box not visible for hidden channels find: "renderBottomUnread(){", replacement: { - match: /(?=&&\(0,\i\.getHasImportantUnread\)\((\i\.record)\))/, + match: /(?<=!0\))(?=&&\(0,\i\.\i\)\((\i\.record)\))/, replace: "&&!$self.isHiddenChannel($1)" } }, { // Make the state of the old version of unreads box not include hidden channels - find: ".useFlattenedChannelIdListWithThreads)", + find: "ignoreRecents:!0", replacement: { - match: /(?=&&\(0,\i\.getHasImportantUnread\)\((\i)\))/, + match: /(?<=\.id\)\))(?=&&\(0,\i\.\i\)\((\i)\))/, replace: "&&!$self.isHiddenChannel($1)" } }, @@ -257,7 +257,7 @@ export default definePlugin({ { find: '"alt+shift+down"', replacement: { - match: /(?<=getChannel\(\i\);return null!=(\i))(?=.{0,150}?getHasImportantUnread\)\(\i\))/, + match: /(?<=getChannel\(\i\);return null!=(\i))(?=.{0,150}?>0\)&&\(0,\i\.\i\)\(\i\))/, replace: (_, channel) => `&&!$self.isHiddenChannel(${channel})` } }, @@ -289,7 +289,7 @@ export default definePlugin({ }, { // If the @everyone role has the required permissions, make the array only contain it - match: /computePermissionsForRoles.+?.value\(\)(?<=channel:(\i).+?)/, + match: /forceRoles:.+?.value\(\)(?<=channel:(\i).+?)/, replace: (m, channel) => `${m}.reduce(...$self.makeAllowedRolesReduce(${channel}.guild_id))` }, { @@ -422,7 +422,7 @@ export default definePlugin({ }, { // Avoid filtering out hidden channels from the channel list - match: /(?<=queryChannels\(\i\){.+?isGuildChannelType\)\((\i)\.type\))(?=&&!\i\.\i\.can\()/, + match: /(?<=queryChannels\(\i\){.+?\)\((\i)\.type\))(?=&&!\i\.\i\.can\()/, replace: "&&!$self.isHiddenChannel($1)" } ] diff --git a/src/plugins/superReactionTweaks/index.ts b/src/plugins/superReactionTweaks/index.ts index 7878ba63..1a5e3a98 100644 --- a/src/plugins/superReactionTweaks/index.ts +++ b/src/plugins/superReactionTweaks/index.ts @@ -47,9 +47,9 @@ export default definePlugin({ } }, { - find: ".trackEmojiSearchEmpty,200", + find: ".EMOJI_PICKER_CONSTANTS_EMOJI_CONTAINER_PADDING_HORIZONTAL)", replacement: { - match: /(\.trackEmojiSearchEmpty,200(?=.+?isBurstReaction:(\i).+?(\i===\i\.EmojiIntention.REACTION)).+?\[\2,\i\]=\i\.useState\().+?\)/, + match: /(openPopoutType:void 0(?=.+?isBurstReaction:(\i).+?(\i===\i\.\i.REACTION)).+?\[\2,\i\]=\i\.useState\().+?\)/, replace: (_, rest, isBurstReactionVariable, isReactionIntention) => `${rest}$self.shouldSuperReactByDefault&&${isReactionIntention})` } } diff --git a/src/plugins/validReply/index.ts b/src/plugins/validReply/index.ts index 21a1bdd1..b65496f4 100644 --- a/src/plugins/validReply/index.ts +++ b/src/plugins/validReply/index.ts @@ -6,7 +6,7 @@ import { Devs } from "@utils/constants"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByCodeLazy } from "@webpack"; import { FluxDispatcher, RestAPI } from "@webpack/common"; import { Message, User } from "discord-types/general"; import { Channel } from "discord-types/general/index.js"; @@ -29,7 +29,7 @@ interface Reply { const fetching = new Map(); let ReplyStore: any; -const { createMessageRecord } = findByPropsLazy("createMessageRecord"); +const createMessageRecord = findByCodeLazy(".createFromServer(", ".isBlockedForMessage", "messageReference:"); export default definePlugin({ name: "ValidReply", diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts index 166a25fe..1cd2bf69 100644 --- a/src/webpack/common/types/utils.d.ts +++ b/src/webpack/common/types/utils.d.ts @@ -219,4 +219,5 @@ export interface IconUtils { export interface Constants { Endpoints: Record; UserFlags: Record; + FriendsSections: Record; } diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts index dd78dc4e..a724769c 100644 --- a/src/webpack/common/utils.ts +++ b/src/webpack/common/utils.ts @@ -16,6 +16,7 @@ * along with this program. If not, see . */ +import { canonicalizeMatch } from "@utils/patches"; import type { Channel } from "discord-types/general"; // eslint-disable-next-line path-alias/no-relative @@ -40,7 +41,8 @@ waitFor(["dispatchToLastSubscribed"], m => ComponentDispatch = m); export const Constants: t.Constants = mapMangledModuleLazy('ME:"/users/@me"', { Endpoints: filters.byProps("USER", "ME"), - UserFlags: filters.byProps("STAFF", "SPAMMER") + UserFlags: filters.byProps("STAFF", "SPAMMER"), + FriendsSections: m => m.PENDING === "PENDING" && m.ADD_FRIEND }); export const RestAPI: t.RestAPI = findLazy(m => typeof m === "object" && m.del && m.put); @@ -157,3 +159,10 @@ export const UserProfileActions = findByPropsLazy("openUserProfileModal", "close export const InviteActions = findByPropsLazy("resolveInvite"); export const IconUtils: t.IconUtils = findByPropsLazy("getGuildBannerURL", "getUserAvatarURL"); + +const openExpressionPickerMatcher = canonicalizeMatch(/setState\({activeView:\i/); +// TODO: type +export const ExpressionPickerStore = mapMangledModuleLazy("expression-picker-last-active-view", { + closeExpressionPicker: filters.byCode("setState({activeView:null"), + openExpressionPicker: m => typeof m === "function" && openExpressionPickerMatcher.test(m.toString()), +}); diff --git a/src/webpack/webpack.ts b/src/webpack/webpack.ts index daca1892..b536063e 100644 --- a/src/webpack/webpack.ts +++ b/src/webpack/webpack.ts @@ -106,7 +106,7 @@ export const find = traceFunction("find", function find(filter: FilterFn, { isIn for (const key in cache) { const mod = cache[key]; - if (!mod?.exports) continue; + if (!mod.loaded || !mod?.exports) continue; if (filter(mod.exports)) { return isWaitFor ? [mod.exports, key] : mod.exports; @@ -142,7 +142,7 @@ export function findAll(filter: FilterFn) { const ret = [] as any[]; for (const key in cache) { const mod = cache[key]; - if (!mod?.exports) continue; + if (!mod.loaded || !mod?.exports) continue; if (filter(mod.exports)) ret.push(mod.exports); @@ -190,7 +190,7 @@ export const findBulk = traceFunction("findBulk", function findBulk(...filterFns outer: for (const key in cache) { const mod = cache[key]; - if (!mod?.exports) continue; + if (!mod.loaded || !mod?.exports) continue; for (let j = 0; j < length; j++) { const filter = filters[j]; @@ -486,7 +486,7 @@ export function mapMangledModuleLazy(code: string, mappers: Re return proxyLazy(() => mapMangledModule(code, mappers)); } -export const DefaultExtractAndLoadChunksRegex = /(?:(?:Promise\.all\(\[)?(\i\.e\("[^)]+?"\)[^\]]*?)(?:\]\))?|Promise\.resolve\(\))\.then\(\i\.bind\(\i,"([^)]+?)"\)\)/; +export const DefaultExtractAndLoadChunksRegex = /(?:(?:Promise\.all\(\[)?(\i\.e\("?[^)]+?"?\)[^\]]*?)(?:\]\))?|Promise\.resolve\(\))\.then\(\i\.bind\(\i,"?([^)]+?)"?\)\)/; export const ChunkIdsRegex = /\("([^"]+?)"\)/g; /**