reminders command
This commit is contained in:
parent
5d66c55b5b
commit
c0d8ad62cb
7 changed files with 184 additions and 35 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
125
src/commands/reminders.ts
Normal 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;
|
42
src/index.ts
42
src/index.ts
|
@ -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
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
for (const guild of config.testGuilds) {
|
if (process.env["NODE_ENV"] === "production") {
|
||||||
logger.info(`Loading draft command ${command.name} for guild ${guild}`);
|
logger.info(`Loading ${cmds.length} commands in global mode...`);
|
||||||
|
|
||||||
bot.createGuildCommand(guild, {
|
bot.bulkEditCommands(cmds);
|
||||||
name: command.name,
|
} else {
|
||||||
description: command.description,
|
logger.info(`Loading ${cmds.length} commands in test mode...`);
|
||||||
type: Constants.ApplicationCommandTypes.CHAT_INPUT,
|
|
||||||
options: command.options
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.info(`Loading command ${command.name}`);
|
|
||||||
|
|
||||||
bot.createCommand({
|
for (const guild of config.testGuilds) {
|
||||||
name: command.name,
|
logger.info(`Loading commands in guild ${guild}...`);
|
||||||
description: command.description,
|
|
||||||
type: Constants.ApplicationCommandTypes.CHAT_INPUT,
|
bot.bulkEditGuildCommands(guild, cmds);
|
||||||
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
16
src/utils/options.ts
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue