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

Discord.js 实现从带固定前缀的自然语句中提取命令的问题

问题根源

你当前的命令匹配逻辑是切除固定前缀后,取拆分出的第一个单词作为命令名,所以类似Hey Bot show me the ping的句式,切除前缀后第一个单词是show,根本匹配不到ping命令,你的run函数自然不会触发,和你在run内加的判断没有关系。

修复步骤

第一步:调整消息匹配逻辑

把原来的取首个单词匹配命令,改成「切除前缀后的所有内容,遍历全部已注册命令,检查是否包含命令名/别名」即可。为了避免误匹配,建议用正则匹配独立单词,排除命令名作为其他单词一部分的情况。

第二步:替换你的messageCreate事件代码

修改后的完整代码如下:

const client = require("..");
var config = require("../settings/config.json");
var ee = require("../settings/embed.json");
const { MessageEmbed } = require("discord.js");

client.on('messageCreate', async message => {
    let prefix = config.prefix
    if (!message.guild) return;
    if (message.author.bot) return;
    if (message.channel.partial) await message.channel.fetch();
    if (message.partial) await message.fetch();

    // 先判断消息是否带前缀,避免无意义处理
    if (!message.content.toLowerCase().startsWith(prefix.toLowerCase())) {
        // 这里保留你原来的@机器人逻辑
        if (message.mentions.has(client.user)) {
            message.channel.send({
                embeds: [new MessageEmbed()
                    .setColor(ee.embed_color)
                    .setAuthor(`TEST`)
                    .setDescription(`Use \`${prefix}help\``)
                    .setFooter(ee.embed_footertext, ee.embed_footericon)
                ]
            });
        }
        return;
    }

    // 切除前缀,拿到后续所有内容
    const contentWithoutPrefix = message.content.slice(prefix.length).trim().toLowerCase();
    const args = contentWithoutPrefix.split(/ +/);

    // 遍历所有已注册命令,匹配是否包含命令名/别名(独立单词匹配)
    let command = null;
    for (const cmd of client.commands.values()) {
        // 匹配命令名
        const nameRegex = new RegExp(`\\b${cmd.name.toLowerCase()}\\b`);
        if (nameRegex.test(contentWithoutPrefix)) {
            command = cmd;
            break;
        }
        // 匹配别名
        if (cmd.aliases && cmd.aliases.length > 0) {
            for (const alias of cmd.aliases) {
                const aliasRegex = new RegExp(`\\b${alias.toLowerCase()}\\b`);
                if (aliasRegex.test(contentWithoutPrefix)) {
                    command = cmd;
                    break;
                }
            }
            if (command) break;
        }
    }

    if (command) {
        if (!message.member.permissions.has(command.permissions || [])) {
            return message.reply({
                embeds: [
                    new MessageEmbed()
                        .setColor(ee.embed_color)
                        .setDescription(`** 缺少权限:${command.permissions} **`)
                ]
            })
        }
        command.run(client, message, args, prefix)
    }
})

第三步:还原你的ping.js代码

你之前修改的run函数逻辑可以删掉,用最初的版本即可,现在只要前缀后的内容包含ping的独立单词,就能触发ping命令的run函数。

可选优化

如果想要匹配更灵活,可以给每个命令新增keywords配置项,比如ping命令可以加:

module.exports = {
    name: "ping",
    aliases: ['p'],
    keywords: ['ping', '延迟', '网速'], // 新增关键词
    permissions : ["SEND_MESSAGES"],
    // 其余代码不变
}

然后在上面的匹配逻辑里,增加对keywords的遍历匹配即可,后续就算用户发Hey Bot 看看网速也能触发ping命令。


内容的提问来源于stack exchange,提问作者Hunwol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:39:00