aboutsummaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/moreUserTags.tsx (renamed from src/plugins/moreUserTags.ts)227
1 files changed, 163 insertions, 64 deletions
diff --git a/src/plugins/moreUserTags.ts b/src/plugins/moreUserTags.tsx
index 90662b0..dbe8cc2 100644
--- a/src/plugins/moreUserTags.ts
+++ b/src/plugins/moreUserTags.tsx
@@ -17,11 +17,13 @@
*/
import { definePluginSettings } from "@api/Settings";
+import { Flex } from "@components/Flex";
import { Devs } from "@utils/constants";
-import { proxyLazy } from "@utils/lazy.js";
+import { Margins } from "@utils/margins";
import definePlugin, { OptionType } from "@utils/types";
-import { find, findByPropsLazy } from "@webpack";
-import { ChannelStore, GuildStore } from "@webpack/common";
+import { findByPropsLazy, findLazy } from "@webpack";
+import { Card, ChannelStore, Forms, GuildStore, Switch, TextInput, Tooltip, useState } from "@webpack/common";
+import { RC } from "@webpack/types";
import { Channel, Message, User } from "discord-types/general";
type PermissionName = "CREATE_INSTANT_INVITE" | "KICK_MEMBERS" | "BAN_MEMBERS" | "ADMINISTRATOR" | "MANAGE_CHANNELS" | "MANAGE_GUILD" | "CHANGE_NICKNAME" | "MANAGE_NICKNAMES" | "MANAGE_ROLES" | "MANAGE_WEBHOOKS" | "MANAGE_GUILD_EXPRESSIONS" | "CREATE_GUILD_EXPRESSIONS" | "VIEW_AUDIT_LOG" | "VIEW_CHANNEL" | "VIEW_GUILD_ANALYTICS" | "VIEW_CREATOR_MONETIZATION_ANALYTICS" | "MODERATE_MEMBERS" | "SEND_MESSAGES" | "SEND_TTS_MESSAGES" | "MANAGE_MESSAGES" | "EMBED_LINKS" | "ATTACH_FILES" | "READ_MESSAGE_HISTORY" | "MENTION_EVERYONE" | "USE_EXTERNAL_EMOJIS" | "ADD_REACTIONS" | "USE_APPLICATION_COMMANDS" | "MANAGE_THREADS" | "CREATE_PUBLIC_THREADS" | "CREATE_PRIVATE_THREADS" | "USE_EXTERNAL_STICKERS" | "SEND_MESSAGES_IN_THREADS" | "CONNECT" | "SPEAK" | "MUTE_MEMBERS" | "DEAFEN_MEMBERS" | "MOVE_MEMBERS" | "USE_VAD" | "PRIORITY_SPEAKER" | "STREAM" | "USE_EMBEDDED_ACTIVITIES" | "USE_SOUNDBOARD" | "USE_EXTERNAL_SOUNDS" | "REQUEST_TO_SPEAK" | "MANAGE_EVENTS" | "CREATE_EVENTS";
@@ -36,6 +38,21 @@ interface Tag {
condition?(message: Message | null, user: User, channel: Channel): boolean;
}
+interface TagSetting {
+ text: string;
+ showInChat: boolean;
+ showInNotChat: boolean;
+}
+interface TagSettings {
+ WEBHOOK: TagSetting,
+ OWNER: TagSetting,
+ ADMINISTRATOR: TagSetting,
+ MODERATOR_STAFF: TagSetting,
+ MODERATOR: TagSetting,
+ VOICE_MODERATOR: TagSetting,
+ [k: string]: TagSetting;
+}
+
const CLYDE_ID = "1081004946872352958";
// PermissionStore.computePermissions is not the same function and doesn't work here
@@ -44,7 +61,7 @@ const PermissionUtil = findByPropsLazy("computePermissions", "canEveryoneRole")
};
const Permissions = findByPropsLazy("SEND_MESSAGES", "VIEW_CREATOR_MONETIZATION_ANALYTICS") as Record<PermissionName, bigint>;
-const Tags = proxyLazy(() => find(m => m.Types?.[0] === "BOT").Types) as Record<string, number>;
+const Tag = findLazy(m => m.Types?.[0] === "BOT") as RC<{ type?: number, className?: string, useRemSizes?: boolean; }> & { Types: Record<string, number>; };
const isWebhook = (message: Message, user: User) => !!message?.webhookId && user.isNonUserBot();
@@ -81,64 +98,119 @@ const tags: Tag[] = [
permissions: ["MOVE_MEMBERS", "MUTE_MEMBERS", "DEAFEN_MEMBERS"]
}
];
+const defaultSettings = Object.fromEntries(
+ tags.map(({ name, displayName }) => [name, { text: displayName, showInChat: true, showInNotChat: true }])
+) as TagSettings;
+
+function SettingsComponent(props: { setValue(v: any): void; }) {
+ settings.store.tagSettings ??= defaultSettings;
+
+ const [tagSettings, setTagSettings] = useState(settings.store.tagSettings as TagSettings);
+ const setValue = (v: TagSettings) => {
+ setTagSettings(v);
+ props.setValue(v);
+ };
+
+ return (
+ <Flex flexDirection="column">
+ {tags.map(t => (
+ <Card style={{ padding: "1em 1em 0" }}>
+ <Forms.FormTitle style={{ width: "fit-content" }}>
+ <Tooltip text={t.description}>
+ {({ onMouseEnter, onMouseLeave }) => (
+ <div
+ onMouseEnter={onMouseEnter}
+ onMouseLeave={onMouseLeave}
+ >
+ {t.displayName} Tag <Tag type={Tag.Types[t.name]} />
+ </div>
+ )}
+ </Tooltip>
+ </Forms.FormTitle>
+
+ <TextInput
+ type="text"
+ value={tagSettings[t.name]?.text ?? t.displayName}
+ placeholder={`Text on tag (default: ${t.displayName})`}
+ onChange={v => {
+ tagSettings[t.name].text = v;
+ setValue(tagSettings);
+ }}
+ className={Margins.bottom16}
+ />
+
+ <Switch
+ value={tagSettings[t.name]?.showInChat ?? true}
+ onChange={v => {
+ tagSettings[t.name].showInChat = v;
+ setValue(tagSettings);
+ }}
+ hideBorder
+ >
+ Show in messages
+ </Switch>
+
+ <Switch
+ value={tagSettings[t.name]?.showInNotChat ?? true}
+ onChange={v => {
+ tagSettings[t.name].showInNotChat = v;
+ setValue(tagSettings);
+ }}
+ hideBorder
+ >
+ Show in member list and profiles
+ </Switch>
+ </Card>
+ ))}
+ </Flex>
+ );
+}
const settings = definePluginSettings({
dontShowForBots: {
- description: "Don't show tags (not including the webhook tag) for bots",
+ description: "Don't show extra tags for bots (excluding webhooks)",
type: OptionType.BOOLEAN
},
dontShowBotTag: {
- description: "Don't show [BOT] text for bots with other tags (verified bots will still have checkmark)",
+ description: "Only show extra tags for bots / Hide [BOT] text",
type: OptionType.BOOLEAN
},
- ...Object.fromEntries(tags.map(({ name, displayName, description }) => [
- `visibility_${name}`, {
- description: `Show ${displayName} tags (${description})`,
- type: OptionType.SELECT,
- options: [
- {
- label: "Always",
- value: "always",
- default: true
- }, {
- label: "Only in chat",
- value: "chat"
- }, {
- label: "Only in member list and profiles",
- value: "not-chat"
- }, {
- label: "Never",
- value: "never"
- }
- ]
- }
- ]))
+ tagSettings: {
+ type: OptionType.COMPONENT,
+ component: SettingsComponent,
+ description: "fill me",
+ }
});
export default definePlugin({
name: "MoreUserTags",
description: "Adds tags for webhooks and moderative roles (owner, admin, etc.)",
- authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev],
+ authors: [Devs.Cyn, Devs.TheSun, Devs.RyanCaoDev, Devs.LordElias],
settings,
patches: [
// add tags to the tag list
{
find: '.BOT=0]="BOT"',
replacement: [
- // add tags to the exported tags list (the Tags variable here)
+ // add tags to the exported tags list (Tag.Types)
{
match: /(\i)\[.\.BOT=0\]="BOT";/,
replace: "$&$1=$self.addTagVariants($1);"
- },
+ }
+ ]
+ },
+ {
+ find: ".DISCORD_SYSTEM_MESSAGE_BOT_TAG_TOOLTIP;",
+ replacement: [
// make the tag show the right text
{
- match: /(switch\((\i)\){.+?)case (\i)\.BOT:default:(\i)=(\i\.\i\.Messages)\.BOT_TAG_BOT/,
+ match: /(switch\((\i)\){.+?)case (\i(?:\.\i)?)\.BOT:default:(\i)=(\i\.\i\.Messages)\.BOT_TAG_BOT/,
replace: (_, origSwitch, variant, tags, displayedText, strings) =>
`${origSwitch}default:{${displayedText} = $self.getTagText(${tags}[${variant}], ${strings})}`
},
// show OP tags correctly
{
- match: /(\i)=(\i)===\i\.ORIGINAL_POSTER/,
+ match: /(\i)=(\i)===\i(?:\.\i)?\.ORIGINAL_POSTER/,
replace: "$1=$self.isOPTag($2)"
},
// add HTML data attributes (for easier theming)
@@ -169,15 +241,15 @@ return type!==null?$2.botTag,type"
{
find: ".hasAvatarForGuild(null==",
replacement: {
- match: /\.usernameSection,user/,
- replace: ".usernameSection,moreTags_channelId:arguments[0].channelId,user"
+ match: /(?=usernameIcon:)/,
+ replace: "moreTags_channelId:arguments[0].channelId,"
}
},
{
find: 'copyMetaData:"User Tag"',
replacement: {
- match: /discriminatorClass:(.{1,100}),botClass:/,
- replace: "discriminatorClass:$1,moreTags_channelId:arguments[0].moreTags_channelId,botClass:"
+ match: /(?=,botClass:)/,
+ replace: ",moreTags_channelId:arguments[0].moreTags_channelId"
}
},
// in profiles
@@ -190,6 +262,37 @@ return type!==null?$2.botTag,type"
},
],
+ start() {
+ if (settings.store.tagSettings) return;
+ // @ts-ignore
+ if (!settings.store.visibility_WEBHOOK) settings.store.tagSettings = defaultSettings;
+ else {
+ const newSettings = { ...defaultSettings };
+ Object.entries(Vencord.PlainSettings.plugins.MoreUserTags).forEach(([name, value]) => {
+ const [setting, tag] = name.split("_");
+ if (setting === "visibility") {
+ switch (value) {
+ case "always":
+ // its the default
+ break;
+ case "chat":
+ newSettings[tag].showInNotChat = false;
+ break;
+ case "not-chat":
+ newSettings[tag].showInChat = false;
+ break;
+ case "never":
+ newSettings[tag].showInChat = false;
+ newSettings[tag].showInNotChat = false;
+ break;
+ }
+ }
+ settings.store.tagSettings = newSettings;
+ delete Vencord.Settings.plugins.MoreUserTags[name];
+ });
+ }
+ },
+
getPermissions(user: User, channel: Channel): string[] {
const guild = GuildStore.getGuild(channel?.guild_id);
if (!guild) return [];
@@ -202,35 +305,36 @@ return type!==null?$2.botTag,type"
.filter(Boolean);
},
- addTagVariants(val: any /* i cant think of a good name */) {
+ addTagVariants(tagConstant) {
let i = 100;
tags.forEach(({ name }) => {
- val[name] = ++i;
- val[i] = name;
- val[`${name}-BOT`] = ++i;
- val[i] = `${name}-BOT`;
- val[`${name}-OP`] = ++i;
- val[i] = `${name}-OP`;
+ tagConstant[name] = ++i;
+ tagConstant[i] = name;
+ tagConstant[`${name}-BOT`] = ++i;
+ tagConstant[i] = `${name}-BOT`;
+ tagConstant[`${name}-OP`] = ++i;
+ tagConstant[i] = `${name}-OP`;
});
- return val;
+ return tagConstant;
},
- isOPTag: (tag: number) => tag === Tags.ORIGINAL_POSTER || tags.some(t => tag === Tags[`${t.name}-OP`]),
+ isOPTag: (tag: number) => tag === Tag.Types.ORIGINAL_POSTER || tags.some(t => tag === Tag.Types[`${t.name}-OP`]),
getTagText(passedTagName: string, strings: Record<string, string>) {
- if (!passedTagName) return "BOT";
+ if (!passedTagName) return strings.BOT_TAG_BOT;
const [tagName, variant] = passedTagName.split("-");
const tag = tags.find(({ name }) => tagName === name);
- if (!tag) return "BOT";
+ if (!tag) return strings.BOT_TAG_BOT;
if (variant === "BOT" && tagName !== "WEBHOOK" && this.settings.store.dontShowForBots) return strings.BOT_TAG_BOT;
+ const tagText = settings.store.tagSettings?.[tag.name]?.text || tag.displayName;
switch (variant) {
case "OP":
- return `${strings.BOT_TAG_FORUM_ORIGINAL_POSTER} • ${tag.displayName}`;
+ return `${strings.BOT_TAG_FORUM_ORIGINAL_POSTER} • ${tagText}`;
case "BOT":
- return `${strings.BOT_TAG_BOT} • ${tag.displayName}`;
+ return `${strings.BOT_TAG_BOT} • ${tagText}`;
default:
- return tag.displayName;
+ return tagText;
}
},
@@ -242,12 +346,12 @@ return type!==null?$2.botTag,type"
channel?: Channel & { isForumPost(): boolean; },
channelId?: string;
origType?: number;
- location: string;
+ location: "chat" | "not-chat";
}): number | null {
if (location === "chat" && user.id === "1")
- return Tags.OFFICIAL;
+ return Tag.Types.OFFICIAL;
if (user.id === CLYDE_ID)
- return Tags.AI;
+ return Tag.Types.AI;
let type = typeof origType === "number" ? origType : null;
@@ -258,24 +362,19 @@ return type!==null?$2.botTag,type"
const perms = this.getPermissions(user, channel);
for (const tag of tags) {
- switch (settings[`visibility_${tag.name}`]) {
- case "always":
- case location:
- break;
- default:
- continue;
- }
+ if (location === "chat" && !settings.tagSettings[tag.name].showInChat) continue;
+ if (location === "not-chat" && !settings.tagSettings[tag.name].showInNotChat) continue;
if (
tag.permissions?.some(perm => perms.includes(perm)) ||
(tag.condition?.(message!, user, channel))
) {
if (channel.isForumPost() && channel.ownerId === user.id)
- type = Tags[`${tag.name}-OP`];
+ type = Tag.Types[`${tag.name}-OP`];
else if (user.bot && !isWebhook(message!, user) && !settings.dontShowBotTag)
- type = Tags[`${tag.name}-BOT`];
+ type = Tag.Types[`${tag.name}-BOT`];
else
- type = Tags[tag.name];
+ type = Tag.Types[tag.name];
break;
}
}