javascript - Discord.js - 秘密获取用户输入
问题描述
我正在使用 Discord.js 制作一个 2 人石头剪刀布游戏。
遗憾的是,Discord API 真的很慢,而且 afaik 不提供任何类型的中间件。当有人选择他们的形状时,其他人会在很长一段时间内看到反应(或聊天消息),直到机器人将其删除,从而破坏整个游戏。
我能想到的秘密获取输入的唯一方法是在私人聊天中向用户发送一条消息,他可以对此做出反应。但是在我看来,必须从服务器切换到私人聊天然后再回到服务器只会让游戏无法玩。与简单地点击反应相比,这对用户来说工作量太大了。
另一种选择是在聊天中发送一条消息,只有特定用户才能看到。它可以说类似“1 = 剪刀,2 = 石头,3 = 纸”。(映射对于每个玩家都是随机的)。然后用户从选项 1、2 和 3 中选择相应的反应。但似乎 Discord 不允许在聊天中发送消息,只有特定用户才能看到。或者有什么办法吗?
有没有什么方法可以在用户不必切换聊天的情况下秘密地获取用户输入?
API 是否可能为我忽略的消息或反应提供任何类型的中间件?
解决方案
Discord does not allow to send a message in chat, which only a specific user can see. Or is there a way?
No, there isn't. Discord API doesn't allow you to specify users that can see a specific guild message.
And is there any way of secetly getting user-input without the user having to switch chats?
There definitely is!
You could use a fairly new feature, buttons. Below is an example code, you can use to base your game on. Things left to implement are:
- Gamestate, e.g. who is on turn, who has how much points, etc.
- Update gamestates (identify gamestate by id?) in the
interactionCreate
event's callback. - Showing the gamestate to the players, e.g. updating the original message.
- Don't allow players to modify the gamestate of other playing pairs.
- Let the user specify an opponent in
!createGame
command. - The actual game logic (determining who won, who gets a point, etc.)
That is all I can think of for now. Take those more of a suggestions than requirements. There is no boundary to ones creativity.
// ... Some object to store the gamestates in? ...
client.on("messageCreate", async (message) => {
// Don't reply to bots
if (message.author.bot) return;
// Basic command handler, just for showcasing the buttons
if (message.content.startsWith("!createGame")) {
// ... Probably some argument handling for the opponent (e.g. a mention) ...
// Create an action row component with buttons attached to it
const actionRow = new Discord.MessageActionRow()
.addComponents(
[["Rock", ""], ["Paper", ""], ["Scissors", "✂️"]].map((buttonProperties) => {
return new Discord.MessageButton()
.setStyle("PRIMARY")
.setLabel(buttonProperties[0])
.setEmoji(buttonProperties[1])
.setCustomId(`rpsgame_${buttonProperties[0].toLowerCase()}`);
})
);
// Send the game message/playground
message.channel.send({
content: "Rock, Paper and Scissors: The game!",
components: [actionRow]
});
}
});
To handle the button clicks, we use the interactionCreate
event.
client.on("interactionCreate", (interaction) => {
// If the interaction is a button
if (interaction.isButton()) {
// If the button belongs to our game
if (interaction.customId.startsWith("rpsgame")) {
// Log what the user has selected to console, as a test
console.log(`A user '${interaction.member.user.tag}' selected ${interaction.component.emoji.name}.`);
// Don't forget to reply to an interaction,
// otherwise an error will be shown on discord.
interaction.update("Update GameState...");
}
}
});
No one will see what the other users have selected, unless you want them to.
Using discord.js ^13.0.1
. If you are on v12, there is a nice package called discord-buttons
.