From b4d84b6125ee4540220ac609eabc38ea4ba6dbcf Mon Sep 17 00:00:00 2001 From: Cal Corum Date: Sat, 7 Jun 2025 23:53:32 -0500 Subject: [PATCH] S12 draft updates plus dataclass overhaul --- cogs/draft.py | 1022 ++++++++++++++++++------------------------------- 1 file changed, 373 insertions(+), 649 deletions(-) diff --git a/cogs/draft.py b/cogs/draft.py index 7bb0eef..3694d69 100644 --- a/cogs/draft.py +++ b/cogs/draft.py @@ -1,9 +1,15 @@ import copy import math import re +from typing import Optional +from api_calls.current import get_current +from api_calls.draft_data import DraftData, get_draft_data +from api_calls.draft_pick import DraftPick, get_one_draftpick, patch_draftpick +from api_calls.player import Player +from exceptions import ApiException, log_exception from helpers import * -from db_calls import db_get, db_patch, patch_draftpick, put_player, db_post, get_player_by_name +from db_calls import db_get, db_patch, put_player, db_post, get_player_by_name from discord.ext import commands, tasks from discord import TextChannel, app_commands @@ -15,9 +21,11 @@ class Draft(commands.Cog): self.bot = bot self.warnings = 0 self.pick_lock = True + self.guild: Optional[discord.Guild] = None + self.fa_team_id = 498 # self.sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') - self.draft_loop.start() + self.draft_loop.start() # type: ignore async def cog_command_error(self, ctx, error): logger.error(msg=error, stack_info=True, exc_info=True) @@ -29,42 +37,47 @@ class Draft(commands.Cog): @tasks.loop(seconds=10) async def draft_loop(self): - # guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) - # if not guild: - # logger.error('Bot not logged in - delaying draft loop') - # return + logger.info(f'JUST ENTERED THE DRAFTD LOOP') + guild_id = os.environ.get('GUILD_ID') + if guild_id is None: + log_exception(AttributeError(f'Guild ID was not found')) + logger.info(f'GUILD ID: {guild_id}') - draft_data = await db_get('draftdata') + guild = self.bot.get_guild(int(guild_id)) + if guild is None: + log_exception(LookupError(f'Guild not found with ID {guild_id}')) + + self.guild = guild + logger.info(f'GUILD: {guild}') + + draft_data = await get_draft_data() now = datetime.datetime.now() # 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 + deadline = draft_data.pick_deadline - # logger.info(f'Timer: {draft_data["timer"]} / Deadline: {deadline} / Warnings: {self.warnings}') + # 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: - current = await db_get('current') - # draft_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) - ]) - if p_query['count'] == 0: - raise ValueError(f'No pick found for overall #{draft_data["currentpick"]}') - draft_pick = p_query['picks'][0] + if draft_data.timer and deadline: + current = await get_current() + draft_pick = await get_one_draftpick(season=current.season, overall=draft_data.currentpick) + if not draft_pick.owner: + log_exception(ValueError(f'Pick #{draft_pick.overall} has no owner associated')) + return - team_role = get_team_role(None, draft_pick['owner'], self.bot) + logger.info(f'getting team role') + team_role = get_team_role(None, draft_pick.owner.model_dump(), self.bot) + logger.info(f'team role: {team_role}') if deadline <= now: + logger.info(f'deadline has past') # Auto-draft # team_list = await get_draft_list(draft_pick['owner']) l_query = await db_get('draftlist', params=[ - ('season', current['season']), ('team_id', draft_pick['owner']['id']) + ('season', current.season), ('team_id', draft_pick.owner.id) ]) - if l_query['count'] > 0: + if l_query and l_query.get('count', 0) > 0: for x in l_query['picks']: this_pick = await self.draft_player(current, draft_data, draft_pick, x['player']) if this_pick['success']: @@ -73,107 +86,116 @@ class Draft(commands.Cog): await self.advance_pick() else: + logger.info(f'deadline has not yet past') # # Slow Draft # if (deadline - datetime.timedelta(hours=10) <= now) and self.warnings == 0: - # current = await db_get('current') - # draft_pick = await get_one_draftpick_byoverall(current['season'], draft_data['currentpick']) + # current = await get_current() + # draft_pick = await get_one_draftpick_byoverall(current.season, draft_data.currentpick) # team_role = get_team_role(None, draft_pick['owner'], self.bot) # await send_to_channel( # self.bot, - # draft_data['ping_channel'], - # f'{team_role.mention if team_role else draft_pick["owner"]["lname"]}\n' - # f'You are two hours in on pick #{draft_pick["overall"]}.' + # draft_data.ping_channel, + # f'{team_role.mention if team_role else draft_pick.owner.lname}\n' + # f'You are two hours in on pick #{draft_pick.overall}.' # ) # self.warnings = 1 # elif (deadline - datetime.timedelta(hours=6) <= now) and self.warnings == 1: - # current = await db_get('current') - # draft_pick = await get_one_draftpick_byoverall(current['season'], draft_data['currentpick']) + # current = await get_current() + # draft_pick = await get_one_draftpick_byoverall(current.season, draft_data.currentpick) # team_role = get_team_role(None, draft_pick['owner'], self.bot) # await send_to_channel( # self.bot, - # draft_data['ping_channel'], - # f'{team_role.mention if team_role else draft_pick["owner"]["lname"]}\n' - # f'You are halfway into the 12-hour timer for pick #{draft_pick["overall"]}.' + # draft_data.ping_channel, + # f'{team_role.mention if team_role else draft_pick.owner.lname}\n' + # f'You are halfway into the 12-hour timer for pick #{draft_pick.overall}.' # ) # self.warnings = 2 # elif (deadline - datetime.timedelta(hours=2) <= now) and self.warnings == 2: - # current = await db_get('current') - # draft_pick = await get_one_draftpick_byoverall(current['season'], draft_data['currentpick']) + # current = await get_current() + # draft_pick = await get_one_draftpick_byoverall(current.season, draft_data.currentpick) # team_role = get_team_role(None, draft_pick['owner'], self.bot) # await send_to_channel( # self.bot, - # draft_data['ping_channel'], - # f'{team_role.mention if team_role else draft_pick["owner"]["lname"]}\n' - # f'You have two hours remaining to make pick #{draft_pick["overall"]}.' + # draft_data.ping_channel, + # f'{team_role.mention if team_role else draft_pick.owner.lname}\n' + # f'You have two hours remaining to make pick #{draft_pick.overall}.' # ) # self.warnings = 3 # elif (deadline - datetime.timedelta(hours=1) <= now) and self.warnings == 3: - # current = await db_get('current') - # draft_pick = await get_one_draftpick_byoverall(current['season'], draft_data['currentpick']) + # current = await get_current() + # draft_pick = await get_one_draftpick_byoverall(current.season, draft_data.currentpick) # team_role = get_team_role(None, draft_pick['owner'], self.bot) # await send_to_channel( # self.bot, - # draft_data['ping_channel'], - # f'{team_role.mention if team_role else draft_pick["owner"]["lname"]}\n' - # f'You have one hour remaining to make pick #{draft_pick["overall"]}.' + # draft_data.ping_channel, + # f'{team_role.mention if team_role else draft_pick.owner.lname}\n' + # f'You have one hour remaining to make pick #{draft_pick.overall}.' # ) # self.warnings = 4 # elif (deadline - datetime.timedelta(minutes=5) <= now) and self.warnings == 4: - # current = await db_get('current') - # draft_pick = await get_one_draftpick_byoverall(current['season'], draft_data['currentpick']) + # current = await get_current() + # draft_pick = await get_one_draftpick_byoverall(current.season, draft_data.currentpick) # team_role = get_team_role(None, draft_pick['owner'], self.bot) # await send_to_channel( # self.bot, - # draft_data['ping_channel'], - # f'{team_role.mention if team_role else draft_pick["owner"]["lname"]}\n' - # f'You have five minutes remaining to make pick #{draft_pick["overall"]}. Is Neil Walker available?' + # draft_data.ping_channel, + # f'{team_role.mention if team_role else draft_pick.owner.lname}\n' + # f'You have five minutes remaining to make pick #{draft_pick.overall}. Is Neil Walker available?' # ) # self.warnings = 5 # 2-minute draft + + logger.info(f'pulling p_channel') + p_channel = discord.utils.get(self.guild.text_channels, id=int(draft_data.ping_channel)) # type: ignore + if not p_channel: + log_exception(LookupError(f'Ping channel with ID {draft_data.ping_channel} not found')) + logger.info(f'p_channel: {p_channel}') + if (deadline - datetime.timedelta(seconds=59) <= now) and self.warnings < 1: - await send_to_channel( - self.bot, - draft_data['ping_channel'], - f'{team_role.mention if team_role else draft_pick["owner"]["lname"]}\n' - f'Less than a minute remaining to make pick #{draft_pick["overall"]}!' + await p_channel.send( + content=f'{team_role.mention if team_role else draft_pick.owner.lname}\nLess than a minute remaining to make pick #{draft_pick.overall}!' ) self.warnings += 1 elif (deadline - datetime.timedelta(seconds=29) <= now) and self.warnings < 2: - await send_to_channel( - self.bot, - draft_data['ping_channel'], - f'{team_role.mention if team_role else draft_pick["owner"]["lname"]}\n' - f'Less than 30 seconds remaining to make pick #{draft_pick["overall"]}!' + await p_channel.send( + content=f'{team_role.mention if team_role else draft_pick.owner.lname}\nLess than 30 seconds remaining to make pick #{draft_pick.overall}!' ) self.warnings += 1 + @draft_loop.before_loop + async def before_weekly_check(self): + await self.bot.wait_until_ready() + async def update_timer(self, draft_data): - deadline = datetime.datetime.now() + datetime.timedelta(minutes=draft_data['pick_minutes']) + deadline = datetime.datetime.now() + datetime.timedelta(minutes=draft_data.pick_minutes) # await patch_draftdata(pick_deadline=deadline) - await db_patch('draftdata', object_id=draft_data['id'], params=[('pick_deadline', deadline)]) + await db_patch('draftdata', object_id=draft_data.id, params=[('pick_deadline', deadline)]) async def send_draft_ping(self, ping=True): - current = await db_get('current') - draft_data = await db_get('draftdata') + current = await get_current() + draft_data = await get_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) - ]) - if p_query['count'] == 0: - raise ValueError(f'No pick found for overall #{draft_data["currentpick"]}') - this_pick = p_query['picks'][0] + this_pick = await get_one_draftpick(season=current.season, overall=draft_data.currentpick) + if not this_pick.owner: + log_exception(ValueError(f'Pick #{this_pick.overall} has no owner associated')) + return + logger.info(f'pick: {this_pick}') - this_team = await db_get('teams', object_id=this_pick['owner']['id']) + + this_team = await db_get('teams', object_id=this_pick.owner.id) logger.info(f'team: {this_team}') + if not this_team: + raise ApiException(f'Team for {this_pick.owner.abbrev} not found') + team_role = get_team_role(None, this_team, self.bot) logger.info(f'role: {team_role}') + team_ping = None if ping and team_role: team_ping = team_role.mention - pick_num = this_pick['overall'] % 16 + pick_num = this_pick.overall % 16 if pick_num == 0: pick_num = 16 @@ -181,13 +203,13 @@ class Draft(commands.Cog): f'role: {team_role}\nping: {team_ping}') embed = get_team_embed(f'{this_team["lname"]} On The Clock', team=this_team) - embed.description = f'Round {this_pick["round"]} / Pick {pick_num} / Overall {this_pick["overall"]}' + embed.description = f'Round {this_pick.round} / Pick {pick_num} / Overall {this_pick.overall}' - # players = await get_players(current['season'], team_abbrev=this_team['abbrev'], sort='wara-desc') + # players = await get_players(current.season, team_abbrev=this_team['abbrev'], sort='wara-desc') p_query = await db_get('players', params=[ - ('season', current['season']), ('team_id', this_team['id']), ('sort', 'cost-desc') + ('season', current.season), ('team_id', this_team['id']), ('sort', 'cost-desc') ]) - if p_query['count'] > 0: + if p_query and p_query.get('count') > 0: count = 0 core_players_string = '' @@ -202,7 +224,7 @@ class Draft(commands.Cog): # roster = await get_team_roster(this_team, 'current') r_query = await db_get(f'teams/{this_team["id"]}/roster/current') - if 'active' in r_query: + if r_query and r_query.get('active'): embed.add_field(name=f'{this_team["sname"]} sWAR', value=f'{r_query["active"]["WARa"]:.2f}') # embed.add_field( @@ -213,22 +235,27 @@ class Draft(commands.Cog): embed.add_field( name=f'Draft Sheet', - value=f'https://docs.google.com/spreadsheets/d/{DRAFT_KEY[current["season"]]}', + value=f'https://docs.google.com/spreadsheets/d/{DRAFT_KEY.get(current.season, f'help-i-dont-know-the-sheet-id-for-season-{current.season}')}', inline=False ) # Last 5 Loop # all_picks = await get_draftpicks( - # current['season'], overall_start=this_pick['overall'] - 15, overall_end=this_pick['overall'] - 1 + # current.season, overall_start=this_pick['overall'] - 15, overall_end=this_pick['overall'] - 1 # ) # last_five = dict(sorted(all_picks.items(), key=lambda item: item[1]["overall"], reverse=True)) l_query = await db_get('draftpicks', params=[ - ('season', current['season']), ('sort', 'order-desc'), ('limit', 5), ('short_output', False), - ('overall_end', this_pick['overall'] - 1), ('player_taken', True) + ('season', current.season), ('sort', 'order-desc'), ('limit', 5), ('short_output', False), + ('overall_end', this_pick.overall - 1), ('player_taken', True) ]) + if not l_query or not l_query.get('picks'): + all_picks = [] + else: + all_picks = l_query['picks'] + last_string = '' count = 0 - for x in l_query['picks']: + for x in all_picks: if x['player'] is not None: last_string += f'Pick #{x["overall"]}: {x["player"]["name"]}\n' count += 1 @@ -240,23 +267,28 @@ class Draft(commands.Cog): # Next 5 Loop # all_picks = await get_draftpicks( - # current['season'], overall_start=this_pick['overall'] + 1, overall_end=this_pick['overall'] + 15 + # current.season, overall_start=this_pick['overall'] + 1, overall_end=this_pick['overall'] + 15 # ) # next_five = dict(sorted(all_picks.items(), key=lambda item: item[1]["overall"])) n_query = await db_get('draftpicks', params=[ - ('season', current['season']), ('sort', 'order-asc'), ('limit', 5), ('short_output', False), - ('overall_start', this_pick['overall'] + 1) + ('season', current.season), ('sort', 'order-asc'), ('limit', 5), ('short_output', False), + ('overall_start', this_pick.overall + 1) ]) + if not n_query or not n_query.get('picks'): + all_picks = [] + else: + all_picks = n_query['picks'] + next_string = '' - for x in n_query['picks']: + for x in all_picks: next_string += f'Pick #{x["overall"]}: {x["owner"]["sname"]}\n' if len(next_string) == 0: next_string = 'None, yet' embed.add_field(name='Next 5', value=next_string) # Pick Deadline - if draft_data['pick_deadline']: - deadline = datetime.datetime.strptime(draft_data['pick_deadline'], '%Y-%m-%dT%H:%M:%S.%f') + if draft_data.pick_deadline: + deadline = draft_data.pick_deadline # deadline = deadline - datetime.timedelta(hours=6) dead_string = deadline.strftime("%b %d @ %H:%M Central") # dead_string = f'' @@ -264,107 +296,135 @@ class Draft(commands.Cog): dead_string = 'None' embed.add_field(name='Pick Deadline', value=dead_string, inline=False) - await send_to_channel(self.bot, draft_data['ping_channel'], content=team_ping, embed=embed) + p_channel = discord.utils.get(self.guild.text_channels, id=int(draft_data.ping_channel)) # type: ignore + if not p_channel: + log_exception(LookupError(f'Ping channel with ID {draft_data.ping_channel} not found')) + + await p_channel.send(content=team_ping, embed=embed) + + # await send_to_channel(self.bot, draft_data.ping_channel, content=team_ping, embed=embed) async def advance_pick(self): self.pick_lock = True - current = await db_get('current') - draft_data = await db_get('draftdata') - starting_round = math.ceil(draft_data['currentpick'] / 16) + current = await get_current() + draft_data = await get_draft_data() + starting_round = math.ceil(draft_data.currentpick / 16) - # draft_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) - ]) - if p_query['count'] == 0: - raise ValueError(f'No pick found for overall #{draft_data["currentpick"]}') - draft_pick = p_query['picks'][0] + draft_pick = await get_one_draftpick(season=current.season, overall=draft_data.currentpick) + if not draft_pick.owner: + log_exception(ValueError(f'Pick #{draft_pick.overall} has no owner associated')) + return + + p_channel = discord.utils.get(self.guild.text_channels, id=int(draft_data.ping_channel)) # type: ignore + if not p_channel: + log_exception(LookupError(f'Ping channel with ID {draft_data.ping_channel} not found')) + + r_channel = discord.utils.get(self.guild.text_channels, id=int(draft_data.result_channel)) # type: ignore + if not r_channel: + log_exception(LookupError(f'Ping channel with ID {draft_data.ping_channel} not found')) + - if draft_pick['player'] is None: - await send_to_channel( - self.bot, - draft_data['ping_channel'], - f'It\'s time to to ***SKIP***. Can I get an F in chat?' + if draft_pick.player is None: + await p_channel.send( + content=f'It\'s time to to ***SKIP***. Can I get an F in chat?' ) self.warnings = 0 - # await patch_draftdata(currentpick=draft_data['currentpick'] + 1) - draft_data = await db_patch('draftdata', object_id=draft_data['id'], params=[ - ('currentpick', draft_data['currentpick'] + 1) + # await patch_draftdata(currentpick=draft_data.currentpick + 1) + d_query = await db_patch('draftdata', object_id=draft_data.id, params=[ + ('currentpick', draft_data.currentpick + 1) ]) + draft_data = DraftData(**d_query) # Advance the current pick until a selection is possible while True: - # draft_data = await db_get('draftdata') - # draft_pick = await get_one_draftpick_byoverall(current['season'], draft_data['currentpick']) - if draft_data['currentpick'] > 512: - await send_to_channel(self.bot, draft_data['ping_channel'], 'Looks like that is the end of the draft!') - await db_patch('draftdata', object_id=draft_data['id'], params=[('timer', False)]) + # draft_data = await get_draft_data() + # draft_pick = await get_one_draftpick_byoverall(current.season, draft_data.currentpick) + if draft_data.currentpick > 512: + await p_channel.send( + content='Looks like that is the end of the draft!' + ) + await db_patch('draftdata', object_id=draft_data.id, params=[('timer', False)]) self.pick_lock = False return - p_query = await db_get('draftpicks', params=[ - ('season', current['season']), ('overall', draft_data['currentpick']), ('short_output', False) - ]) - if p_query['count'] == 0: - raise ValueError(f'No pick found for overall #{draft_data["currentpick"]}') - draft_pick = p_query['picks'][0] + draft_pick = await get_one_draftpick(season=current.season, overall=draft_data.currentpick) + if not draft_pick.owner: + log_exception(ValueError(f'Pick #{draft_pick.overall} has no owner associated')) + return # Check that selection has been made for current pick, advance if so - if draft_pick['player'] is not None: - # await patch_draftdata(currentpick=draft_data['currentpick'] + 1) - draft_data = await db_patch('draftdata', object_id=draft_data['id'], params=[ - ('currentpick', draft_data['currentpick'] + 1) + if draft_pick.player is not None: + # await patch_draftdata(currentpick=draft_data.currentpick + 1) + draft_data = await db_patch('draftdata', object_id=draft_data.id, params=[ + ('currentpick', draft_data.currentpick + 1) ]) else: - round_num = math.ceil(draft_data['currentpick'] / 16) + round_num = math.ceil(draft_data.currentpick / 16) if round_num > starting_round: - await send_to_channel(self.bot, draft_data['result_channel'], f'# Round {round_num}') + await r_channel.send( + content=f'# Round {round_num}' + ) break # If timer is true, set new deadline - # draft_data = await db_get('draftdata') # No longer needed - if draft_data['timer']: + # draft_data = await get_draft_data() # No longer needed + if draft_data.timer: await self.update_timer(draft_data) else: deadline = datetime.datetime.now() + datetime.timedelta(days=690) # await patch_draftdata(pick_deadline=deadline) - await db_patch('draftdata', object_id=draft_data['id'], params=[('pick_deadline', deadline)]) + await db_patch('draftdata', object_id=draft_data.id, params=[('pick_deadline', deadline)]) # Post splash screen to ping_channel await self.send_draft_ping() self.pick_lock = False - async def send_pick_to_sheets(self, draft_pick, player, pick_num): + async def send_pick_to_sheets(self, draft_pick: DraftPick, player, pick_num): + if not draft_pick.origowner or not draft_pick.owner: + log_exception(AttributeError(f'Draft Pick ID #{draft_pick.id} is missing ownership data')) + sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') # this_pick = [[ # draft_pick['round'], pick_num, draft_pick['owner']['abbrev'], draft_pick['owner']['sname'], # player['name'], player['wara'], draft_pick['overall'] # ]] + this_pick = [[ - draft_pick['origowner']['abbrev'], draft_pick['owner']['abbrev'], player['name'], + draft_pick.origowner.abbrev, draft_pick.owner.abbrev, player['name'], player['wara'] ]] + + sheets_key = DRAFT_KEY.get(draft_pick.season) + if sheets_key: + logger.info(f'sending pick to sheets') + sheets.open_by_key(sheets_key).worksheet_by_title('Ordered List').update_values( + crange=f'D{draft_pick.overall + 1}', + values=this_pick + ) + logger.info(f'pick has been sent to sheets') + else: + logger.error(f'Cannot find draft key for season {draft_pick.season}') + - logger.info(f'sending pick to sheets') - sheets.open_by_key(DRAFT_KEY[draft_pick['season']]).worksheet_by_title('Ordered List').update_values( - crange=f'D{draft_pick["overall"] + 1}', - values=this_pick - ) - logger.info(f'pick has been sent to sheets') - - async def draft_player(self, current, draft_data, draft_pick, player): + async def draft_player(self, current, draft_data: DraftData, draft_pick: DraftPick, player): # Is this player available to be drafted? - if player['team'] == draft_pick['owner']: + if draft_pick.owner is None: + log_exception(ValueError(f'Draft pick S{draft_pick.season} / overall {draft_pick.overall} has no owner')) + return + + if player['team']['id'] == draft_pick.owner.id: return {'success': False, 'error': f'{player["name"]} is already on your team, dingus.'} elif player['team']['abbrev'] != 'FA': return { 'success': False, - 'error': f'Hey, uh, {player["team"]["sname"]}, you think {draft_pick["owner"]["abbrev"]} can have ' + 'error': f'Hey, uh, {player["team"]["sname"]}, you think {draft_pick.owner.abbrev} can have ' f'{player["name"]} for free? No? Sorry, I tried.' } # team_roster = await get_team_roster(draft_pick['owner'], 'current') - team_roster = await db_get(f'teams/{draft_pick["owner"]["id"]}/roster/current') + team_roster = await db_get(f'teams/{draft_pick.owner.id}/roster/current') + if not team_roster or not team_roster.get('active'): + raise ApiException(f'Team roster not found for {draft_pick.owner.abbrev}') # Does this team have the cap space to afford this player? max_zeroes = 32 - len(team_roster['active']['players']) @@ -385,24 +445,13 @@ class Draft(commands.Cog): 'error': f'Drafting {player["name"]} would put you at {total_swar:.2f} ' f'sWAR, friendo.' } - - # total_wara = team_roster["active"]["WARa"] + player["wara"] - # if total_wara > 45.00001: - # return { - # 'success': False, - # 'error': f'Drafting {player["name"]} would put you at {total_wara:.2f} ' - # f'WARa, friendo.' - # } - - # Submit the pick logger.info( - f'{draft_pick["owner"]["lname"]} selects {player["name"]} with the #{draft_pick["overall"]} overall pick' + 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']) - draft_pick['player'] = player + draft_pick.player = Player(**player) await patch_draftpick(draft_pick) # TODO: uncomment for live draft - player['team'] = draft_pick['owner'] + player['team']['id'] = draft_pick.owner.id player['demotion_week'] = 1 # await patch_player(player['id'], team_id=draft_pick['owner']['id'], demotion_week=2) await put_player(player) # TODO: uncomment for live draft @@ -412,74 +461,75 @@ class Draft(commands.Cog): # 'player_id': player['id'], # 'oldteam_id': 201, # FA team ID # 'newteam_id': draft_pick['owner']['id'], - # 'season': current['season'], - # 'moveid': f'draft-overall-{draft_pick["overall"]}' + # 'season': current.season, + # 'moveid': f'draft-overall-{draft_pick.overall}' # }]) await db_post('transactions', payload={'count': 1, 'moves': [{ 'week': 0, 'player_id': player['id'], - 'oldteam_id': 302, # FA team ID - 'newteam_id': draft_pick['owner']['id'], - 'season': current['season'], - 'moveid': f'draft-overall-{draft_pick["overall"]}' + 'oldteam_id': self.fa_team_id, + 'newteam_id': draft_pick.owner.id, + 'season': current.season, + 'moveid': f'draft-overall-{draft_pick.overall}' }]}) - await send_to_channel( - self.bot, - draft_data['ping_channel'], + + + p_channel = discord.utils.get(self.guild.text_channels, id=int(draft_data.ping_channel)) # type: ignore + if not p_channel: + log_exception(LookupError(f'Ping channel with ID {draft_data.ping_channel} not found')) + + await p_channel.send( + content=None, embed=await get_player_embed(player, current) ) if player['image2']: embed = get_team_embed(f'{player["name"]}', player["team"], thumbnail=False) embed.set_image(url=player['image2']) - await send_to_channel( - self.bot, - draft_data['ping_channel'], + await p_channel.send( + content=None, embed=embed ) - pick_num = draft_pick['overall'] % 16 + pick_num = draft_pick.overall % 16 if pick_num == 0: pick_num = 16 - await self.send_pick_to_sheets(draft_pick, player, draft_pick['overall']) + await self.send_pick_to_sheets(draft_pick, player, draft_pick.overall) - await send_to_channel( - self.bot, - draft_data['result_channel'], - f'Round {draft_pick["round"]} / Pick {pick_num}: ' - f'{draft_pick["owner"]["abbrev"]} selects **{player["name"]}**' + await p_channel.send( + content=f'Round {draft_pick.round} / Pick {pick_num}: {draft_pick.owner.abbrev} selects **{player["name"]}**' ) return {'success': True} - async def draftdata_to_string(self, current, draft_data): - p_query = await db_get('draftpicks', params=[ - ('season', current['season']), ('overall', draft_data['currentpick']), ('short_output', False) - ]) - if p_query['count'] == 0: - raise ValueError(f'No pick found for overall #{draft_data["currentpick"]}') + async def draftdata_to_string(self, current, draft_data: DraftData): + draft_pick = await get_one_draftpick(season=current.season, overall=draft_data.currentpick) + if not draft_pick.owner: + log_exception(ValueError(f'Pick #{draft_pick.overall} has no owner associated')) + return - draft_pick = p_query['picks'][0] - 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') + if draft_data.pick_deadline: + deadline = draft_data.pick_deadline deadline = deadline - datetime.timedelta(hours=6) dead_string = deadline.strftime("%b %d @ %H:%M Central") else: dead_string = 'None' - guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) + p_channel = discord.utils.get(self.guild.text_channels, id=int(draft_data.ping_channel)) + if not p_channel: + log_exception(LookupError(f'Ping channel with ID {draft_data.ping_channel} not found')) - p_channel = discord.utils.get(guild.text_channels, id=draft_data["ping_channel"]) - r_channel = discord.utils.get(guild.text_channels, id=draft_data["result_channel"]) + r_channel = discord.utils.get(self.guild.text_channels, id=int(draft_data.result_channel)) + if not r_channel: + log_exception(LookupError(f'Result channel with ID {draft_data.result_channel} not found')) - draft_string = f'Current Pick: {draft_data["currentpick"]}\n' \ - f'Pick Owner: {draft_pick["owner"]["sname"] if draft_pick else "N/A"}\n' \ - f'Timer: {"Active" if draft_data["timer"] else "Inactive"} ' \ - f'({draft_data["pick_minutes"]} min total)\n' \ + draft_string = f'Current Pick: {draft_data.currentpick}\n' \ + f'Pick Owner: {draft_pick.owner.sname if draft_pick else "N/A"}\n' \ + f'Timer: {"Active" if draft_data.timer else "Inactive"} ' \ + f'({draft_data.pick_minutes} min total)\n' \ f'Pick Deadline: {dead_string}\n' \ f'Ping Channel: {p_channel.mention}\n' \ - f'Result Channel: {r_channel.mention}\n' + f'Result Channel: {r_channel.mention}\n' \ + f'Pick Lock: {self.pick_lock}' logger.info(f'draft_string: {draft_string}') return draft_string @@ -491,56 +541,57 @@ class Draft(commands.Cog): cal_can_pick_for_all = True if self.pick_lock: - await react_and_reply(ctx, '❌', 'Another pick is already in the works.') + await react_and_reply(ctx, '❌', 'Picks are locked right now') return else: self.pick_lock = True - current = await db_get('current') - team = await get_team_by_owner(current['season'], ctx.author.id) + current = await get_current() + team = await get_team_by_owner(current.season, ctx.author.id) if not team: # if ctx.author.id == 403294362550796299: - # team = await get_team_by_abbrev('HAM', current['season']) + # team = await get_team_by_abbrev('HAM', current.season) # else: await ctx.message.add_reaction('❌') await ctx.send('I don\'t know youuuuuuuuu') self.pick_lock = False return - draft_data = await db_get('draftdata') + draft_data = await get_draft_data() if draft_data is None: logger.error(f'Cannot find draft_data') await send_to_channel(self.bot, 'commissioners-office', f'Failed to GET draftdata') + self.pick_lock = False raise LookupError('Cannot find draftdata, send help') - # draft_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) - ]) - if p_query['count'] == 0: - raise LookupError(f'No pick found for overall #{draft_data["currentpick"]}') - draft_pick = p_query['picks'][0] + + draft_pick = await get_one_draftpick(season=current.season, overall=draft_data.currentpick) + if not draft_pick.owner: + self.pick_lock = False + log_exception(ValueError(f'Pick #{draft_pick.overall} has no owner associated')) + alt_pick_flag = False # Does the current pick belong to this team? - if draft_pick['owner'] != team: + if draft_pick.owner.id != team['id']: alt_pick_flag = True # Does this team have any skipped picks? # raw_picks = await get_draftpicks( - # current['season'], owner_team=team, round_end=math.ceil(draft_pick['overall'] / 16), round_start=1 + # current.season, owner_team=team, round_end=math.ceil(draft_pick['overall'] / 16), round_start=1 # ) + # TODO: add get_draftpicks to api_calls.draft_picks p_query = await db_get('draftpicks', params=[ - ('season', current['season']), ('owner_team_id', team['id']), ('round_start', 1), - ('round_end', math.ceil(draft_pick['overall'] / 16)), ('sort', 'overall-asc'), ('short_output', False) + ('season', current.season), ('owner_team_id', team['id']), ('round_start', 1), + ('round_end', math.ceil(draft_pick.overall / 16)), ('sort', 'overall-asc'), ('short_output', False) ]) if p_query['count'] == 0: raise LookupError(f'Draft picks for {team["abbrev"]} not found') new_pick = None for x in p_query['picks']: - if x["player"] is None and x['overall'] < draft_pick['overall']: - # new_pick = await get_one_draftpick_byoverall(current['season'], team_picks[x]['overall']) + if x["player"] is None and x['overall'] < draft_pick.overall: + # new_pick = await get_one_draftpick_byoverall(current.season, team_picks[x]['overall']) # p_query = await db_get('draftpicks', params=[ - # ('season', current['season']), ('overall', x['overall']), ('short_output', False) + # ('season', current.season), ('overall', x['overall']), ('short_output', False) # ]) # if p_query['count'] == 0: # raise ValueError(f'No pick found for overall #{x["overall"]}') @@ -550,15 +601,14 @@ class Draft(commands.Cog): if new_pick is not None: draft_pick = new_pick else: - # mil_team = await get_team_by_abbrev(f'{team["abbrev"]}MiL', current['season']) + # mil_team = await get_team_by_abbrev(f'{team["abbrev"]}MiL', current.season) # if mil_team == draft_pick['owner']: # team = mil_team if ctx.author.id == self.bot.owner_id and cal_can_pick_for_all: alt_pick_flag = False else: await ctx.message.add_reaction('❌') - await ctx.send(f'You are not on the clock {ctx.author.mention}. **{draft_pick["owner"]["abbrev"]}** is ' - f'up right now.') + await ctx.send(f'You are not on the clock {ctx.author.mention}. **{draft_pick.owner.abbrev}** is up right now.') self.pick_lock = False return @@ -568,15 +618,22 @@ class Draft(commands.Cog): except ValueError as e: logger.error(e) await ctx.send(f'{name} not found') + self.pick_lock = False return - player = await get_player_by_name(current['season'], player_name) + player = await get_player_by_name(current.season, player_name) if player is None: e_msg = f'Could not find {player_name} after matching the name' logger.error(e_msg) await ctx.send(e_msg) + self.pick_lock = False return the_pick = await self.draft_player(current, draft_data, draft_pick, player) + if the_pick is None: + log_exception(ValueError('Did not receive confirmation for this pick.')) + self.pick_lock = False + return + self.pick_lock = False if the_pick['success']: await ctx.message.add_reaction('✅') @@ -588,8 +645,8 @@ class Draft(commands.Cog): @commands.command(name='list', aliases=['draftlist', 'mylist'], help='Set your draft list') # @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) async def draft_list_command(self, ctx, *player_list): - current = await db_get('current') - team = await get_team_by_owner(current['season'], ctx.author.id) + current = await get_current() + team = await get_team_by_owner(current.season, ctx.author.id) if not team: await react_and_reply(ctx, '❌', 'I don\'t know youuuuuuuuu') return @@ -597,8 +654,11 @@ class Draft(commands.Cog): if not player_list: # team_list = await get_draft_list(team) l_query = await db_get('draftlist', params=[ - ('season', current['season']), ('team_id', team['id']) + ('season', current.season), ('team_id', team['id']) ]) + if not l_query: + raise ApiException('There was a database error trying to pull your list') + if l_query['count'] > 0: list_string = 'Current list:\n' for x in l_query['picks']: @@ -621,18 +681,21 @@ class Draft(commands.Cog): player_cog = self.bot.get_cog('Players') try: 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) + player = await get_player_by_name(current.season, player_name) except Exception as e: logger.error(f'Could not draft {x} for {team["abbrev"]}: {e}') errors.append(x) rank -= 1 else: - if player['team']['abbrev'] != 'FA': + if not player: + log_exception(LookupError(f'{player_name} not found')) + + if player.get('team', {'abbrev': None}).get('abbrev') != 'FA': errors.append(player['name']) rank -= 1 else: draft_list.append({ - 'season': current['season'], + 'season': current.season, 'team_id': team['id'], 'rank': rank, 'player_id': player['id'] @@ -652,15 +715,27 @@ class Draft(commands.Cog): await db_post('draftlist', payload={'count': len(draft_list), 'draft_list': draft_list}) await ctx.message.add_reaction('✅') + @commands.command(name='restart-loop', help='Mod: Restart the draft tick loop') + async def restart_loop_command(self, ctx): + if ctx.author.id not in [258104532423147520, 139926308644847616]: + await ctx.send(random_gif('you\'re not my dad')) + return + + self.draft_loop.start() + await ctx.send(random_gif('we are so back')) + @commands.command(name='whomst', aliases=['draftstatus'], help='Get draft status') async def draft_status_command(self, ctx): - current = await db_get('current') - draft_data = await db_get('draftdata') + current = await get_current() + draft_data = await get_draft_data() 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) + async with ctx.typing(): + await ctx.send(await self.draftdata_to_string(current, draft_data)) + + async with ctx.typing(): + if draft_data.ping_channel is not None: + await self.send_draft_ping(ping=False) @app_commands.command(name='draft-mod', description='Mod commands for draft administration') @app_commands.describe( @@ -670,43 +745,43 @@ class Draft(commands.Cog): timer_master='Integer: number of minutes for all draft picks', timer_this_pick='Integer: number of minutes for the current draft pick', timer_active='Boolean: enable/disable the pick timer', - wipe_pick='Integer: overall pick number to delete; cannot be combined with other parameters' + wipe_pick='Integer: overall pick number to delete; cannot be combined with other parameters', + pick_lock='Boolean: enable/disable the !select command' ) async def draftmod_slash_command( - self, interaction: discord.Interaction, result_channel: TextChannel = None, - ping_channel: TextChannel = None, current_overall: int = None, timer_master: int = None, - timer_this_pick: int = None, timer_active: bool = None, wipe_pick: int = None, pick_lock: bool = None): - if interaction.user.id != 258104532423147520: - await interaction.send_message(random_gif('you\'re not my dad')) + self, interaction: discord.Interaction, result_channel: Optional[TextChannel] = None, + ping_channel: Optional[TextChannel] = None, current_overall: Optional[int] = None, timer_master: Optional[int] = None, timer_this_pick: Optional[int] = None, timer_active: Optional[bool] = None, wipe_pick: Optional[int] = None, pick_lock: Optional[bool] = None): + if interaction.user.id not in [258104532423147520, 139926308644847616]: + await interaction.response.send_message(random_gif('you\'re not my dad')) return await interaction.response.defer() - current = await db_get('current') - draft_data = await db_get('draftdata') + current = await get_current() + draft_data = await get_draft_data() pick_deadline = None res_channel_id = None ping_channel_id = None if wipe_pick is not None: - # this_pick = await get_one_draftpick_byoverall(current['season'], overall=wipe_pick) - p_query = await db_get('draftpicks', params=[ - ('season', current['season']), ('overall', wipe_pick), ('short_output', False) - ]) - if p_query['count'] == 0: - raise ValueError(f'No pick found for overall #{wipe_pick}') - this_pick = p_query['picks'][0] + this_pick = await get_one_draftpick(season=current.season, overall=wipe_pick) + # if not this_pick.owner: + # log_exception(ValueError(f'Pick #{this_pick.overall} has no owner associated')) + # return - if not this_pick['player']: + if not this_pick.player: await interaction.edit_original_response(content=f'I don\'t see a player taken {wipe_pick} overall.') else: - fa_team = await get_team_by_abbrev('FA', current['season']) - this_pick['player'] = None - await patch_draftpick(this_pick) - this_pick['player']['team'] = fa_team - this_player = await put_player(this_pick['player']) + fa_team = await get_team_by_abbrev('FA', current.season) + temp_player = this_pick.player.model_dump() - # this_player = await get_player_by_name(current['season'], this_pick['player']['id']) + this_pick.player = None + await patch_draftpick(this_pick) + + temp_player['team'] = fa_team + this_player = await put_player(temp_player) + + # this_player = await get_player_by_name(current.season, this_pick['player']['id']) # this_player = await db_get('players', object_id=this_pick['player']['id']) await interaction.edit_original_response( content='Don\'t forget to delete the transaction from the database.', @@ -732,7 +807,7 @@ class Draft(commands.Cog): timer = timer_master params.append(('pick_minutes', timer_master)) else: - timer = draft_data['pick_minutes'] + timer = draft_data.pick_minutes deadline = datetime.datetime.now() + datetime.timedelta(minutes=timer) else: deadline = datetime.datetime.now() + datetime.timedelta(weeks=1) @@ -741,9 +816,9 @@ class Draft(commands.Cog): params.append(('result_channel', result_channel.id)) if ping_channel is not None: params.append(('ping_channel', ping_channel.id)) - if current_overall is not None and draft_data['timer'] and timer_active is None: + if current_overall is not None and draft_data.timer and timer_active is None: params.append( - ('pick_deadline', datetime.datetime.now() + datetime.timedelta(minutes=draft_data['pick_minutes'])) + ('pick_deadline', datetime.datetime.now() + datetime.timedelta(minutes=draft_data.pick_minutes)) ) if current_overall is not None: params.append(('currentpick', current_overall)) @@ -758,17 +833,20 @@ class Draft(commands.Cog): # ping_channel=ping_channel_id, # pick_minutes=timer_master # ) - await db_patch('draftdata', object_id=draft_data['id'], params=params) + await db_patch('draftdata', object_id=draft_data.id, params=params) - draft_data = await db_get('draftdata') + draft_data = await get_draft_data() await interaction.edit_original_response(content=await self.draftdata_to_string(current, draft_data)) - if timer_active is True or draft_data['timer']: + if timer_active is True or draft_data.timer: self.warnings = 0 - # draft_pick = await get_one_draftpick_byoverall(current['season'], draft_data['currentpick']) + # draft_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) + ('season', current.season), ('overall', draft_data.currentpick), ('short_output', False) ]) + if not p_query: + raise ApiException(f'No pick found for Overall #{draft_data.currentpick}') + if p_query['count'] == 0: raise ValueError(f'No pick found for overall #{wipe_pick}') draft_pick = p_query['picks'][0] @@ -778,388 +856,22 @@ class Draft(commands.Cog): else: await self.send_draft_ping() - # @commands.group(name='draftset', help='Mod commands for running the draft') - # @commands.is_owner() - # async def draft_set_group(self, ctx): - # if ctx.invoked_subcommand is None: - # await ctx.send('draftset what? You forgot the rest of the command.') - # - # @draft_set_group.command(name='results', help='Set result channel') - # @commands.is_owner() - # async def draft_set_results_command(self, ctx, *channel_mention: TextChannel): - # if not channel_mention: - # this_channel = ctx.channel - # else: - # this_channel = channel_mention[0] - # if not this_channel: - # await ctx.send(f'I cannot find **{channel_mention[0]}** - is that spelled correctly?') - # return - # - # draft_data = await db_get('draftdata') - # current_channel = discord.utils.get(ctx.guild.text_channels, id=draft_data["result_channel"]) - # prompt = f'The result channel is currently **{current_channel}** - would you like to set it to ' \ - # f'**{this_channel.mention}**?' - # - # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 15) - # resp = await this_q.ask([ctx.author]) - # - # if not resp: - # await ctx.send('I will leave it be for now.') - # return - # else: - # await patch_draftdata(result_channel=this_channel.id) - # await ctx.send(random_conf_gif()) - # - # @draft_set_group.command(name='ping', help='Set ping channel') - # @commands.is_owner() - # async def draft_set_ping_command(self, ctx, *channel_mention: TextChannel): - # if not channel_mention: - # this_channel = ctx.channel - # else: - # this_channel = channel_mention[0] - # if not this_channel: - # await ctx.send(f'I cannot find **{channel_mention[0]}** - is that spelled correctly?') - # return - # - # draft_data = await db_get('draftdata') - # current_channel = discord.utils.get(ctx.guild.text_channels, id=draft_data["ping_channel"]) - # prompt = f'The result channel is currently **{current_channel}** - would you like to set it to ' \ - # f'**{this_channel.mention}**?' - # - # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 15) - # resp = await this_q.ask([ctx.author]) - # - # if not resp: - # await ctx.send('I will leave it be for now.') - # return - # else: - # await patch_draftdata(ping_channel=this_channel.id) - # await ctx.send(random_conf_gif()) - # - # @draft_set_group.command(name='overall', help='Set current pick') - # @commands.is_owner() - # async def draft_set_overall_command(self, ctx, overall_num: int): - # draft_data = await db_get('draftdata') - # prompt = f'The current pick is #**{draft_data["currentpick"]}** - would you like to set it to ' \ - # f'#**{overall_num}**?' - # - # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 15) - # resp = await this_q.ask([ctx.author]) - # - # if not resp: - # await ctx.send('I will leave it be for now.') - # return - # else: - # await patch_draftdata(currentpick=overall_num) - # await ctx.send(random_conf_gif()) - # - # @draft_set_group.command(name='minutes', help='Set minutes per pick') - # @commands.is_owner() - # async def draft_set_minutes_command(self, ctx, minutes: int): - # draft_data = await db_get('draftdata') - # prompt = f'The current pick time is **{draft_data["pick_minutes"]}** minutes - would you like to set it to ' \ - # f'**{minutes}**?' - # - # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 15) - # resp = await this_q.ask([ctx.author]) - # - # if not resp: - # await ctx.send('I will leave it be for now.') - # return - # else: - # await patch_draftdata(pick_minutes=minutes) - # await self.update_timer(draft_data) - # await ctx.send(random_conf_gif()) - # - # @draft_set_group.command(name='timer', help='Start/stop the timer') - # @commands.is_owner() - # async def timer_start_command(self, ctx, which): - # if which.lower() in ['start', 'go', 'begin', 'on', 'yes']: - # await patch_draftdata(timer=True) - # await ctx.message.add_reaction('✅') - # await ctx.send(f'Just enabled the timer {await get_emoji(ctx, "fingerguns")}') - # else: - # await patch_draftdata(timer=False) - # await ctx.message.add_reaction('✅') - # await ctx.send(f'Just stopped the timer {await get_emoji(ctx, "fingerguns")}') - - # @commands.command(name='keeper', help='Set keeper slots') - # @commands.is_owner() - # async def keeper_command(self, ctx, team_abbrev, draft_round, *, name): - # current = await db_get('current') - # this_team = await get_one_team(team_abbrev) - # if not this_team: - # await ctx.send(f'Are you familiar with this league? Who the fuck is **{team_abbrev}**?') - # return - # - # this_pick = await get_one_draftpick_search(current['season'], this_team['abbrev'], draft_round) - # if not this_pick: - # await ctx.send(f'{await get_emoji(ctx, "grimacing")}Uhh...I couldn\'t find ' - # f'{this_team["abbrev"]} {draft_round}.') - # return - # - # player_cog = self.bot.get_cog('Players') - # player_name = await fuzzy_player_search(ctx, ctx.channel, self.bot, name, player_cog.player_list.keys()) - # this_player = await get_one_player(player_name) - # - # await patch_draftpick(this_pick['id'], player_id=this_player['id']) - # await ctx.send(content=None, embed=await get_player_embed(this_player, current)) - # - # pick_num = this_pick['overall'] % 18 - # if pick_num == 0: - # pick_num = 18 - # - # await self.send_pick_to_sheets(this_pick, this_player, pick_num) - # - # @commands.command(name='cutem', help='Release non-keepers') - # @commands.is_owner() - # async def cutem_command(self, ctx, team_abbrev): - # current = await db_get('current') - # if current['week'] == -2: - # await ctx.send('Advance the week and run transactions before running this.') - # return - # this_team = await get_one_team(team_abbrev) - # if not this_team: - # await ctx.send(f'Are you familiar with this league? Who the fuck is **{team_abbrev}**?') - # return - # - # keepers = [] - # - # all_picks = await get_draftpicks(current['season'], owner_team=this_team) - # for x in all_picks: - # if all_picks[x]['player']: - # keepers.append(all_picks[x]['player']) - # - # full_team = await get_players(current['season'], this_team['abbrev']) - # for x in full_team: - # if full_team[x] not in keepers: - # await patch_player(full_team[x]['id'], team_id=99) - # - # await ctx.send(random_conf_gif()) - - # @commands.command(name='migrateteam', help='Migrate s3 to s4', hidden=True) - # @commands.is_owner() - # async def migrate_teams_command(self, ctx, old_abbrev): - # # Create new team and clean out unused fields - # old_team = await get_one_team(old_abbrev, 4) - # new_team = copy.deepcopy(old_team) - # new_team['season'] = 5 - # del new_team['manager_legacy'] - # del new_team['division_legacy'] - # new_team['manager1_id'] = copy.deepcopy(new_team['manager1']['id']) - # del new_team['manager1'] - # if old_team['manager2']: - # new_team['manager2_id'] = copy.deepcopy(new_team['manager2']['id']) - # del new_team['manager2'] - # del new_team['division'] - # new_team['stadium'] = SBA_WEATHER_CHARTS[old_team['abbrev']] - # # del new_team['gsheet'] - # - # # Post new team and show embed to confirm - # await ctx.send(f'Copying the {old_team["sname"]} into season 4...') - # new_team = await post_team(new_team) - # if new_team: - # embed = get_team_embed(f'Season 4 {new_team["sname"]}', new_team) - # await ctx.send(content=None, embed=embed) - # - # # Post IL and MiL teams - # il_team = new_team - # il_team['abbrev'] = f'{il_team["abbrev"]}IL' - # del il_team['stadium'] - # if not await post_team(il_team): - # await ctx.send('Yikes! I wasn\'t able to post the SIL team.') - # return - # await ctx.send(f'Added {il_team["abbrev"]}') - # - # mil_team = il_team - # mil_team['abbrev'] = f'{old_team["abbrev"]}MiL' - # if not await post_team(mil_team): - # await ctx.send('Yikes! I wasn\'t able to post the MiL team.') - # return - # await ctx.send(f'Added {mil_team["abbrev"]}') - # - # # Update draft picks to new team - # await ctx.send('Alright, lemme move over draft picks...') - # all_picks = await get_draftpicks(5, owner_team=old_team, team_season=3) - # for this_pick in [*all_picks.values()]: - # await patch_draftpick(this_pick['id'], owner_id=new_team['id']) - # - # all_picks = await get_draftpicks(5, orig_owner_team=old_team, team_season=3) - # for this_pick in [*all_picks.values()]: - # await patch_draftpick(this_pick['id'], orig_owner_id=new_team['id']) - # - # await ctx.send('All done!') - - # @commands.command(name='linkteams', help='Migrate s3 to s4', hidden=True) - # @commands.is_owner() - # async def link_teams_command(self, ctx, old_abbrev, new_abbrev): - # old_team = await get_one_team(old_abbrev, 4) - # new_team = await get_one_team(new_abbrev, 5) - # - # active_players = await get_players(4, old_abbrev) - # sil_players = await get_players(4, f'{old_abbrev}SIL') - # mil_players = await get_players(4, f'{old_abbrev}MiL') - # - # prompt = f'I found {len(active_players)} players on {old_abbrev} - want me to add them to {new_team["abbrev"]}?' - # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 15) - # resp = await this_q.ask([ctx.author]) - # - # if not resp: - # await ctx.send('No problem - this is a big decision.') - # return - # else: - # players_not_found = [] - # for name in active_players: - # new_player = await get_one_player(name) - # - # if not new_player: - # players_not_found.append(name) - # else: - # await patch_player(new_player['id'], team_id=new_team['id']) - # - # for name in sil_players: - # new_player = await get_one_player(name) - # - # if not new_player: - # players_not_found.append(name) - # else: - # await patch_player(new_player['id'], team_id=f'{new_team["id"] + 1}') - # - # for name in mil_players: - # new_player = await get_one_player(name) - # - # if not new_player: - # players_not_found.append(name) - # else: - # await patch_player(new_player['id'], team_id=f'{new_team["id"] + 2}') - # - # await ctx.send('All done!') - # - # @commands.command(name='setorder', help='Populate all overall picks', hidden=True) - # @commands.is_owner() - # async def set_order_command(self, ctx, old_abbrev, new_abbrev, overall_num: int): - # old_team = await get_one_team(old_abbrev, 4) - # this_team = await get_one_team(new_abbrev, 5) - # if not this_team: - # this_team = await get_one_team('FA', 5) - # - # all_picks = await get_draftpicks(5, orig_owner_team=this_team) - # count = 1 - # - # await ctx.send(f'Okay, let me set each of their 11 first rounds with multiples of {overall_num} before ' - # f'snaking...') - # for this_pick in [*all_picks.values()]: - # if count > 11 and count % 2 == 0: - # this_overall = ((count - 1) * 18) + (19 - overall_num) - # else: - # this_overall = (count * 18) - (18 - overall_num) - # await patch_draftpick( - # this_pick['id'], - # overall=this_overall, - # orig_owner_id=this_team['id'] - # ) - # count += 1 - # - # await ctx.send(random_conf_gif()) - # - # @commands.command(name='fixorder', help='Populate all overall picks', hidden=True) - # @commands.is_owner() - # async def set_order_command(self, ctx): - # count = 393 - # f_order = { - # "LMM": 1, - # "TK": 2, - # "WV": 3, - # "BSG": 4, - # "BBL": 5, - # "MAD": 6, - # "FA": 7, - # "MKE": 9, - # "VA": 10, - # "DEN": 11, - # "WWS": 12, - # "NN": 13, - # "HOL": 14, - # "CLS": 15, - # "DAL": 16, - # "KSS": 17, - # "PBW": 18 - # } - # - # for x in range(25, 36): - # raw_picks = await get_draftpicks(5, round_start=x, round_end=x) - # all_picks = dict(sorted(raw_picks.items(), key=lambda item: f_order[item[1]["origowner"]["abbrev"]])) - # for this_pick in [*all_picks.values()]: - # await patch_draftpick( - # this_pick['id'], - # overall=count, - # ) - # count += 1 - # - # await ctx.send(random_conf_gif()) - # - # @commands.command(name='newowner', help='Update draft owner seasons', hidden=True) - # @commands.is_owner() - # async def new_owner_command(self, ctx, old_abbrev, new_abbrev): - # old_team = await get_one_team(old_abbrev, 4) - # this_team = await get_one_team(new_abbrev, 5) - # if not this_team: - # this_team = await get_one_team('FA', 5) - # - # all_picks = await get_draftpicks(5, owner_team=old_team, team_season=4) - # await ctx.send(f'Okay, let me update these {len(all_picks)} owner teams..') - # - # for this_pick in [*all_picks.values()]: - # await patch_draftpick( - # this_pick['id'], - # owner_id=this_team['id'] - # ) - # - # await ctx.send(random_conf_gif()) - # - # @commands.command(name='fillgaps', help='Fill draft pick overall gaps', hidden=True) - # @commands.is_owner() - # async def fill_gaps_command(self, ctx): - # raw_picks = await get_draftpicks(season=5) - # all_picks = dict(sorted(raw_picks.items(), key=lambda item: item[1]["overall"])) - # overall = 1 - # - # for this_pick in [*all_picks.values()]: - # if this_pick['overall'] < 600: - # if this_pick['overall'] != overall: - # await patch_draftpick(this_pick['id'], overall=overall) - # logger.info(f'Updating {this_pick["origowner"]["abbrev"]} {this_pick["round"]}: ' - # f'#{this_pick["overall"]} to {overall}') - # overall += 1 - # - # @commands.command(name='dropmildem', help='Remove MiL demotion week', hidden=True) - # @commands.is_owner() - # async def drop_mil_demotion_command(self, ctx): - # current = await db_get('current') - # await ctx.send('I\'m fuckin on it') - # return_string = '' - # for x in range(99, 154): - # this_team = await get_one_team(x) - # if this_team['abbrev'][-3:] == 'MiL': - # return_string += f'Checking {this_team["abbrev"]}...\n' - # mil_players = await get_players(current['season'], this_team['abbrev']) - # count = 0 - # for y in mil_players: - # if mil_players[y]['demotion_week']: - # await patch_player(mil_players[y]['id'], demotion_week=False) - # count += 1 - # return_string += f'Eradicated {count} demotion weeks\n' - # - # await ctx.send(return_string) - # @commands.command(name='keepers', help='Set keepers', hidden=True) - @commands.is_owner() async def keepers_command(self, ctx, team_abbrev, *, player_names): - current = await db_get('current') + if ctx.author.id not in [258104532423147520, 139926308644847616]: + return + + current = await get_current() player_list = [] - this_team = await get_team_by_abbrev(team_abbrev, current['season']) - fa_team = await get_team_by_abbrev('FA', current['season']) + this_team = await get_team_by_abbrev(team_abbrev, current.season) + if not this_team: + raise ApiException(f'{team_abbrev} not found') + + fa_team = await get_team_by_abbrev('FA', current.season) + if not fa_team: + raise ApiException(f'FA team not found') + player_names = re.split(',', player_names) keepers = [] keeper_count = 1 @@ -1167,17 +879,27 @@ class Draft(commands.Cog): for x in player_names: player_cog = self.bot.get_cog('Players') 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) + player = await get_player_by_name(current.season, player_name) + if not player: + raise ApiException(f'{player_name} not found') keepers.append(player["name"]) all_players = [] - # active_roster = await get_players(season=current['season'], team_abbrev=team_abbrev) - # il_players = await get_players(season=current['season'], team_abbrev=f'{team_abbrev}IL') - # mil_players = await get_players(season=current['season'], team_abbrev=f'{team_abbrev}MiL') - active_roster = await db_get('players', params=[('season', current['season']), ('team_id', this_team['id'])]) - il_players = await db_get('players', params=[('season', current['season']), ('team_id', this_team['id'] + 1)]) - mil_players = await db_get('players', params=[('season', current['season']), ('team_id', this_team['id'] + 2)]) + # active_roster = await get_players(season=current.season, team_abbrev=team_abbrev) + # il_players = await get_players(season=current.season, team_abbrev=f'{team_abbrev}IL') + # mil_players = await get_players(season=current.season, team_abbrev=f'{team_abbrev}MiL') + active_roster = await db_get('players', params=[('season', current.season), ('team_id', this_team['id'])]) + if not active_roster: + raise ApiException(f'Active roster not found for {this_team["id"]}') + + il_players = await db_get('players', params=[('season', current.season), ('team_id', this_team['id'] + 1)]) + if not il_players: + raise ApiException(f'Active roster not found for {this_team["id"]}') + + mil_players = await db_get('players', params=[('season', current.season), ('team_id', this_team['id'] + 2)]) + if not mil_players: + raise ApiException(f'Active roster not found for {this_team["id"]}') for guy in active_roster['players']: all_players.append(guy) @@ -1186,8 +908,8 @@ class Draft(commands.Cog): for guy in mil_players['players']: all_players.append(guy) - # all_picks = await get_draftpicks(season=current['season'], owner_team=this_team, round_end=7) - if current['season'] % 2 == 1: + # 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: @@ -1196,8 +918,10 @@ class Draft(commands.Cog): p_query = await db_get( 'draftpicks', - params=[('season', current['season']), ('owner_team_id', this_team['id']), ('pick_round_start', start_round), ('pick_round_end', end_round), ('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')] ) + if not p_query: + raise ApiException(f'No picks found for {this_team["abbrev"]} in rounds {start_round} to {end_round}') # logger.info(f'\n{all_picks}\n') # sorted_picks = sorted(all_picks.items(), key=lambda item: item[1]["overall"]) sorted_picks = p_query['picks'] @@ -1219,7 +943,7 @@ class Draft(commands.Cog): draft_pick['player'] = this_player logger.info(f'Setting {x["name"]} as {this_team["abbrev"]}\'s #{keeper_count} keeper with overall ' - f'pick #{draft_pick["overall"]}') + f'pick #{draft_pick.overall}') await patch_draftpick(draft_pick) await put_player(this_player) @@ -1228,7 +952,7 @@ class Draft(commands.Cog): # 'player_id': x['id'], # 'oldteam_id': 201, # FA team ID # 'newteam_id': this_team['id'], - # 'season': current['season'], + # 'season': current.season, # 'moveid': f'keeper-{this_team["abbrev"]}-{keeper_count}' # }]) @@ -1237,11 +961,11 @@ class Draft(commands.Cog): 'player_id': x['id'], 'oldteam_id': fa_team['id'], # FA team ID 'newteam_id': this_team['id'], - 'season': current['season'], + 'season': current.season, 'moveid': f'keeper-{this_team["abbrev"]}-{keeper_count}' }) all_keepers.append({ - 'season': current['season'], + 'season': current.season, 'team_id': this_team['id'], 'player_id': this_player['id'] }) @@ -1250,7 +974,7 @@ class Draft(commands.Cog): if pick_num == 0: pick_num = 16 try: - await self.send_pick_to_sheets(draft_pick, this_player) + await self.send_pick_to_sheets(draft_pick, this_player, draft_pick['overall']) except Exception as e: logger.error(f'{e}') keeper_count += 1