mirror of
https://github.com/ReVanced/revanced-bots.git
synced 2026-01-29 14:11:02 +00:00
feat(bots/discord): framework changes and new features
- Migrated to a new command framework which looks better and works better - Fixed commands not being bundled correctly - Added message (prefix) commands with argument validation - Added a new CommandErrorType, for invalid arguments - `/eval` is now a bit safer - Corrected colors for the coinflip embed - `/stop` now works even when the bot is not connected to the API
This commit is contained in:
@@ -1,32 +1,37 @@
|
||||
import { EmbedBuilder } from 'discord.js'
|
||||
|
||||
import Command from '$/classes/Command'
|
||||
import { applyCommonEmbedStyles } from '$/utils/discord/embeds'
|
||||
|
||||
import { EmbedBuilder, SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import type { Command } from '../types'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder().setName('coinflip').setDescription('Do a coinflip!').setDMPermission(true).toJSON(),
|
||||
export default new Command({
|
||||
name: 'coinflip',
|
||||
description: 'Do a coinflip!',
|
||||
global: true,
|
||||
|
||||
async execute(_, interaction) {
|
||||
requirements: {
|
||||
defaultCondition: 'pass',
|
||||
},
|
||||
allowMessageCommand: true,
|
||||
async execute(_, trigger) {
|
||||
const result = Math.random() < 0.5 ? ('heads' as const) : ('tails' as const)
|
||||
const embed = applyCommonEmbedStyles(new EmbedBuilder().setTitle('Flipping... 🪙'), true, false, false)
|
||||
const embed = applyCommonEmbedStyles(new EmbedBuilder().setTitle('Flipping... 🪙'), false, false, true)
|
||||
|
||||
await interaction.reply({
|
||||
embeds: [embed.toJSON()],
|
||||
})
|
||||
const reply = await trigger
|
||||
.reply({
|
||||
embeds: [embed.toJSON()],
|
||||
})
|
||||
.then(it => it.fetch())
|
||||
|
||||
embed.setTitle(`The coin landed on... **${result.toUpperCase()}**! ${EmojiMap[result]}`)
|
||||
|
||||
setTimeout(
|
||||
() =>
|
||||
interaction.editReply({
|
||||
reply.edit({
|
||||
embeds: [embed.toJSON()],
|
||||
}),
|
||||
1500,
|
||||
)
|
||||
},
|
||||
} satisfies Command
|
||||
})
|
||||
|
||||
const EmojiMap: Record<'heads' | 'tails', string> = {
|
||||
heads: '🤯',
|
||||
|
||||
@@ -1,44 +1,46 @@
|
||||
import { SlashCommandBuilder, type TextBasedChannel } from 'discord.js'
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { ApplicationCommandOptionType, Message } from 'discord.js'
|
||||
import { ModerationCommand } from '../../classes/Command'
|
||||
|
||||
import { config } from '$/context'
|
||||
import type { Command } from '../types'
|
||||
|
||||
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: {
|
||||
roles: config.moderation?.roles ?? [],
|
||||
export default new ModerationCommand({
|
||||
name: 'reply',
|
||||
description: 'Send a message as the bot',
|
||||
options: {
|
||||
message: {
|
||||
description: 'The message to send',
|
||||
required: true,
|
||||
type: ApplicationCommandOptionType.String,
|
||||
},
|
||||
reference: {
|
||||
description: 'The message ID to reply to (use `latest` to reply to the latest message)',
|
||||
required: false,
|
||||
type: ApplicationCommandOptionType.String,
|
||||
},
|
||||
},
|
||||
allowMessageCommand: false,
|
||||
async execute({ logger, executor }, trigger, { reference: ref, message: msg }) {
|
||||
if (trigger instanceof Message) return
|
||||
|
||||
global: false,
|
||||
|
||||
async execute({ logger }, interaction) {
|
||||
const msg = interaction.options.getString('message', true)
|
||||
const ref = interaction.options.getString('reference')
|
||||
|
||||
const channel = (await interaction.guild!.channels.fetch(interaction.channelId)) as TextBasedChannel
|
||||
const refMsg = ref?.startsWith('latest') ? (await channel.messages.fetch({ limit: 1 })).at(0)?.id : ref
|
||||
const channel = await trigger.guild!.channels.fetch(trigger.channelId)
|
||||
if (!channel?.isTextBased())
|
||||
throw new CommandError(
|
||||
CommandErrorType.InvalidArgument,
|
||||
'This command can only be used in or on text channels',
|
||||
)
|
||||
const refMsg = ref?.startsWith('latest')
|
||||
? await channel.messages.fetch({ limit: 1 }).then(it => it.first())
|
||||
: ref
|
||||
|
||||
await channel.send({
|
||||
content: msg,
|
||||
reply: refMsg ? { messageReference: refMsg, failIfNotExists: true } : undefined,
|
||||
})
|
||||
|
||||
logger.info(`User ${interaction.user.tag} made the bot say: ${msg}`)
|
||||
logger.info(`User ${executor.user.tag} made the bot say: ${msg}`)
|
||||
|
||||
await interaction.reply({
|
||||
await trigger.reply({
|
||||
content: 'OK!',
|
||||
ephemeral: true,
|
||||
})
|
||||
},
|
||||
} satisfies Command
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user