From 5b08dbf1ce2054574ff13154dc254d734cadee51 Mon Sep 17 00:00:00 2001 From: titigmr Date: Mon, 22 Nov 2021 16:24:54 +0100 Subject: [PATCH 01/19] separate dev and user cogs --- .gitignore | 5 +- bot/_bot.py | 2 +- cogs/{ => dev}/owner.py | 10 ++- cogs/{ => dev}/settings.py | 1 + cogs/{ => user}/dice.py | 0 cogs/{ => user}/john.py | 0 cogs/{ => user}/poll.py | 0 cogs/{ => user}/ufd.py | 7 +- cogs/utils/_ufd.py | 138 ++++++++++++++++++++++++------------- config.json | 12 ++-- main.py | 2 +- 11 files changed, 113 insertions(+), 64 deletions(-) rename cogs/{ => dev}/owner.py (85%) rename cogs/{ => dev}/settings.py (99%) rename cogs/{ => user}/dice.py (100%) rename cogs/{ => user}/john.py (100%) rename cogs/{ => user}/poll.py (100%) rename cogs/{ => user}/ufd.py (97%) diff --git a/.gitignore b/.gitignore index 0929d02..91840aa 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,7 @@ # import __pycache__ - +*.egg-info # folders _img_dices @@ -18,4 +18,5 @@ _img_dices .idea # env -.env \ No newline at end of file +.env + diff --git a/bot/_bot.py b/bot/_bot.py index b01c829..4d774f7 100644 --- a/bot/_bot.py +++ b/bot/_bot.py @@ -10,7 +10,7 @@ def __init__(self, config, token): description=self.config["description"] ) for extension in self.config["extensions"]: - self.load_extension(extension) + self.load_extension('cogs.' + extension) async def on_ready(self): print(f'Logged in as {self.user} with extensions: \n{" ".join(self.extensions).replace("cogs.", "")}') diff --git a/cogs/owner.py b/cogs/dev/owner.py similarity index 85% rename from cogs/owner.py rename to cogs/dev/owner.py index 89c29a3..67a99ad 100644 --- a/cogs/owner.py +++ b/cogs/dev/owner.py @@ -8,23 +8,27 @@ def __init__(self, bot): @commands.command(name="load", hidden=True) @commands.is_owner() - async def load(self, ctx, *, cog: str): + async def load(self, ctx, *, cog: str = None): + self.bot.load_extension(self.path + cog) await ctx.send("**`SUCCESS`**") + @commands.command(name="unload", hidden=True) @commands.is_owner() - async def unload(self, ctx, *, cog: str): + async def unload(self, ctx, *, cog: str = None): self.bot.unload_extension(self.path + cog) await ctx.send("**`SUCCESS`**") + @commands.command(name="reload", hidden=True) @commands.is_owner() - async def reload(self, ctx, *, cog: str): + async def reload(self, ctx, *, cog: str = None): self.bot.unload_extension(self.path + cog) self.bot.load_extension(self.path + cog) await ctx.send("**`SUCCESS`**") + @reload.error @load.error @unload.error diff --git a/cogs/settings.py b/cogs/dev/settings.py similarity index 99% rename from cogs/settings.py rename to cogs/dev/settings.py index 2a0148a..eb34b22 100644 --- a/cogs/settings.py +++ b/cogs/dev/settings.py @@ -16,6 +16,7 @@ async def set_prefix(self, ctx, *, new_prefix: str): self.bot.command_prefix = new_prefix await ctx.send(f'Prefix has been set to `{new_prefix}`.') + @set_prefix.error async def pref_error(self, ctx, error): if isinstance(error, commands.MissingPermissions): diff --git a/cogs/dice.py b/cogs/user/dice.py similarity index 100% rename from cogs/dice.py rename to cogs/user/dice.py diff --git a/cogs/john.py b/cogs/user/john.py similarity index 100% rename from cogs/john.py rename to cogs/user/john.py diff --git a/cogs/poll.py b/cogs/user/poll.py similarity index 100% rename from cogs/poll.py rename to cogs/user/poll.py diff --git a/cogs/ufd.py b/cogs/user/ufd.py similarity index 97% rename from cogs/ufd.py rename to cogs/user/ufd.py index 5ea2f3b..23d27f2 100644 --- a/cogs/ufd.py +++ b/cogs/user/ufd.py @@ -20,7 +20,6 @@ def __init__(self, bot): self.bot = bot self.url = ufd.url self.get_all_characters = ufd.get_all_characters - self.ref_atk = ufd.REF_ATK self.n_args = None self.command = None self.args = None @@ -28,7 +27,10 @@ def __init__(self, bot): @commands.cooldown(rate=5, per=30, type=commands.BucketType.user) @commands.command(name="ufd") async def ufd(self, ctx, command=None, *args): - + """ + Command UFD for get information about moves for a character in + SSBU i.e "ufd wario nair fair" + """ self.n_args = len(args) self.command = command self.args = iter(args) @@ -72,6 +74,7 @@ async def ufd(self, ctx, command=None, *args): moves=self.args, get_hitbox=True, args_stats=None) + except (ValueError, KeyError) as error: await ctx.channel.send(f"{error}") return diff --git a/cogs/utils/_ufd.py b/cogs/utils/_ufd.py index 09ffe59..70702d1 100644 --- a/cogs/utils/_ufd.py +++ b/cogs/utils/_ufd.py @@ -26,39 +26,42 @@ "totalframes", "basedamage", "shieldstun"] DEFAULT_EXCLUDE_OVERALL_STATS = ["Stats", "Initial Dash", 'Walk Speed', - "SH / FH / SHFF / FHFF Frames", 'Shield Drop', 'Jump Squat'] + "SH / FH / SHFF / FHFF Frames", + 'Shield Drop', 'Jump Squat'] class UltimateFD: def __init__(self, - character, - moves, - args_stats=None, - get_hitbox=False, - exclude_stats=['movename', - 'whichhitbox', 'notes'], - exclude_moves=['dodge']): + character: str=None, + moves: str = None, + args_stats=None, + get_hitbox: bool =False, + exclude_stats: list =['movename', + 'whichhitbox', + 'notes'], + exclude_moves: list =['dodge']): self.char = character - self.out = exclude_moves + self.exclude_moves = exclude_moves self.exclude_stats = exclude_stats - self.image = get_hitbox self.url = "https://ultimateframedata.com/" self.stats = {} self.all_char = self.get_all_characters(self.url) self.avalaible_stats = {} self.args_stats = DEFAULT_STATS if args_stats is None else args_stats + if character is None: return moves = list(REF_ATK.keys()) if moves == 'all' else moves + data_move = self.get_character_data(name=character) for move in moves: - self._st_move = self.get_character_moves(name=character, - move=move) + st_move = self.get_character_moves(data=data_move, + move=move) - stats = self.get_stats_move(self._st_move, - self.image, + stats = self.get_stats_move(st_move, + get_hitbox, *self.args_stats) self.stats.update(stats) @@ -68,41 +71,45 @@ def __init__(self, def _get_soup(self, url): - r = requests.get(url) - if r.status_code != 200: + """ + Request an url for a valid character + """ + response = requests.get(url) + if response.status_code != 200: raise ValueError( f'Choose a valid character in: {list(self.all_char.keys())}') - return BeautifulSoup(r.content, 'lxml') + return BeautifulSoup(response.content, 'lxml') + def get_stats_move(self, stats_move, image, *kwargs): out_move = {} - for m, s in stats_move.items(): + + for move, stats in stats_move.items(): out_stats = {} - available_stats = self._get_available_stats(st_move=s, - exclude_stats=self.exclude_stats) - self.avalaible_stats[m] = available_stats + available_stats = self._get_available_stats(st_move=stats) + self.avalaible_stats[move] = available_stats if self.args_stats == 'all': kwargs = available_stats - if 'stats' in m: - out_move[m] = self._format_overall_stats(s) + if 'stats' in move: + out_move[move] = self._format_overall_stats(stats) continue if image: if 'hitbox' in available_stats: - if s.a is not None: - end_url_img = s.a["data-featherlight"] + if stats.a is not None: + end_url_img = stats.a["data-featherlight"] url_img = self.url + end_url_img out_stats['hitbox'] = url_img available_stats.remove('hitbox') for arg in kwargs: if arg in available_stats: - val = self._format_stats(soup=s, - class_name=arg) + val = self._format_stats(soup=stats, + class_name=arg) out_stats[arg] = val - out_move[m] = out_stats + out_move[move] = out_stats return out_move def _format_stats(self, soup, class_name): @@ -111,48 +118,81 @@ def _format_stats(self, soup, class_name): return soup.text.strip() return None - def get_character_moves(self, name, move): + + def get_character_data(self, name): + """ + Get list characters moves + """ url_char = self.url + name soup = self._get_soup(url_char) + # for each movename not None get key (name) and value (stats) data_move = {mv.find(class_='movename').text.strip().lower(): mv for mv in soup.find_all(class_='movecontainer') if mv.find(class_='movename') is not None} - - final_dict_move = {} - for m_k, m_s in data_move.items(): - for out_word in self.out: - if self._check_move(ref_atk=REF_ATK, move=move, m_k=m_k, out=out_word): - final_dict_move[m_k] = m_s - return final_dict_move - - def _check_move(self, ref_atk, move, m_k, out): - if move in ref_atk: - if ref_atk[move] in m_k: - if out not in m_k: + return data_move + + + def get_character_moves(self, data: dict, move: str): + """ + Select move in data moves + """ + selected_dict_move = {} + + # check if moves is in REF const and not in exclude moves + for move_k, move_s in data.items(): + for excluded_move in self.exclude_moves: + if self._check_move(move=move, move_k=move_k, out=excluded_move): + selected_dict_move[move_k] = move_s + return selected_dict_move + + @staticmethod + def _check_move(move: str, move_k: str, out: str): + """ + Check for a move if: + - is in REF_ATK moves + - not in excluded moves + Return: + ------- + bool + """ + if move in REF_ATK: + if REF_ATK[move] in move_k: + if out not in move_k: return True return False - def _get_available_stats(self, st_move, exclude_stats): + def _get_available_stats(self, st_move): + """ + Parse BeautiFullSoup object to a list of available stats + """ stats_list = set() - for e in st_move.find_all('div'): - if e.has_attr('class'): - if len(e["class"]) != 0: - stats = " ".join(e['class']) - if stats not in exclude_stats: + for div in st_move.find_all('div'): + if div.has_attr('class'): + if len(div["class"]) != 0: + stats = " ".join(div['class']) + if stats not in self.exclude_stats: stats_list.add(stats) return stats_list def get_all_characters(self, url): + """ + Get list of all characters + + Return: + ------ + - dict, {character: url, ...} + """ soup = self._get_soup(url) characters = {} for balise in soup.find_all('a'): href = balise["href"] - if (href.startswith('/')) and ('stats' not in href): + # href contain character name (remove # or http values) + if ('#' not in href) and ("http" not in href) and ('stats' not in href): name = href.replace('/', '') - url_c = url + href + url_c = url + name characters[name] = url_c return characters diff --git a/config.json b/config.json index 48778ee..006476e 100644 --- a/config.json +++ b/config.json @@ -2,11 +2,11 @@ "description": "", "command_prefix": "!", "extensions": [ - "cogs.dice", - "cogs.john", - "cogs.poll", - "cogs.ufd", - "cogs.owner", - "cogs.settings" + "user.dice", + "user.john", + "user.poll", + "user.ufd", + "dev.owner", + "dev.settings" ] } \ No newline at end of file diff --git a/main.py b/main.py index 2332577..be4e1ee 100644 --- a/main.py +++ b/main.py @@ -3,7 +3,7 @@ from bot import Ramoloss -with open('config.json') as config_file: +with open('config.json', 'r', encoding='utf-8') as config_file: config = json.load(config_file) token = os.environ["DISCORD_TOKEN"] From 5cc2acde86948a602c609ddbd99bd926f2c382ad Mon Sep 17 00:00:00 2001 From: titigmr Date: Mon, 22 Nov 2021 17:10:58 +0100 Subject: [PATCH 02/19] change owner settings --- cogs/dev/owner.py | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/cogs/dev/owner.py b/cogs/dev/owner.py index 67a99ad..b220ac8 100644 --- a/cogs/dev/owner.py +++ b/cogs/dev/owner.py @@ -1,4 +1,5 @@ from discord.ext import commands +from discord.ext.commands.core import command, has_permissions class Owner(commands.Cog): @@ -7,34 +8,60 @@ def __init__(self, bot): self.path = 'cogs.' @commands.command(name="load", hidden=True) + @commands.has_permissions(admin=True) @commands.is_owner() async def load(self, ctx, *, cog: str = None): - - self.bot.load_extension(self.path + cog) + cog = self.parse_args(cog) + for module in cog: + self.bot.load_extension(self.path + module) await ctx.send("**`SUCCESS`**") - @commands.command(name="unload", hidden=True) + @commands.has_permissions(admin=True) @commands.is_owner() async def unload(self, ctx, *, cog: str = None): - self.bot.unload_extension(self.path + cog) + cog = self.parse_args(cog) + for module in cog: + self.bot.unload_extension(self.path + module) await ctx.send("**`SUCCESS`**") - @commands.command(name="reload", hidden=True) + @commands.has_permissions(admin=True) @commands.is_owner() async def reload(self, ctx, *, cog: str = None): - self.bot.unload_extension(self.path + cog) - self.bot.load_extension(self.path + cog) + cog = self.parse_args(cog) + for module in cog: + self.bot.unload_extension(self.path + module) + self.bot.load_extension(self.path + module) await ctx.send("**`SUCCESS`**") + def parse_args(self, cog): + if cog is None: + cog = [cg for cg in + self.bot.config["extensions"] + if 'user' in cg] + return cog + + if isinstance(cog, str): + if ' ' in cog: + raise ValueError('One module at a time!') + if cog in ('owner', 'settings'): + cog = 'dev.' + cog + else: + if 'user' not in cog: + cog = 'user.' + cog + cog = [cog] + return cog @reload.error @load.error @unload.error - async def error_owner(self, ctx, error): - if isinstance(error, commands.NotOwner): - await ctx.send(f"ERROR: {error}") + async def error(self, ctx, error): + if isinstance(error, (commands.NotOwner, + commands.errors.CommandInvokeError)): + await ctx.send(f"```ERROR: {error.__cause__}```") + else: + print(error) def setup(bot): From 21f8a0b1e258a9543754c2d4238f4674ff4ce995 Mon Sep 17 00:00:00 2001 From: titigmr Date: Mon, 22 Nov 2021 23:57:58 +0100 Subject: [PATCH 03/19] refacto --- bot/_bot.py | 3 ++- cogs/dev/owner.py | 7 +++---- cogs/user/ufd.py | 38 ++++++++++++++++++-------------------- cogs/utils/_dice.py | 22 ++++++++++++++-------- cogs/utils/_help.py | 2 +- cogs/utils/_ufd.py | 28 +++++++++++++--------------- 6 files changed, 51 insertions(+), 49 deletions(-) diff --git a/bot/_bot.py b/bot/_bot.py index 4d774f7..1acf127 100644 --- a/bot/_bot.py +++ b/bot/_bot.py @@ -13,7 +13,8 @@ def __init__(self, config, token): self.load_extension('cogs.' + extension) async def on_ready(self): - print(f'Logged in as {self.user} with extensions: \n{" ".join(self.extensions).replace("cogs.", "")}') + print((f'Logged in as {self.user} with extensions:' + f'\n{" ".join(self.extensions).replace("cogs.", "")}')) def run(self, *args, **kwargs): super().run(self.discord_token, reconnect=True) diff --git a/cogs/dev/owner.py b/cogs/dev/owner.py index b220ac8..097cf3f 100644 --- a/cogs/dev/owner.py +++ b/cogs/dev/owner.py @@ -1,5 +1,4 @@ from discord.ext import commands -from discord.ext.commands.core import command, has_permissions class Owner(commands.Cog): @@ -8,7 +7,7 @@ def __init__(self, bot): self.path = 'cogs.' @commands.command(name="load", hidden=True) - @commands.has_permissions(admin=True) + @commands.has_permissions() @commands.is_owner() async def load(self, ctx, *, cog: str = None): cog = self.parse_args(cog) @@ -17,7 +16,7 @@ async def load(self, ctx, *, cog: str = None): await ctx.send("**`SUCCESS`**") @commands.command(name="unload", hidden=True) - @commands.has_permissions(admin=True) + @commands.has_permissions() @commands.is_owner() async def unload(self, ctx, *, cog: str = None): cog = self.parse_args(cog) @@ -26,7 +25,7 @@ async def unload(self, ctx, *, cog: str = None): await ctx.send("**`SUCCESS`**") @commands.command(name="reload", hidden=True) - @commands.has_permissions(admin=True) + @commands.has_permissions() @commands.is_owner() async def reload(self, ctx, *, cog: str = None): cog = self.parse_args(cog) diff --git a/cogs/user/ufd.py b/cogs/user/ufd.py index 23d27f2..5d3227f 100644 --- a/cogs/user/ufd.py +++ b/cogs/user/ufd.py @@ -1,6 +1,7 @@ from textwrap import TextWrapper import discord from discord.ext import commands +from discord.ext.commands.errors import CommandInvokeError from cogs.utils import ( UltimateFD, @@ -60,24 +61,19 @@ async def ufd(self, ctx, command=None, *args): pass case _: - await ctx.channel.send(( + raise ValueError(( "Unrecognized command: make sure you're choosing " "between 'char', 'move', 'index'")) - return case _: if not self.n_args: - await ctx.channel.send('Must choice a move in "ufd list moves"') + raise ValueError('Must choice a move. Availables moves with "ufd list moves"') - try: - char = UltimateFD(character=command, - moves=self.args, - get_hitbox=True, - args_stats=None) + char = UltimateFD(character=command, + moves=self.args, + get_hitbox=True, + args_stats=None) - except (ValueError, KeyError) as error: - await ctx.channel.send(f"{error}") - return for move, statistics in char.stats.items(): embed, hitbox = self.create_stats(move=move, statistics=statistics) @@ -86,6 +82,14 @@ async def ufd(self, ctx, command=None, *args): if hitbox is not None: await ctx.channel.send(hitbox) + @ufd.error + async def error(self, ctx, error): + if isinstance(error, (commands.CommandOnCooldown, CommandInvokeError)): + if isinstance(CommandInvokeError): + error = error.__cause__ + await ctx.send(f'```ERROR: {error.__cause__}```') + print(error) + def show_list(self, selection): """ @@ -97,15 +101,8 @@ def show_list(self, selection): return names - @ufd.error - async def ufd_error(self, ctx, error): - if isinstance(error, commands.CommandOnCooldown): - await ctx.send(error) - else: - print(error) - - - def show_wrap_message(self, list_to_out, title, wrap_at=1000): + @staticmethod + def show_wrap_message(list_to_out, title, wrap_at=1000): """ Show embed message in discord channel with split at wrap_at (default: 1000 chars) @@ -126,6 +123,7 @@ def select_subcommand(self): return next(self.args) return "char" + def select_typecommand(self, choice: str ='char', selection=None): """ Select type command diff --git a/cogs/utils/_dice.py b/cogs/utils/_dice.py index c286124..9e27a67 100644 --- a/cogs/utils/_dice.py +++ b/cogs/utils/_dice.py @@ -19,9 +19,15 @@ class DiceGenerator: """ Dice Image Generator """ - def __init__(self, pt1=(30, 70), pt2=(70, 30), - thinkness=5, shape=(100, 100, 3), - xy=(50, 52), crop=(200, 200), directory='_img_dices'): + + def __init__(self, + pt1=(30, 70), + pt2=(70, 30), + thinkness=5, + shape=(100, 100, 3), + xy=(50, 52), + crop=(200, 200), + directory='_img_dices'): """ Usage example: TODO @@ -34,10 +40,10 @@ def __init__(self, pt1=(30, 70), pt2=(70, 30), self.crop = crop self.directory = self.get_path(directory) - def create_lauch_dice(self, inputs_dice: list, colors='green', line_return: int = 3, save=True): """ - Draw a dice or multiple dices side by side with a value number and a color. + Draw a dice or multiple dices side by side with + a value number and a color. Params: ------ @@ -68,9 +74,9 @@ def create_lauch_dice(self, inputs_dice: list, colors='green', line_return: int list_img = [] img = self.create_image_dice(value=i, - size=50, - color=c, - border=1, save=False) + size=50, + color=c, + border=1, save=False) list_img.append(img) if n == last: line_img = self.create_side_by_side( diff --git a/cogs/utils/_help.py b/cogs/utils/_help.py index 061774a..7154782 100644 --- a/cogs/utils/_help.py +++ b/cogs/utils/_help.py @@ -3,7 +3,7 @@ -with open('config.json') as f: +with open('config.json', 'r', encoding='utf-8') as f: config_arg = json.load(f)["command_prefix"] diff --git a/cogs/utils/_ufd.py b/cogs/utils/_ufd.py index 70702d1..2be3d63 100644 --- a/cogs/utils/_ufd.py +++ b/cogs/utils/_ufd.py @@ -25,21 +25,22 @@ DEFAULT_STATS = ["startup", "advantage", "activeframes", "totalframes", "basedamage", "shieldstun"] -DEFAULT_EXCLUDE_OVERALL_STATS = ["Stats", "Initial Dash", 'Walk Speed', - "SH / FH / SHFF / FHFF Frames", +DEFAULT_EXCLUDE_OVERALL_STATS = ['Stats', 'Initial Dash', + 'Walk Speed', + 'SH / FH / SHFF / FHFF Frames', 'Shield Drop', 'Jump Squat'] class UltimateFD: def __init__(self, - character: str=None, + character: str = None, moves: str = None, args_stats=None, - get_hitbox: bool =False, - exclude_stats: list =['movename', - 'whichhitbox', - 'notes'], - exclude_moves: list =['dodge']): + get_hitbox: bool = False, + exclude_stats: list = ['movename', + 'whichhitbox', + 'notes'], + exclude_moves: list = ['dodge']): self.char = character self.exclude_moves = exclude_moves @@ -58,7 +59,7 @@ def __init__(self, for move in moves: st_move = self.get_character_moves(data=data_move, - move=move) + move=move) stats = self.get_stats_move(st_move, get_hitbox, @@ -67,8 +68,7 @@ def __init__(self, if not self.stats: list_moves = list(REF_ATK.keys()) - raise KeyError(f'No moves found. Moves must be in: {list_moves}') - + raise ValueError(f"No moves found. Moves must be in: {list_moves}") def _get_soup(self, url): """ @@ -80,7 +80,6 @@ def _get_soup(self, url): f'Choose a valid character in: {list(self.all_char.keys())}') return BeautifulSoup(response.content, 'lxml') - def get_stats_move(self, stats_move, image, *kwargs): out_move = {} @@ -112,13 +111,13 @@ def get_stats_move(self, stats_move, image, *kwargs): out_move[move] = out_stats return out_move - def _format_stats(self, soup, class_name): + @staticmethod + def _format_stats(soup, class_name): soup = soup.find(class_=class_name) if soup is not None: return soup.text.strip() return None - def get_character_data(self, name): """ Get list characters moves @@ -132,7 +131,6 @@ def get_character_data(self, name): if mv.find(class_='movename') is not None} return data_move - def get_character_moves(self, data: dict, move: str): """ Select move in data moves From 3ad048432b6f416b9954b1dbdba15a2d414d2d72 Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 00:13:15 +0100 Subject: [PATCH 04/19] add test ufd --- .gitignore | 2 ++ Dockerfile.armv7l | 2 +- Dockerfile.x86_64 | 3 +-- {cogs => bot/cogs}/dev/owner.py | 0 {cogs => bot/cogs}/dev/settings.py | 0 {cogs => bot/cogs}/user/dice.py | 0 {cogs => bot/cogs}/user/john.py | 0 {cogs => bot/cogs}/user/poll.py | 0 {cogs => bot/cogs}/user/ufd.py | 0 {cogs => bot/cogs}/utils/__init__.py | 0 {cogs => bot/cogs}/utils/_args.py | 0 {cogs => bot/cogs}/utils/_dice.py | 0 {cogs => bot/cogs}/utils/_help.py | 0 {cogs => bot/cogs}/utils/_poll.py | 0 {cogs => bot/cogs}/utils/_ufd.py | 0 requirements.txt => bot/requirements.txt | 3 ++- bot/setup.py | 9 +++++++++ tests/test_ufd.py | 14 ++++++++++++++ 18 files changed, 29 insertions(+), 4 deletions(-) rename {cogs => bot/cogs}/dev/owner.py (100%) rename {cogs => bot/cogs}/dev/settings.py (100%) rename {cogs => bot/cogs}/user/dice.py (100%) rename {cogs => bot/cogs}/user/john.py (100%) rename {cogs => bot/cogs}/user/poll.py (100%) rename {cogs => bot/cogs}/user/ufd.py (100%) rename {cogs => bot/cogs}/utils/__init__.py (100%) rename {cogs => bot/cogs}/utils/_args.py (100%) rename {cogs => bot/cogs}/utils/_dice.py (100%) rename {cogs => bot/cogs}/utils/_help.py (100%) rename {cogs => bot/cogs}/utils/_poll.py (100%) rename {cogs => bot/cogs}/utils/_ufd.py (100%) rename requirements.txt => bot/requirements.txt (75%) create mode 100644 bot/setup.py create mode 100644 tests/test_ufd.py diff --git a/.gitignore b/.gitignore index 91840aa..2b783b3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ _img_dices # env .env +# test +.pytest_cache diff --git a/Dockerfile.armv7l b/Dockerfile.armv7l index 75d9787..12c5802 100644 --- a/Dockerfile.armv7l +++ b/Dockerfile.armv7l @@ -3,7 +3,7 @@ ENV DISCORD_TOKEN=${DISCORD_TOKEN} WORKDIR /ramoloss COPY . . RUN apt-get update && apt-get install libatlas-base-dev -y \ - && pip install --no-cache-dir -r requirements.txt \ + && pip install --no-cache-dir -e bot/ \ -i https://www.piwheels.org/simple CMD [ "python", "main.py"] diff --git a/Dockerfile.x86_64 b/Dockerfile.x86_64 index 1a88fe7..6da4cc0 100644 --- a/Dockerfile.x86_64 +++ b/Dockerfile.x86_64 @@ -2,7 +2,6 @@ FROM python:3.7-buster as x86_64 ENV DISCORD_TOKEN=${DISCORD_TOKEN} WORKDIR /ramoloss COPY . . -RUN apt-get update && pip install --no-cache-dir \ - -r requirements.txt +RUN apt-get update && pip install --no-cache-dir -e bot/ CMD [ "python", "main.py"] diff --git a/cogs/dev/owner.py b/bot/cogs/dev/owner.py similarity index 100% rename from cogs/dev/owner.py rename to bot/cogs/dev/owner.py diff --git a/cogs/dev/settings.py b/bot/cogs/dev/settings.py similarity index 100% rename from cogs/dev/settings.py rename to bot/cogs/dev/settings.py diff --git a/cogs/user/dice.py b/bot/cogs/user/dice.py similarity index 100% rename from cogs/user/dice.py rename to bot/cogs/user/dice.py diff --git a/cogs/user/john.py b/bot/cogs/user/john.py similarity index 100% rename from cogs/user/john.py rename to bot/cogs/user/john.py diff --git a/cogs/user/poll.py b/bot/cogs/user/poll.py similarity index 100% rename from cogs/user/poll.py rename to bot/cogs/user/poll.py diff --git a/cogs/user/ufd.py b/bot/cogs/user/ufd.py similarity index 100% rename from cogs/user/ufd.py rename to bot/cogs/user/ufd.py diff --git a/cogs/utils/__init__.py b/bot/cogs/utils/__init__.py similarity index 100% rename from cogs/utils/__init__.py rename to bot/cogs/utils/__init__.py diff --git a/cogs/utils/_args.py b/bot/cogs/utils/_args.py similarity index 100% rename from cogs/utils/_args.py rename to bot/cogs/utils/_args.py diff --git a/cogs/utils/_dice.py b/bot/cogs/utils/_dice.py similarity index 100% rename from cogs/utils/_dice.py rename to bot/cogs/utils/_dice.py diff --git a/cogs/utils/_help.py b/bot/cogs/utils/_help.py similarity index 100% rename from cogs/utils/_help.py rename to bot/cogs/utils/_help.py diff --git a/cogs/utils/_poll.py b/bot/cogs/utils/_poll.py similarity index 100% rename from cogs/utils/_poll.py rename to bot/cogs/utils/_poll.py diff --git a/cogs/utils/_ufd.py b/bot/cogs/utils/_ufd.py similarity index 100% rename from cogs/utils/_ufd.py rename to bot/cogs/utils/_ufd.py diff --git a/requirements.txt b/bot/requirements.txt similarity index 75% rename from requirements.txt rename to bot/requirements.txt index 9621f08..715bf99 100644 --- a/requirements.txt +++ b/bot/requirements.txt @@ -3,6 +3,7 @@ discord.py==1.7.3 lxml==4.6.3 matplotlib==3.4.3 numpy==1.21.2 -opencv-python==4.5.3.56 +#opencv-python==4.5.3.56 Pillow==8.3.2 requests==2.26.0 +pytest==6.2.5 \ No newline at end of file diff --git a/bot/setup.py b/bot/setup.py new file mode 100644 index 0000000..9936377 --- /dev/null +++ b/bot/setup.py @@ -0,0 +1,9 @@ +from setuptools import setup, find_packages + + +REQUIRED_PACKAGES = open('requirements.txt').readlines() + +setup(name="bot", + install_requires=REQUIRED_PACKAGES, + packages=find_packages(), + description='Bot SSBU') \ No newline at end of file diff --git a/tests/test_ufd.py b/tests/test_ufd.py new file mode 100644 index 0000000..9ae08ad --- /dev/null +++ b/tests/test_ufd.py @@ -0,0 +1,14 @@ +from bot.cogs.utils import UltimateFD + + +class TestUFD: + def test_char(self): + ufd = UltimateFD() + char = ufd.all_char + assert 'wario' in list(char.keys()) + assert 'sora' in list(char.keys()) + assert 'donkey_kong' in list(char.keys()) + + def test_move(self): + pass + From a5dcc016e3beedebab32baa90494850be98693e2 Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 01:03:07 +0100 Subject: [PATCH 05/19] add test UFD module --- bot/cogs/utils/_ufd.py | 3 ++- bot/requirements.txt | 5 +++-- bot/setup.py | 6 +++--- tests/test_ufd.py | 27 +++++++++++++++++++++------ 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/bot/cogs/utils/_ufd.py b/bot/cogs/utils/_ufd.py index 2be3d63..964f9b3 100644 --- a/bot/cogs/utils/_ufd.py +++ b/bot/cogs/utils/_ufd.py @@ -34,7 +34,7 @@ class UltimateFD: def __init__(self, character: str = None, - moves: str = None, + moves: str | list = None, args_stats=None, get_hitbox: bool = False, exclude_stats: list = ['movename', @@ -54,6 +54,7 @@ def __init__(self, if character is None: return + moves = moves if isinstance(moves, list) else [moves] moves = list(REF_ATK.keys()) if moves == 'all' else moves data_move = self.get_character_data(name=character) diff --git a/bot/requirements.txt b/bot/requirements.txt index 715bf99..776be9e 100644 --- a/bot/requirements.txt +++ b/bot/requirements.txt @@ -3,7 +3,8 @@ discord.py==1.7.3 lxml==4.6.3 matplotlib==3.4.3 numpy==1.21.2 -#opencv-python==4.5.3.56 +opencv-python==4.5.3.56 Pillow==8.3.2 requests==2.26.0 -pytest==6.2.5 \ No newline at end of file +pytest==6.2.5 +dpytest==0.5.3 \ No newline at end of file diff --git a/bot/setup.py b/bot/setup.py index 9936377..f7e580e 100644 --- a/bot/setup.py +++ b/bot/setup.py @@ -1,9 +1,9 @@ from setuptools import setup, find_packages - -REQUIRED_PACKAGES = open('requirements.txt').readlines() +with open('requirements.txt', 'r', encoding='utf-8') as f: + REQUIRED_PACKAGES = f.readlines() setup(name="bot", install_requires=REQUIRED_PACKAGES, packages=find_packages(), - description='Bot SSBU') \ No newline at end of file + description='Bot SSBU') diff --git a/tests/test_ufd.py b/tests/test_ufd.py index 9ae08ad..5a7f5cb 100644 --- a/tests/test_ufd.py +++ b/tests/test_ufd.py @@ -1,14 +1,29 @@ -from bot.cogs.utils import UltimateFD +from bot.cogs.utils import UltimateFD, REF_ATK class TestUFD: def test_char(self): + """ + Test list of character is valid + """ ufd = UltimateFD() - char = ufd.all_char - assert 'wario' in list(char.keys()) - assert 'sora' in list(char.keys()) - assert 'donkey_kong' in list(char.keys()) + char = list(ufd.all_char.keys()) + assert 'wario' in char + assert 'sora' in char + assert 'donkey_kong' in char + assert 'http' not in char def test_move(self): - pass + ufd = UltimateFD(character='wario', + moves='fair') + move = ufd.stats + assert any(REF_ATK["fair"] in key for key in move) + + def test_list_moves(self): + ufd = UltimateFD(character='wario', + moves=['ub', 'nair']) + move = ufd.stats + assert any(REF_ATK["ub"] in key for key in move) + assert any(REF_ATK["nair"] in key for key in move) + From 6f3923650e52d4e572999a0626b5f1d4edad6ec0 Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 02:42:13 +0100 Subject: [PATCH 06/19] test discord --- bot/_bot.py | 8 +++++--- tests/test_settings.py | 27 +++++++++++++++++++++++++++ tests/test_ufd.py | 25 +++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 tests/test_settings.py diff --git a/bot/_bot.py b/bot/_bot.py index 1acf127..414eac4 100644 --- a/bot/_bot.py +++ b/bot/_bot.py @@ -2,13 +2,15 @@ class Ramoloss(Bot): - def __init__(self, config, token): + def __init__(self, config, token, **kwargs): self.config = config self.discord_token = token + super().__init__( command_prefix=self.config["command_prefix"], - description=self.config["description"] - ) + description=self.config["description"], + **kwargs) + for extension in self.config["extensions"]: self.load_extension('cogs.' + extension) diff --git a/tests/test_settings.py b/tests/test_settings.py new file mode 100644 index 0000000..1e9fbbc --- /dev/null +++ b/tests/test_settings.py @@ -0,0 +1,27 @@ +import json +import pytest +import discord +from bot import Ramoloss +import discord.ext.test as dpytest + + +with open('config.json', 'r', encoding='utf-8') as config_file: + CONFIG = json.load(config_file) + + +@pytest.fixture +def bot_instance(event_loop): + intents = discord.Intents.default() + intents.members = True + bot_ramoloss = Ramoloss(config=CONFIG, + token=None, + loop=event_loop, + intents=intents) + dpytest.configure(bot_ramoloss) + return bot_ramoloss + + +@pytest.mark.asyncio +async def test_ping(bot_instance): + await dpytest.message("!hello") + assert dpytest.verify().message().contains().content("Hello") \ No newline at end of file diff --git a/tests/test_ufd.py b/tests/test_ufd.py index 5a7f5cb..62bda62 100644 --- a/tests/test_ufd.py +++ b/tests/test_ufd.py @@ -1,3 +1,8 @@ +import json +import pytest +import discord +import discord.ext.test as dpytest +from bot import Ramoloss from bot.cogs.utils import UltimateFD, REF_ATK @@ -27,3 +32,23 @@ def test_list_moves(self): assert any(REF_ATK["nair"] in key for key in move) +with open('config.json', 'r', encoding='utf-8') as config_file: + config = json.load(config_file) + + +@pytest.fixture +def bot_instance(event_loop): + intents = discord.Intents.default() + intents.members = True + bot_ramoloss = Ramoloss(config=config, + token=None, + loop=event_loop, + intents=intents) + dpytest.configure(bot_ramoloss) + return bot_ramoloss + + +@pytest.mark.asyncio +async def test_ping(bot_instance): + await dpytest.message("!ufd wario nair") + assert dpytest.verify().message().contains().content("Wario") From a6e36cedf69af1ec23e88ab19863b964c8b1fb55 Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 03:43:38 +0100 Subject: [PATCH 07/19] valid test --- bot/cogs/user/ufd.py | 2 +- bot/cogs/utils/_ufd.py | 6 ++-- tests/test_ufd.py | 71 ++++++++++++++++++++++++++++++++---------- 3 files changed, 59 insertions(+), 20 deletions(-) diff --git a/bot/cogs/user/ufd.py b/bot/cogs/user/ufd.py index 5d3227f..e196565 100644 --- a/bot/cogs/user/ufd.py +++ b/bot/cogs/user/ufd.py @@ -85,7 +85,7 @@ async def ufd(self, ctx, command=None, *args): @ufd.error async def error(self, ctx, error): if isinstance(error, (commands.CommandOnCooldown, CommandInvokeError)): - if isinstance(CommandInvokeError): + if isinstance(error, CommandInvokeError): error = error.__cause__ await ctx.send(f'```ERROR: {error.__cause__}```') print(error) diff --git a/bot/cogs/utils/_ufd.py b/bot/cogs/utils/_ufd.py index 964f9b3..f9f8fb3 100644 --- a/bot/cogs/utils/_ufd.py +++ b/bot/cogs/utils/_ufd.py @@ -34,7 +34,7 @@ class UltimateFD: def __init__(self, character: str = None, - moves: str | list = None, + moves=None, args_stats=None, get_hitbox: bool = False, exclude_stats: list = ['movename', @@ -54,14 +54,14 @@ def __init__(self, if character is None: return - moves = moves if isinstance(moves, list) else [moves] moves = list(REF_ATK.keys()) if moves == 'all' else moves + moves = [moves] if isinstance(moves, str) else moves + data_move = self.get_character_data(name=character) for move in moves: st_move = self.get_character_moves(data=data_move, move=move) - stats = self.get_stats_move(st_move, get_hitbox, *self.args_stats) diff --git a/tests/test_ufd.py b/tests/test_ufd.py index 62bda62..af5d3e1 100644 --- a/tests/test_ufd.py +++ b/tests/test_ufd.py @@ -1,11 +1,28 @@ import json import pytest import discord +import time import discord.ext.test as dpytest from bot import Ramoloss from bot.cogs.utils import UltimateFD, REF_ATK +with open('config.json', 'r', encoding='utf-8') as config_file: + config = json.load(config_file) + + +@pytest.fixture +def bot_instance(event_loop): + intents = discord.Intents.default() + intents.members = True + bot_ramoloss = Ramoloss(config=config, + token=None, + loop=event_loop, + intents=intents) + dpytest.configure(bot_ramoloss) + return bot_ramoloss + + class TestUFD: def test_char(self): """ @@ -17,12 +34,14 @@ def test_char(self): assert 'sora' in char assert 'donkey_kong' in char assert 'http' not in char + time.sleep(1) def test_move(self): ufd = UltimateFD(character='wario', moves='fair') move = ufd.stats assert any(REF_ATK["fair"] in key for key in move) + time.sleep(1) def test_list_moves(self): ufd = UltimateFD(character='wario', @@ -30,25 +49,45 @@ def test_list_moves(self): move = ufd.stats assert any(REF_ATK["ub"] in key for key in move) assert any(REF_ATK["nair"] in key for key in move) + time.sleep(1) -with open('config.json', 'r', encoding='utf-8') as config_file: - config = json.load(config_file) +class TestDiscordUFD: + @pytest.mark.asyncio + async def test_move_command(self, bot_instance): + await dpytest.message("!ufd list moves") + description = dpytest.get_embed().description + assert 'dair' in description + assert 'fsmash' in description + assert 'nb' in description + time.sleep(1) -@pytest.fixture -def bot_instance(event_loop): - intents = discord.Intents.default() - intents.members = True - bot_ramoloss = Ramoloss(config=config, - token=None, - loop=event_loop, - intents=intents) - dpytest.configure(bot_ramoloss) - return bot_ramoloss + + @pytest.mark.asyncio + async def test_char_command(self, bot_instance): + await dpytest.message("!ufd list char") + description = dpytest.get_embed().description + assert 'wario' in description + assert 'sora' in description + assert 'captain_falcon' in description + time.sleep(1) + + + @pytest.mark.asyncio + async def test_wario_command_title(self, bot_instance): + await dpytest.message("!ufd wario ub") + title = dpytest.get_embed().title + assert 'Wario' in title + assert 'Up B' in title + time.sleep(1) + + + async def test_wario_command_stats(self, bot_instance): + await dpytest.message("!ufd wario ub") + fields = dpytest.get_embed().fields + assert 'Startup' in fields + assert 'Shieldstun' in fields + time.sleep(1) -@pytest.mark.asyncio -async def test_ping(bot_instance): - await dpytest.message("!ufd wario nair") - assert dpytest.verify().message().contains().content("Wario") From 451ec05ffc428f8da78af77c6467f97d3bf8968f Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 03:47:40 +0100 Subject: [PATCH 08/19] autopep8 --- tests/test_settings.py | 3 ++- tests/test_ufd.py | 8 +------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/test_settings.py b/tests/test_settings.py index 1e9fbbc..6c056ca 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -1,8 +1,9 @@ import json import pytest import discord -from bot import Ramoloss import discord.ext.test as dpytest +from bot import Ramoloss + with open('config.json', 'r', encoding='utf-8') as config_file: diff --git a/tests/test_ufd.py b/tests/test_ufd.py index af5d3e1..8b8eadf 100644 --- a/tests/test_ufd.py +++ b/tests/test_ufd.py @@ -1,7 +1,7 @@ import json +import time import pytest import discord -import time import discord.ext.test as dpytest from bot import Ramoloss from bot.cogs.utils import UltimateFD, REF_ATK @@ -53,7 +53,6 @@ def test_list_moves(self): class TestDiscordUFD: - @pytest.mark.asyncio async def test_move_command(self, bot_instance): await dpytest.message("!ufd list moves") @@ -63,7 +62,6 @@ async def test_move_command(self, bot_instance): assert 'nb' in description time.sleep(1) - @pytest.mark.asyncio async def test_char_command(self, bot_instance): await dpytest.message("!ufd list char") @@ -73,7 +71,6 @@ async def test_char_command(self, bot_instance): assert 'captain_falcon' in description time.sleep(1) - @pytest.mark.asyncio async def test_wario_command_title(self, bot_instance): await dpytest.message("!ufd wario ub") @@ -82,12 +79,9 @@ async def test_wario_command_title(self, bot_instance): assert 'Up B' in title time.sleep(1) - async def test_wario_command_stats(self, bot_instance): await dpytest.message("!ufd wario ub") fields = dpytest.get_embed().fields assert 'Startup' in fields assert 'Shieldstun' in fields time.sleep(1) - - From e2b2b4293e0915bf5234d662b3e6823d8d59468a Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 03:58:47 +0100 Subject: [PATCH 09/19] add ci pytest --- Makefile | 4 +++- bot/cogs/user/ufd.py | 2 +- ci/build.sh | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 6316413..8798ac9 100644 --- a/Makefile +++ b/Makefile @@ -71,8 +71,10 @@ test-%: @echo "# test $*" bash tests/test-$*.sh -# push +pytest: + python -m pytest tests/ +# push push: push-bot push-%: diff --git a/bot/cogs/user/ufd.py b/bot/cogs/user/ufd.py index e196565..91f898b 100644 --- a/bot/cogs/user/ufd.py +++ b/bot/cogs/user/ufd.py @@ -58,7 +58,7 @@ async def ufd(self, ctx, command=None, *args): await ctx.channel.send(embed=embed_m) case 'index': - pass + raise NotImplementedError case _: raise ValueError(( diff --git a/ci/build.sh b/ci/build.sh index ef845e9..4fa6c6a 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -4,4 +4,5 @@ set -e make build make up make test +make pytest make down \ No newline at end of file From e38e4ef008cb14f2efda3c73d134c933a0420e64 Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 04:03:12 +0100 Subject: [PATCH 10/19] upgrade 3.10 docker image --- Dockerfile.armv7l | 2 +- Dockerfile.x86_64 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile.armv7l b/Dockerfile.armv7l index 12c5802..acdbecc 100644 --- a/Dockerfile.armv7l +++ b/Dockerfile.armv7l @@ -1,4 +1,4 @@ -FROM arm32v7/python:3.7-buster as arch_armv7l +FROM arm32v7/python:3.10-buster as arch_armv7l ENV DISCORD_TOKEN=${DISCORD_TOKEN} WORKDIR /ramoloss COPY . . diff --git a/Dockerfile.x86_64 b/Dockerfile.x86_64 index 6da4cc0..21c8cb6 100644 --- a/Dockerfile.x86_64 +++ b/Dockerfile.x86_64 @@ -1,4 +1,4 @@ -FROM python:3.7-buster as x86_64 +FROM python:3.10-buster as x86_64 ENV DISCORD_TOKEN=${DISCORD_TOKEN} WORKDIR /ramoloss COPY . . From a1215373ab6258b564dee11047820da32a25c13c Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 04:07:50 +0100 Subject: [PATCH 11/19] upgrade opencv --- bot/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/requirements.txt b/bot/requirements.txt index 776be9e..8cb8a65 100644 --- a/bot/requirements.txt +++ b/bot/requirements.txt @@ -3,7 +3,7 @@ discord.py==1.7.3 lxml==4.6.3 matplotlib==3.4.3 numpy==1.21.2 -opencv-python==4.5.3.56 +opencv-python==4.5.4.60 Pillow==8.3.2 requests==2.26.0 pytest==6.2.5 From 01ad875ee482d21fb48694e1e0c3c3c952f5f9aa Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 04:16:37 +0100 Subject: [PATCH 12/19] add pytest exec in docker --- Makefile | 3 ++- bot/requirements.txt | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8798ac9..9895624 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,8 @@ test-%: bash tests/test-$*.sh pytest: - python -m pytest tests/ + docker -it exec bot python -m pytest tests/ + exit # push push: push-bot diff --git a/bot/requirements.txt b/bot/requirements.txt index 8cb8a65..5583601 100644 --- a/bot/requirements.txt +++ b/bot/requirements.txt @@ -1,7 +1,7 @@ beautifulsoup4==4.10.0 discord.py==1.7.3 lxml==4.6.3 -matplotlib==3.4.3 +matplotlib==3.5.0 numpy==1.21.2 opencv-python==4.5.4.60 Pillow==8.3.2 From ded1043e79a78f91a6fc8952b1e21d168762bde9 Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 23 Nov 2021 04:24:11 +0100 Subject: [PATCH 13/19] correct --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9895624..049d3d1 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ test-%: bash tests/test-$*.sh pytest: - docker -it exec bot python -m pytest tests/ + docker exec -it bot python -m pytest tests/ exit # push From 55a03797a25a6cf1223fbcdd43e63387d2717820 Mon Sep 17 00:00:00 2001 From: titigmr Date: Sat, 27 Nov 2021 01:37:36 +0100 Subject: [PATCH 14/19] add test --- Dockerfile.armv7l | 2 ++ Dockerfile.x86_64 | 1 + Makefile | 4 ---- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Dockerfile.armv7l b/Dockerfile.armv7l index acdbecc..83c9cf6 100644 --- a/Dockerfile.armv7l +++ b/Dockerfile.armv7l @@ -5,5 +5,7 @@ COPY . . RUN apt-get update && apt-get install libatlas-base-dev -y \ && pip install --no-cache-dir -e bot/ \ -i https://www.piwheels.org/simple + +RUN pytest tests/ CMD [ "python", "main.py"] diff --git a/Dockerfile.x86_64 b/Dockerfile.x86_64 index 21c8cb6..39c3920 100644 --- a/Dockerfile.x86_64 +++ b/Dockerfile.x86_64 @@ -3,5 +3,6 @@ ENV DISCORD_TOKEN=${DISCORD_TOKEN} WORKDIR /ramoloss COPY . . RUN apt-get update && pip install --no-cache-dir -e bot/ +RUN pytest tests/ CMD [ "python", "main.py"] diff --git a/Makefile b/Makefile index 049d3d1..8a11041 100644 --- a/Makefile +++ b/Makefile @@ -71,10 +71,6 @@ test-%: @echo "# test $*" bash tests/test-$*.sh -pytest: - docker exec -it bot python -m pytest tests/ - exit - # push push: push-bot From 227ffa2b905f18affee00715e7139b2f136503d4 Mon Sep 17 00:00:00 2001 From: titigmr Date: Tue, 30 Nov 2021 15:53:22 +0100 Subject: [PATCH 15/19] change test --- .gitignore | 2 ++ Makefile | 10 ++++++++-- bot/cogs/utils/_ufd.py | 4 ++-- save/create-save.py | 16 ++++++++++++++++ tests/test-container.sh | 6 +++--- tests/test_settings.py | 4 ++-- tests/test_ufd.py | 37 +++++++++++++++++++++++++------------ 7 files changed, 58 insertions(+), 21 deletions(-) create mode 100644 save/create-save.py diff --git a/.gitignore b/.gitignore index 2b783b3..41927af 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ _img_dices # test .pytest_cache +*.html +.env diff --git a/Makefile b/Makefile index 8a11041..2bc0819 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +# include env var +include .env + # repository SHELL = /bin/bash NAME ?= ramoloss @@ -22,7 +25,6 @@ IMAGE_REGISTRY_bot=${REGISTRY}/${REGISTRY_USERNAME}/${IMAGE_bot} export - all: @echo "Usage: NAME=ramoloss make deploy | build | \ up | down | test | check | push | pull " @@ -87,4 +89,8 @@ pull-%: @if [ -n "${REGISTRY_TOKEN}" -a -n "${REGISTRY_LOGIN}" ] ;\ then echo ${REGISTRY_TOKEN} | docker login ${REGISTRY} \ --username ${REGISTRY_LOGIN} --password-stdin ; fi - docker pull ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:latest \ No newline at end of file + docker pull ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:latest + docker tag ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:latest ${NAME}-$*:latest + +deploy: pull up + diff --git a/bot/cogs/utils/_ufd.py b/bot/cogs/utils/_ufd.py index f9f8fb3..ff06ff6 100644 --- a/bot/cogs/utils/_ufd.py +++ b/bot/cogs/utils/_ufd.py @@ -47,7 +47,6 @@ def __init__(self, self.exclude_stats = exclude_stats self.url = "https://ultimateframedata.com/" self.stats = {} - self.all_char = self.get_all_characters(self.url) self.avalaible_stats = {} self.args_stats = DEFAULT_STATS if args_stats is None else args_stats @@ -77,8 +76,9 @@ def _get_soup(self, url): """ response = requests.get(url) if response.status_code != 200: + all_char = self.get_all_characters(self.url) raise ValueError( - f'Choose a valid character in: {list(self.all_char.keys())}') + f'Choose a valid character in: {list(all_char.keys())}') return BeautifulSoup(response.content, 'lxml') def get_stats_move(self, stats_move, image, *kwargs): diff --git a/save/create-save.py b/save/create-save.py new file mode 100644 index 0000000..345d32a --- /dev/null +++ b/save/create-save.py @@ -0,0 +1,16 @@ +import requests +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument('--url', '-u', nargs='*') +parser.add_argument('--name', '-n', nargs='*') + +def write_response(url, file): + content = requests.get(url).content + with open(f'save/{file}.html', 'wb') as f: + f.write(content) + +if __name__ == '__main__': + args = parser.parse_args() + for filename, url_name in zip(args.name, args.url): + write_response(file=filename, url=url_name) \ No newline at end of file diff --git a/tests/test-container.sh b/tests/test-container.sh index c76ba06..6b01a09 100644 --- a/tests/test-container.sh +++ b/tests/test-container.sh @@ -1,11 +1,11 @@ #!/bin/bash -set -e +set -ex -active_container=$(docker ps --filter "name=$APP_NAME" -q) +active_container=$(docker ps --filter "name=bot-$NAME" -q) if [ -z "${active_container}" ]; then echo "no container is running" exit 1 else - echo "container $APP_NAME with id $active_container is running" + echo "container bot-$NAME with id $active_container is running" fi \ No newline at end of file diff --git a/tests/test_settings.py b/tests/test_settings.py index 6c056ca..183ae7b 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -13,7 +13,7 @@ @pytest.fixture def bot_instance(event_loop): intents = discord.Intents.default() - intents.members = True + setattr(intents, 'members', True) bot_ramoloss = Ramoloss(config=CONFIG, token=None, loop=event_loop, @@ -25,4 +25,4 @@ def bot_instance(event_loop): @pytest.mark.asyncio async def test_ping(bot_instance): await dpytest.message("!hello") - assert dpytest.verify().message().contains().content("Hello") \ No newline at end of file + assert dpytest.verify().message().contains().content("Hello") diff --git a/tests/test_ufd.py b/tests/test_ufd.py index 8b8eadf..574fd0b 100644 --- a/tests/test_ufd.py +++ b/tests/test_ufd.py @@ -1,5 +1,5 @@ import json -import time +import requests import pytest import discord import discord.ext.test as dpytest @@ -14,7 +14,7 @@ @pytest.fixture def bot_instance(event_loop): intents = discord.Intents.default() - intents.members = True + setattr(intents, 'members', True) bot_ramoloss = Ramoloss(config=config, token=None, loop=event_loop, @@ -23,25 +23,43 @@ def bot_instance(event_loop): return bot_ramoloss +class MockResponse: + def __init__(self): + self.status_code = 200 + self.content = MockResponse.open_file('wario') + + @staticmethod + def open_file(filename): + with open(f'save/{filename}.html', 'r', encoding='utf-8') as file: + file_content = str(file.readlines()) + return file_content + + def get(self): + return + +def mock_get(*args, **kwargs): + return MockResponse() + + class TestUFD: - def test_char(self): + def test_char(self, monkeypatch): """ Test list of character is valid """ + monkeypatch.setattr(requests, 'get', mock_get) ufd = UltimateFD() - char = list(ufd.all_char.keys()) + char = list(ufd.get_all_characters(ufd.url).keys()) assert 'wario' in char assert 'sora' in char assert 'donkey_kong' in char assert 'http' not in char - time.sleep(1) - def test_move(self): + def test_move(self, monkeypatch): + monkeypatch.setattr(requests, "get", mock_get) ufd = UltimateFD(character='wario', moves='fair') move = ufd.stats assert any(REF_ATK["fair"] in key for key in move) - time.sleep(1) def test_list_moves(self): ufd = UltimateFD(character='wario', @@ -49,7 +67,6 @@ def test_list_moves(self): move = ufd.stats assert any(REF_ATK["ub"] in key for key in move) assert any(REF_ATK["nair"] in key for key in move) - time.sleep(1) class TestDiscordUFD: @@ -60,7 +77,6 @@ async def test_move_command(self, bot_instance): assert 'dair' in description assert 'fsmash' in description assert 'nb' in description - time.sleep(1) @pytest.mark.asyncio async def test_char_command(self, bot_instance): @@ -69,7 +85,6 @@ async def test_char_command(self, bot_instance): assert 'wario' in description assert 'sora' in description assert 'captain_falcon' in description - time.sleep(1) @pytest.mark.asyncio async def test_wario_command_title(self, bot_instance): @@ -77,11 +92,9 @@ async def test_wario_command_title(self, bot_instance): title = dpytest.get_embed().title assert 'Wario' in title assert 'Up B' in title - time.sleep(1) async def test_wario_command_stats(self, bot_instance): await dpytest.message("!ufd wario ub") fields = dpytest.get_embed().fields assert 'Startup' in fields assert 'Shieldstun' in fields - time.sleep(1) From 374baf3d6f5765fe1763add6110820397cf6f562 Mon Sep 17 00:00:00 2001 From: titigmr Date: Fri, 3 Dec 2021 12:55:47 +0100 Subject: [PATCH 16/19] remove env. --- Makefile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 2bc0819..a9ba301 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,3 @@ -# include env var -include .env - # repository SHELL = /bin/bash NAME ?= ramoloss @@ -93,4 +90,4 @@ pull-%: docker tag ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:latest ${NAME}-$*:latest deploy: pull up - + From 5401bed563b3dcaa31f705b5b021f086d2dee326 Mon Sep 17 00:00:00 2001 From: titigmr Date: Wed, 8 Dec 2021 21:48:13 +0100 Subject: [PATCH 17/19] add targets in Makefile and do linter --- Dockerfile.armv7l | 11 ++--------- Dockerfile.x86_64 | 1 - Makefile | 22 +++++++++++----------- bot/__init__.py | 4 +++- bot/cogs/dev/owner.py | 4 ++-- bot/cogs/dev/settings.py | 3 --- bot/cogs/user/dice.py | 1 - bot/cogs/user/john.py | 1 + bot/cogs/user/ufd.py | 32 +++++++++++++++----------------- bot/cogs/utils/__init__.py | 13 +++++++++++-- bot/cogs/utils/_dice.py | 32 +++++++++++++++++++++----------- bot/cogs/utils/_help.py | 13 +++++++------ bot/cogs/utils/_ufd.py | 6 ++++-- bot/requirements.txt | 4 ---- ci/deploy.sh | 0 save/create-save.py | 6 ++++-- tests/{ => bot}/test_settings.py | 1 - tests/{ => bot}/test_ufd.py | 3 ++- tests/test-bot.sh | 1 + tests/test-container.sh | 12 ------------ 20 files changed, 84 insertions(+), 86 deletions(-) create mode 100644 ci/deploy.sh rename tests/{ => bot}/test_settings.py (99%) rename tests/{ => bot}/test_ufd.py (99%) create mode 100644 tests/test-bot.sh diff --git a/Dockerfile.armv7l b/Dockerfile.armv7l index a6dbf96..275eede 100644 --- a/Dockerfile.armv7l +++ b/Dockerfile.armv7l @@ -2,14 +2,7 @@ FROM arm32v7/python:3.10-buster as arch_armv7l ENV DISCORD_TOKEN=${DISCORD_TOKEN} WORKDIR /ramoloss COPY . . -RUN apt-get update && apt-get install libatlas-base-dev -y \ -<<<<<<< HEAD - && pip install --no-cache-dir -e bot/ \ - -i https://www.piwheels.org/simple - -RUN pytest tests/ -======= - && pip install --no-cache-dir -r requirements.txt ->>>>>>> 2e73db2c69a28863c50d9d08c1ab95b8ee9ed139 +RUN apt-get update && apt-get install \ + libatlas-base-dev -y && pip install --no-cache-dir -r requirements.txt CMD [ "python", "main.py"] diff --git a/Dockerfile.x86_64 b/Dockerfile.x86_64 index 39c3920..21c8cb6 100644 --- a/Dockerfile.x86_64 +++ b/Dockerfile.x86_64 @@ -3,6 +3,5 @@ ENV DISCORD_TOKEN=${DISCORD_TOKEN} WORKDIR /ramoloss COPY . . RUN apt-get update && pip install --no-cache-dir -e bot/ -RUN pytest tests/ CMD [ "python", "main.py"] diff --git a/Makefile b/Makefile index 9f7a545..6cb61ec 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,8 @@ DC := $(shell type -p docker-compose) DC_BUILD_ARGS := --pull --force-rm DC_RUN_ARGS := -d --no-build DC_FILE := docker-compose.yml +DC_CONFIG_ARGS := -q +PLATFORM ?= linux/amd64 # docker #REGISTRY ?= docker.io @@ -23,7 +25,7 @@ IMAGE_REGISTRY_bot=${REGISTRY}/${REGISTRY_USERNAME}/${IMAGE_bot} export all: - @echo "Usage: NAME=ramoloss make deploy | build | \ + @echo "Usage: VERSION=latest make deploy | build | \ up | down | test | check | push | pull " @@ -32,15 +34,12 @@ check-var-%: @: $(if $(value $*),,$(error $* is undefined)) @echo ${$*} +# for see configs use: `make DC_CONFIG_ARGS="" check-config` check-config: - ${DC} -f ${DC_FILE} config - -check-config-quiet: - ${DC} -f ${DC_FILE} config -q + ${DC} -f ${DC_FILE} config ${DC_CONFIG_ARGS} # build all or one service build: check-config-quiet - echo ${VERSION} ${DC} -f ${DC_FILE} build ${DC_BUILD_ARGS} build-%: @@ -48,7 +47,7 @@ build-%: ${DC} -f ${DC_FILE} build ${DC_BUILD_ARGS} $* # up all or one service -up: check-config-quiet +up: check-config @if [ -z "${DISCORD_TOKEN}" ] ; \ then echo "ERROR: DISCORD_TOKEN \ not defined" ; exit 1 ; fi @@ -64,8 +63,8 @@ down: down-%: ${DC} -f ${DC_FILE} down $* -# test -test: test-container +# test container and app +test: test-container test-bot test-%: @echo "# test $*" bash tests/test-$*.sh @@ -86,8 +85,9 @@ pull-%: @if [ -n "${REGISTRY_TOKEN}" -a -n "${REGISTRY_LOGIN}" ] ;\ then echo ${REGISTRY_TOKEN} | docker login ${REGISTRY} \ --username ${REGISTRY_LOGIN} --password-stdin ; fi - docker pull ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:latest - docker tag ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:latest ${NAME}-$*:latest + docker pull ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:${VERSION} + docker tag ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:${VERSION} ${NAME}-$*:${VERSION} +# use `make VERSION=latest deploy` deploy: pull up diff --git a/bot/__init__.py b/bot/__init__.py index 1050b9e..9e0457a 100644 --- a/bot/__init__.py +++ b/bot/__init__.py @@ -1 +1,3 @@ -from ._bot import Ramoloss \ No newline at end of file +from ._bot import Ramoloss + +__all__ = ['Ramoloss'] diff --git a/bot/cogs/dev/owner.py b/bot/cogs/dev/owner.py index 097cf3f..5955b9d 100644 --- a/bot/cogs/dev/owner.py +++ b/bot/cogs/dev/owner.py @@ -37,8 +37,8 @@ async def reload(self, ctx, *, cog: str = None): def parse_args(self, cog): if cog is None: cog = [cg for cg in - self.bot.config["extensions"] - if 'user' in cg] + self.bot.config["extensions"] + if 'user' in cg] return cog if isinstance(cog, str): diff --git a/bot/cogs/dev/settings.py b/bot/cogs/dev/settings.py index eb34b22..eb1612c 100644 --- a/bot/cogs/dev/settings.py +++ b/bot/cogs/dev/settings.py @@ -9,20 +9,17 @@ def __init__(self, bot): async def say_hello(self, ctx): await ctx.channel.send(f'Hello {ctx.author.name}') - @commands.has_permissions(administrator=True) @commands.command(name='set_prefix') async def set_prefix(self, ctx, *, new_prefix: str): self.bot.command_prefix = new_prefix await ctx.send(f'Prefix has been set to `{new_prefix}`.') - @set_prefix.error async def pref_error(self, ctx, error): if isinstance(error, commands.MissingPermissions): await ctx.send(error) - def setup(bot): bot.add_cog(Settings(bot)) diff --git a/bot/cogs/user/dice.py b/bot/cogs/user/dice.py index 9e3a826..757fee5 100644 --- a/bot/cogs/user/dice.py +++ b/bot/cogs/user/dice.py @@ -103,7 +103,6 @@ def _random_de(low=1, high=6, size=1): size = int(size) return np.random.randint(low=low, high=high + 1, size=size) - def _operator(self, values): if len(values) < 3: return values diff --git a/bot/cogs/user/john.py b/bot/cogs/user/john.py index 5b76a11..76fa983 100644 --- a/bot/cogs/user/john.py +++ b/bot/cogs/user/john.py @@ -22,5 +22,6 @@ def is_john(message): return True return False + def setup(bot): bot.add_cog(John(bot)) diff --git a/bot/cogs/user/ufd.py b/bot/cogs/user/ufd.py index 91f898b..b98346e 100644 --- a/bot/cogs/user/ufd.py +++ b/bot/cogs/user/ufd.py @@ -38,8 +38,9 @@ async def ufd(self, ctx, command=None, *args): match self.command: case None | 'help': - help_message = self.help(title=TITLE_UFD, - description_command=DESCRIPTION_COMMAND_UFD) + help_message = self.help( + title=TITLE_UFD, + description_command=DESCRIPTION_COMMAND_UFD) await ctx.channel.send(embed=help_message) return @@ -67,16 +68,17 @@ async def ufd(self, ctx, command=None, *args): case _: if not self.n_args: - raise ValueError('Must choice a move. Availables moves with "ufd list moves"') + raise ValueError( + 'Must choice a move. Availables moves with "ufd list moves"') char = UltimateFD(character=command, - moves=self.args, - get_hitbox=True, - args_stats=None) - + moves=self.args, + get_hitbox=True, + args_stats=None) for move, statistics in char.stats.items(): - embed, hitbox = self.create_stats(move=move, statistics=statistics) + embed, hitbox = self.create_stats( + move=move, statistics=statistics) await ctx.channel.send(embed=embed) if hitbox is not None: @@ -90,7 +92,6 @@ async def error(self, ctx, error): await ctx.send(f'```ERROR: {error.__cause__}```') print(error) - def show_list(self, selection): """ Show list of characters with filter not None @@ -100,7 +101,6 @@ def show_list(self, selection): names = [name for name in all_characters if selection in name] return names - @staticmethod def show_wrap_message(list_to_out, title, wrap_at=1000): """ @@ -113,7 +113,6 @@ def show_wrap_message(list_to_out, title, wrap_at=1000): replace_whitespace=False).wrap(output) return [discord.Embed(title=title, description=m) for m in send_messages] - def select_subcommand(self): """ Select subcommand, default 'char' command @@ -123,8 +122,7 @@ def select_subcommand(self): return next(self.args) return "char" - - def select_typecommand(self, choice: str ='char', selection=None): + def select_typecommand(self, choice: str = 'char', selection=None): """ Select type command - if type is 'char' return embed @@ -142,14 +140,13 @@ def select_typecommand(self, choice: str ='char', selection=None): title = "Liste des personnages" case 'move': list_out = [f"**{ref}** ({move.title()})" - for ref, move in REF_ATK.items()] + for ref, move in REF_ATK.items()] title = "Liste des mouvements" list_embed = self.show_wrap_message(list_to_out=list_out, title=title) return list_embed - def create_stats(self, move, statistics, hitbox=None): """ Create stats embed with hitbox if available @@ -157,8 +154,8 @@ def create_stats(self, move, statistics, hitbox=None): title = f"**{self.command.title().replace('_', ' ')} – {move.title()}**" embed = discord.Embed(title=title, - color=0x03F8FC, - url=self.url + self.command) + color=0x03F8FC, + url=self.url + self.command) for stats, amount in statistics.items(): if stats == "hitbox": hitbox = amount @@ -168,5 +165,6 @@ def create_stats(self, move, statistics, hitbox=None): inline=True) return embed, hitbox + def setup(bot): bot.add_cog(UFD(bot)) diff --git a/bot/cogs/utils/__init__.py b/bot/cogs/utils/__init__.py index 407e28a..028ecb7 100644 --- a/bot/cogs/utils/__init__.py +++ b/bot/cogs/utils/__init__.py @@ -1,4 +1,13 @@ -from ._ufd import REF_ATK, DEFAULT_EXCLUDE_OVERALL_STATS, DEFAULT_STATS, UltimateFD +from ._ufd import (REF_ATK, DEFAULT_EXCLUDE_OVERALL_STATS, + DEFAULT_STATS, UltimateFD) from ._poll import EMOJI -from ._help import HelperCommand, TITLE_UFD, DESCRIPTION_COMMAND_UFD, TITLE_POLL, DESCRIPTION_COMMAND_POLL, TITLE_DICE, DESCRIPTION_COMMAND_DICE +from ._help import (HelperCommand, TITLE_UFD, DESCRIPTION_COMMAND_UFD, + TITLE_POLL, DESCRIPTION_COMMAND_POLL, TITLE_DICE, + DESCRIPTION_COMMAND_DICE) from ._args import ParseArgs + +__all__ = ["REF_ATK", "DEFAULT_EXCLUDE_OVERALL_STATS", + "DEFAULT_STATS", "UltimateFD", + "EMOJI", "HelperCommand", "TITLE_UFD", "DESCRIPTION_COMMAND_UFD", + "TITLE_POLL", "DESCRIPTION_COMMAND_POLL", "TITLE_DICE", + "DESCRIPTION_COMMAND_DICE", "ParseArgs"] diff --git a/bot/cogs/utils/_dice.py b/bot/cogs/utils/_dice.py index 9e27a67..dad32e0 100644 --- a/bot/cogs/utils/_dice.py +++ b/bot/cogs/utils/_dice.py @@ -40,7 +40,9 @@ def __init__(self, self.crop = crop self.directory = self.get_path(directory) - def create_lauch_dice(self, inputs_dice: list, colors='green', line_return: int = 3, save=True): + def create_lauch_dice( + self, inputs_dice: list, colors='green', line_return: int = 3, + save=True): """ Draw a dice or multiple dices side by side with a value number and a color. @@ -64,7 +66,8 @@ def create_lauch_dice(self, inputs_dice: list, colors='green', line_return: int list_colors = self.convert_colors(colors, inputs_dice) if len(list_colors) != len(inputs_dice): - raise ValueError('Colors and dice numbers must be in the same size') + raise ValueError( + 'Colors and dice numbers must be in the same size') for (n, i), c in zip(enumerate(inputs_dice), list_colors): if (n % line_return == 0) and (n != 0): @@ -83,7 +86,8 @@ def create_lauch_dice(self, inputs_dice: list, colors='green', line_return: int list_img, how='horizontal', save=False) list_lines.append(line_img) - output_img = self.create_side_by_side(list_lines, how='vertical', save=False) + output_img = self.create_side_by_side( + list_lines, how='vertical', save=False) if save: path = os.path.join(self.directory, 'out.png') output_img.save(path) @@ -115,8 +119,10 @@ def create_image_dice(self, value, size=50, size = self.reformat_size(value, size) img = self.write_white_img(self.shape) rect_border = cv2.rectangle(img, - (self.pt1[0] - border, self.pt1[1] + border), - (self.pt2[0] + border, self.pt2[1] - border), + (self.pt1[0] - border, + self.pt1[1] + border), + (self.pt2[0] + border, + self.pt2[1] - border), color_b, self.thinkness) @@ -129,8 +135,8 @@ def create_image_dice(self, value, size=50, fontcolor = 'white' plt.imshow(rect_center) - plt.annotate(value, xy=self.xy, size=size, ha='center', color=fontcolor, - va='center', fontname=font, weight=weight) + plt.annotate(value, xy=self.xy, size=size, ha='center', + color=fontcolor, va='center', fontname=font, weight=weight) plt.axis('off') plt.savefig(path) plt.close() @@ -183,7 +189,8 @@ def crop_center(pil_img, crop_width, crop_height, slide_x=0, slide_y=15): (img_height + crop_height) // 2)) def create_side_by_side( - self, list_img: list, name='line', how='horizontal', save=False, saved_images=False): + self, list_img: list, name='line', how='horizontal', save=False, + saved_images=False): """Concatenate multiple PIL images verticaly or horizontaly""" if saved_images: @@ -196,7 +203,8 @@ def create_side_by_side( total_width = sum(widths) max_height = max(heights) - new_im = Image.new('RGB', size=(total_width, max_height), color=(255, 255, 255)) + new_im = Image.new('RGB', size=( + total_width, max_height), color=(255, 255, 255)) x_offset = 0 for im in images: @@ -207,7 +215,8 @@ def create_side_by_side( max_width = max(widths) total_height = sum(heights) - new_im = Image.new('RGB', (max_width, total_height), color=(255, 255, 255)) + new_im = Image.new( + 'RGB', (max_width, total_height), color=(255, 255, 255)) y_offset = 0 for im in images: @@ -224,7 +233,8 @@ def create_side_by_side( def convert_colors(input_color, input_dice): """ Convert a list of color with the same size at the list input dice""" if isinstance(input_color, list): - colors = [REF_COLORS[c] for c in input_color if c in REF_COLORS.keys()] + colors = [REF_COLORS[c] + for c in input_color if c in REF_COLORS.keys()] if len(input_color) != len(colors): raise ColorError else: diff --git a/bot/cogs/utils/_help.py b/bot/cogs/utils/_help.py index 7154782..53b4ed7 100644 --- a/bot/cogs/utils/_help.py +++ b/bot/cogs/utils/_help.py @@ -2,7 +2,6 @@ import discord - with open('config.json', 'r', encoding='utf-8') as f: config_arg = json.load(f)["command_prefix"] @@ -17,9 +16,11 @@ ```{config_arg}d 2d4``` Roll one -101 to 150 sided die. ```{config_arg}d 1d[-101:150]``` - Add a one six sided die and a eight sided die (all display). + Add a one six sided die and a eight \ + sided die (all display). ```{config_arg}d 1d6 + 1d8 -v``` - Minus a one six sided die and a eight sided die (only output). + Minus a one six sided die and a eight sided \ + die (only output). ```{config_arg}d 1d6 - 1d8``` Add 6 at a one sided die. ```{config_arg}d 1d6 + 6``` @@ -37,17 +38,17 @@ Create a simple poll. ```{config_arg}poll Kenshuri is a troll?``` For advanced polls use the folowing syntax: - ```{config_arg}poll {{title}} [Option1] [Option2] [Option 3] ...``` + ```{config_arg}poll {{title}} [Option1] \ + [Option2] [Option 3] ...``` *Note: options are limited at 21.* """ - class HelperCommand: def __init__(self): pass def help(self, title, description_command): embed_m = discord.Embed(title=title, - description=description_command) + description=description_command) return embed_m diff --git a/bot/cogs/utils/_ufd.py b/bot/cogs/utils/_ufd.py index ff06ff6..3a02692 100644 --- a/bot/cogs/utils/_ufd.py +++ b/bot/cogs/utils/_ufd.py @@ -141,7 +141,8 @@ def get_character_moves(self, data: dict, move: str): # check if moves is in REF const and not in exclude moves for move_k, move_s in data.items(): for excluded_move in self.exclude_moves: - if self._check_move(move=move, move_k=move_k, out=excluded_move): + if self._check_move(move=move, move_k=move_k, + out=excluded_move): selected_dict_move[move_k] = move_s return selected_dict_move @@ -198,7 +199,8 @@ def get_all_characters(self, url): def _format_overall_stats(self, soup): overall_stats = {} for st in soup.find_all('div'): - if not any(check in st.text for check in DEFAULT_EXCLUDE_OVERALL_STATS): + if not any(check in st.text + for check in DEFAULT_EXCLUDE_OVERALL_STATS): if ' — ' in st.text: spiting_stats = st.text.split(" — ") if len(spiting_stats) == 2: diff --git a/bot/requirements.txt b/bot/requirements.txt index e7b21b7..bd79e05 100644 --- a/bot/requirements.txt +++ b/bot/requirements.txt @@ -3,10 +3,6 @@ discord.py==1.7.3 lxml==4.6.3 matplotlib==3.5.0 numpy==1.21.2 -<<<<<<< HEAD:bot/requirements.txt -opencv-python==4.5.4.60 -======= ->>>>>>> 2e73db2c69a28863c50d9d08c1ab95b8ee9ed139:requirements.txt Pillow==8.3.2 requests==2.26.0 pytest==6.2.5 diff --git a/ci/deploy.sh b/ci/deploy.sh new file mode 100644 index 0000000..e69de29 diff --git a/save/create-save.py b/save/create-save.py index 345d32a..d7fd35b 100644 --- a/save/create-save.py +++ b/save/create-save.py @@ -5,12 +5,14 @@ parser.add_argument('--url', '-u', nargs='*') parser.add_argument('--name', '-n', nargs='*') + def write_response(url, file): - content = requests.get(url).content + content = requests.get(url).content with open(f'save/{file}.html', 'wb') as f: f.write(content) + if __name__ == '__main__': args = parser.parse_args() for filename, url_name in zip(args.name, args.url): - write_response(file=filename, url=url_name) \ No newline at end of file + write_response(file=filename, url=url_name) diff --git a/tests/test_settings.py b/tests/bot/test_settings.py similarity index 99% rename from tests/test_settings.py rename to tests/bot/test_settings.py index 183ae7b..4ad9dc4 100644 --- a/tests/test_settings.py +++ b/tests/bot/test_settings.py @@ -5,7 +5,6 @@ from bot import Ramoloss - with open('config.json', 'r', encoding='utf-8') as config_file: CONFIG = json.load(config_file) diff --git a/tests/test_ufd.py b/tests/bot/test_ufd.py similarity index 99% rename from tests/test_ufd.py rename to tests/bot/test_ufd.py index 574fd0b..4a48563 100644 --- a/tests/test_ufd.py +++ b/tests/bot/test_ufd.py @@ -37,8 +37,9 @@ def open_file(filename): def get(self): return + def mock_get(*args, **kwargs): - return MockResponse() + return MockResponse() class TestUFD: diff --git a/tests/test-bot.sh b/tests/test-bot.sh new file mode 100644 index 0000000..6014c3b --- /dev/null +++ b/tests/test-bot.sh @@ -0,0 +1 @@ +docker exec $NAME-bot pytest \ No newline at end of file diff --git a/tests/test-container.sh b/tests/test-container.sh index eee5462..86bbd5d 100644 --- a/tests/test-container.sh +++ b/tests/test-container.sh @@ -1,15 +1,4 @@ #!/bin/bash -<<<<<<< HEAD -set -ex - -active_container=$(docker ps --filter "name=bot-$NAME" -q) - -if [ -z "${active_container}" ]; then - echo "no container is running" - exit 1 -else - echo "container bot-$NAME with id $active_container is running" -======= set +e APP_NAME=${NAME}-bot @@ -30,5 +19,4 @@ if [ "$test_result" -gt "0" ] ; then ret=$test_result echo "ERROR: timeout with ${APP_NAME}" exit $ret ->>>>>>> 2e73db2c69a28863c50d9d08c1ab95b8ee9ed139 fi \ No newline at end of file From aea32801067f0cb9a03ae7489b8b70180161290f Mon Sep 17 00:00:00 2001 From: titigmr Date: Sat, 11 Dec 2021 20:39:27 +0100 Subject: [PATCH 18/19] change targets --- Makefile | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 6cb61ec..17db512 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ SHELL = /bin/bash NAME ?= ramoloss ARCH ?= $(shell uname -m) VERSION ?= $(shell git describe --tag --abbrev=0) +SERVICES := bot db log # docker-compose DC := $(shell type -p docker-compose) @@ -16,11 +17,11 @@ PLATFORM ?= linux/amd64 #REGISTRY ?= docker.io REGISTRY ?= ghcr.io REPOSITORY ?= ramoloss +REGISTRY_USERNAME ?= toto # image -IMAGE_bot=${NAME}-bot:${VERSION} -IMAGE_REGISTRY_bot=${REGISTRY}/${REGISTRY_USERNAME}/${IMAGE_bot} - +IMAGES = $(foreach srv, $(SERVICES), ${NAME}-${srv}:${VERSION}) +IMAGES_REGISTRY=$(foreach im, $(IMAGE), ${REGISTRY}/${REGISTRY_USERNAME}/${im}) export @@ -30,7 +31,7 @@ all: # check var or config -check-var-%: +check-var: @: $(if $(value $*),,$(error $* is undefined)) @echo ${$*} @@ -39,7 +40,7 @@ check-config: ${DC} -f ${DC_FILE} config ${DC_CONFIG_ARGS} # build all or one service -build: check-config-quiet +build: check-config ${DC} -f ${DC_FILE} build ${DC_BUILD_ARGS} build-%: @@ -53,7 +54,7 @@ up: check-config not defined" ; exit 1 ; fi ${DC} -f ${DC_FILE} up ${DC_RUN_ARGS} -up-%: check-config-quiet +up-%: check-config ${DC} -f ${DC_FILE} up ${DC_RUN_ARGS} $* # down all or one service @@ -76,8 +77,8 @@ push-%: @if [ -z "${REGISTRY}" -a -z "${REGISTRY_USERNAME}" ] ; \ then echo "ERROR: REGISTRY and REGISTRY_USERNAME \ not defined" ; exit 1 ; fi - docker tag ${IMAGE_$*} ${IMAGE_REGISTRY_$*} - docker push ${IMAGE_REGISTRY_$*} + docker tag ${NAME}-$*:${VERSION} ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:${VERSION} + docker push ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:${VERSION} pull: pull-bot @@ -88,6 +89,7 @@ pull-%: docker pull ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:${VERSION} docker tag ${REGISTRY}/${REGISTRY_LOGIN}/${NAME}-$*:${VERSION} ${NAME}-$*:${VERSION} -# use `make VERSION=latest deploy` + +deploy: VERSION=latest deploy: pull up From 2d6157d93b4a3204224397e8469694f4c279aa80 Mon Sep 17 00:00:00 2001 From: titigmr Date: Sat, 15 Jan 2022 14:16:44 +0100 Subject: [PATCH 19/19] add tests --- Dockerfile.armv7l | 4 +++- Dockerfile.x86_64 | 2 ++ Makefile | 6 +++++- bot/_bot.py | 3 ++- bot/cogs/utils/_help.py | 8 ++------ bot/cogs/utils/_ufd.py | 12 ++++++------ save/create-save.py | 4 ++-- tests/bot/test_ufd.py | 34 +++++++++++++++++++--------------- 8 files changed, 41 insertions(+), 32 deletions(-) diff --git a/Dockerfile.armv7l b/Dockerfile.armv7l index 275eede..2f924ec 100644 --- a/Dockerfile.armv7l +++ b/Dockerfile.armv7l @@ -1,8 +1,10 @@ FROM arm32v7/python:3.10-buster as arch_armv7l +RUN useradd -ms /bin/bash bot +USER bot ENV DISCORD_TOKEN=${DISCORD_TOKEN} WORKDIR /ramoloss COPY . . RUN apt-get update && apt-get install \ - libatlas-base-dev -y && pip install --no-cache-dir -r requirements.txt + libatlas-base-dev -y && pip install --no-cache-dir -e /bot CMD [ "python", "main.py"] diff --git a/Dockerfile.x86_64 b/Dockerfile.x86_64 index 21c8cb6..9db87c2 100644 --- a/Dockerfile.x86_64 +++ b/Dockerfile.x86_64 @@ -1,4 +1,6 @@ FROM python:3.10-buster as x86_64 +RUN useradd -ms /bin/bash bot +USER bot ENV DISCORD_TOKEN=${DISCORD_TOKEN} WORKDIR /ramoloss COPY . . diff --git a/Makefile b/Makefile index 17db512..098cee8 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ all: # check var or config -check-var: +check-var-%: @: $(if $(value $*),,$(error $* is undefined)) @echo ${$*} @@ -70,6 +70,10 @@ test-%: @echo "# test $*" bash tests/test-$*.sh +pytest: + docker exec + + # push push: push-bot diff --git a/bot/_bot.py b/bot/_bot.py index 414eac4..378521b 100644 --- a/bot/_bot.py +++ b/bot/_bot.py @@ -1,3 +1,4 @@ +import os from discord.ext.commands import Bot @@ -5,7 +6,7 @@ class Ramoloss(Bot): def __init__(self, config, token, **kwargs): self.config = config self.discord_token = token - + os.environ["command_prefix"] = self.config["command_prefix"] super().__init__( command_prefix=self.config["command_prefix"], description=self.config["description"], diff --git a/bot/cogs/utils/_help.py b/bot/cogs/utils/_help.py index 53b4ed7..4d8f7e7 100644 --- a/bot/cogs/utils/_help.py +++ b/bot/cogs/utils/_help.py @@ -1,13 +1,9 @@ -import json +import os import discord - -with open('config.json', 'r', encoding='utf-8') as f: - config_arg = json.load(f)["command_prefix"] - +config_arg = os.environ.get('command_prefix') REF_COLOR = {'dice': '#8B0000'} - TITLE_DICE = "**Roll a random dice**" DESCRIPTION_COMMAND_DICE = f""" Roll one six sided die. diff --git a/bot/cogs/utils/_ufd.py b/bot/cogs/utils/_ufd.py index 3a02692..9fbb31c 100644 --- a/bot/cogs/utils/_ufd.py +++ b/bot/cogs/utils/_ufd.py @@ -37,14 +37,14 @@ def __init__(self, moves=None, args_stats=None, get_hitbox: bool = False, - exclude_stats: list = ['movename', - 'whichhitbox', - 'notes'], - exclude_moves: list = ['dodge']): + exclude_stats: list = None, + exclude_moves: list = None): self.char = character - self.exclude_moves = exclude_moves - self.exclude_stats = exclude_stats + self.exclude_moves = exclude_stats if exclude_stats is not None else [ + 'movename', 'whichhitbox', 'notes'] + self.exclude_stats = exclude_moves if exclude_moves is not None else [ + 'dodge'] self.url = "https://ultimateframedata.com/" self.stats = {} self.avalaible_stats = {} diff --git a/save/create-save.py b/save/create-save.py index d7fd35b..e27d506 100644 --- a/save/create-save.py +++ b/save/create-save.py @@ -8,8 +8,8 @@ def write_response(url, file): content = requests.get(url).content - with open(f'save/{file}.html', 'wb') as f: - f.write(content) + with open(f'save/{file}.html', 'wb') as file: + file.write(content) if __name__ == '__main__': diff --git a/tests/bot/test_ufd.py b/tests/bot/test_ufd.py index 4a48563..bcf167a 100644 --- a/tests/bot/test_ufd.py +++ b/tests/bot/test_ufd.py @@ -1,4 +1,5 @@ import json +import os import requests import pytest import discord @@ -23,23 +24,26 @@ def bot_instance(event_loop): return bot_ramoloss -class MockResponse: - def __init__(self): - self.status_code = 200 - self.content = MockResponse.open_file('wario') - - @staticmethod - def open_file(filename): - with open(f'save/{filename}.html', 'r', encoding='utf-8') as file: - file_content = str(file.readlines()) - return file_content +def mock_get(*args, **kwargs): + class MockResponse: + def __init__(self, content): + self.status_code = 200 + self.content = content - def get(self): - return + def get(self): + return self.content + print(args[0]) + if 'wario' in args[0]: + file_content = open_file('wario') + else: + file_content = open_file('index') + return MockResponse(file_content) -def mock_get(*args, **kwargs): - return MockResponse() +def open_file(filename): + with open(os.path.join('save', f'{filename}.html'), 'r', encoding='utf-8') as file: + file_content = str(file.readlines()) + return file_content class TestUFD: @@ -56,7 +60,7 @@ def test_char(self, monkeypatch): assert 'http' not in char def test_move(self, monkeypatch): - monkeypatch.setattr(requests, "get", mock_get) + monkeypatch.setattr(requests, 'get', mock_get) ufd = UltimateFD(character='wario', moves='fair') move = ufd.stats