aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuna <luni.siaa@gmail.com>2022-11-23 19:56:20 +0100
committerGitHub <noreply@github.com>2022-11-23 19:56:20 +0100
commit63ffb5bebc3adf8888dd10e4fe05d54e2cf03d86 (patch)
tree53743ddda18c6ae5a8fa0e3d173f9eadb9ddc9af
parent2788d264d4ef65b2725d6bd3ce9202285498519b (diff)
downloadVencord-63ffb5bebc3adf8888dd10e4fe05d54e2cf03d86.tar.gz
Vencord-63ffb5bebc3adf8888dd10e4fe05d54e2cf03d86.tar.bz2
Vencord-63ffb5bebc3adf8888dd10e4fe05d54e2cf03d86.zip
feat(messageTags): Add message quick reply plugin (#241)
-rw-r--r--src/plugins/messageTags.ts247
-rw-r--r--src/utils/constants.ts4
2 files changed, 251 insertions, 0 deletions
diff --git a/src/plugins/messageTags.ts b/src/plugins/messageTags.ts
new file mode 100644
index 0000000..c5de93a
--- /dev/null
+++ b/src/plugins/messageTags.ts
@@ -0,0 +1,247 @@
+/*
+ * 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 <https://www.gnu.org/licenses/>.
+*/
+
+import { DataStore } from "../api";
+import { ApplicationCommandInputType, ApplicationCommandOptionType, findOption, registerCommand, sendBotMessage, unregisterCommand } from "../api/Commands";
+import { Settings } from "../api/settings";
+import { Devs } from "../utils/constants";
+import definePlugin, { OptionType } from "../utils/types";
+
+const settings = Settings.plugins.MessageTags;
+const EMOTE = "<:luna:1035316192220553236>";
+const DATA_KEY = "MessageTags_TAGS";
+const MessageTagsMarker = Symbol("MessageTags");
+const author = {
+ id: "821472922140803112",
+ bot: false
+};
+
+interface Tag {
+ name: string;
+ message: string;
+ enabled: boolean;
+}
+
+const getTags = () => DataStore.get(DATA_KEY).then<Tag[]>(t => t ?? []);
+const getTag = (name: string) => DataStore.get(DATA_KEY).then<Tag | null>((t: Tag[]) => (t ?? []).find((tt: Tag) => tt.name === name) ?? null);
+const addTag = async (tag: Tag) => {
+ const tags = await getTags();
+ tags.push(tag);
+ DataStore.set(DATA_KEY, tags);
+ return tags;
+};
+const removeTag = async (name: string) => {
+ let tags = await getTags();
+ tags = await tags.filter((t: Tag) => t.name !== name);
+ DataStore.set(DATA_KEY, tags);
+ return tags;
+};
+
+function createTagCommand(tag: Tag) {
+ registerCommand({
+ name: tag.name,
+ description: tag.name,
+ inputType: ApplicationCommandInputType.BUILT_IN_TEXT,
+ execute: async (_, ctx) => {
+ if (!await getTag(tag.name)) {
+ sendBotMessage(ctx.channel.id, {
+ author,
+ content: `${EMOTE} The tag **${tag.name}** does not exist anymore! Please reload ur Discord to fix :)`
+ });
+ return { content: `/${tag.name}` };
+ }
+
+ if (settings.clyde) sendBotMessage(ctx.channel.id, {
+ author,
+ content: `${EMOTE} The tag **${tag.name}** has been sent!`
+ });
+ return { content: tag.message.replaceAll("\\n", "\n") };
+ },
+ [MessageTagsMarker]: true,
+ }, "CustomTags");
+}
+
+
+export default definePlugin({
+ name: "MessageTags",
+ description: "Allows you to save messages and to use them with a simple command.",
+ authors: [Devs.Luna],
+ options: {
+ clyde: {
+ name: "Clyde message on send",
+ description: "If enabled, clyde will send you an ephemeral message when a tag was used.",
+ type: OptionType.BOOLEAN,
+ default: true
+ }
+ },
+ dependencies: ["CommandsAPI"],
+
+ async start() {
+ for (const tag of await getTags()) createTagCommand(tag);
+ },
+
+ commands: [
+ {
+ name: "tags",
+ description: "Manage all the tags for yourself",
+ inputType: ApplicationCommandInputType.BUILT_IN,
+ options: [
+ {
+ name: "create",
+ description: "Create a new tag",
+ type: ApplicationCommandOptionType.SUB_COMMAND,
+ options: [
+ {
+ name: "tag-name",
+ description: "The name of the tag to trigger the response",
+ type: ApplicationCommandOptionType.STRING,
+ required: true
+ },
+ {
+ name: "message",
+ description: "The message that you will send when using this tag",
+ type: ApplicationCommandOptionType.STRING,
+ required: true
+ }
+ ]
+ },
+ {
+ name: "list",
+ description: "List all tags from yourself",
+ type: ApplicationCommandOptionType.SUB_COMMAND,
+ options: []
+ },
+ {
+ name: "delete",
+ description: "Remove a tag from your yourself",
+ type: ApplicationCommandOptionType.SUB_COMMAND,
+ options: [
+ {
+ name: "tag-name",
+ description: "The name of the tag to trigger the response",
+ type: ApplicationCommandOptionType.STRING,
+ required: true
+ }
+ ]
+ },
+ {
+ name: "preview",
+ description: "Preview a tag without sending it publicly",
+ type: ApplicationCommandOptionType.SUB_COMMAND,
+ options: [
+ {
+ name: "tag-name",
+ description: "The name of the tag to trigger the response",
+ type: ApplicationCommandOptionType.STRING,
+ required: true
+ }
+ ]
+ }
+ ],
+
+ async execute(args, ctx) {
+
+ switch (args[0].name) {
+ case "create": {
+ const name: string = findOption(args[0].options, "tag-name", "");
+ const message: string = findOption(args[0].options, "message", "");
+
+ if (await getTag(name))
+ return sendBotMessage(ctx.channel.id, {
+ author,
+ content: `${EMOTE} A Tag with the name **${name}** already exists!`
+ });
+
+ const tag = {
+ name: name,
+ enabled: true,
+ message: message
+ };
+
+ createTagCommand(tag);
+ await addTag(tag);
+
+ sendBotMessage(ctx.channel.id, {
+ author,
+ content: `${EMOTE} Successfully created the tag **${name}**!`
+ });
+ break; // end 'create'
+ }
+ case "delete": {
+ const name: string = findOption(args[0].options, "tag-name", "");
+
+ if (!await getTag(name))
+ return sendBotMessage(ctx.channel.id, {
+ author,
+ content: `${EMOTE} A Tag with the name **${name}** does not exist!`
+ });
+
+ unregisterCommand(name);
+ await removeTag(name);
+
+ sendBotMessage(ctx.channel.id, {
+ author,
+ content: `${EMOTE} Successfully deleted the tag **${name}**!`
+ });
+ break; // end 'delete'
+ }
+ case "list": {
+ sendBotMessage(ctx.channel.id, {
+ author,
+ embeds: [
+ {
+ // @ts-ignore
+ title: "All Tags:",
+ // @ts-ignore
+ description: (await getTags())
+ .map(tag => `\`${tag.name}\`: ${tag.message.slice(0, 72).replaceAll("\\n", " ")}${tag.message.length > 72 ? "..." : ""}`)
+ .join("\n") || `${EMOTE} Woops! There are no tags yet, use \`/tags create\` to create one!`,
+ // @ts-ignore
+ color: 0xd77f7f,
+ type: "rich",
+ }
+ ]
+ });
+ break; // end 'list'
+ }
+ case "preview": {
+ const name: string = findOption(args[0].options, "tag-name", "");
+ const tag = await getTag(name);
+
+ if (!tag)
+ return sendBotMessage(ctx.channel.id, {
+ author,
+ content: `${EMOTE} A Tag with the name **${name}** does not exist!`
+ });
+
+ sendBotMessage(ctx.channel.id, {
+ author,
+ content: tag.message.replaceAll("\\n", "\n")
+ });
+ break; // end 'preview'
+ }
+ }
+
+ return sendBotMessage(ctx.channel.id, {
+ author,
+ content: "Invalid sub-command"
+ });
+ }
+ }
+ ]
+});
diff --git a/src/utils/constants.ts b/src/utils/constants.ts
index dc0a80d..3766c74 100644
--- a/src/utils/constants.ts
+++ b/src/utils/constants.ts
@@ -152,5 +152,9 @@ export const Devs = Object.freeze({
jewdev: {
name: "jewdev",
id: 222369866529636353n
+ },
+ Luna: {
+ name: "Luny",
+ id: 821472922140803112n
}
});