discord.js v13批量解封命令无响应及零封禁无提示问题
Discord.js v13 批量解封命令问题修复
问题1:点击反应无响应
原因:awaitReactions参数中未正确指定filter属性,原代码用变量名作为键名,导致Discord.js无法识别过滤规则,因此不会捕获用户的反应操作。
修复:将balls.awaitReactions({ johncena, max: 1, time: ms("1m")})修改为balls.awaitReactions({ filter: johncena, max: 1, time: ms("1m"), errors: ['time']}),明确指定过滤规则为filter字段,同时添加errors参数处理超时场景,避免后续代码因collected为空报错。
问题2:无封禁用户时无提示
原因:一是未导入ms模块,调用ms("1m")会触发未捕获的引用错误;二是setTimeout延迟执行逻辑,导致错误抛出后无法及时触发提示;另外未处理用户超时未反应的情况,会导致后续代码因react23847为undefined报错。
修复:
- 补充导入
ms模块; - 确认操作后立即获取封禁列表,提前判断是否存在封禁用户,无需延迟;
- 新增超时处理逻辑,用户未在规定时间内反应时发送提示;
- 优化错误捕获,确保提示能正常发送。
修复后完整代码
const { MessageEmbed } = require("discord.js"); const Discord = require("discord.js"); const { parse } = require("twemoji-parser"); const JUGNU = require("../../../handlers/Client"); const { Queue } = require("distube"); const ms = require('ms'); // 补充导入ms模块 module.exports = { name: "unbanall", aliases: ["allunban"], description: `批量解封服务器所有被封禁用户`, userPermissions: ['ADMINISTRATOR'], botPermissions: ['EMBED_LINKS', "ADMINISTRATOR"], category: "Mod", cooldown: 5, inVoiceChannel: false, inSameVoiceChannel: false, Player: false, djOnly: false, /** * * @param {JUGNU} client * @param {Message} message * @param {String[]} args * @param {String} prefix * @param {Queue} queue */ run: async (client, message, args, prefix, queue, interaction, com) => { try { // 提前判断权限,减少嵌套 if (message.author.id !== message.guild.ownerId) { return message.channel.send({ content: `只有服务器所有者可以使用此命令...` }).catch(e => {}); } const confirmEmbed = new MessageEmbed() .setColor("RED") .setTitle(`移除所有封禁`) .setDescription(`请确认你是否要解除此服务器的所有封禁。 **注意:** 此过程可能需要一段时间,且无法轻易停止或撤销。 **你是否要继续?** ✅ - 是,解除所有封禁。 ❌ - 否,取消命令。`) .setThumbnail(`${client.user.displayAvatarURL({ dynamic: true })}`) .setTimestamp() .setFooter({ text: "copyright plusbot" }); const confirmMsg = await message.channel.send({ embeds: [confirmEmbed] }); // 确保两个反应都添加完成 await Promise.all([confirmMsg.react('✅'), confirmMsg.react('❌')]); const filter = (reaction, user) => { return ['✅', '❌'].includes(reaction.emoji.name) && !user.bot && user.id === message.author.id; }; confirmMsg.awaitReactions({ filter, max: 1, time: ms("1m"), errors: ['time'] }) .then(async collected => { const reaction = collected.first(); if (reaction.emoji.name === '✅') { await message.channel.send({ content: `请稍等!我们正在开始处理...` }).catch(e => {}); const bans = await message.guild.bans.fetch(); if (bans.size === 0) { return message.channel.send({ content: "当前服务器没有被封禁的用户。" }); } let successCount = 0; // 逐个处理解封,捕获单个用户的解封失败 bans.forEach(async ban => { try { await message.guild.members.unban(ban.user.id); successCount++; } catch (e) { console.log(`解封用户 ${ban.user.tag} 失败: ${e}`); } }); // 等待所有解封操作完成后发送统计提示 setTimeout(() => { message.channel.send({ content: `解封操作完成,共成功解封 ${successCount} 名用户。` }).catch(e => {}); console.log(`已完成解封,成功解封 ${successCount} 名用户。`); }, bans.size * 1000); } else if (reaction.emoji.name === '❌') { return message.channel.send(`正在取消解封操作...`).catch(e => {}); } }) .catch(err => { // 处理用户超时未反应的情况 if (err instanceof Discord.Collection && err.has('time')) { return message.channel.send(`你未在规定时间内确认,命令已取消。`).catch(e => {}); } if (client.config.debugmode) console.log(err); }); } catch (e) { console.log(e); } } };
额外优化说明
- 使用
await替代链式then,代码结构更清晰易读; - 添加单个用户解封失败的捕获逻辑,避免因单个用户问题中断整个流程;
- 新增解封完成后的统计提示,明确告知用户操作结果;
- 调整权限判断位置,减少代码嵌套层级。
内容的提问来源于stack exchange,提问作者Tiffany
相关产品推荐
相关产品推荐

