You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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直接崩了。

解决方案步骤

  1. 用try-catch包裹ms()的转换逻辑,把错误拦下来,不让它扩散到整个Bot进程
  2. 额外校验转换后的时长是否有效(必须是大于0的毫秒数)
  3. 修正你代码里的权限判断逻辑——原来当目标用户有管理权限时,你错误地发送了“已被禁言”的消息,这明显不对,应该提示无法禁言管理员

修改后的完整代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 13:27:33