-
Notifications
You must be signed in to change notification settings - Fork 12
Implement automatic AssignedCommitteeAction reminders
#496
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 8 commits
dd6753c
546327d
b5debac
9b715f3
cb26e33
e5011ea
368eeb6
5e4cf49
f4466b9
1cb04e1
dd43aa1
1e6ea40
761f935
c5828dc
b6e743c
37c3fa7
1d91dee
9d37364
5aaebb0
0a7a349
db59186
22cb57c
f0f0112
aca9e1e
9dd6abd
8e2a778
9e63648
87e49dd
19bb09f
f985d13
1e4d3a4
1a6ff75
59b99fa
20355dc
b02dbbb
e2c3c85
2aa79c6
c1fb645
70dab40
a0a6e7e
27f7e25
3184b7b
596cf1c
507c606
a301780
d2460c9
943396b
5d59687
418935f
c06749a
4f1e2cb
0076173
e2fd452
f0305f7
f924052
aee134e
b1290a4
90c0f09
8a1b803
2ffc3db
11fef08
1baa621
c210434
789ea43
4263312
0a81cb5
95c4043
241359b
587a50c
cffdd3a
cb3bb7c
91ffe50
8afa060
62943e1
6c70d8f
cbf86ff
c818360
d7a62fc
a6289be
2781cb7
c8a8b99
e03d5eb
d722b2e
c6cf1c6
a8fdf12
3474e1a
d6f283e
74df853
42ea847
96727b3
aae579e
131cbba
a39a407
b522ffc
0c050b1
b132470
8e90ddd
d3b4dee
782abd0
4fd15ed
58cbe32
9cfa1b2
22baf94
96a3da1
ebd3012
45aedb2
30a25c5
fbfe551
c35c0fe
442645c
968de9a
3f5eb53
fd38761
06dd1a7
446e1ee
bc78b44
0350cf6
fe4ebf0
478d4fe
83d8123
b012157
bf1fb37
c3e86f0
44256ba
59d6eb5
4e9c8c4
b2df3a9
921a22b
9ecb004
c952460
988474d
00b506a
bb30670
6830854
7144700
c58177a
86cd574
c228ce3
a507a1e
e11b8b5
51f0f0b
895b5f6
a7be843
45e3498
cc1973b
f9705bd
24c1183
55719c4
388b00a
c8c1f3d
4a7a7f2
6cba58d
bdb0284
0589839
0e77494
2f36ba5
ecf8500
05079cf
8b4d792
d675ce3
a8a7239
374890c
ffd141d
29537aa
7111431
7bd3252
d72fc41
638648b
346b5d6
3b8777a
91db80e
779e388
80b10be
57926ca
be18725
aefa6ce
d85ea0a
0cb3f15
13715cf
f5d2657
b76659c
c0cb7f0
4f1c72e
aa34ca0
e23fda5
d7957c9
2e00660
f994c22
f0808a0
b907bbd
209937e
5602a99
1cf3e5a
55db57c
c1aeb42
c9d6a2a
e9aefb3
047df12
d889ea5
6e7abbf
67c8671
db08018
7e00cb2
68008ec
77a1580
e1bbb82
fc7f517
54ce074
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,12 +3,14 @@ | |||||||||||||||||||||||||||||||||
| import logging | ||||||||||||||||||||||||||||||||||
| import random | ||||||||||||||||||||||||||||||||||
| from enum import Enum | ||||||||||||||||||||||||||||||||||
| from typing import TYPE_CHECKING | ||||||||||||||||||||||||||||||||||
| from typing import TYPE_CHECKING, overload, override | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| import discord | ||||||||||||||||||||||||||||||||||
| from discord.ext import tasks | ||||||||||||||||||||||||||||||||||
| from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist, ValidationError | ||||||||||||||||||||||||||||||||||
| from django.db.models import Q | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| from config import settings | ||||||||||||||||||||||||||||||||||
| from db.core.models import AssignedCommitteeAction, DiscordMember | ||||||||||||||||||||||||||||||||||
| from exceptions import ( | ||||||||||||||||||||||||||||||||||
| CommitteeRoleDoesNotExistError, | ||||||||||||||||||||||||||||||||||
|
|
@@ -19,21 +21,24 @@ | |||||||||||||||||||||||||||||||||
| CommandChecks, | ||||||||||||||||||||||||||||||||||
| TeXBotBaseCog, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| from utils.error_capture_decorators import capture_guild_does_not_exist_error | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if TYPE_CHECKING: | ||||||||||||||||||||||||||||||||||
| from collections.abc import Sequence | ||||||||||||||||||||||||||||||||||
| from collections.abc import Iterable, Sequence | ||||||||||||||||||||||||||||||||||
| from collections.abc import Set as AbstractSet | ||||||||||||||||||||||||||||||||||
| from logging import Logger | ||||||||||||||||||||||||||||||||||
| from typing import Final | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| from utils import ( | ||||||||||||||||||||||||||||||||||
| TeXBot, | ||||||||||||||||||||||||||||||||||
| TeXBotApplicationContext, | ||||||||||||||||||||||||||||||||||
| TeXBotAutocompleteContext, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| __all__: "Sequence[str]" = ( | ||||||||||||||||||||||||||||||||||
| "CommitteeActionsTrackingBaseCog", | ||||||||||||||||||||||||||||||||||
| "CommitteeActionsTrackingContextCommandsCog", | ||||||||||||||||||||||||||||||||||
| "CommitteeActionsTrackingRemindersTaskCog", | ||||||||||||||||||||||||||||||||||
| "CommitteeActionsTrackingSlashCommandsCog", | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
@@ -110,6 +115,135 @@ async def _create_action( | |||||||||||||||||||||||||||||||||
| ) from create_action_error | ||||||||||||||||||||||||||||||||||
| return action | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @overload | ||||||||||||||||||||||||||||||||||
| async def get_user_actions( | ||||||||||||||||||||||||||||||||||
| self, action_user: discord.Member | discord.User, status: str | ||||||||||||||||||||||||||||||||||
| ) -> list[AssignedCommitteeAction]: ... | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @overload | ||||||||||||||||||||||||||||||||||
| async def get_user_actions( | ||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||
| action_user: "Iterable[discord.Member]", | ||||||||||||||||||||||||||||||||||
| status: list[str], | ||||||||||||||||||||||||||||||||||
| ) -> dict[discord.Member, list[AssignedCommitteeAction]]: ... | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| async def get_user_actions( | ||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||
| action_user: "discord.Member | discord.User | Iterable[discord.Member]", | ||||||||||||||||||||||||||||||||||
| status: str | list[str], | ||||||||||||||||||||||||||||||||||
| ) -> list[AssignedCommitteeAction] | dict[discord.Member, list[AssignedCommitteeAction]]: | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| Get the actions for a given user. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Takes in the user and returns a list of their actions. | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| if isinstance(action_user, (discord.User, discord.Member)): | ||||||||||||||||||||||||||||||||||
| user_actions: list[AssignedCommitteeAction] | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if not status: | ||||||||||||||||||||||||||||||||||
| user_actions = [ | ||||||||||||||||||||||||||||||||||
| action | ||||||||||||||||||||||||||||||||||
| async for action in await AssignedCommitteeAction.objects.afilter( | ||||||||||||||||||||||||||||||||||
| ( | ||||||||||||||||||||||||||||||||||
| Q(status=Status.IN_PROGRESS.value) | ||||||||||||||||||||||||||||||||||
| | Q(status=Status.BLOCKED.value) | ||||||||||||||||||||||||||||||||||
| | Q(status=Status.NOT_STARTED.value) | ||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||
| discord_id=int(action_user.id), | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||
| user_actions = [ | ||||||||||||||||||||||||||||||||||
| action | ||||||||||||||||||||||||||||||||||
| async for action in await AssignedCommitteeAction.objects.afilter( | ||||||||||||||||||||||||||||||||||
| status=status, | ||||||||||||||||||||||||||||||||||
| discord_id=int(action_user.id), | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| return user_actions | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| actions: list[AssignedCommitteeAction] = [ | ||||||||||||||||||||||||||||||||||
| action async for action in AssignedCommitteeAction.objects.select_related().all() | ||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| committee_actions: dict[discord.Member, list[AssignedCommitteeAction]] = { | ||||||||||||||||||||||||||||||||||
| committee: [ | ||||||||||||||||||||||||||||||||||
| action | ||||||||||||||||||||||||||||||||||
| for action in actions | ||||||||||||||||||||||||||||||||||
| if str(action.discord_member) == DiscordMember.hash_discord_id(committee.id) # type: ignore[has-type] | ||||||||||||||||||||||||||||||||||
MattyTheHacker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
| and action.status in status | ||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||
| for committee in action_user | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
MattyTheHacker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||
| committee: actions for committee, actions in committee_actions.items() if actions | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| class CommitteeActionsTrackingRemindersTaskCog(CommitteeActionsTrackingBaseCog): | ||||||||||||||||||||||||||||||||||
| """Cog class that defines the committee-actions tracking reminders task functionality.""" | ||||||||||||||||||||||||||||||||||
MattyTheHacker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @override | ||||||||||||||||||||||||||||||||||
| def __init__(self, bot: "TeXBot") -> None: | ||||||||||||||||||||||||||||||||||
| """Start all task managers when this cog is initialised.""" | ||||||||||||||||||||||||||||||||||
| if settings["COMMITTEE_ACTIONS_REMINDERS"]: | ||||||||||||||||||||||||||||||||||
| _ = self.committee_actions_reminders_task.start() | ||||||||||||||||||||||||||||||||||
MattyTheHacker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| super().__init__(bot) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @override | ||||||||||||||||||||||||||||||||||
| def cog_unload(self) -> None: | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| Unload-hook that ends all running tasks whenever the tasks cog is unloaded. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| This may be run dynamically or when the bot closes. | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| self.committee_actions_reminders_task.cancel() | ||||||||||||||||||||||||||||||||||
MattyTheHacker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @tasks.loop(**settings["COMMITTEE_ACTIONS_REMINDERS_INTERVAL"]) | ||||||||||||||||||||||||||||||||||
| @capture_guild_does_not_exist_error | ||||||||||||||||||||||||||||||||||
| async def committee_actions_reminders_task(self) -> None: | ||||||||||||||||||||||||||||||||||
MattyTheHacker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| Definition of the background task that sends reminders of committee actions. | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| The task will run every interval specified in the settings and will send reminders | ||||||||||||||||||||||||||||||||||
| to all committee members who have actions that are either in progress or not started. | ||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||
| committee_general_channel: discord.TextChannel | None = discord.utils.get( | ||||||||||||||||||||||||||||||||||
| self.bot.main_guild.text_channels, | ||||||||||||||||||||||||||||||||||
| name="committee-general", # TODO: Make this user-configurable # noqa: FIX002 | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| if not committee_general_channel: | ||||||||||||||||||||||||||||||||||
| logger.warning( | ||||||||||||||||||||||||||||||||||
| "Committee-general channel could not be found! " | ||||||||||||||||||||||||||||||||||
MattyTheHacker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
| "Actions reminders task will not run until next restart." | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| self.committee_actions_reminders_task.cancel() | ||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| committee_role: discord.Role = await self.bot.committee_role | ||||||||||||||||||||||||||||||||||
MattyTheHacker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
| committee_members: list[discord.Member] = committee_role.members | ||||||||||||||||||||||||||||||||||
MattyTheHacker marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||
| all_actions: dict[ | ||||||||||||||||||||||||||||||||||
| discord.Member, list[AssignedCommitteeAction] | ||||||||||||||||||||||||||||||||||
| ] = await self.get_user_actions( | ||||||||||||||||||||||||||||||||||
| committee_members, | ||||||||||||||||||||||||||||||||||
| [Status.NOT_STARTED.value, Status.IN_PROGRESS.value, Status.BLOCKED.value], | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| all_actions_message: str = "\n".join( | ||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||
| f"\n{committee.mention}, Actions:" | ||||||||||||||||||||||||||||||||||
| f"\n{', \n'.join(str(action.description) + f' ({AssignedCommitteeAction.Status(action.status).label})' for action in actions)}" # noqa: E501 | ||||||||||||||||||||||||||||||||||
| for committee, actions in all_actions.items() | ||||||||||||||||||||||||||||||||||
|
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() | |
| 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() |
MattyTheHacker marked this conversation as resolved.
Show resolved
Hide resolved
MattyTheHacker marked this conversation as resolved.
Show resolved
Hide resolved
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing documentation for 3 new config settings in |
Uh oh!
There was an error while loading. Please reload this page.