, pluginName: string) {
delete patch.group;
}
+ if (patch.predicate && !patch.predicate()) return;
+
canonicalizeFind(patch);
if (!Array.isArray(patch.replacement)) {
patch.replacement = [patch.replacement];
}
+ patch.replacement = patch.replacement.filter(({ predicate }) => !predicate || predicate());
+
if (IS_REPORTER) {
patch.replacement.forEach(r => {
delete r.predicate;
diff --git a/src/plugins/invisibleChat.desktop/index.tsx b/src/plugins/invisibleChat.desktop/index.tsx
index 01199d999..c7eb29e7e 100644
--- a/src/plugins/invisibleChat.desktop/index.tsx
+++ b/src/plugins/invisibleChat.desktop/index.tsx
@@ -133,10 +133,12 @@ export default definePlugin({
message: message,
channel: ChannelStore.getChannel(message.channel_id),
onClick: async () => {
- await iteratePasswords(message).then((res: string | false) => {
- if (res) return void this.buildEmbed(message, res);
- return void buildDecModal({ message });
- });
+ const res = await iteratePasswords(message);
+
+ if (res)
+ this.buildEmbed(message, res);
+ else
+ buildDecModal({ message });
}
}
: null;
@@ -169,9 +171,9 @@ export default definePlugin({
message.embeds.push({
type: "rich",
- title: "Decrypted Message",
+ rawTitle: "Decrypted Message",
color: "0x45f5f5",
- description: revealed,
+ rawDescription: revealed,
footer: {
text: "Made with ❤️ by c0dine and Sammy!",
},
diff --git a/src/plugins/mentionAvatars/README.md b/src/plugins/mentionAvatars/README.md
new file mode 100644
index 000000000..912b51916
--- /dev/null
+++ b/src/plugins/mentionAvatars/README.md
@@ -0,0 +1,5 @@
+# MentionAvatars
+
+Shows user avatars inside mentions
+
+![](https://github.com/user-attachments/assets/fc76ea47-5e19-4063-a592-c57785a75cc7)
diff --git a/src/plugins/mentionAvatars/index.tsx b/src/plugins/mentionAvatars/index.tsx
new file mode 100644
index 000000000..549693142
--- /dev/null
+++ b/src/plugins/mentionAvatars/index.tsx
@@ -0,0 +1,44 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import "./styles.css";
+
+import ErrorBoundary from "@components/ErrorBoundary";
+import { Devs } from "@utils/constants";
+import definePlugin from "@utils/types";
+import { SelectedGuildStore, useState } from "@webpack/common";
+import { User } from "discord-types/general";
+
+export default definePlugin({
+ name: "MentionAvatars",
+ description: "Shows user avatars inside mentions",
+ authors: [Devs.Ven],
+
+ patches: [{
+ find: ".USER_MENTION)",
+ replacement: {
+ match: /children:"@"\.concat\((null!=\i\?\i:\i)\)(?<=\.useName\((\i)\).+?)/,
+ replace: "children:$self.renderUsername({username:$1,user:$2})"
+ }
+ }],
+
+ renderUsername: ErrorBoundary.wrap((props: { user: User, username: string; }) => {
+ const { user, username } = props;
+ const [isHovering, setIsHovering] = useState(false);
+
+ if (!user) return <>@{username}>;
+
+ return (
+ setIsHovering(true)}
+ onMouseLeave={() => setIsHovering(false)}
+ >
+
+ @{username}
+
+ );
+ }, { noop: true })
+});
diff --git a/src/plugins/mentionAvatars/styles.css b/src/plugins/mentionAvatars/styles.css
new file mode 100644
index 000000000..33404d7b5
--- /dev/null
+++ b/src/plugins/mentionAvatars/styles.css
@@ -0,0 +1,8 @@
+.vc-mentionAvatars-avatar {
+ vertical-align: middle;
+ width: 1em;
+ height: 1em;
+ margin: 0 4px 0.2rem 2px;
+ border-radius: 50%;
+ box-sizing: border-box;
+}
diff --git a/src/plugins/messageLogger/HistoryModal.tsx b/src/plugins/messageLogger/HistoryModal.tsx
new file mode 100644
index 000000000..d1b5bf29c
--- /dev/null
+++ b/src/plugins/messageLogger/HistoryModal.tsx
@@ -0,0 +1,91 @@
+/*
+ * Vencord, a Discord client mod
+ * Copyright (c) 2024 Vendicated and contributors
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+import { classNameFactory } from "@api/Styles";
+import ErrorBoundary from "@components/ErrorBoundary";
+import { Margins } from "@utils/margins";
+import { classes } from "@utils/misc";
+import { ModalCloseButton, ModalContent, ModalHeader, ModalProps, ModalRoot, ModalSize, openModal } from "@utils/modal";
+import { findByPropsLazy } from "@webpack";
+import { TabBar, Text, Timestamp, TooltipContainer, useState } from "@webpack/common";
+
+import { parseEditContent } from ".";
+
+const CodeContainerClasses = findByPropsLazy("markup", "codeContainer");
+const MiscClasses = findByPropsLazy("messageContent", "markupRtl");
+
+const cl = classNameFactory("vc-ml-modal-");
+
+export function openHistoryModal(message: any) {
+ openModal(props =>
+
+
+
+ );
+}
+
+export function HistoryModal({ modalProps, message }: { modalProps: ModalProps; message: any; }) {
+ const [currentTab, setCurrentTab] = useState(message.editHistory.length);
+ const timestamps = [message.firstEditTimestamp, ...message.editHistory.map(m => m.timestamp)];
+ const contents = [...message.editHistory.map(m => m.content), message.content];
+
+ return (
+
+
+ Message Edit History
+
+
+
+
+
+ {message.firstEditTimestamp.getTime() !== message.timestamp.getTime() && (
+
+
+
+
+
+ )}
+
+ {timestamps.map((timestamp, index) => (
+
+
+
+ ))}
+
+
+
+ {parseEditContent(contents[currentTab], message)}
+
+
+
+ );
+}
diff --git a/src/plugins/messageLogger/index.tsx b/src/plugins/messageLogger/index.tsx
index fdd6dc9b9..9181306ad 100644
--- a/src/plugins/messageLogger/index.tsx
+++ b/src/plugins/messageLogger/index.tsx
@@ -24,21 +24,26 @@ import { Settings } from "@api/Settings";
import { disableStyle, enableStyle } from "@api/Styles";
import ErrorBoundary from "@components/ErrorBoundary";
import { Devs } from "@utils/constants";
+import { proxyLazy } from "@utils/lazy";
import { Logger } from "@utils/Logger";
+import { classes } from "@utils/misc";
import definePlugin, { OptionType } from "@utils/types";
-import { findByPropsLazy } from "@webpack";
-import { ChannelStore, FluxDispatcher, i18n, Menu, MessageStore, Parser, Timestamp, UserStore, useStateFromStores } from "@webpack/common";
+import { findByCodeLazy, findByPropsLazy } from "@webpack";
+import { ChannelStore, FluxDispatcher, i18n, Menu, MessageStore, Parser, SelectedChannelStore, Timestamp, UserStore, useStateFromStores } from "@webpack/common";
import { Message } from "discord-types/general";
import overlayStyle from "./deleteStyleOverlay.css?managed";
import textStyle from "./deleteStyleText.css?managed";
+import { openHistoryModal } from "./HistoryModal";
interface MLMessage extends Message {
deleted?: boolean;
editHistory?: { timestamp: Date; content: string; }[];
+ firstEditTimestamp?: Date;
}
const styles = findByPropsLazy("edited", "communicationDisabled", "isSystemMessage");
+const getMessage = findByCodeLazy('replace(/^\\n+|\\n+$/g,"")');
function addDeleteStyle() {
if (Settings.plugins.MessageLogger.deleteStyle === "text") {
@@ -125,10 +130,22 @@ const patchChannelContextMenu: NavContextMenuPatchCallback = (children, { channe
);
};
+export function parseEditContent(content: string, message: Message) {
+ return Parser.parse(content, true, {
+ channelId: message.channel_id,
+ messageId: message.id,
+ allowLinks: true,
+ allowHeading: true,
+ allowList: true,
+ allowEmojiLinks: true,
+ viewingChannelId: SelectedChannelStore.getChannelId(),
+ });
+}
+
export default definePlugin({
name: "MessageLogger",
description: "Temporarily logs deleted and edited messages.",
- authors: [Devs.rushii, Devs.Ven, Devs.AutumnVN, Devs.Nickyux],
+ authors: [Devs.rushii, Devs.Ven, Devs.AutumnVN, Devs.Nickyux, Devs.Kyuuhachi],
dependencies: ["MessageUpdaterAPI"],
contextMenus: {
@@ -150,11 +167,11 @@ export default definePlugin({
(oldMsg, newMsg) => oldMsg?.editHistory === newMsg?.editHistory
);
- return (
+ return Settings.plugins.MessageLogger.inlineEdits && (
<>
{message.editHistory?.map(edit => (
- {Parser.parse(edit.content)}
+ {parseEditContent(edit.content, message)}
openHistoryModal(message)}
+ aria-role="button"
+ >
+ {children}
+
+ );
+ },
+
+ Messages: proxyLazy(() => ({
+ DELETED_MESSAGE_COUNT: getMessage("{count, plural, =0 {No deleted messages} one {{count} deleted message} other {{count} deleted messages}}")
+ })),
+
patches: [
{
// MessageStore
@@ -324,7 +368,8 @@ export default definePlugin({
match: /this\.customRenderedContent=(\i)\.customRenderedContent,/,
replace: "this.customRenderedContent = $1.customRenderedContent," +
"this.deleted = $1.deleted || false," +
- "this.editHistory = $1.editHistory || [],"
+ "this.editHistory = $1.editHistory || []," +
+ "this.firstEditTimestamp = $1.firstEditTimestamp || this.editedTimestamp || this.timestamp,"
}
]
},
@@ -337,7 +382,7 @@ export default definePlugin({
// Pass through editHistory & deleted & original attachments to the "edited message" transformer
match: /(?<=null!=\i\.edited_timestamp\)return )\i\(\i,\{reactions:(\i)\.reactions.{0,50}\}\)/,
replace:
- "Object.assign($&,{ deleted:$1.deleted, editHistory:$1.editHistory, attachments:$1.attachments })"
+ "Object.assign($&,{ deleted:$1.deleted, editHistory:$1.editHistory, firstEditTimestamp:$1.firstEditTimestamp })"
},
{
@@ -356,7 +401,8 @@ export default definePlugin({
" return $2;" +
"})())," +
"deleted: arguments[1]?.deleted," +
- "editHistory: arguments[1]?.editHistory"
+ "editHistory: arguments[1]?.editHistory," +
+ "firstEditTimestamp: new Date(arguments[1]?.firstEditTimestamp ?? $2.editedTimestamp ?? $2.timestamp)"
},
{
// Preserve deleted attribute on attachments
@@ -404,6 +450,11 @@ export default definePlugin({
// Render editHistory in the deepest div for message content
match: /(\)\("div",\{id:.+?children:\[)/,
replace: "$1 (!!arguments[0].message.editHistory?.length && $self.renderEdits(arguments[0])),"
+ },
+ {
+ // Make edit marker clickable
+ match: /"span",\{(?=className:\i\.edited,)/,
+ replace: "$self.EditMarker,{message:arguments[0].message,"
}
]
},
@@ -433,6 +484,30 @@ export default definePlugin({
replace: "children:arguments[0].message.deleted?[]:$1"
}
]
+ },
+ {
+ // Message grouping
+ find: "NON_COLLAPSIBLE.has(",
+ replacement: {
+ match: /if\((\i)\.blocked\)return \i\.\i\.MESSAGE_GROUP_BLOCKED;/,
+ replace: '$&else if($1.deleted) return"MESSAGE_GROUP_DELETED";',
+ },
+ predicate: () => Settings.plugins.MessageLogger.collapseDeleted
+ },
+ {
+ // Message group rendering
+ find: "Messages.NEW_MESSAGES_ESTIMATED_WITH_DATE",
+ replacement: [
+ {
+ match: /(\i).type===\i\.\i\.MESSAGE_GROUP_BLOCKED\|\|/,
+ replace: '$&$1.type==="MESSAGE_GROUP_DELETED"||',
+ },
+ {
+ match: /(\i).type===\i\.\i\.MESSAGE_GROUP_BLOCKED\?.*?:/,
+ replace: '$&$1.type==="MESSAGE_GROUP_DELETED"?$self.Messages.DELETED_MESSAGE_COUNT:',
+ },
+ ],
+ predicate: () => Settings.plugins.MessageLogger.collapseDeleted
}
]
});
diff --git a/src/plugins/messageLogger/messageLogger.css b/src/plugins/messageLogger/messageLogger.css
index d5a9c5f17..2759129d9 100644
--- a/src/plugins/messageLogger/messageLogger.css
+++ b/src/plugins/messageLogger/messageLogger.css
@@ -8,11 +8,15 @@
.emoji,
[data-type="sticker"],
iframe,
- .messagelogger-deleted-attachment:not([class*="hiddenAttachment_"]),
+ .messagelogger-deleted-attachment,
[class|="inlineMediaEmbed"]
) {
filter: grayscale(1) !important;
transition: 150ms filter ease-in-out;
+
+ &[class*="hiddenMosaicItem_"] {
+ filter: grayscale(1) blur(var(--custom-message-attachment-spoiler-blur-radius, 44px)) !important;
+ }
}
.messagelogger-deleted
@@ -23,8 +27,7 @@
iframe,
.messagelogger-deleted-attachment,
[class|="inlineMediaEmbed"]
-):hover,
-.messagelogger-deleted {
+):hover {
filter: grayscale(0) !important;
}
@@ -35,3 +38,17 @@
.theme-light .messagelogger-edited {
opacity: 0.5;
}
+
+.messagelogger-edit-marker {
+ cursor: pointer;
+}
+
+.vc-ml-modal-timestamp {
+ cursor: unset;
+ height: unset;
+}
+
+.vc-ml-modal-tab-bar {
+ flex-wrap: wrap;
+ gap: 16px;
+}
diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx
index be81a8a89..45538fb66 100644
--- a/src/plugins/moreUserTags/index.tsx
+++ b/src/plugins/moreUserTags/index.tsx
@@ -256,6 +256,7 @@ export default definePlugin({
// in profiles
{
find: ",overrideDiscriminator:",
+ group: true,
replacement: [
{
// prevent channel id from getting ghosted
@@ -263,7 +264,7 @@ export default definePlugin({
match: /user:\i,nick:\i,/,
replace: "$&moreTags_channelId,"
}, {
- match: /,botType:(\i\((\i)\)),/g,
+ match: /,botType:(\i),(?<=user:(\i).+?)/g,
replace: ",botType:$self.getTag({user:$2,channelId:moreTags_channelId,origType:$1,location:'not-chat'}),"
}
]
diff --git a/src/plugins/permissionsViewer/index.tsx b/src/plugins/permissionsViewer/index.tsx
index 6401d9450..6a503f2da 100644
--- a/src/plugins/permissionsViewer/index.tsx
+++ b/src/plugins/permissionsViewer/index.tsx
@@ -34,7 +34,7 @@ import UserPermissions from "./components/UserPermissions";
import { getSortedRoles, sortPermissionOverwrites } from "./utils";
const PopoutClasses = findByPropsLazy("container", "scroller", "list");
-const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "text");
+const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "banner");
export const enum PermissionsSortOrder {
HighestRole,
diff --git a/src/plugins/reviewDB/index.tsx b/src/plugins/reviewDB/index.tsx
index 7fdc1509a..456e15a57 100644
--- a/src/plugins/reviewDB/index.tsx
+++ b/src/plugins/reviewDB/index.tsx
@@ -37,8 +37,7 @@ import { getCurrentUserInfo, readNotification } from "./reviewDbApi";
import { settings } from "./settings";
import { showToast } from "./utils";
-const PopoutClasses = findByPropsLazy("container", "scroller", "list");
-const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "text");
+const RoleButtonClasses = findByPropsLazy("button", "buttonInner", "icon", "banner");
const guildPopoutPatch: NavContextMenuPatchCallback = (children, { guild }: { guild: Guild, onClose(): void; }) => {
if (!guild) return;
@@ -181,9 +180,9 @@ export default definePlugin({
onClick={() => openReviewsModal(user.id, user.username)}
look={Button.Looks.FILLED}
size={Button.Sizes.NONE}
- color={RoleButtonClasses.color}
- className={classes(RoleButtonClasses.button, RoleButtonClasses.banner)}
- innerClassName={classes(RoleButtonClasses.buttonInner, RoleButtonClasses.banner)}
+ color={RoleButtonClasses.bannerColor}
+ className={classes(RoleButtonClasses.button, RoleButtonClasses.icon, RoleButtonClasses.banner)}
+ innerClassName={classes(RoleButtonClasses.buttonInner, RoleButtonClasses.icon, RoleButtonClasses.banner)}
>
diff --git a/src/plugins/roleColorEverywhere/index.tsx b/src/plugins/roleColorEverywhere/index.tsx
index 37177caad..3e7d216b7 100644
--- a/src/plugins/roleColorEverywhere/index.tsx
+++ b/src/plugins/roleColorEverywhere/index.tsx
@@ -60,7 +60,7 @@ export default definePlugin({
find: 'location:"UserMention',
replacement: [
{
- match: /user:(\i),channel:(\i).{0,400}?"@"\.concat\(.+?\)/,
+ match: /onContextMenu:\i,color:\i,\.\.\.\i(?=,children:)(?<=user:(\i),channel:(\i).{0,500}?)/,
replace: "$&,color:$self.getUserColor($1?.id,{channelId:$2?.id})"
}
],
diff --git a/src/plugins/showAllRoles/index.ts b/src/plugins/showAllRoles/index.ts
index 02d9f964c..97f0181fa 100644
--- a/src/plugins/showAllRoles/index.ts
+++ b/src/plugins/showAllRoles/index.ts
@@ -15,8 +15,8 @@ export default definePlugin({
{
find: ".Messages.VIEW_ALL_ROLES",
replacement: {
- match: /return null!=\i(?=\?\i\.slice)/,
- replace: "return false"
+ match: /(\i)\.slice\(0,\i\)/,
+ replace: "$1"
}
}
]
diff --git a/src/plugins/showHiddenChannels/index.tsx b/src/plugins/showHiddenChannels/index.tsx
index 538200afa..2d8b0c190 100644
--- a/src/plugins/showHiddenChannels/index.tsx
+++ b/src/plugins/showHiddenChannels/index.tsx
@@ -257,7 +257,7 @@ export default definePlugin({
{
find: '"alt+shift+down"',
replacement: {
- match: /(?<=getChannel\(\i\);return null!=(\i))(?=.{0,150}?>0\)&&\(0,\i\.\i\)\(\i\))/,
+ match: /(?<=getChannel\(\i\);return null!=(\i))(?=.{0,200}?>0\)&&\(0,\i\.\i\)\(\i\))/,
replace: (_, channel) => `&&!$self.isHiddenChannel(${channel})`
}
},
@@ -265,8 +265,8 @@ export default definePlugin({
{
find: ".APPLICATION_STORE&&null!=",
replacement: {
- match: /(?<=getState\(\)\.channelId.{0,30}?\(0,\i\.\i\)\(\i\))(?=\.map\()/,
- replace: ".filter(e=>!$self.isHiddenChannel(e))"
+ match: /getState\(\)\.channelId.+?(?=\.map\(\i=>\i\.id)/,
+ replace: "$&.filter(e=>!$self.isHiddenChannel(e))"
}
},
{
diff --git a/src/plugins/showHiddenThings/index.ts b/src/plugins/showHiddenThings/index.ts
index 599bcd36d..90bb345ef 100644
--- a/src/plugins/showHiddenThings/index.ts
+++ b/src/plugins/showHiddenThings/index.ts
@@ -18,34 +18,21 @@
import { definePluginSettings, migratePluginSettings } from "@api/Settings";
import { Devs } from "@utils/constants";
-import definePlugin, { OptionType } from "@utils/types";
+import definePlugin, { OptionType, PluginSettingDef } from "@utils/types";
+
+const opt = (description: string) => ({
+ type: OptionType.BOOLEAN,
+ description,
+ default: true,
+ restartNeeded: true
+} satisfies PluginSettingDef);
const settings = definePluginSettings({
- showTimeouts: {
- type: OptionType.BOOLEAN,
- description: "Show member timeout icons in chat.",
- default: true,
- },
- showInvitesPaused: {
- type: OptionType.BOOLEAN,
- description: "Show the invites paused tooltip in the server list.",
- default: true,
- },
- showModView: {
- type: OptionType.BOOLEAN,
- description: "Show the member mod view context menu item in all servers.",
- default: true,
- },
- disableDiscoveryFilters: {
- type: OptionType.BOOLEAN,
- description: "Disable filters in Server Discovery search that hide servers that don't meet discovery criteria.",
- default: true,
- },
- disableDisallowedDiscoveryFilters: {
- type: OptionType.BOOLEAN,
- description: "Disable filters in Server Discovery search that hide NSFW & disallowed servers.",
- default: true,
- },
+ showTimeouts: opt("Show member timeout icons in chat."),
+ showInvitesPaused: opt("Show the invites paused tooltip in the server list."),
+ showModView: opt("Show the member mod view context menu item in all servers."),
+ disableDiscoveryFilters: opt("Disable filters in Server Discovery search that hide servers that don't meet discovery criteria."),
+ disableDisallowedDiscoveryFilters: opt("Disable filters in Server Discovery search that hide NSFW & disallowed servers."),
});
migratePluginSettings("ShowHiddenThings", "ShowTimeouts");
diff --git a/src/plugins/showMeYourName/index.tsx b/src/plugins/showMeYourName/index.tsx
index 8d1504e1a..4f9fcf304 100644
--- a/src/plugins/showMeYourName/index.tsx
+++ b/src/plugins/showMeYourName/index.tsx
@@ -67,7 +67,7 @@ export default definePlugin({
const { nick } = author;
const prefix = withMentionPrefix ? "@" : "";
- if (isRepliedMessage && !settings.store.inReplies || username === nick.toLowerCase())
+ if (isRepliedMessage && !settings.store.inReplies || username.toLowerCase() === nick.toLowerCase())
return <>{prefix}{nick}>;
if (settings.store.mode === "user-nick")
diff --git a/src/plugins/urbanDictionary/README.md b/src/plugins/urbanDictionary/README.md
deleted file mode 100644
index e065456a3..000000000
--- a/src/plugins/urbanDictionary/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Urban Dictionary
-
-Use /urban slash command to search for a definition for a word on [Urban Dictionary](https://www.urbandictionary.com/).
-
-## Preview
-
-![preview](https://i.imgur.com/1zwzj38.png)
-
-## Usage
-
-- Enable this plugin
-- Set plugin settings as desired
-- Type /urban and start getting definitions right into your Discord client.
diff --git a/src/plugins/urbanDictionary/index.ts b/src/plugins/urbanDictionary/index.ts
deleted file mode 100644
index 89dcdcba4..000000000
--- a/src/plugins/urbanDictionary/index.ts
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Vencord, a modification for Discord's desktop app
- * Copyright (c) 2022 Vendicated and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
-*/
-
-import { ApplicationCommandOptionType, sendBotMessage } from "@api/Commands";
-import { ApplicationCommandInputType } from "@api/Commands/types";
-import { definePluginSettings } from "@api/Settings";
-import { Devs } from "@utils/constants";
-import definePlugin, { OptionType } from "@utils/types";
-
-const settings = definePluginSettings({
- resultsAmount: {
- type: OptionType.NUMBER,
- description: "The amount of results you want to get (more gives better results, but is slower)",
- default: 10
- }
-});
-
-export default definePlugin({
- name: "UrbanDictionary",
- description: "Search for a word on Urban Dictionary via /urban slash command",
- authors: [Devs.jewdev],
- dependencies: ["CommandsAPI"],
- settings,
- commands: [
- {
- name: "urban",
- description: "Returns the definition of a word from Urban Dictionary",
- inputType: ApplicationCommandInputType.BUILT_IN,
- options: [
- {
- type: ApplicationCommandOptionType.STRING,
- name: "word",
- description: "The word to search for on Urban Dictionary",
- required: true
- }
- ],
- execute: async (args, ctx) => {
- try {
- const query: string = encodeURIComponent(args[0].value);
- const { list } = await fetch(`https://api.urbandictionary.com/v0/define?term=${query}&per_page=${settings.store.resultsAmount}`).then(response => response.json());
-
- if (!list.length)
- return void sendBotMessage(ctx.channel.id, { content: "No results found." });
-
- const definition = list.reduce((prev, curr) => {
- return prev.thumbs_up > curr.thumbs_up ? prev : curr;
- });
-
- const linkify = (text: string) => text
- .replaceAll("\r\n", "\n")
- .replace(/([*>_`~\\])/gsi, "\\$1")
- .replace(/\[(.+?)\]/g, (_, word) => `[${word}](https://www.urbandictionary.com/define.php?term=${encodeURIComponent(word)} "Define '${word}' on Urban Dictionary")`)
- .trim();
-
- return void sendBotMessage(ctx.channel.id, {
- embeds: [
- {
- type: "rich",
- author: {
- name: `Uploaded by "${definition.author}"`,
- url: `https://www.urbandictionary.com/author.php?author=${encodeURIComponent(definition.author)}`,
- },
- title: definition.word,
- url: `https://www.urbandictionary.com/define.php?term=${encodeURIComponent(definition.word)}`,
- description: linkify(definition.definition),
- fields: [
- {
- name: "Example",
- value: linkify(definition.example),
- },
- {
- name: "Want more definitions?",
- value: `Check out [more definitions](https://www.urbandictionary.com/define.php?term=${query} "Define "${args[0].value}" on Urban Dictionary") on Urban Dictionary.`,
- },
- ],
- color: 0xFF9900,
- footer: { text: `👍 ${definition.thumbs_up.toString()} | 👎 ${definition.thumbs_down.toString()}`, icon_url: "https://www.urbandictionary.com/favicon.ico" },
- timestamp: new Date(definition.written_on).toISOString(),
- },
- ] as any,
- });
- } catch (error) {
- sendBotMessage(ctx.channel.id, {
- content: `Something went wrong: \`${error}\``,
- });
- }
- }
- }
- ]
-});
diff --git a/src/plugins/viewIcons/index.tsx b/src/plugins/viewIcons/index.tsx
index b2e7d56df..6bde04be0 100644
--- a/src/plugins/viewIcons/index.tsx
+++ b/src/plugins/viewIcons/index.tsx
@@ -183,14 +183,22 @@ export default definePlugin({
},
patches: [
- // Profiles Modal pfp
- ...[".MODAL,hasProfileEffect", ".FULL_SIZE,hasProfileEffect:"].map(find => ({
- find,
+ // Avatar component used in User DMs "User Profile" popup in the right and Profiles Modal pfp
+ {
+ find: ".overlay:void 0,status:",
+ replacement: {
+ match: /avatarSrc:(\i),eventHandlers:(\i).+?"div",{...\2,/,
+ replace: "$&style:{cursor:\"pointer\"},onClick:()=>{$self.openImage($1)},"
+ }
+ },
+ // Old Profiles Modal pfp
+ {
+ find: ".MODAL,hasProfileEffect",
replacement: {
match: /\{src:(\i)(?=,avatarDecoration)/,
replace: "{src:$1,onClick:()=>$self.openImage($1)"
}
- })),
+ },
// Banners
...[".NITRO_BANNER,", "=!1,canUsePremiumCustomization:"].map(find => ({
find,
@@ -202,7 +210,7 @@ export default definePlugin({
'onClick:ev=>$1&&ev.target.style.backgroundImage&&$self.openImage($2),style:{cursor:$1?"pointer":void 0,'
}
})),
- // User DMs "User Profile" popup in the right
+ // Old User DMs "User Profile" popup in the right
{
find: ".avatarPositionPanel",
replacement: {
@@ -210,14 +218,6 @@ export default definePlugin({
replace: "$1style:($2)?{cursor:\"pointer\"}:{},onClick:$2?()=>{$self.openImage($3)}"
}
},
- {
- find: ".canUsePremiumProfileCustomization,{avatarSrc:",
- replacement: {
- match: /children:\(0,\i\.jsx\)\(\i,{src:(\i)/,
- replace: "style:{cursor:\"pointer\"},onClick:()=>{$self.openImage($1)},$&"
-
- }
- },
// Group DMs top small & large icon
{
find: /\.recipients\.length>=2(?! delete a.deleted);
return clone;
diff --git a/src/plugins/wikisearch/index.ts b/src/plugins/wikisearch/index.ts
deleted file mode 100644
index 81dc37af1..000000000
--- a/src/plugins/wikisearch/index.ts
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Vencord, a modification for Discord's desktop app
- * Copyright (c) 2023 Vendicated and contributors
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
-*/
-
-import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, sendBotMessage } from "@api/Commands";
-import { Devs } from "@utils/constants";
-import definePlugin from "@utils/types";
-
-export default definePlugin({
- name: "Wikisearch",
- description: "Searches Wikipedia for your requested query. (/wikisearch)",
- authors: [Devs.Samu],
- dependencies: ["CommandsAPI"],
- commands: [
- {
- name: "wikisearch",
- description: "Searches Wikipedia for your request.",
- inputType: ApplicationCommandInputType.BUILT_IN,
- options: [
- {
- name: "search",
- description: "Word to search for",
- type: ApplicationCommandOptionType.STRING,
- required: true
- },
- ],
- execute: async (_, ctx) => {
- const word = findOption(_, "search", "");
-
- if (!word) {
- return sendBotMessage(ctx.channel.id, {
- content: "No word was defined!"
- });
- }
-
- const dataSearchParams = new URLSearchParams({
- action: "query",
- format: "json",
- list: "search",
- formatversion: "2",
- origin: "*",
- srsearch: word
- });
-
- const data = await fetch("https://en.wikipedia.org/w/api.php?" + dataSearchParams).then(response => response.json())
- .catch(err => {
- console.log(err);
- sendBotMessage(ctx.channel.id, { content: "There was an error. Check the console for more info" });
- return null;
- });
-
- if (!data) return;
-
- if (!data.query?.search?.length) {
- console.log(data);
- return sendBotMessage(ctx.channel.id, { content: "No results given" });
- }
-
- const altData = await fetch(`https://en.wikipedia.org/w/api.php?action=query&format=json&prop=info%7Cdescription%7Cimages%7Cimageinfo%7Cpageimages&list=&meta=&indexpageids=1&pageids=${data.query.search[0].pageid}&formatversion=2&origin=*`)
- .then(res => res.json())
- .then(data => data.query.pages[0])
- .catch(err => {
- console.log(err);
- sendBotMessage(ctx.channel.id, { content: "There was an error. Check the console for more info" });
- return null;
- });
-
- if (!altData) return;
-
- const thumbnailData = altData.thumbnail;
-
- const thumbnail = thumbnailData && {
- url: thumbnailData.source.replace(/(50px-)/ig, "1000px-"),
- height: thumbnailData.height * 100,
- width: thumbnailData.width * 100
- };
-
- sendBotMessage(ctx.channel.id, {
- embeds: [
- {
- type: "rich",
- title: data.query.search[0].title,
- url: `https://wikipedia.org/w/index.php?curid=${data.query.search[0].pageid}`,
- color: "0x8663BE",
- description: data.query.search[0].snippet.replace(/( |<([^>]+)>)/ig, "").replace(/(")/ig, "\"") + "...",
- image: thumbnail,
- footer: {
- text: "Powered by the Wikimedia API",
- },
- }
- ] as any
- });
- }
- }
- ]
-});
diff --git a/src/utils/misc.ts b/src/utils/misc.ts
index 7d6b4affc..28c371c5b 100644
--- a/src/utils/misc.ts
+++ b/src/utils/misc.ts
@@ -24,7 +24,7 @@ import { DevsById } from "./constants";
* Calls .join(" ") on the arguments
* classes("one", "two") => "one two"
*/
-export function classes(...classes: Array) {
+export function classes(...classes: Array) {
return classes.filter(Boolean).join(" ");
}
diff --git a/src/webpack/common/types/utils.d.ts b/src/webpack/common/types/utils.d.ts
index ee3f69944..ce1e3e268 100644
--- a/src/webpack/common/types/utils.d.ts
+++ b/src/webpack/common/types/utils.d.ts
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-import { Guild, GuildMember } from "discord-types/general";
+import { Guild, GuildMember, User } from "discord-types/general";
import type { ReactNode } from "react";
import { LiteralUnion } from "type-fest";
@@ -256,3 +256,63 @@ export interface PopoutActions {
close(key: string): void;
setAlwaysOnTop(key: string, alwaysOnTop: boolean): void;
}
+
+export type UserNameUtilsTagInclude = LiteralUnion<"auto" | "always" | "never", string>;
+export interface UserNameUtilsTagOptions {
+ forcePomelo?: boolean;
+ identifiable?: UserNameUtilsTagInclude;
+ decoration?: UserNameUtilsTagInclude;
+ mode?: "full" | "username";
+}
+
+export interface UsernameUtils {
+ getGlobalName(user: User): string;
+ getFormattedName(user: User, useTagInsteadOfUsername?: boolean): string;
+ getName(user: User): string;
+ useName(user: User): string;
+ getUserTag(user: User, options?: UserNameUtilsTagOptions): string;
+ useUserTag(user: User, options?: UserNameUtilsTagOptions): string;
+
+
+ useDirectMessageRecipient: any;
+ humanizeStatus: any;
+}
+
+export class DisplayProfile {
+ userId: string;
+ banner?: string;
+ bio?: string;
+ pronouns?: string;
+ accentColor?: number;
+ themeColors?: number[];
+ popoutAnimationParticleType?: any;
+ profileEffectId?: string;
+ _userProfile?: any;
+ _guildMemberProfile?: any;
+ canUsePremiumProfileCustomization: boolean;
+ canEditThemes: boolean;
+ premiumGuildSince: Date | null;
+ premiumSince: Date | null;
+ premiumType?: number;
+ primaryColor?: number;
+
+ getBadges(): Array<{
+ id: string;
+ description: string;
+ icon: string;
+ link?: string;
+ }>;
+ getBannerURL(options: { canAnimate: boolean; size: number; }): string;
+ getLegacyUsername(): string | null;
+ hasFullProfile(): boolean;
+ hasPremiumCustomization(): boolean;
+ hasThemeColors(): boolean;
+ isUsingGuildMemberBanner(): boolean;
+ isUsingGuildMemberBio(): boolean;
+ isUsingGuildMemberPronouns(): boolean;
+}
+
+export interface DisplayProfileUtils {
+ getDisplayProfile(userId: string, guildId?: string, customStores?: any): DisplayProfile | null;
+ useDisplayProfile(userId: string, guildId?: string, customStores?: any): DisplayProfile | null;
+}
diff --git a/src/webpack/common/utils.ts b/src/webpack/common/utils.ts
index a6853c84a..280b2ba90 100644
--- a/src/webpack/common/utils.ts
+++ b/src/webpack/common/utils.ts
@@ -73,6 +73,25 @@ const ToastPosition = {
BOTTOM: 1
};
+export interface ToastData {
+ message: string,
+ id: string,
+ /**
+ * Toasts.Type
+ */
+ type: number,
+ options?: ToastOptions;
+}
+
+export interface ToastOptions {
+ /**
+ * Toasts.Position
+ */
+ position?: number;
+ component?: React.ReactNode,
+ duration?: number;
+}
+
export const Toasts = {
Type: ToastType,
Position: ToastPosition,
@@ -81,23 +100,9 @@ export const Toasts = {
// hack to merge with the following interface, dunno if there's a better way
...{} as {
- show(data: {
- message: string,
- id: string,
- /**
- * Toasts.Type
- */
- type: number,
- options?: {
- /**
- * Toasts.Position
- */
- position?: number;
- component?: React.ReactNode,
- duration?: number;
- };
- }): void;
+ show(data: ToastData): void;
pop(): void;
+ create(message: string, type: number, options?: ToastOptions): ToastData;
}
};
@@ -105,18 +110,15 @@ export const Toasts = {
waitFor("showToast", m => {
Toasts.show = m.showToast;
Toasts.pop = m.popToast;
+ Toasts.create = m.createToast;
});
/**
* Show a simple toast. If you need more options, use Toasts.show manually
*/
-export function showToast(message: string, type = ToastType.MESSAGE) {
- Toasts.show({
- id: Toasts.genId(),
- message,
- type
- });
+export function showToast(message: string, type = ToastType.MESSAGE, options?: ToastOptions) {
+ Toasts.show(Toasts.create(message, type, options));
}
export const UserUtils = {
@@ -172,3 +174,9 @@ export const PopoutActions: t.PopoutActions = mapMangledModuleLazy('type:"POPOUT
close: filters.byCode('type:"POPOUT_WINDOW_CLOSE"'),
setAlwaysOnTop: filters.byCode('type:"POPOUT_WINDOW_SET_ALWAYS_ON_TOP"'),
});
+
+export const UsernameUtils: t.UsernameUtils = findByPropsLazy("useName", "getGlobalName");
+export const DisplayProfileUtils: t.DisplayProfileUtils = mapMangledModuleLazy(/=\i\.getUserProfile\(\i\),\i=\i\.getGuildMemberProfile\(/, {
+ getDisplayProfile: filters.byCode(".getGuildMemberProfile("),
+ useDisplayProfile: filters.byCode(/\[\i\.\i,\i\.\i],\(\)=>/)
+});
diff --git a/src/webpack/patchWebpack.ts b/src/webpack/patchWebpack.ts
index 4b3b28a8e..f32aeb789 100644
--- a/src/webpack/patchWebpack.ts
+++ b/src/webpack/patchWebpack.ts
@@ -259,7 +259,6 @@ function patchFactories(factories: Record boolean;
+type PropsFilter = Array;
+type CodeFilter = Array;
+type StoreNameFilter = string;
+
+const stringMatches = (s: string, filter: CodeFilter) =>
+ filter.every(f =>
+ typeof f === "string"
+ ? s.includes(f)
+ : f.test(s)
+ );
+
export const filters = {
- byProps: (...props: string[]): FilterFn =>
+ byProps: (...props: PropsFilter): FilterFn =>
props.length === 1
? m => m[props[0]] !== void 0
: m => props.every(p => m[p] !== void 0),
- byCode: (...code: string[]): FilterFn => m => {
- if (typeof m !== "function") return false;
- const s = Function.prototype.toString.call(m);
- for (const c of code) {
- if (!s.includes(c)) return false;
- }
- return true;
+ byCode: (...code: CodeFilter): FilterFn => {
+ code = code.map(canonicalizeMatch);
+ return m => {
+ if (typeof m !== "function") return false;
+ return stringMatches(Function.prototype.toString.call(m), code);
+ };
},
- byStoreName: (name: string): FilterFn => m =>
+ byStoreName: (name: StoreNameFilter): FilterFn => m =>
m.constructor?.displayName === name,
- componentByCode: (...code: string[]): FilterFn => {
+ componentByCode: (...code: CodeFilter): FilterFn => {
const filter = filters.byCode(...code);
return m => {
if (filter(m)) return true;
if (!m.$$typeof) return false;
- if (m.type && m.type.render) return filter(m.type.render); // memo + forwardRef
- if (m.type) return filter(m.type); // memos
- if (m.render) return filter(m.render); // forwardRefs
+ if (m.type)
+ return m.type.render
+ ? filter(m.type.render) // memo + forwardRef
+ : filter(m.type); // memo
+ if (m.render) return filter(m.render); // forwardRef
return false;
};
}
@@ -245,15 +257,9 @@ export const findBulk = traceFunction("findBulk", function findBulk(...filterFns
* Find the id of the first module factory that includes all the given code
* @returns string or null
*/
-export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: string[]) {
- outer:
+export const findModuleId = traceFunction("findModuleId", function findModuleId(...code: CodeFilter) {
for (const id in wreq.m) {
- const str = wreq.m[id].toString();
-
- for (const c of code) {
- if (!str.includes(c)) continue outer;
- }
- return id;
+ if (stringMatches(wreq.m[id].toString(), code)) return id;
}
const err = new Error("Didn't find module with code(s):\n" + code.join("\n"));
@@ -272,7 +278,7 @@ export const findModuleId = traceFunction("findModuleId", function findModuleId(
* Find the first module factory that includes all the given code
* @returns The module factory or null
*/
-export function findModuleFactory(...code: string[]) {
+export function findModuleFactory(...code: CodeFilter) {
const id = findModuleId(...code);
if (!id) return null;
@@ -325,7 +331,7 @@ export function findLazy(filter: FilterFn) {
/**
* Find the first module that has the specified properties
*/
-export function findByProps(...props: string[]) {
+export function findByProps(...props: PropsFilter) {
const res = find(filters.byProps(...props), { isIndirect: true });
if (!res)
handleModuleNotFound("findByProps", ...props);
@@ -335,7 +341,7 @@ export function findByProps(...props: string[]) {
/**
* Find the first module that has the specified properties, lazily
*/
-export function findByPropsLazy(...props: string[]) {
+export function findByPropsLazy(...props: PropsFilter) {
if (IS_REPORTER) lazyWebpackSearchHistory.push(["findByProps", props]);
return proxyLazy(() => findByProps(...props));
@@ -344,7 +350,7 @@ export function findByPropsLazy(...props: string[]) {
/**
* Find the first function that includes all the given code
*/
-export function findByCode(...code: string[]) {
+export function findByCode(...code: CodeFilter) {
const res = find(filters.byCode(...code), { isIndirect: true });
if (!res)
handleModuleNotFound("findByCode", ...code);
@@ -354,7 +360,7 @@ export function findByCode(...code: string[]) {
/**
* Find the first function that includes all the given code, lazily
*/
-export function findByCodeLazy(...code: string[]) {
+export function findByCodeLazy(...code: CodeFilter) {
if (IS_REPORTER) lazyWebpackSearchHistory.push(["findByCode", code]);
return proxyLazy(() => findByCode(...code));
@@ -363,7 +369,7 @@ export function findByCodeLazy(...code: string[]) {
/**
* Find a store by its displayName
*/
-export function findStore(name: string) {
+export function findStore(name: StoreNameFilter) {
const res = find(filters.byStoreName(name), { isIndirect: true });
if (!res)
handleModuleNotFound("findStore", name);
@@ -373,7 +379,7 @@ export function findStore(name: string) {
/**
* Find a store by its displayName, lazily
*/
-export function findStoreLazy(name: string) {
+export function findStoreLazy(name: StoreNameFilter) {
if (IS_REPORTER) lazyWebpackSearchHistory.push(["findStore", [name]]);
return proxyLazy(() => findStore(name));
@@ -382,7 +388,7 @@ export function findStoreLazy(name: string) {
/**
* Finds the component which includes all the given code. Checks for plain components, memos and forwardRefs
*/
-export function findComponentByCode(...code: string[]) {
+export function findComponentByCode(...code: CodeFilter) {
const res = find(filters.componentByCode(...code), { isIndirect: true });
if (!res)
handleModuleNotFound("findComponentByCode", ...code);
@@ -407,7 +413,7 @@ export function findComponentLazy(filter: FilterFn) {
/**
* Finds the first component that includes all the given code, lazily
*/
-export function findComponentByCodeLazy(...code: string[]) {
+export function findComponentByCodeLazy(...code: CodeFilter) {
if (IS_REPORTER) lazyWebpackSearchHistory.push(["findComponentByCode", code]);
return LazyComponent(() => {
@@ -421,7 +427,7 @@ export function findComponentByCodeLazy(...code: string[
/**
* Finds the first component that is exported by the first prop name, lazily
*/
-export function findExportedComponentLazy(...props: string[]) {
+export function findExportedComponentLazy(...props: PropsFilter) {
if (IS_REPORTER) lazyWebpackSearchHistory.push(["findExportedComponent", props]);
return LazyComponent(() => {
@@ -445,10 +451,13 @@ export function findExportedComponentLazy(...props: stri
* closeModal: filters.byCode("key==")
* })
*/
-export const mapMangledModule = traceFunction("mapMangledModule", function mapMangledModule(code: string, mappers: Record): Record {
+export const mapMangledModule = traceFunction("mapMangledModule", function mapMangledModule(code: string | RegExp | CodeFilter, mappers: Record): Record {
+ if (!Array.isArray(code)) code = [code];
+ code = code.map(canonicalizeMatch);
+
const exports = {} as Record;
- const id = findModuleId(code);
+ const id = findModuleId(...code);
if (id === null)
return exports;
@@ -482,7 +491,7 @@ export const mapMangledModule = traceFunction("mapMangledModule", function mapMa
* closeModal: filters.byCode("key==")
* })
*/
-export function mapMangledModuleLazy(code: string, mappers: Record): Record {
+export function mapMangledModuleLazy(code: string | RegExp | CodeFilter, mappers: Record): Record {
if (IS_REPORTER) lazyWebpackSearchHistory.push(["mapMangledModule", [code, mappers]]);
return proxyLazy(() => mapMangledModule(code, mappers));
@@ -497,7 +506,7 @@ export const ChunkIdsRegex = /\("([^"]+?)"\)/g;
* @param matcher A RegExp that returns the chunk ids array as the first capture group and the entry point id as the second. Defaults to a matcher that captures the first lazy chunk loading found in the module factory
* @returns A promise that resolves with a boolean whether the chunks were loaded
*/
-export async function extractAndLoadChunks(code: string[], matcher: RegExp = DefaultExtractAndLoadChunksRegex) {
+export async function extractAndLoadChunks(code: CodeFilter, matcher: RegExp = DefaultExtractAndLoadChunksRegex) {
const module = findModuleFactory(...code);
if (!module) {
const err = new Error("extractAndLoadChunks: Couldn't find module factory");
@@ -562,7 +571,7 @@ export async function extractAndLoadChunks(code: string[], matcher: RegExp = Def
* @param matcher A RegExp that returns the chunk ids array as the first capture group and the entry point id as the second. Defaults to a matcher that captures the first lazy chunk loading found in the module factory
* @returns A function that returns a promise that resolves with a boolean whether the chunks were loaded, on first call
*/
-export function extractAndLoadChunksLazy(code: string[], matcher = DefaultExtractAndLoadChunksRegex) {
+export function extractAndLoadChunksLazy(code: CodeFilter, matcher = DefaultExtractAndLoadChunksRegex) {
if (IS_REPORTER) lazyWebpackSearchHistory.push(["extractAndLoadChunks", [code, matcher]]);
return makeLazy(() => extractAndLoadChunks(code, matcher));
@@ -572,7 +581,7 @@ export function extractAndLoadChunksLazy(code: string[], matcher = DefaultExtrac
* Wait for a module that matches the provided filter to be registered,
* then call the callback with the module as the first argument
*/
-export function waitFor(filter: string | string[] | FilterFn, callback: CallbackFn, { isIndirect = false }: { isIndirect?: boolean; } = {}) {
+export function waitFor(filter: string | PropsFilter | FilterFn, callback: CallbackFn, { isIndirect = false }: { isIndirect?: boolean; } = {}) {
if (IS_REPORTER && !isIndirect) lazyWebpackSearchHistory.push(["waitFor", Array.isArray(filter) ? filter : [filter]]);
if (typeof filter === "string")
@@ -593,21 +602,18 @@ export function waitFor(filter: string | string[] | FilterFn, callback: Callback
/**
* Search modules by keyword. This searches the factory methods,
* meaning you can search all sorts of things, displayName, methodName, strings somewhere in the code, etc
- * @param filters One or more strings or regexes
+ * @param code One or more strings or regexes
* @returns Mapping of found modules
*/
-export function search(...filters: Array) {
+export function search(...code: CodeFilter) {
const results = {} as Record;
const factories = wreq.m;
- outer:
+
for (const id in factories) {
const factory = factories[id].original ?? factories[id];
- const str: string = factory.toString();
- for (const filter of filters) {
- if (typeof filter === "string" && !str.includes(filter)) continue outer;
- if (filter instanceof RegExp && !filter.test(str)) continue outer;
- }
- results[id] = factory;
+
+ if (stringMatches(factory.toString(), code))
+ results[id] = factory;
}
return results;