From e54cf885ade01e2884f68361c05b17358f1f452c Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Wed, 11 Dec 2024 14:52:28 -0600 Subject: [PATCH] Migrated to rotating log handler Added random_gif() Moved back from exception-handler cog to local error handling Updated !keepers to be season agnostic Added new !sync param to update and clear local guild Added error checking to !player command --- .gitignore | 3 +- cogs/admins.py | 35 +++--- cogs/dice.py | 46 ++++--- cogs/draft.py | 70 ++++++----- cogs/exception-handler.py | 19 +-- cogs/fun.py | 53 +++++---- cogs/gameday.py | 103 ++++++++-------- cogs/gameplay.py | 19 +-- cogs/owner.py | 64 ++++++---- cogs/players.py | 212 ++++++++++++++++++--------------- cogs/transactions.py | 244 +++++++++++--------------------------- db_calls.py | 77 ++++++------ db_calls_gameday.py | 6 +- db_calls_gameplay.py | 46 +++---- helpers.py | 49 +++++--- majordomo.py | 41 +++++-- 16 files changed, 541 insertions(+), 546 deletions(-) diff --git a/.gitignore b/.gitignore index 9c6a216..40a8c96 100644 --- a/.gitignore +++ b/.gitignore @@ -57,4 +57,5 @@ major-domo-service-creds.json get-monthly.py team-rocket* card-creation/ -.dockerignore \ No newline at end of file +.dockerignore +docker-compose.yml diff --git a/cogs/admins.py b/cogs/admins.py index 8a2a610..0b7f93b 100644 --- a/cogs/admins.py +++ b/cogs/admins.py @@ -11,6 +11,7 @@ from typing import Optional from discord.ext import commands, tasks from discord import app_commands +logger = logging.getLogger('discord_app') class Admins(commands.Cog): def __init__(self, bot): @@ -61,7 +62,7 @@ class Admins(commands.Cog): await channel.send(content=msg_content) except Exception as e: - logging.error(f'Error blasting a message: {type(e)}: {e}') + logger.error(f'Error blasting a message: {type(e)}: {e}') await interaction.response.send_message(content=f'Uh oh\n\n{type(e)}: {e}') # @commands.command(name='sendstats', help='all, batting, pitching') @@ -79,17 +80,17 @@ class Admins(commands.Cog): # for row in csv_reader: # strat_code = row[0] # inj_rating = row[1] - # logging.info(f'strat_code: {strat_code} / inj_rating: {inj_rating}') + # logger.info(f'strat_code: {strat_code} / inj_rating: {inj_rating}') # p_query = await db_get('players', params=[ # ('season', 8), ('strat_code', strat_code) # ]) # if p_query['count'] == 0: - # logging.error(f'Could not find strat_code {strat_code}') + # logger.error(f'Could not find strat_code {strat_code}') # errors.append(f'**{strat_code}** - {inj_rating} not found') # else: # player = p_query['players'][0] # player['injury_rating'] = inj_rating - # logging.info(f'patching {player["name"]} ({player["strat_code"]}) with injury {inj_rating}') + # logger.info(f'patching {player["name"]} ({player["strat_code"]}) with injury {inj_rating}') # await patch_player(player) # Try to get card @@ -99,7 +100,7 @@ class Admins(commands.Cog): sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') scorecard = sheets.open_by_url(sheet_url) except Exception as e: - logging.error(f'Failed to access scorecard {sheet_url}: {e}') + logger.error(f'Failed to access scorecard {sheet_url}: {e}') await ctx.send(content='Is that sheet public? I can\'t access it.') return @@ -113,7 +114,7 @@ class Admins(commands.Cog): week_num = g_data[0][5] game_num = g_data[1][5] - logging.info(f'gdata: {g_data}\nweek/game: {week_num}/{game_num}') + logger.info(f'gdata: {g_data}\nweek/game: {week_num}/{game_num}') dupe_g_query = await db_get('games', params=[ ('season', current['season']), ('week_start', week_num), ('week_end', week_num), @@ -134,11 +135,11 @@ class Admins(commands.Cog): return this_game = g_query['games'][0] - logging.info(f'this_game: {this_game}') + logger.info(f'this_game: {this_game}') playtable = scorecard.worksheet_by_title('Playtable') all_plays = playtable.get_values('B3', 'BG300') - logging.info(f'all_plays: {all_plays}') + logger.info(f'all_plays: {all_plays}') play_keys = [ 'play_num', 'batter_id', 'batter_pos', 'pitcher_id', 'on_base_code', 'inning_half', 'inning_num', @@ -157,7 +158,7 @@ class Admins(commands.Cog): this_data[play_keys[count]] = x p_data.append(this_data) - logging.info(f'p_data: {p_data}') + logger.info(f'p_data: {p_data}') await db_post('plays', payload={'plays': p_data}) await ctx.send(f'go check logs, nerd') @@ -193,7 +194,7 @@ class Admins(commands.Cog): # ] # ) # counter += 1 - # logging.warning(f'all_vals samples:\n0: {all_vals[0]}\n100: {all_vals[100]}\n1000: {all_vals[1000]}\n' + # logger.warning(f'all_vals samples:\n0: {all_vals[0]}\n100: {all_vals[100]}\n1000: {all_vals[1000]}\n' # f'2000: {all_vals[2000]}') # # await ctx.send('Sending transactions to sheets...') @@ -276,16 +277,16 @@ class Admins(commands.Cog): current = await db_get('current') if current['week'] != -1: - logging.info('entering the thot check') + logger.info('entering the thot check') await interaction.edit_original_response(content='https://c.tenor.com/FCAj8xDvEHwAAAAC/be-gone-thot.gif') player_role = get_role(interaction, SBA_PLAYERS_ROLE_NAME) - logging.info('beginning sleep') + logger.info('beginning sleep') await asyncio.sleep(random.randint(3, 7)) try: await interaction.user.remove_roles(player_role) except Exception as e: - logging.error(f'unable to remove {player_role} role from {interaction.user}: {e}') + logger.error(f'unable to remove {player_role} role from {interaction.user}: {e}') return @@ -343,7 +344,7 @@ class Admins(commands.Cog): await interaction.edit_original_response( content='No fuzzy search here can help you. Ya gotta get it right.') return - # logging.info(f'keeper_slash - this_player: {this_player}') + # logger.info(f'keeper_slash - this_player: {this_player}') if this_player['team']['id'] != this_team['id']: await interaction.edit_original_response( content=f'Lol {this_player["name"]}. Oh my god be more I hate you.') @@ -355,16 +356,16 @@ class Admins(commands.Cog): 'team_id': this_team['id'], 'player_id': this_player['id'] }) - # logging.info(f'keeper_slash - updated k_list') + # logger.info(f'keeper_slash - updated k_list') keeper_string += f'{get_pos_nickname(this_player["pos_1"])} - ' \ f'{this_player["name"]} ({this_player["wara"]:.2f})\n' keeper_swar += this_player['wara'] - # logging.info(f'keeper_slash - updated keeper_swar') + # logger.info(f'keeper_slash - updated keeper_swar') this_pick = picks[count] this_pick['player'] = this_player - # logging.info(f'keeper_slash - patching draftpick') + # logger.info(f'keeper_slash - patching draftpick') await patch_draftpick(this_pick) count += 1 diff --git a/cogs/dice.py b/cogs/dice.py index c1d73cd..cd2528c 100644 --- a/cogs/dice.py +++ b/cogs/dice.py @@ -8,18 +8,22 @@ from discord import app_commands from discord.app_commands import Choice import random +logger = logging.getLogger('discord_app') class Dice(commands.Cog): def __init__(self, bot): self.bot = bot self.rolls = [] self.current = None + + async def cog_command_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error}\n\nRun !help to see the command requirements') - # self.updates.start() - - # async def cog_command_error(self, ctx, error): - # await ctx.send(f'{error}') - + async def slash_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error[:1600]}') + async def get_dice_embed(self, channel, title, message): try: team_abbrev = re.split('-', channel.name) @@ -28,7 +32,7 @@ class Dice(commands.Cog): else: team = None except (ValueError, AttributeError, requests.ReadTimeout) as e: - logging.info(f'{type(e)}: {e}') + logger.info(f'{type(e)}: {e}') team = None if team: @@ -45,14 +49,6 @@ class Dice(commands.Cog): return embed - # @tasks.loop(minutes=5) - # async def updates(self): - # self.current = await db_get('current') - # if len(self.rolls) > 0: - # all_rolls = self.rolls - # self.rolls = [] - # await post_dice(all_rolls) - @commands.command(name='ab', aliases=['atbat', 'swing', 'pa'], help='ab, atbat, or swing') async def ab_roll(self, ctx): """ @@ -99,7 +95,7 @@ class Dice(commands.Cog): roll_message += f'\n**Check injury for pitcher injury rating {13 - d_six_two - d_six_three}**\n' \ f'Oops! All injuries!' - logging.info(f'roll_message: {roll_message}') + logger.info(f'roll_message: {roll_message}') await ctx.channel.send( content=None, embed=await self.get_dice_embed(ctx.channel, f'At bat roll for {ctx.author.name}', roll_message) @@ -117,11 +113,11 @@ class Dice(commands.Cog): @commands.command(name='scout', help='!scout pitcher or !scout batter') async def scout_ab_roll(self, ctx, roll_type: str): - if roll_type[0] not in ['p', 'b']: + if roll_type[0].lower() not in ['p', 'b']: await ctx.send(f'Ya gotta tell me if you\'re rolling for a pitcher or batter') await ctx.send(random_gif(random_from_list(['come on', 'figure it out', 'fucking christ']))) return - if roll_type[0] == 'p': + if roll_type[0].lower() == 'p': d_six_one = random.randint(4, 6) else: d_six_one = random.randint(1, 3) @@ -133,7 +129,7 @@ class Dice(commands.Cog): f'{d_twenty}\nDetails:[1d6;2d6;1d20 ({d_six_one} - {d_six_two} {d_six_three} - ' \ f'{d_twenty})]```' - logging.info(f'scouting roll_message: {roll_message}') + logger.info(f'scouting roll_message: {roll_message}') await ctx.channel.send( content=None, embed=await self.get_dice_embed(ctx.channel, f'At bat roll for {ctx.author.name}', roll_message) @@ -340,11 +336,11 @@ class Dice(commands.Cog): # injury_string = f'```md\n# {injury_roll}\n' \ # f'Details:[3d6 ({d_six_one} {d_six_two} {d_six_three})]\n```\n' # - # logging.info(f'injury rating: {rating.value}p{games.value}') + # logger.info(f'injury rating: {rating.value}p{games.value}') # # injury_list = inj_data[p_ratings[rating.value - 1]][f'p{games.value}'] # injury_result = injury_list[injury_roll - 3] - # logging.info( + # logger.info( # f'injury rating: {rating.value}p{games.value} / array: {injury_list}[{injury_roll - 2}] / result: {injury_result}') # # if isinstance(injury_result, int): @@ -353,7 +349,7 @@ class Dice(commands.Cog): # content=random_gif(random_from_list(['salute', 'press f', 'pay respects'])) # ) # except Exception as e: - # logging.info(f'failed to post funny gif') + # logger.info(f'failed to post funny gif') # injury_string += f'With a roll of {injury_roll}, the injury length is **{injury_result} ' \ # f'game{"s" if injury_result > 1 else ""}**.' # elif injury_result == 'REM': @@ -362,7 +358,7 @@ class Dice(commands.Cog): # content=random_gif(random_from_list(['could be worse', 'not too bad'])) # ) # except Exception as e: - # logging.info(f'failed to post funny gif') + # logger.info(f'failed to post funny gif') # injury_string += f'With a roll of {injury_roll}, the injury length is **REMAINDER OF GAME** for batters ' \ # f'or **FATIGUED** for pitchers' # else: @@ -371,7 +367,7 @@ class Dice(commands.Cog): # content=random_gif(random_from_list(['it is fine', 'nothing to see here', 'i wasn\'t worried'])) # ) # except Exception as e: - # logging.info(f'failed to post funny gif') + # logger.info(f'failed to post funny gif') # injury_string += f'With a roll of {injury_roll}, the player is **OKAY** - no injury!' # # embed = await self.get_dice_embed( @@ -1588,13 +1584,13 @@ class Dice(commands.Cog): return numbers = re.split('d', roll_string.lower()) - logging.info(f'numbers: {numbers}') + logger.info(f'numbers: {numbers}') num_dice = int(numbers[0]) die_sides = int(numbers[1]) all_rolls = [] total = 0 - logging.info(f'num_dice: {num_dice} / die_sides: {die_sides}') + logger.info(f'num_dice: {num_dice} / die_sides: {die_sides}') if num_dice < 1 or die_sides < 1: await ctx.send('Hurr hurr, let\'s roll negative dice, amirite!') diff --git a/cogs/draft.py b/cogs/draft.py index ed425fa..7a07c3b 100644 --- a/cogs/draft.py +++ b/cogs/draft.py @@ -8,6 +8,7 @@ from discord.ext import commands, tasks from discord import TextChannel, app_commands +logger = logging.getLogger('discord_app') class Draft(commands.Cog): def __init__(self, bot): @@ -17,24 +18,32 @@ class Draft(commands.Cog): # self.sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') self.draft_loop.start() + + async def cog_command_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error}\n\nRun !help to see the command requirements') + async def slash_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error[:1600]}') + @tasks.loop(seconds=10) async def draft_loop(self): # guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) # if not guild: - # logging.error('Bot not logged in - delaying draft loop') + # logger.error('Bot not logged in - delaying draft loop') # return draft_data = await db_get('draftdata') now = datetime.datetime.now() - # logging.info('Entering draft loop') + # logger.info('Entering draft loop') try: deadline = datetime.datetime.strptime(draft_data['pick_deadline'], '%Y-%m-%dT%H:%M:%S.%f') except Exception as e: deadline = None - # logging.info(f'Timer: {draft_data["timer"]} / Deadline: {deadline} / Warnings: {self.warnings}') - # logging.info(f'10 Hrs?: {deadline - datetime.timedelta(hours=10) <= now}') + # logger.info(f'Timer: {draft_data["timer"]} / Deadline: {deadline} / Warnings: {self.warnings}') + # logger.info(f'10 Hrs?: {deadline - datetime.timedelta(hours=10) <= now}') # Timer is active and pick is due if draft_data['timer'] and deadline: @@ -147,7 +156,7 @@ class Draft(commands.Cog): async def send_draft_ping(self, ping=True): current = await db_get('current') draft_data = await db_get('draftdata') - logging.info(f'current: {current}\nd_data: {draft_data}') + logger.info(f'current: {current}\nd_data: {draft_data}') # this_pick = await get_one_draftpick_byoverall(current['season'], draft_data['currentpick']) p_query = await db_get('draftpicks', params=[ ('season', current['season']), ('overall', draft_data['currentpick']), ('short_output', False) @@ -156,11 +165,11 @@ class Draft(commands.Cog): raise ValueError(f'No pick found for overall #{draft_data["currentpick"]}') this_pick = p_query['picks'][0] - logging.info(f'pick: {this_pick}') + logger.info(f'pick: {this_pick}') this_team = await db_get('teams', object_id=this_pick['owner']['id']) - logging.info(f'team: {this_team}') + logger.info(f'team: {this_team}') team_role = get_team_role(None, this_team, self.bot) - logging.info(f'role: {team_role}') + logger.info(f'role: {team_role}') team_ping = None if ping and team_role: team_ping = team_role.mention @@ -168,7 +177,7 @@ class Draft(commands.Cog): if pick_num == 0: pick_num = 16 - logging.info(f'current: {current}\ndata: {draft_data}\npick: {this_pick}\nteam: {this_team}\n' + logger.info(f'current: {current}\ndata: {draft_data}\npick: {this_pick}\nteam: {this_team}\n' f'role: {team_role}\nping: {team_ping}') embed = get_team_embed(f'{this_team["lname"]} On The Clock', team=this_team) @@ -336,12 +345,12 @@ class Draft(commands.Cog): player['wara'] ]] - logging.info(f'sending pick to sheets') + logger.info(f'sending pick to sheets') sheets.open_by_key(SBA_SEASON9_DRAFT_KEY).worksheet_by_title('Ordered List').update_values( crange=f'D{draft_pick["overall"] + 1}', values=this_pick ) - logging.info(f'pick has been sent to sheets') + logger.info(f'pick has been sent to sheets') async def draft_player(self, current, draft_data, draft_pick, player): # Is this player available to be drafted? @@ -386,7 +395,7 @@ class Draft(commands.Cog): # } # Submit the pick - logging.info( + logger.info( f'{draft_pick["owner"]["lname"]} selects {player["name"]} with the #{draft_pick["overall"]} overall pick' ) # await patch_draftpick(draft_pick['id'], player_id=player['id']) @@ -450,7 +459,7 @@ class Draft(commands.Cog): raise ValueError(f'No pick found for overall #{draft_data["currentpick"]}') draft_pick = p_query['picks'][0] - logging.info(f'draft_pick: {draft_pick}') + logger.info(f'draft_pick: {draft_pick}') if draft_data['pick_deadline']: deadline = datetime.datetime.strptime(draft_data['pick_deadline'], '%Y-%m-%dT%H:%M:%S.%f') @@ -471,7 +480,7 @@ class Draft(commands.Cog): f'Pick Deadline: {dead_string}\n' \ f'Ping Channel: {p_channel.mention}\n' \ f'Result Channel: {r_channel.mention}\n' - logging.info(f'draft_string: {draft_string}') + logger.info(f'draft_string: {draft_string}') return draft_string @@ -618,7 +627,7 @@ class Draft(commands.Cog): player_name = await fuzzy_player_search(ctx, ctx.channel, self.bot, x, player_cog.player_list.keys()) player = await get_player_by_name(current['season'], player_name) except Exception as e: - logging.error(f'Could not draft {x} for {team["abbrev"]}: {e}') + logger.error(f'Could not draft {x} for {team["abbrev"]}: {e}') errors.append(x) rank -= 1 else: @@ -652,7 +661,7 @@ class Draft(commands.Cog): current = await db_get('current') draft_data = await db_get('draftdata') - logging.info(f'building draft string') + logger.info(f'building draft string') await ctx.send(await self.draftdata_to_string(current, draft_data)) if draft_data["ping_channel"] is not None: await self.send_draft_ping(ping=False) @@ -1123,7 +1132,7 @@ class Draft(commands.Cog): # if this_pick['overall'] < 600: # if this_pick['overall'] != overall: # await patch_draftpick(this_pick['id'], overall=overall) - # logging.info(f'Updating {this_pick["origowner"]["abbrev"]} {this_pick["round"]}: ' + # logger.info(f'Updating {this_pick["origowner"]["abbrev"]} {this_pick["round"]}: ' # f'#{this_pick["overall"]} to {overall}') # overall += 1 # @@ -1154,6 +1163,7 @@ class Draft(commands.Cog): player_list = [] this_team = await get_team_by_abbrev(team_abbrev, current['season']) + fa_team = await get_team_by_abbrev('FA', current['season']) player_names = re.split(',', player_names) keepers = [] keeper_count = 1 @@ -1181,32 +1191,38 @@ class Draft(commands.Cog): all_players.append(guy) # all_picks = await get_draftpicks(season=current['season'], owner_team=this_team, round_end=7) + if current['season'] % 2 == 1: + start_round = 1 + end_round = 7 + else: + start_round = 2 + end_round = 8 + p_query = await db_get( 'draftpicks', - params=[('season', current['season']), ('owner_team_id', this_team['id']), ('pick_round_start', 2), - ('pick_round_end', 8), ('sort', 'order-asc')] + params=[('season', current['season']), ('owner_team_id', this_team['id']), ('pick_round_start', start_round), ('pick_round_end', end_round), ('sort', 'order-asc')] ) - # logging.info(f'\n{all_picks}\n') + # logger.info(f'\n{all_picks}\n') # sorted_picks = sorted(all_picks.items(), key=lambda item: item[1]["overall"]) sorted_picks = p_query['picks'] # for p in all_picks: # sorted_picks.append(all_picks[p]) - # logging.info(f'{sorted_picks}') + # logger.info(f'{sorted_picks}') all_moves = [] all_keepers = [] for x in all_players: - logging.info(f'Checking {x["name"]} for keeper status') + logger.info(f'Checking {x["name"]} for keeper status') this_player = copy.deepcopy(x) if x["name"] in keepers: - logging.info(f'{x["name"]} is a keeper') + logger.info(f'{x["name"]} is a keeper') draft_pick = sorted_picks[keeper_count - 1] this_player['demotion_week'] = 2 draft_pick['player'] = this_player - logging.info(f'Setting {x["name"]} as {this_team["abbrev"]}\'s #{keeper_count} keeper with overall ' + logger.info(f'Setting {x["name"]} as {this_team["abbrev"]}\'s #{keeper_count} keeper with overall ' f'pick #{draft_pick["overall"]}') await patch_draftpick(draft_pick) @@ -1223,7 +1239,7 @@ class Draft(commands.Cog): all_moves.append({ 'week': -1, 'player_id': x['id'], - 'oldteam_id': 400, # FA team ID + 'oldteam_id': fa_team['id'], # FA team ID 'newteam_id': this_team['id'], 'season': current['season'], 'moveid': f'keeper-{this_team["abbrev"]}-{keeper_count}' @@ -1240,10 +1256,10 @@ class Draft(commands.Cog): try: await self.send_pick_to_sheets(draft_pick, this_player) except Exception as e: - logging.error(f'{e}') + logger.error(f'{e}') keeper_count += 1 else: - this_player['team'] = {'id': 400} + this_player['team'] = {'id': fa_team['id']} await put_player(this_player) await db_post('transactions', payload={'count': len(all_moves), 'moves': all_moves}) diff --git a/cogs/exception-handler.py b/cogs/exception-handler.py index 462c91e..f2a244a 100644 --- a/cogs/exception-handler.py +++ b/cogs/exception-handler.py @@ -4,19 +4,20 @@ from discord import Interaction from discord.app_commands import AppCommandError import logging +logger = logging.getLogger('discord_app') class ExceptionHandler(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot = bot - @commands.Cog.listener() - async def on_command_error(self, ctx: commands.Context, error) -> None: - e_string = f'{error}' - logging.error(e_string) - if 'Command' in e_string and 'not found' in e_string: - pass - else: - await ctx.send(f'Hmm...do you know what this error means:\n\n{error}') + # @commands.Cog.listener() + # async def on_command_error(self, ctx: commands.Context, error) -> None: + # e_string = f'{error}' + # logger.error(e_string) + # if 'Command' in e_string and 'not found' in e_string: + # pass + # else: + # await ctx.send(f'Hmm...do you know what this error means:\n\n{error}') # attaching the handler when the cog is loaded # and storing the old handler @@ -38,7 +39,7 @@ class ExceptionHandler(commands.Cog): interaction: Interaction, error: AppCommandError ): - logging.error(f'interaction: {interaction} / error: {error}') + logger.error(f'interaction: {interaction} / error: {error}') await interaction.channel.send(f'Hmm...do you know what this error means:\n\n{error}') diff --git a/cogs/fun.py b/cogs/fun.py index 059f974..8808712 100644 --- a/cogs/fun.py +++ b/cogs/fun.py @@ -9,6 +9,8 @@ from datetime import datetime, timedelta from discord.ext import commands, tasks from typing import Literal +logger = logging.getLogger('discord_app') + db = SqliteDatabase( 'storage/sba_is_fun.db', pragmas={ @@ -67,21 +69,21 @@ class Fun(commands.Cog): @tasks.loop(hours=20) async def daily_check(self): try: - # logging.info(f'trying to start cc check') + # logger.info(f'trying to start cc check') guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: - # logging.info(f'no guild found for cc check') + # logger.info(f'no guild found for cc check') await asyncio.sleep(15) guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: - logging.error(f'Fun cog could not access guild') + logger.error(f'Fun cog could not access guild') return except Exception as e: - logging.error(f'Could not run daily_check: {e}') + logger.error(f'Could not run daily_check: {e}') return if guild.id != 613880856032968834: - logging.info(f'Not checking CCs outside of SBa server') + logger.info(f'Not checking CCs outside of SBa server') return # = {'member': , 'commands': [(, )]} del_notifs = {} @@ -92,7 +94,7 @@ class Fun(commands.Cog): for x in Command.select(): # Final check / deleted if x.last_used + timedelta(days=90) < now: - logging.warning(f'Deleting `!cc {x.name}`') + logger.warning(f'Deleting `!cc {x.name}`') owner = guild.get_member(x.creator.discordid) if owner: if owner.id not in del_notifs: @@ -104,7 +106,7 @@ class Fun(commands.Cog): del_counter += 1 elif x.last_used + timedelta(days=60) < now and (x.sent_warns is None or x.sent_warns == 0): - logging.warning(f'Warning for `!cc {x.name}`') + logger.warning(f'Warning for `!cc {x.name}`') x.sent_warns = 1 x.save() owner = guild.get_member(x.creator.discordid) @@ -115,13 +117,13 @@ class Fun(commands.Cog): warn_notifs[owner.id]['commands'].append((x.name, x.message)) # else: - # logging.warning( + # logger.warning( # f'Command last used {x.last_used} / delta: {now - x.last_used} \n/>60 days: ' # f'{x.last_used + timedelta(days=60) < now} / sent_warns: {x.sent_warns}' # ) db.close() - logging.info(f'deletions: {del_notifs}\nwarnings: {warn_notifs}') + logger.info(f'deletions: {del_notifs}\nwarnings: {warn_notifs}') for member in del_notifs: plural = len(del_notifs[member]["commands"]) > 1 @@ -135,12 +137,12 @@ class Fun(commands.Cog): try: await del_notifs[member]['member'].send(msg_content) except Exception as e: - logging.error(f'fun daily_check - could not send deletion message to {del_notifs[member]["member"]} ' + logger.error(f'fun daily_check - could not send deletion message to {del_notifs[member]["member"]} ' f'/ trying short_msg') try: await del_notifs[member]['member'].send(short_msg_content) except Exception as e: - logging.error(f'fun daily_check - still could not send deletion message') + logger.error(f'fun daily_check - still could not send deletion message') for member in warn_notifs: plural = len(warn_notifs[member]["commands"]) > 1 @@ -155,19 +157,24 @@ class Fun(commands.Cog): try: await warn_notifs[member]['member'].send(msg_content) except Exception as e: - logging.error(f'fun daily_check - could not send warn message to {warn_notifs[member]["member"]} ' + logger.error(f'fun daily_check - could not send warn message to {warn_notifs[member]["member"]} ' f'/ trying short_msg') try: await warn_notifs[member]['member'].send(short_msg_content) except Exception as e: - logging.error(f'fun daily_check - still could not send warn message') + logger.error(f'fun daily_check - still could not send warn message') - logging.info(f'Deleted {del_counter} commands; sent deletion notifications to {len(del_notifs)} users; ' + logger.info(f'Deleted {del_counter} commands; sent deletion notifications to {len(del_notifs)} users; ' f'sent warnings to {len(warn_notifs)} users') + + async def cog_command_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error}\n\nRun !help to see the command requirements') - # async def cog_command_error(self, ctx, error): - # await ctx.send(f'{error}') - + async def slash_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error[:1600]}') + @commands.Cog.listener(name='on_message') async def on_message_listener(self, message): if message.author.bot or message.channel.guild.id != int(os.environ.get('GUILD_ID')) \ @@ -187,7 +194,7 @@ class Fun(commands.Cog): db.close() time_since = datetime.now() - last_soak.timestamp - # logging.info(f'time_since: {time_since} / seconds: {time_since.seconds} / days: {time_since.days}') + # logger.info(f'time_since: {time_since} / seconds: {time_since.seconds} / days: {time_since.days}') gif_search = None if time_since.days >= 2: ts_string = f'{time_since.days} days' @@ -214,7 +221,7 @@ class Fun(commands.Cog): try: await message.channel.send(random_gif(gif_search)) except Exception as e: - logging.error(e) + logger.error(e) @commands.command(name='lastsoak', aliases=['ls'], help='Get a link to the last mention of soaking') async def last_soak_command(self, ctx): @@ -347,7 +354,7 @@ class Fun(commands.Cog): try: column_one += f'**{all_commands[x].name}** by {all_commands[x].creator.name}\n' except Exception as e: - logging.error(f'Error building !allcc embed: {e}') + logger.error(f'Error building !allcc embed: {e}') break this_embed.add_field(name=f'{(this_page - 1) * 40 + 1}-{this_page * 40 - 20}', value=column_one) @@ -355,7 +362,7 @@ class Fun(commands.Cog): try: column_two += f'**{all_commands[x].name}** by {all_commands[x].creator.name}\n' except Exception as e: - logging.error(f'Error building !allcc embed: {e}') + logger.error(f'Error building !allcc embed: {e}') break if len(column_two) > 0: this_embed.add_field(name=f'{(this_page - 1) * 40 + 21}-{this_page * 40}', value=column_two) @@ -379,7 +386,7 @@ class Fun(commands.Cog): await view.wait() if view.value: - logging.info(f'got a value: {view.value}') + logger.info(f'got a value: {view.value}') if view.value == 'left': page_num = page_num - 1 if page_num > 1 else last_page elif view.value == 'right': @@ -553,7 +560,7 @@ class Fun(commands.Cog): # time_start = datetime.now() # # async for member in ctx.guild.fetch_members(): - # logging.warning(f'member: {member}') + # logger.warning(f'member: {member}') # await member.add_roles(*all_roles) # # time_end = datetime.now() diff --git a/cogs/gameday.py b/cogs/gameday.py index 7908fa3..339d2c3 100644 --- a/cogs/gameday.py +++ b/cogs/gameday.py @@ -9,6 +9,7 @@ from db_calls_gameday import * import discord from discord.ext import commands +logger = logging.getLogger('discord_app') class Gameday(commands.Cog): def __init__(self, bot): @@ -56,7 +57,7 @@ class Gameday(commands.Cog): if roster_check['batting_count'] != 9: errors.append(f'{team_name} has {roster_check["batting_count"]} players in the batting order') - logging.info(f'{"home" if home else "away"} error count: {len(errors)}') + logger.info(f'{"home" if home else "away"} error count: {len(errors)}') return { 'valid': True if len(errors) == 0 else False, 'errors': errors @@ -69,11 +70,11 @@ class Gameday(commands.Cog): occupied = '●' unoccupied = '○' - logging.info(f'checking baserunners') + logger.info(f'checking baserunners') first_base = unoccupied if not gs['on_first'] else occupied second_base = unoccupied if not gs['on_second'] else occupied third_base = unoccupied if not gs['on_third'] else occupied - logging.info(f'checking inning and score') + logger.info(f'checking inning and score') if gs['final']: outs = '' inning = 'FINAL' @@ -82,11 +83,11 @@ class Gameday(commands.Cog): half = '▲' if gs['top_half'] else '▼' inning = f'{half} {gs["inning"]}' - logging.info(f'getting pitcher and batter members') + logger.info(f'getting pitcher and batter members') pbc_data = self.get_pbc(this_game) batter_member = pbc_data['batter'] pitcher_member = pbc_data['pitcher'] - logging.info(f'getting pitcher and batter players') + logger.info(f'getting pitcher and batter players') if not batter_member: this_batter = {'name': 'BATTER NOT FOUND', 'image': LOGO} else: @@ -98,16 +99,16 @@ class Gameday(commands.Cog): # pitcher_name = this_pitcher['name'].split(' ', 1)[1] # batter_name = this_batter['name'].split(' ', 1)[1] - logging.info(f'setting player names') + logger.info(f'setting player names') # pitcher_name = this_pitcher['name'] if len(this_pitcher['name']) <= 19 else f'{this_pitcher["name"][:16]}...' # batter_name = this_batter['name'] if len(this_batter['name']) <= 19 else f'{this_batter["name"][:16]}...' - logging.info(f'setting player stats') + logger.info(f'setting player stats') era = f'{6.9:.2f}' avg = f'{.420:.3f}' if avg[0] == '0': avg = avg[1:] - logging.info(f'generating game string') + logger.info(f'generating game string') game_string = f'```\n' \ f'{away_team["abbrev"]: ^4}{gs["away_score"]: ^3} {second_base}' \ f'{inning: >12}\n' \ @@ -197,10 +198,10 @@ class Gameday(commands.Cog): """ rbi = 0 - # logging.info(f'this_state:\n{this_state}\n') + # logger.info(f'this_state:\n{this_state}\n') if this_state['on_third']: if not force_only or (force_only and this_state['on_second'] and this_state['on_first']): - logging.info(f'runner {this_state["on_third"]["id"]} scores') + logger.info(f'runner {this_state["on_third"]["id"]} scores') on_third = get_one_atbat( game_id=this_state['game']['id'], batter_id=this_state['on_third']['player_id'] ) @@ -208,11 +209,11 @@ class Gameday(commands.Cog): patch_game_state(this_state['id'], on_third_id=False) rbi += 1 - # logging.info('pre-on_second') + # logger.info('pre-on_second') if this_state['on_second']: if not force_only or (force_only and this_state['on_first']): if num_bases > 1: - logging.info(f'runner {this_state["on_second"]["id"]} scores') + logger.info(f'runner {this_state["on_second"]["id"]} scores') on_second = get_one_atbat( game_id=this_state['game']['id'], batter_id=this_state['on_second']['player_id'] ) @@ -220,13 +221,13 @@ class Gameday(commands.Cog): patch_game_state(this_state['id'], on_second_id=False) rbi += 1 else: - logging.info(f'runner {this_state["on_second"]["id"]} from second to third') + logger.info(f'runner {this_state["on_second"]["id"]} from second to third') patch_game_state(this_state['id'], on_second_id=False, on_third_id=this_state['on_second']['id']) - # logging.info('pre-on_first') + # logger.info('pre-on_first') if this_state['on_first']: if num_bases > 2: - logging.info(f'runner {this_state["on_first"]["id"]} scores') + logger.info(f'runner {this_state["on_first"]["id"]} scores') on_first = get_one_atbat( game_id=this_state['game']['id'], batter_id=this_state['on_first']['player_id'] ) @@ -234,10 +235,10 @@ class Gameday(commands.Cog): patch_game_state(this_state['id'], on_first_id=False) rbi += 1 elif num_bases == 2: - logging.info(f'runner {this_state["on_first"]["id"]} from first to third') + logger.info(f'runner {this_state["on_first"]["id"]} from first to third') patch_game_state(this_state['id'], on_first_id=False, on_third_id=this_state['on_first']['id']) else: - logging.info(f'runner {this_state["on_first"]["id"]} from first to second') + logger.info(f'runner {this_state["on_first"]["id"]} from first to second') patch_game_state(this_state['id'], on_first_id=False, on_second_id=this_state['on_first']['id']) return rbi @@ -263,7 +264,7 @@ class Gameday(commands.Cog): batting_order = this_state['home_batter_up'] # Get pitcher and batter - logging.info('get pitcher and batter') + logger.info('get pitcher and batter') try: this_batter = get_one_member( game_id=this_game['id'], team_id=bat_team_id, batting_order=batting_order, active=1 @@ -397,7 +398,7 @@ class Gameday(commands.Cog): # f'{ab: >3} {run: >2} {hit: ^3} {double: >2} {triple: >2} {hr: >2} {rbi: >3} ' \ # f'{sb: >2} {so: ^3}\n```' - logging.info(f'batter_string: {batter_string}') + logger.info(f'batter_string: {batter_string}') return batter_string @staticmethod @@ -451,7 +452,7 @@ class Gameday(commands.Cog): # f'{win: >2} {loss: >2} {save: >2} {era: >5} {ip: >5} ' \ # f'{so: >3} {whip: >4}\n```' - logging.info(f'pitcher_string: {pitcher_string}') + logger.info(f'pitcher_string: {pitcher_string}') return pitcher_string @staticmethod @@ -467,7 +468,7 @@ class Gameday(commands.Cog): this_state = get_game_state(game_id=this_game['id'])['states'][0] rbi = 0 if from_base == 3 and this_state['on_third']: - logging.info(f'runner {this_state["on_third"]["id"]} scores') + logger.info(f'runner {this_state["on_third"]["id"]} scores') this_runner = get_atbat( game_id=this_state['game']['id'], batter_id=this_state['on_third']['player_id'] )['atbats'] @@ -478,7 +479,7 @@ class Gameday(commands.Cog): elif from_base == 2 and this_state['on_second']: if num_bases > 1: - logging.info(f'runner {this_state["on_second"]["id"]} scores') + logger.info(f'runner {this_state["on_second"]["id"]} scores') this_runner = get_atbat( game_id=this_state['game']['id'], batter_id=this_state['on_second']['player_id'] )['atbats'] @@ -487,12 +488,12 @@ class Gameday(commands.Cog): patch_game_state(this_state['id'], on_second_id=False) rbi += 1 else: - logging.info(f'runner {this_state["on_second"]["id"]} from second to third') + logger.info(f'runner {this_state["on_second"]["id"]} from second to third') patch_game_state(this_state['id'], on_second_id=False, on_third_id=this_state['on_second']['id']) elif from_base == 1 and this_state['on_first']: if num_bases > 2: - logging.info(f'runner {this_state["on_first"]["id"]} scores') + logger.info(f'runner {this_state["on_first"]["id"]} scores') this_runner = get_atbat( game_id=this_state['game']['id'], batter_id=this_state['on_first']['player_id'] )['atbats'] @@ -501,10 +502,10 @@ class Gameday(commands.Cog): patch_game_state(this_state['id'], on_first_id=False) rbi += 1 elif num_bases == 2: - logging.info(f'runner {this_state["on_first"]["id"]} from first to third') + logger.info(f'runner {this_state["on_first"]["id"]} from first to third') patch_game_state(this_state['id'], on_first_id=False, on_third_id=this_state['on_first']['id']) else: - logging.info(f'runner {this_state["on_first"]["id"]} from first to second') + logger.info(f'runner {this_state["on_first"]["id"]} from first to second') patch_game_state(this_state['id'], on_first_id=False, on_second_id=this_state['on_first']['id']) return rbi @@ -590,7 +591,7 @@ class Gameday(commands.Cog): this_pitcher = data['pitcher'] # Get OBC and patch GameState score if necessary - logging.info('Get OBC and patch GameState score if necessary') + logger.info('Get OBC and patch GameState score if necessary') obc = self.on_base_code(this_state) rbi = 0 @@ -604,7 +605,7 @@ class Gameday(commands.Cog): new_outs = this_state['outs'] + outs # Advance runners - logging.info('Advance runners') + logger.info('Advance runners') if obc > 0 and bases > 0: rbi = self.advance_runners(this_state, bases, error=error, force_only=force_only) if bases == 4: @@ -624,7 +625,7 @@ class Gameday(commands.Cog): if this_state['top_half']: # Update score, batter up, and runner on first - logging.info(f'current batter: {this_state["away_batter_up"]} / next: {next_batters["away"]}') + logger.info(f'current batter: {this_state["away_batter_up"]} / next: {next_batters["away"]}') patch_game_state( this_state['id'], away_score=this_state['away_score'] + rbi, @@ -643,7 +644,7 @@ class Gameday(commands.Cog): inning=new_inning ) - logging.info(f'post AB:\ngame_id: {this_game["id"]}\nbatter_id: {this_batter["player_id"]}\n' + logger.info(f'post AB:\ngame_id: {this_game["id"]}\nbatter_id: {this_batter["player_id"]}\n' f'pitcher_id: {this_pitcher["player_id"]}\nobc: {obc}\ninning: {this_state["inning"]}\n' f'hit: {hit}\nrbi: {rbi}\nab: {ab}\nerror: {error}') this_ab = post_atbat({ @@ -671,16 +672,16 @@ class Gameday(commands.Cog): ds = get_defense_totals(x['id']) if bs['empty'] and rs['empty'] and ch['empty'] and len(ds['defense']) == 0: - logging.info(f'No stats for {this_player["name"]} - moving on') + logger.info(f'No stats for {this_player["name"]} - moving on') else: dpos = None if len(ds['defense']) == 1: - logging.info('one defense found') + logger.info('one defense found') if ds['defense'][0]['pos'] == x['position']: - logging.info('matches position') + logger.info('matches position') dpos = ds['defense'][0] else: - logging.info('doesn\'t match position') + logger.info('doesn\'t match position') line = ds['defense'][0] bats.append([ this_player['name'], this_player['team']['abbrev'], x['position'], '', '', '', @@ -690,13 +691,13 @@ class Gameday(commands.Cog): line['robs'], line['raa'], line['rto'] ]) else: - logging.info('many defenses found') + logger.info('many defenses found') for line in ds['defense']: if line['pos'] == line['pos']: - logging.info('this one matches pos') + logger.info('this one matches pos') dpos = line else: - logging.info('this one does not matche pos') + logger.info('this one does not matche pos') bats.append([ this_player['name'], this_player['team']['abbrev'], x['position'], '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', line['xch'], @@ -705,7 +706,7 @@ class Gameday(commands.Cog): line['robs'], line['raa'], line['rto'] ]) if not dpos: - logging.info('no defense found; adding blanks') + logger.info('no defense found; adding blanks') dpos = { 'xch': '', 'xhit': '', @@ -717,7 +718,7 @@ class Gameday(commands.Cog): 'raa': '', 'rto': '', } - logging.info('done with defense') + logger.info('done with defense') bats.append([ this_player['name'], this_player['team']['abbrev'], x['position'], bs['pa'], bs['ab'], bs['run'], @@ -737,7 +738,7 @@ class Gameday(commands.Cog): cs = get_chaos_totals(x['id']) if bs['empty'] and cs['empty']: - logging.info(f'No stats for {this_player["name"]} - moving on') + logger.info(f'No stats for {this_player["name"]} - moving on') else: arms.append([ this_player['name'], this_player['team']['abbrev'], bs['ip'], bs['hit'], bs['run'], bs['erun'], @@ -911,7 +912,7 @@ class Gameday(commands.Cog): # current = await db_get('current') this_team = await get_one_team(team_abbrev) this_game = get_game(channel_id=ctx.channel.id, active=1) - logging.info(f'this_game: {this_game}') + logger.info(f'this_game: {this_game}') if this_team['id'] not in [this_game['away_team_id'], this_game['home_team_id']]: away_team = await get_one_team(this_game['away_team_id']) home_team = await get_one_team(this_game['home_team_id']) @@ -961,7 +962,7 @@ class Gameday(commands.Cog): old_member = patch_lineup_member(members['members'][x]['id'], active=False) this_state = get_one_game_state(game_id=this_game['id']) - logging.info(f'old_member_id: {old_member["id"]} / on_first: {this_state["on_first"]} / ' + logger.info(f'old_member_id: {old_member["id"]} / on_first: {this_state["on_first"]} / ' f'on_second: {this_state["on_second"]} / on_third: {this_state["on_third"]}') if old_member in [this_state['on_first'], this_state['on_second'], this_state['on_third']]: if old_member == this_state['on_first']: @@ -1011,11 +1012,11 @@ class Gameday(commands.Cog): check_string += f'- {error_string}\n\n' if away_check['valid'] and home_check['valid']: - logging.info('Both lineups valid - sending gamestate') + logger.info('Both lineups valid - sending gamestate') content = None embed = await self.game_state_embed(this_game, full_length=False) else: - logging.info('Both lineups are not valid - sending check_string') + logger.info('Both lineups are not valid - sending check_string') content = check_string embed = None @@ -1339,7 +1340,7 @@ class Gameday(commands.Cog): # if resp is not None: # base_taken = resp # - # logging.info(f'defender: {defender}') + # logger.info(f'defender: {defender}') # post_defense({ # 'game_id': this_game['id'], # 'player_id': this_defender['player_id'], @@ -1532,7 +1533,7 @@ class Gameday(commands.Cog): error = 1 if hit == 0: data = self.log_play_core(this_game, bases=resp, error=1) - logging.info(f'error: {resp}') + logger.info(f'error: {resp}') if resp == 1: patch_game_state( state_id=this_state['id'], @@ -1953,7 +1954,7 @@ class Gameday(commands.Cog): async def show_pitcher_command(self, ctx): this_game = get_game(channel_id=ctx.channel.id, active=1) gs = get_game_state(game_id=this_game['id'])['states'][0] - logging.info(f'gs: {gs}') + logger.info(f'gs: {gs}') if gs['top_half']: this_member = get_one_member( @@ -1978,7 +1979,7 @@ class Gameday(commands.Cog): async def show_batter_command(self, ctx): this_game = get_game(channel_id=ctx.channel.id, active=1) gs = get_game_state(game_id=this_game['id'])['states'][0] - logging.info(f'gs: {gs}') + logger.info(f'gs: {gs}') if gs['top_half']: this_member = get_one_member( @@ -2009,7 +2010,7 @@ class Gameday(commands.Cog): gs = get_game_state(game_id=this_game['id'])['states'][0] pos = ctx.message.content.split(' ')[1].upper() - logging.info(f'pos: {pos}') + logger.info(f'pos: {pos}') this_player = await get_one_player(self.get_defender(this_game, pos)['player_id']) await ctx.send(content=None, embed=await get_player_embed(this_player, await db_get('current'))) @@ -2304,7 +2305,7 @@ class Gameday(commands.Cog): # Check for on base elif da_roll <= round(obp * 1000): bb_chance = (batter_bb + pitcher_bb) / (batter_ob + pitcher_ob - batter_hit - pitcher_hit) - logging.info(f'bb_chance: {bb_chance}') + logger.info(f'bb_chance: {bb_chance}') if random.random() <= bb_chance: result = 'Walk!' else: @@ -2324,7 +2325,7 @@ class Gameday(commands.Cog): embed.add_field(name='Result', value=result) - logging.info(f'{pitcher_player["name"]} vs {batter_player["name"]}\n' + logger.info(f'{pitcher_player["name"]} vs {batter_player["name"]}\n' f'batter OB: {batter_ob} / pitcher OB: {pitcher_ob}\n' f'batter BB: {batter_bb} / pitcher BB: {pitcher_bb}\n' f'batter hit: {batter_hit} / pitcher hit: {pitcher_hit}\n' diff --git a/cogs/gameplay.py b/cogs/gameplay.py index f2fc901..0a55b37 100644 --- a/cogs/gameplay.py +++ b/cogs/gameplay.py @@ -17,6 +17,7 @@ from db_calls_gameplay import StratGame, StratPlay, StratLineup, get_one_game, p get_current_play, post_play, get_one_lineup, advance_runners, patch_play, complete_play, get_batting_stats, \ get_pitching_stats, undo_play, get_latest_play, advance_one_runner, get_play_by_num +logger = logging.getLogger('discord_app') class Gameplay(commands.Cog): def __init__(self, bot): @@ -104,7 +105,7 @@ class Gameplay(commands.Cog): ) ) except Exception as e: - logging.info(f'ERROR: {e} / TYPE: {type(e)}') + logger.info(f'ERROR: {e} / TYPE: {type(e)}') away_lineup = await get_team_lineups(game.id, game.away_team_id) home_lineup = await get_team_lineups(game.id, game.home_team_id) if litmus == 0: @@ -127,7 +128,7 @@ class Gameplay(commands.Cog): async def get_game_state_embed(self, game: StratGame, full_length=True): game_state = await self.get_game_state(game) - logging.info(f'game_state: {game_state}') + logger.info(f'game_state: {game_state}') embed = get_team_embed( f'{game_state["away_team"]["sname"]} @ {game_state["home_team"]["sname"]}', @@ -375,13 +376,13 @@ class Gameplay(commands.Cog): all_lineups.append(this_lineup) - logging.info(f'Setting lineup for {owner_team["sname"]} in {"PD" if this_game.is_pd else "SBa"} game') + logger.info(f'Setting lineup for {owner_team["sname"]} in {"PD" if this_game.is_pd else "SBa"} game') post_lineups(all_lineups) try: await interaction.edit_original_response(content=None, embed=await self.get_game_state_embed(this_game)) except IntegrityError as e: - logging.info(f'Unable to pull game_state for game_id {this_game.id} until both lineups are in: {e}') + logger.info(f'Unable to pull game_state for game_id {this_game.id} until both lineups are in: {e}') await interaction.response.send_message(f'Game state will be posted once both lineups are in') return @@ -523,7 +524,7 @@ class Gameplay(commands.Cog): this_play = get_current_play(this_game.id) batter_to_base = 1 - logging.info(f'this_play: {this_play}') + logger.info(f'this_play: {this_play}') # Handle runner starting at second if this_play.on_second: this_runner = await get_player(this_game, this_play.on_second) @@ -547,7 +548,7 @@ class Gameplay(commands.Cog): else: await question.delete() - logging.info(f'this_play: {this_play}') + logger.info(f'this_play: {this_play}') # Handle runner starting at first if this_play.on_first and (not this_play.on_second or this_play.on_second_final != 3): this_runner = await get_player(this_game, this_play.on_first) @@ -571,7 +572,7 @@ class Gameplay(commands.Cog): else: await question.delete() - logging.info(f'this_play: {this_play}') + logger.info(f'this_play: {this_play}') # Handle batter runner if either runner from first or runner from second advanced if (this_play.on_first and this_play.on_first_final != 2) or \ (this_play.on_second and this_play.on_second_final != 3): @@ -593,7 +594,7 @@ class Gameplay(commands.Cog): else: await question.delete() - logging.info(f'this_play: {this_play}') + logger.info(f'this_play: {this_play}') complete_play(this_play.id, batter_to_base=batter_to_base) await ctx.send(content=None, embed=await self.get_game_state_embed(this_game, full_length=False)) @@ -1187,7 +1188,7 @@ class Gameplay(commands.Cog): defender = get_one_lineup( this_game.id, team_id=this_play.pitcher.team_id, position=pos ) - logging.info(f'defender: {defender}') + logger.info(f'defender: {defender}') patch_play(this_play.id, defender_id=defender.id, error=1 if error_allowed != 'out' else 0, check_pos=pos) # Not hit and no error diff --git a/cogs/owner.py b/cogs/owner.py index efe5d6c..0359ae0 100644 --- a/cogs/owner.py +++ b/cogs/owner.py @@ -7,6 +7,7 @@ from discord.ext import commands from discord.ext.commands import Greedy, Context from typing import Optional, Literal +logger = logging.getLogger('discord_app') class Owner(commands.Cog): def __init__(self, bot): @@ -17,7 +18,7 @@ class Owner(commands.Cog): async def load(self, ctx, *, cog: str): try: await self.bot.load_extension(f'cogs.{cog}') - logging.warning(f'Loaded {cog}') + logger.warning(f'Loaded {cog}') except Exception as e: await ctx.send(f'**ERROR:** {type(e).__name__} - {e}') else: @@ -28,7 +29,7 @@ class Owner(commands.Cog): async def unload(self, ctx, *, cog: str): try: await self.bot.unload_extension(f'cogs.{cog}') - logging.warning(f'Unloaded {cog}') + logger.warning(f'Unloaded {cog}') except Exception as e: await ctx.send(f'**ERROR:** {type(e).__name__} - {e}') else: @@ -39,9 +40,9 @@ class Owner(commands.Cog): async def reload(self, ctx, *, cog: str): try: await self.bot.unload_extension(f'cogs.{cog}') - logging.warning(f'Unloaded {cog}') + logger.warning(f'Unloaded {cog}') await self.bot.load_extension(f'cogs.{cog}') - logging.warning(f'Reloaded {cog}') + logger.warning(f'Reloaded {cog}') except Exception as e: await ctx.send(f'**ERROR:** {type(e).__name__} - {e}') else: @@ -55,14 +56,14 @@ class Owner(commands.Cog): for x in cogs: try: await self.bot.unload_extension(f'cogs.{x}') - logging.warning(f'Unloaded {x}') + logger.warning(f'Unloaded {x}') except Exception as e: await ctx.send(f'Failed to unload **{x}**') for x in cogs: try: await self.bot.load_extension(f'cogs.{x}') - logging.warning(f'Loaded {x}') + logger.warning(f'Loaded {x}') except Exception as e: await ctx.send(f'Failed to load **{x}**') @@ -78,49 +79,64 @@ class Owner(commands.Cog): # sync = await self.bot.tree.sync() # else: # sync = await self.bot.tree.sync(guild=discord.Object(os.environ.get('GUILD_ID'))) - # logging.warning(f'sync: {sync}') + # logger.warning(f'sync: {sync}') # except Exception as e: - # logging.error(f'failed to sync: {e}') + # logger.error(f'failed to sync: {e}') # # await ctx.send(f'Just ran the sync. Here is the output:\n{sync}') - @commands.command() + @commands.command(name='sync', help='~ current guild, * global -> current, ! clear and sync current') @commands.is_owner() - async def sync(self, ctx: Context, guilds: Greedy[Object], spec: Optional[Literal['~', "*", '!']] = None) -> None: + async def sync(self, ctx: Context, guilds: Greedy[Object], spec: Optional[Literal['~', "*", '!', '^']] = None) -> None: """ - !sync -> global sync - !sync ~ -> sync current guild - !sync * -> copies all global app commands to current guild and syncs - !sync id_1 id_2 -> syncs guilds with id 1 and 2 + !sync + This takes all global commands within the CommandTree and sends them to Discord. (see CommandTree for more info.) + !sync ~ + This will sync all guild commands for the current contexts guild. + !sync * + This command copies all global commands to the current guild (within the CommandTree) and syncs. + !sync ^ + This command will remove all guild commands from the CommandTree and syncs, which effectively removes all commands from the guild. + !sync 123 456 789 + This command will sync the 3 guild ids we passed: 123, 456 and 789. Only their guilds and guild-bound commands. """ + logger.info(f'{ctx.author.name} has initiated a sync from guild ID {ctx.guild.id}') if not guilds: if spec == "~": - fmt = await ctx.bot.tree.sync(guild=ctx.guild) + synced = await ctx.bot.tree.sync(guild=ctx.guild) elif spec == "*": ctx.bot.tree.copy_global_to(guild=ctx.guild) - fmt = await ctx.bot.tree.sync(guild=ctx.guild) - elif spec == '!': + synced = await ctx.bot.tree.sync(guild=ctx.guild) + elif spec == "^": ctx.bot.tree.clear_commands(guild=ctx.guild) - await ctx.send(f'Cleared all local commands.') - fmt = await ctx.bot.tree.sync(guild=ctx.guild) + await ctx.bot.tree.sync(guild=ctx.guild) + synced = [] + elif spec == '!': + await ctx.bot.tree.sync() + + ctx.bot.tree.copy_global_to(guild=ctx.guild) + await ctx.bot.tree.sync(guild=ctx.guild) + + ctx.bot.tree.clear_commands(guild=ctx.guild) + synced = await ctx.bot.tree.sync(guild=ctx.guild) else: - fmt = await ctx.bot.tree.sync() + synced = await ctx.bot.tree.sync() await ctx.send( - f"Synced {len(fmt)} commands {'globally' if spec is None else 'to the current guild.'}" + f"Synced {len(synced)} commands {'globally' if spec is None else 'to the current guild.'}" ) return - fmt = 0 + ret = 0 for guild in guilds: try: await ctx.bot.tree.sync(guild=guild) except discord.HTTPException: pass else: - fmt += 1 + ret += 1 - await ctx.send(f"Synced the tree to {fmt}/{len(guilds)} guilds.") + await ctx.send(f"Synced the tree to {ret}/{len(guilds)}.") async def setup(bot): diff --git a/cogs/players.py b/cogs/players.py index 1419d95..bf2e769 100644 --- a/cogs/players.py +++ b/cogs/players.py @@ -14,6 +14,7 @@ from db_calls import db_get, db_patch, get_team_by_abbrev, get_team_by_owner, pu db_delete from typing import Literal, Optional +logger = logging.getLogger('discord_app') class BatStat(pydantic.BaseModel): player_id: int @@ -91,7 +92,15 @@ class Players(commands.Cog): self.build_master_player_list.start() self.live_scorecard_loop.start() + + async def cog_command_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error}\n\nRun !help to see the command requirements') + async def slash_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error[:1600]}') + # async def cog_command_error(self, ctx, error): # await ctx.send(f'{error}\n\nRun !help to see the command requirements') @@ -115,7 +124,7 @@ class Players(commands.Cog): if tquery['count'] > 0: team = tquery['teams'][0] except (ValueError, AttributeError, requests.ReadTimeout) as e: - logging.info(f'{type(e)}: {e}') + logger.info(f'{type(e)}: {e}') if team is not None: embed = discord.Embed( @@ -134,28 +143,28 @@ class Players(commands.Cog): async def game_scorebug(self, sheets_data, include_images: bool = True, full_length: bool = True): away_team = await db_get('teams', object_id=sheets_data.get_value('B5')) home_team = await db_get('teams', object_id=sheets_data.get_value('B6')) - logging.info(f'getting gamestate / full_length: {full_length}') + logger.info(f'getting gamestate / full_length: {full_length}') all_data = sheets_data.get_values('B2', 'S20', include_tailing_empty_rows=True) # game_state = sheets_data.get_values('B2', 'G8', include_tailing_empty_rows=True) game_state = [ all_data[0][:6], all_data[1][:6], all_data[2][:6], all_data[3][:6], all_data[4][:6], all_data[5][:6], all_data[6][:6] ] - logging.info(f'gamestate: {game_state}') + logger.info(f'gamestate: {game_state}') header = game_state[0][0] is_final = header[-5:] == 'FINAL' # inning_desc = {header.split(" - ")[1]} away_score = game_state[3][2] home_score = game_state[4][2] which_half = game_state[3][4] - logging.info(f'getting runners') + logger.info(f'getting runners') # runners = sheets_data.get_values('K11', 'L14', include_tailing_empty_rows=True) runners = [ all_data[9][9:11], all_data[10][9:11], all_data[11][9:11], all_data[12][9:11] ] - logging.info(f'runners: {runners}') - logging.info(f'getting matchups') + logger.info(f'runners: {runners}') + logger.info(f'getting matchups') this_embed = get_team_embed( # title=f'[{away_team["sname"]}]({get_team_url(away_team)}) @ ' @@ -194,16 +203,16 @@ class Players(commands.Cog): inline=False ) - logging.info(f'Checking if not full_length') + logger.info(f'Checking if not full_length') if not full_length: - logging.info(f'not full_length, returning now') + logger.info(f'not full_length, returning now') return this_embed # matchups = sheets_data.get_values('K3', 'O6', include_tailing_empty_rows=True) matchups = [ all_data[1][9:14], all_data[2][9:14], all_data[3][9:14], all_data[4][9:14], ] - logging.info(f'matchups: {matchups}') + logger.info(f'matchups: {matchups}') p_name = matchups[0][0] this_embed.add_field( @@ -261,14 +270,14 @@ class Players(commands.Cog): @tasks.loop(count=1) async def build_master_player_list(self): - # logging.info(f'build_master_player_list - getting current') + # logger.info(f'build_master_player_list - getting current') current = await db_get('current') - # logging.info(f'build_master_player_list - getting all_players') + # logger.info(f'build_master_player_list - getting all_players') p_query = await db_get('players', timeout=8, params=[('season', current['season'])]) - # logging.info(f'build_master_player_list - building player_list') + # logger.info(f'build_master_player_list - building player_list') self.player_list = {x['name'].lower(): x['id'] for x in p_query['players']} - logging.info(f'player list count: {len(self.player_list)}') - logging.debug(f'player list: {self.player_list}') + logger.info(f'player list count: {len(self.player_list)}') + logger.debug(f'player list: {self.player_list}') @build_master_player_list.before_loop async def before_build_master_player_list(self): @@ -285,12 +294,12 @@ class Players(commands.Cog): if len(self.voice_channels) > 0: all_embeds = [] for x in self.scorecards.values(): - logging.info(f'looping through scorecards') + logger.info(f'looping through scorecards') await asyncio.sleep(1) - logging.info(f'creating embeds') + logger.info(f'creating embeds') all_embeds.append(await self.game_scorebug(x, include_images=False)) - logging.info(f'embeds: {all_embeds}') + logger.info(f'embeds: {all_embeds}') if len(all_embeds) > 0: # Clear old messages async for message in score_channel.history(limit=25): @@ -327,7 +336,7 @@ class Players(commands.Cog): except Exception as e: await send_to_channel(self.bot, 'commissioners-office', f'Could not update live scorecard:\n\n{e}') - logging.error(f'Could not update live scorecard: {e}') + logger.error(f'Could not update live scorecard: {e}') @live_scorecard_loop.before_loop async def before_live_scorecard_loop(self): @@ -521,7 +530,7 @@ class Players(commands.Cog): await message.author.send('I deleted your last trade-block message to help keep it clean.') # if len(message.content) == 1 and not message.content.isnumeric() and message.content.lower() != 'k': - # logging.info( + # logger.info( # f'Found spam from **{message.author.nick}** in **{message.channel.name}**: {message.content}' # ) # if 'shitpost' not in message.channel.name and 'sbb' not in message.channel.name: @@ -587,7 +596,7 @@ class Players(commands.Cog): embed.add_field(name=f'{team["sname"]} Overview', value=overview_string, inline=False) except (ValueError, TypeError) as e: - logging.info(f'Could not pull standings for season {team["season"]} {team["abbrev"]}') + logger.info(f'Could not pull standings for season {team["season"]} {team["abbrev"]}') # Get player info il_players = None @@ -634,7 +643,7 @@ class Players(commands.Cog): upcoming_string = '' full_sched = sorted(team_schedule, key=lambda y: y['id']) - logging.info(f'full_sched: {full_sched}') + logger.info(f'full_sched: {full_sched}') for matchup in full_sched: st_abbrev = matchup['awayteam']['abbrev'] @@ -686,41 +695,50 @@ class Players(commands.Cog): name_reg = re.compile(r'(s\d+)* *(.*)', re.IGNORECASE) player_search = name_reg.search(name) - logging.info(f'player_search: {player_search}') - logging.info(f'player_search.group(): {player_search.group()} / group(1): {player_search.group(1)} ' + logger.info(f'player_search: {player_search}') + logger.info(f'player_search.group(): {player_search.group()} / group(1): {player_search.group(1)} ' f'/ group(2): {player_search.group(2)}') - # No season is included - if not player_search.group(1): - p_name = await fuzzy_player_search(ctx, ctx.channel, self.bot, name, self.player_list.keys()) - player = await db_get('players', object_id=self.player_list[p_name]) - # Season is included - else: - season = int(player_search.group(1)[1:]) + async with ctx.typing(): + # No season is included + if not player_search.group(1): + try: + p_name = await fuzzy_player_search(ctx, ctx.channel, self.bot, name, self.player_list.keys()) + except ValueError as e: + logger.error(e) + await ctx.send(f'{name} not found') + return + player = await db_get('players', object_id=self.player_list[p_name]) + # Season is included + else: + season = int(player_search.group(1)[1:]) - p_query = await db_get('players', params=[('season', season), ('name', player_search.group(2))]) - if p_query['count'] == 0: - async with ctx.typing(): + p_query = await db_get('players', params=[('season', season), ('name', player_search.group(2))]) + if p_query['count'] == 0: p_query = await db_get('players', params=[('season', season), ('short_output', True)]) if p_query['count'] == 0: await ctx.send(f'I did not find any players in season {season}') return - p_name = await fuzzy_player_search( - ctx, ctx.channel, self.bot, player_search.group(2).strip(), - [x['name'].lower() for x in p_query['players']] - ) - p_query2 = await db_get('players', params=[('season', season), ('name', p_name)]) - player = p_query2['players'][0] + try: + p_name = await fuzzy_player_search( + ctx, ctx.channel, self.bot, player_search.group(2).strip(), + [x['name'].lower() for x in p_query['players']] + ) + except ValueError as e: + logger.error(e) + await ctx.send(f'{name} not found') + return + p_query2 = await db_get('players', params=[('season', season), ('name', p_name)]) + player = p_query2['players'][0] - async with ctx.typing(): embeds = [await get_player_embed(player, current, ctx, season)] if player['image2']: embed = get_team_embed(f'{player["name"]}', player["team"], thumbnail=False) embed.set_image(url=player['image2']) embeds.append(embed) - await ctx.send(content=None, embeds=embeds) + await ctx.send(content=None, embeds=embeds) @commands.command(name='career', help='Get player\'s career stats') async def career_command(self, ctx, *, name): @@ -1050,7 +1068,7 @@ class Players(commands.Cog): current = await db_get('current') div_embed = await self.get_division_standings(current) wc_embed = await self.get_wildcard_standings(current) - logging.info(f'div_embed: {div_embed}\nwc_embed: {wc_embed}') + logger.info(f'div_embed: {div_embed}\nwc_embed: {wc_embed}') view = Pagination(responders=[ctx.author], timeout=15) view.left_button.label = 'Division' @@ -1067,7 +1085,7 @@ class Players(commands.Cog): await view.wait() if view.value: - logging.info(f'standings_button_loop - view.value: {view.value}') + logger.info(f'standings_button_loop - view.value: {view.value}') if view.value == 'cancel': await st_message.edit(view=None) return @@ -1089,7 +1107,7 @@ class Players(commands.Cog): embed = wc_embed view.right_button.disabled = True - logging.info(f'standings_button_loop - start: {start} / embed == div_embed? {embed == div_embed} / ' + logger.info(f'standings_button_loop - start: {start} / embed == div_embed? {embed == div_embed} / ' f'embed == wc_embed {embed == wc_embed}') await st_message.delete() st_message = await ctx.send(content=None, embed=embed, view=view) @@ -1278,14 +1296,14 @@ class Players(commands.Cog): # Go get scorecard await interaction.response.send_message(content='I\'ll go grab that card now...') - logging.info(f'Checking scorecard {sheet_url}') + logger.info(f'Checking scorecard {sheet_url}') # Try to get card try: sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') scorecard = sheets.open_by_url(sheet_url) except Exception as e: - logging.error(f'Failed to access scorecard {sheet_url}: {e}') + logger.error(f'Failed to access scorecard {sheet_url}: {e}') await interaction.edit_original_response(content='Is that sheet public? I can\'t access it.') return @@ -1312,7 +1330,7 @@ class Players(commands.Cog): home_mgr_name = g_data[4][1] away_team = await get_team_by_abbrev(at_abbrev, current['season']) home_team = await get_team_by_abbrev(ht_abbrev, current['season']) - logging.info(f'away_manager: {away_mgr_name} / home_manager: {home_mgr_name}') + logger.info(f'away_manager: {away_mgr_name} / home_manager: {home_mgr_name}') if away_team['manager2'] is not None and away_team['manager2']['name'].lower() == away_mgr_name.lower(): away_manager = away_team['manager2'] else: @@ -1322,7 +1340,7 @@ class Players(commands.Cog): else: home_manager = home_team['manager1'] - logging.info(f'gdata: {g_data}\nweek/game: {week_num}/{game_num}') + logger.info(f'gdata: {g_data}\nweek/game: {week_num}/{game_num}') # Confirm submitting GM if await get_team_by_owner(current['season'], interaction.user.id) not in [home_team, away_team] and \ @@ -1354,11 +1372,11 @@ class Players(commands.Cog): try: await db_delete('plays/game', object_id=dupe_game['id']) except ValueError as e: - logging.error(f'No plays for game {dupe_game["id"]}') + logger.error(f'No plays for game {dupe_game["id"]}') try: await db_delete('decisions/game', object_id=dupe_game['id']) except ValueError as e: - logging.error(f'No decisions for game {dupe_game["id"]}') + logger.error(f'No decisions for game {dupe_game["id"]}') await db_post(f'games/wipe/{dupe_game["id"]}') else: await interaction.edit_original_response( @@ -1378,16 +1396,16 @@ class Players(commands.Cog): ) return this_game = g_query['games'][0] - logging.info(f'this_game: {this_game}') + logger.info(f'this_game: {this_game}') # TODO: check for stats and wipe - logging.info(f'checking for old stats') + logger.info(f'checking for old stats') await interaction.edit_original_response(content='Here I go sheetsing again...', view=None) - logging.info(f'sba-submit - reading scorecard') + logger.info(f'sba-submit - reading scorecard') playtable = scorecard.worksheet_by_title('Playtable') all_plays = playtable.get_values('B3', 'BW300') - logging.debug(f'all_plays: {all_plays}') + logger.debug(f'all_plays: {all_plays}') play_keys = [ 'play_num', 'batter_id', 'batter_pos', 'pitcher_id', 'on_base_code', 'inning_half', 'inning_num', @@ -1412,13 +1430,13 @@ class Players(commands.Cog): p_data.append(this_data) final_inning = line[6] - logging.info(f'players - final_inning: {final_inning}') - logging.info(f'p_data: {p_data}') + logger.info(f'players - final_inning: {final_inning}') + logger.info(f'p_data: {p_data}') # Post plays try: resp = await db_post('plays', payload={'plays': p_data}) except ValueError as e: - logging.error(f'POST plays error: {e}') + logger.error(f'POST plays error: {e}') await interaction.edit_original_response( content=f'The following errors were found in your **wk{week_num}g{game_num}** scorecard. ' f'Please resolve them and resubmit - thanks!\n\n{e}' @@ -1432,9 +1450,9 @@ class Players(commands.Cog): except pygsheets.WorksheetNotFound as e: sc_tab = scorecard.worksheet_by_title('Box Score') score_table = sc_tab.get_values('T6', 'V7') - logging.info(f'players - score_table: {score_table}') + logger.info(f'players - score_table: {score_table}') # final_inning = all_plays[len(all_plays) - 1][6] - # logging.info(f'players - final_inning: {final_inning}') + # logger.info(f'players - final_inning: {final_inning}') # Log game result try: @@ -1444,7 +1462,7 @@ class Players(commands.Cog): ('game_num', game_num), ('scorecard_url', sheet_url) ]) except ValueError as e: - logging.error(f'PATCH game error: {e}') + logger.error(f'PATCH game error: {e}') await interaction.edit_original_response( content=f'I was not able to log the game result. Go bug cal - it\'s probably his fault.' ) @@ -1454,7 +1472,7 @@ class Players(commands.Cog): # Pull pitching decisions pitching = scorecard.worksheet_by_title('Pitcherstats') all_decisions = pitching.get_values('B3', 'O30') - logging.info(f'all_decisions: {all_decisions}') + logger.info(f'all_decisions: {all_decisions}') pit_keys = [ 'pitcher_id', 'rest_ip', 'is_start', 'base_rest', 'extra_rest', 'rest_required', 'win', @@ -1491,12 +1509,12 @@ class Players(commands.Cog): await db_delete(f'plays/game', object_id=this_game['id'], timeout=6) return - logging.info(f'pit_data: {pit_data}') + logger.info(f'pit_data: {pit_data}') # Post decisions try: d_resp = await db_post('decisions', payload={'decisions': pit_data}) except ValueError as e: - logging.error(f'POST decisions error: {e}') + logger.error(f'POST decisions error: {e}') await interaction.edit_original_response( content=f'The following errors were found in your **wk{week_num}g{game_num}** scorecard. ' f'Please resolve them and resubmit - thanks!\n\n{e}' @@ -1551,21 +1569,21 @@ class Players(commands.Cog): embed.add_field(name='Pitching', value=pitching_string, inline=False) # Key Plays pull - logging.info(f'pull highlight stats for embed') + logger.info(f'pull highlight stats for embed') p_query = await db_get('plays', params=[ ('game_id', this_game['id']), ('sort', 'wpa-desc'), ('limit', 3) ]) key_plays = '' for play in p_query['plays']: - logging.info(f'this_play: {play}') + logger.info(f'this_play: {play}') this_line = f'- {play["inning_half"].title()} {play["inning_num"]}: ' # Offensive Play if play['wpa'] > 0: - logging.info('OFFENSE') + logger.info('OFFENSE') if play['runner'] is not None: - logging.info('RUNNER') + logger.info('RUNNER') if play['on_third'] == play['runner']['id']: s_base = 'HOME' elif play['on_second'] == play['runner']['id']: @@ -1574,7 +1592,7 @@ class Players(commands.Cog): s_base = 'second' this_line += f'{play["runner"]["name"]} ({play["runner"]["team"]["abbrev"]}) steals {s_base}' else: - logging.info('BATTER') + logger.info('BATTER') if play['homerun'] == 1: h_name = 'homers' elif play['triple'] == 1: @@ -1585,18 +1603,18 @@ class Players(commands.Cog): h_name = 'sac flies' else: h_name = 'singles' - logging.info('RBI?') + logger.info('RBI?') if play['rbi'] > 0: rbi_string = f' in {play["rbi"]} run{"s" if play["rbi"] > 1 else ""}' else: rbi_string = '' - logging.info('LINE?') + logger.info('LINE?') this_line += f'{play["batter"]["name"]} ({play["batter"]["team"]["abbrev"]}) {h_name}{rbi_string}' # Defensive Play else: - logging.info('DEFENSE') + logger.info('DEFENSE') if play['catcher'] is not None: - logging.info('CATCHER') + logger.info('CATCHER') if play['on_third_final'] == 0: s_base = 'HOME' elif play['on_second_final'] == 0: @@ -1606,7 +1624,7 @@ class Players(commands.Cog): this_line += f'{play["catcher"]["name"]} ({play["catcher"]["team"]["abbrev"]}) throws out the ' \ f'runner at {s_base}' elif play['defender'] is not None: - logging.info('DEFENDER') + logger.info('DEFENDER') if play['outs'] == 3: play_string = 'turns a TRIPLE PLAY' elif play['outs'] == 2: @@ -1615,7 +1633,7 @@ class Players(commands.Cog): play_string = f'makes a tough play at {play["check_pos"]}' this_line += f'{play["defender"]["name"]} ({play["defender"]["team"]["abbrev"]}) {play_string}' else: - logging.info('PITCHER') + logger.info('PITCHER') if play['so'] == 1: if play['starting_outs'] == 2: out_th = 'for the 3rd out' @@ -1781,7 +1799,7 @@ class Players(commands.Cog): # ) # await interaction.edit_original_response(content='You are all set!') # except Exception as e: - # logging.error(f'could not freeze sheet for game {this_game["id"]}') + # logger.error(f'could not freeze sheet for game {this_game["id"]}') # await interaction.edit_original_response( # content='You didn\'t give me edit perms so I couldn\'t lock the rosters in your sheet, ' # 'but everything else went through.' @@ -1814,8 +1832,8 @@ class Players(commands.Cog): show_dice = False if not team or not team_role: - await interaction.response.send_message( - f'Do you have a team here? You don\'t look familiar. {await get_emoji(interaction, "realeyes")}' + await interaction.edit_original_response( + content=f'Do you have a team here? You don\'t look familiar. {await get_emoji(interaction, "realeyes")}' ) return @@ -1824,7 +1842,7 @@ class Players(commands.Cog): try: await team_role.edit(colour=color_int) except Exception as e: - logging.info(f'Error setting {team["sname"]} color to {color_hex}') + logger.info(f'Error setting {team["sname"]} color to {color_hex}') errors.append(f'- Error setting {team["sname"]} color to {color_hex}:\n{e}\n\n') team['color'] = color_hex await db_patch('teams', object_id=team['id'], params=[('color', color_hex)]) @@ -1839,7 +1857,7 @@ class Players(commands.Cog): await db_patch('teams', object_id=mil_team['id'], params=[('color', mil_color_hex)]) show_mil = True except Exception as e: - logging.info(f'Error setting {team["sname"]} color to {mil_color_hex}') + logger.info(f'Error setting {team["sname"]} color to {mil_color_hex}') errors.append(f'- Error setting {team["sname"]} color to {mil_color_hex}:\n{e}\n\n') if mil_team_image_url is not None: if requests.get(mil_team_image_url, timeout=3).status_code != 200: @@ -1852,7 +1870,7 @@ class Players(commands.Cog): await db_patch('teams', object_id=team['id'], params=[('dice_color', dice_color_hex)]) show_dice = True except Exception as e: - logging.info(f'Error setting {team["sname"]} color to {color_hex}') + logger.info(f'Error setting {team["sname"]} color to {color_hex}') errors.append(f'- Error setting {team["sname"]} color to {color_hex}:\n{e}\n\n') team = await db_get('teams', object_id=team['id']) @@ -1873,15 +1891,15 @@ class Players(commands.Cog): embeds.append(mil_embed) if show_dice: - logging.info(f'entering show_dice') + logger.info(f'entering show_dice') team['color'] = team['dice_color'] dice_embed = get_team_embed(f'{team["lname"]} Dice Test', team=team) - logging.info(f'got base embed: {dice_embed}') + logger.info(f'got base embed: {dice_embed}') dice_embed.add_field( name='Little Test Data', value='This is what we\'ve got for your dice rolls!' ) - logging.info(f'done with embed: {dice_embed}') + logger.info(f'done with embed: {dice_embed}') embeds.append(dice_embed) await interaction.edit_original_response(content=None, embeds=embeds) @@ -1909,7 +1927,7 @@ class Players(commands.Cog): overwrites=overwrites, category=discord.utils.get(ctx.guild.categories, name=f'Voice Channels') ) - logging.info(f'Just created voice channel: {channel_name} for {ctx.author}') + logger.info(f'Just created voice channel: {channel_name} for {ctx.author}') self.voice_channels.append(this_vc) await ctx.send(f'Just created {this_vc} for you!') @@ -1921,7 +1939,7 @@ class Players(commands.Cog): try: await this_vc.delete() except Exception as e: - logging.error(f'could not delete {this_vc}.') + logger.error(f'could not delete {this_vc}.') break @commands.command(name='private', help='Get private vc') @@ -1975,7 +1993,7 @@ class Players(commands.Cog): await ctx.send('Fine. I bet they didn\'t wanna talk to you anyway.') return - logging.info(f'getting roles') + logger.info(f'getting roles') this_team_role = discord.utils.get(ctx.guild.roles, name=f'{this_team["lname"]}') other_team_role = discord.utils.get(ctx.guild.roles, name=f'{other_team["lname"]}') @@ -1983,11 +2001,11 @@ class Players(commands.Cog): await ctx.send(f'Tell Cal that we\'re missing a team role to create this channel.') return - logging.info(f'getting overwrites') + logger.info(f'getting overwrites') overwrites = {ctx.guild.default_role: discord.PermissionOverwrite(speak=False), this_team_role: discord.PermissionOverwrite(speak=True), other_team_role: discord.PermissionOverwrite(speak=True)} - logging.info(f'creating channel') + logger.info(f'creating channel') this_vc = await ctx.guild.create_voice_channel( channel_name, overwrites=overwrites, @@ -2004,7 +2022,7 @@ class Players(commands.Cog): try: await this_vc.delete() except Exception as e: - logging.error(f'could not delete {this_vc}.') + logger.error(f'could not delete {this_vc}.') break @commands.command(name='headshot', aliases=['hs'], help='Set headshot pic') @@ -2197,7 +2215,7 @@ class Players(commands.Cog): # # await interaction.response.send_message(content=f'{team["sname"]} Keepers:\n{keeper_string}') # all_players = await db_get('players', api_ver=3, params=[('team_abbrev', team['abbrev'])]) - # logging.info(f'all_players: {all_players}') + # logger.info(f'all_players: {all_players}') # # fa = await get_team_by_abbrev('FA', current['season']) # for y in all_players['players']: @@ -2257,12 +2275,12 @@ class Players(commands.Cog): await interaction.response.send_message(f'I am checking sheets now...', ephemeral=True) - logging.info(f'scorebug_slash: full_length: {full_length}') + logger.info(f'scorebug_slash: full_length: {full_length}') try: game_embed = await self.game_scorebug(this_scorecard, full_length=full_length) await interaction.edit_original_response(content=None, embed=game_embed) except Exception as e: - logging.error(e) + logger.error(e) await interaction.edit_original_response( content='I was not able to generate a scorebug for this game' ) @@ -2358,11 +2376,11 @@ class Players(commands.Cog): injury_string = f'```md\n# {injury_roll}\n' \ f'Details:[3d6 ({d_six_one} {d_six_two} {d_six_three})]\n```\n' - logging.info(f'injury rating: {rating.value}p{games.value}') + logger.info(f'injury rating: {rating.value}p{games.value}') injury_list = inj_data[p_ratings[rating.value - 1]][f'p{games.value}'] injury_result = injury_list[injury_roll - 3] - logging.info(f'injury rating: {rating.value}p{games.value} / array: {injury_list}[{injury_roll - 2}] / result: {injury_result}') + logger.info(f'injury rating: {rating.value}p{games.value} / array: {injury_list}[{injury_roll - 2}] / result: {injury_result}') if isinstance(injury_result, int): try: @@ -2370,7 +2388,7 @@ class Players(commands.Cog): content=random_gif(random_from_list(['salute', 'press f', 'pay respects', 'well shit'])) ) except Exception as e: - logging.info(f'failed to post funny gif') + logger.info(f'failed to post funny gif') injury_string += f'With a roll of {injury_roll}, the injury length is **{injury_result} ' \ f'game{"s" if injury_result > 1 else ""}**.' elif injury_result == 'REM': @@ -2379,7 +2397,7 @@ class Players(commands.Cog): content=random_gif(random_from_list(['could be worse', 'not too bad'])) ) except Exception as e: - logging.info(f'failed to post funny gif') + logger.info(f'failed to post funny gif') injury_string += f'With a roll of {injury_roll}, the injury length is **REMAINDER OF GAME** for batters ' \ f'or **FATIGUED** for pitchers' else: @@ -2388,7 +2406,7 @@ class Players(commands.Cog): content=random_gif(random_from_list(['it is fine', 'nothing to see here', 'i wasn\'t worried'])) ) except Exception as e: - logging.info(f'failed to post funny gif') + logger.info(f'failed to post funny gif') injury_string += f'With a roll of {injury_roll}, the player is **OKAY** - no injury!' embed = await self.get_dice_embed( diff --git a/cogs/transactions.py b/cogs/transactions.py index dc7205f..cca3143 100644 --- a/cogs/transactions.py +++ b/cogs/transactions.py @@ -5,6 +5,7 @@ from helpers import * from db_calls import db_get, db_patch, get_team_by_owner, get_team_by_abbrev, get_player_by_name, put_player, db_post from discord.ext import commands, tasks OFFSEASON_FLAG = True +logger = logging.getLogger('discord_app') class SBaTransaction: @@ -22,7 +23,7 @@ class SBaTransaction: if first_team and team_role: self.add_team(first_team, team_role) if (first_team and not team_role) or (team_role and not first_team): - logging.error(f'Trade creation failed:\nteam: {first_team}\nteam_role: {team_role}') + logger.error(f'Trade creation failed:\nteam: {first_team}\nteam_role: {team_role}') raise ValueError('Trade creation failed') def add_team(self, new_team, role): @@ -69,7 +70,7 @@ class SBaTransaction: async def not_available(self, player, this_week=False): transactions = await self.get_player_moves(player, this_week) - logging.info(f'Is {player["name"]} not available? - {len(transactions)}') + logger.info(f'Is {player["name"]} not available? - {len(transactions)}') if len(transactions) > 0: return True return False @@ -160,7 +161,7 @@ class SBaTransaction: for player in mil_roster: mil_wara += player['wara'] - logging.info(f'checking future moves') + logger.info(f'checking future moves') if self.effective_week > self.current['week']: # set_moves = await get_transactions( # self.current['season'], team_abbrev=this_team['abbrev'], week_start=self.effective_week, @@ -201,9 +202,9 @@ class SBaTransaction: mil_roster.remove(x['player']) mil_wara -= x['player']['wara'] - logging.info(f'updating rosters') + logger.info(f'updating rosters') for x in self.players: - logging.info(f'x player: {x}') + logger.info(f'x player: {x}') # If player is joining this team, add to roster and add WARa if self.players[x]['to'] == this_team: team_roster.append(self.players[x]['player']) @@ -218,8 +219,8 @@ class SBaTransaction: # If player is leaving this team next week, remove from roster and subtract WARa if self.players[x]['player']['team'] == this_team: - logging.info(f'major league player') - # logging.info(f'team roster: {team_roster}') + logger.info(f'major league player') + # logger.info(f'team roster: {team_roster}') team_roster.remove(self.players[x]['player']) # 06-13: COMMENTED OUT TO RESOLVE MID-WEEK IL REPLACEMENT BEING SENT BACK DOWN # if self.effective_week != self.current['week']: @@ -227,9 +228,9 @@ class SBaTransaction: # If player is leaving MiL team next week, remove from roster and subtract WARa if self.players[x]['player']['team']['abbrev'] == f'{this_team["abbrev"]}MiL': - logging.info(f'minor league player') + logger.info(f'minor league player') mil_roster.remove(self.players[x]['player']) - # logging.info(f'mil roster: {mil_roster}') + # logger.info(f'mil roster: {mil_roster}') if self.effective_week != self.current['week']: mil_wara -= self.players[x]['player']['wara'] @@ -283,7 +284,7 @@ class SBaTransaction: moveid = f'Season-{self.current["season"]:03d}-Week-{self.effective_week:0>2}-{datetime.datetime.now().strftime("%d-%H:%M:%S")}' moves = [] - logging.warning(f'move_id: {moveid} / move_type: {self.move_type} / avoid_freeze: {self.avoid_freeze} / ' + logger.warning(f'move_id: {moveid} / move_type: {self.move_type} / avoid_freeze: {self.avoid_freeze} / ' f'week: {self.current["week"]}') if self.current['freeze'] and not self.avoid_freeze: frozen = True @@ -329,7 +330,15 @@ class Transactions(commands.Cog): self.trade_season = False self.weekly_loop.start() + + async def cog_command_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error}\n\nRun !help to see the command requirements') + async def slash_error(self, ctx, error): + logger.error(msg=error, stack_info=True, exc_info=True) + await ctx.send(f'{error[:1600]}') + @tasks.loop(minutes=1) async def weekly_loop(self): if OFFSEASON_FLAG: @@ -337,7 +346,7 @@ class Transactions(commands.Cog): current = await db_get('current') now = datetime.datetime.now() - logging.debug(f'Datetime: {now} / weekday: {now.weekday()}') + logger.debug(f'Datetime: {now} / weekday: {now.weekday()}') # Begin Freeze # if now.weekday() == 0 and now.hour == 5 and not current['freeze']: # Spring/Summer @@ -346,14 +355,14 @@ class Transactions(commands.Cog): await db_patch('current', object_id=current['id'], params=[('week', current['week']), ('freeze', True)]) await self.run_transactions(current) - logging.debug(f'Building freeze string') + logger.debug(f'Building freeze string') week_num = f'Week {current["week"]}' stars = f'{"":*<32}' freeze_message = f'```\n' \ f'{stars}\n'\ f'{week_num: >9} Freeze Period Begins\n' \ f'{stars}\n```' - logging.debug(f'Freeze string:\n\n{freeze_message}') + logger.debug(f'Freeze string:\n\n{freeze_message}') await send_to_channel(self.bot, 'transaction-log', freeze_message) if current['week'] > 0 and current['week'] <= 18: @@ -439,11 +448,11 @@ class Transactions(commands.Cog): ('frozen', True) ]) if m_query['count'] == 0: - logging.warning(f'No transactions to process for the freeze in week {current["week"]}') + logger.warning(f'No transactions to process for the freeze in week {current["week"]}') return moves = m_query['transactions'] - logging.info(f'freeze / all_moves: {len(moves)}') + logger.info(f'freeze / all_moves: {len(moves)}') # {'player name': [[Player, TeamAdding, moveid], [Player, OtherTeamAdding, moveid]]} added_players = {} @@ -472,25 +481,25 @@ class Transactions(commands.Cog): added_players[move["player"]["name"]].append( [move["player"], move["newteam"], tiebreaker, move["moveid"]] ) - logging.info(f'freeze / added_players: {added_players.keys()}') + logger.info(f'freeze / added_players: {added_players.keys()}') # Check added_players for keys (player names) with more than one move in their list for name in added_players: if len(added_players[name]) > 1: contested_players[name] = added_players[name] - logging.info(f'freeze / contested_players: {contested_players.keys()}') + logger.info(f'freeze / contested_players: {contested_players.keys()}') # Determine winner for contested players, mark moveid cancelled for loser def tiebreaker(val): - logging.info(f'tiebreaker: {val}') + logger.info(f'tiebreaker: {val}') return val[2] for guy in contested_players: contested_players[guy].sort(key=tiebreaker) first = True - logging.info(f'Contested Player: {contested_players[guy]}\n\n') + logger.info(f'Contested Player: {contested_players[guy]}\n\n') for x in contested_players[guy]: - logging.info(f'First: {first} / x: {x}\n\n') + logger.info(f'First: {first} / x: {x}\n\n') if not first: await db_patch('transactions', object_id=x[3], params=[('frozen', False), ('cancelled', True)]) # await patch_transaction(move_id=x[3], cancelled=True, frozen=False) @@ -522,37 +531,6 @@ class Transactions(commands.Cog): await db_patch('transactions', object_id=move_id, params=[('frozen', False)]) await self.post_move_to_transaction_log(move_id) - # async def send_move_to_sheets(self, move_id): - # return - # current = await db_get('current') - # sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') - # trans_tab = sheets.open_by_key(SBA_ROSTER_KEY).worksheet_by_title('Transactions') - # all_vals = [] - # all_moves = await get_transactions( - # season=current['season'], - # move_id=move_id - # ) - # - # counter = 0 - # for move in [*all_moves.values()]: - # all_vals.append([ - # move['player']['name'], - # move['oldteam']['sname'], - # move['newteam']['sname'], - # move['week'], - # current['transcount'] + counter - # ]) - # counter += 1 - # - # try: - # trans_tab.update_values( - # crange=f'A{current["transcount"] + 3}', - # values=all_vals - # ) - # await patch_current(transcount=current['transcount'] + counter) - # except Exception as e: - # await send_to_channel(self.bot, 'commissioners-office', f'Failed sending move {move_id} to sheets') - async def post_move_to_transaction_log(self, move_id): current = await db_get('current') # all_moves = await get_transactions( @@ -617,98 +595,6 @@ class Transactions(commands.Cog): ) await info_channel.send(weekly_str) - # async def send_stats_to_sheets(self, channel='commissioners-office', which='all'): - # current = await db_get('current') - # b_stats = None - # p_stats = None - # - # if which == 'all' or which == 'batting': - # await send_to_channel(self.bot, channel, 'Collecting batting stats...') - # b_stats = await get_battingstat(current['season'], timeout=90) - # - # if which == 'all' or which == 'pitching': - # await send_to_channel(self.bot, channel, 'Collecting pitching stats...') - # p_stats = await get_pitchingstat(current['season'], timeout=90) - # - # sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') - # if b_stats: - # await send_to_channel(self.bot, channel, f'Preparing batting stats ({len(b_stats)} lines found)...') - # batting_stats = [] - # - # for x in [*b_stats.values()]: - # batting_stats.append([ - # x['player']['name'], x['team']['abbrev'], x['pos'], x['pa'], x['ab'], x['run'], x['hit'], x['rbi'], - # x['double'], x['triple'], x['hr'], x['bb'], x['so'], x['hbp'], x['sac'], x['ibb'], x['gidp'], - # x['sb'], x['cs'], x['xch'], x['xhit'], x['error'], x['pb'], x['sbc'], x['csc'], x['week'], - # x['game'], f'{x["week"]}.{x["game"]}' - # ]) - # await patch_current(bstatcount=len(batting_stats)) - # await send_to_channel(self.bot, channel, f'Sending {len(batting_stats)} batting lines...') - # sheets.open_by_key(SBA_STATS_KEY).worksheet_by_title('Batting Data').update_values( - # crange='A2', - # values=batting_stats - # ) - # await send_to_channel(self.bot, channel, f'Batting stats have been sent') - # elif which == 'all' or which == 'batting': - # await send_to_channel(self.bot, channel, 'No batting stats found') - # - # if p_stats: - # await send_to_channel(self.bot, channel, f'Preparing pitching stats ({len(p_stats)} lines found)...') - # pitching_stats = [] - # - # for x in [*p_stats.values()]: - # pitching_stats.append([ - # x['player']['name'], x['team']['abbrev'], x['ip'], x['hit'], x['run'], x['erun'], x['so'], x['bb'], - # x['hbp'], x['wp'], x['balk'], x['hr'], 1 if x['gs'] else 0, 1 if x['win'] else 0, - # 1 if x['loss'] else 0, 1 if x['hold'] else 0, 1 if x['sv'] else 0, 1 if x['bsv'] else 0, x['week'], - # x['game'], f'{x["week"]}.{x["game"]}' - # ]) - # await patch_current(pstatcount=len(pitching_stats)) - # await send_to_channel(self.bot, channel, f'Sending {len(pitching_stats)} pitching lines...') - # sheets.open_by_key(SBA_STATS_KEY).worksheet_by_title('Pitching Data').update_values( - # crange='A2', - # values=pitching_stats - # ) - # await send_to_channel(self.bot, channel, f'Pitching stats have been sent') - # elif which == 'all' or which == 'pitching': - # await send_to_channel(self.bot, channel, 'No pitching stats found') - - # async def update_roster_sheet(self, season): - # logging.info(f'calling the db') - # # csv_data = db_get('players', api_ver=3, params=[('season', 6), ('csv', True)], as_csv=True) - # # csv = DataFrame(csv_data).to_csv(header=False, index=False) - # # csv = pandas.read_csv(csv_data) - # - # ap = await db_get('players', api_ver=3, timeout=8, params=[('season', season)]) - # player_data = [ - # ['name', 'sWAR', 'image', 'vanity_card', 'team_abbrev', 'inj_rat', 'pos_1', 'pos_2', 'pos_3', 'pos_4', - # 'pos_5', 'pos_6', 'pos_7', 'pos_8', 'last_game', 'last_game2', 'il_return', 'dem_week', 'strat_code', - # 'bbref_id'] - # ] - # for x in ap: - # player_data.append([ - # ap[x]['name'], ap[x]['wara'], ap[x]['image'], ap[x]['vanity_card'], ap[x]['team']['abbrev'], - # ap[x]['injury_rating'], ap[x]['pos_1'], ap[x]['pos_2'], ap[x]['pos_3'], ap[x]['pos_4'], ap[x]['pos_5'], - # ap[x]['pos_6'], ap[x]['pos_7'], ap[x]['pos_8'], ap[x]['last_game'], ap[x]['last_game2'], - # ap[x]['il_return'], ap[x]['demotion_week'], ap[x]['strat_code'], ap[x]['bbref_id'] - # ]) - # # logging.info(f'\n\nCSV:\n{player_data}\n') - # # auth sheets - # logging.info(f'authorizing sheets') - # sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json', retries=1) - # # get sheet - # logging.info(f'getting sheet') - # master_sheet = sheets.open_by_key(SBA_ROSTER_KEY) - # # get worksheet - # logging.info(f'getting worksheet') - # roster_sheet = master_sheet.worksheet_by_title('API Import') - # - # logging.info(f'updating values') - # roster_sheet.update_values( - # crange='A1', - # values=player_data - # ) - @staticmethod def on_team_il(team, player): player_team_abbrev = player['team']['abbrev'] @@ -756,9 +642,21 @@ class Transactions(commands.Cog): return team = await get_team_by_owner(current['season'], ctx.author.id) + if team is None: + await ctx.send(f'Who are you? Why are you talking to me, you don\'t have a team.') + return + team_role = get_team_role(ctx, team) - player_cog = self.bot.get_cog('Players') + if team_role is None: + await ctx.send(f'I could not find a team role for the {team["lname"]}') + return + poke_role = get_role(ctx, 'Pokétwo') + if poke_role is None: + await ctx.send(f'I could not find the poke role. This is an emergency.') + return + + player_cog = self.bot.get_cog('Players') # Create trade channel overwrites = {ctx.guild.default_role: discord.PermissionOverwrite(read_messages=False), @@ -853,7 +751,7 @@ class Transactions(commands.Cog): await fuzzy_player_search(ctx, trade.channel, self.bot, resp, player_cog.player_list.keys()) ) except ValueError as e: - logging.error(f'Could not find player *{resp}*') + logger.error(f'Could not find player *{resp}*') else: if player is None: await trade.send(f'{await get_emoji(ctx, "squint")}') @@ -1003,7 +901,7 @@ class Transactions(commands.Cog): await fuzzy_player_search(ctx, trade.channel, self.bot, resp, player_cog.player_list.keys()) ) except ValueError as e: - logging.error(f'Could not find player *{resp}*') + logger.error(f'Could not find player *{resp}*') else: if player is None: await trade.send(f'{await get_emoji(ctx, "squint")}') @@ -1032,16 +930,16 @@ class Transactions(commands.Cog): roster_errors = [] for team in trade.teams: data = await trade.check_major_league_errors(team) - logging.warning(f'Done checking data - checking sWAR now ({data["wara"]}') + logger.warning(f'Done checking data - checking sWAR now ({data["wara"]}') if data['wara'] > 32.001 and not OFFSEASON_FLAG: errors.append(f'- {trade.teams[team]["team"]["abbrev"]} would have {data["wara"]:.2f} WARa') - logging.warning(f'Now checking roster {len(data["roster"])}') + logger.warning(f'Now checking roster {len(data["roster"])}') if len(data['roster']) > 26 and not OFFSEASON_FLAG: errors.append(f'- {trade.teams[team]["team"]["abbrev"]} would have {len(data["roster"])} players') - logging.warning(f'Any errors? {errors}') + logger.warning(f'Any errors? {errors}') if (data['wara'] > 32.001 or len(data['roster']) > 26) and not OFFSEASON_FLAG: roster_string = '' for x in data['roster']: @@ -1081,7 +979,7 @@ class Transactions(commands.Cog): choas = get_role(ctx, 'CHOAS ALERT') await send_to_channel(self.bot, f'season-{current["season"]}-chat', f'{choas.mention}') except Exception as e: - logging.error(f'Couldn\'t ping chaos for a trade') + logger.error(f'Couldn\'t ping chaos for a trade') await trade.timed_delete() # @commands.command(name='picktrade', help='Trade draft picks', hidden=True) @@ -1249,16 +1147,16 @@ class Transactions(commands.Cog): # errors = [] # for team in trade.teams: # data = await trade.check_major_league_errors(team) - # logging.warning(f'Done checking data - checking WARa now ({data["wara"]}') + # logger.warning(f'Done checking data - checking WARa now ({data["wara"]}') # # if data['wara'] > 32.001: # errors.append(f'- {trade.teams[team]["team"]["abbrev"]} would have {data["wara"]:.2f} WARa') # - # logging.warning(f'Now checking roster {len(data["roster"])}') + # logger.warning(f'Now checking roster {len(data["roster"])}') # if len(data['roster']) > 26: # errors.append(f'- {trade.teams[team]["team"]["abbrev"]} would have {len(data["roster"])} players') # - # logging.warning(f'Any errors? {errors}') + # logger.warning(f'Any errors? {errors}') # if data['wara'] > 32.001 or len(data['roster']) > 26: # roster_string = '' # for x in data['roster']: @@ -1296,7 +1194,7 @@ class Transactions(commands.Cog): # choas = get_role(ctx, 'CHOAS ALERT') # await send_to_channel(self.bot, f'season-{current["season"]}-chat', f'{choas.mention}') # except Exception as e: - # logging.error('I was not able to ping CHOAS ALERT') + # logger.error('I was not able to ping CHOAS ALERT') # await trade.timed_delete() @commands.command(name='dropadd', aliases=['drop', 'add', 'adddrop', 'longil'], help='FA/MiL moves') @@ -1373,7 +1271,7 @@ class Transactions(commands.Cog): await fuzzy_player_search(ctx, dropadd.channel, self.bot, resp, player_cog.player_list.keys()) ) except ValueError as e: - logging.error(f'Could not find player *{resp}*') + logger.error(f'Could not find player *{resp}*') else: if player is None: await dropadd.send(f'{await get_emoji(ctx, "squint")}') @@ -1424,7 +1322,7 @@ class Transactions(commands.Cog): await fuzzy_player_search(ctx, dropadd.channel, self.bot, resp, player_cog.player_list.keys()) ) except ValueError as e: - logging.error(f'Could not find player *{resp}*') + logger.error(f'Could not find player *{resp}*') else: if player is None: await dropadd.send(f'{await get_emoji(ctx, "squint")}') @@ -1482,7 +1380,7 @@ class Transactions(commands.Cog): await fuzzy_player_search(ctx, dropadd.channel, self.bot, resp, player_cog.player_list.keys()) ) except ValueError as e: - logging.error(f'Could not find player *{resp}*') + logger.error(f'Could not find player *{resp}*') else: if player is None: await dropadd.send(f'{await get_emoji(ctx, "squint")}') @@ -1513,16 +1411,16 @@ class Transactions(commands.Cog): roster_errors = [] for team in dropadd.teams: data = await dropadd.check_major_league_errors(team) - logging.warning(f'Done checking data - checking WARa now ({data["wara"]})') + logger.warning(f'Done checking data - checking WARa now ({data["wara"]})') if data['wara'] > 32.001 and not OFFSEASON_FLAG: errors.append(f'- {dropadd.teams[team]["team"]["abbrev"]} would have {data["wara"]:.2f} sWAR') - logging.warning(f'Now checking roster {len(data["roster"])}') + logger.warning(f'Now checking roster {len(data["roster"])}') if len(data['roster']) > 26 and not OFFSEASON_FLAG: errors.append(f'- {dropadd.teams[team]["team"]["abbrev"]} would have {len(data["roster"])} players') - logging.warning(f'Any errors? {errors}') + logger.warning(f'Any errors? {errors}') if (data['wara'] > 32.001 or len(data['roster']) > 26) and not OFFSEASON_FLAG: roster_string = '' for x in data['roster']: @@ -1640,7 +1538,7 @@ class Transactions(commands.Cog): await fuzzy_player_search(ctx, dropadd.channel, self.bot, resp, player_cog.player_list.keys()) ) except ValueError as e: - logging.error(f'Could not find player *{resp}*') + logger.error(f'Could not find player *{resp}*') else: if player is None: await dropadd.send(f'{await get_emoji(ctx, "squint")}') @@ -1683,7 +1581,7 @@ class Transactions(commands.Cog): await fuzzy_player_search(ctx, dropadd.channel, self.bot, resp, player_cog.player_list.keys()) ) except ValueError as e: - logging.error(f'Could not find player *{resp}*') + logger.error(f'Could not find player *{resp}*') else: if player is None: await dropadd.send(f'{await get_emoji(ctx, "squint")}') @@ -1725,7 +1623,7 @@ class Transactions(commands.Cog): await fuzzy_player_search(ctx, dropadd.channel, self.bot, resp, player_cog.player_list.keys()) ) except ValueError as e: - logging.error(f'Could not find player *{resp}*') + logger.error(f'Could not find player *{resp}*') else: if player is None: await dropadd.send(f'{await get_emoji(ctx, "squint")}') @@ -1771,7 +1669,7 @@ class Transactions(commands.Cog): await fuzzy_player_search(ctx, dropadd.channel, self.bot, resp, player_cog.player_list.keys()) ) except ValueError as e: - logging.error(f'Could not find player *{resp}*') + logger.error(f'Could not find player *{resp}*') else: if player is None: await dropadd.send(f'{await get_emoji(ctx, "squint")}') @@ -1880,7 +1778,7 @@ class Transactions(commands.Cog): ('week_end', current['season']), ('team_abbrev', team['abbrev']), ('frozen', True) ]) frozen_moves = t_query['transactions'] - logging.info(f'Num Moves: {len(set_moves)}') + logger.info(f'Num Moves: {len(set_moves)}') embed = get_team_embed(f'{team["lname"]} Guaranteed Transactions', team=team) embed.description = f'Week {current["week"] + 1} Moves' @@ -1967,11 +1865,11 @@ class Transactions(commands.Cog): embed.add_field(name='Position Checks', value=pos_string, inline=False) for pos in roster['active']: if pos in ['C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF']: - logging.info(f'Pos: {pos} / {roster["active"][pos]}') + logger.info(f'Pos: {pos} / {roster["active"][pos]}') if roster["active"][pos] < 2: errors.append(f'- Only have {roster["active"][pos]} {pos} (need 2)') # elif pos in ['SP', 'RP']: - # logging.info(f'Pos: {pos} / {roster["active"][pos]}') + # logger.info(f'Pos: {pos} / {roster["active"][pos]}') # if roster["active"][pos] < 5: # errors.append(f'- Only have {roster["active"][pos]} {pos} (need 5)') @@ -1991,21 +1889,21 @@ class Transactions(commands.Cog): il_team = await get_team_by_abbrev(f'{team["abbrev"]}MiL', current['season']) if current['week'] != 0: - logging.info('entering the thot check') + logger.info('entering the thot check') await react_and_reply(ctx, '👀', 'https://c.tenor.com/FCAj8xDvEHwAAAAC/be-gone-thot.gif') player_role = get_role(ctx, SBA_PLAYERS_ROLE_NAME) bonked_role = get_role(ctx, 'BAINSHED') - logging.info('beginning sleep') + logger.info('beginning sleep') await asyncio.sleep(3) # try: # await ctx.author.add_roles(bonked_role) # except Exception as e: - # logging.error(f'unable to add {bonked_role} role to {ctx.author}: {e}') + # logger.error(f'unable to add {bonked_role} role to {ctx.author}: {e}') try: await ctx.author.remove_roles(player_role) except Exception as e: - logging.error(f'unable to remove {player_role} role from {ctx.author}: {e}') + logger.error(f'unable to remove {player_role} role from {ctx.author}: {e}') return @@ -2022,7 +1920,7 @@ class Transactions(commands.Cog): player_name = await fuzzy_player_search(ctx, ctx.channel, self.bot, x, player_cog.player_list.keys()) player = await get_player_by_name(current['season'], player_name) except Exception as e: - logging.error(f'Could not demote {x} for {team["abbrev"]}: {e}') + logger.error(f'Could not demote {x} for {team["abbrev"]}: {e}') errors.append(x) else: if player['team']['id'] != team['id']: @@ -2065,7 +1963,7 @@ class Transactions(commands.Cog): try: await ctx.author.add_roles(player_role) except Exception as e: - logging.error(f'unable to add {player_role} role to {ctx.author}: {e}') + logger.error(f'unable to add {player_role} role to {ctx.author}: {e}') await react_and_reply( ctx, '😩', f'{e}\n\nLooks like you didn\'t apologize hard enough. I can\'t role you back up.') diff --git a/db_calls.py b/db_calls.py index afc1dc8..aa9c0d9 100644 --- a/db_calls.py +++ b/db_calls.py @@ -10,6 +10,7 @@ AUTH_TOKEN = {'Authorization': f'Bearer {os.environ.get("API_TOKEN")}'} # DB_URL = 'http://database/api' DB_URL = 'https://sba.manticorum.com/api' master_debug = True +logger = logging.getLogger('discord_app') def param_char(other_params): @@ -36,16 +37,16 @@ def get_req_url(endpoint: str, api_ver: int = 3, object_id: int = None, params: def log_return_value(log_string: str): if master_debug: - logging.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n') + logger.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n') else: - logging.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n') + logger.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}\n') async def db_get(endpoint: str, api_ver: int = 3, object_id: int = None, params: list = None, none_okay: bool = True, timeout: int = 3): req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id, params=params) log_string = f'get:\n{endpoint} id: {object_id} params: {params}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.get(req_url) as r: @@ -55,11 +56,11 @@ async def db_get(endpoint: str, api_ver: int = 3, object_id: int = None, params: return js elif none_okay: e = await r.text() - logging.error(e) + logger.error(e) return None else: e = await r.text() - logging.error(e) + logger.error(e) raise ValueError(f'DB: {e}') @@ -67,7 +68,7 @@ async def db_patch( endpoint: str, object_id: int, params: list, api_ver: int = 3, timeout: int = 3, payload: dict = None): req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id, params=params) log_string = f'patch:\n{endpoint}/{object_id} {params}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.patch(req_url, json=payload) as r: @@ -77,14 +78,14 @@ async def db_patch( return js else: e = await r.text() - logging.error(e) + logger.error(e) raise ValueError(f'DB: {e}') async def db_post(endpoint: str, api_ver: int = 3, payload: dict = None, timeout: int = 3): req_url = get_req_url(endpoint, api_ver=api_ver) log_string = f'post:\n{endpoint} payload: {payload}\ntype: {type(payload)}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.post(req_url, json=payload) as r: @@ -94,14 +95,14 @@ async def db_post(endpoint: str, api_ver: int = 3, payload: dict = None, timeout return js else: e = await r.text() - logging.error(e) + logger.error(e) raise ValueError(f'DB: {e}') async def db_put(endpoint: str, api_ver: int = 3, payload: dict = None, object_id: int = None, timeout: int = 3): req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id) log_string = f'put:{req_url}\npayload: {payload}\nobject_id: {object_id}\ntype: {type(payload)}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.put(req_url, json=payload) as r: @@ -111,7 +112,7 @@ async def db_put(endpoint: str, api_ver: int = 3, payload: dict = None, object_i return js else: e = await r.text() - logging.error(e) + logger.error(e) raise ValueError(f'DB: {e}') # retries = 0 @@ -120,7 +121,7 @@ async def db_put(endpoint: str, api_ver: int = 3, payload: dict = None, object_i # resp = requests.put(req_url, json=payload, headers=AUTH_TOKEN, timeout=timeout) # break # except requests.Timeout as e: - # logging.error(f'Post Timeout: {req_url} / retries: {retries} / timeout: {timeout}') + # logger.error(f'Post Timeout: {req_url} / retries: {retries} / timeout: {timeout}') # if retries > 1: # raise ConnectionError(f'DB: The internet was a bit too slow for me to grab the data I needed. Please ' # f'hang on a few extra seconds and try again.') @@ -131,19 +132,19 @@ async def db_put(endpoint: str, api_ver: int = 3, payload: dict = None, object_i # data = resp.json() # log_string = f'{data}' # if master_debug: - # logging.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}') + # logger.info(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}') # else: - # logging.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}') + # logger.debug(f'return: {log_string[:1200]}{" [ S N I P P E D ]" if len(log_string) > 1200 else ""}') # return data # else: - # logging.warning(resp.text) + # logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') async def db_delete(endpoint: str, object_id: int, api_ver: int = 3, timeout=3): req_url = get_req_url(endpoint, api_ver=api_ver, object_id=object_id) log_string = f'delete:\n{endpoint} {object_id}' - logging.info(log_string) if master_debug else logging.debug(log_string) + logger.info(log_string) if master_debug else logger.debug(log_string) async with aiohttp.ClientSession(headers=AUTH_TOKEN) as session: async with session.delete(req_url) as r: @@ -153,7 +154,7 @@ async def db_delete(endpoint: str, object_id: int, api_ver: int = 3, timeout=3): return js else: e = await r.text() - logging.error(e) + logger.error(e) raise ValueError(f'DB: {e}') @@ -193,7 +194,7 @@ async def put_player(this_player: dict): async def patch_draftpick(this_pick: dict): - logging.info(f'attempting to patch draftpick:\n{this_pick}') + logger.info(f'attempting to patch draftpick:\n{this_pick}') this_pick['player_id'] = None if this_pick['player'] is None else this_pick['player']['id'] this_pick['origowner_id'] = None if this_pick['origowner'] is None else this_pick['origowner']['id'] this_pick['owner_id'] = None if this_pick['owner'] is None else this_pick['owner']['id'] @@ -270,7 +271,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -288,7 +289,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return resp.json() # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -297,7 +298,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return resp.json() # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -335,7 +336,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -545,7 +546,7 @@ async def get_player_headshot(player_name): # # if resp.status_code == 200: # # return True # # else: -# # logging.warning(resp.text) +# # logger.warning(resp.text) # # raise ValueError(f'DB: {resp.text}') # # @@ -618,7 +619,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -636,7 +637,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -712,7 +713,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -724,7 +725,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -735,7 +736,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -746,7 +747,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -789,7 +790,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -801,7 +802,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -812,7 +813,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -847,7 +848,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -934,7 +935,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -955,7 +956,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return resp.json() # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -984,7 +985,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -1007,7 +1008,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # @@ -1051,7 +1052,7 @@ async def get_player_headshot(player_name): # if resp.status_code == 200: # return True # else: -# logging.warning(resp.text) +# logger.warning(resp.text) # raise ValueError(f'DB: {resp.text}') # # diff --git a/db_calls_gameday.py b/db_calls_gameday.py index 983b44d..223b3ef 100644 --- a/db_calls_gameday.py +++ b/db_calls_gameday.py @@ -5,6 +5,8 @@ from peewee import * from playhouse.shortcuts import model_to_dict import logging +logger = logging.getLogger('discord_app') + db = SqliteDatabase( 'storage/gameday.db', pragmas={ @@ -324,14 +326,14 @@ def get_atbat_pitching_totals(pitcher_member_id): if outs_recorded.count() > 0: complete_inn = math.floor((outs_recorded.count() + totals[0].gidp) / 3) extra_outs = (outs_recorded.count() + totals[0].gidp) % 3 - logging.info(f'comp_in: {complete_inn} / extra_outs: {extra_outs}') + logger.info(f'comp_in: {complete_inn} / extra_outs: {extra_outs}') ip = complete_inn + (extra_outs / 3.0) else: ip = 0.0 if totals.count() > 0: walks = totals[0].bbs + totals[0].ibbs - logging.info(f'bbs: {totals[0].bbs} / ibbs: {totals[0].ibbs} / walks: {walks}') + logger.info(f'bbs: {totals[0].bbs} / ibbs: {totals[0].ibbs} / walks: {walks}') this_line = { 'empty': False, 'ip': ip, diff --git a/db_calls_gameplay.py b/db_calls_gameplay.py index 6e3a405..eaa9d32 100644 --- a/db_calls_gameplay.py +++ b/db_calls_gameplay.py @@ -10,6 +10,8 @@ from dataclasses import dataclass from helpers import SBA_SEASON, get_player_url from db_calls import get_team_by_owner, get_one_team, get_one_player +logger = logging.getLogger('discord_app') + db = SqliteDatabase( 'storage/gameplay.db', pragmas={ @@ -38,26 +40,26 @@ def pd_get_req_url(endpoint: str, api_ver: int = 1, object_id: int = None, param for x in params: req_url += f'{param_char(other_params)}{x[0]}={x[1]}' other_params = True - logging.info(f'PD GET: {req_url}') + logger.info(f'PD GET: {req_url}') return req_url def pd_db_get(endpoint: str, api_ver: int = 1, object_id: int = None, params: list = None, none_okay: bool = True): req_url = pd_get_req_url(endpoint, api_ver=api_ver, object_id=object_id, params=params) - logging.info(f'get:\n{endpoint} id: {object_id} params: {params}') + logger.info(f'get:\n{endpoint} id: {object_id} params: {params}') resp = requests.get(req_url, timeout=3) if resp.status_code == 200: data = resp.json() - logging.info(f'return: {data}') + logger.info(f'return: {data}') return data elif none_okay: data = resp.json() - logging.info(f'return: {data}') + logger.info(f'return: {data}') return None else: - logging.warning(resp.text) + logger.warning(resp.text) raise ValueError(f'DB: {resp.text}') @@ -70,10 +72,10 @@ def pd_get_one_team(team_abbrev: str): # resp = requests.get(req_url, timeout=3) # if resp.status_code == 200: # data = resp.json() - # logging.info(f'return: {data}') + # logger.info(f'return: {data}') # return data['teams'][0] # else: - # logging.warning(resp.text) + # logger.warning(resp.text) # raise ValueError(f'PD DB: {resp.text}') @@ -190,7 +192,7 @@ async def get_game_team(game: StratGame, gm_id: int = None, team_abbrev: str = N if not gm_id and not team_abbrev and not team_id: raise KeyError(f'get_game_team requires either one of gm_id, team_abbrev, or team_id to not be None') - logging.info(f'getting game team for game {game.id} / gm_id: {gm_id} / ' + logger.info(f'getting game team for game {game.id} / gm_id: {gm_id} / ' f'tm_abbrev: {team_abbrev} / team_id: {team_id}') if game.is_pd: if gm_id: @@ -284,7 +286,7 @@ def get_one_lineup( Lineup.game_id == game_id, Lineup.team_id == team_id, Lineup.position == position, Lineup.active == active ) - logging.info(f'get_one_lineup / this_lineup: {this_lineup}') + logger.info(f'get_one_lineup / this_lineup: {this_lineup}') if as_obj: return this_lineup @@ -377,7 +379,7 @@ def make_sub(lineup_dict: dict): Lineup.game_id == lineup_dict['game_id'], Lineup.team_id == lineup_dict['team_id'], Lineup.batting_order == lineup_dict['batting_order'], Lineup.active == True ) - logging.info(f'subbed_player: {subbed_player}') + logger.info(f'subbed_player: {subbed_player}') if subbed_player: subbed_player = patch_lineup(subbed_player.id, active=False) @@ -421,7 +423,7 @@ async def get_player(game, lineup_member) -> dict: player = this_card['player'] player['name'] = player['p_name'] player['team'] = this_card['team'] - logging.info(f'player: {player}') + logger.info(f'player: {player}') return player else: return await get_one_player( @@ -582,7 +584,7 @@ db.create_tables([Play]) def post_play(play_dict: dict) -> StratPlay: - logging.info(f'play_dict: {play_dict}') + logger.info(f'play_dict: {play_dict}') new_play = Play.create(**play_dict) # return_play = model_to_dict(new_play) return_play = convert_stratplay(new_play) @@ -894,7 +896,7 @@ def complete_play(play_id, batter_to_base: int = None): this_play.complete = True this_play.save() - logging.info(f'starting the inning calc') + logger.info(f'starting the inning calc') new_inning_half = this_play.inning_half new_inning_num = this_play.inning_num if this_play.runner or this_play.wild_pitch or this_play.passed_ball or this_play.pick_off or this_play.balk: @@ -929,7 +931,7 @@ def complete_play(play_id, batter_to_base: int = None): new_batting_order = 1 # Not an inning-ending play else: - logging.info(f'starting the obc calc') + logger.info(f'starting the obc calc') bases_occ = [False, False, False, False] # Set the occupied bases for the next play and lineup member occupying it @@ -996,7 +998,7 @@ def complete_play(play_id, batter_to_base: int = None): pitcher = get_one_lineup(this_play.game_id, team_id=new_pteam_id, position='P') pitcher_id = pitcher.id if pitcher else None - logging.info(f'done the obc calc') + logger.info(f'done the obc calc') next_play = Play.create(**{ 'game_id': this_play.game.id, 'play_num': this_play.play_num + 1, @@ -1097,7 +1099,7 @@ def get_batting_stats(game_id, lineup_id: int = None, team_id: int = None): done_batters.append(x.batter.id) db.close() - logging.info(f'batting stats: {return_batters}') + logger.info(f'batting stats: {return_batters}') return return_batters @@ -1142,7 +1144,7 @@ def get_pitching_stats(game_id, lineup_id: int = None, team_id: int = None): ((Play.on_first_final == 4) | (Play.on_second_final == 4) | (Play.on_third_final == 4) | (Play.batter_final == 4)) & (Play.error == 0) ).join(Lineup, on=Play.pitcher).where(Play.game_id == game_id) - logging.info(f'earned_runs: {earned_runs_pl}') + logger.info(f'earned_runs: {earned_runs_pl}') earned_runs_tm = Play.select().where( ((Play.on_first_final == 4) | (Play.on_second_final == 4) | (Play.on_third_final == 4) | (Play.batter_final == 4)) & (Play.error == 0) @@ -1156,14 +1158,14 @@ def get_pitching_stats(game_id, lineup_id: int = None, team_id: int = None): pitching_stats = pitching_stats.where(Play.pitcher.team_id == team_id) earned_runs_pl = earned_runs_pl.where(Play.pitcher.team_id == team_id) earned_runs_tm = earned_runs_tm.where(Play.pitcher.team_id == team_id) - logging.info(f'query: {pitching_stats}') - logging.info(f'count: {pitching_stats.count()}') - logging.info(f'first entry: {pitching_stats[0]}') + logger.info(f'query: {pitching_stats}') + logger.info(f'count: {pitching_stats.count()}') + logger.info(f'first entry: {pitching_stats[0]}') done_pitchers = [] return_pitchers = [] for x in pitching_stats: - logging.info(f'x: {x}') + logger.info(f'x: {x}') if x.pitcher.id not in done_pitchers: return_pitchers.append({ 'pitcher_id': x.pitcher_id, @@ -1191,6 +1193,6 @@ def get_pitching_stats(game_id, lineup_id: int = None, team_id: int = None): done_pitchers.append(x.pitcher_id) db.close() - logging.info(f'pitching stats: {return_pitchers}') + logger.info(f'pitching stats: {return_pitchers}') return return_pitchers diff --git a/helpers.py b/helpers.py index f9a05d7..c7ff93b 100644 --- a/helpers.py +++ b/helpers.py @@ -18,6 +18,7 @@ import requests from discord.ext import commands from difflib import get_close_matches +logger = logging.getLogger('discord_app') SBA_SEASON = 11 PD_SEASON = 7 @@ -362,7 +363,7 @@ class Pagination(discord.ui.View): @discord.ui.button(label='⏮️', style=discord.ButtonStyle.blurple) async def left_button(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user not in self.responders: - logging.info(f'{interaction.user} is not in {self.responders}') + logger.info(f'{interaction.user} is not in {self.responders}') return self.value = 'left' @@ -372,7 +373,7 @@ class Pagination(discord.ui.View): @discord.ui.button(label='❌️', style=discord.ButtonStyle.secondary) async def cancel_button(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user not in self.responders: - logging.info(f'{interaction.user} is not in {self.responders}') + logger.info(f'{interaction.user} is not in {self.responders}') return self.value = 'cancel' @@ -382,7 +383,7 @@ class Pagination(discord.ui.View): @discord.ui.button(label='⏭️', style=discord.ButtonStyle.blurple) async def right_button(self, interaction: discord.Interaction, button: discord.ui.Button): if interaction.user not in self.responders: - logging.info(f'{interaction.user} is not in {self.responders}') + logger.info(f'{interaction.user} is not in {self.responders}') return self.value = 'right' @@ -479,7 +480,7 @@ def random_conf_gif(): else: return data['data']['url'] else: - logging.warning(resp.text) + logger.warning(resp.text) raise ValueError(f'DB: {resp.text}') @@ -659,7 +660,7 @@ async def fuzzy_player_search(ctx, channel, bot, name, master_list, author = Non :param master_list: list of names :return: """ - logging.warning(f'fuzzy player search - len(master_list): {len(master_list)}') + logger.warning(f'fuzzy player search - len(master_list): {len(master_list)}') if name.lower() in master_list: return name.lower() @@ -751,12 +752,13 @@ def get_team_embed(title, team=None, thumbnail: bool = True): async def get_or_create_role(ctx, role_name, mentionable=True): + logger.info(f'Getting or creating role: {role_name}') this_role = discord.utils.get(ctx.guild.roles, name=role_name) - logging.info(f'this_role: {this_role} / role_name: {role_name} (POST SEARCH)') + logger.info(f'this_role: {this_role} / role_name: {role_name} (POST SEARCH)') if not this_role: this_role = await ctx.guild.create_role(name=role_name, mentionable=mentionable) - logging.info(f'this_role: {this_role} / role_name: {role_name} (PRE RETURN)') + logger.info(f'this_role: {this_role} / role_name: {role_name} (PRE RETURN)') return this_role @@ -768,13 +770,13 @@ def get_role(ctx, role_name, bot=None): if bot: guild = bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: - logging.error('Cannot send to channel - bot not logged in') + logger.error('Cannot send to channel - bot not logged in') return role = discord.utils.get(guild.roles, name=role_name) else: role = discord.utils.get(ctx.guild.roles, name=role_name) - logging.info(f'this_role: {role} / role_name: {role_name} (PRE RETURN)') + logger.info(f'this_role: {role} / role_name: {role_name} (PRE RETURN)') if role: return role else: @@ -788,7 +790,7 @@ def get_team_role(ctx, team, bot=None): async def send_to_channel(bot, channel_name, content=None, embed=None): guild = bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: - logging.error('Cannot send to channel - bot not logged in') + logger.error('Cannot send to channel - bot not logged in') return this_channel = discord.utils.get(guild.text_channels, name=channel_name) @@ -1049,7 +1051,7 @@ async def create_channel( category=this_category ) - logging.info(f'Creating channel ({channel_name}) in ({category_name})') + logger.info(f'Creating channel ({channel_name}) in ({category_name})') return this_channel @@ -1072,7 +1074,7 @@ async def toggle_draft_sheet() -> None: sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') this_sheet = sheets.open_by_key(SBA_SEASON6_DRAFT_KEY) my_cards = this_sheet.worksheet_by_title('BUTTON') - logging.info(f'Toggling the draft button...') + logger.info(f'Toggling the draft button...') my_cards.update_value( 'B3', 'FALSE' @@ -1088,7 +1090,7 @@ async def log_injury(current: dict, inj_dict: dict) -> None: this_sheet = sheets.open_by_key(SBA_ROSTER_KEY) injury_sheet = this_sheet.worksheet_by_title('Injury Log') - logging.info(f'updating values') + logger.info(f'updating values') try: injury_sheet.update_values( @@ -1100,7 +1102,7 @@ async def log_injury(current: dict, inj_dict: dict) -> None: ]] ) except Exception as e: - logging.error(f'log_injury sheets: {e}') + logger.error(f'log_injury sheets: {e}') raise Exception(e) @@ -1142,7 +1144,7 @@ def random_gif(search_term: str): else: return data['data']['url'] else: - logging.warning(resp.text) + logger.warning(resp.text) raise ValueError(f'DB: {resp.text}') @@ -1150,9 +1152,24 @@ def new_rand_conf_gif(): return random_gif('all done') +def random_gif(search_term: str): + req_url = f'https://api.giphy.com/v1/gifs/translate?s={search_term}&api_key=H86xibttEuUcslgmMM6uu74IgLEZ7UOD' + + resp = requests.get(req_url, timeout=3) + if resp.status_code == 200: + data = resp.json() + if 'trump' in data['data']['title']: + return random_conf_gif() + else: + return data['data']['url'] + else: + logger.warning(resp.text) + raise ValueError(f'DB: {resp.text}') + + def random_from_list(data_list: list): item = data_list[random.randint(0, len(data_list) - 1)] - logging.info(f'random_from_list: {item}') + # logger.info(f'random_from_list: {item}') return item diff --git a/majordomo.py b/majordomo.py index e6cd6c4..0937179 100644 --- a/majordomo.py +++ b/majordomo.py @@ -1,19 +1,36 @@ import asyncio import datetime import logging +from logging.handlers import RotatingFileHandler import os import discord from discord.ext import commands -date = f'{datetime.datetime.now().year}-{datetime.datetime.now().month}-{datetime.datetime.now().day}' -log_level = logging.INFO if os.environ.get('LOG_LEVEL') == 'INFO' else 'WARN' -logging.basicConfig( - filename=f'logs/discord/{date}.log', - format='%(asctime)s - majordomo - %(levelname)s - %(message)s', - level=log_level +raw_log_level = os.getenv('LOG_LEVEL') +if raw_log_level == 'DEBUG': + log_level = logging.DEBUG +elif raw_log_level == 'INFO': + log_level = logging.INFO +elif raw_log_level == 'WARN': + log_level = logging.WARNING +else: + log_level = logging.ERROR + +logger = logging.getLogger('discord_app') +logger.setLevel(log_level) + +handler = RotatingFileHandler( + filename='logs/discord.log', + # encoding='utf-8', + maxBytes=32 * 1024 * 1024, # 32 MiB + backupCount=5, # Rotate through 5 files ) +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +handler.setFormatter(formatter) +logger.addHandler(handler) + COGS = [ 'cogs.owner', 'cogs.transactions', @@ -40,19 +57,19 @@ bot = commands.Bot( @bot.event async def on_ready(): - logging.info('Logged in as:') - logging.info(bot.user.name) - logging.info(bot.user.id) + logger.info('Logged in as:') + logger.info(bot.user.name) + logger.info(bot.user.id) async def main(): for c in COGS: try: await bot.load_extension(c) - logging.info(f'Loaded cog: {c}') + logger.info(f'Loaded cog: {c}') except Exception as e: - logging.error(f'Failed to load cog: {c}') - logging.error(f'{e}') + logger.error(f'Failed to load cog: {c}') + logger.error(f'{e}') async with bot: await bot.start(os.environ.get('BOT_TOKEN'))