This commit is contained in:
cirroskais 2024-04-18 14:56:15 -04:00
parent 29a80dcedc
commit b940741c2f
No known key found for this signature in database
GPG key ID: 5FC73EBF2678E33D
10 changed files with 192 additions and 40 deletions

19
bin/delete.js Normal file
View file

@ -0,0 +1,19 @@
import { logger } from "@discordeno/utils";
import REST from "../src/lib/handlers/RESTHandler";
import * as InteractionHandler from "../src/lib/handlers/InteractionHandler";
import * as CommandHandler from "../src/lib/handlers/CommandHandler";
await InteractionHandler.load();
const registered = await REST.getGlobalApplicationCommands();
for (let { id, name, type } of registered) {
const cmd = CommandHandler.commands.get(name);
if (cmd && cmd.type == type) continue;
await REST.deleteGlobalApplicationCommand(id);
logger.info(`Deleted ${name}(${id})`);
}
process.exit();

20
bin/list.js Normal file
View file

@ -0,0 +1,20 @@
import { logger } from "@discordeno/utils";
import REST from "../src/lib/handlers/RESTHandler";
const registered = await REST.getGlobalApplicationCommands();
const TYPES = ["CHAT_INPUT", "USER", "MESSAGE"];
logger.info("┌" + "-".repeat(58) + "┐");
logger.info("| " + "ID".padEnd(24, " ") + " | " + "NAME".padEnd(16, " ") + " | " + "TYPE".padEnd(10, " ") + " |");
logger.info("├" + "-".repeat(58) + "┤");
for (let { id, name, type } of registered) {
logger.info(
"| " + id.padEnd(24, " ") + " | " + name.padEnd(16, " ") + " | " + TYPES[type - 1].padEnd(10, " ") + " |",
);
}
logger.info("└" + "-".repeat(58) + "┘");
process.exit();

28
bin/update.js Normal file
View file

@ -0,0 +1,28 @@
import { logger } from "@discordeno/utils";
import REST from "../src/lib/handlers/RESTHandler";
import * as InteractionHandler from "../src/lib/handlers/InteractionHandler";
import * as CommandHandler from "../src/lib/handlers/CommandHandler";
await InteractionHandler.load();
for (let [key, value] of CommandHandler.commands.entries()) {
const response = await fetch(`https://discord.com/api/v10/applications/${REST.applicationId}/commands`, {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: "Bot " + process.env.DISCORD_TOKEN },
body: JSON.stringify({
name: value.name,
type: value.type,
description: value?.description || "",
options: value?.options,
nsfw: value?.nsfw,
integration_types: [0, 1],
contexts: [0, 1, 2],
}),
});
const command = await response.json();
logger.info(`Registered ${command.name}(${command.id})`);
}
process.exit();

View file

@ -1,16 +1,22 @@
{ {
"name": "bot-template", "name": "bot-template",
"module": "src/index.ts", "module": "src/index.ts",
"devDependencies": { "devDependencies": {
"@discordeno/types": "^19.0.0-next.d81b28a", "@discordeno/types": "^19.0.0-next.d81b28a",
"@types/bun": "latest" "@types/bun": "latest"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "^5.0.0" "typescript": "^5.0.0"
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@discordeno/bot": "^19.0.0-next.d81b28a", "@discordeno/bot": "^19.0.0-next.d81b28a",
"@discordeno/rest": "^19.0.0-next.d81b28a" "@discordeno/rest": "^19.0.0-next.d81b28a"
} },
"scripts": {
"dev": "bun run --watch src/index.ts",
"bot:list": "bun run bin/list.js",
"bot:delete": "bun run bin/delete.js",
"bot:update": "bun run bin/update.js"
}
} }

View file

@ -1,4 +1,4 @@
import { createBot, Intents } from "@discordeno/bot"; import { createBot, Intents, logger } from "@discordeno/bot";
import * as interactionHandler from "./lib/handlers/InteractionHandler"; import * as interactionHandler from "./lib/handlers/InteractionHandler";
const client = createBot({ const client = createBot({
@ -6,7 +6,7 @@ const client = createBot({
intents: Intents.Guilds, intents: Intents.Guilds,
events: { events: {
ready(payload, rawPayload) { ready(payload, rawPayload) {
console.log("Logged in"); logger.info(`Logged into ${payload.user.username}`);
}, },
interactionCreate: interactionHandler.handle, interactionCreate: interactionHandler.handle,
}, },

View file

@ -1,13 +1,13 @@
import type { Command } from "../lib/types/command"; import type { Command } from "../lib/types/command";
import { MessageComponentTypes, TextStyles, type Interaction } from "@discordeno/bot"; import { MessageComponentTypes, TextStyles } from "@discordeno/bot";
import SlashCommand from "../lib/classes/SlashCommand"; import SlashCommand from "../lib/classes/SlashCommand";
import Modal from "../lib/classes/Modal"; import Modal from "../lib/classes/Modal";
import { collectModal } from "../lib/handlers/ModalHandler"; import { collectModal } from "../lib/handlers/ModalHandler";
export default class extends SlashCommand implements Command { export default class extends SlashCommand implements Command {
static name = "ping"; name = "default";
static description = "Show a test modal"; description = "Show a test modal";
static options = []; options = [];
constructor() { constructor() {
super(); super();
@ -20,9 +20,9 @@ export default class extends SlashCommand implements Command {
components: [ components: [
{ {
type: MessageComponentTypes.InputText, type: MessageComponentTypes.InputText,
customId: "dope", customId: "default",
style: TextStyles.Short, style: TextStyles.Short,
label: "dope", label: "default",
}, },
], ],
}, },
@ -31,11 +31,9 @@ export default class extends SlashCommand implements Command {
collectModal(modal) collectModal(modal)
.then(({ interaction, values }) => { .then(({ interaction, values }) => {
if (!interaction.data?.components) return; if (!interaction.data?.components) return;
interaction.respond("dope: " + values.get("dope")); interaction.respond("default: " + values.get("default"));
}) })
.catch((_) => { .catch((_) => {});
// whatever bro dont respond to my modal 🙄
});
return modal; return modal;
} }

72
src/interactions/send.ts Normal file
View file

@ -0,0 +1,72 @@
import type { Command } from "../lib/types/command";
import { MessageComponentTypes, TextStyles } from "@discordeno/bot";
import SlashCommand from "../lib/classes/SlashCommand";
import Modal from "../lib/classes/Modal";
import { collectModal } from "../lib/handlers/ModalHandler";
interface SendMailResponse {
success: boolean;
message: string;
}
export default class extends SlashCommand implements Command {
name = "send";
description = "Send mail to a user in the Enigmatica 9 server!";
options = [];
constructor() {
super();
}
async run() {
const modal = new Modal().setTitle("Send Mail").setComponents([
{
type: MessageComponentTypes.ActionRow,
components: [
{
type: MessageComponentTypes.InputText,
customId: "recipient",
style: TextStyles.Short,
label: "Recipient",
},
],
},
{
type: MessageComponentTypes.ActionRow,
components: [
{
type: MessageComponentTypes.InputText,
customId: "content",
style: TextStyles.Paragraph,
label: "Message",
},
],
},
]);
collectModal(modal)
.then(async ({ interaction, values }) => {
if (!interaction.data?.components) return;
const user = interaction?.member?.user || { username: "[unknown]" };
try {
const response = await fetch(process.env.MAIL_SERVER + "/send", {
method: "POST",
body: JSON.stringify({
author: user.username,
recipient: values.get("recipient"),
content: values.get("content"),
}),
});
const body = (await response.json()) as SendMailResponse;
interaction.respond(body.message);
} catch (e) {
return interaction.respond((e as Error).message);
}
})
.catch((_) => {});
return modal;
}
}

View file

@ -13,7 +13,9 @@ export async function load(client: Bot) {
for (let i = 0; i < files.length; i++) { for (let i = 0; i < files.length; i++) {
let value = files[i]; let value = files[i];
const interaction = await import(import.meta.dirname + "/../../interactions/" + value); const interaction = await import(import.meta.dirname + "/../../interactions/" + value);
interactions.set(interaction.default.name, interaction.default); const cmd = new interaction.default();
interactions.set(cmd.name, interaction.default);
} }
CommandHandler.load(client, interactions); CommandHandler.load(client, interactions);

View file

@ -9,12 +9,13 @@ function getModalValues(interaction: Interaction): Map<string, string> {
const values = new Map(); const values = new Map();
if (!interaction.data?.components) return values; if (!interaction.data?.components) return values;
const actionRow: Component = interaction.data?.components[0]; interaction.data?.components.forEach((actionRow: Component) => {
if (actionRow.components?.length) { if (actionRow.components?.length) {
actionRow.components.forEach((value, index) => { actionRow.components.forEach((value, index) => {
values.set(value.customId, value.value); values.set(value.customId, value.value);
}); });
} }
});
return values; return values;
} }
@ -25,10 +26,13 @@ export function collectModal(modal: Modal): Promise<ModalResponse> {
modal.setId(id); modal.setId(id);
modals.set(id, resolve); modals.set(id, resolve);
setTimeout(() => { setTimeout(
modals.delete(id); () => {
reject(new Error("Modal timeout")); modals.delete(id);
}, 1000 * 60 * 30); reject(new Error("Modal timeout"));
},
1000 * 60 * 30,
);
}); });
} }

View file

@ -1,5 +1,8 @@
declare module "bun" { declare module "bun" {
interface Env { interface Env {
DISCORD_TOKEN: string; DISCORD_ID: string;
} DISCORD_TOKEN: string;
DISCORD_SECRET: string;
MAIL_SERVER: string;
}
} }