import copy import math import discord import pydantic import re from discord import app_commands from discord.ext import tasks from discord.app_commands import Choice from helpers import * from db_calls import db_get, db_patch, get_team_by_abbrev, get_team_by_owner, patch_player, get_player_by_name, db_post, \ db_delete from typing import Literal, Optional class BatStat(pydantic.BaseModel): player_id: int team_id: int pos: str pa: int = 0 ab: int = 0 run: int = 0 hit: int = 0 rbi: int = 0 double: int = 0 triple: int = 0 hr: int = 0 bb: int = 0 so: int = 0 hbp: int = 0 sac: int = 0 ibb: int = 0 gidp: int = 0 sb: int = 0 cs: int = 0 bphr: int = 0 bpfo: int = 0 bp1b: int = 0 bplo: int = 0 xba: int = 0 xbt: int = 0 xch: int = 0 xhit: int = 0 error: int = 0 pb: int = 0 sbc: int = 0 csc: int = 0 roba: int = 0 robs: int = 0 raa: int = 0 rto: int = 0 week: int game: int season: int class PitStat(pydantic.BaseModel): player_id: int team_id: int ip: float = 0.0 hit: int = 0 run: int = 0 erun: int = 0 so: int = 0 bb: int = 0 hbp: int = 0 wp: int = 0 balk: int = 0 hr: int = 0 gs: int = 0 win: int = 0 loss: int = 0 hold: int = 0 sv: int = 0 bsv: int = 0 ir: int = 0 irs: int = 0 week: int game: int season: int class Players(commands.Cog): def __init__(self, bot): self.bot = bot self.player_list = {} self.scorecards = {} self.voice_channels = [] self.build_master_player_list.start() self.live_scorecard_loop.start() # async def cog_command_error(self, ctx, error): # await ctx.send(f'{error}\n\nRun !help to see the command requirements') # async def slash_error(self, ctx, error): # await ctx.send(f'{error}') # @commands.Cog.listener() # async def on_app_command_error(self, interaction, error): # command = interaction.app_command # ctx = interaction.context # # await ctx.send(f"An error occurred while executing the {command} command: {error}") async def get_dice_embed(self, channel, title, message): team = None try: current = await db_get('current') team_abbrev = re.split('-', channel.name) if len(team_abbrev[0]) <= 4 and team_abbrev not in ['the', 'city']: tquery = await db_get('teams', params=[('season', current['season']), ('team_abbrev', team_abbrev[0])]) if tquery['count'] > 0: team = tquery['teams'][0] except (ValueError, AttributeError, requests.ReadTimeout) as e: logging.info(f'{type(e)}: {e}') if team is not None: embed = discord.Embed( color=int(team["dice_color"], 16) if team["dice_color"] else int(team["color"], 16) ) else: embed = discord.Embed( color=int('0x000000', 16) ) if title and message: embed.add_field(name=title, value=message) return embed @tasks.loop(count=1) async def build_master_player_list(self): guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: logging.error(f'build_master_player_list - could not pull guild / retrying in 15 seconds') await asyncio.sleep(15) guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) logging.info(f'build_master_player_list - guild: {guild}') logging.info(f'build_master_player_list - getting current') current = await db_get('current') logging.info(f'build_master_player_list - getting all_players') p_query = await db_get('players', timeout=8, params=[('season', current['season'])]) logging.info(f'build_master_player_list - building player_list') self.player_list = {x['name'].lower(): x['id'] for x in p_query['players']} logging.info(f'player list count: {len(self.player_list)}') logging.debug(f'player list: {self.player_list}') @tasks.loop(minutes=3) async def live_scorecard_loop(self): guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) if not guild: logging.error(f'live_scorecard_loop - could not pull guild / retrying in 15 seconds') await asyncio.sleep(15) guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) logging.info(f'live_scorecard_loop - guild: {guild}') score_channel = discord.utils.get(guild.text_channels, name='live-sba-scores') player_role = get_role(score_channel, SBA_PLAYERS_ROLE_NAME, bot=self.bot) try: if len(self.voice_channels) > 0: game_strings = [] for x in self.scorecards.values(): await asyncio.sleep(1) this_string = x.get_value('A1') if ' F' not in this_string: game_strings.append(this_string) if len(game_strings) > 0: # Clear old messages async for message in score_channel.history(limit=25): await message.delete() embed = get_team_embed('SBa Scoreboard') embed.add_field(name='Live Games', value="\n\n".join(game_strings)) embed.set_footer( text=f'SBa Season {SBA_SEASON}', icon_url=LOGO ) await score_channel.set_permissions(player_role, read_messages=True) await score_channel.send(content=None, embed=embed) return self.scorecards = {} await score_channel.set_permissions(player_role, read_messages=False) except Exception as e: await send_to_channel(self.bot, 'commissioners-office', f'Could not update live scorecard:\n\n{e}') logging.error(f'Could not update live scorecard: {e}') @staticmethod async def update_injuries(ctx): current = await db_get('current') injury_log = discord.utils.get(ctx.guild.text_channels, name='injury-log') # Build new messages # inj_by_team = {'Black Bears': [Player Objs], 'Questants': [Player Objs]} # inj_by_week = {'Week 1': [Player Objs], 'Week 2': [Player Objs]} inj_team = {} inj_week = {} i_query = await db_get('injuries', params=[ ('season', current['season']), ('is_active', True), ('sort', 'return-asc') ]) for x in i_query['injuries']: player = x['player'] this_team = await get_major_team(player['team']) if this_team['sname'] not in inj_team.keys(): inj_team[this_team['sname']] = [player] else: inj_team[this_team['sname']].append(player) if f'Week {x["end_week"]}' not in inj_week.keys(): inj_week[f'Week {x["end_week"]}'] = [player] else: inj_week[f'Week {x["end_week"]}'].append(player) team_embed = discord.Embed(title='Current Injuries by Team') team_embed.description = 'Player Name (Return Date)' team_embed.set_thumbnail(url=LOGO) # for team in inj_by_team: for team in inj_team: team_string = '' for player in inj_team[team]: team_string += f'{player["name"]} ({player["il_return"]})\n' team_embed.add_field(name=team, value=team_string) week_embed = discord.Embed(title='Current Injuries by Return Week') week_embed.description = 'Player Name (Return Date)' week_embed.set_thumbnail(url=LOGO) # for week in inj_by_week: for week in inj_week: week_string = '' for player in inj_week[week]: week_string += f'{player["name"]} ({player["il_return"]})\n' week_embed.add_field(name=week, value=week_string) # Clear old messages async for message in injury_log.history(limit=25): await message.delete() # Send new messages await injury_log.send(content=None, embed=team_embed) await injury_log.send(content=None, embed=week_embed) @staticmethod def team_stan_line(stan, s_type: str = 'div'): if stan["wins"] + stan["losses"] == 0: winpct = f'{0:.3f}' else: winpct = f'{stan["wins"] / (stan["wins"] + stan["losses"]):.3f}' team_string = f'{stan["team"]["abbrev"]: <4} {stan["wins"]: >2}-{stan["losses"]: <2} {winpct} ' if s_type == 'div': if stan["div_gb"] is None: gb = '--' else: gb = stan["div_gb"] team_string += f'{gb: >5}' if stan["div_e_num"] is None: team_string += f' -- ' else: e_num = stan["div_e_num"] if stan["div_e_num"] > 0 else 'E' team_string += f' {e_num: >2} ' else: if stan["wc_gb"] is None: # This is a division leader - return nothing and continue return '' else: gb = stan["wc_gb"] if stan["wc_gb"] >= 0.0 else f'--' if stan["wc_e_num"]: e_num = stan["wc_e_num"] elif stan["wc_e_num"] == 0: e_num = 'E' else: e_num = '--' team_string += f'{gb: >4} {e_num: >2} ' team_string += f'{stan["run_diff"]: >4}\n' return team_string @staticmethod async def game_progress(current): # s_query = await db_get('schedules', params=[ # ('season', current['season']), ('week_start', current['week']), ('week_end', current['week']) # ]) # r_query = await db_get('results', params=[ # ('season', current['season']), ('week_start', current['week']), ('week_end', current['week']) # ]) gp_query = await db_get('games', params=[ ('season', current['season']), ('week', current['week']), ('played', True), ('short_output', True) ]) all_query = await db_get('games', params=[ ('season', current['season']), ('week', current['week']), ('short_output', True) ]) return {'games_played': gp_query['count'], 'game_count': all_query['count']} @commands.Cog.listener(name='on_message') async def on_message_listener(self, message): # if 'bad man' in message.content: # await message.channel.send( # 'https://cdn.discordapp.com/attachments/619600872782954539/682411826335711268/image0.jpg' # ) if message.author.bot or isinstance(message.channel, discord.DMChannel): return tm = message.content.lower() if tm in ['shut up, jack', 'shut up jack']: await message.channel.send('Shut up, Jack') return # elif message.content[-3:] == '...': # await message.channel.send('https://media.tenor.com/images/423f15eef7688d3010c4d83a16902574/tenor.gif') # return elif 'DELIBERAT' in message.content: await message.channel.send('https://tenor.com/view/fbi-swat-jelleton-gif-14190942') elif 'domo sux' in tm or 'domo sucks' in tm or 'fuck domo' in tm or 'fuck you domo' in tm: await message.add_reaction('🖕') elif 'joe momma' in tm or 'joe mama' in tm: await message.channel.send('https://tenor.com/view/shaq-big-dunk-basketball-chris-dudley-shaquille-' 'o-neal-gif-13864249') elif 'i\'m dad' in tm or 'im dad' in tm: await message.channel.send( 'https://tenor.com/view/dad-jokes-aht-aht-dad-jokes-aht-aht-ha-ha-ha-knee-slapper-gif-26152690' ) # elif 'fifa' in tm or 'soccer' in tm or 'world cup' in tm or 'the wc' in tm or 'this wc' in tm or 'futbol' in tm: # randint = random.randint(1, 5) # if randint == 5: # await message.channel.send(f'||{message.content}\n{message.author.name}, apparently||\n\n' # f'Ugh, I can\'t with this soccer talk.') # await message.delete() # else: # await message.channel.send(random_soccer()) if message.channel.name in ['trade-block', 'jacks-trading-post']: count = 0 async for x in message.channel.history(): if x.author.id == message.author.id and x.id != message.id: count += 1 await x.delete() if count > 1: await message.author.send(f'I have deleted your previous {count} trade-block messages to ' f'keep it clean.') elif count == 1: await message.author.send('I deleted your last trade-block message to help keep it clean.') # if len(message.content) == 1 and not message.content.isnumeric() and message.content.lower() != 'k': # logging.info( # f'Found spam from **{message.author.nick}** in **{message.channel.name}**: {message.content}' # ) # if 'shitpost' not in message.channel.name and 'sbb' not in message.channel.name: # await send_to_channel( # self.bot, # 'commissioners-office', # f'Just deleted this message from **{message.author.nick}** in **{message.channel.name}**:' # f'\n\n{message.content}' # ) # await message.delete() # await message.author.send( # f'Hi there. I just deleted your \'{message.content}\' message from #{message.channel.name}. I am ' # f'told to delete 1-character messages due to spam.' # ) # @staticmethod # def get_standings_embed(current, progress, al_standings, nl_standings): # embed = discord.Embed(title=f'Season {current["season"]} | Week {current["week"]} | ' # f'{progress["games_played"]}/{progress["game_count"]} games played', # color=0xB70000) # embed.add_field(name=f'**Full Standings**', value=SBA_STANDINGS_URL, inline=False) # embed.add_field(name=f'**American League**', value=al_standings, inline=False) # embed.add_field(name=f'**National League**', value=nl_standings, inline=False) # # return embed @commands.command(name='team', aliases=['roster', 'myboys', 'mybois'], help='Get team overview') async def team_command(self, ctx, team_abbrev: str = None): current = await db_get('current') # Get Team if team_abbrev is not None: team = await get_team_by_abbrev(team_abbrev, current['season']) else: team = await get_team_by_owner(season=current['season'], owner_id=ctx.author.id) # Create team embed embed = get_team_embed(f'{team["lname"]} Overview', team) # Get standings if team['abbrev'][-2:].lower() != 'il': try: s_query = await db_get(f'standings/team/{team["id"]}') if s_query is not None: team_standings = s_query overview_string = f'Record: {team_standings["wins"]}-{team_standings["losses"]} ' \ f'({team_standings["run_diff"]} RD)\n' \ f'Pythag Record: {team_standings["pythag_wins"]}-{team_standings["pythag_losses"]}\n' division_string = '' if team_standings['div_gb']: division_string += f'{team_standings["div_gb"]} GB in ' \ f'{team_standings["team"]["division"]["league_abbrev"]} ' \ f'{team_standings["team"]["division"]["division_name"]} / ' \ f'{team_standings["wc_gb"]} GB in ' \ f'{team_standings["team"]["division"]["league_abbrev"]} WC\n' else: division_string += f'1st in {team_standings["team"]["division"]["league_abbrev"]} ' \ f'{team_standings["team"]["division"]["division_name"]}\n' overview_string += division_string overview_string += f'Last 8: ({team_standings["last8_wins"]}-{team_standings["last8_losses"]}) / ' \ f'Streak: {team_standings["streak_wl"].upper()}{team_standings["streak_num"]}' embed.add_field(name=f'{team["sname"]} Overview', value=overview_string, inline=False) except (ValueError, TypeError) as e: logging.info(f'Could not pull standings for season {team["season"]} {team["abbrev"]}') # Get player info il_players = None if team['abbrev'][-2:].lower() != 'il': il_team = await get_team_by_abbrev(team['abbrev'], current['season']) p_query = await db_get('players', params=[ ('season', current['season']), ('team_id', il_team['id']), ('sort', 'cost-desc') ]) il_players = p_query['players'] p_query = await db_get('players', params=[ ('season', current['season']), ('team_id', team['id']), ('sort', 'cost-desc') ]) players = p_query['players'] il_wara = 0 active_wara = 0 if il_players: for x in il_players: il_wara += x['wara'] if players: count = 0 top_player_string = '' for x in players: if count < 5: top_player_string += f'{x["pos_1"]} {x["name"]} ({x["wara"]:.2f})\n' active_wara += x['wara'] count += 1 embed.add_field(name='Core Players', value=top_player_string) embed.add_field(name='Total sWAR', value=f'{active_wara:.2f}') if il_wara > 0: embed.add_field(name='Injured sWAR', value=f'{il_wara:.2f}') s_query = await db_get('schedules', params=[ ('season', current['season']), ('team_abbrev', team['abbrev']), ('week_start', current['week']), ('week_end', current['week']+2 if current['week']+2 > 0 else 2), ('short_output', False) ]) if s_query['count'] > 0: team_schedule = s_query['schedules'] this_week_string = '' upcoming_string = '' full_sched = sorted(team_schedule, key=lambda y: y['id']) logging.info(f'full_sched: {full_sched}') for matchup in full_sched: st_abbrev = matchup['awayteam']['abbrev'] if matchup['hometeam'] == team: st_abbrev = matchup['awayteam']['abbrev'] r_query = await db_get('standings', params=[('season', current['season']), ('team_abbrev', st_abbrev)]) opp_record = None if r_query['count'] == 0 else r_query['standings'][0] if matchup['week'] == current['week']: if matchup['hometeam'] == team: this_week_string += f'Week {current["week"]}: vs ' \ f'{matchup["awayteam"]["lname"]} ' \ f'({opp_record["wins"]}-{opp_record["losses"]})\n' else: this_week_string += f'Week {current["week"]}: @ {matchup["hometeam"]["lname"]} ' \ f'({opp_record["wins"]}-{opp_record["losses"]})\n' else: if matchup['hometeam'] == team: upcoming_string += f'Week {matchup["week"]}: vs ' \ f'{matchup["awayteam"]["lname"]} ' \ f'({opp_record["wins"]}-{opp_record["losses"]})\n' else: upcoming_string += f'Week {matchup["week"]}: @ ' \ f'{matchup["hometeam"]["lname"]} ' \ f'({opp_record["wins"]}-{opp_record["losses"]})\n' if len(this_week_string) > 0: embed.add_field(name='This Week', value=this_week_string, inline=False) if len(upcoming_string) > 0: embed.add_field(name='Upcoming Schedule', value=upcoming_string, inline=False) # Add roster link embed.add_field( name=f'{team["abbrev"]} Roster Page', value=f'https://sba.manticorum.com/teams/{current["season"]}/{team["abbrev"]}', inline=False ) await ctx.send(content=None, embed=embed) @commands.command(name='player', aliases=['card'], help='Get player overview') async def player_command(self, ctx, *, name): current = await db_get('current') season = current['season'] # if 'strider' in name.lower(): # await ctx.send(f'Ope. Strider has been reserved for Cal.') name_reg = re.compile(r'(s\d+)* *(.*)', re.IGNORECASE) player_search = name_reg.search(name) logging.info(f'player_search: {player_search}') logging.info(f'player_search.group(): {player_search.group()} / group(1): {player_search.group(1)} ' f'/ group(2): {player_search.group(2)}') # No season is included if not player_search.group(1): p_name = await fuzzy_player_search(ctx, ctx.channel, self.bot, name, self.player_list.keys()) player = await db_get('players', object_id=self.player_list[p_name]) # Season is included else: season = int(player_search.group(1)[1:]) p_query = await db_get('players', params=[('season', season), ('name', player_search.group(2))]) if p_query['count'] == 0: async with ctx.typing(): p_query = await db_get('players', params=[('season', season), ('short_output', True)]) if p_query['count'] == 0: await ctx.send(f'I did not find any players in season {season}') return p_name = await fuzzy_player_search( ctx, ctx.channel, self.bot, player_search.group(2).strip(), [x['name'].lower() for x in p_query['players']] ) p_query2 = await db_get('players', params=[('season', season), ('name', p_name)]) player = p_query2['players'][0] async with ctx.typing(): embeds = [await get_player_embed(player, current, ctx, season)] if player['image2']: embed = get_team_embed(f'{player["name"]}', player["team"], thumbnail=False) embed.set_image(url=player['image2']) embeds.append(embed) await ctx.send(content=None, embeds=embeds) @commands.command(name='career', help='Get player\'s career stats') async def career_command(self, ctx, *, name): await ctx.send(f'That mother fucker Cal hasn\'t updated this command for the new API.') await ctx.send(random_gif('god dammit')) return # Get BattingCareer b = await get_battingcareer(name) # Get PitchingCareer p = await get_pitchingcareer(name) if not b and not p: await ctx.send('Who? Please splel berter') return player = { 'name': b['name'] if b else p['name'], } # Build custom embed embed = get_team_embed(f'{player["name"]} Career Stats') embed.color = int('0xa6ce39', 16) player_photo = await get_player_headshot(b['name']) if player_photo: embed.set_thumbnail(url=player_photo) player_pages = f'[SBa]({get_player_url(player)}) / ' \ f'[BBRef]({get_player_url(player, "bbref")})' embed.add_field(name='Player Page', value=player_pages) batting_string = None pitching_string = None if b: if b['ab'] > 0: singles = b['hit'] - b['hr'] - b['triple'] - b['double'] avg = b['hit'] / b['ab'] obp = (b['hit'] + b['bb'] + b['ibb'] + b['hbp']) / b['pa'] slg = ((b['hr'] * 4) + (b['triple'] * 3) + (b['double'] * 2) + singles) / b['ab'] ops = obp + slg woba = ((b['bb'] * .69) + (b['hbp'] * .72) + (singles * .89) + (b['double'] * 1.27) + (b['triple'] * 1.62) + (b['hr'] * 2.1)) / (b['pa'] - b['hbp'] - b['sac']) ab = f'{b["ab"]:.0f}' run = f'{b["run"]:.0f}' hit = f'{b["hit"]:.0f}' double = f'{b["double"]:.0f}' triple = f'{b["triple"]:.0f}' hr = f'{b["hr"]:.0f}' rbi = f'{b["rbi"]:.0f}' sb = f'{b["sb"]:.0f}' cs = f'{b["cs"]:.0f}' so = f'{b["so"]:.0f}' batting_string = f'```\n' \ f' AVG OBP SLG OPS\n' \ f' {avg:.3f} {obp:.3f} {slg:.3f} {ops:.3f}\n``````\n' \ f' AB R H HR RBI SB\n' \ f'{ab: ^4} {run: ^3} {hit: ^3} {hr: >3} {rbi: >3} ' \ f'{sb: >3}\n```' if p: if p['ip'] > 0: win = f'{p["win"]:.0f}' loss = f'{p["loss"]:.0f}' save = f'{p["sv"]:.0f}' era = f'{(p["erun"] * 9) / p["ip"]:.2f}' game = f'{p["game"]:.0f}' gs = f'{p["gs"]:.0f}' ip = f'{p["ip"]:.0f}' if p["ip"] % 1 == 0: ip += '.0' elif str(p["ip"] % 1)[2] == '3': ip += '.1' else: ip += '.2' so = f'{p["so"]:.0f}' whip = f'{(p["bb"] + p["hit"]) / p["ip"]:.2f}' pitching_string = f'```\n' \ f' W-L SV ERA IP SO WHIP\n' \ f'{win: >2}-{loss: <2} {save: >2} {era: >5} {ip: ^5} ' \ f'{so: ^4} {whip: >4}\n```' if batting_string and pitching_string: if b['ab'] > p['ip']: embed.add_field(name='Batting Stats', value=batting_string, inline=False) else: embed.add_field(name='Pitching Stats', value=pitching_string, inline=False) elif batting_string: embed.add_field(name='Batting Stats', value=batting_string, inline=False) elif pitching_string: embed.add_field(name='Pitching Stats', value=pitching_string, inline=False) await ctx.send(content=None, embed=embed) @commands.command(name='schedule', help='This week and next') async def schedule_command(self, ctx, week: Optional[int] = None): current = await db_get('current') if week is not None: schedule_week = week elif current['week'] < 1: schedule_week = 1 else: schedule_week = current['week'] g1_query = await db_get('games', params=[ ('season', current['season']), ('week_start', schedule_week), ('week_end', schedule_week) ]) g2_query = await db_get('games', params=[ ('season', current['season']), ('week_start', schedule_week + 1), ('week_end', schedule_week + 1) ]) games_played = 0 games_wk1, games_wk2 = {}, {} for x in g1_query['games']: if x['away_score'] is not None: games_played += 1 game_id = f'{x["away_team"]["id"]}-{x["home_team"]["id"]}' if game_id not in games_wk1: games_wk1[game_id] = { 'away_wins': 0, 'home_wins': 0, 'away_team': x["away_team"], 'home_team': x["home_team"] } if x['away_score'] is not None: if x['away_score'] > x['home_score']: games_wk1[game_id]['away_wins'] += 1 else: games_wk1[game_id]['home_wins'] += 1 for x in g2_query['games']: game_id = f'{x["away_team"]["id"]}-{x["home_team"]["id"]}' if game_id not in games_wk2: games_wk2[game_id] = { 'away_wins': 0, 'home_wins': 0, 'away_team': x["away_team"], 'home_team': x["home_team"] } embed = get_team_embed(f'Season {current["season"]} | Week {schedule_week} | ' f'{games_played}/{g1_query["count"]} games played') embed.add_field(name='Full Schedule', value=SBA_SCHEDULE_URL, inline=False) string_this_week_0 = '' string_this_week_1 = '' count = 0 for x in games_wk1.values(): this_line = f'`({x["away_wins"]}) {x["away_team"]["abbrev"]: >4}` ' \ f'{await team_emoji(ctx, x["away_team"])} @ ' \ f'{await team_emoji(ctx, x["home_team"])} ' \ f'`{x["home_team"]["abbrev"]: <4} ({x["home_wins"]})`\n' if count > 7: string_this_week_1 += this_line else: string_this_week_0 += this_line count += 1 string_next_week_0 = '' string_next_week_1 = '' count = 0 for x in games_wk2.values(): this_line = f'`{x["away_team"]["abbrev"]: >4}` {await team_emoji(ctx, x["away_team"])} @ ' \ f'{await team_emoji(ctx, x["home_team"])} `{x["home_team"]["abbrev"]: <4}`\n' if count > 7: string_next_week_1 += this_line else: string_next_week_0 += this_line count += 1 if len(string_this_week_0) > 0: embed.add_field( name=f'**Week {schedule_week} Games:**', value=string_this_week_0, inline=False ) await ctx.send(content=None, embed=embed) if len(string_this_week_1) > 0: if len(embed.fields) > 1: embed.remove_field(0) embed.set_field_at( index=0, name=f'**Week {schedule_week} Part 2:**', value=string_this_week_1, inline=False ) await ctx.send(content=None, embed=embed) if len(string_next_week_0) > 0: if len(embed.fields) > 1: embed.remove_field(0) embed.set_field_at( index=0, name=f'**Week {schedule_week + 1} Games:**', value=string_next_week_0, inline=False ) embed.title = f'Season {current["season"]} | Week {schedule_week + 1}' await ctx.send(content=None, embed=embed) if len(string_next_week_1) > 0: if len(embed.fields) > 1: embed.remove_field(0) embed.set_field_at( index=0, name=f'**Week {schedule_week + 1} Part 2:**', value=string_next_week_1, inline=False ) await ctx.send(content=None, embed=embed) @commands.command(name='weather', help='Roll ballpark weather') async def weather_command(self, ctx, team_abbrev=None): current = await db_get('current') if team_abbrev is not None: t_query = await db_get('teams', params=[('season', current['season']), ('team_abbrev', team_abbrev)]) else: t_query = await db_get('teams', params=[ ('season', current['season']), ('team_abbrev', ctx.channel.name.split('-')[0]) ]) if t_query['count'] == 0: t_query = await db_get('teams', params=[('season', current['season']), ('owner_id', ctx.author.id)]) if t_query['count'] == 0: await ctx.send(f'I could not find a weather chart for you.') team = t_query['teams'][0] d_twenty = random.randint(1, 20) embed = get_team_embed('Weather Chart', team, thumbnail=False) embed.set_image(url=team['stadium']) embed.add_field(name=f'Weather roll for {ctx.author.name}', value=f'```md\n# {d_twenty}\nDetails:[1d20 ({d_twenty})]\n```') await ctx.send(content=None, embed=embed) async def get_division_standings(self, current) -> discord.Embed: d1_query = await db_get('standings', params=[ ('season', current['season']), ('division_abbrev', 'FD') ]) div_one = d1_query['standings'] d2_query = await db_get('standings', params=[ ('season', current['season']), ('division_abbrev', 'NLW') ]) div_two = d2_query['standings'] d3_query = await db_get('standings', params=[ ('season', current['season']), ('division_abbrev', 'IWGP') ]) div_three = d3_query['standings'] d4_query = await db_get('standings', params=[ ('season', current['season']), ('division_abbrev', 'BAL') ]) div_four = d4_query['standings'] div_one_standings = f'```\nTeam W-L PCT GB E# RD\n' for team in div_one: div_one_standings += self.team_stan_line(team) div_one_standings += f'\n```' div_two_standings = f'```\nTeam W-L PCT GB E# RD\n' for team in div_two: div_two_standings += self.team_stan_line(team) div_two_standings += f'\n```' div_three_standings = f'```\nTeam W-L PCT GB E# RD\n' for team in div_three: div_three_standings += self.team_stan_line(team) div_three_standings += f'\n```' div_four_standings = f'```\nTeam W-L PCT GB E# RD\n' for team in div_four: div_four_standings += self.team_stan_line(team) div_four_standings += f'\n```' progress = await self.game_progress(current) embed = discord.Embed(title=f'Season {current["season"]} | Week {current["week"]} | ' f'{progress["games_played"]}/{progress["game_count"]} games played', color=0xB70000) embed.add_field(name=f'**Full Standings**', value=SBA_STANDINGS_URL, inline=False) embed.add_field(name=f'**Fun Diff**', value=div_one_standings, inline=False) embed.add_field(name=f'**NL West**', value=div_two_standings, inline=False) embed.add_field(name=f'**IWGP**', value=div_three_standings, inline=False) embed.add_field(name=f'**Crabbers**', value=div_four_standings, inline=False) return embed async def get_wildcard_standings(self, current) -> discord.Embed: a_query = await db_get('standings', params=[ ('season', current['season']), ('league_abbrev', 'SBa') ]) al_teams = a_query['standings'] # n_query = await db_get('standings', params=[ # ('season', current['season']), ('league_abbrev', 'nl') # ]) # nl_teams = n_query['standings'] al_wildcard = f'```\nTeam W-L PCT GB E# RD\n' for team in al_teams: al_wildcard += self.team_stan_line(team, s_type='wc') al_wildcard += '```' # nl_wildcard = f'```\nTeam W-L PCT GB E# RD\n' # for team in nl_teams: # nl_wildcard += self.team_stan_line(team, s_type='wc') # nl_wildcard += '```' progress = await self.game_progress(current) embed = discord.Embed(title=f'Season {current["season"]} | Week {current["week"]} | ' f'{progress["games_played"]}/{progress["game_count"]} games played', color=0xB70000) embed.add_field(name=f'**Full Standings**', value=SBA_STANDINGS_URL, inline=False) embed.add_field(name=f'**AL Wildcard**', value=al_wildcard, inline=False) # embed.add_field(name=f'**NL Wildcard**', value=nl_wildcard, inline=False) return embed async def standings_button_loop(self, ctx, start: Literal['division', 'wildcard']): async with ctx.typing(): current = await db_get('current') div_embed = await self.get_division_standings(current) wc_embed = await self.get_wildcard_standings(current) logging.info(f'div_embed: {div_embed}\nwc_embed: {wc_embed}') view = Pagination(responders=[ctx.author], timeout=15) view.left_button.label = 'Division' view.right_button.label = 'Wildcard' if start == 'division': embed = div_embed view.left_button.disabled = True else: embed = wc_embed view.right_button.disabled = True st_message = await ctx.send(content=None, embed=embed, view=view) while True: await view.wait() if view.value: logging.info(f'standings_button_loop - view.value: {view.value}') if view.value == 'cancel': await st_message.edit(view=None) return elif view.value == 'left': start = 'division' elif view.value == 'right': start = 'wildcard' else: await st_message.edit(view=None) return view = Pagination(responders=[ctx.author], timeout=15) view.left_button.label = 'Division' view.right_button.label = 'Wildcard' if start == 'division': embed = div_embed view.left_button.disabled = True else: embed = wc_embed view.right_button.disabled = True logging.info(f'standings_button_loop - start: {start} / embed == div_embed? {embed == div_embed} / ' f'embed == wc_embed {embed == wc_embed}') await st_message.delete() st_message = await ctx.send(content=None, embed=embed, view=view) @commands.command(name='standings', help='Current standings') async def standings_command(self, ctx): await self.standings_button_loop(ctx, 'division') @commands.command(name='wildcard', aliases=['wc'], help='Current wildcard') async def wildcard_command(self, ctx): await self.standings_button_loop(ctx, 'wildcard') @app_commands.command(name='setinjury', description='Set the return date for injured player') @app_commands.guilds(discord.Object(id=os.environ.get('GUILD_ID'))) @app_commands.describe( player_name='Name of injured player', this_week='The current SBa week', this_game='The game number in which the player got injured', inj_games='The number of games the player will miss' ) @app_commands.checks.has_any_role(SBA_PLAYERS_ROLE_NAME) async def set_injury_slash( self, interaction: discord.Interaction, player_name: str, this_week: int, this_game: int, inj_games: int): await interaction.response.defer() current = await db_get('current') p_query = await db_get('players', params=[('name', player_name), ('season', current['season'])]) if p_query['count'] == 0: await interaction.edit_original_response(content=f'I did not find anybody named **{player_name}**.') return player = p_query['players'][0] # Check if player is on owner's team team = await get_team_by_owner(current['season'], interaction.user.id) if not player['team'] == team and not player['team']['abbrev'][:len(team['abbrev'])] == team['abbrev']: await interaction.edit_original_response( content=f'Is this some kind of tom foolery? {player["name"]} is on {player["team"]["abbrev"]} aka ' f'not your team. I\'m watching you.' ) return i_query = await db_get('injuries', params=[('player_id', player['id']), ('is_active', True)]) if i_query['count'] > 0: await interaction.edit_original_response(content=f'Hm. It looks like {player["name"]} is already hurt.') return out_weeks = math.floor(inj_games / 4) out_games = inj_games % 4 return_week = this_week + out_weeks return_game = this_game + 1 + out_games if this_game + 1 + out_games > 4: return_week += 1 return_game -= 4 return_date = f'w{return_week:>02}g{return_game:>02}' player['il_return'] = return_date if await patch_player(player): embed = get_team_embed(f'Injury Update', team=team) embed.add_field( name=f'{player["name"]}', value=f'{team["sname"]} {player["pos_1"]} {player["name"]} is injured until {return_date}' ) await db_post('injuries', payload={ 'season': current['season'], 'player_id': player['id'], 'total_games': inj_games, 'start_week': this_week if this_game != 4 else this_week + 1, 'start_game': this_game + 1 if this_game != 4 else 1, 'end_week': return_week, 'end_game': return_game }) await interaction.edit_original_response(content=random_salute_gif()) await send_to_channel(self.bot, 'sba-network-news', content=None, embed=embed) await self.update_injuries(interaction) else: await interaction.edit_original_response(content='Well that didn\'t work.') @app_commands.command(name='clearinjury', description='Clear the injury for a player') @app_commands.describe(player_name='Name of injured player') @app_commands.checks.has_any_role(SBA_PLAYERS_ROLE_NAME) async def clear_injury_slash(self, interaction: discord.Interaction, player_name: str): await interaction.response.defer() current = await db_get('current') p_query = await db_get('players', params=[('name', player_name), ('season', current['season'])]) if p_query['count'] == 0: await interaction.response.send_message(f'I did not find anybody named **{player_name}**.') return player = p_query['players'][0] i_query = await db_get('injuries', params=[('player_id', player['id']), ('is_active', True)]) if not player['il_return'] and i_query['count'] == 0: await interaction.edit_original_response(content='Huh? He isn\'t injured, numb nuts.') return team = await get_team_by_owner(current['season'], interaction.user.id) if not player['team'] == team and not player['team']['abbrev'][:len(team['abbrev'])] == team['abbrev']: await interaction.edit_original_response( content=f'Is this some kind of tom foolery? {player["name"]} is on {player["team"]["abbrev"]} aka ' f'not your team. I\'m watching you.' ) return old_injury = player['il_return'] view = Confirm(responders=[interaction.user]) await interaction.edit_original_response( content=f'{player["name"]}\'s return was set for {player["il_return"]}. Is he eligible to play again?', view=view ) await view.wait() if view.value: player['il_return'] = None await interaction.edit_original_response( content='Okay. Working on it...', view=None ) player['il_return'] = None if await patch_player(player): embed = get_team_embed(f'Injury Update', team=team) embed.add_field( name=f'{player["name"]}', value=f'{team["sname"]} {player["pos_1"]} {player["name"]}\'s injury ({old_injury}) has ended' ) await db_patch('injuries', object_id=i_query['injuries'][0]['id'], params=[('is_active', False)]) await interaction.edit_original_response( content=random_conf_gif(), view=None ) await send_to_channel(self.bot, 'sba-network-news', content=None, embed=embed) await self.update_injuries(interaction) else: await interaction.edit_original_response(content='Well that didn\'t work.') else: await interaction.edit_original_response( content='You keep thinking on it.', view=None ) @commands.command(name='links', aliases=['scorecards', 'scorecard', 'link', 'resources', 'resource'], help='Links for league resources') async def scorecard_command(self, ctx): await ctx.send( '# SCORECARD\n' '\n' '# REFERENCES\n' '**Rules Reference**:\n\n' '**League Guidelines**:\n\n' '**Scouting Reference**:\n' ) @commands.command(name='rest', help='Pitcher rest charts', hidden=True) async def rest_command(self, ctx): # sp_rest_url = 'https://lh3.googleusercontent.com/pw/ACtC-3eeRv52FZIUZNNafBBpwxJIx_OViLYHbsyi129GkJkIiv7r-X3O' \ # 'In9_mfkr9GVl2NbLhCJ9j1IQD5DX75bLwX0gVAFExkGNolnngKck9yx6g-qjQ6QoXkc2t821UwxGoRNbZadxfd3wUn32a' \ # 'zdQnJxnZw=w419-h703-no?authuser=0' # rp_rest_url = 'https://lh3.googleusercontent.com/pw/ACtC-3eU_nNLYv2KLJTCom9BUSkjY-kD-VBumaiPYQxzfDB23yvkozLc' \ # 'Qt9ai-xIwXe7CsGJ61qKgv6s6-lJp3_LRImwDFfP2VzUyPDFjE3P_CiuL6FsZCrzIBylQdLBXtxEsVmnGeSLv1WtJ--Wf' \ # '3KzZVoOkQ=w525-h453-no?authuser=0' # # sp_embed = discord.Embed(title='SP Rest Chart') # sp_embed.set_image(url=sp_rest_url) # await ctx.send(content=None, embed=sp_embed) # # rp_embed = discord.Embed(title='RP Rest Chart') # rp_embed.set_image(url=rp_rest_url) # await ctx.send(content=None, embed=rp_embed) # await ctx.send('For full rules, see ') await ctx.send('This command has been deprecated - please run `/charts rest`') @app_commands.command(name='sba-submit', description='Submit scorecard and game result') @app_commands.checks.has_any_role(SBA_PLAYERS_ROLE_NAME) async def submit_slash(self, interaction: discord.Interaction, sheet_url: str): current = await db_get('current') # Go get scorecard await interaction.response.send_message(content='I\'ll go grab that card now...') logging.info(f'Checking scorecard {sheet_url}') # Try to get card try: sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') scorecard = sheets.open_by_url(sheet_url) except Exception as e: logging.error(f'Failed to access scorecard {sheet_url}: {e}') await interaction.edit_original_response(content='Is that sheet public? I can\'t access it.') return # Get outline data from the sheet await asyncio.sleep(1) setup_tab = scorecard.worksheet_by_title('Setup') scorecard_version = setup_tab.get_value('V35') if int(scorecard_version) != current['bet_week']: await interaction.edit_original_response( content=f'It looks like this scorecard is out of date. Did you create a new card at the start of the ' f'game? If you did, let Cal know about this error. If not, I\'ll need you to use an up to ' f'date card.' ) return g_data = setup_tab.get_values('C3', 'D7') # setup_vals = setup_tab.get_values('B7', 'R33') week_num = g_data[1][0] game_num = g_data[2][0] at_abbrev = g_data[3][0] ht_abbrev = g_data[4][0] away_mgr_name = g_data[3][1] home_mgr_name = g_data[4][1] away_team = await get_team_by_abbrev(at_abbrev, current['season']) home_team = await get_team_by_abbrev(ht_abbrev, current['season']) logging.info(f'away_manager: {away_mgr_name} / home_manager: {home_mgr_name}') if away_team['manager2'] is not None and away_team['manager2']['name'].lower() == away_mgr_name.lower(): away_manager = away_team['manager2'] else: away_manager = away_team['manager1'] if home_team['manager2'] is not None and home_team['manager2']['name'].lower() == home_mgr_name.lower(): home_manager = home_team['manager2'] else: home_manager = home_team['manager1'] logging.info(f'gdata: {g_data}\nweek/game: {week_num}/{game_num}') # Confirm submitting GM if await get_team_by_owner(current['season'], interaction.user.id) not in [home_team, away_team] and \ interaction.user.id != self.bot.owner_id: await interaction.edit_original_response( content=f'{await get_emoji(interaction, "squint")} Only a GM of the two teams can submit scorecards.' ) return # Confirm teams and matchup dupe_g_query = await db_get('games', params=[ ('season', current['season']), ('week', week_num), ('game_num', game_num), ('away_team_id', away_team['id']), ('home_team_id', home_team['id']) ]) if dupe_g_query['count'] != 0: dupe_game = dupe_g_query['games'][0] view = Confirm(responders=[interaction.user], timeout=30) await interaction.edit_original_response( content=f'This game has already been played! Would you like me to wipe the old one and re-submit?', view=view ) await view.wait() if view.value: await interaction.edit_original_response( content='Okay, let me wipe the old shit...', view=None ) try: await db_delete('plays/game', object_id=dupe_game['id']) except ValueError as e: logging.error(f'No plays for game {dupe_game["id"]}') try: await db_delete('decisions/game', object_id=dupe_game['id']) except ValueError as e: logging.error(f'No decisions for game {dupe_game["id"]}') await db_post(f'games/wipe/{dupe_game["id"]}') else: await interaction.edit_original_response( content='You think on it some more and get back to me later.', view=None ) return g_query = await db_get('games', params=[ ('season', current['season']), ('week', week_num), ('away_team_id', away_team['id']), ('home_team_id', home_team['id']), ('played', False) ]) if g_query['count'] == 0: await interaction.edit_original_response( content=f'I don\'t see any games between {away_team["abbrev"]} and {home_team["abbrev"]} ' f'in week {week_num}.' ) return this_game = g_query['games'][0] logging.info(f'this_game: {this_game}') # TODO: check for stats and wipe logging.info(f'checking for old stats') await interaction.edit_original_response(content='Here I go sheetsing again...', view=None) logging.info(f'sba-submit - reading scorecard') playtable = scorecard.worksheet_by_title('Playtable') all_plays = playtable.get_values('B3', 'BG300') logging.debug(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_id', 'on_first_final', 'on_second_id', 'on_second_final', 'on_third_id', 'on_third_final', 'batter_final', 'pa', 'ab', 'run', 'e_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}') # Post plays try: resp = await db_post('plays', payload={'plays': p_data}) except ValueError as e: logging.error(f'POST plays error: {e}') await interaction.edit_original_response( content=f'The following errors were found in your **wk{week_num}g{game_num}** scorecard. ' f'Please resolve them and resubmit - thanks!\n\n{e}' ) return # Post box score to news-ticker try: sc_tab = scorecard.worksheet_by_title('Scorecard') score_table = sc_tab.get_values('BW8', 'BY9') except pygsheets.WorksheetNotFound as e: sc_tab = scorecard.worksheet_by_title('Box Score') score_table = sc_tab.get_values('T6', 'V7') final_inning = all_plays[len(all_plays) - 1][6] # Log game result try: g_resp = await db_patch('games', object_id=this_game['id'], params=[ ('away_score', int(score_table[0][0])), ('home_score', int(score_table[1][0])), ('away_manager_id', away_manager['id']), ('home_manager_id', home_manager['id']), ('game_num', game_num) ]) except ValueError as e: logging.error(f'PATCH game error: {e}') await interaction.edit_original_response( content=f'I was not able to log the game result. Go bug cal - it\'s probably his fault.' ) await db_delete(f'plays/game', object_id=this_game['id']) return # Pull pitching decisions pitching = scorecard.worksheet_by_title('Pitcherstats') all_decisions = pitching.get_values('B3', 'N30') logging.info(f'all_decisions: {all_decisions}') pit_keys = [ 'pitcher_id', 'rest_ip', 'is_start', 'base_rest', 'extra_rest', 'rest_required', 'win', 'loss', 'is_save', 'hold', 'b_save', 'irunners', 'irunners_scored' ] pit_data = [] wp = None lp = None sv = None b_sv = [] holds = [] for line in all_decisions: this_data = {'game_id': this_game['id'], 'season': this_game['season'], 'week': this_game['week'], 'game_num': game_num} for count, x in enumerate(line): if x != '': this_data[pit_keys[count]] = x pit_data.append(this_data) if line[6] == '1': wp = await db_get('players', object_id=line[0]) if line[7] == '1': lp = await db_get('players', object_id=line[0]) if line[8] == '1': sv = await db_get('players', object_id=line[0]) if line[10] == '1': b_sv.append(await db_get('players', object_id=line[0])) if line[9] == '1': holds.append(await db_get('players', object_id=line[0])) if wp is None or lp is None: await interaction.edit_original_response( content='You card is missing either a Winning Pitcher or Losing Pitcher' ) await db_delete(f'plays/game', object_id=this_game['id'], timeout=6) return logging.info(f'pit_data: {pit_data}') # Post decisions try: d_resp = await db_post('decisions', payload={'decisions': pit_data}) except ValueError as e: logging.error(f'POST decisions error: {e}') await interaction.edit_original_response( content=f'The following errors were found in your **wk{week_num}g{game_num}** scorecard. ' f'Please resolve them and resubmit - thanks!\n\n{e}' ) await db_post(f'games/wipe/{this_game["id"]}') await db_delete('plays/game', object_id=this_game['id']) return # Post scorecard to news channel card_url = f'<{SBA_BASE_URL}/scorecards/?season={current["season"]}&week={week_num}&game={game_num}' \ f'&away_abbrev={away_team["abbrev"]}&home_abbrev={home_team["abbrev"]}>' extras = '' if int(final_inning) > 9: extras = f' F/{final_inning}' embed = get_team_embed( f'{away_team["sname"]} {score_table[0][0]} @ ' f'{score_table[1][0]} {home_team["sname"]}{extras}', team=away_team if int(score_table[0][0]) > int(score_table[1][0]) else home_team ) embed.description = f'Week {week_num} | Game {game_num}' embed.add_field( name='Box Score', value=f'```\n' f'Team | R | H | E |\n' f'{away_team["abbrev"]: <4} | {score_table[0][0]: >2} | {score_table[0][1]: >2} | ' f'{score_table[0][2]: >2} |\n' f'{home_team["abbrev"]: <4} | {score_table[1][0]: >2} | {score_table[1][1]: >2} | ' f'{score_table[1][2]: >2} |\n' f'```', inline=False ) pitching_string = f'WP: {wp["name"]}\n' \ f'LP: {lp["name"]}\n' \ f'{"HD: " if len(holds) > 0 else ""}' hold_string = '' count = 1 for x in holds: hold_string += f'{x["name"]}' if count < len(holds): hold_string += ', ' count += 1 if len(hold_string) > 0: hold_string = f'{hold_string}\n' pitching_string += hold_string if sv is not None: pitching_string += f'SV: {sv["name"]}' embed.add_field(name='Pitching', value=pitching_string, inline=False) # Key Plays pull logging.info(f'pull highlight stats for embed') p_query = await db_get('plays', params=[ ('game_id', this_game['id']), ('sort', 'wpa-desc'), ('limit', 3) ]) key_plays = '' for play in p_query['plays']: logging.info(f'this_play: {play}') this_line = f'- {play["inning_half"].title()} {play["inning_num"]}: ' # Offensive Play if play['wpa'] > 0: logging.info('OFFENSE') if play['runner'] is not None: logging.info('RUNNER') if play['on_third'] == play['runner']['id']: s_base = 'HOME' elif play['on_second'] == play['runner']['id']: s_base = 'third' else: s_base = 'second' this_line += f'{play["runner"]["name"]} ({play["runner"]["team"]["abbrev"]}) steals {s_base}' else: logging.info('BATTER') if play['homerun'] == 1: h_name = 'homers' elif play['triple'] == 1: h_name = 'triples' elif play['double'] == 1: h_name = 'doubles' elif play['sac'] == 1: h_name = 'sac flies' else: h_name = 'singles' logging.info('RBI?') if play['rbi'] > 0: rbi_string = f' in {play["rbi"]} run{"s" if play["rbi"] > 1 else ""}' else: rbi_string = '' logging.info('LINE?') this_line += f'{play["batter"]["name"]} ({play["batter"]["team"]["abbrev"]}) {h_name}{rbi_string}' # Defensive Play else: logging.info('DEFENSE') if play['catcher'] is not None: logging.info('CATCHER') if play['on_third_final'] == 0: s_base = 'HOME' elif play['on_second_final'] == 0: s_base = 'third' else: s_base = 'second' this_line += f'{play["catcher"]["name"]} ({play["catcher"]["team"]["abbrev"]}) throws out the ' \ f'runner at {s_base}' elif play['defender'] is not None: logging.info('DEFENDER') if play['outs'] == 3: play_string = 'turns a TRIPLE PLAY' elif play['outs'] == 2: play_string = 'rolls a double play' else: play_string = f'makes a tough play at {play["check_pos"]}' this_line += f'{play["defender"]["name"]} ({play["defender"]["team"]["abbrev"]}) {play_string}' else: logging.info('PITCHER') if play['so'] == 1: if play['starting_outs'] == 2: out_th = 'for the 3rd out' elif play['starting_outs'] == 1: out_th = 'for the 2nd out' else: out_th = 'to leadoff the inning' play_string = f'gets a K {out_th}' elif play['on_base_code'] != '000' and play['starting_outs'] + play['outs'] > 2: num_runners = play["on_base_code"].count("1") play_string = f'strands {num_runners} runner{"s" if num_runners > 1 else ""}' else: if play['starting_outs'] == 2: play_string = 'records the 3rd out' elif play['starting_outs'] == 1: play_string = 'records the 2nd out' else: play_string = 'retires the leadoff batter' this_line += f'{play["pitcher"]["name"]} ({play["pitcher"]["team"]["abbrev"]}) {play_string}' if play['is_go_ahead']: this_line += ' to take the lead' a_score = play['away_score'] h_score = play['home_score'] if play['inning_half'] == 'top': a_score += play['rbi'] else: h_score += play['rbi'] if a_score > h_score: score_string = f'{away_team["abbrev"]} up {a_score}-{h_score}' elif h_score > a_score: score_string = f'{home_team["abbrev"]} up {h_score}-{a_score}' else: score_string = f'tied at {a_score}' key_plays += f'{this_line}, {score_string}\n' if len(key_plays) > 0: embed.add_field( name='Key Plays', value=key_plays, inline=False ) # batting_string = '' # count = 1 # if len(final_doubles) > 0: # batting_string += '2B: ' # # for x in final_doubles: # player = await get_one_player(x[0]) # batting_string += f'{player["name"]}' # # if x[1] > 1: # batting_string += f' {x[1]}' # # if count < len(final_doubles): # batting_string += ', ' # else: # batting_string += '\n' # count += 1 # # count = 1 # if len(final_triples) > 0: # batting_string += '3B: ' # # for x in final_triples: # player = await get_one_player(x[0]) # batting_string += f'{player["name"]}' # # if x[1] > 1: # batting_string += f' {x[1]}' # # if count < len(final_triples): # batting_string += ', ' # else: # batting_string += '\n' # count += 1 # # count = 1 # if len(final_homeruns) > 0: # batting_string += 'HR: ' # # for x in final_homeruns: # player = await get_one_player(x[0]) # batting_string += f'{player["name"]}' # # if x[1] > 1: # batting_string += f' {x[1]}' # # if count < len(final_homeruns): # batting_string += ', ' # else: # batting_string += '\n' # count += 1 # # if len(batting_string) > 0: # embed.add_field(name='Batting', value=batting_string, inline=False) # # baserunning_string = '' # count = 1 # if len(final_sbs) > 0: # baserunning_string += 'SB: ' # # for x in final_sbs: # player = await get_one_player(x[0]) # baserunning_string += f'{player["name"]}' # # if x[1] > 1: # baserunning_string += f' {x[1]}' # # if count < len(final_sbs): # baserunning_string += ', ' # else: # baserunning_string += '\n' # count += 1 # # count = 1 # if len(final_cscs) > 0: # baserunning_string += 'CSc: ' # # for x in final_cscs: # player = await get_one_player(x[0]) # baserunning_string += f'{player["name"]}' # # if x[1] > 1: # baserunning_string += f' {x[1]}' # # if count < len(final_cscs): # baserunning_string += ', ' # else: # baserunning_string += '\n' # count += 1 # # if len(baserunning_string) > 0: # embed.add_field(name='Baserunning', value=baserunning_string, inline=False) embed.add_field( name='Scorecard', value=f'[Website]({card_url}) / [Sheets]({sheet_url})', inline=False ) embed.set_footer(text='Please share the highlights!') await send_to_channel( self.bot, 'sba-network-news', content=None, embed=embed ) update = await interaction.channel.send('I\'m tallying standings now...') if await db_post(f'standings/s{current["season"]}/recalculate', timeout=8): await update.delete() await interaction.edit_original_response(content='You are all set!') # try: # setup_tab.update_values( # crange=f'B7', # values=setup_vals # ) # await interaction.edit_original_response(content='You are all set!') # except Exception as e: # logging.error(f'could not freeze sheet for game {this_game["id"]}') # await interaction.edit_original_response( # content='You didn\'t give me edit perms so I couldn\'t lock the rosters in your sheet, ' # 'but everything else went through.' # ) @app_commands.command(name='branding', description='Update your team branding') @app_commands.guilds(discord.Object(id=os.environ.get('GUILD_ID'))) @app_commands.rename( team_image_url='team_logo_url', mil_team_image_url='minor_league_logo_url', ) @app_commands.describe( color_hex='Color hex code to use for your team', team_image_url='URL ending in .png or .jpg of your team logo', mil_color_hex='Color hex code to use for your minor league team', mil_team_image_url='URL ending in .png or .jpg of your minor league team logo', dice_color_hex='Color hex code to use for your dice rolls', ) @app_commands.checks.has_any_role(SBA_PLAYERS_ROLE_NAME) async def branding_slash_command( self, interaction: discord.Interaction, color_hex: str = None, team_image_url: str = None, mil_color_hex: str = None, mil_team_image_url: str = None, dice_color_hex: str = None): await interaction.response.defer() current = await db_get('current') team = await get_team_by_owner(current['season'], interaction.user.id) mil_team = await get_team_by_abbrev(f'{team["abbrev"]}MiL', current['season']) team_role = get_team_role(interaction, team) errors = [] show_mil = False show_dice = False if not team or not team_role: await interaction.response.send_message( f'Do you have a team here? You don\'t look familiar. {await get_emoji(interaction, "realeyes")}' ) return if color_hex is not None: color_int = int(color_hex, 16) try: await team_role.edit(colour=color_int) except Exception as e: logging.info(f'Error setting {team["sname"]} color to {color_hex}') errors.append(f'- Error setting {team["sname"]} color to {color_hex}:\n{e}\n\n') team['color'] = color_hex await db_patch('teams', object_id=team['id'], params=[('color', color_hex)]) if team_image_url is not None: if requests.get(team_image_url, timeout=3).status_code != 200: errors.append(f'- I wasn\'t able to pull that image. Was it a public URL?\n\n') else: team['thumbnail'] = team_image_url await db_patch('teams', object_id=team['id'], params=[('thumbnail', team_image_url)]) if mil_color_hex is not None: try: await db_patch('teams', object_id=mil_team['id'], params=[('color', mil_color_hex)]) show_mil = True except Exception as e: logging.info(f'Error setting {team["sname"]} color to {mil_color_hex}') errors.append(f'- Error setting {team["sname"]} color to {mil_color_hex}:\n{e}\n\n') if mil_team_image_url is not None: if requests.get(mil_team_image_url, timeout=3).status_code != 200: errors.append(f'- I wasn\'t able to pull that image. Was it a public URL?\n\n') else: await db_patch('teams', object_id=mil_team['id'], params=[('thumbnail', mil_team_image_url)]) show_mil = True if dice_color_hex is not None: try: await db_patch('teams', object_id=team['id'], params=[('dice_color', dice_color_hex)]) show_dice = True except Exception as e: logging.info(f'Error setting {team["sname"]} color to {color_hex}') errors.append(f'- Error setting {team["sname"]} color to {color_hex}:\n{e}\n\n') team = await db_get('teams', object_id=team['id']) major_embed = get_team_embed(f'{team["lname"]} Test', team=team) major_embed.add_field( name='Little Test Data', value='Run the command again if you want to change anything!' ) embeds = [major_embed] if show_mil: mil_team = await db_get('teams', object_id=mil_team['id']) mil_embed = get_team_embed(f'{mil_team["lname"]} Test', team=mil_team) mil_embed.add_field( name='Little Test Data', value='Run the command again if you want to change anything!' ) embeds.append(mil_embed) if show_dice: logging.info(f'entering show_dice') team['color'] = team['dice_color'] dice_embed = get_team_embed(f'{team["lname"]} Dice Test', team=team) logging.info(f'got base embed: {dice_embed}') dice_embed.add_field( name='Little Test Data', value='This is what we\'ve got for your dice rolls!' ) logging.info(f'done with embed: {dice_embed}') embeds.append(dice_embed) await interaction.edit_original_response(content=None, embeds=embeds) @commands.command(name='picks', aliases=['mypicks', 'draftpicks'], help='See your picks') async def picks_command(self, ctx, *team_abbrev): await ctx.send('Go away.') return @commands.command(name='vc', aliases=['voice', 'gameplay'], help='Get voice channel') @commands.has_any_role(SBA_PLAYERS_ROLE_NAME, 'Paper Dynasty Players') async def voice_channel_command(self, ctx): prompt = 'Would you like to get a gameplay channel?' this_q = Question(self.bot, ctx.channel, prompt, qtype='yesno', timeout=15) resp = await this_q.ask([ctx.author]) if not resp: await ctx.send('Fine. I bet they didn\'t wanna talk to you anyway.') return else: overwrites = {ctx.guild.default_role: discord.PermissionOverwrite(speak=True)} channel_name = f'Gameplay {random_codename()}' this_vc = await ctx.guild.create_voice_channel( channel_name, overwrites=overwrites, category=discord.utils.get(ctx.guild.categories, name=f'Voice Channels') ) logging.info(f'Just created voice channel: {channel_name} for {ctx.author}') self.voice_channels.append(this_vc) await ctx.send(f'Just created {this_vc} for you!') while True: await asyncio.sleep(900) if len(this_vc.members) == 0: self.voice_channels.remove(this_vc) try: await this_vc.delete() except Exception as e: logging.error(f'could not delete {this_vc}.') break @commands.command(name='private', help='Get private vc') @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) async def private_vc_command(self, ctx): current = await db_get('current') this_team = await get_team_by_owner(current['season'], ctx.author.id) async def get_other_team(): prompt = f'Please enter the abbrev of the team you are playing.' this_q = Question(self.bot, ctx.channel, prompt, qtype='text', timeout=15) resp = await this_q.ask([ctx.author]) if not resp: await ctx.send('You keep thinking about it and hit me up later if you figure it out.') return None else: other_team = await get_team_by_abbrev(resp, current['season']) if not other_team: await ctx.send(f'What\'s a **{resp}**? If you could go ahead and run this command again, that\'d ' f'be great.') return None else: return other_team if not this_team: await ctx.send('Hmm...I can\'t find your team. Are you from around here?') return g_query = await db_get('games', params=[ ('season', current['season']), ('week', current['week']), ('team1_id', this_team['id']) ]) if g_query['count'] == 0: other_team = await get_other_team() if not other_team: await ctx.send(f'Idk who you are playing this week.') channel_name = f'{this_team["abbrev"]} vs {other_team["abbrev"]} Muted' else: this_game = g_query['games'][0] if this_team == this_game['away_team']: other_team = this_game['home_team'] else: other_team = this_game['away_team'] channel_name = f'{this_game["away_team"]["sname"]} @ {this_game["home_team"]["sname"]} Muted' prompt = f'Would you like to get a private voice channel for {this_team["abbrev"]} and {other_team["abbrev"]}?' this_q = Question(self.bot, ctx.channel, prompt, qtype='yesno', timeout=15) resp = await this_q.ask([ctx.author]) if not resp: await ctx.send('Fine. I bet they didn\'t wanna talk to you anyway.') return logging.info(f'getting roles') this_team_role = discord.utils.get(ctx.guild.roles, name=f'{this_team["lname"]}') other_team_role = discord.utils.get(ctx.guild.roles, name=f'{other_team["lname"]}') if None in [this_team_role, other_team_role]: await ctx.send(f'Tell Cal that we\'re missing a team role to create this channel.') return logging.info(f'getting overwrites') overwrites = {ctx.guild.default_role: discord.PermissionOverwrite(speak=False), this_team_role: discord.PermissionOverwrite(speak=True), other_team_role: discord.PermissionOverwrite(speak=True)} logging.info(f'creating channel') this_vc = await ctx.guild.create_voice_channel( channel_name, overwrites=overwrites, category=discord.utils.get(ctx.guild.categories, name=f'Voice Channels') ) self.voice_channels.append(this_vc) await ctx.send(f'Just created {this_vc} for you!') while True: await asyncio.sleep(900) if len(this_vc.members) == 0: self.voice_channels.remove(this_vc) try: await this_vc.delete() except Exception as e: logging.error(f'could not delete {this_vc}.') break @commands.command(name='headshot', aliases=['hs'], help='Set headshot pic') @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) async def headshot_command(self, ctx, url, *, player_name): if ctx.channel.name == 'season-6-chat': await ctx.send('Not in season 6 chat, dumbass.') return current = await db_get('current') this_team = await get_team_by_owner(current['season'], ctx.author.id) if not this_team: await ctx.send('Hmm...I can\'t find your team. Are you from around here?') return p_name = await fuzzy_player_search( ctx, ctx.channel, self.bot, player_name, self.player_list.keys(), author=ctx.author ) player = await get_player_by_name(current['season'], p_name) if player is None: await ctx.send(random_gif('it didn\'t work')) return player_embed = await get_player_embed(player, current) player_embed.set_thumbnail(url=url) prompt = 'Would you like to save this image?' this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 15, player_embed) resp = await this_q.ask([ctx.author]) if not resp: await ctx.send('That\'s okay. It wasn\'t a very good picture anyway.') return else: player['headshot'] = url await patch_player(player) await ctx.send(random_conf_word()) @commands.command(name='fancycard', aliases=['fc'], help='Set vanity card') @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) async def vanity_card_command(self, ctx, url, *, player_name): if ctx.channel.name == 'season-6-chat': await ctx.send('Not in season 6 chat, dumbass.') return current = await db_get('current') this_team = await get_team_by_owner(current['season'], ctx.author.id) if not this_team: await ctx.send('Hmm...I can\'t find your team. Are you from around here?') return p_name = await fuzzy_player_search( ctx, ctx.channel, self.bot, player_name, self.player_list.keys(), author=ctx.author ) player = await get_player_by_name(current['season'], p_name) if player is None: await ctx.send(random_gif('it didn\'t work')) return player_embed = await get_player_embed(player, current) player_embed.set_thumbnail(url=url) prompt = 'Would you like to save this image?' this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 15, player_embed) resp = await this_q.ask([ctx.author]) if not resp: await ctx.send('That\'s okay. It wasn\'t a very good picture anyway.') return else: player['vanity_card'] = url await patch_player(player) await ctx.send(random_conf_word()) @commands.command(name='getfc', help='Get last season vanity card') @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) async def get_vanity_card_command(self, ctx, *, player_name): if ctx.channel.name == 'season-5-chat': await ctx.send('Not in season 5 chat, dumbass.') return current = await db_get('current') this_team = await get_team_by_owner(current['season'], ctx.author.id) if not this_team: await ctx.send('Hmm...I can\'t find your team. Are you from around here?') return p_name = await fuzzy_player_search( ctx, ctx.channel, self.bot, player_name, self.player_list.keys(), author=ctx.author ) player = await get_player_by_name(current['season'], p_name) p_query = await db_get('players', params=[('season', current['season'] - 1), ('name', p_name)]) if p_query['count'] == 0: await ctx.send(f'I could not find **{p_name}** from Season {current["season"] - 1}') return player['vanity_card'] = p_query['players'][0]['vanity_card'] await patch_player(player) player_embed = await get_player_embed(player, current) await ctx.send(content=None, embed=player_embed) @app_commands.command(name='charts') async def chart_command(self, interaction: discord.Interaction, chart_name: Literal[ 'rest', 'sac-bunt', 'squeeze-bunt', 'rob-hr', 'defense-matters', 'block-plate', 'hit-and-run', 'g1', 'g2', 'g3', 'groundball']): gb_url = 'https://sombaseball.ddns.net/static/images/season04/ground-ball-chart' all_charts = { 'rest': [f'{SBA_IMAGE_URL}/season05/charts/rest.png'], 'sac-bunt': [ f'{SBA_IMAGE_URL}/season05/charts/sac-bunt.png', f'{SBA_IMAGE_URL}/season05/charts/sac-bunt-help.png' ], 'squeeze-bunt': [ f'{SBA_IMAGE_URL}/season05/charts/squeeze-bunt.png', f'{SBA_IMAGE_URL}/season05/charts/squeeze-bunt-help.png' ], 'rob-hr': [f'{SBA_IMAGE_URL}/season05/charts/rob-hr.png'], 'defense-matters': [f'{SBA_IMAGE_URL}/season05/charts/defense-matters.png'], 'block-plate': [f'{SBA_IMAGE_URL}/season05/charts/block-plate.png'], 'hit-and-run': [ f'{SBA_IMAGE_URL}/season05/charts/hit-and-run.png', f'{SBA_IMAGE_URL}/season05/charts/hit-and-run-pitcher.png' ], 'g1': [f'{gb_url}-g1.png', f'{gb_url}01.png', f'{gb_url}02.png'], 'g2': [f'{gb_url}-g2.png', f'{gb_url}01.png', f'{gb_url}02.png'], 'g3': [f'{gb_url}-g3.png', f'{gb_url}01.png', f'{gb_url}02.png'], 'groundball': [f'{gb_url}01.png', f'{gb_url}02.png'] } first = True for link in all_charts[chart_name]: if first: await interaction.response.send_message(link) first = False else: await interaction.followup.send(link) @commands.command(name='pitcherbatting', aliases=['pbat', 'pitbat'], help='Show specific pitcher batting card') @commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME) async def pitcher_batting_command(self, ctx: commands.Context, card_num: int = 1): if card_num > 8: await ctx.send(f'I only have pitcher batting cards 1 through 8. Why don\'t you try again.') return if card_num < 1: await ctx.send(f'I only have pitcher batting cards 1 through 8. Why don\'t you try again.') return team = await get_team_by_owner(SBA_SEASON, ctx.author.id) embed = get_team_embed(f'Pitcher Batting Card #{card_num}', team=team, thumbnail=False) embed.set_image(url=f'{SBA_BASE_URL}/static/images/pitbat/card-{card_num}.png') await ctx.send(content=None, embed=embed) @app_commands.command(name='keepers', description='Mod: Set team keepers') @app_commands.checks.has_any_role('Da Commish') async def set_keepers_slash( self, interaction: discord.Interaction, team_abbrev: str, keep1: str = None, keep2: str = None, keep3: str = None, keep4: str = None, keep5: str = None, keep6: str = None, keep7: str = None): await interaction.response.defer() current = await db_get('current') team = await get_team_by_abbrev(team_abbrev, current['season']) keepers = [] keeper_string = '' keeper_swar = 0 def get_pos_abbrev(position): if 'B' in position: return 'IF' if 'F' in position: return 'OF' if 'P' in position: return 'P' if position == 'C': return 'C' return 'DH' for x in [keep1, keep2, keep3, keep4, keep5, keep6, keep7]: if x: p_name = await fuzzy_player_search( interaction, interaction.channel, self.bot, x, self.player_list.keys(), author=interaction.user ) this_p = await get_player_by_name(current['season'], p_name) keepers.append(this_p) keeper_string += f'{get_pos_abbrev(this_p["pos_1"])} - {this_p["name"]} ({this_p["wara"]:.2f})\n' keeper_swar += this_p['wara'] await interaction.response.send_message(content=f'{team["sname"]} Keepers:\n{keeper_string}') all_players = await db_get('players', api_ver=3, params=[('team_abbrev', team['abbrev'])]) logging.info(f'all_players: {all_players}') fa = await get_team_by_abbrev('FA', current['season']) for y in all_players['players']: if y not in keepers: y['team'] = fa await patch_player(y) await interaction.channel.send( f'Just yeeted **{len(all_players["players"]) - len(keepers)}** players into the sun!' ) embed = get_team_embed(title=f'{team["lname"]} Keepers', team=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) group_publish = app_commands.Group(name='publish', description='Make a scorecard publicly accessible') @group_publish.command(name='josef') @app_commands.describe(sheet_url='The full URL of your publicly shared scorecard') async def pub_josef_slash(self, interaction: discord.Interaction, sheet_url: str): sheets = pygsheets.authorize(service_file='storage/major-domo-service-creds.json') try: if 'https://' in sheet_url: scorecard = sheets.open_by_url(sheet_url).worksheet_by_title('ASCII') else: scorecard = sheets.open_by_key(sheet_url).worksheet_by_title('ASCII') except Exception as e: await interaction.response.send_message( 'Frick. I wasn\'t able to publish that card. Is that card ID correct?' ) return self.scorecards[f'{interaction.channel_id}'] = scorecard await interaction.response.send_message( f'Your scorecard has been published. Anyone may now run `/scorebug` in ' f'this channel to get the scorebug.') @app_commands.command(name='scorebug', description='Pull the scorebug for the game in this channel') @commands.has_any_role(SBA_PLAYERS_ROLE_NAME, PD_PLAYERS_ROLE_NAME) async def scorebug_slash(self, interaction: discord.Interaction): if not self.scorecards: await interaction.response.send_message( 'Uhh...I don\'t see any games in this channel. You in the right place?' ) return this_scorecard = self.scorecards[f'{interaction.channel_id}'] if not this_scorecard: await interaction.response.send_message( 'Uhh...I don\'t see any games in this channel. You in the right place?' ) return await interaction.response.send_message(f'I am checking sheets now...', ephemeral=True) score_text = this_scorecard.get_value('A1') await interaction.edit_original_response(content=score_text) @app_commands.command(name='injury', description='Make an injury check; rating = left of "p", games = right') @app_commands.guilds(discord.Object(id=os.environ.get('GUILD_ID'))) @app_commands.choices(games=[ Choice(name='70', value=70), Choice(name='65', value=65), Choice(name='60', value=60), Choice(name='50', value=50), Choice(name='40', value=40), Choice(name='30', value=30), Choice(name='20', value=20), ], rating=[ Choice(name='1', value=1), Choice(name='2', value=2), Choice(name='3', value=3), Choice(name='4', value=4), Choice(name='5', value=5), Choice(name='6', value=6), ]) async def injury_roll_slash(self, interaction: discord.Interaction, rating: Choice[int], games: Choice[int]): team = None await interaction.response.defer() d_six_one = random.randint(1, 6) d_six_two = random.randint(1, 6) d_six_three = random.randint(1, 6) injury_roll = d_six_one + d_six_two + d_six_three inj_data = { 'one': { 'p70': ['OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'REM', 'REM', 1, 1, 2, 2, 3, 3, 4, 4], 'p65': [2, 2, 'OK', 'REM', 1, 2, 3, 3, 4, 4, 4, 4, 5, 6, 8, 12], 'p60': ['OK', 'OK', 'REM', 1, 2, 3, 4, 4, 4, 5, 5, 6, 8, 12, 16, 16], 'p50': ['OK', 'REM', 1, 2, 3, 4, 4, 5, 5, 6, 8, 8, 12, 16, 16, 'OK'], 'p40': ['OK', 1, 2, 3, 4, 4, 5, 6, 6, 8, 8, 12, 16, 24, 'REM', 'OK'], 'p30': ['OK', 4, 1, 3, 4, 5, 6, 8, 8, 12, 16, 24, 4, 2, 'REM', 'OK'], 'p20': ['OK', 1, 2, 4, 5, 8, 8, 24, 16, 12, 12, 6, 4, 3, 'REM', 'OK'] }, 'two': { 'p70': [4, 3, 2, 2, 1, 1, 'REM', 'OK', 'REM', 'OK', 2, 1, 2, 2, 3, 4], 'p65': [8, 5, 4, 2, 2, 'OK', 1, 'OK', 'REM', 1, 'REM', 2, 3, 4, 6, 12], 'p60': [1, 3, 4, 5, 2, 2, 'OK', 1, 3, 'REM', 4, 4, 6, 8, 12, 3], 'p50': [4, 'OK', 'OK', 'REM', 1, 2, 4, 3, 4, 5, 4, 6, 8, 12, 12, 'OK'], 'p40': ['OK', 'OK', 'REM', 1, 2, 3, 4, 4, 5, 4, 6, 8, 12, 16, 16, 'OK'], 'p30': ['OK', 'REM', 1, 2, 3, 4, 4, 5, 6, 5, 8, 12, 16, 24, 'REM', 'OK'], 'p20': ['OK', 1, 4, 4, 5, 5, 6, 6, 12, 8, 16, 24, 8, 3, 2, 'REM'] }, 'three': { 'p70': [], 'p65': ['OK', 'OK', 'REM', 1, 3, 'OK', 'REM', 1, 2, 1, 2, 3, 4, 4, 5, 'REM'], 'p60': ['OK', 5, 'OK', 'REM', 1, 2, 2, 3, 4, 4, 1, 3, 5, 6, 8, 'REM'], 'p50': ['OK', 'OK', 'REM', 1, 2, 3, 4, 4, 5, 4, 4, 6, 8, 8, 12, 'REM'], 'p40': ['OK', 1, 1, 2, 3, 4, 4, 5, 6, 5, 6, 8, 8, 12, 4, 'REM'], 'p30': ['OK', 1, 2, 3, 4, 5, 4, 6, 5, 6, 8, 8, 12, 16, 1, 'REM'], 'p20': ['OK', 1, 2, 4, 4, 8, 8, 6, 5, 12, 6, 16, 24, 3, 4, 'REM'] }, 'four': { 'p70': [], 'p65': [], 'p60': ['OK', 'OK', 'REM', 3, 3, 'OK', 'REM', 1, 2, 1, 4, 4, 5, 6, 8, 'REM'], 'p50': ['OK', 6, 4, 'OK', 'REM', 1, 2, 4, 4, 3, 5, 3, 6, 8, 12, 'REM'], 'p40': ['OK', 'OK', 'REM', 1, 2, 3, 4, 4, 5, 4, 4, 6, 8, 8, 12, 'REM'], 'p30': ['OK', 1, 1, 2, 3, 4, 4, 5, 6, 5, 6, 8, 8, 12, 4, 'REM'], 'p20': ['OK', 1, 2, 3, 4, 5, 4, 6, 5, 6, 12, 8, 8, 16, 1, 'REM'] }, 'five': { 'p70': [], 'p65': [], 'p60': ['OK', 'REM', 'REM', 'REM', 3, 'OK', 1, 'REM', 2, 1, 'OK', 4, 5, 2, 6, 8], 'p50': ['OK', 'OK', 'REM', 1, 1, 'OK', 'REM', 3, 2, 4, 4, 5, 5, 6, 8, 12], 'p40': ['OK', 6, 6, 'OK', 1, 3, 2, 4, 4, 5, 'REM', 3, 8, 6, 12, 1], 'p30': ['OK', 'OK', 'REM', 4, 1, 2, 5, 4, 6, 3, 4, 8, 5, 6, 12, 'REM'], 'p20': ['OK', 'REM', 2, 3, 4, 4, 5, 4, 6, 5, 8, 6, 8, 1, 12, 'REM'] }, 'six': { 'p70': [], 'p65': [], 'p60': [], 'p50': [], 'p40': ['OK', 6, 6, 'OK', 1, 3, 2, 4, 4, 5, 'REM', 3, 8, 6, 1, 12], 'p30': ['OK', 'OK', 'REM', 5, 1, 3, 6, 4, 5, 2, 4, 8, 3, 5, 12, 'REM'], 'p20': ['OK', 'REM', 4, 6, 2, 3, 6, 4, 8, 5, 5, 6, 3, 1, 12, 'REM'] } } p_ratings = ['one', 'two', 'three', 'four', 'five', 'six'] injury_string = f'```md\n# {injury_roll}\n' \ f'Details:[3d6 ({d_six_one} {d_six_two} {d_six_three})]\n```\n' logging.info(f'injury rating: {rating.value}p{games.value}') injury_list = inj_data[p_ratings[rating.value - 1]][f'p{games.value}'] injury_result = injury_list[injury_roll - 3] logging.info(f'injury rating: {rating.value}p{games.value} / array: {injury_list}[{injury_roll - 2}] / result: {injury_result}') if isinstance(injury_result, int): try: await interaction.edit_original_response( content=random_gif(random_from_list(['salute', 'press f', 'pay respects', 'well shit'])) ) except Exception as e: logging.info(f'failed to post funny gif') injury_string += f'With a roll of {injury_roll}, the injury length is **{injury_result} ' \ f'game{"s" if injury_result > 1 else ""}**.' elif injury_result == 'REM': try: await interaction.edit_original_response( content=random_gif(random_from_list(['could be worse', 'not too bad'])) ) except Exception as e: logging.info(f'failed to post funny gif') injury_string += f'With a roll of {injury_roll}, the injury length is **REMAINDER OF GAME** for batters ' \ f'or **FATIGUED** for pitchers' else: try: await interaction.edit_original_response( content=random_gif(random_from_list(['it is fine', 'nothing to see here', 'i wasn\'t worried'])) ) except Exception as e: logging.info(f'failed to post funny gif') injury_string += f'With a roll of {injury_roll}, the player is **OKAY** - no injury!' embed = await self.get_dice_embed( interaction.channel.name, f'Injury roll for {interaction.user.name}', injury_string ) embed.set_footer(text='For pitchers, add their current rest to the injury') await interaction.channel.send(content=None, embed=embed) # this_roll = { # 'season': self.current['season'], # 'week': self.current['week'], # 'team_id': team["id"] if team else None, # 'roller': interaction.user.id, # 'threedsix': d_six_one + d_six_two + d_six_three # } # self.rolls.append(this_roll) async def setup(bot): await bot.add_cog(Players(bot))