diff --git a/hockey/dev.py b/hockey/dev.py index 16ade410f4..828fc72ef0 100644 --- a/hockey/dev.py +++ b/hockey/dev.py @@ -51,6 +51,22 @@ async def hockeydev(self, ctx: commands.Context) -> None: """ pass + @hockeydev.command(name="errorchannel") + async def set_loop_error_channel(self, ctx: commands.Context, channel: discord.TextChannel): + """ + Specify an error channel for the hockey loop. + """ + if not channel.permissions_for(ctx.me).send_messages: + await ctx.send( + "I need permission to send messages in {channel}".format(channel=channel.mention) + ) + return + await self.config.loop_error_channel.set(channel.id) + await self.config.loop_error_guild.set(channel.guild.id) + await ctx.send( + "I will attempt to send error messages in {channel}.".format(channel=channel.mention) + ) + @hockeydev.command(name="resetpickemsweekly", with_app_command=False) async def reset_weekly_pickems_data(self, ctx: commands.Context) -> None: """ diff --git a/hockey/hockey.py b/hockey/hockey.py index 74bd8a8228..ba5717b6e5 100644 --- a/hockey/hockey.py +++ b/hockey/hockey.py @@ -14,6 +14,7 @@ from redbot.core import Config, commands from redbot.core.i18n import Translator, cog_i18n from redbot.core.utils import AsyncIter +from redbot.core.utils.chat_formatting import box from .api import GameState, NewAPI, Schedule from .constants import BASE_URL, CONFIG_ID, CONTENT_URL, HEADSHOT_URL, TEAMS @@ -73,6 +74,8 @@ def __init__(self, bot): "print": False, "last_day": 0, "enable_slash": False, + "loop_error_channel": None, + "loop_error_guild": None, } default_global["player_db"] = 0 default_guild = { @@ -227,9 +230,35 @@ async def add_cog_to_dev_env(self): pass await self._get_commit() + def hockey_loop_error(self, future: asyncio.Future): + try: + if not future.done(): + message = "Hockey encountered an error: `{exception}`\n{stack}".format( + exception=future.exception(), stack=box(str(future.get_stack())) + ) + log.exception(message) + asyncio.create_task(self.hockey_send_error_task(message)) + except asyncio.CancelledError: + # we ignore cancelled errors + pass + + async def hockey_send_error_task(self, message: str): + guild = None + channel = None + if guild_id := await self.config.loop_error_guild(): + guild = self.bot.get_guild(guild_id) + if guild is None: + return + if channel_id := await self.config.loop_error_channel(): + channel = guild.get_channel(channel_id) + if channel is None: + return + await channel.send(message) + async def cog_load(self) -> None: asyncio.create_task(self.add_cog_to_dev_env()) self.loop = asyncio.create_task(self.game_check_loop()) + self.loop.add_done_callback(self.hockey_loop_error) await self.migrate_settings() async def migrate_settings(self) -> None: diff --git a/hockey/hockeyset.py b/hockey/hockeyset.py index e5d525735a..f7028f2fd2 100644 --- a/hockey/hockeyset.py +++ b/hockey/hockeyset.py @@ -111,13 +111,6 @@ async def hockey_settings(self, ctx: commands.Context) -> None: # All Hockey setup commands # ####################################################################### - @commands.group(name="hockeyslash") - async def hockey_slash(self, ctx: commands.Context): - """ - commands for enabling/disabling slash commands - """ - pass - @commands.group(name="hockeyevents", aliases=["nhlevents"]) @commands.bot_has_permissions(manage_events=True) @commands.admin_or_permissions(manage_guild=True) @@ -224,19 +217,6 @@ async def set_team_events(self, ctx: commands.Context, team: TeamFinder): await asyncio.sleep(1) await ctx.send(f"Finished creating events for {number_of_games} games.") - @hockey_slash.command(name="global") - @commands.is_owner() - async def hockey_global_slash(self, ctx: commands.Context): - """Toggle this cog to register slash commands""" - current = await self.config.enable_slash() - await self.config.enable_slash.set(not current) - verb = _("enabled") if not current else _("disabled") - await ctx.send(_("Slash commands are {verb}.").format(verb=verb)) - if not current: - self.bot.tree.add_command(self.hockey_commands.app_command) - else: - self.bot.tree.remove_command("hockey") - async def check_notification_settings(self, guild: discord.Guild, goal: bool = False) -> str: reply = "" mentionable_roles = []