diff options
| author | 2019-06-27 22:09:34 +0200 | |
|---|---|---|
| committer | 2019-06-27 22:09:34 +0200 | |
| commit | 725656f471715fe96c92fac3b0155213f17029c1 (patch) | |
| tree | af100655ac12684bf4337b750d59447eeb1f30bb | |
| parent | Truncating long names that misalign logs + adding 3 chars to account for watc... (diff) | |
Removing the old talentpool/bigbrother files + changing the extension loader
| -rw-r--r-- | bot/__main__.py | 2 | ||||
| -rw-r--r-- | bot/cogs/bigbrother.py | 258 | ||||
| -rw-r--r-- | bot/cogs/nominations.py | 120 |
3 files changed, 1 insertions, 379 deletions
diff --git a/bot/__main__.py b/bot/__main__.py index 8afec2718..44d4d9c02 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -38,7 +38,6 @@ bot.load_extension("bot.cogs.modlog") # Commands, etc bot.load_extension("bot.cogs.antispam") -bot.load_extension("bot.cogs.bigbrother") bot.load_extension("bot.cogs.bot") bot.load_extension("bot.cogs.clean") bot.load_extension("bot.cogs.cogs") @@ -69,6 +68,7 @@ bot.load_extension("bot.cogs.sync") bot.load_extension("bot.cogs.tags") bot.load_extension("bot.cogs.token_remover") bot.load_extension("bot.cogs.utils") +bot.load_extension("bot.cogs.watchchannels") bot.load_extension("bot.cogs.wolfram") bot.run(BotConfig.token) diff --git a/bot/cogs/bigbrother.py b/bot/cogs/bigbrother.py deleted file mode 100644 index df7a0b576..000000000 --- a/bot/cogs/bigbrother.py +++ /dev/null @@ -1,258 +0,0 @@ -import asyncio -import logging -import re -from collections import defaultdict, deque -from typing import List, Union - -from discord import Color, Embed, Guild, Member, Message, User -from discord.ext.commands import Bot, Context, group - -from bot.constants import ( - BigBrother as BigBrotherConfig, Channels, Emojis, Guild as GuildConfig, Roles -) -from bot.decorators import with_role -from bot.pagination import LinePaginator -from bot.utils import messages -from bot.utils.moderation import post_infraction - -log = logging.getLogger(__name__) - -URL_RE = re.compile(r"(https?://[^\s]+)") - - -class BigBrother: - """User monitoring to assist with moderation.""" - - def __init__(self, bot: Bot): - self.bot = bot - self.watched_users = set() # { user_id } - self.channel_queues = defaultdict(lambda: defaultdict(deque)) # { user_id: { channel_id: queue(messages) } - self.last_log = [None, None, 0] # [user_id, channel_id, message_count] - self.consuming = False - - def update_cache(self, api_response: List[dict]): - """ - Updates the internal cache of watched users from the given `api_response`. - This function will only add (or update) existing keys, it will not delete - keys that were not present in the API response. - A user is only added if the bot can find a channel - with the given `channel_id` in its channel cache. - """ - - for entry in api_response: - user_id = entry['user'] - self.watched_users.add(user_id) - - async def on_ready(self): - """Retrieves watched users from the API.""" - - self.channel = self.bot.get_channel(Channels.big_brother_logs) - if self.channel is None: - log.error("Cannot find Big Brother channel. Cannot watch users.") - else: - data = await self.bot.api_client.get( - 'bot/infractions', - params={ - 'active': 'true', - 'type': 'watch' - } - ) - self.update_cache(data) - - async def on_member_ban(self, guild: Guild, user: Union[User, Member]): - if guild.id == GuildConfig.id and user.id in self.watched_users: - [active_watch] = await self.bot.api_client.get( - 'bot/infractions', - params={ - 'active': 'true', - 'type': 'watch', - 'user__id': str(user.id) - } - ) - await self.bot.api_client.put( - 'bot/infractions/' + str(active_watch['id']), - json={'active': False} - ) - self.watched_users.remove(user.id) - del self.channel_queues[user.id] - await self.channel.send( - f"{Emojis.bb_message}:hammer: {user} got banned, so " - f"`BigBrother` will no longer relay their messages." - ) - - async def on_message(self, msg: Message): - """Queues up messages sent by watched users.""" - - if msg.author.id in self.watched_users: - if not self.consuming: - self.bot.loop.create_task(self.consume_messages()) - - log.trace(f"Received message: {msg.content} ({len(msg.attachments)} attachments)") - self.channel_queues[msg.author.id][msg.channel.id].append(msg) - - async def consume_messages(self): - """Consumes the message queues to log watched users' messages.""" - - if not self.consuming: - self.consuming = True - log.trace("Sleeping before consuming...") - await asyncio.sleep(BigBrotherConfig.log_delay) - - log.trace("Begin consuming messages.") - channel_queues = self.channel_queues.copy() - self.channel_queues.clear() - for _, queues in channel_queues.items(): - for queue in queues.values(): - while queue: - msg = queue.popleft() - log.trace(f"Consuming message: {msg.clean_content} ({len(msg.attachments)} attachments)") - - self.last_log[2] += 1 # Increment message count. - await self.send_header(msg) - await self.log_message(msg) - - if self.channel_queues: - log.trace("Queue not empty; continue consumption.") - self.bot.loop.create_task(self.consume_messages()) - else: - log.trace("Done consuming messages.") - self.consuming = False - - async def send_header(self, message: Message): - """ - Sends a log message header to the given channel. - - A header is only sent if the user or channel are different than the previous, or if the configured message - limit for a single header has been exceeded. - - :param message: the first message in the queue - """ - - last_user, last_channel, msg_count = self.last_log - limit = BigBrotherConfig.header_message_limit - - # Send header if user/channel are different or if message limit exceeded. - if message.author.id != last_user or message.channel.id != last_channel or msg_count > limit: - self.last_log = [message.author.id, message.channel.id, 0] - - embed = Embed(description=f"{message.author.mention} in [#{message.channel.name}]({message.jump_url})") - embed.set_author(name=message.author.nick or message.author.name, icon_url=message.author.avatar_url) - await self.channel.send(embed=embed) - - async def log_message(self, message: Message): - """ - Logs a watched user's message in the given channel. - - Attachments are also sent. All non-image or non-video URLs are put in inline code blocks to prevent preview - embeds from being automatically generated. - - :param message: the message to log - """ - - content = message.clean_content - if content: - # Put all non-media URLs in inline code blocks. - media_urls = {embed.url for embed in message.embeds if embed.type in ("image", "video")} - for url in URL_RE.findall(content): - if url not in media_urls: - content = content.replace(url, f"`{url}`") - - await self.channel.send(content) - - await messages.send_attachments(message, self.channel) - - @group(name='bigbrother', aliases=('bb',), invoke_without_command=True) - @with_role(Roles.owner, Roles.admin, Roles.moderator) - async def bigbrother_group(self, ctx: Context): - """Monitor users, NSA-style.""" - - await ctx.invoke(self.bot.get_command("help"), "bigbrother") - - @bigbrother_group.command(name='watched', aliases=('all',)) - @with_role(Roles.owner, Roles.admin, Roles.moderator) - async def watched_command(self, ctx: Context, from_cache: bool = True): - """ - Shows all users that are currently monitored and in which channel. - 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}>" 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 - ) - - else: - active_watches = await self.bot.api_client.get( - 'bot/infractions', - params={ - 'active': 'true', - 'type': 'watch' - } - ) - self.update_cache(active_watches) - lines = tuple( - f"• <@{entry['user']}>: {entry['reason'] or '*no reason provided*'}" - for entry in active_watches - ) - - await LinePaginator.paginate( - lines or ("There's nothing here yet.",), - ctx, - Embed(title="Watched users", color=Color.blue()), - empty=False - ) - - @bigbrother_group.command(name='watch', aliases=('w',)) - @with_role(Roles.owner, Roles.admin, Roles.moderator) - async def watch_command(self, ctx: Context, user: User, *, reason: str): - """ - Relay messages sent by the given `user` to the `#big-brother-logs` channel - - A `reason` for watching is required, which is added for the user to be watched as a - note (aka: shadow warning) - """ - - if user.id in self.watched_users: - return await ctx.send(":x: That user is already watched.") - - await post_infraction( - ctx, user, type='watch', reason=reason, hidden=True - ) - self.watched_users.add(user.id) - await ctx.send(f":ok_hand: will now relay messages sent by {user}") - - @bigbrother_group.command(name='unwatch', aliases=('uw',)) - @with_role(Roles.owner, Roles.admin, Roles.moderator) - async def unwatch_command(self, ctx: Context, user: User): - """Stop relaying messages by the given `user`.""" - - active_watches = await self.bot.api_client.get( - 'bot/infractions', - params={ - 'active': 'true', - 'type': 'watch', - 'user__id': str(user.id) - } - ) - if active_watches: - [infraction] = active_watches - await self.bot.api_client.patch( - 'bot/infractions/' + str(infraction['id']), - json={'active': False} - ) - await ctx.send(f":ok_hand: will no longer relay messages sent by {user}") - self.watched_users.remove(user.id) - if user.id in self.channel_queues: - del self.channel_queues[user.id] - else: - await ctx.send(":x: that user is currently not being watched") - - -def setup(bot: Bot): - bot.add_cog(BigBrother(bot)) - log.info("Cog loaded: BigBrother") diff --git a/bot/cogs/nominations.py b/bot/cogs/nominations.py deleted file mode 100644 index 93ee0d885..000000000 --- a/bot/cogs/nominations.py +++ /dev/null @@ -1,120 +0,0 @@ -import logging - -from discord import Color, Embed, User -from discord.ext.commands import Context, group - -from bot.cogs.bigbrother import BigBrother, Roles -from bot.constants import Channels -from bot.decorators import with_role -from bot.pagination import LinePaginator - - -log = logging.getLogger(__name__) - - -class Nominations(BigBrother): - """Monitor potential helpers, NSA-style.""" - - async def on_ready(self): - """Retrieve nominees from the API.""" - - self.channel = self.bot.get_channel(Channels.talent_pool) - if self.channel is None: - log.error("Cannot find talent pool channel. Cannot watch nominees.") - else: - nominations = await self.bot.api_client.get( - 'bot/nominations', - params={'active': 'true'} - ) - self.update_cache(nominations) - - async def on_member_ban(self, *_): - pass - - @group(name='nominations', aliases=('n',), invoke_without_command=True) - @with_role(Roles.owner, Roles.admin, Roles.moderator) - async def bigbrother_group(self, ctx: Context): - """Nominate helpers, NSA-style.""" - - await ctx.invoke(self.bot.get_command("help"), "nominations") - - @bigbrother_group.command(name='nominated', aliases=('nominees', 'all')) - @with_role(Roles.owner, Roles.admin, Roles.moderator) - async def watched_command(self, ctx: Context, from_cache: bool = True): - if from_cache: - lines = tuple(f"• <@{user_id}>" for user_id in self.watched_users) - - else: - active_nominations = await self.bot.api_client.get( - 'bot/nominations', - params={'active': 'true'} - ) - self.update_cache(active_nominations) - lines = tuple( - f"• <@{entry['user']}>: {entry['reason'] or '*no reason provided*'}" - for entry in active_nominations - ) - - await LinePaginator.paginate( - lines or ("There's nothing here yet.",), - ctx, - Embed( - title="Nominated users" + " (cached)" * from_cache, - color=Color.blue() - ), - empty=False - ) - - @bigbrother_group.command(name='nominate', aliases=('n',)) - @with_role(Roles.owner, Roles.admin, Roles.moderator) - async def watch_command(self, ctx: Context, user: User, *, reason: str): - """Talent pool the given `user`.""" - - active_nominations = await self.bot.api_client.get( - 'bot/nominations/' + str(user.id), - ) - if active_nominations: - active_nominations = await self.bot.api_client.put( - 'bot/nominations/' + str(user.id), - json={'active': True} - ) - await ctx.send(":ok_hand: user's watch was updated") - - else: - active_nominations = await self.bot.api_client.post( - 'bot/nominations/' + str(user.id), - json={ - 'active': True, - 'author': ctx.author.id, - 'reason': reason, - } - ) - self.watched_users.add(user.id) - await ctx.send(":ok_hand: user added to talent pool") - - @bigbrother_group.command(name='unnominate', aliases=('un',)) - @with_role(Roles.owner, Roles.admin, Roles.moderator) - async def unwatch_command(self, ctx: Context, user: User): - """Stop talent pooling the given `user`.""" - - nomination = await self.bot.api_client.get( - 'bot/nominations/' + str(user.id) - ) - - if not nomination['active']: - await ctx.send(":x: the nomination is already inactive") - - else: - await self.bot.api_client.put( - 'bot/nominations/' + str(user.id), - json={'active': False} - ) - self.watched_users.remove(user.id) - if user.id in self.channel_queues: - del self.channel_queues[user.id] - await ctx.send(f":ok_hand: {user} is no longer part of the talent pool") - - -def setup(bot): - bot.add_cog(Nominations(bot)) - log.info("Cog loaded: Nominations") |