Add remove command for reminders
This commit is contained in:
@ -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
|
||||||
|
Reference in New Issue
Block a user