aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Daniel Brown <[email protected]>2019-02-24 13:00:58 -0600
committerGravatar GitHub <[email protected]>2019-02-24 13:00:58 -0600
commitf447bafbe53cfc0ecfbc418366d76059d3c40e96 (patch)
tree365cd0dcdbb7b16dea1b4766bd0097e4e94d0367
parentMerge branch 'master' into rules_command (diff)
parentMerge pull request #307 from python-discord/bb-improvements (diff)
Merge branch 'master' into rules_command
-rw-r--r--bot/cogs/alias.py12
-rw-r--r--bot/cogs/bigbrother.py126
-rw-r--r--bot/cogs/off_topic_names.py10
-rw-r--r--bot/cogs/reddit.py4
-rw-r--r--bot/cogs/reminders.py3
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