aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Leon Sandøy <[email protected]>2019-02-23 22:39:09 +0100
committerGravatar GitHub <[email protected]>2019-02-23 22:39:09 +0100
commitfda5da103fae32c208d5f5b2293b83bd230b4025 (patch)
treed57df495afbf1f43505ad838983c6349f4287f3d
parentMerge pull request #314 from python-discord/Hemlock-Another-Role-Tweak (diff)
parentMerge 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.py12
-rw-r--r--bot/cogs/bigbrother.py126
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)