Discord.js v13 临时禁言命令:如何校验禁言时长格式有效性以避免Bot崩溃?
嘿,我来帮你搞定这个Discord Bot的tempmute崩溃问题!你遇到的核心问题是ms包在收到无效输入(比如空值、乱码、不符合格式的字符串)时会直接抛出错误,而你的代码没做任何错误处理,导致整个Bot进程直接崩溃。咱们只需要添加输入校验和错误捕获就能解决,顺便还能修正你代码里的一个小逻辑bug。
问题根源拆解
看你提供的错误日志,当args[1]是undefined(也就是没输入时长)或者格式完全不对的时候,ms()会直接抛出Error: val is not a non-empty string or a valid number,而你的代码没有捕获这个错误,所以Bot直接崩了。
解决方案步骤
- 用
try-catch包裹ms()的转换逻辑,把错误拦下来,不让它扩散到整个Bot进程 - 额外校验转换后的时长是否有效(必须是大于0的毫秒数)
- 修正你代码里的权限判断逻辑——原来当目标用户有管理权限时,你错误地发送了“已被禁言”的消息,这明显不对,应该提示无法禁言管理员
修改后的完整代码
const ms = require('ms'); const { Permissions } = require('discord.js'); module.exports = { name: 'tempmute', description: "Temporarily mutes a user", execute(message, args) { const target = message.mentions.members.first(); const muteRole = message.guild.roles.cache.find(role => role.name === "muted"); // 先检查命令使用者有没有权限 if (!message.member.permissions.has(Permissions.FLAGS.MODERATE_MEMBERS)) { return message.reply("你没权限用这个命令哦!"); } // 检查有没有提到正确的用户 if (!target) { return message.reply("得先@一个服务器里的有效成员才行!"); } // 不能禁言Bot自己 if (target.id === message.client.user.id) { return message.reply("我才不会禁言自己呢😎"); } // 不能禁言自己 if (target.id === message.member.id) { return message.reply("你咋能禁言自己呢?!"); } // 不能禁言管理员 if (target.permissions.has(Permissions.FLAGS.MODERATE_MEMBERS)) { return message.reply("我没法禁言有管理权限的用户哦!"); } // 检查有没有输入时长 if (!args[1]) { return message.reply("得指定禁言时长呀,比如`10m`是10分钟,`1h`是1小时~"); } // 处理时长转换,捕获错误 let duration; try { duration = ms(args[1]); // 确保时长是正数,不能是0或者负数 if (!duration || duration <= 0) { throw new Error("时长得大于0哦"); } } catch (err) { return message.reply("时长格式不对呀,试试`5m`、`2h`、`1d`这种格式,时长必须大于0!"); } // 执行禁言操作,也加个错误捕获防止意外 try { target.roles.add(muteRole.id); message.reply(`<@${target.user.id}> 已经被禁言 ${ms(duration)}啦!`); // 设置自动解除禁言的定时器,顺便检查用户还在不在服务器、有没有禁言角色 setTimeout(() => { if (target && target.roles.cache.has(muteRole.id)) { target.roles.remove(muteRole.id); message.channel.send(`<@${target.user.id}> 的禁言到期啦!`); } }, duration); } catch (err) { message.reply("执行禁言的时候出错了,检查一下禁言角色是不是存在,还有我有没有管理角色的权限哦!"); console.error(err); // 后台打日志方便排查问题 } } }
关键修改点说明
- 提前返回,避免嵌套地狱:把所有错误判断(权限、目标用户、时长存在性等)都改成
return直接结束函数,代码结构更清爽,可读性更高 try-catch捕获转换错误:不管用户输入啥乱七八糟的内容,ms()抛出的错误都会被我们接住,Bot再也不会崩溃了,还能给用户友好提示- 时长有效性校验:额外检查转换后的毫秒数是不是大于0,避免设置0时长或者负数时长的无效操作
- 修正权限逻辑:原来的错误逻辑改成“无法禁言管理员”,符合实际需求
- 增强定时器健壮性:自动解除禁言前,先检查用户是否还在服务器、是否还拥有禁言角色,避免出现用户已经离开服务器还去操作角色的错误
- 全局操作错误捕获:执行禁言和解除禁言时也加了
try-catch,处理角色不存在或者Bot权限不足的情况,还会在后台打日志方便排查问题
这样改完之后,不管用户怎么输入错误的时长,甚至乱敲字符,Bot都能稳稳地给出提示,再也不会崩溃啦!
内容的提问来源于stack exchange,提问作者Miki_hero
相关产品推荐
相关产品推荐

