Add message modification support for interval and cron jobs in modals
This commit is contained in:
@ -149,6 +149,17 @@ def format_job_for_ui(job: Job) -> str:
|
|||||||
|
|
||||||
msg += f"\nData:\n{generate_state(job.__getstate__(), job)}\n"
|
msg += f"\nData:\n{generate_state(job.__getstate__(), job)}\n"
|
||||||
|
|
||||||
|
if isinstance(job.trigger, apscheduler.triggers.interval.IntervalTrigger):
|
||||||
|
msg += (
|
||||||
|
"\nNote: This is an interval job. Due to UI limitations, you can only modify the message, not the trigger settings.\n"
|
||||||
|
"To change the trigger settings, please delete and recreate the job.\n"
|
||||||
|
)
|
||||||
|
elif isinstance(job.trigger, apscheduler.triggers.cron.CronTrigger):
|
||||||
|
msg += (
|
||||||
|
"\nNote: This is a cron job. Due to UI limitations, you can only modify the message, not the trigger settings.\n"
|
||||||
|
"To change the trigger settings, please delete and recreate the job.\n"
|
||||||
|
)
|
||||||
|
|
||||||
logger.debug(f"Formatted job for UI: {msg}")
|
logger.debug(f"Formatted job for UI: {msg}")
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@ -327,6 +338,8 @@ class ReminderListView(discord.ui.View):
|
|||||||
ephemeral=True,
|
ephemeral=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await self.refresh(interaction)
|
||||||
|
|
||||||
async def handle_pause_unpause(self, interaction: discord.Interaction, job_id: str) -> None:
|
async def handle_pause_unpause(self, interaction: discord.Interaction, job_id: str) -> None:
|
||||||
"""Handle pausing or unpausing a reminder job.
|
"""Handle pausing or unpausing a reminder job.
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ class DateReminderModifyModal(discord.ui.Modal, title="Modify reminder"):
|
|||||||
except discord.HTTPException:
|
except discord.HTTPException:
|
||||||
logger.warning("Failed to send error message via followup")
|
logger.warning("Failed to send error message via followup")
|
||||||
|
|
||||||
logger.exception(f"Error in ReminderModifyModal: {error}")
|
logger.exception(f"Error in {self.__class__.__name__}: {error}")
|
||||||
traceback.print_exception(type(error), error, error.__traceback__)
|
traceback.print_exception(type(error), error, error.__traceback__)
|
||||||
|
|
||||||
|
|
||||||
@ -196,6 +196,102 @@ class CronReminderModifyModal(discord.ui.Modal, title="Modify reminder"):
|
|||||||
self.job = job
|
self.job = job
|
||||||
self.job_id = job.id
|
self.job_id = job.id
|
||||||
|
|
||||||
|
# message
|
||||||
|
self.message_input = discord.ui.TextInput(
|
||||||
|
label="Reminder message",
|
||||||
|
default=job.kwargs.get("message", ""),
|
||||||
|
placeholder="What do you want to be reminded of?",
|
||||||
|
max_length=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _update_message(self, old_message: str, new_message: str) -> bool:
|
||||||
|
"""Update the message of a job.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
old_message (str): The old message.
|
||||||
|
new_message (str): The new message.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: Whether the message was changed.
|
||||||
|
"""
|
||||||
|
if new_message == old_message:
|
||||||
|
return False
|
||||||
|
|
||||||
|
job: Job | None = scheduler.get_job(self.job_id)
|
||||||
|
if not job:
|
||||||
|
return False
|
||||||
|
|
||||||
|
old_kwargs = job.kwargs.copy()
|
||||||
|
scheduler.modify_job(
|
||||||
|
self.job_id,
|
||||||
|
kwargs={
|
||||||
|
**old_kwargs,
|
||||||
|
"message": new_message,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.debug(f"Modified job {self.job_id} with new message: {new_message}")
|
||||||
|
logger.debug(f"Old kwargs: {old_kwargs}, New kwargs: {job.kwargs}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def on_submit(self, interaction: discord.Interaction) -> None:
|
||||||
|
"""Called when the modal is submitted for a cron-based reminder.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interaction (discord.Interaction): The Discord interaction where this modal was triggered from.
|
||||||
|
"""
|
||||||
|
old_message: str = self.job.kwargs.get("message", "")
|
||||||
|
|
||||||
|
new_message: str = self.message_input.value
|
||||||
|
|
||||||
|
# Get the job to modify
|
||||||
|
job_to_modify: Job | None = scheduler.get_job(self.job_id)
|
||||||
|
if not job_to_modify:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"Failed to get job.\n{new_message=}",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Defer early for long operations
|
||||||
|
await interaction.response.defer(ephemeral=True)
|
||||||
|
|
||||||
|
# Update the message if changed
|
||||||
|
msg: str = f"Modified job `{escape_markdown(self.job_id)}`:\n"
|
||||||
|
changes_made = False
|
||||||
|
|
||||||
|
# Update message if changed
|
||||||
|
message_changed: bool = await self._update_message(old_message, new_message)
|
||||||
|
if message_changed:
|
||||||
|
msg += f"Old message: `{escape_markdown(old_message)}`\n"
|
||||||
|
msg += f"New message: `{escape_markdown(new_message)}`.\n"
|
||||||
|
changes_made = True
|
||||||
|
|
||||||
|
# Send confirmation message
|
||||||
|
if changes_made:
|
||||||
|
await interaction.followup.send(content=msg)
|
||||||
|
else:
|
||||||
|
await interaction.followup.send(content=f"No changes made to job `{escape_markdown(self.job_id)}`.", ephemeral=True)
|
||||||
|
|
||||||
|
async def on_error(self, interaction: discord.Interaction, error: Exception) -> None:
|
||||||
|
"""A callback that is called when on_submit fails with an error.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interaction (discord.Interaction): The Discord interaction where this modal was triggered from.
|
||||||
|
error (Exception): The raised exception.
|
||||||
|
"""
|
||||||
|
# Check if the interaction has already been responded to
|
||||||
|
if not interaction.response.is_done():
|
||||||
|
await interaction.response.send_message("Oops! Something went wrong.", ephemeral=True)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
await interaction.followup.send("Oops! Something went wrong.", ephemeral=True)
|
||||||
|
except discord.HTTPException:
|
||||||
|
logger.warning("Failed to send error message via followup")
|
||||||
|
|
||||||
|
logger.exception(f"Error in {self.__class__.__name__}: {error}")
|
||||||
|
traceback.print_exception(type(error), error, error.__traceback__)
|
||||||
|
|
||||||
|
|
||||||
class IntervalReminderModifyModal(discord.ui.Modal, title="Modify reminder"):
|
class IntervalReminderModifyModal(discord.ui.Modal, title="Modify reminder"):
|
||||||
"""A modal for modifying an interval-based reminder."""
|
"""A modal for modifying an interval-based reminder."""
|
||||||
@ -209,3 +305,101 @@ class IntervalReminderModifyModal(discord.ui.Modal, title="Modify reminder"):
|
|||||||
super().__init__(title="Modify Reminder")
|
super().__init__(title="Modify Reminder")
|
||||||
self.job = job
|
self.job = job
|
||||||
self.job_id = job.id
|
self.job_id = job.id
|
||||||
|
|
||||||
|
# message
|
||||||
|
self.message_input = discord.ui.TextInput(
|
||||||
|
label="Reminder message",
|
||||||
|
default=job.kwargs.get("message", ""),
|
||||||
|
placeholder="What do you want to be reminded of?",
|
||||||
|
max_length=200,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.add_item(self.message_input)
|
||||||
|
|
||||||
|
async def _update_message(self, old_message: str, new_message: str) -> bool:
|
||||||
|
"""Update the message of a job.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
old_message (str): The old message.
|
||||||
|
new_message (str): The new message.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: Whether the message was changed.
|
||||||
|
"""
|
||||||
|
if new_message == old_message:
|
||||||
|
return False
|
||||||
|
|
||||||
|
job: Job | None = scheduler.get_job(self.job_id)
|
||||||
|
if not job:
|
||||||
|
return False
|
||||||
|
|
||||||
|
old_kwargs = job.kwargs.copy()
|
||||||
|
scheduler.modify_job(
|
||||||
|
self.job_id,
|
||||||
|
kwargs={
|
||||||
|
**old_kwargs,
|
||||||
|
"message": new_message,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.debug(f"Modified job {self.job_id} with new message: {new_message}")
|
||||||
|
logger.debug(f"Old kwargs: {old_kwargs}, New kwargs: {job.kwargs}")
|
||||||
|
return True
|
||||||
|
|
||||||
|
async def on_submit(self, interaction: discord.Interaction) -> None:
|
||||||
|
"""Called when the modal is submitted for an interval-based reminder.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interaction (discord.Interaction): The Discord interaction where this modal was triggered from.
|
||||||
|
"""
|
||||||
|
old_message: str = self.job.kwargs.get("message", "")
|
||||||
|
|
||||||
|
new_message: str = self.message_input.value
|
||||||
|
|
||||||
|
# Get the job to modify
|
||||||
|
job_to_modify: Job | None = scheduler.get_job(self.job_id)
|
||||||
|
if not job_to_modify:
|
||||||
|
await interaction.response.send_message(
|
||||||
|
f"Failed to get job.\n{new_message=}",
|
||||||
|
ephemeral=True,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Defer early for long operations
|
||||||
|
await interaction.response.defer(ephemeral=True)
|
||||||
|
|
||||||
|
# Update the message if changed
|
||||||
|
msg: str = f"Modified job `{escape_markdown(self.job_id)}`:\n"
|
||||||
|
changes_made = False
|
||||||
|
|
||||||
|
# Update message if changed
|
||||||
|
message_changed: bool = await self._update_message(old_message, new_message)
|
||||||
|
if message_changed:
|
||||||
|
msg += f"Old message: `{escape_markdown(old_message)}`\n"
|
||||||
|
msg += f"New message: `{escape_markdown(new_message)}`.\n"
|
||||||
|
changes_made = True
|
||||||
|
|
||||||
|
# Send confirmation message
|
||||||
|
if changes_made:
|
||||||
|
await interaction.followup.send(content=msg)
|
||||||
|
else:
|
||||||
|
await interaction.followup.send(content=f"No changes made to job `{escape_markdown(self.job_id)}`.", ephemeral=True)
|
||||||
|
|
||||||
|
async def on_error(self, interaction: discord.Interaction, error: Exception) -> None:
|
||||||
|
"""A callback that is called when on_submit fails with an error.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interaction (discord.Interaction): The Discord interaction where this modal was triggered from.
|
||||||
|
error (Exception): The raised exception.
|
||||||
|
"""
|
||||||
|
# Check if the interaction has already been responded to
|
||||||
|
if not interaction.response.is_done():
|
||||||
|
await interaction.response.send_message("Oops! Something went wrong.", ephemeral=True)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
await interaction.followup.send("Oops! Something went wrong.", ephemeral=True)
|
||||||
|
except discord.HTTPException:
|
||||||
|
logger.warning("Failed to send error message via followup")
|
||||||
|
|
||||||
|
logger.exception(f"Error in {self.__class__.__name__}: {error}")
|
||||||
|
traceback.print_exception(type(error), error, error.__traceback__)
|
||||||
|
Reference in New Issue
Block a user