diff --git a/hockey/game.py b/hockey/game.py index 3d22ebb93..56b3f76b3 100644 --- a/hockey/game.py +++ b/hockey/game.py @@ -941,12 +941,21 @@ async def check_team_goals(self, bot: Red) -> None: if str(goal.goal_id) in team_data[goal.team_name]["goal_id"]: # attempts to edit the goal if the scorers have changed old_goal = Goal(**team_data[goal.team_name]["goal_id"][str(goal.goal_id)]["goal"]) - if goal.description != old_goal.description or goal.link != old_goal.link: + if goal != old_goal: # goal.home_shots = old_goal.home_shots # goal.away_shots = old_goal.away_shots # This is to keep shots consistent between edits # Shots should not update as the game continues bot.dispatch("hockey_goal_edit", self, goal) + log.debug( + "Before desc=%s after desc=%s equal=%s before link=%s after link=%s equal=%s", + old_goal.description, + goal.description, + old_goal.description == goal.description, + old_goal.link, + goal.link, + old_goal.link == goal.link, + ) # This is here in order to prevent the bot attempting to edit the same # goal b2b causing increase of requests to discord for editing and @@ -979,7 +988,7 @@ def done_edit_callback(task): else: log.debug("Found existing edit task, waiting for %s", key) task = cog._edit_tasks[key] - await task.wait() + await asyncio.wait_for(task, timeout=30) log.debug("Done waiting for %s", key) cog._edit_tasks[key] = asyncio.create_task( goal.edit_team_goal(bot, self), name=key diff --git a/hockey/goal.py b/hockey/goal.py index cd9d5872e..22b936c0d 100644 --- a/hockey/goal.py +++ b/hockey/goal.py @@ -1,7 +1,7 @@ from __future__ import annotations import asyncio -from datetime import datetime, timezone +from datetime import datetime, timedelta, timezone from typing import TYPE_CHECKING, List, Optional, Tuple, Union import discord @@ -69,6 +69,23 @@ def team_name(self): def emoji(self) -> Union[discord.PartialEmoji, str]: return self.team.emoji + def __eq__(self, other) -> bool: + if not isinstance(other, Goal): + return False + if ( + self.description == other.description + and str(self.link) == str(other.link) + # if one of these is a URL then the standard == will be false causing + # us to constantly try and edit goals we've already edited. + # So instead, let's just cast to string. + and self.goal_id == other.goal_id + ): + return True + return False + + def __ne__(self, other) -> bool: + return not self.__eq__(other) + def to_json(self) -> dict: return { "goal_id": self.goal_id, @@ -85,7 +102,7 @@ def to_json(self) -> dict: "strength": self.strength, "empty_net": self.empty_net, "event": self.event, - "link": str(self.link) if self.link else None, + "link": str(self.link) if self.link is not None else None, "image": self.image, "home_shots": self.home_shots, "away_shots": self.away_shots, @@ -421,6 +438,13 @@ async def edit_team_goal(self, bot: Red, game_data: Game) -> None: channel = await get_channel_obj(bot, int(channel_id), {"guild_id": int(guild_id)}) if channel is None: continue + if datetime.now(timezone.utc) - discord.utils.snowflake_time( + int(message_id) + ) >= timedelta(hours=1): + # Discord has a limit on how many messages older than 1 hour that can be edited. + # So we will just ignore any since they are likely complete and pushed out + # of view of chat anyway. + continue if channel.is_news(): asyncio.create_task(self.edit_goal(bot, channel, message_id, em, text)) # This is to prevent endlessly waiting incase someone