aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/__main__.py18
-rw-r--r--bot/cogs/information.py126
-rw-r--r--bot/cogs/moderation.py4
-rw-r--r--bot/cogs/off_topic_names.py26
-rw-r--r--bot/constants.py6
-rw-r--r--config-default.yml7
6 files changed, 174 insertions, 13 deletions
diff --git a/bot/__main__.py b/bot/__main__.py
index d6cfc5d5b..c5c8b8909 100644
--- a/bot/__main__.py
+++ b/bot/__main__.py
@@ -5,7 +5,7 @@ from aiohttp import AsyncResolver, ClientSession, TCPConnector
from discord import Game
from discord.ext.commands import Bot, when_mentioned_or
-from bot.constants import Bot as BotConfig # , ClickUp
+from bot.constants import Bot as BotConfig, DEBUG_MODE
from bot.utils.service_discovery import wait_for_rmq
@@ -38,31 +38,30 @@ else:
# Internal/debug
bot.load_extension("bot.cogs.logging")
-bot.load_extension("bot.cogs.modlog")
bot.load_extension("bot.cogs.security")
bot.load_extension("bot.cogs.events")
bot.load_extension("bot.cogs.filtering")
# Commands, etc
-# bot.load_extension("bot.cogs.antispam")
+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")
-# Local setups usually don't have the clickup key set,
-# and loading the cog would simply spam errors in the console.
-# if ClickUp.key is not None:
-# bot.load_extension("bot.cogs.clickup")
-# else:
-# log.info("`CLICKUP_KEY` not set in the environment, not loading the ClickUp cog.")
+# Only load this in production
+if not DEBUG_MODE:
+ bot.load_extension("bot.cogs.modlog")
+ bot.load_extension("bot.cogs.verification")
+# Feature cogs
bot.load_extension("bot.cogs.deployment")
bot.load_extension("bot.cogs.defcon")
bot.load_extension("bot.cogs.doc")
bot.load_extension("bot.cogs.eval")
bot.load_extension("bot.cogs.fun")
bot.load_extension("bot.cogs.hiphopify")
+bot.load_extension("bot.cogs.information")
bot.load_extension("bot.cogs.moderation")
bot.load_extension("bot.cogs.off_topic_names")
bot.load_extension("bot.cogs.snakes")
@@ -70,7 +69,6 @@ bot.load_extension("bot.cogs.snekbox")
bot.load_extension("bot.cogs.tags")
bot.load_extension("bot.cogs.token_remover")
bot.load_extension("bot.cogs.utils")
-bot.load_extension("bot.cogs.verification")
if has_rmq:
bot.load_extension("bot.cogs.rmq")
diff --git a/bot/cogs/information.py b/bot/cogs/information.py
new file mode 100644
index 000000000..f61b130a6
--- /dev/null
+++ b/bot/cogs/information.py
@@ -0,0 +1,126 @@
+import logging
+import textwrap
+from datetime import datetime
+
+from dateutil.relativedelta import relativedelta
+from discord import CategoryChannel, Colour, Embed, TextChannel, VoiceChannel
+from discord.ext.commands import Bot, Context, command
+
+from bot.constants import Emojis
+from bot.utils.time import humanize
+
+log = logging.getLogger(__name__)
+
+
+class Information:
+ """
+ A cog with commands for generating embeds with
+ server information, such as server statistics
+ and user information.
+ """
+
+ def __init__(self, bot: Bot):
+ self.bot = bot
+
+ @command(name="roles")
+ async def roles_info(self, ctx: Context):
+ """
+ Returns a list of all roles and their
+ corresponding IDs.
+ """
+
+ # Sort the roles alphabetically and remove the @everyone role
+ roles = sorted(ctx.guild.roles, key=lambda role: role.name)
+ roles = [role for role in roles if role.name != "@everyone"]
+
+ # Build a string
+ role_string = ""
+ for role in roles:
+ role_string += f"`{role.id}` - {role.mention}\n"
+
+ # Build an embed
+ embed = Embed(
+ title="Role information",
+ colour=Colour.blurple(),
+ description=role_string
+ )
+
+ embed.set_footer(text=f"Total roles: {len(roles)}")
+
+ await ctx.send(embed=embed)
+
+ @command(name="server", aliases=["server_info", "guild", "guild_info"])
+ async def server_info(self, ctx: Context):
+ """
+ Returns an embed full of
+ server information.
+ """
+
+ now = datetime.now()
+ created_delta = relativedelta(now, ctx.guild.created_at)
+ created = humanize(created_delta, accuracy="days")
+ features = ", ".join(ctx.guild.features)
+ region = ctx.guild.region
+
+ # How many of each type of channel?
+ roles = len(ctx.guild.roles)
+ channels = ctx.guild.channels
+ text_channels = 0
+ category_channels = 0
+ voice_channels = 0
+ for channel in channels:
+ if type(channel) == TextChannel:
+ text_channels += 1
+ elif type(channel) == CategoryChannel:
+ category_channels += 1
+ elif type(channel) == VoiceChannel:
+ voice_channels += 1
+
+ # How many of each user status?
+ member_count = ctx.guild.member_count
+ members = ctx.guild.members
+ online = 0
+ dnd = 0
+ idle = 0
+ offline = 0
+ for member in members:
+ if str(member.status) == "online":
+ online += 1
+ elif str(member.status) == "offline":
+ offline += 1
+ elif str(member.status) == "idle":
+ idle += 1
+ elif str(member.status) == "dnd":
+ dnd += 1
+
+ embed = Embed(
+ colour=Colour.blurple(),
+ description=textwrap.dedent(f"""
+ **Server information**
+ Created: {created} ago
+ Voice region: {region}
+ Features: {features}
+
+ **Counts**
+ Members: {member_count}
+ Roles: {roles}
+ Text: {text_channels}
+ Voice: {voice_channels}
+ Channel categories: {category_channels}
+
+ **Members**
+ {Emojis.status_online} {online}
+ {Emojis.status_idle} {idle}
+ {Emojis.status_dnd} {dnd}
+ {Emojis.status_offline} {offline}
+ """)
+ )
+
+ embed.set_thumbnail(url=ctx.guild.icon_url)
+
+ await ctx.send(embed=embed)
+
+
+def setup(bot):
+ bot.add_cog(Information(bot))
+ log.info("Cog loaded: Information")
diff --git a/bot/cogs/moderation.py b/bot/cogs/moderation.py
index 585bba6a6..0a0bbae53 100644
--- a/bot/cogs/moderation.py
+++ b/bot/cogs/moderation.py
@@ -663,8 +663,8 @@ def parse_rfc1123(time_str):
def _silent_exception(future):
try:
future.exception()
- except Exception as e:
- log.debug(f"_silent_exception silenced the following exception: {e}")
+ except Exception: # noqa: S110
+ pass
def setup(bot):
diff --git a/bot/cogs/off_topic_names.py b/bot/cogs/off_topic_names.py
index f089e0b5a..bcf3148f8 100644
--- a/bot/cogs/off_topic_names.py
+++ b/bot/cogs/off_topic_names.py
@@ -111,6 +111,32 @@ class OffTopicNames:
error_reason = response.get('message', "No reason provided.")
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)
+ async def delete_command(self, ctx, name: OffTopicName):
+ """Removes a off-topic name from the rotation."""
+
+ result = await self.bot.http_session.delete(
+ URLs.site_off_topic_names_api,
+ headers=self.headers,
+ params={'name': name}
+ )
+
+ response = await result.json()
+
+ if result.status == 200:
+ if response['deleted'] == 0:
+ await ctx.send(f":warning: No name matching `{name}` was found in the database.")
+ else:
+ log.info(
+ f"{ctx.author.name}#{ctx.author.discriminator}"
+ f" deleted the off-topic channel name '{name}"
+ )
+ await ctx.send(":ok_hand:")
+ else:
+ error_reason = response.get('message', "No reason provided.")
+ 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)
async def list_command(self, ctx):
diff --git a/bot/constants.py b/bot/constants.py
index 54d37b3f0..ab426a7ab 100644
--- a/bot/constants.py
+++ b/bot/constants.py
@@ -237,6 +237,12 @@ class Emojis(metaclass=YAMLGetter):
green_chevron: str
red_chevron: str
white_chevron: str
+ lemoneye2: str
+
+ status_online: str
+ status_offline: str
+ status_idle: str
+ status_dnd: str
bullet: str
new: str
diff --git a/config-default.yml b/config-default.yml
index 17c438a8f..0519244b0 100644
--- a/config-default.yml
+++ b/config-default.yml
@@ -26,6 +26,11 @@ style:
white_chevron: "<:whitechevron:418110396973711363>"
lemoneye2: "<:lemoneye2:435193765582340098>"
+ status_online: "<:status_online:470326272351010816>"
+ status_idle: "<:status_idle:470326266625785866>"
+ status_dnd: "<:status_dnd:470326272082313216>"
+ status_offline: "<:status_offline:470326266537705472>"
+
bullet: "\u2022"
pencil: "\u270F"
new: "\U0001F195"
@@ -267,7 +272,7 @@ anti_spam:
discord_emojis:
interval: 10
- max: 6
+ max: 20
links:
interval: 10