diff --git a/.gitignore b/.gitignore index 59cd0e4..affb8ee 100644 --- a/.gitignore +++ b/.gitignore @@ -154,11 +154,11 @@ token.txt credentials.txt options.txt gwendolyn/resources/star_wars/destinyPoints.txt -gwendolyn/resources/bedre_netflix/ +gwendolyn/resources/plex/ gwendolyn/resources/games/hilo/ gwendolyn/resources/games/blackjack_tables/ gwendolyn/resources/games/old_images/ -gwendolyn/resources/games/connect4Boards/ +gwendolyn/resources/games/connect_four_boards/ gwendolyn/resources/games/hex_boards/ gwendolyn/resources/games/hangman_boards/ gwendolyn/resources/lookup/monsters.json diff --git a/gwendolyn/cogs/game_cog.py b/gwendolyn/cogs/game_cog.py index 0caad15..8b04fd9 100644 --- a/gwendolyn/cogs/game_cog.py +++ b/gwendolyn/cogs/game_cog.py @@ -50,7 +50,7 @@ class BlackjackCog(commands.Cog): @cog_ext.cog_subcommand(**params["blackjack_bet"]) async def blackjack_bet(self, ctx, bet): """Enter the game of blackjack with a bet.""" - await self.bot.games.blackjack.enterGame(ctx, bet) + await self.bot.games.blackjack.enter_game(ctx, bet) @cog_ext.cog_subcommand(**params["blackjack_stand"]) async def blackjack_stand(self, ctx, hand=""): diff --git a/gwendolyn/cogs/misc_cog.py b/gwendolyn/cogs/misc_cog.py index cd2bffe..5042757 100644 --- a/gwendolyn/cogs/misc_cog.py +++ b/gwendolyn/cogs/misc_cog.py @@ -15,7 +15,7 @@ class MiscCog(commands.Cog): self.bot = bot self.bot.remove_command("help") self.generators = bot.other.generators - self.bedre_netflix = bot.other.bedre_netflix + self.plex = bot.other.plex self.nerd_shit = bot.other.nerd_shit @cog_ext.cog_slash(**params["ping"]) @@ -76,17 +76,17 @@ class MiscCog(commands.Cog): @cog_ext.cog_slash(**params["add_movie"]) async def add_movie(self, ctx, movie): """Search for a movie and add it to the Plex server.""" - await self.bedre_netflix.requestMovie(ctx, movie) + await self.plex.request_movie(ctx, movie) @cog_ext.cog_slash(**params["add_show"]) async def add_show(self, ctx, show): """Search for a show and add it to the Plex server.""" - await self.bedre_netflix.requestShow(ctx, show) + await self.plex.request_show(ctx, show) @cog_ext.cog_slash(**params["downloading"]) async def downloading(self, ctx, parameters="-d"): """Get the current downloading torrents.""" - await self.bedre_netflix.downloading(ctx, parameters) + await self.plex.downloading(ctx, parameters) @cog_ext.cog_slash(**params["wolf"]) async def wolf(self, ctx, query): diff --git a/gwendolyn/funcs/games/blackjack.py b/gwendolyn/funcs/games/blackjack.py index 4b5b1be..57c053a 100644 --- a/gwendolyn/funcs/games/blackjack.py +++ b/gwendolyn/funcs/games/blackjack.py @@ -12,12 +12,12 @@ import random # Used to shuffle the blackjack cards import math # Used for flooring decimal numbers import datetime # Used to generate the game id import asyncio # Used for sleeping +from shutil import copyfile + import discord # Used for discord.file import discord_slash # Used for typehints from PIL import Image, ImageDraw, ImageFont -from shutil import copyfile - from gwendolyn.utils import replace_multiple @@ -28,14 +28,14 @@ class Blackjack(): *Methods* --------- hit(ctx: discord_slash.context.SlashContext, - handNumber: int = 0) + hand_number: int = 0) double(ctx: discord_slash.context.SlashContext, - handNumber: int = 0) + hand_number: int = 0) stand(ctx: discord_slash.context.SlashContext, - handNumber: int = 0) + hand_number: int = 0) split(ctx: discord_slash.context.SlashContext, - handNumber: int = 0) - enterGame(ctx: discord_slash.context.SlashContext, bet: int) + hand_number: int = 0) + enter_game(ctx: discord_slash.context.SlashContext, bet: int) start(ctx: discord_slash.context.SlashContext) hilo(ctx: discord_slash.context.SlashContext) shuffle(ctx: discord_slash.context.SlashContext) @@ -47,6 +47,7 @@ class Blackjack(): self.bot = bot self.draw = DrawBlackjack(bot) self.decks = 4 + self.long_strings = self.bot.long_strings def _blackjack_shuffle(self, channel: str): """ @@ -62,25 +63,26 @@ class Blackjack(): """ self.bot.log("Shuffling the blackjack deck") - with open("gwendolyn/resources/games/deck_of_cards.txt", "r") as f: - deck = f.read() + deck_path = "gwendolyn/resources/games/deck_of_cards.txt" + with open(deck_path, "r") as file_pointer: + deck = file_pointer.read() - allDecks = deck.split("\n") * self.decks - random.shuffle(allDecks) + all_decks = deck.split("\n") * self.decks + random.shuffle(all_decks) blackjack_cards = self.bot.database["blackjack cards"] cards = {"_id": channel} - cardUpdater = {"$set": {"_id": channel, "cards": allDecks}} - blackjack_cards.update_one(cards, cardUpdater, upsert=True) + card_updater = {"$set": {"_id": channel, "cards": all_decks}} + blackjack_cards.update_one(cards, card_updater, upsert=True) # Creates hilo file self.bot.log(f"creating hilo doc for {channel}") data = 0 blackjack_hilo = self.bot.database["hilo"] - hiloUpdater = {"$set": {"_id": channel, "hilo": data}} - blackjack_hilo.update_one({"_id": channel}, hiloUpdater, upsert=True) + hilo_updater = {"$set": {"_id": channel, "hilo": data}} + blackjack_hilo.update_one({"_id": channel}, hilo_updater, upsert=True) - def _calcHandValue(self, hand: list): + def _calc_hand_value(self, hand: list): """ Calculate the value of a blackjack hand. @@ -95,36 +97,33 @@ class Blackjack(): *Returns* --------- - handValue: int + hand_value: int The blackjack value of the hand. """ - values = [] - values.append(0) + values = [0] for card in hand: - cardValue = card[0] - cardValue = replace_multiple(cardValue, ["0", "k", "q", "j"], "10") - if cardValue == "a": + card_value = replace_multiple(card[0], ["0", "k", "q", "j"], "10") + if card_value == "a": length = len(values) - for x in range(length): - values.append(values[x] + 11) - values[x] += 1 + for i in range(length): + values.append(values[i] + 11) + values[i] += 1 else: - for x in range(len(values)): - values[x] += int(cardValue) + values = [int(i)+int(card_value) for i in values] values.sort() - handValue = values[0] + hand_value = values[0] for value in values: if value <= 21: - handValue = value + hand_value = value - self.bot.log(f"Calculated the value of {hand} to be {handValue}") + self.bot.log(f"Calculated the value of {hand} to be {hand_value}") - return handValue + return hand_value - def _drawCard(self, channel: str): + def _draw_card(self, channel: str): """ Draw a card from the stack. @@ -136,9 +135,9 @@ class Blackjack(): self.bot.log("drawing a card") blackjack_cards = self.bot.database["blackjack cards"] - drawnCard = blackjack_cards.find_one({"_id": channel})["cards"][0] + drawn_card = blackjack_cards.find_one({"_id": channel})["cards"][0] blackjack_cards.update_one({"_id": channel}, {"$pop": {"cards": -1}}) - value = self._calcHandValue([drawnCard]) + value = self._calc_hand_value([drawn_card]) blackjack_hilo = self.bot.database["hilo"] @@ -147,9 +146,9 @@ class Blackjack(): elif value >= 10: blackjack_hilo.update_one({"_id": channel}, {"$inc": {"hilo": -1}}) - return drawnCard + return drawn_card - def _dealerDraw(self, channel: str): + def _dealer_draw(self, channel: str): """ Draw a card for the dealer. @@ -166,20 +165,20 @@ class Blackjack(): game = self.bot.database["blackjack games"].find_one({"_id": channel}) done = False - dealerHand = game["dealer hand"] + dealer_hand = game["dealer hand"] blackjack_games = self.bot.database["blackjack games"] - if self._calcHandValue(dealerHand) < 17: - dealerHand.append(self._drawCard(channel)) - dealerUpdater = {"$set": {"dealer hand": dealerHand}} - blackjack_games.update_one({"_id": channel}, dealerUpdater) + if self._calc_hand_value(dealer_hand) < 17: + dealer_hand.append(self._draw_card(channel)) + dealer_updater = {"$set": {"dealer hand": dealer_hand}} + blackjack_games.update_one({"_id": channel}, dealer_updater) else: done = True - if self._calcHandValue(dealerHand) > 21: - dealerUpdater = {"$set": {"dealer busted": True}} - blackjack_games.update_one({"_id": channel}, dealerUpdater) + if self._calc_hand_value(dealer_hand) > 21: + dealer_updater = {"$set": {"dealer busted": True}} + blackjack_games.update_one({"_id": channel}, dealer_updater) return done @@ -194,9 +193,9 @@ class Blackjack(): *Returns* --------- - sendMessage: str + send_message: str The message to send to the channel. - allStanding: bool + all_standing: bool If all players are standing. gameDone: bool If the game has finished. @@ -209,53 +208,53 @@ class Blackjack(): blackjack_games = self.bot.database["blackjack games"] blackjack_games.update_one({"_id": channel}, {"$inc": {"round": 1}}) - allStanding = True - preAllStanding = True - message = self.bot.long_strings["Blackjack all players standing"] + all_standing = True + pre_all_standing = True + message = self.long_strings["Blackjack all players standing"] if game["all standing"]: self.bot.log("All are standing") - done = self._dealerDraw(channel) + done = self._dealer_draw(channel) message = "The dealer draws a card." blackjack_games.find_one({"_id": channel}) self.bot.log("Testing if all are standing") for user in game["user hands"]: - userHand = game["user hands"][user] - test_parameters = [userHand, allStanding, preAllStanding, True] - standingTest = (self._testIfStanding(*test_parameters)) - newUser, allStanding, preAllStanding = standingTest - handUpdater = {"$set": {"user hands."+user: newUser}} - blackjack_games.update_one({"_id": channel}, handUpdater) + user_hand = game["user hands"][user] + test_parameters = [user_hand, all_standing, pre_all_standing, True] + standing_test = (self._test_if_standing(*test_parameters)) + new_user, all_standing, pre_all_standing = standing_test + hand_updater = {"$set": {"user hands."+user: new_user}} + blackjack_games.update_one({"_id": channel}, hand_updater) - if allStanding: - gameUpdater = {"$set": {"all standing": True}} - blackjack_games.update_one({"_id": channel}, gameUpdater) + if all_standing: + game_updater = {"$set": {"all standing": True}} + blackjack_games.update_one({"_id": channel}, game_updater) - self.draw.drawImage(channel) + self.draw.draw_image(channel) - if allStanding: + if all_standing: if not done: return message, True, done else: return "The dealer is done drawing cards", True, done - elif preAllStanding: + elif pre_all_standing: return "", True, done else: + send_message = self.long_strings["Blackjack commands"] + if game["round"] == 0: - firstRoundMsg = self.bot.long_strings["Blackjack first round"] + send_message = send_message.format( + self.long_strings["Blackjack first round"]) else: - firstRoundMsg = "" + send_message = send_message.format("") - sendMessage = self.bot.long_strings["Blackjack commands"] - print(firstRoundMsg) - sendMessage = sendMessage.format(firstRoundMsg) - return sendMessage, False, done + return send_message, False, done - def _testIfStanding(self, hand: dict, allStanding: bool, - preAllStanding: bool, topLevel: bool): + def _test_if_standing(self, hand: dict, all_standing: bool, + pre_all_standing: bool, top_level: bool): """ Test if a player is standing on all their hands. @@ -265,13 +264,13 @@ class Blackjack(): ------------ hand: dict The hand to test and reset. - allStanding: bool + all_standing: bool Is set to True at the top level. If it's false, the player is not standing on one of the previously tested hands. - preAllStanding: bool + pre_all_standing: bool Is set to True at the top level. - topLevel: bool + top_level: bool If the input hand is _all_ if the player's hands. If False, it's one of the hands resulting from a split. @@ -279,10 +278,10 @@ class Blackjack(): --------- hand: dict The reset hand. - allStanding: bool + all_standing: bool If the player is standing on all their hands. - preAllStanding: bool - Is true if allStanding is True, or if a player has done + pre_all_standing: bool + Is true if all_standing is True, or if a player has done something equivalent to standing but still needs to see the newly drawn card. """ @@ -291,33 +290,54 @@ class Blackjack(): hand["standing"] = True if not hand["standing"]: - allStanding = False + all_standing = False - if self._calcHandValue(hand["hand"]) >= 21 or hand["doubled"]: + if self._calc_hand_value(hand["hand"]) >= 21 or hand["doubled"]: hand["standing"] = True else: - preAllStanding = False + pre_all_standing = False hand["hit"] = False - if topLevel: + if top_level: if hand["split"] >= 1: - testHand = hand["other hand"] - test_parameters = [testHand, allStanding, preAllStanding, False] - standingTest = (self._testIfStanding(*test_parameters)) - hand["other hand"], allStanding, preAllStanding = standingTest + test_hand = hand["other hand"] + test_parameters = [ + test_hand, + all_standing, + pre_all_standing, + False + ] + standing_test = (self._test_if_standing(*test_parameters)) + hand["other hand"] = standing_test[0] + all_standing = standing_test[1] + pre_all_standing = standing_test[2] if hand["split"] >= 2: - testHand = hand["third hand"] - test_parameters = [testHand, allStanding, preAllStanding, False] - standingTest = (self._testIfStanding(*test_parameters)) - hand["third hand"], allStanding, preAllStanding = standingTest + test_hand = hand["third hand"] + test_parameters = [ + test_hand, + all_standing, + pre_all_standing, + False + ] + standing_test = (self._test_if_standing(*test_parameters)) + hand["third hand"] = standing_test[0] + all_standing = standing_test[1] + pre_all_standing = standing_test[2] if hand["split"] >= 3: - testHand = hand["fourth hand"] - test_parameters = [testHand, allStanding, preAllStanding, False] - standingTest = (self._testIfStanding(*test_parameters)) - hand["fourth hand"], allStanding, preAllStanding = standingTest + test_hand = hand["fourth hand"] + test_parameters = [ + test_hand, + all_standing, + pre_all_standing, + False + ] + standing_test = (self._test_if_standing(*test_parameters)) + hand["fourth hand"] = standing_test[0] + all_standing = standing_test[1] + pre_all_standing = standing_test[2] - return hand, allStanding, preAllStanding + return hand, all_standing, pre_all_standing def _blackjack_finish(self, channel: str): """ @@ -330,54 +350,57 @@ class Blackjack(): *Returns* --------- - finalWinnings: str + final_winnings: str The winnings message. """ - finalWinnings = "*Final Winnings:*\n" + final_winnings = "*Final Winnings:*\n" game = self.bot.database["blackjack games"].find_one({"_id": channel}) - dealerValue = self._calcHandValue(game["dealer hand"]) - dealerBlackjack = game["dealer blackjack"] - dealerBusted = game["dealer busted"] + dealer_value = self._calc_hand_value(game["dealer hand"]) + dealer_blackjack = game["dealer blackjack"] + dealer_busted = game["dealer busted"] for user in game["user hands"]: - _calcWinningsParams = [ + calc_winnings_parameters = [ game["user hands"][user], - dealerValue, + dealer_value, True, - dealerBlackjack, - dealerBusted + dealer_blackjack, + dealer_busted ] - winningCalc = (self._calcWinnings(*_calcWinningsParams)) - winnings, netWinnings, reason = winningCalc + winnings_calc = (self._calc_winning(*calc_winnings_parameters)) + winnings, net_winnings, reason = winnings_calc user_name = self.bot.database_funcs.get_name(user) if winnings < 0: if winnings == -1: - finalWinnings += f"{user_name} lost 1 GwendoBuck {reason}\n" + final_winnings += "{} lost 1 GwendoBuck {}\n".format( + user_name, + reason + ) else: - moneyLost = -1 * winnings - winningText = f"{user_name} lost {moneyLost} GwendoBucks" - winningText += f" {reason}\n" - finalWinnings += winningText + money_lost = -1 * winnings + winnings_text = f"{user_name} lost {money_lost} GwendoBucks" + winnings_text += f" {reason}\n" + final_winnings += winnings_text else: if winnings == 1: - finalWinnings += f"{user_name} won 1 GwendoBuck {reason}\n" + final_winnings += f"{user_name} won 1 GwendoBuck {reason}\n" else: - winningText = f"{user_name} won {winnings} GwendoBucks" - winningText += f" {reason}\n" - finalWinnings += winningText + winnings_text = f"{user_name} won {winnings} GwendoBucks" + winnings_text += f" {reason}\n" + final_winnings += winnings_text - self.bot.money.addMoney(user, netWinnings) + self.bot.money.addMoney(user, net_winnings) self.bot.database["blackjack games"].delete_one({"_id": channel}) - return finalWinnings + return final_winnings - def _calcWinnings(self, hand: dict, dealerValue: int, topLevel: bool, - dealerBlackjack: bool, dealerBusted: bool): + def _calc_winning(self, hand: dict, dealer_value: int, top_level: bool, + dealer_blackjack: bool, dealer_busted: bool): """ Calculate how much a user has won/lost in the blackjack game. @@ -385,21 +408,21 @@ class Blackjack(): ------------ hand: dict The hand to calculate the winnings of. - dealerValue: int + dealer_value: int The dealer's hand value. - topLevel: bool + top_level: bool If the input hand is _all_ if the player's hands. If False, it's one of the hands resulting from a split. - dealerBlackjack: bool + dealer_blackjack: bool If the dealer has a blackjack. - dealerBusted: bool + dealer_busted: bool If the dealer busted. *Returns* --------- winnings: int How much the player has won/lost. - netWinnings: int + net_winnings: int winnings minus the original bet. This is added to the user's account, since the bet was removed from their account when they placed the bet. @@ -410,77 +433,77 @@ class Blackjack(): reason = "" bet = hand["bet"] winnings = -1 * bet - netWinnings = 0 - handValue = self._calcHandValue(hand["hand"]) + net_winnings = 0 + hand_value = self._calc_hand_value(hand["hand"]) - if hand["blackjack"] and not dealerBlackjack: + if hand["blackjack"] and not dealer_blackjack: reason += "(blackjack)" winnings += math.floor(2.5 * bet) - netWinnings += math.floor(2.5 * bet) - elif dealerBlackjack: + net_winnings += math.floor(2.5 * bet) + elif dealer_blackjack: reason += "(dealer blackjack)" elif hand["busted"]: reason += "(busted)" else: - if dealerBusted: + if dealer_busted: reason = "(dealer busted)" winnings += 2 * bet - netWinnings += 2 * bet - elif handValue > dealerValue: + net_winnings += 2 * bet + elif hand_value > dealer_value: winnings += 2 * bet - netWinnings += 2 * bet + net_winnings += 2 * bet reason = "(highest value)" - elif handValue == dealerValue: + elif hand_value == dealer_value: reason = "(pushed)" winnings += bet - netWinnings += bet + net_winnings += bet else: reason = "(highest value)" - if topLevel: + if top_level: if hand["split"] >= 1: - _calcWinningsParams = [ + calc_winnings_parameters = [ hand["other hand"], - dealerValue, + dealer_value, False, - dealerBlackjack, - dealerBusted + dealer_blackjack, + dealer_busted ] - winningsCalc = self._calcWinnings(*_calcWinningsParams) - winningsTemp, netWinningsTemp, reasonTemp = winningsCalc - winnings += winningsTemp - netWinnings += netWinningsTemp - reason += reasonTemp + winnings_calc = self._calc_winning(*calc_winnings_parameters) + winnings_temp, net_winnings_temp, reason_temp = winnings_calc + winnings += winnings_temp + net_winnings += net_winnings_temp + reason += reason_temp if hand["split"] >= 2: - _calcWinningsParams = [ + calc_winnings_parameters = [ hand["third hand"], - dealerValue, + dealer_value, False, - dealerBlackjack, - dealerBusted + dealer_blackjack, + dealer_busted ] - winningsCalc = self._calcWinnings(*_calcWinningsParams) - winningsTemp, netWinningsTemp, reasonTemp = winningsCalc - winnings += winningsTemp - netWinnings += netWinningsTemp - reason += reasonTemp + winnings_calc = self._calc_winning(*calc_winnings_parameters) + winnings_temp, net_winnings_temp, reason_temp = winnings_calc + winnings += winnings_temp + net_winnings += net_winnings_temp + reason += reason_temp if hand["split"] >= 3: - _calcWinningsParams = [ + calc_winnings_parameters = [ hand["fourth hand"], - dealerValue, + dealer_value, False, - dealerBlackjack, - dealerBusted + dealer_blackjack, + dealer_busted ] - winningsCalc = self._calcWinnings(*_calcWinningsParams) - winningsTemp, netWinningsTemp, reasonTemp = winningsCalc - winnings += winningsTemp - netWinnings += netWinningsTemp - reason += reasonTemp + winnings_calc = self._calc_winning(*calc_winnings_parameters) + winnings_temp, net_winnings_temp, reason_temp = winnings_calc + winnings += winnings_temp + net_winnings += net_winnings_temp + reason += reason_temp - return winnings, netWinnings, reason + return winnings, net_winnings, reason - def _getHandNumber(self, user: dict, handNumber: int): + def _get_hand_number(self, user: dict, hand_number: int): """ Get the hand with the given number. @@ -488,36 +511,36 @@ class Blackjack(): ------------ user: dict The full hand dict of the user. - handNumber: int + hand_number: int The number of the hand to get. *Returns* --------- hand: dict The hand. - handNumber: int - The same as handNumber, except if the user hasn't + hand_number: int + The same as hand_number, except if the user hasn't split. If the user hasn't split, returns 0. """ hand = None if user["split"] == 0: hand = user - handNumber = 0 + hand_number = 0 else: - if handNumber != 0: - if handNumber == 1: + if hand_number != 0: + if hand_number == 1: hand = user - elif handNumber == 2: + elif hand_number == 2: hand = user["other hand"] - elif handNumber == 3: + elif hand_number == 3: hand = user["third hand"] - elif handNumber == 4: + elif hand_number == 4: hand = user["fourth hand"] - return hand, handNumber + return hand, hand_number - def _isRoundDone(self, game: dict): + def _is_round_done(self, game: dict): """ Find out if the round is done. @@ -528,33 +551,33 @@ class Blackjack(): *Returns* --------- - roundDone: bool + round_done: bool Whether the round is done. """ - roundDone = True + round_done = True for person in game["user hands"].values(): if (not person["hit"]) and (not person["standing"]): - roundDone = False + round_done = False if person["split"] > 0: if not person["other hand"]["hit"]: if not person["other hand"]["standing"]: - roundDone = False + round_done = False if person["split"] > 1: if not person["third hand"]["hit"]: if not person["third hand"]["standing"]: - roundDone = False + round_done = False if person["split"] > 2: if not person["fourth hand"]["hit"]: if not person["fourth hand"]["standing"]: - roundDone = False + round_done = False - return roundDone + return round_done - async def _blackjack_loop(self, channel, gameRound: int, gameID: str): + async def _blackjack_loop(self, channel, game_round: int, game_id: str): """ Run blackjack logic and continue if enough time passes. @@ -562,32 +585,33 @@ class Blackjack(): ------------ channel: guildChannel or DMChannel The channel the game is happening in. - gameRound: int + game_round: int The round to start. - gameID: str + game_id: str The ID of the game. """ - self.bot.log("Loop "+str(gameRound), str(channel.id)) + self.bot.log("Loop "+str(game_round), str(channel.id)) - old_imagePath = f"gwendolyn/resources/games/old_images/blackjack{channel.id}" - with open(old_imagePath, "r") as f: - old_image = await channel.fetch_message(int(f.read())) + old_images_path = "gwendolyn/resources/games/old_images/" + old_image_path = old_images_path + f"blackjack{channel.id}" + with open(old_image_path, "r") as file_pointer: + old_image = await channel.fetch_message(int(file_pointer.read())) - continueData = (self._blackjack_continue(str(channel.id))) - new_message, allStanding, gamedone = continueData + continue_data = (self._blackjack_continue(str(channel.id))) + new_message, all_standing, game_done = continue_data if new_message != "": self.bot.log(new_message, str(channel.id)) await channel.send(new_message) - if not gamedone: + if not game_done: await old_image.delete() - tablesPath = "gwendolyn/resources/games/blackjack_tables/" - file_path = f"{tablesPath}blackjack_table{channel.id}.png" + tables_path = "gwendolyn/resources/games/blackjack_tables/" + file_path = f"{tables_path}blackjack_table{channel.id}.png" old_image = await channel.send(file=discord.File(file_path)) - with open(old_imagePath, "w") as f: - f.write(str(old_image.id)) + with open(old_image_path, "w") as file_pointer: + file_pointer.write(str(old_image.id)) - if allStanding: + if all_standing: await asyncio.sleep(5) else: await asyncio.sleep(120) @@ -596,26 +620,26 @@ class Blackjack(): game = blackjack_games.find_one({"_id": str(channel.id)}) if game is None: - rightRound = False + right_round = False else: - realRound = game["round"] or -1 - realID = game["gameID"] or -1 - rightRound = gameRound == realRound and gameID == realID + real_round = game["round"] or -1 + real_id = game["game_id"] or -1 + right_round = game_round == real_round and game_id == real_id - if rightRound: - if not gamedone: - log_message = f"Loop {gameRound} calling self._blackjack_loop()" + if right_round: + if not game_done: + log_message = f"Loop {game_round} starting a new blackjack loop" self.bot.log(log_message, str(channel.id)) - await self._blackjack_loop(channel, gameRound+1, gameID) + await self._blackjack_loop(channel, game_round+1, game_id) else: new_message = self._blackjack_finish(str(channel.id)) await channel.send(new_message) else: - log_message = f"Ending loop on round {gameRound}" + log_message = f"Ending loop on round {game_round}" self.bot.log(log_message, str(channel.id)) async def hit(self, ctx: discord_slash.context.SlashContext, - handNumber: int = 0): + hand_number: int = 0): """ Hit on a hand. @@ -623,73 +647,73 @@ class Blackjack(): ------------ ctx: discord_slash.context.SlashContext The context of the command. - handNumber: int = 0 + hand_number: int = 0 The number of the hand to hit. """ await self.bot.defer(ctx) channel = str(ctx.channel_id) user = f"#{ctx.author.id}" - roundDone = False + round_done = False blackjack_games = self.bot.database["blackjack games"] game = blackjack_games.find_one({"_id": channel}) if user in game["user hands"]: - userHands = game["user hands"][user] - hand, handNumber = self._getHandNumber(userHands, handNumber) + user_hands = game["user hands"][user] + hand, hand_number = self._get_hand_number(user_hands, hand_number) if hand is None: log_message = "They didn't specify a hand" - sendMessage = "You need to specify a hand" + send_message = "You need to specify a hand" elif game["round"] <= 0: log_message = "They tried to hit on the 0th round" - sendMessage = "You can't hit before you see your cards" + send_message = "You can't hit before you see your cards" elif hand["hit"]: log_message = "They've already hit this round" - sendMessage = "You've already hit this round" + send_message = "You've already hit this round" elif hand["standing"]: log_message = "They're already standing" - sendMessage = "You can't hit when you're standing" + send_message = "You can't hit when you're standing" else: - hand["hand"].append(self._drawCard(channel)) + hand["hand"].append(self._draw_card(channel)) hand["hit"] = True - handValue = self._calcHandValue(hand["hand"]) + hand_value = self._calc_hand_value(hand["hand"]) - if handValue > 21: + if hand_value > 21: hand["busted"] = True - if handNumber == 2: - handPath = f"user hands.{user}.other hand" - elif handNumber == 3: - handPath = f"user hands.{user}.third hand" - elif handNumber == 4: - handPath = f"user hands.{user}.fourth hand" + if hand_number == 2: + hand_path = f"user hands.{user}.other hand" + elif hand_number == 3: + hand_path = f"user hands.{user}.third hand" + elif hand_number == 4: + hand_path = f"user hands.{user}.fourth hand" else: - handPath = f"user hands.{user}" + hand_path = f"user hands.{user}" - gameUpdater = {"$set": {handPath: hand}} - blackjack_games.update_one({"_id": channel}, gameUpdater) + game_updater = {"$set": {hand_path: hand}} + blackjack_games.update_one({"_id": channel}, game_updater) game = blackjack_games.find_one({"_id": channel}) - roundDone = self._isRoundDone(game) + round_done = self._is_round_done(game) - sendMessage = f"{ctx.author.display_name} hit" + send_message = f"{ctx.author.display_name} hit" log_message = "They succeeded" else: log_message = "They tried to hit without being in the game" - sendMessage = "You have to enter the game before you can hit" + send_message = "You have to enter the game before you can hit" - await ctx.send(sendMessage) + await ctx.send(send_message) self.bot.log(log_message) - if roundDone: - gameID = game["gameID"] + if round_done: + game_id = game["game_id"] self.bot.log("Hit calling self._blackjack_loop()", channel) - await self._blackjack_loop(ctx.channel, game["round"]+1, gameID) + await self._blackjack_loop(ctx.channel, game["round"]+1, game_id) async def double(self, ctx: discord_slash.context.SlashContext, - handNumber: int = 0): + hand_number: int = 0): """ Double a hand. @@ -697,86 +721,86 @@ class Blackjack(): ------------ ctx: discord_slash.context.SlashContext The context of the command. - handNumber: int = 0 + hand_number: int = 0 The number of the hand to double. """ await self.bot.defer(ctx) channel = str(ctx.channel_id) user = f"#{ctx.author.id}" - roundDone = False + round_done = False blackjack_games = self.bot.database["blackjack games"] game = blackjack_games.find_one({"_id": channel}) if user in game["user hands"]: - handParams = [game["user hands"][user], handNumber] - hand, handNumber = self._getHandNumber(*handParams) + hand_parameters = [game["user hands"][user], hand_number] + hand, hand_number = self._get_hand_number(*hand_parameters) if hand is None: log_message = "They didn't specify a hand" - sendMessage = "You need to specify a hand" + send_message = "You need to specify a hand" elif game["round"] <= 0: log_message = "They tried to hit on the 0th round" - sendMessage = "You can't hit before you see your cards" + send_message = "You can't hit before you see your cards" elif hand["hit"]: log_message = "They've already hit this round" - sendMessage = "You've already hit this round" + send_message = "You've already hit this round" elif hand["standing"]: log_message = "They're already standing" - sendMessage = "You can't hit when you're standing" + send_message = "You can't hit when you're standing" elif len(hand["hand"]) != 2: log_message = "They tried to double after round 1" - sendMessage = "You can only double on the first round" + send_message = "You can only double on the first round" elif self.bot.money.checkBalance(user) < hand["bet"]: log_message = "They tried to double without being in the game" - sendMessage = "You can't double when you're not in the game" + send_message = "You can't double when you're not in the game" else: bet = hand["bet"] self.bot.money.addMoney(user, -1 * bet) - hand["hand"].append(self._drawCard(channel)) + hand["hand"].append(self._draw_card(channel)) hand["hit"] = True hand["doubled"] = True hand["bet"] += bet - handValue = self._calcHandValue(hand["hand"]) + hand_value = self._calc_hand_value(hand["hand"]) - if handValue > 21: + if hand_value > 21: hand["busted"] = True - if handNumber == 2: - handPath = f"user hands.{user}.other hand" - elif handNumber == 3: - handPath = f"user hands.{user}.third hand" - elif handNumber == 4: - handPath = f"user hands.{user}.fourth hand" + if hand_number == 2: + hand_path = f"user hands.{user}.other hand" + elif hand_number == 3: + hand_path = f"user hands.{user}.third hand" + elif hand_number == 4: + hand_path = f"user hands.{user}.fourth hand" else: - handPath = f"user hands.{user}" + hand_path = f"user hands.{user}" - gameUpdater = {"$set": {handPath: hand}} - blackjack_games.update_one({"_id": channel}, gameUpdater) + game_updater = {"$set": {hand_path: hand}} + blackjack_games.update_one({"_id": channel}, game_updater) game = blackjack_games.find_one({"_id": channel}) - roundDone = self._isRoundDone(game) + round_done = self._is_round_done(game) - sendMessage = self.bot.long_strings["Blackjack double"] + send_message = self.long_strings["Blackjack double"] user_name = self.bot.database_funcs.get_name(user) - sendMessage = sendMessage.format(bet, user_name) + send_message = send_message.format(bet, user_name) log_message = "They succeeded" else: log_message = "They tried to double without being in the game" - sendMessage = "You can't double when you're not in the game" + send_message = "You can't double when you're not in the game" - await ctx.send(sendMessage) + await ctx.send(send_message) self.bot.log(log_message) - if roundDone: - gameID = game["gameID"] + if round_done: + game_id = game["game_id"] self.bot.log("Double calling self._blackjack_loop()", channel) - await self._blackjack_loop(ctx.channel, game["round"]+1, gameID) + await self._blackjack_loop(ctx.channel, game["round"]+1, game_id) async def stand(self, ctx: discord_slash.context.SlashContext, - handNumber: int = 0): + hand_number: int = 0): """ Stand on a hand. @@ -784,67 +808,67 @@ class Blackjack(): ------------ ctx: discord_slash.context.SlashContext The context of the command. - handNumber: int = 0 + hand_number: int = 0 The number of the hand to stand on. """ await self.bot.defer(ctx) channel = str(ctx.channel_id) user = f"#{ctx.author.id}" - roundDone = False + round_done = False blackjack_games = self.bot.database["blackjack games"] game = blackjack_games.find_one({"_id": channel}) if game is not None and user in game["user hands"]: - handParams = [game["user hands"][user], handNumber] - hand, handNumber = self._getHandNumber(*handParams) + hand_parameters = [game["user hands"][user], hand_number] + hand, hand_number = self._get_hand_number(*hand_parameters) if hand is None: - sendMessage = "You need to specify which hand" + send_message = "You need to specify which hand" log_message = "They didn't specify a hand" elif game["round"] <= 0: - sendMessage = "You can't stand before you see your cards" + send_message = "You can't stand before you see your cards" log_message = "They tried to stand on round 0" elif hand["hit"]: - sendMessage = "You've already hit this round" + send_message = "You've already hit this round" log_message = "They'd already hit this round" elif hand["standing"]: - sendMessage = "You're already standing" + send_message = "You're already standing" log_message = "They're already standing" else: hand["standing"] = True - if handNumber == 2: - handPath = f"user hands.{user}.other hand" - elif handNumber == 3: - handPath = f"user hands.{user}.third hand" - elif handNumber == 4: - handPath = f"user hands.{user}.fourth hand" + if hand_number == 2: + hand_path = f"user hands.{user}.other hand" + elif hand_number == 3: + hand_path = f"user hands.{user}.third hand" + elif hand_number == 4: + hand_path = f"user hands.{user}.fourth hand" else: - handPath = f"user hands.{user}" + hand_path = f"user hands.{user}" - gameUpdater = {"$set": {handPath: hand}} - blackjack_games.update_one({"_id": channel}, gameUpdater) + game_updater = {"$set": {hand_path: hand}} + blackjack_games.update_one({"_id": channel}, game_updater) game = blackjack_games.find_one({"_id": channel}) - roundDone = self._isRoundDone(game) + round_done = self._is_round_done(game) - sendMessage = f"{ctx.author.display_name} is standing" + send_message = f"{ctx.author.display_name} is standing" log_message = "They succeeded" else: log_message = "They tried to stand without being in the game" - sendMessage = "You have to enter the game before you can stand" + send_message = "You have to enter the game before you can stand" - await ctx.send(sendMessage) + await ctx.send(send_message) self.bot.log(log_message) - if roundDone: - gameID = game["gameID"] + if round_done: + game_id = game["game_id"] self.bot.log("Stand calling self._blackjack_loop()", channel) - await self._blackjack_loop(ctx.channel, game["round"]+1, gameID) + await self._blackjack_loop(ctx.channel, game["round"]+1, game_id) async def split(self, ctx: discord_slash.context.SlashContext, - handNumber: int = 0): + hand_number: int = 0): """ Split a hand. @@ -852,141 +876,141 @@ class Blackjack(): ------------ ctx: discord_slash.context.SlashContext The context of the command. - handNumber: int = 0 + hand_number: int = 0 The number of the hand to split. """ await self.bot.defer(ctx) channel = str(ctx.channel_id) user = f"#{ctx.author.id}" - roundDone = False - handNumberError = False + round_done = False + hand_number_error = False blackjack_games = self.bot.database["blackjack games"] game = blackjack_games.find_one({"_id": channel}) if game["user hands"][user]["split"] == 0: hand = game["user hands"][user] - newHand = game["user hands"][user]["other hand"] - handNumber = 0 - otherHand = 2 + new_hand = game["user hands"][user]["other hand"] + hand_number = 0 + other_hand = 2 else: - if handNumber == 1: + if hand_number == 1: hand = game["user hands"][user] - elif handNumber == 2: + elif hand_number == 2: hand = game["user hands"][user]["other hand"] - elif handNumber == 3: + elif hand_number == 3: hand = game["user hands"][user]["third hand"] else: - handNumberError = True + hand_number_error = True if game["user hands"][user]["split"] == 1: - newHand = game["user hands"][user]["third hand"] - otherHand = 3 + new_hand = game["user hands"][user]["third hand"] + other_hand = 3 else: - newHand = game["user hands"][user]["fourth hand"] - otherHand = 4 + new_hand = game["user hands"][user]["fourth hand"] + other_hand = 4 - if handNumberError: + if hand_number_error: log_message = "They didn't specify a hand" - sendMessage = "You have to specify the hand you're hitting with" + send_message = "You have to specify the hand you're hitting with" elif game["round"] == 0: log_message = "They tried to split on round 0" - sendMessage = "You can't split before you see your cards" + send_message = "You can't split before you see your cards" elif game["user hands"][user]["split"] > 3: log_message = "They tried to split more than three times" - sendMessage = "You can only split 3 times" + send_message = "You can only split 3 times" elif hand["hit"]: log_message = "They've already hit" - sendMessage = "You've already hit or split this hand." + send_message = "You've already hit or split this hand." elif hand["standing"]: log_message = "They're already standing" - sendMessage = "You're already standing" + send_message = "You're already standing" elif len(hand["hand"]) != 2: log_message = "They tried to split after the first round" - sendMessage = "You can only split on the first round" + send_message = "You can only split on the first round" else: - firstCard = self._calcHandValue([hand["hand"][0]]) - secondCard = self._calcHandValue([hand["hand"][1]]) - if firstCard != secondCard: + first_card = self._calc_hand_value([hand["hand"][0]]) + second_card = self._calc_hand_value([hand["hand"][1]]) + if first_card != second_card: log_message = "They tried to split two different cards" - sendMessage = self.bot.long_strings["Blackjack different cards"] + send_message = self.long_strings["Blackjack different cards"] else: bet = hand["bet"] if self.bot.money.checkBalance(user) < bet: log_message = "They didn't have enough GwendoBucks" - sendMessage = "You don't have enough GwendoBucks" + send_message = "You don't have enough GwendoBucks" else: self.bot.money.addMoney(user, -1 * bet) hand["hit"] = True - newHand["hit"] = True + new_hand["hit"] = True - newHand = { + new_hand = { "hand": [], "bet": 0, "standing": False, "busted": False, "blackjack": False, "hit": True, "doubled": False } - newHand["bet"] = hand["bet"] + new_hand["bet"] = hand["bet"] - newHand["hand"].append(hand["hand"].pop(1)) - newHand["hand"].append(self._drawCard(channel)) - hand["hand"].append(self._drawCard(channel)) + new_hand["hand"].append(hand["hand"].pop(1)) + new_hand["hand"].append(self._draw_card(channel)) + hand["hand"].append(self._draw_card(channel)) hand["hit"] = True - handValue = self._calcHandValue(hand["hand"]) - otherHandValue = self._calcHandValue(newHand["hand"]) - if handValue > 21: + hand_value = self._calc_hand_value(hand["hand"]) + other_hand_value = self._calc_hand_value(new_hand["hand"]) + if hand_value > 21: hand["busted"] = True - elif handValue == 21: + elif hand_value == 21: hand["blackjack"] = True - if otherHandValue > 21: - newHand["busted"] = True - elif otherHandValue == 21: - newHand["blackjack"] = True + if other_hand_value > 21: + new_hand["busted"] = True + elif other_hand_value == 21: + new_hand["blackjack"] = True - if handNumber == 2: - handPath = f"user hands.{user}.other hand" - elif handNumber == 3: - handPath = f"user hands.{user}.third hand" + if hand_number == 2: + hand_path = f"user hands.{user}.other hand" + elif hand_number == 3: + hand_path = f"user hands.{user}.third hand" else: - handPath = f"user hands.{user}" + hand_path = f"user hands.{user}" - gameUpdater = {"$set": {handPath: hand}} - blackjack_games.update_one({"_id": channel}, gameUpdater) + game_updater = {"$set": {hand_path: hand}} + blackjack_games.update_one({"_id": channel}, game_updater) - if otherHand == 3: - otherHandPath = f"user hands.{user}.third hand" - elif otherHand == 4: - otherHandPath = f"user hands.{user}.fourth hand" + if other_hand == 3: + other_hand_path = f"user hands.{user}.third hand" + elif other_hand == 4: + other_hand_path = f"user hands.{user}.fourth hand" else: - otherHandPath = f"user hands.{user}.other hand" + other_hand_path = f"user hands.{user}.other hand" - gameUpdater = {"$set": {otherHandPath: newHand}} - blackjack_games.update_one({"_id": channel}, gameUpdater) + game_updater = {"$set": {other_hand_path: new_hand}} + blackjack_games.update_one({"_id": channel}, game_updater) - splitUpdater = {"$inc": {"user hands."+user+".split": 1}} - blackjack_games.update_one({"_id": channel}, splitUpdater) + split_updater = {"$inc": {"user hands."+user+".split": 1}} + blackjack_games.update_one({"_id": channel}, split_updater) game = blackjack_games.find_one({"_id": channel}) - roundDone = self._isRoundDone(game) + round_done = self._is_round_done(game) - sendMessage = self.bot.long_strings["Blackjack split"] + send_message = self.long_strings["Blackjack split"] user_name = self.bot.database_funcs.get_name(user) - sendMessage = sendMessage.format(user_name) + send_message = send_message.format(user_name) log_message = "They succeeded" - await ctx.send(sendMessage) + await ctx.send(send_message) self.bot.log(log_message) - if roundDone: - gameID = game["gameID"] + if round_done: + game_id = game["game_id"] self.bot.log("Stand calling self._blackjack_loop()", channel) - await self._blackjack_loop(ctx.channel, game["round"]+1, gameID) + await self._blackjack_loop(ctx.channel, game["round"]+1, game_id) - async def enterGame(self, ctx: discord_slash.context.SlashContext, - bet: int): + async def enter_game(self, ctx: discord_slash.context.SlashContext, + bet: int): """ Enter the blackjack game. @@ -1007,51 +1031,48 @@ class Blackjack(): self.bot.log(f"{user_name} is trying to join the Blackjack game") if game is None: - sendMessage = "There is no game going on in this channel" - log_message = sendMessage + send_message = "There is no game going on in this channel" + log_message = send_message elif user in game["user hands"]: - sendMessage = "You're already in the game!" + send_message = "You're already in the game!" log_message = "They're already in the game" elif len(game["user hands"]) >= 5: - sendMessage = "There can't be more than 5 players in a game" + send_message = "There can't be more than 5 players in a game" log_message = "There were already 5 players in the game" elif game["round"] != 0: - sendMessage = "The table is no longer taking bets" + send_message = "The table is no longer taking bets" log_message = "They tried to join after the game begun" elif bet < 0: - sendMessage = "You can't bet a negative amount" + send_message = "You can't bet a negative amount" log_message = "They tried to bet a negative amount" elif self.bot.money.checkBalance(user) < bet: - sendMessage = "You don't have enough GwendoBucks" + send_message = "You don't have enough GwendoBucks" log_message = "They didn't have enough GwendoBucks" else: self.bot.money.addMoney(user, -1 * bet) - playerHand = [self._drawCard(channel) for _ in range(2)] + player_hand = [self._draw_card(channel) for _ in range(2)] - handValue = self._calcHandValue(playerHand) + hand_value = self._calc_hand_value(player_hand) - if handValue == 21: - blackjack_hand = True - else: - blackjack_hand = False + blackjack_hand = (hand_value == 21) - newHand = { - "hand": playerHand, "bet": bet, "standing": False, + new_hand = { + "hand": player_hand, "bet": bet, "standing": False, "busted": False, "blackjack": blackjack_hand, "hit": True, "doubled": False, "split": 0, "other hand": {}, "third hand": {}, "fourth hand": {} } - function = {"$set": {f"user hands.{user}": newHand}} + function = {"$set": {f"user hands.{user}": new_hand}} collection.update_one({"_id": channel}, function) - enterGameText = "entered the game with a bet of" - betText = f"{bet} GwendoBucks" - sendMessage = f"{user_name} {enterGameText} {betText}" - log_message = sendMessage + enter_game_text = "entered the game with a bet of" + bet_text = f"{bet} GwendoBucks" + send_message = f"{user_name} {enter_game_text} {bet_text}" + log_message = send_message self.bot.log(log_message) - await ctx.send(sendMessage) + await ctx.send(send_message) async def start(self, ctx: discord_slash.context.SlashContext): """ @@ -1064,17 +1085,17 @@ class Blackjack(): """ await self.bot.defer(ctx) channel = str(ctx.channel_id) - blackjack_minCards = 50 + blackjack_min_cards = 50 self.bot.log("Starting blackjack game") await ctx.send("Starting a new game of blackjack") - cardsLeft = 0 + cards_left = 0 cards = self.bot.database["blackjack cards"].find_one({"_id": channel}) if cards is not None: - cardsLeft = len(cards["cards"]) + cards_left = len(cards["cards"]) # Shuffles if not enough cards - if cardsLeft < blackjack_minCards: + if cards_left < blackjack_min_cards: self._blackjack_shuffle(channel) self.bot.log("Shuffling the blackjack deck...", channel) await ctx.channel.send("Shuffling the deck...") @@ -1082,68 +1103,69 @@ class Blackjack(): game = self.bot.database["blackjack games"].find_one({"_id": channel}) self.bot.log("Trying to start a blackjack game in "+channel) - gameStarted = False + game_started = False if game is None: - dealerHand = [self._drawCard(channel), self._drawCard(channel)] - gameID = datetime.datetime.now().strftime('%Y%m%d%H%M%S') + dealer_hand = [self._draw_card(channel), self._draw_card(channel)] + game_id = datetime.datetime.now().strftime('%Y%m%d%H%M%S') - newGame = { - "_id": channel, "dealer hand": dealerHand, + new_game = { + "_id": channel, "dealer hand": dealer_hand, "dealer busted": False, "dealer blackjack": False, "user hands": {}, "all standing": False, "round": 0, - "gameID": gameID + "game_id": game_id } - if self._calcHandValue(dealerHand) == 21: - newGame["dealer blackjack"] = True + if self._calc_hand_value(dealer_hand) == 21: + new_game["dealer blackjack"] = True - self.bot.database["blackjack games"].insert_one(newGame) + self.bot.database["blackjack games"].insert_one(new_game) - tableImagesPath = "gwendolyn/resources/games/blackjack_tables/" - emptyTableImagePath = f"gwendolyn/resources/games/blackjack_table.png" - newTableImagePath = f"{tableImagesPath}blackjack_table{channel}.png" - copyfile(emptyTableImagePath, newTableImagePath) + table_images_path = "gwendolyn/resources/games/blackjack_tables/" + empty_table_image = "gwendolyn/resources/games/blackjack_table.png" + new_table_image = f"{table_images_path}blackjack_table{channel}.png" + copyfile(empty_table_image, new_table_image) - gameStarted = True + game_started = True - if gameStarted: - sendMessage = self.bot.long_strings["Blackjack started"] - await ctx.channel.send(sendMessage) + if game_started: + send_message = self.long_strings["Blackjack started"] + await ctx.channel.send(send_message) - tableImagesPath = "gwendolyn/resources/games/blackjack_tables/" - file_path = f"{tableImagesPath}blackjack_table{channel}.png" + table_images_path = "gwendolyn/resources/games/blackjack_tables/" + file_path = f"{table_images_path}blackjack_table{channel}.png" old_image = await ctx.channel.send(file=discord.File(file_path)) + old_images_path = "gwendolyn/resources/games/old_images/blackjack" - with open("gwendolyn/resources/games/old_images/blackjack"+channel, "w") as f: - f.write(str(old_image.id)) + with open(old_images_path+channel, "w") as file_pointer: + file_pointer.write(str(old_image.id)) await asyncio.sleep(30) - gamedone = False + game_done = False blackjack_games = self.bot.database["blackjack games"] game = blackjack_games.find_one({"_id": channel}) if len(game["user hands"]) == 0: - gamedone = True - sendMessage = "No one entered the game. Ending the game." - await ctx.channel.send(sendMessage) + game_done = True + send_message = "No one entered the game. Ending the game." + await ctx.channel.send(send_message) - gameID = game["gameID"] + game_id = game["game_id"] # Loop of game rounds - if not gamedone: + if not game_done: self.bot.log("start() calling _blackjack_loop()", channel) - await self._blackjack_loop(ctx.channel, 1, gameID) + await self._blackjack_loop(ctx.channel, 1, game_id) else: new_message = self._blackjack_finish(channel) await ctx.channel.send(new_message) else: - sendMessage = self.bot.long_strings["Blackjack going on"] - await ctx.channel.send(sendMessage) + send_message = self.long_strings["Blackjack going on"] + await ctx.channel.send(send_message) self.bot.log("There was already a game going on") async def hilo(self, ctx: discord_slash.context.SlashContext): @@ -1187,15 +1209,15 @@ class Blackjack(): The context of the command. """ channel = ctx.channel_id - cardsLeft = 0 + cards_left = 0 blackjack_games = self.bot.database["blackjack cards"] cards = blackjack_games.find_one({"_id": str(channel)}) if cards is not None: - cardsLeft = len(cards["cards"]) + cards_left = len(cards["cards"]) - decksLeft = round(cardsLeft/52, 1) - sendMessage = f"Cards left:\n{cardsLeft} cards, {decksLeft} decks" - await ctx.send(sendMessage, hidden=True) + decks_left = round(cards_left/52, 1) + send_message = f"Cards left:\n{cards_left} cards, {decks_left} decks" + await ctx.send(send_message, hidden=True) class DrawBlackjack(): @@ -1204,7 +1226,7 @@ class DrawBlackjack(): *Methods* --------- - drawImage(channel: str) + draw_image(channel: str) *Attributes* ------------ @@ -1215,14 +1237,18 @@ class DrawBlackjack(): PLACEMENT: list The order to place the user hands in. """ + # pylint: disable=too-few-public-methods def __init__(self, bot): """Initialize the class.""" self.bot = bot + # pylint: disable=invalid-name self.BORDER = 100 + self.SMALLBORDER = int(self.BORDER/3.5) self.PLACEMENT = [2, 1, 3, 0, 4] + # pylint: enable=invalid-name - def drawImage(self, channel: str): + def draw_image(self, channel: str): """ Draw the table image. @@ -1234,139 +1260,140 @@ class DrawBlackjack(): self.bot.log("Drawing blackjack table", channel) game = self.bot.database["blackjack games"].find_one({"_id": channel}) - font = ImageFont.truetype('gwendolyn/resources/fonts/futura-bold.ttf', 50) - smallFont = ImageFont.truetype('gwendolyn/resources/fonts/futura-bold.ttf', 40) - self.SMALLBORDER = int(self.BORDER/3.5) + fonts_path = "gwendolyn/resources/fonts/" + font = ImageFont.truetype(fonts_path+'futura-bold.ttf', 50) + small_font = ImageFont.truetype(fonts_path+'futura-bold.ttf', 40) table = Image.open("gwendolyn/resources/games/blackjack_table.png") - textImage = ImageDraw.Draw(table) + text_image = ImageDraw.Draw(table) hands = game["user hands"] - dealerBusted = game["dealer busted"] - dealerBlackjack = game["dealer blackjack"] + dealer_busted = game["dealer busted"] + dealer_blackjack = game["dealer blackjack"] if not game["all standing"]: - handParams = [ + hand_parameters = [ game["dealer hand"], True, False, False ] else: - handParams = [ + hand_parameters = [ game["dealer hand"], False, - dealerBusted, - dealerBlackjack + dealer_busted, + dealer_blackjack ] - dealerHand = self._drawHand(*handParams) + dealer_hand = self._draw_hand(*hand_parameters) - pastePosition = (800-self.SMALLBORDER, 20-self.SMALLBORDER) - table.paste(dealerHand, pastePosition, dealerHand) + paste_position = (800-self.SMALLBORDER, 20-self.SMALLBORDER) + table.paste(dealer_hand, paste_position, dealer_hand) - for x in range(len(hands)): - key, value = list(hands.items())[x] + for i in range(len(hands)): + key, value = list(hands.items())[i] key = self.bot.database_funcs.get_name(key) - handParams = [ + hand_parameters = [ value["hand"], False, value["busted"], value["blackjack"] ] - userHand = self._drawHand(*handParams) - positionX = 32-self.SMALLBORDER+(384*self.PLACEMENT[x]) + user_hand = self._draw_hand(*hand_parameters) + position_x = 32-self.SMALLBORDER+(384*self.PLACEMENT[i]) if value["split"] >= 1: - handParamsTwo = [ + hand_parameters_two = [ value["other hand"]["hand"], False, value["other hand"]["busted"], value["other hand"]["blackjack"] ] - userOtherHand = self._drawHand(*handParamsTwo) + user_other_hand = self._draw_hand(*hand_parameters_two) if value["split"] >= 2: - handParamsThree = [ + hand_parameters_three = [ value["third hand"]["hand"], False, value["third hand"]["busted"], value["third hand"]["blackjack"] ] - userThirdHand = self._drawHand(*handParamsThree) + user_third_hand = self._draw_hand(*hand_parameters_three) if value["split"] >= 3: - handParamsFour = [ + hand_parameters_four = [ value["fourth hand"]["hand"], False, value["fourth hand"]["busted"], value["fourth hand"]["blackjack"] ] - userFourthHand = self._drawHand(*handParamsFour) + user_fourth_hand = self._draw_hand(*hand_parameters_four) if value["split"] == 3: - positionOne = (positionX, 280-self.SMALLBORDER) - positionTwo = (positionX, 420-self.SMALLBORDER) - positionThree = (positionX, 560-self.SMALLBORDER) - positionFour = (positionX, 700-self.SMALLBORDER) + position_one = (position_x, 280-self.SMALLBORDER) + position_two = (position_x, 420-self.SMALLBORDER) + position_three = (position_x, 560-self.SMALLBORDER) + position_four = (position_x, 700-self.SMALLBORDER) - table.paste(userHand, positionOne, userHand) - table.paste(userOtherHand, positionTwo, userOtherHand) - table.paste(userThirdHand, positionThree, userThirdHand) - table.paste(userFourthHand, positionFour, userFourthHand) + table.paste(user_hand, position_one, user_hand) + table.paste(user_other_hand, position_two, user_other_hand) + table.paste(user_third_hand, position_three, user_third_hand) + table.paste(user_fourth_hand, position_four, user_fourth_hand) elif value["split"] == 2: - positionOne = (positionX, 420-self.SMALLBORDER) - positionTwo = (positionX, 560-self.SMALLBORDER) - positionThree = (positionX, 700-self.SMALLBORDER) + position_one = (position_x, 420-self.SMALLBORDER) + position_two = (position_x, 560-self.SMALLBORDER) + position_three = (position_x, 700-self.SMALLBORDER) - table.paste(userHand, positionOne, userHand) - table.paste(userOtherHand, positionTwo, userOtherHand) - table.paste(userThirdHand, positionThree, userThirdHand) + table.paste(user_hand, position_one, user_hand) + table.paste(user_other_hand, position_two, user_other_hand) + table.paste(user_third_hand, position_three, user_third_hand) elif value["split"] == 1: - positionOne = (positionX, 560-self.SMALLBORDER) - positionTwo = (positionX, 700-self.SMALLBORDER) + position_one = (position_x, 560-self.SMALLBORDER) + position_two = (position_x, 700-self.SMALLBORDER) - table.paste(userHand, positionOne, userHand) - table.paste(userOtherHand, positionTwo, userOtherHand) + table.paste(user_hand, position_one, user_hand) + table.paste(user_other_hand, position_two, user_other_hand) else: - positionOne = (positionX, 680-self.SMALLBORDER) - table.paste(userHand, positionOne, userHand) + position_one = (position_x, 680-self.SMALLBORDER) + table.paste(user_hand, position_one, user_hand) - textWidth = font.getsize(key)[0] - textX = 32+(384*self.PLACEMENT[x])+117-int(textWidth/2) + text_width = font.getsize(key)[0] + text_x = 32+(384*self.PLACEMENT[i])+117-int(text_width/2) black = (0, 0, 0) white = (255, 255, 255) - if textWidth < 360: + if text_width < 360: # Black shadow behind and slightly below white text - textImage.text((textX-3, 1010-3), key, fill=black, font=font) - textImage.text((textX+3, 1010-3), key, fill=black, font=font) - textImage.text((textX-3, 1010+3), key, fill=black, font=font) - textImage.text((textX+3, 1010+3), key, fill=black, font=font) - textImage.text((textX, 1005), key, fill=white, font=font) + text_image.text((text_x-3, 1010-3), key, fill=black, font=font) + text_image.text((text_x+3, 1010-3), key, fill=black, font=font) + text_image.text((text_x-3, 1010+3), key, fill=black, font=font) + text_image.text((text_x+3, 1010+3), key, fill=black, font=font) + text_image.text((text_x, 1005), key, fill=white, font=font) else: - textWidth = smallFont.getsize(key)[0] - shadows = [ - (textX-2, 1020-2), - (textX+2, 1020-2), - (textX-2, 1020+2), - (textX+2, 1020+2) + text_width = small_font.getsize(key)[0] + positions = [ + (text_x-2, 1020-2), + (text_x+2, 1020-2), + (text_x-2, 1020+2), + (text_x+2, 1020+2), + (text_x, 1015) ] - textImage.text(shadows[0], key, fill=black, font=smallFont) - textImage.text(shadows[1], key, fill=black, font=smallFont) - textImage.text(shadows[2], key, fill=black, font=smallFont) - textImage.text(shadows[3], key, fill=black, font=smallFont) - textImage.text((textX, 1015), key, fill=white, font=smallFont) + text_image.text(positions[0], key, fill=black, font=small_font) + text_image.text(positions[1], key, fill=black, font=small_font) + text_image.text(positions[2], key, fill=black, font=small_font) + text_image.text(positions[3], key, fill=black, font=small_font) + text_image.text(positions[4], key, fill=white, font=small_font) self.bot.log("Saving table image") - tableImagesPath = "gwendolyn/resources/games/blackjack_tables/" - tableImagePath = f"{tableImagesPath}blackjack_table{channel}.png" - table.save(tableImagePath) + table_images_path = "gwendolyn/resources/games/blackjack_tables/" + table_image_path = f"{table_images_path}blackjack_table{channel}.png" + table.save(table_image_path) return - def _drawHand(self, hand: dict, dealer: bool, busted: bool, - blackjack: bool): + def _draw_hand(self, hand: dict, dealer: bool, busted: bool, + blackjack: bool): """ Draw a hand. @@ -1388,82 +1415,85 @@ class DrawBlackjack(): The image of the hand. """ self.bot.log("Drawing hand {hand}, {busted}, {blackjack}") - font = ImageFont.truetype('gwendolyn/resources/fonts/futura-bold.ttf', 200) - font2 = ImageFont.truetype('gwendolyn/resources/fonts/futura-bold.ttf', 120) + fonts_path = "gwendolyn/resources/fonts/" + font = ImageFont.truetype(fonts_path+'futura-bold.ttf', 200) + font_two = ImageFont.truetype(fonts_path+'futura-bold.ttf', 120) length = len(hand) - backgroundWidth = (self.BORDER*2)+691+(125*(length-1)) - backgroundSize = (backgroundWidth, (self.BORDER*2)+1065) - background = Image.new("RGBA", backgroundSize, (0, 0, 0, 0)) - textImage = ImageDraw.Draw(background) - cardY = self.BORDER+self.PLACEMENT[1] + background_width = (self.BORDER*2)+691+(125*(length-1)) + background_size = (background_width, (self.BORDER*2)+1065) + background = Image.new("RGBA", background_size, (0, 0, 0, 0)) + text_image = ImageDraw.Draw(background) + card_y = self.BORDER+self.PLACEMENT[1] + cards_path = "gwendolyn/resources/games/cards/" if dealer: - img = Image.open("gwendolyn/resources/games/cards/"+hand[0].upper()+".png") - cardPosition = (self.BORDER+self.PLACEMENT[0], cardY) - background.paste(img, cardPosition, img) + img = Image.open(cards_path+hand[0].upper()+".png") + card_position = (self.BORDER+self.PLACEMENT[0], card_y) + background.paste(img, card_position, img) img = Image.open("gwendolyn/resources/games/cards/red_back.png") - cardPosition = (125+self.BORDER+self.PLACEMENT[0], cardY) - background.paste(img, cardPosition, img) + card_position = (125+self.BORDER+self.PLACEMENT[0], card_y) + background.paste(img, card_position, img) else: - for x in range(length): - cardPath = f"gwendolyn/resources/games/cards/{hand[x].upper()}.png" - img = Image.open(cardPath) - cardPosition = (self.BORDER+(x*125)+self.PLACEMENT[0], cardY) - background.paste(img, cardPosition, img) + for i in range(length): + card_path = cards_path + f"{hand[i].upper()}.png" + img = Image.open(card_path) + card_position = (self.BORDER+(i*125)+self.PLACEMENT[0], card_y) + background.paste(img, card_position, img) - w, h = background.size - textHeight = 290+self.BORDER + width, height = background.size + text_height = 290+self.BORDER white = (255, 255, 255) black = (0, 0, 0) red = (255, 50, 50) gold = (155, 123, 0) if busted: - textWidth = font.getsize("BUSTED")[0] - textX = int(w/2)-int(textWidth/2) + text_width = font.getsize("BUSTED")[0] + text_x = int(width/2)-int(text_width/2) positions = [ - (textX-10, textHeight+20-10), - (textX+10, textHeight+20-10), - (textX-10, textHeight+20+10), - (textX+10, textHeight+20+10), - (textX-5, textHeight-5), - (textX+5, textHeight-5), - (textX-5, textHeight+5), - (textX+5, textHeight+5), - (textX, textHeight) + (text_x-10, text_height+20-10), + (text_x+10, text_height+20-10), + (text_x-10, text_height+20+10), + (text_x+10, text_height+20+10), + (text_x-5, text_height-5), + (text_x+5, text_height-5), + (text_x-5, text_height+5), + (text_x+5, text_height+5), + (text_x, text_height) ] - textImage.text(positions[0], "BUSTED", fill=black, font=font) - textImage.text(positions[1], "BUSTED", fill=black, font=font) - textImage.text(positions[2], "BUSTED", fill=black, font=font) - textImage.text(positions[3], "BUSTED", fill=black, font=font) - textImage.text(positions[4], "BUSTED", fill=white, font=font) - textImage.text(positions[5], "BUSTED", fill=white, font=font) - textImage.text(positions[6], "BUSTED", fill=white, font=font) - textImage.text(positions[7], "BUSTED", fill=white, font=font) - textImage.text(positions[8], "BUSTED", fill=red, font=font) + text_image.text(positions[0], "BUSTED", fill=black, font=font) + text_image.text(positions[1], "BUSTED", fill=black, font=font) + text_image.text(positions[2], "BUSTED", fill=black, font=font) + text_image.text(positions[3], "BUSTED", fill=black, font=font) + text_image.text(positions[4], "BUSTED", fill=white, font=font) + text_image.text(positions[5], "BUSTED", fill=white, font=font) + text_image.text(positions[6], "BUSTED", fill=white, font=font) + text_image.text(positions[7], "BUSTED", fill=white, font=font) + text_image.text(positions[8], "BUSTED", fill=red, font=font) elif blackjack: - textWidth = font2.getsize("BLACKJACK")[0] - textX = int(w/2)-int(textWidth/2) + text_width = font_two.getsize("BLACKJACK")[0] + text_x = int(width/2)-int(text_width/2) positions = [ - (textX-6, textHeight+20-6), - (textX+6, textHeight+20-6), - (textX-6, textHeight+20+6), - (textX+6, textHeight+20+6), - (textX-3, textHeight-3), - (textX+3, textHeight-3), - (textX-3, textHeight+3), - (textX+3, textHeight+3), - (textX, textHeight) + (text_x-6, text_height+20-6), + (text_x+6, text_height+20-6), + (text_x-6, text_height+20+6), + (text_x+6, text_height+20+6), + (text_x-3, text_height-3), + (text_x+3, text_height-3), + (text_x-3, text_height+3), + (text_x+3, text_height+3), + (text_x, text_height) ] - textImage.text(positions[0], "BLACKJACK", fill=black, font=font2) - textImage.text(positions[1], "BLACKJACK", fill=black, font=font2) - textImage.text(positions[2], "BLACKJACK", fill=black, font=font2) - textImage.text(positions[3], "BLACKJACK", fill=black, font=font2) - textImage.text(positions[4], "BLACKJACK", fill=white, font=font2) - textImage.text(positions[5], "BLACKJACK", fill=white, font=font2) - textImage.text(positions[6], "BLACKJACK", fill=white, font=font2) - textImage.text(positions[7], "BLACKJACK", fill=white, font=font2) - textImage.text(positions[8], "BLACKJACK", fill=gold, font=font2) + text = "BLACKJACK" + text_image.text(positions[0], text, fill=black, font=font_two) + text_image.text(positions[1], text, fill=black, font=font_two) + text_image.text(positions[2], text, fill=black, font=font_two) + text_image.text(positions[3], text, fill=black, font=font_two) + text_image.text(positions[4], text, fill=white, font=font_two) + text_image.text(positions[5], text, fill=white, font=font_two) + text_image.text(positions[6], text, fill=white, font=font_two) + text_image.text(positions[7], text, fill=white, font=font_two) + text_image.text(positions[8], text, fill=gold, font=font_two) - resizedSize = (int(w/3.5), int(h/3.5)) - return background.resize(resizedSize, resample=Image.BILINEAR) + resized_size = (int(width/3.5), int(height/3.5)) + return background.resize(resized_size, resample=Image.BILINEAR) diff --git a/gwendolyn/funcs/games/connect_four.py b/gwendolyn/funcs/games/connect_four.py index 430b38c..7dc0322 100644 --- a/gwendolyn/funcs/games/connect_four.py +++ b/gwendolyn/funcs/games/connect_four.py @@ -9,13 +9,13 @@ Contains the classes that deal with playing and drawing connect four. import random # Used to shuffle players and by the ai to pick from # similar options import copy # Used to deepcopy boards +from typing import Union # Used for typehints import math # Used for math.inf 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 typing import Union # Used for typehints ROWCOUNT = 6 COLUMNCOUNT = 7 @@ -28,7 +28,7 @@ class ConnectFour(): *Methods* --------- start(ctx: SlashContext, opponent: Union[int, Discord.User]) - placePiece(ctx: Union[SlashContext, discord.Message], + place_piece(ctx: Union[SlashContext, discord.Message], user: int, column: int) surrender(ctx: SlashContext) """ @@ -37,6 +37,8 @@ class ConnectFour(): """Initialize the class.""" self.bot = bot self.draw = DrawConnectFour(bot) + self.database_funcs = self.bot.database_funcs + # pylint: disable=invalid-name self.AISCORES = { "middle": 3, "two in a row": 10, @@ -48,6 +50,7 @@ class ConnectFour(): "avoid losing": 100 } self.REACTIONS = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣"] + # pylint: enable=invalid-name async def start(self, ctx: SlashContext, opponent: Union[int, discord.User]): @@ -69,53 +72,52 @@ class ConnectFour(): channel = str(ctx.channel_id) game = self.bot.database["connect 4 games"].find_one({"_id": channel}) - startedGame = False - canStart = True + started_game = False + can_start = True if game is not None: - sendMessage = self.bot.long_strings["Connect 4 going on"] + send_message = self.bot.long_strings["Connect 4 going on"] log_message = "There was already a game going on" - canStart = False - elif type(opponent) == int: + can_start = False + elif isinstance(opponent, int): # Opponent is Gwendolyn if opponent in range(1, 6): difficulty = int(opponent) - diffText = f" with difficulty {difficulty}" + difficulty_text = f" with difficulty {difficulty}" opponent = f"#{self.bot.user.id}" else: - sendMessage = "Difficulty doesn't exist" + send_message = "Difficulty doesn't exist" log_message = "They challenged a difficulty that doesn't exist" - canStart = False - elif type(opponent) == discord.User: + can_start = False + elif isinstance(opponent, discord.User): if opponent.bot: # User has challenged a bot if opponent == self.bot.user: # It was Gwendolyn difficulty = 3 - diffText = f" with difficulty {difficulty}" + difficulty_text = f" with difficulty {difficulty}" opponent = f"#{self.bot.user.id}" else: - sendMessage = "You can't challenge a bot!" + send_message = "You can't challenge a bot!" log_message = "They tried to challenge a bot" - canStart = False + can_start = False else: # Opponent is another player if ctx.author != opponent: opponent = f"#{opponent.id}" difficulty = 5 - diffText = "" + difficulty_text = "" else: - sendMessage = "You can't play against yourself" + send_message = "You can't play against yourself" log_message = "They tried to play against themself" - canStart = False + can_start = False - if canStart: - x, y = COLUMNCOUNT, ROWCOUNT - board = [[0 for _ in range(x)] for _ in range(y)] + if can_start: + board = [[0 for _ in range(COLUMNCOUNT)] for _ in range(ROWCOUNT)] players = [user, opponent] random.shuffle(players) - newGame = { + new_game = { "_id": channel, "board": board, "winner": 0, @@ -126,42 +128,45 @@ class ConnectFour(): "difficulty": difficulty } - self.bot.database["connect 4 games"].insert_one(newGame) + self.bot.database["connect 4 games"].insert_one(new_game) - self.draw.drawImage(channel) + self.draw.draw_image(channel) - gwendoTurn = (players[0] == f"#{self.bot.user.id}") - startedGame = True + gwendolyn_turn = (players[0] == f"#{self.bot.user.id}") + started_game = True - opponentName = self.bot.database_funcs.get_name(opponent) - turnName = self.bot.database_funcs.get_name(players[0]) + opponent_name = self.database_funcs.get_name(opponent) + turn_name = self.database_funcs.get_name(players[0]) - startedText = f"Started game against {opponentName}{diffText}." - turnText = f"It's {turnName}'s turn" - sendMessage = f"{startedText} {turnText}" + started_text = "Started game against {}{}.".format( + opponent_name, + difficulty_text + ) + turn_text = f"It's {turn_name}'s turn" + send_message = f"{started_text} {turn_text}" log_message = "They started a game" self.bot.log(log_message) - await ctx.send(sendMessage) + await ctx.send(send_message) # Sets the whole game in motion - if startedGame: - boardsPath = "gwendolyn/resources/games/connect4Boards/" - file_path = f"{boardsPath}board{ctx.channel_id}.png" + 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_imagesPath = "gwendolyn/resources/games/old_images/" - old_imagePath = f"{old_imagesPath}connect_four{ctx.channel_id}" - with open(old_imagePath, "w") as f: - f.write(str(old_image.id)) + 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)) - if gwendoTurn: - await self._connect_fourAI(ctx) + if gwendolyn_turn: + await self._connect_four_ai(ctx) else: for reaction in self.REACTIONS: await old_image.add_reaction(reaction) - async def placePiece(self, ctx: Union[SlashContext, discord.Message], + async def place_piece(self, ctx: Union[SlashContext, discord.Message], user: int, column: int): """ Place a piece on the board. @@ -180,90 +185,95 @@ class ConnectFour(): The column the player is placing the piece in. """ channel = str(ctx.channel.id) - connect4Games = self.bot.database["connect 4 games"] - game = connect4Games.find_one({"_id": channel}) - playerNumber = game["players"].index(user)+1 - user_name = self.bot.database_funcs.get_name(user) - placedPiece = False + 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) + placed_piece = False if game is None: - sendMessage = "There's no game in this channel" + send_message = "There's no game in this channel" log_message = "There was no game in the channel" else: board = game["board"] - board = self._placeOnBoard(board, playerNumber, column) + board = self._place_on_board(board, player_number, column) if board is None: - sendMessage = "There isn't any room in that column" + send_message = "There isn't any room in that column" log_message = "There wasn't any room in the column" else: updater = {"$set": {"board": board}} - connect4Games.update_one({"_id": channel}, updater) + connect_four_games.update_one({"_id": channel}, updater) turn = (game["turn"]+1) % 2 updater = {"$set": {"turn": turn}} - connect4Games.update_one({"_id": channel}, updater) + connect_four_games.update_one({"_id": channel}, updater) self.bot.log("Checking for win") - won, winDirection, winCoordinates = self._isWon(board) + won, win_direction, win_coordinates = self._is_won(board) if won != 0: - gameWon = True + game_won = True updater = {"$set": {"winner": won}} - connect4Games.update_one({"_id": channel}, updater) - updater = {"$set": {"win direction": winDirection}} - connect4Games.update_one({"_id": channel}, updater) - updater = {"$set": {"win coordinates": winCoordinates}} - connect4Games.update_one({"_id": channel}, updater) + 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) - sendMessage = "{} placed a piece in column {} and won. " - sendMessage = sendMessage.format(user_name, column+1) + send_message = "{} placed a piece in column {} and won. " + send_message = send_message.format(user_name, column+1) log_message = f"{user_name} won" - winAmount = int(game["difficulty"])**2+5 + win_amount = int(game["difficulty"])**2+5 if game["players"][won-1] != f"#{self.bot.user.id}": - sendMessage += "Adding {} GwendoBucks to their account" - sendMessage = sendMessage.format(winAmount) + send_message += "Adding {} GwendoBucks to their account" + send_message = send_message.format(win_amount) elif 0 not in board[0]: - gameWon = True - sendMessage = "It's a draw!" + game_won = True + send_message = "It's a draw!" log_message = "The game ended in a draw" else: - gameWon = False - otherUserId = game["players"][turn] - otherUserName = self.bot.database_funcs.get_name(otherUserId) - sendMessage = self.bot.long_strings["Connect 4 placed"] - formatParams = [user_name, column+1, otherUserName] - sendMessage = sendMessage.format(*formatParams) + 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" - gwendoTurn = (game["players"][turn] == f"#{self.bot.user.id}") + gwendolyn_turn = ( + game["players"][turn] == f"#{self.bot.user.id}") - placedPiece = True + placed_piece = True - await ctx.channel.send(sendMessage) + await ctx.channel.send(send_message) self.bot.log(log_message) - if placedPiece: - self.draw.drawImage(channel) + if placed_piece: + self.draw.draw_image(channel) - old_imagePath = f"gwendolyn/resources/games/old_images/connect_four{channel}" - with open(old_imagePath, "r") as f: - old_image = await ctx.channel.fetch_message(int(f.read())) + 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") - file_path = f"gwendolyn/resources/games/connect4Boards/board{channel}.png" + 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)) - if gameWon: - self._endGame(channel) + if game_won: + self._end_game(channel) else: - with open(old_imagePath, "w") as f: - f.write(str(old_image.id)) - if gwendoTurn: - await self._connect_fourAI(ctx) + with open(old_image_path, "w") as file_pointer: + file_pointer.write(str(old_image.id)) + if gwendolyn_turn: + await self._connect_four_ai(ctx) else: for reaction in self.REACTIONS: await old_image.add_reaction(reaction) @@ -282,37 +292,39 @@ class ConnectFour(): game = self.bot.database["connect 4 games"].find_one({"_id": channel}) if f"#{ctx.author.id}" in game["players"]: - loserIndex = game["players"].index(f"#{ctx.author.id}") - winnerIndex = (loserIndex+1) % 2 - winnerID = game["players"][winnerIndex] - winnerName = self.bot.database_funcs.get_name(winnerID) + 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) - sendMessage = f"{ctx.author.display_name} surrenders." - sendMessage += f" This means {winnerName} is the winner." - if winnerID != f"#{self.bot.user.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 - sendMessage += f" Adding {reward} to their account" + send_message += f" Adding {reward} to their account" - await ctx.send(sendMessage) - old_imagePath = f"gwendolyn/resources/games/old_images/connect_four{channel}" - with open(old_imagePath, "r") as f: - old_image = await ctx.channel.fetch_message(int(f.read())) + 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) if old_image is not None: await old_image.delete() else: self.bot.log("The old image was already deleted") - self._endGame(channel) + self._end_game(channel) else: await ctx.send("You can't surrender when you're not a player") - def _placeOnBoard(self, board: dict, player: int, column: int): + def _place_on_board(self, board: dict, player: int, column: int): """ Place a piece in a given board. - This differs from placePiece() by not having anything to do + This differs from place_piece() by not having anything to do with any actual game. It just places the piece in a game dict. *Parameters* @@ -329,21 +341,21 @@ class ConnectFour(): board: dict The board with the placed piece. """ - placementX, placementY = -1, column + placement_x, placement_y = -1, column - for x, line in list(enumerate(board))[::-1]: + for i, line in list(enumerate(board))[::-1]: if line[column] == 0: - placementX = x + placement_x = i break - board[placementX][placementY] = player + board[placement_x][placement_y] = player - if placementX == -1: + if placement_x == -1: return None else: return board - def _endGame(self, channel: str): + def _end_game(self, channel: str): game = self.bot.database["connect 4 games"].find_one({"_id": channel}) winner = game["winner"] @@ -353,87 +365,87 @@ class ConnectFour(): reward = difficulty**2 + 5 self.bot.money.addMoney(game["players"][winner-1], reward) - self.bot.database_funcs.delete_game("connect 4 games", channel) + self.database_funcs.delete_game("connect 4 games", channel) - def _isWon(self, board: dict): + def _is_won(self, board: dict): won = 0 - winDirection = "" - winCoordinates = [0, 0] + win_direction = "" + win_coordinates = [0, 0] for row in range(ROWCOUNT): for place in range(COLUMNCOUNT): if won == 0: - piecePlayer = board[row][place] - if piecePlayer != 0: + piece_player = board[row][place] + if piece_player != 0: # Checks horizontal if place <= COLUMNCOUNT-4: - pieceOne = board[row][place+1] - pieceTwo = board[row][place+2] - pieceThree = board[row][place+3] + piece_one = board[row][place+1] + piece_two = board[row][place+2] + piece_three = board[row][place+3] - pieces = [pieceOne, pieceTwo, pieceThree] + pieces = [piece_one, piece_two, piece_three] else: pieces = [0] - if all(x == piecePlayer for x in pieces): - won = piecePlayer - winDirection = "h" - winCoordinates = [row, place] + if all(x == piece_player for x in pieces): + won = piece_player + win_direction = "h" + win_coordinates = [row, place] # Checks vertical if row <= ROWCOUNT-4: - pieceOne = board[row+1][place] - pieceTwo = board[row+2][place] - pieceThree = board[row+3][place] + piece_one = board[row+1][place] + piece_two = board[row+2][place] + piece_three = board[row+3][place] - pieces = [pieceOne, pieceTwo, pieceThree] + pieces = [piece_one, piece_two, piece_three] else: pieces = [0] - if all(x == piecePlayer for x in pieces): - won = piecePlayer - winDirection = "v" - winCoordinates = [row, place] + if all(x == piece_player for x in pieces): + won = piece_player + win_direction = "v" + win_coordinates = [row, place] # Checks right diagonal - goodRow = (row <= ROWCOUNT-4) - goodColumn = (place <= COLUMNCOUNT-4) - if goodRow and goodColumn: - pieceOne = board[row+1][place+1] - pieceTwo = board[row+2][place+2] - pieceThree = board[row+3][place+3] + good_row = (row <= ROWCOUNT-4) + good_column = (place <= COLUMNCOUNT-4) + if good_row and good_column: + piece_one = board[row+1][place+1] + piece_two = board[row+2][place+2] + piece_three = board[row+3][place+3] - pieces = [pieceOne, pieceTwo, pieceThree] + pieces = [piece_one, piece_two, piece_three] else: pieces = [0] - if all(x == piecePlayer for x in pieces): - won = piecePlayer - winDirection = "r" - winCoordinates = [row, place] + if all(x == piece_player for x in pieces): + won = piece_player + win_direction = "r" + win_coordinates = [row, place] # Checks left diagonal if row <= ROWCOUNT-4 and place >= 3: - pieceOne = board[row+1][place-1] - pieceTwo = board[row+2][place-2] - pieceThree = board[row+3][place-3] + piece_one = board[row+1][place-1] + piece_two = board[row+2][place-2] + piece_three = board[row+3][place-3] - pieces = [pieceOne, pieceTwo, pieceThree] + pieces = [piece_one, piece_two, piece_three] else: pieces = [0] - if all(x == piecePlayer for x in pieces): - won = piecePlayer - winDirection = "l" - winCoordinates = [row, place] + if all(i == piece_player for i in pieces): + won = piece_player + win_direction = "l" + win_coordinates = [row, place] - return won, winDirection, winCoordinates + return won, win_direction, win_coordinates - async def _connect_fourAI(self, ctx: SlashContext): - def outOfRange(possibleScores: list): - allowedRange = max(possibleScores)*(1-0.1) - moreThanOne = len(possibleScores) != 1 - return (min(possibleScores) <= allowedRange) and moreThanOne + async def _connect_four_ai(self, ctx: SlashContext): + 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) @@ -446,11 +458,11 @@ class ConnectFour(): scores = [-math.inf for _ in range(COLUMNCOUNT)] for column in range(COLUMNCOUNT): - testBoard = copy.deepcopy(board) - testBoard = self._placeOnBoard(testBoard, player, column) - if testBoard is not None: - _minimaxParams = [ - testBoard, + test_board = copy.deepcopy(board) + test_board = self._place_on_board(test_board, player, column) + if test_board is not None: + minimax_parameters = [ + test_board, difficulty, player % 2+1, player, @@ -458,79 +470,79 @@ class ConnectFour(): math.inf, False ] - scores[column] = await self._minimax(*_minimaxParams) + scores[column] = await self._minimax(*minimax_parameters) self.bot.log(f"Best score for column {column} is {scores[column]}") - possibleScores = scores.copy() + possible_scores = scores.copy() - while outOfRange(possibleScores): - possibleScores.remove(min(possibleScores)) + while out_of_range(possible_scores): + possible_scores.remove(min(possible_scores)) - highestScore = random.choice(possibleScores) + highest_score = random.choice(possible_scores) - bestColumns = [i for i, x in enumerate(scores) if x == highestScore] - placement = random.choice(bestColumns) + best_columns = [i for i, x in enumerate(scores) if x == highest_score] + placement = random.choice(best_columns) - await self.placePiece(ctx, f"#{self.bot.user.id}", placement) + await self.place_piece(ctx, f"#{self.bot.user.id}", placement) - def _AICalcPoints(self, board: dict, player: int): + def _ai_calc_points(self, board: dict, player: int): score = 0 - otherPlayer = player % 2+1 + other_player = player % 2+1 # Adds points for middle placement # Checks horizontal for row in range(ROWCOUNT): if board[row][3] == player: score += self.AISCORES["middle"] - rowArray = [int(i) for i in list(board[row])] + row_array = [int(i) for i in list(board[row])] for place in range(COLUMNCOUNT-3): - window = rowArray[place:place+4] - score += self._evaluateWindow(window, player, otherPlayer) + window = row_array[place:place+4] + score += self._evaluate_window(window, player, other_player) # Checks Vertical for column in range(COLUMNCOUNT): - columnArray = [int(i[column]) for i in list(board)] + column_array = [int(i[column]) for i in list(board)] for place in range(ROWCOUNT-3): - window = columnArray[place:place+4] - score += self._evaluateWindow(window, player, otherPlayer) + window = column_array[place:place+4] + score += self._evaluate_window(window, player, other_player) # Checks right diagonal for row in range(ROWCOUNT-3): for place in range(COLUMNCOUNT-3): - pieceOne = board[row][place] - pieceTwo = board[row+1][place+1] - pieceThree = board[row+2][place+2] - pieceFour = board[row+3][place+3] + piece_one = board[row][place] + piece_two = board[row+1][place+1] + piece_three = board[row+2][place+2] + piece_four = board[row+3][place+3] - window = [pieceOne, pieceTwo, pieceThree, pieceFour] - score += self._evaluateWindow(window, player, otherPlayer) + window = [piece_one, piece_two, piece_three, piece_four] + score += self._evaluate_window(window, player, other_player) for place in range(3, COLUMNCOUNT): - pieceOne = board[row][place] - pieceTwo = board[row+1][place-1] - pieceThree = board[row+2][place-2] - pieceFour = board[row+3][place-3] + piece_one = board[row][place] + piece_two = board[row+1][place-1] + piece_three = board[row+2][place-2] + piece_four = board[row+3][place-3] - window = [pieceOne, pieceTwo, pieceThree, pieceFour] - score += self._evaluateWindow(window, player, otherPlayer) + window = [piece_one, piece_two, piece_three, piece_four] + score += self._evaluate_window(window, player, other_player) return score - def _evaluateWindow(self, window: list, player: int, otherPlayer: int): + def _evaluate_window(self, window: list, player: int, other_player: int): if window.count(player) == 4: return self.AISCORES["win"] elif window.count(player) == 3 and window.count(0) == 1: return self.AISCORES["three in a row"] elif window.count(player) == 2 and window.count(0) == 2: return self.AISCORES["two in a row"] - elif window.count(otherPlayer) == 4: + elif window.count(other_player) == 4: return self.AISCORES["enemy win"] else: return 0 async def _minimax(self, board: dict, depth: int, player: int, - originalPlayer: int, alpha: int, beta: int, - maximizingPlayer: bool): + original_player: int, alpha: int, beta: int, + maximizing_player: bool): """ Evaluate the minimax value of a board. @@ -543,12 +555,12 @@ class ConnectFour(): is returned. player: int The player who can place a piece. - originalPlayer: int + original_player: int The AI player. alpha, beta: int Used with alpha/beta pruning, in order to prune options that will never be picked. - maximizingPlayer: bool + maximizing_player: bool Whether the current player is the one trying to maximize their score. @@ -558,27 +570,27 @@ class ConnectFour(): The minimax value of the board. """ terminal = 0 not in board[0] - points = self._AICalcPoints(board, originalPlayer) + points = self._ai_calc_points(board, original_player) # The depth is how many moves ahead the computer checks. This # value is the difficulty. if depth == 0 or terminal or (points > 5000 or points < -6000): return points - if maximizingPlayer: + if maximizing_player: value = -math.inf for column in range(0, COLUMNCOUNT): - testBoard = copy.deepcopy(board) - testBoard = self._placeOnBoard(testBoard, player, column) - if testBoard is not None: - _minimaxParams = [ - testBoard, + test_board = copy.deepcopy(board) + test_board = self._place_on_board(test_board, player, column) + if test_board is not None: + minimax_parameters = [ + test_board, depth-1, (player % 2)+1, - originalPlayer, + original_player, alpha, beta, False ] - evaluation = await self._minimax(*_minimaxParams) + evaluation = await self._minimax(*minimax_parameters) if evaluation < -9000: evaluation += self.AISCORES["avoid losing"] value = max(value, evaluation) @@ -589,19 +601,19 @@ class ConnectFour(): else: value = math.inf for column in range(0, COLUMNCOUNT): - testBoard = copy.deepcopy(board) - testBoard = self._placeOnBoard(testBoard, player, column) - if testBoard is not None: - _minimaxParams = [ - testBoard, + test_board = copy.deepcopy(board) + test_board = self._place_on_board(test_board, player, column) + if test_board is not None: + minimax_parameters = [ + test_board, depth-1, (player % 2)+1, - originalPlayer, + original_player, alpha, beta, True ] - evaluation = await self._minimax(*_minimaxParams) + evaluation = await self._minimax(*minimax_parameters) if evaluation < -9000: evaluation += self.AISCORES["avoid losing"] value = min(value, evaluation) @@ -617,7 +629,7 @@ class DrawConnectFour(): *Methods* --------- - drawImage(channel: str) + draw_image(channel: str) *Attributes* ------------ @@ -665,13 +677,17 @@ class DrawConnectFour(): PIECESTARTX, PIECESTARTY: int Where the top left piece should be placed. WINBARWHITE: RGBA tuple - White, but with the alpha set to winbarAlpha. + White, but with the alpha set to win_bar_alpha. """ def __init__(self, bot): """Initialize the class.""" self.bot = bot + self.database_funcs = self.bot.database_funcs + win_bar_alpha = 160 + font_path = "gwendolyn/resources/fonts/futura-bold.ttf" + # pylint: disable=invalid-name self.BORDER = 40 self.GRIDBORDER = 40 self.CORNERSIZE = 300 @@ -691,29 +707,29 @@ class DrawConnectFour(): self.PLAYER1COLOR = (254, 74, 73) self.PLAYER2COLOR = (254, 215, 102) self.BOARDCOLOR = (42, 183, 202) - winbarAlpha = 160 self.WINBARCOLOR = (250, 250, 250, 255) self.PIECESIZE = 300 - fontPath = "gwendolyn/resources/fonts/futura-bold.ttf" + # pylint: enable=invalid-name - self.FONT = ImageFont.truetype(fontPath, self.TEXTSIZE) + board_width = self.WIDTH-(2*(self.BORDER+self.GRIDBORDER)) + board_height = self.HEIGHT-(2*(self.BORDER+self.GRIDBORDER)) + board_size = [board_width, board_height] + piece_width = board_size[0]//COLUMNCOUNT + piece_height = board_size[1]//ROWCOUNT + piece_start = (self.BORDER+self.GRIDBORDER)-(self.PIECESIZE//2) - boardWidth = self.WIDTH-(2*(self.BORDER+self.GRIDBORDER)) - boardHeight = self.HEIGHT-(2*(self.BORDER+self.GRIDBORDER)) - boardSize = [boardWidth, boardHeight] + # pylint: disable=invalid-name + self.FONT = ImageFont.truetype(font_path, self.TEXTSIZE) + self.PIECEGRIDSIZE = [piece_width, piece_height] - pieceWidth = boardSize[0]//COLUMNCOUNT - pieceHeight = boardSize[1]//ROWCOUNT - self.PIECEGRIDSIZE = [pieceWidth, pieceHeight] + self.PIECESTARTX = piece_start+(self.PIECEGRIDSIZE[0]//2) + self.PIECESTARTY = piece_start+(self.PIECEGRIDSIZE[1]//2) - pieceStart = (self.BORDER+self.GRIDBORDER)-(self.PIECESIZE//2) - self.PIECESTARTX = pieceStart+(self.PIECEGRIDSIZE[0]//2) - self.PIECESTARTY = pieceStart+(self.PIECEGRIDSIZE[1]//2) - - self.WINBARWHITE = (255, 255, 255, winbarAlpha) + self.WINBARWHITE = (255, 255, 255, win_bar_alpha) + # pylint: enable=invalid-name # Draws the whole thing - def drawImage(self, channel: str): + def draw_image(self, channel: str): """ Draw an image of the connect four board. @@ -727,32 +743,33 @@ class DrawConnectFour(): board = game["board"] - imageSize = (self.WIDTH, self.HEIGHT+self.BOTTOMBORDER) - background = Image.new("RGB", imageSize, self.BACKGROUNDCOLOR) - d = ImageDraw.Draw(background, "RGBA") + image_size = (self.WIDTH, self.HEIGHT+self.BOTTOMBORDER) + background = Image.new("RGB", image_size, self.BACKGROUNDCOLOR) + drawer = ImageDraw.Draw(background, "RGBA") - self._drawBoard(d) + self._draw_board(drawer) - self._drawPieces(d, board) + self._draw_pieces(drawer, board) if game["winner"] != 0: - self._drawWin(background, game) + self._draw_win(background, game) - self._drawFooter(d, game) + self._draw_footer(drawer, game) - background.save(f"gwendolyn/resources/games/connect4Boards/board{channel}.png") + boards_path = "gwendolyn/resources/games/connect_four_boards/" + background.save(boards_path + f"board{channel}.png") - def _drawBoard(self, d: ImageDraw): + def _draw_board(self, drawer: ImageDraw): # This whole part was the easiest way to make a rectangle with # rounded corners and an outline - drawParams = { + draw_parameters = { "fill": self.BOARDCOLOR, "outline": self.BOARDOUTLINECOLOR, "width": self.BOARDOUTLINESIZE } # - Corners -: - cornerPositions = [ + corner_positions = [ [ ( self.BORDER, @@ -788,13 +805,13 @@ class DrawConnectFour(): ] ] - d.ellipse(cornerPositions[0], **drawParams) - d.ellipse(cornerPositions[1], **drawParams) - d.ellipse(cornerPositions[2], **drawParams) - d.ellipse(cornerPositions[3], **drawParams) + drawer.ellipse(corner_positions[0], **draw_parameters) + drawer.ellipse(corner_positions[1], **draw_parameters) + drawer.ellipse(corner_positions[2], **draw_parameters) + drawer.ellipse(corner_positions[3], **draw_parameters) # - Rectangle -: - rectanglePositions = [ + rectangle_positions = [ [ ( self.BORDER+(self.CORNERSIZE//2), @@ -813,11 +830,11 @@ class DrawConnectFour(): ) ] ] - d.rectangle(rectanglePositions[0], **drawParams) - d.rectangle(rectanglePositions[1], **drawParams) + drawer.rectangle(rectangle_positions[0], **draw_parameters) + drawer.rectangle(rectangle_positions[1], **draw_parameters) # - Removing outline on the inside -: - cleanUpPositions = [ + clean_up_positions = [ [ ( self.BORDER+(self.CORNERSIZE//2), @@ -844,43 +861,43 @@ class DrawConnectFour(): ) ] ] - d.rectangle(cleanUpPositions[0], fill=self.BOARDCOLOR) - d.rectangle(cleanUpPositions[1], fill=self.BOARDCOLOR) - d.rectangle(cleanUpPositions[2], fill=self.BOARDCOLOR) + drawer.rectangle(clean_up_positions[0], fill=self.BOARDCOLOR) + drawer.rectangle(clean_up_positions[1], fill=self.BOARDCOLOR) + drawer.rectangle(clean_up_positions[2], fill=self.BOARDCOLOR) - def _drawPieces(self, d: ImageDraw, board: list): - for x, line in enumerate(board): - for y, piece in enumerate(line): + def _draw_pieces(self, drawer: ImageDraw, board: list): + for piece_x, line in enumerate(board): + for piece_y, piece in enumerate(line): if piece == 1: - pieceColor = self.PLAYER1COLOR - outlineWidth = self.PIECEOUTLINESIZE - outlineColor = self.PIECEOUTLINECOLOR + piece_color = self.PLAYER1COLOR + outline_width = self.PIECEOUTLINESIZE + outline_color = self.PIECEOUTLINECOLOR elif piece == 2: - pieceColor = self.PLAYER2COLOR - outlineWidth = self.PIECEOUTLINESIZE - outlineColor = self.PIECEOUTLINECOLOR + piece_color = self.PLAYER2COLOR + outline_width = self.PIECEOUTLINESIZE + outline_color = self.PIECEOUTLINECOLOR else: - pieceColor = self.BACKGROUNDCOLOR - outlineWidth = self.EMPTYOUTLINESIZE - outlineColor = self.EMPTYOUTLINECOLOR + piece_color = self.BACKGROUNDCOLOR + outline_width = self.EMPTYOUTLINESIZE + outline_color = self.EMPTYOUTLINECOLOR - startX = self.PIECESTARTX + self.PIECEGRIDSIZE[0]*y - startY = self.PIECESTARTY + self.PIECEGRIDSIZE[1]*x + start_x = self.PIECESTARTX + self.PIECEGRIDSIZE[0]*piece_y + start_y = self.PIECESTARTY + self.PIECEGRIDSIZE[1]*piece_x position = [ - (startX, startY), - (startX+self.PIECESIZE, startY+self.PIECESIZE) + (start_x, start_y), + (start_x+self.PIECESIZE, start_y+self.PIECESIZE) ] - pieceParams = { - "fill": pieceColor, - "outline": outlineColor, - "width": outlineWidth + piece_parameters = { + "fill": piece_color, + "outline": outline_color, + "width": outline_width } - d.ellipse(position, **pieceParams) + drawer.ellipse(position, **piece_parameters) - def _drawWin(self, background: Image, game: dict): + def _draw_win(self, background: Image, game: dict): """ Draw the bar that shows the winning pieces. @@ -893,19 +910,23 @@ class DrawConnectFour(): """ coordinates = game["win coordinates"] start = self.BORDER + self.GRIDBORDER - startX = start + self.PIECEGRIDSIZE[0]*coordinates[1] - startY = start + self.PIECEGRIDSIZE[1]*coordinates[0] - a = (self.PIECEGRIDSIZE[0]*4-self.GRIDBORDER-self.BORDER)**2 - b = (self.PIECEGRIDSIZE[1]*4-self.GRIDBORDER-self.BORDER)**2 - diagonalLength = (math.sqrt(a+b))/self.PIECEGRIDSIZE[0] - sizeRatio = self.PIECEGRIDSIZE[1]/self.PIECEGRIDSIZE[0] - diagonalAngle = math.degrees(math.atan(sizeRatio)) + start_x = start + self.PIECEGRIDSIZE[0]*coordinates[1] + start_y = start + self.PIECEGRIDSIZE[1]*coordinates[0] + diagonal_length = ( + (math.sqrt( + (self.PIECEGRIDSIZE[0]*4-self.GRIDBORDER-self.BORDER)**2+ + (self.PIECEGRIDSIZE[1]*4-self.GRIDBORDER-self.BORDER)**2 + ))/ + self.PIECEGRIDSIZE[0] + ) + size_ratio = self.PIECEGRIDSIZE[1]/self.PIECEGRIDSIZE[0] + diagonal_angle = math.degrees(math.atan(size_ratio)) if game["win direction"] == "h": - imageSize = (self.PIECEGRIDSIZE[0]*4, self.PIECEGRIDSIZE[1]) - winBar = Image.new("RGBA", imageSize, (0, 0, 0, 0)) - winD = ImageDraw.Draw(winBar) - drawPositions = [ + 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) + draw_position = [ [ (0, 0), (self.PIECEGRIDSIZE[0], self.PIECEGRIDSIZE[1]) @@ -917,15 +938,15 @@ class DrawConnectFour(): (int(self.PIECEGRIDSIZE[0]*3.5), self.PIECEGRIDSIZE[1]) ] ] - winD.ellipse(drawPositions[0], fill=self.WINBARWHITE) - winD.ellipse(drawPositions[1], fill=self.WINBARWHITE) - winD.rectangle(drawPositions[2], fill=self.WINBARWHITE) + win_drawer.ellipse(draw_position[0], fill=self.WINBARWHITE) + win_drawer.ellipse(draw_position[1], fill=self.WINBARWHITE) + win_drawer.rectangle(draw_position[2], fill=self.WINBARWHITE) elif game["win direction"] == "v": - imageSize = (self.PIECEGRIDSIZE[0], self.PIECEGRIDSIZE[1]*4) - winBar = Image.new("RGBA", imageSize, (0, 0, 0, 0)) - winD = ImageDraw.Draw(winBar) - drawPositions = [ + 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) + draw_position = [ [ (0, 0), (self.PIECEGRIDSIZE[0], self.PIECEGRIDSIZE[1]) @@ -937,16 +958,16 @@ class DrawConnectFour(): (self.PIECEGRIDSIZE[0], int(self.PIECEGRIDSIZE[1]*3.5)) ] ] - winD.ellipse(drawPositions[0], fill=self.WINBARWHITE) - winD.ellipse(drawPositions[1], fill=self.WINBARWHITE) - winD.rectangle(drawPositions[2], fill=self.WINBARWHITE) + win_drawer.ellipse(draw_position[0], fill=self.WINBARWHITE) + win_drawer.ellipse(draw_position[1], fill=self.WINBARWHITE) + win_drawer.rectangle(draw_position[2], fill=self.WINBARWHITE) elif game["win direction"] == "r": - imageWidth = int(self.PIECEGRIDSIZE[0]*diagonalLength) - imageSize = (imageWidth, self.PIECEGRIDSIZE[1]) - winBar = Image.new("RGBA", imageSize, (0, 0, 0, 0)) - winD = ImageDraw.Draw(winBar) - drawPositions = [ + 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)) + win_drawer = ImageDraw.Draw(win_bar) + draw_position = [ [ ( 0, @@ -957,10 +978,10 @@ class DrawConnectFour(): ) ], [ ( - (self.PIECEGRIDSIZE[0]*(diagonalLength-1)), + (self.PIECEGRIDSIZE[0]*(diagonal_length-1)), 0 ), ( - self.PIECEGRIDSIZE[0]*diagonalLength, + self.PIECEGRIDSIZE[0]*diagonal_length, self.PIECEGRIDSIZE[1] ) ], [ @@ -968,33 +989,33 @@ class DrawConnectFour(): int(self.PIECEGRIDSIZE[0]*0.5), 0 ), ( - int(self.PIECEGRIDSIZE[0]*(diagonalLength-0.5)), + int(self.PIECEGRIDSIZE[0]*(diagonal_length-0.5)), self.PIECEGRIDSIZE[1] ) ] ] - winD.ellipse(drawPositions[0], fill=self.WINBARWHITE) - winD.ellipse(drawPositions[1], fill=self.WINBARWHITE) - winD.rectangle(drawPositions[2], fill=self.WINBARWHITE) - winBar = winBar.rotate(-diagonalAngle, expand=1) - startX -= 90 - startY -= 100 + win_drawer.ellipse(draw_position[0], fill=self.WINBARWHITE) + win_drawer.ellipse(draw_position[1], fill=self.WINBARWHITE) + win_drawer.rectangle(draw_position[2], fill=self.WINBARWHITE) + win_bar = win_bar.rotate(-diagonal_angle, expand=1) + start_x -= 90 + start_y -= 100 elif game["win direction"] == "l": - imageWidth = int(self.PIECEGRIDSIZE[0]*diagonalLength) - imageSize = (imageWidth, self.PIECEGRIDSIZE[1]) - winBar = Image.new("RGBA", imageSize, (0, 0, 0, 0)) - winD = ImageDraw.Draw(winBar) - drawPositions = [ + 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)) + win_drawer = ImageDraw.Draw(win_bar) + draw_position = [ [ (0, 0), (self.PIECEGRIDSIZE[0], self.PIECEGRIDSIZE[1]) ], [ ( - (self.PIECEGRIDSIZE[0]*(diagonalLength-1)), + (self.PIECEGRIDSIZE[0]*(diagonal_length-1)), 0 ), ( - self.PIECEGRIDSIZE[0]*diagonalLength, + self.PIECEGRIDSIZE[0]*diagonal_length, self.PIECEGRIDSIZE[1] ) ], [ @@ -1002,67 +1023,77 @@ class DrawConnectFour(): int(self.PIECEGRIDSIZE[0]*0.5), 0 ), ( - int(self.PIECEGRIDSIZE[0]*(diagonalLength-0.5)), + int(self.PIECEGRIDSIZE[0]*(diagonal_length-0.5)), self.PIECEGRIDSIZE[1] ) ] ] - winD.ellipse(drawPositions[0], fill=self.WINBARWHITE) - winD.ellipse(drawPositions[1], fill=self.WINBARWHITE) - winD.rectangle(drawPositions[2], fill=self.WINBARWHITE) - winBar = winBar.rotate(diagonalAngle, expand=1) - startX -= self.PIECEGRIDSIZE[0]*3 + 90 - startY -= self.GRIDBORDER + 60 + win_drawer.ellipse(draw_position[0], fill=self.WINBARWHITE) + win_drawer.ellipse(draw_position[1], fill=self.WINBARWHITE) + win_drawer.rectangle(draw_position[2], fill=self.WINBARWHITE) + win_bar = win_bar.rotate(diagonal_angle, expand=1) + start_x -= self.PIECEGRIDSIZE[0]*3 + 90 + start_y -= self.GRIDBORDER + 60 - mask = winBar.copy() + mask = win_bar.copy() - winBarImage = Image.new("RGBA", mask.size, color=self.WINBARCOLOR) - background.paste(winBarImage, (startX, startY), mask) + win_bar_image = Image.new("RGBA", mask.size, color=self.WINBARCOLOR) + background.paste(win_bar_image, (start_x, start_y), mask) - def _drawFooter(self, d: ImageDraw, game: dict): + def _draw_footer(self, drawer: ImageDraw, game: dict): if game["players"][0] == "Gwendolyn": player1 = "Gwendolyn" else: - player1 = self.bot.database_funcs.get_name(game["players"][0]) + player1 = self.database_funcs.get_name(game["players"][0]) if game["players"][1] == "Gwendolyn": player2 = "Gwendolyn" else: - player2 = self.bot.database_funcs.get_name(game["players"][1]) + player2 = self.database_funcs.get_name(game["players"][1]) - exampleHeight = self.HEIGHT - self.BORDER - exampleHeight += (self.BOTTOMBORDER+self.BORDER)//2 - self.TEXTSIZE//2 - textWidth = self.FONT.getsize(player2)[0] - exampleRPadding = self.BORDER+self.TEXTSIZE+textWidth+self.TEXTPADDING - circlePositions = [ + circle_height = self.HEIGHT - self.BORDER + circle_height += (self.BOTTOMBORDER+self.BORDER)//2 - self.TEXTSIZE//2 + text_width = self.FONT.getsize(player2)[0] + circle_right_padding = ( + self.BORDER+self.TEXTSIZE+text_width+self.TEXTPADDING + ) + circle_positions = [ [ ( self.BORDER, - exampleHeight + circle_height ), ( self.BORDER+self.TEXTSIZE, - exampleHeight+self.TEXTSIZE + circle_height+self.TEXTSIZE ) ], [ ( - self.WIDTH-exampleRPadding, - exampleHeight + self.WIDTH-circle_right_padding, + circle_height ), ( - self.WIDTH-self.BORDER-textWidth-self.TEXTPADDING, - exampleHeight+self.TEXTSIZE + self.WIDTH-self.BORDER-text_width-self.TEXTPADDING, + circle_height+self.TEXTSIZE ) ] ] - circleParams = { + circle_parameters = { "outline": self.BOARDOUTLINECOLOR, "width": 3 } - d.ellipse(circlePositions[0], fill=self.PLAYER1COLOR, **circleParams) - d.ellipse(circlePositions[1], fill=self.PLAYER2COLOR, **circleParams) + drawer.ellipse( + circle_positions[0], + fill=self.PLAYER1COLOR, + **circle_parameters + ) + drawer.ellipse( + circle_positions[1], + fill=self.PLAYER2COLOR, + **circle_parameters + ) - textPositions = [ - (self.BORDER+self.TEXTSIZE+self.TEXTPADDING, exampleHeight), - (self.WIDTH-self.BORDER-textWidth, exampleHeight) + text_positions = [ + (self.BORDER+self.TEXTSIZE+self.TEXTPADDING, circle_height), + (self.WIDTH-self.BORDER-text_width, circle_height) ] - d.text(textPositions[0], player1, font=self.FONT, fill=(0, 0, 0)) - d.text(textPositions[1], player2, font=self.FONT, fill=(0, 0, 0)) + drawer.text(text_positions[0], player1, font=self.FONT, fill=(0, 0, 0)) + drawer.text(text_positions[1], player2, font=self.FONT, fill=(0, 0, 0)) diff --git a/gwendolyn/funcs/games/hangman.py b/gwendolyn/funcs/games/hangman.py index 46e01da..0f247e4 100644 --- a/gwendolyn/funcs/games/hangman.py +++ b/gwendolyn/funcs/games/hangman.py @@ -8,12 +8,12 @@ Deals with commands and logic for hangman games. DrawHangman() Draws the image shown to the player. """ -import requests # Used for getting the word in Hangman.start() import datetime # Used for generating the game id import string # string.ascii_uppercase used -import discord # Used for discord.file and type hints import math # Used by DrawHangman(), mainly for drawing circles import random # Used to draw poorly +import requests # Used for getting the word in Hangman.start() +import discord # Used for discord.file and type hints from discord_slash.context import SlashContext # Used for typehints from PIL import ImageDraw, Image, ImageFont # Used to draw the image @@ -38,16 +38,16 @@ class Hangman(): ------------ draw: DrawHangman The DrawHangman used to draw the hangman image. - APIURL: str + API_url: str The url to get the words from. APIPARAMS: dict The parameters to pass to every api call. """ self.__bot = bot self.__draw = DrawHangman(bot) - self.__APIURL = "https://api.wordnik.com/v4/words.json/randomWords?" - apiKey = self.__bot.credentials["wordnik_key"] - self.__APIPARAMS = { + self.__API_url = "https://api.wordnik.com/v4/words.json/randomWords?" # pylint: disable=invalid-name + api_key = self.__bot.credentials["wordnik_key"] + self.__APIPARAMS = { # pylint: disable=invalid-name "hasDictionaryDef": True, "minCorpusCount": 5000, "maxCorpusCount": -1, @@ -56,7 +56,7 @@ class Hangman(): "minLength": 3, "maxLength": 11, "limit": 1, - "api_key": apiKey + "api_key": api_key } async def start(self, ctx: SlashContext): @@ -73,59 +73,60 @@ class Hangman(): user = f"#{ctx.author.id}" game = self.__bot.database["hangman games"].find_one({"_id": channel}) user_name = self.__bot.database_funcs.get_name(user) - startedGame = False + started_game = False if game is None: word = "-" while "-" in word or "." in word: - response = requests.get(self.__APIURL, params=self.__APIPARAMS) + response = requests.get(self.__API_url, params=self.__APIPARAMS) word = list(response.json()[0]["word"].upper()) self.__bot.log("Found the word \""+"".join(word)+"\"") guessed = [False] * len(word) - gameID = datetime.datetime.now().strftime("%Y%m%d%H%M%S") - newGame = { + game_id = datetime.datetime.now().strftime("%Y%m%d%H%M%S") + new_game = { "_id": channel, "player": user, "guessed letters": [], "word": word, - "game ID": gameID, + "game ID": game_id, "misses": 0, "guessed": guessed } - self.__bot.database["hangman games"].insert_one(newGame) + self.__bot.database["hangman games"].insert_one(new_game) - remainingLetters = list(string.ascii_uppercase) + remaining_letters = list(string.ascii_uppercase) - self.__draw.drawImage(channel) + self.__draw.draw_image(channel) log_message = "Game started" - sendMessage = f"{user_name} started game of hangman." - startedGame = True + send_message = f"{user_name} started game of hangman." + started_game = True else: log_message = "There was already a game going on" - sendMessage = self.__bot.long_strings["Hangman going on"] + send_message = self.__bot.long_strings["Hangman going on"] self.__bot.log(log_message) - await ctx.send(sendMessage) + await ctx.send(send_message) - if startedGame: - boardsPath = "gwendolyn/resources/games/hangman_boards/" - file_path = f"{boardsPath}hangman_board{channel}.png" - newImage = await ctx.channel.send(file=discord.File(file_path)) + if started_game: + boards_path = "gwendolyn/resources/games/hangman_boards/" + file_path = f"{boards_path}hangman_board{channel}.png" + new_image = await ctx.channel.send(file=discord.File(file_path)) - blankMessage = await ctx.channel.send("_ _") - reactionMessages = { - newImage: remainingLetters[:15], - blankMessage: remainingLetters[15:] + blank_message = await ctx.channel.send("_ _") + reaction_messages = { + new_image: remaining_letters[:15], + blank_message: remaining_letters[15:] } - old_messages = f"{newImage.id}\n{blankMessage.id}" + old_messages = f"{new_image.id}\n{blank_message.id}" + old_images_path = "gwendolyn/resources/games/old_images/" - with open(f"gwendolyn/resources/games/old_images/hangman{channel}", "w") as f: - f.write(old_messages) + with open(old_images_path+f"hangman{channel}", "w") as file_pointer: + file_pointer.write(old_messages) - for message, letters in reactionMessages.items(): + for message, letters in reaction_messages.items(): for letter in letters: emoji = chr(ord(letter)+127397) await message.add_reaction(emoji) @@ -148,9 +149,10 @@ class Hangman(): await ctx.send("You can't end a game you're not in") else: self.__bot.database["hangman games"].delete_one({"_id": channel}) + old_images_path = "gwendolyn/resources/games/old_images/" - with open(f"gwendolyn/resources/games/old_images/hangman{channel}", "r") as f: - messages = f.read().splitlines() + with open(old_images_path+f"hangman{channel}", "r") as file_pointer: + messages = file_pointer.read().splitlines() for message in messages: old_message = await ctx.channel.fetch_message(int(message)) @@ -176,89 +178,91 @@ class Hangman(): hangman_games = self.__bot.database["hangman games"] game = hangman_games.find_one({"_id": channel}) - gameExists = (game is not None) - singleLetter = (len(guess) == 1 and guess.isalpha()) - newGuess = (guess not in game["guessed letters"]) - validGuess = (gameExists and singleLetter and newGuess) + game_exists = (game is not None) + single_letter = (len(guess) == 1 and guess.isalpha()) + new_guess = (guess not in game["guessed letters"]) + valid_guess = (game_exists and single_letter and new_guess) - if validGuess: + if valid_guess: self.__bot.log("Guessed the letter") - correctGuess = 0 + correct_guess = 0 - for x, letter in enumerate(game["word"]): + for i, letter in enumerate(game["word"]): if guess == letter: - correctGuess += 1 - updater = {"$set": {f"guessed.{x}": True}} + correct_guess += 1 + updater = {"$set": {f"guessed.{i}": True}} hangman_games.update_one({"_id": channel}, updater) - if correctGuess == 0: + if correct_guess == 0: updater = {"$inc": {"misses": 1}} hangman_games.update_one({"_id": channel}, updater) updater = {"$push": {"guessed letters": guess}} hangman_games.update_one({"_id": channel}, updater) - remainingLetters = list(string.ascii_uppercase) + remaining_letters = list(string.ascii_uppercase) game = hangman_games.find_one({"_id": channel}) for letter in game["guessed letters"]: - remainingLetters.remove(letter) + remaining_letters.remove(letter) - if correctGuess == 1: - sendMessage = "Guessed {}. There was 1 {} in the word." - sendMessage = sendMessage.format(guess, guess) + if correct_guess == 1: + send_message = "Guessed {}. There was 1 {} in the word." + send_message = send_message.format(guess, guess) else: - sendMessage = "Guessed {}. There were {} {}s in the word." - sendMessage = sendMessage.format(guess, correctGuess, guess) + send_message = "Guessed {}. There were {} {}s in the word." + send_message = send_message.format(guess, correct_guess, guess) - self.__draw.drawImage(channel) + self.__draw.draw_image(channel) if game["misses"] == 6: hangman_games.delete_one({"_id": channel}) - sendMessage += self.__bot.long_strings["Hangman lost game"] - remainingLetters = [] + send_message += self.__bot.long_strings["Hangman lost game"] + remaining_letters = [] elif all(game["guessed"]): hangman_games.delete_one({"_id": channel}) self.__bot.money.addMoney(user, 15) - sendMessage += self.__bot.long_strings["Hangman guessed word"] - remainingLetters = [] + send_message += self.__bot.long_strings["Hangman guessed word"] + remaining_letters = [] - await message.channel.send(sendMessage) + await message.channel.send(send_message) + old_images_path = "gwendolyn/resources/games/old_images/" - with open(f"gwendolyn/resources/games/old_images/hangman{channel}", "r") as f: - old_message_ids = f.read().splitlines() + with open(old_images_path+f"hangman{channel}", "r") as file_pointer: + old_message_ids = file_pointer.read().splitlines() - for oldID in old_message_ids: - old_message = await message.channel.fetch_message(int(oldID)) + for old_id in old_message_ids: + old_message = await message.channel.fetch_message(int(old_id)) self.__bot.log("Deleting old message") await old_message.delete() - boardsPath = "gwendolyn/resources/games/hangman_boards/" - file_path = f"{boardsPath}hangman_board{channel}.png" - newImage = await message.channel.send(file=discord.File(file_path)) + boards_path = "gwendolyn/resources/games/hangman_boards/" + file_path = f"{boards_path}hangman_board{channel}.png" + new_image = await message.channel.send(file=discord.File(file_path)) - if len(remainingLetters) > 0: - if len(remainingLetters) > 15: - blankMessage = await message.channel.send("_ _") - reactionMessages = { - newImage: remainingLetters[:15], - blankMessage: remainingLetters[15:] + if len(remaining_letters) > 0: + if len(remaining_letters) > 15: + blank_message = await message.channel.send("_ _") + reaction_messages = { + new_image: remaining_letters[:15], + blank_message: remaining_letters[15:] } else: - blankMessage = "" - reactionMessages = {newImage: remainingLetters} + blank_message = "" + reaction_messages = {new_image: remaining_letters} - if blankMessage != "": - old_messages = f"{newImage.id}\n{blankMessage.id}" + if blank_message != "": + old_messages = f"{new_image.id}\n{blank_message.id}" else: - old_messages = str(newImage.id) + old_messages = str(new_image.id) - old_imagePath = f"gwendolyn/resources/games/old_images/hangman{channel}" - with open(old_imagePath, "w") as f: - f.write(old_messages) + old_images_path = "gwendolyn/resources/games/old_images/" + old_image_path = old_images_path + f"hangman{channel}" + with open(old_image_path, "w") as file_pointer: + file_pointer.write(old_messages) - for message, letters in reactionMessages.items(): + for message, letters in reaction_messages.items(): for letter in letters: emoji = chr(ord(letter)+127397) await message.add_reaction(emoji) @@ -270,7 +274,7 @@ class DrawHangman(): *Methods* --------- - drawImage(channel: str) + draw_image(channel: str) """ def __init__(self, bot): @@ -293,6 +297,7 @@ class DrawHangman(): SMALLFONT """ self.__bot = bot + # pylint: disable=invalid-name self.__CIRCLESIZE = 120 self.__LINEWIDTH = 12 @@ -318,129 +323,132 @@ class DrawHangman(): FONTPATH = "gwendolyn/resources/fonts/comic-sans-bold.ttf" self.__FONT = ImageFont.truetype(FONTPATH, LETTERSIZE) self.__SMALLFONT = ImageFont.truetype(FONTPATH, WORDSIZE) + # pylint: enable=invalid-name - def __deviate(self, preDeviance: int, preDevianceAccuracy: int, - positionChange: float, maxmin: int, - maxAcceleration: float): - randomDeviance = random.uniform(-positionChange, positionChange) - devianceAccuracy = preDevianceAccuracy + randomDeviance - if devianceAccuracy > maxmin * maxAcceleration: - devianceAccuracy = maxmin * maxAcceleration - elif devianceAccuracy < -maxmin * maxAcceleration: - devianceAccuracy = -maxmin * maxAcceleration + def __deviate(self, pre_deviance: int, pre_deviance_accuracy: int, + position_change: float, maxmin: int, + max_acceleration: float): + random_deviance = random.uniform(-position_change, position_change) + deviance_accuracy = pre_deviance_accuracy + random_deviance + if deviance_accuracy > maxmin * max_acceleration: + deviance_accuracy = maxmin * max_acceleration + elif deviance_accuracy < -maxmin * max_acceleration: + deviance_accuracy = -maxmin * max_acceleration - deviance = preDeviance + devianceAccuracy + deviance = pre_deviance + deviance_accuracy if deviance > maxmin: deviance = maxmin elif deviance < -maxmin: deviance = -maxmin - return deviance, devianceAccuracy + return deviance, deviance_accuracy - def __badCircle(self): - circlePadding = (self.__LINEWIDTH*3) - imageWidth = self.__CIRCLESIZE+circlePadding - imageSize = (imageWidth, imageWidth) - background = Image.new("RGBA", imageSize, color=(0, 0, 0, 0)) + def __bad_circle(self): + circle_padding = (self.__LINEWIDTH*3) + image_width = self.__CIRCLESIZE+circle_padding + image_size = (image_width, image_width) + background = Image.new("RGBA", image_size, color=(0, 0, 0, 0)) - d = ImageDraw.Draw(background, "RGBA") + drawer = ImageDraw.Draw(background, "RGBA") middle = (self.__CIRCLESIZE+(self.__LINEWIDTH*3))/2 - devianceX = 0 - devianceY = 0 - devianceAccuracyX = 0 - devianceAccuracyY = 0 + deviance_x = 0 + deviance_y = 0 + deviance_accuracy_x = 0 + deviance_accuracy_y = 0 start = random.randint(-100, -80) - degreesAmount = 360 + random.randint(-10, 30) + degreess_amount = 360 + random.randint(-10, 30) - for degree in range(degreesAmount): - devianceXParams = [ - devianceX, - devianceAccuracyX, + for degree in range(degreess_amount): + deviance_x, deviance_accuracy_x = self.__deviate( + deviance_x, + deviance_accuracy_x, self.__LINEWIDTH/100, self.__LINEWIDTH, 0.03 - ] - devianceYParams = [ - devianceY, - devianceAccuracyY, + ) + deviance_y, deviance_accuracy_y = self.__deviate( + deviance_y, + deviance_accuracy_y, self.__LINEWIDTH/100, self.__LINEWIDTH, 0.03 - ] - devianceX, devianceAccuracyX = self.__deviate(*devianceXParams) - devianceY, devianceAccuracyY = self.__deviate(*devianceYParams) + ) radians = math.radians(degree+start) - circleX = (math.cos(radians) * (self.__CIRCLESIZE/2)) - circleY = (math.sin(radians) * (self.__CIRCLESIZE/2)) + circle_x = (math.cos(radians) * (self.__CIRCLESIZE/2)) + circle_y = (math.sin(radians) * (self.__CIRCLESIZE/2)) - x = middle + circleX - (self.__LINEWIDTH/2) + devianceX - y = middle + circleY - (self.__LINEWIDTH/2) + devianceY + position_x = middle + circle_x - (self.__LINEWIDTH/2) + deviance_x + position_y = middle + circle_y - (self.__LINEWIDTH/2) + deviance_y - circlePosition = [(x, y), (x+self.__LINEWIDTH, y+self.__LINEWIDTH)] - d.ellipse(circlePosition, fill=(0, 0, 0, 255)) + circle_position = [ + (position_x, position_y), + (position_x+self.__LINEWIDTH, position_y+self.__LINEWIDTH) + ] + drawer.ellipse(circle_position, fill=(0, 0, 0, 255)) return background - def __badLine(self, length: int, rotated: bool = False): + def __bad_line(self, length: int, rotated: bool = False): if rotated: - w, h = length+self.__LINEWIDTH*3, self.__LINEWIDTH*3 + width, height = length+self.__LINEWIDTH*3, self.__LINEWIDTH*3 else: - w, h = self.__LINEWIDTH*3, length+self.__LINEWIDTH*3 - background = Image.new("RGBA", (w, h), color=(0, 0, 0, 0)) + width, height = self.__LINEWIDTH*3, length+self.__LINEWIDTH*3 + background = Image.new("RGBA", (width, height), color=(0, 0, 0, 0)) - d = ImageDraw.Draw(background, "RGBA") + drawer = ImageDraw.Draw(background, "RGBA") - possibleDeviance = int(self.__LINEWIDTH/3) - devianceX = random.randint(-possibleDeviance, possibleDeviance) - devianceY = 0 - devianceAccuracyX = 0 - devianceAccuracyY = 0 + possible_deviance = int(self.__LINEWIDTH/3) + deviance_x = random.randint(-possible_deviance, possible_deviance) + deviance_y = 0 + deviance_accuracy_x = 0 + deviance_accuracy_y = 0 for pixel in range(length): - devianceParamsX = [ - devianceX, - devianceAccuracyX, + deviance_x, deviance_accuracy_x = self.__deviate( + deviance_x, + deviance_accuracy_x, self.__LINEWIDTH/1000, self.__LINEWIDTH, 0.004 - ] - devianceParamsY = [ - devianceY, - devianceAccuracyY, + ) + deviance_y, deviance_accuracy_y = self.__deviate( + deviance_y, + deviance_accuracy_y, self.__LINEWIDTH/1000, self.__LINEWIDTH, 0.004 - ] - devianceX, devianceAccuracyX = self.__deviate(*devianceParamsX) - devianceY, devianceAccuracyY = self.__deviate(*devianceParamsY) + ) if rotated: - x = self.__LINEWIDTH + pixel + devianceX - y = self.__LINEWIDTH + devianceY + position_x = self.__LINEWIDTH + pixel + deviance_x + position_y = self.__LINEWIDTH + deviance_y else: - x = self.__LINEWIDTH + devianceX - y = self.__LINEWIDTH + pixel + devianceY + position_x = self.__LINEWIDTH + deviance_x + position_y = self.__LINEWIDTH + pixel + deviance_y - circlePosition = [(x, y), (x+self.__LINEWIDTH, y+self.__LINEWIDTH)] - d.ellipse(circlePosition, fill=(0, 0, 0, 255)) + circle_position = [ + (position_x, position_y), + (position_x+self.__LINEWIDTH, position_y+self.__LINEWIDTH) + ] + drawer.ellipse(circle_position, fill=(0, 0, 0, 255)) return background - def __drawMan(self, misses: int, seed: str): + def __draw_man(self, misses: int, seed: str): random.seed(seed) - manSize = (self.__MANX, self.__MANY) - background = Image.new("RGBA", manSize, color=(0, 0, 0, 0)) + man_size = (self.__MANX, self.__MANY) + background = Image.new("RGBA", man_size, color=(0, 0, 0, 0)) if misses >= 1: - head = self.__badCircle() - pasteX = (self.__MANX-(self.__CIRCLESIZE+(self.__LINEWIDTH*3)))//2 - pastePosition = (pasteX, 0) - background.paste(head, pastePosition, head) + head = self.__bad_circle() + paste_x = (self.__MANX-(self.__CIRCLESIZE+(self.__LINEWIDTH*3)))//2 + paste_position = (paste_x, 0) + background.paste(head, paste_position, head) if misses >= 2: - body = self.__badLine(self.__BODYSIZE) - pasteX = (self.__MANX-(self.__LINEWIDTH*3))//2 - pastePosition = (pasteX, self.__CIRCLESIZE) - background.paste(body, pastePosition, body) + body = self.__bad_line(self.__BODYSIZE) + paste_x = (self.__MANX-(self.__LINEWIDTH*3))//2 + paste_position = (paste_x, self.__CIRCLESIZE) + background.paste(body, paste_position, body) if misses >= 3: limbs = random.sample(["rl", "ll", "ra", "la"], min(misses-2, 4)) @@ -450,131 +458,138 @@ class DrawHangman(): random.seed(seed) for limb in limbs: - limbDrawing = self.__badLine(self.__LIMBSIZE, True) - xPosition = (self.__MANX-(self.__LINEWIDTH*3))//2 + limb_drawing = self.__bad_line(self.__LIMBSIZE, True) + x_position = (self.__MANX-(self.__LINEWIDTH*3))//2 if limb[1] == "a": rotation = random.randint(-45, 45) shift = math.sin(math.radians(rotation)) - lineLength = self.__LIMBSIZE+(self.__LINEWIDTH*3) - compensation = int(shift*lineLength) - limbDrawing = limbDrawing.rotate(rotation, expand=1) - yPosition = self.__CIRCLESIZE + self.__ARMPOSITION + line_length = self.__LIMBSIZE+(self.__LINEWIDTH*3) + compensation = int(shift*line_length) + limb_drawing = limb_drawing.rotate(rotation, expand=1) + y_position = self.__CIRCLESIZE + self.__ARMPOSITION if limb == "ra": compensation = min(-compensation, 0) else: - xPosition -= self.__LIMBSIZE + x_position -= self.__LIMBSIZE compensation = min(compensation, 0) - yPosition += compensation + y_position += compensation else: rotation = random.randint(-15, 15) - yPosition = self.__CIRCLESIZE+self.__BODYSIZE-self.__LINEWIDTH + y_position = self.__CIRCLESIZE+self.__BODYSIZE-self.__LINEWIDTH if limb == "rl": - limbDrawing = limbDrawing.rotate(rotation-45, expand=1) + limb_drawing = limb_drawing.rotate(rotation-45, expand=1) else: - xPosition += -limbDrawing.size[0]+self.__LINEWIDTH*3 - limbDrawing = limbDrawing.rotate(rotation+45, expand=1) + x_position += -limb_drawing.size[0]+self.__LINEWIDTH*3 + limb_drawing = limb_drawing.rotate(rotation+45, expand=1) - pastePosition = (xPosition, yPosition) - background.paste(limbDrawing, pastePosition, limbDrawing) + paste_position = (x_position, y_position) + background.paste(limb_drawing, paste_position, limb_drawing) return background - def __badText(self, text: str, big: bool, color: tuple = (0, 0, 0, 255)): + def __bad_text(self, text: str, big: bool, color: tuple = (0, 0, 0, 255)): if big: font = self.__FONT else: font = self.__SMALLFONT - w, h = font.getsize(text) - img = Image.new("RGBA", (w, h), color=(0, 0, 0, 0)) - d = ImageDraw.Draw(img, "RGBA") + width, height = font.getsize(text) + img = Image.new("RGBA", (width, height), color=(0, 0, 0, 0)) + drawer = ImageDraw.Draw(img, "RGBA") - d.text((0, 0), text, font=font, fill=color) + drawer.text((0, 0), text, font=font, fill=color) return img - def __drawGallows(self): - gallowSize = (self.__GALLOWX, self.__GALLOWY) - background = Image.new("RGBA", gallowSize, color=(0, 0, 0, 0)) + def __draw_gallows(self): + gallow_size = (self.__GALLOWX, self.__GALLOWY) + background = Image.new("RGBA", gallow_size, color=(0, 0, 0, 0)) - bottomLine = self.__badLine(int(self.__GALLOWX * 0.75), True) - bottomLineX = int(self.__GALLOWX * 0.125) - bottomLineY = self.__GALLOWY-(self.__LINEWIDTH*4) - pastePosition = (bottomLineX, bottomLineY) - background.paste(bottomLine, pastePosition, bottomLine) + bottom_line = self.__bad_line(int(self.__GALLOWX * 0.75), True) + bottom_line_x = int(self.__GALLOWX * 0.125) + bottom_line_y = self.__GALLOWY-(self.__LINEWIDTH*4) + paste_position = (bottom_line_x, bottom_line_y) + background.paste(bottom_line, paste_position, bottom_line) - lineTwo = self.__badLine(self.__GALLOWY-self.__LINEWIDTH*6) - lineTwoX = int(self.__GALLOWX*(0.75*self.__PHI)) - lineTwoY = self.__LINEWIDTH*2 - pastePosition = (lineTwoX, lineTwoY) - background.paste(lineTwo, pastePosition, lineTwo) + line_two = self.__bad_line(self.__GALLOWY-self.__LINEWIDTH*6) + line_two_x = int(self.__GALLOWX*(0.75*self.__PHI)) + line_two_y = self.__LINEWIDTH*2 + paste_position = (line_two_x, line_two_y) + background.paste(line_two, paste_position, line_two) - topLine = self.__badLine(int(self.__GALLOWY*0.30), True) - pasteX = int(self.__GALLOWX*(0.75*self.__PHI))-self.__LINEWIDTH - pastePosition = (pasteX, self.__LINEWIDTH*3) - background.paste(topLine, pastePosition, topLine) + top_line = self.__bad_line(int(self.__GALLOWY*0.30), True) + paste_x = int(self.__GALLOWX*(0.75*self.__PHI))-self.__LINEWIDTH + paste_position = (paste_x, self.__LINEWIDTH*3) + background.paste(top_line, paste_position, top_line) - lastLine = self.__badLine(int(self.__GALLOWY*0.125)) - pasteX += int(self.__GALLOWY*0.30) - background.paste(lastLine, (pasteX, self.__LINEWIDTH*3), lastLine) + last_line = self.__bad_line(int(self.__GALLOWY*0.125)) + paste_x += int(self.__GALLOWY*0.30) + background.paste(last_line, (paste_x, self.__LINEWIDTH*3), last_line) return background - def __drawLetterLines(self, word: str, guessed: list, misses: int): - letterWidth = self.__LETTERLINELENGTH+self.__LETTERLINEDISTANCE - imageWidth = letterWidth*len(word) - imageSize = (imageWidth, self.__LETTERLINELENGTH+self.__LINEWIDTH*3) - letterLines = Image.new("RGBA", imageSize, color=(0, 0, 0, 0)) - for x, letter in enumerate(word): - line = self.__badLine(self.__LETTERLINELENGTH, True) - pasteX = x*(self.__LETTERLINELENGTH+self.__LETTERLINEDISTANCE) - pastePosition = (pasteX, self.__LETTERLINELENGTH) - letterLines.paste(line, pastePosition, line) - if guessed[x]: - letterDrawing = self.__badText(letter, True) - letterWidth = self.__FONT.getsize(letter)[0] - letterX = x*(self.__LETTERLINELENGTH+self.__LETTERLINEDISTANCE) - letterX -= (letterWidth//2) - letterX += (self.__LETTERLINELENGTH//2)+(self.__LINEWIDTH*2) - letterLines.paste(letterDrawing, (letterX, 0), letterDrawing) + def __draw_letter_lines(self, word: str, guessed: list, misses: int): + letter_width = self.__LETTERLINELENGTH+self.__LETTERLINEDISTANCE + image_width = letter_width*len(word) + image_size = (image_width, self.__LETTERLINELENGTH+self.__LINEWIDTH*3) + letter_lines = Image.new("RGBA", image_size, color=(0, 0, 0, 0)) + for i, letter in enumerate(word): + line = self.__bad_line(self.__LETTERLINELENGTH, True) + paste_x = i*(self.__LETTERLINELENGTH+self.__LETTERLINEDISTANCE) + paste_position = (paste_x, self.__LETTERLINELENGTH) + letter_lines.paste(line, paste_position, line) + if guessed[i]: + letter_drawing = self.__bad_text(letter, True) + letter_width = self.__FONT.getsize(letter)[0] + letter_x = i*(self.__LETTERLINELENGTH+self.__LETTERLINEDISTANCE) + letter_x -= (letter_width//2) + letter_x += (self.__LETTERLINELENGTH//2)+(self.__LINEWIDTH*2) + letter_lines.paste( + letter_drawing, + (letter_x, 0), + letter_drawing + ) elif misses == 6: - letterDrawing = self.__badText(letter, True, (242, 66, 54)) - letterWidth = self.__FONT.getsize(letter)[0] - letterX = x*(self.__LETTERLINELENGTH+self.__LETTERLINEDISTANCE) - letterX -= (letterWidth//2) - letterX += (self.__LETTERLINELENGTH//2)+(self.__LINEWIDTH*2) - letterLines.paste(letterDrawing, (letterX, 0), letterDrawing) + letter_drawing = self.__bad_text(letter, True, (242, 66, 54)) + letter_width = self.__FONT.getsize(letter)[0] + letter_x = i*(self.__LETTERLINELENGTH+self.__LETTERLINEDISTANCE) + letter_x -= (letter_width//2) + letter_x += (self.__LETTERLINELENGTH//2)+(self.__LINEWIDTH*2) + letter_lines.paste( + letter_drawing, + (letter_x, 0), + letter_drawing + ) - return letterLines + return letter_lines - def __shortestDist(self, positions: list, newPosition: tuple): - __shortestDist = math.inf - x, y = newPosition + def __shortest_dist(self, positions: list, new_position: tuple): + shortest_dist = math.inf for i, j in positions: - xDistance = abs(i-x) - yDistance = abs(j-y) - dist = math.sqrt(xDistance**2+yDistance**2) - if __shortestDist > dist: - __shortestDist = dist - return __shortestDist + x_distance = abs(i-new_position[0]) + y_distance = abs(j-new_position[1]) + dist = math.sqrt(x_distance**2+y_distance**2) + if shortest_dist > dist: + shortest_dist = dist + return shortest_dist - def __drawMisses(self, guesses: list, word: str): + def __draw_misses(self, guesses: list, word: str): background = Image.new("RGBA", (600, 400), color=(0, 0, 0, 0)) pos = [] for guess in guesses: if guess not in word: placed = False while not placed: - letter = self.__badText(guess, True) + letter = self.__bad_text(guess, True) w, h = self.__FONT.getsize(guess) x = random.randint(0, 600-w) y = random.randint(0, 400-h) - if self.__shortestDist(pos, (x, y)) > 70: + if self.__shortest_dist(pos, (x, y)) > 70: pos.append((x, y)) background.paste(letter, (x, y), letter) placed = True return background - def drawImage(self, channel: str): + def draw_image(self, channel: str): """ Draw a hangman Image. @@ -589,24 +604,24 @@ class DrawHangman(): random.seed(game["game ID"]) background = Image.open("gwendolyn/resources/paper.jpg") - gallow = self.__drawGallows() - man = self.__drawMan(game["misses"], game["game ID"]) + gallow = self.__draw_gallows() + man = self.__draw_man(game["misses"], game["game ID"]) random.seed(game["game ID"]) - letterLineParams = [game["word"], game["guessed"], game["misses"]] - letterLines = self.__drawLetterLines(*letterLineParams) + letter_line_parameters = [game["word"], game["guessed"], game["misses"]] + letter_lines = self.__draw_letter_lines(*letter_line_parameters) random.seed(game["game ID"]) - misses = self.__drawMisses(game["guessed letters"], game["word"]) + misses = self.__draw_misses(game["guessed letters"], game["word"]) background.paste(gallow, (100, 100), gallow) background.paste(man, (300, 210), man) - background.paste(letterLines, (120, 840), letterLines) + background.paste(letter_lines, (120, 840), letter_lines) background.paste(misses, (600, 150), misses) - missesText = self.__badText("MISSES", False) - missesTextWidth = missesText.size[0] - background.paste(missesText, (850-missesTextWidth//2, 50), missesText) + misses_text = self.__bad_text("MISSES", False) + misses_text_width = misses_text.size[0] + background.paste(misses_text, (850-misses_text_width//2, 50), misses_text) - boardPath = f"gwendolyn/resources/games/hangman_boards/hangman_board{channel}.png" - background.save(boardPath) + board_path = f"gwendolyn/resources/games/hangman_boards/hangman_board{channel}.png" + background.save(board_path) diff --git a/gwendolyn/funcs/games/hex.py b/gwendolyn/funcs/games/hex.py index 5700bd8..1f33f26 100644 --- a/gwendolyn/funcs/games/hex.py +++ b/gwendolyn/funcs/games/hex.py @@ -28,7 +28,7 @@ class HexGame(): await ctx.send("You can't surrender when you're not a player.") else: opponent = (players.index(user) + 1) % 2 - opponentName = self.bot.database_funcs.get_name(players[opponent]) + opponent_name = self.bot.database_funcs.get_name(players[opponent]) self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"winner":opponent + 1}}) await ctx.send(f"{ctx.author.display_name} surrendered") @@ -71,9 +71,9 @@ class HexGame(): self.draw.drawSwap(channel) opponent = game["players"][::-1][game["turn"]-1] - gwendoTurn = (opponent == f"#{self.bot.user.id}") - opponentName = self.bot.database_funcs.get_name(opponent) - await ctx.send(f"The color of the players were swapped. It is now {opponentName}'s turn") + gwendolyn_turn = (opponent == f"#{self.bot.user.id}") + opponent_name = self.bot.database_funcs.get_name(opponent) + await ctx.send(f"The color of the players were swapped. It is now {opponent_name}'s turn") with open(f"gwendolyn/resources/games/old_images/hex{channel}", "r") as f: old_image = await ctx.channel.fetch_message(int(f.read())) @@ -90,7 +90,7 @@ class HexGame(): with open(f"gwendolyn/resources/games/old_images/hex{channel}", "w") as f: f.write(str(old_image.id)) - if gwendoTurn: + if gwendolyn_turn: await self.hexAI(ctx) # Starts the game @@ -100,109 +100,109 @@ class HexGame(): channel = str(ctx.channel_id) game = self.bot.database["hex games"].find_one({"_id":channel}) - startedGame = False - canStart = True + started_game = False + can_start = True if game != None: - sendMessage = "There's already a hex game going on in this channel" + send_message = "There's already a hex game going on in this channel" log_message = "There was already a game going on" - canStart = False + can_start = False else: if type(opponent) == int: # Opponent is Gwendolyn if opponent in range(1, 6): - opponentName = "Gwendolyn" + opponent_name = "Gwendolyn" difficulty = int(opponent) - diffText = f" with difficulty {difficulty}" + difficulty_text = f" with difficulty {difficulty}" opponent = f"#{self.bot.user.id}" else: - sendMessage = "Difficulty doesn't exist" + send_message = "Difficulty doesn't exist" log_message = "They tried to play against a difficulty that doesn't exist" - canStart = False + can_start = False elif type(opponent) == discord.member.Member: if opponent.bot: # User has challenged a bot if opponent == self.bot.user: # It was Gwendolyn - opponentName = "Gwendolyn" + opponent_name = "Gwendolyn" difficulty = 2 - diffText = f" with difficulty {difficulty}" + difficulty_text = f" with difficulty {difficulty}" opponent = f"#{self.bot.user.id}" else: - sendMessage = "You can't challenge a bot!" + send_message = "You can't challenge a bot!" log_message = "They tried to challenge a bot" - canStart = False + can_start = False else: # Opponent is another player if ctx.author != opponent: - opponentName = opponent.display_name + opponent_name = opponent.display_name opponent = f"#{opponent.id}" difficulty = 5 - diffText = "" + difficulty_text = "" else: - sendMessage = "You can't play against yourself" + send_message = "You can't play against yourself" log_message = "They tried to play against themself" - canStart = False + can_start = False else: - canStart = False + can_start = False log_message = f"Opponent was neither int or member. It was {type(opponent)}" - sendMessage = "Something went wrong" + send_message = "Something went wrong" - if canStart: + if can_start: # board is 11x11 board = [[0 for i in range(self.BOARDWIDTH)] for j in range(self.BOARDWIDTH)] players = [user, opponent] random.shuffle(players) # random starting player gameHistory = [] - newGame = {"_id":channel,"board":board, "winner":0, + new_game = {"_id":channel,"board":board, "winner":0, "players":players, "turn":1, "difficulty":difficulty, "gameHistory":gameHistory} - self.bot.database["hex games"].insert_one(newGame) + self.bot.database["hex games"].insert_one(new_game) # draw the board self.draw.drawBoard(channel) - gwendoTurn = (players[0] == f"#{self.bot.user.id}") - startedGame = True + gwendolyn_turn = (players[0] == f"#{self.bot.user.id}") + started_game = True - turnName = self.bot.database_funcs.get_name(players[0]) - sendMessage = f"Started Hex game against {opponentName}{diffText}. It's {turnName}'s turn" + turn_name = self.bot.database_funcs.get_name(players[0]) + send_message = f"Started Hex game against {opponent_name}{difficulty_text}. It's {turn_name}'s turn" log_message = "Game started" - await ctx.send(sendMessage) + await ctx.send(send_message) self.bot.log(log_message) - if startedGame: + if started_game: file_path = f"gwendolyn/resources/games/hex_boards/board{ctx.channel_id}.png" - newImage = await ctx.channel.send(file = discord.File(file_path)) + new_image = await ctx.channel.send(file = discord.File(file_path)) with open(f"gwendolyn/resources/games/old_images/hex{ctx.channel_id}", "w") as f: - f.write(str(newImage.id)) + f.write(str(new_image.id)) - if gwendoTurn: + if gwendolyn_turn: await self.hexAI(ctx) # Places a piece at the given location and checks things afterwards async def placeHex(self, ctx, position : str, user): channel = str(ctx.channel_id) game = self.bot.database["hex games"].find_one({"_id":channel}) - placedPiece = False + placed_piece = False if game == None: - sendMessage = "There's no game in this channel" + send_message = "There's no game in this channel" self.bot.log("There was no game going on") elif not (position[0].isalpha() and position[1:].isnumeric() and len(position) in [2, 3]): - sendMessage = "The position must be a letter followed by a number." + send_message = "The position must be a letter followed by a number." self.bot.log(f"The position was not valid, {position}") else: players = game["players"] if user not in players: - sendMessage = f"You can't place when you're not in the game. The game's players are: {self.bot.database_funcs.get_name(game['players'][0])} and {self.bot.database_funcs.get_name(game['players'][1])}." + send_message = f"You can't place when you're not in the game. The game's players are: {self.bot.database_funcs.get_name(game['players'][0])} and {self.bot.database_funcs.get_name(game['players'][1])}." self.bot.log("They aren't in the game") elif players[game["turn"]-1] != user: - sendMessage = "It's not your turn" + send_message = "It's not your turn" self.bot.log("It wasn't their turn") else: player = game["turn"] @@ -215,7 +215,7 @@ class HexGame(): if board is None: self.bot.log("It was an invalid position") - sendMessage = ("That's an invalid position. You must place your piece on an empty field.") + send_message = ("That's an invalid position. You must place your piece on an empty field.") else: # If the move is valid: self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"board":board}}) @@ -227,34 +227,34 @@ class HexGame(): winner = self.evaluateBoard(game["board"])[1] if winner == 0: # Continue with the game. - gameWon = False - sendMessage = self.bot.database_funcs.get_name(game["players"][player-1])+" placed at "+position.upper()+". It's now "+self.bot.database_funcs.get_name(game["players"][turn-1])+"'s turn."# The score is "+str(score) + game_won = False + send_message = self.bot.database_funcs.get_name(game["players"][player-1])+" placed at "+position.upper()+". It's now "+self.bot.database_funcs.get_name(game["players"][turn-1])+"'s turn."# The score is "+str(score) else: # Congratulations! - gameWon = True + game_won = True self.bot.database["hex games"].update_one({"_id":channel},{"$set":{"winner":winner}}) - sendMessage = self.bot.database_funcs.get_name(game["players"][player-1])+" placed at "+position.upper()+" and won!" + send_message = self.bot.database_funcs.get_name(game["players"][player-1])+" placed at "+position.upper()+" and won!" if game["players"][winner-1] != f"#{self.bot.user.id}": - winAmount = game["difficulty"]*10 - sendMessage += " Adding "+str(winAmount)+" GwendoBucks to their account." + win_amount = game["difficulty"]*10 + send_message += " Adding "+str(win_amount)+" GwendoBucks to their account." self.bot.database["hex games"].update_one({"_id":channel}, {"$push":{"gameHistory":(int(position[1])-1, ord(position[0])-97)}}) # Is it now Gwendolyn's turn? - gwendoTurn = False + gwendolyn_turn = False if game["players"][turn-1] == f"#{self.bot.user.id}": self.bot.log("It's Gwendolyn's turn") - gwendoTurn = True + gwendolyn_turn = True - placedPiece = True + placed_piece = True if user == f"#{self.bot.user.id}": - await ctx.channel.send(sendMessage) + await ctx.channel.send(send_message) else: - await ctx.send(sendMessage) + await ctx.send(send_message) - if placedPiece: + if placed_piece: # Update the board self.draw.drawHexPlacement(channel,player, position) @@ -270,7 +270,7 @@ class HexGame(): file_path = f"gwendolyn/resources/games/hex_boards/board{channel}.png" old_image = await ctx.channel.send(file = discord.File(file_path)) - if gameWon: + if game_won: self.bot.log("Dealing with the winning player") game = self.bot.database["hex games"].find_one({"_id":channel}) @@ -284,7 +284,7 @@ class HexGame(): with open(f"gwendolyn/resources/games/old_images/hex{channel}", "w") as f: f.write(str(old_image.id)) - if gwendoTurn: + if gwendolyn_turn: await self.hexAI(ctx) # Returns a board where the placement has ocurred @@ -314,11 +314,11 @@ class HexGame(): game = self.bot.database["hex games"].find_one({"_id":channel}) if user not in game["players"]: - sendMessage = "You're not a player in the game" + send_message = "You're not a player in the game" elif len(game["gameHistory"]) == 0: - sendMessage = "You can't undo nothing" + send_message = "You can't undo nothing" elif user != game["players"][(game["turn"] % 2)]: # If it's not your turn - sendMessage = "It's not your turn" + send_message = "It's not your turn" else: turn = game["turn"] self.bot.log("Undoing {}'s last move".format(self.bot.database_funcs.get_name(user))) @@ -332,10 +332,10 @@ class HexGame(): # Update the board self.draw.drawHexPlacement(channel,0,"abcdefghijk"[lastMove[1]]+str(lastMove[0]+1)) # The zero makes the hex disappear - sendMessage = f"You undid your last move at {lastMove}" + send_message = f"You undid your last move at {lastMove}" undid = True - await ctx.send(sendMessage) + await ctx.send(send_message) if undid: with open(f"gwendolyn/resources/games/old_images/hex{channel}", "r") as f: old_image = await ctx.channel.fetch_message(int(f.read())) @@ -417,20 +417,20 @@ class HexGame(): return scores[2]-scores[1], winner - def minimaxHex(self, board, depth, alpha, beta, maximizingPlayer): + def minimaxHex(self, board, depth, alpha, beta, maximizing_player): # The depth is how many moves ahead the computer checks. This value is the difficulty. if depth == 0 or 0 not in sum(board,[]): score = self.evaluateBoard(board)[0] return score # if final depth is not reached, look another move ahead: - if maximizingPlayer: # red player predicts next move + if maximizing_player: # red player predicts next move maxEval = -math.inf possiblePlaces = [i for i,v in enumerate(sum(board,[])) if v == 0] #self.bot.log("Judging a red move at depth {}".format(depth)) for i in possiblePlaces: - testBoard = copy.deepcopy(board) - testBoard[i // self.BOARDWIDTH][i % self.BOARDWIDTH] = 1 # because maximizingPlayer is Red which is number 1 - evaluation = self.minimaxHex(testBoard,depth-1,alpha,beta,False) + test_board = copy.deepcopy(board) + test_board[i // self.BOARDWIDTH][i % self.BOARDWIDTH] = 1 # because maximizing_player is Red which is number 1 + evaluation = self.minimaxHex(test_board,depth-1,alpha,beta,False) maxEval = max(maxEval, evaluation) alpha = max(alpha, evaluation) if beta <= alpha: @@ -442,9 +442,9 @@ class HexGame(): possiblePlaces = [i for i,v in enumerate(sum(board,[])) if v == 0] #self.bot.log("Judging a blue move at depth {}".format(depth)) for i in possiblePlaces: - testBoard = copy.deepcopy(board) - testBoard[i // self.BOARDWIDTH][i % self.BOARDWIDTH] = 2 # because minimizingPlayer is Blue which is number 2 - evaluation = self.minimaxHex(testBoard,depth-1,alpha,beta,True) + test_board = copy.deepcopy(board) + test_board[i // self.BOARDWIDTH][i % self.BOARDWIDTH] = 2 # because minimizingPlayer is Blue which is number 2 + evaluation = self.minimaxHex(test_board,depth-1,alpha,beta,True) minEval = min(minEval, evaluation) beta = min(beta, evaluation) if beta <= alpha: diff --git a/gwendolyn/funcs/games/invest.py b/gwendolyn/funcs/games/invest.py index 8977503..eaac8f0 100644 --- a/gwendolyn/funcs/games/invest.py +++ b/gwendolyn/funcs/games/invest.py @@ -62,8 +62,8 @@ class Invest(): portfolio: str The portfolio. """ - investmentsDatabase = self.bot.database["investments"] - userInvestments = investmentsDatabase.find_one({"_id": user}) + investments_database = self.bot.database["investments"] + userInvestments = investments_database.find_one({"_id": user}) user_name = self.bot.database_funcs.get_name(user) @@ -101,7 +101,7 @@ class Invest(): *Returns* --------- - sendMessage: str + send_message: str The message to return to the user. """ if buyAmount < 100: @@ -111,9 +111,9 @@ class Invest(): elif self.getPrice(stock) <= 0: return f"{stock} is not traded on the american market." else: - investmentsDatabase = self.bot.database["investments"] + investments_database = self.bot.database["investments"] stockPrice = self.getPrice(stock) - userInvestments = investmentsDatabase.find_one({"_id": user}) + userInvestments = investments_database.find_one({"_id": user}) self.bot.money.addMoney(user, -1*buyAmount) stock = stock.upper() @@ -126,18 +126,18 @@ class Invest(): currentValue = int(valueChange * value["purchased"]) newAmount = currentValue + buyAmount - valuePath = f"investments.{stock}.value at purchase" - updater = {"$set": {valuePath: stockPrice}} - investmentsDatabase.update_one({"_id": user}, updater) + value_path = f"investments.{stock}.value at purchase" + updater = {"$set": {value_path: stockPrice}} + investments_database.update_one({"_id": user}, updater) - purchasedPath = f"investments.{stock}.purchased" - updater = {"$set": {purchasedPath: newAmount}} - investmentsDatabase.update_one({"_id": user}, updater) + purchased_path = f"investments.{stock}.purchased" + updater = {"$set": {purchased_path: newAmount}} + investments_database.update_one({"_id": user}, updater) if value["purchased for"] != "?": - purchasedForPath = f"investments.{stock}.purchased for" - updater = {"$set": {purchasedForPath: buyAmount}} - investmentsDatabase.update_one({"_id": user}, updater) + purchasedFor_path = f"investments.{stock}.purchased for" + updater = {"$set": {purchasedFor_path: buyAmount}} + investments_database.update_one({"_id": user}, updater) else: updater = { "$set": { @@ -148,9 +148,9 @@ class Invest(): } } } - investmentsDatabase.update_one({"_id": user}, updater) + investments_database.update_one({"_id": user}, updater) else: - newUser = { + new_user = { "_id": user, "investments": { stock: { @@ -160,12 +160,12 @@ class Invest(): } } } - investmentsDatabase.insert_one(newUser) + investments_database.insert_one(new_user) user_name = self.bot.database_funcs.get_name(user) - sendMessage = "{} bought {} GwendoBucks worth of {} stock" - sendMessage = sendMessage.format(user_name, buyAmount, stock) - return sendMessage + send_message = "{} bought {} GwendoBucks worth of {} stock" + send_message = send_message.format(user_name, buyAmount, stock) + return send_message def sellStock(self, user: str, stock: str, sellAmount: int): """ @@ -182,15 +182,15 @@ class Invest(): *Returns* --------- - sendMessage: str + send_message: str The message to return to the user. """ if sellAmount <= 0: return "no" else: - investmentsDatabase = self.bot.database["investments"] - userData = investmentsDatabase.find_one({"_id": user}) - userInvestments = userData["investments"] + investments_database = self.bot.database["investments"] + user_data = investments_database.find_one({"_id": user}) + userInvestments = user_data["investments"] stock = stock.upper() @@ -199,29 +199,29 @@ class Invest(): stockPrice = self.getPrice(stock) priceChange = (stockPrice / value["value at purchase"]) purchasedAmount = int(priceChange * value["purchased"]) - purchasedPath = f"investments.{stock}.purchased" - updater = {"$set": {purchasedPath: purchasedAmount}} - investmentsDatabase.update_one({"_id": user}, updater) - valueAtPurchasePath = f"investments.{stock}.value at purchase" - updater = {"$set": {valueAtPurchasePath: stockPrice}} - investmentsDatabase.update_one({"_id": user}, updater) + purchased_path = f"investments.{stock}.purchased" + updater = {"$set": {purchased_path: purchasedAmount}} + investments_database.update_one({"_id": user}, updater) + valueAtPurchase_path = f"investments.{stock}.value at purchase" + updater = {"$set": {valueAtPurchase_path: stockPrice}} + investments_database.update_one({"_id": user}, updater) if value["purchased"] >= sellAmount: self.bot.money.addMoney(user, sellAmount) if sellAmount < value["purchased"]: - purchasedPath = f"investments.{stock}.purchased" - updater = {"$inc": {purchasedPath: -sellAmount}} - investmentsDatabase.update_one({"_id": user}, updater) + purchased_path = f"investments.{stock}.purchased" + updater = {"$inc": {purchased_path: -sellAmount}} + investments_database.update_one({"_id": user}, updater) - purchasedForPath = f"investments.{stock}.purchased for" - updater = {"$set": {purchasedForPath: "?"}} - investmentsDatabase.update_one({"_id": user}, updater) + purchasedFor_path = f"investments.{stock}.purchased for" + updater = {"$set": {purchasedFor_path: "?"}} + investments_database.update_one({"_id": user}, updater) else: updater = {"$unset": {f"investments.{stock}": ""}} - investmentsDatabase.update_one({"_id": user}, updater) + investments_database.update_one({"_id": user}, updater) user_name = self.bot.database_funcs.get_name(user) - sendMessage = "{} sold {} GwendoBucks worth of {} stock" - return sendMessage.format(user_name, sellAmount, stock) + send_message = "{} sold {} GwendoBucks worth of {} stock" + return send_message.format(user_name, sellAmount, stock) else: return f"You don't have enough {stock} stocks to do that" else: diff --git a/gwendolyn/funcs/games/money.py b/gwendolyn/funcs/games/money.py index 51d179a..e46583d 100644 --- a/gwendolyn/funcs/games/money.py +++ b/gwendolyn/funcs/games/money.py @@ -51,10 +51,10 @@ class Money(): """ self.bot.log("checking "+user+"'s account balance") - userData = self.database["users"].find_one({"_id": user}) + user_data = self.database["users"].find_one({"_id": user}) - if userData is not None: - return userData["money"] + if user_data is not None: + return user_data["money"] else: return 0 @@ -90,18 +90,18 @@ class Money(): """ self.bot.log("adding "+str(amount)+" to "+user+"'s account") - userData = self.database["users"].find_one({"_id": user}) + user_data = self.database["users"].find_one({"_id": user}) - if userData is not None: + if user_data is not None: updater = {"$inc": {"money": amount}} self.database["users"].update_one({"_id": user}, updater) else: - newUser = { + new_user = { "_id": user, "user name": self.bot.database_funcs.get_name(user), "money": amount } - self.database["users"].insert_one(newUser) + self.database["users"].insert_one(new_user) # Transfers money from one user to another async def giveMoney(self, ctx: discord_slash.context.SlashContext, @@ -125,15 +125,15 @@ class Money(): if member.display_name.lower() == username.lower(): username = member.display_name user_id = f"#{member.id}" - newUser = { + new_user = { "_id": user_id, "user name": username, "money": 0 } - self.bot.database["users"].insert_one(newUser) + self.bot.database["users"].insert_one(new_user) userid = f"#{ctx.author.id}" - userData = self.database["users"].find_one({"_id": userid}) + user_data = self.database["users"].find_one({"_id": userid}) targetUser = self.bot.database_funcs.get_id(username) if amount <= 0: @@ -142,7 +142,7 @@ class Money(): elif targetUser is None: self.bot.log("They weren't in the system") await ctx.send("The target doesn't exist") - elif userData is None or userData["money"] < amount: + elif user_data is None or user_data["money"] < amount: self.bot.log("They didn't have enough GwendoBucks") await ctx.send("You don't have that many GwendoBuck") else: diff --git a/gwendolyn/funcs/games/trivia.py b/gwendolyn/funcs/games/trivia.py index d03c2be..e0d2284 100644 --- a/gwendolyn/funcs/games/trivia.py +++ b/gwendolyn/funcs/games/trivia.py @@ -45,7 +45,7 @@ class Trivia(): *Returns* --------- - sendMessage: str + send_message: str The message to return to the user. """ triviaQuestions = self.bot.database["trivia questions"] @@ -110,7 +110,7 @@ class Trivia(): *Returns* --------- - sendMessage: str + send_message: str The message to send if the function failed. """ triviaQuestions = self.bot.database["trivia questions"] @@ -185,10 +185,10 @@ class Trivia(): self.bot.database_funcs.delete_game(*delete_gameParams) self.bot.log("Time's up for the trivia question", channelId) - sendMessage = self.bot.long_strings["Trivia time up"] - formatParams = [chr(correctAnswer), options[correctAnswer-97]] - sendMessage = sendMessage.format(*formatParams) - await ctx.send(sendMessage) + send_message = self.bot.long_strings["Trivia time up"] + format_parameters = [chr(correctAnswer), options[correctAnswer-97]] + send_message = send_message.format(*format_parameters) + await ctx.send(send_message) else: await ctx.send(question, hidden=True) diff --git a/gwendolyn/funcs/lookup/lookup_funcs.py b/gwendolyn/funcs/lookup/lookup_funcs.py index efe24ca..418ed32 100644 --- a/gwendolyn/funcs/lookup/lookup_funcs.py +++ b/gwendolyn/funcs/lookup/lookup_funcs.py @@ -152,13 +152,13 @@ class LookupFuncs(): data = json.load(open('gwendolyn/resources/lookup/spells.json', encoding = "utf8")) if query in data: self.bot.log("Returning spell information") - sendMessage = (f"***{query}***\n*{data[query]['level']} level {data[query]['school']}\nCasting Time: {data[query]['casting_time']}\nRange:{data[query]['range']}\nComponents:{data[query]['components']}\nDuration:{data[query]['duration']}*\n \n{data[query]['description']}") + send_message = (f"***{query}***\n*{data[query]['level']} level {data[query]['school']}\nCasting Time: {data[query]['casting_time']}\nRange:{data[query]['range']}\nComponents:{data[query]['components']}\nDuration:{data[query]['duration']}*\n \n{data[query]['description']}") else: self.bot.log("I don't know that spell (error code 501)") - sendMessage = "I don't think that's a spell (error code 501)" + send_message = "I don't think that's a spell (error code 501)" - if len(sendMessage) > 2000: - await ctx.send(sendMessage[:2000]) - await ctx.send(sendMessage[2000:]) + if len(send_message) > 2000: + await ctx.send(send_message[:2000]) + await ctx.send(send_message[2000:]) else: - await ctx.send(sendMessage) + await ctx.send(send_message) diff --git a/gwendolyn/funcs/other/__init__.py b/gwendolyn/funcs/other/__init__.py index 8612103..9cef1df 100644 --- a/gwendolyn/funcs/other/__init__.py +++ b/gwendolyn/funcs/other/__init__.py @@ -2,4 +2,4 @@ __all__ = ["Other"] -from .other import Other \ No newline at end of file +from .other import Other diff --git a/gwendolyn/funcs/other/bedre_netflix.py b/gwendolyn/funcs/other/bedre_netflix.py deleted file mode 100644 index f8226ec..0000000 --- a/gwendolyn/funcs/other/bedre_netflix.py +++ /dev/null @@ -1,413 +0,0 @@ -import requests, imdb, discord, json, math, time, asyncio - -class BedreNetflix(): - def __init__(self,bot): - self.bot = bot - ip = ["localhost", "192.168.0.40"][self.bot.options["testing"]] - - self.radarrURL = "http://"+ip+":7878/api/v3/" - self.sonarrURL = "http://"+ip+":8989/api/" - self.qbittorrentURL = "http://"+ip+":8080/api/v2/" - self.moviePath = "/media/plex/Server/movies/" - self.showPath = "/media/plex/Server/Shows/" - - #Returns a list of no more than 5 options when user requests a movie - async def requestMovie(self, ctx, movieName): - await self.bot.defer(ctx) - - self.bot.log("Searching for "+movieName) - movieList = imdb.IMDb().search_movie(movieName) - movies = [] - for movie in movieList: - if movie["kind"] == "movie": - movies.append(movie) - if len(movies) > 5: - movies = movies[:5] - - if len(movies) == 1: - messageTitle = "**Is it this movie?**" - else: - messageTitle = "**Is it any of these movies?**" - - messageText = "" - imdb_ids = [] - - for x, movie in enumerate(movies): - try: - messageText += "\n"+str(x+1)+") "+movie["title"]+" ("+str(movie["year"])+")" - except: - try: - messageText += "\n"+str(x+1)+") "+movie["title"] - except: - messageText += "Error" - imdb_ids.append(movie.movieID) - - self.bot.log("Returning a list of "+str(len(movies))+" possible movies: "+str(imdb_ids)) - - em = discord.Embed(title=messageTitle,description=messageText,colour=0x00FF00) - - message = await ctx.send(embed=em) - - messageData = {"message_id":message.id,"imdb_ids":imdb_ids} - - with open("gwendolyn/resources/bedre_netflix/old_message"+str(ctx.channel.id),"w") as f: - json.dump(messageData,f) - - if len(movies) == 1: - await message.add_reaction("✔️") - else: - for x in range(len(movies)): - await message.add_reaction(["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣"][x]) - - await message.add_reaction("❌") - - message = await ctx.channel.fetch_message(message.id) - if message.content != "" and not isinstance(ctx.channel, discord.DMChannel): - await message.clear_reactions() - - #Adds the requested movie to Bedre Netflix - async def add_movie(self, message, imdbId, editMessage = True): - if imdbId == None: - self.bot.log("Did not find what the user was searching for") - if editMessage: - await message.edit(embed = None, content = "Try searching for the IMDB id") - else: - await message.channel.send("Try searching for the IMDB id") - else: - self.bot.log("Trying to add movie "+str(imdbId)) - apiKey = self.bot.credentials["radarr_key"] - response = requests.get(self.radarrURL+"movie/lookup/imdb?imdbId=tt"+imdbId+"&apiKey="+apiKey) - lookupData = response.json() - postData = {"qualityProfileId": 1, - "rootFolderPath" : self.moviePath, - "monitored" : True, - "addOptions": {"searchForMovie": True}} - for key in ["tmdbId","title","titleSlug","images","year"]: - postData.update({key : lookupData[key]}) - - r = requests.post(url= self.radarrURL+"movie?apikey="+apiKey,json = postData) - - if r.status_code == 201: - if editMessage: - await message.edit(embed = None, content = postData["title"]+" successfully added to Bedre Netflix") - else: - await message.channel.send(postData["title"]+" successfully added to Bedre Netflix") - - self.bot.log("Added "+postData["title"]+" to Bedre Netflix") - elif r.status_code == 400: - text = f"{postData['title']} is either already on Bedre Netflix, downloading, or not available" - if editMessage: - await message.edit(embed = None, content = text) - else: - await message.channel.send(text) - else: - if editMessage: - await message.edit(embed = None, content = "Something went wrong") - else: - await message.channel.send("Something went wrong") - self.bot.log(str(r.status_code)+" "+r.reason) - - #Returns a list of no more than 5 options when user requests a show - async def requestShow(self, ctx, showName): - await self.bot.defer(ctx) - - self.bot.log("Searching for "+showName) - movies = imdb.IMDb().search_movie(showName) #Replace with tvdb - shows = [] - for movie in movies: - if movie["kind"] in ["tv series","tv miniseries"]: - shows.append(movie) - if len(shows) > 5: - shows = shows[:5] - - if len(shows) == 1: - messageTitle = "**Is it this show?**" - else: - messageTitle = "**Is it any of these shows?**" - - messageText = "" - imdb_names = [] - - for x, show in enumerate(shows): - try: - messageText += "\n"+str(x+1)+") "+show["title"]+" ("+str(show["year"])+")" - except: - try: - messageText += "\n"+str(x+1)+") "+show["title"] - except: - messageText += "Error" - imdb_names.append(show["title"]) - - self.bot.log("Returning a list of "+str(len(shows))+" possible shows: "+str(imdb_names)) - - em = discord.Embed(title=messageTitle,description=messageText,colour=0x00FF00) - - message = await ctx.send(embed=em) - - messageData = {"message_id":message.id,"imdb_names":imdb_names} - - with open("gwendolyn/resources/bedre_netflix/old_message"+str(ctx.channel.id),"w") as f: - json.dump(messageData,f) - - if len(shows) == 1: - await message.add_reaction("✔️") - else: - for x in range(len(shows)): - await message.add_reaction(["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣"][x]) - - await message.add_reaction("❌") - - message = await ctx.channel.fetch_message(message.id) - if message.content != "" and not isinstance(ctx.channel, discord.DMChannel): - await message.clear_reactions() - - #Adds the requested show to Bedre Netflix - async def add_show(self, message, imdb_name): - if imdb_name == None: - self.bot.log("Did not find what the user was searching for") - await message.edit(embed = None, content = "Try searching for the IMDB id") - else: - self.bot.log("Trying to add show "+str(imdb_name)) - apiKey = self.bot.credentials["sonarr_key"] - response = requests.get(self.sonarrURL+"series/lookup?term="+imdb_name.replace(" ","%20")+"&apiKey="+apiKey) - lookupData = response.json()[0] - postData = {"ProfileId" : 1, - "rootFolderPath" : self.showPath, - "monitored" : True, - "addOptions" : {"searchForMissingEpisodes" : True}} - for key in ["tvdbId","title","titleSlug","images","seasons"]: - postData.update({key : lookupData[key]}) - - r = requests.post(url= self.sonarrURL+"series?apikey="+apiKey,json = postData) - - if r.status_code == 201: - await message.edit(embed = None, content = postData["title"]+" successfully added to Bedre Netflix") - self.bot.log("Added a "+postData["title"]+" to Bedre Netflix") - elif r.status_code == 400: - text = f"{postData['title']} is either already on Bedre Netflix, downloading, or not available" - await message.edit(embed = None, content = text) - else: - await message.edit(embed = None, content = "Something went wrong") - self.bot.log(str(r.status_code)+" "+r.reason) - - #Generates a list of all torrents and returns formatted list and whether all torrents are downloaded - async def genDownloadList(self, showDM, showMovies, showShows, episodes): - self.bot.log("Generating torrent list") - titleWidth = 100 - message = [] - allDownloaded = True - - if showDM: - message.append("") - DMSectionTitle = "*Torrent Downloads*" - DMSectionTitleLine = "-"*((titleWidth-len(DMSectionTitle))//2) - message.append(DMSectionTitleLine+DMSectionTitle+DMSectionTitleLine) - response = requests.get(self.qbittorrentURL+"torrents/info") - torrentList = response.json() - - if len(torrentList) > 0: - for torrent in torrentList: - torrentName = torrent["name"] - if len(torrentName) > 30: - if torrentName[26] == " ": - torrentName = torrentName[:26]+"...." - else: - torrentName = torrentName[:27]+"..." - while len(torrentName) < 30: - torrentName += " " - - if torrent["size"] == 0: - downloadedRatio = 0 - elif torrent["amount_left"] == 0: - downloadedRatio = 1 - else: - downloadedRatio = min(torrent["downloaded"]/torrent["size"],1) - progressBar = "|"+("█"*math.floor(downloadedRatio*20)) - while len(progressBar) < 21: - progressBar += " " - - progressBar += "| "+str(math.floor(downloadedRatio*100))+"%" - - while len(progressBar) < 27: - progressBar += " " - - etaInSeconds = torrent["eta"] - - if etaInSeconds >= 8640000: - eta = "∞" - else: - eta = "" - if etaInSeconds >= 86400: - eta += str(math.floor(etaInSeconds/86400))+"d " - if etaInSeconds >= 3600: - eta += str(math.floor((etaInSeconds%86400)/3600))+"h " - if etaInSeconds >= 60: - eta += str(math.floor((etaInSeconds%3600)/60))+"m " - - eta += str(etaInSeconds%60)+"s" - - torrentInfo = torrentName+" "+progressBar+" (Eta: "+eta+")" - - if torrent["state"] == "stalledDL": - torrentInfo += " (Stalled)" - - if not (downloadedRatio == 1 and torrent["last_activity"] < time.time()-7200): - message.append(torrentInfo) - - if downloadedRatio < 1 and torrent["state"] != "stalledDL": - allDownloaded = False - else: - message.append("No torrents currently downloading") - - if showMovies: - message.append("") - movieSectionTitle = "*Missing movies not downloading*" - movieSectionTitleLine = "-"*((titleWidth-len(movieSectionTitle))//2) - message.append(movieSectionTitleLine+movieSectionTitle+movieSectionTitleLine) - movieList = requests.get(self.radarrURL+"movie?apiKey="+self.bot.credentials["radarr_key"]).json() - movieQueue = requests.get(self.radarrURL+"queue?apiKey="+self.bot.credentials["radarr_key"]).json() - movieQueueIDs = [] - - for queueItem in movieQueue["records"]: - movieQueueIDs.append(queueItem["movieId"]) - - for movie in movieList: - if not movie["hasFile"]: - if movie["id"] not in movieQueueIDs: - movieName = movie["title"] - if len(movieName) > 40: - if movieName[36] == " ": - movieName = movieName[:36]+"...." - else: - movieName = movieName[:37]+"..." - - while len(movieName) < 41: - movieName += " " - - if movie["monitored"]: - movieInfo = movieName+"Could not find a torrent" - else: - movieInfo = movieName+"No torrent exists. Likely because the movie is not yet released on DVD" - - message.append(movieInfo) - - if showShows: - message.append("") - showSectionTitle = "*Missing shows not downloading*" - showSectionTitleLine = "-"*((titleWidth-len(showSectionTitle))//2) - message.append(showSectionTitleLine+showSectionTitle+showSectionTitleLine) - - showList = requests.get(self.sonarrURL+"series?apiKey="+self.bot.credentials["sonarr_key"]).json() - - for show in showList: - if show["seasons"][0]["seasonNumber"] == 0: - seasons = show["seasons"][1:] - else: - seasons = show["seasons"] - if any(i["statistics"]["episodeCount"] != i["statistics"]["totalEpisodeCount"] for i in seasons): - if all(i["statistics"]["episodeCount"] == 0 for i in seasons): - message.append(show["title"] + " (all episodes)") - else: - if episodes: - missingEpisodes = sum(i["statistics"]["totalEpisodeCount"] - i["statistics"]["episodeCount"] for i in seasons) - message.append(show["title"] + f" ({missingEpisodes} episodes)") - - message.append("-"*titleWidth) - - messageText = "```"+"\n".join(message[1:])+"```" - if messageText == "``````": - messageText = "There are no torrents downloading right. If the torrent you're looking for was added more than 24 hours ago, it might already be on Bedre Netflix." - return messageText, allDownloaded - - async def downloading(self, ctx, content): - async def SendLongMessage(ctx,messageText): - if len(messageText) <= 1994: - await ctx.send("```"+messageText+"```") - else: - cutOffIndex = messageText[:1994].rfind("\n") - await ctx.send("```"+messageText[:cutOffIndex]+"```") - await SendLongMessage(ctx,messageText[cutOffIndex+1:]) - - await self.bot.defer(ctx) - - # showDM, showMovies, showShows, episodes - params = [False, False, False, False] - showDMArgs = ["d", "dm", "downloading", "downloadmanager"] - showMoviesArgs = ["m", "movies"] - showShowsArgs = ["s", "shows", "series"] - episodesArgs = ["e", "episodes"] - argList = [showDMArgs, showMoviesArgs, showShowsArgs, episodesArgs] - inputArgs = [] - validArguments = True - - while content != "" and validArguments: - if content[0] == " ": - content = content[1:] - elif content[0] == "-": - if content[1] == "-": - argStart = 2 - if " " in content: - argStop = content.find(" ") - else: - argStop = None - else: - argStart = 1 - argStop = 2 - - inputArgs.append(content[argStart:argStop]) - if argStop is None: - content = "" - else: - content = content[argStop:] - else: - validArguments = False - - if validArguments: - for x, argAliases in enumerate(argList): - argInInput = [i in inputArgs for i in argAliases] - if any(argInInput): - inputArgs.remove(argAliases[argInInput.index(True)]) - params[x] = True - - if len(inputArgs) != 0 or (params[2] == False and params[3] == True): - validArguments = False - - showAnything = any(i for i in params) - if validArguments and showAnything: - messageText, allDownloaded = await self.genDownloadList(*params) - if messageText.startswith("```"): - - if len(messageText) <= 2000: - if not allDownloaded: - updatesLeft = 60 - messageText = messageText[:-3]+"\nThis message will update every 10 seconds for "+str(math.ceil(updatesLeft/6))+" more minutes\n```" - old_message = await ctx.send(messageText) - - while ((not allDownloaded) and updatesLeft > 0): - await asyncio.sleep(10) - updatesLeft -= 1 - messageText, allDownloaded = await self.genDownloadList(*params) - messageText = messageText[:-3]+"\nThis message will update every 10 seconds for "+str(math.ceil(updatesLeft/6))+" more minutes\n```" - await old_message.edit(content = messageText) - - messageText, allDownloaded = await self.genDownloadList(*params) - - if messageText.startswith("```"): - if allDownloaded: - self.bot.log("All torrents are downloaded") - else: - messageText = messageText[:-3]+"\nThis message will not update anymore\n```" - self.bot.log("The message updated 20 times") - - await old_message.edit(content = messageText) - - else: - await ctx.send(messageText) - else: - messageText = messageText[3:-3] - await SendLongMessage(ctx,messageText) - else: - await ctx.send(messageText) - else: - await ctx.send("Invalid or repeated parameters. Use '/help downloading' to see valid parameters.") - diff --git a/gwendolyn/funcs/other/generators.py b/gwendolyn/funcs/other/generators.py index 8b8b5d9..c3a99a6 100644 --- a/gwendolyn/funcs/other/generators.py +++ b/gwendolyn/funcs/other/generators.py @@ -72,15 +72,15 @@ class Generators(): # Ends name if the name ends if new_letter == "\n": done = True - genName = "".join(chain) - self.bot.log("Generated "+genName[:-1]) + gen_name = "".join(chain) + self.bot.log("Generated "+gen_name[:-1]) # Returns the name - await ctx.send(genName) + await ctx.send(gen_name) # Generates a random tavern name async def tavernGen(self, ctx): - # Lists first parts, second parts and third parts of tavern names + # _lists first parts, second parts and third parts of tavern names fp = ["The Silver","The Golden","The Staggering","The Laughing","The Prancing","The Gilded","The Running","The Howling","The Slaughtered","The Leering","The Drunken","The Leaping","The Roaring","The Frowning","The Lonely","The Wandering","The Mysterious","The Barking","The Black","The Gleaming","The Tap-Dancing","The Sad","The Sexy","The Artificial","The Groovy","The Merciful","The Confused","The Pouting","The Horny","The Okay","The Friendly","The Hungry","The Handicapped","The Fire-breathing","The One-Eyed","The Psychotic","The Mad","The Evil","The Idiotic","The Trusty","The Busty"] sp = ["Eel","Dolphin","Dwarf","Pegasus","Pony","Rose","Stag","Wolf","Lamb","Demon","Goat","Spirit","Horde","Jester","Mountain","Eagle","Satyr","Dog","Spider","Star","Dad","Rat","Jeremy","Mouse","Unicorn","Pearl","Ant","Crab","Penguin","Octopus","Lawyer","Ghost","Toad","Handjob","Immigrant","SJW","Dragon","Bard","Sphinx","Soldier","Salmon","Owlbear","Kite","Frost Giant","Arsonist"] tp = [" Tavern"," Inn","","","","","","","","",""] diff --git a/gwendolyn/funcs/other/nerd_shit.py b/gwendolyn/funcs/other/nerd_shit.py index 1e8274a..22b7159 100644 --- a/gwendolyn/funcs/other/nerd_shit.py +++ b/gwendolyn/funcs/other/nerd_shit.py @@ -38,10 +38,10 @@ class NerdShit(): heights += [height] width = max(width,int(pod.img['@width'])) if titleChucks[x][count] == "": - placeForText = 0 + placeFor_text = 0 else: - placeForText = 30 - height += int(pod.img["@height"]) + 10 + placeForText + placeFor_text = 30 + height += int(pod.img["@height"]) + 10 + placeFor_text width += 10 height += 5 @@ -55,18 +55,18 @@ class NerdShit(): old_image = Image.open("gwendolyn/resources/wolfTemp.png") oldSize = old_image.size if titleChucks[x][count] == "": - placeForText = 0 + placeFor_text = 0 else: - placeForText = 30 - newSize = (width,int(oldSize[1]+10+placeForText)) - newImage = Image.new("RGB",newSize,color=(255,255,255)) - newImage.paste(old_image, (int((int(oldSize[0]+10)-oldSize[0])/2),int(((newSize[1]-placeForText)-oldSize[1])/2)+placeForText)) + placeFor_text = 30 + newSize = (width,int(oldSize[1]+10+placeFor_text)) + new_image = Image.new("RGB",newSize,color=(255,255,255)) + new_image.paste(old_image, (int((int(oldSize[0]+10)-oldSize[0])/2),int(((newSize[1]-placeFor_text)-oldSize[1])/2)+placeFor_text)) if titleChucks[x][count] != "": - d = ImageDraw.Draw(newImage,"RGB") + d = ImageDraw.Draw(new_image,"RGB") d.text((5,7),titleChucks[x][count],font=fnt,fill=(150,150,150)) - wolfImage.paste(newImage,(0,heights[count])) - newImage.close() + wolfImage.paste(new_image,(0,heights[count])) + new_image.close() old_image.close() count += 1 diff --git a/gwendolyn/funcs/other/other.py b/gwendolyn/funcs/other/other.py index f901e1d..f560a78 100644 --- a/gwendolyn/funcs/other/other.py +++ b/gwendolyn/funcs/other/other.py @@ -7,7 +7,7 @@ import lxml # Used in imageFunc import fandom # Used in findWikiPage import d20 # Used in rollDice import ast -from .bedre_netflix import BedreNetflix +from .plex import Plex from .nerd_shit import NerdShit from .generators import Generators @@ -19,16 +19,16 @@ fandom.set_wiki("senkulpa") class MyStringifier(d20.MarkdownStringifier): def _str_expression(self, node): if node.comment == None: - resultText = "Result" + result_text = "Result" else: - resultText = node.comment.capitalize() + result_text = node.comment.capitalize() - return f"**{resultText}**: {self._stringify(node.roll)}\n**Total**: {int(node.total)}" + return f"**{result_text}**: {self._stringify(node.roll)}\n**Total**: {int(node.total)}" class Other(): def __init__(self, bot): self.bot = bot - self.bedre_netflix = BedreNetflix(self.bot) + self.plex = Plex(self.bot) self.nerd_shit = NerdShit(self.bot) self.generators = Generators(self.bot) @@ -41,11 +41,11 @@ class Other(): self.bot.log("Picking a movie") with open("gwendolyn/resources/movies.txt", "r") as f: - movieList = f.read().split("\n") - movieName = random.choice(movieList) + movie_list = f.read().split("\n") + movie_name = random.choice(movie_list) - self.bot.log(f"Searching for {movieName}") - searchResult = imdbClient.search_movie(movieName) + self.bot.log(f"Searching for {movie_name}") + searchResult = imdbClient.search_movie(movie_name) self.bot.log("Getting the data") movie = searchResult[0] @@ -74,17 +74,17 @@ class Other(): author = ctx.author.display_name now = datetime.datetime.now() if time_in_range(now.replace(hour=5, minute=0, second=0, microsecond=0),now.replace(hour=10, minute=0, second=0, microsecond=0), now): - sendMessage = "Good morning, "+str(author) + send_message = "Good morning, "+str(author) elif time_in_range(now.replace(hour=13, minute=0, second=0, microsecond=0),now.replace(hour=18, minute=0, second=0, microsecond=0), now): - sendMessage = "Good afternoon, "+str(author) + send_message = "Good afternoon, "+str(author) elif time_in_range(now.replace(hour=18, minute=0, second=0, microsecond=0),now.replace(hour=22, minute=0, second=0, microsecond=0), now): - sendMessage = "Good evening, "+str(author) + send_message = "Good evening, "+str(author) elif time_in_range(now.replace(hour=22, minute=0, second=0, microsecond=0),now.replace(hour=23, minute=59, second=59, microsecond=0), now): - sendMessage = "Good night, "+str(author) + send_message = "Good night, "+str(author) else: - sendMessage = "Hello, "+str(author) + send_message = "Hello, "+str(author) - await ctx.send(sendMessage) + await ctx.send(send_message) # Finds a random picture online async def imageFunc(self, ctx): diff --git a/gwendolyn/funcs/other/plex.py b/gwendolyn/funcs/other/plex.py new file mode 100644 index 0000000..953911d --- /dev/null +++ b/gwendolyn/funcs/other/plex.py @@ -0,0 +1,536 @@ +"""Plex integration with the bot.""" +from math import floor, ceil +import time +import json +import asyncio +import requests +import imdb +import discord + +class Plex(): + """Container for Plex functions and commands.""" + def __init__(self,bot): + self.bot = bot + self.credentials = self.bot.credentials + self.long_strings = self.bot.long_strings + server_ip = ["localhost", "192.168.0.40"][self.bot.options["testing"]] + + self.radarr_url = "http://"+server_ip+":7878/api/v3/" + self.sonarr_url = "http://"+server_ip+":8989/api/" + self.qbittorrent_url = "http://"+server_ip+":8080/api/v2/" + self.movie_path = "/media/plex/Server/movies/" + self.show_path = "/media/plex/Server/Shows/" + + + async def request_movie(self, ctx, movie_name): + """Request a movie for the Plex Server""" + await self.bot.defer(ctx) + + self.bot.log("Searching for "+movie_name) + movie_list = imdb.IMDb().search_movie(movie_name) + movies = [] + for movie in movie_list: + if movie["kind"] == "movie": + movies.append(movie) + if len(movies) > 5: + movies = movies[:5] + + if len(movies) == 1: + message_title = "**Is it this movie?**" + else: + message_title = "**Is it any of these movies?**" + + message_text = "" + imdb_ids = [] + + for i, movie in enumerate(movies): + try: + message_text += "\n"+str(i+1)+") "+movie["title"] + try: + message_text += " ("+str(movie["year"])+")" + except KeyError: + self.bot.log(f"{movie['title']} has no year.") + except KeyError: + message_text += "Error" + imdb_ids.append(movie.movieID) + + self.bot.log( + f"Returning a list of {len(movies)} possible movies: {imdb_ids}" + ) + + embed = discord.Embed( + title=message_title, + description=message_text, + colour=0x00FF00 + ) + + message = await ctx.send(embed=embed) + + message_data = {"message_id":message.id,"imdb_ids":imdb_ids} + + file_path = f"gwendolyn/resources/plex/old_message{ctx.channel.id}" + with open(file_path,"w") as file_pointer: + json.dump(message_data, file_pointer) + + if len(movies) == 1: + await message.add_reaction("✔️") + else: + for i in range(len(movies)): + await message.add_reaction(["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣"][i]) + + await message.add_reaction("❌") + + message = await ctx.channel.fetch_message(message.id) + if (message.content != "" and + not isinstance(ctx.channel, discord.DMChannel)): + await message.clear_reactions() + + + async def add_movie(self, message, imdb_id, edit_message = True): + """Add a movie to Plex server.""" + if imdb_id is None: + self.bot.log("Did not find what the user was searching for") + if edit_message: + await message.edit( + embed = None, + content = "Try searching for the IMDB id" + ) + else: + await message.channel.send("Try searching for the IMDB id") + else: + self.bot.log("Trying to add movie "+str(imdb_id)) + api_key = self.credentials["radarr_key"] + request_url = self.radarr_url+"movie/lookup/imdb?imdbId=tt"+imdb_id + request_url += "&apiKey="+api_key + response = requests.get(request_url) + lookup_data = response.json() + post_data = {"qualityProfileId": 1, + "rootFolder_path" : self.movie_path, + "monitored" : True, + "addOptions": {"searchForMovie": True}} + for key in ["tmdbId","title","titleSlug","images","year"]: + post_data.update({key : lookup_data[key]}) + + response = requests.post( + url= self.radarr_url+"movie?apikey="+api_key, + json = post_data + ) + + if response.status_code == 201: + success_message = "{} successfully added to Plex".format( + post_data["title"] + ) + if edit_message: + await message.edit( + embed = None, + content = success_message + ) + else: + await message.channel.send(success_message) + + self.bot.log("Added "+post_data["title"]+" to Plex") + elif response.status_code == 400: + fail_text = self.long_strings["Already on Plex"].format( + post_data['title'] + ) + if edit_message: + await message.edit(embed = None, content = fail_text) + else: + await message.channel.send(fail_text) + else: + if edit_message: + await message.edit( + embed = None, + content = "Something went wrong" + ) + else: + await message.channel.send("Something went wrong") + self.bot.log(str(response.status_code)+" "+response.reason) + + async def request_show(self, ctx, show_name): + """Request a show for the Plex server.""" + await self.bot.defer(ctx) + + self.bot.log("Searching for "+show_name) + movies = imdb.IMDb().search_movie(show_name) # Replace with tvdb + shows = [] + for movie in movies: + if movie["kind"] in ["tv series","tv miniseries"]: + shows.append(movie) + if len(shows) > 5: + shows = shows[:5] + + if len(shows) == 1: + message_title = "**Is it this show?**" + else: + message_title = "**Is it any of these shows?**" + + message_text = "" + imdb_names = [] + + for i, show in enumerate(shows): + try: + message_text += f"\n{i+1}) {show['title']} ({show['year']})" + except KeyError: + try: + message_text += "\n"+str(i+1)+") "+show["title"] + except KeyError: + message_text += "Error" + imdb_names.append(show["title"]) + + self.bot.log( + f"Returning a list of {len(shows)} possible shows: {imdb_names}" + ) + + embed = discord.Embed( + title=message_title, + description=message_text, + colour=0x00FF00 + ) + + message = await ctx.send(embed=embed) + + message_data = {"message_id":message.id,"imdb_names":imdb_names} + + file_path = "gwendolyn/resources/plex/old_message"+str(ctx.channel.id) + with open(file_path,"w") as file_pointer: + json.dump(message_data, file_pointer) + + if len(shows) == 1: + await message.add_reaction("✔️") + else: + for i in range(len(shows)): + await message.add_reaction(["1️⃣","2️⃣","3️⃣","4️⃣","5️⃣"][i]) + + await message.add_reaction("❌") + + message = await ctx.channel.fetch_message(message.id) + if message.content != "": + if not isinstance(ctx.channel, discord.DMChannel): + await message.clear_reactions() + + async def add_show(self, message, imdb_name): + """Add the requested show to Plex.""" + if imdb_name is None: + self.bot.log("Did not find what the user was searching for") + await message.edit( + embed = None, + content = "Try searching for the IMDB id" + ) + else: + self.bot.log("Trying to add show "+str(imdb_name)) + api_key = self.credentials["sonarr_key"] + request_url = self.sonarr_url+"series/lookup?term=" + request_url += imdb_name.replace(" ","%20") + request_url += "&apiKey="+api_key + response = requests.get(request_url) + lookup_data = response.json()[0] + post_data = { + "ProfileId" : 1, + "rootFolder_path" : self.show_path, + "monitored" : True, + "addOptions" : {"searchForMissingEpisodes" : True} + } + for key in ["tvdbId","title","titleSlug","images","seasons"]: + post_data.update({key : lookup_data[key]}) + + + response = requests.post( + url= self.sonarr_url+"series?apikey="+api_key, + json = post_data + ) + + if response.status_code == 201: + await message.edit( + embed = None, + content = post_data["title"]+" successfully added to Plex" + ) + self.bot.log("Added a "+post_data["title"]+" to Plex") + elif response.status_code == 400: + text = self.long_strings["Already on Plex"].format( + post_data['title'] + ) + await message.edit(embed = None, content = text) + else: + await message.edit( + embed = None, + content = "Something went wrong" + ) + self.bot.log(str(response.status_code)+" "+response.reason) + + async def __generate_download_list(self, show_dm, show_movies, show_shows, + episodes): + """Generate a list of all torrents. + + *Returns* + message_text: str + A formatted list of all torrents + + all_downloaded: bool + Whether all torrents are downloaded + """ + self.bot.log("Generating torrent list") + title_width = 100 + message = [] + all_downloaded = True + + if show_dm: + message.append("") + dm_section_title = "*Torrent Downloads*" + dm_section_title_line = "-"*((title_width-len(dm_section_title))//2) + message.append( + dm_section_title_line+dm_section_title+dm_section_title_line + ) + response = requests.get(self.qbittorrent_url+"torrents/info") + torrent_list = response.json() + + if len(torrent_list) > 0: + for torrent in torrent_list: + torrent_name = torrent["name"] + if len(torrent_name) > 30: + if torrent_name[26] == " ": + torrent_name = torrent_name[:26]+"...." + else: + torrent_name = torrent_name[:27]+"..." + while len(torrent_name) < 30: + torrent_name += " " + + if torrent["size"] == 0: + download_ratio = 0 + elif torrent["amount_left"] == 0: + download_ratio = 1 + else: + download_ratio = min( + torrent["downloaded"]/torrent["size"], + 1 + ) + progress_bar = "|"+("█"*floor(download_ratio*20)) + while len(progress_bar) < 21: + progress_bar += " " + + progress_bar += "| "+str(floor(download_ratio*100))+"%" + + while len(progress_bar) < 27: + progress_bar += " " + + eta_in_seconds = torrent["eta"] + + if eta_in_seconds >= 8640000: + eta = "∞" + else: + eta = "" + if eta_in_seconds >= 86400: + eta += str(floor(eta_in_seconds/86400))+"d " + if eta_in_seconds >= 3600: + eta += str(floor((eta_in_seconds%86400)/3600))+"h " + if eta_in_seconds >= 60: + eta += str(floor((eta_in_seconds%3600)/60))+"m " + + eta += str(eta_in_seconds%60)+"s" + + torrent_info = f"{torrent_name} {progress_bar} " + torrent_info += f"(Eta: {eta})" + + if torrent["state"] == "stalledDL": + torrent_info += " (Stalled)" + + if not (download_ratio == 1 and + torrent["last_activity"] < time.time()-7200): + message.append(torrent_info) + + if download_ratio < 1 and torrent["state"] != "stalledDL": + all_downloaded = False + else: + message.append("No torrents currently downloading") + + if show_movies: + message.append("") + movies_section_title = "*Missing movies not downloading*" + movies_section_line = ( + "-"*((title_width-len(movies_section_title))//2) + ) + message.append( + movies_section_line+movies_section_title+movies_section_line + ) + movie_list = requests.get( + self.radarr_url+"movie?api_key="+self.credentials["radarr_key"] + ).json() + movie_queue = requests.get( + self.radarr_url+"queue?api_key="+self.credentials["radarr_key"] + ).json() + movie_queue_ids = [] + + for queue_item in movie_queue["records"]: + movie_queue_ids.append(queue_item["movieId"]) + + for movie in movie_list: + if (not movie["hasFile"] and + movie["id"] not in movie_queue_ids): + movie_name = movie["title"] + if len(movie_name) > 40: + if movie_name[36] == " ": + movie_name = movie_name[:36]+"...." + else: + movie_name = movie_name[:37]+"..." + + while len(movie_name) < 41: + movie_name += " " + + if movie["monitored"]: + movie_info = movie_name+"Could not find a torrent" + else: + movie_info = self.long_strings["No torrent"].format( + movie_name + ) + + message.append(movie_info) + + if show_shows: + message.append("") + show_section_title = "*Missing shows not downloading*" + show_section_line = "-"*((title_width-len(show_section_title))//2) + message.append( + show_section_line+show_section_title+show_section_line + ) + + show_list = requests.get( + self.sonarr_url+"series?api_key="+self.credentials["sonarr_key"] + ).json() + + for show in show_list: + if show["seasons"][0]["seasonNumber"] == 0: + seasons = show["seasons"][1:] + else: + seasons = show["seasons"] + if any( + ( + i["statistics"]["episodeCount"] != + i["statistics"]["totalEpisodeCount"] + ) for i in seasons): + if all( + i["statistics"]["episodeCount"] == 0 for i in seasons + ): + message.append(show["title"] + " (all episodes)") + else: + if episodes: + missing_episodes = sum( + (i["statistics"]["totalEpisodeCount"] - + i["statistics"]["episodeCount"]) + for i in seasons) + message.append( + f"{show['title']} ({missing_episodes} episodes)" + ) + + message.append("-"*title_width) + + message_text = "```"+"\n".join(message[1:])+"```" + if message_text == "``````": + message_text = self.long_strings["No torrents downloading"] + return message_text, all_downloaded + + async def downloading(self, ctx, content): + """Send message with list of all downloading torrents.""" + async def send_long_message(ctx,message_text): + if len(message_text) <= 1994: + await ctx.send("```"+message_text+"```") + else: + cut_off_index = message_text[:1994].rfind("\n") + await ctx.send("```"+message_text[:cut_off_index]+"```") + await send_long_message(ctx,message_text[cut_off_index+1:]) + + await self.bot.defer(ctx) + + # showDM, showMovies, showShows, episodes + parameters = [False, False, False, False] + show_dm_args = ["d", "dm", "downloading", "downloadmanager"] + show_movies_args = ["m", "movies"] + show_shows_args = ["s", "shows", "series"] + show_episode_args = ["e", "episodes"] + arg_list = [ + show_dm_args, show_movies_args, show_shows_args, show_episode_args + ] + input_args = [] + valid_arguments = True + + while content != "" and valid_arguments: + if content[0] == " ": + content = content[1:] + elif content[0] == "-": + if content[1] == "-": + arg_start = 2 + if " " in content: + arg_stop = content.find(" ") + else: + arg_stop = None + else: + arg_start = 1 + arg_stop = 2 + + input_args.append(content[arg_start:arg_stop]) + if arg_stop is None: + content = "" + else: + content = content[arg_stop:] + else: + valid_arguments = False + + if valid_arguments: + for arg_index, arg_aliases in enumerate(arg_list): + arg_in_input = [i in input_args for i in arg_aliases] + if any(arg_in_input): + input_args.remove(arg_aliases[arg_in_input.index(True)]) + parameters[arg_index] = True + + if len(input_args) != 0 or (not parameters[2] and parameters[3]): + valid_arguments = False + + show_anything = any(i for i in parameters) + if not (valid_arguments and show_anything): + await ctx.send(self.long_strings["Invalid parameters"]) + else: + message_text, all_downloaded = await self.__generate_download_list( + *parameters + ) + if not message_text.startswith("```"): + await ctx.send(message_text) + + elif len(message_text) > 2000: + message_text = message_text[3:-3] + await send_long_message(ctx,message_text) + + elif all_downloaded: + await ctx.send(message_text) + + else: + updates_left = 60 + message_text = self.long_strings["Update"].format( + message_text[:-3], ceil(updates_left/6) + ) + old_message = await ctx.send(message_text) + + while ((not all_downloaded) and updates_left > 0): + await asyncio.sleep(10) + updates_left -= 1 + message_text, all_downloaded = await ( + self.__generate_download_list(*parameters) + ) + message_text = self.long_strings["Update"].format( + message_text[:-3], + ceil(updates_left/6) + ) + await old_message.edit(content = message_text) + + message_text, all_downloaded = await ( + self.__generate_download_list(*parameters) + ) + + if message_text.startswith("```"): + if all_downloaded: + self.bot.log("All torrents are downloaded") + else: + message_text = self.long_strings["No updates"].format( + message_text[:-3] + ) + self.bot.log("The message updated 20 times") + + await old_message.edit(content = message_text) diff --git a/gwendolyn/funcs/star_wars_funcs/star_wars_char.py b/gwendolyn/funcs/star_wars_funcs/star_wars_char.py index fd749f8..ebfa53a 100644 --- a/gwendolyn/funcs/star_wars_funcs/star_wars_char.py +++ b/gwendolyn/funcs/star_wars_funcs/star_wars_char.py @@ -6,7 +6,7 @@ class StarWarsChar(): def __init__(self, bot): self.bot = bot - def getCharName(self, user : str): + def getChar_name(self, user : str): self.bot.log("Getting name for "+self.bot.database_funcs.get_name(user)+"'s character") userCharacter = self.bot.database["starwars characters"].find_one({"_id":user}) @@ -239,7 +239,7 @@ class StarWarsChar(): return name, text1+text2+"\n\n"+text3+divider+text4+"\n"+divider+text5+text6+text7+text8 - def charData(self,user : str,cmd : str): + def char_data(self,user : str,cmd : str): userCharacter = self.bot.database["starwars characters"].find_one({"_id":user}) key = string.capwords(cmd.split(" ")[0]) @@ -508,7 +508,7 @@ class StarWarsChar(): self.bot.database["starwars characters"].delete_one({"_id":user}) await ctx.send("Character for " + self.bot.database_funcs.get_name(user) + " deleted") else: - await ctx.send(self.replaceWithSpaces(str(self.charData(user,cmd)))) + await ctx.send(self.replaceWithSpaces(str(self.char_data(user,cmd)))) if returnEmbed: em = discord.Embed(title = title, description = text, colour=0xDEADBF) diff --git a/gwendolyn/funcs/star_wars_funcs/star_wars_destiny.py b/gwendolyn/funcs/star_wars_funcs/star_wars_destiny.py index acb2cc6..1f5a7c2 100644 --- a/gwendolyn/funcs/star_wars_funcs/star_wars_destiny.py +++ b/gwendolyn/funcs/star_wars_funcs/star_wars_destiny.py @@ -52,21 +52,21 @@ class StarWarsDestiny(): if cmd == "": self.bot.log("Retrieving destiny pool info") with open("gwendolyn/resources/star_wars/destinyPoints.txt","rt") as f: - sendMessage = self.bot.star_wars.roll.resultToEmoji(f.read()) + send_message = self.bot.star_wars.roll.resultToEmoji(f.read()) else: commands = cmd.upper().split(" ") if commands[0] == "N": if len(commands) > 1: - sendMessage = self.destinyNew(int(commands[1])) + send_message = self.destinyNew(int(commands[1])) else: - sendMessage = "You need to give an amount of players (error code 921)" + send_message = "You need to give an amount of players (error code 921)" elif commands[0] == "U": - sendMessage = self.destinyUse(user) + send_message = self.destinyUse(user) else: - sendMessage = "I didn't quite understand that (error code 922)" + send_message = "I didn't quite understand that (error code 922)" - messageList = sendMessage.split("\n") - await ctx.send(messageList[0]) - if len(messageList) > 1: - for messageItem in messageList[1:]: + message_list = send_message.split("\n") + await ctx.send(message_list[0]) + if len(message_list) > 1: + for messageItem in message_list[1:]: await ctx.channel.send(messageItem) diff --git a/gwendolyn/funcs/star_wars_funcs/star_wars_roll.py b/gwendolyn/funcs/star_wars_funcs/star_wars_roll.py index bd17710..c923a5c 100644 --- a/gwendolyn/funcs/star_wars_funcs/star_wars_roll.py +++ b/gwendolyn/funcs/star_wars_funcs/star_wars_roll.py @@ -4,7 +4,7 @@ import string import json with open("gwendolyn/resources/star_wars/starwarsskills.json", "r") as f: - skillData = json.load(f) + skill_data = json.load(f) class StarWarsRoll(): def __init__(self, bot): @@ -288,12 +288,12 @@ class StarWarsRoll(): characteristic = random.choice(["brawn"] * 3 + ["agility"] * 3 + ["intellect", "cunning", "presence"]) results = "**Gruesome Injury**: The target's "+characteristic+" is permanently one lower, "+dd+dd+dd+dd - sendMessage = "Roll: "+str(roll)+"\nInjury:\n"+results + send_message = "Roll: "+str(roll)+"\nInjury:\n"+results - messageList = sendMessage.split("\n") - await ctx.send(messageList[0]) - if len(messageList) > 1: - for messageItem in messageList[1:]: + message_list = send_message.split("\n") + await ctx.send(message_list[0]) + if len(message_list) > 1: + for messageItem in message_list[1:]: await ctx.channel.send(messageItem) # Parses the command into something the other functions understand @@ -312,19 +312,19 @@ class StarWarsRoll(): rollParameters = [0,0,0,0,0,0,0] if string.capwords(commands[0]) == "Obligations": - sendMessage = self.obligationRoll() + send_message = self.obligationRoll() - elif string.capwords(commands[0]) in skillData: + elif string.capwords(commands[0]) in skill_data: self.bot.log("Oh look! This guy has skills!") if self.bot.star_wars.character.userHasChar(user): self.bot.log("They have a character. That much we know") - skillLevel = self.bot.star_wars.character.charData(user,"Skills " + string.capwords(commands[0])) + skillLevel = self.bot.star_wars.character.char_data(user,"Skills " + string.capwords(commands[0])) if string.capwords(commands[0]) == "Lightsaber": self.bot.log("The skill is lightsaber") - charLevel = self.bot.star_wars.character.charData(user,"Characteristics " + self.bot.star_wars.character.lightsaberChar(user)) + charLevel = self.bot.star_wars.character.char_data(user,"Characteristics " + self.bot.star_wars.character.lightsaberChar(user)) else: - charLevel = self.bot.star_wars.character.charData(user,"Characteristics " + skillData[string.capwords(commands[0])]) + charLevel = self.bot.star_wars.character.char_data(user,"Characteristics " + skill_data[string.capwords(commands[0])]) abilityDice = abs(charLevel-skillLevel) proficiencyDice = min(skillLevel,charLevel) @@ -334,14 +334,14 @@ class StarWarsRoll(): validCommand = True else: self.bot.log("Okay, no they don't i guess") - sendMessage = "You don't have a user. You can make one with /starwarscharacter" + send_message = "You don't have a user. You can make one with /starwarscharacter" elif string.capwords(commands[0]) in ["Ranged","Piloting"]: self.bot.log("They fucked up writing the name of a ranged or piloting skill") if string.capwords(commands[0]) == "Ranged": - sendMessage = "Did you mean \"Ranged - Heavy\" or \"Ranged - Light\" (error code 913)" + send_message = "Did you mean \"Ranged - Heavy\" or \"Ranged - Light\" (error code 913)" else: - sendMessage = "Did you mean \"Piloting - Planetary\" or \"Piloting - Space\" (error code 913)" + send_message = "Did you mean \"Piloting - Planetary\" or \"Piloting - Space\" (error code 913)" else: validCommand = True @@ -372,19 +372,19 @@ class StarWarsRoll(): simplified = self.simplify(rollResults) - name = self.bot.star_wars.character.getCharName(user) + name = self.bot.star_wars.character.getChar_name(user) self.bot.log("Returns results and simplified results") if simplified == "": - sendMessage = name + " rolls: " + "\n" + self.diceResultToEmoji(diceResults) + "\nEverything cancels out!" + send_message = name + " rolls: " + "\n" + self.diceResultToEmoji(diceResults) + "\nEverything cancels out!" else: - sendMessage = name + " rolls: " + "\n" + self.diceResultToEmoji(diceResults) + "\n" + self.resultToEmoji(simplified) + send_message = name + " rolls: " + "\n" + self.diceResultToEmoji(diceResults) + "\n" + self.resultToEmoji(simplified) - messageList = sendMessage.split("\n") - await ctx.send(messageList[0]) - if len(messageList) > 1: - for messageItem in messageList[1:]: + message_list = send_message.split("\n") + await ctx.send(message_list[0]) + if len(message_list) > 1: + for messageItem in message_list[1:]: if messageItem == "": self.bot.log("Tried to send empty message") else: diff --git a/gwendolyn/resources/help/help-downloading.txt b/gwendolyn/resources/help/help-downloading.txt index 879ce89..b62f3dd 100644 --- a/gwendolyn/resources/help/help-downloading.txt +++ b/gwendolyn/resources/help/help-downloading.txt @@ -1,4 +1,4 @@ -Viser dig de film og serier der er "requested" men ikke endnu på Bedre Netflix. Kommandoen kan tage imod op til 4 parametre: +Viser dig de film og serier der er "requested" men ikke endnu på Plex. Kommandoen kan tage imod op til 4 parametre: `-d`, `--downloading`, `--dm`, `--downloadManager` - Viser de torrents der er _ved_ at downloade. Hvis ingen parametre er givet, bliver det her parameter givet automatisk som det eneste. diff --git a/gwendolyn/resources/help/help-movie.txt b/gwendolyn/resources/help/help-movie.txt index 8fa0eed..6c072de 100644 --- a/gwendolyn/resources/help/help-movie.txt +++ b/gwendolyn/resources/help/help-movie.txt @@ -1 +1 @@ -Giver titlen på en tilfældig film fra Bedre Netflix. \ No newline at end of file +Giver titlen på en tilfældig film fra Plex. \ No newline at end of file diff --git a/gwendolyn/resources/help/help.txt b/gwendolyn/resources/help/help.txt index 8db0a65..74da75f 100644 --- a/gwendolyn/resources/help/help.txt +++ b/gwendolyn/resources/help/help.txt @@ -3,7 +3,7 @@ `/spell` - Slå en besværgelse op. `/monster` - Slå et monster op. `/image` - Finder et tilfældigt billede fra internettet. -`/movie` - Giver titlen på en tilfældig film fra Bedre Netflix +`/movie` - Giver titlen på en tilfældig film fra Plex `/name` - Genererer et tilfældigt navn. `/tavern` - Genererer en tilfældig tavern. `/give` - Lader dig give GwendoBucks til andre. @@ -17,8 +17,8 @@ `/hex` - Lader dig spille et spil Hex. `/hangman` - Lader dig spille et spil hangman. `/wolf` - Lader dig slå ting op på Wolfram Alpha. -`/add_movie` - Lader dig tilføje film til Bedre Netflix. -`/add_show` - Lader dig tilføje tv shows til Bedre Netflix. +`/add_movie` - Lader dig tilføje film til Plex. +`/add_show` - Lader dig tilføje tv shows til Plex. `/downloading` - Viser dig hvor langt de torrents der er ved at downloade er kommet. `/thank` - Lader dig takke Gwendolyn. Du kan få ekstra information om kommandoerne med "/help [kommando]". diff --git a/gwendolyn/resources/longStrings.json b/gwendolyn/resources/longStrings.json deleted file mode 100644 index b5d9c11..0000000 --- a/gwendolyn/resources/longStrings.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "missing parameters" : "Missing command parameters. Try using `!help [command]` to find out how to use the command.", - "Can't log in": "Could not log in. Remember to write your bot token in the credentials.txt file", - "Blackjack all players standing": "All players are standing. The dealer now shows his cards and draws.", - "Blackjack first round": ". You can also double down with \"/blackjack double\" or split with \"/blackjack split\"", - "Blackjack commands": "You have 2 minutes to either hit or stand with \"/blackjack hit\" or \"/blackjack stand\"{}. It's assumed you're standing if you don't make a choice.", - "Blackjack double": "Adding another {} GwendoBucks to {}'s bet and drawing another card.", - "Blackjack different cards": "You can only split if your cards have the same value", - "Blackjack split": "Splitting {}'s hand into 2. Adding their original bet to the second hand. You can use \"/blackjack hit/stand/double 1\" and \"/blackjack hit/stand/double 2\" to play the different hands.", - "Blackjack started": "Blackjack game started. Use \"/blackjack bet [amount]\" to enter the game within the next 30 seconds.", - "Blackjack going on": "There's already a blackjack game going on. Try again in a few minutes.", - "Stock value": "The current {} stock is valued at **{}** GwendoBucks", - "Stock parameters": "You must give both a stock name and an amount of GwendoBucks you wish to spend.", - "Trivia going on": "There's already a trivia question going on. Try again in like, a minute", - "Trivia time up": "Time's up! The answer was \"*{}) {}*\". Anyone who answered that has gotten 1 GwendoBuck", - "Connect 4 going on": "There's already a connect 4 game going on in this channel", - "Connect 4 placed": "{} placed a piece in column {}. It's now {}'s turn", - "Hangman going on": "There's already a Hangman game going on in the channel", - "Hangman lost game": " You've guessed wrong six times and have lost the game.", - "Hangman guessed word": " You've guessed the word! Congratulations! Adding 15 GwendoBucks to your account" -} \ No newline at end of file diff --git a/gwendolyn/resources/long_strings.json b/gwendolyn/resources/long_strings.json index b5d9c11..c5964a3 100644 --- a/gwendolyn/resources/long_strings.json +++ b/gwendolyn/resources/long_strings.json @@ -17,5 +17,11 @@ "Connect 4 placed": "{} placed a piece in column {}. It's now {}'s turn", "Hangman going on": "There's already a Hangman game going on in the channel", "Hangman lost game": " You've guessed wrong six times and have lost the game.", - "Hangman guessed word": " You've guessed the word! Congratulations! Adding 15 GwendoBucks to your account" + "Hangman guessed word": " You've guessed the word! Congratulations! Adding 15 GwendoBucks to your account", + "Already on Plex": "{} is either already on Plex, downloading, or not available", + "No torrent": "{}No torrent exists. Likely because the movie is not yet released on DVD", + "No torrents downloading": "There are no torrents downloading right. If the torrent you're looking for was added more than 24 hours ago, it might already be on Plex.", + "Update": "{}\nThis message will update every 10 seconds for {} more minutes\n```", + "No updates": "{}\nThis message will not update anymore\n```", + "Invalid parameters": "Invalid or repeated parameters. Use '/help downloading' to see valid parameters." } \ No newline at end of file diff --git a/gwendolyn/resources/slash_parameters.json b/gwendolyn/resources/slash_parameters.json index 119dd88..275b2e9 100644 --- a/gwendolyn/resources/slash_parameters.json +++ b/gwendolyn/resources/slash_parameters.json @@ -1,7 +1,7 @@ { "add_movie" : { "name" : "add_movie", - "description" : "Request a movie for Bedre Netflix", + "description" : "Request a movie for Plex", "options" : [ { "name" : "movie", @@ -13,7 +13,7 @@ }, "add_show" : { "name" : "add_show", - "description" : "Request a show for Bedre Netflix", + "description" : "Request a show for Plex", "options" : [ { "name" : "show", @@ -147,7 +147,7 @@ }, "downloading" : { "name" : "downloading", - "description" : "See current downloads for Bedre Netflix", + "description" : "See current downloads for Plex", "options" : [ { "name" : "parameters", @@ -162,7 +162,7 @@ "description" : "Set the 'playing' text for Gwendolyn", "options" : [ { - "name" : "gameText", + "name" : "game_text", "description" : "The game to set the 'playing' text to", "type" : 3, "required" : "true" diff --git a/gwendolyn/resources/starting_files.json b/gwendolyn/resources/starting_files.json index b22855e..78affaa 100644 --- a/gwendolyn/resources/starting_files.json +++ b/gwendolyn/resources/starting_files.json @@ -65,10 +65,10 @@ "folder" : [ "gwendolyn/resources/lookup", "gwendolyn/resources/games/blackjack_tables", - "gwendolyn/resources/games/connect4Boards", + "gwendolyn/resources/games/connect_four_boards", "gwendolyn/resources/games/hex_boards", "gwendolyn/resources/games/hangman_boards", - "gwendolyn/resources/bedre_netflix", + "gwendolyn/resources/plex", "gwendolyn/resources/games/old_images" ] } \ No newline at end of file diff --git a/gwendolyn/utils/event_handlers.py b/gwendolyn/utils/event_handlers.py index 80e73bb..ca8093b 100644 --- a/gwendolyn/utils/event_handlers.py +++ b/gwendolyn/utils/event_handlers.py @@ -72,7 +72,7 @@ class EventHandler(): channel = message.channel reacted_message = f"{user.display_name} reacted to a message" self.bot.log(reacted_message, str(channel.id)) - plex_data = tests.bedre_netflix_reaction_test(message) + plex_data = tests.plex_reaction_test(message) # plex_data is a list containing 3 elements: whether it was # the add_show/add_movie command message the reaction was to # (bool), whether it's a movie (bool) (if false, it's a @@ -84,10 +84,10 @@ class EventHandler(): 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.placePiece(*params) + await self.bot.games.connect_four.place_piece(*params) if plex_data[0]: - plex_functions = self.bot.other.bedre_netflix + plex_functions = self.bot.other.plex if plex_data[1]: movie_pick = emoji_to_command(reaction.emoji) if movie_pick == "none": diff --git a/gwendolyn/utils/helper_classes.py b/gwendolyn/utils/helper_classes.py index cf950ed..8f9f535 100644 --- a/gwendolyn/utils/helper_classes.py +++ b/gwendolyn/utils/helper_classes.py @@ -27,7 +27,7 @@ class DatabaseFuncs(): user: discord.User) -> bool hangman_reaction_test(message: discord.Message, user: discord.User) -> bool - bedre_netflix_reaction_test(message: discord.Message, + plex_reaction_test(message: discord.Message, user: discord.User) -> bool, bool, list imdb_commands() @@ -206,7 +206,7 @@ class DatabaseFuncs(): return game_message - def bedre_netflix_reaction_test(self, message: discord.Message): + def plex_reaction_test(self, message: discord.Message): """ Test if the given message is the response to a plex request. @@ -227,7 +227,7 @@ class DatabaseFuncs(): Gwendolyn presented after the request. """ channel = message.channel - old_messages_path = "gwendolyn/resources/bedre_netflix/" + old_messages_path = "gwendolyn/resources/plex/" file_path = old_messages_path + f"old_message{str(channel.id)}" if os.path.isfile(file_path): with open(file_path, "r") as file_pointer: diff --git a/gwendolyn/utils/util_functions.py b/gwendolyn/utils/util_functions.py index cd1d185..d6f62b3 100644 --- a/gwendolyn/utils/util_functions.py +++ b/gwendolyn/utils/util_functions.py @@ -16,7 +16,7 @@ Contains utility functions used by parts of the bot. new_string: str) -> str emoji_to_command(emoji: str) -> str """ -import json # Used by longString(), get_params() and make_files() +import json # Used by long_strings(), get_params() and make_files() import logging # Used for logging import os # Used by make_files() to check if files exist import sys # Used to specify printing for logging diff --git a/requirements.txt b/requirements.txt index ce8b57f..a46b098 100644 --- a/requirements.txt +++ b/requirements.txt @@ -21,7 +21,7 @@ idna==2.10 IMDbPY==2020.9.25 isort==5.8.0 jaraco.context==4.0.0 -lark-parser==0.11.2 +lark-parser==0.9.0 lazy-object-proxy==1.6.0 lxml==4.6.3 mccabe==0.6.1