Add remove command for reminders

This commit is contained in:
2025-04-08 17:57:50 +02:00
parent 3e5e23591d
commit d55f1993e8

View File

@ -17,6 +17,7 @@ import sentry_sdk
from apscheduler import events from apscheduler import events
from apscheduler.events import EVENT_JOB_ERROR, EVENT_JOB_MISSED, JobExecutionEvent from apscheduler.events import EVENT_JOB_ERROR, EVENT_JOB_MISSED, JobExecutionEvent
from apscheduler.job import Job from apscheduler.job import Job
from apscheduler.jobstores.base import JobLookupError
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger from apscheduler.triggers.cron import CronTrigger
@ -27,8 +28,9 @@ from discord_webhook import DiscordWebhook
from dotenv import load_dotenv from dotenv import load_dotenv
from loguru import logger from loguru import logger
from interactions.api.models.misc import Snowflake
if TYPE_CHECKING: if TYPE_CHECKING:
from apscheduler.job import Job
from discord.guild import GuildChannel from discord.guild import GuildChannel
from discord.interactions import InteractionChannel from discord.interactions import InteractionChannel
from discord.types.channel import _BaseChannel from discord.types.channel import _BaseChannel
@ -46,6 +48,42 @@ sentry_sdk.init(
) )
def generate_markdown_state(state: dict[str, Any]) -> str:
"""Format the __getstate__ dictionary for Discord markdown.
Args:
state (dict): The __getstate__ dictionary.
Returns:
str: The formatted string.
"""
if not state:
return "```json\nNo state found.\n```"
# discord.app_commands.errors.CommandInvokeError: Command 'remove' raised an exception: TypeError: Object of type IntervalTrigger is not JSON serializable
# Convert the IntervalTrigger to a string representation
for key, value in state.items():
if isinstance(value, IntervalTrigger):
state[key] = "IntervalTrigger"
elif isinstance(value, DateTrigger):
state[key] = "DateTrigger"
elif isinstance(value, Job):
state[key] = "Job"
elif isinstance(value, Snowflake):
state[key] = str(value)
try:
msg: str = json.dumps(state, indent=4, default=str)
except TypeError as e:
e.add_note("This is likely due to a non-serializable object in the state. Please check the state for any non-serializable objects.")
e.add_note(f"{state=}")
logger.error(f"Failed to serialize state: {e}")
return "```json\nFailed to serialize state.\n```"
return "```json\n" + msg + "\n```"
def parse_time(date_to_parse: str | None, timezone: str | None = os.getenv("TIMEZONE")) -> datetime.datetime | None: def parse_time(date_to_parse: str | None, timezone: str | None = os.getenv("TIMEZONE")) -> datetime.datetime | None:
"""Parse a date string into a datetime object. """Parse a date string into a datetime object.
@ -1023,6 +1061,36 @@ class RemindGroup(discord.app_commands.Group):
else: else:
await interaction.followup.send(content="No new reminders were added.") await interaction.followup.send(content="No new reminders were added.")
# /remind remove
@discord.app_commands.command(name="remove", description="Remove a reminder")
async def remove(self, interaction: discord.Interaction, job_id: str) -> None:
"""Remove a scheduled reminder.
Args:
interaction (discord.Interaction): The interaction object for the command.
job_id (str): The identifier of the job to remove.
"""
await interaction.response.defer()
logger.debug(f"Removing reminder with ID {job_id} for {interaction.user} ({interaction.user.id}) in {interaction.channel}")
logger.debug(f"Arguments: {locals()}")
try:
job: Job | None = scheduler.get_job(job_id)
if not job:
await interaction.followup.send(content=f"Reminder with ID {job_id} not found.", ephemeral=True)
return
scheduler.remove_job(job_id)
logger.info(f"Removed job {job_id}. {job.__getstate__()}")
await interaction.followup.send(
content=f"Reminder with ID {job_id} removed successfully.\n{generate_markdown_state(job.__getstate__())}",
)
except JobLookupError as e:
logger.exception(f"Failed to remove job {job_id}")
await interaction.followup.send(content=f"Failed to remove reminder with ID {job_id}. {e}", ephemeral=True)
logger.info(f"Job {job_id} removed from the scheduler.")
intents: discord.Intents = discord.Intents.default() intents: discord.Intents = discord.Intents.default()
intents.guild_scheduled_events = True intents.guild_scheduled_events = True