Skip to content

Conversation

@MattyTheHacker
Copy link
Member

No description provided.

@MattyTheHacker MattyTheHacker linked an issue May 18, 2025 that may be closed by this pull request
@MattyTheHacker MattyTheHacker self-assigned this May 18, 2025
@MattyTheHacker MattyTheHacker added the enhancement New feature or request label May 18, 2025
@MattyTheHacker MattyTheHacker force-pushed the 453-action-reminders branch from 20e6524 to 546327d Compare May 18, 2025 22:53
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_actions helper to centralize action-fetching logic and refactors existing list commands to use it.
  • Defines a new CommitteeActionsTrackingRemindersTaskCog to 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"])

@MattyTheHacker MattyTheHacker added sync Request bots to automatically keep this PR up to date with it's base branch and removed conflict A bot has identified that this PR has a conflict, preventing automatic syncing to the base branch labels Nov 25, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

cls, value: "LiteralString", emoji: "LiteralString | None" = None
) -> "AssignedCommitteeAction.Status":
if not emoji: # NOTE: Will also check for empty strings
raise ValueError
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message for the ValueError should be descriptive to help with debugging. Currently, raising ValueError with no message makes it difficult to understand what went wrong.

Suggested change
raise ValueError
raise ValueError("The 'emoji' argument must be provided and non-empty when creating a Status.")

Copilot uses AI. Check for mistakes.
def values(self) -> "Sequence[str]":
return [status.value for status in self.__iter__()]

def emojis(self) -> "Sequence[str]":
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The return type annotation should be list[str] instead of Sequence[str] since the method explicitly returns a list. This provides more accurate type information to callers.

Suggested change
def emojis(self) -> "Sequence[str]":
def emojis(self) -> "list[str]":

Copilot uses AI. Check for mistakes.
] = 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)
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] For clarity and explicitness, consider using TODO_FILTER.values() instead of TODO_FILTER directly. While the current code should work because Status enums inherit from str, using .values() makes it clearer that you're filtering by the status value strings.

Suggested change
else Q(raw_status__in=AssignedCommitteeAction.Status.TODO_FILTER)
else Q(raw_status__in=AssignedCommitteeAction.Status.TODO_FILTER.values())

Copilot uses AI. Check for mistakes.
Comment on lines +281 to +288
f"\n{committee}, Actions:"
f"\n{
', \n'.join(
action.status.emoji + f' {action.description} ({action.status.label})'
for action in actions
)
}"
for committee, actions in all_actions.items()
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The variable name committee is ambiguous. It's actually a discord.Member or discord.User object representing a committee member. Consider renaming it to committee_member or member for clarity.

Suggested change
f"\n{committee}, Actions:"
f"\n{
', \n'.join(
action.status.emoji + f' {action.description} ({action.status.label})'
for action in actions
)
}"
for committee, actions in all_actions.items()
f"\n{committee_member}, Actions:"
f"\n{
', \n'.join(
action.status.emoji + f' {action.description} ({action.status.label})'
for action in actions
)
}"
for committee_member, actions in all_actions.items()

Copilot uses AI. Check for mistakes.
return obj

@classproperty
def TODO_FILTER(cls) -> "AssignedCommitteeAction._StatusCollection": # noqa: D102, N802
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The TODO_FILTER class property lacks documentation. Consider adding a docstring to explain its purpose and what statuses it includes, e.g.:

@classproperty
def TODO_FILTER(cls) -> "AssignedCommitteeAction._StatusCollection":
    """Return a collection of statuses representing incomplete actions (In Progress, Blocked, Not Started)."""
    return AssignedCommitteeAction._StatusCollection(
        [cls.IN_PROGRESS, cls.BLOCKED, cls.NOT_STARTED]
    )
Suggested change
def TODO_FILTER(cls) -> "AssignedCommitteeAction._StatusCollection": # noqa: D102, N802
def TODO_FILTER(cls) -> "AssignedCommitteeAction._StatusCollection": # noqa: D102, N802
"""Return a collection of statuses representing incomplete actions (In Progress, Blocked, Not Started)."""

Copilot uses AI. Check for mistakes.
iterable = list(iterable)
if not iterable:
NO_STATUSES_GIVEN_MESSAGE: Final[str] = (
f"Cannot instantiate {type(Self).__name__} with no 'statuses'."
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message references Self which is a type hint, not a runtime type. This should be cls instead. The correct message should be:

f"Cannot instantiate {cls.__name__} with no 'statuses'."
Suggested change
f"Cannot instantiate {type(Self).__name__} with no 'statuses'."
f"Cannot instantiate {cls.__name__} with no 'statuses'."

Copilot uses AI. Check for mistakes.

if raw_send_committee_actions_reminders not in TRUE_VALUES | FALSE_VALUES:
INVALID_SEND_COMMITTEE_ACTIONS_REMINDERS_MESSAGE: Final[str] = (
"SEND_COMMITTEE_ACTIONS_REMINDERS must be a boolean value."
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two extra spaces before "must" in the error message. It should be:

"SEND_COMMITTEE_ACTIONS_REMINDERS must be a boolean value."
Suggested change
"SEND_COMMITTEE_ACTIONS_REMINDERS must be a boolean value."
"SEND_COMMITTEE_ACTIONS_REMINDERS must be a boolean value."

Copilot uses AI. Check for mistakes.
action.status.emoji
+ f' {action.description} ({action.status.label})'
for action in actions
if action.discord_member.discord_id == discord_id
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This filter condition is redundant. The actions collection from filtered_actions.items() already contains only actions for the specific discord_id due to the grouping in _get_actions_grouped_by_member_id. This unnecessary check should be removed for clarity and performance.

Suggested change
if action.discord_member.discord_id == discord_id

Copilot uses AI. Check for mistakes.
return self.Status(self.raw_status)

@status.setter
def status(self, value: Status, /) -> None:
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The status property setter lacks a docstring. Consider adding documentation to explain that it sets the raw_status field from a Status enum value, e.g.:

@status.setter
def status(self, value: Status, /) -> None:
    """Set the action's status from a Status enum value."""
    self.raw_status = value.value
Suggested change
def status(self, value: Status, /) -> None:
def status(self, value: Status, /) -> None:
"""Set the action's status from a Status enum value."""

Copilot uses AI. Check for mistakes.
return obj

@classproperty
def TODO_FILTER(cls) -> "AssignedCommitteeAction._StatusCollection": # noqa: D102, N802
Copy link

Copilot AI Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normal methods should have 'self', rather than 'cls', as their first parameter.

Copilot uses AI. Check for mistakes.
@automatic-pr-updater automatic-pr-updater bot added conflict A bot has identified that this PR has a conflict, preventing automatic syncing to the base branch and removed sync Request bots to automatically keep this PR up to date with it's base branch labels Dec 1, 2025
@automatic-pr-updater
Copy link
Contributor

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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conflict A bot has identified that this PR has a conflict, preventing automatic syncing to the base branch enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement persistent actions tracker Implement reminders for actions

5 participants