-
-
Notifications
You must be signed in to change notification settings - Fork 750
Manage nomination threads in bot #1928
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
Changes from all commits
edb18d5
292a500
c217c3e
6bd2a56
0a4ba0b
e62ff5b
96911a9
108bf32
8c89ef9
6af8737
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 |
|---|---|---|
|
|
@@ -10,12 +10,12 @@ | |
|
|
||
| import arrow | ||
| from dateutil.parser import isoparse | ||
| from discord import Embed, Emoji, Member, Message, NoMoreItems, PartialMessage, TextChannel | ||
| from discord import Embed, Emoji, Member, Message, NoMoreItems, NotFound, PartialMessage, TextChannel | ||
| from discord.ext.commands import Context | ||
|
|
||
| from bot.api import ResponseCodeError | ||
| from bot.bot import Bot | ||
| from bot.constants import Channels, Colours, Emojis, Guild | ||
| from bot.constants import Channels, Colours, DEFAULT_THREAD_ARCHIVE_TIME, Emojis, Guild, Roles | ||
| from bot.log import get_logger | ||
| from bot.utils.members import get_or_fetch_member | ||
| from bot.utils.messages import count_unique_users_reaction, pin_no_system_message | ||
|
|
@@ -36,9 +36,8 @@ | |
| MAX_EMBED_SIZE = 4000 | ||
|
|
||
| # Regex for finding the first message of a nomination, and extracting the nominee. | ||
| # Historic nominations will have 2 role mentions at the start, new ones won't, optionally match for this. | ||
| NOMINATION_MESSAGE_REGEX = re.compile( | ||
| r"(?:<@&\d+> <@&\d+>\n)*?<@!?(\d+?)> \(.+#\d{4}\) for Helper!\n\n\*\*Nominated by:\*\*", | ||
| r"<@!?(\d+)> \(.+#\d{4}\) for Helper!\n\n", | ||
| re.MULTILINE | ||
| ) | ||
|
|
||
|
|
@@ -78,14 +77,14 @@ def schedule_review(self, user_id: int) -> None: | |
|
|
||
| async def post_review(self, user_id: int, update_database: bool) -> None: | ||
| """Format the review of a user and post it to the nomination voting channel.""" | ||
| review, reviewed_emoji = await self.make_review(user_id) | ||
| if not review: | ||
| review, reviewed_emoji, nominee = await self.make_review(user_id) | ||
| if not nominee: | ||
| return | ||
|
|
||
| guild = self.bot.get_guild(Guild.id) | ||
| channel = guild.get_channel(Channels.nomination_voting) | ||
|
|
||
| log.trace(f"Posting the review of {user_id}") | ||
| log.trace(f"Posting the review of {nominee} ({nominee.id})") | ||
| messages = await self._bulk_send(channel, review) | ||
|
|
||
| await pin_no_system_message(messages[0]) | ||
|
|
@@ -95,12 +94,18 @@ async def post_review(self, user_id: int, update_database: bool) -> None: | |
| for reaction in (reviewed_emoji, "\N{THUMBS UP SIGN}", "\N{THUMBS DOWN SIGN}"): | ||
|
Contributor
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. This is a general comment, but the Doesn't need to be fixed in this PR since it's out of scope, but that was Not Fun debugging.
Member
Author
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. This has been fixed in 4bde791 |
||
| await last_message.add_reaction(reaction) | ||
|
|
||
| thread = await last_message.create_thread( | ||
| name=f"Nomination - {nominee}", | ||
| auto_archive_duration=DEFAULT_THREAD_ARCHIVE_TIME | ||
| ) | ||
| await thread.send(fr"<@&{Roles.mod_team}> <@&{Roles.admins}>") | ||
|
|
||
| if update_database: | ||
| nomination = self._pool.cache.get(user_id) | ||
| await self.bot.api_client.patch(f"bot/nominations/{nomination['id']}", json={"reviewed": True}) | ||
|
|
||
| async def make_review(self, user_id: int) -> typing.Tuple[str, Optional[Emoji]]: | ||
| """Format a generic review of a user and return it with the reviewed emoji.""" | ||
| async def make_review(self, user_id: int) -> typing.Tuple[str, Optional[Emoji], Optional[Member]]: | ||
| """Format a generic review of a user and return it with the reviewed emoji and the user themselves.""" | ||
| log.trace(f"Formatting the review of {user_id}") | ||
|
|
||
| # Since `cache` is a defaultdict, we should take care | ||
|
|
@@ -110,25 +115,25 @@ async def make_review(self, user_id: int) -> typing.Tuple[str, Optional[Emoji]]: | |
| nomination = self._pool.cache.get(user_id) | ||
| if not nomination: | ||
| log.trace(f"There doesn't appear to be an active nomination for {user_id}") | ||
| return "", None | ||
| return f"There doesn't appear to be an active nomination for {user_id}", None, None | ||
|
|
||
| guild = self.bot.get_guild(Guild.id) | ||
| member = await get_or_fetch_member(guild, user_id) | ||
| nominee = await get_or_fetch_member(guild, user_id) | ||
|
|
||
| if not member: | ||
| if not nominee: | ||
| return ( | ||
| f"I tried to review the user with ID `{user_id}`, but they don't appear to be on the server :pensive:" | ||
| ), None | ||
| ), None, None | ||
|
|
||
| opening = f"{member.mention} ({member}) for Helper!" | ||
| opening = f"{nominee.mention} ({nominee}) for Helper!" | ||
|
|
||
| current_nominations = "\n\n".join( | ||
| f"**<@{entry['actor']}>:** {entry['reason'] or '*no reason given*'}" | ||
| for entry in nomination['entries'][::-1] | ||
| ) | ||
| current_nominations = f"**Nominated by:**\n{current_nominations}" | ||
|
|
||
| review_body = await self._construct_review_body(member) | ||
| review_body = await self._construct_review_body(nominee) | ||
|
|
||
| reviewed_emoji = self._random_ducky(guild) | ||
| vote_request = ( | ||
|
|
@@ -138,7 +143,7 @@ async def make_review(self, user_id: int) -> typing.Tuple[str, Optional[Emoji]]: | |
| ) | ||
|
|
||
| review = "\n\n".join((opening, current_nominations, review_body, vote_request)) | ||
| return review, reviewed_emoji | ||
| return review, reviewed_emoji, nominee | ||
|
|
||
| async def archive_vote(self, message: PartialMessage, passed: bool) -> None: | ||
| """Archive this vote to #nomination-archive.""" | ||
|
|
@@ -210,8 +215,18 @@ async def archive_vote(self, message: PartialMessage, passed: bool) -> None: | |
| colour=colour | ||
| )) | ||
|
|
||
| # Thread channel IDs are the same as the message ID of the parent message. | ||
| nomination_thread = message.guild.get_thread(message.id) | ||
| if not nomination_thread: | ||
| log.warning(f"Could not find a thread linked to {message.channel.id}-{message.id}") | ||
| return | ||
|
|
||
| for message_ in messages: | ||
| await message_.delete() | ||
| with contextlib.suppress(NotFound): | ||
| await message_.delete() | ||
|
|
||
| with contextlib.suppress(NotFound): | ||
| await nomination_thread.edit(archived=True) | ||
|
|
||
| async def _construct_review_body(self, member: Member) -> str: | ||
| """Formats the body of the nomination, with details of activity, infractions, and previous nominations.""" | ||
|
|
@@ -360,10 +375,10 @@ async def _previous_nominations_review(self, member: Member) -> Optional[str]: | |
|
|
||
| @staticmethod | ||
| def _random_ducky(guild: Guild) -> Union[Emoji, str]: | ||
| """Picks a random ducky emoji. If no duckies found returns :eyes:.""" | ||
| """Picks a random ducky emoji. If no duckies found returns 👀.""" | ||
| duckies = [emoji for emoji in guild.emojis if emoji.name.startswith("ducky")] | ||
| if not duckies: | ||
| return ":eyes:" | ||
| return "\N{EYES}" | ||
| return random.choice(duckies) | ||
|
|
||
| @staticmethod | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.