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 db_calls_gameplay import get_one_game 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 from typing import Literal 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.build_master_player_list.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}') @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 = {} all_injuries = await db_get('players', params=[ ('season', current['season']), ('is_injured', True) ]) for x in all_injuries: player = all_injuries[x] 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 {player["il_return"][1:3]}' not in inj_week.keys(): inj_week[f'Week {player["il_return"][1:3]}'] = [player] else: inj_week[f'Week {player["il_return"][1:3]}'].append(player) inj_by_team = dict(sorted(inj_team.items())) inj_by_week = dict(sorted(inj_week.items())) 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: team_string = '' for player in inj_by_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: week_string = '' for player in inj_by_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"] < 0: gb = stan["div_gb"] if stan["div_gb"] >= 0.0 else f'+{stan["div_gb"] * -1}' 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'+{stan["wc_gb"] * -1}' 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: >5} {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']) ]) game_count = 0 for x in s_query['schedules']: game_count += x['gamecount'] return {'games_played': r_query['count'], 'game_count': game_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('standings', params=[ ('season', current['season']), ('team_abbrev', team['abbrev']) ]) if s_query['count'] > 0: team_standings = s_query['standings'][0] 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 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://sombaseball.ddns.net/teams?abbrev={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'] 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] 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: int): await ctx.send(f'That mother fucker Cal hasn\'t updated this command for the new API.') await ctx.send(random_gif('this idiot')) return current = await db_get('current') if week: schedule_week = week[0] elif current['week'] < 1: schedule_week = 1 else: schedule_week = current['week'] this_week_raw = await get_schedule( current['season'], week_start=schedule_week, week_end=schedule_week ) next_week_raw = await get_schedule( current['season'], week_start=schedule_week + 1, week_end=schedule_week + 1 ) results_this_week = await get_results( current['season'], week=schedule_week ) this_week = dict(sorted(this_week_raw.items(), key=lambda item: item[1]["id"])) next_week = dict(sorted(next_week_raw.items(), key=lambda item: item[1]["id"])) game_count = 0 for x in this_week: game_count += this_week[x]['gamecount'] embed = get_team_embed(f'Season {current["season"]} | Week {schedule_week} | ' f'{len(results_this_week)}/{game_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 this_week: away_wins = 0 away_losses = 0 weekly_results = await get_results(current['season'], week=schedule_week, away_abbrev=this_week[x]['awayteam']['abbrev']) for y in weekly_results: if weekly_results[y]['awayteam'] == this_week[x]['awayteam'] and \ weekly_results[y]['hometeam'] == this_week[x]['hometeam']: if weekly_results[y]['awayscore'] > weekly_results[y]['homescore']: away_wins += 1 else: away_losses += 1 this_line = f'`({away_wins}) {this_week[x]["awayteam"]["abbrev"]: >4}` ' \ f'{await team_emoji(ctx, this_week[x]["awayteam"])} @ ' \ f'{await team_emoji(ctx, this_week[x]["hometeam"])} ' \ f'`{this_week[x]["hometeam"]["abbrev"]: <4} ({away_losses})`\n' if count > 8: 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 next_week: this_line = f'`{next_week[x]["awayteam"]["abbrev"]: >4}` ' \ f'{await team_emoji(ctx, next_week[x]["awayteam"])} @ ' \ f'{await team_emoji(ctx, next_week[x]["hometeam"])} ' \ f'`{next_week[x]["hometeam"]["abbrev"]: <4}`\n' if count > 8: 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']), ('league_abbrev', 'al'), ('division_abbrev', 'e') ]) div_one = d1_query['standings'] d2_query = await db_get('standings', params=[ ('season', current['season']), ('league_abbrev', 'al'), ('division_abbrev', 'w') ]) div_two = d2_query['standings'] d3_query = await db_get('standings', params=[ ('season', current['season']), ('league_abbrev', 'nl'), ('division_abbrev', 'e') ]) div_three = d3_query['standings'] d4_query = await db_get('standings', params=[ ('season', current['season']), ('league_abbrev', 'nl'), ('division_abbrev', 'w') ]) 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'**AL East**', value=div_one_standings, inline=False) embed.add_field(name=f'**AL West**', value=div_two_standings, inline=False) embed.add_field(name=f'**NL East**', value=div_three_standings, inline=False) embed.add_field(name=f'**NL West**', 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', 'al') ]) 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 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): await db_patch('current', object_id=current['id'], params=[('injury_count', current['injury_count'] + 1)]) 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 log_injury( # current, {'player': player, 'type': 'new', 'current_game': this_game, 'injury_length': inj_games} # ) 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] if not player['il_return']: 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'] await interaction.edit_original_response( content=f'{player["name"]}\'s return was set for {player["il_return"]}.' ) view = Confirm(responders=[interaction.user]) await interaction.edit_original_response( content='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): await db_patch( 'current', object_id=current['id'], params=[('injury_count', current['injury_count'] + 1)] ) 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 log_injury( # current, {'player': player, 'type': 'clear', 'current_game': None, 'injury_length': None} # ) 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( '***S C O R E C A R D S***\n' '**OG Card**:\n\n' '**S6 PCD**:\n\n' '**Foxx\'s**:\n\n' '**Josef\'s**:\n\n\n' '***R E F E R E N C E S***\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).worksheet_by_title('Results') # 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 # try: # away_bats = scorecard.get_values('A3', 'AK19') # home_bats = scorecard.get_values('A33', 'AK49') # away_arms = scorecard.get_values('A22', 'V30') # home_arms = scorecard.get_values('A52', 'V59') # away_team = await get_one_team(away_arms[0][1]) # home_team = await get_one_team(home_arms[0][1]) # week_num = away_bats[0][35] # game_num = home_bats[0][36] # except Exception as e: # logging.error(f'Failed to read scorecard {sheet_url}: {e}') # await interaction.edit_original_response(content=f'Oof, I got you an error:\n\n{e}.') # return # # # Confirm teams and matchup # this_matchup = await get_schedule( # current['season'], away_abbrev=away_team['abbrev'], home_abbrev=home_team['abbrev'], week_start=week_num, # week_end=week_num # ) # if len(this_matchup) != 1: # await interaction.edit_original_response( # content=f'Hmm...it doesn\'t look like {away_team["abbrev"]} played {home_team["abbrev"]} in ' # f'week {week_num}.' # ) # return # # # Confirm stats for game don't already exist # old_home_bat = await get_battingstat( # season=current['season'], team_abbrev=home_team['abbrev'], week_start=week_num, # week_end=week_num, game_num=game_num) # old_away_bat = await get_battingstat( # season=current['season'], team_abbrev=away_team['abbrev'], week_start=week_num, # week_end=week_num, game_num=game_num) # old_home_arm = await get_pitchingstat( # season=current['season'], team_abbrev=home_team['abbrev'], week_start=week_num, # week_end=week_num, game_num=game_num) # old_away_arm = await get_pitchingstat( # season=current['season'], team_abbrev=away_team['abbrev'], week_start=week_num, # week_end=week_num, game_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 # # if len(old_home_bat) + len(old_away_bat) + len(old_home_arm) + len(old_away_arm) > 0: # view = Confirm(responders=[interaction.user]) # question = await interaction.channel.send( # f'I already see stats for {away_team["abbrev"]} @ {home_team["abbrev"]} week {week_num} game ' # f'{game_num}. Would you like me to remove those and update with this card?', # view=view # ) # await view.wait() # # if view.value: # logging.info(f'sba-submit - view.value') # this_game = { # 'season': current['season'], # 'week': week_num, # 'game_num': game_num, # 'away_team_id': away_team['id'], # 'home_team_id': home_team['id'] # } # # await question.edit( # content='What a pain in my balls. Let\'s start by deleting the batting stats...', # view=None # ) # if await delete_battingstats(this_game): # await question.edit(content='Batting stats are gone - now the pitching stats...') # # if await delete_pitchingstats(this_game): # await question.edit( # content='Pitching stats are gone - now to recalculate everybody\'s season batting lines...' # ) # # if await recalc_batting_seasons(current['season'], away_team['id']): # if await recalc_batting_seasons(current['season'], home_team['id']): # await question.edit( # content='Batting lines are done - now to recalculate pitching lines...' # ) # # if await recalc_pitching_seasons(current['season'], away_team['id']): # if await recalc_pitching_seasons(current['season'], home_team['id']): # await question.edit( # content='Pitching lines are done - now to recalculate fielding lines...' # ) # # if await recalc_fielding_seasons(current['season'], away_team['id']): # if await recalc_fielding_seasons(current['season'], home_team['id']): # await question.edit( # content=f'All done. Don\'t suck next time ' # f'{await get_emoji(interaction.guild, "lakemonsters")}' # ) # # week_games = await get_results( # current['season'], away_abbrev=away_team['abbrev'], home_abbrev=home_team['abbrev'], week=week_num # ) # this_game = None # for x in week_games: # if week_games[x]['game'] == game_num: # this_game = week_games[x] # break # if this_game: # await db_delete('results', object_id=this_game['id']) # # else: # logging.info(f'sba-submit - view.value "else"') # await interaction.channel.send('Alright, we\'ll call it a day here.') # return # # logging.info(f'sba-submit - reading scorecard') # # Read scorecard # errors = [] # b_counts = {'sbc': 0, 'csc': 0, 'sb': 0, 'cs': 0, 'so': 0, 'bb': 0, 'run': 0, 'rbi': 0, 'xba': 0, 'xbt': 0, # 'raa': 0, 'rto': 0} # p_counts = {'gs': 0, 'win': 0, 'loss': 0, 'so': 0, 'bb': 0, 'run': 0, 'erun': 0, 'ir': 0, 'irs': 0} # positions = ['C', '1B', '2B', '3B', 'SS', 'LF', 'CF', 'RF', 'DH', 'PH', 'PR', 'P'] # pit_nums = [f'{x}' for x in range(20)] # # bat_stats = ['player', 'team', 'pos', 'pa', 'ab', 'run', 'hit', 'rbi', 'double', 'triple', 'hr', 'bb', 'so', # 'hbp', 'sac', 'ibb', 'gidp', 'sb', 'cs', 'bphr', 'bpfo', 'bp1b', 'bplo', 'xba', 'xbt', 'xch', # 'xhit', 'error', 'pb', 'sbc', 'csc', 'roba', 'robs', 'raa', 'rto', 'week', 'game'] # pit_stats = ['player', 'team', 'ip', 'hit', 'run', 'erun', 'so', 'bb', 'hbp', 'wp', 'balk', 'hr', 'ir', 'irs', # 'gs', 'win', 'loss', 'hold', 'sv', 'bsv', 'week', 'game'] # # new_bat_stats = [] # new_pit_stats = [] # final_box_away = {'r': 0, 'h': 0, 'e': 0, 'ip': 0} # final_box_home = {'r': 0, 'h': 0, 'e': 0, 'ip': 0} # final_wp = None # final_lp = None # final_holds = [] # final_sv = None # final_bsv = [] # final_doubles = [] # final_triples = [] # final_homeruns = [] # final_sbs = [] # final_cscs = [] # # # Read batting stats # for group in [away_bats, home_bats]: # for line in group: # if line[0]: # # Dictionary to hold data to be passed to db for BatStat model # this_batter = {'season': current['season']} # # # Keeping count so we can add stat name and data from sheet into this_batter dict # for count in range(len(bat_stats)): # if line[count] != '' and line[count] != '#REF' and line[count] != 0: # this_batter[bat_stats[count]] = line[count] # # # Add this_batter to collection new_bat_stats # try: # this_batter['player_id'] = self.player_list[line[0].lower()] # this_batter['team_id'] = away_team['id'] if line[1].lower() == away_team['abbrev'].lower() \ # else home_team['id'] # # Check for pitcher int in position # if this_batter['pos'] in pit_nums: # this_batter['pos'] = 'P' # this_bat_stat = BatStat.parse_obj(this_batter) # new_bat_stats.append(this_bat_stat.dict()) # # # Get stats for news-ticker # if this_batter['team_id'] == away_team['id']: # final_box_away['r'] += this_bat_stat.run # final_box_away['h'] += this_bat_stat.hit # final_box_away['e'] += this_bat_stat.error # else: # final_box_home['r'] += this_bat_stat.run # final_box_home['h'] += this_bat_stat.hit # final_box_home['e'] += this_bat_stat.error # # if this_bat_stat.double: # final_doubles.append((this_batter['player_id'], this_bat_stat.double)) # if this_bat_stat.triple: # final_triples.append((this_batter['player_id'], this_bat_stat.triple)) # if this_bat_stat.hr: # final_homeruns.append((this_batter['player_id'], this_bat_stat.hr)) # if this_bat_stat.sb: # final_sbs.append((this_batter['player_id'], this_bat_stat.sb)) # if this_bat_stat.csc: # final_cscs.append((this_batter['player_id'], this_bat_stat.csc)) # # except Exception as e: # errors.append(f'{line[0]}: {e}') # # # Read pitching stats # for group in [away_arms, home_arms]: # for line in group: # if line[0]: # # Dictionary to hold data for PitStat model # this_pitcher = {'season': current['season']} # # # Keeping count so we can add stat name and data from sheet into this_pitcher dict # for count in range(len(pit_stats)): # if line[count] != '' and line[count] != '#REF' and line[count] != 0: # this_pitcher[pit_stats[count]] = line[count] # # # Add this_pitcher to collection new_pit_stats # try: # this_pitcher['player_id'] = self.player_list[line[0].lower()] # this_pitcher['team_id'] = away_team['id'] if line[1].lower() == away_team['abbrev'].lower() \ # else home_team['id'] # this_pit_stat = PitStat.parse_obj(this_pitcher) # # # Update IP to an even third # first_digit = f'{this_pit_stat.ip % 1}'[2] # if first_digit == '0': # this_pit_stat.ip = math.floor(this_pit_stat.ip) # elif first_digit in ['1', '3']: # this_pit_stat.ip = math.floor(this_pit_stat.ip) + (1/3) # else: # this_pit_stat.ip = math.floor(this_pit_stat.ip) + (2/3) # # new_pit_stats.append(this_pit_stat.dict()) # # # Get stats for news-ticker # if this_pit_stat.win: # final_wp = this_pit_stat.player_id # if this_pit_stat.loss: # final_lp = this_pit_stat.player_id # if this_pit_stat.sv: # final_sv = this_pit_stat.player_id # if this_pit_stat.bsv: # final_bsv.append(this_pit_stat.player_id) # if this_pit_stat.hold: # final_holds.append(this_pit_stat.player_id) # if this_pitcher['team_id'] == away_team['id']: # final_box_away['ip'] += this_pit_stat.ip # else: # final_box_home['ip'] += this_pit_stat.ip # except Exception as e: # errors.append(f'{line[0]}: {e}') # # # Error checks # await interaction.edit_original_response( # content='Just finished reading the scorecard. Now to look for all of your mistakes...' # ) # for line in new_bat_stats: # b_counts['sbc'] += line['sbc'] # b_counts['csc'] += line['csc'] # b_counts['sb'] += line['sb'] # b_counts['cs'] += line['cs'] # b_counts['so'] += line['so'] # b_counts['bb'] += line['bb'] + line['ibb'] # b_counts['run'] += line['run'] # b_counts['rbi'] += line['rbi'] # b_counts['xba'] += line['xba'] # b_counts['xbt'] += line['xbt'] # b_counts['raa'] += line['raa'] # b_counts['rto'] += line['rto'] # if line['pos'] not in positions: # errors.append(f'{line["pos"]} not a valid position') # for line in new_pit_stats: # logging.info(f'line: {line}') # p_counts['gs'] += line['gs'] # p_counts['win'] += line['win'] # p_counts['loss'] += line['loss'] # p_counts['bb'] += line['bb'] # p_counts['so'] += line['so'] # p_counts['run'] += line['run'] # p_counts['erun'] += line['erun'] # p_counts['ir'] += line['ir'] # p_counts['irs'] += line['irs'] # # if b_counts['sbc'] > b_counts['sb'] + b_counts['cs']: # errors.append(f'There are {b_counts["sbc"]} stolen base attempts (SBa), but {b_counts["sb"]} SB and ' # f'{b_counts["cs"]} CS.') # if b_counts['csc'] > b_counts['cs']: # errors.append(f'There are {b_counts["sbc"]} catcher caught stealings (CSc), but ' # f'{b_counts["cs"]} baserunner CS.') # if b_counts['so'] != p_counts['so']: # errors.append(f'There are {b_counts["so"]} batter strikeouts, but {p_counts["so"]} pitcher strikeouts.') # if b_counts['bb'] != p_counts['bb']: # errors.append(f'There are {b_counts["bb"]} batter walks, but {p_counts["bb"]} pitcher.') # if b_counts['run'] != p_counts['run']: # errors.append(f'There are {b_counts["run"]} batter runs, but {p_counts["run"]} pitcher runs.') # if b_counts['rbi'] > b_counts['run']: # errors.append(f'There are {b_counts["rbi"]} runs batted in, but {b_counts["run"]} runs scored.') # if b_counts['rto'] > b_counts['raa']: # errors.append(f'There are {b_counts["rto"]} runners thrown out, but {b_counts["raa"]} runner ' # f'advance attempts.') # if b_counts['xbt'] > b_counts['xba']: # errors.append(f'There are {b_counts["xbt"]} extra bases taken, but {b_counts["xba"]} extra ' # f'base attempts.') # if p_counts['erun'] > p_counts['run']: # errors.append(f'There are {p_counts["erun"]} earned runs and {p_counts["run"]} total runs. ') # if p_counts['gs'] != 2: # errors.append(f'There should be 2 GS, but I see {p_counts["gs"]} of them.') # if p_counts['win'] != 1: # errors.append(f'There should be 1 W, but I see {p_counts["win"]} of them.') # if p_counts['loss'] != 1: # errors.append(f'There should be 1 L, but I see {p_counts["loss"]} of them.') # if p_counts['irs'] > p_counts['ir']: # errors.append(f'There are {p_counts["irs"]} inherited runners scored and {p_counts["ir"]} ' # f'inherited runners.') # # # Post errors, if any, or post stats to db # if len(errors) > 0: # error_message = '\n- '.join(errors) # 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- {error_message}' # ) # logging.error(f'Scorecard errors: {error_message}') # return # else: # bat_conf = await post_battingstats(new_bat_stats) # pit_conf = await post_pitchingstats(new_pit_stats) # # if bat_conf and pit_conf: # await interaction.edit_original_response( # content=f'You did it! I just logged the stats for **wk{week_num}g{game_num}**' # ) # # # Update last games for pitchers # for x in new_pit_stats: # this_pitcher = await get_one_player(x["player_id"]) # game_string = f'{float(x["ip"]):.2}IP w{x["week"]}g{x["game"]}' # await patch_player(this_pitcher['id'], last_game=game_string, last_game2=this_pitcher['last_game']) # else: # await interaction.edit_original_response( # content='So the stats looked okay, but I had an accident when I tried to post them. They ' # 'did not go through.' # ) # # # Post scorecard to weekly archive # 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"]}>' # # try: # # archive_channel = get_channel(interaction, name=f'week-{week_num}-archive') # # logging.info(f'archive_channel: {archive_channel}') # # if not archive_channel: # # archive_channel = await create_channel( # # interaction, # # channel_name=f'week-{week_num}-archive', # # category_name=f'Season {current["season"]} Archives', # # read_send_roles=[get_role(interaction, 'Gameplay Bots')] # # ) # # # # await archive_channel.send( # # f'Game {game_num}: **{away_team["sname"]}** {await team_emoji(interaction, away_team)} ' # # f'{final_box_away["r"]} @ {final_box_home["r"]} ' # # f'{await team_emoji(interaction, home_team)} **{home_team["sname"]}**\n{card_url}') # # except Exception as e: # # await interaction.edit_original_response( # # content='Ope. I wasn\'t able to post this to the archive channel.' # # ) # # # Post box score to news-ticker # # extras = '' # if final_box_home['ip'] > 9: # extras = f' F/{math.floor(final_box_home["ip"])}' # embed = get_team_embed( # f'{away_team["sname"]} {final_box_away["r"]} @ ' # f'{final_box_home["r"]} {home_team["sname"]}{extras}', # team=away_team if final_box_away['r'] > final_box_home['r'] 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} | {final_box_away["r"]: >2} | {final_box_away["h"]: >2} | ' # f'{final_box_away["e"]: >2} |\n' # f'{home_team["abbrev"]: <4} | {final_box_home["r"]: >2} | {final_box_home["h"]: >2} | ' # f'{final_box_home["e"]: >2} |\n' # f'```', # inline=False # ) # # wp = await get_one_player(final_wp) # lp = await get_one_player(final_lp) # if final_sv: # sv = await get_one_player(final_sv) # else: # sv = None # holds = [] # bsvs = [] # for x in final_holds: # holds.append(await get_one_player(x)) # for x in final_bsv: # bsvs.append(await get_one_player(x)) # # 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 += ', ' # elif len(holds) > 0: # hold_string += '\n' # count += 1 # pitching_string += hold_string # # if sv: # pitching_string += f'SV: {sv["name"]}' # # embed.add_field(name='Pitching', value=pitching_string, 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})' # ) # embed.set_footer(text='Please share the highlights!') # # await send_to_channel( # self.bot, # 'sba-network-news', # content=None, # embed=embed # ) # # result = { # 'week': week_num, # 'game': game_num, # 'away_team_id': away_team['id'], # 'home_team_id': home_team['id'], # 'away_score': final_box_away["r"], # 'home_score': final_box_home["r"], # 'season': current['season'], # 'scorecard_url': sheet_url # } # if await db_post('results', payload={'results': [result]}): # update = await interaction.channel.send('I\'m tallying standings now...') # if await db_post(f'standings/s{current["season"]}/recalculate'): # await update.delete() @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=0.5).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', color_hex)]) show_mil = 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') if mil_team_image_url is not None: if requests.get(mil_team_image_url, timeout=0.5).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='setcolor', help='Set team color') # @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) # async def set_color_command(self, ctx, color_code): # current = await db_get('current') # team = await get_team_by_owner(current['season'], ctx.author.id) # team_role = get_team_role(ctx, team) # color_int = int(color_code, 16) # # if not team or not team_role: # await ctx.send(f'Do you have a team here? You don\'t look familiar. {await get_emoji(ctx, "realeyes")}') # return # # await team_role.edit(colour=color_int) # await patch_team(team, color=color_code) # team = await get_team_by_owner(current['season'], ctx.author.id) # # embed = get_team_embed(f'{team["lname"]} Test', team=team) # embed.add_field( # name='Reminder', # value='Don\'t forget to set your team thumbnail image with the !setthumbnail command!' # ) # await ctx.send(content='Got it! What do you think?', embed=embed) # # @commands.command(name='setthumbnail', help='Set team pic') # @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) # async def set_thumbnail_command(self, ctx, thumbnail_url): # current = await db_get('current') # team = await get_team_by_owner(current['season'], ctx.author.id) # team_role = get_team_role(ctx, team) # # if not team or not team_role: # await ctx.send(f'Do you have a team here? You don\'t look familiar. {await get_emoji(ctx, "realeyes")}') # return # # if requests.get(thumbnail_url, timeout=0.5).status_code != 200: # await ctx.send('I wasn\'t able to pull that thumbnail. Was it a public URL?') # # await patch_team(team, thumbnail=thumbnail_url) # team = await get_team_by_owner(current['season'], ctx.author.id) # # embed = get_team_embed(f'{team["lname"]} Test', team=team) # embed.add_field( # name='Reminder', # value='Don\'t forget to set your team color with the !setcolor command!' # ) # # await ctx.send(content='Got it! What do you think?', embed=embed) # # @commands.command(name='setminorthumbnail', help='Set minor team pic') # @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) # async def set_minor_pic_command(self, ctx, thumbnail_url): # current = await db_get('current') # team = await get_team_by_owner(current['season'], ctx.author.id) # minor_team = await get_one_team(team['id'] + 2) # # if not minor_team: # await ctx.send(f'Do you have a team here? You don\'t look familiar. {await get_emoji(ctx, "realeyes")}') # return # # if requests.get(thumbnail_url, timeout=0.5).status_code != 200: # await ctx.send('I wasn\'t able to pull that thumbnail. Was it a public URL?') # # await patch_team(minor_team, thumbnail=thumbnail_url) # minor_team = await get_one_team(team['id'] + 2) # # embed = get_team_embed(f'{minor_team["sname"]} Test', team=minor_team) # embed.add_field( # name='Reminder', # value='Don\'t forget to set your team color with the !setminorcolor command!' # ) # await ctx.send(content='Got it! What do you think?', embed=embed) # # @commands.command(name='setminorcolor', help='Set minor team color') # @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) # async def set_minor_color_command(self, ctx, color_code): # current = await db_get('current') # team = await get_team_by_owner(current['season'], ctx.author.id) # minor_team = await get_one_team(team['id'] + 2) # # if not minor_team: # await ctx.send(f'Do you have a team here? You don\'t look familiar. {await get_emoji(ctx, "realeyes")}') # return # # await patch_team(minor_team, color=color_code) # minor_team = await get_one_team(team['id'] + 2) # team = await get_team_by_owner(current['season'], ctx.author.id) # # embed = get_team_embed(f'{minor_team["sname"]} Test', team=minor_team) # embed.add_field( # name='Reminder', # value='Don\'t forget to set your team thumbnail image with the !setminorthumbnail command!' # ) # await ctx.send(content='Got it! What do you think?', embed=embed) # # @commands.command(name='setdicecolor', help='Set dice embed color') # @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) # async def set_dice_color_command(self, ctx, color_code): # current = await db_get('current') # team = await get_team_by_owner(current['season'], ctx.author.id) # # await patch_team(team, dice_color=color_code) # embed = discord.Embed( # title=f'Dice Color: {color_code}', # color=int(color_code, 16) # ) # embed.add_field( # name='Reminder', # value='Any dice rolled in your home stadium will use this color!' # ) # await ctx.send(content=None, embed=embed) @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 # current = await db_get('current') # # if team_abbrev: # team = await get_one_team(team_abbrev[0]) # else: # team = await get_team_by_owner(current['season'], ctx.author.id) # # if not team: # await ctx.send('I don\'t know what team you\'re looking for.') # return # # raw_picks = await get_draftpicks(season=5, owner_team=team, team_season=5) # logging.info(f'raw_picks: {raw_picks}') # try: # all_picks = dict(sorted(raw_picks.items(), key=lambda item: item[1]["overall"])) # except TypeError as e: # all_picks = dict(sorted(raw_picks.items(), key=lambda item: item[1]["round"])) # pick_string = '' # # for x in all_picks: # squiggles = '~~' if all_picks[x]['player'] else '' # selection = f'- {all_picks[x]["player"]["name"]}' if all_picks[x]["player"] else '' # overall = f'#{all_picks[x]["overall"]} - ' if all_picks[x]["overall"] else '' # pick_string += f'{squiggles}{overall}{all_picks[x]["origowner"]["abbrev"]} {all_picks[x]["round"]}' \ # f'{squiggles} {selection}\n' # # embed = get_team_embed(f'{team["lname"]}', team=team) # embed.add_field(name=f'Season {current["season"]} Draft Picks', value=pick_string) # # await ctx.send(content=None, embed=embed) # @commands.command(name='fixscore', help='Change result') # @commands.has_any_role(SBA_PLAYERS_ROLE_NAME) # async def fix_score_command( # self, ctx, away_team, away_score: int, home_team, home_score: int, week_num: int, game_num: int): # current = await db_get('current') # week_games = await get_results(current['season'], away_abbrev=away_team, home_abbrev=home_team, week=week_num) # this_game = None # # for x in week_games: # if week_games[x]['game'] == game_num: # this_game = week_games[x] # break # # if this_game is None: # await ctx.send('I don\'t see a record of that game. Make sure you\'ve got the week and game number right. ' # 'If so, go ahead and log it with the !result command') # return # # if this_game['awayscore'] == away_score and this_game['homescore'] == home_score: # await ctx.send('Good news, everyone! That is already the score I have listed!') # return # # await ctx.send(f'I\'ve got that game listed as {this_game["awayteam"]["abbrev"]} ' # f'{await team_emoji(ctx, this_game["awayteam"])} {this_game["awayscore"]} @ ' # f'{this_game["homescore"]} {await team_emoji(ctx, this_game["hometeam"])} ' # f'{this_game["hometeam"]["abbrev"]}') # prompt = f'Would you like to change this to {this_game["awayteam"]["abbrev"]} ' \ # f'{await team_emoji(ctx, this_game["awayteam"])} {away_score} @ ' \ # f'{home_score} {await team_emoji(ctx, this_game["hometeam"])} {this_game["hometeam"]["abbrev"]}?' # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 30) # resp = await this_q.ask([ctx.author]) # # if not resp: # await ctx.send('Mmkay. I\'ll leave it alone for now.') # return # else: # if await patch_result(this_game['id'], away_score=away_score, home_score=home_score): # await ctx.message.add_reaction('✅') # await ctx.send(f'{get_team_role(ctx, this_game["awayteam"]).mention} ' # f'{get_team_role(ctx, this_game["hometeam"]).mention}') # await ctx.send(random_conf_gif()) # @commands.command(name='newaward', help='Grant award') # @commands.has_any_role('Awards Team', 'Da Commish') # async def new_award_command(self, ctx, *, award_name): # # f'{"In-Season" if in_or_off.lower() == "in" else "Off-Season"}' # current = await db_get('current') # award = { # 'name': award_name, # 'season': None, # 'timing': None, # 'manager1': None, # 'manager2': None, # 'player': None, # 'team': None, # 'image': None, # 'invalid': False # } # # async def add_recipient(search_string): # try: # this_team = await get_one_team(search_string, season=award['season']) # award['team'] = this_team # except ValueError: # try: # this_manager = await get_one_manager(search_string) # if not award['manager1']: # award['manager1'] = this_manager # else: # award['manager2'] = this_manager # except ValueError: # try: # search_name = await fuzzy_player_search( # ctx, ctx.channel, self.bot, search_string, self.player_list) # this_player = await get_one_player(search_name, season=award['season']) # award['player'] = this_player # except ValueError: # try: # this_player = await get_one_player(search_string, season=award['season']) # award['player'] = this_player # except ValueError: # await ctx.send(f'I do not recognize **{search_string}**. Will you check the spelling and ' # f'try again?') # # def get_embed(): # this_embed = discord.Embed(title=award['name']) # this_embed.description = f'{award["timing"]} - S{award["season"]}' # if award['manager1']: # this_embed.add_field(name='Manager', value=award['manager1']) # if award['manager2']: # this_embed.add_field(name='Manager', value=award['manager2']) # if award['player']: # this_embed.add_field(name='Player', value=f'{award["player"]["name"]}') # if award['team']: # this_embed.add_field(name='Team', value=f'{award["team"]["lname"]}') # if award['image']: # try: # this_embed.set_image(url=award['image']) # except: # award['invalid'] = True # this_embed.add_field(name='Image', value='Invalid URL') # return this_embed # # prompt = f'Is this for season {current["season"]}?' # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', timeout=45) # resp = await this_q.ask([ctx.author]) # # if resp is None: # await ctx.send('Think on it. Get back to me.') # return # elif resp: # award['season'] = current['season'] # else: # prompt = 'Please enter the season for this award.' # this_q = Question(self.bot, ctx.channel, prompt, 'int', timeout=45) # resp = await this_q.ask([ctx.author]) # # if not resp: # await ctx.send('Think on it. Get back to me.') # return # else: # award['season'] = resp # # prompt = f'Is this an In-Season award (as opposed to off-season)?' # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', timeout=45) # resp = await this_q.ask([ctx.author]) # # if resp is None: # await ctx.send('Think on it. Get back to me.') # return # elif resp: # award['timing'] = 'In-Season' # else: # award['timing'] = 'Off-Season' # await ctx.send('Got it - I\'ll put this down as an Off-Season award') # # prompt = 'Is this the start you wanted?' # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', timeout=45, embed=get_embed()) # resp = await this_q.ask([ctx.author]) # # if not resp: # await ctx.send('No worries - run `!newaward Award_Name` again to rename it.') # return # # # Get team/player/managers # while True: # prompt = 'Please enter the team abbreviation, player name, or manager name of the recipient.' # this_q = Question(self.bot, ctx.channel, prompt, 'text', timeout=45) # resp = await this_q.ask([ctx.author]) # # if resp is None: # await ctx.send('You think on it and hit me up when you\'re ready.') # return # else: # await add_recipient(resp) # # await ctx.send('Here is the current award', embed=get_embed()) # # prompt = 'Would you like to (re)enter a recipient?' # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', timeout=45) # resp = await this_q.ask([ctx.author]) # # if resp is None: # await ctx.send('We can hold off on this for now. Let me know when you\'re ready to start again.') # return # elif not resp: # break # # # Get image URL # while True: # prompt = 'Would you like to (re)enter an image URL for this award?' # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', timeout=45, embed=get_embed()) # resp = await this_q.ask([ctx.author]) # # if not resp: # break # else: # prompt = 'Please enter the image URL.' # this_q = Question(self.bot, ctx.channel, prompt, 'url', timeout=45) # resp = await this_q.ask([ctx.author]) # # if resp is None: # await ctx.send('Okey doke, nevermind. I get it. It\'s fine. We only did all this work for nothing. ' # 'Let me know when you want to start again.') # return # elif not resp: # await ctx.send(f'**{resp}** is not a valid URL.') # else: # award['image'] = resp # # prompt = 'Would you like to submit this award?' # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', timeout=45, embed=get_embed()) # resp = await this_q.ask([ctx.author]) # # if not resp: # await ctx.send('Really? After all the ti- nevermind. Fine. Kill it. It\'s over. Bye.') # return # else: # await post_award(award) # await ctx.send(random_conf_gif()) # # @commands.command(name='record', help='Record through week num') # async def record_command(self, ctx, team_abbrev, week_num: int): # this_team = await get_one_team(team_abbrev) # this_record = await get_team_record(this_team, week_num) # # await ctx.send(f'The {this_team["sname"]} were ({this_record["w"]}-{this_record["l"]}) through ' # f'week {week_num}.') @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}') await ctx.send(f'Just created {this_vc} for you!') while True: await asyncio.sleep(900) if len(this_vc.members) == 0: await this_vc.delete() logging.info(f'Just deleted voice channel: {channel_name}') 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 s_query = await db_get('schedules', params=[ ('season', current['season']), ('team_abbrev', this_team['abbrev']), ('week_start', current['week']), ('week_end', current['week']), ('short_output', False) ]) if s_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_matchup = s_query['schedules'][0] if this_team == this_matchup['awayteam']: other_team = this_matchup['hometeam'] else: other_team = this_matchup['awayteam'] channel_name = f'{this_matchup["awayteam"]["sname"]} @ {this_matchup["hometeam"]["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 resp is None: await ctx.send('Fine. I bet they didn\'t wanna talk to you anyway.') return elif not resp: channel_name = f'{this_team["abbrev"]} vs {other_team["abbrev"]}' 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') ) await ctx.send(f'Just created {this_vc} for you!') while True: await asyncio.sleep(900) if len(this_vc.members) == 0: await this_vc.delete() 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: this_game = get_one_game(channel_id=interaction.channel_id) if not this_game: await interaction.response.send_message( 'Uhh...I don\'t see any games in this channel. You in the right place?' ) return embed = self.bot.get_cog('Gameplay').get_game_state_embed(this_game, full_length=False) await interaction.response.send_message(content=None, embed=embed) score_text = this_scorecard.get_value('A1') await interaction.response.send_message(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='86', value=86), Choice(name='80', value=80), Choice(name='70', value=70), 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': { 'p86': ['OK', 'OK', 'OK', 'OK', 'OK', 'OK', 'REM', 'REM', 1, 1, 2, 2, 3, 3, 4, 5], 'p80': [2, 2, 'OK', 'REM', 1, 2, 3, 3, 4, 4, 5, 5, 6, 8, 12, 16], 'p70': ['OK', 'OK', 'REM', 1, 2, 3, 4, 5, 5, 6, 6, 8, 12, 16, 20, 20], 'p60': ['OK', 'REM', 1, 2, 3, 4, 5, 6, 6, 8, 12, 12, 16, 20, 20, 'OK'], 'p50': ['OK', 1, 2, 3, 4, 5, 6, 8, 8, 12, 12, 16, 20, 30, 'REM', 'OK'], 'p40': ['OK', 5, 1, 3, 5, 6, 8, 12, 12, 16, 20, 30, 4, 2, 'REM', 'OK'], 'p30': ['OK', 1, 2, 5, 6, 8, 12, 16, 20, 30, 12, 8, 4, 3, 'REM', 'OK'], 'p20': ['OK', 1, 2, 5, 6, 12, 12, 30, 20, 16, 16, 8, 4, 3, 'REM', 'OK'] }, 'two': { 'p86': [4, 3, 2, 2, 1, 1, 'REM', 'OK', 'REM', 'OK', 2, 1, 2, 2, 3, 5], 'p80': [12, 6, 4, 2, 2, 'OK', 1, 'OK', 'REM', 1, 'REM', 2, 3, 5, 8, 16], 'p70': [1, 3, 4, 6, 2, 2, 'OK', 1, 3, 'REM', 4, 5, 8, 12, 16, 3], 'p60': [5, 'OK', 'OK', 'REM', 1, 2, 5, 3, 4, 6, 4, 8, 12, 16, 16, 'OK'], 'p50': ['OK', 'OK', 'REM', 1, 2, 3, 4, 5, 6, 5, 8, 12, 16, 20, 20, 'OK'], 'p40': ['OK', 'REM', 1, 2, 3, 4, 5, 6, 8, 6, 12, 16, 20, 30, 'REM', 'OK'], 'p30': ['OK', 1, 2, 4, 5, 6, 8, 6, 12, 16, 8, 20, 30, 3, 5, 'REM'], 'p20': ['OK', 1, 4, 5, 6, 6, 8, 8, 16, 12, 20, 30, 12, 3, 2, 'REM'] }, 'three': { 'p86': [], 'p80': ['OK', 'OK', 'REM', 1, 3, 'OK', 'REM', 1, 2, 1, 2, 3, 4, 5, 6, 'REM'], 'p70': ['OK', 6, 'OK', 'REM', 1, 2, 2, 3, 4, 5, 1, 3, 6, 8, 12, 'REM'], 'p60': ['OK', 'OK', 'REM', 1, 2, 3, 4, 5, 6, 4, 5, 8, 12, 12, 16, 'REM'], 'p50': ['OK', 1, 1, 2, 3, 4, 5, 6, 8, 6, 8, 12, 12, 16, 5, 'REM'], 'p40': ['OK', 1, 2, 3, 4, 6, 5, 8, 6, 8, 12, 12, 16, 20, 1, 'REM'], 'p30': ['OK', 2, 3, 4, 5, 8, 6, 8, 12, 12, 16, 6, 20, 30, 1, 'REM'], 'p20': ['OK', 1, 2, 4, 5, 12, 12, 8, 6, 16, 8, 20, 30, 3, 5, 'REM'] }, 'four': { 'p86': [], 'p80': [], 'p70': ['OK', 'OK', 'REM', 3, 3, 'OK', 'REM', 1, 2, 1, 4, 5, 6, 8, 12, 'REM'], 'p60': ['OK', 8, 4, 'OK', 'REM', 1, 2, 4, 5, 3, 6, 3, 8, 12, 16, 'REM'], 'p50': ['OK', 'OK', 'REM', 1, 2, 3, 4, 5, 6, 4, 5, 8, 12, 12, 16, 'REM'], 'p40': ['OK', 1, 1, 2, 3, 4, 5, 6, 8, 6, 8, 12, 12, 16, 5, 'REM'], 'p30': ['OK', 'REM', 2, 3, 4, 5, 6, 6, 8, 8, 16, 12, 12, 1, 20, 'REM'], 'p20': ['OK', 1, 2, 3, 4, 6, 5, 8, 6, 8, 16, 12, 12, 20, 1, 'REM'] }, 'five': { 'p86': [], 'p80': [], 'p70': [], 'p60': ['OK', 'OK', 'REM', 1, 1, 'OK', 'REM', 3, 2, 4, 5, 6, 8, 6, 12, 16], 'p50': ['OK', 8, 8, 'OK', 1, 3, 2, 4, 5, 6, 'REM', 3, 12, 8, 16, 1], 'p40': ['OK', 'OK', 'REM', 5, 1, 2, 6, 4, 8, 3, 5, 12, 6, 8, 16, 'REM'], 'p30': ['OK', 'REM', 2, 3, 5, 4, 6, 5, 8, 6, 12, 8, 3, 1, 16, 'REM'], 'p20': ['OK', 'REM', 2, 3, 5, 4, 6, 5, 8, 6, 12, 8, 12, 1, 16, 'REM'] }, 'six': { 'p86': [], 'p80': [], 'p70': [], 'p60': [], 'p50': ['OK', 8, 3, 'OK', 1, 3, 2, 4, 5, 6, 'REM', 8, 12, 3, 16, 1], 'p40': ['OK', 'OK', 'REM', 5, 1, 3, 8, 4, 6, 2, 5, 12, 3, 4, 16, 'REM'], 'p30': ['OK', 'REM', 4, 5, 2, 3, 6, 4, 8, 5, 12, 6, 3, 1, 16, 'REM'], 'p20': ['OK', 'REM', 2, 3, 5, 4, 6, 5, 8, 6, 12, 8, 12, 1, 16, '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'])) ) 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))