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