import copy import math import re from helpers import * from db_calls import db_get, db_patch, patch_draftpick, put_player, db_post, get_player_by_name from discord.ext import commands, tasks from discord import TextChannel, app_commands class Draft(commands.Cog): def __init__(self, bot): self.bot = bot self.warnings = 0 self.pick_lock = True # self.sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') self.draft_loop.start() @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') # return draft_data = await db_get('draftdata') now = datetime.datetime.now() # logging.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}') # 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] team_role = get_team_role(None, draft_pick['owner'], self.bot) if deadline <= now: # 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']) ]) if l_query['count'] > 0: for x in l_query['picks']: this_pick = await self.draft_player(current, draft_data, draft_pick, x['player']) if this_pick['success']: break await self.advance_pick() else: # # 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']) # 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"]}.' # ) # 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']) # 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"]}.' # ) # 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']) # 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"]}.' # ) # 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']) # 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"]}.' # ) # 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']) # 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?' # ) # self.warnings = 5 # 2-minute draft 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"]}!' ) 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"]}!' ) self.warnings += 1 async def update_timer(self, draft_data): 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)]) 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}') # 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] logging.info(f'pick: {this_pick}') this_team = await db_get('teams', object_id=this_pick['owner']['id']) logging.info(f'team: {this_team}') team_role = get_team_role(None, this_team, self.bot) logging.info(f'role: {team_role}') team_ping = None if ping and team_role: team_ping = team_role.mention pick_num = this_pick['overall'] % 16 if pick_num == 0: pick_num = 16 logging.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) 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') p_query = await db_get('players', params=[ ('season', current['season']), ('team_id', this_team['id']), ('sort', 'cost-desc') ]) if p_query['count'] > 0: count = 0 core_players_string = '' for x in p_query['players']: if count < 5: core_players_string += f'{x["pos_1"]} {x["name"]} ({x["wara"]})\n' else: break count += 1 embed.add_field(name='Core Players', value=core_players_string) # 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: embed.add_field(name=f'{this_team["sname"]} sWAR', value=f'{r_query["active"]["WARa"]:.2f}') # embed.add_field( # name=f'{this_team["abbrev"]} Roster Page', # value=f'https://sombaseball.ddns.net/teams?abbrev={this_team["abbrev"]}', # inline=False # ) embed.add_field( name=f'Draft Sheet', value=f'https://docs.google.com/spreadsheets/d/{SBA_SEASON8_DRAFT_KEY}', inline=False ) # Last 5 Loop # all_picks = await get_draftpicks( # 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) ]) last_string = '' count = 0 for x in l_query['picks']: if x['player'] is not None: last_string += f'Pick #{x["overall"]}: {x["player"]["name"]}\n' count += 1 if count >= 5: break if len(last_string) == 0: last_string = 'None, yet' embed.add_field(name='Last 5', value=last_string) # Next 5 Loop # all_picks = await get_draftpicks( # 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) ]) next_string = '' for x in n_query['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') # deadline = deadline - datetime.timedelta(hours=6) dead_string = deadline.strftime("%b %d @ %H:%M Central") # dead_string = f'' else: 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) 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) # 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_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?' ) 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) ]) # 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)]) 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] # 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) ]) else: 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}') break # If timer is true, set new deadline # draft_data = await db_get('draftdata') # 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)]) # 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): 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'], player['wara'] ]] logging.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') async def draft_player(self, current, draft_data, draft_pick, player): # Is this player available to be drafted? if player['team'] == draft_pick['owner']: 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 ' 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') # Does this team have the cap space to afford this player? max_zeroes = 32 - len(team_roster['active']['players']) max_counted = 26 - max_zeroes total_swar = 0 count = 0 for x in team_roster['active']['players']: count += 1 if count > max_counted: break total_swar += x['wara'] if total_swar > 38.00001: return { 'success': False, '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 logging.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']) draft_pick['player'] = player await patch_draftpick(draft_pick) # TODO: uncomment for live draft player['team'] = draft_pick['owner'] player['demotion_week'] = 2 # await patch_player(player['id'], team_id=draft_pick['owner']['id'], demotion_week=2) await put_player(player) # TODO: uncomment for live draft # await post_transactions([{ # 'week': -1, # '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"]}' # }]) 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"]}' }]}) await send_to_channel( self.bot, draft_data['ping_channel'], 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'], embed=embed ) 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 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"]}**' ) 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"]}') draft_pick = p_query['picks'][0] logging.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') 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(guild.text_channels, id=draft_data["ping_channel"]) r_channel = discord.utils.get(guild.text_channels, id=draft_data["result_channel"]) 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' logging.info(f'draft_string: {draft_string}') return draft_string # @commands.command(name='start', help='Start pick timer') # @commands.is_owner() # async def advance_draft_command(self, ctx): # current = await db_get('current') # draft_data = await db_get('draftdata') # draft_pick = await get_one_draftpick_byoverall(current['season'], draft_data['currentpick']) # # if draft_pick['player']: # await self.advance_pick() # else: # if draft_data['timer']: # deadline = datetime.datetime.now() + datetime.timedelta(minutes=draft_data['pick_minutes']) # else: # deadline = datetime.datetime.now() + datetime.timedelta(days=690) # await patch_draftdata(pick_deadline=deadline) # # self.warnings = 0 # await self.send_draft_ping() @commands.command(name='select', aliases=['pick', 'draft'], help='Draft a player') @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) async def draft_command(self, ctx, *, name): cal_can_pick_for_all = True if self.pick_lock: await react_and_reply(ctx, '❌', 'Another pick is already in the works.') return else: self.pick_lock = True current = await db_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']) 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_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] alt_pick_flag = False # Does the current pick belong to this team? if draft_pick['owner'] != team: 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 # ) 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) ]) if p_query['count'] == 0: raise ValueError(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']) # p_query = await db_get('draftpicks', params=[ # ('season', current['season']), ('overall', x['overall']), ('short_output', False) # ]) # if p_query['count'] == 0: # raise ValueError(f'No pick found for overall #{x["overall"]}') new_pick = x break if new_pick is not None: draft_pick = new_pick else: # 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.') self.pick_lock = False 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()) player = await get_player_by_name(current['season'], player_name) the_pick = await self.draft_player(current, draft_data, draft_pick, player) self.pick_lock = False if the_pick['success']: await ctx.message.add_reaction('✅') if not alt_pick_flag: await self.advance_pick() else: await react_and_reply(ctx, '❌', the_pick['error']) @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) if not team: await react_and_reply(ctx, '❌', 'I don\'t know youuuuuuuuu') return 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']) ]) if l_query['count'] > 0: list_string = 'Current list:\n' for x in l_query['picks']: list_string += f'{x["rank"]}. {x["player"]["name"]}\n' await ctx.send(list_string) else: await ctx.send('I do not have a list for you.') return else: player_list = ' '.join(player_list) player_names = re.split(',', player_list) draft_list = [] spelling = [] errors = [] rank = 0 for x in player_names: rank += 1 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) except Exception as e: logging.error(f'Could not draft {x} for {team["abbrev"]}: {e}') errors.append(x) rank -= 1 else: if player['team']['abbrev'] != 'FA': errors.append(player['name']) rank -= 1 else: draft_list.append({ 'season': current['season'], 'team_id': team['id'], 'rank': rank, 'player_id': player['id'] }) if len(errors) > 0: error_string = 'The following players have already been drafted: ' error_string += ', '.join(errors) await react_and_reply(ctx, '😬', error_string) if len(spelling) > 0: error_string = 'Who the fuck is this: ' error_string += ', '.join(spelling) await react_and_reply(ctx, '❓', error_string) # await post_draft_list(draft_list) await db_post('draftlist', payload={'count': len(draft_list), 'draft_list': draft_list}) await ctx.message.add_reaction('✅') @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') logging.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) @app_commands.command(name='draft-mod', description='Mod commands for draft administration') @app_commands.describe( result_channel='Text Channel: where Major Domo posts draft results', ping_channel='Text Channel: where Major Domo pings for draft picks', current_overall='Integer: override the current pick number', 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' ) 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')) return await interaction.response.defer() current = await db_get('current') draft_data = await db_get('draftdata') 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] 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']) # 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.', embed=await get_player_embed(this_player, current) ) return if pick_lock is not None: if pick_lock: self.pick_lock = True else: self.pick_lock = False params = [] if timer_this_pick is not None: params.append(('pick_deadline', datetime.datetime.now() + datetime.timedelta(minutes=timer_this_pick))) if timer_active is not None: params.append(('timer', timer_active)) if timer_active is True: if timer_this_pick is not None: timer = timer_this_pick elif timer_master is not None: timer = timer_master params.append(('pick_minutes', timer_master)) else: timer = draft_data['pick_minutes'] deadline = datetime.datetime.now() + datetime.timedelta(minutes=timer) else: deadline = datetime.datetime.now() + datetime.timedelta(weeks=1) params.append(('pick_deadline', deadline)) if result_channel is not None: 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: params.append( ('pick_deadline', datetime.datetime.now() + datetime.timedelta(minutes=draft_data['pick_minutes'])) ) if current_overall is not None: params.append(('currentpick', current_overall)) if timer_master is not None: params.append(('pick_minutes', timer_master)) # await patch_draftdata( # currentpick=current_overall, # timer=timer_active, # pick_deadline=pick_deadline, # result_channel=res_channel_id, # ping_channel=ping_channel_id, # pick_minutes=timer_master # ) await db_patch('draftdata', object_id=draft_data['id'], params=params) draft_data = await db_get('draftdata') await interaction.edit_original_response(content=await self.draftdata_to_string(current, draft_data)) if timer_active is True or draft_data['timer']: self.warnings = 0 # 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 #{wipe_pick}') draft_pick = p_query['picks'][0] if draft_pick['player']: await self.advance_pick() 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) # logging.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') player_list = [] this_team = await get_team_by_abbrev(team_abbrev, current['season']) player_names = re.split(',', player_names) keepers = [] keeper_count = 1 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) 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)]) for guy in active_roster['players']: all_players.append(guy) for guy in il_players['players']: all_players.append(guy) 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) 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')] ) # logging.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}') all_moves = [] all_keepers = [] for x in all_players: logging.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') 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 ' f'pick #{draft_pick["overall"]}') await patch_draftpick(draft_pick) await put_player(this_player) # await post_transactions([{ # 'week': -1, # 'player_id': x['id'], # 'oldteam_id': 201, # FA team ID # 'newteam_id': this_team['id'], # 'season': current['season'], # 'moveid': f'keeper-{this_team["abbrev"]}-{keeper_count}' # }]) all_moves.append({ 'week': -1, 'player_id': x['id'], 'oldteam_id': 400, # FA team ID 'newteam_id': this_team['id'], 'season': current['season'], 'moveid': f'keeper-{this_team["abbrev"]}-{keeper_count}' }) all_keepers.append({ 'season': current['season'], 'team_id': this_team['id'], 'player_id': this_player['id'] }) pick_num = draft_pick['overall'] % 16 if pick_num == 0: pick_num = 16 try: await self.send_pick_to_sheets(draft_pick, this_player) except Exception as e: logging.error(f'{e}') keeper_count += 1 else: this_player['team'] = {'id': 400} await put_player(this_player) await db_post('transactions', payload={'count': len(all_moves), 'moves': all_moves}) await db_post('keepers', payload={'count': len(all_keepers), 'keepers': all_keepers}) await ctx.send(f'Posted {len(all_moves)} transactions with {len(all_keepers)} keepers for {this_team["lname"]}') async def setup(bot): await bot.add_cog(Draft(bot))