feat(bots/discord): add source

This commit is contained in:
PalmDevs
2024-03-28 21:52:23 +07:00
parent b3b7723b4f
commit f9d50a0a6b
30 changed files with 1482 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
import type { SlashCommandBuilder } from '@discordjs/builders'
import type { ChatInputCommandInteraction } from 'discord.js'
// Temporary system
export type Command = {
data: ReturnType<SlashCommandBuilder['toJSON']>
// The function has to return void or Promise<void>
// because TS may complain about some code paths not returning a value
/**
* The function to execute when this command is triggered
* @param interaction The interaction that triggered this command
*/
execute: (context: typeof import('../context'), interaction: ChatInputCommandInteraction) => Promise<void> | void
memberRequirements?: {
/**
* The mode to use when checking for requirements.
* - `all` means that the user needs meet all requirements specified.
* - `any` means that the user needs to meet any of the requirements specified.
*
* @default "all"
*/
mode?: 'all' | 'any'
/**
* The permissions required to use this command (in BitFields).
* For safety reasons, this is set to `-1n` and only bot owners can use this command unless explicitly specified.
*
* - **0n** means that everyone can use this command.
* - **-1n** means that only bot owners can use this command.
* @default -1n
*/
permissions?: bigint
/**
* The roles required to use this command.
* By default, this is set to `[]`.
*/
roles?: string[]
}
/**
* Whether this command can only be used by bot owners.
* For safety reasons, this is set to `true` and only bot owners can use this command unless explicitly specified.
* @default true
*/
ownerOnly?: boolean
/**
* Whether to register this command as a global slash command.
* For safety reasons, this is set to `false` and commands will be registered in allowed guilds only.
* @default false
*/
global?: boolean
}

View File

@@ -0,0 +1,54 @@
import { PermissionFlagsBits, SlashCommandBuilder, type TextBasedChannel } from 'discord.js'
import type { Command } from '.'
export default {
data: new SlashCommandBuilder()
.setName('reply')
.setDescription('Send a message as the bot')
.addStringOption(option => option.setName('message').setDescription('The message to send').setRequired(true))
.addStringOption(option =>
option
.setName('reference')
.setDescription('The message ID to reply to (use `latest` to reply to the latest message)')
.setRequired(false),
)
.toJSON(),
memberRequirements: {
mode: 'all',
roles: ['955220417969262612', '973886585294704640'],
permissions: PermissionFlagsBits.ManageMessages,
},
global: false,
async execute({ logger }, interaction) {
const msg = interaction.options.getString('message', true)
const ref = interaction.options.getString('reference')
const resolvedRef = ref?.startsWith('latest')
? (await interaction.channel?.messages.fetch({ limit: 1 }))?.at(0)?.id
: ref
try {
const channel = (await interaction.guild!.channels.fetch(interaction.channelId)) as TextBasedChannel | null
if (!channel) throw new Error('Channel not found (or not cached)')
await channel.send({
content: msg,
reply: {
messageReference: resolvedRef!,
failIfNotExists: true,
},
})
logger.warn(`User ${interaction.user.tag} made the bot say: ${msg}`)
await interaction.reply({
content: 'OK!',
ephemeral: true,
})
} catch (e) {
await interaction.reply({})
}
},
} satisfies Command

View File

@@ -0,0 +1,28 @@
import { SlashCommandBuilder } from 'discord.js'
import type { Command } from '.'
export default {
data: new SlashCommandBuilder().setName('stop').setDescription('Stops the bot').toJSON(),
ownerOnly: true,
global: true,
async execute({ api, logger }, interaction) {
api.isStopping = true
logger.fatal('Stopping bot...')
await interaction.reply({
content: 'Stopping... (I will go offline once done)',
ephemeral: true,
})
api.client.disconnect()
logger.warn('Disconnected from API')
await interaction.client.destroy()
logger.warn('Disconnected from Discord API')
logger.info(`Bot stopped, requested by ${interaction.user.id}`)
process.exit(0)
},
} satisfies Command