diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b7368ca --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.formatting.provider": "black" +} diff --git a/Objects/PokeObj.py b/Objects/PokeObj.py index a826839..0fbfb48 100644 --- a/Objects/PokeObj.py +++ b/Objects/PokeObj.py @@ -3,17 +3,18 @@ import random from datetime import datetime + class PokeObj: def __init__(self, pokeObj, psn): - #print(pokeObj.keys()) - self.name = pokeObj['name'] + # print(pokeObj.keys()) + self.name = pokeObj["name"] self.nickname = None - self.index = pokeObj['id'] - self.type = [type['type']['name'] for type in pokeObj['types']] - if len(pokeObj['moves']) < 4: - self.moves = [item['move'] for item in random.sample(pokeObj['moves'], len(pokeObj['moves']))] + self.index = pokeObj["id"] + self.type = [type["type"]["name"] for type in pokeObj["types"]] + if len(pokeObj["moves"]) < 4: + self.moves = [item["move"] for item in random.sample(pokeObj["moves"], len(pokeObj["moves"]))] else: - self.moves = [item['move'] for item in random.sample(pokeObj['moves'], 4)] + self.moves = [item["move"] for item in random.sample(pokeObj["moves"], 4)] self.lvl = 5 self.exp = 0 @@ -21,7 +22,7 @@ def __init__(self, pokeObj, psn): self.caughtInfo = (datetime.now().strftime("%a, %b %d, %Y - %I:%M %p"), psn.display_name, psn.id) def __repr__(self): - return "{}#{}".format(self.name,self.index) + return "{}#{}".format(self.name, self.index) def __eq__(self, other): if self.nickname == None or other.nickname == None: @@ -43,7 +44,7 @@ def name(self, PokeName): @property def nickname(self): return self._nickname - + @nickname.setter def nickname(self, new_name): self._nickname = new_name @@ -51,7 +52,7 @@ def nickname(self, new_name): @property def index(self): return self._index - + @index.setter def index(self, index): self._index = index @@ -63,5 +64,3 @@ def moves(self): @moves.setter def moves(self, moves): self._moves = moves - - diff --git a/Objects/user.py b/Objects/user.py index fd07332..5063933 100644 --- a/Objects/user.py +++ b/Objects/user.py @@ -1,22 +1,23 @@ from config import * from Objects.PokeObj import * + class User: def __init__(self, user, poke): self.user = user.id - self.pokeList = {poke['name'] : [PokeObj(poke, user)]} + self.pokeList = {poke["name"]: [PokeObj(poke, user)]} self.items = [] def __repr__(self): prnt_str = "__{}'s Pokemon__: include **{}/802** Pokemon:\n".format(self.user.name, len(self.pokeList.keys())) for PokeName in self.pokeList.keys(): - prnt_str += "{} *x{}*\n".format(PokeName.capitalize(),len(self.pokeList[PokeName])) + prnt_str += "{} *x{}*\n".format(PokeName.capitalize(), len(self.pokeList[PokeName])) return prnt_str @property def items(self): return self._items - + @items.setter def items(self, value): print(value) @@ -27,13 +28,13 @@ def items(self, value): def getPokeList(self): return self._pokeList.keys() - + def addPokeList(self, value, user): - #print(value) - if value['name'] in self.pokeList.keys(): - self.pokeList[value['name']].append(PokeObj(value, user)) + # print(value) + if value["name"] in self.pokeList.keys(): + self.pokeList[value["name"]].append(PokeObj(value, user)) else: - self.pokeList[value['name']] = [PokeObj(value, user)] + self.pokeList[value["name"]] = [PokeObj(value, user)] def removePokemon(self, name): if name in self.pokeList.keys(): @@ -59,7 +60,7 @@ def embed_list(self, user): embed = discord.Embed(type="rich", title=str_title, color=0xEEE8AA) str_desc = "" for PokeName in self.pokeList.keys(): - str_desc += "{} *x{}*\n".format(PokeName.capitalize(),len(self.pokeList[PokeName])) - embed.description = str_desc[:2048 - len(str_title + str_footer)] + str_desc += "{} *x{}*\n".format(PokeName.capitalize(), len(self.pokeList[PokeName])) + embed.description = str_desc[: 2048 - len(str_title + str_footer)] embed.set_footer(text=str_footer) return embed diff --git a/PokeCord.py b/PokeCord.py index 9fea193..8b047ed 100644 --- a/PokeCord.py +++ b/PokeCord.py @@ -1,7 +1,8 @@ from discord.ext import commands import config as config from Objects.user import * -#from pil import method_sum_check + +# from pil import method_sum_check import random from datetime import time, datetime, timedelta @@ -12,51 +13,52 @@ from PIL import Image, ImageDraw from io import BytesIO -#Trainer -> [Items, box, ] +# Trainer -> [Items, box, ] + def check_is_pm(ctx): return ctx.message.channel.type == discord.ChannelType.private - #return ctx.message.channel.type == discord.ChannelType.text + # return ctx.message.channel.type == discord.ChannelType.text + class PokeCord(commands.Cog): def __init__(self, bot): self.bot = bot self.channel_bind = {} self.time_to_spawn = None - self.wild_pokemon = None #Spawned Pokemon + self.wild_pokemon = None # Spawned Pokemon self.imgur_results = None self.spawn_msg = None self.trainer_list = {} def __getstate__(self): - return ({ - 'channel_bind' : self.channel_bind, - 'time' : self.time_to_spawn, - 'store' : self.wild_pokemon, - 'imgur' : self.imgur_results, - 'msg' : self.spawn_msg, - 'users' : self.trainer_list - }) - pass + return { + "channel_bind": self.channel_bind, + "time": self.time_to_spawn, + "store": self.wild_pokemon, + "imgur": self.imgur_results, + "msg": self.spawn_msg, + "users": self.trainer_list, + } def __setstate__(self, dictState): - self.channel_bind = dictState['channel_bind'] - self.time_to_spawn = dictState['time'] - self.wild_pokemon = dictState['store'] - if 'imgr' in dictState: - self.imgur_results = dictState['imgr'] + self.channel_bind = dictState["channel_bind"] + self.time_to_spawn = dictState["time"] + self.wild_pokemon = dictState["store"] + if "imgr" in dictState: + self.imgur_results = dictState["imgr"] else: - self.imgur_results = dictState['imgur'] - self.spawn_msg = dictState['msg'] - self.trainer_list = dictState['users'] - # if self.time_to_spawn != None: + self.imgur_results = dictState["imgur"] + self.spawn_msg = dictState["msg"] + self.trainer_list = dictState["users"] + # if self.time_to_spawn != None: # asyncio.create_task(self.timed_spawn()) @property def time_to_spawn(self): return self._time_to_spawn - + @time_to_spawn.setter def time_to_spawn(self, value): self._time_to_spawn = value @@ -74,37 +76,37 @@ def setToSpawn(self): else: return True - @property + @property def appeared(self): - #print("A pokemon appeared: {}".format((self.wild_pokemon != None))) + # print("A pokemon appeared: {}".format((self.wild_pokemon != None))) return self.wild_pokemon != None -############################################################################## -############################################################################## -############################################################################## - - #If last command was restart - #i = 0 - ##async for message in client.logs_from(client.get_channel(CHANNEL_IDs), limit=2): - ## if (datetime.utcnow() - message.timestamp).total_seconds() <= 30: - ## if message.content == "Restarting..." and i == 0: - ## await client.edit_message(message, "Restarted!") - ## if message.content == (BOT_PREFIX + "restart") and i == 1: - ## await client.add_reaction(message, '👌') - ## i = i + 1 - + ############################################################################## + ############################################################################## + ############################################################################## + + # If last command was restart + # i = 0 + ##async for message in client.logs_from(client.get_channel(CHANNEL_IDs), limit=2): + ## if (datetime.utcnow() - message.timestamp).total_seconds() <= 30: + ## if message.content == "Restarting..." and i == 0: + ## await client.edit_message(message, "Restarted!") + ## if message.content == (BOT_PREFIX + "restart") and i == 1: + ## await client.add_reaction(message, '👌') + ## i = i + 1 + def update_pickle(self): - with open("IO Files/PokeCord.pickle", 'wb') as file: + with open("IO Files/PokeCord.pickle", "wb") as file: try: pickle.dump(self, file) pass except Exception as Err: - print(Err) + print(Err) @commands.Cog.listener() async def on_command_completion(self, context): self.update_pickle() - #print(dir(context)) #For checking is a command that changes the bot state + # print(dir(context)) #For checking is a command that changes the bot state #!! Someone get the last message or something @commands.Cog.listener() @@ -113,13 +115,13 @@ async def on_ready(self): log.info(f"Access to - {guild.name}") if guild.id not in self.channel_bind: for channel in guild.text_channels: - log.info(f"{channel.name} - {guild.me.permissions_in(channel)}") # send_messages + log.info(f"{channel.name} - {guild.me.permissions_in(channel)}") # send_messages if guild.me.permissions_in(channel).send_messages: self.channel_bind[guild.id] = channel.id break log.info(f"{(guild.me.permissions_in(channel).send_messages)}") - #self.channel_bind[guild.id] = channels[0] - #Check if a pokemon is queued to be spawned + # self.channel_bind[guild.id] = channels[0] + # Check if a pokemon is queued to be spawned if self.appeared: game = discord.Game("Who's That Pokemon?") await self.bot.change_presence(status=discord.Status.online, activity=game) @@ -128,9 +130,10 @@ async def on_ready(self): await asyncio.sleep(self.getSeconds()) await self._spawn() else: - self.time_to_spawn = datetime.now() + timedelta(minutes=random.randint(1,10)) + self.time_to_spawn = datetime.now() + timedelta(minutes=random.randint(1, 10)) await asyncio.sleep(self.getSeconds()) await self._spawn() + # #If time to spawn in the future set in motion # if self.time_to_spawn > datetime.now(): # await asyncio.sleep(self.getSeconds()) @@ -138,26 +141,22 @@ async def on_ready(self): @commands.Cog.listener() async def on_message(self, message): - #Bot or wrong channel do nothing - if ( - message.author == self.bot.user or - message.content[1:].startswith("spawn") or - message.channel.type != discord.ChannelType.text - ): #or message.channel == CHANNEL_IDs: + # Bot or wrong channel do nothing + if message.author == self.bot.user or message.content[1:].startswith("spawn") or message.channel.type != discord.ChannelType.text: # or message.channel == CHANNEL_IDs: return - #print(f"[{datetime.now().strftime('%b-%d %H:%M')}] On Message ({message.channel.type}) {message.content}") - #Pokemon is going to be found + # print(f"[{datetime.now().strftime('%b-%d %H:%M')}] On Message ({message.channel.type}) {message.content}") + # Pokemon is going to be found if self.setToSpawn(): pass else: - #Pokemon is ready for capture + # Pokemon is ready for capture if self.appeared: if not await self.check_capture(message): return if not self.setToSpawn(): - self.time_to_spawn = datetime.now() + timedelta(minutes=random.randint(1,10)) - await message.channel.send('Pokemon set to spawn!') + self.time_to_spawn = datetime.now() + timedelta(minutes=random.randint(1, 10)) + await message.channel.send("Pokemon set to spawn!") await asyncio.sleep(self.getSeconds()) await self._spawn() self.update_pickle() @@ -170,18 +169,19 @@ async def on_message(self, message): # await asyncio.sleep(self.getSeconds()) # await self.cmd_spawn('spawn', message) - #------------------------------------------------- + # ------------------------------------------------- # Commands - #------------------------------------------------- + # ------------------------------------------------- @commands.is_owner() - @commands.command(name='bind', - usage='[channel_id]', + @commands.command( + name="bind", + usage="[channel_id]", help="""Changes the channel the bot listens to. If no argument is given binds to current channel. optional [channel_id] - will link the channel given, if permissible. - """ - ) - async def cmd_bind(self, ctx, channel:discord.TextChannel = None): + """, + ) + async def cmd_bind(self, ctx, channel: discord.TextChannel = None): if channel == None and ctx.message.channel.type == discord.ChannelType.private: await ctx.channel.send("Unable to bind to *direct messages*. Give *channel id* or give command in channel.") return @@ -192,23 +192,23 @@ async def cmd_bind(self, ctx, channel:discord.TextChannel = None): await ctx.channel.send(f"Unable to send messages in channel ({channel.name}) given") self.channel_bind[channel.guild.id] = channel.id - @commands.command(name='info') - async def cmd_info(self, context, emoji = None): + @commands.command(name="info") + async def cmd_info(self, context, emoji=None): await context.send("\u2716") - foundEmoji = discord.utils.find(lambda m: m.name == 'heavy_multiplication_x', self.bot.emojis) + foundEmoji = discord.utils.find(lambda m: m.name == "heavy_multiplication_x", self.bot.emojis) if emoji == None: print("Info") else: print(emoji) @commands.is_owner() - @commands.command(name='edit_embed') + @commands.command(name="edit_embed") async def cmd_edit_embed(self, cmd, message, content=None): msg_list = [] find_message = await message.channel.send(content) - msg_list.append(await message.channel.send('What in the embed do you want to change?')) + msg_list.append(await message.channel.send("What in the embed do you want to change?")) msg_list.append(await client.wait_for_message(author=message.author)) - msg_list.append(await message.channel.send('What would you like it to change to?')) + msg_list.append(await message.channel.send("What would you like it to change to?")) msg_list.append(await client.wait_for_message(author=message.author)) for msg in msg_list: print("{}{}{}".format(bcolors.WARNING, msg.content, bcolors.ENDC)) @@ -229,16 +229,16 @@ async def cmd_edit_embed(self, cmd, message, content=None): elif msg_list[1].content.strip(" ")[1].lower() == "author": new_embed.set_author(name=msg_list[3].content) else: - await message.channel.send('The requested field is not availiable.') + await message.channel.send("The requested field is not availiable.") await client.edit_message(find_message, embed=new_embed) client.delete_messages(msg_list) - @commands.command(name='spawn') + @commands.command(name="spawn") @commands.is_owner() async def cmd_spawn(self, context, message=None): await self._spawn(context.channel, message) - @commands.command(name='missing') + @commands.command(name="missing") async def cmd_missing(self, context, message=None): if self.spawn_msg != None: new_embed = discord.Embed() @@ -247,15 +247,11 @@ async def cmd_missing(self, context, message=None): new_embed.set_thumbnail(url=imgur_result) await client.edit_message(self.spawn_msg, embed=new_embed) - @commands.command( - name='inventory', - aliases=['backpack'], - help="Displays pokemon and items" - ) - async def cmd_inventory(self, context, member:discord.Member = None): + @commands.command(name="inventory", aliases=["backpack"], help="Displays pokemon and items") + async def cmd_inventory(self, context, member: discord.Member = None): if member is None: if context.author.id in self.trainer_list.keys(): - #print(self.trainer_list[context.author.id]) + # print(self.trainer_list[context.author.id]) await context.channel.send(embed=self.trainer_list[context.author.id].embed_list(context.author)) else: msg = "{} you have caught no Pokemon".format(context.author.name) @@ -267,7 +263,7 @@ async def cmd_inventory(self, context, member:discord.Member = None): else: await context.send(f"{member.name} has caught no Pokemon") - @commands.command(name='bad_gif') + @commands.command(name="bad_gif") @commands.is_owner() async def cmd_bad_gif(self, context, message=None): if message == None: @@ -275,8 +271,8 @@ async def cmd_bad_gif(self, context, message=None): msg = "No pokemon is spawned" await context.channel.send(msg) return - file = open("IO Files/badGIF.txt", 'a+') - file.write("{}#{}\n".format(self.wild_pokemon['name'], self.wild_pokemon['id'])) + file = open("IO Files/badGIF.txt", "a+") + file.write("{}#{}\n".format(self.wild_pokemon["name"], self.wild_pokemon["id"])) file.close() msg = "Pokemon has been added to file" await context.channel.send(msg) @@ -284,29 +280,26 @@ async def cmd_bad_gif(self, context, message=None): self.sort_gif_file() @commands.command( - name='release', - usage=' [pokemon index=0]', + name="release", + usage=" [pokemon index=0]", help="""Removes a pokemon from your inventory. - name of the pokemon you want to release optional [pokemon index] - caught multiple of the same pokemon and want to release a particular one - """ - ) - async def cmd_release(self, ctx, pokemonName : str, pokemon_index:int = 0): + """, + ) + async def cmd_release(self, ctx, pokemonName: str, pokemon_index: int = 0): if ctx.author.id in self.trainer_list: trainer = self.trainer_list[ctx.author.id] if trainer.hasPokemon(pokemonName): trainer.removePokemon(pokemonName) - await ctx.channel.send(f"*{ctx.author.mention}*, {pokemonName} has been released.") + await ctx.channel.send(f"*{ctx.author.mention}*, {pokemonName} has been released.") else: - await ctx.channel.send(f"*{ctx.author.display_name}*, haven't caught any {pokemonName}.") + await ctx.channel.send(f"*{ctx.author.display_name}*, haven't caught any {pokemonName}.") else: await ctx.channel.send(f"*{ctx.author.display_name}*, haven't caught any pokemon!") - @commands.command( - name='trade', - help="Trade a pokemon between two users" - ) - async def cmd_trade(self, ctx, member:discord.Member, give_pokemon:str, get_pokemon:str): + @commands.command(name="trade", help="Trade a pokemon between two users") + async def cmd_trade(self, ctx, member: discord.Member, give_pokemon: str, get_pokemon: str): if member.id in self.trainer_list and ctx.author.id in self.trainer_list: trainer_give = self.trainer_list[ctx.author.id] trainer_get = self.trainer_list[member.id] @@ -318,34 +311,30 @@ async def cmd_trade(self, ctx, member:discord.Member, give_pokemon:str, get_poke return else: sent_message = await ctx.send(f"*{member.display_name}*, *{ctx.author.display_name}* wants to trade {give_pokemon} for {get_pokemon}") - await sent_message.add_reaction('\u2716') # X - await sent_message.add_reaction('\u2714') # ✔ + await sent_message.add_reaction("\u2716") # X + await sent_message.add_reaction("\u2714") # ✔ def check(reaction, user): - #print(f"Reaction = {dir(reaction.emoji)} - {reaction.emoji}") - return ( - user == member and - reaction.message.id == sent_message.id and - (reaction.emoji == '\u2716' or reaction.emoji == '\u2714') - ) + # print(f"Reaction = {dir(reaction.emoji)} - {reaction.emoji}") + return user == member and reaction.message.id == sent_message.id and (reaction.emoji == "\u2716" or reaction.emoji == "\u2714") try: - reaction, user = await self.bot.wait_for('reaction_add', timeout=60.0, check=check) + reaction, user = await self.bot.wait_for("reaction_add", timeout=60.0, check=check) except asyncio.TimeoutError: await ctx.send("No Reponse. Canceling trade.") await sent_message.delete() pass else: - if reaction.emoji == '\u2714': + if reaction.emoji == "\u2714": await ctx.send("Trade Accepted!") else: await ctx.send("Trade Rejected") else: await ctx.send("One of you haven't captured pokemon.") - #------------------------------------------------- + # ------------------------------------------------- # Other Functions - #------------------------------------------------- + # ------------------------------------------------- async def timed_spawn(self, ctx): await asyncio.sleep(self.getSeconds()) @@ -358,29 +347,29 @@ async def _spawn(self, channel=None, message=None): return self.time_to_spawn = None - await channel.send('A Wild Pokémon appears!') + await channel.send("A Wild Pokémon appears!") if message != None: if message.isdigit(): pokeNum = message url = f"http://pokeapi.co/api/v2/pokemon/{message}/" else: - #print error + # print error msg = "When using spawn must be number if input given" await channel.send(msg) return else: - pokeNum = str(random.randint(1,200)) + pokeNum = str(random.randint(1, 200)) url = "http://pokeapi.co/api/v2/pokemon/" + pokeNum + "/" - #Checks if Pokemon has already been found, if so pulls file + # Checks if Pokemon has already been found, if so pulls file if os.path.isfile("IO Files/Pokemon/Pokemon#{}".format(pokeNum)): - with open('IO Files/Pokemon/Pokemon#{}'.format(pokeNum), 'r') as file: + with open("IO Files/Pokemon/Pokemon#{}".format(pokeNum), "r") as file: self.wild_pokemon = json.load(file) else: t0 = datetime.now() self.wild_pokemon = requests.post(url).json() print(f"Obtained Pokemon - {datetime.now() - t0}") - with open(f"IO Files/Pokemon/Pokemon#{self.wild_pokemon['id']}", 'w') as file: + with open(f"IO Files/Pokemon/Pokemon#{self.wild_pokemon['id']}", "w") as file: json.dump(self.wild_pokemon, file) embed = discord.Embed() @@ -393,23 +382,23 @@ async def _spawn(self, channel=None, message=None): await self.bot.change_presence(status=discord.Status.online, activity=game) def sort_gif_file(self): - with open("IO Files/badGIF.txt", 'r') as file: + with open("IO Files/badGIF.txt", "r") as file: docText = file.read().strip() - #print(docText.split("\n")) + # print(docText.split("\n")) docText = docText.split("\n") - with open("IO Files/sorted_badGIF.txt", 'w') as file: - file.write("\n".join(sorted(set(docText), key=lambda item: int(item.split('#')[-1])))) + with open("IO Files/sorted_badGIF.txt", "w") as file: + file.write("\n".join(sorted(set(docText), key=lambda item: int(item.split("#")[-1])))) async def check_capture(self, message): if self.wild_pokemon is None: return False - if self.wild_pokemon['name'] == message.content.lower(): + if self.wild_pokemon["name"] == message.content.lower(): await self.bot.change_presence(status=discord.Status.invisible) - print("[{}]: '{}' caught by {}".format(datetime.now().strftime("%b-%d %H:%M"), self.wild_pokemon['name'], message.author)) + print("[{}]: '{}' caught by {}".format(datetime.now().strftime("%b-%d %H:%M"), self.wild_pokemon["name"], message.author)) embed = discord.Embed(type="rich", title="Gotcha!", color=0xEEE8AA) - embed.description = "{} was caught by {}".format(self.wild_pokemon['name'].upper(), message.author.mention) - embed.set_thumbnail(url="https://play.pokemonshowdown.com/sprites/xyani/{}.gif".format(self.wild_pokemon['name'])) + embed.description = "{} was caught by {}".format(self.wild_pokemon["name"].upper(), message.author.mention) + embed.set_thumbnail(url="https://play.pokemonshowdown.com/sprites/xyani/{}.gif".format(self.wild_pokemon["name"])) # await client.send_message(message.channel, "Gotcha!\n{} was caught by {}".format(self.wild_pokemon['name'].upper(), message.author.mention)) await message.channel.send(embed=embed) if message.author.id in self.trainer_list.keys(): @@ -421,64 +410,54 @@ async def check_capture(self, message): return False async def convert_bw(self, poke): - response = requests.get(poke['sprites']['front_default']) + response = requests.get(poke["sprites"]["front_default"]) print("Obtained Image") img = Image.open(BytesIO(response.content)) - shape_img = img.convert('RGBA') + shape_img = img.convert("RGBA") pixdata = shape_img.load() width, height = shape_img.size for x in range(0, width - 1): for y in range(0, height - 1): - if pixdata[x,y] != (0, 0, 0, 0): - pixdata[x,y] = black - shape_img.save('Images/bw_image.png') + if pixdata[x, y] != (0, 0, 0, 0): + pixdata[x, y] = black + shape_img.save("Images/bw_image.png") async def convert_gif_bw(self, poke): txtfile_name = "Images/PokeGIF.gif" - #Get the gif file - response = requests.get("https://play.pokemonshowdown.com/sprites/xyani/" + poke['name'] + ".gif") + # Get the gif file + response = requests.get("https://play.pokemonshowdown.com/sprites/xyani/" + poke["name"] + ".gif") print("Obtained image: {}".format(response)) #'Download' the file frames = Image.open(BytesIO(response.content)) all_frames = [] width, height = frames.size - #Creates a viewing picture - compilation = Image.new('RGBA', size=(width * 5, height * 10)) + # Creates a viewing picture + compilation = Image.new("RGBA", size=(width * 5, height * 10)) - prev_frame = Image.new('RGBA', size=frames.size, color=(255,255,255,0)) + prev_frame = Image.new("RGBA", size=frames.size, color=(255, 255, 255, 0)) for i in range(frames.n_frames): frames.seek(i) if len(all_frames) <= 50: - compilation.paste(frames, box=(width * int(i % 5), height * int(i / 5))) - + compilation.paste(frames, box=(width * int(i % 5), height * int(i / 5))) + disp_frame, prev_frame = method_dispose(frames, prev_frame) frames.seek(0) - disp_frame = disp_frame.convert('RGB') + disp_frame = disp_frame.convert("RGB") pixdata = disp_frame.load() - #Change Colors + # Change Colors for x in range(width): for y in range(height): - if pixdata[x,y] != white: - pixdata[x,y] = black + if pixdata[x, y] != white: + pixdata[x, y] = black all_frames.append(disp_frame) compilation.save("Images/GIFcollage.png") - #Save the gif - all_frames[0].save( - txtfile_name, - save_all=True, - append_images=all_frames[1:], - optimize=False, - duration=frames.info['duration'], - loop=0, - disposal=1, - transparency=255, - background=0 - ) - #Upload to Imgur + # Save the gif + all_frames[0].save(txtfile_name, save_all=True, append_images=all_frames[1:], optimize=False, duration=frames.info["duration"], loop=0, disposal=1, transparency=255, background=0) + # Upload to Imgur try: - self.imgur_result = config.imgur_client.upload_from_path(txtfile_name, config=None, anon=True)['link'] + self.imgur_result = config.imgur_client.upload_from_path(txtfile_name, config=None, anon=True)["link"] except Exception as Err: print(Err) raise Err @@ -488,7 +467,7 @@ async def wait_msg_delete(self, msg, after): await asyncio.sleep(after) await client.delete_message(msg) - @commands.command(name='clean', aliases=['clear'], help='Deletes # of messages') + @commands.command(name="clean", aliases=["clear"], help="Deletes # of messages") @commands.is_owner() async def cmd_clean(self, context, numMessages: int = 0): if numMessages == 0: @@ -497,7 +476,7 @@ async def cmd_clean(self, context, numMessages: int = 0): else: eleted = await context.channel.purge(limit=numMessages + 1) - @commands.command(name='debug', help='Admin testing bot')# , hidden=True) + @commands.command(name="debug", help="Admin testing bot") # , hidden=True) @commands.is_owner() async def cmd_debug(self, context, *, message): embed = discord.Embed(type="rich", title="__Debug__", color=0x7F0000) @@ -513,6 +492,7 @@ async def cmd_debug(self, context, *, message): await context.message.delete() return + def method_dispose(frames, previous_frame): # 0 PIL = Overlay and pass # 1 PIL = Overlay and return previous @@ -521,7 +501,7 @@ def method_dispose(frames, previous_frame): current_frame = frames.convert() new_frame.alpha_composite(current_frame, dest=frames.dispose_extent[0:2], source=frames.dispose_extent) if frames.disposal_method == 0: - return new_frame, Image.new('RGBA', box=frames.size) + return new_frame, Image.new("RGBA", box=frames.size) elif frames.disposal_method == 1: return new_frame, new_frame.copy() elif frames.disposal_method == 2 or frames.disposal_method == 3: @@ -530,4 +510,4 @@ def method_dispose(frames, previous_frame): return new_frame, previous_frame.copy() else: print("UNKNOWN disposal_method") - return current_frame, current_frame.copy() \ No newline at end of file + return current_frame, current_frame.copy() diff --git a/config.py b/config.py index 95f5ffe..c2ce3e7 100644 --- a/config.py +++ b/config.py @@ -6,29 +6,30 @@ # api # import discord -from imgurpython import ImgurClient #swap to pyimgur in the future +from imgurpython import ImgurClient # swap to pyimgur in the future # DISCORD VARS # -#client = discord.Client() +# client = discord.Client() BOT_PREFIX = env.get("BOT_PREFIX") -CHANNEL_IDs = ("449281327988998156") +CHANNEL_IDs = "449281327988998156" # PYTHON VALS # class bcolors: - HEADER = '\033[95m' - OKBLUE = '\033[94m' - OKGREEN = '\033[92m' - WARNING = '\033[93m' - FAIL = '\033[91m' - ENDC = '\033[0m' - BOLD = '\033[1m' - UNDERLINE = '\033[4m' + HEADER = "\033[95m" + OKBLUE = "\033[94m" + OKGREEN = "\033[92m" + WARNING = "\033[93m" + FAIL = "\033[91m" + ENDC = "\033[0m" + BOLD = "\033[1m" + UNDERLINE = "\033[4m" + # Globals # imgur_client = ImgurClient(env.get("imgur_client_id"), env.get("imgur_client_secret")) # Image Vars # -white = (255,255,255) +white = (255, 255, 255) black = (0, 0, 0, 255) diff --git a/env.py b/env.py index 182653e..cc7e929 100644 --- a/env.py +++ b/env.py @@ -1,11 +1,8 @@ import os from dotenv import dotenv_values -var = { - **dotenv_values(".env"), - **dotenv_values(".env.local"), - **os.environ -} +var = {**dotenv_values(".env"), **dotenv_values(".env.local"), **os.environ} + def get(key): - return var[key] \ No newline at end of file + return var[key] diff --git a/log.py b/log.py index f49efdf..0055676 100644 --- a/log.py +++ b/log.py @@ -1,37 +1,46 @@ from datetime import datetime from enum import Enum + class LEVEL(Enum): - INFO = 1 - ERROR = 2 - WARN = 3 - DEBUG = 4 - def __ge__(self, other): - if self.__class__ is other.__class__: - return self.value >= other.value - return NotImplemented - def __gt__(self, other): - if self.__class__ is other.__class__: - return self.value > other.value - return NotImplemented - def __le__(self, other): - if self.__class__ is other.__class__: - return self.value <= other.value - return NotImplemented - def __lt__(self, other): - if self.__class__ is other.__class__: - return self.value < other.value - return NotImplemented + INFO = 1 + ERROR = 2 + WARN = 3 + DEBUG = 4 + + def __ge__(self, other): + if self.__class__ is other.__class__: + return self.value >= other.value + return NotImplemented + + def __gt__(self, other): + if self.__class__ is other.__class__: + return self.value > other.value + return NotImplemented + + def __le__(self, other): + if self.__class__ is other.__class__: + return self.value <= other.value + return NotImplemented + + def __lt__(self, other): + if self.__class__ is other.__class__: + return self.value < other.value + return NotImplemented + level = LEVEL.DEBUG + def separator(): - print('~~~~~~~~~~~~') + print("~~~~~~~~~~~~") + def info(*args, **kwargs): - if level >= LEVEL.INFO: - print(f"[{datetime.now().strftime('%b-%d %H:%M')}] INFO",*args,**kwargs) + if level >= LEVEL.INFO: + print(f"[{datetime.now().strftime('%b-%d %H:%M')}] INFO", *args, **kwargs) + # def error() # def warn() -# def debug() \ No newline at end of file +# def debug() diff --git a/main.py b/main.py index fa3a933..f9e70e9 100644 --- a/main.py +++ b/main.py @@ -17,12 +17,13 @@ bot = commands.Bot(command_prefix=config.BOT_PREFIX) + @bot.event async def on_connect(): log.separator() log.info(f"Logged in as {bot.user.name}(ID: {bot.user.id})") if os.path.isfile("IO Files/PokeCord.pickle"): - with open("IO Files/PokeCord.pickle", 'rb') as file: + with open("IO Files/PokeCord.pickle", "rb") as file: try: Poke = pickle.load(file) if isinstance(Poke, PokeCord): @@ -40,34 +41,39 @@ async def on_connect(): Poke = PokeCord(bot) bot.add_cog(Poke) + @bot.event async def on_command(context): log.info(f"'{context.command}' by {context.author}") pass + @bot.event async def on_command_error(ctx, error): print(error) - #print(dir(error)) + # print(dir(error)) if isinstance(error, commands.errors.CheckFailure): - await ctx.send('You do not have the correct role for this command.') + await ctx.send("You do not have the correct role for this command.") -@bot.command(name='restart') + +@bot.command(name="restart") async def cmd_restart(ctx): print(sys.executable) print(sys.argv) - await ctx.send('Restarting...') + await ctx.send("Restarting...") try: await bot.close() except: pass finally: - os.execl(Path(sys.executable), '"' + sys.executable + '"', * sys.argv) + os.execl(Path(sys.executable), '"' + sys.executable + '"', *sys.argv) + -@bot.command(name='shutdown') +@bot.command(name="shutdown") @commands.is_owner() async def cmd_shutdown(context): await bot.close() + log.info("Start Bot") -bot.run(env.get("TOKEN")) \ No newline at end of file +bot.run(env.get("TOKEN")) diff --git a/pil.py b/pil.py index 8000b91..238d2c0 100644 --- a/pil.py +++ b/pil.py @@ -9,16 +9,17 @@ from requests.models import Response -white = (255,255,255) #255 -black = (0, 0, 0) #255 -transparent = (255, 255, 255) #0 +white = (255, 255, 255) # 255 +black = (0, 0, 0) # 255 +transparent = (255, 255, 255) # 0 + class PilPokemon: def __init__(self): - self.response : requests.Response = None - self.original_image : Image.Image = None - self.normal_image : list(Image.Image) = [] - self.grayscale_image : list(Image.Image) = [] + self.response: requests.Response = None + self.original_image: Image.Image = None + self.normal_image: list(Image.Image) = [] + self.grayscale_image: list(Image.Image) = [] def getGrayscalePokemon(self, pokemon_id): self.getGIF(pokemon_id) @@ -34,7 +35,7 @@ def requestPokemon(self, pokemon_id) -> str: return None else: self.pokemon = response.json() - return self.pokemon['name'] + return self.pokemon["name"] # If pokemon name is known elif type(pokemon_id) == str: return pokemon_id @@ -42,13 +43,13 @@ def requestPokemon(self, pokemon_id) -> str: return None def _getFrames(self) -> Image.Image: - self.original_image = Image.open(BytesIO(self.response.content)) + self.original_image = Image.open(BytesIO(self.response.content)) def getGIF(self, pokemon_id) -> Image.Image: name = self.requestPokemon(pokemon_id) if not name: return None - self.response = requests.get(f"https://play.pokemonshowdown.com/sprites/xyani/{name.lower()}.gif") + self.response = requests.get(f"https://play.pokemonshowdown.com/sprites/xyani/{name.lower()}.gif") if self.response.status_code == 404: return None else: @@ -58,19 +59,20 @@ def getGIF(self, pokemon_id) -> Image.Image: self._getFrames() return self.original_image - ''' + """ Rebuilds an image based off of dispose methods using two frames - ''' + """ + def _method_dispose(self, i, frames, previous_frame): # 0 PIL = Overlay and pass # 1 PIL = Overlay and return previous # 2 PIL = Erase Overlay - new_frame : Image.Image = previous_frame.copy() + new_frame: Image.Image = previous_frame.copy() current_frame = frames.convert() new_frame.alpha_composite(current_frame, dest=frames.dispose_extent[0:2], source=frames.dispose_extent) if frames.disposal_method == 0: - return new_frame, Image.new('RGBA', box=frames.size) + return new_frame, Image.new("RGBA", box=frames.size) elif frames.disposal_method == 1: return new_frame, new_frame.copy() elif frames.disposal_method == 2 or frames.disposal_method == 3: @@ -90,17 +92,17 @@ def getNormalizedImage(self): width, height = frames.size corrected_prev_frame = None - pass_frame = Image.new('RGBA', size=frames.size, color=(255,255,255,0)) + pass_frame = Image.new("RGBA", size=frames.size, color=(255, 255, 255, 0)) for i in range(frames.n_frames): frames.seek(i) disp_frame, pass_frame = self._method_dispose(i, frames, pass_frame) frames.seek(0) - disp_frame = disp_frame.convert('RGB') - + disp_frame = disp_frame.convert("RGB") + self.normal_image.append(disp_frame) def getGrayscaleGIF(self): - if not self.normal_image: # Is Empty + if not self.normal_image: # Is Empty self.getNormalizedImage() if not self.normal_image: return None @@ -108,51 +110,43 @@ def getGrayscaleGIF(self): self.grayscale_image.clear() for frame in self.normal_image: - copy_frame : Image.Image = frame.copy() + copy_frame: Image.Image = frame.copy() pixdata = copy_frame.load() - #Change Colors + # Change Colors for x in range(copy_frame.width): for y in range(copy_frame.height): - if pixdata[x,y] != white: - pixdata[x,y] = black - copy_frame = copy_frame.convert('P') + if pixdata[x, y] != white: + pixdata[x, y] = black + copy_frame = copy_frame.convert("P") self.grayscale_image.append(copy_frame) # Assumption for now is images will be list - def showCollageGIF(self, images:list, num_frame_columns:int = 8): + def showCollageGIF(self, images: list, num_frame_columns: int = 8): width, height = images[0].size num_frame_rows = math.ceil(len(images) / num_frame_columns) - compilation = Image.new('RGBA', size=(width * num_frame_columns, height * num_frame_rows)) + compilation = Image.new("RGBA", size=(width * num_frame_columns, height * num_frame_rows)) for i in range(len(images)): image = images[i] the_frame = image.convert() draw = ImageDraw.Draw(the_frame) - draw.rectangle((0,0, *image.size), outline=(0,0,0,255)) + draw.rectangle((0, 0, *image.size), outline=(0, 0, 0, 255)) dest = (width * int(i % num_frame_columns), height * int(i / num_frame_columns)) compilation.paste(the_frame, dest) compilation.show() - - def saveGIF(self, images:list, filename:str = 'test.gif'): + def saveGIF(self, images: list, filename: str = "test.gif"): images[0].save( - fp=filename, - format='GIF', - save_all=True, - append_images=images[1:], - optimize=False, - duration=self.original_image.info['duration'], - loop=0, - disposal=1, - transparency=255, - background=0 + fp=filename, format="GIF", save_all=True, append_images=images[1:], optimize=False, duration=self.original_image.info["duration"], loop=0, disposal=1, transparency=255, background=0 ) + ### -def _getFrames(response:requests.Response) -> Image.Image: +def _getFrames(response: requests.Response) -> Image.Image: return Image.open(BytesIO(response.content)) -def getPokemonGIF(pokemon_name:str) -> Image.Image: + +def getPokemonGIF(pokemon_name: str) -> Image.Image: """Given a pokemon's name will retrieve the gif of that pokemon Args: @@ -164,12 +158,13 @@ def getPokemonGIF(pokemon_name:str) -> Image.Image: if type(pokemon_name) is not str: return None - response:requests.Response = requests.get(f"https://play.pokemonshowdown.com/sprites/xyani/{name.lower()}.gif") + response: requests.Response = requests.get(f"https://play.pokemonshowdown.com/sprites/xyani/{name.lower()}.gif") if response.status_code == 404: return None else: return _getFrames(response) + def _method_dispose(i, frames, previous_frame): """ Rebuilds an image based off of dispose methods using two frames @@ -177,12 +172,12 @@ def _method_dispose(i, frames, previous_frame): # 0 PIL = Overlay and pass # 1 PIL = Overlay and return previous # 2 PIL = Erase Overlay - new_frame : Image.Image = previous_frame.copy() + new_frame: Image.Image = previous_frame.copy() current_frame = frames.convert() new_frame.alpha_composite(current_frame, dest=frames.dispose_extent[0:2], source=frames.dispose_extent) if frames.disposal_method == 0: - return new_frame, Image.new('RGBA', box=frames.size) + return new_frame, Image.new("RGBA", box=frames.size) elif frames.disposal_method == 1: return new_frame, new_frame.copy() elif frames.disposal_method == 2 or frames.disposal_method == 3: @@ -193,7 +188,8 @@ def _method_dispose(i, frames, previous_frame): print("UNKNOWN disposal_method") exit() -def getNormalizedImage(frames:Image.Image) -> list: + +def getNormalizedImage(frames: Image.Image) -> list: """Input is a GIF, taking each frame and rebuilding the image according to the disposal method of the frame @@ -208,17 +204,18 @@ def getNormalizedImage(frames:Image.Image) -> list: width, height = frames.size corrected_prev_frame = None - pass_frame = Image.new('RGBA', size=frames.size, color=(255,255,255,0)) + pass_frame = Image.new("RGBA", size=frames.size, color=(255, 255, 255, 0)) for i in range(frames.n_frames): frames.seek(i) disp_frame, pass_frame = _method_dispose(i, frames, pass_frame) frames.seek(0) - disp_frame = disp_frame.convert('RGB') - + disp_frame = disp_frame.convert("RGB") + normal_image.append(disp_frame) return normal_image -def getGrayscaleGIF(frames:list) -> list: + +def getGrayscaleGIF(frames: list) -> list: """Given a list of images will remove color from all. Assumption is background is white @@ -232,16 +229,17 @@ def getGrayscaleGIF(frames:list) -> list: for frame in frames: pixdata = frame.load() - #Change Colors + # Change Colors for x in range(frame.width): for y in range(frame.height): - if pixdata[x,y] != white: - pixdata[x,y] = black - frame = frame.convert('P') + if pixdata[x, y] != white: + pixdata[x, y] = black + frame = frame.convert("P") grayscale_image.append(frame) return grayscale_image -def getGrayscalePokemon(pokemon_id:str) -> list: + +def getGrayscalePokemon(pokemon_id: str) -> list: """Takes the pokemon string and outputs the grayscale image list Args: @@ -254,8 +252,10 @@ def getGrayscalePokemon(pokemon_id:str) -> list: normal_image = getNormalizedImage(original_image) return getGrayscaleGIF(normal_image) + ### + def getPokemon(val): url = "http://pokeapi.co/api/v2/pokemon/" + val + "/" t0 = time.time() @@ -263,13 +263,15 @@ def getPokemon(val): print(f"Obtained Pokemon - {time.time() - t0}") return poke + def getGIFimage(name): response = requests.get(f"https://play.pokemonshowdown.com/sprites/xyani/{name.lower()}.gif") print(f"Obtained Image: {response} : {response.url}") frames = Image.open(BytesIO(response.content)) return frames -def simpleCollage(frames:Image.Image, num_images_width : int = 5, num_images_height : int = 10, fit : bool = False): + +def simpleCollage(frames: Image.Image, num_images_width: int = 5, num_images_height: int = 10, fit: bool = False): """Prints each frame with the frame number and disposal method in the corner. Args: @@ -282,35 +284,30 @@ def simpleCollage(frames:Image.Image, num_images_width : int = 5, num_images_hei if fit: num_images_height = math.ceil(frames.n_frames / num_images_width) print(f"Frames in image ({num_images_width}x{num_images_height}): {frames.n_frames} - {frames.filename if frames.filename else 'N/A'}") - compilation = Image.new('RGBA', size=(width * num_images_width, height * num_images_height)) + compilation = Image.new("RGBA", size=(width * num_images_width, height * num_images_height)) fnt = ImageFont.load_default().font last_dispose_method_2 = 0 for i in range(frames.n_frames): frames.seek(i) the_frame = frames.convert() draw = ImageDraw.Draw(the_frame) - draw.rectangle(frames.dispose_extent, outline=(0,0,0,255)) - draw.text((0,0), f"F{i}-M{frames.disposal_method}", font=fnt, fill=(255, 0, 0)) - - compilation.alpha_composite( - the_frame, - dest=( - width * int(i % num_images_width), - height * int(i / num_images_width) - ) - ) + draw.rectangle(frames.dispose_extent, outline=(0, 0, 0, 255)) + draw.text((0, 0), f"F{i}-M{frames.disposal_method}", font=fnt, fill=(255, 0, 0)) + + compilation.alpha_composite(the_frame, dest=(width * int(i % num_images_width), height * int(i / num_images_width))) if frames.disposal_method == 2: last_dispose_method_2 = i frames.seek(0) if i == (num_images_width * num_images_height): break compilation.show() - compilation.save("compilation.png") + compilation.save("compilation.png") + -def reformCollage(frames, num_images_width : int = 5, num_images_height : int = 10, fit : bool = False): +def reformCollage(frames, num_images_width: int = 5, num_images_height: int = 10, fit: bool = False): """ Pastes each frame not going back to the first frame - Details: + Details: Image background yellow If pixel is transparency color change to transparent teal If pixel is background color change to solid red @@ -321,103 +318,88 @@ def reformCollage(frames, num_images_width : int = 5, num_images_height : int = num_images_height = math.ceil(frames.n_frames / num_images_width) print(f"Frames in image ({num_images_width}x{num_images_height}): {frames.n_frames} - {frames.filename}") frames.seek(0) - backgroundColor = frames.info['background'] - compilation = Image.new('RGBA', size=(width * num_images_width, height * num_images_height), color=(255, 255, 0))#, color=(255,0,0)) + backgroundColor = frames.info["background"] + compilation = Image.new("RGBA", size=(width * num_images_width, height * num_images_height), color=(255, 255, 0)) # , color=(255,0,0)) fnt = ImageFont.load_default().font - #print(f"Disposal Method - {frames.disposal_method}, Disposal Extend - {frames.dispose_extent}, Info - {frames.info}") + # print(f"Disposal Method - {frames.disposal_method}, Disposal Extend - {frames.dispose_extent}, Info - {frames.info}") for i in range(frames.n_frames): frames.seek(i) - the_frame = Image.new('RGBA', size=frames.size) + the_frame = Image.new("RGBA", size=frames.size) pixdata = the_frame.load() for x in range(width): for y in range(height): palette = frames.getpalette() - a_pixel = frames.getpixel((x,y)) - if a_pixel == frames.info['transparency']: + a_pixel = frames.getpixel((x, y)) + if a_pixel == frames.info["transparency"]: pixdata[x, y] = (0, 255, 255, 0) - #pixdata[x,y] = tuple(palette[a_pixel:a_pixel+3] + [100]) - elif a_pixel == frames.info['background']: - pixdata[x, y] = (255, 0 , 0, 255) + # pixdata[x,y] = tuple(palette[a_pixel:a_pixel+3] + [100]) + elif a_pixel == frames.info["background"]: + pixdata[x, y] = (255, 0, 0, 255) else: - pixdata[x,y] = tuple(palette[a_pixel:a_pixel+3])# + [255]) - #the_frame.alpha_composite(frames, dest=frames.dispose_extent[0:2], source=frames.dispose_extent) - #the_frame = frames.convert() + pixdata[x, y] = tuple(palette[a_pixel : a_pixel + 3]) # + [255]) + # the_frame.alpha_composite(frames, dest=frames.dispose_extent[0:2], source=frames.dispose_extent) + # the_frame = frames.convert() draw = ImageDraw.Draw(the_frame) - draw.rectangle(frames.dispose_extent, outline=(255,173,0,255)) + draw.rectangle(frames.dispose_extent, outline=(255, 173, 0, 255)) # draw.text((0,0), f"F{i}-M{frames.disposal_method}", font=fnt, fill=(255, 0, 0)) - compilation.alpha_composite( - the_frame, - dest=( - width * int(i % num_images_width), - height * int(i / num_images_width) - ) - ) + compilation.alpha_composite(the_frame, dest=(width * int(i % num_images_width), height * int(i / num_images_width))) if i == (num_images_width * num_images_height): - break; + break compilation.show() - compilation.save("compilation.png") + compilation.save("compilation.png") + def GIFconvertBW(frames): width, height = frames.size all_frames = [] corrected_prev_frame = None - pass_frame = Image.new('RGBA', size=frames.size, color=(255,255,255,0)) - #disposal_method_list = [] + pass_frame = Image.new("RGBA", size=frames.size, color=(255, 255, 255, 0)) + # disposal_method_list = [] for i in range(frames.n_frames): frames.seek(i) if i == 4: frames.save(f"frames_{i}.png") disp_frame, pass_frame = method_dispose(i, frames, pass_frame) frames.seek(0) - disp_frame = disp_frame.convert('RGB') + disp_frame = disp_frame.convert("RGB") pixdata = disp_frame.load() - #Change Colors + # Change Colors for x in range(width): for y in range(height): - if pixdata[x,y] != white: - pixdata[x,y] = black + if pixdata[x, y] != white: + pixdata[x, y] = black - disp_frame = disp_frame.convert('P') + disp_frame = disp_frame.convert("P") all_frames.append(disp_frame) - print(f"Save {len(all_frames)} frames in 'test.gif'") - all_frames[0].save( - fp="test.gif", - format='GIF', - save_all=True, - append_images=all_frames[1:], - optimize=False, - duration=frames.info['duration'], - loop=0, - disposal=1, - transparency=255, - background=0 - ) + all_frames[0].save(fp="test.gif", format="GIF", save_all=True, append_images=all_frames[1:], optimize=False, duration=frames.info["duration"], loop=0, disposal=1, transparency=255, background=0) simpleCollage(Image.open("test.gif"), 12, fit=True) + ########################################## # Frame Process Methods # ########################################## -#crop_frame = current_frame.crop(frames.dispose_extent) -#new_frame.alpha_composite(crop_frame, dest=frames.dispose_extent[0:2]) +# crop_frame = current_frame.crop(frames.dispose_extent) +# new_frame.alpha_composite(crop_frame, dest=frames.dispose_extent[0:2]) + def method_dispose(i, frames, previous_frame): # 0 PIL = Overlay and pass # 1 PIL = Overlay and return previous # 2 PIL = Erase Overlay - new_frame : Image.Image = previous_frame.copy() + new_frame: Image.Image = previous_frame.copy() current_frame = frames.convert() new_frame.alpha_composite(current_frame, dest=frames.dispose_extent[0:2], source=frames.dispose_extent) if frames.disposal_method == 0: - return new_frame, Image.new('RGBA', box=frames.size) + return new_frame, Image.new("RGBA", box=frames.size) elif frames.disposal_method == 1: return new_frame, new_frame.copy() elif frames.disposal_method == 2 or frames.disposal_method == 3: @@ -428,19 +410,20 @@ def method_dispose(i, frames, previous_frame): print("UNKNOWN disposal_method") exit() -def method_sum_check(i, current_frame : Image, previous_frame : Image, size_opt_color): + +def method_sum_check(i, current_frame: Image, previous_frame: Image, size_opt_color): width, height = current_frame.size if previous_frame is None: - disp_frame = current_frame.copy() + disp_frame = current_frame.copy() else: - #Remove borders + # Remove borders pixdata = current_frame.load() if size_opt_color is not None: if pixdata[0, 0] == size_opt_color: for x in range(width): for y in range(height): if pixdata[x, y] == size_opt_color: - pixdata[x,y] = white + (0, ) + pixdata[x, y] = white + (0,) # elif pixdata[x, y][3] == 255: # break; @@ -459,59 +442,62 @@ def method_sum_check(i, current_frame : Image, previous_frame : Image, size_opt if pixdata[x, y][3] == 0: curr_alpha_sum += 1 - percent_diff = (curr_alpha_sum / prev_alpha_sum) * 100.0 - if percent_diff > 109.0: # or percent_diff > 100.0: #percent - #print(f"{i} = {percent_diff:6.2f}%: Check Sum (Prev-{prev_alpha_sum} vs Curr-{curr_alpha_sum})") + if percent_diff > 109.0: # or percent_diff > 100.0: #percent + # print(f"{i} = {percent_diff:6.2f}%: Check Sum (Prev-{prev_alpha_sum} vs Curr-{curr_alpha_sum})") disp_frame = Image.alpha_composite(previous_frame, current_frame) else: - #print(f"\t{i} = {percent_diff:6.2f}%: Check Sum (Prev-{prev_alpha_sum} vs Curr-{curr_alpha_sum})") + # print(f"\t{i} = {percent_diff:6.2f}%: Check Sum (Prev-{prev_alpha_sum} vs Curr-{curr_alpha_sum})") disp_frame = current_frame.copy() - + pre_recolor = disp_frame.copy() return disp_frame, pre_recolor -def method_simple_recolor(current_frame : Image): + +def method_simple_recolor(current_frame: Image): width, height = current_frame.size pixdata = current_frame.load() for x in range(width): for y in range(height): - if pixdata[x,y][3] == 255: - pixdata[x,y] = black + (255,) + if pixdata[x, y][3] == 255: + pixdata[x, y] = black + (255,) else: - pixdata[x,y] = white + (255,) + pixdata[x, y] = white + (255,) return current_frame -def method_gather_colors(current_frame : Image, hitBlackLine = False, colorsToCheck = [transparent]): - current_frame = frames.convert('RGB') + +def method_gather_colors(current_frame: Image, hitBlackLine=False, colorsToCheck=[transparent]): + current_frame = frames.convert("RGB") pixdata = current_frame.load() width, height = current_frame.size for x in range(0, width - 1): for y in range(0, height - 1): if hitBlackLine: - if pixdata[x,y] not in colorsToCheck: - pixdata[x,y] = black + if pixdata[x, y] not in colorsToCheck: + pixdata[x, y] = black else: - pixdata[x,y] = white + pixdata[x, y] = white else: - if pixdata[x,y] <= (60,60,60): + if pixdata[x, y] <= (60, 60, 60): hitBlackLine = True - elif pixdata[x,y] not in colorsToCheck: - colorsToCheck.append(pixdata[x,y]) + elif pixdata[x, y] not in colorsToCheck: + colorsToCheck.append(pixdata[x, y]) + ########################################## + def main(): print("Args Entered: {}".format(sys.argv)) # If random pokemon wanted if len(sys.argv) == 1: - poke = getPokemon(str(random.randint(1,200))) - frames = getGIFimage(poke['name']) + poke = getPokemon(str(random.randint(1, 200))) + frames = getGIFimage(poke["name"]) # If specific number wanted elif sys.argv[1].isdigit(): poke = getPokemon(sys.argv[1]) - frames = getGIFimage(poke['name']) + frames = getGIFimage(poke["name"]) # If pokemon name is known else: frames = getGIFimage(sys.argv[1]) @@ -519,7 +505,8 @@ def main(): simpleCollage(frames, 12, fit=True) GIFconvertBW(frames) - #import pdb; pdb.set_trace() + # import pdb; pdb.set_trace() + # def getStillImg(pokeObj): # response = requests.get(poke['sprites']['front_default']) @@ -559,4 +546,4 @@ def main(): # shape_img.save('test_image.png') if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..57ce6b2 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,2 @@ +[tool.black] +line-length = 200 \ No newline at end of file diff --git a/sql/main.py b/sql/main.py index 200cf3d..8bbc286 100644 --- a/sql/main.py +++ b/sql/main.py @@ -1,8 +1,9 @@ # Project Includes from sqlalchemy.orm import session -#from sql.tables import Pokemon -import tables # database for bot -from pil import PilPokemon # Request and parser for pokemon + +# from sql.tables import Pokemon +import tables # database for bot +from pil import PilPokemon # Request and parser for pokemon # Built in Python Libraries import json @@ -12,19 +13,22 @@ # from PIL import Image, ImageDraw # from io import BytesIO + def getPokemonInfo(pokemonValue): url = f"http://pokeapi.co/api/v2/pokemon/{pokemonValue}/" wild_pokemon = requests.post(url).json() - with open(f"JSON Pokemon/Pokemon#{wild_pokemon['id']}", 'w') as file: + with open(f"JSON Pokemon/Pokemon#{wild_pokemon['id']}", "w") as file: json.dump(wild_pokemon, file, indent=4) + def setupFolders(): - imgFolder = Path('Images') + imgFolder = Path("Images") if not imgFolder.exists(): imgFolder.mkdir() pass -if __name__ == '__main__': + +if __name__ == "__main__": setupFolders() pokemon = PilPokemon() pokemon.getGIF(1) @@ -33,7 +37,7 @@ def setupFolders(): if not Path(filename).exists(): pokemon.saveGIF(pokemon.normal_image, filename) - qry = tables.session.query(tables.Pokemon).filter(tables.Pokemon.id==pokemon.details["id"]) + qry = tables.session.query(tables.Pokemon).filter(tables.Pokemon.id == pokemon.details["id"]) if not qry.first(): print("Add") sqlPokemon = tables.Pokemon.fromJson(pokemon.details) @@ -41,4 +45,3 @@ def setupFolders(): tables.session.add(sqlPokemon) tables.session.commit() - diff --git a/sql/tables.py b/sql/tables.py index 3a8dbce..f1d8ea6 100644 --- a/sql/tables.py +++ b/sql/tables.py @@ -5,46 +5,46 @@ Base = declarative_base() + class Trainer(Base): - __tablename__ = 'trainer' - id = Column(String, primary_key=True) # Discord ID of User - pokemon = relationship('PokemonMapping', backref='trainer') + __tablename__ = "trainer" + id = Column(String, primary_key=True) # Discord ID of User + pokemon = relationship("PokemonMapping", backref="trainer") + class Moves(Base): - __tablename__ = 'moves' + __tablename__ = "moves" id = Column(Integer, primary_key=True) name = Column(String) + class Pokemon(Base): - __tablename__ = 'pokemon' + __tablename__ = "pokemon" id = Column(Integer, primary_key=True) pokemon = Column(String(length=32)) type = Column(String) type2 = Column(String, default=None) - image_path = Column(String) # Path to image + image_path = Column(String) # Path to image def fromJson(self, pokemonDetails) -> Pokemon: - sqlPokemon = Pokemon( - id=pokemonDetails['id'], - pokemon=pokemonDetails['name'], - type=pokemonDetails['types'][0]['type']['name'], - image_path=None - ) - if len(pokemonDetails.details['types']) == 2: - sqlPokemon.type2 = pokemonDetails.details['types'][1]['type']['name'] + sqlPokemon = Pokemon(id=pokemonDetails["id"], pokemon=pokemonDetails["name"], type=pokemonDetails["types"][0]["type"]["name"], image_path=None) + if len(pokemonDetails.details["types"]) == 2: + sqlPokemon.type2 = pokemonDetails.details["types"][1]["type"]["name"] return sqlPokemon + class PokeCord(Base): - __tablename__ = 'pokecord' - discord_server = Column(String, primary_key=True) - channel_bind = Column(String) # Channel to post in - message_id = Column(String) # Message with the wild pokemon - wild_pokemon = Column(Integer, ForeignKey(Pokemon.id)) # Pokemon that appeared - appear_time = Column(DateTime) # Time to appear + __tablename__ = "pokecord" + discord_server = Column(String, primary_key=True) + channel_bind = Column(String) # Channel to post in + message_id = Column(String) # Message with the wild pokemon + wild_pokemon = Column(Integer, ForeignKey(Pokemon.id)) # Pokemon that appeared + appear_time = Column(DateTime) # Time to appear + class PokemonMapping(Base): - __tablename__ = 'pokemon_mapping' + __tablename__ = "pokemon_mapping" id = Column(Integer, primary_key=True, autoincrement=True) obtained = Column(DateTime, default=datetime.today()) trainer_id = Column(String, ForeignKey(Trainer.id)) @@ -57,16 +57,18 @@ class PokemonMapping(Base): move3 = Column(Integer, ForeignKey(Moves.id)) move4 = Column(Integer, ForeignKey(Moves.id)) + class ItemMapping(Base): - __tablename__ = 'item_mapping' + __tablename__ = "item_mapping" id = Column(Integer, primary_key=True, autoincrement=True) trainer = Column(String, ForeignKey(Trainer.id)) item = Column(String) -engine = create_engine('sqlite:///test.db') -#Base.metadata.drop_all(bind=engine) + +engine = create_engine("sqlite:///test.db") +# Base.metadata.drop_all(bind=engine) Base.metadata.create_all(engine) Base.metadata.bind = engine DBSession = sessionmaker(bind=engine) -session = DBSession() \ No newline at end of file +session = DBSession()