diff --git a/README.md b/README.md index 345d35bb..787786c1 100644 --- a/README.md +++ b/README.md @@ -140,19 +140,27 @@ pnpm run prisma:gen ### DB GUI ```bash -pnpm prisma:studio +pnpm run prisma:studio ``` ### Deploying your commands to a test Discord Server - Please make sure you have filled out your `GUILD_ID`, `TOKEN` and `CLIENT_ID` in the `.env` file. -- Add your commands into the `src/command/index.ts` file like so. +- Add your commands into the `src/slash-commands/index.ts` & `src/context-menu-commands/index.ts` file like so. ```ts -import yourCommand from './yourCommand'; +// File: src/slash-commands/index.ts +import yourCommand from './your-command'; -export const commandList: Command[] = [yourCommand]; +export const commandList: SlashCommand[] = [yourCommand]; +``` + +```ts +// File: src/context-menu-commands/index.ts +import yourCommand from './your-command'; + +export const commandList: ContextMenuCommand[] = [yourCommand] ``` - Run the `deploy:command` command. @@ -182,6 +190,7 @@ pnpm run deploy:command ### Running lints and tests ```bash +pnpm run lint pnpm run format pnpm run test ``` diff --git a/bin/autobump.ts b/bin/autobump.ts index 4a02d361..1415d3db 100644 --- a/bin/autobump.ts +++ b/bin/autobump.ts @@ -1,7 +1,7 @@ import type { ThreadChannel } from 'discord.js'; import { Result } from 'oxide.ts'; import { getDiscordClient } from '../src/clients'; -import { listAllThreads } from '../src/commands/autobump-threads/utils'; +import { listAllThreads } from '../src/slash-commands/autobump-threads/utils'; import { loadEnv } from '../src/utils/load-env'; import { logger } from '../src/utils/logger'; diff --git a/bin/broadcast-reminder.ts b/bin/broadcast-reminder.ts index 94ebc122..004ba19e 100644 --- a/bin/broadcast-reminder.ts +++ b/bin/broadcast-reminder.ts @@ -1,8 +1,8 @@ import { ChannelType } from 'discord.js'; import { Result } from 'oxide.ts'; import { getDiscordClient } from '../src/clients'; -import { formatReminderMessage, getReminderByTime, removeReminders } from '../src/commands/reminder/utils'; -import { getReminderChannel } from '../src/commands/serverSettings/utils'; +import { formatReminderMessage, getReminderByTime, removeReminders } from '../src/slash-commands/reminder/utils'; +import { getReminderChannel } from '../src/slash-commands/server-settings/utils'; import { getCurrentUnixTime } from '../src/utils/date'; import { loadEnv } from '../src/utils/load-env'; import { logger } from '../src/utils/logger'; diff --git a/bin/cleanup-expired-referrals.ts b/bin/cleanup-expired-referrals.ts index f82bac75..79a6e7ed 100644 --- a/bin/cleanup-expired-referrals.ts +++ b/bin/cleanup-expired-referrals.ts @@ -1,5 +1,5 @@ import { Result } from 'oxide.ts'; -import { cleanupExpiredCode } from '../src/commands/referral/cleanupExpiredCode'; +import { cleanupExpiredCode } from '../src/slash-commands/referral/utils'; import { loadEnv } from '../src/utils/load-env'; import { logger } from '../src/utils/logger'; diff --git a/bin/main.ts b/bin/main.ts index a21ced83..426c82f8 100644 --- a/bin/main.ts +++ b/bin/main.ts @@ -1,9 +1,10 @@ import { InteractionType } from 'discord-api-types/v10'; import { Result } from 'oxide.ts'; import { getDiscordClient } from '../src/clients'; -import { commandList, contextMenuCommandList } from '../src/commands'; -import { deployGlobalCommands } from '../src/commands/deploy-command'; import { getConfigs } from '../src/config'; +import { commands as contextMenuCommandList } from '../src/context-menu-commands'; +import { deployGlobalCommands } from '../src/deploy-command'; +import { commands as slashCommandList } from '../src/slash-commands'; import { loadEnv } from '../src/utils/load-env'; import { logger } from '../src/utils/logger'; import { processMessage } from '../src/utils/message-processor'; @@ -21,8 +22,9 @@ const main = async () => { // This should only be run once during the bot startup in production. // For development usage, please use `pnpm deploy:command` logger.info('[main]: Deploying global commands'); + const commands = [...slashCommandList, ...contextMenuCommandList]; const op = await Result.safe( - deployGlobalCommands([...commandList, ...contextMenuCommandList], { + deployGlobalCommands(commands, { token, clientId: client.user.id, }) @@ -45,7 +47,7 @@ const main = async () => { if (isCommand) { const { commandName } = interaction; logger.info(`[main]: RECEIVED COMMAND. COMMAND: ${commandName}`); - const command = commandList.find((cmd) => cmd.data.name === commandName); + const command = slashCommandList.find((cmd) => cmd.data.name === commandName); return await command?.execute(interaction); } @@ -61,7 +63,7 @@ const main = async () => { if (isAutocomplete) { const { commandName } = interaction; logger.info(`[main]: RECEIVED AUTOCOMPLETE. COMMAND: ${commandName}`); - const command = commandList.find((cmd) => cmd.data.name === commandName); + const command = slashCommandList.find((cmd) => cmd.data.name === commandName); return await command?.autocomplete?.(interaction); } } catch (error) { diff --git a/biome.json b/biome.json index 7e902484..29352963 100644 --- a/biome.json +++ b/biome.json @@ -25,7 +25,7 @@ "indentStyle": "space", "indentWidth": 2, "lineWidth": 160, - "ignore": ["node_modules/**", "./src/commands/referral/generated"] + "ignore": ["node_modules/**", "./src/slash-commands/referral/generated"] }, "javascript": { "formatter": { diff --git a/scripts/build-referral-list.ts b/scripts/build-referral-list.ts index 90b457f9..85b8aca9 100644 --- a/scripts/build-referral-list.ts +++ b/scripts/build-referral-list.ts @@ -5,9 +5,10 @@ import wretch from 'wretch'; import { logger } from '../src/utils/logger'; const ozbargainApi = wretch('https://www.ozbargain.com.au/wiki/list_of_referral_links'); -const OUTPUT_DIR = path.join(__dirname, '..', 'src', 'commands', 'referral', 'generated'); +const referralModuleDir = path.join(__dirname, '..', 'src', 'slash-commands', 'referral'); +const OUTPUT_DIR = path.join(referralModuleDir, 'generated'); -const getOzbReferralNodes = async () => { +const getOzbReferralNodes = async (): Promise => { logger.info('[get-ozbargain-referral-nodes]: Fetching Ozbargain referral list'); const rawHtml = await ozbargainApi.get().text(); const htmlTree = parseHtml(rawHtml); diff --git a/scripts/delete-global-commands.ts b/scripts/delete-global-commands.ts index c2c38bc8..8140bd6d 100644 --- a/scripts/delete-global-commands.ts +++ b/scripts/delete-global-commands.ts @@ -1,5 +1,5 @@ import { Result } from 'oxide.ts'; -import { deployGlobalCommands } from '../src/commands/deploy-command'; +import { deployGlobalCommands } from '../src/deploy-command'; import { loadEnv } from '../src/utils/load-env'; import { logger } from '../src/utils/logger'; diff --git a/scripts/delete-guild-commands.ts b/scripts/delete-guild-commands.ts index 0b8a8bc0..ccbd0ece 100644 --- a/scripts/delete-guild-commands.ts +++ b/scripts/delete-guild-commands.ts @@ -1,5 +1,5 @@ import { Result } from 'oxide.ts'; -import { deployGuildCommands } from '../src/commands/deploy-command'; +import { deployGuildCommands } from '../src/deploy-command'; import { getCurrentUnixTime } from '../src/utils/date'; import { loadEnv } from '../src/utils/load-env'; import { logger } from '../src/utils/logger'; diff --git a/scripts/deploy-guild-commands.ts b/scripts/deploy-guild-commands.ts index 3ede43fd..4bfcfb50 100644 --- a/scripts/deploy-guild-commands.ts +++ b/scripts/deploy-guild-commands.ts @@ -1,6 +1,7 @@ import { Result } from 'oxide.ts'; -import { commandList, contextMenuCommandList } from '../src/commands'; -import { deployGuildCommands } from '../src/commands/deploy-command'; +import { commands as slashCommandList } from '../src/slash-commands'; +import { commands as contextMenuCommandList } from '../src/context-menu-commands'; +import { deployGuildCommands } from '../src/deploy-command'; import { getCurrentUnixTime } from '../src/utils/date'; import { loadEnv } from '../src/utils/load-env'; import { logger } from '../src/utils/logger'; @@ -16,8 +17,9 @@ const deploy = async () => { } logger.info('[deploy-guild-commands]: Deploying guild commands'); + const commands = [...slashCommandList, ...contextMenuCommandList]; const op = await Result.safe( - deployGuildCommands([...commandList, ...contextMenuCommandList,], { + deployGuildCommands(commands, { token, clientId, guildId, diff --git a/src/commands/referral/cleanupExpiredCode.ts b/src/commands/referral/cleanupExpiredCode.ts deleted file mode 100644 index 6d8e31ef..00000000 --- a/src/commands/referral/cleanupExpiredCode.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { getDbClient } from '../../clients'; - -export const cleanupExpiredCode = async () => { - const db = getDbClient(); - const currentDate = new Date(); - return db.referralCode.deleteMany({ - where: { - expiry_date: { - lt: currentDate, - }, - }, - }); -}; diff --git a/src/config.ts b/src/config.ts index 99334ded..a4242124 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,4 +1,4 @@ -import { thankUserInMessage } from './commands'; +import { thankUserInMessage } from './slash-commands/reputation/give-reputation'; import type { CommandConfig } from './utils/message-processor'; export const getConfigs = (): CommandConfig => { diff --git a/src/context-menu-commands/builder.ts b/src/context-menu-commands/builder.ts new file mode 100644 index 00000000..94b980c1 --- /dev/null +++ b/src/context-menu-commands/builder.ts @@ -0,0 +1,8 @@ +import type { ContextMenuCommandBuilder, ContextMenuCommandInteraction } from 'discord.js'; + +export type ContextMenuCommandInteractionHandler = (interaction: ContextMenuCommandInteraction) => Promise; + +export interface ContextMenuCommand { + data: ContextMenuCommandBuilder; + execute: ContextMenuCommandInteractionHandler; +} diff --git a/src/context-menu-commands/index.ts b/src/context-menu-commands/index.ts new file mode 100644 index 00000000..f7721ec3 --- /dev/null +++ b/src/context-menu-commands/index.ts @@ -0,0 +1,4 @@ +import type { ContextMenuCommand } from './builder'; +import pinMessageCommand from './pin-message'; + +export const commands: ContextMenuCommand[] = [pinMessageCommand]; diff --git a/src/commands/contextMenuCommands/pin/index.test.ts b/src/context-menu-commands/pin-message/index.test.ts similarity index 100% rename from src/commands/contextMenuCommands/pin/index.test.ts rename to src/context-menu-commands/pin-message/index.test.ts diff --git a/src/commands/contextMenuCommands/pin/index.ts b/src/context-menu-commands/pin-message/index.ts similarity index 90% rename from src/commands/contextMenuCommands/pin/index.ts rename to src/context-menu-commands/pin-message/index.ts index be804307..d731d10e 100644 --- a/src/commands/contextMenuCommands/pin/index.ts +++ b/src/context-menu-commands/pin-message/index.ts @@ -1,6 +1,6 @@ import { ApplicationCommandType, ContextMenuCommandBuilder, type ContextMenuCommandInteraction } from 'discord.js'; -import { logger } from '../../../utils/logger'; -import type { ContextMenuCommand } from '../../builder'; +import { logger } from '../../utils/logger'; +import type { ContextMenuCommand } from '../builder'; export const data = new ContextMenuCommandBuilder().setName('Pin').setType(ApplicationCommandType.Message); diff --git a/src/commands/deploy-command.ts b/src/deploy-command.ts similarity index 70% rename from src/commands/deploy-command.ts rename to src/deploy-command.ts index 11015195..4c9a432e 100644 --- a/src/commands/deploy-command.ts +++ b/src/deploy-command.ts @@ -1,6 +1,7 @@ import { REST, type RequestData, type RouteLike } from '@discordjs/rest'; import { Routes } from 'discord-api-types/v10'; -import type { Command, ContextMenuCommand } from './builder'; +import type { ContextMenuCommand } from './context-menu-commands/builder'; +import type { SlashCommand } from './slash-commands/builder'; interface DiscordRequestConfig { token: string; @@ -19,7 +20,7 @@ const registerCommands = async ({ request, token, body }: DiscordRequestPayload) return rest.put(request, { body }); }; -export const deployGuildCommands = async (commandList: Array, config: DiscordRequestConfig) => { +export const deployGuildCommands = async (commandList: Array, config: DiscordRequestConfig) => { const { token, clientId, guildId } = config; const commands = commandList.map((cmd) => cmd.data.toJSON()); @@ -28,7 +29,7 @@ export const deployGuildCommands = async (commandList: Array, config: Omit) => { +export const deployGlobalCommands = async (commandList: Array, config: Omit) => { const { token, clientId } = config; const commands = commandList.map((cmd) => cmd.data.toJSON()); diff --git a/src/commands/8ball/index.test.ts b/src/slash-commands/8ball/index.test.ts similarity index 100% rename from src/commands/8ball/index.test.ts rename to src/slash-commands/8ball/index.test.ts diff --git a/src/commands/8ball/index.ts b/src/slash-commands/8ball/index.ts similarity index 93% rename from src/commands/8ball/index.ts rename to src/slash-commands/8ball/index.ts index 757a21e1..ceab4f4a 100644 --- a/src/commands/8ball/index.ts +++ b/src/slash-commands/8ball/index.ts @@ -1,7 +1,7 @@ import { type ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; import { logger } from '../../utils/logger'; import { getRandomIntInclusive } from '../../utils/random'; -import type { Command } from '../builder'; +import type { SlashCommand } from '../builder'; const data = new SlashCommandBuilder() .setName('8ball') @@ -32,7 +32,7 @@ export const ask8Ball = async (interaction: ChatInputCommandInteraction) => { await interaction.reply(`Q: ${question}\nA: ${reply}`); }; -const command: Command = { +const command: SlashCommand = { data, execute: ask8Ball, }; diff --git a/src/commands/allCap/index.test.ts b/src/slash-commands/all-cap/index.test.ts similarity index 100% rename from src/commands/allCap/index.test.ts rename to src/slash-commands/all-cap/index.test.ts diff --git a/src/commands/allCap/index.ts b/src/slash-commands/all-cap/index.ts similarity index 95% rename from src/commands/allCap/index.ts rename to src/slash-commands/all-cap/index.ts index c3d5153a..d4b76bfb 100644 --- a/src/commands/allCap/index.ts +++ b/src/slash-commands/all-cap/index.ts @@ -3,7 +3,7 @@ import { Result } from 'oxide.ts'; import { isBlank } from '../../utils/is-blank'; import { logger } from '../../utils/logger'; import { fetchLastMessageBeforeId } from '../../utils/message-fetcher'; -import type { Command } from '../builder'; +import type { SlashCommand } from '../builder'; const data = new SlashCommandBuilder() .setName('allcap') @@ -44,7 +44,7 @@ export const allCapExpandText = async (interaction: ChatInputCommandInteraction) await interaction.reply(reply); }; -const command: Command = { +const command: SlashCommand = { data, execute: allCapExpandText, }; diff --git a/src/commands/autobump-threads/add-thread.test.ts b/src/slash-commands/autobump-threads/add-thread.test.ts similarity index 100% rename from src/commands/autobump-threads/add-thread.test.ts rename to src/slash-commands/autobump-threads/add-thread.test.ts diff --git a/src/commands/autobump-threads/add-thread.ts b/src/slash-commands/autobump-threads/add-thread.ts similarity index 91% rename from src/commands/autobump-threads/add-thread.ts rename to src/slash-commands/autobump-threads/add-thread.ts index ce591379..5d0a2fa3 100644 --- a/src/commands/autobump-threads/add-thread.ts +++ b/src/slash-commands/autobump-threads/add-thread.ts @@ -1,7 +1,7 @@ import { ChannelType, SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import { logger } from '../../utils/logger'; -import type { CommandHandler, Subcommand } from '../builder'; +import type { SlashCommandHandler, Subcommand } from '../builder'; import { addAutobumpThread } from './utils'; const data = new SlashCommandSubcommandBuilder() @@ -9,7 +9,7 @@ const data = new SlashCommandSubcommandBuilder() .setDescription('Add thread to autobump list') .addChannelOption((option) => option.setName('thread').setDescription('thread to be auto-bumped').setRequired(true)); -export const addAutobumpThreadCommand: CommandHandler = async (interaction) => { +export const addAutobumpThreadCommand: SlashCommandHandler = async (interaction) => { const guildId = interaction.guildId!; const thread = interaction.options.getChannel('thread', true); logger.info(`[add-autobump-thread]: Adding thread ${thread.id} to autobump list for guild ${guildId}`); diff --git a/src/commands/autobump-threads/index.ts b/src/slash-commands/autobump-threads/index.ts similarity index 73% rename from src/commands/autobump-threads/index.ts rename to src/slash-commands/autobump-threads/index.ts index 485ed79a..1f900185 100644 --- a/src/commands/autobump-threads/index.ts +++ b/src/slash-commands/autobump-threads/index.ts @@ -1,9 +1,9 @@ import { type GuildMember, SlashCommandBuilder } from 'discord.js'; import { isAdmin, isModerator } from '../../utils/permission'; -import addThread from '../autobump-threads/add-thread'; -import listThreads from '../autobump-threads/list-threads'; -import removeThread from '../autobump-threads/remove-thread'; -import type { Command, CommandHandler } from '../builder'; +import type { SlashCommand, SlashCommandHandler } from '../builder'; +import addThread from './add-thread'; +import listThreads from './list-threads'; +import removeThread from './remove-thread'; const data = new SlashCommandBuilder() .setName('autobump-threads') @@ -14,7 +14,7 @@ const data = new SlashCommandBuilder() const subcommands = [listThreads, addThread, removeThread]; -const execute: CommandHandler = async (interaction) => { +const execute: SlashCommandHandler = async (interaction) => { const member = interaction.member as GuildMember; if (!isAdmin(member) && !isModerator(member)) { await interaction.reply("You don't have enough permission to run this command."); @@ -26,7 +26,7 @@ const execute: CommandHandler = async (interaction) => { return subcommand?.execute(interaction); }; -const command: Command = { +const command: SlashCommand = { data, execute, }; diff --git a/src/commands/autobump-threads/list-threads.test.ts b/src/slash-commands/autobump-threads/list-threads.test.ts similarity index 100% rename from src/commands/autobump-threads/list-threads.test.ts rename to src/slash-commands/autobump-threads/list-threads.test.ts diff --git a/src/commands/autobump-threads/list-threads.ts b/src/slash-commands/autobump-threads/list-threads.ts similarity index 91% rename from src/commands/autobump-threads/list-threads.ts rename to src/slash-commands/autobump-threads/list-threads.ts index 77f9e3eb..0dc337f1 100644 --- a/src/commands/autobump-threads/list-threads.ts +++ b/src/slash-commands/autobump-threads/list-threads.ts @@ -2,7 +2,7 @@ import type { ServerChannelsSettings } from '@prisma/client'; import { SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import { logger } from '../../utils/logger'; -import type { CommandHandler, Subcommand } from '../builder'; +import type { SlashCommandHandler, Subcommand } from '../builder'; import { listThreadsByGuild } from './utils'; const data = new SlashCommandSubcommandBuilder().setName('list').setDescription('Show list of autobump threads'); @@ -14,7 +14,7 @@ const buildThreadList = (threadIds: ServerChannelsSettings['autobumpThreads']) = }, startText); }; -export const listAutobumpThreadsCommand: CommandHandler = async (interaction) => { +export const listAutobumpThreadsCommand: SlashCommandHandler = async (interaction) => { const guildId = interaction.guildId!; const threads = await Result.safe(listThreadsByGuild(guildId)); logger.info(`[list-autobump-threads]: Listing autobump threads for guild ${guildId}`); diff --git a/src/commands/autobump-threads/remove-thread.test.ts b/src/slash-commands/autobump-threads/remove-thread.test.ts similarity index 100% rename from src/commands/autobump-threads/remove-thread.test.ts rename to src/slash-commands/autobump-threads/remove-thread.test.ts diff --git a/src/commands/autobump-threads/remove-thread.ts b/src/slash-commands/autobump-threads/remove-thread.ts similarity index 88% rename from src/commands/autobump-threads/remove-thread.ts rename to src/slash-commands/autobump-threads/remove-thread.ts index 6ab7a84d..da668a98 100644 --- a/src/commands/autobump-threads/remove-thread.ts +++ b/src/slash-commands/autobump-threads/remove-thread.ts @@ -1,7 +1,7 @@ import { SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import { logger } from '../../utils/logger'; -import type { CommandHandler, Subcommand } from '../builder'; +import type { SlashCommandHandler, Subcommand } from '../builder'; import { removeAutobumpThread } from './utils'; const data = new SlashCommandSubcommandBuilder() @@ -9,7 +9,7 @@ const data = new SlashCommandSubcommandBuilder() .setDescription('Remove thread from autobump list') .addChannelOption((option) => option.setName('thread').setDescription('thread not to be auto-bumped').setRequired(true)); -export const removeAutobumpThreadCommand: CommandHandler = async (interaction) => { +export const removeAutobumpThreadCommand: SlashCommandHandler = async (interaction) => { const guildId = interaction.guildId!; const thread = interaction.options.getChannel('thread', true); logger.info(`[remove-autobump-thread]: Removing thread ${thread.id} from autobump list for guild ${guildId}`); diff --git a/src/commands/autobump-threads/utils.ts b/src/slash-commands/autobump-threads/utils.ts similarity index 100% rename from src/commands/autobump-threads/utils.ts rename to src/slash-commands/autobump-threads/utils.ts diff --git a/src/commands/builder.ts b/src/slash-commands/builder.ts similarity index 55% rename from src/commands/builder.ts rename to src/slash-commands/builder.ts index 4f2b46e7..0f0575a7 100644 --- a/src/commands/builder.ts +++ b/src/slash-commands/builder.ts @@ -1,29 +1,21 @@ import type { AutocompleteInteraction, ChatInputCommandInteraction, - ContextMenuCommandBuilder, - ContextMenuCommandInteraction, SlashCommandBuilder, SlashCommandSubcommandBuilder, SlashCommandSubcommandsOnlyBuilder, } from 'discord.js'; -export type CommandHandler = (interaction: ChatInputCommandInteraction) => Promise; +export type SlashCommandHandler = (interaction: ChatInputCommandInteraction) => Promise; export type AutocompleteHandler = (autocomplete: AutocompleteInteraction) => Promise; -export type ContextMenuCommandInteractionHandler = (interaction: ContextMenuCommandInteraction) => Promise; -export interface Command { +export interface SlashCommand { data: Omit | SlashCommandSubcommandsOnlyBuilder; - execute: CommandHandler; + execute: SlashCommandHandler; autocomplete?: AutocompleteHandler; } export interface Subcommand { data: SlashCommandSubcommandBuilder | ((subcommandGroup: SlashCommandSubcommandBuilder) => SlashCommandSubcommandBuilder); - execute: CommandHandler; -} - -export interface ContextMenuCommand { - data: ContextMenuCommandBuilder; - execute: ContextMenuCommandInteractionHandler; + execute: SlashCommandHandler; } diff --git a/src/commands/cowsay/index.test.ts b/src/slash-commands/cowsay/index.test.ts similarity index 100% rename from src/commands/cowsay/index.test.ts rename to src/slash-commands/cowsay/index.test.ts diff --git a/src/commands/cowsay/index.ts b/src/slash-commands/cowsay/index.ts similarity index 97% rename from src/commands/cowsay/index.ts rename to src/slash-commands/cowsay/index.ts index 2d074045..b4d66ae5 100644 --- a/src/commands/cowsay/index.ts +++ b/src/slash-commands/cowsay/index.ts @@ -4,7 +4,7 @@ import { Result } from 'oxide.ts'; import { isBlank } from '../../utils/is-blank'; import { logger } from '../../utils/logger'; import { fetchLastMessageBeforeId } from '../../utils/message-fetcher'; -import type { Command } from '../builder'; +import type { SlashCommand } from '../builder'; // Only 35 characters per line due to limitation in phone screen width const WRAP_TEXT_LIMIT = 35; @@ -80,7 +80,7 @@ export const cowsay = async (interaction: ChatInputCommandInteraction) => { await interaction.reply(reply); }; -const command: Command = { +const command: SlashCommand = { data, execute: cowsay, }; diff --git a/src/commands/danhSomeone/index.test.ts b/src/slash-commands/danh-someone/index.test.ts similarity index 100% rename from src/commands/danhSomeone/index.test.ts rename to src/slash-commands/danh-someone/index.test.ts diff --git a/src/commands/danhSomeone/index.ts b/src/slash-commands/danh-someone/index.ts similarity index 95% rename from src/commands/danhSomeone/index.ts rename to src/slash-commands/danh-someone/index.ts index c2aca9dc..967f17c0 100644 --- a/src/commands/danhSomeone/index.ts +++ b/src/slash-commands/danh-someone/index.ts @@ -1,7 +1,7 @@ import { type ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; import { logger } from '../../utils/logger'; import { getRandomBoolean, getRandomIntInclusive } from '../../utils/random'; -import type { Command } from '../builder'; +import type { SlashCommand } from '../builder'; const MAX_MENTIONS = 10; @@ -53,7 +53,7 @@ export const danhSomeone = async (interaction: ChatInputCommandInteraction) => { await interaction.reply(messages); }; -const command: Command = { +const command: SlashCommand = { data: getData(), execute: danhSomeone, }; diff --git a/src/commands/disclaimer/index.test.ts b/src/slash-commands/disclaimer/index.test.ts similarity index 100% rename from src/commands/disclaimer/index.test.ts rename to src/slash-commands/disclaimer/index.test.ts diff --git a/src/commands/disclaimer/index.ts b/src/slash-commands/disclaimer/index.ts similarity index 95% rename from src/commands/disclaimer/index.ts rename to src/slash-commands/disclaimer/index.ts index b7df1caa..e11b3b17 100644 --- a/src/commands/disclaimer/index.ts +++ b/src/slash-commands/disclaimer/index.ts @@ -1,6 +1,6 @@ import { type ChatInputCommandInteraction, EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import { logger } from '../../utils/logger'; -import type { Command } from '../builder'; +import type { SlashCommand } from '../builder'; const data = new SlashCommandBuilder() .setName('disclaimer') @@ -32,7 +32,7 @@ export const getDisclaimer = async (interaction: ChatInputCommandInteraction) => await interaction.reply({ embeds: [embedMessage] }); }; -const command: Command = { +const command: SlashCommand = { data, execute: getDisclaimer, }; diff --git a/src/commands/index.ts b/src/slash-commands/index.ts similarity index 53% rename from src/commands/index.ts rename to src/slash-commands/index.ts index 58e566cd..98d730fd 100644 --- a/src/commands/index.ts +++ b/src/slash-commands/index.ts @@ -1,23 +1,22 @@ import ask8ball from './8ball'; -import allCap from './allCap'; +import allCap from './all-cap'; import autobumpThread from './autobump-threads'; -import type { Command, ContextMenuCommand } from './builder'; -import pinMessageContextMenuCommand from './contextMenuCommands/pin'; +import type { SlashCommand } from './builder'; import cowsayCommand from './cowsay'; -import danhCommand from './danhSomeone'; +import danhCommand from './danh-someone'; import getdisclaimer from './disclaimer'; import insultCommand from './insult'; -import mockCommand from './mockSomeone'; -import removeUserByRole from './moderateUsers'; +import mockCommand from './mock-someone'; +import removeUserByRole from './moderate-users'; import playPowerball from './powerball'; -import quoteOfTheDay from './quoteOfTheDay'; +import quoteOfTheDay from './quote-of-the-day'; import referral from './referral'; import reminder from './reminder'; import reputation from './reputation'; -import serverSettings from './serverSettings'; +import serverSettings from './server-settings'; import weatherCommand from './weather'; -export const commandList: Command[] = [ +export const commands: SlashCommand[] = [ allCap, ask8ball, autobumpThread, @@ -35,7 +34,3 @@ export const commandList: Command[] = [ serverSettings, removeUserByRole, ]; - -export const contextMenuCommandList: ContextMenuCommand[] = [pinMessageContextMenuCommand]; - -export * from './reputation'; diff --git a/src/commands/insult/index.test.ts b/src/slash-commands/insult/index.test.ts similarity index 95% rename from src/commands/insult/index.test.ts rename to src/slash-commands/insult/index.test.ts index e1e5d168..c02451c7 100644 --- a/src/commands/insult/index.test.ts +++ b/src/slash-commands/insult/index.test.ts @@ -3,7 +3,7 @@ import type { ChatInputCommandInteraction } from 'discord.js'; import { describe, expect, expectTypeOf, it } from 'vitest'; import { mockDeep, mockReset } from 'vitest-mock-extended'; import { insult } from '.'; -import { randomCreate } from './insultGenerator'; +import { randomCreate } from './insult-generator'; const mockInteraction = mockDeep(); diff --git a/src/commands/insult/index.ts b/src/slash-commands/insult/index.ts similarity index 87% rename from src/commands/insult/index.ts rename to src/slash-commands/insult/index.ts index eeb3cdfb..a830ad89 100644 --- a/src/commands/insult/index.ts +++ b/src/slash-commands/insult/index.ts @@ -1,8 +1,8 @@ import { type ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; import { isBlank } from '../../utils/is-blank'; import { logger } from '../../utils/logger'; -import type { Command } from '../builder'; -import { randomInsultGenerator } from './insultGenerator'; +import type { SlashCommand } from '../builder'; +import { randomInsultGenerator } from './insult-generator'; const data = new SlashCommandBuilder() .setName('insult') @@ -25,7 +25,7 @@ export const insult = async (interaction: ChatInputCommandInteraction) => { await interaction.reply(insultText); }; -const command: Command = { +const command: SlashCommand = { data, execute: insult, }; diff --git a/src/commands/insult/insultGenerator.ts b/src/slash-commands/insult/insult-generator.ts similarity index 100% rename from src/commands/insult/insultGenerator.ts rename to src/slash-commands/insult/insult-generator.ts diff --git a/src/commands/mockSomeone/index.test.ts b/src/slash-commands/mock-someone/index.test.ts similarity index 100% rename from src/commands/mockSomeone/index.test.ts rename to src/slash-commands/mock-someone/index.test.ts diff --git a/src/commands/mockSomeone/index.ts b/src/slash-commands/mock-someone/index.ts similarity index 96% rename from src/commands/mockSomeone/index.ts rename to src/slash-commands/mock-someone/index.ts index a1d9a92f..84ae8e22 100644 --- a/src/commands/mockSomeone/index.ts +++ b/src/slash-commands/mock-someone/index.ts @@ -4,7 +4,7 @@ import { isBlank } from '../../utils/is-blank'; import { logger } from '../../utils/logger'; import { fetchLastMessageBeforeId } from '../../utils/message-fetcher'; import { getRandomBoolean } from '../../utils/random'; -import type { Command } from '../builder'; +import type { SlashCommand } from '../builder'; const data = new SlashCommandBuilder() .setName('mock') @@ -55,7 +55,7 @@ export const mockSomeone = async (interaction: ChatInputCommandInteraction) => { await interaction.reply(reply); }; -const command: Command = { +const command: SlashCommand = { data, execute: mockSomeone, }; diff --git a/src/commands/moderateUsers/index.test.ts b/src/slash-commands/moderate-users/index.test.ts similarity index 100% rename from src/commands/moderateUsers/index.test.ts rename to src/slash-commands/moderate-users/index.test.ts diff --git a/src/commands/moderateUsers/index.ts b/src/slash-commands/moderate-users/index.ts similarity index 96% rename from src/commands/moderateUsers/index.ts rename to src/slash-commands/moderate-users/index.ts index 8f90a978..76ab6165 100644 --- a/src/commands/moderateUsers/index.ts +++ b/src/slash-commands/moderate-users/index.ts @@ -1,7 +1,7 @@ import { type ChatInputCommandInteraction, type GuildMember, SlashCommandBuilder, type ThreadChannel } from 'discord.js'; import { logger } from '../../utils/logger'; import { isAdmin, isModerator } from '../../utils/permission'; -import type { Command } from '../builder'; +import type { SlashCommand } from '../builder'; const data = new SlashCommandBuilder() .setName('removeuserbyrole') @@ -35,7 +35,7 @@ export const removeUserByRole = async (interaction: ChatInputCommandInteraction) await interaction.editReply('Done'); }; -const command: Command = { +const command: SlashCommand = { data, execute: removeUserByRole, }; diff --git a/src/commands/powerball/index.test.ts b/src/slash-commands/powerball/index.test.ts similarity index 100% rename from src/commands/powerball/index.test.ts rename to src/slash-commands/powerball/index.test.ts diff --git a/src/commands/powerball/index.ts b/src/slash-commands/powerball/index.ts similarity index 95% rename from src/commands/powerball/index.ts rename to src/slash-commands/powerball/index.ts index 6e9e951c..1e6d44c7 100644 --- a/src/commands/powerball/index.ts +++ b/src/slash-commands/powerball/index.ts @@ -1,7 +1,7 @@ import { type ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; import { logger } from '../../utils/logger'; import { getRandomIntInclusive, getUniqueRandomIntInclusive } from '../../utils/random'; -import type { Command } from '../builder'; +import type { SlashCommand } from '../builder'; const data = new SlashCommandBuilder() .setName('powerball') @@ -46,7 +46,7 @@ export const powerball = async (interaction: ChatInputCommandInteraction) => { interaction.reply(games); }; -const command: Command = { +const command: SlashCommand = { data, execute: powerball, }; diff --git a/src/commands/quoteOfTheDay/fetchQuote.ts b/src/slash-commands/quote-of-the-day/fetch-quote.ts similarity index 100% rename from src/commands/quoteOfTheDay/fetchQuote.ts rename to src/slash-commands/quote-of-the-day/fetch-quote.ts diff --git a/src/commands/quoteOfTheDay/index.test.ts b/src/slash-commands/quote-of-the-day/index.test.ts similarity index 97% rename from src/commands/quoteOfTheDay/index.test.ts rename to src/slash-commands/quote-of-the-day/index.test.ts index 26bc8150..982844d5 100644 --- a/src/commands/quoteOfTheDay/index.test.ts +++ b/src/slash-commands/quote-of-the-day/index.test.ts @@ -5,7 +5,7 @@ import { beforeEach, describe, expect, it } from 'vitest'; import { mockDeep, mockReset } from 'vitest-mock-extended'; import { getQuoteOfTheDay } from '.'; import { server } from '../../../mocks/server'; -import { ZEN_QUOTES_URL } from './fetchQuote'; +import { ZEN_QUOTES_URL } from './fetch-quote'; const mockInteraction = mockDeep(); diff --git a/src/commands/quoteOfTheDay/index.ts b/src/slash-commands/quote-of-the-day/index.ts similarity index 90% rename from src/commands/quoteOfTheDay/index.ts rename to src/slash-commands/quote-of-the-day/index.ts index da5c8f4b..2d50def9 100644 --- a/src/commands/quoteOfTheDay/index.ts +++ b/src/slash-commands/quote-of-the-day/index.ts @@ -1,8 +1,8 @@ import { type ChatInputCommandInteraction, EmbedBuilder, SlashCommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import { logger } from '../../utils/logger'; -import type { Command } from '../builder'; -import { fetchQuote } from './fetchQuote'; +import type { SlashCommand } from '../builder'; +import { fetchQuote } from './fetch-quote'; const data = new SlashCommandBuilder().setName('qotd').setDescription('Get Quote of the Day'); @@ -35,7 +35,7 @@ export const getQuoteOfTheDay = async (interaction: ChatInputCommandInteraction) await interaction.editReply({ embeds: [embed] }); }; -const command: Command = { +const command: SlashCommand = { data, execute: getQuoteOfTheDay, }; diff --git a/src/commands/referral/generated/ozbargain-services.json b/src/slash-commands/referral/generated/ozbargain-services.json similarity index 99% rename from src/commands/referral/generated/ozbargain-services.json rename to src/slash-commands/referral/generated/ozbargain-services.json index d0d33997..077fa79a 100644 --- a/src/commands/referral/generated/ozbargain-services.json +++ b/src/slash-commands/referral/generated/ozbargain-services.json @@ -1 +1 @@ -["13 seeds","1st energy","3commas","abra","active truth","admirals","adore beauty","aeg power tools","afterpay","ahm health insurance","airalo","airbike","airbnb - airbnb host","airtax","airvpn","airwallex","alpaka","alpha-h","alternative brewing","amaysim","amazingco","amber","amber electric","american express - business explorer card","american express - centurion personal charge card","american express - essential credit card","american express - explorer credit card","american express - platinum business card","american express - platinum card","american express - platinum card 275,000 points referee offer","american express - platinum edge credit card","american express - qantas business rewards card","american express - qantas discovery card","american express - qantas premium card","american express - qantas ultimate card","american express - velocity business card","american express - velocity escape card","american express - velocity platinum card","amino z","ampol","appliances online","arcline by racv","artscow - 1. new accounts","artscow - name stamp","asian pantry","asos","athena home loan","athletic greens","aura buy invest donate","aussie broadband","aussie house sitters","aussie pharma direct","australian unity","autoguru","awardwallet","backblaze","bake (formerly cake defi)","bamboo","banggood","bano","baopals","barbell foods","beach burrito","beam","beam wallet","beauty amora","beerhug","befrugal","belong - belong (mobile)","belong - belong broadband","better world books","bill hero","billy bubbles","binance - lite - usdt","binance - standard","binary lane","bird","bitcoin.com.au","bitpanda","bitrefill","bitstamp","bizcover","black type x","blackship","block earner","blossom","bluetti australia","blys","board game master","bokksu","bondi sands","boody bamboo clothing","boost your super","boozebud","border bank","bose australia","boxcryptor - boxcryptor unlimited","brand house direct","brazilian beauty","brookfarm","brooks running","bubble tea club","bulk nutrients","bunny.net","bupa","burgertory","butterfly network","buyandship","buyee japanese proxy service","bybit","byte australia","caltex / star mart - caltex fuelpay","canningvale","canva","cardly","caremax","cariuma","cashrewards","castlery","cell care","cellar one","cellardoor.co","chargrill charlie's","chatbooks","chatime","cheeky plant co.","chefgood","chefs on wheels","chipolo","chope - chope phuket","circles.life","classpass","code camp","coinjar","coinlist","coinspot","coinstash","cointracker","cointracking","cointree crypto exchange","comgateway","coolkidz australia","core powerfoods","coupert","covau energy","cowcow - $3.99 shoptell items","cowcow - $7.99 shoptell items","cowcow - custom glasses cloths","cowcow - custom handbag mirrors","cowcow - name stamp","creative labs","crypto.com","cryptospend","cubo ai","cult beauty","cupshe","currencyfair","daniel's donuts","dashlane","dataquest","decathlon australia","deeds brewing","degoo","dental 99","dharma bums","di pacci coffee company","diamond energy","didi - didi","digital ocean","dinner twist","dinnerly","distrokid","doctors' health fund","dollar shave club - fbuy.me links","doordash","doordash - drivers/dashers only","douugh","dozen deals","dr. dough","dresden vision","drinkmate australia","drop","dropbox","duolingo","dymocks tutoring","dynadot","e-living furniture","e-pocket","easyequities","eatclub","ecoflow","econaps","elbaite","elite supplements","ellus & krue","energy locals","enphase","eskimo","esr gear","etax accountants","ethique","etoro","etsy - seller","ettitude","eubi australia","euca (proud products)","eva mattress","evee","everyday mobile from woolworths","everyday rewards","everyplate","evolve skateboards","exetel","expressvpn","eyebuydirect","ezlicence","fancraze","fantastic services","fantuan","fast cover travel insurance","fastmail","felix mobile","fever","fig & blooms","first table australia","fishme","fite","fitstop","fiverr","flexicar","flexiroam","flip","foody bag","framefox","freelancer","freeletics","french sweet","from japan","funding","furthr","future broadband","futuregolf","fuzenet internet","gami chicken & beer","garden of vegan","garden street gin club","gate.io","gdgt deals (engadget stacksocial)","gemini exchange","giffgaff","gift card exchange","gimme","glamcorner","globird energy","gocardless","gocashback","gocatch","goldfields toys & games","good pair days","goodments","goodnessme","google workspace","gozney","groupon uk","grow my money (formerly super rewards)","guzman y gomez","gwent","gym and fitness","h&m","hay","hellofresh - $115-$125 off 1st box","heritage bank - $250 gift card with loan","hey bianca","heymax","hif","hillview farms","hipcamp","hnry","hodlnaut","homeseer","honey","honey insurance","hopper","hotel tonight","hp instant ink","hqhair","humble bundle - humble choice","hummingbird","hyper karting","icebreaker","ifttt","ig group","iherb.com","independent reserve","infinicloud","ing","inglewood coffee roasters","ingogo","instarem","institchu","integrately","interactive brokers australia","ipantry","ipaymy","iri shopper panel","italki","ivacy vpn","iwallpaper / macos game studio - iwallpaper","iwoot","jamie kay","jimmy brings","joonya eco wipes","juniper","just esim hong kong","just wines","kegland","kennards self storage - kennard's self storage","kent street cellars","ker-ching!","kickback australia","kiehl's","kitsch","kiwico","klarna","klook travel","knobby","koala","kogan","koh","koinly","koogle","krisp","kucoin","kx pilates","lalal.ai","launtel","leaptel","ledger","ledn","life cykel","lila beauty","lime","linea","lingoda","linode","loaded lifting","loans.com.au","localcart","lookfantastic au","lookfantastic uk","looma's","loop earplugs","loyalty app","lskd","lucy & yak","lumin","lumo energy","luno","luxury escapes","lyka","lyka - first free box offer (for up to 5 referrals)","mac cosmetics","mad paws","madura tea","marley spoon","marriott","mashable","mask co","masterremit","mate communicate","matrix education","me bank","mealpal","mee audio","memberbuy","menulog - drivers/couriers","meta store","mexc global","minisforum","missguided australia","mixbook","mobimatter","mobvoi","modibodi","mofo smile","momentum energy","moneygram","monta","moo","moogoo","moomoo","mosh","mr. rebates","mubi","muscle diets","muscle nation","my foodie box","my muscle chef","mypaynow","myprotein, uk","myus.com","naked wines","nanoblock","naritas finance","natvia","navexa","nba top shot","nectr","need supplies","neowin","neuron mobility","news demon","nexo","nextpair","nielsen - homescan","nightowl convenience","no pong","noa home","nodeone","nomad, us","nomador","nonda","nordpass","nordvpn","normcore coffee","nourished life","novelship","numobile","nuphy australia","nuphy studio","nuraphone","oakley","okcoin","okx","olive young","on oceania pty ltd","one month","one.com - warp","onedrive","onmarket bookbuilds","orange poland","orbitremit","origin energy - origin spike","ororo","otaku mode","otter ai","oura","outschool","ovo energy","oz hair & beauty","ozsale","ozsale mobile","panda remit","park on king","parkhound","patpat","pay.com.au","payo","paysend","pd car insurance","pearler","peloton","pennytel mobile","peoplecare","pepper leaf","perifit","pet chemist","pet circle","petzyo","phoenix health fund","photobookshop","picodi australia","pikmo","pingme","piping rock","planet express","plenti (previously ratesetter)","plico","pluralsight","pocketsmith","pod & parcel","pokémon go","pokitpal","polestar","polymail","popcar","popcultcha","powerpal","powershop","presearch","private internet access","probikekit","prohashing","proton mail","proud mary coffee","pure plant protein","pure-product","purevpn","qantas insurance - health insurance","qantas insurance - qantas wellbeing app","quad lock australia","quandoo","quantfury","quidco","quietgrowth","quiksilver","quizlet","qv skincare","qwertee","raiz","rakuten","rapha","ray-ban","readwise","rebtel","receiptjar","recollect","recyclesmart","red bull mobile","red energy","redteago","reflections holiday parks","refresh valet","remarkable","remitly","rentbetter","reship.com","revolut","revolution beauty","rewardsbunny","ride on! entertainment","ritual","roamless","roberts space industries","roboform","robot my life","rocketmiles","rollie nation","rollin' insurance (previously poncho insurance)","runescape","rush gold","ry (recreate yourself)","safestyle","safewill","san churro","sans drinks","saxo markets","sayso","scratch pet food","scribd","seats.aero","secret lab chairs","selfwealth","setapp","shady rays","share with oscar","sharesies","sharesight","shein","shenzen audio","shopback au","shping","sigmaos","simple. (mortgage broker)","simsdirect","singapore airlines - krispay / kris+","singx","skillshare","skrill","skrill - btc crypto","sleeping duck","smart traveller","smile","snap send solve","sniip","socialgood","society6","sodastream","solaredge","solbari","soulara","sovol3d","spaceship","sparrow and fox","speechify","spintel","sportitude","spriggy","square","square enix - final fantasy 14","stackry","stacksocial","stake","starlink","step one","sticker mule","stockspot","stratia","student universe us","stylevana","sugarsync","sukin","sumo","sunglass hut","super obvious","superfeast","superhero","superloop","surfshark vpn","surfstitch","surveyz","swagbucks","sweat coin","swingvision","swoop broadband","swyftx crypto exchange","syfe","sync","t bar tea","taco bell","tamburlaine organic wines","tangerine telecom","tanggram","taxibox","teamm8","ted baker","tel-u","tempdrop","temple & webster","temu","tennis gear","tesla","teslafi","teslascope","tessie","the dinner ladies","the garden superstore","the iconic","the memo","the oodie","the pass loyalty app","the perfect underwear","the shade","the sippery","the whisky club","the whisky list","the wine collective","thinx","tidy me","tiger brokers","tile","tipple","tirtyl","topcashback au","topcashback uk","topcashback us","total tools","tour radar","tradingview","tripod coffee","true protein","truefire","trustedhousesitters","tyresales","tyroola","ubank","uber - drivers only","uber - riders only (uber pool)","uber carshare (formerly car next door)","uber eats","ubigi","ufodrive","ugg australia","ultra violette","unbrk","unique muscle","uniti wireless / uniti internet","unstoppable domains","unyoked","up bank","updoc","upstreet","urban company","urban plant growers","vauld","ventraip","vetsupply","viator","vic's meat","vincero watches","vinomofo","virgin active","virgin money","virgin voyages","virgo","vitable","vmp","vodafone","voip.ms","vpa australia","vultr","waggly club","waxit car care","we might be tiny","webull - deposit fund for fractional shares/vouchers reward","webull - transfer stock for trading vouchers reward","well home loans","wemoney","westfund health insurance","westpac - westpac choice account","wework","whitehat jr","who gives a crap","whoop","wiggle australia","wiggle uk","wilson parking","windscribe","wirex","wise","wolfit box","wonderbly","woolovers","workflowy","world of learning","world of warships","worldfirst","worldremit","wrapd (formerly her black book)","xe","xendpay","yak pay","yesstyle.com, hong kong","yolla calling app","yomojo","you need a budget","you plate it","youfoodz","youhodler","zavvi au","zavvi uk","zeller","zenmarket","zero co","zip pay","zipmex","zoho","zorali","zumba","zwift"] \ No newline at end of file +["13 seeds","1st energy","3commas","abra","active truth","admirals","adore beauty","aeg power tools","afterpay","ahm health insurance","airalo","airbike","airbnb - airbnb host","airtax","airvpn","airwallex","alpaka","alpha-h","alternative brewing","amaysim","amazingco","amber","amber electric","american express - business explorer card","american express - centurion personal charge card","american express - essential credit card","american express - explorer credit card","american express - platinum business card","american express - platinum card","american express - platinum card 275,000 points referee offer","american express - platinum edge credit card","american express - qantas business rewards card","american express - qantas discovery card","american express - qantas premium card","american express - qantas ultimate card","american express - velocity business card","american express - velocity escape card","american express - velocity platinum card","amino z","ampol","appliances online","arcline by racv","artscow - 1. new accounts","artscow - name stamp","asian pantry","asos","athena home loan","athletic greens","aura buy invest donate","aussie broadband","aussie house sitters","aussie pharma direct","australian unity","autoguru","awardwallet","backblaze","bake (formerly cake defi)","bamboo","banggood","bano","baopals","barbell foods","beach burrito","beam","beam wallet","beauty amora","beerhug","befrugal","belong - belong (mobile)","belong - belong broadband","better world books","bill hero","billy bubbles","binance - lite - usdt","binance - standard","binary lane","bird","bitcoin.com.au","bitpanda","bitrefill","bitstamp","bizcover","black type x","blackship","block earner","blossom","bluetti australia","blys","board game master","bokksu","bondi sands","boody bamboo clothing","boost your super","boozebud","border bank","bose australia","boxcryptor - boxcryptor unlimited","brand house direct","brazilian beauty","brookfarm","brooks running","bubble tea club","bulk nutrients","bunny.net","bupa","burgertory","butterfly network","buyandship","buyee japanese proxy service","bybit","byte australia","caltex / star mart - caltex fuelpay","canningvale","canva","cardly","caremax","cariuma","cashrewards","castlery","cell care","cellar one","cellardoor.co","chargrill charlie's","chatbooks","chatime","cheeky plant co.","chefgood","chefs on wheels","chipolo","chope - chope phuket","circles.life","classpass","code camp","coinjar","coinlist","coinspot","coinstash","cointracker","cointracking","cointree crypto exchange","comgateway","coolkidz australia","core powerfoods","coupert","covau energy","cowcow - $3.99 shoptell items","cowcow - $7.99 shoptell items","cowcow - custom glasses cloths","cowcow - custom handbag mirrors","cowcow - name stamp","creative labs","crypto.com","cryptospend","cubo ai","cult beauty","cupshe","currencyfair","daniel's donuts","dashlane","dataquest","decathlon australia","deeds brewing","degoo","dental 99","dharma bums","di pacci coffee company","diamond energy","didi - didi","digital ocean","dinner twist","dinnerly","distrokid","doctors' health fund","dollar shave club - fbuy.me links","doordash","doordash - drivers/dashers only","douugh","dozen deals","dr. dough","dresden vision","drinkmate australia","drop","dropbox","duolingo","dymocks tutoring","dynadot","e-living furniture","e-pocket","easyequities","eatclub","ecoflow","econaps","elbaite","elite supplements","ellus & krue","energy locals","enphase","eskimo","esr gear","etax accountants","ethique","etoro","etsy - seller","ettitude","eubi australia","euca (proud products)","eva mattress","evee","everyday mobile from woolworths","everyday rewards","everyplate","evolve skateboards","exetel","expressvpn","eyebuydirect","ezlicence","fancraze","fantastic services","fantuan","fast cover travel insurance","fastmail","felix mobile","fever","fig & blooms","first table australia","fishme","fite","fitstop","fiverr","flexicar","flexiroam","flip","foody bag","framefox","freelancer","freeletics","french sweet","from japan","funding","furthr","future broadband","futuregolf","fuzenet internet","gami chicken & beer","garden of vegan","garden street gin club","gate.io","gdgt deals (engadget stacksocial)","gemini exchange","giffgaff","gift card exchange","gimme","glamcorner","globird energy","gocardless","gocashback","gocatch","goldfields toys & games","good pair days","goodments","goodnessme","google workspace","gozney","groupon uk","grow my money (formerly super rewards)","guzman y gomez","gwent","gym and fitness","h&m","hay","hellofresh - $115-$125 off 1st box","heritage bank - $250 gift card with loan","hey bianca","heymax","hif","hillview farms","hipcamp","hnry","hodlnaut","homeseer","honey","honey insurance","hopper","hotel tonight","hp instant ink","hqhair","humble bundle - humble choice","hummingbird","hyper karting","icebreaker","ifttt","ig group","iherb.com","independent reserve","infinicloud","ing","inglewood coffee roasters","ingogo","instarem","institchu","integrately","interactive brokers australia","ipantry","ipaymy","iri shopper panel","italki","ivacy vpn","iwallpaper / macos game studio - iwallpaper","iwoot","jamie kay","jimmy brings","joonya eco wipes","juniper","just esim hong kong","just wines","kegland","kennards self storage - kennard's self storage","kent street cellars","ker-ching!","kickback australia","kiehl's","kitsch","kiwico","klarna","klook travel","knobby","koala","kogan","koh","koinly","koogle","krisp","kucoin","kx pilates","lalal.ai","launtel","leaptel","ledger","ledn","life cykel","lila beauty","lime","linea","lingoda","linode","loaded lifting","loans.com.au","localcart","lookfantastic au","lookfantastic uk","looma's","loop earplugs","loyalty app","lskd","lucy & yak","lumin","lumo energy","luno","luxury escapes","lyka","lyka - first free box offer (for up to 5 referrals)","mac cosmetics","mad paws","madura tea","marley spoon","marriott","mashable","mask co","masterremit","mate communicate","matrix education","me bank","mealpal","mee audio","memberbuy","menulog - drivers/couriers","meta store","mexc global","minisforum","missguided australia","mixbook","mobimatter","mobvoi","modibodi","mofo smile","momentum energy","moneygram","monta","moo","moogoo","moomoo","mosh","mr. rebates","mubi","muscle diets","muscle nation","my foodie box","my muscle chef","mypaynow","myprotein, uk","myus.com","naked wines","nanoblock","naritas finance","natvia","navexa","nba top shot","nectr","need supplies","neowin","neuron mobility","news demon","nexo","nextpair","nielsen - homescan","nightowl convenience","no pong","noa home","nodeone","nomad, us","nomador","nonda","nordpass","nordvpn","normcore coffee","nourished life","novelship","numobile","nuphy australia","nuphy studio","nuraphone","oakley","okcoin","okx","olive young","on oceania pty ltd","one month","one.com - warp","onedrive","onmarket bookbuilds","orange poland","orbitremit","origin energy - origin spike","ororo","otaku mode","otter ai","oura","outschool","ovo energy","oz hair & beauty","ozsale","ozsale mobile","panda remit","park on king","parkhound","patpat","pay.com.au","payo","paysend","pd car insurance","pearler","peloton","pennytel mobile","peoplecare","pepper leaf","perifit","pet chemist","pet circle","petzyo","phoenix health fund","photobookshop","picodi australia","pikmo","pingme","piping rock","planet express","plenti (previously ratesetter)","plico","pluralsight","pocketsmith","pod & parcel","pokémon go","pokitpal","polestar","polymail","popcar","popcultcha","powerpal","powershop","presearch","private internet access","probikekit","prohashing","proton mail","proud mary coffee","pure plant protein","pure-product","purevpn","qantas insurance - health insurance","qantas insurance - qantas wellbeing app","quad lock australia","quandoo","quantfury","quidco","quietgrowth","quiksilver","quizlet","qv skincare","qwertee","raiz","rakuten","rapha","ray-ban","readwise","rebtel","receiptjar","recollect","recyclesmart","red bull mobile","red energy","redteago","reflections holiday parks","refresh valet","remarkable","remitly","rentbetter","reship.com","revolut","revolution beauty","rewardsbunny","ride on! entertainment","ritual","roamless","roberts space industries","roboform","robot my life","rocketmiles","rollie nation","rollin' insurance (previously poncho insurance)","runescape","rush gold","ry (recreate yourself)","safestyle","safewill","san churro","sans drinks","saxo markets","sayso","scratch pet food","scribd","seats.aero","secret lab chairs","selfwealth","setapp","shady rays","share with oscar","sharesies","sharesight","shein","shenzen audio","shopback au","shping","sigmaos","simple. (mortgage broker)","simsdirect","singapore airlines - krispay / kris+","singx","skillshare","skrill","skrill - btc crypto","sleeping duck","smart traveller","smile","snap send solve","sniip","socialgood","society6","sodastream","solaredge","solbari","soulara","sovol3d","spaceship","sparrow and fox","speechify","spintel","sportitude","spriggy","square","square enix - final fantasy 14","stackry","stacksocial","stake","starlink","step one","sticker mule","stockspot","stratia","student universe us","stylevana","sugarsync","sukin","sumo","sunglass hut","super obvious","superfeast","superhero","superloop","surfshark vpn","surfstitch","surveyz","swagbucks","sweat coin","swingvision","swoop broadband","swyftx crypto exchange","syfe","sync","t bar tea","taco bell","tamburlaine organic wines","tangerine telecom","tanggram","taxibox","teamm8","ted baker","tel-u","tempdrop","temple & webster","temu","tennis gear","tesla","teslafi","teslascope","tessie","the dinner ladies","the garden superstore","the iconic","the memo","the oodie","the pass loyalty app","the perfect underwear","the shade","the sippery","the whisky club","the whisky list","the wine collective","thinx","tidy me","tiger brokers","tile","tipple","tirtyl","topcashback au","topcashback uk","topcashback us","total tools","tour radar","tradingview","tripod coffee","true protein","truefire","trustedhousesitters","tyresales","tyroola","ubank","uber - drivers only","uber - riders only (uber pool)","uber carshare (formerly car next door)","uber eats","ubigi","ufodrive","ugg australia","ultra violette","unbrk","unique muscle","uniti wireless / uniti internet","unstoppable domains","unyoked","up bank","updoc","upstreet","urban company","urban plant growers","vauld","ventraip","vetsupply","viator","vic's meat","vincero watches","vinomofo","virgin active","virgin money","virgin voyages","virgo","vitable","vmp","vodafone","voip.ms","vpa australia","vultr","waggly club","waxit car care","we might be tiny","webull - deposit fund for fractional shares/vouchers reward","webull - transfer stock for trading vouchers reward","well home loans","wemoney","westfund health insurance","westpac - westpac choice account","wework","whitehat jr","who gives a crap","whoop","wiggle australia","wiggle uk","wilson parking","windscribe","wirex","wise","wolfit box","wonderbly","woolovers","workflowy","world of learning","world of warships","worldfirst","worldremit","wrapd (formerly her black book)","xe","xendpay","yak pay","yesstyle.com, hong kong","yolla calling app","yomojo","you need a budget","you plate it","youfoodz","youhodler","zavvi au","zavvi uk","zeller","zenmarket","zero co","zip pay","zipmex","zoho","zorali","zumba","zwift"] diff --git a/src/commands/referral/index.ts b/src/slash-commands/referral/index.ts similarity index 78% rename from src/commands/referral/index.ts rename to src/slash-commands/referral/index.ts index 7b8cf3d4..a29d95e0 100644 --- a/src/commands/referral/index.ts +++ b/src/slash-commands/referral/index.ts @@ -1,8 +1,8 @@ import { SlashCommandBuilder } from 'discord.js'; -import type { AutocompleteHandler, Command, CommandHandler } from '../builder'; +import type { AutocompleteHandler, SlashCommand, SlashCommandHandler } from '../builder'; -import * as referralNew from './referralNew'; -import * as referralRandom from './referralRandom'; +import * as referralNew from './referral-new'; +import * as referralRandom from './referral-random'; // referral new $SERVICE_NAME $LINK/CODE $EXPIRY_DATE(DD/MM/YYYY) // referral random $SERVICE_NAME @@ -24,13 +24,13 @@ const autocomplete: AutocompleteHandler = async (interaction) => { return subcommand?.autocomplete?.(interaction); }; -const execute: CommandHandler = async (interaction) => { +const execute: SlashCommandHandler = async (interaction) => { const requestedSubcommand = interaction.options.getSubcommand(true); const subcommand = subcommands.find(({ data: { name } }) => name === requestedSubcommand); return subcommand?.execute?.(interaction); }; -const command: Command = { +const command: SlashCommand = { data: getData(), execute, autocomplete, diff --git a/src/commands/referral/parseDate.ts b/src/slash-commands/referral/parse-date.ts similarity index 100% rename from src/commands/referral/parseDate.ts rename to src/slash-commands/referral/parse-date.ts diff --git a/src/commands/referral/referralNew.test.ts b/src/slash-commands/referral/referral-new.test.ts similarity index 99% rename from src/commands/referral/referralNew.test.ts rename to src/slash-commands/referral/referral-new.test.ts index 1bd735bc..58bd0281 100644 --- a/src/commands/referral/referralNew.test.ts +++ b/src/slash-commands/referral/referral-new.test.ts @@ -3,7 +3,7 @@ import type { AutocompleteInteraction, ChatInputCommandInteraction, Guild } from import { beforeEach, describe, expect, it, vi } from 'vitest'; import { captor, mockDeep, mockReset } from 'vitest-mock-extended'; import { getOrCreateUser } from '../reputation/utils'; -import { DEFAULT_EXPIRY_DAYS_FROM_NOW, autocomplete, execute } from './referralNew'; +import { DEFAULT_EXPIRY_DAYS_FROM_NOW, autocomplete, execute } from './referral-new'; import { services } from './services'; import { type CreateReferralInput, createReferralCode, findExistingReferralCode } from './utils'; diff --git a/src/commands/referral/referralNew.ts b/src/slash-commands/referral/referral-new.ts similarity index 95% rename from src/commands/referral/referralNew.ts rename to src/slash-commands/referral/referral-new.ts index 6a69bc00..37d4cff0 100644 --- a/src/commands/referral/referralNew.ts +++ b/src/slash-commands/referral/referral-new.ts @@ -2,8 +2,8 @@ import { addDays, getUnixTime } from 'date-fns'; import { type Guild, SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import { logger } from '../../utils/logger'; -import type { AutocompleteHandler, CommandHandler } from '../builder'; -import { parseDate } from './parseDate'; +import type { AutocompleteHandler, SlashCommandHandler } from '../builder'; +import { parseDate } from './parse-date'; import { searchServices, services } from './services'; import { createReferralCode, findExistingReferralCode } from './utils'; @@ -30,7 +30,7 @@ export const autocomplete: AutocompleteHandler = async (interaction) => { interaction.respond(options); }; -export const execute: CommandHandler = async (interaction) => { +export const execute: SlashCommandHandler = async (interaction) => { const code = interaction.options.getString('link_or_code', true); const service = interaction.options.getString('service', true).toLowerCase(); logger.info(`[referral-new]: Adding new referral code for ${service} with code/link: ${code}`); diff --git a/src/commands/referral/referralRandom.test.ts b/src/slash-commands/referral/referral-random.test.ts similarity index 96% rename from src/commands/referral/referralRandom.test.ts rename to src/slash-commands/referral/referral-random.test.ts index d9f436cd..16d9fa00 100644 --- a/src/commands/referral/referralRandom.test.ts +++ b/src/slash-commands/referral/referral-random.test.ts @@ -1,14 +1,9 @@ -import { PrismaClient } from '@prisma/client'; import { type AutocompleteInteraction, type ChatInputCommandInteraction, Collection, type GuildMember } from 'discord.js'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { captor, mockDeep, mockReset } from 'vitest-mock-extended'; -import { getDbClient } from '../../clients'; -import { autocomplete, execute } from './referralRandom'; +import { autocomplete, execute } from './referral-random'; import { type GetAllReferralCodesForServiceInput, getAllReferralCodesForService } from './utils'; -vi.mock('../../clients'); -const mockGetDbClient = vi.mocked(getDbClient); - vi.mock('./utils'); const mockGetAllReferralCodesForService = vi.mocked(getAllReferralCodesForService); diff --git a/src/commands/referral/referralRandom.ts b/src/slash-commands/referral/referral-random.ts similarity index 93% rename from src/commands/referral/referralRandom.ts rename to src/slash-commands/referral/referral-random.ts index b5077ab7..3decea6d 100644 --- a/src/commands/referral/referralRandom.ts +++ b/src/slash-commands/referral/referral-random.ts @@ -2,7 +2,7 @@ import { type Guild, SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import { logger } from '../../utils/logger'; import { getRandomIntInclusive } from '../../utils/random'; -import type { AutocompleteHandler, CommandHandler } from '../builder'; +import type { AutocompleteHandler, SlashCommandHandler } from '../builder'; import { searchServices } from './services'; import { getAllReferralCodesForService } from './utils'; @@ -20,7 +20,7 @@ export const autocomplete: AutocompleteHandler = async (interaction) => { await interaction.respond(options); }; -export const execute: CommandHandler = async (interaction) => { +export const execute: SlashCommandHandler = async (interaction) => { const service = interaction.options.getString('service', true)?.trim().toLowerCase() ?? ''; const guildId = (interaction.guild as Guild).id; diff --git a/src/commands/referral/services.test.ts b/src/slash-commands/referral/services.test.ts similarity index 100% rename from src/commands/referral/services.test.ts rename to src/slash-commands/referral/services.test.ts diff --git a/src/commands/referral/services.ts b/src/slash-commands/referral/services.ts similarity index 100% rename from src/commands/referral/services.ts rename to src/slash-commands/referral/services.ts diff --git a/src/commands/referral/utils.ts b/src/slash-commands/referral/utils.ts similarity index 84% rename from src/commands/referral/utils.ts rename to src/slash-commands/referral/utils.ts index 296cda42..c69de7de 100644 --- a/src/commands/referral/utils.ts +++ b/src/slash-commands/referral/utils.ts @@ -54,3 +54,15 @@ export const getAllReferralCodesForService = async ({ guildId, service }: GetAll }, }); }; + +export const cleanupExpiredCode = async () => { + const db = getDbClient(); + const currentDate = new Date(); + return db.referralCode.deleteMany({ + where: { + expiry_date: { + lt: currentDate, + }, + }, + }); +}; diff --git a/src/commands/reminder/index.ts b/src/slash-commands/reminder/index.ts similarity index 92% rename from src/commands/reminder/index.ts rename to src/slash-commands/reminder/index.ts index ade02eae..6101929e 100644 --- a/src/commands/reminder/index.ts +++ b/src/slash-commands/reminder/index.ts @@ -1,5 +1,5 @@ import { type ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; -import type { Command } from '../builder'; +import type { SlashCommand } from '../builder'; import list from './list'; import remindDuration from './remind-duration'; import remindOnDate from './remind-on-date'; @@ -23,7 +23,7 @@ const execute = async (interaction: ChatInputCommandInteraction) => { return subcommand?.execute(interaction); }; -const command: Command = { +const command: SlashCommand = { data, execute, }; diff --git a/src/commands/reminder/list.test.ts b/src/slash-commands/reminder/list.test.ts similarity index 100% rename from src/commands/reminder/list.test.ts rename to src/slash-commands/reminder/list.test.ts diff --git a/src/commands/reminder/list.ts b/src/slash-commands/reminder/list.ts similarity index 89% rename from src/commands/reminder/list.ts rename to src/slash-commands/reminder/list.ts index 6d7af01d..d43058b3 100644 --- a/src/commands/reminder/list.ts +++ b/src/slash-commands/reminder/list.ts @@ -1,7 +1,7 @@ import type { Reminder } from '@prisma/client'; import { SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; -import type { CommandHandler, Subcommand } from '../builder'; +import type { SlashCommandHandler, Subcommand } from '../builder'; import { getUserReminders } from './utils'; export const data = new SlashCommandSubcommandBuilder().setName('list').setDescription('Get a list of your reminders'); @@ -13,7 +13,7 @@ const formatReminders = (reminders: Reminder[]) => { return `${reminderList}`; }; -export const execute: CommandHandler = async (interaction) => { +export const execute: SlashCommandHandler = async (interaction) => { const { user } = interaction.member!; const guildId = interaction.guildId!; const op = await Result.safe(getUserReminders(user.id, guildId)); diff --git a/src/commands/reminder/remind-duration.test.ts b/src/slash-commands/reminder/remind-duration.test.ts similarity index 100% rename from src/commands/reminder/remind-duration.test.ts rename to src/slash-commands/reminder/remind-duration.test.ts diff --git a/src/commands/reminder/remind-duration.ts b/src/slash-commands/reminder/remind-duration.ts similarity index 92% rename from src/commands/reminder/remind-duration.ts rename to src/slash-commands/reminder/remind-duration.ts index 44148116..2e1ea353 100644 --- a/src/commands/reminder/remind-duration.ts +++ b/src/slash-commands/reminder/remind-duration.ts @@ -2,7 +2,7 @@ import { addSeconds, getUnixTime } from 'date-fns'; import { SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import parseDuration from 'parse-duration'; -import type { CommandHandler, Subcommand } from '../builder'; +import type { SlashCommandHandler, Subcommand } from '../builder'; import { saveReminder } from './utils'; export const data = new SlashCommandSubcommandBuilder() @@ -11,7 +11,7 @@ export const data = new SlashCommandSubcommandBuilder() .addStringOption((option) => option.setName('duration').setDescription('The time from now you wanted to be reminded. e.g. 1hour 20minutes').setRequired(true)) .addStringOption((option) => option.setName('message').setDescription('The message to get reminded for').setRequired(true)); -export const execute: CommandHandler = async (interaction) => { +export const execute: SlashCommandHandler = async (interaction) => { const { user } = interaction.member!; const guildId = interaction.guildId!; const message = interaction.options.getString('message', true); diff --git a/src/commands/reminder/remind-on-date.test.ts b/src/slash-commands/reminder/remind-on-date.test.ts similarity index 100% rename from src/commands/reminder/remind-on-date.test.ts rename to src/slash-commands/reminder/remind-on-date.test.ts diff --git a/src/commands/reminder/remind-on-date.ts b/src/slash-commands/reminder/remind-on-date.ts similarity index 90% rename from src/commands/reminder/remind-on-date.ts rename to src/slash-commands/reminder/remind-on-date.ts index db96f5b9..01796714 100644 --- a/src/commands/reminder/remind-on-date.ts +++ b/src/slash-commands/reminder/remind-on-date.ts @@ -1,7 +1,7 @@ import { SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import { convertDateToEpoch } from '../../utils/date'; -import type { CommandHandler, Subcommand } from '../builder'; +import type { SlashCommandHandler, Subcommand } from '../builder'; import { saveReminder } from './utils'; export const data = new SlashCommandSubcommandBuilder() @@ -10,7 +10,7 @@ export const data = new SlashCommandSubcommandBuilder() .addStringOption((option) => option.setName('date').setDescription('The date to get a reminder on. Follow this format: DD/MM/YYYY hh:mm').setRequired(true)) .addStringOption((option) => option.setName('message').setDescription('The message to get reminded for').setRequired(true)); -export const execute: CommandHandler = async (interaction) => { +export const execute: SlashCommandHandler = async (interaction) => { const { user } = interaction.member!; const guildId = interaction.guildId!; const message = interaction.options.getString('message', true); diff --git a/src/commands/reminder/remove.test.ts b/src/slash-commands/reminder/remove.test.ts similarity index 100% rename from src/commands/reminder/remove.test.ts rename to src/slash-commands/reminder/remove.test.ts diff --git a/src/commands/reminder/remove.ts b/src/slash-commands/reminder/remove.ts similarity index 87% rename from src/commands/reminder/remove.ts rename to src/slash-commands/reminder/remove.ts index 030f6263..8a16acdb 100644 --- a/src/commands/reminder/remove.ts +++ b/src/slash-commands/reminder/remove.ts @@ -1,6 +1,6 @@ import { SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; -import type { CommandHandler, Subcommand } from '../builder'; +import type { SlashCommandHandler, Subcommand } from '../builder'; import { removeReminder } from './utils'; export const data = new SlashCommandSubcommandBuilder() @@ -8,7 +8,7 @@ export const data = new SlashCommandSubcommandBuilder() .setDescription('Delete a reminder') .addStringOption((option) => option.setName('id').setDescription('Reminder ID. This must be provided').setRequired(true)); -export const execute: CommandHandler = async (interaction) => { +export const execute: SlashCommandHandler = async (interaction) => { const { user } = interaction.member!; const guildId = interaction.guildId!; const reminderId = interaction.options.getString('id', true); diff --git a/src/commands/reminder/update.test.ts b/src/slash-commands/reminder/update.test.ts similarity index 100% rename from src/commands/reminder/update.test.ts rename to src/slash-commands/reminder/update.test.ts diff --git a/src/commands/reminder/update.ts b/src/slash-commands/reminder/update.ts similarity index 92% rename from src/commands/reminder/update.ts rename to src/slash-commands/reminder/update.ts index cd6d343a..5bdb9d37 100644 --- a/src/commands/reminder/update.ts +++ b/src/slash-commands/reminder/update.ts @@ -1,7 +1,7 @@ import { SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import { convertDateToEpoch } from '../../utils/date'; -import type { CommandHandler, Subcommand } from '../builder'; +import type { SlashCommandHandler, Subcommand } from '../builder'; import { updateReminder } from './utils'; export const data = new SlashCommandSubcommandBuilder() @@ -11,7 +11,7 @@ export const data = new SlashCommandSubcommandBuilder() .addStringOption((option) => option.setName('date').setDescription('The date to get a reminder on. Follow this format: DD/MM/YYYY hh:mm').setRequired(false)) .addStringOption((option) => option.setName('message').setDescription('The message to get reminded for').setRequired(false)); -export const execute: CommandHandler = async (interaction) => { +export const execute: SlashCommandHandler = async (interaction) => { const { user } = interaction.member!; const guildId = interaction.guildId!; const reminderId = interaction.options.getString('id', true); diff --git a/src/commands/reminder/utils.ts b/src/slash-commands/reminder/utils.ts similarity index 100% rename from src/commands/reminder/utils.ts rename to src/slash-commands/reminder/utils.ts diff --git a/src/commands/reputation/checkReputation.test.ts b/src/slash-commands/reputation/check-reputation.test.ts similarity index 93% rename from src/commands/reputation/checkReputation.test.ts rename to src/slash-commands/reputation/check-reputation.test.ts index 889e2580..694afa17 100644 --- a/src/commands/reputation/checkReputation.test.ts +++ b/src/slash-commands/reputation/check-reputation.test.ts @@ -1,7 +1,7 @@ import type { ChatInputCommandInteraction } from 'discord.js'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { mockDeep, mockReset } from 'vitest-mock-extended'; -import { checkReputation } from './checkReputation'; +import { checkReputation } from './check-reputation'; import { getOrCreateUser } from './utils'; vi.mock('./utils'); diff --git a/src/commands/reputation/checkReputation.ts b/src/slash-commands/reputation/check-reputation.ts similarity index 100% rename from src/commands/reputation/checkReputation.ts rename to src/slash-commands/reputation/check-reputation.ts diff --git a/src/commands/reputation/giveReputation.test.ts b/src/slash-commands/reputation/give-reputation.test.ts similarity index 98% rename from src/commands/reputation/giveReputation.test.ts rename to src/slash-commands/reputation/give-reputation.test.ts index 12da8c09..b22a8057 100644 --- a/src/commands/reputation/giveReputation.test.ts +++ b/src/slash-commands/reputation/give-reputation.test.ts @@ -1,7 +1,7 @@ import { type ChatInputCommandInteraction, Collection, type Message, type User } from 'discord.js'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { mockDeep, mockReset } from 'vitest-mock-extended'; -import { giveRepSlashCommand, thankUserInMessage } from './giveReputation'; +import { giveRepSlashCommand, thankUserInMessage } from './give-reputation'; import { getOrCreateUser, updateRep } from './utils'; vi.mock('./utils'); diff --git a/src/commands/reputation/giveReputation.ts b/src/slash-commands/reputation/give-reputation.ts similarity index 100% rename from src/commands/reputation/giveReputation.ts rename to src/slash-commands/reputation/give-reputation.ts diff --git a/src/commands/reputation/index.ts b/src/slash-commands/reputation/index.ts similarity index 73% rename from src/commands/reputation/index.ts rename to src/slash-commands/reputation/index.ts index d520d830..f9ae0c7d 100644 --- a/src/commands/reputation/index.ts +++ b/src/slash-commands/reputation/index.ts @@ -1,10 +1,10 @@ import { type ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; -import type { Command } from '../builder'; -import checkRep from './checkReputation'; -import giveRep from './giveReputation'; +import type { SlashCommand } from '../builder'; +import checkRep from './check-reputation'; +import giveRep from './give-reputation'; import leaderboard from './leaderboard'; -import setRep from './setReputation'; -import takeRep from './takeReputation'; +import setRep from './set-reputation'; +import takeRep from './take-reputation'; const data = new SlashCommandBuilder() .setName('rep') @@ -24,11 +24,9 @@ const execute = async (interaction: ChatInputCommandInteraction) => { return subcommand?.execute(interaction); }; -const command: Command = { +const command: SlashCommand = { data, execute, }; export default command; - -export { thankUserInMessage } from './giveReputation'; diff --git a/src/commands/reputation/leaderboard.test.ts b/src/slash-commands/reputation/leaderboard.test.ts similarity index 100% rename from src/commands/reputation/leaderboard.test.ts rename to src/slash-commands/reputation/leaderboard.test.ts diff --git a/src/commands/reputation/leaderboard.ts b/src/slash-commands/reputation/leaderboard.ts similarity index 100% rename from src/commands/reputation/leaderboard.ts rename to src/slash-commands/reputation/leaderboard.ts diff --git a/src/commands/reputation/setReputation.test.ts b/src/slash-commands/reputation/set-reputation.test.ts similarity index 97% rename from src/commands/reputation/setReputation.test.ts rename to src/slash-commands/reputation/set-reputation.test.ts index a3f0f2be..2aa65779 100644 --- a/src/commands/reputation/setReputation.test.ts +++ b/src/slash-commands/reputation/set-reputation.test.ts @@ -2,7 +2,7 @@ import type { ChatInputCommandInteraction, GuildMember, User } from 'discord.js' import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; import { mockDeep, mockReset } from 'vitest-mock-extended'; import { isAdmin } from '../../utils/permission'; -import { setReputation } from './setReputation'; +import { setReputation } from './set-reputation'; import { getOrCreateUser, updateRep } from './utils'; vi.mock('./utils'); diff --git a/src/commands/reputation/setReputation.ts b/src/slash-commands/reputation/set-reputation.ts similarity index 100% rename from src/commands/reputation/setReputation.ts rename to src/slash-commands/reputation/set-reputation.ts diff --git a/src/commands/reputation/takeReputation.test.ts b/src/slash-commands/reputation/take-reputation.test.ts similarity index 98% rename from src/commands/reputation/takeReputation.test.ts rename to src/slash-commands/reputation/take-reputation.test.ts index d3a9a02c..4d962eab 100644 --- a/src/commands/reputation/takeReputation.test.ts +++ b/src/slash-commands/reputation/take-reputation.test.ts @@ -2,7 +2,7 @@ import type { ChatInputCommandInteraction, GuildMember, User } from 'discord.js' import { beforeEach, describe, expect, it, vi } from 'vitest'; import { mockDeep, mockReset } from 'vitest-mock-extended'; import { isAdmin } from '../../utils/permission'; -import { takeReputation } from './takeReputation'; +import { takeReputation } from './take-reputation'; import { getOrCreateUser, updateRep } from './utils'; vi.mock('./utils'); diff --git a/src/commands/reputation/takeReputation.ts b/src/slash-commands/reputation/take-reputation.ts similarity index 100% rename from src/commands/reputation/takeReputation.ts rename to src/slash-commands/reputation/take-reputation.ts diff --git a/src/commands/reputation/utils.ts b/src/slash-commands/reputation/utils.ts similarity index 100% rename from src/commands/reputation/utils.ts rename to src/slash-commands/reputation/utils.ts diff --git a/src/commands/serverSettings/index.ts b/src/slash-commands/server-settings/index.ts similarity index 83% rename from src/commands/serverSettings/index.ts rename to src/slash-commands/server-settings/index.ts index 8c2d6d84..9adc7b17 100644 --- a/src/commands/serverSettings/index.ts +++ b/src/slash-commands/server-settings/index.ts @@ -1,13 +1,13 @@ import { type GuildMember, SlashCommandBuilder } from 'discord.js'; import { isAdmin, isModerator } from '../../utils/permission'; -import type { Command, CommandHandler } from '../builder'; +import type { SlashCommand, SlashCommandHandler } from '../builder'; import setReminderChannel from './set-reminder-channel'; const data = new SlashCommandBuilder().setName('server-settings').setDescription('ADMIN ONLY COMMAND. Server Settings.').addSubcommand(setReminderChannel.data); const subcommands = [setReminderChannel]; -const execute: CommandHandler = async (interaction) => { +const execute: SlashCommandHandler = async (interaction) => { const member = interaction.member as GuildMember; if (!isAdmin(member) && !isModerator(member)) { await interaction.reply("You don't have enough permission to run this command."); @@ -19,7 +19,7 @@ const execute: CommandHandler = async (interaction) => { return subcommand?.execute(interaction); }; -const command: Command = { +const command: SlashCommand = { data, execute, }; diff --git a/src/commands/serverSettings/set-reminder-channel.test.ts b/src/slash-commands/server-settings/set-reminder-channel.test.ts similarity index 100% rename from src/commands/serverSettings/set-reminder-channel.test.ts rename to src/slash-commands/server-settings/set-reminder-channel.test.ts diff --git a/src/commands/serverSettings/set-reminder-channel.ts b/src/slash-commands/server-settings/set-reminder-channel.ts similarity index 91% rename from src/commands/serverSettings/set-reminder-channel.ts rename to src/slash-commands/server-settings/set-reminder-channel.ts index ec939fb5..f4b1aa9f 100644 --- a/src/commands/serverSettings/set-reminder-channel.ts +++ b/src/slash-commands/server-settings/set-reminder-channel.ts @@ -1,7 +1,7 @@ import { SlashCommandSubcommandBuilder } from 'discord.js'; import { Result } from 'oxide.ts'; import { logger } from '../../utils/logger'; -import type { CommandHandler, Subcommand } from '../builder'; +import type { SlashCommandHandler, Subcommand } from '../builder'; import { setReminderChannel } from './utils'; export const data = new SlashCommandSubcommandBuilder() @@ -9,7 +9,7 @@ export const data = new SlashCommandSubcommandBuilder() .setDescription('ADMIN COMMAND. Set channel to send reminder messages to.') .addChannelOption((option) => option.setName('channel').setDescription('channel to send reminder messages to').setRequired(true)); -export const execute: CommandHandler = async (interaction) => { +export const execute: SlashCommandHandler = async (interaction) => { const guildId = interaction.guildId!; const channel = interaction.options.getChannel('channel', true); logger.info(`[set-reminder-channel]: ${interaction.member!.user.username} is setting reminder channel to ${channel.name}`); diff --git a/src/commands/serverSettings/utils.ts b/src/slash-commands/server-settings/utils.ts similarity index 100% rename from src/commands/serverSettings/utils.ts rename to src/slash-commands/server-settings/utils.ts diff --git a/src/commands/weather/fetchWeather.ts b/src/slash-commands/weather/fetch-weather.ts similarity index 100% rename from src/commands/weather/fetchWeather.ts rename to src/slash-commands/weather/fetch-weather.ts diff --git a/src/commands/weather/index.test.ts b/src/slash-commands/weather/index.test.ts similarity index 98% rename from src/commands/weather/index.test.ts rename to src/slash-commands/weather/index.test.ts index 72a1c819..b907c3c0 100644 --- a/src/commands/weather/index.test.ts +++ b/src/slash-commands/weather/index.test.ts @@ -5,7 +5,7 @@ import { beforeEach, describe, expect, it } from 'vitest'; import { mockDeep, mockReset } from 'vitest-mock-extended'; import { DEFAULT_LOCATION, weather } from '.'; import { server } from '../../../mocks/server'; -import { WEATHER_URL } from './fetchWeather'; +import { WEATHER_URL } from './fetch-weather'; const mockWeatherMessage = faker.lorem.words(10); diff --git a/src/commands/weather/index.ts b/src/slash-commands/weather/index.ts similarity index 91% rename from src/commands/weather/index.ts rename to src/slash-commands/weather/index.ts index 2d3772ec..8da1bc6d 100644 --- a/src/commands/weather/index.ts +++ b/src/slash-commands/weather/index.ts @@ -2,8 +2,8 @@ import { type ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.j import { Result } from 'oxide.ts'; import { isBlank } from '../../utils/is-blank'; import { logger } from '../../utils/logger'; -import type { Command } from '../builder'; -import { fetchWeather } from './fetchWeather'; +import type { SlashCommand } from '../builder'; +import { fetchWeather } from './fetch-weather'; export const DEFAULT_LOCATION = 'Brisbane'; @@ -33,7 +33,7 @@ export const weather = async (interaction: ChatInputCommandInteraction) => { await interaction.editReply(`\`\`\`\n${weatherData.unwrap()}\n\`\`\``); }; -const command: Command = { +const command: SlashCommand = { data, execute: weather, }; diff --git a/vitest.config.mts b/vitest.config.mts index 9bb00146..7553aae9 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -9,7 +9,7 @@ export default defineConfig({ provider: 'v8', clean: true, include: ['src/**/*.ts'], - exclude: ['src/utils/random.*', 'src/config.ts', 'src/deploy-command.ts', 'src/clients/**.ts', 'src/commands/**/index.ts', 'src/commands/**/utils.ts'], + exclude: ['src/utils/random.*', 'src/config.ts', 'src/deploy-command.ts', 'src/clients/**.ts', 'src/*-commands/index.ts', 'src/*-commands/**/utils.ts'], }, clearMocks: true, setupFiles: ['./vitest.setup.ts'],