diff options
author | 2023-03-04 15:07:49 +0000 | |
---|---|---|
committer | 2023-03-04 15:07:49 +0000 | |
commit | e9aa8f1621f9fcff0ace8e6cbe37c98449641773 (patch) | |
tree | 7a9abbc31a4f81030f720ce06d8cb1dc1771b6f5 | |
parent | Bump inactivity removal threshold and display in message (diff) |
Split default nomination listing into groups
-rw-r--r-- | bot/exts/recruitment/talentpool/_api.py | 3 | ||||
-rw-r--r-- | bot/exts/recruitment/talentpool/_cog.py | 116 | ||||
-rw-r--r-- | bot/exts/recruitment/talentpool/_review.py | 19 |
3 files changed, 101 insertions, 37 deletions
diff --git a/bot/exts/recruitment/talentpool/_api.py b/bot/exts/recruitment/talentpool/_api.py index 7b6c67fc3..e12111de5 100644 --- a/bot/exts/recruitment/talentpool/_api.py +++ b/bot/exts/recruitment/talentpool/_api.py @@ -124,6 +124,9 @@ class NominationAPI: Returns a dictionary mapping user ID to message count. """ + if not user_ids: + return {} + result = await self.site_api.post( "bot/users/metricity_activity_data", json=user_ids, diff --git a/bot/exts/recruitment/talentpool/_cog.py b/bot/exts/recruitment/talentpool/_cog.py index 7a9db7886..b92afdbcc 100644 --- a/bot/exts/recruitment/talentpool/_cog.py +++ b/bot/exts/recruitment/talentpool/_cog.py @@ -15,7 +15,7 @@ from bot.bot import Bot from bot.constants import Bot as BotConfig, Channels, Emojis, Guild, MODERATION_ROLES, Roles, STAFF_ROLES from bot.converters import MemberOrUser, UnambiguousMemberOrUser from bot.exts.recruitment.talentpool._api import Nomination, NominationAPI -from bot.exts.recruitment.talentpool._review import RECENT_ACTIVITY_DAYS, Reviewer +from bot.exts.recruitment.talentpool._review import Reviewer from bot.log import get_logger from bot.pagination import LinePaginator from bot.utils import time @@ -152,6 +152,9 @@ class TalentPool(Cog, name="Talentpool"): if messages_per_user[nomination.user_id] > 0: continue + if nomination.reviewed: + continue + log.info("Removing %s from the talent pool due to inactivity", nomination.user_id) await nomination_discussion.send( @@ -176,56 +179,105 @@ class TalentPool(Cog, name="Talentpool"): ctx: Context, ) -> None: """ - Shows the users that are currently in the talent pool, ordered by next to be reviewed. + Shows the users that are currently in the talent pool. - Note that this order will change over time, so should not be relied upon. + The "Recent Nominations" sections shows users nominated in the past 7 days, + so will not be considered for autoreview. + + In the "Autoreview Priority" section a :zzz: emoji will be shown next to + users that have not been active recently enough to be considered for autoreview. + Note that the order in this section will change over time so should not be relied upon. """ - await self.list_nominated_users(ctx, order_by_priority=True) + await self.show_nominations_list(ctx, grouped_view=True) @list_group.command(name="oldest") async def list_oldest(self, ctx: Context) -> None: """Shows the users that are currently in the talent pool, ordered by oldest nomination.""" - await self.list_nominated_users(ctx, oldest_first=True) + await self.show_nominations_list(ctx, oldest_first=True) @list_group.command(name='newest') async def list_newest(self, ctx: Context) -> None: """Shows the users that are currently in the talent pool, ordered by newest nomination.""" - await self.list_nominated_users(ctx, oldest_first=False) + await self.show_nominations_list(ctx, oldest_first=False) - async def list_nominated_users( + async def show_nominations_list( self, ctx: Context, + *, oldest_first: bool = False, - order_by_priority: bool = False + grouped_view: bool = False, ) -> None: """ Lists the currently nominated users. - The optional kwarg `oldest_first` orders the list by oldest entry. + If `grouped_view` is passed, nominations will be displayed in the groups + being reviewed, recent nominations, and others by autoreview priority. + + Otherwise, nominations will be sorted by age + (ordered based on the value of `oldest_first`). """ now = datetime.now(tz=timezone.utc) + nominations = await self.api.get_nominations(active=True) + messages_per_user = await self.api.get_activity( + [nomination.user_id for nomination in nominations], + days=DAYS_UNTIL_INACTIVE + ) + + if grouped_view: + reviewed_nominations = [] + recent_nominations = [] + other_nominations = [] + for nomination in nominations: + if nomination.reviewed: + reviewed_nominations.append(nomination) + elif not self.reviewer.is_nomination_old_enough(nomination, now): + recent_nominations.append(nomination) + else: + other_nominations.append(nomination) + + other_nominations = await self.reviewer.sort_nominations_to_review(other_nominations, now) + + lines = [ + "**Being Reviewed:**", + *await self.list_nominations(ctx, reviewed_nominations, messages_per_user), + "**Recent Nominations:**", + *await self.list_nominations(ctx, recent_nominations, messages_per_user), + "**Other Nominations by Autoreview Priority:**", + *await self.list_nominations(ctx, other_nominations, messages_per_user, show_inactive=True) + ] + else: + if oldest_first: + nominations.reverse() + lines = await self.list_nominations(ctx, nominations, messages_per_user, show_reviewed=True) + + if not lines: + lines = ["There are no active nominations"] + embed = Embed( title="Talent Pool active nominations", color=Color.blue() ) - nominations = await self.api.get_nominations(active=True) + await LinePaginator.paginate(lines, ctx, embed, empty=False) - if not nominations: - embed.description = "There are no active nominations." - await ctx.send(embed=embed) - return + async def list_nominations( + self, + ctx: Context, + nominations: list[Nomination], + messages_per_user: dict[int, int], + show_reviewed: bool = False, + show_inactive: bool = False, + ) -> list[str]: + """ + Formats the given nominations into a list. - if order_by_priority: - nominations = await self.reviewer.sort_nominations_to_review(nominations, now) - elif oldest_first: - nominations.reverse() + Pass `show_reviewed` to indicate reviewed nominations, and `show_inactive` to + indicate if the user doesn't have recent enough activity to be autoreviewed. + """ + lines: list[str] = [] - messages_per_user = await self.api.get_activity( - [nomination.user_id for nomination in nominations], - days=RECENT_ACTIVITY_DAYS - ) + if not nominations: + return ["*None*"] - lines: list[str] = [] for nomination in nominations: line = f"• `{nomination.user_id}`" @@ -233,23 +285,19 @@ class TalentPool(Cog, name="Talentpool"): if member: line += f" ({member.name}#{member.discriminator})" else: - line += " (not in server)" + line += " (not on server)" line += f", added {time.format_relative(nomination.inserted_at)}" - is_ready_for_review = await self.reviewer.is_nomination_ready_for_review( - nomination, - messages_per_user[nomination.user_id], - now - ) - if nomination.reviewed: + if show_reviewed and nomination.reviewed: line += " *(reviewed)*" - elif is_ready_for_review: - line += " *(ready for review)*" - lines.append(line) + is_active = self.reviewer.is_user_active_enough(messages_per_user[nomination.user_id]) + if show_inactive and not is_active: + line += " :zzz:" - await LinePaginator.paginate(lines, ctx, embed, empty=False) + lines.append(line) + return lines @nomination_group.command( name="forcenominate", diff --git a/bot/exts/recruitment/talentpool/_review.py b/bot/exts/recruitment/talentpool/_review.py index 9436f2bad..9abf3affa 100644 --- a/bot/exts/recruitment/talentpool/_review.py +++ b/bot/exts/recruitment/talentpool/_review.py @@ -109,6 +109,17 @@ class Reviewer: return True + @staticmethod + def is_nomination_old_enough(nomination: Nomination, now: datetime) -> bool: + """Check if a nomination is old enough to autoreview.""" + time_since_nomination = now - nomination.inserted_at + return time_since_nomination > MIN_NOMINATION_TIME + + @staticmethod + def is_user_active_enough(user_message_count: int) -> bool: + """Check if a user's message count is enough for them to be autoreviewed.""" + return user_message_count > 0 + async def is_nomination_ready_for_review( self, nomination: Nomination, @@ -125,16 +136,15 @@ class Reviewer: - They are still a member of the server. """ guild = self.bot.get_guild(Guild.id) - time_since_nomination = now - nomination.inserted_at return ( # Must be an active nomination nomination.active and # ... that has not already been reviewed not nomination.reviewed and # ... and has been nominated for long enough - time_since_nomination > MIN_NOMINATION_TIME and + self.is_nomination_old_enough(nomination, now) and # ... and is for a user that has been active recently - user_message_count > 0 and + self.is_user_active_enough(user_message_count) and # ... and is currently a member of the server await get_or_fetch_member(guild, nomination.id) is not None ) @@ -146,6 +156,9 @@ class Reviewer: The priority of the review is determined based on how many nominations the user has (more nominations = higher priority), and the age of the nomination. """ + if not nominations: + return [] + oldest_date = min(nomination.inserted_at for nomination in nominations) max_entries = max(len(nomination.entries) for nomination in nominations) |