import copy from helpers import * from db_calls import db_get, db_patch, db_post, patch_player, get_player_by_name, patch_draftpick import csv import math import pygsheets from typing import Optional from discord.ext import commands, tasks from discord import app_commands class Admins(commands.Cog): def __init__(self, bot): self.bot = bot @commands.command(name='current', help='Current db info') @commands.is_owner() async def current_command(self, ctx): current = await db_get('current') current_string = '' for x in current: current_string += f'{x}: {current[x]}\n' await ctx.send(current_string) @commands.command(name='blast', help='Megaphone') @commands.is_owner() async def blast_command(self, ctx, channel_name, *, message): await send_to_channel(self.bot, channel_name, message) await ctx.send(random_conf_gif()) @app_commands.command(name='blast', description='Send a message') @app_commands.guilds(discord.Object(id=os.environ.get('GUILD_ID'))) @app_commands.checks.has_any_role('Da Commish') async def blast_slash( self, interaction: discord.Interaction, channel: discord.TextChannel, msg_content: str = None, embed_title: str = None, embed_field_name: str = None, image_url: str = None, color_hex: str = None): current = await db_get('current') try: embed = None if embed_title: embed = discord.Embed( title=embed_title, color=int(color_hex, 16) if color_hex is not None else int('0xa5fffc', 16) ) embed.set_footer(text=f'SBa Season {current["season"]}', icon_url=LOGO) embed.set_image(url=image_url) if embed_field_name: embed.add_field( name=embed_field_name if embed_field_name is not None else "** **", value=msg_content ) await channel.send(content=None, embed=embed) await interaction.response.send_message(content=random_conf_gif()) return await channel.send(content=msg_content) except Exception as e: logging.error(f'Error blasting a message: {type(e)}: {e}') await interaction.response.send_message(content=f'Uh oh\n\n{type(e)}: {e}') # @commands.command(name='sendstats', help='all, batting, pitching') # @commands.is_owner() # async def send_stats_command(self, ctx, which='all'): # trans_cog = self.bot.get_cog('Transactions') # await trans_cog.send_stats_to_sheets(which=which) @commands.command(name='test', hidden=True) @commands.is_owner() async def test_command(self, ctx, sheet_url: str): # errors = [] # with open('storage/s89-injuries.csv') as csv_file: # csv_reader = csv.reader(csv_file, delimiter=';') # for row in csv_reader: # strat_code = row[0] # inj_rating = row[1] # logging.info(f'strat_code: {strat_code} / inj_rating: {inj_rating}') # p_query = await db_get('players', params=[ # ('season', 8), ('strat_code', strat_code) # ]) # if p_query['count'] == 0: # logging.error(f'Could not find strat_code {strat_code}') # errors.append(f'**{strat_code}** - {inj_rating} not found') # else: # player = p_query['players'][0] # player['injury_rating'] = inj_rating # logging.info(f'patching {player["name"]} ({player["strat_code"]}) with injury {inj_rating}') # await patch_player(player) # Try to get card current = await db_get('current') try: sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') scorecard = sheets.open_by_url(sheet_url) except Exception as e: logging.error(f'Failed to access scorecard {sheet_url}: {e}') await ctx.send(content='Is that sheet public? I can\'t access it.') return await asyncio.sleep(1) setup_tab = scorecard.worksheet_by_title('Setup') g_data = setup_tab.get_values('M2', 'R3') at_abbrev = g_data[0][0] ht_abbrev = g_data[1][0] away_team = await get_team_by_abbrev(at_abbrev, current['season']) home_team = await get_team_by_abbrev(ht_abbrev, current['season']) week_num = g_data[0][5] game_num = g_data[1][5] logging.info(f'gdata: {g_data}\nweek/game: {week_num}/{game_num}') dupe_g_query = await db_get('games', params=[ ('season', current['season']), ('week_start', week_num), ('week_end', week_num), ('away_team_id', away_team['id']), ('home_team_id', home_team['id']), ('game_num', game_num) ]) if dupe_g_query['count'] != 0: await ctx.send(f'This game has already been played! Maybe one day I can automatically wipe it for you.') return g_query = await db_get('games', params=[ ('season', current['season']), ('week_start', week_num), ('week_end', week_num), ('away_team_id', away_team['id']), ('home_team_id', home_team['id']) ]) if g_query['count'] == 0: await ctx.send( f'I don\'t see any games between {away_team["abbrev"]} and {home_team["abbrev"]} in week {week_num}.' ) return this_game = g_query['games'][0] logging.info(f'this_game: {this_game}') playtable = scorecard.worksheet_by_title('Playtable') all_plays = playtable.get_values('B3', 'BG300') logging.info(f'all_plays: {all_plays}') play_keys = [ 'play_num', 'batter_id', 'batter_pos', 'pitcher_id', 'on_base_code', 'inning_half', 'inning_num', 'batting_order', 'starting_outs', 'away_score', 'home_score', 'on_first', 'on_first_final', 'on_second', 'on_second_final', 'on_third', 'on_third_final', 'batter_final', 'pa', 'ab', 'run', 'pitcher_earned_run', 'hit', 'rbi', 'double', 'triple', 'homerun', 'bb', 'so', 'hbp', 'sac', 'ibb', 'gidp', 'bphr', 'bpfo', 'bp1b', 'bplo', 'sb', 'cs', 'outs', 'pitcher_rest_outs', 'wpa', 'catcher_id', 'defender_id', 'runner_id', 'check_pos', 'error', 'wild_pitch', 'passed_ball', 'pick_off', 'balk', 'is_go_ahead', 'is_tied', 'is_new_inning', 'inherited_runners', 'inherited_scored', 'on_hook_for_loss', 'run_differential' ] p_data = [] for line in all_plays: this_data = {'game_id': this_game['id']} for count, x in enumerate(line): if x != '': this_data[play_keys[count]] = x p_data.append(this_data) logging.info(f'p_data: {p_data}') await db_post('plays', payload={'plays': p_data}) await ctx.send(f'go check logs, nerd') # raw_plays = playtable.get_values('B3', 'BG10') # @commands.command(name='sendmoves', help='Send moves to sheets') # @commands.is_owner() # async def send_moves_command(self, ctx): # current = await db_get('current') # await ctx.send('Authenticating with sheets...') # sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') # trans_tab = sheets.open_by_key(SBA_ROSTER_KEY).worksheet_by_title('Transactions') # await ctx.send('Collecting transactions...') # all_vals = [] # all_moves = await get_transactions( # season=current['season'], # timeout=30 # ) # await ctx.send(f'Processing transactions ({len(all_moves)} found)...') # total_moves = len(all_moves) # # counter = 0 # for move in [*all_moves.values()]: # all_vals.insert( # 0, # [ # move['player']['name'], # move['oldteam']['sname'], # move['newteam']['sname'], # move['week'], # total_moves + 416 - counter # ] # ) # counter += 1 # logging.warning(f'all_vals samples:\n0: {all_vals[0]}\n100: {all_vals[100]}\n1000: {all_vals[1000]}\n' # f'2000: {all_vals[2000]}') # # await ctx.send('Sending transactions to sheets...') # try: # trans_tab.update_values( # crange=f'A420', # values=all_vals # ) # await ctx.send('All done!') # except Exception as e: # await ctx.send('Failed sending to sheets') # @commands.command(name='xpick', help='Expansion pick') # @commands.is_owner() # async def expansion_pick_command(self, ctx, team_abbrev, *, name): # current = await db_get('current') # 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_one_player(player_name) # team = await get_one_team(team_abbrev) # old_team = copy.deepcopy(player["team"]) # # if not team: # await ctx.send(f'Who the fuck is **{team_abbrev}**? Get your shit together - it\'s DRAFT TIME!!!') # return # # if old_team['id'] == 99: # await ctx.send(f'Tell that bastard they\'re an idiot. {player["name"]} is a Free Agent.') # return # # await patch_player(player['id'], team_id=team['id']) # await ctx.send(content=None, embed=await get_player_embed(await get_one_player(player['id']), current)) # await send_to_channel( # self.bot, # 's4-draft-picks', # f'Expansion Draft: {await get_emoji(ctx, team["sname"])}{team["sname"]} select **{player["name"]}** from ' # f'{await get_emoji(ctx, old_team["sname"])}{old_team["abbrev"]}' # ) # @commands.command(name='injimport') # @commands.is_owner() # async def injury_import_command(self, ctx): # sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') # inj_tab = sheets.open_by_key('1uKRf7YwTcEfp8D7gUutQRwnOHW37hl6XcBbtqw3PbN4').worksheet_by_title('Sheet1') # raw_data = inj_tab.get_values('A1', 'B545') # # for line in raw_data: # player = await get_one_player(line[0]) # await patch_player(player['id'], pitcher_injury=line[1]) @commands.command(name='setdemweek', help='Set player\'s demotion week') @commands.is_owner() async def set_dem_week_command(self, ctx, week_num, *, player_name): current = await db_get('current') player_cog = self.bot.get_cog('Players') player_name = await fuzzy_player_search(ctx, ctx.channel, self.bot, player_name, player_cog.player_list.keys()) # player = await get_one_player(player_name) p_query = await db_get('players', params=[('season', current['season']), ('name', player_name)]) player = p_query['players'][0] player['demotion_week'] = week_num await patch_player(player) await ctx.send(random_conf_gif()) @app_commands.command(name='set-keepers', description='Post final keepers') @app_commands.guilds(discord.Object(id=os.environ.get('GUILD_ID'))) # @app_commands.checks.has_any_role('Da Commish') async def keeper_slash( self, interaction: discord.Interaction, keeper_1_name: str, keeper_2_name: Optional[str] = None, keeper_3_name: Optional[str] = None, keeper_4_name: Optional[str] = None, keeper_5_name: Optional[str] = None, keeper_6_name: Optional[str] = None, keeper_7_name: Optional[str] = None, team_abbrev: Optional[str] = None): if interaction.channel.name == 'season-9-chat': await interaction.response.send_message(f'everybody laugh at {interaction.user.display_name} for trying ' f'to run keepers here') return await interaction.response.defer() current = await db_get('current') if current['week'] != -1: logging.info('entering the thot check') await interaction.edit_original_response(content='https://c.tenor.com/FCAj8xDvEHwAAAAC/be-gone-thot.gif') player_role = get_role(interaction, SBA_PLAYERS_ROLE_NAME) logging.info('beginning sleep') await asyncio.sleep(random.randint(3, 7)) try: await interaction.user.remove_roles(player_role) except Exception as e: logging.error(f'unable to remove {player_role} role from {interaction.user}: {e}') return owner_team = await get_team_by_owner(current['season'], interaction.user.id) if team_abbrev is not None and interaction.user.id != 258104532423147520 and \ team_abbrev != owner_team['abbrev']: await interaction.edit_original_response( content='Omg you are so quirky and random trying to set another team\'s keepers.') return else: team_abbrev = owner_team['abbrev'] this_team = await get_team_by_abbrev(team_abbrev, current['season']) if this_team is None: await interaction.edit_original_response(content=f'Team {team_abbrev} not found') return def get_pos_nickname(position): if 'B' in position: return 'IF' elif position == 'SS': return 'IF' elif 'F' in position: return 'OF' elif 'P' in position: return 'P' elif position == 'C': return 'C' else: return 'DH' k_query = await db_get('keepers', params=[('team_id', this_team['id'])]) if k_query['count'] > 0: await interaction.edit_original_response(content=random_gif('please go away')) await interaction.channel.send('You\'ve already posted your keepers. I can\'t help you.') return k_list = [] k_ids = [] keeper_string = '' keeper_swar = 0.0 p_query = await db_get('draftpicks', params=[ ('season', current['season']), ('owner_team_id', this_team['id']), ('pick_round_start', 1), ('pick_round_end', 8), ('sort', 'order-asc'), ('short_output', False) ]) picks = p_query['picks'] count = 0 for x in [keeper_1_name, keeper_2_name, keeper_3_name, keeper_4_name, keeper_5_name, keeper_6_name, keeper_7_name]: if x is not None: this_player = await get_player_by_name(current['season'], x) if this_player is None: await interaction.edit_original_response( content='No fuzzy search here can help you. Ya gotta get it right.') return # logging.info(f'keeper_slash - this_player: {this_player}') if this_player['team']['id'] != this_team['id']: await interaction.edit_original_response( content=f'Lol {this_player["name"]}. Oh my god be more I hate you.') return k_ids.append(this_player['id']) k_list.append({ 'season': current['season'], 'team_id': this_team['id'], 'player_id': this_player['id'] }) # logging.info(f'keeper_slash - updated k_list') keeper_string += f'{get_pos_nickname(this_player["pos_1"])} - ' \ f'{this_player["name"]} ({this_player["wara"]:.2f})\n' keeper_swar += this_player['wara'] # logging.info(f'keeper_slash - updated keeper_swar') this_pick = picks[count] this_pick['player'] = this_player # logging.info(f'keeper_slash - patching draftpick') await patch_draftpick(this_pick) count += 1 resp = await db_post('keepers', payload={ 'count': len(k_list), 'keepers': k_list }) output_string = f'{resp}\nMoving remaining players to FA...' await interaction.edit_original_response(content=output_string) fa_team = await get_team_by_abbrev('FA', current['season']) p_query = await db_get('players', params=[ ('season', current['season']), ('team_id', this_team['id']) ]) for x in p_query['players']: if x['id'] not in k_ids: x['team'] = fa_team await patch_player(x) output_string += f'\nNon-kept players have been booted\nBuilding embeds...' await interaction.edit_original_response(content=output_string) embed = get_team_embed(title=f'{this_team["lname"]} Keepers', team=this_team) embed.add_field(name=f'Keepers', value=keeper_string) embed.add_field(name='Total sWAR', value=f'{keeper_swar:.2f}') await send_to_channel(self.bot, 'sba-network-news', content=None, embed=embed) output_string += f'\nJust sent keeper message to sba-network-news' await interaction.edit_original_response(content=output_string) @commands.command(name='migrate-players', help='Migrate players between "same-set" seasons') @commands.has_any_role('Da Commish') async def migrate_players(self, ctx, from_season: int, to_season: int): if to_season - 1 != from_season: await ctx.send(f'The "to_season" ({to_season}) has to be right after the "from_season" ({from_season}).') return p_query = await db_get('players', params=[('season', from_season)]) await ctx.send(f'Pulling players now...') all_players = p_query['players'] t_query = await db_get('teams', params=[('season', to_season), ('active_only', True)]) await ctx.send(f'Pulling teams now...') all_teams = dict([(x["abbrev"], x["id"]) for x in t_query['teams']]) new_players = [] socialism = { "Aaron Bummer": 0.76, "Aaron Hicks": 0.74, "Adam Frazier": 0.31, "Adrian Sampson": 1.09, "Akil Baddoo": 0.28, "Albert Abreu": 0.41, "Albert Almora Jr": 0.44, "Alek Thomas": 0.71, "Alex Young": 1.19, "Alfonso Rivas": 0.37, "Andre Pallante": 0.7, "Andrew McCutchen": 0.4, "Andrew Velazquez": 0.84, "Anthony Bass": 1.29, "Anthony Bender": 0.7, "Anthony Misiewicz": 0.11, "Anthony Rendon": 1.09, "Antonio Senzatela": 0.29, "Aristides Aquino": 1.07, "Austin Gomber": 0.13, "Austin Voth": 0.53, "Bailey Falter": 0.83, "Beau Brieske": 0.46, "Brad Keller": 0.09, "Bradley Zimmer": 0.18, "Brandon Belt": 0.21, "Brandon Lowe": 0.79, "Braxton Garrett": 0.8, "Brayan Bello": 0.38, "Brock Burke": 1.34, "Caleb Smith": 0.08, "Carlos Carrasco": 0.43, "Carson Kelly": 0.53, "Cavan Biggio": 0.62, "Cionel Perez": 1.63, "Cody Morris": 0.91, "Connor Joe": 0.4, "Curt Casali": 1.67, "Dakota Hudson": 0.02, "Dane Dunning": 0.35, "Daniel Castano": 0.15, "Daniel Lynch": 0.25, "Darren ODay": 0.16, "David Fletcher": 1.01, "David Peralta": 0.3, "David Price": 0.58, "David Villar": 1.51, "Dermis Garcia": 0.67, "Devin Smeltzer": 0.69, "Dillon Peters": 0.28, "Domingo German": 0.52, "Dominic Leone": 0.34, "Drew Smith": 0.51, "Edmundo Sosa": 1.55, "Eduardo Rodriguez": 0.06, "Elehuris Montero": 0.11, "Elias Diaz": 0.22, "Emmanuel Rivera": 0.94, "Eric Hosmer": 0.55, "Gabriel Arias": 0.74, "Gabriel Moreno": 2.02, "Garrett Hill": 0.36, "Gary Sanchez": 0.4, "Geraldo Perdomo": 0.29, "German Marquez": 0.53, "Gilberto Celestino": 0.18, "Glenn Otto": 0.2, "Graham Ashcraft": 0.56, "Harrison Bader": 0.74, "Huascar Brazoban": 0.99, "Hunter Brown": 2.39, "Hunter Harvey": 0.85, "Hunter Strickland": 0.05, "Ian Gibaut": 0.28, "Ildemaro Vargas": 1.42, "Jaime Barria": 1.36, "Jake Bird": 0.33, "Jake Cave": 0.71, "Jake Junis": 0.77, "Jake Meyers": 0.65, "Jalen Beeks": 0.61, "James Kaprielian": 0.49, "Jandel Gustave": 0.12, "Jarlin Garcia": 0.32, "Jason Foley": 0.17, "Javier Baez": 0.89, "Jeff Hoffman": 0.83, "Jeimer Candelario": 0.27, "Jesse Chavez": 0.31, "Jharel Cotton": 0.37, "Jimmy Herget": 1.76, "Joel Payamps": 1.04, "Joey Bart": 0.58, "Joey Krehbiel": 0.17, "Joey Wendle": 1.36, "Johan Camargo": 0.25, "John Brebbia": 0.79, "Jonah Bride": 0.11, "Jonathan Hernandez": 0.44, "Jordan Lyles": 0.3, "Jorge Alfaro": 0.61, "Jorge Mateo": 1.34, "Jorge Soler": 0.28, "Jose Cuas": 0.35, "Jose Ruiz": 0.17, "Jose Urena": 0.17, "Jose Urquidy": 0.47, "Josh Donaldson": 0.92, "Josh Rogers": 0.2, "Josh Smith": 0.25, "Josiah Gray": 0.18, "JP Sears": 0.62, "JT Chargois": 0.75, "Jurickson Profar": 0.99, "Justin Bruihl": 0.14, "KeBryan Hayes": 1.61, "Ken Waldichuk": 0.31, "Kendall Graveman": 0.52, "Ketel Marte": 0.56, "Kevin Smith": 0.42, "Kutter Crawford": 0.14, "Kyle Bradish": 0.19, "Kyle Freeland": 0.89, "Kyle Hendricks": 0.32, "Kyle Isbel": 0.15, "Lance McCullers Jr": 1.9, "Louie Varland": 0.83, "Lucas Gilbreath": 0.47, "Lucas Giolito": 0.17, "Lucas Luetge": 0.64, "Luis Barrera": 0.49, "Luis Torrens": 0.13, "Luke Maile": 0.71, "Luke Raley": 0.88, "Luke Voit": 0.29, "MacKenzie Gore": 0.16, "Manuel Rodriguez": 0.49, "Marwin Gonzalez": 0.71, "Matt Foster": 0.15, "Matt Moore": 1.71, "Matt Reynolds": 0.46, "Mauricio Dubon": 0.08, "Max Kepler": 0.99, "Meibrys Viloria": 0.84, "Michael Massey": 0.76, "Michael Rucker": 0.48, "Michael A Taylor": 1.48, "Miguel Andujar": 0.15, "Mike Baumann": 0.16, "Mike Brosseau": 0.65, "Mike Clevinger": 0.28, "Mychal Givens": 0.44, "Nathan Eovaldi": 0.74, "Nelson Cruz": 0.04, "Nick Madrigal": 0.64, "Nick Nelson": 0.1, "Nick Pivetta": 0.78, "Nick Vespi": 0.38, "Nolan Jones": 0.22, "Nomar Mazara": 0.25, "Odubel Herrera": 0.22, "Oswaldo Cabrera": 2.33, "Owen Miller": 0.13, "Paolo Espino": 0.24, "Paul Blackburn": 0.68, "Paul DeJong": 0.26, "Pavin Smith": 0.31, "Rafael Ortega": 0.17, "Raimel Tapia": 0.14, "Ralph Garza": 0.46, "Rich Hill": 0.39, "Richard Bleier": 0.4, "Roberto Perez": 1.82, "Robinson Chirinos": 0.1, "Rodolfo Castro": 1.06, "Ross Detwiler": 0.51, "Ryan Feltner": 0.05, "Ryan Jeffers": 0.8, "Ryan Kreidler": 1, "Ryan Mountcastle": 0.45, "Sam Hilliard": 0.42, "Sam Long": 0.08, "Seth Lugo": 0.36, "Shane Baz": 0.2, "Shawn Armstrong": 0.11, "Spenser Watkins": 0.05, "Stuart Fairchild": 1.15, "Tanner Rainey": 0.22, "Taylor Clarke": 0.41, "Taylor Walls": 1.13, "Tim Mayza": 0.41, "Tomas Nido": 0.2, "Tommy Edman": 2.14, "Tommy Nance": 0.23, "Tommy Pham": 0.14, "Tony Kemp": 0.41, "Trent Grisham": 1.04, "Trevor Larnach": 1.52, "Trevor Williams": 0.85, "Trey Mancini": 0.5, "Tucker Barnhart": 0.07, "Tyler Heineman": 0.24, "Tyler Kinley": 1.54, "Tyler ONeill": 0.71, "Victor Caratini": 0.4, "Victor Reyes": 0.06, "Will Vest": 0.05, "Willi Castro": 0.64, "Yadiel Hernandez": 0.26, "Yu Chang": 0.33, "Zach Davies": 0.28, "Zach McKinstry": 0.68, "Zack Greinke": 1.03, "Zack Littell": 0.12 } for x in all_players: this_new = copy.deepcopy(x) this_new['season'] = to_season del this_new['il_return'], this_new['demotion_week'] if x['name'] in socialism: this_new['wara'] = socialism[x["name"]] new_team_abbrev = x['team']['abbrev'] if new_team_abbrev[-3:] == 'MiL': new_team_abbrev = new_team_abbrev[:-3] elif new_team_abbrev[-2:] == 'IL': new_team_abbrev = new_team_abbrev[:-2] this_new['team_id'] = all_teams[new_team_abbrev] new_players.append(this_new) await db_post('players', payload={'players': new_players}, timeout=20) await ctx.send(random_gif('all done boss')) async def setup(bot): await bot.add_cog(Admins(bot))