reminders command

This commit is contained in:
Julian 2022-08-27 13:22:42 -04:00
parent 5d66c55b5b
commit c0d8ad62cb
Signed by: NotNite
GPG Key ID: BD91A5402CCEB08A
7 changed files with 184 additions and 35 deletions

View File

@ -4,7 +4,6 @@ type Command = {
name: string; name: string;
description: string; description: string;
aliases?: string[]; aliases?: string[];
draft: boolean;
options?: ApplicationCommandOptions[]; options?: ApplicationCommandOptions[];
type?: 1; type?: 1;

View File

@ -2,10 +2,12 @@ import Command from "./command";
import ping from "./ping"; import ping from "./ping";
import remind from "./remind"; import remind from "./remind";
import reminders from "./reminders";
const commands: { [key: string]: Command } = { const commands: { [key: string]: Command } = {
ping, ping,
remind remind,
reminders
}; };
export default commands; export default commands;

View File

@ -3,7 +3,6 @@ import Command from "./command";
const ping: Command = { const ping: Command = {
name: "ping", name: "ping",
description: "Ping the bot.", description: "Ping the bot.",
draft: false,
command: async (interaction) => { command: async (interaction) => {
await interaction.createMessage("Pong!"); await interaction.createMessage("Pong!");
} }

View File

@ -3,14 +3,19 @@ import Command from "./command";
import db from "../things/db"; import db from "../things/db";
import bot from "../things/bot"; import bot from "../things/bot";
import { Constants } from "eris"; import { Constants, InteractionDataOptionsString } from "eris";
import parse from "parse-duration"; import parse from "parse-duration";
import logger from "../things/logger"; import logger from "../things/logger";
import {
Optional,
unravelOption,
unravelOptionalOption
} from "../utils/options";
const remind: Command = { const remind: Command = {
name: "remind", name: "remind",
description: "Reminds you to do something.", description: "Reminds you to do something.",
draft: false,
options: [ options: [
{ {
name: "when", name: "when",
@ -25,18 +30,19 @@ const remind: Command = {
} }
], ],
command: async (interaction) => { command: async (interaction) => {
const whenOption = interaction.data.options?.find((x) => x.name === "when"); // i love abusing types
const whatOption = interaction.data.options?.find((x) => x.name === "what"); const options = interaction.data.options!;
const whenOption = unravelOption<InteractionDataOptionsString>(
let what = null; "when",
if (whatOption?.type === Constants.ApplicationCommandOptionTypes.STRING) options
what = whatOption.value; );
const whatOption = unravelOptionalOption<
// fucking ts Optional<InteractionDataOptionsString>
if (whenOption?.type != Constants.ApplicationCommandOptionTypes.STRING) >("what", options);
return;
const when = parse(whenOption.value); const when = parse(whenOption.value);
const what = whatOption?.value;
if (when === null) { if (when === null) {
await interaction.createMessage({ await interaction.createMessage({
content: content:

125
src/commands/reminders.ts Normal file
View File

@ -0,0 +1,125 @@
import Command from "./command";
import db from "../things/db";
import {
CommandInteraction,
Constants,
InteractionDataOptionsNumber,
InteractionDataOptionsSubCommand
} from "eris";
import {
Optional,
unravelOption,
unravelOptionalOption
} from "../utils/options";
async function listReminders(interaction: CommandInteraction) {
const userReminders = await db.reminder.findMany({
where: {
user: (interaction.member || interaction.user)!.id
}
});
console.log(userReminders);
await interaction.createMessage({
embeds: [
{
title: "Your reminders",
description: userReminders
.map((x) => {
const timestamp = `<t:${Math.floor(x.sendAt.getTime() / 1000)}:R>`;
const id = `ID: \`${x.id}\``;
const message = x.message || "No message set";
return `${timestamp} - ${id} - ${message}`;
})
.join("\n")
}
]
});
}
async function deleteReminder(interaction: CommandInteraction, id: number) {
const reminder = await db.reminder.findUnique({
where: {
id
}
});
if (!reminder) {
await interaction.createMessage({
content: "That reminder doesn't exist.",
flags: Constants.MessageFlags.EPHEMERAL
});
return;
}
const user = (interaction.member || interaction.user)!.id;
if (reminder.user !== user) {
await interaction.createMessage({
content: "You can't delete someone else's reminder.",
flags: Constants.MessageFlags.EPHEMERAL
});
return;
}
await db.reminder.delete({
where: {
id
}
});
await interaction.createMessage({
content: "Reminder deleted.",
flags: Constants.MessageFlags.EPHEMERAL
});
}
const reminders: Command = {
name: "reminders",
description: "List your set reminders.",
options: [
{
name: "list",
description: "List all your reminders.",
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND
},
{
name: "delete",
description: "Delete a reminder.",
type: Constants.ApplicationCommandOptionTypes.SUB_COMMAND,
options: [
{
name: "id",
description: "The ID of the reminder to delete.",
required: true,
type: Constants.ApplicationCommandOptionTypes.NUMBER
}
]
}
],
command: async (interaction) => {
const options = interaction.data.options!;
const listOption = unravelOptionalOption<
Optional<InteractionDataOptionsSubCommand>
>("list", options);
const deleteOption = unravelOptionalOption<
Optional<InteractionDataOptionsSubCommand>
>("delete", options);
if (listOption !== undefined) await listReminders(interaction);
if (deleteOption !== undefined) {
const id = unravelOption<InteractionDataOptionsNumber>(
"id",
deleteOption.options!
);
await deleteReminder(interaction, id.value);
}
}
};
export default reminders;

View File

@ -6,29 +6,26 @@ import commands from "./commands/index";
import Eris, { Constants } from "eris"; import Eris, { Constants } from "eris";
bot.on("ready", () => { bot.on("ready", () => {
for (const command of Object.values(commands)) { const cmds = Object.values(commands).map((x) => {
if (command.draft) { return {
logger.info(`Loading draft command ${command.name}`); name: x.name,
description: x.description,
type: Constants.ApplicationCommandTypes.CHAT_INPUT,
options: x.options
};
});
if (process.env["NODE_ENV"] === "production") {
logger.info(`Loading ${cmds.length} commands in global mode...`);
bot.bulkEditCommands(cmds);
} else {
logger.info(`Loading ${cmds.length} commands in test mode...`);
for (const guild of config.testGuilds) { for (const guild of config.testGuilds) {
logger.info(`Loading draft command ${command.name} for guild ${guild}`); logger.info(`Loading commands in guild ${guild}...`);
bot.createGuildCommand(guild, { bot.bulkEditGuildCommands(guild, cmds);
name: command.name,
description: command.description,
type: Constants.ApplicationCommandTypes.CHAT_INPUT,
options: command.options
});
}
} else {
logger.info(`Loading command ${command.name}`);
bot.createCommand({
name: command.name,
description: command.description,
type: Constants.ApplicationCommandTypes.CHAT_INPUT,
options: command.options
});
} }
} }
@ -49,6 +46,11 @@ bot.on("interactionCreate", async (interaction) => {
{ err }, { err },
`Error running command ${commandName} for interaction ${interaction.id}` `Error running command ${commandName} for interaction ${interaction.id}`
); );
await interaction.createMessage({
content: ":warn: Something went wrong running this command.",
flags: Constants.MessageFlags.EPHEMERAL
});
} }
} else { } else {
logger.warn(`Unhandled command ${commandName}?`); logger.warn(`Unhandled command ${commandName}?`);

16
src/utils/options.ts Normal file
View File

@ -0,0 +1,16 @@
import { InteractionDataOptions, InteractionDataOptionsSubCommand } from "eris";
export type Optional<T> = T | undefined;
export function unravelOption<T extends InteractionDataOptions>(
name: string,
options: InteractionDataOptions[]
): T {
return options.find((x) => x.name === name) as T;
}
export function unravelOptionalOption<
T extends Optional<InteractionDataOptions>
>(name: string, options: InteractionDataOptions[]): T {
return options.find((x) => x.name === name) as T;
}