user14200689
user14200689

Reputation:

Discord.py - Change Channel Permissions

I am working on a litte discord game right now. The goal is a pokemon fight game.

To do this, a player challenges another player with ?attack <name>. He then has 30 seconds to accept or decline the challenge.

The attack-command:

@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 = ["✅", "❌"]

        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("✅")
            await message_fight_player.add_reaction("❌")

            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) == "✅":

                    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)

The command works fine, but now comes the problem, I want to send a message that the fight has been accepted. An emoji (👀) should then be added to this message, if you click on this emoji you should be able to watch the fight.

I've tried that with on_raw_reaction_add, but the problem is that it creates a new channel every time someone clicks the emoji.

@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

So whenever someone clicks on the emoji, I want that person to be added to the channel. Same as player_1 and player_2, but the viewer should have read_messages = True and send_messages = False.

Upvotes: 0

Views: 562

Answers (1)

TheV
TheV

Reputation: 63

You specifically create a new text channel on all 👀 raw_reaction_add(s) using

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

as far as I know discord doesn't have a bultin function to move users to other text channels, only voice channels using await move_to(channel) Closest you could get is to generate a text link to the channel that the user will have to click:

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

Upvotes: 1

Related Questions