diff --git a/cogs/admins.py b/cogs/admins.py index 85d27bf..b90bcb4 100644 --- a/cogs/admins.py +++ b/cogs/admins.py @@ -13,7 +13,7 @@ from helpers import * import in_game from in_game import ai_manager from in_game.gameplay_models import Play, Session, select, engine, Game, Cardset, Lineup, Team, Player -from in_game.gameplay_queries import get_team_or_none +from in_game.gameplay_queries import get_team_or_none, reset_cache logger = logging.getLogger('discord_app') @@ -491,16 +491,25 @@ class Admins(commands.Cog): @app_commands.checks.has_any_role('Da Commish') async def reset_cache_command( self, interaction: discord.Interaction, player_cache: Optional[bool] = True, - batting_cache: Optional[bool] = True, pitching_cache: Optional[bool] = True, team_cache: bool = True): + scouting_cache: Optional[bool] = True, team_cache: bool = True): await interaction.response.defer() - if player_cache: - in_game.data_cache.PLAYER_CACHE = {} - if batting_cache: - in_game.data_cache.BATTINGCARD_CACHE = {} - if pitching_cache: - in_game.data_cache.PITCHINGCARD_CACHE = {} - if team_cache: - in_game.data_cache.TEAM_CACHE = {} + # if player_cache: + # in_game.data_cache.PLAYER_CACHE = {} + # if batting_cache: + # in_game.data_cache.BATTINGCARD_CACHE = {} + # if pitching_cache: + # in_game.data_cache.PITCHINGCARD_CACHE = {} + # if team_cache: + # in_game.data_cache.TEAM_CACHE = {} + + with Session(engine) as session: + reset_cache( + session=session, + players=player_cache, + scouting=scouting_cache, + team=team_cache + ) + await interaction.edit_original_response( content=random_gif(random.choice(['all done', 'yes sir', 'complete', 'finished'])) ) diff --git a/cogs/gameplay.py b/cogs/gameplay.py index ae27d7f..318b2eb 100644 --- a/cogs/gameplay.py +++ b/cogs/gameplay.py @@ -49,62 +49,69 @@ class Gameplay(commands.Cog): logger.info(f'Getting sheets') self.sheets = pygsheets.authorize(service_file='storage/paper-dynasty-service-creds.json', retries=1) - @tasks.loop(minutes=2) + @tasks.loop(minutes=1) async def live_scorecard(self): - logger.info(f'Checking live scorecard loop') - - guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) - score_channel = discord.utils.get(guild.text_channels, name='live-pd-scores') + try: + logger.info(f'Checking live scorecard loop') + + guild = self.bot.get_guild(int(os.environ.get('GUILD_ID'))) + score_channel = discord.utils.get(guild.text_channels, name='live-pd-scores') - if score_channel is None: - logger.error(f'Could not find live-pd-channel') - return + if score_channel is None: + logger.error(f'Could not find live-pd-channel') + return - if len(self.game_states) == 0: - logger.info(f'No active game_states') - return - - player_role = discord.utils.get(guild.roles, name=PD_PLAYERS_ROLE_NAME) - all_embeds = [] - logger.info(f'player role: {player_role}') + if len(self.game_states) == 0: + logger.info(f'No active game_states') + return + + player_role = discord.utils.get(guild.roles, name=PD_PLAYERS_ROLE_NAME) + all_embeds = [] + logger.info(f'player role: {player_role}') - with Session(engine) as session: - for key in self.game_states: - if not self.game_states[key]['ack']: - if not self.game_states[key]['play'].game.active: - logger.info(f'Game {self.game_states[key]["play"].game.id} is complete, removing from game_states') - del self.game_states[key] - - else: - try: - logger.info(f'Appending scorebug for Game {self.game_states[key]["play"].game.id}') - this_channel = discord.utils.get(guild.text_channels, id=self.game_states[key]["play"].game.channel_id) - logger.info(f'this_channel: {this_channel}') - - this_embed = await get_scorebug_embed(session, self.game_states[key]["play"].game, full_length=False, live_scorecard=True) - this_embed.set_image(url=None) - this_embed.insert_field_at( - index=0, - name='Ballpark', - value=f'{this_channel.mention}' - ) - all_embeds.append(this_embed) + with Session(engine) as session: + for key in self.game_states: + if not self.game_states[key]['ack']: + if not self.game_states[key]['play'].game.active: + logger.info(f'Game {self.game_states[key]["play"].game.id} is complete, removing from game_states') + del self.game_states[key] + + else: + try: + logger.info(f'Appending scorebug for Game {self.game_states[key]["play"].game.id}') + this_channel = discord.utils.get(guild.text_channels, id=self.game_states[key]["play"].game.channel_id) + logger.info(f'this_channel: {this_channel}') + + this_embed = await get_scorebug_embed(session, self.game_states[key]["play"].game, full_length=False, live_scorecard=True) + this_embed.set_image(url=None) + this_embed.insert_field_at( + index=0, + name='Ballpark', + value=f'{this_channel.mention}' + ) + all_embeds.append(this_embed) - self.game_states[key]['ack'] = True - except Exception as e: - logger.error(f'Unable to add to game_states: {e}') - logger.error(f'Game: {self.game_states[key]["play"].game.id}') - - if len(all_embeds) == 0: - logger.info(f'No active game embeds, returning') - await score_channel.set_permissions(player_role, read_messages=False) - return - - async for message in score_channel.history(limit=25): - await message.delete() + self.game_states[key]['ack'] = True + except Exception as e: + logger.error(f'Unable to add to game_states: {e}') + logger.error(f'Game: {self.game_states[key]["play"].game.id}') + + if len(all_embeds) == 0: + logger.info(f'No active game embeds, returning') + await score_channel.set_permissions(player_role, read_messages=False) + return + + async for message in score_channel.history(limit=25): + await message.delete() - await score_channel.set_permissions(player_role, read_messages=True) - await score_channel.send(content=None, embeds=all_embeds) + await score_channel.set_permissions(player_role, read_messages=True) + await score_channel.send(content=None, embeds=all_embeds) + except Exception as e: + logger.error(f'Failed running live scorecard: {e}') + try: + await send_to_channel(self.bot, 'commissioners-office', f'PD Live Scorecard just failed: {e}') + except Exception as e: + logger.error(f'Couldn\'t even send the error to the private channel :/') @live_scorecard.before_loop async def before_live_scoreboard(self): @@ -227,6 +234,13 @@ class Gameplay(commands.Cog): await self.post_play(session, interaction, next_play, buffer_message) + def kickstart_live_scorecard(self): + try: + self.live_scorecard.start() + logger.info(f'Kick started the live scorecard') + except RuntimeError as e: + logger.info(f'Live scorecard is already running') + @commands.command(name='test-write', help='Test concurrent db writes', hidden=True) @commands.is_owner() async def test_write_command(self, ctx): @@ -241,7 +255,6 @@ class Gameplay(commands.Cog): session.commit() await ctx.send(f'Am I alive? Did it work?') - group_new_game = app_commands.Group(name='new-game', description='Start a new baseball game') @group_new_game.command(name='mlb-campaign', description='Start a new MLB campaign game against an AI') @@ -262,6 +275,7 @@ class Gameplay(commands.Cog): async def new_game_mlb_campaign_command( self, interaction: discord.Interaction, league: Choice[str], away_team_abbrev: str, home_team_abbrev: str, roster: Choice[str]): await interaction.response.defer() + self.kickstart_live_scorecard() with Session(engine) as session: teams = await new_game_checks(session, interaction, away_team_abbrev, home_team_abbrev) @@ -441,6 +455,7 @@ class Gameplay(commands.Cog): @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) async def new_game_gauntlet_command(self, interaction: discord.Interaction, roster: Choice[str]): await interaction.response.defer() + self.kickstart_live_scorecard() with Session(engine) as session: try: @@ -663,6 +678,7 @@ class Gameplay(commands.Cog): @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) async def new_game_exhibition_command(self, interaction: discord.Interaction, away_team_abbrev: str, home_team_abbrev: str, roster: Choice[str], cardsets: Literal['Minor League', 'Major League', 'Hall of Fame', 'Flashback', 'Custom'] = 'Custom'): await interaction.response.defer() + self.kickstart_live_scorecard() with Session(engine) as session: teams = await new_game_checks(session, interaction, away_team_abbrev, home_team_abbrev) @@ -836,6 +852,7 @@ class Gameplay(commands.Cog): @app_commands.checks.has_any_role(PD_PLAYERS_ROLE_NAME) async def new_game_unlimited_command(self, interaction: discord.Interaction, away_team_abbrev: str, home_team_abbrev: str): await interaction.response.defer() + self.kickstart_live_scorecard() with Session(engine) as session: teams = await new_game_checks(session, interaction, away_team_abbrev, home_team_abbrev) diff --git a/in_game/gameplay_models.py b/in_game/gameplay_models.py index 905c003..3728a48 100644 --- a/in_game/gameplay_models.py +++ b/in_game/gameplay_models.py @@ -21,7 +21,7 @@ logger = logging.getLogger('discord_app') # engine = create_engine(sqlite_url, echo=False, connect_args=connect_args) postgres_url = f'postgresql://{os.getenv('DB_USERNAME')}:{os.getenv('DB_PASSWORD')}@{os.getenv('DB_URL')}/{os.getenv('DB_NAME')}' engine = create_engine(postgres_url, pool_size=10, max_overflow=30) -CACHE_LIMIT = 1209600 # in seconds +CACHE_LIMIT = 259200 # 1209600 # in seconds SBA_COLOR = 'a6ce39' SBA_LOGO = 'https://sombaseball.ddns.net/static/images/sba-logo.png' diff --git a/in_game/gameplay_queries.py b/in_game/gameplay_queries.py index 1c28ae5..1d1e77b 100644 --- a/in_game/gameplay_queries.py +++ b/in_game/gameplay_queries.py @@ -6,7 +6,7 @@ from typing import Literal import pydantic from sqlalchemy import func from api_calls import db_get, db_post -from sqlmodel import col +from sqlmodel import col, update from in_game.gameplay_models import CACHE_LIMIT, BatterScouting, BatterScoutingBase, BattingCard, BattingCardBase, BattingRatings, BattingRatingsBase, Card, CardBase, Cardset, CardsetBase, GameCardsetLink, Lineup, PitcherScouting, PitchingCard, PitchingCardBase, PitchingRatings, PitchingRatingsBase, Player, PlayerBase, PositionRating, PositionRatingBase, RosterLink, Session, Team, TeamBase, select, or_, Game, Play from exceptions import DatabaseError, PositionNotFoundException, log_errors, log_exception, PlayNotFoundException @@ -1315,3 +1315,22 @@ def get_pitcher_runs_by_innings(session: Session, this_game: Game, this_pitcher: return runs + +def reset_cache(session: Session, players: bool = True, scouting: bool = True, team: bool = True): + if players: + logger.warning(f'Resetting created date for Players') + session.exec(update(Player).values(created=datetime.datetime.now() - datetime.timedelta(days=365))) + if scouting: + logger.warning(f'Resetting created date for scouting objects') + session.exec(update(BattingCard).values(created=datetime.datetime.now() - datetime.timedelta(days=365))) + session.exec(update(BatterScouting).values(created=datetime.datetime.now() - datetime.timedelta(days=365))) + session.exec(update(PitchingCard).values(created=datetime.datetime.now() - datetime.timedelta(days=365))) + session.exec(update(PitcherScouting).values(created=datetime.datetime.now() - datetime.timedelta(days=365))) + session.exec(update(PositionRating).values(created=datetime.datetime.now() - datetime.timedelta(days=365))) + session.exec(update(PitchingRatings).values(created=datetime.datetime.now() - datetime.timedelta(days=365))) + session.exec(update(BattingRatings).values(created=datetime.datetime.now() - datetime.timedelta(days=365))) + if team: + logger.warning(f'Resetting created date for Teams') + session.exec(update(Team).values(created=datetime.datetime.now() - datetime.timedelta(days=365))) + + session.commit()