diff options
author | 2019-02-23 22:39:09 +0100 | |
---|---|---|
committer | 2019-02-23 22:39:09 +0100 | |
commit | fda5da103fae32c208d5f5b2293b83bd230b4025 (patch) | |
tree | d57df495afbf1f43505ad838983c6349f4287f3d | |
parent | Merge pull request #314 from python-discord/Hemlock-Another-Role-Tweak (diff) | |
parent | Merge branch 'master' into bb-improvements (diff) |
Merge pull request #307 from python-discord/bb-improvements
Unwatch reason / Nomination improvements
-rw-r--r-- | bot/cogs/alias.py | 12 | ||||
-rw-r--r-- | bot/cogs/bigbrother.py | 126 |
2 files changed, 96 insertions, 42 deletions
diff --git a/bot/cogs/alias.py b/bot/cogs/alias.py index 8574927fc..bf40fe409 100644 --- a/bot/cogs/alias.py +++ b/bot/cogs/alias.py @@ -74,20 +74,18 @@ class Alias: self, ctx: Context, user: User, *, reason: str ): """ - Alias for invoking <prefix>bigbrother watch user [text_channel]. + Alias for invoking <prefix>bigbrother watch [user] [reason]. """ await self.invoke(ctx, "bigbrother watch", user, reason=reason) @command(name="unwatch", hidden=True) - async def bigbrother_unwatch_alias(self, ctx, user: User): + async def bigbrother_unwatch_alias(self, ctx, user: User, *, reason: str): """ - Alias for invoking <prefix>bigbrother unwatch user. - - user: discord.User - A user instance to unwatch + Alias for invoking <prefix>bigbrother unwatch [user] [reason]. """ - await self.invoke(ctx, "bigbrother unwatch", user) + await self.invoke(ctx, "bigbrother unwatch", user, reason=reason) @command(name="home", hidden=True) async def site_home_alias(self, ctx): @@ -108,7 +106,7 @@ class Alias: @command(name="reload", hidden=True) async def cogs_reload_alias(self, ctx, *, cog_name: str): """ - Alias for invoking <prefix>cogs reload cog_name. + Alias for invoking <prefix>cogs reload [cog_name]. cog_name: str - name of the cog to be reloaded. """ diff --git a/bot/cogs/bigbrother.py b/bot/cogs/bigbrother.py index 03d2f1d42..135745601 100644 --- a/bot/cogs/bigbrother.py +++ b/bot/cogs/bigbrother.py @@ -44,6 +44,7 @@ class BigBrother: self.last_log = [None, None, 0] # [user_id, channel_id, message_count] self.consuming = False self.infraction_watch_prefix = "bb watch: " # Please do not change or we won't be able to find old reasons + self.nomination_prefix = "Helper nomination: " self.bot.loop.create_task(self.get_watched_users()) @@ -77,10 +78,20 @@ class BigBrother: data = await response.json() self.update_cache(data) - async def get_watch_information(self, user_id: int) -> WatchInformation: + async def update_watched_users(self): + async with self.bot.http_session.get(URLs.site_bigbrother_api, headers=self.HEADERS) as response: + if response.status == 200: + data = await response.json() + self.update_cache(data) + log.trace("Updated Big Brother watchlist cache") + return True + else: + return False + + async def get_watch_information(self, user_id: int, prefix: str) -> WatchInformation: """ Fetches and returns the latest watch reason for a user using the infraction API """ - re_bb_watch = rf"^{self.infraction_watch_prefix}" + re_bb_watch = rf"^{prefix}" user_id = str(user_id) try: @@ -108,7 +119,7 @@ class BigBrother: date = latest_reason_infraction["inserted_at"] # Get the latest reason without the prefix - latest_reason = latest_reason_infraction['reason'][len(self.infraction_watch_prefix):] + latest_reason = latest_reason_infraction['reason'][len(prefix):] log.trace(f"The latest bb watch reason for {user_id}: {latest_reason}") return WatchInformation(reason=latest_reason, actor_id=actor_id, inserted_at=date) @@ -208,7 +219,11 @@ class BigBrother: # Retrieve watch reason from API if it's not already in the cache if message.author.id not in self.watch_reasons: log.trace(f"No watch information for {message.author.id} found in cache; retrieving from API") - user_watch_information = await self.get_watch_information(message.author.id) + if destination == self.bot.get_channel(Channels.talent_pool): + prefix = self.nomination_prefix + else: + prefix = self.infraction_watch_prefix + user_watch_information = await self.get_watch_information(message.author.id, prefix) self.watch_reasons[message.author.id] = user_watch_information self.last_log = [message.author.id, message.channel.id, 0] @@ -235,6 +250,13 @@ class BigBrother: # Adding nomination info to author_field author_field = f"{author_field} (nominated {time_delta} by {actor})" + else: + if inserted_at: + # Get time delta since insertion + date_time = parse_rfc1123(inserted_at).replace(tzinfo=None) + time_delta = time_since(date_time, precision="minutes", max_units=1) + + author_field = f"{author_field} (added {time_delta})" embed = Embed(description=f"{message.author.mention} in [#{message.channel.name}]({message.jump_url})") embed.set_author(name=author_field, icon_url=message.author.avatar_url) @@ -291,7 +313,6 @@ class BigBrother: self.watched_users[user.id] = channel # Add a note (shadow warning) with the reason for watching - reason = f"{self.infraction_watch_prefix}{reason}" await post_infraction(ctx, user, type="warning", reason=reason, hidden=True) else: data = await response.json() @@ -313,35 +334,25 @@ class BigBrother: By default, the users are returned from the cache. If this is not desired, `from_cache` can be given as a falsy value, e.g. e.g. 'no'. """ - - if from_cache: - lines = tuple( - f"• <@{user_id}> in <#{self.watched_users[user_id].id}>" - for user_id in self.watched_users - ) - await LinePaginator.paginate( - lines or ("There's nothing here yet.",), - ctx, - Embed(title="Watched users (cached)", color=Color.blue()), - empty=False - ) - + if not from_cache: + updated = await self.update_watched_users() + if not updated: + await ctx.send(f":x: Failed to update cache: non-200 response from the API") + return + title = "Watched users (updated cache)" else: - async with self.bot.http_session.get(URLs.site_bigbrother_api, headers=self.HEADERS) as response: - if response.status == 200: - data = await response.json() - self.update_cache(data) - lines = tuple(f"• <@{entry['user_id']}> in <#{entry['channel_id']}>" for entry in data) - - await LinePaginator.paginate( - lines or ("There's nothing here yet.",), - ctx, - Embed(title="Watched users", color=Color.blue()), - empty=False - ) - - else: - await ctx.send(f":x: got non-200 response from the API") + title = "Watched users (from cache)" + + lines = tuple( + f"• <@{user_id}> in <#{self.watched_users[user_id].id}>" + for user_id in self.watched_users + ) + await LinePaginator.paginate( + lines or ("There's nothing here yet.",), + ctx, + Embed(title=title, color=Color.blue()), + empty=False + ) @bigbrother_group.command(name='watch', aliases=('w',)) @with_role(*MODERATION_ROLES) @@ -353,14 +364,28 @@ class BigBrother: note (aka: shadow warning) """ + # Update cache to avoid double watching of a user + await self.update_watched_users() + + if user.id in self.watched_users: + message = f":x: User is already being watched in {self.watched_users[user.id].name}" + await ctx.send(message) + return + channel_id = Channels.big_brother_logs + reason = f"{self.infraction_watch_prefix}{reason}" + await self._watch_user(ctx, user, reason, channel_id) @bigbrother_group.command(name='unwatch', aliases=('uw',)) @with_role(*MODERATION_ROLES) - async def unwatch_command(self, ctx: Context, user: User): - """Stop relaying messages by the given `user`.""" + async def unwatch_command(self, ctx: Context, user: User, *, reason: str): + """ + Stop relaying messages by the given `user`. + + A `reason` for unwatching is required, which will be added as a note to the user. + """ url = f"{URLs.site_bigbrother_api}?user_id={user.id}" async with self.bot.http_session.delete(url, headers=self.HEADERS) as response: @@ -368,14 +393,20 @@ class BigBrother: await ctx.send(f":ok_hand: will no longer relay messages sent by {user}") if user.id in self.watched_users: + channel = self.watched_users[user.id] + del self.watched_users[user.id] if user.id in self.channel_queues: del self.channel_queues[user.id] if user.id in self.watch_reasons: del self.watch_reasons[user.id] else: + channel = None log.warning(f"user {user.id} was unwatched but was not found in the cache") + reason = f"Unwatched ({channel.name if channel else 'unknown channel'}): {reason}" + await post_infraction(ctx, user, type="warning", reason=reason, hidden=True) + else: data = await response.json() reason = data.get('error_message', "no message provided") @@ -395,8 +426,33 @@ class BigBrother: # !nominate command does not show up under "BigBrother" in the help embed, but under # the header HelperNomination for users with the helper role. + member = ctx.guild.get_member(user.id) + + if member and any(role.id in STAFF_ROLES for role in member.roles): + await ctx.send(f":x: {user.mention} is already a staff member!") + return + channel_id = Channels.talent_pool + # Update watch cache to avoid overwriting active nomination reason + await self.update_watched_users() + + if user.id in self.watched_users: + if self.watched_users[user.id].id == Channels.talent_pool: + prefix = "Additional nomination: " + else: + # If the user is being watched in big-brother, don't add them to talent-pool + message = ( + f":x: {user.mention} can't be added to the talent-pool " + "as they are currently being watched in big-brother." + ) + await ctx.send(message) + return + else: + prefix = self.nomination_prefix + + reason = f"{prefix}{reason}" + await self._watch_user(ctx, user, reason, channel_id) |