userflags/index.tsx

170 lines
5.2 KiB
TypeScript
Raw Permalink Normal View History

2024-10-12 12:39:41 -04:00
/*
* Vencord, a Discord client mod
* Copyright (c) 2024 Vendicated and contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import { ApplicationCommandInputType, ApplicationCommandOptionType, Argument, CommandContext, findOption, sendBotMessage } from "@api/Commands";
2024-10-12 13:19:48 -04:00
import { DataStore } from "@api/index";
2024-10-12 12:39:41 -04:00
import { addAccessory } from "@api/MessageAccessories";
2024-10-06 15:01:19 -04:00
import { Devs } from "@utils/constants";
import definePlugin from "@utils/types";
import { Parser, React, Text } from "@webpack/common";
2024-10-12 12:39:41 -04:00
let userFlags = new Map<string, Flag>();
2024-10-16 23:38:57 -04:00
enum FlagType {
DANGER = "danger",
WARNING = "warning",
INFO = "info",
POSITIVE = "positive"
}
type FlagRegistryEntry = {
label: string;
color: string;
emoji: string;
};
const flagRegistry: Record<FlagType, FlagRegistryEntry> = {
2024-10-16 23:38:57 -04:00
[FlagType.DANGER]: {
label: "Danger",
color: "#ff7473",
emoji: "🛑"
2024-10-16 23:57:15 -04:00
},
2024-10-16 23:38:57 -04:00
[FlagType.WARNING]: {
label: "Warning",
color: "#ffb02e",
emoji: "⚠️"
2024-10-16 23:57:15 -04:00
},
2024-10-16 23:38:57 -04:00
[FlagType.INFO]: {
label: "Info",
color: "#62a8ff",
2024-10-17 00:58:11 -04:00
emoji: ""
2024-10-16 23:57:15 -04:00
},
2024-10-16 23:38:57 -04:00
[FlagType.POSITIVE]: {
label: "Positive",
color: "#62ff74",
emoji: "✅"
2024-10-16 23:38:57 -04:00
}
};
2024-10-12 12:39:41 -04:00
type Flag = {
2024-10-16 23:38:57 -04:00
type: FlagType;
2024-10-12 12:39:41 -04:00
text: string;
};
const subscribers = new Set<() => void>();
function subscribe(callback: () => void) {
subscribers.add(callback);
return () => subscribers.delete(callback);
};
2024-10-12 12:57:36 -04:00
function Flag({ id }: { id: string; }) {
const flag = React.useSyncExternalStore(subscribe, () => userFlags.get(id));
if (!flag) return null;
2024-10-12 12:57:36 -04:00
return (
2024-10-12 12:39:41 -04:00
<div>
2024-10-12 12:57:36 -04:00
<Text
2024-10-12 13:23:10 -04:00
variant="text-md/bold"
style={{ color: flagRegistry[flag.type].color }}
2024-10-12 12:57:36 -04:00
>
{Parser.parse(flagRegistry[flag.type].emoji)} {flag.text}
2024-10-12 12:39:41 -04:00
</Text>
2024-10-17 00:51:55 -04:00
</div>
2024-10-12 12:39:41 -04:00
);
}
2024-10-06 15:01:19 -04:00
export default definePlugin({
name: "UserFlags",
2024-10-12 12:39:41 -04:00
description: `Add "flags" to users that will always show under their messages`,
2024-10-06 15:01:19 -04:00
authors: [Devs.nin0dev],
2024-10-12 12:39:41 -04:00
dependencies: ["MessageAccessoriesAPI"],
2024-10-12 13:19:48 -04:00
async start() {
const savedFlags = await DataStore.get("USERFLAGS");
if (savedFlags) {
if (typeof savedFlags === "string") {
userFlags = new Map<string, Flag>(JSON.parse(savedFlags));
} else {
2024-10-17 00:42:42 -04:00
userFlags = new Map<string, Flag>(savedFlags);
}
2024-10-12 13:19:48 -04:00
}
addAccessory("flag", (props: Record<string, any>) => (
<Flag id={props.message.author.id} />
), 4);
2024-10-12 12:39:41 -04:00
},
commands: [
{
name: "flag set",
description: "Set a flag on a user",
inputType: ApplicationCommandInputType.BOT,
options: [
{
name: "user",
type: ApplicationCommandOptionType.USER,
description: "The user to set a flag to",
required: true
},
{
2024-10-17 00:42:42 -04:00
name: "type",
type: ApplicationCommandOptionType.STRING,
description: "The type of flag to add",
choices: Object.entries(flagRegistry).map(([key, flag]) => ({
name: key,
label: flag.label,
displayName: flag.label,
value: key,
})),
2024-10-12 12:39:41 -04:00
required: true
},
{
name: "message",
type: ApplicationCommandOptionType.STRING,
description: "The flag content",
required: true
},
],
2024-10-12 13:19:48 -04:00
execute: async (args: Argument[], ctx: CommandContext) => {
const user = findOption(args, "user", "");
2024-10-16 23:38:57 -04:00
const type = findOption<FlagType>(args, "type", FlagType.INFO);
const text = findOption(args, "message", "");
userFlags.set(user, {
type,
text
2024-10-12 12:39:41 -04:00
});
subscribers.forEach(cb => cb());
2024-10-12 12:39:41 -04:00
sendBotMessage(ctx.channel.id, {
content: `Flag set on <@${user}> with content \`${text}\`!`
2024-10-12 12:39:41 -04:00
});
await DataStore.set("USERFLAGS", userFlags);
2024-10-12 12:39:41 -04:00
return;
}
},
{
name: "flag delete",
description: "Delete the flag from a user",
inputType: ApplicationCommandInputType.BOT,
options: [
{
name: "user",
type: ApplicationCommandOptionType.USER,
description: "The user to delete the flag from",
required: true
}
],
2024-10-12 13:19:48 -04:00
execute: async (args: Argument[], ctx: CommandContext) => {
const user = findOption(args, "user", "");
userFlags.delete(user);
subscribers.forEach(cb => cb());
2024-10-12 12:39:41 -04:00
sendBotMessage(ctx.channel.id, {
content: `Flag removed from <@${user}>`
2024-10-12 12:39:41 -04:00
});
await DataStore.set("USERFLAGS", userFlags);
2024-10-12 12:39:41 -04:00
return;
}
}
]
2024-10-06 15:01:19 -04:00
});