diff options
| author | 2019-02-24 13:00:58 -0600 | |
|---|---|---|
| committer | 2019-02-24 13:00:58 -0600 | |
| commit | f447bafbe53cfc0ecfbc418366d76059d3c40e96 (patch) | |
| tree | 365cd0dcdbb7b16dea1b4766bd0097e4e94d0367 | |
| parent | Merge branch 'master' into rules_command (diff) | |
| parent | Merge pull request #307 from python-discord/bb-improvements (diff) | |
Merge branch 'master' into rules_command
| -rw-r--r-- | bot/cogs/alias.py | 12 | ||||
| -rw-r--r-- | bot/cogs/bigbrother.py | 126 | ||||
| -rw-r--r-- | bot/cogs/off_topic_names.py | 10 | ||||
| -rw-r--r-- | bot/cogs/reddit.py | 4 | ||||
| -rw-r--r-- | bot/cogs/reminders.py | 3 | 
5 files changed, 104 insertions, 51 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) diff --git a/bot/cogs/off_topic_names.py b/bot/cogs/off_topic_names.py index 25b8a48b8..4dde9169f 100644 --- a/bot/cogs/off_topic_names.py +++ b/bot/cogs/off_topic_names.py @@ -5,7 +5,7 @@ from datetime import datetime, timedelta  from discord import Colour, Embed  from discord.ext.commands import BadArgument, Bot, Context, Converter, group -from bot.constants import Channels, Keys, Roles, URLs +from bot.constants import Channels, Keys, MODERATION_ROLES, URLs  from bot.decorators import with_role  from bot.pagination import LinePaginator @@ -87,14 +87,14 @@ class OffTopicNames:              self.updater_task = await self.bot.loop.create_task(coro)      @group(name='otname', aliases=('otnames', 'otn'), invoke_without_command=True) -    @with_role(Roles.owner, Roles.admin, Roles.moderator) +    @with_role(*MODERATION_ROLES)      async def otname_group(self, ctx):          """Add or list items from the off-topic channel name rotation."""          await ctx.invoke(self.bot.get_command("help"), "otname")      @otname_group.command(name='add', aliases=('a',)) -    @with_role(Roles.owner, Roles.admin, Roles.moderator) +    @with_role(*MODERATION_ROLES)      async def add_command(self, ctx, name: OffTopicName):          """Adds a new off-topic name to the rotation.""" @@ -117,7 +117,7 @@ class OffTopicNames:              await ctx.send(f":warning: got non-200 from the API: {error_reason}")      @otname_group.command(name='delete', aliases=('remove', 'rm', 'del', 'd')) -    @with_role(Roles.owner, Roles.admin, Roles.moderator) +    @with_role(*MODERATION_ROLES)      async def delete_command(self, ctx, name: OffTopicName):          """Removes a off-topic name from the rotation.""" @@ -143,7 +143,7 @@ class OffTopicNames:              await ctx.send(f":warning: got non-200 from the API: {error_reason}")      @otname_group.command(name='list', aliases=('l',)) -    @with_role(Roles.owner, Roles.admin, Roles.moderator) +    @with_role(*MODERATION_ROLES)      async def list_command(self, ctx):          """          Lists all currently known off-topic channel names in a paginator. diff --git a/bot/cogs/reddit.py b/bot/cogs/reddit.py index 952fa4682..2e3d32b2d 100644 --- a/bot/cogs/reddit.py +++ b/bot/cogs/reddit.py @@ -7,7 +7,7 @@ from datetime import datetime, timedelta  from discord import Colour, Embed, TextChannel  from discord.ext.commands import Bot, Context, group -from bot.constants import Channels, ERROR_REPLIES, Reddit as RedditConfig, Roles +from bot.constants import Channels, ERROR_REPLIES, Reddit as RedditConfig, STAFF_ROLES  from bot.converters import Subreddit  from bot.decorators import with_role  from bot.pagination import LinePaginator @@ -257,7 +257,7 @@ class Reddit:              time="week"          ) -    @with_role(Roles.owner, Roles.admin, Roles.moderator, Roles.helpers) +    @with_role(*STAFF_ROLES)      @reddit_group.command(name="subreddits", aliases=("subs",))      async def subreddits_command(self, ctx: Context):          """ diff --git a/bot/cogs/reminders.py b/bot/cogs/reminders.py index ddf5cc1f3..2a9a9d6dc 100644 --- a/bot/cogs/reminders.py +++ b/bot/cogs/reminders.py @@ -11,7 +11,7 @@ from discord.ext.commands import Bot, Context, group  from bot.constants import (      Channels, Icons, Keys, NEGATIVE_REPLIES, -    POSITIVE_REPLIES, Roles, URLs +    POSITIVE_REPLIES, STAFF_ROLES, URLs  )  from bot.pagination import LinePaginator  from bot.utils.scheduling import Scheduler @@ -19,7 +19,6 @@ from bot.utils.time import humanize_delta, parse_rfc1123, wait_until  log = logging.getLogger(__name__) -STAFF_ROLES = (Roles.owner, Roles.admin, Roles.moderator, Roles.helpers)  WHITELISTED_CHANNELS = (Channels.bot,)  MAXIMUM_REMINDERS = 5 | 
