第一条命令始终使用开关 discord.js 执行

First command always executing with switch discord.js

我在使用 JavaScript 和 discord.js 的 switch 语句时遇到问题。我希望机器人执行带前缀和不带前缀的两个命令。当我尝试执行不带前缀的命令时,它会起作用,但是当我尝试执行前缀命令时,机器人会同时响应我询问的命令和我的非前缀命令中的第一种情况。这是代码:

const Discord = require('discord.js')
const fs = require('fs')
const token = "xxx"

const client = new Discord.Client({
    intents: [
        Discord.Intents.FLAGS.GUILDS,
        Discord.Intents.FLAGS.GUILD_MESSAGES
    ]
})

client.commands = new Discord.Collection()

const commandFiles = fs.readdirSync(`./commands/`).filter(file => file.endsWith('.js'))

for (const file of commandFiles){
    const command = require(`./commands/${file}`)

    client.commands.set(command.name, command)
}

//ready event

client.on('ready', () => {
    console.log('online')
})

const prefix = 'ao'

//message event

client.on('messageCreate', (message) => {

    const args = message.content.slice(prefix.length).trim().split(/ +/);
    var command = args.shift().toLowerCase()

    if(message.author.bot) return;

    //non-prefix commands

    switch(!message.content.startsWith(prefix)){
        
        case message.content.includes('ping'):
            message.reply('pong')

            break;

        case message.content.includes('hello'):
            message.reply('hello')

            break;
    }

    //prefix commands

    switch(command){

        case command = 'ciao':
            message.reply('ciao')

            break;
    }

})

client.login(token)

例如,如果我只输入“hello”或“ping”,机器人会回复正确的命令,但当我尝试使用“prefix + ciao”时,机器人会回复“pong”和“ciao”。

您的代码存在的问题是,您在代码中尝试执行的操作根本不是 switch 语句的工作方式。让我们首先看看 switch 语句实际上应该如何工作。

switch 语句如何工作

假设您有一个像 message.content 这样的值,您想要重复检查它的值。例如,你想知道是否 message.content == "ping",你想知道是否 message.content == "hello",等等。一种写法是这样的,使用经典的 if 语句:

if (message.content == "ping") {
    // Do stuff for ping
}
else if (message.content == "hello") {
    // Do stuff for hello
}

//... and so on

else {
    // Do stuff if none of the above cases equals value of message.content
}

如您所见,如果您有数十个值要与同一个 message.content 变量进行比较,这将变得非常冗长且重复。 switch 语句是一种快捷方式,其工作方式与上面的 if 语句完全相同,但语法更简洁且重复性更少。这是上面的 if 语句重写为 switch 语句的样子:

switch (message.content) {
    case "ping":
        // Do stuff for ping
        break;

    case "hello":
        // Do stuff for hello
        break;

    //... and so on

    default:
        // Do stuff if none of the above cases equals value of message.content
        break;
}

如您所见,switch 语句更清晰且重复更少,因此在 discord bot command-handling.

等情况下更受欢迎

问题

现在我们已经了解了 switch 语句应该如何工作,让我们看看您实际上是如何使用它们的。首先,你的 non-prefix 一个:

switch(!message.content.startsWith(prefix)){
        
        case message.content.includes('ping'):
            message.reply('pong')

            break;

        case message.content.includes('hello'):
            message.reply('hello')

            break;
    }

现在,让我们使用不适合您的测试用例来查看此代码:当消息内容为 prefix + "ciao" 时。由于此消息中存在前缀,因此 !message.content.startsWith(prefix) 的计算结果为 false。现在,让我们将上述 switch 语句中的所有其他值转换为它们的计算结果:

switch(false){
        
        case false: //message doesn't include 'ping'
            message.reply('pong')

            break;

        case false: //message doesn't include 'hello'
            message.reply('hello')

            break;
    }

你明白为什么你现在遇到问题了吗?你的第一个 switch 语句基本上等同于做一堆 if (false == false) 语句,所以每当你做 prefix + "ciao" 时,第一个 switch 中的第一个 case 将总是被执行。

这是你第一个 switch 的问题,但你的第二个也有问题:

switch(command){

        case command = 'ciao':
            message.reply('ciao')

            break;
    }

case 中发生的是技术上无效的语法。 command = 'ciao' 将变量 command 的值设置为 'ciao',它并没有真正检查 command 等于 'ciao' 的情况。然而,像 x = y 这样的赋值语句做 return y,这就是为什么这第二个 switch 最终为你工作。但是,我们可以通过删除不必要的 x =.

来简化操作

解决方案

要解决这些问题,您需要做两件事。首先,修复 switch 语句中的语法和逻辑问题。其次,重新排序和重组您的代码以正确分离前缀和 non-prefix 命令的逻辑。

这是我所做的修复。我添加了解释某些更改的评论:

var args = message.content.trim().split(/ +/); //Args with no prefix
var command = args.shift().toLowerCase(); //Command with no prefix

if(message.author.bot) return;

//non-prefix commands

if (!message.content.startsWith(prefix)) { //Check if no prefix with 'if'

    switch(command){
        
        case 'ping': //Use proper 'switch' and 'case' syntax like so
            message.reply('pong')

            break;

        case 'hello':
            message.reply('hello')

            break;
    }

}

//prefix commands

else {

    //Args and command accounting for prefix
    args = message.content.slice(prefix.length).trim().split(/ +/);
    command = args.shift().toLowerCase();

    switch(command){

        case 'ciao': //Removed incorrect "command = 'ciao'" syntax
            message.reply('ciao')

            break;
    }

}

这应该可以解决您遇到的问题并解决您的 switch 语句中的问题。而且,由于实际的 switch 语法比您尝试使用的语法简单得多,因此您添加命令也应该容易得多。