diff --git a/src/plugins/apiNotices.ts b/src/plugins/apiNotices.ts index 8922acee..af7cb15e 100644 --- a/src/plugins/apiNotices.ts +++ b/src/plugins/apiNotices.ts @@ -29,13 +29,12 @@ export default definePlugin({ find: 'displayName="NoticeStore"', replacement: [ { - match: /;.{1,2}=null;.{0,70}getPremiumSubscription/g, - replace: - ";if(Vencord.Api.Notices.currentNotice)return false$&" + match: /(?=;\i=null;.{0,70}getPremiumSubscription)/g, + replace: ";if(Vencord.Api.Notices.currentNotice)return false" }, { match: /(?<=,NOTICE_DISMISS:function\(\i\){)(?=if\(null==(\i)\))/, - replace: 'if($1?.id=="VencordNotice")return($1=null,Vencord.Api.Notices.nextNotice(),true);' + replace: (_, notice) => `if(${notice}.id=="VencordNotice")return(${notice}=null,Vencord.Api.Notices.nextNotice(),true);` } ] } diff --git a/src/plugins/crashHandler.ts b/src/plugins/crashHandler.ts index 79db7820..e35dfed6 100644 --- a/src/plugins/crashHandler.ts +++ b/src/plugins/crashHandler.ts @@ -64,8 +64,8 @@ export default definePlugin({ { find: 'dispatch({type:"MODAL_POP_ALL"})', replacement: { - match: /(?<=(?\i)=function\(\){\(0,\i\.\i\)\(\);\i\.\i\.dispatch\({type:"MODAL_POP_ALL"}\).+};)/, - replace: "$self.popAllModals=$;" + match: /"MODAL_POP_ALL".+?};(?<=(\i)=function.+?)/, + replace: (m, popAll) => `${m}$self.popAllModals=${popAll};` } } ], diff --git a/src/plugins/disableDMCallIdle.ts b/src/plugins/disableDMCallIdle.ts index c620f544..2ba861cf 100644 --- a/src/plugins/disableDMCallIdle.ts +++ b/src/plugins/disableDMCallIdle.ts @@ -27,9 +27,9 @@ export default definePlugin({ { find: ".Messages.BOT_CALL_IDLE_DISCONNECT", replacement: { - match: /function (?.{1,3})\(\){.{1,100}\.Messages\.BOT_CALL_IDLE_DISCONNECT.+?}}/, - replace: "function $(){}", - }, - }, - ], + match: /(?<=function \i\(\){)(?=.{1,100}\.Messages\.BOT_CALL_IDLE_DISCONNECT)/, + replace: "return;" + } + } + ] }); diff --git a/src/plugins/experiments.tsx b/src/plugins/experiments.tsx index a3125ae7..686b822d 100644 --- a/src/plugins/experiments.tsx +++ b/src/plugins/experiments.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { definePluginSettings } from "@api/settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; import { findByPropsLazy } from "@webpack"; @@ -24,49 +24,71 @@ import { Forms, React } from "@webpack/common"; const KbdStyles = findByPropsLazy("key", "removeBuildOverride"); +const settings = definePluginSettings({ + enableIsStaff: { + description: "Enable isStaff", + type: OptionType.BOOLEAN, + default: false, + restartNeeded: true + }, + forceStagingBanner: { + description: "Whether to force Staging banner under user area.", + type: OptionType.BOOLEAN, + default: false, + restartNeeded: true + } +}); + export default definePlugin({ name: "Experiments", + description: "Enable Access to Experiments in Discord!", authors: [ Devs.Megu, Devs.Ven, Devs.Nickyux, - Devs.BanTheNons + Devs.BanTheNons, + Devs.Nuckyz ], - description: "Enable Access to Experiments in Discord!", - patches: [{ - find: "Object.defineProperties(this,{isDeveloper", - replacement: { - match: /(?<={isDeveloper:\{[^}]+,get:function\(\)\{return )\w/, - replace: "true" + settings, + + patches: [ + { + find: "Object.defineProperties(this,{isDeveloper", + replacement: { + match: /(?<={isDeveloper:\{[^}]+?,get:function\(\)\{return )\w/, + replace: "true" + } }, - }, { - find: 'type:"user",revision', - replacement: { - match: /!(\w{1,3})&&"CONNECTION_OPEN".+?;/g, - replace: "$1=!0;" + { + find: 'type:"user",revision', + replacement: { + match: /!(\i)&&"CONNECTION_OPEN".+?;/g, + replace: "$1=!0;" + } }, - }, { - find: ".isStaff=function(){", - predicate: () => Settings.plugins.Experiments.enableIsStaff === true, - replacement: [ - { - match: /return\s*(\w+)\.hasFlag\((.+?)\.STAFF\)}/, - replace: "return Vencord.Webpack.Common.UserStore.getCurrentUser().id===$1.id||$1.hasFlag($2.STAFF)}" - }, - { - match: /hasFreePremium=function\(\){return this.isStaff\(\)\s*\|\|/, - replace: "hasFreePremium=function(){return ", - }, - ], - }], - options: { - enableIsStaff: { - description: "Enable isStaff (requires restart)", - type: OptionType.BOOLEAN, - default: false, - restartNeeded: true, + { + find: ".isStaff=function(){", + predicate: () => settings.store.enableIsStaff, + replacement: [ + { + match: /return\s*?(\i)\.hasFlag\((\i\.\i)\.STAFF\)}/, + replace: (_, user, flags) => `return Vencord.Webpack.Common.UserStore.getCurrentUser().id===${user}.id||${user}.hasFlag(${flags}.STAFF)}` + }, + { + match: /hasFreePremium=function\(\){return this.isStaff\(\)\s*?\|\|/, + replace: "hasFreePremium=function(){return ", + } + ] + }, + { + find: ".Messages.DEV_NOTICE_STAGING", + predicate: () => settings.store.forceStagingBanner, + replacement: { + match: /"staging"===window\.GLOBAL_ENV\.RELEASE_CHANNEL/, + replace: "true" + } } - }, + ], settingsAboutComponent: () => { const isMacOS = navigator.platform.includes("Mac"); diff --git a/src/plugins/fakeNitro.ts b/src/plugins/fakeNitro.ts index a09a95a3..e9b19ca1 100644 --- a/src/plugins/fakeNitro.ts +++ b/src/plugins/fakeNitro.ts @@ -72,7 +72,7 @@ migratePluginSettings("FakeNitro", "NitroBypass"); export default definePlugin({ name: "FakeNitro", - authors: [Devs.Arjix, Devs.D3SOX, Devs.Ven, Devs.obscurity, Devs.captain], + authors: [Devs.Arjix, Devs.D3SOX, Devs.Ven, Devs.obscurity, Devs.captain, Devs.Nuckyz], description: "Allows you to stream in nitro quality, send fake emojis/stickers and use client themes.", dependencies: ["MessageEventsAPI"], @@ -82,16 +82,16 @@ export default definePlugin({ predicate: () => Settings.plugins.FakeNitro.enableEmojiBypass === true, replacement: [ { - match: /(?<=(?\i)=\i\.intention)/, - replace: ",fakeNitroIntention=$" + match: /(?<=(\i)=\i\.intention)/, + replace: (_, intention) => `,fakeNitroIntention=${intention}` }, { match: /(?<=\.(?:canUseEmojisEverywhere|canUseAnimatedEmojis)\(\i)(?=\))/g, replace: ',typeof fakeNitroIntention!=="undefined"?fakeNitroIntention:void 0' }, { - match: /(?<=&&!\i&&)!(?\i)(?=\)return \i\.\i\.DISALLOW_EXTERNAL;)/, - replace: `(!$&&(typeof fakeNitroIntention==="undefined"||![${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)))` + match: /(?<=&&!\i&&)!(\i)(?=\)return \i\.\i\.DISALLOW_EXTERNAL;)/, + replace: (_, canUseExternal) => `(!${canUseExternal}&&(typeof fakeNitroIntention==="undefined"||![${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)))` } ] }, @@ -99,16 +99,16 @@ export default definePlugin({ find: "canUseAnimatedEmojis:function", predicate: () => Settings.plugins.FakeNitro.enableEmojiBypass === true, replacement: { - match: /(?<=(?:canUseEmojisEverywhere|canUseAnimatedEmojis):function\((?\i))\){(?.+?\))/g, - replace: `,fakeNitroIntention){$||fakeNitroIntention==null||[${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)` + match: /(?<=(?:canUseEmojisEverywhere|canUseAnimatedEmojis):function\(\i)\){(.+?\))/g, + replace: (_, premiumCheck) => `,fakeNitroIntention){${premiumCheck}||fakeNitroIntention==null||[${EmojiIntentions.CHAT},${EmojiIntentions.GUILD_STICKER_RELATED_EMOJI}].includes(fakeNitroIntention)` } }, { find: "canUseStickersEverywhere:function", predicate: () => Settings.plugins.FakeNitro.enableStickerBypass === true, replacement: { - match: /canUseStickersEverywhere:function\(.+?\{/, - replace: "$&return true;" + match: /(?<=canUseStickersEverywhere:function\(\i\){)/, + replace: "return true;" }, }, { @@ -128,8 +128,8 @@ export default definePlugin({ "canStreamMidQuality" ].map(func => { return { - match: new RegExp(`${func}:function\\(.+?\\{`), - replace: "$&return true;" + match: new RegExp(`(?<=${func}:function\\(\\i\\){)`), + replace: "return true;" }; }) }, diff --git a/src/plugins/ignoreActivities.tsx b/src/plugins/ignoreActivities.tsx index 3d53bbc0..07b458f8 100644 --- a/src/plugins/ignoreActivities.tsx +++ b/src/plugins/ignoreActivities.tsx @@ -21,7 +21,7 @@ import ErrorBoundary from "@components/ErrorBoundary"; import { Devs } from "@utils/constants"; import { useForceUpdater } from "@utils/misc"; import definePlugin from "@utils/types"; -import { findByPropsLazy } from "@webpack"; +import { findByPropsLazy, findStoreLazy } from "@webpack"; import { Tooltip } from "webpack/common"; enum ActivitiesTypes { @@ -37,7 +37,7 @@ interface IgnoredActivity { const RegisteredGamesClasses = findByPropsLazy("overlayToggleIconOff", "overlayToggleIconOn"); const TryItOutClasses = findByPropsLazy("tryItOutBadge", "tryItOutBadgeIcon"); const BaseShapeRoundClasses = findByPropsLazy("baseShapeRound", "baseShapeRoundLeft", "baseShapeRoundRight"); -const RunningGameStore = findByPropsLazy("getRunningGames", "getGamesSeen"); +const RunningGameStore = findStoreLazy("RunningGameStore"); function ToggleIconOff() { return ( @@ -71,7 +71,7 @@ function ToggleIconOff() { ); } -function ToggleIconOn() { +function ToggleIconOn({ forceWhite }: { forceWhite?: boolean; }) { return ( ); } -function ToggleActivityComponent({ activity }: { activity: IgnoredActivity; }) { +function ToggleActivityComponent({ activity, forceWhite }: { activity: IgnoredActivity; forceWhite?: boolean; }) { const forceUpdate = useForceUpdater(); return ( @@ -105,7 +106,7 @@ function ToggleActivityComponent({ activity }: { activity: IgnoredActivity; }) { { ignoredActivitiesCache.has(activity.id) ? - : + : } )} @@ -117,9 +118,9 @@ function ToggleActivityComponentWithBackground({ activity }: { activity: Ignored return (
- +
); } @@ -142,28 +143,32 @@ export default definePlugin({ name: "IgnoreActivities", authors: [Devs.Nuckyz], description: "Ignore certain activities (like games and actual activities) from showing up on your status. You can configure which ones are ignored from the Registered Games and Activities tabs.", - patches: [{ - find: ".Messages.SETTINGS_GAMES_TOGGLE_OVERLAY", - replacement: { - match: /!(\i)\|\|(null==\i\)return null;var \i=(\i)\.overlay.+?children:)(\[.{0,70}overlayStatusText.+?\])(?=}\)}\(\))/, - replace: (_, platformCheck, restWithoutPlatformCheck, props, children) => "" - + `${restWithoutPlatformCheck}` - + `(${platformCheck}?${children}:[])` - + `.concat(Vencord.Plugins.plugins.IgnoreActivities.renderToggleGameActivityButton(${props}))` + patches: [ + { + find: ".Messages.SETTINGS_GAMES_TOGGLE_OVERLAY", + replacement: { + match: /!(\i)\|\|(null==\i\)return null;var \i=(\i)\.overlay.+?children:)(\[.{0,70}overlayStatusText.+?\])(?=}\)}\(\))/, + replace: (_, platformCheck, restWithoutPlatformCheck, props, children) => "" + + `${restWithoutPlatformCheck}` + + `(${platformCheck}?${children}:[])` + + `.concat(Vencord.Plugins.plugins.IgnoreActivities.renderToggleGameActivityButton(${props}))` + } + }, + { + find: ".overlayBadge", + replacement: { + match: /(?<=\(\)\.badgeContainer.+?(\i)\.name}\):null)/, + replace: (_, props) => `,$self.renderToggleActivityButton(${props})` + } + }, + { + find: '.displayName="LocalActivityStore"', + replacement: { + match: /LISTENING.+?\)\);(?<=(\i)\.push.+?)/, + replace: (m, activities) => `${m}${activities}=${activities}.filter($self.isActivityNotIgnored);` + } } - }, { - find: ".overlayBadge", - replacement: { - match: /.badgeContainer.+?.\?\(0,.\.jsx\)\(.{1,2},{name:(?.)\.name}\):null/, - replace: "$&,$self.renderToggleActivityButton($)" - } - }, { - find: '.displayName="LocalActivityStore"', - replacement: { - match: /(?.)\.push\(.\({type:.\..{1,3}\.LISTENING.+?\)\)/, - replace: "$&;$=$.filter($self.isActivityNotIgnored);" - } - }], + ], async start() { const ignoredActivitiesData = await DataStore.get>("IgnoreActivities_ignoredActivities") ?? new Map(); @@ -217,5 +222,5 @@ export default definePlugin({ } } return true; - }, + } }); diff --git a/src/plugins/moyai.ts b/src/plugins/moyai.ts index fabc97fb..146ac3f6 100644 --- a/src/plugins/moyai.ts +++ b/src/plugins/moyai.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { Settings } from "@api/settings"; +import { definePluginSettings } from "@api/settings"; import { makeRange } from "@components/PluginSettings/components/SettingSliderComponent"; import { Devs } from "@utils/constants"; import { sleep } from "@utils/misc"; @@ -54,15 +54,36 @@ const MOYAI = "🗿"; const MOYAI_URL = "https://raw.githubusercontent.com/MeguminSama/VencordPlugins/main/plugins/moyai/moyai.mp3"; +const settings = definePluginSettings({ + volume: { + description: "Volume of the 🗿🗿🗿", + type: OptionType.SLIDER, + markers: makeRange(0, 1, 0.1), + default: 0.5, + stickToMarkers: false + }, + triggerWhenUnfocused: { + description: "Trigger the 🗿 even when the window is unfocused", + type: OptionType.BOOLEAN, + default: true + }, + ignoreBots: { + description: "Ignore bots", + type: OptionType.BOOLEAN, + default: true + } +}); + export default definePlugin({ name: "Moyai", authors: [Devs.Megu, Devs.Nuckyz], description: "🗿🗿🗿🗿🗿🗿🗿🗿", + settings, async onMessage(e: IMessageCreate) { if (e.optimistic || e.type !== "MESSAGE_CREATE") return; if (e.message.state === "SENDING") return; - if (Settings.plugins.Moyai.ignoreBots && e.message.author?.bot) return; + if (settings.store.ignoreBots && e.message.author?.bot) return; if (!e.message.content) return; if (e.channelId !== SelectedChannelStore.getChannelId()) return; @@ -76,7 +97,7 @@ export default definePlugin({ onReaction(e: IReactionAdd) { if (e.optimistic || e.type !== "MESSAGE_REACTION_ADD") return; - if (Settings.plugins.Moyai.ignoreBots && UserStore.getUser(e.userId)?.bot) return; + if (settings.store.ignoreBots && UserStore.getUser(e.userId)?.bot) return; if (e.channelId !== SelectedChannelStore.getChannelId()) return; const name = e.emoji.name.toLowerCase(); @@ -103,28 +124,6 @@ export default definePlugin({ FluxDispatcher.unsubscribe("MESSAGE_CREATE", this.onMessage); FluxDispatcher.unsubscribe("MESSAGE_REACTION_ADD", this.onReaction); FluxDispatcher.unsubscribe("VOICE_CHANNEL_EFFECT_SEND", this.onVoiceChannelEffect); - }, - - options: { - volume: { - description: "Volume of the 🗿🗿🗿", - type: OptionType.SLIDER, - markers: makeRange(0, 1, 0.1), - default: 0.5, - stickToMarkers: false, - }, - triggerWhenUnfocused: { - description: "Trigger the 🗿 even when the window is unfocused", - type: OptionType.BOOLEAN, - default: true, - restartNeeded: false, - }, - ignoreBots: { - description: "Ignore bots", - type: OptionType.BOOLEAN, - default: true, - restartNeeded: false, - } } }); @@ -158,9 +157,9 @@ function getMoyaiCount(message: string) { } function boom() { - if (!Settings.plugins.Moyai.triggerWhenUnfocused && !document.hasFocus()) return; + if (!settings.store.triggerWhenUnfocused && !document.hasFocus()) return; const audioElement = document.createElement("audio"); audioElement.src = MOYAI_URL; - audioElement.volume = Settings.plugins.Moyai.volume; + audioElement.volume = settings.store.volume; audioElement.play(); } diff --git a/src/plugins/noScreensharePreview.ts b/src/plugins/noScreensharePreview.ts index b09f2063..50b2a964 100644 --- a/src/plugins/noScreensharePreview.ts +++ b/src/plugins/noScreensharePreview.ts @@ -30,9 +30,9 @@ export default definePlugin({ "\\i\\.default\\.makeChunkedRequest\\(", "\\i\\.\\i\\.post\\({url:" ].map(match => ({ - match: new RegExp(`return\\[(?\\d),${match}\\i\\.\\i\\.STREAM_PREVIEW.+?}\\)\\];`), - replace: 'return[$,Promise.resolve({body:"",status:204})];' + match: new RegExp(`(?=return\\[(\\d),${match}\\i\\.\\i\\.STREAM_PREVIEW.+?}\\)\\];)`), + replace: (_, code) => `return[${code},Promise.resolve({body:"",status:204})];` })) - }, - ], + } + ] }); diff --git a/src/plugins/pronoundb/index.ts b/src/plugins/pronoundb/index.ts index 7ebe9192..820b66ec 100644 --- a/src/plugins/pronoundb/index.ts +++ b/src/plugins/pronoundb/index.ts @@ -41,7 +41,7 @@ export default definePlugin({ replace: "[$1, $self.PronounsChatComponent(e)]" } }, - // Hijack the discord pronouns section (hidden without experiment) and add a wrapper around the text section + // Hijack the discord pronouns section and add a wrapper around the text section { find: ".Messages.BOT_PROFILE_SLASH_COMMANDS", replacement: { @@ -49,12 +49,12 @@ export default definePlugin({ replace: "$&&$self.PronounsProfileWrapper($,$,$)" } }, - // Make pronouns experiment be enabled by default + // Force enable pronouns component ignoring the experiment value { - find: "2022-01_pronouns", + find: ".Messages.USER_POPOUT_PRONOUNS", replacement: { - match: "!1", // false - replace: "!0" + match: /\i\.\i\.useExperiment\({}\)\.showPronouns/, + replace: "true" } } ], diff --git a/src/plugins/revealAllSpoilers.ts b/src/plugins/revealAllSpoilers.ts index ead169fc..9cb7b6b4 100644 --- a/src/plugins/revealAllSpoilers.ts +++ b/src/plugins/revealAllSpoilers.ts @@ -32,8 +32,8 @@ export default definePlugin({ { find: ".removeObscurity=function", replacement: { - match: /\.removeObscurity=function\((\i)\){/, - replace: ".removeObscurity=function($1){$self.reveal($1);" + match: /(?<=\.removeObscurity=function\((\i)\){)/, + replace: (_, event) => `$self.reveal(${event});` } } ], diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx index 60e0c51f..70c5045b 100644 --- a/src/plugins/showHiddenChannels/index.tsx +++ b/src/plugins/showHiddenChannels/index.tsx @@ -64,29 +64,29 @@ export default definePlugin({ patches: [ { // RenderLevel defines if a channel is hidden, collapsed in category, visible, etc - find: ".CannotShow", + find: ".CannotShow=", // These replacements only change the necessary CannotShow's replacement: [ { - match: /(?<=isChannelGatedAndVisible\(this\.record\.guild_id,this\.record\.id\).+?renderLevel:)(?\i)\..+?(?=,)/, - replace: "this.category.isCollapsed?$.WouldShowIfUncollapsed:$.Show" + match: /(?<=isChannelGatedAndVisible\(this\.record\.guild_id,this\.record\.id\).+?renderLevel:)(\i)\..+?(?=,)/, + replace: (_, RenderLevels) => `this.category.isCollapsed?${RenderLevels}.WouldShowIfUncollapsed:${RenderLevels}.Show` }, // Move isChannelGatedAndVisible renderLevel logic to the bottom to not show hidden channels in case they are muted { - match: /(?<=(?if\(!\i\.\i\.can\(\i\.\i\.VIEW_CHANNEL.+?{)if\(this\.id===\i\).+?};)(?if\(!\i\.\i\.isChannelGatedAndVisible\(.+?})(?.+?)(?=return{renderLevel:\i\.Show.{1,40}return \i)/, - replace: "$$$}" + match: /(?<=(if\(!\i\.\i\.can\(\i\.\i\.VIEW_CHANNEL.+?{)if\(this\.id===\i\).+?};)(if\(!\i\.\i\.isChannelGatedAndVisible\(.+?})(.+?)(?=return{renderLevel:\i\.Show.{0,40}?return \i)/, + replace: (_, permissionCheck, isChannelGatedAndVisibleCondition, rest) => `${rest}${permissionCheck}${isChannelGatedAndVisibleCondition}}` }, { - match: /(?<=renderLevel:(?\i\(this,\i\)\?\i\.Show:\i\.WouldShowIfUncollapsed).+?renderLevel:).+?(?=,)/, - replace: "$" + match: /(?<=renderLevel:(\i\(this,\i\)\?\i\.Show:\i\.WouldShowIfUncollapsed).+?renderLevel:).+?(?=,)/, + replace: (_, renderLevelExpression) => renderLevelExpression }, { - match: /(?<=activeJoinedRelevantThreads.+?renderLevel:.+?,threadIds:\i\(this.record.+?renderLevel:)(?\i)\..+?(?=,)/, - replace: "$.Show" + match: /(?<=activeJoinedRelevantThreads.+?renderLevel:.+?,threadIds:\i\(this.record.+?renderLevel:)(\i)\..+?(?=,)/, + replace: (_, RenderLevels) => `${RenderLevels}.Show` }, { - match: /(?<=getRenderLevel=function.+?return ).+?\?(?.+?):\i\.CannotShow(?=})/, - replace: "$" + match: /(?<=getRenderLevel=function.+?return ).+?\?(.+?):\i\.CannotShow(?=})/, + replace: (_, renderLevelExpressionWithoutPermCheck) => renderLevelExpressionWithoutPermCheck } ] }, @@ -95,18 +95,18 @@ export default definePlugin({ replacement: [ { // Do not show confirmation to join a voice channel when already connected to another if clicking on a hidden voice channel - match: /(?<=getCurrentClientVoiceChannelId\(\i\.guild_id\);if\()(?=.+?\((?\i)\))/, - replace: "!$self.isHiddenChannel($)&&" + match: /(?<=getCurrentClientVoiceChannelId\((\i)\.guild_id\);if\()/, + replace: (_, channel) => `!$self.isHiddenChannel(${channel})&&` }, { // Make Discord think we are connected to a voice channel so it shows us inside it - match: /(?=\|\|\i\.default\.selectVoiceChannel\((?\i)\.id\))/, - replace: "||$self.isHiddenChannel($)" + match: /(?=\|\|\i\.default\.selectVoiceChannel\((\i)\.id\))/, + replace: (_, channel) => `||$self.isHiddenChannel(${channel})` }, { // Make Discord think we are connected to a voice channel so it shows us inside it - match: /(?<=\|\|\i\.default\.selectVoiceChannel\((?\i)\.id\);!__OVERLAY__&&\()/, - replace: "$self.isHiddenChannel($)||" + match: /(?<=\|\|\i\.default\.selectVoiceChannel\((\i)\.id\);!__OVERLAY__&&\()/, + replace: (_, channel) => `$self.isHiddenChannel(${channel})||` } ] }, @@ -119,7 +119,7 @@ export default definePlugin({ "renderInviteButton", "renderOpenChatButton" ].map(func => ({ - match: new RegExp(`(?<=\\i\\.${func}=function\\(\\){)`, "g"), // Global because Discord has multiple declarations of the same functions + match: new RegExp(`(?<=${func}=function\\(\\){)`, "g"), // Global because Discord has multiple declarations of the same functions replace: "if($self.isHiddenChannel(this.props.channel))return null;" })) ] @@ -129,17 +129,8 @@ export default definePlugin({ predicate: () => settings.store.showMode === ShowMode.LockIcon, replacement: { // Lock Icon - match: /(?=switch\((?\i)\.type\).{1,30}\.GUILD_ANNOUNCEMENT.{1,30}\(0,\i\.\i\))/, - replace: "if($self.isHiddenChannel($))return $self.LockIcon;" - } - }, - { - find: ".UNREAD_HIGHLIGHT", - predicate: () => settings.store.hideUnreads === true, - replacement: { - // Hide unreads - match: /(?<=\i\.connected,\i=)(?=(?\i)\.unread)/, - replace: "$self.isHiddenChannel($.channel)?false:" + match: /(?=switch\((\i)\.type\).{0,30}\.GUILD_ANNOUNCEMENT.{0,30}\(0,\i\.\i\))/, + replace: (_, channel) => `if($self.isHiddenChannel(${channel}))return $self.LockIcon;` } }, { @@ -148,36 +139,44 @@ export default definePlugin({ replacement: [ // Make the channel appear as muted if it's hidden { - match: /(?<=\i\.name,\i=)(?=(?\i)\.muted)/, - replace: "$self.isHiddenChannel($.channel)?true:" + match: /(?<=\i\.name,\i=)(?=(\i)\.muted)/, + replace: (_, props) => `$self.isHiddenChannel(${props}.channel)?true:` }, // Add the hidden eye icon if the channel is hidden { - match: /(?<=(?\i)=\i\.channel,.+?\(\)\.children.+?:null)/, - replace: ",$self.isHiddenChannel($)?$self.HiddenChannelIcon():null" + match: /\(\).children.+?:null(?<=(\i)=\i\.channel,.+?)/, + replace: (m, channel) => `${m},$self.isHiddenChannel(${channel})?$self.HiddenChannelIcon():null` }, // Make voice channels also appear as muted if they are muted { - match: /(?<=\i\(\)\.wrapper:\i\(\)\.notInteractive,)(?.+?)(?(?\i)\?\i\.MUTED)/, - replace: "$:\"\",$$?\"\"" + match: /(?<=\.wrapper:\i\(\)\.notInteractive,)(.+?)((\i)\?\i\.MUTED)/, + replace: (_, otherClasses, mutedClassExpression, isMuted) => `${mutedClassExpression}:"",${otherClasses}${isMuted}?""` } ] }, - // Make muted channels also appear as unread if hide unreads is false, using the HiddenIconWithMutedStyle and the channel is hidden { find: ".UNREAD_HIGHLIGHT", - predicate: () => settings.store.hideUnreads === false && settings.store.showMode === ShowMode.HiddenIconWithMutedStyle, - replacement: { - match: /(?<=(?\i)=\i\.channel,.+?\.LOCKED:\i)/, - replace: "&&!($self.settings.store.hideUnreads===false&&$self.isHiddenChannel($))" - } + replacement: [ + { + // Make muted channels also appear as unread if hide unreads is false, using the HiddenIconWithMutedStyle and the channel is hidden + predicate: () => settings.store.hideUnreads === false && settings.store.showMode === ShowMode.HiddenIconWithMutedStyle, + match: /\.LOCKED:\i(?<=(\i)=\i\.channel,.+?)/, + replace: (m, channel) => `${m}&&!$self.isHiddenChannel(${channel})` + }, + { + // Hide unreads + predicate: () => settings.store.hideUnreads === true, + match: /(?<=\i\.connected,\i=)(?=(\i)\.unread)/, + replace: (_, props) => `$self.isHiddenChannel(${props}.channel)?false:` + } + ] }, { // Hide New unreads box for hidden channels find: '.displayName="ChannelListUnreadsStore"', replacement: { - match: /(?<=return null!=(?\i))(?=.{1,130}hasRelevantUnread\(\i\))/g, // Global because Discord has multiple methods like that in the same module - replace: "&&!$self.isHiddenChannel($)" + match: /(?<=return null!=(\i))(?=.{0,130}?hasRelevantUnread\(\i\))/g, // Global because Discord has multiple methods like that in the same module + replace: (_, channel) => `&&!$self.isHiddenChannel(${channel})` } }, // Only render the channel header and buttons that work when transitioning to a hidden channel @@ -185,20 +184,20 @@ export default definePlugin({ find: "Missing channel in Channel.renderHeaderToolbar", replacement: [ { - match: /(?<=renderHeaderToolbar=function.+?case \i\.\i\.GUILD_TEXT:)(?=.+?;(?.+?{channel:(?\i)},"notifications"\)\);))/, - replace: "if($self.isHiddenChannel($)){$break;}" + match: /(?<=renderHeaderToolbar=function.+?case \i\.\i\.GUILD_TEXT:)(?=.+?;(.+?{channel:(\i)},"notifications"\)\);))/, + replace: (_, pushNotificationButtonExpression, channel) => `if($self.isHiddenChannel(${channel})){${pushNotificationButtonExpression}break;}` }, { - match: /(?<=renderHeaderToolbar=function.+?case \i\.\i\.GUILD_FORUM:if\(!\i\){)(?=.+?;(?.+?{channel:(?\i)},"notifications"\)\)))/, - replace: "if($self.isHiddenChannel($)){$;break;}" + match: /(?<=renderHeaderToolbar=function.+?case \i\.\i\.GUILD_FORUM:if\(!\i\){)(?=.+?;(.+?{channel:(\i)},"notifications"\)\)))/, + replace: (_, pushNotificationButtonExpression, channel) => `if($self.isHiddenChannel(${channel})){${pushNotificationButtonExpression};break;}` }, { - match: /(?<=(?\i)\.renderMobileToolbar=function.+?case \i\.\i\.GUILD_FORUM:)/, - replace: "if($self.isHiddenChannel($.props.channel))break;" + match: /renderMobileToolbar=function.+?case \i\.\i\.GUILD_FORUM:(?<=(\i)\.renderMobileToolbar.+?)/, + replace: (m, that) => `${m}if($self.isHiddenChannel(${that}.props.channel))break;` }, { - match: /(?<=renderHeaderBar=function.+?hideSearch:(?\i)\.isDirectory\(\))/, - replace: "||$self.isHiddenChannel($)" + match: /(?<=renderHeaderBar=function.+?hideSearch:(\i)\.isDirectory\(\))/, + replace: (_, channel) => `||$self.isHiddenChannel(${channel})` }, { match: /(?<=renderSidebar=function\(\){)/, @@ -213,25 +212,23 @@ export default definePlugin({ // Avoid trying to fetch messages from hidden channels { find: '"MessageManager"', - replacement: [ - { - match: /(?<=if\(null!=(?\i)\).{1,100}"Skipping fetch because channelId is a static route".{1,10}else{)/, - replace: "if($self.isHiddenChannel({channelId:$}))return;" - }, - ] + replacement: { + match: /"Skipping fetch because channelId is a static route"\);else{(?=.+?getChannel\((\i)\))/, + replace: (m, channelId) => `${m}if($self.isHiddenChannel({channelId:${channelId}}))return;` + } }, // Patch keybind handlers so you can't accidentally jump to hidden channels { find: '"alt+shift+down"', replacement: { - match: /(?<=getChannel\(\i\);return null!=(?\i))(?=.{1,130}hasRelevantUnread\(\i\))/, - replace: "&&!$self.isHiddenChannel($)" + match: /(?<=getChannel\(\i\);return null!=(\i))(?=.{0,130}?hasRelevantUnread\(\i\))/, + replace: (_, channel) => `&&!$self.isHiddenChannel(${channel})` } }, { find: '"alt+down"', replacement: { - match: /(?<=getState\(\)\.channelId.{1,30}\(0,\i\.\i\)\(\i\))(?=\.map\()/, + match: /(?<=getState\(\)\.channelId.{0,30}?\(0,\i\.\i\)\(\i\))(?=\.map\()/, replace: ".filter(ch=>!$self.isHiddenChannel(ch))" } }, @@ -239,8 +236,8 @@ export default definePlugin({ { find: 'jumboable?"jumbo":"default"', replacement: { - match: /(?<=(?\i)=function.{1,20}node,\i=\i.isInteracting.+?}}\)},)/, - replace: "shcEmojiComponentExport=($self.setEmojiComponent($),void 0)," + match: /jumboable\?"jumbo":"default",emojiId.+?}}\)},(?<=(\i)=function\(\i\){var \i=\i\.node.+?)/, + replace: (m, component) => `${m}shcEmojiComponentExport=($self.setEmojiComponent(${component}),void 0),` } }, { @@ -248,13 +245,13 @@ export default definePlugin({ replacement: [ { // Export the channel beggining header - match: /(?<=function (?\i)\(.{1,600}computePermissionsForRoles.+?}\)})(?=var)/, - replace: "$self.setChannelBeginHeaderComponent($);" + match: /computePermissionsForRoles.+?}\)}(?<=function (\i)\(.+?)(?=var)/, + replace: (m, component) => `${m}$self.setChannelBeginHeaderComponent(${component});` }, { // Patch the header to only return allowed users and roles if it's a hidden channel (Like when it's used on the HiddenChannelLockScreen) - match: /(?<=MANAGE_ROLES.{1,60}return)(?=\(.+?(?\(0,\i\.jsxs\)\("div",{className:\i\(\)\.members.+?guildId:(?\i)\.guild_id.+?roleColor.+?]}\)))/, - replace: " $self.isHiddenChannel($)?$:" + match: /MANAGE_ROLES.{0,60}?return(?=\(.+?(\(0,\i\.jsxs\)\("div",{className:\i\(\)\.members.+?guildId:(\i)\.guild_id.+?roleColor.+?]}\)))/, + replace: (m, component, channel) => `${m} $self.isHiddenChannel(${channel})?${component}:` } ] }, @@ -263,23 +260,23 @@ export default definePlugin({ replacement: [ { // Remove the divider and the open chat button for the HiddenChannelLockScreen - match: /(?<=function \i\((?\i)\).{1,2000}"more-options-popout"\)\);if\()/, - replace: "(!$self.isHiddenChannel($.channel)||$.inCall)&&" + match: /"more-options-popout"\)\);if\((?<=function \i\((\i)\).+?)/, + replace: (m, props) => `${m}(!$self.isHiddenChannel(${props}.channel)||${props}.inCall)&&` }, { // Render our HiddenChannelLockScreen component instead of the main voice channel component - match: /(?<=renderContent=function.{1,1700}children:)/, - replace: "!this.props.inCall&&$self.isHiddenChannel(this.props.channel)?$self.HiddenChannelLockScreen(this.props.channel):" + match: /this\.renderVoiceChannelEffects.+?children:(?<=renderContent=function.+?)/, + replace: "$&!this.props.inCall&&$self.isHiddenChannel(this.props.channel)?$self.HiddenChannelLockScreen(this.props.channel):" }, { // Disable gradients for the HiddenChannelLockScreen of voice channels - match: /(?<=renderContent=function.{1,1600}disableGradients:)/, - replace: "!this.props.inCall&&$self.isHiddenChannel(this.props.channel)||" + match: /this\.renderVoiceChannelEffects.+?disableGradients:(?<=renderContent=function.+?)/, + replace: "$&!this.props.inCall&&$self.isHiddenChannel(this.props.channel)||" }, { // Disable useless components for the HiddenChannelLockScreen of voice channels - match: /(?<=renderContent=function.{1,800}render(?!Header).{0,30}:)(?!void)/g, - replace: "!this.props.inCall&&$self.isHiddenChannel(this.props.channel)?null:" + match: /(?:{|,)render(?!Header|ExternalHeader).{0,30}?:(?<=renderContent=function.+?)(?!void)/g, + replace: "$&!this.props.inCall&&$self.isHiddenChannel(this.props.channel)?null:" } ] }, @@ -288,40 +285,58 @@ export default definePlugin({ replacement: [ { // Render our HiddenChannelLockScreen component instead of the main stage channel component - match: /(?<=(?\i)\.getGuildId\(\).{1,30}Guild voice channel without guild id\..{1,1400}children:)(?=.{1,20}}\)}function)/, - replace: "$self.isHiddenChannel($)?$self.HiddenChannelLockScreen($):" + match: /Guild voice channel without guild id.+?children:(?<=(\i)\.getGuildId\(\).+?)(?=.{0,20}?}\)}function)/, + replace: (m, channel) => `${m}$self.isHiddenChannel(${channel})?$self.HiddenChannelLockScreen(${channel}):` }, { // Disable useless components for the HiddenChannelLockScreen of stage channels - match: /(?<=(?\i)\.getGuildId\(\).{1,30}Guild voice channel without guild id\..{1,1000}render(?!Header).{0,30}:)/g, - replace: "$self.isHiddenChannel($)?null:" + match: /render(?!Header).{0,30}?:(?<=(\i)\.getGuildId\(\).+?Guild voice channel without guild id.+?)/g, + replace: (m, channel) => `${m}$self.isHiddenChannel(${channel})?null:` }, // Prevent Discord from replacing our route if we aren't connected to the stage channel { - match: /(?<=if\()(?=!\i&&!\i&&!\i.{1,80}(?\i)\.getGuildId\(\).{1,50}Guild voice channel without guild id\.)/, - replace: "!$self.isHiddenChannel($)&&" + match: /(?=!\i&&!\i&&!\i.{0,80}?(\i)\.getGuildId\(\).{0,50}?Guild voice channel without guild id)(?<=if\()/, + replace: (_, channel) => `!$self.isHiddenChannel(${channel})&&` }, { // Disable gradients for the HiddenChannelLockScreen of stage channels - match: /(?<=(?\i)\.getGuildId\(\).{1,30}Guild voice channel without guild id\..{1,600}disableGradients:)/, - replace: "$self.isHiddenChannel($)||" + match: /Guild voice channel without guild id.+?disableGradients:(?<=(\i)\.getGuildId\(\).+?)/, + replace: (m, channel) => `${m}$self.isHiddenChannel(${channel})||` }, { // Disable strange styles applied to the header for the HiddenChannelLockScreen of stage channels - match: /(?<=(?\i)\.getGuildId\(\).{1,30}Guild voice channel without guild id\..{1,600}style:)/, - replace: "$self.isHiddenChannel($)?undefined:" + match: /Guild voice channel without guild id.+?style:(?<=(\i)\.getGuildId\(\).+?)/, + replace: (m, channel) => `${m}$self.isHiddenChannel(${channel})?undefined:` }, { // Remove the divider and amount of users in stage channel components for the HiddenChannelLockScreen - match: /\(0,\i\.jsx\)\(\i\.\i\.Divider.+?}\)]}\)(?=.+?:(?\i)\.guild_id)/, - replace: "$self.isHiddenChannel($)?null:($&)" + match: /\(0,\i\.jsx\)\(\i\.\i\.Divider.+?}\)]}\)(?=.+?:(\i)\.guild_id)/, + replace: (m, channel) => `$self.isHiddenChannel(${channel})?null:(${m})` }, { // Remove the open chat button for the HiddenChannelLockScreen - match: /(?<=null,)(?=.{1,120}channelId:(?\i)\.id,.+?toggleRequestToSpeakSidebar:\i,iconClassName:\i\(\)\.buttonIcon)/, - replace: "!$self.isHiddenChannel($)&&" + match: /"recents".+?null,(?=.{0,120}?channelId:(\i)\.id)/, + replace: (m, channel) => `${m}!$self.isHiddenChannel(${channel})&&` } ], + }, + { + // The module wasn't being found, so lets just escape everything + // eslint-disable-next-line no-useless-escape + find: "\^https\:\/\/\(\?\:canary\.\|ptb\.\)\?discord.com\/channels\/\(\\\\\d\+\|", + replacement: { + // Make mentions of hidden channels work + match: /\i\.\i\.can\(\i\.\i\.VIEW_CHANNEL,\i\)/, + replace: "true" + }, + }, + { + find: ".shouldCloseDefaultModals", + replacement: { + // Show inside voice channel instead of trying to join them when clicking on a channel mention + match: /(?<=getChannel\((\i)\)\)(?=.{0,100}?selectVoiceChannel))/, + replace: (_, channelId) => `&&!$self.isHiddenChannel({channelId:${channelId}})` + } } ], diff --git a/src/plugins/spotifyCrack.ts b/src/plugins/spotifyCrack.ts index c64154aa..2682ccb4 100644 --- a/src/plugins/spotifyCrack.ts +++ b/src/plugins/spotifyCrack.ts @@ -16,53 +16,55 @@ * along with this program. If not, see . */ -import { migratePluginSettings, Settings } from "@api/settings"; +import { definePluginSettings, migratePluginSettings } from "@api/settings"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; +const settings = definePluginSettings({ + noSpotifyAutoPause: { + description: "Disable Spotify auto-pause", + type: OptionType.BOOLEAN, + default: true, + restartNeeded: true + }, + keepSpotifyActivityOnIdle: { + description: "Keep Spotify activity playing when idling", + type: OptionType.BOOLEAN, + default: false, + restartNeeded: true + } +}); + migratePluginSettings("SpotifyCrack", "Ify"); export default definePlugin({ name: "SpotifyCrack", description: "Free listen along, no auto-pausing in voice chat, and allows activity to continue playing when idling", - authors: [ - Devs.Cyn, - Devs.Nuckyz - ], + authors: [Devs.Cyn, Devs.Nuckyz], + settings, - patches: [{ - find: 'dispatch({type:"SPOTIFY_PROFILE_UPDATE"', - replacement: [{ - match: /(function\((.{1,2})\){)(.{1,6}dispatch\({type:"SPOTIFY_PROFILE_UPDATE")/, - replace: (_, functionStart, data, functionBody) => `${functionStart}${data}.body.product="premium";${functionBody}` - }], - }, { - find: '.displayName="SpotifyStore"', - predicate: () => Settings.plugins.SpotifyCrack.noSpotifyAutoPause, - replacement: { - match: /function (.{1,2})\(\).{0,200}SPOTIFY_AUTO_PAUSED\);.{0,}}}}/, - replace: "function $1(){}" - } - }, { - find: '.displayName="SpotifyStore"', - predicate: () => Settings.plugins.SpotifyCrack.keepSpotifyActivityOnIdle, - replacement: { - match: /(shouldShowActivity=function\(\){.{1,50})&&!.{1,6}\.isIdle\(\)(.{0,}?})/, - replace: (_, functionDeclarationAndExpression, restOfFunction) => `${functionDeclarationAndExpression}${restOfFunction}` - } - }], + patches: [ + { - options: { - noSpotifyAutoPause: { - description: "Disable Spotify auto-pause", - type: OptionType.BOOLEAN, - default: true, - restartNeeded: true, + find: 'dispatch({type:"SPOTIFY_PROFILE_UPDATE"', + replacement: { + match: /SPOTIFY_PROFILE_UPDATE.+?isPremium:(?="premium"===(\i)\.body\.product)/, + replace: (m, req) => `${m}(${req}.body.product="premium")&&` + }, }, - keepSpotifyActivityOnIdle: { - description: "Keep Spotify activity playing when idling", - type: OptionType.BOOLEAN, - default: false, - restartNeeded: true, + { + find: '.displayName="SpotifyStore"', + replacement: [ + { + predicate: () => settings.store.noSpotifyAutoPause, + match: /(?<=function \i\(\){)(?=.{0,200}SPOTIFY_AUTO_PAUSED\))/, + replace: "return;" + }, + { + predicate: () => settings.store.keepSpotifyActivityOnIdle, + match: /(?<=shouldShowActivity=function\(\){.{0,50})&&!\i\.\i\.isIdle\(\)/, + replace: "" + } + ] } - } + ] }); diff --git a/src/plugins/typingIndicator.tsx b/src/plugins/typingIndicator.tsx index 27c143b0..9af09bca 100644 --- a/src/plugins/typingIndicator.tsx +++ b/src/plugins/typingIndicator.tsx @@ -121,8 +121,8 @@ export default definePlugin({ { find: ".UNREAD_HIGHLIGHT", replacement: { - match: /(?<=(?\i)=\i\.channel,.+?\(\)\.children.+?:null)/, - replace: ",$self.TypingIndicator($.id)" + match: /\(\).children.+?:null(?<=(\i)=\i\.channel,.+?)/, + replace: (m, channel) => `${m},$self.TypingIndicator(${channel}.id)` } } ], diff --git a/src/plugins/volumeBooster.ts b/src/plugins/volumeBooster.ts index 6553a5c7..7d814491 100644 --- a/src/plugins/volumeBooster.ts +++ b/src/plugins/volumeBooster.ts @@ -16,14 +16,26 @@ * along with this program. If not, see . */ -import { makeRange } from "@components/PluginSettings/components/SettingSliderComponent"; +import { definePluginSettings } from "@api/settings"; +import { makeRange } from "@components/PluginSettings/components"; import { Devs } from "@utils/constants"; import definePlugin, { OptionType } from "@utils/types"; +const settings = definePluginSettings({ + multiplier: { + description: "Volume Multiplier", + type: OptionType.SLIDER, + markers: makeRange(1, 5, 1), + default: 2, + stickToMarkers: true, + } +}); + export default definePlugin({ name: "VolumeBooster", authors: [Devs.Nuckyz], description: "Allows you to set the user and stream volume above the default maximum.", + settings, patches: [ // Change the max volume for sliders to allow for values above 200 @@ -33,11 +45,10 @@ export default definePlugin({ ].map(find => ({ find, replacement: { - match: /maxValue:(?\i\.\i)\?(?\d+?):(?\d+?),/, - replace: "" - + "maxValue:$" - + "?$*Vencord.Settings.plugins.VolumeBooster.multiplier" - + ":$*Vencord.Settings.plugins.VolumeBooster.multiplier," + match: /(?<=maxValue:\i\.\i)\?(\d+?):(\d+?)(?=,)/, + replace: (_, higherMaxVolume, minorMaxVolume) => "" + + `?${higherMaxVolume}*$self.settings.store.multiplier` + + `:${minorMaxVolume}*$self.settings.store.multiplier` } })), // Prevent Audio Context Settings sync from trying to sync with values above 200, changing them to 200 before we send to Discord @@ -45,16 +56,16 @@ export default definePlugin({ find: "AudioContextSettingsMigrated", replacement: [ { - match: /(?updateAsync\("audioContextSettings".{1,50})(?return (?\i)\.volume=(?\i))/, - replace: "$if($>200)return $.volume=200;$" + match: /(?<=updateAsync\("audioContextSettings".{0,50})(?=return (\i)\.volume=(\i))/, + replace: (_, volumeOptions, newVolume) => `if(${newVolume}>200)return ${volumeOptions}.volume=200;` }, { - match: /(?Object\.entries\(\i\.localMutes\).+?)volume:(?.+?),/, - replace: "$volume:$>200?200:$," + match: /(?<=Object\.entries\(\i\.localMutes\).+?volume:).+?(?=,)/, + replace: "$&>200?200:$&" }, { - match: /(?Object\.entries\(\i\.localVolumes\).+?)volume:(?.+?)}\)/, - replace: "$volume:$>200?200:$})" + match: /(?<=Object\.entries\(\i\.localVolumes\).+?volume:).+?(?=})/, + replace: "$&>200?200:$&" } ] }, @@ -63,24 +74,13 @@ export default definePlugin({ find: '.displayName="MediaEngineStore"', replacement: [ { - match: /(?\.settings\.audioContextSettings.+?)(?\i\[\i\])=(?\i\.volume)(?.+?)setLocalVolume\((?.+?),.+?\)/, - replace: "" - + "$" - + "($>200?undefined:$=$)" - + "$" - + "setLocalVolume($,$??$)" + match: /(?<=\.settings\.audioContextSettings.+?)(\i\[\i\])=(\i\.volume)(.+?setLocalVolume\(\i,).+?\)/, + replace: (_, localVolume, syncVolume, rest) => "" + + `(${localVolume}>200?void 0:${localVolume}=${syncVolume})` + + rest + + `${localVolume}??${syncVolume})` } ] } ], - - options: { - multiplier: { - description: "Volume Multiplier", - type: OptionType.SLIDER, - markers: makeRange(1, 5, 1), - default: 2, - stickToMarkers: true, - } - } }); diff --git a/src/plugins/whoReacted.tsx b/src/plugins/whoReacted.tsx index 8ab1c5f7..4b1c828f 100644 --- a/src/plugins/whoReacted.tsx +++ b/src/plugins/whoReacted.tsx @@ -93,8 +93,8 @@ export default definePlugin({ patches: [{ find: ",reactionRef:", replacement: { - match: /((.)=(.{1,3})\.hideCount)(,.+?reactionCount.+?\}\))/, - replace: "$1,whoReactedProps=$3$4,$2?null:$self.renderUsers(whoReactedProps)" + match: /(?<=(\i)=(\i)\.hideCount,)(.+?reactionCount.+?\}\))/, + replace: (_, hideCount, props, rest) => `whoReactedProps=${props},${rest},${hideCount}?null:$self.renderUsers(whoReactedProps)` } }],