From fb6037299ba228f8d5f183821fd0140a60df7186 Mon Sep 17 00:00:00 2001 From: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com> Date: Sun, 18 Feb 2024 00:18:51 +0100 Subject: [PATCH 1/2] list currently firing alarms in !listreminders --- matrix_reminder_bot/bot_commands.py | 66 +++++++++++++++++++---------- matrix_reminder_bot/reminder.py | 5 +-- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/matrix_reminder_bot/bot_commands.py b/matrix_reminder_bot/bot_commands.py index 07332a5..2f27808 100644 --- a/matrix_reminder_bot/bot_commands.py +++ b/matrix_reminder_bot/bot_commands.py @@ -1,6 +1,6 @@ import logging from datetime import datetime, timedelta, timezone -from typing import Optional, Tuple +from typing import List, Optional, Tuple import arrow import dateparser @@ -366,7 +366,7 @@ async def _silence(self): reminder_text = " ".join(self.args) if reminder_text: # Find the alarm job via its reminder text - alarm_job = ALARMS.get((self.room.room_id, reminder_text.upper())) + alarm_job = ALARMS.get((self.room.room_id, reminder_text.upper())).alarm_job if alarm_job: await self._remove_and_silence_alarm(alarm_job, reminder_text) @@ -389,14 +389,14 @@ async def _silence(self): else: # No reminder text provided. Check if there's a reminder currently firing # in the room instead then - for alarm_info, job in ALARMS.items(): + for alarm_info, reminder in ALARMS.items(): if alarm_info[0] == self.room.room_id: # Found one! reminder_text = alarm_info[ 1 ].capitalize() # normalize the text a bit - await self._remove_and_silence_alarm(job, reminder_text) + await self._remove_and_silence_alarm(reminder.alarm_job, reminder_text) text = f"Alarm '{reminder_text}' silenced." # Prevent the `else` clause from being triggered @@ -422,6 +422,10 @@ async def _list_reminders(self): Sends a message listing them in the following format, using the alarm clock emoji ⏰ to indicate an alarm: + ⏰ Firing Alarms + + * [🔁 every ;] ; + 1️⃣ One-time Reminders * [⏰] : @@ -440,9 +444,17 @@ async def _list_reminders(self): """ output = "" - cron_reminder_lines = [] - one_shot_reminder_lines = [] - interval_reminder_lines = [] + cron_reminder_lines: List = [] + one_shot_reminder_lines: List = [] + interval_reminder_lines: List = [] + firing_alarms_lines: List = [] + + for alarm in ALARMS.values(): + line = "- " + if isinstance(alarm.job.trigger, IntervalTrigger): + line += f"🔁 every {readabledelta(alarm.recurse_timedelta)}; " + line += f'"*{alarm.reminder_text}*"' + firing_alarms_lines.append(line) # Sort the reminder types for reminder in REMINDERS.values(): @@ -461,13 +473,8 @@ async def _list_reminders(self): next_execution = reminder.job.next_run_time next_execution = arrow.get(next_execution) - # Cron-based reminders - if isinstance(reminder.job.trigger, CronTrigger): - # A human-readable cron tab, in addition to the actual tab - line += f"{prettify_cron(reminder.cron_tab)} (`{reminder.cron_tab}`); next run {next_execution.humanize()}" - # One-time reminders - elif isinstance(reminder.job.trigger, DateTrigger): + if isinstance(reminder.job.trigger, DateTrigger): # Just print when the reminder will go off line += f"{next_execution.humanize()}" @@ -476,22 +483,28 @@ async def _list_reminders(self): # Print the interval, and when it will next go off line += f"every {readabledelta(reminder.recurse_timedelta)}; next run {next_execution.humanize()}" + # Cron-based reminders + elif isinstance(reminder.job.trigger, CronTrigger): + # A human-readable cron tab, in addition to the actual tab + line += f"{prettify_cron(reminder.cron_tab)} (`{reminder.cron_tab}`); next run {next_execution.humanize()}" + # Add the reminder's text line += f'; *"{reminder.reminder_text}"*' # Output the status of each reminder. We divide up the reminders by type in order # to show them in separate sections, and display them differently - if isinstance(reminder.job.trigger, CronTrigger): - cron_reminder_lines.append(line) - elif isinstance(reminder.job.trigger, DateTrigger): + if isinstance(reminder.job.trigger, DateTrigger): one_shot_reminder_lines.append(line) elif isinstance(reminder.job.trigger, IntervalTrigger): interval_reminder_lines.append(line) + elif isinstance(reminder.job.trigger, CronTrigger): + cron_reminder_lines.append(line) if ( - not one_shot_reminder_lines - and not cron_reminder_lines + not firing_alarms_lines + and not one_shot_reminder_lines and not interval_reminder_lines + and not cron_reminder_lines ): await send_text_to_room( self.client, @@ -500,18 +513,22 @@ async def _list_reminders(self): ) return + if firing_alarms_lines: + output += "\n\n" + "**⏰ Firing Alarms**" + "\n\n" + output += "\n".join(firing_alarms_lines) + if one_shot_reminder_lines: output += "\n\n" + "**1️⃣ One-time Reminders**" + "\n\n" output += "\n".join(one_shot_reminder_lines) - if cron_reminder_lines: - output += "\n\n" + "**📅 Cron Reminders**" + "\n\n" - output += "\n".join(cron_reminder_lines) - if interval_reminder_lines: output += "\n\n" + "**🔁 Repeating Reminders**" + "\n\n" output += "\n".join(interval_reminder_lines) + if cron_reminder_lines: + output += "\n\n" + "**📅 Cron Reminders**" + "\n\n" + output += "\n".join(cron_reminder_lines) + await send_text_to_room(self.client, self.room.room_id, output) @command_syntax("") @@ -531,7 +548,10 @@ async def _delete_reminder(self): # Cancel the reminder and associated alarms reminder.cancel() - text = "Reminder cancelled." + text = "Reminder" + if reminder.alarm: + text = "Alarm" + text += f' "*{reminder_text}*" cancelled.' else: text = f"Unknown reminder '{reminder_text}'." diff --git a/matrix_reminder_bot/reminder.py b/matrix_reminder_bot/reminder.py index b77b3c0..3658db5 100644 --- a/matrix_reminder_bot/reminder.py +++ b/matrix_reminder_bot/reminder.py @@ -3,7 +3,6 @@ from typing import Dict, Optional, Tuple import pytz -from apscheduler.job import Job from apscheduler.schedulers.asyncio import AsyncIOScheduler from apscheduler.triggers.cron import CronTrigger from apscheduler.triggers.date import DateTrigger @@ -126,7 +125,7 @@ async def _fire(self): seconds=int(timedelta_seconds(ALARM_TIMEDELTA)), ), ) - ALARMS[(self.room_id, self.reminder_text.upper())] = self.alarm_job + ALARMS[(self.room_id, self.reminder_text.upper())] = self # Send the message to the room await send_text_to_room( @@ -203,4 +202,4 @@ def has_target(self) -> bool: # reminder_text should be accessed and stored as uppercase in order to # allow for case-insensitive matching when carrying out user actions REMINDERS: Dict[Tuple[str, str], Reminder] = {} -ALARMS: Dict[Tuple[str, str], Job] = {} +ALARMS: Dict[Tuple[str, str], Reminder] = {} From 8c61201a07f7256e3e066166d158360af843f43f Mon Sep 17 00:00:00 2001 From: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com> Date: Sun, 18 Feb 2024 00:52:15 +0100 Subject: [PATCH 2/2] lint --- matrix_reminder_bot/bot_commands.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/matrix_reminder_bot/bot_commands.py b/matrix_reminder_bot/bot_commands.py index 2f27808..33b6d1e 100644 --- a/matrix_reminder_bot/bot_commands.py +++ b/matrix_reminder_bot/bot_commands.py @@ -396,7 +396,9 @@ async def _silence(self): 1 ].capitalize() # normalize the text a bit - await self._remove_and_silence_alarm(reminder.alarm_job, reminder_text) + await self._remove_and_silence_alarm( + reminder.alarm_job, reminder_text + ) text = f"Alarm '{reminder_text}' silenced." # Prevent the `else` clause from being triggered