2968 lines
138 KiB
Python
2968 lines
138 KiB
Python
import math
|
|
import pydantic
|
|
import re
|
|
|
|
from discord import app_commands
|
|
from discord.ext import tasks
|
|
|
|
from db_calls_gameplay import get_one_game
|
|
from helpers import *
|
|
from db_calls import *
|
|
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 <command_name> to see the command requirements')
|
|
|
|
async def slash_error(self, ctx, error):
|
|
await ctx.send(f'{error}')
|
|
|
|
@tasks.loop(count=1)
|
|
async def build_master_player_list(self):
|
|
current = await get_current()
|
|
all_players = await get_players(current['season'])
|
|
self.player_list = {all_players[player]['name'].lower(): all_players[player]['id'] for player in all_players}
|
|
logging.debug(f'player list: {self.player_list}')
|
|
logging.warning(f'player list count: {len(self.player_list)}')
|
|
|
|
@staticmethod
|
|
async def update_injuries(ctx):
|
|
current = await 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 get_players(current['season'], 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):
|
|
this_week = await get_schedule(
|
|
current['season'],
|
|
week_start=current['week'],
|
|
week_end=current['week']
|
|
)
|
|
results_this_week = await get_results(
|
|
current['season'],
|
|
week=current['week']
|
|
)
|
|
|
|
game_count = 0
|
|
for x in this_week:
|
|
game_count += this_week[x]['gamecount']
|
|
|
|
return {'games_played': len(results_this_week), '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:
|
|
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, *abbrev):
|
|
current = await get_current()
|
|
|
|
# Get Team
|
|
if abbrev:
|
|
team = await get_one_team(abbrev[0])
|
|
else:
|
|
team = await get_team_by_owner(current['season'], ctx.author.id)
|
|
|
|
# Create team embed
|
|
embed = get_team_embed(f'{team["lname"]} Overview', team)
|
|
|
|
# Get standings
|
|
if team['abbrev'][-2:].lower() != 'il':
|
|
try:
|
|
team_standings = await get_standings(current['season'], team_abbrev=team['abbrev'])
|
|
if team_standings:
|
|
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_players = await get_players(current['season'], team_abbrev=f'{team["abbrev"]}IL', sort='wara-desc')
|
|
players = await get_players(current['season'], team_abbrev=team['abbrev'], sort='wara-desc')
|
|
il_wara = 0
|
|
active_wara = 0
|
|
|
|
if il_players:
|
|
for x in il_players:
|
|
il_wara += il_players[x]['wara']
|
|
|
|
if players:
|
|
count = 0
|
|
top_player_string = ''
|
|
|
|
for x in players:
|
|
if count < 5:
|
|
top_player_string += f'{players[x]["pos_1"]} {players[x]["name"]} ({players[x]["wara"]:.2f})\n'
|
|
active_wara += players[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}')
|
|
|
|
# Get near schedule
|
|
team_schedule = await get_schedule(
|
|
current['season'],
|
|
team_abbrev1=team["abbrev"],
|
|
week_start=current['week'],
|
|
week_end=current['week']+2 if current['week']+2 > 0 else 2,
|
|
)
|
|
if team_schedule:
|
|
this_week_string = ''
|
|
upcoming_string = ''
|
|
|
|
full_sched = dict(sorted(team_schedule.items(), key=lambda item: item[1]["id"]))
|
|
|
|
for matchup in full_sched:
|
|
if full_sched[matchup]['hometeam'] == team:
|
|
opp_record = await get_standings(
|
|
season=current['season'],
|
|
team_abbrev=full_sched[matchup]['awayteam']['abbrev']
|
|
)
|
|
else:
|
|
opp_record = await get_standings(
|
|
season=current['season'],
|
|
team_abbrev=full_sched[matchup]['hometeam']['abbrev']
|
|
)
|
|
if full_sched[matchup]['week'] == current['week']:
|
|
if full_sched[matchup]['hometeam'] == team:
|
|
this_week_string += f'Week {current["week"]}: vs ' \
|
|
f'{full_sched[matchup]["awayteam"]["lname"]} ' \
|
|
f'({opp_record["wins"]}-{opp_record["losses"]})\n'
|
|
else:
|
|
this_week_string += f'Week {current["week"]}: @ {full_sched[matchup]["hometeam"]["lname"]} ' \
|
|
f'({opp_record["wins"]}-{opp_record["losses"]})\n'
|
|
else:
|
|
if full_sched[matchup]['hometeam'] == team:
|
|
upcoming_string += f'Week {full_sched[matchup]["week"]}: vs ' \
|
|
f'{full_sched[matchup]["awayteam"]["lname"]} ' \
|
|
f'({opp_record["wins"]}-{opp_record["losses"]})\n'
|
|
else:
|
|
upcoming_string += f'Week {full_sched[matchup]["week"]}: @ ' \
|
|
f'{full_sched[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 get_current()
|
|
|
|
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):
|
|
player = await get_one_player(
|
|
await fuzzy_player_search(ctx, ctx.channel, self.bot, name, self.player_list.keys())
|
|
)
|
|
# Season is included
|
|
else:
|
|
season = int(player_search.group(1)[1:])
|
|
|
|
try:
|
|
player = await get_one_player(player_search.group(2), season=season)
|
|
except Exception as e:
|
|
logging.error(e)
|
|
async with ctx.typing():
|
|
all_players = await get_players(season)
|
|
all_player_names = {all_players[player]['name'].lower(): all_players[player]['id'] for player in all_players}
|
|
player = await get_one_player(
|
|
await fuzzy_player_search(ctx, ctx.channel, self.bot, player_search.group(2).strip(), all_player_names),
|
|
season=season
|
|
)
|
|
|
|
embed = await get_player_embed(player, current, ctx)
|
|
|
|
await ctx.send(content=None, embed=embed)
|
|
if player['image2']:
|
|
embed = get_team_embed(f'{player["name"]}', player["team"], thumbnail=False)
|
|
embed.set_image(url=player['image2'])
|
|
await ctx.send(content=None, embed=embed)
|
|
|
|
@commands.command(name='career', help='Get player\'s career stats')
|
|
async def career_command(self, ctx, *, name):
|
|
# 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):
|
|
current = await 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: str):
|
|
current = await 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)
|
|
|
|
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)
|
|
|
|
@commands.command(name='standings', help='Current standings')
|
|
async def standings_command(self, ctx):
|
|
current = await get_current()
|
|
div_one = await get_standings(current['season'], league_abbrev='al', division_abbrev='e')
|
|
div_two = await get_standings(current['season'], league_abbrev='al', division_abbrev='w')
|
|
div_three = await get_standings(current['season'], league_abbrev='nl', division_abbrev='e')
|
|
div_four = await get_standings(current['season'], league_abbrev='nl', division_abbrev='w')
|
|
|
|
div_one_standings = f'```\nTeam W-L PCT GB E# RD\n'
|
|
for team in div_one:
|
|
div_one_standings += self.team_stan_line(div_one[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(div_two[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(div_three[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(div_four[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)
|
|
embed.set_footer(text='Run !wildcard to see wildcard standings')
|
|
|
|
await ctx.send(content=None, embed=embed)
|
|
|
|
@commands.command(name='wildcard', aliases=['wc'], help='Current wildcard')
|
|
async def wildcard_command(self, ctx):
|
|
current = await get_current()
|
|
|
|
al_teams = await get_standings(current['season'], league_abbrev='al')
|
|
nl_teams = await get_standings(current['season'], league_abbrev='nl')
|
|
|
|
al_wildcard = f'```\nTeam W-L PCT GB E# RD\n'
|
|
for team in al_teams:
|
|
al_wildcard += self.team_stan_line(al_teams[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(nl_teams[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)
|
|
embed.set_footer(text='Run !standings to see divisional standings')
|
|
|
|
await ctx.send(content=None, embed=embed)
|
|
|
|
# @commands.command(name='setinjury', aliases=['clearinjury'], help='!SetInjury or !ClearInjury')
|
|
# @commands.has_any_role(SBA_PLAYERS_ROLE_NAME)
|
|
# async def set_injury_command(self, ctx, *, player_name):
|
|
# await ctx.send('This command has been deprecated. Please use `/setinjury` or `/clearinjury`')
|
|
# return
|
|
#
|
|
# current = await get_current()
|
|
#
|
|
# player = await get_one_player(player_name)
|
|
#
|
|
# # Check if player is on owner's team
|
|
# team = await get_team_by_owner(current['season'], ctx.author.id)
|
|
# if not player['team'] == team and not player['team']['abbrev'][:len(team['abbrev'])] == team['abbrev']:
|
|
# await ctx.send(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
|
|
#
|
|
# embed = get_team_embed(f'Injury Update', team=team)
|
|
# if player['il_return']:
|
|
# # Confirm injury is over
|
|
# old_injury = player['il_return']
|
|
# prompt = f'{player["name"]}\'s return was set for {player["il_return"]}. Is he eligible to play again?'
|
|
# this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 60.0)
|
|
# resp = await this_q.ask([ctx.author])
|
|
# if not resp:
|
|
# await ctx.send('Okay, let me know when it\'s over.')
|
|
# return
|
|
# else:
|
|
# player['il_return'] = None
|
|
# if await patch_player(player['id'], il_return=False):
|
|
# embed.add_field(
|
|
# name=f'{player["name"]}',
|
|
# value=f'{team["sname"]} {player["pos_1"]} {player["name"]}\'s injury ({old_injury}) has ended'
|
|
# )
|
|
# # await log_channel.send(
|
|
# # f'{player["team"]["sname"]} {player["pos_1"]} {player["name"]}\'s IL stint is over.'
|
|
# # )
|
|
# else:
|
|
# # Get injury end date
|
|
# prompt = f'When is {player["name"]} eligible to play again? (eg: w17g2)'
|
|
# this_q = Question(self.bot, ctx.channel, prompt, 'text', 60.0)
|
|
# resp = await this_q.ask([ctx.author])
|
|
# injury_pattern = 'wk[0-9]+g[1-7]|w[0-9]+g[1-7]'
|
|
#
|
|
# if not resp:
|
|
# await ctx.send('Tell you hwat. You recount it. Math is hard. Then you can get back to me.')
|
|
# return
|
|
# elif not re.search(injury_pattern, resp.lower()):
|
|
# await ctx.send('I, uh...I was expecting something shorter like this: w12g4. Try again maybe?')
|
|
# return
|
|
# else:
|
|
# date_list = re.split('[a-z]+', resp.lower())
|
|
# return_date = f'w{date_list[1]:0>2}g{date_list[2]}'
|
|
# player['il_return'] = return_date
|
|
# if await patch_player(player['id'], il_return=return_date):
|
|
# embed.add_field(
|
|
# name=f'{player["name"]}',
|
|
# value=f'{team["sname"]} {player["pos_1"]} {player["name"]} is injured until {return_date}'
|
|
# )
|
|
# # await log_channel.send(
|
|
# # f'{player["team"]["sname"]} {player["pos_1"]} {player["name"]} can return {player["il_return"]}'
|
|
# # )
|
|
#
|
|
# await ctx.send(random_salute_gif())
|
|
# await send_to_channel(self.bot, 'sba-network-news', content=None, embed=embed)
|
|
# await self.update_injuries(ctx)
|
|
|
|
@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):
|
|
current = await get_current()
|
|
|
|
player = await get_one_player(player_name)
|
|
|
|
# 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.response.send_message(
|
|
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}'
|
|
if await patch_player(player['id'], il_return=return_date):
|
|
await patch_current(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.response.send_message(random_salute_gif())
|
|
await send_to_channel(self.bot, 'sba-network-news', content=None, embed=embed)
|
|
await self.update_injuries(interaction)
|
|
else:
|
|
await interaction.response.send_message('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):
|
|
current = await get_current()
|
|
player = await get_one_player(player_name)
|
|
|
|
if not player['il_return']:
|
|
await interaction.response.send_message('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.response.send_message(
|
|
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.response.send_message(f'{player["name"]}\'s return was set for {player["il_return"]}.')
|
|
view = Confirm(responders=[interaction.user])
|
|
question = await interaction.channel.send('Is he eligible to play again?', view=view)
|
|
await view.wait()
|
|
|
|
if view.value:
|
|
player['il_return'] = None
|
|
if await patch_player(player['id'], il_return=False):
|
|
await patch_current(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 question.edit(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.response.message_update('Well that didn\'t work.')
|
|
else:
|
|
await question.edit(content='You keep thinking on it.', view=None)
|
|
|
|
# @commands.command(name='result', help='Log result')
|
|
# @commands.has_any_role(SBA_PLAYERS_ROLE_NAME)
|
|
# async def result_command(
|
|
# self, ctx, away_abbrev: str, away_score: int, home_abbrev: str, home_score: int, *week: int):
|
|
# # current = await get_current()
|
|
# # away_team = await get_one_team(away_abbrev)
|
|
# # home_team = await get_one_team(home_abbrev)
|
|
# # this_week = week[0] if week else current['week']
|
|
# #
|
|
# # this_matchup = await get_schedule(current['season'], week_start=this_week, week_end=this_week,
|
|
# # away_abbrev=away_team["abbrev"], home_abbrev=home_team["abbrev"])
|
|
# # these_results = await get_results(current['season'], week=this_week, away_abbrev=away_team["abbrev"],
|
|
# # home_abbrev=home_team["abbrev"])
|
|
# #
|
|
# # # Check if scores match a weekly matchup
|
|
# # game_count = 0
|
|
# # legal = False
|
|
# # for x in this_matchup:
|
|
# # if this_matchup[x]['awayteam'] == away_team and this_matchup[x]['hometeam'] == home_team:
|
|
# # legal = True
|
|
# # game_count = this_matchup[x]['gamecount']
|
|
# # if not legal:
|
|
# # raise ValueError(f'I do not see a matchup between {away_team["abbrev"]} and {home_team["abbrev"]} '
|
|
# # f'in week {this_week}')
|
|
# #
|
|
# # # Check if author is gm of these teams or the bot owner
|
|
# # if ctx.author.id not in [away_team['gmid'], away_team['gmid2'], home_team['gmid'], home_team['gmid2']] \
|
|
# # and ctx.author.id != self.bot.owner_id:
|
|
# # await ctx.message.add_reaction('❌')
|
|
# # raise PermissionError('Only GMs of these teams can enter results')
|
|
# #
|
|
# # if len(these_results) >= game_count:
|
|
# # raise ValueError('It looks like that series is complete')
|
|
# #
|
|
# # prompt = f'Should I log {away_team["abbrev"]} {await team_emoji(ctx, away_team)} {away_score} @ ' \
|
|
# # f'{home_score} {await team_emoji(ctx, home_team)} {home_team["abbrev"]} ' \
|
|
# # f'as w{this_week}g{len(these_results) + 1}?'
|
|
# # this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 45)
|
|
# # resp = await this_q.ask([ctx.author])
|
|
# #
|
|
# # if not resp:
|
|
# # await ctx.send('No worries, I\'ll be here when you\'re ready.')
|
|
# # return
|
|
# # else:
|
|
# # result = {
|
|
# # 'week': this_week,
|
|
# # 'game': len(these_results) + 1,
|
|
# # 'away_team_id': away_team['id'],
|
|
# # 'home_team_id': home_team['id'],
|
|
# # 'away_score': away_score,
|
|
# # 'home_score': home_score,
|
|
# # 'season': current['season']
|
|
# # }
|
|
# # if await post_result(result):
|
|
# # await ctx.message.add_reaction('✅')
|
|
# # await ctx.send(random_conf_gif())
|
|
# # update = await ctx.send('I\'m tallying standings now...')
|
|
# # if await post_standings_recalc(current['season']):
|
|
# # await update.delete()
|
|
# await ctx.send(f'You no longer have to submit scores manually. They will be added when you run `/sba-submit`')
|
|
|
|
# @commands.command(name='drive', help='Season 5 Drive')
|
|
# async def drive_command(self, ctx):
|
|
# await ctx.send('Here is a link to the Season 5 drive:\n'
|
|
# 'https://drive.google.com/drive/folders/1W8B54gZsDXXT3coKVtnGYNiYnUAPcwNB?usp=sharing')
|
|
|
|
# @commands.command(name='rules', aliases=['rulesref', 'rulesreference', 'reference'], help='Rules reference')
|
|
# async def rules_command(self, ctx):
|
|
# await ctx.send('Here is the online rules reference: <https://sombaseball.ddns.net/rules>\n\n'
|
|
# 'Here is a link to the google doc:\n'
|
|
# 'https://docs.google.com/document/d/1yGZcHy9zN2MUi4hnce12dAzlFpIApbn7zR24vCkPl1o')
|
|
|
|
@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<https://docs.google.com/spreadsheets/d/1t6bfTFpHODRINIC2RF9lDt1XpHsnzeU0rYvSnpgWch'
|
|
'I/edit?usp=sharing>\n'
|
|
'**S6 PCD**:\n<https://docs.google.com/spreadsheets/d/1XeBbQjao6R4Z5HYJAbftFjfWQU9Jq2swKtYsg483TI0'
|
|
'/edit#gid=970312780>\n'
|
|
'**Foxx\'s**:\n<https://docs.google.com/spreadsheets/d/1NODWy7XeYcEBfQW_EmiwnthGTfn_JX5FDy6Hwjmf0f'
|
|
'k/edit?usp=sharing>\n'
|
|
'**Josef\'s**:\n<https://docs.google.com/spreadsheets/d/1g_ixDp9ZFuSyc5cNTQegsEwhpr_5yxpiIHhOvgchH'
|
|
'9k/edit?usp=sharing>\n\n'
|
|
'***R E F E R E N C E S***\n'
|
|
'**Rules Reference**:\n<https://docs.google.com/document/d/1wu63XSgfQE2wadiegWaaDda11QvqkN0liRurKm0'
|
|
'vcTs/edit?usp=sharing>\n'
|
|
'**League Guidelines**:\n<https://docs.google.com/document/d/1VVoGCDD3vaqy7NyZBKJ2BV8BvmiZJTie11hrh'
|
|
'pt_joI/edit?usp=sharing>\n'
|
|
'**Scouting Reference**:\n<https://docs.google.com/spreadsheets/d/1HErEweHt-cpf-a8X6pXMO13n0-aiVppF'
|
|
'g1jISNr5DpE/edit?usp=sharing>'
|
|
)
|
|
|
|
@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 <https://sombaseball.ddns.net/rules#pitcher-endurance>')
|
|
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 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 delete_result(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 post_result(result):
|
|
update = await interaction.channel.send('I\'m tallying standings now...')
|
|
if await post_standings_recalc(current['season']):
|
|
await update.delete()
|
|
|
|
# @commands.command(name='submit', help='Submit scorecard')
|
|
# @commands.has_any_role(SBA_PLAYERS_ROLE_NAME)
|
|
# async def submit_command(self, ctx, sheet_url):
|
|
# # current = await get_current()
|
|
# #
|
|
# # # Ask for confirmation to pull card
|
|
# # prompt = 'Has your opponent double-checked this card for accuracy? They get pretty whiny when you miss ' \
|
|
# # 'a hold or an RBI. (Yes/No)'
|
|
# # this_q = Question(bot=self.bot, channel=ctx.channel, prompt=prompt, qtype='yesno', timeout=30)
|
|
# # async with ctx.typing():
|
|
# # if not os.environ.get("TESTING"):
|
|
# # await asyncio.sleep(4)
|
|
# # resp = await this_q.ask([ctx.author])
|
|
# #
|
|
# # if not resp:
|
|
# # await ctx.send('Not a problem at all. You folks think it over and come back to me when you\'re sure.')
|
|
# # return
|
|
# # else:
|
|
# # await ctx.message.add_reaction('👀')
|
|
# # await ctx.send('Hold my sheets, I\'m going in.')
|
|
# #
|
|
# # # Go get scorecard
|
|
# # logging.info(f'Checking scorecard {sheet_url}')
|
|
# # async with ctx.typing():
|
|
# # # 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 open scorecard {sheet_url} with this error: {e}')
|
|
# # await ctx.message.add_reaction('❌')
|
|
# # await ctx.send(f'{ctx.message.author.mention}, I can\'t access that sheet.')
|
|
# # 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', 'V29')
|
|
# # 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} with this error: {e}')
|
|
# # await ctx.message.add_reaction('❌')
|
|
# # await ctx.send(f'Yikes. I ran into an error reading this card. This could be ugly:\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 ctx.send(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)
|
|
# #
|
|
# # if len(old_home_bat) + len(old_away_bat) + len(old_home_arm) + len(old_away_arm) > 0:
|
|
# # if len(old_home_bat) > 0:
|
|
# # await ctx.send(f'I already see batting stats for the {home_team["sname"]} from w{week_num}g{game_num}')
|
|
# # if len(old_away_bat) > 0:
|
|
# # await ctx.send(f'I already see batting stats for the {away_team["sname"]} from w{week_num}g{game_num}')
|
|
# # if len(old_home_arm) > 0:
|
|
# # await ctx.send(f'I already see pitching stats for the {home_team["sname"]} from w{week_num}g{game_num}')
|
|
# # if len(old_away_arm) > 0:
|
|
# # await ctx.send(f'I already see pitching stats for the {away_team["sname"]} from w{week_num}g{game_num}')
|
|
# # await ctx.send('Double check the week and game number and then get back to me.')
|
|
# # return
|
|
# #
|
|
# # # Confirm submitting GM
|
|
# # if await get_team_by_owner(current['season'], ctx.author.id) not in [home_team, away_team] and \
|
|
# # ctx.author.id != self.bot.owner_id:
|
|
# # await ctx.send(f'{await get_emoji(ctx, "squint")} Only a GM of the two teams can submit scorecards.')
|
|
# # return
|
|
# #
|
|
# # # 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 ctx.send('Just finished reading the scorecard. Now to look for all of your mistakes...')
|
|
# # async with ctx.typing():
|
|
# # 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 ctx.message.add_reaction('❌')
|
|
# # await ctx.send(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 ctx.message.add_reaction('✅')
|
|
# # await ctx.send(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 ctx.send('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"]}>'
|
|
# # archive_channel = discord.utils.get(ctx.guild.text_channels, name=f'week-{week_num}-archive')
|
|
# # if not archive_channel:
|
|
# # overwrites = {ctx.guild.default_role: discord.PermissionOverwrite(send_messages=False, embed_links=False),
|
|
# # ctx.guild.me: discord.PermissionOverwrite(send_messages=True)}
|
|
# # archive_channel = await ctx.guild.create_text_channel(
|
|
# # f'week-{week_num}-archive',
|
|
# # overwrites=overwrites,
|
|
# # category=discord.utils.get(ctx.guild.categories, name=f'Season {current["season"]} Archives'),
|
|
# # position=0
|
|
# # )
|
|
# #
|
|
# # await archive_channel.send(
|
|
# # f'Game {game_num}: **{away_team["sname"]}** {await team_emoji(ctx, away_team)} '
|
|
# # f'{final_box_away["r"]} @ {final_box_home["r"]} '
|
|
# # f'{await team_emoji(ctx, home_team)} **{home_team["sname"]}**\n{card_url}')
|
|
# #
|
|
# # # 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=card_url)
|
|
# # embed.set_footer(text='Please share the highlights!')
|
|
# #
|
|
# # await send_to_channel(
|
|
# # self.bot,
|
|
# # 'sba-network-news',
|
|
# # content=None,
|
|
# # embed=embed
|
|
# # )
|
|
# await ctx.send(f'Please run `/sba-submit` to submit scorecards.')
|
|
|
|
# @commands.command(name='removestats', help='Remove scorecard')
|
|
# @commands.has_any_role(SBA_PLAYERS_ROLE_NAME)
|
|
# async def remove_stats_command(self, ctx, away_abbrev, home_abbrev, week_num, game_num):
|
|
# current = await get_current()
|
|
#
|
|
# owner_team = await get_team_by_owner(current['season'], ctx.author.id)
|
|
# away_team = await get_one_team(away_abbrev)
|
|
# home_team = await get_one_team(home_abbrev)
|
|
#
|
|
# # 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 ctx.send(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
|
|
# s_type = 'Regular' if current['week'] < current['playoffs_begin'] else 'Post'
|
|
# old_home_bat = await get_battingstat(
|
|
# season=current['season'], s_type=s_type, 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'], s_type=s_type, 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'], s_type=s_type, 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'], s_type=s_type, team_abbrev=away_team['abbrev'], week_start=week_num,
|
|
# week_end=week_num, game_num=game_num)
|
|
#
|
|
# if len(old_home_bat) + len(old_away_bat) + len(old_home_arm) + len(old_away_arm) == 0:
|
|
# await ctx.send('Good news: I don\'t see any stats for that game. Bad news: you seemed to think there '
|
|
# 'were some.')
|
|
# return
|
|
#
|
|
# # Confirm submitting GM
|
|
# if owner_team not in [home_team, away_team] and ctx.author.id != self.bot.owner_id:
|
|
# await ctx.send(f'{await get_emoji(ctx, "squint")} Only a GM of the two teams can remove stats.')
|
|
# return
|
|
#
|
|
# prompt = 'Are you sure? This will snap these stats out of existence.'
|
|
# this_q = Question(self.bot, ctx.channel, prompt, 'yesno', 30)
|
|
# resp = await this_q.ask([ctx.author])
|
|
#
|
|
# if not resp:
|
|
# await ctx.send('Whew. There for a second I thought you fucked up a scorecard. I\'ll leave this one be.')
|
|
# return
|
|
#
|
|
# 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 ctx.send('What a pain in my balls. Let\'s start by deleting the batting stats.')
|
|
# async with ctx.typing():
|
|
# if await delete_battingstats(this_game):
|
|
# await ctx.send('Batting stats are gone - now the pitching stats.')
|
|
#
|
|
# async with ctx.typing():
|
|
# if await delete_pitchingstats(this_game):
|
|
# await ctx.send('Pitching stats are gone - now to recalculate everybody\'s season batting lines.')
|
|
#
|
|
# async with ctx.typing():
|
|
# if await recalc_batting_seasons(current['season'], away_team['id']):
|
|
# if await recalc_batting_seasons(current['season'], home_team['id']):
|
|
# await ctx.send('Batting lines are done - now to recalculate pitching lines.')
|
|
#
|
|
# async with ctx.typing():
|
|
# if await recalc_pitching_seasons(current['season'], away_team['id']):
|
|
# if await recalc_pitching_seasons(current['season'], home_team['id']):
|
|
# await ctx.send('Pitching lines are done - now to recalculate fielding lines.')
|
|
#
|
|
# async with ctx.typing():
|
|
# if await recalc_fielding_seasons(current['season'], away_team['id']):
|
|
# await recalc_fielding_seasons(current['season'], home_team['id'])
|
|
#
|
|
# await ctx.send(f'All done. Don\'t suck next time {await get_emoji(ctx, "lakemonsters")}')
|
|
|
|
@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):
|
|
current = await get_current()
|
|
team = await get_team_by_owner(current['season'], interaction.user.id)
|
|
mil_team = await get_one_team(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:
|
|
try:
|
|
color_int = int(color_hex, 16)
|
|
await team_role.edit(colour=color_int)
|
|
await patch_team(team, color=color_hex)
|
|
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 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:
|
|
await patch_team(team, thumbnail=team_image_url)
|
|
if mil_color_hex is not None:
|
|
try:
|
|
await patch_team(mil_team, 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(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 patch_team(mil_team, thumbnail=mil_team_image_url)
|
|
show_mil = True
|
|
if dice_color_hex is not None:
|
|
try:
|
|
await patch_team(team, 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 get_one_team(team['id'], season=current['season'])
|
|
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 get_one_team(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.response.send_message(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 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 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 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 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 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 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 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 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 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_one_team(resp)
|
|
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
|
|
|
|
try:
|
|
this_matchup = await get_one_schedule(
|
|
season=current['season'],
|
|
team_abbrev1=this_team['abbrev'],
|
|
week=current['week']
|
|
)
|
|
except ValueError as e:
|
|
other_team = await get_other_team()
|
|
if not other_team:
|
|
return
|
|
channel_name = f'{this_team["abbrev"]} vs {other_team["abbrev"]} Muted'
|
|
else:
|
|
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:
|
|
other_team = await get_other_team()
|
|
if not other_team:
|
|
return
|
|
channel_name = f'{this_team["abbrev"]} vs {other_team["abbrev"]}'
|
|
|
|
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"]}')
|
|
|
|
overwrites = {ctx.guild.default_role: discord.PermissionOverwrite(speak=False),
|
|
this_team_role: discord.PermissionOverwrite(speak=True),
|
|
other_team_role: discord.PermissionOverwrite(speak=True)}
|
|
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 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
|
|
|
|
player = await get_one_player(
|
|
await fuzzy_player_search(ctx, ctx.channel, self.bot, player_name, self.player_list.keys())
|
|
)
|
|
|
|
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:
|
|
await patch_player(player['id'], headshot=url)
|
|
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 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
|
|
|
|
player = await get_one_player(
|
|
await fuzzy_player_search(ctx, ctx.channel, self.bot, player_name, self.player_list.keys())
|
|
)
|
|
|
|
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:
|
|
await patch_player(player['id'], vanity_card=url)
|
|
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 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
|
|
|
|
player = await get_one_player(
|
|
await fuzzy_player_search(ctx, ctx.channel, self.bot, player_name, self.player_list.keys())
|
|
)
|
|
|
|
old_player = await get_one_player(player["name"], season=current["season"]-1)
|
|
await patch_player(
|
|
pid=player["id"],
|
|
vanity_card=old_player["vanity_card"]
|
|
)
|
|
player["vanity_card"] = old_player["vanity_card"]
|
|
|
|
player_embed = await get_player_embed(player, current)
|
|
await ctx.send(content=None, embed=player_embed)
|
|
|
|
@commands.command(name='charts', aliases=['chart'], help='Run `/charts` for all charts')
|
|
async def legacy_charts_command(self, ctx):
|
|
await ctx.send(f'Run `/charts` for all charts')
|
|
|
|
@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='pitupdate', description='Mod: Update pitcher ratings')
|
|
@app_commands.checks.has_any_role('Da Commish')
|
|
async def pit_update_slash(
|
|
self, interaction: discord.Interaction, player_name: str, swar: float = None, injury_games: int = None):
|
|
player = await get_one_player(
|
|
await fuzzy_player_search(interaction, interaction.channel, self.bot, player_name, self.player_list),
|
|
)
|
|
current = await get_current()
|
|
|
|
await patch_player(
|
|
player['id'],
|
|
wara=swar if swar is not None else player['wara'],
|
|
injury_rating=f'{player["injury_rating"][:2]}{injury_games}' if injury_games is not None else player["injury_rating"]
|
|
)
|
|
new_player = await get_one_player(player['id'])
|
|
await interaction.response.send_message(content=None, embed=await get_player_embed(new_player, current))
|
|
|
|
@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):
|
|
team = await get_one_team(team_abbrev)
|
|
|
|
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:
|
|
this_p = await get_one_player(
|
|
await fuzzy_player_search(interaction, interaction.channel, self.bot, x, self.player_list)
|
|
)
|
|
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 = db_get('players', api_ver=3, params=[('team_abbrev', team['abbrev'])])
|
|
logging.info(f'all_players: {all_players}')
|
|
|
|
fa = await get_one_team('FA')
|
|
for y in all_players['players']:
|
|
if y not in keepers:
|
|
await patch_player(y['id'], team_id=fa['id'])
|
|
|
|
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)
|
|
|
|
|
|
async def setup(bot):
|
|
await bot.add_cog(Players(bot))
|