mirror of
				https://github.com/TheLovinator1/discord-reminder-bot.git
				synced 2025-10-31 00:29:49 +01:00 
			
		
		
		
	Add Loguru for enhanced logging and update logging statements for clarity
This commit is contained in:
		
							
								
								
									
										1
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @@ -18,6 +18,7 @@ | |||||||
|         "jobstore", |         "jobstore", | ||||||
|         "jobstores", |         "jobstores", | ||||||
|         "levelname", |         "levelname", | ||||||
|  |         "loguru", | ||||||
|         "Lovinator", |         "Lovinator", | ||||||
|         "pycodestyle", |         "pycodestyle", | ||||||
|         "pydocstyle", |         "pydocstyle", | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ from __future__ import annotations | |||||||
| import asyncio | import asyncio | ||||||
| import datetime | import datetime | ||||||
| import json | import json | ||||||
| import logging |  | ||||||
| import tempfile | import tempfile | ||||||
| from pathlib import Path | from pathlib import Path | ||||||
| from typing import TYPE_CHECKING, Any | from typing import TYPE_CHECKING, Any | ||||||
| @@ -13,6 +12,7 @@ import sentry_sdk | |||||||
| from apscheduler.job import Job | from apscheduler.job import Job | ||||||
| from discord.abc import PrivateChannel | from discord.abc import PrivateChannel | ||||||
| from discord_webhook import DiscordWebhook | from discord_webhook import DiscordWebhook | ||||||
|  | from loguru import logger | ||||||
|  |  | ||||||
| from discord_reminder_bot.misc import calc_time, calculate | from discord_reminder_bot.misc import calc_time, calculate | ||||||
| from discord_reminder_bot.parser import parse_time | from discord_reminder_bot.parser import parse_time | ||||||
| @@ -28,17 +28,13 @@ if TYPE_CHECKING: | |||||||
|  |  | ||||||
|     from discord_reminder_bot import settings |     from discord_reminder_bot import settings | ||||||
|  |  | ||||||
| logger: logging.Logger = logging.getLogger(__name__) |  | ||||||
| logger.setLevel(logging.DEBUG) |  | ||||||
| logging.getLogger("discord.client").setLevel(logging.INFO) |  | ||||||
|  |  | ||||||
| sentry_sdk.init( | sentry_sdk.init( | ||||||
|     dsn="https://c4c61a52838be9b5042144420fba5aaa@o4505228040339456.ingest.us.sentry.io/4508707268984832", |     dsn="https://c4c61a52838be9b5042144420fba5aaa@o4505228040339456.ingest.us.sentry.io/4508707268984832", | ||||||
|     traces_sample_rate=1.0, |     traces_sample_rate=1.0, | ||||||
|  |     send_default_pii=True, | ||||||
| ) | ) | ||||||
|  |  | ||||||
| GUILD_ID = discord.Object(id=341001473661992962) |  | ||||||
|  |  | ||||||
| scheduler: settings.AsyncIOScheduler = get_scheduler() | scheduler: settings.AsyncIOScheduler = get_scheduler() | ||||||
| msg_to_cleanup: list[discord.InteractionMessage] = [] | msg_to_cleanup: list[discord.InteractionMessage] = [] | ||||||
|  |  | ||||||
| @@ -58,7 +54,7 @@ class RemindBotClient(discord.Client): | |||||||
|     async def on_error(self, event_method: str, *args: list[Any], **kwargs: dict[str, Any]) -> None: |     async def on_error(self, event_method: str, *args: list[Any], **kwargs: dict[str, Any]) -> None: | ||||||
|         """Log errors that occur in the bot.""" |         """Log errors that occur in the bot.""" | ||||||
|         # Log the error |         # Log the error | ||||||
|         logger.exception("An error occurred in %s", event_method) |         logger.exception(f"An error occurred in {event_method} with args: {args} and kwargs: {kwargs}") | ||||||
|  |  | ||||||
|         # Add context to Sentry |         # Add context to Sentry | ||||||
|         with sentry_sdk.push_scope() as scope: |         with sentry_sdk.push_scope() as scope: | ||||||
| @@ -100,26 +96,26 @@ class RemindBotClient(discord.Client): | |||||||
|  |  | ||||||
|     async def on_ready(self) -> None: |     async def on_ready(self) -> None: | ||||||
|         """Log when the bot is ready.""" |         """Log when the bot is ready.""" | ||||||
|         logger.info("Logged in as %s (%s)", self.user, self.user.id if self.user else "N/A ID") |         logger.info(f"Logged in as {self.user} ({self.user.id if self.user else 'Unknown'})") | ||||||
|  |  | ||||||
|     async def close(self) -> None: |     async def close(self) -> None: | ||||||
|         """Close the bot and cleanup views.""" |         """Close the bot and cleanup views.""" | ||||||
|         logger.info("Closing bot and cleaning up views.") |         logger.info("Closing bot and cleaning up views.") | ||||||
|         for msg in msg_to_cleanup: |         for msg in msg_to_cleanup: | ||||||
|             logger.debug("Removing view: %s", msg.id) |             logger.debug(f"Removing view: {msg.id}") | ||||||
|             try: |             try: | ||||||
|                 # If the message is "/remind list timed out.", skip it |                 # If the message is "/remind list timed out.", skip it | ||||||
|                 if "/remind list timed out." in msg.content: |                 if "`/remind list` timed out." in msg.content: | ||||||
|                     logger.debug("Message %s is a timeout message. Skipping.", msg.id) |                     logger.debug(f"Message {msg.id} is a timeout message. Skipping.") | ||||||
|                     continue |                     continue | ||||||
|  |  | ||||||
|                 await msg.delete() |                 await msg.delete() | ||||||
|             except discord.HTTPException as e: |             except discord.HTTPException as e: | ||||||
|                 if e.status != 401: |                 if e.status != 401: | ||||||
|                     # Skip if the webhook token is invalid |                     # Skip if the webhook token is invalid | ||||||
|                     logger.error("Failed to remove view: %s", e)  # noqa: TRY400 |                     logger.error(f"Failed to remove view: {msg.id} - {e.text} - {e.status} - {e.code}") | ||||||
|             except asyncio.exceptions.CancelledError: |             except asyncio.exceptions.CancelledError: | ||||||
|                 logger.error("Failed to remove view: Task was cancelled.")  # noqa: TRY400 |                 logger.error("Failed to remove view: Task was cancelled.") | ||||||
|  |  | ||||||
|         return await super().close() |         return await super().close() | ||||||
|  |  | ||||||
| @@ -138,13 +134,12 @@ class RemindBotClient(discord.Client): | |||||||
|                 time: str = "Paused" |                 time: str = "Paused" | ||||||
|                 if hasattr(job, "next_run_time") and job.next_run_time and isinstance(job.next_run_time, datetime.datetime): |                 if hasattr(job, "next_run_time") and job.next_run_time and isinstance(job.next_run_time, datetime.datetime): | ||||||
|                     time = job.next_run_time.strftime("%Y-%m-%d %H:%M:%S") |                     time = job.next_run_time.strftime("%Y-%m-%d %H:%M:%S") | ||||||
|  |                 logger.info(rf"\t{job.id}: {job.name} - {time} - {msg}") | ||||||
|  |  | ||||||
|                 logger.info("\t%s: %s (%s)", msg[:50] or "No message", time, job.id) |         except (AttributeError, LookupError): | ||||||
|         except Exception: |  | ||||||
|             logger.exception("Failed to loop through jobs") |             logger.exception("Failed to loop through jobs") | ||||||
|  |  | ||||||
|         self.tree.copy_global_to(guild=GUILD_ID) |         await self.tree.sync() | ||||||
|         await self.tree.sync(guild=GUILD_ID) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class RemindGroup(discord.app_commands.Group): | class RemindGroup(discord.app_commands.Group): | ||||||
| @@ -178,8 +173,8 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|         # TODO(TheLovinator): Check if we have access to the channel and user # noqa: TD003 |         # TODO(TheLovinator): Check if we have access to the channel and user # noqa: TD003 | ||||||
|         await interaction.response.defer() |         await interaction.response.defer() | ||||||
|  |  | ||||||
|         logger.info("New reminder from %s (%s) in %s", interaction.user, interaction.user.id, interaction.channel) |         logger.info(f"New reminder from {interaction.user} ({interaction.user.id}) in {interaction.channel}") | ||||||
|         logger.info("Arguments: %s", {k: v for k, v in locals().items() if k != "self" and v is not None}) |         logger.info(f"Arguments: {locals()}") | ||||||
|  |  | ||||||
|         # Check if we have access to the specified channel or the current channel |         # Check if we have access to the specified channel or the current channel | ||||||
|         target_channel: InteractionChannel | None = channel or interaction.channel |         target_channel: InteractionChannel | None = channel or interaction.channel | ||||||
| @@ -218,7 +213,7 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|                     "message": message, |                     "message": message, | ||||||
|                 }, |                 }, | ||||||
|             ) |             ) | ||||||
|             logger.info("User reminder job created: %s for %s at %s", user_reminder, user.id, time) |             logger.info(f"User reminder job created: {user_reminder} for {user.id} at {parsed_time}") | ||||||
|  |  | ||||||
|             dm_message = f" and a DM to {user.display_name}" |             dm_message = f" and a DM to {user.display_name}" | ||||||
|             if not dm_and_current_channel: |             if not dm_and_current_channel: | ||||||
| @@ -239,7 +234,7 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|                 "author_id": interaction.user.id, |                 "author_id": interaction.user.id, | ||||||
|             }, |             }, | ||||||
|         ) |         ) | ||||||
|         logger.info("Channel reminder job created: %s for %s at %s", channel_job, channel_id, time) |         logger.info(f"Channel reminder job created: {channel_job} for {channel_id}") | ||||||
|  |  | ||||||
|         msg: str = ( |         msg: str = ( | ||||||
|             f"Hello {interaction.user.display_name},\n" |             f"Hello {interaction.user.display_name},\n" | ||||||
| @@ -251,7 +246,7 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|  |  | ||||||
|     # /remind event |     # /remind event | ||||||
|     @discord.app_commands.command(name="event", description="Add a new Discord event.") |     @discord.app_commands.command(name="event", description="Add a new Discord event.") | ||||||
|     async def add_event(  # noqa: PLR0913, PLR0917, PLR6301 |     async def add_event(  # noqa: C901, PLR0913, PLR0917, PLR6301 | ||||||
|         self, |         self, | ||||||
|         interaction: discord.Interaction, |         interaction: discord.Interaction, | ||||||
|         message: str, |         message: str, | ||||||
| @@ -272,8 +267,8 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|         """ |         """ | ||||||
|         await interaction.response.defer() |         await interaction.response.defer() | ||||||
|  |  | ||||||
|         logger.info("New event from %s (%s) in %s", interaction.user, interaction.user.id, interaction.channel) |         logger.info(f"New event from {interaction.user} ({interaction.user.id}) in {interaction.channel}") | ||||||
|         logger.info("Arguments: %s", {k: v for k, v in locals().items() if k != "self" and v is not None}) |         logger.info(f"Arguments: {locals()}") | ||||||
|  |  | ||||||
|         guild: discord.Guild | None = interaction.guild |         guild: discord.Guild | None = interaction.guild | ||||||
|         if not guild: |         if not guild: | ||||||
| @@ -296,15 +291,19 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|  |  | ||||||
|         reason_msg: str = f"Event created by {interaction.user} ({interaction.user.id})." |         reason_msg: str = f"Event created by {interaction.user} ({interaction.user.id})." | ||||||
|  |  | ||||||
|         event: discord.ScheduledEvent = await guild.create_scheduled_event( |         try: | ||||||
|             name=message, |             event: discord.ScheduledEvent = await guild.create_scheduled_event( | ||||||
|             start_time=event_start_time, |                 name=message, | ||||||
|             entity_type=discord.EntityType.external, |                 start_time=event_start_time, | ||||||
|             privacy_level=discord.PrivacyLevel.guild_only, |                 entity_type=discord.EntityType.external, | ||||||
|             end_time=event_end_time, |                 privacy_level=discord.PrivacyLevel.guild_only, | ||||||
|             reason=reason or reason_msg, |                 end_time=event_end_time, | ||||||
|             location=location, |                 reason=reason or reason_msg, | ||||||
|         ) |                 location=location, | ||||||
|  |             ) | ||||||
|  |         except discord.Forbidden as e: | ||||||
|  |             await interaction.followup.send(content=f"I don't have permission to create events in this guild: {e}", ephemeral=True) | ||||||
|  |             return | ||||||
|  |  | ||||||
|         if start_immediately: |         if start_immediately: | ||||||
|             await event.start() |             await event.start() | ||||||
| @@ -354,12 +353,12 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|         for job in jobs: |         for job in jobs: | ||||||
|             # If the job has guild_id and it's not the current guild, skip it |             # If the job has guild_id and it's not the current guild, skip it | ||||||
|             if job.kwargs.get("guild_id") and job.kwargs.get("guild_id") != guild.id: |             if job.kwargs.get("guild_id") and job.kwargs.get("guild_id") != guild.id: | ||||||
|                 logger.debug("Skipping job: %s because it's not in the current guild.", job.id) |                 logger.debug(f"Skipping job: {job.id} because it's not in the current guild.") | ||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|             # If the job has channel_id and it's not in the current guild, skip it |             # If the job has channel_id and it's not in the current guild, skip it | ||||||
|             if job.kwargs.get("channel_id") and job.kwargs.get("channel_id") not in list_of_channels_in_current_guild: |             if job.kwargs.get("channel_id") and job.kwargs.get("channel_id") not in list_of_channels_in_current_guild: | ||||||
|                 logger.debug("Skipping job: %s because it's not in the current guild's channels.", job.id) |                 logger.debug(f"Skipping job: {job.id} because it's not in the current guild.") | ||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|             jobs_in_guild.append(job) |             jobs_in_guild.append(job) | ||||||
| @@ -421,15 +420,15 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|         try: |         try: | ||||||
|             await interaction.response.defer() |             await interaction.response.defer() | ||||||
|         except discord.HTTPException as e: |         except discord.HTTPException as e: | ||||||
|             logger.exception("Failed to defer interaction: text=%s, status=%s, code=%s", e.text, e.status, e.code) |             logger.exception(f"Failed to defer interaction: {e.text=}, {e.status=}, {e.code=}") | ||||||
|             return |             return | ||||||
|         except discord.InteractionResponded as e: |         except discord.InteractionResponded as e: | ||||||
|             logger.exception("Interaction already responded to - interaction: %s", e.interaction) |             logger.exception(f"Interaction already responded to - interaction: {interaction}, {e}") | ||||||
|             return |             return | ||||||
|  |  | ||||||
|         # Log kwargs |         # Log kwargs | ||||||
|         logger.info("New cron job from %s (%s) in %s", interaction.user, interaction.user.id, interaction.channel) |         logger.info(f"New cron job from {interaction.user} ({interaction.user.id}) in {interaction.channel}") | ||||||
|         logger.info("Cron job arguments: %s", {k: v for k, v in locals().items() if k != "self" and v is not None}) |         logger.info(f"Cron job arguments: {locals()}") | ||||||
|  |  | ||||||
|         # Get the channel ID |         # Get the channel ID | ||||||
|         channel_id: int | None = channel.id if channel else (interaction.channel.id if interaction.channel else None) |         channel_id: int | None = channel.id if channel else (interaction.channel.id if interaction.channel else None) | ||||||
| @@ -548,8 +547,8 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|         """  # noqa: E501 |         """  # noqa: E501 | ||||||
|         await interaction.response.defer() |         await interaction.response.defer() | ||||||
|  |  | ||||||
|         logger.info("New interval job from %s (%s) in %s", interaction.user, interaction.user.id, interaction.channel) |         logger.info(f"New interval job from {interaction.user} ({interaction.user.id}) in {interaction.channel}") | ||||||
|         logger.info("Arguments: %s", {k: v for k, v in locals().items() if k != "self" and v is not None}) |         logger.info(f"Arguments: {locals()}") | ||||||
|  |  | ||||||
|         # Only allow intervals of 30 seconds or more so we don't spam the channel |         # Only allow intervals of 30 seconds or more so we don't spam the channel | ||||||
|         if weeks == days == hours == minutes == 0 and seconds < 30: |         if weeks == days == hours == minutes == 0 and seconds < 30: | ||||||
| @@ -673,18 +672,18 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|             # Can't be 0 because that's the default value for jobs without a guild |             # Can't be 0 because that's the default value for jobs without a guild | ||||||
|             guild_id: int = interaction.guild.id if interaction.guild else -1 |             guild_id: int = interaction.guild.id if interaction.guild else -1 | ||||||
|             channels_in_this_guild: list[int] = [c.id for c in interaction.guild.channels] if interaction.guild else [] |             channels_in_this_guild: list[int] = [c.id for c in interaction.guild.channels] if interaction.guild else [] | ||||||
|             logger.debug("Guild ID: %s, Channels in this guild: %s", guild_id, channels_in_this_guild) |             logger.debug(f"Guild ID: {guild_id}") | ||||||
|  |  | ||||||
|             for job in jobs_data.get("jobs", []): |             for job in jobs_data.get("jobs", []): | ||||||
|                 # Check if the job is in the current guild |                 # Check if the job is in the current guild | ||||||
|                 job_guild_id = job.get("kwargs", {}).get("guild_id", 0) |                 job_guild_id = job.get("kwargs", {}).get("guild_id", 0) | ||||||
|                 if job_guild_id and job_guild_id != guild_id: |                 if job_guild_id and job_guild_id != guild_id: | ||||||
|                     logger.debug("Removing job: %s because it's not in the current guild. %s vs %s", job.get("id"), job_guild_id, guild_id) |                     logger.debug(f"Removing job: {job.get('id')} because it's not in the current guild.") | ||||||
|                     jobs_data["jobs"].remove(job) |                     jobs_data["jobs"].remove(job) | ||||||
|  |  | ||||||
|                 # Check if the channel is in the current guild |                 # Check if the channel is in the current guild | ||||||
|                 if job.get("kwargs", {}).get("channel_id") not in channels_in_this_guild: |                 if job.get("kwargs", {}).get("channel_id") not in channels_in_this_guild: | ||||||
|                     logger.debug("Removing job: %s because it's not in the current guild's channels.", job.get("id")) |                     logger.debug(f"Removing job: {job.get('id')} because it's not in the current guild.") | ||||||
|                     jobs_data["jobs"].remove(job) |                     jobs_data["jobs"].remove(job) | ||||||
|  |  | ||||||
|         msg: str = "All reminders in this server have been backed up." if not all_servers else "All reminders have been backed up." |         msg: str = "All reminders in this server have been backed up." if not all_servers else "All reminders have been backed up." | ||||||
| @@ -712,7 +711,7 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|         """ |         """ | ||||||
|         await interaction.response.defer() |         await interaction.response.defer() | ||||||
|  |  | ||||||
|         logger.info("Restoring reminders from file for %s (%s) in %s", interaction.user, interaction.user.id, interaction.channel) |         logger.info(f"Restoring reminders from file for {interaction.user} ({interaction.user.id}) in {interaction.channel}") | ||||||
|  |  | ||||||
|         # Get the old jobs |         # Get the old jobs | ||||||
|         old_jobs: list[Job] = scheduler.get_jobs() |         old_jobs: list[Job] = scheduler.get_jobs() | ||||||
| @@ -755,7 +754,7 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|  |  | ||||||
|         # Save the file to a temporary file and import the jobs |         # Save the file to a temporary file and import the jobs | ||||||
|         with tempfile.NamedTemporaryFile(mode="w+", delete=False, encoding="utf-8", suffix=".json") as temp_file: |         with tempfile.NamedTemporaryFile(mode="w+", delete=False, encoding="utf-8", suffix=".json") as temp_file: | ||||||
|             logger.info("Saving attachment to %s", temp_file.name) |             logger.info(f"Saving attachment to {temp_file.name}") | ||||||
|             await attachment.save(Path(temp_file.name)) |             await attachment.save(Path(temp_file.name)) | ||||||
|  |  | ||||||
|             # Load the jobs data from the file |             # Load the jobs data from the file | ||||||
| @@ -763,7 +762,7 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|             jobs_data: dict = json.load(temp_file) |             jobs_data: dict = json.load(temp_file) | ||||||
|  |  | ||||||
|             logger.info("Importing jobs from file") |             logger.info("Importing jobs from file") | ||||||
|             logger.debug("Jobs data: %s", jobs_data) |             logger.debug(f"Jobs data: {jobs_data}") | ||||||
|  |  | ||||||
|             with tempfile.NamedTemporaryFile(mode="w+", delete=False, encoding="utf-8", suffix=".json") as temp_import_file: |             with tempfile.NamedTemporaryFile(mode="w+", delete=False, encoding="utf-8", suffix=".json") as temp_import_file: | ||||||
|                 # We can't import jobs with the same ID so remove them from the JSON |                 # We can't import jobs with the same ID so remove them from the JSON | ||||||
| @@ -771,10 +770,10 @@ class RemindGroup(discord.app_commands.Group): | |||||||
|                 jobs_already_exist = [job.get("id") for job in jobs_data.get("jobs", []) if scheduler.get_job(job.get("id"))] |                 jobs_already_exist = [job.get("id") for job in jobs_data.get("jobs", []) if scheduler.get_job(job.get("id"))] | ||||||
|                 jobs_data["jobs"] = jobs |                 jobs_data["jobs"] = jobs | ||||||
|                 for job_id in jobs_already_exist: |                 for job_id in jobs_already_exist: | ||||||
|                     logger.debug("Removed job: %s because it already exists.", job_id) |                     logger.debug(f"Removed job: {job_id} because it already exists.") | ||||||
|  |  | ||||||
|                 logger.debug("Jobs data after removing existing jobs: %s", jobs_data) |                 logger.debug(f"Jobs data after removing existing jobs: {jobs_data}") | ||||||
|                 logger.info("Jobs already exist: %s", jobs_already_exist) |                 logger.info(f"Jobs already exist: {jobs_already_exist}") | ||||||
|  |  | ||||||
|                 # Write the new data to a temporary file |                 # Write the new data to a temporary file | ||||||
|                 json.dump(jobs_data, temp_import_file) |                 json.dump(jobs_data, temp_import_file) | ||||||
| @@ -823,7 +822,7 @@ def send_webhook(url: str = "", message: str = "") -> None: | |||||||
|  |  | ||||||
|     if not url: |     if not url: | ||||||
|         url = get_webhook_url() |         url = get_webhook_url() | ||||||
|         logger.error("No webhook URL provided. Using the one from settings.") |         logger.error(f"No webhook URL provided. Using the one from settings: {url}") | ||||||
|         webhook: DiscordWebhook = DiscordWebhook( |         webhook: DiscordWebhook = DiscordWebhook( | ||||||
|             url=url, |             url=url, | ||||||
|             username="discord-reminder-bot", |             username="discord-reminder-bot", | ||||||
| @@ -851,7 +850,7 @@ async def send_to_discord(channel_id: int, message: str, author_id: int) -> None | |||||||
|  |  | ||||||
|     # Channels we can't send messages to |     # Channels we can't send messages to | ||||||
|     if isinstance(channel, discord.ForumChannel | discord.CategoryChannel | PrivateChannel): |     if isinstance(channel, discord.ForumChannel | discord.CategoryChannel | PrivateChannel): | ||||||
|         logger.warning("We haven't implemented sending messages to this channel type (%s)", type(channel)) |         logger.warning(f"We haven't implemented sending messages to this channel type {type(channel)}") | ||||||
|         return |         return | ||||||
|  |  | ||||||
|     await channel.send(f"<@{author_id}>\n{message}") |     await channel.send(f"<@{author_id}>\n{message}") | ||||||
| @@ -865,17 +864,17 @@ async def send_to_user(user_id: int, guild_id: int, message: str) -> None: | |||||||
|         guild_id: The guild ID to get the user from. |         guild_id: The guild ID to get the user from. | ||||||
|         message: The message to send. |         message: The message to send. | ||||||
|     """ |     """ | ||||||
|     logger.info("Sending message to user %s in guild %s:\n%s", user_id, guild_id, message) |     logger.info(f"Sending message to user {user_id} in guild {guild_id}") | ||||||
|     try: |     try: | ||||||
|         guild: discord.Guild | None = bot.get_guild(guild_id) |         guild: discord.Guild | None = bot.get_guild(guild_id) | ||||||
|         if guild is None: |         if guild is None: | ||||||
|             guild = await bot.fetch_guild(guild_id) |             guild = await bot.fetch_guild(guild_id) | ||||||
|     except discord.NotFound: |     except discord.NotFound: | ||||||
|         current_guilds: Sequence[discord.Guild] = bot.guilds |         current_guilds: Sequence[discord.Guild] = bot.guilds | ||||||
|         logger.exception("Guild not found. Current guilds: %s", current_guilds) |         logger.exception(f"Guild not found. Current guilds: {current_guilds}") | ||||||
|         return |         return | ||||||
|     except discord.HTTPException: |     except discord.HTTPException: | ||||||
|         logger.exception("Failed to fetch guild") |         logger.exception(f"Failed to fetch guild {guild_id}") | ||||||
|         return |         return | ||||||
|  |  | ||||||
|     try: |     try: | ||||||
| @@ -883,21 +882,21 @@ async def send_to_user(user_id: int, guild_id: int, message: str) -> None: | |||||||
|         if member is None: |         if member is None: | ||||||
|             member = await guild.fetch_member(user_id) |             member = await guild.fetch_member(user_id) | ||||||
|     except discord.Forbidden: |     except discord.Forbidden: | ||||||
|         logger.exception("We do not have access to the guild. Guild: %s, User: %s", guild_id, user_id) |         logger.exception(f"We do not have access to the guild. Guild: {guild_id}, User: {user_id}") | ||||||
|         return |         return | ||||||
|     except discord.NotFound: |     except discord.NotFound: | ||||||
|         logger.exception("Member not found. Guild: %s, User: %s", guild_id, user_id) |         logger.exception(f"Member not found. Guild: {guild_id}, User: {user_id}") | ||||||
|         return |         return | ||||||
|     except discord.HTTPException: |     except discord.HTTPException: | ||||||
|         logger.exception("Fetching the member failed. Guild: %s, User: %s", guild_id, user_id) |         logger.exception(f"Fetching the member failed. Guild: {guild_id}, User: {user_id}") | ||||||
|         return |         return | ||||||
|  |  | ||||||
|     try: |     try: | ||||||
|         await member.send(message) |         await member.send(message) | ||||||
|     except discord.HTTPException: |     except discord.HTTPException: | ||||||
|         logger.exception("Failed to send message (%s) to user (%s) in guild (%s)", message, user_id, guild_id) |         logger.exception(f"Failed to send message '{message}' to user '{user_id}' in guild '{guild_id}'") | ||||||
|  |  | ||||||
|  |  | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|     bot_token: str = get_bot_token() |     bot_token: str = get_bot_token() | ||||||
|     bot.run(bot_token, root_logger=True) |     bot.run(bot_token) | ||||||
|   | |||||||
| @@ -1,17 +1,15 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import logging |  | ||||||
| from typing import TYPE_CHECKING | from typing import TYPE_CHECKING | ||||||
|  |  | ||||||
| from apscheduler.triggers.date import DateTrigger | from apscheduler.triggers.date import DateTrigger | ||||||
|  | from loguru import logger | ||||||
|  |  | ||||||
| if TYPE_CHECKING: | if TYPE_CHECKING: | ||||||
|     import datetime |     import datetime | ||||||
|  |  | ||||||
|     from apscheduler.job import Job |     from apscheduler.job import Job | ||||||
|  |  | ||||||
| logger: logging.Logger = logging.getLogger(__name__) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def calculate(job: Job) -> str | None: | def calculate(job: Job) -> str | None: | ||||||
|     """Calculate the time left for a job. |     """Calculate the time left for a job. | ||||||
| @@ -26,8 +24,8 @@ def calculate(job: Job) -> str | None: | |||||||
|  |  | ||||||
|     # Check if the job is paused |     # Check if the job is paused | ||||||
|     if trigger_time is None: |     if trigger_time is None: | ||||||
|         logger.error("Couldn't calculate time for job: %s: %s", job.id, job.name) |         logger.error(f"Couldn't calculate time for job: {job.id}") | ||||||
|         logger.error("State: %s", job.__getstate__() if hasattr(job, "__getstate__") else "No state") |         logger.error(f"State: {job.__getstate__() if hasattr(job, '__getstate__') else 'No state'}") | ||||||
|         return None |         return None | ||||||
|  |  | ||||||
|     return f"<t:{int(trigger_time.timestamp())}:R>" |     return f"<t:{int(trigger_time.timestamp())}:R>" | ||||||
|   | |||||||
| @@ -1,15 +1,13 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import datetime | import datetime | ||||||
| import logging |  | ||||||
| from zoneinfo import ZoneInfo, ZoneInfoNotFoundError | from zoneinfo import ZoneInfo, ZoneInfoNotFoundError | ||||||
|  |  | ||||||
| import dateparser | import dateparser | ||||||
|  | from loguru import logger | ||||||
|  |  | ||||||
| from discord_reminder_bot.settings import get_timezone | from discord_reminder_bot.settings import get_timezone | ||||||
|  |  | ||||||
| logger: logging.Logger = logging.getLogger(__name__) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def parse_time(date_to_parse: str | None, timezone: str | None = None, use_dotenv: bool = True) -> datetime.datetime | None:  # noqa: FBT001, FBT002 | def parse_time(date_to_parse: str | None, timezone: str | None = None, use_dotenv: bool = True) -> datetime.datetime | None:  # noqa: FBT001, FBT002 | ||||||
|     """Parse a date string into a datetime object. |     """Parse a date string into a datetime object. | ||||||
| @@ -22,7 +20,7 @@ def parse_time(date_to_parse: str | None, timezone: str | None = None, use_doten | |||||||
|     Returns: |     Returns: | ||||||
|         datetime.datetime: The parsed datetime object. |         datetime.datetime: The parsed datetime object. | ||||||
|     """ |     """ | ||||||
|     logger.info("Parsing date: '%s' with timezone: '%s'", date_to_parse, timezone) |     logger.info(f"Parsing date: '{date_to_parse}' with timezone: '{timezone}'") | ||||||
|  |  | ||||||
|     if not date_to_parse: |     if not date_to_parse: | ||||||
|         logger.error("No date provided to parse.") |         logger.error("No date provided to parse.") | ||||||
| @@ -35,7 +33,7 @@ def parse_time(date_to_parse: str | None, timezone: str | None = None, use_doten | |||||||
|     try: |     try: | ||||||
|         tz = ZoneInfo(timezone) |         tz = ZoneInfo(timezone) | ||||||
|     except (ZoneInfoNotFoundError, ModuleNotFoundError): |     except (ZoneInfoNotFoundError, ModuleNotFoundError): | ||||||
|         logger.error("Invalid timezone provided: '%s'. Using default timezone: '%s'", timezone, get_timezone(use_dotenv))  # noqa: TRY400 |         logger.error(f"Invalid timezone provided: '{timezone}'. Using {get_timezone(use_dotenv)} instead.") | ||||||
|         tz = ZoneInfo("UTC") |         tz = ZoneInfo("UTC") | ||||||
|  |  | ||||||
|     try: |     try: | ||||||
| @@ -51,4 +49,6 @@ def parse_time(date_to_parse: str | None, timezone: str | None = None, use_doten | |||||||
|     except (ValueError, TypeError): |     except (ValueError, TypeError): | ||||||
|         return None |         return None | ||||||
|  |  | ||||||
|  |     logger.debug(f"Parsed date: {parsed_date} from '{date_to_parse}'") | ||||||
|  |  | ||||||
|     return parsed_date |     return parsed_date | ||||||
|   | |||||||
| @@ -1,6 +1,5 @@ | |||||||
| from __future__ import annotations | from __future__ import annotations | ||||||
|  |  | ||||||
| import logging |  | ||||||
| from typing import TYPE_CHECKING | from typing import TYPE_CHECKING | ||||||
|  |  | ||||||
| import discord | import discord | ||||||
| @@ -10,6 +9,7 @@ from apscheduler.schedulers.asyncio import AsyncIOScheduler | |||||||
| from apscheduler.triggers.cron import CronTrigger | from apscheduler.triggers.cron import CronTrigger | ||||||
| from apscheduler.triggers.interval import IntervalTrigger | from apscheduler.triggers.interval import IntervalTrigger | ||||||
| from discord.ui import Button, Select | from discord.ui import Button, Select | ||||||
|  | from loguru import logger | ||||||
|  |  | ||||||
| from discord_reminder_bot.misc import DateTrigger, calc_time, calculate | from discord_reminder_bot.misc import DateTrigger, calc_time, calculate | ||||||
| from discord_reminder_bot.parser import parse_time | from discord_reminder_bot.parser import parse_time | ||||||
| @@ -21,9 +21,6 @@ if TYPE_CHECKING: | |||||||
|     from apscheduler.schedulers.asyncio import AsyncIOScheduler |     from apscheduler.schedulers.asyncio import AsyncIOScheduler | ||||||
|  |  | ||||||
|  |  | ||||||
| logger: logging.Logger = logging.getLogger(__name__) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class ModifyJobModal(discord.ui.Modal, title="Modify Job"): | class ModifyJobModal(discord.ui.Modal, title="Modify Job"): | ||||||
|     """Modal for modifying a job.""" |     """Modal for modifying a job.""" | ||||||
|  |  | ||||||
| @@ -53,12 +50,12 @@ class ModifyJobModal(discord.ui.Modal, title="Modify Job"): | |||||||
|         self.job_name.placeholder = self.job.kwargs.get("message", "No message found") |         self.job_name.placeholder = self.job.kwargs.get("message", "No message found") | ||||||
|         self.job_date.placeholder = self.job.next_run_time.strftime("%Y-%m-%d %H:%M:%S %Z") |         self.job_date.placeholder = self.job.next_run_time.strftime("%Y-%m-%d %H:%M:%S %Z") | ||||||
|  |  | ||||||
|         logger.info("Job '%s' Modal created", self.job.name) |         logger.info(f"Job '{job_name_label}' modified: Initializing modal") | ||||||
|         logger.info("\tCurrent date: '%s'", self.job.next_run_time) |         logger.info(f"\tCurrent date: '{self.job.next_run_time}'") | ||||||
|         logger.info("\tCurrent message: '%s'", self.job.kwargs.get("message", "N/A")) |         logger.info(f"\tCurrent message: '{self.job.kwargs.get('message', 'No message found')}") | ||||||
|  |  | ||||||
|         logger.info("\tName label: '%s'", self.job_name.label) |         logger.info(f"\tName label: '{self.job_name.label}'") | ||||||
|         logger.info("\tDate label: '%s'", self.job_date.label) |         logger.info(f"\tDate label: '{self.job_date.label}'") | ||||||
|  |  | ||||||
|     async def on_submit(self, interaction: discord.Interaction) -> None: |     async def on_submit(self, interaction: discord.Interaction) -> None: | ||||||
|         """Submit the job modifications. |         """Submit the job modifications. | ||||||
| @@ -66,27 +63,29 @@ class ModifyJobModal(discord.ui.Modal, title="Modify Job"): | |||||||
|         Args: |         Args: | ||||||
|             interaction: The interaction object for the command. |             interaction: The interaction object for the command. | ||||||
|         """ |         """ | ||||||
|         logger.info("Job '%s' modified: Submitting changes", self.job.name) |         job_msg: str = self.job.kwargs.get("message", "No message found") | ||||||
|  |         logger.info(f"Job '{job_msg}' modified: Submitting changes") | ||||||
|         new_name: str = self.job_name.value |         new_name: str = self.job_name.value | ||||||
|         new_date_str: str = self.job_date.value |         new_date_str: str = self.job_date.value | ||||||
|         old_date: datetime.datetime = self.job.next_run_time |         old_date: datetime.datetime = self.job.next_run_time | ||||||
|  |  | ||||||
|         # if both are empty, do nothing |         # if both are empty, do nothing | ||||||
|         if not new_name and not new_date_str: |         if not new_name and not new_date_str: | ||||||
|             logger.info("Job '%s' modified: No changes submitted", self.job.name) |             logger.info(f"Job '{job_msg}' modified: No changes submitted.") | ||||||
|  |  | ||||||
|             await interaction.response.send_message( |             await interaction.response.send_message( | ||||||
|                 content=f"Job **{self.job.name}** was not modified by {interaction.user.mention}.\nNo changes submitted.", |                 content=f"Job **{job_msg}**.\nNo changes submitted.", | ||||||
|  |                 ephemeral=True, | ||||||
|             ) |             ) | ||||||
|             return |             return | ||||||
|  |  | ||||||
|         if new_date_str and new_date_str != old_date.strftime("%Y-%m-%d %H:%M:%S %Z"): |         if new_date_str and new_date_str != old_date.strftime("%Y-%m-%d %H:%M:%S %Z"): | ||||||
|             new_date: datetime.datetime | None = parse_time(new_date_str) |             new_date: datetime.datetime | None = parse_time(new_date_str) | ||||||
|             if not new_date: |             if not new_date: | ||||||
|                 logger.error("Job '%s' modified: Failed to parse date: '%s'", self.job.name, new_date_str) |                 logger.error(f"Job '{job_msg}' modified: Failed to parse date: '{new_date_str}'") | ||||||
|                 await interaction.response.send_message( |                 await interaction.response.send_message( | ||||||
|                     content=( |                     content=( | ||||||
|                         f"Failed modifying job **{self.job.name}**\n" |                         f"Failed modifying job **{job_msg}**\n" | ||||||
|                         f"Job ID: **{self.job.id}**\n" |                         f"Job ID: **{self.job.id}**\n" | ||||||
|                         f"Failed to parse date: **{new_date_str}**\n" |                         f"Failed to parse date: **{new_date_str}**\n" | ||||||
|                         f"Defaulting to old date: **{old_date.strftime('%Y-%m-%d %H:%M:%S')}** {calc_time(old_date)}" |                         f"Defaulting to old date: **{old_date.strftime('%Y-%m-%d %H:%M:%S')}** {calc_time(old_date)}" | ||||||
| @@ -94,8 +93,8 @@ class ModifyJobModal(discord.ui.Modal, title="Modify Job"): | |||||||
|                 ) |                 ) | ||||||
|                 return |                 return | ||||||
|  |  | ||||||
|             logger.info("Job '%s' modified: New date: '%s'", self.job.name, new_date) |             logger.info(f"Job '{job_msg}' modified: New date: '{new_date}'") | ||||||
|             logger.info("Job '%s' modified: Old date: '%s'", self.job.name, old_date) |             logger.info(f"Job '{job_msg}' modified: Old date: '{old_date}'") | ||||||
|             self.job.modify(next_run_time=new_date) |             self.job.modify(next_run_time=new_date) | ||||||
|  |  | ||||||
|             old_date_str: str = old_date.strftime("%Y-%m-%d %H:%M:%S") |             old_date_str: str = old_date.strftime("%Y-%m-%d %H:%M:%S") | ||||||
| @@ -103,16 +102,16 @@ class ModifyJobModal(discord.ui.Modal, title="Modify Job"): | |||||||
|  |  | ||||||
|             await interaction.response.send_message( |             await interaction.response.send_message( | ||||||
|                 content=( |                 content=( | ||||||
|                     f"Job **{self.job.name}** was modified by {interaction.user.mention}:\n" |                     f"Job **{job_msg}** was modified by {interaction.user.mention}:\n" | ||||||
|                     f"Job ID: **{self.job.id}**\n" |                     f"Job ID: **{self.job.id}**\n" | ||||||
|                     f"Old date: **{old_date_str}** {calculate(self.job)} {calc_time(old_date)}\n" |                     f"Old date: **{old_date_str}** {calculate(self.job)} {calc_time(old_date)}\n" | ||||||
|                     f"New date: **{new_date_str}** {calculate(self.job)} {calc_time(new_date)}" |                     f"New date: **{new_date_str}** {calculate(self.job)} {calc_time(new_date)}" | ||||||
|                 ), |                 ), | ||||||
|             ) |             ) | ||||||
|  |  | ||||||
|         if self.job_name.value and self.job.name != new_name: |         if self.job_name.value and job_msg != new_name: | ||||||
|             logger.info("Job '%s' modified: New name: '%s'", self.job.name, new_name) |             logger.info(f"Job '{job_msg}' modified: New name: '{new_name}'") | ||||||
|             logger.info("Job '%s' modified: Old name: '%s'", self.job.name, self.job.name) |             logger.info(f"Job '{job_msg}' modified: Old name: '{job_msg}'") | ||||||
|             self.job.modify(name=new_name) |             self.job.modify(name=new_name) | ||||||
|  |  | ||||||
|             await interaction.response.send_message( |             await interaction.response.send_message( | ||||||
| @@ -187,12 +186,12 @@ class JobSelector(Select): | |||||||
|         for job in jobs: |         for job in jobs: | ||||||
|             # If the job has guild_id and it's not the current guild, skip it |             # If the job has guild_id and it's not the current guild, skip it | ||||||
|             if job.kwargs.get("guild_id") and job.kwargs.get("guild_id") != guild.id: |             if job.kwargs.get("guild_id") and job.kwargs.get("guild_id") != guild.id: | ||||||
|                 logger.debug("Skipping job: %s because it's not in the current guild.", job.id) |                 logger.debug(f"Skipping job: {job.id} because it's not in the current guild.") | ||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|             # If the job has channel_id and it's not in the current guild, skip it |             # If the job has channel_id and it's not in the current guild, skip it | ||||||
|             if job.kwargs.get("channel_id") and job.kwargs.get("channel_id") not in list_of_channels_in_current_guild: |             if job.kwargs.get("channel_id") and job.kwargs.get("channel_id") not in list_of_channels_in_current_guild: | ||||||
|                 logger.debug("Skipping job: %s because it's not in the current guild's channels.", job.id) |                 logger.debug(f"Skipping job: {job.id} because it's not from a channel in the current guild.") | ||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|             jobs_in_guild.append(job) |             jobs_in_guild.append(job) | ||||||
| @@ -252,14 +251,14 @@ class JobManagementView(discord.ui.View): | |||||||
|         self.add_item(JobSelector(scheduler, self.guild)) |         self.add_item(JobSelector(scheduler, self.guild)) | ||||||
|         self.update_buttons() |         self.update_buttons() | ||||||
|  |  | ||||||
|         logger.debug("JobManagementView created for job: %s", job.id) |         logger.debug(f"JobManagementView created for job: {self.job.id}") | ||||||
|  |  | ||||||
|     async def on_timeout(self) -> None: |     async def on_timeout(self) -> None: | ||||||
|         """Handle the view timeout.""" |         """Handle the view timeout.""" | ||||||
|         if self.message: |         if self.message: | ||||||
|             await self.message.edit(content="`/remind list` timed out.", embed=None, view=None) |             await self.message.edit(content="`/remind list` timed out.", embed=None, view=None) | ||||||
|         else: |         else: | ||||||
|             logger.debug("No message to edit for job: %s", self.job.id) |             logger.debug(f"No message to edit for job: {self.job.id}") | ||||||
|         self.stop() |         self.stop() | ||||||
|  |  | ||||||
|     async def on_error(self, interaction: discord.Interaction, error: Exception, item: discord.ui.Item) -> None: |     async def on_error(self, interaction: discord.Interaction, error: Exception, item: discord.ui.Item) -> None: | ||||||
| @@ -312,9 +311,9 @@ class JobManagementView(discord.ui.View): | |||||||
|         """ |         """ | ||||||
|         job_kwargs: dict = self.job.kwargs or {} |         job_kwargs: dict = self.job.kwargs or {} | ||||||
|  |  | ||||||
|         logger.info("Deleting job: %s because %s clicked the button.", self.job.id, interaction.user.name) |         logger.info(f"Deleting job: {self.job.id}. Clicked by {interaction.user.name}") | ||||||
|         if hasattr(self.job, "__getstate__"): |         if hasattr(self.job, "__getstate__"): | ||||||
|             logger.debug("State: %s", self.job.__getstate__() if hasattr(self.job, "__getstate__") else "No state") |             logger.debug(f"State: {self.job.__getstate__() if hasattr(self.job, '__getstate__') else 'No state'}") | ||||||
|  |  | ||||||
|         job_msg: str | int = job_kwargs.get("message", "No message found") |         job_msg: str | int = job_kwargs.get("message", "No message found") | ||||||
|         msg: str = f"**Job '{job_msg}' has been deleted.**\n" |         msg: str = f"**Job '{job_msg}' has been deleted.**\n" | ||||||
| @@ -346,7 +345,7 @@ class JobManagementView(discord.ui.View): | |||||||
|         if job_kwargs.get("guild_id"): |         if job_kwargs.get("guild_id"): | ||||||
|             msg += f"**Guild**: {job_kwargs.get('guild_id')}\n" |             msg += f"**Guild**: {job_kwargs.get('guild_id')}\n" | ||||||
|  |  | ||||||
|         logger.debug("Deletion message: %s", msg) |         logger.debug(f"Deletion message: {msg}") | ||||||
|  |  | ||||||
|         self.job.remove() |         self.job.remove() | ||||||
|         await interaction.response.send_message(msg) |         await interaction.response.send_message(msg) | ||||||
| @@ -360,9 +359,9 @@ class JobManagementView(discord.ui.View): | |||||||
|             interaction: The interaction object for the command. |             interaction: The interaction object for the command. | ||||||
|             button: The button that was clicked. |             button: The button that was clicked. | ||||||
|         """ |         """ | ||||||
|         logger.info("Modifying job: %s. Clicked by %s", self.job.id, interaction.user.name) |         logger.info(f"Modifying job: {self.job.id}. Clicked by {interaction.user.name}") | ||||||
|         if hasattr(self.job, "__getstate__"): |         if hasattr(self.job, "__getstate__"): | ||||||
|             logger.debug("State: %s", self.job.__getstate__() if hasattr(self.job, "__getstate__") else "No state") |             logger.debug(f"State: {self.job.__getstate__() if hasattr(self.job, '__getstate__') else 'No state'}") | ||||||
|  |  | ||||||
|         modal = ModifyJobModal(self.job, self.scheduler) |         modal = ModifyJobModal(self.job, self.scheduler) | ||||||
|         await interaction.response.send_modal(modal) |         await interaction.response.send_modal(modal) | ||||||
| @@ -377,17 +376,17 @@ class JobManagementView(discord.ui.View): | |||||||
|         """ |         """ | ||||||
|         if hasattr(self.job, "next_run_time"): |         if hasattr(self.job, "next_run_time"): | ||||||
|             if self.job.next_run_time is None: |             if self.job.next_run_time is None: | ||||||
|                 logger.info("State: %s", self.job.__getstate__()) |                 logger.info(f"State: {self.job.__getstate__() if hasattr(self.job, '__getstate__') else 'No state'}") | ||||||
|                 self.job.resume() |                 self.job.resume() | ||||||
|                 status = "resumed" |                 status = "resumed" | ||||||
|                 button.label = "Pause" |                 button.label = "Pause" | ||||||
|             else: |             else: | ||||||
|                 logger.info("State: %s", self.job.__getstate__()) |                 logger.info(f"State: {self.job.__getstate__() if hasattr(self.job, '__getstate__') else 'No state'}") | ||||||
|                 self.job.pause() |                 self.job.pause() | ||||||
|                 status = "paused" |                 status = "paused" | ||||||
|                 button.label = "Resume" |                 button.label = "Resume" | ||||||
|         else: |         else: | ||||||
|             logger.error("Got a job without a next_run_time: %s", self.job.id) |             logger.error(f"Got a job without a next_run_time: {self.job.id}") | ||||||
|             status: str = f"What is this? {self.job.__getstate__()}" |             status: str = f"What is this? {self.job.__getstate__()}" | ||||||
|             button.label = "What?" |             button.label = "What?" | ||||||
|  |  | ||||||
| @@ -409,11 +408,11 @@ class JobManagementView(discord.ui.View): | |||||||
|  |  | ||||||
|     def update_buttons(self) -> None: |     def update_buttons(self) -> None: | ||||||
|         """Update the visibility of buttons based on job status.""" |         """Update the visibility of buttons based on job status.""" | ||||||
|         logger.debug("Updating buttons for job: %s", self.job.id) |         logger.debug(f"Updating buttons for job: {self.job.id}") | ||||||
|         self.pause_button.label = "Resume" if self.job.next_run_time is None else "Pause" |         self.pause_button.label = "Resume" if self.job.next_run_time is None else "Pause" | ||||||
|  |  | ||||||
|         logger.debug("Pause button disabled: %s", self.pause_button.disabled) |         logger.debug(f"Pause button disabled: {self.pause_button.disabled}") | ||||||
|         logger.debug("Pause button label: %s", self.pause_button.label) |         logger.debug(f"Pause button label: {self.pause_button.label}") | ||||||
|  |  | ||||||
|     async def interaction_check(self, interaction: discord.Interaction) -> bool:  # noqa: ARG002 |     async def interaction_check(self, interaction: discord.Interaction) -> bool:  # noqa: ARG002 | ||||||
|         """Check the interaction and update buttons before responding. |         """Check the interaction and update buttons before responding. | ||||||
| @@ -424,11 +423,11 @@ class JobManagementView(discord.ui.View): | |||||||
|         Returns: |         Returns: | ||||||
|             bool: Whether the interaction is valid. |             bool: Whether the interaction is valid. | ||||||
|         """ |         """ | ||||||
|         logger.info("Interaction check for job: %s", self.job.id) |         logger.info(f"Interaction check for job: {self.job.id}") | ||||||
|         logger.debug("Timeout was %s before interaction check", self.timeout) |         logger.debug(f"Timeout was {self.timeout} before interaction check.") | ||||||
|  |  | ||||||
|         self.timeout = 30 |         self.timeout = 30 | ||||||
|         logger.debug("Checking interaction for job: %s", self.job.id) |         logger.debug(f"Checking interaction for job: {self.job.id}") | ||||||
|  |  | ||||||
|         self.update_buttons() |         self.update_buttons() | ||||||
|         return True |         return True | ||||||
|   | |||||||
| @@ -30,6 +30,9 @@ dependencies = [ | |||||||
|  |  | ||||||
|     # For error tracking |     # For error tracking | ||||||
|     "sentry-sdk>=2.20.0,<3.0.0", # https://github.com/getsentry/sentry-python |     "sentry-sdk>=2.20.0,<3.0.0", # https://github.com/getsentry/sentry-python | ||||||
|  |  | ||||||
|  |     # For logging | ||||||
|  |     "loguru>=0.7.3,<1.0.0", # https://github.com/Delgan/loguru | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [dependency-groups] | [dependency-groups] | ||||||
| @@ -75,9 +78,14 @@ discord-webhook = {version = ">=1.3.1,<2.0.0"} | |||||||
| # For loading environment variables from a .env file | # For loading environment variables from a .env file | ||||||
| python-dotenv = {version = ">=1.0.1,<2.0.0"} | python-dotenv = {version = ">=1.0.1,<2.0.0"} | ||||||
|  |  | ||||||
|  | # https://github.com/getsentry/sentry-python | ||||||
| # For error tracking | # For error tracking | ||||||
| sentry-sdk = {version = ">=2.20.0,<3.0.0"} | sentry-sdk = {version = ">=2.20.0,<3.0.0"} | ||||||
|  |  | ||||||
|  | # https://github.com/Delgan/loguru | ||||||
|  | # For logging | ||||||
|  | loguru = {version = ">=0.7.3,<1.0.0"} | ||||||
|  |  | ||||||
| [tool.poetry.dev-dependencies] | [tool.poetry.dev-dependencies] | ||||||
| pytest = "*" | pytest = "*" | ||||||
| pre-commit = "*" | pre-commit = "*" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user