diff --git a/gwendolyn/cogs/event_cog.py b/gwendolyn/cogs/event_cog.py index 9fd379a..525a9b6 100644 --- a/gwendolyn/cogs/event_cog.py +++ b/gwendolyn/cogs/event_cog.py @@ -29,11 +29,6 @@ class EventCog(commands.Cog): """Log when an error occurs.""" await self.bot.error_handler.on_error(method) - @commands.Cog.listener() - async def on_reaction_add(self, reaction, user): - """Handle when someone reacts to a message.""" - await self.bot.event_handler.on_reaction_add(reaction, user) - @commands.Cog.listener() async def on_component(self, ctx): """Handle when someone reacts to a message.""" diff --git a/gwendolyn/cogs/game_cog.py b/gwendolyn/cogs/game_cog.py index 76a9d9d..4388dd4 100644 --- a/gwendolyn/cogs/game_cog.py +++ b/gwendolyn/cogs/game_cog.py @@ -105,11 +105,6 @@ class ConnectFourCog(commands.Cog): """Start a game of connect four against Gwendolyn.""" await self.bot.games.connect_four.start(ctx, difficulty) - @cog_ext.cog_subcommand(**params["connect_four_surrender"]) - async def connect_four_surrender(self, ctx): - """Surrender the game of connect four.""" - await self.bot.games.connect_four.surrender(ctx) - class HangmanCog(commands.Cog): """Contains all the hangman commands.""" diff --git a/gwendolyn/funcs/games/connect_four.py b/gwendolyn/funcs/games/connect_four.py index 7dc0322..4e1938a 100644 --- a/gwendolyn/funcs/games/connect_four.py +++ b/gwendolyn/funcs/games/connect_four.py @@ -15,7 +15,13 @@ import discord # Used for typehints, discord.file and to check whether # the opponent in ConnectFour.start is a discord.User from PIL import Image, ImageDraw, ImageFont # Used by DrawConnectFour() -from discord_slash.context import SlashContext # Used for typehints +from discord_slash.context import SlashContext, ComponentContext # Used for +# typehints +from discord_slash.utils.manage_components import (create_button, +create_actionrow) +from discord_slash.model import ButtonStyle + +from gwendolyn.utils import encode_id ROWCOUNT = 6 COLUMNCOUNT = 7 @@ -37,7 +43,7 @@ class ConnectFour(): """Initialize the class.""" self.bot = bot self.draw = DrawConnectFour(bot) - self.database_funcs = self.bot.database_funcs + self.get_name = self.bot.database_funcs.get_name # pylint: disable=invalid-name self.AISCORES = { "middle": 3, @@ -49,9 +55,41 @@ class ConnectFour(): "win": 10000, "avoid losing": 100 } - self.REACTIONS = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣"] # pylint: enable=invalid-name + def _encode_board_string(self, board: list): + string = [str(i) for row in board for i in row] + + while len(string) > 0 and string[0] == "0": + string = string[1:] + + if string == "": + string = "0" + + dec = 0 + for i, digit in enumerate(string[::-1]): + dec += (3**i)*int(digit) + + return str(dec) + + def _decode_board_string(self, board_string: str): + dec = int(board_string) + string = [] + while dec: + string.append(str(dec % 3)) + dec = dec // 3 + + while len(string) < ROWCOUNT * COLUMNCOUNT: + string.append("0") + + string = string[::-1] + + board = [ + [int(x) for x in string[i*COLUMNCOUNT:i*COLUMNCOUNT+COLUMNCOUNT]] + for i in range(ROWCOUNT)] + + return board + async def start(self, ctx: SlashContext, opponent: Union[int, discord.User]): """ @@ -68,23 +106,18 @@ class ConnectFour(): searches when minimaxing. """ await self.bot.defer(ctx) - user = f"#{ctx.author.id}" + user = ctx.author.id channel = str(ctx.channel_id) - game = self.bot.database["connect 4 games"].find_one({"_id": channel}) started_game = False can_start = True - if game is not None: - send_message = self.bot.long_strings["Connect 4 going on"] - log_message = "There was already a game going on" - can_start = False - elif isinstance(opponent, int): + if isinstance(opponent, int): # Opponent is Gwendolyn if opponent in range(1, 6): difficulty = int(opponent) difficulty_text = f" with difficulty {difficulty}" - opponent = f"#{self.bot.user.id}" + opponent = self.bot.user.id else: send_message = "Difficulty doesn't exist" log_message = "They challenged a difficulty that doesn't exist" @@ -96,7 +129,7 @@ class ConnectFour(): # It was Gwendolyn difficulty = 3 difficulty_text = f" with difficulty {difficulty}" - opponent = f"#{self.bot.user.id}" + opponent = self.bot.user.id else: send_message = "You can't challenge a bot!" log_message = "They tried to challenge a bot" @@ -104,7 +137,7 @@ class ConnectFour(): else: # Opponent is another player if ctx.author != opponent: - opponent = f"#{opponent.id}" + opponent = opponent.id difficulty = 5 difficulty_text = "" else: @@ -117,26 +150,13 @@ class ConnectFour(): players = [user, opponent] random.shuffle(players) - new_game = { - "_id": channel, - "board": board, - "winner": 0, - "win direction": "", - "win coordinates": [0, 0], - "players": players, - "turn": 0, - "difficulty": difficulty - } + self.draw.draw_image(channel, board, 0, [0,0], "", players) - self.bot.database["connect 4 games"].insert_one(new_game) - - self.draw.draw_image(channel) - - gwendolyn_turn = (players[0] == f"#{self.bot.user.id}") + gwendolyn_turn = (players[0] == self.bot.user.id) started_game = True - opponent_name = self.database_funcs.get_name(opponent) - turn_name = self.database_funcs.get_name(players[0]) + opponent_name = self.get_name(f"#{opponent}") + turn_name = self.get_name(f"#{players[0]}") started_text = "Started game against {}{}.".format( opponent_name, @@ -147,138 +167,202 @@ class ConnectFour(): log_message = "They started a game" self.bot.log(log_message) - await ctx.send(send_message) # Sets the whole game in motion if started_game: boards_path = "gwendolyn/resources/games/connect_four_boards/" file_path = f"{boards_path}board{ctx.channel_id}.png" - old_image = await ctx.channel.send(file=discord.File(file_path)) - - old_images_path = "gwendolyn/resources/games/old_images/" - old_image_path = f"{old_images_path}connect_four{ctx.channel_id}" - with open(old_image_path, "w") as file_pointer: - file_pointer.write(str(old_image.id)) + image_message = await ctx.send( + send_message, file=discord.File(file_path) + ) + board_string = self._encode_board_string(board) if gwendolyn_turn: - await self._connect_four_ai(ctx) + await self._connect_four_ai( + ctx, board_string, players, difficulty, image_message.id + ) else: - for reaction in self.REACTIONS: - await old_image.add_reaction(reaction) + buttons = [] + for i in range(7): + custom_id = encode_id( + [ + "connectfour", + "place", + str(players[0]), + board_string, + str(i), + str(players[0]), + str(players[1]), + str(difficulty), + str(image_message.id) + ] + ) + buttons.append(create_button( + style=ButtonStyle.blue, + label=str(i+1), + custom_id=custom_id, + disabled=(board[0][i] != 0) + )) - async def place_piece(self, ctx: Union[SlashContext, discord.Message], - user: int, column: int): + custom_id = encode_id( + [ + "connectfour", + "end", + str(players[0]), + str(players[1]), + str(image_message.id) + ] + ) + buttons.append(create_button( + style=ButtonStyle.red, + label="Surrender", + custom_id=custom_id + )) + + action_rows = [] + for x in range(((len(buttons)-1)//4)+1): + row_buttons = buttons[ + (x*4):(min(len(buttons),x*4+4)) + ] + action_rows.append(create_actionrow(*row_buttons)) + + await image_message.edit( + components=action_rows + ) + else: + await ctx.send(send_message) + + async def place_piece(self, ctx: ComponentContext, board_string: str, + column: int, players: list[int], difficulty: int, + placer: int, message_id: int): """ Place a piece on the board. *Parameters* - ------------ - ctx: Union[SlashContext, discord.Message] - The context of the command/reaction. ctx can only be - SlashContext if the piece is placed by the bot - immediately after the player starts the game with a - command. Otherwise, ctx will be the message the player - reacted to when placing a piece. - user: int - The player-number of the player placing the piece. column: int The column the player is placing the piece in. """ - channel = str(ctx.channel.id) - connect_four_games = self.bot.database["connect 4 games"] - game = connect_four_games.find_one({"_id": channel}) - player_number = game["players"].index(user)+1 - user_name = self.database_funcs.get_name(user) + + player_number = players.index(placer)+1 + user_name = self.get_name(f"#{placer}") placed_piece = False - if game is None: - send_message = "There's no game in this channel" - log_message = "There was no game in the channel" + board = self._decode_board_string(board_string) + board = self._place_on_board(board, player_number, column) + + if board is None: + send_message = "There isn't any room in that column" + log_message = "There wasn't any room in the column" else: - board = game["board"] - board = self._place_on_board(board, player_number, column) + turn = player_number % 2 - if board is None: - send_message = "There isn't any room in that column" - log_message = "There wasn't any room in the column" + self.bot.log("Checking for win") + winner, win_direction, win_coordinates = self._is_won(board) + + if winner != 0: + game_won = True + send_message = "{} placed a piece in column {} and won. " + send_message = send_message.format(user_name, column+1) + log_message = f"{user_name} won" + win_amount = difficulty**2+5 + if players[winner-1] != self.bot.user.id: + send_message += "Adding {} GwendoBucks to their account" + send_message = send_message.format(win_amount) + elif 0 not in board[0]: + game_won = True + send_message = "It's a draw!" + log_message = "The game ended in a draw" else: - updater = {"$set": {"board": board}} - connect_four_games.update_one({"_id": channel}, updater) - turn = (game["turn"]+1) % 2 - updater = {"$set": {"turn": turn}} - connect_four_games.update_one({"_id": channel}, updater) + game_won = False + other_user_id = f"#{players[turn]}" + other_user_name = self.get_name(other_user_id) + send_message = self.bot.long_strings["Connect 4 placed"] + format_parameters = [user_name, column+1, other_user_name] + send_message = send_message.format(*format_parameters) + log_message = "They placed the piece" - self.bot.log("Checking for win") - won, win_direction, win_coordinates = self._is_won(board) + gwendolyn_turn = (players[turn] == self.bot.user.id) - if won != 0: - game_won = True - updater = {"$set": {"winner": won}} - connect_four_games.update_one({"_id": channel}, updater) - updater = {"$set": {"win direction": win_direction}} - connect_four_games.update_one({"_id": channel}, updater) - updater = {"$set": {"win coordinates": win_coordinates}} - connect_four_games.update_one({"_id": channel}, updater) + placed_piece = True - send_message = "{} placed a piece in column {} and won. " - send_message = send_message.format(user_name, column+1) - log_message = f"{user_name} won" - win_amount = int(game["difficulty"])**2+5 - if game["players"][won-1] != f"#{self.bot.user.id}": - send_message += "Adding {} GwendoBucks to their account" - send_message = send_message.format(win_amount) - elif 0 not in board[0]: - game_won = True - send_message = "It's a draw!" - log_message = "The game ended in a draw" - else: - game_won = False - other_user_id = game["players"][turn] - other_user_name = self.database_funcs.get_name( - other_user_id) - send_message = self.bot.long_strings["Connect 4 placed"] - format_parameters = [user_name, column+1, other_user_name] - send_message = send_message.format(*format_parameters) - log_message = "They placed the piece" - - gwendolyn_turn = ( - game["players"][turn] == f"#{self.bot.user.id}") - - placed_piece = True - - await ctx.channel.send(send_message) self.bot.log(log_message) if placed_piece: - self.draw.draw_image(channel) + channel = str(ctx.channel) + self.draw.draw_image( + channel, board, winner, win_coordinates, win_direction, players) - old_images_path = "gwendolyn/resources/games/old_images/" - old_image_path = old_images_path + f"connect_four{channel}" - with open(old_image_path, "r") as file_pointer: - old_image_id = int(file_pointer.read()) - old_image = await ctx.channel.fetch_message(old_image_id) - - if old_image is not None: - await old_image.delete() - else: - self.bot.log("The old image was already deleted") boards_path = "gwendolyn/resources/games/connect_four_boards/" file_path = boards_path + f"board{channel}.png" - old_image = await ctx.channel.send(file=discord.File(file_path)) + image_message = await ctx.channel.send( + send_message, file=discord.File(file_path)) if game_won: - self._end_game(channel) + self._end_game(winner, players, difficulty) else: - with open(old_image_path, "w") as file_pointer: - file_pointer.write(str(old_image.id)) + board_string = self._encode_board_string(board) if gwendolyn_turn: - await self._connect_four_ai(ctx) + await self._connect_four_ai( + ctx, board_string, players, difficulty, image_message.id + ) else: - for reaction in self.REACTIONS: - await old_image.add_reaction(reaction) + buttons = [] + for i in range(7): + custom_id = encode_id( + [ + "connectfour", + "place", + str(players[turn]), + board_string, + str(i), + str(players[0]), + str(players[1]), + str(difficulty), + str(image_message.id) + ] + ) + buttons.append(create_button( + style=ButtonStyle.blue, + label=str(i+1), + custom_id=custom_id, + disabled=(board[0][i] != 0) + )) - async def surrender(self, ctx: SlashContext): + custom_id = encode_id( + [ + "connectfour", + "end", + str(players[0]), + str(players[1]), + str(difficulty), + str(image_message.id) + ] + ) + buttons.append(create_button( + style=ButtonStyle.red, + label="Surrender", + custom_id=custom_id + )) + + action_rows = [] + for x in range(((len(buttons)-1)//4)+1): + row_buttons = buttons[ + (x*4):(min(len(buttons),x*4+4)) + ] + action_rows.append(create_actionrow(*row_buttons)) + + await image_message.edit( + components=action_rows + ) + else: + await ctx.channel.send(send_message) + + old_message = await ctx.channel.fetch_message(message_id) + await old_message.delete() + + async def surrender(self, ctx: ComponentContext, players: list, + difficulty: int, message_id: int): """ Surrender a connect four game. @@ -287,38 +371,25 @@ class ConnectFour(): ctx: SlashContext The context of the command. """ - await self.bot.defer(ctx) - channel = str(ctx.channel_id) - game = self.bot.database["connect 4 games"].find_one({"_id": channel}) - if f"#{ctx.author.id}" in game["players"]: - loser_index = game["players"].index(f"#{ctx.author.id}") - winner_index = (loser_index+1) % 2 - winner_id = game["players"][winner_index] - winner_name = self.database_funcs.get_name(winner_id) + loser_index = players.index(ctx.author.id) + winner_index = (loser_index+1) % 2 + winner_id = players[winner_index] + winner_name = self.get_name(f"#{winner_id}") - send_message = f"{ctx.author.display_name} surrenders." - send_message += f" This means {winner_name} is the winner." - if winner_id != f"#{self.bot.user.id}": - difficulty = int(game["difficulty"]) - reward = difficulty**2 + 5 - send_message += f" Adding {reward} to their account" + send_message = f"{ctx.author.display_name} surrenders." + send_message += f" This means {winner_name} is the winner." + if winner_id != self.bot.user.id: + difficulty = int(difficulty) + reward = difficulty**2 + 5 + send_message += f" Adding {reward} to their account" - await ctx.send(send_message) - old_images_path = "gwendolyn/resources/games/old_images/" - old_image_path = old_images_path + f"connect_four{channel}" - with open(old_image_path, "r") as file_pointer: - old_image_id = int(file_pointer.read()) - old_image = await ctx.channel.fetch_message(old_image_id) + await ctx.channel.send(send_message) - if old_image is not None: - await old_image.delete() - else: - self.bot.log("The old image was already deleted") + self._end_game(winner_index+1, players, difficulty) + old_image = await ctx.channel.fetch_message(message_id) + await old_image.delete() - self._end_game(channel) - else: - await ctx.send("You can't surrender when you're not a player") def _place_on_board(self, board: dict, player: int, column: int): """ @@ -355,17 +426,12 @@ class ConnectFour(): else: return board - def _end_game(self, channel: str): - game = self.bot.database["connect 4 games"].find_one({"_id": channel}) - - winner = game["winner"] + def _end_game(self, winner: int, players: list, difficulty: int): if winner != 0: - if game["players"][winner-1] != f"#{self.bot.user.id}": - difficulty = int(game["difficulty"]) + if players[winner-1] != f"#{self.bot.user.id}": + difficulty = int(difficulty) reward = difficulty**2 + 5 - self.bot.money.addMoney(game["players"][winner-1], reward) - - self.database_funcs.delete_game("connect 4 games", channel) + self.bot.money.addMoney(f"#{players[winner-1]}", reward) def _is_won(self, board: dict): won = 0 @@ -441,20 +507,19 @@ class ConnectFour(): return won, win_direction, win_coordinates - async def _connect_four_ai(self, ctx: SlashContext): + async def _connect_four_ai(self, + ctx: Union[SlashContext, ComponentContext], + board_string: str, players: list, + difficulty: int, message_id: int): def out_of_range(possible_scores: list): allowed_range = max(possible_scores)*(1-0.1) more_than_one = len(possible_scores) != 1 return (min(possible_scores) <= allowed_range) and more_than_one - channel = str(ctx.channel.id) - self.bot.log("Figuring out best move") - game = self.bot.database["connect 4 games"].find_one({"_id": channel}) - board = game["board"] - player = game["players"].index(f"#{self.bot.user.id}")+1 - difficulty = game["difficulty"] + board = self._decode_board_string(board_string) + player = players.index(self.bot.user.id)+1 scores = [-math.inf for _ in range(COLUMNCOUNT)] for column in range(COLUMNCOUNT): @@ -483,7 +548,15 @@ class ConnectFour(): best_columns = [i for i, x in enumerate(scores) if x == highest_score] placement = random.choice(best_columns) - await self.place_piece(ctx, f"#{self.bot.user.id}", placement) + await self.place_piece( + ctx, + board_string, + placement, + players, + difficulty, + self.bot.user.id, + message_id + ) def _ai_calc_points(self, board: dict, player: int): score = 0 @@ -683,7 +756,7 @@ class DrawConnectFour(): def __init__(self, bot): """Initialize the class.""" self.bot = bot - self.database_funcs = self.bot.database_funcs + self.get_name = self.bot.database_funcs.get_name win_bar_alpha = 160 font_path = "gwendolyn/resources/fonts/futura-bold.ttf" @@ -729,19 +802,15 @@ class DrawConnectFour(): # pylint: enable=invalid-name # Draws the whole thing - def draw_image(self, channel: str): + def draw_image(self, channel: str, board: list, winner: int, + win_coordinates: list, win_direction: str, players: list): """ Draw an image of the connect four board. *Parameters* ------------ - channel: str - The id of the channel the game is in. """ self.bot.log("Drawing connect four board") - game = self.bot.database["connect 4 games"].find_one({"_id": channel}) - - board = game["board"] image_size = (self.WIDTH, self.HEIGHT+self.BOTTOMBORDER) background = Image.new("RGB", image_size, self.BACKGROUNDCOLOR) @@ -751,10 +820,10 @@ class DrawConnectFour(): self._draw_pieces(drawer, board) - if game["winner"] != 0: - self._draw_win(background, game) + if winner != 0: + self._draw_win(background, win_coordinates, win_direction) - self._draw_footer(drawer, game) + self._draw_footer(drawer, players) boards_path = "gwendolyn/resources/games/connect_four_boards/" background.save(boards_path + f"board{channel}.png") @@ -897,7 +966,8 @@ class DrawConnectFour(): } drawer.ellipse(position, **piece_parameters) - def _draw_win(self, background: Image, game: dict): + def _draw_win(self, background: Image, win_coordinates: list, + win_direction: str): """ Draw the bar that shows the winning pieces. @@ -908,10 +978,9 @@ class DrawConnectFour(): game: dict The game data. """ - coordinates = game["win coordinates"] start = self.BORDER + self.GRIDBORDER - start_x = start + self.PIECEGRIDSIZE[0]*coordinates[1] - start_y = start + self.PIECEGRIDSIZE[1]*coordinates[0] + start_x = start + self.PIECEGRIDSIZE[0]*win_coordinates[1] + start_y = start + self.PIECEGRIDSIZE[1]*win_coordinates[0] diagonal_length = ( (math.sqrt( (self.PIECEGRIDSIZE[0]*4-self.GRIDBORDER-self.BORDER)**2+ @@ -922,7 +991,7 @@ class DrawConnectFour(): size_ratio = self.PIECEGRIDSIZE[1]/self.PIECEGRIDSIZE[0] diagonal_angle = math.degrees(math.atan(size_ratio)) - if game["win direction"] == "h": + if win_direction == "h": image_size = (self.PIECEGRIDSIZE[0]*4, self.PIECEGRIDSIZE[1]) win_bar = Image.new("RGBA", image_size, (0, 0, 0, 0)) win_drawer = ImageDraw.Draw(win_bar) @@ -942,7 +1011,7 @@ class DrawConnectFour(): win_drawer.ellipse(draw_position[1], fill=self.WINBARWHITE) win_drawer.rectangle(draw_position[2], fill=self.WINBARWHITE) - elif game["win direction"] == "v": + elif win_direction == "v": image_size = (self.PIECEGRIDSIZE[0], self.PIECEGRIDSIZE[1]*4) win_bar = Image.new("RGBA", image_size, (0, 0, 0, 0)) win_drawer = ImageDraw.Draw(win_bar) @@ -962,7 +1031,7 @@ class DrawConnectFour(): win_drawer.ellipse(draw_position[1], fill=self.WINBARWHITE) win_drawer.rectangle(draw_position[2], fill=self.WINBARWHITE) - elif game["win direction"] == "r": + elif win_direction == "r": image_width = int(self.PIECEGRIDSIZE[0]*diagonal_length) image_size = (image_width, self.PIECEGRIDSIZE[1]) win_bar = Image.new("RGBA", image_size, (0, 0, 0, 0)) @@ -1001,7 +1070,7 @@ class DrawConnectFour(): start_x -= 90 start_y -= 100 - elif game["win direction"] == "l": + elif win_direction == "l": image_width = int(self.PIECEGRIDSIZE[0]*diagonal_length) image_size = (image_width, self.PIECEGRIDSIZE[1]) win_bar = Image.new("RGBA", image_size, (0, 0, 0, 0)) @@ -1040,16 +1109,16 @@ class DrawConnectFour(): win_bar_image = Image.new("RGBA", mask.size, color=self.WINBARCOLOR) background.paste(win_bar_image, (start_x, start_y), mask) - def _draw_footer(self, drawer: ImageDraw, game: dict): - if game["players"][0] == "Gwendolyn": + def _draw_footer(self, drawer: ImageDraw, players: list): + if players[0] == "Gwendolyn": player1 = "Gwendolyn" else: - player1 = self.database_funcs.get_name(game["players"][0]) + player1 = self.get_name(f"#{players[0]}") - if game["players"][1] == "Gwendolyn": + if players[1] == "Gwendolyn": player2 = "Gwendolyn" else: - player2 = self.database_funcs.get_name(game["players"][1]) + player2 = self.get_name(f"#{players[1]}") circle_height = self.HEIGHT - self.BORDER circle_height += (self.BOTTOMBORDER+self.BORDER)//2 - self.TEXTSIZE//2 diff --git a/gwendolyn/funcs/games/hangman.py b/gwendolyn/funcs/games/hangman.py index b4373f7..0b93d11 100644 --- a/gwendolyn/funcs/games/hangman.py +++ b/gwendolyn/funcs/games/hangman.py @@ -164,9 +164,6 @@ class Hangman(): ctx: SlashContext The context of the command. """ - for msg_id in messages: - msg = await ctx.channel.fetch_message(msg_id) - await msg.delete() self.bot.log("Deleting old messages") @@ -175,6 +172,10 @@ class Hangman(): file_path = f"{boards_path}hangman_board{game_id}.png" os.remove(file_path) + for msg_id in messages: + msg = await ctx.channel.fetch_message(msg_id) + await msg.delete() + async def guess(self, ctx: ComponentContext, guess: str, word: str, guessed_letters: str, game_id: str, *messages: list[str]): """ @@ -189,9 +190,6 @@ class Hangman(): guess: str The guess. """ - for msg_id in messages: - msg = await ctx.channel.fetch_message(msg_id) - await msg.delete() misses = 0 guessed_letters += guess @@ -293,6 +291,10 @@ class Hangman(): os.remove(file_path) + for msg_id in messages: + msg = await ctx.channel.fetch_message(msg_id) + await msg.delete() + diff --git a/gwendolyn/resources/slash_parameters.json b/gwendolyn/resources/slash_parameters.json index 479e254..e5ecf1c 100644 --- a/gwendolyn/resources/slash_parameters.json +++ b/gwendolyn/resources/slash_parameters.json @@ -140,11 +140,6 @@ } ] }, - "connect_four_surrender" : { - "base" : "connect_four", - "name" : "surrender", - "description" : "Surrender the game of connect four" - }, "downloading" : { "name" : "downloading", "description" : "See current downloads for Plex", diff --git a/gwendolyn/utils/event_handlers.py b/gwendolyn/utils/event_handlers.py index 3c297b2..778a710 100644 --- a/gwendolyn/utils/event_handlers.py +++ b/gwendolyn/utils/event_handlers.py @@ -7,8 +7,6 @@ Classes used to handle bot events and errors. ErrorHandler """ import traceback # Used to get the traceback of errors -import sys # Used to get traceback when the specific error is not - # available import discord # Used to init discord.Game and discord.Status, as well # as compare errors to discord errors and as typehints @@ -16,7 +14,7 @@ from discord.ext import commands # Used to compare errors with command # errors from discord_slash.context import SlashContext, ComponentContext -from gwendolyn.utils.util_functions import emoji_to_command, decode_id +from gwendolyn.utils.util_functions import decode_id class EventHandler(): @@ -63,24 +61,9 @@ class EventHandler(): log_message = f"{ctx.author.display_name} ran {full_command}" self.bot.log(log_message, str(ctx.channel_id), level=25) - async def on_reaction_add(self, reaction: discord.Reaction, - user: discord.User): - """Take action if the reaction is on a command message.""" - if not user.bot: - tests = self.bot.database_funcs - message = reaction.message - channel = message.channel - reacted_message = f"{user.display_name} reacted to a message" - self.bot.log(reacted_message, str(channel.id)) - reaction_test_parameters = [message, f"#{str(user.id)}"] - - if tests.connect_four_reaction_test(*reaction_test_parameters): - column = emoji_to_command(reaction.emoji) - params = [message, f"#{user.id}", column-1] - await self.bot.games.connect_four.place_piece(*params) - async def on_component(self, ctx: ComponentContext): info = decode_id(ctx.custom_id) + self.bot.log(f"Component action with info {info}") channel = ctx.origin_message.channel if info[0].lower() == "plex": @@ -105,6 +88,27 @@ class EventHandler(): elif info[1].lower() == "end": await self.bot.games.hangman.stop(ctx, *info[3:]) + elif info[0].lower() == "connectfour": + connect_four = self.bot.games.connect_four + if info[1].lower() == "place" and str(ctx.author_id) == info[2]: + params = [ + ctx, + info[3], + int(info[4]), + [int(info[5]), int(info[6])], + int(info[7]), + ctx.author_id, + int(info[8]) + ] + await connect_four.place_piece(*params) + if info[1].lower() == "end": + if str(ctx.author_id) in [info[2], info[3]]: + params = [ + ctx, [int(info[2]), int(info[3])], info[4], info[5] + ] + await connect_four.surrender(*params) + + class ErrorHandler(): """ @@ -145,12 +149,8 @@ class ErrorHandler(): async def on_error(self, method: str): """Log when there's an error.""" - error_type = sys.exc_info()[0] - if error_type == discord.errors.NotFound: - self.bot.log("Deleted message before I could add all reactions") - else: - exception = traceback.format_exc() + exception = traceback.format_exc() - exception_string = "".join(exception) - log_messages = [f"exception in {method}", f"{exception_string}"] - self.bot.log(log_messages, level=40) + exception_string = "".join(exception) + log_messages = [f"exception in {method}", f"{exception_string}"] + self.bot.log(log_messages, level=40) diff --git a/gwendolyn/utils/util_functions.py b/gwendolyn/utils/util_functions.py index 853a4c9..c2a6cf8 100644 --- a/gwendolyn/utils/util_functions.py +++ b/gwendolyn/utils/util_functions.py @@ -359,7 +359,7 @@ def encode_id(info: list): try: dec += (37**i) * BASE_37.index(letter.upper()) except ValueError: - log_this("Could not encode letter {letter}", level=30) + log_this(f"Could not encode letter {letter}", level=30) custom_id = []