首页 > 解决方案 > Discord.py - 更改频道权限

问题描述

我现在正在开发一个小小的不和谐游戏。目标是口袋妖怪格斗游戏。

为此,一名玩家用 挑战另一名玩家?attack <name>。然后他有 30 秒的时间接受或拒绝挑战。

攻击命令:

@commands.command()
async def attack(self, ctx, member : Union[discord.Member, int] = None):

    with open("attack.json", "r") as f:
        data = json.load(f)

        attack_dict = {
            "player_1": 1,
            "player_2": 1,
            "attack_message": 1,
        }

        data[str(ctx.guild.id)] = attack_dict

        with open("attack.json", "w") as f:
            json.dump(data, f, indent=4)

        valid_reactions = ["✅&quot;, "❌&quot;]

        if member == ctx.message.author:

            embed = discord.Embed(
                title="You can not fight yourself!",
                color=0xf7fcfd
            )

            await ctx.send(embed=embed)
            return

        else:

            embed = discord.Embed(
                title=f"{ctx.message.author.name} wants to fight against {member.display_name}",
                description="Click on the check mark to accept the fight!",
                color=0xf7fcfd
            )

            message_fight_player = await ctx.send(embed=embed)
            await message_fight_player.add_reaction("✅&quot;)
            await message_fight_player.add_reaction("❌&quot;)

            def check(reaction, user):
                return user == member and user != ctx.author and user.bot is False and str(reaction.emoji) in valid_reactions

            try:

                reaction, user = await self.client.wait_for("reaction_add", timeout=30.0, check=check)

                if str(reaction.emoji) == "✅&quot;:

                    await message_fight_player.delete()

                    embed = discord.Embed(
                        title=f"{user.display_name} accepted the fight against {ctx.message.author.display_name}! :eyes:",
                        description="Click on the emoji to watch the fight!",
                        color=0xf7fcfd
                    )

                    message_accept_player = await ctx.send(embed=embed)

                    with open("attack.json", "r") as f:
                        data = json.load(f)

                        data[str(ctx.guild.id)]["player_1"] = ctx.message.author.id
                        data[str(ctx.guild.id)]["player_2"] = member.id
                        data[str(ctx.guild.id)]["attack_message"] = message_accept_player.id

                        with open("attack.json", "w") as f:
                            json.dump(data, f, indent=4)

                    await message_accept_player.add_reaction("")
                    await message_accept_player.delete(delay=30)

                    await asyncio.sleep(30)

                    with open("attack.json", "r") as f:
                        data = json.load(f)

                        del data[str(ctx.guild.id)]

                        with open("attack.json", "w") as f:
                            json.dump(data, f, indent=2)

                else:

                    await message_fight_player.delete()

                    with open("attack.json", "r") as f:
                        data = json.load(f)

                        del data[str(ctx.guild.id)]

                        with open("attack.json", "w") as f:
                            json.dump(data, f, indent=2)

                    embed = discord.Embed(
                        title=f"{member.display_name} did not want to fight against {ctx.message.author.name}! :thinking:",
                        color=0xf7fcfd
                    )

                    message_declare_player = await ctx.send(embed=embed)
                    await message_declare_player.delete(delay=10)

            except asyncio.TimeoutError:

                await message_fight_player.delete()

                embed = discord.Embed(
                    title=f"{member.display_name} did not want to fight against {ctx.message.author.name}! :thinking:",
                    color=0xf7fcfd
                )

                message_timeout_player = await ctx.send(embed=embed)
                await message_timeout_player.delete(delay=10)

                with open("attack.json", "r") as f:
                    data = json.load(f)

                    del data[str(ctx.guild.id)]

                    with open("attack.json", "w") as f:
                        json.dump(data, f, indent=2)

该命令工作正常,但现在问题来了,我想发送一条消息,表明战斗已被接受。然后应该在此消息中添加一个表情符号(),如果您单击此表情符号,您应该能够观看战斗。

我已经尝试过on_raw_reaction_add,但问题是每次有人点击表情符号时它都会创建一个新频道。

@commands.Cog.listener()
async def on_raw_reaction_add(self, payload):

    guild_id = payload.guild_id
    guild = self.client.get_guild(guild_id)

    user_id = payload.user_id
    user = self.client.get_user(user_id)

    channel_id = payload.channel_id
    channel = self.client.get_channel(channel_id)

    message_id = payload.message_id
    emoji = payload.emoji.name

    member = discord.utils.find(lambda m : m.id == payload.user_id, guild.members)

    try:

        with open("attack.json", "r") as jsonData:
            data = json.load(jsonData)

            attack_message_id = data[str(guild_id)]["attack_message"]
            player_1 = data[str(guild_id)]["player_1"]
            player_2 = data[str(guild_id)]["player_2"]

        if message_id == attack_message_id and emoji == "" and user.bot is False:

            message = await channel.fetch_message(message_id)
            await message.remove_reaction("",user)

            category = discord.utils.get(guild.categories, name = "Pokemon")

            if category is None:

                category = await guild.create_category(name="Pokemon")

            player_1_name = self.client.get_user(player_1)
            player_2_name = self.client.get_user(player_2)

            overwrites = {
                guild.default_role: discord.PermissionOverwrite(read_messages=False),
                player_1_name: discord.PermissionOverwrite(read_messages=True, send_messages=True),
                player_2_name: discord.PermissionOverwrite(read_messages=True, send_messages=True),
                member: discord.PermissionOverwrite(read_messages=True, send_messages=False)
            }

            attack_channel = await category.create_text_channel("⁉️ poke-fight", overwrites=overwrites)

    except:

        return

因此,每当有人点击表情符号时,我希望将该人添加到频道中。player_1与and相同player_2,但查看器应具有 read_messages = True 和 send_messages = False。

标签: pythonpython-3.xdiscorddiscord.py

解决方案


您专门使用在所有 raw_reaction_add(s) 上创建一个新的文本通道

attack_channel = await category.create_text_channel("⁉️ poke-fight", overwrites=overwrites)

据我所知,discord 没有将用户移动到其他文本频道的 bultin 功能,只有使用Closest 的语音await move_to(channel)频道 才能生成用户必须点击的频道的文本链接:

await channel.send(f'view fight in {attack_channel.mention}')


推荐阅读