From c138a608d6ec1cf9cde46ab34e3d31b37604f99f Mon Sep 17 00:00:00 2001 From: insert Date: Sun, 20 Jul 2025 23:36:18 -0400 Subject: [PATCH] feat: statistical live update --- cogs/liveupdate.py | 107 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 3 deletions(-) diff --git a/cogs/liveupdate.py b/cogs/liveupdate.py index 160e2b0..abcf67b 100644 --- a/cogs/liveupdate.py +++ b/cogs/liveupdate.py @@ -10,6 +10,7 @@ import itertools import aiosqlite as sqlite3 from nextcord.ext import commands, application_checks, tasks from nextcord import TextInputStyle, IntegrationType +import re import timeit timings = [] @@ -145,6 +146,65 @@ async def classiclivegameworker(self,serverid,userid,channelid,gameid,offset): await self.bot.db.commit() await warning.send(f"Deleted {lastserverid} from the database due to 403 error") +async def statisticallivegameworker(self,serverid,userid,channelid,gameid,offset): + begin = timeit.default_timer() + lastserverid = serverid + try: + async with aiohttp.ClientSession() as session: + channel = self.bot.get_channel(channelid) + data = await session.get(f"https://mmolb.com/api/game/{gameid}/live?after={offset}") + data = await data.json() + basedata = await session.get(f"https://mmolb.com/api/game/{gameid}") + basedata = await basedata.json() + if basedata["State"] == "Complete": + await self.bot.db.execute(f""" + DELETE from liveupdate WHERE channelid = {channelid} AND gameid = '{gameid}' + """) + if len(data["entries"]) > 0: + finalstr = "" + offsetadd = 0 + maysend = False + for i in data["entries"]: + offsetadd += 1 + if i["event"] == "InningEnd": + finalstr += f"\n{i['message']} | {basedata["AwayTeamName"]} {basedata["AwayTeamEmoji"]} {data["entries"][-1]["away_score"]} vs {basedata["HomeTeamName"]} {basedata["HomeTeamEmoji"]} {data["entries"][-1]["home_score"]}" + maysend = True + for r in re.findall(r'[A-Za-z éö1-9]*out[A-Za-z éö1-9]*',i['message'],re.IGNORECASE): + finalstr += f"\n🔴 {r}" + maysend = True + + if "scores" in i['message'] or "homers" in i['message']: + if data["entries"][-1]["inning_side"] == 1: + finalstr += f"\n{basedata["AwayTeamName"]} {basedata["AwayTeamEmoji"]} {data["entries"][-1]["away_score"]} vs {basedata["HomeTeamName"]} {basedata["HomeTeamEmoji"]} **{data["entries"][-1]["home_score"]}**" + else: + finalstr += f"\n{basedata["AwayTeamName"]} {basedata["AwayTeamEmoji"]} **{data["entries"][-1]["away_score"]}** vs {basedata["HomeTeamName"]} {basedata["HomeTeamEmoji"]} {data["entries"][-1]["home_score"]}" + for r in re.findall(r'(?<=)([A-Za-z, !.]+)(?=<\/strong>)',i['message'],re.IGNORECASE): + finalstr += f"\n🟢 {r}" + maysend = True + for r in re.findall(r'(?:[A-Za-z éö]*)(?:walks?|steals?|error|signles?|doubles?|triples?|to (?:first|second|third) base)(?:[A-Za-z éö]*)',i['message'],re.IGNORECASE): + finalstr += f"\n👟 {r}" + maysend = True + if i["event"] == "Recordkeeping": + await self.bot.db.execute(f""" + DELETE from liveupdate WHERE channelid = {channelid} AND gameid = '{gameid}' + """) + maysend = True + finalstr += f"{i['message'].replace("", "**").replace("", "**")}\n" + if maysend: + await channel.send(finalstr) + await self.bot.db.execute(f""" + UPDATE liveupdate set offset = {offset+offsetadd} WHERE channelid = '{channelid}' AND gameid = '{gameid}' AND classic = 2 + """) + except Exception as e: + warning = self.bot.get_channel(1365478368555827270) + await warning.send(e) + except nextcord.Forbidden: + warning = self.bot.get_channel(1365478368555827270) + await self.bot.db.execute("DELETE from teamsubscriptions WHERE serverid = ?", (lastserverid,)) + await self.bot.db.execute("DELETE from liveupdate WHERE serverid = ?", (lastserverid,)) + await self.bot.db.execute("DELETE from spotlightsubscriptions WHERE serverid = ?", (lastserverid,)) + await self.bot.db.commit() + await warning.send(f"Deleted {lastserverid} from the database due to 403 error") async def spotlightsubscriptionworker(self,serverid,channelid,classic,gameid,data): try: @@ -152,6 +212,8 @@ async def spotlightsubscriptionworker(self,serverid,channelid,classic,gameid,dat test = await check.fetchone() if test is None: channel = self.bot.get_channel(channelid) + if channel is None: + return if data["State"] == "Complete": return check = await self.bot.db.execute("SELECT serverid,userid,channelid,messageid,gameid,offset FROM liveupdate WHERE channelid = ? AND gameid = ? AND classic = ?", (channelid,gameid,classic)) @@ -164,6 +226,7 @@ async def spotlightsubscriptionworker(self,serverid,channelid,classic,gameid,dat ({channel.guild.id}, {self.bot.application_id}, {channelid}, {message.id}, "{gameid}", {len(data["EventLog"])}, 0) """) else: + await channel.send(content=f"{data["AwayTeamName"]} {data["AwayTeamEmoji"]} vs {data["HomeTeamName"]} {data["HomeTeamEmoji"]}\n> PLAY BALL") await self.bot.db.execute(f""" INSERT INTO liveupdate VALUES ({channel.guild.id}, {self.bot.application_id}, {channelid}, NULL, "{gameid}", {len(data["EventLog"])}, 1) @@ -205,11 +268,18 @@ async def teamsubscriptionworker(self,serverid,channelid,teamid,classic): INSERT INTO liveupdate VALUES ({channel.guild.id}, {self.bot.application_id}, {channelid}, {message.id}, "{gameid}", {len(data["EventLog"])}, 0) """) - else: + elif classic == 1: + await channel.send(content=f"{data["AwayTeamName"]} {data["AwayTeamEmoji"]} vs {data["HomeTeamName"]} {data["HomeTeamEmoji"]}\n> PLAY BALL") await self.bot.db.execute(f""" INSERT INTO liveupdate VALUES ({channel.guild.id}, {self.bot.application_id}, {channelid}, NULL, "{gameid}", {len(data["EventLog"])}, 1) """) + else: + await channel.send(content=f"{data["AwayTeamName"]} {data["AwayTeamEmoji"]} vs {data["HomeTeamName"]} {data["HomeTeamEmoji"]}\n🤖 PLAY BALL") + await self.bot.db.execute(f""" + INSERT INTO liveupdate VALUES + ({channel.guild.id}, {self.bot.application_id}, {channelid}, NULL, "{gameid}", {len(data["EventLog"])}, 2) + """) except KeyError: return except sqlite3.OperationalError: @@ -239,10 +309,10 @@ async def feedsubscriptionworker(self,serverid,channelid,teamid,offset): finalstr = "" for index in itertools.islice(data, offset, len(data)): finalstr += f"\n{index['emoji']} Season {index['season']} Day {index['day']}: {index['text']}" - await channel.send(finalstr) await self.bot.db.execute(f""" UPDATE feedsubscriptions set offset = {len(data)} WHERE channelid = '{channelid}' AND teamid = '{teamid}' """) + await channel.send(finalstr) except Exception as e: warning = self.bot.get_channel(1365478368555827270) await warning.send(e) @@ -425,6 +495,32 @@ class liveupdate(commands.Cog): thanksdiscord = closestteam[:20] await interaction.response.send_autocomplete(thanksdiscord) + @subscribe.subcommand( + name="statistical", + description="Subscribe to a team using a modified version of classic, will spam the channel", + ) + async def statisitcalteamsubscribe(self, interaction: nextcord.Interaction, team: str): + if team not in self.bot.teams_dict: + await interaction.response.send_message("Invalid Team!", ephemeral=True) + await interaction.response.defer() + teamid = self.bot.teams_dict[team] + await interaction.edit_original_message(content="This channel is now subscribed to updates") + await self.bot.db.execute(f""" + INSERT INTO teamsubscriptions VALUES + ({interaction.guild_id}, {interaction.channel_id}, "{teamid}", 2) + """) + await self.bot.db.commit() + + @statisitcalteamsubscribe.on_autocomplete("team") + async def statisitcalteamsubscribeac(self, interaction: nextcord.Interaction, team: str): + if not team: + thanksdiscord = self.bot.teams_list[:20] + await interaction.response.send_autocomplete(thanksdiscord) + return + closestteam = [name for name in self.bot.teams_list if name.lower().startswith(team.lower())] + thanksdiscord = closestteam[:20] + await interaction.response.send_autocomplete(thanksdiscord) + @subscribe.subcommand( name="feed", description="Subscribe to a team's feed", @@ -599,6 +695,9 @@ class liveupdate(commands.Cog): res = await self.bot.db.execute("SELECT serverid,userid,channelid,gameid,offset FROM liveupdate WHERE classic = 1") res = await res.fetchall() worklist = worklist + [classiclivegameworker(self,serverid,userid,channelid,gameid,offset) for [serverid,userid,channelid,gameid,offset] in res] + res = await self.bot.db.execute("SELECT serverid,userid,channelid,gameid,offset FROM liveupdate WHERE classic = 2") + res = await res.fetchall() + worklist = worklist + [statisticallivegameworker(self,serverid,userid,channelid,gameid,offset) for [serverid,userid,channelid,gameid,offset] in res] await asyncio.gather(*worklist,return_exceptions=True) await self.bot.db.commit() game = nextcord.Game(f"Broadcasting {len(worklist)} games") @@ -633,8 +732,10 @@ class liveupdate(commands.Cog): game = await game.json() gameid = game["game_id"] except KeyError: - game = await session.get("https://mmolb.com/api/event-games") + game = await session.get("https://mmolb.com/api/superstar-games") game = await game.json() + if game["games"][-1]['status'] == "Scheduled": #The game has been posted to the api but doesn't exist + return gameid = game["games"][-1]["game_id"] data = await session.get(f"https://mmolb.com/api/game/{gameid}") data = await data.json()