mirror of
https://github.com/ReVanced/revanced-bots.git
synced 2026-01-11 13:56:15 +00:00
fix(bots/discord/commands): refactor and add checks
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { SlashCommandBuilder, type TextBasedChannel } from 'discord.js'
|
||||
|
||||
import { config } from '$/context'
|
||||
import type { Command } from '..'
|
||||
|
||||
export default {
|
||||
@@ -16,7 +17,7 @@ export default {
|
||||
.toJSON(),
|
||||
|
||||
memberRequirements: {
|
||||
roles: ['955220417969262612', '973886585294704640'],
|
||||
roles: config.moderation?.roles ?? [],
|
||||
},
|
||||
|
||||
global: false,
|
||||
|
||||
@@ -2,8 +2,10 @@ import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import type { Command } from '..'
|
||||
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { config } from '$/context'
|
||||
import { applyReferenceToModerationActionEmbed, createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { sendModerationReplyAndLogs } from '$/utils/discord/moderation'
|
||||
import { parseDuration } from '$/utils/duration'
|
||||
|
||||
export default {
|
||||
@@ -23,27 +25,34 @@ export default {
|
||||
|
||||
global: false,
|
||||
|
||||
async execute({ config, logger }, interaction) {
|
||||
const user = interaction.options.getUser('member', true)
|
||||
const reason = interaction.options.getString('reason') ?? undefined
|
||||
async execute({ logger }, interaction) {
|
||||
const user = interaction.options.getUser('user', true)
|
||||
const reason = interaction.options.getString('reason') ?? 'No reason provided'
|
||||
const dmd = interaction.options.getString('dmd')
|
||||
|
||||
const member = await interaction.guild!.members.fetch(user.id)
|
||||
const moderator = await interaction.guild!.members.fetch(interaction.user.id)
|
||||
|
||||
if (member.bannable) throw new CommandError(CommandErrorType.Generic, 'This user cannot be banned by the bot.')
|
||||
|
||||
if (moderator.roles.highest.comparePositionTo(member.roles.highest) <= 0)
|
||||
throw new CommandError(
|
||||
CommandErrorType.InvalidUser,
|
||||
'You cannot ban a user with a role equal to or higher than yours.',
|
||||
)
|
||||
|
||||
const dms = Math.floor(dmd ? parseDuration(dmd) : 0 / 1000)
|
||||
await interaction.guild!.members.ban(user, {
|
||||
reason: `Banned by moderator ${interaction.user.tag} (${interaction.user.id}): ${reason}`,
|
||||
deleteMessageSeconds: dms,
|
||||
})
|
||||
|
||||
const embed = createModerationActionEmbed('Banned', user, interaction.user, reason ?? 'No reason provided')
|
||||
const reply = await interaction.reply({ embeds: [embed] }).then(it => it.fetch())
|
||||
|
||||
const logConfig = config.moderation?.log
|
||||
if (logConfig) {
|
||||
const channel = await interaction.guild!.channels.fetch(logConfig.thread ?? logConfig.channel)
|
||||
if (!channel || !channel.isTextBased())
|
||||
return void logger.warn('The moderation log channel does not exist, skipping logging')
|
||||
|
||||
await channel.send({ embeds: [applyReferenceToModerationActionEmbed(embed, reply.url)] })
|
||||
}
|
||||
await sendModerationReplyAndLogs(
|
||||
interaction,
|
||||
createModerationActionEmbed('Banned', user, interaction.user, reason),
|
||||
)
|
||||
logger.info(
|
||||
`${interaction.user.tag} (${interaction.user.id}) banned ${user.tag} (${user.id}) because ${reason}, deleting their messages sent in the previous ${dms}s`,
|
||||
)
|
||||
},
|
||||
} satisfies Command
|
||||
|
||||
@@ -5,7 +5,8 @@ import { applyRolePreset } from '$/utils/discord/rolePresets'
|
||||
import type { Command } from '..'
|
||||
|
||||
import { config } from '$/context'
|
||||
import { applyReferenceToModerationActionEmbed, createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { sendModerationReplyAndLogs } from '$/utils/discord/moderation'
|
||||
import { parseDuration } from '$/utils/duration'
|
||||
|
||||
export default {
|
||||
@@ -23,9 +24,9 @@ export default {
|
||||
|
||||
global: false,
|
||||
|
||||
async execute({ config, logger }, interaction) {
|
||||
async execute({ logger }, interaction) {
|
||||
const user = interaction.options.getUser('member', true)
|
||||
const reason = interaction.options.getString('reason')
|
||||
const reason = interaction.options.getString('reason') ?? 'No reason provided'
|
||||
const duration = interaction.options.getString('duration')
|
||||
const durationMs = duration ? parseDuration(duration) : null
|
||||
|
||||
@@ -35,6 +36,8 @@ export default {
|
||||
'The duration must be at least 1 millisecond long.',
|
||||
)
|
||||
|
||||
const expires = durationMs ? Date.now() + durationMs : null
|
||||
const moderator = await interaction.guild!.members.fetch(interaction.user.id)
|
||||
const member = await interaction.guild!.members.fetch(user.id)
|
||||
if (!member)
|
||||
throw new CommandError(
|
||||
@@ -42,25 +45,23 @@ export default {
|
||||
'The provided member is not in the server or does not exist.',
|
||||
)
|
||||
|
||||
await applyRolePreset(member, 'mute', durationMs ? Date.now() + durationMs : null)
|
||||
if (member.manageable)
|
||||
throw new CommandError(CommandErrorType.Generic, 'This user cannot be managed by the bot.')
|
||||
|
||||
const embed = createModerationActionEmbed(
|
||||
'Muted',
|
||||
user,
|
||||
interaction.user,
|
||||
reason ?? 'No reason provided',
|
||||
durationMs,
|
||||
if (moderator.roles.highest.comparePositionTo(member.roles.highest) <= 0)
|
||||
throw new CommandError(
|
||||
CommandErrorType.InvalidUser,
|
||||
'You cannot mute a user with a role equal to or higher than yours.',
|
||||
)
|
||||
|
||||
await applyRolePreset(member, 'mute', durationMs ? Date.now() + durationMs : null)
|
||||
await sendModerationReplyAndLogs(
|
||||
interaction,
|
||||
createModerationActionEmbed('Muted', user, interaction.user, reason, durationMs),
|
||||
)
|
||||
|
||||
const reply = await interaction.reply({ embeds: [embed] }).then(it => it.fetch())
|
||||
|
||||
const logConfig = config.moderation?.log
|
||||
if (logConfig) {
|
||||
const channel = await interaction.guild!.channels.fetch(logConfig.thread ?? logConfig.channel)
|
||||
if (!channel || !channel.isTextBased())
|
||||
return void logger.warn('The moderation log channel does not exist, skipping logging')
|
||||
|
||||
await channel.send({ embeds: [applyReferenceToModerationActionEmbed(embed, reply.url)] })
|
||||
}
|
||||
logger.info(
|
||||
`Moderator ${interaction.user.tag} (${interaction.user.id}) muted ${user.tag} (${user.id}) until ${expires} because ${reason}`,
|
||||
)
|
||||
},
|
||||
} satisfies Command
|
||||
|
||||
@@ -48,12 +48,18 @@ export default {
|
||||
|
||||
logger.info(`Setting slowmode to ${duration}ms on ${channel.id}`)
|
||||
|
||||
await channel.setRateLimitPerUser(
|
||||
duration / 1000,
|
||||
`Slowmode set by @${interaction.user.username} (${interaction.user.id})`,
|
||||
)
|
||||
await channel.setRateLimitPerUser(duration / 1000, `Set by ${interaction.user.tag} (${interaction.user.id})`)
|
||||
|
||||
await interaction.reply({
|
||||
embeds: [createSuccessEmbed(`Slowmode set to ${durationToString(duration)} on ${channel.toString()}`)],
|
||||
embeds: [
|
||||
createSuccessEmbed(
|
||||
`Slowmode ${duration ? `set to ${durationToString(duration)}` : 'removed'} on ${channel.toString()}`,
|
||||
),
|
||||
],
|
||||
})
|
||||
|
||||
logger.info(
|
||||
`${interaction.user.tag} (${interaction.user.id}) set the slowmode on ${channel.name} (${channel.id}) to ${duration}ms`,
|
||||
)
|
||||
},
|
||||
} satisfies Command
|
||||
|
||||
@@ -3,7 +3,8 @@ import { SlashCommandBuilder } from 'discord.js'
|
||||
import type { Command } from '..'
|
||||
|
||||
import { config } from '$/context'
|
||||
import { applyReferenceToModerationActionEmbed, createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { sendModerationReplyAndLogs } from '$/utils/discord/moderation'
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
@@ -18,24 +19,15 @@ export default {
|
||||
|
||||
global: false,
|
||||
|
||||
async execute({ config, logger }, interaction) {
|
||||
const user = interaction.options.getUser('member', true)
|
||||
async execute({ logger }, interaction) {
|
||||
const user = interaction.options.getUser('user', true)
|
||||
|
||||
await interaction.guild!.members.unban(
|
||||
user,
|
||||
`Unbanned by moderator ${interaction.user.tag} (${interaction.user.id})`,
|
||||
)
|
||||
|
||||
const embed = createModerationActionEmbed('Unbanned', user, interaction.user)
|
||||
const reply = await interaction.reply({ embeds: [embed] }).then(it => it.fetch())
|
||||
|
||||
const logConfig = config.moderation?.log
|
||||
if (logConfig) {
|
||||
const channel = await interaction.guild!.channels.fetch(logConfig.thread ?? logConfig.channel)
|
||||
if (!channel || !channel.isTextBased())
|
||||
return void logger.warn('The moderation log channel does not exist, skipping logging')
|
||||
|
||||
await channel.send({ embeds: [applyReferenceToModerationActionEmbed(embed, reply.url)] })
|
||||
}
|
||||
await sendModerationReplyAndLogs(interaction, createModerationActionEmbed('Unbanned', user, interaction.user))
|
||||
logger.info(`${interaction.user.tag} (${interaction.user.id}) unbanned ${user.tag} (${user.id})`)
|
||||
},
|
||||
} satisfies Command
|
||||
|
||||
@@ -2,8 +2,11 @@ import { SlashCommandBuilder } from 'discord.js'
|
||||
|
||||
import CommandError, { CommandErrorType } from '$/classes/CommandError'
|
||||
import { config } from '$/context'
|
||||
import { applyReferenceToModerationActionEmbed, createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { appliedPresets } from '$/database/schemas'
|
||||
import { createModerationActionEmbed } from '$/utils/discord/embeds'
|
||||
import { sendModerationReplyAndLogs } from '$/utils/discord/moderation'
|
||||
import { removeRolePreset } from '$/utils/discord/rolePresets'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import type { Command } from '..'
|
||||
|
||||
export default {
|
||||
@@ -19,7 +22,7 @@ export default {
|
||||
|
||||
global: false,
|
||||
|
||||
async execute({ config, logger }, interaction) {
|
||||
async execute({ logger, database }, interaction) {
|
||||
const user = interaction.options.getUser('member', true)
|
||||
const member = await interaction.guild!.members.fetch(user.id)
|
||||
if (!member)
|
||||
@@ -28,18 +31,16 @@ export default {
|
||||
'The provided member is not in the server or does not exist.',
|
||||
)
|
||||
|
||||
if (
|
||||
!(await database.query.appliedPresets.findFirst({
|
||||
where: and(eq(appliedPresets.memberId, member.id), eq(appliedPresets.preset, 'mute')),
|
||||
}))
|
||||
)
|
||||
throw new CommandError(CommandErrorType.Generic, 'This user is not muted.')
|
||||
|
||||
await removeRolePreset(member, 'mute')
|
||||
const embed = createModerationActionEmbed('Unmuted', user, interaction.user)
|
||||
await sendModerationReplyAndLogs(interaction, createModerationActionEmbed('Unmuted', user, interaction.user))
|
||||
|
||||
const reply = await interaction.reply({ embeds: [embed] }).then(it => it.fetch())
|
||||
|
||||
const logConfig = config.moderation?.log
|
||||
if (logConfig) {
|
||||
const channel = await interaction.guild!.channels.fetch(logConfig.thread ?? logConfig.channel)
|
||||
if (!channel || !channel.isTextBased())
|
||||
return void logger.warn('The moderation log channel does not exist, skipping logging')
|
||||
|
||||
await channel.send({ embeds: [applyReferenceToModerationActionEmbed(embed, reply.url)] })
|
||||
}
|
||||
logger.info(`Moderator ${interaction.user.tag} (${interaction.user.id}) unmuted ${user.tag} (${user.id})`)
|
||||
},
|
||||
} satisfies Command
|
||||
|
||||
Reference in New Issue
Block a user