在Discord.JS中有条件的角色分配



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

在概念上很简单,bot真正做的就是允许任何人分配一个"Dead">角色给他们提到的任何成员。

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命令,当它给人死亡角色并宣布成员被淘汰,如果成员已经死亡或具有Staff,则不会抛出相应的错误。的角色。它只是宣布该成员已被淘汰,而不管他们具有什么角色。

•键入任何带有的单词!before(如!)测试)会导致"需要提及成员">错误。(这包括!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!`);
}
}
});

谢谢大家的帮助!你也可以随意评论最终的代码,欢迎所有的提示和花絮!

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

例如:

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

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

检查角色

您试图在其中搜索的member.roles.cache是一个Collection对象,它扩展了普通的JavaScript Map。映射将其值存储在一个Key-Value对中。在本例中,角色是值,键是自动生成的Snowflake,它基本上是一个惟一的ID。现在,也许与直觉相反,.has()函数实际上并不是在搜索您的缓存(Map)是否有与您解析为参数的任何值匹配的值,而是是否有与之匹配的键。

搜索Map中是否有特定的值有点棘手。有几种方法可以做到这一点。其中之一是快速将Map转换为数组并在该数组上调用.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语句移动到if语句块中,在我们知道它是一个!kill命令后执行。这样,只有当我们实际执行!kill命令时,才需要上面提到的成员。

好的,所以你总是需要提到成员的原因这有两个原因,首先您没有返回ping命令,其次是因为您没有在需要它的命令中检查成员。你不需要在全局上这样做。级别,因为不是每个命令都需要提及。因此,这里的解决方法是将成员check移到代码的实际命令部分。

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

对于第一个问题,您需要通过角色的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!`);
}
}
});

最新更新