Implement automatic AssignedCommitteeAction reminders#496
Implement automatic AssignedCommitteeAction reminders#496MattyTheHacker wants to merge 217 commits into
AssignedCommitteeAction reminders#496Conversation
20e6524 to
546327d
Compare
There was a problem hiding this comment.
Pull Request Overview
Implements automatic reminders for assigned committee actions by introducing new configuration options and a background task.
- Adds environment settings for enabling reminders and configuring their interval.
- Introduces
get_user_actionshelper to centralize action-fetching logic and refactors existing list commands to use it. - Defines a new
CommitteeActionsTrackingRemindersTaskCogto run a periodic Discord reminder task.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| config.py | Added _setup_committee_actions_reminders and _setup_committee_actions_reminders_interval to parse new env vars. |
| cogs/committee_actions_tracking.py | Added get_user_actions overloads, refactored list commands, and created the reminders task cog. |
| cogs/init.py | Registered CommitteeActionsTrackingRemindersTaskCog. |
Comments suppressed due to low confidence (1)
cogs/committee_actions_tracking.py:205
- [nitpick] There are no tests covering the background reminders task. Adding unit tests for the enabled/disabled path and interval parsing would ensure this feature works reliably.
@tasks.loop(**settings["COMMITTEE_ACTIONS_REMINDERS_INTERVAL"])
|
This pull request has a merge conflict with the base branch! Please resolve the conflict manually, remove the conflict label and re-add the filter label (if applicable). |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 6 changed files in this pull request and generated 20 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
This pull request has a merge conflict with the base branch! Please resolve the conflict manually, remove the conflict label and re-add the filter label (if applicable). |
Signed-off-by: Matty Widdop <18513864+MattyTheHacker@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 6 changed files in this pull request and generated 7 comments.
Comments suppressed due to low confidence (3)
cogs/committee_actions_tracking.py:997
AssignedCommitteeAction.Status(value=raw_status)is not a valid Enum/TextChoices call (Enum values are passed positionally), and it’s redundant here becauseraw_statusis already the stored code. This will raise at runtime when a status filter is provided; filter withQ(raw_status=raw_status)(and validateraw_statusif needed).
filtered_actions: Mapping[
str, Collection[AssignedCommitteeAction]
] = await self._get_actions_grouped_by_member_id(
filter_query=Q(raw_status=AssignedCommitteeAction.Status(value=raw_status).value)
if raw_status is not None
else Q(raw_status__in=AssignedCommitteeAction.Status.TODO_FILTER)
)
cogs/committee_actions_tracking.py:310
- This task sends a single message containing all actions. If the formatted output exceeds Discord’s 2000-character limit,
send(...)will fail and no reminders will be delivered. Consider chunking the output (similar to/list-all) or sending one message per member / using embeds.
await committee_action_reminders_channel.send(
content=f"{actions_reminder_info_message}\n{all_actions_message}",
)
cogs/committee_actions_tracking.py:835
- When no
raw_statusfilter is provided, the query usesStatus.TODO_FILTER(in-progress, blocked, not-started), but the user-facing text says "in progress actions". Update the message to match the actual default filter (e.g., “to-do actions” or “in progress / blocked / not started”).
f"User: {action_member.mention if ping else action_member} has no {
'in progress actions'
if not raw_status
else 'actions matching given filter'
}."
| BLOCKED = "BLK", "no_entry", _("Blocked") | ||
| CANCELLED = "CND", "wastebasket", _("Cancelled") | ||
| COMPLETE = "CMP", "white_check_mark", _("Complete") | ||
| IN_PROGRESS = "INP", "yellow_circle", _("In Progress") | ||
| NOT_STARTED = "NST", "red_circle", _("Not Started") | ||
|
|
||
| emoji: str | ||
|
|
||
| @overload | ||
| def __new__(cls, value: "LiteralString") -> "AssignedCommitteeAction.Status": ... | ||
|
|
||
| @overload | ||
| def __new__( | ||
| cls, value: "LiteralString", emoji: "LiteralString" | ||
| ) -> "AssignedCommitteeAction.Status": ... | ||
|
|
||
| def __new__( # noqa: D102 | ||
| cls, value: "LiteralString", emoji: "LiteralString | None" = None | ||
| ) -> "AssignedCommitteeAction.Status": |
| ) | ||
| if value | ||
| } | ||
|
|
| Q(AssignedCommitteeAction.Status.TODO_FILTER), | ||
| discord_member__discord_id=interaction_user.id, |
| if isinstance(action_user, (discord.User, discord.Member)): | ||
| user_actions: Collection[AssignedCommitteeAction] = [ | ||
| action | ||
| async for action in AssignedCommitteeAction.objects.filter( | ||
| raw_status__in=(status_item.value for status_item in status), | ||
| discord_member__discord_id=int(action_user.id), | ||
| ) | ||
| ] | ||
|
|
||
| return {action_user: user_actions} if user_actions else {} | ||
|
|
||
| return { | ||
| user: actions | ||
| for user in action_user | ||
| if ( | ||
| actions := [ | ||
| action | ||
| async for action in AssignedCommitteeAction.objects.filter( | ||
| discord_member__discord_id=user.id, | ||
| raw_status__in=(status_item.value for status_item in status), | ||
| ) | ||
| ] | ||
| ) |
| await action_board_message.edit( | ||
| content=f"## Committee Actions Tracking Board\n{ | ||
| '\n'.join( | ||
| [ |
| actions_reminder_info_message: str = ( | ||
| f"Wakey wakey committee!\n" | ||
| "Here are your actions that are either in progress or not started yet.\n" | ||
| f"I'll remind you again <t:{next_reminder_unix}:R>" |
No description provided.