如何让 Discord.js 回复不和谐的 DM 消息
How to make Discord.js reply to discord DM messages
我正在尝试让 discord.js 阅读 Discord 上的 DM 消息,以获得一个 server/faction 从头开始制作的应用程序机器人,但我有它可以发送第一部分,当你键入 %apply 到 bot 尝试通过问题 2 时出现问题它不断得到问题 2 而不是去问题 3
我试图过滤掉与传递的消息不同的 DM 消息,所以我有几个 if 命令
bot.on("message", function(message) {
if (message.author.equals(bot.user)) return;
if (message.content === "%apply") {
apply = "TRUE";
a0 = message.author.lastMessageID
message.author.sendMessage("```We need to ask some questions so we can know a litte bit about yourself```");
message.author.sendMessage("```Application Started - Type '#Cancel' to cancel the application```");
message.author.sendMessage("```Question 1: In-Game Name?```");
}
if ((message.guild === null) && (message.author.lastMessageID != a0) && (message.content != "%apply") && (apply === "TRUE")) {
a1 = message.author.lastMessageID;
message.author.sendMessage("```Question 2: Age?```");
}
if ((message.guild === null) && (message.author.lastMessageID != a1) && (message.author.lastMessageID != a0) && (apply === "TRUE")) {
a2 = message.author.lastMessageID;
message.author.sendMessage("```Question 3: Timezone? NA, AU, EU, NZ, or Other? (If other, describe your timezone)```");
}
if ((message.guild === null) && (message.author.lastMessageID != a2) && (message.author.lastMessageID != a1) && (message.author.lastMessageID != a0) && (apply === "TRUE")) {
a3 = message.author.lastMessageID;
message.author.sendMessage("```Question 4: Do you have schematica?```");
}
我预计它会从问题 1 到问题 2 再到问题 3
您的变量 a0, ... , a3
在 "onMessage"
范围内,并且每次在您的回调中都未定义。因此,如果您的消息不是 %apply
,您将陷入 "Question 2" 步骤
您应该在全局变量中跟踪您的用户注册步骤,并阅读它以了解您正在进行的步骤。
以下是如何执行此操作的简短示例。
请注意,这是一个非常基本的方法,如果您需要向应用程序添加更复杂的功能,使用一些 in-memory 数据库可能会更好。
它还需要更多的控制,我想还有一些其他的数据存储来跟踪用户的答案。
let userApplications = {}
bot.on("message", function(message) {
if (message.author.equals(bot.user)) return;
let authorId = message.author.id;
if (message.content === "%apply") {
console.log(`Apply begin for authorId ${authorId}`);
// User is not already in a registration process
if (!(authorId in userApplications)) {
userApplications[authorId] = { "step" : 1}
message.author.send("```We need to ask some questions so we can know a litte bit about yourself```");
message.author.send("```Application Started - Type '#Cancel' to cancel the application```");
message.author.send("```Question 1: In-Game Name?```");
}
} else {
if (message.channel.type === "dm" && authorId in userApplications) {
let authorApplication = userApplications[authorId];
if (authorApplication.step == 1 ) {
message.author.send("```Question 2: Age?```");
authorApplication.step ++;
}
else if (authorApplication.step == 2) {
message.author.send("```Question 3: Timezone? NA, AU, EU, NZ, or Other? (If other, describe your timezone)```");
authorApplication.step ++;
}
else if (authorApplication.step == 3) {
message.author.send("```Question 4: Do you have schematica?```");
authorApplication.step ++;
}
else if (authorApplication.step == 4) {
message.author.send("```Thanks for your registration. Type %apply to register again```");
delete userApplications[authorId];
}
}
}
});
其他一些快速笔记:
sendMessage(msg)
在 discord.js 中已弃用 api,现在应使用 send(msg)
- 测试收到的消息是否是 dm,我认为最好检查
message.channel.type
而不是寻找空的 message.guildId
前言
虽然@Gruntzy's answer is not wrong, there's another solution that's built into Discord.js and meant for these situations - TextChannel.awaitMessages()
。您可以在如下所示的系统中使用它。
示例代码
const questions = [ // ------------------------------------
"What's your IGN?", //
"How old are you?", // Define the questions you'd like the
"What time zone do you reside in?", // application to have in this array.
"Do you have Schematica?" //
]; // ------------------------------------
const applying = [];
bot.on("message", async message => {
if (message.author.bot) return;
if (message.content.toLowerCase() === "%apply") {
if (applying.includes(message.author.id)) return;
try {
console.log(`${message.author.tag} began applying.`);
applying.push(message.author.id);
await message.channel.send(":pencil: **Application started!** Type `#cancel` to exit.");
for (let i = 0, cancel = false; i < questions.length && cancel === false; i++) {
await message.channel.send(questions[i]);
await message.channel.awaitMessages(m => m.author.id === message.author.id, { max: 1, time: 300000, errors: ["time"] })
.then(collected => {
if (collected.first().content.toLowerCase() === "#cancel") {
await message.channel.send(":x: **Application cancelled.**");
applying.splice(applying.indexOf(message.author.id), 1);
cancel = true;
console.log(`${message.author.tag} cancelled their application.`);
}
}).catch(() => {
await message.channel.send(":hourglass: **Application timed out.**");
applying.splice(applying.indexOf(message.author.id), 1);
cancel = true;
console.log(`${message.author.tag} let their application time out.`);
});
}
await message.channel.send(":thumbsup: **You're all done!**");
console.log(`${message.author.tag} finished applying.`);
} catch(err) {
console.error(err);
}
}
});
说明
为了让代码更容易理解,我们一步一步来...
1.前几行。
questions
数组包含您希望在应用程序中提出的所有问题。为了效率,我实现了一个数组;只需更改一行即可添加或删除问题,并且不会一遍又一遍地复制和粘贴相同的代码。
applying
数组将帮助我们跟踪应用程序过程中的用户。
2。消息事件。
- 我已经实现了一个箭头函数 (ES6) 作为回调并将其声明为异步,因此我们可以在其中使用
await
。
- 我们防止机器人触发任何命令。
- 我们检查 case iNsEnSiTiVeLy 是否应该 运行 命令。
- 您会注意到前面的代码包含在
try...catch
statement. This allows us to catch any unhandled promise rejections (i.e. if TextChannel.send()
中,很容易引发错误。
3。 %apply
命令。
- 我们将用户添加到
applying
数组。
- 我们发送开始消息。
- 注意关键字
await
:它在继续之前等待承诺实现。
- 我们使用
for
循环遍历 questions
数组。
- 在循环中,我们发送问题然后调用
TextChannel.awaitMessages()
。我们的第一个参数是消息必须通过的过滤器,第二个是选项。
- 循环完成后,我们发送完成消息。此时,您可以随心所欲地处理申请。
我正在尝试让 discord.js 阅读 Discord 上的 DM 消息,以获得一个 server/faction 从头开始制作的应用程序机器人,但我有它可以发送第一部分,当你键入 %apply 到 bot 尝试通过问题 2 时出现问题它不断得到问题 2 而不是去问题 3
我试图过滤掉与传递的消息不同的 DM 消息,所以我有几个 if 命令
bot.on("message", function(message) {
if (message.author.equals(bot.user)) return;
if (message.content === "%apply") {
apply = "TRUE";
a0 = message.author.lastMessageID
message.author.sendMessage("```We need to ask some questions so we can know a litte bit about yourself```");
message.author.sendMessage("```Application Started - Type '#Cancel' to cancel the application```");
message.author.sendMessage("```Question 1: In-Game Name?```");
}
if ((message.guild === null) && (message.author.lastMessageID != a0) && (message.content != "%apply") && (apply === "TRUE")) {
a1 = message.author.lastMessageID;
message.author.sendMessage("```Question 2: Age?```");
}
if ((message.guild === null) && (message.author.lastMessageID != a1) && (message.author.lastMessageID != a0) && (apply === "TRUE")) {
a2 = message.author.lastMessageID;
message.author.sendMessage("```Question 3: Timezone? NA, AU, EU, NZ, or Other? (If other, describe your timezone)```");
}
if ((message.guild === null) && (message.author.lastMessageID != a2) && (message.author.lastMessageID != a1) && (message.author.lastMessageID != a0) && (apply === "TRUE")) {
a3 = message.author.lastMessageID;
message.author.sendMessage("```Question 4: Do you have schematica?```");
}
我预计它会从问题 1 到问题 2 再到问题 3
您的变量 a0, ... , a3
在 "onMessage"
范围内,并且每次在您的回调中都未定义。因此,如果您的消息不是 %apply
,您将陷入 "Question 2" 步骤
您应该在全局变量中跟踪您的用户注册步骤,并阅读它以了解您正在进行的步骤。 以下是如何执行此操作的简短示例。 请注意,这是一个非常基本的方法,如果您需要向应用程序添加更复杂的功能,使用一些 in-memory 数据库可能会更好。 它还需要更多的控制,我想还有一些其他的数据存储来跟踪用户的答案。
let userApplications = {}
bot.on("message", function(message) {
if (message.author.equals(bot.user)) return;
let authorId = message.author.id;
if (message.content === "%apply") {
console.log(`Apply begin for authorId ${authorId}`);
// User is not already in a registration process
if (!(authorId in userApplications)) {
userApplications[authorId] = { "step" : 1}
message.author.send("```We need to ask some questions so we can know a litte bit about yourself```");
message.author.send("```Application Started - Type '#Cancel' to cancel the application```");
message.author.send("```Question 1: In-Game Name?```");
}
} else {
if (message.channel.type === "dm" && authorId in userApplications) {
let authorApplication = userApplications[authorId];
if (authorApplication.step == 1 ) {
message.author.send("```Question 2: Age?```");
authorApplication.step ++;
}
else if (authorApplication.step == 2) {
message.author.send("```Question 3: Timezone? NA, AU, EU, NZ, or Other? (If other, describe your timezone)```");
authorApplication.step ++;
}
else if (authorApplication.step == 3) {
message.author.send("```Question 4: Do you have schematica?```");
authorApplication.step ++;
}
else if (authorApplication.step == 4) {
message.author.send("```Thanks for your registration. Type %apply to register again```");
delete userApplications[authorId];
}
}
}
});
其他一些快速笔记:
sendMessage(msg)
在 discord.js 中已弃用 api,现在应使用send(msg)
- 测试收到的消息是否是 dm,我认为最好检查
message.channel.type
而不是寻找空的message.guildId
前言
虽然@Gruntzy's answer is not wrong, there's another solution that's built into Discord.js and meant for these situations - TextChannel.awaitMessages()
。您可以在如下所示的系统中使用它。
示例代码
const questions = [ // ------------------------------------
"What's your IGN?", //
"How old are you?", // Define the questions you'd like the
"What time zone do you reside in?", // application to have in this array.
"Do you have Schematica?" //
]; // ------------------------------------
const applying = [];
bot.on("message", async message => {
if (message.author.bot) return;
if (message.content.toLowerCase() === "%apply") {
if (applying.includes(message.author.id)) return;
try {
console.log(`${message.author.tag} began applying.`);
applying.push(message.author.id);
await message.channel.send(":pencil: **Application started!** Type `#cancel` to exit.");
for (let i = 0, cancel = false; i < questions.length && cancel === false; i++) {
await message.channel.send(questions[i]);
await message.channel.awaitMessages(m => m.author.id === message.author.id, { max: 1, time: 300000, errors: ["time"] })
.then(collected => {
if (collected.first().content.toLowerCase() === "#cancel") {
await message.channel.send(":x: **Application cancelled.**");
applying.splice(applying.indexOf(message.author.id), 1);
cancel = true;
console.log(`${message.author.tag} cancelled their application.`);
}
}).catch(() => {
await message.channel.send(":hourglass: **Application timed out.**");
applying.splice(applying.indexOf(message.author.id), 1);
cancel = true;
console.log(`${message.author.tag} let their application time out.`);
});
}
await message.channel.send(":thumbsup: **You're all done!**");
console.log(`${message.author.tag} finished applying.`);
} catch(err) {
console.error(err);
}
}
});
说明
为了让代码更容易理解,我们一步一步来...
1.前几行。
questions
数组包含您希望在应用程序中提出的所有问题。为了效率,我实现了一个数组;只需更改一行即可添加或删除问题,并且不会一遍又一遍地复制和粘贴相同的代码。applying
数组将帮助我们跟踪应用程序过程中的用户。
2。消息事件。
- 我已经实现了一个箭头函数 (ES6) 作为回调并将其声明为异步,因此我们可以在其中使用
await
。 - 我们防止机器人触发任何命令。
- 我们检查 case iNsEnSiTiVeLy 是否应该 运行 命令。
- 您会注意到前面的代码包含在
try...catch
statement. This allows us to catch any unhandled promise rejections (i.e. ifTextChannel.send()
中,很容易引发错误。
3。 %apply
命令。
- 我们将用户添加到
applying
数组。 - 我们发送开始消息。
- 注意关键字
await
:它在继续之前等待承诺实现。
- 注意关键字
- 我们使用
for
循环遍历questions
数组。 - 在循环中,我们发送问题然后调用
TextChannel.awaitMessages()
。我们的第一个参数是消息必须通过的过滤器,第二个是选项。 - 循环完成后,我们发送完成消息。此时,您可以随心所欲地处理申请。