Mostly messaging adjustments, fix for failing to talley votes
This commit is contained in:
		
							parent
							
								
									e27cfba763
								
							
						
					
					
						commit
						f3965b73d8
					
				| @ -10,13 +10,15 @@ from redbot.core.bot import Red | ||||
| from redbot.core.utils import AsyncIter | ||||
| 
 | ||||
| from werewolf.builder import parse_code | ||||
| from werewolf.constants import ALIGNMENT_NEUTRAL | ||||
| from werewolf.player import Player | ||||
| from werewolf.role import Role | ||||
| from werewolf.votegroup import VoteGroup | ||||
| 
 | ||||
| log = logging.getLogger("red.fox_v3.werewolf.game") | ||||
| 
 | ||||
| HALF_DAY_LENGTH = 24  # FixMe: to 120 later for 4 minute days | ||||
| HALF_DAY_LENGTH = 60  # FixMe: Make configurable | ||||
| HALF_NIGHT_LENGTH = 60 | ||||
| 
 | ||||
| 
 | ||||
| async def anyone_has_role( | ||||
| @ -167,7 +169,7 @@ class Game: | ||||
|                 await player.member.add_roles(*[self.game_role]) | ||||
|         except discord.Forbidden: | ||||
|             log.exception(f"Unable to add role **{self.game_role.name}**") | ||||
|             await ctx.send( | ||||
|             await ctx.maybe_send_embed( | ||||
|                 f"Unable to add role **{self.game_role.name}**\n" | ||||
|                 f"Bot is missing `manage_roles` permissions" | ||||
|             ) | ||||
| @ -210,7 +212,7 @@ class Game: | ||||
|                     category=self.channel_category, | ||||
|                 ) | ||||
|             except discord.Forbidden: | ||||
|                 await ctx.send( | ||||
|                 await ctx.maybe_send_embed( | ||||
|                     "Unable to create Game Channel and none was provided\n" | ||||
|                     "Grant Bot appropriate permissions or assign a game_channel" | ||||
|                 ) | ||||
| @ -225,7 +227,7 @@ class Game: | ||||
|                 ) | ||||
|             except discord.Forbidden as e: | ||||
|                 log.exception("Unable to rename Game Channel") | ||||
|                 await ctx.send("Unable to rename Game Channel, ignoring") | ||||
|                 await ctx.maybe_send_embed("Unable to rename Game Channel, ignoring") | ||||
| 
 | ||||
|             try: | ||||
|                 for target, ow in overwrite.items(): | ||||
| @ -235,7 +237,7 @@ class Game: | ||||
|                         target=target, overwrite=curr, reason="(BOT) New game of werewolf" | ||||
|                     ) | ||||
|             except discord.Forbidden: | ||||
|                 await ctx.send( | ||||
|                 await ctx.maybe_send_embed( | ||||
|                     "Unable to edit Game Channel permissions\n" | ||||
|                     "Grant Bot appropriate permissions to manage permissions" | ||||
|                 ) | ||||
| @ -406,14 +408,17 @@ class Game: | ||||
|         await vote_message.add_reaction("👎") | ||||
| 
 | ||||
|         await asyncio.sleep(15) | ||||
|         reaction_list = vote_message.reactions | ||||
| 
 | ||||
|         if True:  # TODO: Allow customizable vote history deletion. | ||||
|             await vote_message.delete() | ||||
|         # Refetch for reactions | ||||
|         vote_message = await self.village_channel.fetch_message(id=vote_message.id) | ||||
|         reaction_list = vote_message.reactions | ||||
| 
 | ||||
|         raw_up_votes = sum(p for p in reaction_list if p.emoji == "👍" and not p.me) | ||||
|         raw_down_votes = sum(p for p in reaction_list if p.emoji == "👎" and not p.me) | ||||
| 
 | ||||
|         if True:  # TODO: Allow customizable vote history deletion. | ||||
|             await vote_message.delete() | ||||
| 
 | ||||
|         # TODO: Support vote count modifying roles. (Need notify and count function) | ||||
|         voted_to_lynch = raw_down_votes > raw_up_votes | ||||
| 
 | ||||
| @ -492,13 +497,13 @@ class Game: | ||||
|             return | ||||
|         await self._notify("at_night_start") | ||||
| 
 | ||||
|         await asyncio.sleep(12)  # 2 minutes FixMe to 120 later | ||||
|         await asyncio.sleep(HALF_NIGHT_LENGTH)  # 2 minutes FixMe to 120 later | ||||
|         await self.village_channel.send( | ||||
|             embed=discord.Embed(title="**Two minutes of night remain...**") | ||||
|             embed=discord.Embed(title=f"**{HALF_NIGHT_LENGTH / 60} minutes of night remain...**") | ||||
|         ) | ||||
|         await asyncio.sleep(9)  # 1.5 minutes FixMe to 90 later | ||||
|         await asyncio.sleep(HALF_NIGHT_LENGTH)  # 1.5 minutes FixMe to 90 later | ||||
|         await self.village_channel.send( | ||||
|             embed=discord.Embed(title="**Thirty seconds until sunrise...**") | ||||
|             embed=discord.Embed(title=f"**{HALF_NIGHT_LENGTH / 60} minutes until sunrise...**") | ||||
|         ) | ||||
|         await asyncio.sleep(3)  # .5 minutes FixMe to 30 Later | ||||
| 
 | ||||
| @ -560,8 +565,7 @@ class Game: | ||||
|                 ) | ||||
|             else: | ||||
|                 embed.add_field( | ||||
|                     name=f"{i} - {status}{player.member.display_name}", | ||||
|                     inline=False, | ||||
|                     name=f"{i} - {status}{player.member.display_name}", inline=False, value="" | ||||
|                 ) | ||||
| 
 | ||||
|         return await channel.send(embed=embed) | ||||
| @ -585,16 +589,16 @@ class Game: | ||||
|         if votegroup is not None: | ||||
|             self.p_channels[channel_id]["votegroup"] = votegroup | ||||
| 
 | ||||
|     async def join(self, member: discord.Member, channel: discord.TextChannel): | ||||
|     async def join(self, ctx, member: discord.Member): | ||||
|         """ | ||||
|         Have a member join a game | ||||
|         """ | ||||
|         if self.started: | ||||
|             await channel.send("**Game has already started!**") | ||||
|             await ctx.maybe_send_embed("**Game has already started!**") | ||||
|             return | ||||
| 
 | ||||
|         if await self.get_player_by_member(member) is not None: | ||||
|             await channel.send(f"{member.display_name} is already in the game!") | ||||
|             await ctx.maybe_send_embed(f"{member.display_name} is already in the game!") | ||||
|             return | ||||
| 
 | ||||
|         self.players.append(Player(member)) | ||||
| @ -609,7 +613,7 @@ class Game: | ||||
|         #             f"Bot is missing `manage_roles` permissions" | ||||
|         #         ) | ||||
| 
 | ||||
|         await channel.send( | ||||
|         await ctx.maybe_send_embed( | ||||
|             f"{member.display_name} has been added to the game, " | ||||
|             f"total players is **{len(self.players)}**" | ||||
|         ) | ||||
| @ -645,15 +649,15 @@ class Game: | ||||
|         player = await self.get_player_by_member(ctx.author) | ||||
| 
 | ||||
|         if player is None: | ||||
|             await ctx.send("You're not in this game!") | ||||
|             await ctx.maybe_send_embed("You're not in this game!") | ||||
|             return | ||||
| 
 | ||||
|         if not player.alive: | ||||
|             await ctx.send("**Corpses** can't participate...") | ||||
|             await ctx.maybe_send_embed("**Corpses** can't participate...") | ||||
|             return | ||||
| 
 | ||||
|         if player.role.blocked: | ||||
|             await ctx.send("Something is preventing you from doing this...") | ||||
|             await ctx.maybe_send_embed("Something is preventing you from doing this...") | ||||
|             return | ||||
| 
 | ||||
|         # Let role do target validation, might be alternate targets | ||||
| @ -821,7 +825,7 @@ class Game: | ||||
|     async def set_code(self, ctx: commands.Context, game_code): | ||||
|         if game_code is not None: | ||||
|             self.game_code = game_code | ||||
|         await ctx.send("Code has been set") | ||||
|         await ctx.maybe_send_embed("Code has been set") | ||||
| 
 | ||||
|     async def get_roles(self, ctx, game_code=None): | ||||
|         if game_code is not None: | ||||
| @ -833,10 +837,12 @@ class Game: | ||||
|         try: | ||||
|             self.roles = await parse_code(self.game_code, self) | ||||
|         except ValueError as e: | ||||
|             await ctx.send("Invalid Code: Code contains unknown character\n{}".format(e)) | ||||
|             await ctx.maybe_send_embed( | ||||
|                 "Invalid Code: Code contains unknown character\n{}".format(e) | ||||
|             ) | ||||
|             return False | ||||
|         except IndexError as e: | ||||
|             await ctx.send("Invalid Code: Code references unknown role\n{}".format(e)) | ||||
|             await ctx.maybe_send_embed("Invalid Code: Code references unknown role\n{}".format(e)) | ||||
| 
 | ||||
|         if not self.roles: | ||||
|             return False | ||||
| @ -898,7 +904,8 @@ class Game: | ||||
|             self.game_over = True | ||||
|             alignment1 = alive_players[0].role.alignment | ||||
|             alignment2 = alive_players[1].role.alignment | ||||
|             if alignment1 == alignment2:  # Same team | ||||
|             # Same team and not neutral | ||||
|             if alignment1 == alignment2 and alignment1 != ALIGNMENT_NEUTRAL: | ||||
|                 winners = alive_players | ||||
|             else: | ||||
|                 winners = [max(alive_players, key=lambda p: p.role.alignment)] | ||||
|  | ||||
| @ -35,9 +35,13 @@ class Player: | ||||
| 
 | ||||
|     async def send_dm(self, message): | ||||
|         try: | ||||
|             await self.member.send(message)  # Lets do embeds later | ||||
|             await self.member.send(message)  # Lets ToDo embeds later | ||||
|         except discord.Forbidden: | ||||
|             log.info(f"Unable to mention {self.member.__repr__()}") | ||||
|             await self.role.game.village_channel.send( | ||||
|                 f"Couldn't DM {self.mention}, uh oh", | ||||
|                 allowed_mentions=discord.AllowedMentions(users=[self.member]), | ||||
|             ) | ||||
|         except AttributeError: | ||||
|             log.exception("Someone messed up and added a bot to the game (I think)") | ||||
|             await self.role.game.village_channel.send("Someone messed up and added a bot to the game :eyes:") | ||||
|  | ||||
| @ -72,9 +72,9 @@ class Werewolf(Cog): | ||||
|         code = await gb.build_game(ctx) | ||||
| 
 | ||||
|         if code != "": | ||||
|             await ctx.send(f"Your game code is **{code}**") | ||||
|             await ctx.maybe_send_embed(f"Your game code is **{code}**") | ||||
|         else: | ||||
|             await ctx.send("No code generated") | ||||
|             await ctx.maybe_send_embed("No code generated") | ||||
| 
 | ||||
|     @checks.guildowner() | ||||
|     @commands.group() | ||||
| @ -117,10 +117,10 @@ class Werewolf(Cog): | ||||
|         """ | ||||
|         if role is None: | ||||
|             await self.config.guild(ctx.guild).role_id.set(None) | ||||
|             await ctx.send("Cleared Game Role") | ||||
|             await ctx.maybe_send_embed("Cleared Game Role") | ||||
|         else: | ||||
|             await self.config.guild(ctx.guild).role_id.set(role.id) | ||||
|             await ctx.send("Game Role has been set to **{}**".format(role.name)) | ||||
|             await ctx.maybe_send_embed("Game Role has been set to **{}**".format(role.name)) | ||||
| 
 | ||||
|     @commands.guild_only() | ||||
|     @wwset.command(name="category") | ||||
| @ -130,14 +130,14 @@ class Werewolf(Cog): | ||||
|         """ | ||||
|         if category_id is None: | ||||
|             await self.config.guild(ctx.guild).category_id.set(None) | ||||
|             await ctx.send("Cleared Game Channel Category") | ||||
|             await ctx.maybe_send_embed("Cleared Game Channel Category") | ||||
|         else: | ||||
|             category = discord.utils.get(ctx.guild.categories, id=int(category_id)) | ||||
|             if category is None: | ||||
|                 await ctx.send("Category not found") | ||||
|                 await ctx.maybe_send_embed("Category not found") | ||||
|                 return | ||||
|             await self.config.guild(ctx.guild).category_id.set(category.id) | ||||
|             await ctx.send("Game Channel Category has been set to **{}**".format(category.name)) | ||||
|             await ctx.maybe_send_embed("Game Channel Category has been set to **{}**".format(category.name)) | ||||
| 
 | ||||
|     @commands.guild_only() | ||||
|     @wwset.command(name="channel") | ||||
| @ -147,10 +147,10 @@ class Werewolf(Cog): | ||||
|         """ | ||||
|         if channel is None: | ||||
|             await self.config.guild(ctx.guild).channel_id.set(None) | ||||
|             await ctx.send("Cleared Game Channel") | ||||
|             await ctx.maybe_send_embed("Cleared Game Channel") | ||||
|         else: | ||||
|             await self.config.guild(ctx.guild).channel_id.set(channel.id) | ||||
|             await ctx.send("Game Channel has been set to **{}**".format(channel.mention)) | ||||
|             await ctx.maybe_send_embed("Game Channel has been set to **{}**".format(channel.mention)) | ||||
| 
 | ||||
|     @commands.guild_only() | ||||
|     @wwset.command(name="logchannel") | ||||
| @ -160,10 +160,10 @@ class Werewolf(Cog): | ||||
|         """ | ||||
|         if channel is None: | ||||
|             await self.config.guild(ctx.guild).log_channel_id.set(None) | ||||
|             await ctx.send("Cleared Game Log Channel") | ||||
|             await ctx.maybe_send_embed("Cleared Game Log Channel") | ||||
|         else: | ||||
|             await self.config.guild(ctx.guild).log_channel_id.set(channel.id) | ||||
|             await ctx.send("Game Log Channel has been set to **{}**".format(channel.mention)) | ||||
|             await ctx.maybe_send_embed("Game Log Channel has been set to **{}**".format(channel.mention)) | ||||
| 
 | ||||
|     @commands.group() | ||||
|     async def ww(self, ctx: commands.Context): | ||||
| @ -181,9 +181,9 @@ class Werewolf(Cog): | ||||
|         """ | ||||
|         game = await self._get_game(ctx, game_code) | ||||
|         if not game: | ||||
|             await ctx.send("Failed to start a new game") | ||||
|             await ctx.maybe_send_embed("Failed to start a new game") | ||||
|         else: | ||||
|             await ctx.send("Game is ready to join! Use `[p]ww join`") | ||||
|             await ctx.maybe_send_embed("Game is ready to join! Use `[p]ww join`") | ||||
| 
 | ||||
|     @commands.guild_only() | ||||
|     @ww.command(name="join") | ||||
| @ -195,10 +195,27 @@ class Werewolf(Cog): | ||||
|         game: Game = await self._get_game(ctx) | ||||
| 
 | ||||
|         if not game: | ||||
|             await ctx.send("No game to join!\nCreate a new one with `[p]ww new`") | ||||
|             await ctx.maybe_send_embed("Failed to join a game!") | ||||
|             return | ||||
| 
 | ||||
|         await game.join(ctx.author, ctx.channel) | ||||
|         await game.join(ctx, ctx.author) | ||||
|         await ctx.tick() | ||||
| 
 | ||||
|     @commands.guild_only() | ||||
|     @commands.admin() | ||||
|     @ww.command(name="forcejoin") | ||||
|     async def ww_forcejoin(self, ctx: commands.Context, target: discord.Member): | ||||
|         """ | ||||
|         Force someone to join a game of Werewolf | ||||
|         """ | ||||
| 
 | ||||
|         game: Game = await self._get_game(ctx) | ||||
| 
 | ||||
|         if not game: | ||||
|             await ctx.maybe_send_embed("Failed to join a game!") | ||||
|             return | ||||
| 
 | ||||
|         await game.join(ctx, target) | ||||
|         await ctx.tick() | ||||
| 
 | ||||
|     @commands.guild_only() | ||||
| @ -213,7 +230,7 @@ class Werewolf(Cog): | ||||
|         game = await self._get_game(ctx) | ||||
| 
 | ||||
|         if not game: | ||||
|             await ctx.send("No game to join!\nCreate a new one with `[p]ww new`") | ||||
|             await ctx.maybe_send_embed("No game to join!\nCreate a new one with `[p]ww new`") | ||||
|             return | ||||
| 
 | ||||
|         await game.set_code(ctx, code) | ||||
| @ -239,7 +256,7 @@ class Werewolf(Cog): | ||||
|         """ | ||||
|         game = await self._get_game(ctx) | ||||
|         if not game: | ||||
|             await ctx.send("No game running, cannot start") | ||||
|             await ctx.maybe_send_embed("No game running, cannot start") | ||||
| 
 | ||||
|         if not await game.setup(ctx): | ||||
|             pass  # ToDo something? | ||||
| @ -257,13 +274,13 @@ class Werewolf(Cog): | ||||
|         #     await ctx.send("Cannot stop game from PM!") | ||||
|         #     return | ||||
|         if ctx.guild.id not in self.games or self.games[ctx.guild.id].game_over: | ||||
|             await ctx.send("No game to stop") | ||||
|             await ctx.maybe_send_embed("No game to stop") | ||||
|             return | ||||
| 
 | ||||
|         game = await self._get_game(ctx) | ||||
|         game.game_over = True | ||||
|         await game.current_action.cancel() | ||||
|         await ctx.send("Game has been stopped") | ||||
|         await ctx.maybe_send_embed("Game has been stopped") | ||||
| 
 | ||||
|     @commands.guild_only() | ||||
|     @ww.command(name="vote") | ||||
| @ -277,7 +294,7 @@ class Werewolf(Cog): | ||||
|             target_id = None | ||||
| 
 | ||||
|         if target_id is None: | ||||
|             await ctx.send("`id` must be an integer") | ||||
|             await ctx.maybe_send_embed("`id` must be an integer") | ||||
|             return | ||||
| 
 | ||||
|         # if ctx.guild is None: | ||||
| @ -294,7 +311,7 @@ class Werewolf(Cog): | ||||
|         game = await self._get_game(ctx) | ||||
| 
 | ||||
|         if game is None: | ||||
|             await ctx.send("No game running, cannot vote") | ||||
|             await ctx.maybe_send_embed("No game running, cannot vote") | ||||
|             return | ||||
| 
 | ||||
|         # Game handles response now | ||||
| @ -304,7 +321,7 @@ class Werewolf(Cog): | ||||
|         elif channel in (c["channel"] for c in game.p_channels.values()): | ||||
|             await game.vote(ctx.author, target_id, channel) | ||||
|         else: | ||||
|             await ctx.send("Nothing to vote for in this channel") | ||||
|             await ctx.maybe_send_embed("Nothing to vote for in this channel") | ||||
| 
 | ||||
|     @ww.command(name="choose") | ||||
|     async def ww_choose(self, ctx: commands.Context, data): | ||||
| @ -315,7 +332,7 @@ class Werewolf(Cog): | ||||
|         """ | ||||
| 
 | ||||
|         if ctx.guild is not None: | ||||
|             await ctx.send("This action is only available in DM's") | ||||
|             await ctx.maybe_send_embed("This action is only available in DM's") | ||||
|             return | ||||
|         # DM nonsense, find their game | ||||
|         # If multiple games, panic | ||||
| @ -323,7 +340,7 @@ class Werewolf(Cog): | ||||
|             if await game.get_player_by_member(ctx.author): | ||||
|                 break  # game = game | ||||
|         else: | ||||
|             await ctx.send("You're not part of any werewolf game") | ||||
|             await ctx.maybe_send_embed("You're not part of any werewolf game") | ||||
|             return | ||||
| 
 | ||||
|         await game.choose(ctx, data) | ||||
| @ -344,7 +361,7 @@ class Werewolf(Cog): | ||||
|             if from_name: | ||||
|                 await menu(ctx, from_name, DEFAULT_CONTROLS) | ||||
|             else: | ||||
|                 await ctx.send("No roles containing that name were found") | ||||
|                 await ctx.maybe_send_embed("No roles containing that name were found") | ||||
| 
 | ||||
|     @ww_search.command(name="alignment") | ||||
|     async def ww_search_alignment(self, ctx: commands.Context, alignment: int): | ||||
| @ -354,7 +371,7 @@ class Werewolf(Cog): | ||||
|             if from_alignment: | ||||
|                 await menu(ctx, from_alignment, DEFAULT_CONTROLS) | ||||
|             else: | ||||
|                 await ctx.send("No roles with that alignment were found") | ||||
|                 await ctx.maybe_send_embed("No roles with that alignment were found") | ||||
| 
 | ||||
|     @ww_search.command(name="category") | ||||
|     async def ww_search_category(self, ctx: commands.Context, category: int): | ||||
| @ -364,7 +381,7 @@ class Werewolf(Cog): | ||||
|             if pages: | ||||
|                 await menu(ctx, pages, DEFAULT_CONTROLS) | ||||
|             else: | ||||
|                 await ctx.send("No roles in that category were found") | ||||
|                 await ctx.maybe_send_embed("No roles in that category were found") | ||||
| 
 | ||||
|     @ww_search.command(name="index") | ||||
|     async def ww_search_index(self, ctx: commands.Context, idx: int): | ||||
| @ -374,23 +391,29 @@ class Werewolf(Cog): | ||||
|             if idx_embed is not None: | ||||
|                 await ctx.send(embed=idx_embed) | ||||
|             else: | ||||
|                 await ctx.send("Role ID not found") | ||||
|                 await ctx.maybe_send_embed("Role ID not found") | ||||
| 
 | ||||
|     async def _get_game(self, ctx: commands.Context, game_code=None) -> Union[Game, None]: | ||||
|         guild: discord.Guild = getattr(ctx, "guild", None) | ||||
| 
 | ||||
|         if guild is None: | ||||
|             # Private message, can't get guild | ||||
|             await ctx.send("Cannot start game from DM!") | ||||
|             await ctx.maybe_send_embed("Cannot start game from DM!") | ||||
|             return None | ||||
|         if guild.id not in self.games or self.games[guild.id].game_over: | ||||
|             await ctx.send("Starting a new game...") | ||||
|             await ctx.maybe_send_embed("Starting a new game...") | ||||
|             valid, role, category, channel, log_channel = await self._get_settings(ctx) | ||||
| 
 | ||||
|             if not valid: | ||||
|                 await ctx.send("Cannot start a new game") | ||||
|                 await ctx.maybe_send_embed("Cannot start a new game") | ||||
|                 return None | ||||
| 
 | ||||
|             who_has_the_role = await anyone_has_role(guild.members, role) | ||||
|             if who_has_the_role: | ||||
|                 await ctx.maybe_send_embed( | ||||
|                     f"Cannot continue, {who_has_the_role.display_name} already has the game role." | ||||
|                 ) | ||||
|                 return None | ||||
|             self.games[guild.id] = Game( | ||||
|                 self.bot, guild, role, category, channel, log_channel, game_code | ||||
|             ) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 bobloy
						bobloy