【问题标题】:Discord JS add role by reaction command doesn't work after restartDiscord JS通过反应命令添加角色在重启后不起作用
【发布时间】:2020-12-30 16:18:03
【问题描述】:

我正在尝试执行“通过反应添加角色”命令。因此,当成员对特定消息做出反应时,该成员将获得一个角色。它确实有效,但是当我重新启动我的机器人时,它不再添加角色。有人可以帮忙吗?

这里是代码:

bot.on('message', msg=>{
    if(msg.content.startsWith(prefix + "react")){
        let embed = new Discord.MessageEmbed()
        .setTitle("Reactions Roles")
        .setDescription("React to get a role!")
        .setColor("BLUE")
        msg.channel.send(embed).then(m=> m.react("emoji_id"))
    }
})

bot.on("messageReactionAdd", async (reaction, user)=>{
    if (reaction.message.partial) await reaction.message.fetch();
    if (reaction.partial) await reaction.fetch();
    if(user.bot) return;
    if(!reaction.message.guild) return;
    if(reaction.message.channel.id === "channel_id"){
        if(reaction.emoji.id === "emoji_id"){
            await reaction.message.guild.members.cache.get(user.id).roles.add("role_id")
        }
    }
})

bot.on('messageReactionRemove', async (reaction, user)=>{
    if(reaction.message.partial) await reaction.message.fetch();
    if(reaction.partial) await reaction.fetch();

    if(user.bot) return;
    if(!reaction.message.guild) return;

    if(reaction.message.channel.id === "channel_id"){
        if(reaction.emoji.id === "emoji_id"){
            await reaction.message.guild.members.cache.get(user.id).roles.remove("role_id")
        }
    }
})

【问题讨论】:

  • 只是为了澄清。当您重新启动机器人时,您希望它对旧消息做出反应并应用角色,还是不对新消息做出反应?
  • @MagnusVestergaard 不,我希望机器人对旧消息做出反应并添加角色。重新启动机器人时发送新消息会很尴尬。它应该对旧消息做好自己的工作。
  • 问题是您的代码只注册新消息/反应,因此您必须添加一些代码来扫描已发送的消息并检查这些反应。我回家看看是否记得用一些示例代码来回答。

标签: javascript discord discord.js


【解决方案1】:

我刚刚遇到了同样的问题并已修复。您的确切用例在文档中进行了深入解释,但我也会做一个小解释:https://discordjs.guide/popular-topics/reactions.html#listening-for-reactions-on-old-messages

DiscordJS 有一个“缓存”,用于加快查询速度(即,每当用户发送消息时,DiscordJS 都会将其保存在本地——它最多可以保存一定数量的最近消息,我相信是 100 条)。所以当你听反应时,discordJS 基本上只会听缓存的反应(至少从我的理解来看)。要让它收听非缓存消息,您必须使用“Partials”,这正是它听起来的样子——完整​​对象的部分。这意味着您将只获得一个具有 ID 的对象,而不是完整的 MessageReaction/User 对象(它们上有一个名为 fetch() 的函数,它允许您获取完整的对象)。使用 Partials 可以让您监听对旧的未缓存消息的反应。

要使用 Partials,请像这样创建客户端:

const bot = new Client({
  partials: ['MESSAGE', 'CHANNEL', 'USER', 'REACTION'],
});

稍后当您收听messageReactionAdd 之类的内容时要小心!您将按照以下方式做一些事情:

client.on(
  'messageReactionAdd',
  async (potentialPartialReaction, potentialPartialUser) => {
    try {
      const reaction = await potentialPartialReaction.fetch();
      const user = await potentialPartialUser.fetch();
    } catch (err) {
      console.log(err);
    }

    // can use reaction and user here!
});

我相信这应该适用于您的情况,但如果没有,请告诉我。这在 DiscordJS v12 中对我有用。

【讨论】:

    【解决方案2】:

    要让您的机器人检查之前的消息是否已被响应,您可以使用与此类似的代码

    let guildID = "xxx";
    let channelID = "xxx";
    let emojiID = "xxx";
    let roleID = "xxx";
    
    
    bot.on("ready", async () => {
    
        let guild = bot.guilds.cache.find(guild => guild.id == guildID);
        let channel = await guild.channels.cache.find(ch => ch.id == channelID)
    
        // You can set any limit you want, for performance I used a low number
        channel.messages.fetch({ limit: 10 })
            .then(async messages => {
                messages.forEach(async message => {
    
                    if (message.partial) await message.fetch();
                    if (!message.guild) return;
    
                    for (let reactionObj of message.reactions.cache) {
                        for (let reaction of reactionObj) {
                            if (typeof reaction == "string") continue;
                            if (reaction.emoji.id != emojiID) continue;
                            reaction.users.fetch()
                                .then(async users => {
                                    users.forEach(async user => {
                                        if (user.bot) return;
                                        console.log("Adding role")
                                        await reaction.message.guild.members.cache.get(user.id).roles.add(roleID)
                                    })
                                })
                        }
                    }
    
                });
            })
            .catch(console.error);
    });
    

    您可能想进行一些更改,但这可行。

    分解它...

    1. 获取特定频道(或多个)中的消息
    2. 检查消息是否有反应
    3. 检查任何反应是否与特定表情符号匹配
    4. 将角色添加到公会成员
    5. 在尝试添加之前,可以选择检查成员是否已经拥有该角色

    请注意,此代码可能不是最有效的,但它可以完成工作。此外,它适用于“非自定义”表情符号,因为您必须检查 emoji.name 而不是 emoji.id。

    正如@michael.grigoryan 所建议的,强烈建议您查看文档。

    编辑:删除以前的答案,以消除混乱

    【讨论】:

      【解决方案3】:

      我做了一些测试,发现了一些很奇怪的东西。

      当您重新启动机器人并尝试对机器人重新启动之前发送的消息做出反应时,机器人不会记录反应。但是,如果您发送一条新消息并对其做出反应,机器人将突然开始记录所有消息的反应。

      我认为这与部分有关,但我不是那里的专家!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-22
        • 1970-01-01
        • 2021-09-04
        • 2020-08-03
        • 1970-01-01
        • 2020-09-26
        • 2021-04-18
        • 2020-08-06
        相关资源
        最近更新 更多