From 7740d9a732b810dd73e6a62cb4245f632b9e721e Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Mon, 27 Jan 2025 22:37:46 +0100 Subject: [PATCH 01/22] moreUserTags: rewrite --- src/plugins/moreUserTags/consts.ts | 56 ++++++++++ src/plugins/moreUserTags/index.tsx | 147 ++++++++++++++++++++++++++ src/plugins/moreUserTags/settings.tsx | 76 +++++++++++++ src/plugins/moreUserTags/types.ts | 28 +++++ 4 files changed, 307 insertions(+) create mode 100644 src/plugins/moreUserTags/consts.ts create mode 100644 src/plugins/moreUserTags/index.tsx create mode 100644 src/plugins/moreUserTags/settings.tsx create mode 100644 src/plugins/moreUserTags/types.ts diff --git a/src/plugins/moreUserTags/consts.ts b/src/plugins/moreUserTags/consts.ts new file mode 100644 index 00000000000..422672f383f --- /dev/null +++ b/src/plugins/moreUserTags/consts.ts @@ -0,0 +1,56 @@ +import { RC } from "@webpack/types"; +import type { ITag } from "./types"; +import { findByCodeLazy, findLazy } from "@webpack"; +import { GuildStore } from "@webpack/common"; +import { Channel, Guild, Message, User } from "discord-types/general"; + +export const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot(); +export const tags: ITag[] = [ + { + name: "WEBHOOK", + displayName: "Webhook", + description: "Messages sent by webhooks", + condition: isWebhook + }, { + name: "OWNER", + displayName: "Owner", + description: "Owns the server", + condition: (_, user, channel) => GuildStore.getGuild(channel?.guild_id)?.ownerId === user.id + }, { + name: "ADMINISTRATOR", + displayName: "Admin", + description: "Has the administrator permission", + permissions: ["ADMINISTRATOR"] + }, { + name: "MODERATOR_STAFF", + displayName: "Staff", + description: "Can manage the server, channels or roles", + permissions: ["MANAGE_GUILD", "MANAGE_CHANNELS", "MANAGE_ROLES"] + }, { + name: "MODERATOR", + displayName: "Mod", + description: "Can manage messages or kick/ban people", + permissions: ["MANAGE_MESSAGES", "KICK_MEMBERS", "BAN_MEMBERS"] + }, { + name: "VOICE_MODERATOR", + displayName: "VC Mod", + description: "Can manage voice chats", + permissions: ["MOVE_MEMBERS", "MUTE_MEMBERS", "DEAFEN_MEMBERS"] + }, { + name: "CHAT_MODERATOR", + displayName: "Chat Mod", + description: "Can timeout people", + permissions: ["MODERATE_MEMBERS"] + } +]; + +export const Tag = findLazy(m => m.Types?.[0] === "BOT") as RC<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; + +// PermissionStore.computePermissions will not work here since it only gets permissions for the current user +export const computePermissions: (options: { + user?: { id: string; } | string | null; + context?: Guild | Channel | null; + overwrites?: Channel["permissionOverwrites"] | null; + checkElevated?: boolean /* = true */; + excludeGuildPermissions?: boolean /* = false */; +}) => bigint = findByCodeLazy(".getCurrentUser()", ".computeLurkerPermissionsAllowList()"); diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx new file mode 100644 index 00000000000..7a781c96081 --- /dev/null +++ b/src/plugins/moreUserTags/index.tsx @@ -0,0 +1,147 @@ +import definePlugin from "@utils/types"; +import { Devs } from "@utils/constants"; +import { settings } from './settings'; +import { computePermissions, isWebhook, Tag, tags } from "./consts"; +import { getIntlMessage } from "@utils/discord"; +import { ChannelStore, GuildStore, PermissionsBits } from "@webpack/common"; +import { Channel, Message, User } from "discord-types/general"; +import { tag } from "type-fest/source/opaque"; + + +export default definePlugin({ + name: "MoreUserTags", + description: "Adds tags for webhooks and moderative roles (owner, admin, etc.)", + authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN], + settings, + patches: [ + // Add tags + { + find: '.ORIGINAL_POSTER=', + replacement: { + match: /function\(\i\){(?=.{1,30}.BOT)/, + replace: "$&$self.genTagTypes(arguments[0]);" + } + }, + // Render Tags in messages + { + find: '.Types.ORIGINAL_POSTER', + replacement: { + match: /(?<=let (\i).{1,200}children:\i}=\i;.{0,100}.isSystemDM.{0,350}),null==\i\)(?=.{1,30}?null:)/, + replace: ',($1=$self.getTag({...arguments[0],location:"chat",origType:$1}))$&' + } + }, + { + find: '.STAFF_ONLY_DM:', + replacement: { + match: /(?<=type:(\i).{10,1000}.REMIX.{10,100})default:(\i)=/, + replace: "default:$2=$self.tagObj[$1];" + } + } + ], + tagObj: {}, + + genTagTypes(obj) { + let i = 100; + + for (const { name } of tags) { + obj[name] = ++i; + obj[i] = name; + obj[`${name}-BOT`] = ++i; + obj[i] = `${name}-BOT`; + obj[`${name}-OP`] = ++i; + obj[i] = `${name}-OP`; + } + + this.tagObj = obj; + }, + + getTagText(passedTagName: string, originalText: string) { + try { + if (!passedTagName) return getIntlMessage("APP_TAG"); + const [tagName, variant] = passedTagName.split("-"); + + const tag = tags.find(({ name }) => tagName === name); + if (!tag) return getIntlMessage("APP_TAG"); + + if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return getIntlMessage("APP_TAG"); + + const tagText = settings.store.tagSettings?.[tag.name]?.text || tag.displayName; + switch (variant) { + case "OP": + return `${getIntlMessage("BOT_TAG_FORUM_ORIGINAL_POSTER")} • ${tagText}`; + case "BOT": + return `${getIntlMessage("APP_TAG")} • ${tagText}`; + default: + return tagText; + } + } catch { + return originalText; + } + }, + + getTag({ + message, user, channelId, origType, location, channel + }: { + message?: Message, + user: User & { isClyde(): boolean; }, + channel?: Channel & { isForumPost(): boolean; isMediaPost(): boolean; }, + channelId?: string; + origType?: number; + location: "chat" | "not-chat"; + }): number | null { + if (!user) + return null; + if (location === "chat" && user.id === "1") + return Tag.Types.OFFICIAL; + if (user.isClyde()) + return Tag.Types.AI; + + let type = typeof origType === "number" ? origType : null; + + channel ??= ChannelStore.getChannel(channelId!) as any; + if (!channel) return type; + + const settings = this.settings.store; + const perms = this.getPermissions(user, channel); + + for (const tag of tags) { + if (location === "chat" && !settings.tagSettings[tag.name].showInChat) continue; + if (location === "not-chat" && !settings.tagSettings[tag.name].showInNotChat) continue; + + // If the owner tag is disabled, and the user is the owner of the guild, + // avoid adding other tags because the owner will always match the condition for them + if ( + tag.name !== "OWNER" && + GuildStore.getGuild(channel?.guild_id)?.ownerId === user.id && + (location === "chat" && !settings.tagSettings.OWNER.showInChat) || + (location === "not-chat" && !settings.tagSettings.OWNER.showInNotChat) + ) continue; + + if ( + tag.permissions?.some(perm => perms.includes(perm)) || + (tag.condition?.(message!, user, channel)) + ) { + if ((channel.isForumPost() || channel.isMediaPost()) && channel.ownerId === user.id) + type = Tag.Types[`${tag.name}-OP`]; + else if (user.bot && !isWebhook(message!, user) && !settings.dontShowBotTag) + type = Tag.Types[`${tag.name}-BOT`]; + else + type = Tag.Types[tag.name]; + break; + } + } + return type; + }, + getPermissions(user: User, channel: Channel): string[] { + const guild = GuildStore.getGuild(channel?.guild_id); + if (!guild) return []; + + const permissions = computePermissions({ user, context: guild, overwrites: channel.permissionOverwrites }); + return Object.entries(PermissionsBits) + .map(([perm, permInt]) => + permissions & permInt ? perm : "" + ) + .filter(Boolean); + }, +}); + diff --git a/src/plugins/moreUserTags/settings.tsx b/src/plugins/moreUserTags/settings.tsx new file mode 100644 index 00000000000..44b2392f59f --- /dev/null +++ b/src/plugins/moreUserTags/settings.tsx @@ -0,0 +1,76 @@ +import { definePluginSettings } from "@api/Settings"; +import { Margins } from "@utils/margins"; +import { OptionType } from "@utils/types"; +import { Card, Flex, Forms, Switch, TextInput, Tooltip } from "@webpack/common"; +import { TagSettings } from "./types"; +import { Tag, tags } from "./consts"; + + +const defaultSettings = Object.fromEntries( + tags.map(({ name, displayName }) => [name, { text: displayName, showInChat: true, showInNotChat: true }]) +) as TagSettings; + +function SettingsComponent() { + const tagSettings = settings.store.tagSettings ??= defaultSettings; + + return ( + + {tags.map(t => ( + + + + {({ onMouseEnter, onMouseLeave }) => ( +
+ {t.displayName} Tag +
+ )} +
+
+ + tagSettings[t.name].text = v} + className={Margins.bottom16} + /> + + tagSettings[t.name].showInChat = v} + hideBorder + > + Show in messages + + + tagSettings[t.name].showInNotChat = v} + hideBorder + > + Show in member list and profiles + +
+ ))} +
+ ); +} + +export const settings = definePluginSettings({ + dontShowForBots: { + description: "Don't show extra tags for bots (excluding webhooks)", + type: OptionType.BOOLEAN + }, + dontShowBotTag: { + description: "Only show extra tags for bots / Hide [BOT] text", + type: OptionType.BOOLEAN + }, + tagSettings: { + type: OptionType.COMPONENT, + component: SettingsComponent, + description: "fill me" + } +}); diff --git a/src/plugins/moreUserTags/types.ts b/src/plugins/moreUserTags/types.ts new file mode 100644 index 00000000000..85eefce6be1 --- /dev/null +++ b/src/plugins/moreUserTags/types.ts @@ -0,0 +1,28 @@ +import type { Channel, Message, User } from "discord-types/general"; +import type { Permissions } from "@webpack/types"; + +export interface ITag { + // name used for identifying, must be alphanumeric + underscores + name: string; + // name shown on the tag itself, can be anything probably; automatically uppercase'd + displayName: string; + description: string; + permissions?: Permissions[]; + condition?(message: Message | null, user: User, channel: Channel): boolean; +} + +export interface TagSetting { + text: string; + showInChat: boolean; + showInNotChat: boolean; +} +export interface TagSettings { + WEBHOOK: TagSetting, + OWNER: TagSetting, + ADMINISTRATOR: TagSetting, + MODERATOR_STAFF: TagSetting, + MODERATOR: TagSetting, + VOICE_MODERATOR: TagSetting, + TRIAL_MODERATOR: TagSetting, + [k: string]: TagSetting; +} From b74e5e2af3ea76d43585cc5fd62c7f8b594daaf0 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Mon, 27 Jan 2025 22:47:16 +0100 Subject: [PATCH 02/22] moreUserTags: readable tags/devs --- src/plugins/moreUserTags/index.tsx | 39 ++++++++++++++---------------- src/utils/constants.ts | 4 +++ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 7a781c96081..2ee593ca0de 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -5,13 +5,12 @@ import { computePermissions, isWebhook, Tag, tags } from "./consts"; import { getIntlMessage } from "@utils/discord"; import { ChannelStore, GuildStore, PermissionsBits } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; -import { tag } from "type-fest/source/opaque"; export default definePlugin({ name: "MoreUserTags", description: "Adds tags for webhooks and moderative roles (owner, admin, etc.)", - authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN], + authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN, Devs.hen], settings, patches: [ // Add tags @@ -23,6 +22,7 @@ export default definePlugin({ } }, // Render Tags in messages + // Maybe there is a better way to catch this horror { find: '.Types.ORIGINAL_POSTER', replacement: { @@ -30,11 +30,12 @@ export default definePlugin({ replace: ',($1=$self.getTag({...arguments[0],location:"chat",origType:$1}))$&' } }, + // Make discord actually use our tags { find: '.STAFF_ONLY_DM:', replacement: { match: /(?<=type:(\i).{10,1000}.REMIX.{10,100})default:(\i)=/, - replace: "default:$2=$self.tagObj[$1];" + replace: "default:$2=$self.getTagText($self.tagObj[$1]);" } } ], @@ -55,27 +56,23 @@ export default definePlugin({ this.tagObj = obj; }, - getTagText(passedTagName: string, originalText: string) { - try { - if (!passedTagName) return getIntlMessage("APP_TAG"); - const [tagName, variant] = passedTagName.split("-"); + getTagText(passedTagName: string) { + if (!passedTagName) return getIntlMessage("APP_TAG"); + const [tagName, variant] = passedTagName.split("-"); - const tag = tags.find(({ name }) => tagName === name); - if (!tag) return getIntlMessage("APP_TAG"); + const tag = tags.find(({ name }) => tagName === name); + if (!tag) return getIntlMessage("APP_TAG"); - if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return getIntlMessage("APP_TAG"); + if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return getIntlMessage("APP_TAG"); - const tagText = settings.store.tagSettings?.[tag.name]?.text || tag.displayName; - switch (variant) { - case "OP": - return `${getIntlMessage("BOT_TAG_FORUM_ORIGINAL_POSTER")} • ${tagText}`; - case "BOT": - return `${getIntlMessage("APP_TAG")} • ${tagText}`; - default: - return tagText; - } - } catch { - return originalText; + const tagText = settings.store.tagSettings?.[tag.name]?.text || tag.displayName; + switch (variant) { + case "OP": + return `${getIntlMessage("BOT_TAG_FORUM_ORIGINAL_POSTER")} • ${tagText}`; + case "BOT": + return `${getIntlMessage("APP_TAG")} • ${tagText}`; + default: + return tagText; } }, diff --git a/src/utils/constants.ts b/src/utils/constants.ts index e7582591257..5b93efbf8b4 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -579,6 +579,10 @@ export const Devs = /* #__PURE__*/ Object.freeze({ name: "jamesbt365", id: 158567567487795200n, }, + hen: { + id: 279266228151779329n, + name: "Hen" + } } satisfies Record); // iife so #__PURE__ works correctly From 97f540c5fbb99195ce36edbf606f78044daf8d64 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Mon, 27 Jan 2025 22:53:36 +0100 Subject: [PATCH 03/22] no more lint fails for you, sadan --- src/plugins/moreUserTags/consts.ts | 11 +++++++++-- src/plugins/moreUserTags/index.tsx | 19 +++++++++++++------ src/plugins/moreUserTags/settings.tsx | 9 ++++++++- src/plugins/moreUserTags/types.ts | 8 +++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/plugins/moreUserTags/consts.ts b/src/plugins/moreUserTags/consts.ts index 422672f383f..7f952b90ee4 100644 --- a/src/plugins/moreUserTags/consts.ts +++ b/src/plugins/moreUserTags/consts.ts @@ -1,9 +1,16 @@ -import { RC } from "@webpack/types"; -import type { ITag } from "./types"; +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + import { findByCodeLazy, findLazy } from "@webpack"; import { GuildStore } from "@webpack/common"; +import { RC } from "@webpack/types"; import { Channel, Guild, Message, User } from "discord-types/general"; +import type { ITag } from "./types"; + export const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot(); export const tags: ITag[] = [ { diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 2ee593ca0de..a6f49d647ca 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -1,11 +1,18 @@ -import definePlugin from "@utils/types"; +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + import { Devs } from "@utils/constants"; -import { settings } from './settings'; -import { computePermissions, isWebhook, Tag, tags } from "./consts"; import { getIntlMessage } from "@utils/discord"; +import definePlugin from "@utils/types"; import { ChannelStore, GuildStore, PermissionsBits } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; +import { computePermissions, isWebhook, Tag, tags } from "./consts"; +import { settings } from "./settings"; + export default definePlugin({ name: "MoreUserTags", @@ -15,7 +22,7 @@ export default definePlugin({ patches: [ // Add tags { - find: '.ORIGINAL_POSTER=', + find: ".ORIGINAL_POSTER=", replacement: { match: /function\(\i\){(?=.{1,30}.BOT)/, replace: "$&$self.genTagTypes(arguments[0]);" @@ -24,7 +31,7 @@ export default definePlugin({ // Render Tags in messages // Maybe there is a better way to catch this horror { - find: '.Types.ORIGINAL_POSTER', + find: ".Types.ORIGINAL_POSTER", replacement: { match: /(?<=let (\i).{1,200}children:\i}=\i;.{0,100}.isSystemDM.{0,350}),null==\i\)(?=.{1,30}?null:)/, replace: ',($1=$self.getTag({...arguments[0],location:"chat",origType:$1}))$&' @@ -32,7 +39,7 @@ export default definePlugin({ }, // Make discord actually use our tags { - find: '.STAFF_ONLY_DM:', + find: ".STAFF_ONLY_DM:", replacement: { match: /(?<=type:(\i).{10,1000}.REMIX.{10,100})default:(\i)=/, replace: "default:$2=$self.getTagText($self.tagObj[$1]);" diff --git a/src/plugins/moreUserTags/settings.tsx b/src/plugins/moreUserTags/settings.tsx index 44b2392f59f..e0cff67fc2d 100644 --- a/src/plugins/moreUserTags/settings.tsx +++ b/src/plugins/moreUserTags/settings.tsx @@ -1,9 +1,16 @@ +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + import { definePluginSettings } from "@api/Settings"; import { Margins } from "@utils/margins"; import { OptionType } from "@utils/types"; import { Card, Flex, Forms, Switch, TextInput, Tooltip } from "@webpack/common"; -import { TagSettings } from "./types"; + import { Tag, tags } from "./consts"; +import { TagSettings } from "./types"; const defaultSettings = Object.fromEntries( diff --git a/src/plugins/moreUserTags/types.ts b/src/plugins/moreUserTags/types.ts index 85eefce6be1..2a63451d9da 100644 --- a/src/plugins/moreUserTags/types.ts +++ b/src/plugins/moreUserTags/types.ts @@ -1,5 +1,11 @@ -import type { Channel, Message, User } from "discord-types/general"; +/* + * Vencord, a Discord client mod + * Copyright (c) 2025 Vendicated and contributors + * SPDX-License-Identifier: GPL-3.0-or-later + */ + import type { Permissions } from "@webpack/types"; +import type { Channel, Message, User } from "discord-types/general"; export interface ITag { // name used for identifying, must be alphanumeric + underscores From c219cdcfde75139b2b295907af4c2d6a6a78c172 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Mon, 27 Jan 2025 23:09:12 +0100 Subject: [PATCH 04/22] moreUserTags: removed 'add tags' patch --- src/plugins/moreUserTags/index.tsx | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index a6f49d647ca..6b9d6c52a5c 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -6,7 +6,7 @@ import { Devs } from "@utils/constants"; import { getIntlMessage } from "@utils/discord"; -import definePlugin from "@utils/types"; +import definePlugin, { StartAt } from "@utils/types"; import { ChannelStore, GuildStore, PermissionsBits } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; @@ -20,14 +20,6 @@ export default definePlugin({ authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN, Devs.hen], settings, patches: [ - // Add tags - { - find: ".ORIGINAL_POSTER=", - replacement: { - match: /function\(\i\){(?=.{1,30}.BOT)/, - replace: "$&$self.genTagTypes(arguments[0]);" - } - }, // Render Tags in messages // Maybe there is a better way to catch this horror { @@ -47,9 +39,14 @@ export default definePlugin({ } ], tagObj: {}, + startAt: StartAt.Init, + start() { + this.genTagTypes(); + }, - genTagTypes(obj) { + genTagTypes() { let i = 100; + const obj = {}; for (const { name } of tags) { obj[name] = ++i; @@ -125,15 +122,17 @@ export default definePlugin({ tag.permissions?.some(perm => perms.includes(perm)) || (tag.condition?.(message!, user, channel)) ) { + console.log("TAGS HELP", tag, this.tagObj); if ((channel.isForumPost() || channel.isMediaPost()) && channel.ownerId === user.id) - type = Tag.Types[`${tag.name}-OP`]; + type = this.tagObj[`${tag.name}-OP`]; else if (user.bot && !isWebhook(message!, user) && !settings.dontShowBotTag) - type = Tag.Types[`${tag.name}-BOT`]; + type = this.tagObj[`${tag.name}-BOT`]; else - type = Tag.Types[tag.name]; + type = this.tagObj[tag.name]; break; } } + console.log("TAGS", type); return type; }, getPermissions(user: User, channel: Channel): string[] { From f9ab7d306b69848b48d4f4e3c296349628510900 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Tue, 28 Jan 2025 08:39:31 +0100 Subject: [PATCH 05/22] moreUserTags: rename obj/format --- src/plugins/moreUserTags/index.tsx | 112 +++++++++++++++++------------ 1 file changed, 67 insertions(+), 45 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 6b9d6c52a5c..8c551348e29 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -6,18 +6,41 @@ import { Devs } from "@utils/constants"; import { getIntlMessage } from "@utils/discord"; -import definePlugin, { StartAt } from "@utils/types"; +import definePlugin from "@utils/types"; import { ChannelStore, GuildStore, PermissionsBits } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; import { computePermissions, isWebhook, Tag, tags } from "./consts"; import { settings } from "./settings"; +const genTagTypes = () => { + let i = 100; + const obj = {}; + + for (const { name } of tags) { + obj[name] = ++i; + obj[i] = name; + obj[`${name}-BOT`] = ++i; + obj[i] = `${name}-BOT`; + obj[`${name}-OP`] = ++i; + obj[i] = `${name}-OP`; + } + + return obj; +}; export default definePlugin({ name: "MoreUserTags", - description: "Adds tags for webhooks and moderative roles (owner, admin, etc.)", - authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN, Devs.hen], + description: + "Adds tags for webhooks and moderative roles (owner, admin, etc.)", + authors: [ + Devs.Cyn, + Devs.TheSun, + Devs.RyanCaoDev, + Devs.LordElias, + Devs.AutumnVN, + Devs.hen, + ], settings, patches: [ // Render Tags in messages @@ -26,39 +49,20 @@ export default definePlugin({ find: ".Types.ORIGINAL_POSTER", replacement: { match: /(?<=let (\i).{1,200}children:\i}=\i;.{0,100}.isSystemDM.{0,350}),null==\i\)(?=.{1,30}?null:)/, - replace: ',($1=$self.getTag({...arguments[0],location:"chat",origType:$1}))$&' - } + replace: + ',($1=$self.getTag({...arguments[0],location:"chat",origType:$1}))$&', + }, }, // Make discord actually use our tags { find: ".STAFF_ONLY_DM:", replacement: { match: /(?<=type:(\i).{10,1000}.REMIX.{10,100})default:(\i)=/, - replace: "default:$2=$self.getTagText($self.tagObj[$1]);" - } - } + replace: "default:$2=$self.getTagText($self.localTags[$1]);", + }, + }, ], - tagObj: {}, - startAt: StartAt.Init, - start() { - this.genTagTypes(); - }, - - genTagTypes() { - let i = 100; - const obj = {}; - - for (const { name } of tags) { - obj[name] = ++i; - obj[i] = name; - obj[`${name}-BOT`] = ++i; - obj[i] = `${name}-BOT`; - obj[`${name}-OP`] = ++i; - obj[i] = `${name}-OP`; - } - - this.tagObj = obj; - }, + localTags: genTagTypes(), getTagText(passedTagName: string) { if (!passedTagName) return getIntlMessage("APP_TAG"); @@ -106,29 +110,47 @@ export default definePlugin({ const perms = this.getPermissions(user, channel); for (const tag of tags) { - if (location === "chat" && !settings.tagSettings[tag.name].showInChat) continue; - if (location === "not-chat" && !settings.tagSettings[tag.name].showInNotChat) continue; + if ( + location === "chat" && + !settings.tagSettings[tag.name].showInChat + ) + continue; + if ( + location === "not-chat" && + !settings.tagSettings[tag.name].showInNotChat + ) + continue; // If the owner tag is disabled, and the user is the owner of the guild, // avoid adding other tags because the owner will always match the condition for them if ( - tag.name !== "OWNER" && - GuildStore.getGuild(channel?.guild_id)?.ownerId === user.id && - (location === "chat" && !settings.tagSettings.OWNER.showInChat) || - (location === "not-chat" && !settings.tagSettings.OWNER.showInNotChat) - ) continue; + (tag.name !== "OWNER" && + GuildStore.getGuild(channel?.guild_id)?.ownerId === + user.id && + location === "chat" && + !settings.tagSettings.OWNER.showInChat) || + (location === "not-chat" && + !settings.tagSettings.OWNER.showInNotChat) + ) + continue; if ( - tag.permissions?.some(perm => perms.includes(perm)) || - (tag.condition?.(message!, user, channel)) + tag.permissions?.some((perm) => perms.includes(perm)) || + tag.condition?.(message!, user, channel) ) { - console.log("TAGS HELP", tag, this.tagObj); - if ((channel.isForumPost() || channel.isMediaPost()) && channel.ownerId === user.id) - type = this.tagObj[`${tag.name}-OP`]; - else if (user.bot && !isWebhook(message!, user) && !settings.dontShowBotTag) - type = this.tagObj[`${tag.name}-BOT`]; - else - type = this.tagObj[tag.name]; + console.log("TAGS HELP", tag, this.localTags); + if ( + (channel.isForumPost() || channel.isMediaPost()) && + channel.ownerId === user.id + ) + type = this.localTags[`${tag.name}-OP`]; + else if ( + user.bot && + !isWebhook(message!, user) && + !settings.dontShowBotTag + ) + type = this.localTags[`${tag.name}-BOT`]; + else type = this.localTags[tag.name]; break; } } From ae1ed2579ff7f5ee984afdd0571bc9e6b36222b3 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Tue, 28 Jan 2025 21:45:31 +0100 Subject: [PATCH 06/22] moreUserTags: memberList --- src/plugins/moreUserTags/index.tsx | 50 +++++++++++++----------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 8c551348e29..8742e314f49 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -31,24 +31,16 @@ const genTagTypes = () => { export default definePlugin({ name: "MoreUserTags", - description: - "Adds tags for webhooks and moderative roles (owner, admin, etc.)", - authors: [ - Devs.Cyn, - Devs.TheSun, - Devs.RyanCaoDev, - Devs.LordElias, - Devs.AutumnVN, - Devs.hen, - ], + description: "Adds tags for webhooks and moderative roles (owner, admin, etc.)", + authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN, Devs.hen], settings, patches: [ // Render Tags in messages // Maybe there is a better way to catch this horror { - find: ".Types.ORIGINAL_POSTER", + find: ".isVerifiedBot(),hideIcon:", replacement: { - match: /(?<=let (\i).{1,200}children:\i}=\i;.{0,100}.isSystemDM.{0,350}),null==\i\)(?=.{1,30}?null:)/, + match: /(?<=let (\i).{1,500}.isSystemDM.{0,350}),null==(\i\))(?=.{1,30}?null:)/, replace: ',($1=$self.getTag({...arguments[0],location:"chat",origType:$1}))$&', }, @@ -61,6 +53,16 @@ export default definePlugin({ replace: "default:$2=$self.getTagText($self.localTags[$1]);", }, }, + // Member list + // In the current state it makes smth like + // null != U && U && ($1=blahblahblah) + { + find: ".lostPermission)", + replacement: { + match: /(?<=return .{0,20})\.bot?(?=.{0,100}type:(\i))/, + replace: "&& ($1=$self.getTag({...arguments[0],location:'non-chat',origType:$1}))" + } + } ], localTags: genTagTypes(), @@ -110,15 +112,9 @@ export default definePlugin({ const perms = this.getPermissions(user, channel); for (const tag of tags) { - if ( - location === "chat" && - !settings.tagSettings[tag.name].showInChat - ) + if (location === "chat" && !settings.tagSettings[tag.name].showInChat) continue; - if ( - location === "not-chat" && - !settings.tagSettings[tag.name].showInNotChat - ) + if (location === "not-chat" && !settings.tagSettings[tag.name].showInNotChat) continue; // If the owner tag is disabled, and the user is the owner of the guild, @@ -126,7 +122,7 @@ export default definePlugin({ if ( (tag.name !== "OWNER" && GuildStore.getGuild(channel?.guild_id)?.ownerId === - user.id && + user.id && location === "chat" && !settings.tagSettings.OWNER.showInChat) || (location === "not-chat" && @@ -135,26 +131,24 @@ export default definePlugin({ continue; if ( - tag.permissions?.some((perm) => perms.includes(perm)) || + tag.permissions?.some(perm => perms.includes(perm)) || tag.condition?.(message!, user, channel) ) { - console.log("TAGS HELP", tag, this.localTags); - if ( - (channel.isForumPost() || channel.isMediaPost()) && - channel.ownerId === user.id - ) + if ((channel.isForumPost() || channel.isMediaPost()) && channel.ownerId === user.id) type = this.localTags[`${tag.name}-OP`]; + else if ( user.bot && !isWebhook(message!, user) && !settings.dontShowBotTag ) type = this.localTags[`${tag.name}-BOT`]; + else type = this.localTags[tag.name]; break; } } - console.log("TAGS", type); + return type; }, getPermissions(user: User, channel: Channel): string[] { From 9ea2f6f8bcd5646edf46af1e11588a3959d6a802 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Tue, 28 Jan 2025 22:50:11 +0100 Subject: [PATCH 07/22] moreUserTags: profile support --- src/plugins/moreUserTags/index.tsx | 36 ++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 8742e314f49..48a82084fd0 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -42,7 +42,7 @@ export default definePlugin({ replacement: { match: /(?<=let (\i).{1,500}.isSystemDM.{0,350}),null==(\i\))(?=.{1,30}?null:)/, replace: - ',($1=$self.getTag({...arguments[0],location:"chat",origType:$1}))$&', + ",($1=$self.getTag({...arguments[0],isChat:true,origType:$1}))$&", }, }, // Make discord actually use our tags @@ -60,7 +60,25 @@ export default definePlugin({ find: ".lostPermission)", replacement: { match: /(?<=return .{0,20})\.bot?(?=.{0,100}type:(\i))/, - replace: "&& ($1=$self.getTag({...arguments[0],location:'non-chat',origType:$1}))" + replace: "&& ($1=$self.getTag({...arguments[0],isChat:false,origType:$1}))" + } + }, + + // Next both 2 patches are goint together + // First one passes down the react dom channelId which is required to get tag + // Second one actually gets/displays it + { + find: ".hasAvatarForGuild(null==", + replacement: { + match: /user:\i,(?=.{0,50}.BITE_SIZE)/, + replace: "$&channelId:arguments[0].channelId," + }, + }, + { + find: ".clickableUsername", + replacement: { + match: /null!=(\i)(?=.{0,100}type:\i)/, + replace: "($1=$self.getTag({...arguments[0],isChat:false,origType:$1}),$1!==null)" } } ], @@ -87,18 +105,18 @@ export default definePlugin({ }, getTag({ - message, user, channelId, origType, location, channel + message, user, channelId, origType, isChat, channel, ...rest }: { message?: Message, user: User & { isClyde(): boolean; }, channel?: Channel & { isForumPost(): boolean; isMediaPost(): boolean; }, channelId?: string; origType?: number; - location: "chat" | "not-chat"; + isChat?: boolean; }): number | null { if (!user) return null; - if (location === "chat" && user.id === "1") + if (isChat && user.id === "1") return Tag.Types.OFFICIAL; if (user.isClyde()) return Tag.Types.AI; @@ -112,9 +130,9 @@ export default definePlugin({ const perms = this.getPermissions(user, channel); for (const tag of tags) { - if (location === "chat" && !settings.tagSettings[tag.name].showInChat) + if (isChat && !settings.tagSettings[tag.name].showInChat) continue; - if (location === "not-chat" && !settings.tagSettings[tag.name].showInNotChat) + if (!isChat && !settings.tagSettings[tag.name].showInNotChat) continue; // If the owner tag is disabled, and the user is the owner of the guild, @@ -123,9 +141,9 @@ export default definePlugin({ (tag.name !== "OWNER" && GuildStore.getGuild(channel?.guild_id)?.ownerId === user.id && - location === "chat" && + isChat && !settings.tagSettings.OWNER.showInChat) || - (location === "not-chat" && + (!isChat && !settings.tagSettings.OWNER.showInNotChat) ) continue; From 6ef97124cc403e02c498cbddc916605d4ed4043a Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Wed, 29 Jan 2025 16:26:49 +0100 Subject: [PATCH 08/22] moreUserTags: better typing --- src/plugins/moreUserTags/consts.ts | 4 ++-- src/plugins/moreUserTags/index.tsx | 7 +++---- src/plugins/moreUserTags/types.ts | 24 +++++++++++------------- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/plugins/moreUserTags/consts.ts b/src/plugins/moreUserTags/consts.ts index 7f952b90ee4..899498c7d37 100644 --- a/src/plugins/moreUserTags/consts.ts +++ b/src/plugins/moreUserTags/consts.ts @@ -12,7 +12,7 @@ import { Channel, Guild, Message, User } from "discord-types/general"; import type { ITag } from "./types"; export const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot(); -export const tags: ITag[] = [ +export const tags = [ { name: "WEBHOOK", displayName: "Webhook", @@ -49,7 +49,7 @@ export const tags: ITag[] = [ description: "Can timeout people", permissions: ["MODERATE_MEMBERS"] } -]; +] as const satisfies ITag[]; export const Tag = findLazy(m => m.Types?.[0] === "BOT") as RC<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 48a82084fd0..ae87f4ca845 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -148,10 +148,9 @@ export default definePlugin({ ) continue; - if ( - tag.permissions?.some(perm => perms.includes(perm)) || - tag.condition?.(message!, user, channel) - ) { + if ("permissions" in tag ? + tag.permissions.some(perm => perms.includes(perm)) : + tag.condition(message!, user, channel)) { if ((channel.isForumPost() || channel.isMediaPost()) && channel.ownerId === user.id) type = this.localTags[`${tag.name}-OP`]; diff --git a/src/plugins/moreUserTags/types.ts b/src/plugins/moreUserTags/types.ts index 2a63451d9da..40d8ac7d379 100644 --- a/src/plugins/moreUserTags/types.ts +++ b/src/plugins/moreUserTags/types.ts @@ -7,28 +7,26 @@ import type { Permissions } from "@webpack/types"; import type { Channel, Message, User } from "discord-types/general"; -export interface ITag { +import { tags } from "./consts"; + +export type ITag = { // name used for identifying, must be alphanumeric + underscores name: string; // name shown on the tag itself, can be anything probably; automatically uppercase'd displayName: string; description: string; - permissions?: Permissions[]; +} & ({ + permissions: Permissions[]; +} | { condition?(message: Message | null, user: User, channel: Channel): boolean; -} +}); export interface TagSetting { text: string; showInChat: boolean; showInNotChat: boolean; } -export interface TagSettings { - WEBHOOK: TagSetting, - OWNER: TagSetting, - ADMINISTRATOR: TagSetting, - MODERATOR_STAFF: TagSetting, - MODERATOR: TagSetting, - VOICE_MODERATOR: TagSetting, - TRIAL_MODERATOR: TagSetting, - [k: string]: TagSetting; -} + +export type TagSettings = { + [k in typeof tags[number]["name"]]: TagSetting; +}; From 7ea9677ffa1a2ddfa9f1598dfb1a25cc3ed80809 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Wed, 29 Jan 2025 17:22:35 +0100 Subject: [PATCH 09/22] moreUserTags: use decorations --- src/plugins/moreUserTags/consts.ts | 5 ++-- src/plugins/moreUserTags/index.tsx | 42 +++++++++++++++++++++--------- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/plugins/moreUserTags/consts.ts b/src/plugins/moreUserTags/consts.ts index 899498c7d37..8542f3d98d1 100644 --- a/src/plugins/moreUserTags/consts.ts +++ b/src/plugins/moreUserTags/consts.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { findByCodeLazy, findLazy } from "@webpack"; +import { findByCodeLazy, findByPropsLazy, findLazy } from "@webpack"; import { GuildStore } from "@webpack/common"; import { RC } from "@webpack/types"; import { Channel, Guild, Message, User } from "discord-types/general"; @@ -51,7 +51,8 @@ export const tags = [ } ] as const satisfies ITag[]; -export const Tag = findLazy(m => m.Types?.[0] === "BOT") as RC<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; +export const Tag = findLazy(m => m.Types?.[0] === "BOT") as RC<{ type?: number | null, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; +export const classNames = findByPropsLazy("botTagCompact"); // PermissionStore.computePermissions will not work here since it only gets permissions for the current user export const computePermissions: (options: { diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index ae87f4ca845..56c369e3e27 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -10,7 +10,7 @@ import definePlugin from "@utils/types"; import { ChannelStore, GuildStore, PermissionsBits } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; -import { computePermissions, isWebhook, Tag, tags } from "./consts"; +import { classNames, computePermissions, isWebhook, Tag, tags } from "./consts"; import { settings } from "./settings"; const genTagTypes = () => { @@ -35,16 +35,16 @@ export default definePlugin({ authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN, Devs.hen], settings, patches: [ - // Render Tags in messages - // Maybe there is a better way to catch this horror - { - find: ".isVerifiedBot(),hideIcon:", - replacement: { - match: /(?<=let (\i).{1,500}.isSystemDM.{0,350}),null==(\i\))(?=.{1,30}?null:)/, - replace: - ",($1=$self.getTag({...arguments[0],isChat:true,origType:$1}))$&", - }, - }, + // // Render Tags in messages + // // Maybe there is a better way to catch this horror + // { + // find: ".isVerifiedBot(),hideIcon:", + // replacement: { + // match: /(?<=let (\i).{1,500}.isSystemDM.{0,350}),null==(\i\))(?=.{1,30}?null:)/, + // replace: + // ",($1=$self.getTag({...arguments[0],isChat:true,origType:$1}))$&", + // }, + // }, // Make discord actually use our tags { find: ".STAFF_ONLY_DM:", @@ -82,6 +82,19 @@ export default definePlugin({ } } ], + renderMessageDecoration(props) { + const tag = this.getTag({ + message: props.message, + isChat: true + }); + + return tag && ; + }, localTags: genTagTypes(), getTagText(passedTagName: string) { @@ -105,15 +118,17 @@ export default definePlugin({ }, getTag({ - message, user, channelId, origType, isChat, channel, ...rest + message, user, channelId, origType, isChat, channel }: { message?: Message, - user: User & { isClyde(): boolean; }, + user?: User & { isClyde(): boolean; }, channel?: Channel & { isForumPost(): boolean; isMediaPost(): boolean; }, channelId?: string; origType?: number; isChat?: boolean; }): number | null { + user ??= message?.author as any; + if (!user) return null; if (isChat && user.id === "1") @@ -123,6 +138,7 @@ export default definePlugin({ let type = typeof origType === "number" ? origType : null; + channelId ??= message?.channel_id as any; channel ??= ChannelStore.getChannel(channelId!) as any; if (!channel) return type; From f22d9fc08bc590de036e43b8b03d94d1d9bb0009 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Wed, 29 Jan 2025 18:51:25 +0100 Subject: [PATCH 10/22] moreUserTags: revert to patching --- src/plugins/moreUserTags/index.tsx | 35 ++++++++++-------------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 56c369e3e27..e7f54b0b71b 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -10,7 +10,7 @@ import definePlugin from "@utils/types"; import { ChannelStore, GuildStore, PermissionsBits } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; -import { classNames, computePermissions, isWebhook, Tag, tags } from "./consts"; +import { computePermissions, isWebhook, Tag, tags } from "./consts"; import { settings } from "./settings"; const genTagTypes = () => { @@ -35,16 +35,16 @@ export default definePlugin({ authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN, Devs.hen], settings, patches: [ - // // Render Tags in messages - // // Maybe there is a better way to catch this horror - // { - // find: ".isVerifiedBot(),hideIcon:", - // replacement: { - // match: /(?<=let (\i).{1,500}.isSystemDM.{0,350}),null==(\i\))(?=.{1,30}?null:)/, - // replace: - // ",($1=$self.getTag({...arguments[0],isChat:true,origType:$1}))$&", - // }, - // }, + // Render Tags in messages + // Maybe there is a better way to catch this horror + { + find: ".isVerifiedBot(),hideIcon:", + replacement: { + match: /(?<=let (\i).{1,500}.isSystemDM.{0,350}),null==(\i\))(?=.{1,30}?null:)/, + replace: + ",($1=$self.getTag({...arguments[0],isChat:true,origType:$1}))$&", + }, + }, // Make discord actually use our tags { find: ".STAFF_ONLY_DM:", @@ -82,19 +82,6 @@ export default definePlugin({ } } ], - renderMessageDecoration(props) { - const tag = this.getTag({ - message: props.message, - isChat: true - }); - - return tag && ; - }, localTags: genTagTypes(), getTagText(passedTagName: string) { From 5a6ea90478f7aa061c548882b33987fb609b358c Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Mon, 3 Feb 2025 17:43:19 +0100 Subject: [PATCH 11/22] moreUserTags: use decorations --- src/plugins/moreUserTags/consts.ts | 3 +- src/plugins/moreUserTags/index.tsx | 78 ++++++++++++++---------------- 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/plugins/moreUserTags/consts.ts b/src/plugins/moreUserTags/consts.ts index 8542f3d98d1..e2ccc0709ad 100644 --- a/src/plugins/moreUserTags/consts.ts +++ b/src/plugins/moreUserTags/consts.ts @@ -52,7 +52,8 @@ export const tags = [ ] as const satisfies ITag[]; export const Tag = findLazy(m => m.Types?.[0] === "BOT") as RC<{ type?: number | null, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; -export const classNames = findByPropsLazy("botTagCompact"); +export const messageClassNames = findByPropsLazy("botTagCompact"); +export const memberListClassNames = findByPropsLazy("memberInner"); // PermissionStore.computePermissions will not work here since it only gets permissions for the current user export const computePermissions: (options: { diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index e7f54b0b71b..2e370d2e578 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -7,10 +7,10 @@ import { Devs } from "@utils/constants"; import { getIntlMessage } from "@utils/discord"; import definePlugin from "@utils/types"; -import { ChannelStore, GuildStore, PermissionsBits } from "@webpack/common"; +import { ChannelStore, GuildStore, PermissionsBits, UserStore } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; -import { computePermissions, isWebhook, Tag, tags } from "./consts"; +import { computePermissions, memberListClassNames, messageClassNames, Tag, tags } from "./consts"; import { settings } from "./settings"; const genTagTypes = () => { @@ -35,16 +35,6 @@ export default definePlugin({ authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias, Devs.AutumnVN, Devs.hen], settings, patches: [ - // Render Tags in messages - // Maybe there is a better way to catch this horror - { - find: ".isVerifiedBot(),hideIcon:", - replacement: { - match: /(?<=let (\i).{1,500}.isSystemDM.{0,350}),null==(\i\))(?=.{1,30}?null:)/, - replace: - ",($1=$self.getTag({...arguments[0],isChat:true,origType:$1}))$&", - }, - }, // Make discord actually use our tags { find: ".STAFF_ONLY_DM:", @@ -53,16 +43,6 @@ export default definePlugin({ replace: "default:$2=$self.getTagText($self.localTags[$1]);", }, }, - // Member list - // In the current state it makes smth like - // null != U && U && ($1=blahblahblah) - { - find: ".lostPermission)", - replacement: { - match: /(?<=return .{0,20})\.bot?(?=.{0,100}type:(\i))/, - replace: "&& ($1=$self.getTag({...arguments[0],isChat:false,origType:$1}))" - } - }, // Next both 2 patches are goint together // First one passes down the react dom channelId which is required to get tag @@ -83,6 +63,35 @@ export default definePlugin({ } ], localTags: genTagTypes(), + renderMessageDecoration(props) { + const tagId = this.getTag({ + message: props.message, + user: UserStore.getUser(props.message.author.id), + channelId: props.message.channel_id, + isChat: false + }); + + return tagId && + ; + }, + renderMemberListDecorator(props) { + const tagId = this.getTag({ + user: props.user, + channel: props.channel, + isChat: false + }); + + return tagId && + ; + }, getTagText(passedTagName: string) { if (!passedTagName) return getIntlMessage("APP_TAG"); @@ -116,14 +125,11 @@ export default definePlugin({ }): number | null { user ??= message?.author as any; - if (!user) - return null; - if (isChat && user.id === "1") - return Tag.Types.OFFICIAL; - if (user.isClyde()) - return Tag.Types.AI; + if (!user) return null; + if (isChat && user.id === "1") return null; + if (user.isClyde()) return null; - let type = typeof origType === "number" ? origType : null; + const type = typeof origType === "number" ? origType : null; channelId ??= message?.channel_id as any; channel ??= ChannelStore.getChannel(channelId!) as any; @@ -154,18 +160,8 @@ export default definePlugin({ if ("permissions" in tag ? tag.permissions.some(perm => perms.includes(perm)) : tag.condition(message!, user, channel)) { - if ((channel.isForumPost() || channel.isMediaPost()) && channel.ownerId === user.id) - type = this.localTags[`${tag.name}-OP`]; - - else if ( - user.bot && - !isWebhook(message!, user) && - !settings.dontShowBotTag - ) - type = this.localTags[`${tag.name}-BOT`]; - - else type = this.localTags[tag.name]; - break; + + return this.localTags[tag.name]; } } From e2b0e259daad633a05c6f0e2aa8f471a12e73134 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Mon, 3 Feb 2025 19:18:35 +0100 Subject: [PATCH 12/22] moreUserTags: cleanup --- src/plugins/moreUserTags/index.tsx | 59 +++++++++--------------------- 1 file changed, 17 insertions(+), 42 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 2e370d2e578..586c7055350 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -7,7 +7,7 @@ import { Devs } from "@utils/constants"; import { getIntlMessage } from "@utils/discord"; import definePlugin from "@utils/types"; -import { ChannelStore, GuildStore, PermissionsBits, UserStore } from "@webpack/common"; +import { ChannelStore, GuildStore, PermissionsBits, SelectedChannelStore, UserStore } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; import { computePermissions, memberListClassNames, messageClassNames, Tag, tags } from "./consts"; @@ -20,10 +20,6 @@ const genTagTypes = () => { for (const { name } of tags) { obj[name] = ++i; obj[i] = name; - obj[`${name}-BOT`] = ++i; - obj[i] = `${name}-BOT`; - obj[`${name}-OP`] = ++i; - obj[i] = `${name}-OP`; } return obj; @@ -44,25 +40,20 @@ export default definePlugin({ }, }, - // Next both 2 patches are goint together - // First one passes down the react dom channelId which is required to get tag - // Second one actually gets/displays it - { - find: ".hasAvatarForGuild(null==", - replacement: { - match: /user:\i,(?=.{0,50}.BITE_SIZE)/, - replace: "$&channelId:arguments[0].channelId," - }, - }, + // User profile + // TODO: replace with API { find: ".clickableUsername", replacement: { match: /null!=(\i)(?=.{0,100}type:\i)/, - replace: "($1=$self.getTag({...arguments[0],isChat:false,origType:$1}),$1!==null)" + replace: "($1=$self.getTag({...arguments[0],channelId:$self.getChannelId(),isChat:false,origType:$1}),$1!==null)" } } ], localTags: genTagTypes(), + getChannelId() { + return SelectedChannelStore.getChannelId(); + }, renderMessageDecoration(props) { const tagId = this.getTag({ message: props.message, @@ -93,47 +84,31 @@ export default definePlugin({ ; }, - getTagText(passedTagName: string) { - if (!passedTagName) return getIntlMessage("APP_TAG"); - const [tagName, variant] = passedTagName.split("-"); - + getTagText(tagName: string) { + if (!tagName) return getIntlMessage("APP_TAG"); const tag = tags.find(({ name }) => tagName === name); - if (!tag) return getIntlMessage("APP_TAG"); - - if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return getIntlMessage("APP_TAG"); - - const tagText = settings.store.tagSettings?.[tag.name]?.text || tag.displayName; - switch (variant) { - case "OP": - return `${getIntlMessage("BOT_TAG_FORUM_ORIGINAL_POSTER")} • ${tagText}`; - case "BOT": - return `${getIntlMessage("APP_TAG")} • ${tagText}`; - default: - return tagText; - } + if (!tag) return tagName || getIntlMessage("APP_TAG"); + + if (tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return; + + return settings.store.tagSettings?.[tag.name]?.text || tag.displayName; }, getTag({ - message, user, channelId, origType, isChat, channel + message, user, channelId, isChat, channel }: { message?: Message, user?: User & { isClyde(): boolean; }, channel?: Channel & { isForumPost(): boolean; isMediaPost(): boolean; }, channelId?: string; - origType?: number; isChat?: boolean; }): number | null { - user ??= message?.author as any; - if (!user) return null; if (isChat && user.id === "1") return null; if (user.isClyde()) return null; - const type = typeof origType === "number" ? origType : null; - - channelId ??= message?.channel_id as any; channel ??= ChannelStore.getChannel(channelId!) as any; - if (!channel) return type; + if (!channel) return null; const settings = this.settings.store; const perms = this.getPermissions(user, channel); @@ -165,7 +140,7 @@ export default definePlugin({ } } - return type; + return null; }, getPermissions(user: User, channel: Channel): string[] { const guild = GuildStore.getGuild(channel?.guild_id); From ac1c720b17f6bad18dd808b5019a95cb664a7d3c Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Tue, 4 Feb 2025 06:05:53 +0100 Subject: [PATCH 13/22] moreUserTags: change classes --- src/plugins/moreUserTags/consts.ts | 4 +--- src/plugins/moreUserTags/index.tsx | 10 +++++----- src/plugins/moreUserTags/styles.css | 4 ++++ 3 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 src/plugins/moreUserTags/styles.css diff --git a/src/plugins/moreUserTags/consts.ts b/src/plugins/moreUserTags/consts.ts index e2ccc0709ad..14ea3dd9eaf 100644 --- a/src/plugins/moreUserTags/consts.ts +++ b/src/plugins/moreUserTags/consts.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -import { findByCodeLazy, findByPropsLazy, findLazy } from "@webpack"; +import { findByCodeLazy, findLazy } from "@webpack"; import { GuildStore } from "@webpack/common"; import { RC } from "@webpack/types"; import { Channel, Guild, Message, User } from "discord-types/general"; @@ -52,8 +52,6 @@ export const tags = [ ] as const satisfies ITag[]; export const Tag = findLazy(m => m.Types?.[0] === "BOT") as RC<{ type?: number | null, className?: string, useRemSizes?: boolean; }> & { Types: Record; }; -export const messageClassNames = findByPropsLazy("botTagCompact"); -export const memberListClassNames = findByPropsLazy("memberInner"); // PermissionStore.computePermissions will not work here since it only gets permissions for the current user export const computePermissions: (options: { diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 586c7055350..b8db0af6be1 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -4,13 +4,15 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +import "./styles.css"; + import { Devs } from "@utils/constants"; import { getIntlMessage } from "@utils/discord"; import definePlugin from "@utils/types"; import { ChannelStore, GuildStore, PermissionsBits, SelectedChannelStore, UserStore } from "@webpack/common"; import { Channel, Message, User } from "discord-types/general"; -import { computePermissions, memberListClassNames, messageClassNames, Tag, tags } from "./consts"; +import { computePermissions, Tag, tags } from "./consts"; import { settings } from "./settings"; const genTagTypes = () => { @@ -63,9 +65,9 @@ export default definePlugin({ }); return tagId && ; }, @@ -77,9 +79,7 @@ export default definePlugin({ }); return tagId && ; }, diff --git a/src/plugins/moreUserTags/styles.css b/src/plugins/moreUserTags/styles.css new file mode 100644 index 00000000000..809e78eac32 --- /dev/null +++ b/src/plugins/moreUserTags/styles.css @@ -0,0 +1,4 @@ +.vc-more-user-tags-tag { + position: relative; + bottom: 0.1rem; +} From 4810df4c2c1b94757d574f2372d7ae0eca1befd0 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Tue, 4 Feb 2025 08:49:05 +0100 Subject: [PATCH 14/22] moreUserTags: fix center offset --- src/plugins/moreUserTags/styles.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/plugins/moreUserTags/styles.css b/src/plugins/moreUserTags/styles.css index 809e78eac32..83c678ddde7 100644 --- a/src/plugins/moreUserTags/styles.css +++ b/src/plugins/moreUserTags/styles.css @@ -1,4 +1,3 @@ .vc-more-user-tags-tag { - position: relative; - bottom: 0.1rem; + margin-top: unset !important; } From 8d1cab9c53b44a3e3de9c0c694f5e2774988b966 Mon Sep 17 00:00:00 2001 From: Nuckyz <61953774+Nuckyz@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:04:34 -0300 Subject: [PATCH 15/22] Fix alignment for tags in messages --- src/plugins/moreUserTags/index.tsx | 2 +- src/plugins/moreUserTags/styles.css | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index b8db0af6be1..574facb11da 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -66,7 +66,7 @@ export default definePlugin({ return tagId && ; diff --git a/src/plugins/moreUserTags/styles.css b/src/plugins/moreUserTags/styles.css index 83c678ddde7..1062a94e596 100644 --- a/src/plugins/moreUserTags/styles.css +++ b/src/plugins/moreUserTags/styles.css @@ -1,3 +1,8 @@ -.vc-more-user-tags-tag { +.vc-more-user-tags-message-tag { + /* Remove default margin from tags in messages */ margin-top: unset !important; + + /* Align with Discord default tags in messages */ + position: relative; + bottom: 0.01em; } From a04a97c25671334b742a085f1620368c07393f60 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Tue, 4 Feb 2025 21:37:43 +0100 Subject: [PATCH 16/22] moreUserTags: generate settings if not present --- src/plugins/moreUserTags/index.tsx | 13 +++++++++++++ src/plugins/moreUserTags/settings.tsx | 8 +++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 574facb11da..35986fe1052 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -14,6 +14,7 @@ import { Channel, Message, User } from "discord-types/general"; import { computePermissions, Tag, tags } from "./consts"; import { settings } from "./settings"; +import { TagSettings } from "./types"; const genTagTypes = () => { let i = 100; @@ -52,6 +53,18 @@ export default definePlugin({ } } ], + start() { + const tagSettings = settings.store.tagSettings || {} as TagSettings; + for (const tag of Object.values(tags)) { + tagSettings[tag.name] ??= { + showInChat: true, + showInNotChat: true, + text: tag.displayName + }; + } + + settings.store.tagSettings = tagSettings; + }, localTags: genTagTypes(), getChannelId() { return SelectedChannelStore.getChannelId(); diff --git a/src/plugins/moreUserTags/settings.tsx b/src/plugins/moreUserTags/settings.tsx index e0cff67fc2d..c1775ee8b29 100644 --- a/src/plugins/moreUserTags/settings.tsx +++ b/src/plugins/moreUserTags/settings.tsx @@ -18,7 +18,7 @@ const defaultSettings = Object.fromEntries( ) as TagSettings; function SettingsComponent() { - const tagSettings = settings.store.tagSettings ??= defaultSettings; + const tagSettings = settings.store.tagSettings as TagSettings; return ( @@ -69,11 +69,13 @@ function SettingsComponent() { export const settings = definePluginSettings({ dontShowForBots: { description: "Don't show extra tags for bots (excluding webhooks)", - type: OptionType.BOOLEAN + type: OptionType.BOOLEAN, + default: false }, dontShowBotTag: { description: "Only show extra tags for bots / Hide [BOT] text", - type: OptionType.BOOLEAN + type: OptionType.BOOLEAN, + default: false }, tagSettings: { type: OptionType.COMPONENT, From 06c2ba5f7ae03d2ef430b1b64d5e7db158cb6f8b Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Tue, 4 Feb 2025 21:40:04 +0100 Subject: [PATCH 17/22] moreUserTags: removed unused const --- src/plugins/moreUserTags/settings.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/plugins/moreUserTags/settings.tsx b/src/plugins/moreUserTags/settings.tsx index c1775ee8b29..b8bba764316 100644 --- a/src/plugins/moreUserTags/settings.tsx +++ b/src/plugins/moreUserTags/settings.tsx @@ -12,11 +12,6 @@ import { Card, Flex, Forms, Switch, TextInput, Tooltip } from "@webpack/common"; import { Tag, tags } from "./consts"; import { TagSettings } from "./types"; - -const defaultSettings = Object.fromEntries( - tags.map(({ name, displayName }) => [name, { text: displayName, showInChat: true, showInNotChat: true }]) -) as TagSettings; - function SettingsComponent() { const tagSettings = settings.store.tagSettings as TagSettings; From 90f2e4670f1d00691dbc0c480751b4a9af9af82e Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Wed, 5 Feb 2025 13:30:28 +0100 Subject: [PATCH 18/22] moreUserTags: actually use settings --- src/plugins/moreUserTags/index.tsx | 11 +++++++++-- src/plugins/moreUserTags/settings.tsx | 5 +++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 35986fe1052..74293523cfe 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -37,10 +37,15 @@ export default definePlugin({ // Make discord actually use our tags { find: ".STAFF_ONLY_DM:", - replacement: { + replacement: [{ match: /(?<=type:(\i).{10,1000}.REMIX.{10,100})default:(\i)=/, replace: "default:$2=$self.getTagText($self.localTags[$1]);", + }, { + match: /(?<=type:(\i).{10,1000}.REMIX.{10,100})\.BOT:(?=default:)/, + replace: "$&return null;", + predicate: () => settings.store.dontShowBotTag }, + ], }, // User profile @@ -116,14 +121,16 @@ export default definePlugin({ channelId?: string; isChat?: boolean; }): number | null { + const settings = this.settings.store; + if (!user) return null; if (isChat && user.id === "1") return null; if (user.isClyde()) return null; + if (user.bot && settings.dontShowForBots) return null; channel ??= ChannelStore.getChannel(channelId!) as any; if (!channel) return null; - const settings = this.settings.store; const perms = this.getPermissions(user, channel); for (const tag of tags) { diff --git a/src/plugins/moreUserTags/settings.tsx b/src/plugins/moreUserTags/settings.tsx index b8bba764316..f48634e1a6f 100644 --- a/src/plugins/moreUserTags/settings.tsx +++ b/src/plugins/moreUserTags/settings.tsx @@ -68,9 +68,10 @@ export const settings = definePluginSettings({ default: false }, dontShowBotTag: { - description: "Only show extra tags for bots / Hide [BOT] text", + description: "Only show extra tags for bots / Hide [APP] text", type: OptionType.BOOLEAN, - default: false + default: false, + restartNeeded: true }, tagSettings: { type: OptionType.COMPONENT, From d474337ca1dc06860ba56d465d6b9599872027bc Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Wed, 5 Feb 2025 13:36:51 +0100 Subject: [PATCH 19/22] moreUserTags: oops --- src/plugins/moreUserTags/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 74293523cfe..0ed7d0974df 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -107,8 +107,6 @@ export default definePlugin({ const tag = tags.find(({ name }) => tagName === name); if (!tag) return tagName || getIntlMessage("APP_TAG"); - if (tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return; - return settings.store.tagSettings?.[tag.name]?.text || tag.displayName; }, From 29512a553d56c7569b3ee6830e4c1df14591c76c Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Wed, 5 Feb 2025 16:54:59 +0100 Subject: [PATCH 20/22] moreUserTags: use proper height --- src/plugins/moreUserTags/index.tsx | 2 +- src/plugins/moreUserTags/styles.css | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 0ed7d0974df..1b87a3e74f5 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -84,7 +84,7 @@ export default definePlugin({ return tagId && ; diff --git a/src/plugins/moreUserTags/styles.css b/src/plugins/moreUserTags/styles.css index 1062a94e596..37a8b011417 100644 --- a/src/plugins/moreUserTags/styles.css +++ b/src/plugins/moreUserTags/styles.css @@ -1,4 +1,4 @@ -.vc-more-user-tags-message-tag { +.vc-mut-message-tag { /* Remove default margin from tags in messages */ margin-top: unset !important; @@ -6,3 +6,7 @@ position: relative; bottom: 0.01em; } + +.vc-mut-message-verified { + height: 1rem !important; +} From 97676c67e3857b4fa07668f9c127cef1611ac83d Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Wed, 5 Feb 2025 18:58:40 +0100 Subject: [PATCH 21/22] balls From ddd66687c0890bbebb61b0d2782cabb22cbed720 Mon Sep 17 00:00:00 2001 From: simidzu2ay Date: Wed, 5 Feb 2025 19:09:12 +0100 Subject: [PATCH 22/22] moreUserTags: use classFactory --- src/plugins/moreUserTags/index.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/moreUserTags/index.tsx b/src/plugins/moreUserTags/index.tsx index 1b87a3e74f5..0e4247a32d4 100644 --- a/src/plugins/moreUserTags/index.tsx +++ b/src/plugins/moreUserTags/index.tsx @@ -6,6 +6,7 @@ import "./styles.css"; +import { classNameFactory } from "@api/Styles"; import { Devs } from "@utils/constants"; import { getIntlMessage } from "@utils/discord"; import definePlugin from "@utils/types"; @@ -16,6 +17,8 @@ import { computePermissions, Tag, tags } from "./consts"; import { settings } from "./settings"; import { TagSettings } from "./types"; +const cl = classNameFactory("vc-mut-"); + const genTagTypes = () => { let i = 100; const obj = {}; @@ -84,7 +87,7 @@ export default definePlugin({ return tagId && ;