diff --git a/src/plugins/apiMessageAccessories.ts b/src/plugins/apiMessageAccessories.ts index 8d018102b..5f6c6935c 100644 --- a/src/plugins/apiMessageAccessories.ts +++ b/src/plugins/apiMessageAccessories.ts @@ -27,7 +27,7 @@ export default definePlugin({ { find: "_messageAttachmentToEmbedMedia", replacement: { - match: /\(\)\.container\)},(.+?)\)};return/, + match: /\(\)\.container,children:[[^\]]*]\)},(.+?)\)};return/, replace: (_, accessories) => `().container)},Vencord.Api.MessageAccessories._modifyAccessories([${accessories}],this.props))};return`, }, diff --git a/src/plugins/betterGifAltText.ts b/src/plugins/betterGifAltText.ts index f185e04e1..56d7b5474 100644 --- a/src/plugins/betterGifAltText.ts +++ b/src/plugins/betterGifAltText.ts @@ -29,7 +29,7 @@ export default definePlugin({ { find: "onCloseImage=", replacement: { - match: /(return .{1,2}\.createElement.{0,50}isWindowFocused)/, + match: /(return.{0,10}\.jsx.{0,50}isWindowFocused)/, replace: "Vencord.Plugins.plugins.BetterGifAltText.altify(e);$1", }, diff --git a/src/plugins/noBlockedMessages.ts b/src/plugins/noBlockedMessages.ts index 71e1e107b..6c7a49686 100644 --- a/src/plugins/noBlockedMessages.ts +++ b/src/plugins/noBlockedMessages.ts @@ -28,8 +28,8 @@ export default definePlugin({ find: 'safety_prompt:"DMSpamExperiment",response:"show_redacted_messages"', replacement: [ { - match: /collapsedReason;return (?=\w{1,2}.createElement)/, - replace: "collapsedReason; return null;" + match: /\.collapsedReason;return/, + replace: ".collapsedReason;return null;return;" } ] } diff --git a/src/plugins/plainFolderIcon.ts b/src/plugins/plainFolderIcon.ts index b727ab2f8..35f903fa3 100644 --- a/src/plugins/plainFolderIcon.ts +++ b/src/plugins/plainFolderIcon.ts @@ -26,8 +26,8 @@ export default definePlugin({ patches: [{ find: "().expandedFolderIconWrapper", replacement: [{ - match: /\(\w\|\|\w\)(&&\(\w=\w\.createElement\(\w+\.animated)/, - replace: "true$1", + match: /\(\w\|\|\w\)&&(\(.{0,40}\(.{1,3}\.animated)/, + replace: "$1", }] }] }); diff --git a/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx b/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx index 4d12dd51a..139fb8a63 100644 --- a/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx +++ b/src/plugins/pronoundb/components/PronounsProfileWrapper.tsx @@ -20,27 +20,28 @@ import { useAwaiter } from "../../../utils/misc"; import { Settings } from "../../../Vencord"; import { UserStore } from "../../../webpack/common"; import { fetchPronouns, formatPronouns } from "../pronoundbUtils"; -import { PronounMapping, UserProfileProps } from "../types"; +import { PronounMapping, UserProfilePronounsProps, UserProfileProps } from "../types"; -export default function PronounsProfileWrapper(props: UserProfileProps, pronounsComponent: JSX.Element) { +export default function PronounsProfileWrapper(PronounsComponent: React.ElementType, props: UserProfilePronounsProps, profileProps: UserProfileProps) { + const user = UserStore.getUser(profileProps.userId) ?? {}; // Don't bother fetching bot or system users - if (props.user.bot || props.user.system) return null; + if (user.bot || user.system) return null; // Respect showSelf options - if (!Settings.plugins.PronounDB.showSelf && props.user.id === UserStore.getCurrentUser().id) return null; + if (!Settings.plugins.PronounDB.showSelf && user.id === UserStore.getCurrentUser().id) + return null; const [result, , isPending] = useAwaiter( - () => fetchPronouns(props.user.id), + () => fetchPronouns(user.id), null, e => console.error("Fetching pronouns failed: ", e) ); - // If the promise completed, the result was not "unspecified", and there is a mapping for the code, then return a span with the pronouns + // If the promise completed, the result was not "unspecified", and there is a mapping for the code, then render if (!isPending && result && result !== "unspecified" && PronounMapping[result]) { // First child is the header, second is a div with the actual text - const [, pronounsBodyComponent] = pronounsComponent.props.children as [JSX.Element, JSX.Element]; - pronounsBodyComponent.props.children = formatPronouns(result); - return pronounsComponent; + props.currentPronouns ||= formatPronouns(result); + return ; } - // Otherwise, return null so nothing else is rendered - else return null; + + return null; } diff --git a/src/plugins/pronoundb/index.ts b/src/plugins/pronoundb/index.ts index 5dfeda5cc..121e0d6e6 100644 --- a/src/plugins/pronoundb/index.ts +++ b/src/plugins/pronoundb/index.ts @@ -44,13 +44,28 @@ export default definePlugin({ }, // Hijack the discord pronouns section (hidden without experiment) and add a wrapper around the text section { - find: ".headerTagUsernameNoNickname", + find: "currentPronouns:", + all: true, replacement: { - match: /(?<=""!==(.{1,2})&&).+?children:\1.+?(?=,)/, - replace: "Vencord.Plugins.plugins.PronounDB.PronounsProfileWrapper(e, $1)" + match: /\(0,.{1,3}\.jsxs?\)\((.{1,10}),(\{[^[}]*currentPronouns:[^}]*(\w)\.pronouns[^}]*\})\)/, + replace: (original, PronounComponent, pronounProps, fullProps) => { + // UserSettings + if (fullProps.includes("onPronounsChange")) return original; + + return `Vencord.Plugins.plugins.PronounDB.PronounsProfileWrapper(${PronounComponent}, ${pronounProps}, ${fullProps})`; + } + } + }, + // Make pronouns experiment be enabled by default + { + find: "2022-01_pronouns", + replacement: { + match: "!1", // false + replace: "!0" } } ], + options: { pronounsFormat: { type: OptionType.SELECT, diff --git a/src/plugins/pronoundb/types.ts b/src/plugins/pronoundb/types.ts index 51e04759a..9cfd77c8a 100644 --- a/src/plugins/pronoundb/types.ts +++ b/src/plugins/pronoundb/types.ts @@ -16,15 +16,13 @@ * along with this program. If not, see . */ -import { User } from "discord-types/general"; - export interface UserProfileProps { - customStatus: JSX.Element, - displayProfile: { - // In the future (if discord ever uses their pronouns system) this taking priority can be a plugin setting - pronouns: string; - }; - user: User; + userId: string; +} + +export interface UserProfilePronounsProps { + currentPronouns: string | null; + hidePersonalInformation: boolean; } export interface PronounsResponse { diff --git a/src/plugins/viewIcons.tsx b/src/plugins/viewIcons.tsx index bd70bd6ce..399bf72b0 100644 --- a/src/plugins/viewIcons.tsx +++ b/src/plugins/viewIcons.tsx @@ -16,15 +16,20 @@ * along with this program. If not, see . */ +import type { Guild } from "discord-types/general"; + import { Devs } from "../utils/constants"; -import { LazyComponent } from "../utils/misc"; +import { LazyComponent, lazyWebpack } from "../utils/misc"; import { ModalRoot, ModalSize, openModal } from "../utils/modal"; import definePlugin from "../utils/types"; -import { find } from "../webpack"; +import { filters, find } from "../webpack"; +import { Menu } from "../webpack/common"; const ImageModal = LazyComponent(() => find(m => m.prototype?.render?.toString().includes("OPEN_ORIGINAL_IMAGE"))); const MaskedLink = LazyComponent(() => find(m => m.type?.toString().includes("MASKED_LINK)"))); +const GuildBannerStore = lazyWebpack(filters.byProps("getGuildBannerURL")); + const OPEN_URL = "Vencord.Plugins.plugins.ViewIcons.openImage("; export default definePlugin({ name: "ViewIcons", @@ -32,6 +37,10 @@ export default definePlugin({ description: "Makes Avatars/Banners in user profiles clickable, and adds Guild Context Menu Entries to View Banner/Icon.", openImage(url: string) { + const u = new URL(url); + u.searchParams.set("size", "512"); + url = u.toString(); + openModal(modalProps => ( `{src:${src},onClick:()=>${OPEN_URL}${src}.replace(/\\?.+$/, "")+"?size=512"),avatarDecoration` + replace: (_, src) => `{src:${src},onClick:()=>${OPEN_URL}${src}),avatarDecoration` } }, { find: "().popoutNoBannerPremium", replacement: { match: /style:.{0,10}\{\},(.{1,2})\)/, - replace: (m, style) => `onClick:${style}.backgroundImage&&(${style}.cursor="pointer",()=>${OPEN_URL}${style}.backgroundImage.replace("url(", "").replace(/(\\?size=.+)?\\)/, "?size=512"))),${m}` + replace: (m, style) => + `onClick:${style}.backgroundImage&&(${style}.cursor="pointer",` + + `()=>${OPEN_URL}${style}.backgroundImage.replace("url(", ""))),${m}` } }, { find: '"GuildContextMenu:', replacement: [ { match: /\w=(\w)\.id/, - replace: (m, guild) => `_guild=${guild},${m}` + replace: "_guild=$1,$&" }, { - match: /(?<=createElement\((.{1,5}),\{id:"leave-guild".{0,100},)(.{1,2}\.createElement)\((.{1,5}),null,(.{1,2})\)(?=\)\}function)/, - replace: (_, menu, createElement, menuGroup, copyIdElement) => - `${createElement}(${menuGroup},null,[` + - `_guild.icon&&${createElement}(${menu},` + - `{id:"viewicons-copy-icon",label:"View Icon",action:()=>${OPEN_URL}_guild.getIconURL(void 0,true)+"size=512")}),` + - `_guild.banner&&${createElement}(${menu},` + - `{id:"viewicons-copy-banner",label:"View Banner",action:()=>${OPEN_URL}Vencord.Webpack.findByProps("getGuildBannerURL").getGuildBannerURL(_guild).replace(/\\?size=.+/, "?size=512"))})` - + `,${copyIdElement}])` + match: /(id:"leave-guild".{0,200}),(\(0,.{1,3}\.jsxs?\).{0,200}function)/, + replace: "$1,Vencord.Plugins.plugins.ViewIcons.buildGuildContextMenuEntries(_guild),$2" } ] } - ] + ], + + buildGuildContextMenuEntries(guild: Guild) { + return ( + + {guild.banner && ( + this.openImage(GuildBannerStore.getGuildBannerURL(guild))} + /> + )} + {guild.icon && ( + this.openImage(guild.getIconURL(0, true))} + /> + )} + + ); + } }); diff --git a/src/plugins/webhookTags.ts b/src/plugins/webhookTags.ts index adf261ad1..e02895af6 100644 --- a/src/plugins/webhookTags.ts +++ b/src/plugins/webhookTags.ts @@ -42,7 +42,7 @@ export default definePlugin({ { find: ".Types.ORIGINAL_POSTER", replacement: { - match: /return null==(.)\?null:.\.createElement\((.)\.Z/, + match: /return null==(.)\?null:\(0,.{1,3}\.jsxs?\)\((.{1,3})\.Z/, replace: (orig, type, BotTag) => `if(arguments[0].message.webhookId&&arguments[0].user.isNonUserBot()){${type}=${BotTag}.Z.Types.WEBHOOK}${orig}`, }, diff --git a/test/generateReport.ts b/test/generateReport.ts index 8bc444f15..7de600458 100644 --- a/test/generateReport.ts +++ b/test/generateReport.ts @@ -37,7 +37,7 @@ const browser = await pup.launch({ }); const page = await browser.newPage(); -await page.setUserAgent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36"); +await page.setUserAgent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36"); function maybeGetError(handle: JSHandle) { return (handle as JSHandle)?.getProperty("message")