【问题标题】:Conditional role-giving in Discord.JSDiscord.JS 中的条件角色赋予
【发布时间】:2021-11-18 15:55:27
【问题描述】:

我对 JavaScript 编码非常陌生,我正在为 Discord 服务器设置一个简单的事件机器人。

概念上非常简单,机器人真正做的就是允许任何人为他们提到的任何成员分配一个“死亡”角色。

const { Client, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
var prefix = "!";
client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`) });
client.on("messageCreate", (message) => {
    let staff = message.guild.roles.cache.find(r => r.name === "Staff");
    let dead = message.guild.roles.cache.find(r => r.name === "Dead");
    let member = message.mentions.members.first();
    if (!message.content.startsWith(prefix)) return;
    //Ping command
    if (message.content.startsWith(prefix + "ping")) {
        message.channel.send("Pong!");
    }
    //Error if command doesn't include a mention
    if (!member)
        return message.channel.send('You need to mention a member, <@' + message.author.id + '>')
    //Kill command
    if (message.content.startsWith(prefix + "kill")) {
        if (message.member.roles.cache.has(staff)) {
            return message.channel.send(`${member} is not participating in the event!`);
        }
        if (message.member.roles.cache.has(dead)) {
            return message.channel.send(`${member.toString()} is already dead!`);
        } else {
            member.roles.add(dead);
            return message.channel.send(`${member.toString()} has been eliminated!`);
        }

    }
}
);
client.login('Token');

但是,我遇到的问题是:

• kill 命令,虽然它可以赋予人们 Dead 角色并宣布成员被淘汰,但如果成员已经死亡或具有 ,它不会引发相应的错误>员工角色。它只是宣布该成员已被淘汰,无论他们担任什么角色。

• 键入任何前面带有 ! 的单词(如 !test)会导致 “需要提及成员” 错误。 (这包括 !ping 命令)

我在这里做错了什么?我检查了 v13 的 Discord.js 文档,但似乎找不到答案。提前致谢!

编辑: 修复了一切!我忘记了用于 ping 的 return,最终我为 kill 命令使用了不正确的函数。这是最终代码,它按预期工作。

const { Client, Intents } = require('discord.js');
const client = new Client({ intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES] });
var prefix = "!";
client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`) });
client.on("messageCreate", (message) => {
    if (!message.content.startsWith(prefix)) return;
//Ping command
    if (message.content.startsWith(prefix + "ping")) {
        return message.channel.send('Pong! <@' + message.author.id + '>');
    }
//Kill command
    if (message.content.startsWith(prefix + "kill")) {
        let member = message.mentions.members.first();
        let dead = message.guild.roles.cache.find(r => r.name === "Dead");
//No mention
        if (!member)
        return message.channel.send('You need to mention a member, <@' + message.author.id + '>');
//Staff check
        if (member.roles.cache.find(r => r.name == "Staff")) {
            return message.channel.send(`${member} is not participating in the event!`);
        }
//Dead check
        if (member.roles.cache.find(r => r.name == "Dead")) {
            return message.channel.send(`${member.toString()} is already dead!`);
        } else {
            member.roles.add(dead);
            return message.channel.send(`${member.toString()} has been eliminated!`);
        }
    }
});

感谢大家的帮助!并随时批评最终代码,欢迎所有提示和花絮!

【问题讨论】:

    标签: discord discord.js


    【解决方案1】:

    好的,所以你总是得到“需要提及成员”的原因有两个原因,首先你没有返回 ping 命令,其次是因为你没有在您需要的命令。您不需要在“全局”级别上执行此操作,因为并非每个命令都需要提及。所以这里的解决方法是将成员检查移动到代码的实际命令部分。

    我还建议使用某种可以捕获错误命令的命令处理程序。

    至于第一个问题,你需要通过角色的ID来检查角色。那是因为角色管理器的cache 是一个集合,它由该集合中任何它的ID 映射。所以只需在最后添加一个.id 就可以了。

    您的代码以正确的方式:

    client.on("messageCreate", (message) => {
        if (!message.content.startsWith(prefix)) return;
        //Ping command
        if (message.content.startsWith(prefix + "ping")) {
            return message.channel.send("Pong!");
        }
        //Kill command
        if (message.content.startsWith(prefix + "kill")) {
            let staff = message.guild.roles.cache.find(r => r.name === "Staff");
            let dead = message.guild.roles.cache.find(r => r.name === "Dead");
            let member = message.mentions.members.first();
            //Error if command doesn't include a mention
            if (!member) return message.channel.send('You need to mention a member, <@' + message.author.id + '>');
    
            if (message.member.roles.cache.has(staff.id)) {
                return message.channel.send(`${member} is not participating in the event!`);
            }
            if (message.member.roles.cache.has(dead.id)) {
                return message.channel.send(`${member.toString()} is already dead!`);
            } else {
                member.roles.add(dead);
                return message.channel.send(`${member.toString()} has been eliminated!`);
            }
    
        }
    });
    

    【讨论】:

    • 哎呀,这太接近了!它确实使它加载了其他错误,但它似乎也不起作用。现在它说由于某种原因没有人参加该活动。难道是因为.cache
    【解决方案2】:

    这是因为代码正在执行您的所有条件。如果您希望 ping 实际上只是 ping 而不是执行命令的其余部分,您可以将 return 添加到它。

    例如:

    return message.channel.send("Pong!");
    

    我看到你已经在你的代码中使用了return,但是例如 ping 命令响应没有返回语句,这就是为什么它会检查member 是否为空

    【讨论】:

    • 我不敢相信我忽略了 Ping 命令上的return。是的,这解决了ping错误。非常感谢!
    【解决方案3】:

    检查角色

    您尝试在其中搜索的 member.roles.cache 是一个 Collection 对象,它扩展了普通的 JavaScript Map。映射将它们的值存储在键值对中。在这种情况下,角色是值,键是自动生成的雪花,基本上是唯一的 ID。现在,也许与直觉相反,.has() 函数实际上并不是在搜索您的缓存(Map)是否具有与您作为参数解析的任何值匹配的值,而是它是否具有与之匹配的键。

    搜索 Map 中是否有特定值有点棘手。有几种方法可以解决。其中之一是将 Map 快速转换为 Array 并在该数组上调用 .includes() ,如下所示:

    Array.from(yourMap.values()).includes(yourRole)
    

    或者,您可以遍历 Map 的所有值并根据您的角色检查它们,如下所示:

    const findInMap = (map, val) => {
      for (let [k, v] of map) {
        if (v === val) { 
          return true; 
        }
      }  
      return false;
    }
    

    说实话,我不喜欢这两种方式,但由于您无法选择如何存储角色,所以您必须做出应有的决定,对吧?

    “需要提及成员”

    在编程中跟踪程序在执行时所采用的路径 非常重要。在您的 .on('messageCreate') 函数中,我们可以看看这个。

    首先,我们获取一堆变量并检查消息是否以您预定义的命令前缀开头。如果它没有返回,那么它会立即离开代码块,这很好。 但是,在下一个 if 语句中,这有点错误。您检查命令是否为 !ping,如果是,则发回一条消息。即使我们知道其中的其余代码与我们收到的消息无关,您也不会在任何地方告诉程序离开代码块,例如使用 return 语句。

    因为你只检查消息是否有你的前缀,然后没有什么能阻止它到达询问是否提到成员的 if 语句,它将为每条以 ! 开头的消息执行。

    解决方案

    要解决这个问题,您可以非常简单地将检查提到的成员的 if 语句移到 if 语句块中,该块在我们知道它是一个 !kill 命令后执行。这样,如果我们实际执行 !kill 命令,它只需要提到的成员。

    【讨论】:

    • ping 问题解决了,你是对的。我错过了退货声明。我当时忽略了它。不过,使用数组来解决地图可能有点太复杂了。但是,答案确实澄清了我在 JS 中一直存在的一些问题。我并没有真正研究过 JS,因此了解所有这些内容非常有见地。感谢您提供如此完整的答案!
    猜你喜欢
    • 2020-10-07
    • 2018-06-10
    • 2021-06-06
    • 2021-04-09
    • 2020-07-21
    • 1970-01-01
    • 1970-01-01
    • 2018-10-11
    • 1970-01-01
    相关资源
    最近更新 更多