diff --git a/GameFiles/Game.py b/GameFiles/Game.py index b81b7a8..e0bfd50 100644 --- a/GameFiles/Game.py +++ b/GameFiles/Game.py @@ -81,6 +81,14 @@ class Game: def is_gm(self, user: discord.Member) -> bool: return self.get_gm_role() in user.roles + @started_only + def get_player_role_id(self) -> int: + return self.config["player_role"] + + @started_only + def get_player_role(self) -> discord.Role: + return self.guild.get_role(self.get_player_role_id()) + @started_only def get_game_category_id(self) -> int: return self.config["category"] @@ -89,6 +97,14 @@ class Game: def get_game_category(self) -> discord.CategoryChannel: return self.guild.get_channel(self.get_game_category_id()) + @started_only + def get_announcements_channel_id(self) -> int: + return self.config["announce_chan"] + + @started_only + def get_announcements_channel(self) -> discord.TextChannel: + return self.guild.get_channel(self.get_announcements_channel_id()) + @started_only def get_votes_channel_id(self) -> int: return self.config["votes_chan"] @@ -108,6 +124,16 @@ class Game: vote_count[self.config["vote"][str(player_id)]] += 1 return vote_count[True] > vote_count[False] + @started_only + def get_player_channel_id(self, player: Union[int, discord.Member]) -> int: + if isinstance(player, discord.Member): + player = player.id + return self.config["player_info"][str(player)]["channel"] + + @started_only + def get_player_channel(self, player: Union[int, discord.Member]) -> discord.TextChannel: + return self.guild.get_channel(self.get_player_channel_id(player)) + async def start(self, gm_role: discord.Role, player_role: discord.Role): if self.is_started(): raise ValueError("Game already started") @@ -193,6 +219,7 @@ class Game: "Do you want to elect the following government?", f":crown: <@{president}> as president", f":person_in_tuxedo: <@{chancellor}> as chancellor", + "You can vote by typing `!ja` or `!nein` in your channel" "", ] for player_id in self.get_players_id(): @@ -214,5 +241,28 @@ class Game: else: await (await self.get_votes_channel().fetch_message(self.config["vote"]["message"])).edit(content = message_content_str, allowed_mentions = discord.AllowedMentions.none()) + @vote_running + async def cast_vote(self, user: discord.Member, vote: Union[bool, None]): + logging.debug(f"[{self.guild.name}] Casting vote with value {vote} for user {user.display_name}") + self.config["vote"][str(user.id)] = vote + await self.update_vote_message() + self.save_function() - + @vote_running + async def stop_vote(self): + logging.debug(f"[{self.guild.name}] Stopping the vote") + passed = self.is_vote_passing() + self.config["vote"]["revealed"] = True + await self.update_vote_message() + await self.get_votes_channel().send("**The vote has ended**") + announcement_content = [ + f"{self.get_player_role().mention} the vote has ended!", + f"{':green_square:' if passed else ':red_square:'} The vote has **{'' if passed else 'not '}passed**" + ] + if passed: + president = self.config["vote"]["president"] + chancellor = self.config["vote"]["chancellor"] + announcement_content.append(f"Congratulations to president <@{president}> and chancellor <@{chancellor}>!") + await self.get_announcements_channel().send("\n".join(announcement_content), allowed_mentions = discord.AllowedMentions(roles = True)) + self.config["vote"] = None + self.save_function() diff --git a/SecretBot.py b/SecretBot.py index d6492a7..c96e817 100755 --- a/SecretBot.py +++ b/SecretBot.py @@ -85,6 +85,15 @@ class SecretBot(commands.Cog): await ctx.reply(f":dragon_face: You have no power here!") raise utils.CheckFailDoNotNotify + async def check_is_administrator_or_gm(self, ctx: commands.Context): + """ + If the user that sent the command is not either an administrator of the server or a gm of the game, notify them and raise utils.CheckFailDoNotNotify. + """ + game = self.games_file[ctx.guild] + if not (utils.is_administrator(ctx.author) or (game.is_started() and game.is_gm(ctx.author))): + await ctx.reply(f":dragon_face: You have no power here!") + raise utils.CheckFailDoNotNotify + @commands.command(help = "See if I'm alive") async def ping(self, ctx: commands.Context): await ctx.reply(":ping_pong:", mention_author = True) @@ -104,18 +113,17 @@ class SecretBot(commands.Cog): async def delete_game(self, ctx: commands.Context): game = self.games_file[ctx.guild] if game.is_started(): - if game.is_gm(ctx.author) or utils.is_administrator(ctx.author): - gm_role = game.get_gm_role() - await game.delete() - await ctx.guild.get_member(self.bot.user.id).remove_roles(gm_role) - await ctx.reply(":white_check_mark: Game deleted!") - else: - await ctx.reply(f":dragon_face: You have no power here!") + await self.check_is_administrator_or_gm(ctx) + gm_role = game.get_gm_role() + await game.delete() + await ctx.guild.get_member(self.bot.user.id).remove_roles(gm_role) + await ctx.reply(":white_check_mark: Game deleted!") else: await ctx.reply(":x: Game is not running") @commands.command("StartVote") - async def start_vote(self, ctx:commands.Context, president: discord.Member, chancellor: discord.Member): + async def start_vote(self, ctx: commands.Context, president: discord.Member, chancellor: discord.Member): + await self.check_is_administrator_or_gm(ctx) game = self.games_file[ctx.guild] if not game.is_started(): await ctx.reply(":x: Game is not running") @@ -126,6 +134,41 @@ class SecretBot(commands.Cog): await game.start_vote(president, chancellor) await ctx.message.delete() + async def cast_vote(self, ctx: commands.Context, vote: bool): + game = self.games_file[ctx.guild] + if game.is_started() and game.is_vote_running(): + if ctx.author.id in game.get_players_id(): + if ctx.channel == game.get_player_channel(ctx.author): + await game.cast_vote(ctx.author, vote) + await ctx.reply(":pencil: Your vote has been registered. Thank you citizen.") + else: + await ctx.reply(":x: Please cast your vote in your dedicated channel.") + else: + await ctx.reply(":x: Only players can cast votes") + else: + await ctx.reply(":x: There isn't a vote running") + + @commands.command("ja") + async def vote_yes(self, ctx: commands.Context): + await self.cast_vote(ctx, True) + + @commands.command("nein") + async def vote_no(self, ctx: commands.Context): + await self.cast_vote(ctx, False) + + @commands.command("StopTheCount") + async def stop_vote(self, ctx: commands.Context): + await self.check_is_administrator_or_gm(ctx) + game = self.games_file[ctx.guild] + if not game.is_started(): + await ctx.reply(":x: Game is not running") + return + if not game.is_vote_running(): + await ctx.reply(":x: No vote is running") + return + await game.stop_vote() + await ctx.message.delete() + if __name__ == '__main__': argparser = argparse.ArgumentParser(description = "Secret Hitler helper bot", formatter_class = argparse.ArgumentDefaultsHelpFormatter)