From ef65c2dda630b8dac9613ab1b9f6f05e03cb0b48 Mon Sep 17 00:00:00 2001 From: Elnath Date: Sat, 12 Jun 2021 20:54:55 +0200 Subject: [PATCH] GM and observer roles created by the bot on game start --- GameFiles/Game.py | 38 ++++++++++++++++++++++++++++++++++---- SecretBot.py | 7 ++----- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/GameFiles/Game.py b/GameFiles/Game.py index 235aac5..d6c7f5e 100644 --- a/GameFiles/Game.py +++ b/GameFiles/Game.py @@ -117,6 +117,14 @@ class Game: def get_player_role(self) -> discord.Role: return self.guild.get_role(self.get_player_role_id()) + @game_started + def get_observer_role_id(self) -> int: + return self.config["observer_role"] + + @game_started + def get_observer_role(self) -> discord.Role: + return self.guild.get_role(self.get_observer_role_id()) + @game_started def get_game_category_id(self) -> int: return self.config["category"] @@ -171,13 +179,12 @@ class Game: return self.guild.get_channel(self.get_player_channel_id(player)) @save_on_success - async def start(self, gm_role: discord.Role, player_role: discord.Role): + async def start(self, player_role: discord.Role, bot_user_id: int): if self.is_started(): raise ValueError("Game already started") logger.info(f"[{self.guild.name}] Starting game") tasks = [] # Asyncio tasks scheduled to run in parallel (e.g. channel creation), so that we can wait them all at the end of the function self.config["game_started"] = True - self.config["gm_role"] = gm_role.id self.config["player_role"] = player_role.id self.config["players"] = [member.id for member in player_role.members] self.config["player_info"] = {str(player): {} for player in self.config["players"]} @@ -188,10 +195,19 @@ class Game: self.config["drawn"] = None self.config["enacted"] = [] + gm_role = await self.guild.create_role(name = "GM", hoist = True, mentionable = True, permissions = self.guild.default_role.permissions) + self.config["gm_role"] = gm_role.id + await self.guild.get_member(bot_user_id).add_roles(gm_role) # Need to be here otherwise the bot won't have the permissions needed to set up private channels + logger.debug("Created GM role") + observer_role = await self.guild.create_role(name = "Observer", mentionable = True, permissions = self.guild.default_role.permissions) + self.config["observer_role"] = observer_role.id + logger.debug("Created Observer role") + category_permissions = { self.guild.default_role: discord.PermissionOverwrite(send_messages = False), gm_role: discord.PermissionOverwrite(send_messages = True), player_role: discord.PermissionOverwrite(send_messages = True), + observer_role: discord.PermissionOverwrite(send_messages = False, read_messages = True), } game_category = await self.guild.create_category("In-game", overwrites = category_permissions) self.config["category"] = game_category.id @@ -221,21 +237,32 @@ class Game: tasks.append(asyncio.create_task(create_announcements_and_vote_chans())) async def create_discussion_chan(): - # Permissions are inherited from the category + # Permissions are inherited from the category so they are synced to it self.config["discussion_chan"] = (await game_category.create_text_channel("discussion", position = 3)).id # Permissions are inherited from the category logger.debug(f"[{self.guild.name}] Created discussion channel") tasks.append(asyncio.create_task(create_discussion_chan())) + async def create_observers_chan(): + perms = { + self.guild.default_role: discord.PermissionOverwrite(read_messages = False), + gm_role: discord.PermissionOverwrite(read_messages = True), + observer_role: discord.PermissionOverwrite(read_messages = True), + } + self.config["observer_chan"] = (await game_category.create_text_channel("observers", overwrites = perms, position = 4)).id + logger.debug(f"[{self.guild}] Created observers channel") + tasks.append(asyncio.create_task(create_observers_chan())) + async def create_player_channel(player: discord.Member, position: int): perms = { self.guild.default_role: discord.PermissionOverwrite(read_messages = False), player: discord.PermissionOverwrite(read_messages = True), gm_role: discord.PermissionOverwrite(read_messages = True), + observer_role: discord.PermissionOverwrite(read_messages = True, send_messages = False), } self.config["player_info"][str(player.id)]["channel"] = (await game_category.create_text_channel(player.name, overwrites = perms, position = position)).id logger.debug(f"[{self.guild.name}] Created channel for player {player.name}") for i, player in enumerate(player_role.members): - tasks.append(asyncio.create_task(create_player_channel(player, 4+i))) + tasks.append(asyncio.create_task(create_player_channel(player, 5 + i))) await asyncio.wait(tasks) @@ -245,8 +272,11 @@ class Game: category = self.get_game_category() await asyncio.wait([channel.delete() for channel in category.channels]) await category.delete() + # Need to delete the roles last + await asyncio.wait([self.get_gm_role().delete(), self.get_observer_role().delete()]) self.config.clear() self.config.update(self.new_dict()) + logger.debug(f"[{self.guild.name}] Game deleted") @save_on_success async def start_vote(self, president: discord.Member, chancellor: discord.Member): diff --git a/SecretBot.py b/SecretBot.py index fedf18d..c1a7087 100755 --- a/SecretBot.py +++ b/SecretBot.py @@ -172,14 +172,13 @@ class SecretBot(commands.Cog): await ctx.reply(":ping_pong:", mention_author = True) @commands.command("StartGame") - async def start_game(self, ctx: commands.Context, gm_role: discord.Role, player_role: discord.Role): + async def start_game(self, ctx: commands.Context, player_role: discord.Role): await self.check_is_administrator(ctx) game = self.games_file[ctx.guild] if game.is_started(): await ctx.reply(":x: a game is already running") else: - await ctx.guild.get_member(self.bot.user.id).add_roles(gm_role) - await game.start(gm_role, player_role) + await game.start(player_role, self.bot.user.id) await ctx.reply(":white_check_mark: Game started!") @commands.command("DeleteGame", help = "Delete a running game and all of its associated channels") @@ -190,9 +189,7 @@ class SecretBot(commands.Cog): async def delete_game(self, ctx: commands.Context): game = await self.get_running_game_or_error_message(ctx) - gm_role = game.get_gm_role() await game.delete() - await ctx.guild.get_member(self.bot.user.id).remove_roles(gm_role) try: await ctx.reply(":white_check_mark: Game deleted!") except discord.NotFound: # If the command is executed in a game channel, then the channel won't exist anymore for the reply