v12 不会删除机器人的反应,但 v13 会删除机器人的反应 (discord.js)

Posted

技术标签:

【中文标题】v12 不会删除机器人的反应,但 v13 会删除机器人的反应 (discord.js)【英文标题】:v12 doesn't remove bot's react, but v13 remove bot's react (discord.js) 【发布时间】:2021-10-10 07:20:20 【问题描述】:

命令从v12升级到v13的过程中,我发现命令去掉了它自己创建的bot反应,而v12没有。

两个机器人都有管理员权限。 来自djs-games module、game connect four 的 v12。我将 v12 改进为 v13

v12:

const discord = require('discord.js')

class ConnectFour 

    constructor() 
        this.gameEmbed = null
    

    startGame (msg) 

        const challenger = msg.author;
        const oppenent = msg.mentions.users.first();

        if(!oppenent) return msg.channel.send(`**With whom do you wanna play Connect Four?**`)
         
        const board = [
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
        ];

        const renderBoard = (board) => 
            let tempString = "";
            for (const boardSection of board) 
                tempString += `$boardSection.join("")\n`;
            

            tempString = tempString.concat("1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣");
            return tempString;
        

        const initialState = renderBoard(board);

        const initial = new discord.MessageEmbed()
        .setTitle(`???? $msg.author.username its your turn!`)
        .setDescription(initialState)
        .setFooter(`$challenger.username vs $oppenent.username`)
        msg.channel.send(initial).then(gameMessage => 

            gameMessage.react("1️⃣")
            gameMessage.react("2️⃣")
            gameMessage.react("3️⃣")
            gameMessage.react("4️⃣")
            gameMessage.react("5️⃣")
            gameMessage.react("6️⃣")
            gameMessage.react("7️⃣")
    
            const gameFilter = (reaction, user) => ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣"].includes(reaction.emoji.name) && (user.id === oppenent.id || user.id === challenger.id);
    
            const gameCollector = gameMessage.createReactionCollector(gameFilter);
    
            const gameData = [
                 member: challenger, playerColor: "????" ,
                 member: oppenent, playerColor: "????"
            ]
    
            let player = 0;
    
            const checkFour = (a, b, c, d) => (a === b) && (b === c) && (c === d) && (a !== "⚪");
    
            const horizontalCheck = () => 
    
                for (let i = 0; i < 6; i++) 
    
                    for (let j = 0; j < 4; j++) 
                        if(checkFour(board[i][j], board[i][j + 1], board[i][j + 2], board[i][j + 3])) return [
                            board[i][j], board[i][j + 1], board[i][j + 2], board[i][j + 3]
                        ];
                    
                
            
    
            const verticalCheck = () => 
                for (let j = 0; j < 7; j++) 
                    for (let i = 0; i < 3; i++) 
    
                        if(checkFour(board[i][j], board[i + 1][j], board[i + 2][j], board[i + 3][j])) return [
                            board[i][j], board[i + 1][j], board[i + 2][j], board[i + 3][j]
                        ]
                    
                
            
    
            const diagonal1 = () => 
                for (let col = 0; col < 4; col++) 
                    for (let row = 0; row < 3; row++) 
                        if(checkFour(board[row][col], board[row + 1][col + 1], board[row + 2][col + 2], board[row + 3][col + 3])) return [
                            board[row][col], board[row + 1][col + 1], board[row + 2][col + 2], board[row + 3][col + 3]
                        ]
                    
                
            
    
            const diagonal2 = () => 
                for (let col = 0; col < 4; col++) 
                    for (let row = 5; row > 2; row--) 
                        if(checkFour(board[row][col], board[row - 1][col + 1], board[row - 2][col + 2], board[row - 3][col + 3])) return [
                            board[row][col], board[row - 1][col + 1], board[row - 2][col + 2], board[row - 3][col + 3]
                        ]
                    
                
            
    
            const tieCheck = () => 
                let count = 0;
                for (const el of board) 
                    for (const string of el) 
                        if(string !== "⚪") count++;
                    
                
                if(count === 42) return true;
                else return false;
            
    
            const checks = [horizontalCheck, verticalCheck, diagonal1, diagonal2];
    
            gameCollector.on("collect", (reaction, user) => 
    
                reaction.message.reactions.cache.get(reaction.emoji.name).users.remove(user.id);
    
                if(user.id === gameData[player].member.id) 
    
                    const openSpaces = [];
    
                    switch (reaction.emoji.name) 
                        case "1️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][0] === "⚪") openSpaces.push( i, j: 0);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "2️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][1] === "⚪") openSpaces.push( i, j: 1);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "3️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][2] === "⚪") openSpaces.push( i, j: 2);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "4️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][3] === "⚪") openSpaces.push( i, j: 3);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "5️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][4] === "⚪") openSpaces.push( i, j: 4);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "6️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][5] === "⚪") openSpaces.push( i, j: 5);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "7️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][6] === "⚪") openSpaces.push( i, j: 6);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                    
    
                    if(tieCheck()) 
                        gameMessage.reactions.removeAll()
                        const TieEmbed = new discord.MessageEmbed()
                        .setTitle(`The game ended, it is Tie!`)
                        .setDescription(renderBoard(board))
                        .setFooter(`$challenger.username vs $oppenent.username`)
                        gameCollector.stop("Tie Game")
                        return gameMessage.edit(TieEmbed)
                    
    
                    for (const func of checks) 
    
                        const data = func();
                        if(data) 
                            gameMessage.reactions.removeAll()
    
                            const WinEmbed = new discord.MessageEmbed()
                            .setTitle(`$gameData[player].member.username has won the game!`)
                            .setDescription(renderBoard(board))
                            .setFooter(`$challenger.username vs $oppenent.username`)
                            gameCollector.stop(`$gameData[player].member.id won`);
                            return gameMessage.edit(WinEmbed)
                        
                    
    
                    player = (player + 1) % 2;
    
                    const newEmbed = new discord.MessageEmbed()
                    .setTitle(`$gameData[player].playerColor - $gameData[player].member.username its your turn!`)
                    .setDescription(renderBoard(board))
                    .setFooter(`$challenger.username vs $oppenent.username`)
                    gameMessage.edit("",  embed: newEmbed);
                
            )
        )

    




module.exports = ConnectFour;

v13:

const discord = require('discord.js')

class ConnectFour 

    constructor() 
        this.gameEmbed = null
    

    startGame (msg) 

        const challenger = msg.author;
        const oppenent = msg.mentions.users.first();

        if(!oppenent) return msg.channel.send(`**With whom do you wanna play Connect Four?**`)
         
        const board = [
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
            ["⚪", "⚪", "⚪", "⚪", "⚪", "⚪", "⚪"],
        ];

        const renderBoard = (board) => 
            let tempString = "";
            for (const boardSection of board) 
                tempString += `$boardSection.join("")\n`;
            

            tempString = tempString.concat("1️⃣2️⃣3️⃣4️⃣5️⃣6️⃣7️⃣");
            return tempString;
        

        const initialState = renderBoard(board);

        const initial = new discord.MessageEmbed()
        .setTitle(`???? $msg.author.username its your turn!`)
        .setDescription(initialState)
        .setFooter(`$challenger.username vs $oppenent.username`)
        msg.channel.send(embeds : [initial]).then(gameMessage => 

            gameMessage.react("1️⃣")
            gameMessage.react("2️⃣")
            gameMessage.react("3️⃣")
            gameMessage.react("4️⃣")
            gameMessage.react("5️⃣")
            gameMessage.react("6️⃣")
            gameMessage.react("7️⃣")
    
            const gameFilter = (reaction, user) => ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣"].includes(reaction.emoji.name) && (user.id === oppenent.id || user.id === challenger.id);
    
            const gameCollector = gameMessage.createReactionCollector(gameFilter);
    
            const gameData = [
                 member: challenger, playerColor: "????" ,
                 member: oppenent, playerColor: "????"
            ]
    
            let player = 0;
    
            const checkFour = (a, b, c, d) => (a === b) && (b === c) && (c === d) && (a !== "⚪");
    
            const horizontalCheck = () => 
    
                for (let i = 0; i < 6; i++) 
    
                    for (let j = 0; j < 4; j++) 
                        if(checkFour(board[i][j], board[i][j + 1], board[i][j + 2], board[i][j + 3])) return [
                            board[i][j], board[i][j + 1], board[i][j + 2], board[i][j + 3]
                        ];
                    
                
            
    
            const verticalCheck = () => 
                for (let j = 0; j < 7; j++) 
                    for (let i = 0; i < 3; i++) 
    
                        if(checkFour(board[i][j], board[i + 1][j], board[i + 2][j], board[i + 3][j])) return [
                            board[i][j], board[i + 1][j], board[i + 2][j], board[i + 3][j]
                        ]
                    
                
            
    
            const diagonal1 = () => 
                for (let col = 0; col < 4; col++) 
                    for (let row = 0; row < 3; row++) 
                        if(checkFour(board[row][col], board[row + 1][col + 1], board[row + 2][col + 2], board[row + 3][col + 3])) return [
                            board[row][col], board[row + 1][col + 1], board[row + 2][col + 2], board[row + 3][col + 3]
                        ]
                    
                
            
    
            const diagonal2 = () => 
                for (let col = 0; col < 4; col++) 
                    for (let row = 5; row > 2; row--) 
                        if(checkFour(board[row][col], board[row - 1][col + 1], board[row - 2][col + 2], board[row - 3][col + 3])) return [
                            board[row][col], board[row - 1][col + 1], board[row - 2][col + 2], board[row - 3][col + 3]
                        ]
                    
                
            
    
            const tieCheck = () => 
                let count = 0;
                for (const el of board) 
                    for (const string of el) 
                        if(string !== "⚪") count++;
                    
                
                if(count === 42) return true;
                else return false;
            
    
            const checks = [horizontalCheck, verticalCheck, diagonal1, diagonal2];
    
            gameCollector.on("collect", (reaction, user) => 
    
                reaction.message.reactions.cache.get(reaction.emoji.name).users.remove(user.id);
    
                if(user.id === gameData[player].member.id) 
    
                    const openSpaces = [];
    
                    switch (reaction.emoji.name) 
                        case "1️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][0] === "⚪") openSpaces.push( i, j: 0);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "2️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][1] === "⚪") openSpaces.push( i, j: 1);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "3️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][2] === "⚪") openSpaces.push( i, j: 2);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "4️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][3] === "⚪") openSpaces.push( i, j: 3);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "5️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][4] === "⚪") openSpaces.push( i, j: 4);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "6️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][5] === "⚪") openSpaces.push( i, j: 5);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                        case "7️⃣":
                            for (let i = 5; i > -1 ; i--) 
                                if(board[i][6] === "⚪") openSpaces.push( i, j: 6);
                            
                            if(openSpaces.length == 0) return msg.channel.send(`**$gameData[player].member, that column is already full. Choose another one**`).then(msg1 => msg1.delete(timeout: 10000))
                            else board[openSpaces[0].i][openSpaces[0].j] = gameData[player].playerColor;
                        break;
                    
    
                    if(tieCheck()) 
                        gameMessage.reactions.removeAll()
                        const TieEmbed = new discord.MessageEmbed()
                        .setTitle(`The game ended, it is Tie!`)
                        .setDescription(renderBoard(board))
                        .setFooter(`$challenger.username vs $oppenent.username`)
                        gameCollector.stop("Tie Game")
                        return gameMessage.edit(embeds : [TieEmbed])
                    
    
                    for (const func of checks) 
    
                        const data = func();
                        if(data) 
                            gameMessage.reactions.removeAll()
    
                            const WinEmbed = new discord.MessageEmbed()
                            .setTitle(`$gameData[player].member.username has won the game!`)
                            .setDescription(renderBoard(board))
                            .setFooter(`$challenger.username vs $oppenent.username`)
                            gameCollector.stop(`$gameData[player].member.id won`);
                            return gameMessage.edit(embeds : [WinEmbed])
                        
                    
    
                    player = (player + 1) % 2;
    
                    const newEmbed = new discord.MessageEmbed()
                    .setTitle(`$gameData[player].playerColor - $gameData[player].member.username its your turn!`)
                    .setDescription(renderBoard(board))
                    .setFooter(`$challenger.username vs $oppenent.username`)
                    gameMessage.edit(embed: [newEmbed]);
                
            )
        )

    




module.exports = ConnectFour;

输出:

我认为它的原因是:

reaction.message.reactions.cache.get(reaction.emoji.name).users.remove(user.id); //line 122

在 v13 中,机器人自动删除了它自己创建的自己的反应。 我希望机器人不会像那样自动删除,以便用户可以轻松交互。

如果有任何错误,请原谅我,因为我是这种编程语言的新手。

谢谢!

【问题讨论】:

【参考方案1】:

所以要让它在 discord.js v13 上运行,我必须做一些事情。

要收集公会用户的反应,您需要GUILD_MESSAGE_REACTIONS 意图。所以我将其添加到我的client 的意图中。

const client = new Discord.Client( intents: ["GUILDS", "GUILD_MESSAGES", "GUILD_MESSAGE_REACTIONS"] );

接下来,他们更改了您为 Message.createReactionCollector() 指定过滤器的方式。所以我相应地更新了代码。

const gameCollector = gameMessage.createReactionCollector( filter: gameFilter );

最后,要编辑带有嵌入的消息,您需要将newEmbed 放在MessageEditOptions 属性embeds 的数组中。您在embeds 末尾缺少“s”,这可能是一个错误,因为您在其他任何地方都正确使用了它。

gameMessage.edit(embeds: [newEmbed]);

结果是一个运行良好的游戏:)

【讨论】:

以上是关于v12 不会删除机器人的反应,但 v13 会删除机器人的反应 (discord.js)的主要内容,如果未能解决你的问题,请参考以下文章

不和谐白名单 discord.js v13 [关闭]

Discord.js v12 如何获取对特定消息做出反应的人的 id?

对反应角色不和谐机器人有问题

Discord js v12 如果有人对嵌入做出反应,则发送消息

Discord.js V12 粗鲁的话过滤器不起作用

如何在 V13 中为 discord.js 上的成员分配角色?