diff --git a/bot/modules/sysadmin/__init__.py b/bot/modules/sysadmin/__init__.py index 5401a965..bd276c1c 100644 --- a/bot/modules/sysadmin/__init__.py +++ b/bot/modules/sysadmin/__init__.py @@ -1,3 +1,5 @@ from .module import module -from .exec_cmds import * +from . import exec_cmds +from . import guild_log +from . import status diff --git a/bot/modules/sysadmin/guild_log.py b/bot/modules/sysadmin/guild_log.py new file mode 100644 index 00000000..092fc1f5 --- /dev/null +++ b/bot/modules/sysadmin/guild_log.py @@ -0,0 +1,84 @@ +import datetime +import discord + +from meta import client, conf +from utils.lib import mail + + +@client.add_after_event("guild_remove") +async def log_left_guild(client, guild): + # Build embed + embed = discord.Embed(title="`{0.name} (ID: {0.id})`".format(guild), + colour=discord.Colour.red(), + timestamp=datetime.datetime.utcnow()) + embed.set_author(name="Left guild!") + embed.set_thumbnail(url=guild.icon_url) + + # Add more specific information about the guild + embed.add_field(name="Owner", value="{0.name} (ID: {0.id})".format(guild.owner), inline=False) + embed.add_field(name="Members (cached)", value="{}".format(len(guild.members)), inline=False) + embed.add_field(name="Now studying in", value="{} guilds".format(len(client.guilds)), inline=False) + + # Retrieve the guild log channel and log the event + log_chid = conf.bot.get("guild_log_channel") + if log_chid: + await mail(client, log_chid, embed=embed) + + +@client.add_after_event("guild_join") +async def log_joined_guild(client, guild): + owner = guild.owner + icon = guild.icon_url + + bots = 0 + known = 0 + unknown = 0 + other_members = set(mem.id for mem in client.get_all_members() if mem.guild != guild) + + for member in guild.members: + if member.bot: + bots += 1 + elif member.id in other_members: + known += 1 + else: + unknown += 1 + + mem1 = "people I know" if known != 1 else "person I know" + mem2 = "new friends" if unknown != 1 else "new friend" + mem3 = "bots" if bots != 1 else "bot" + mem4 = "total members" + known = "`{}`".format(known) + unknown = "`{}`".format(unknown) + bots = "`{}`".format(bots) + total = "`{}`".format(guild.member_count) + mem_str = "{0:<5}\t{4},\n{1:<5}\t{5},\n{2:<5}\t{6}, and\n{3:<5}\t{7}.".format( + known, + unknown, + bots, + total, + mem1, + mem2, + mem3, + mem4 + ) + region = str(guild.region) + created = "".format(int(guild.created_at.timestamp())) + + embed = discord.Embed( + title="`{0.name} (ID: {0.id})`".format(guild), + colour=discord.Colour.green(), + timestamp=datetime.datetime.utcnow() + ) + embed.set_author(name="Joined guild!") + embed.set_thumbnail(url=icon) + + embed.add_field(name="Owner", value="{0} (ID: {0.id})".format(owner), inline=False) + embed.add_field(name="Region", value=region, inline=False) + embed.add_field(name="Created at", value=created, inline=False) + embed.add_field(name="Members", value=mem_str, inline=False) + embed.add_field(name="Now studying in", value="{} guilds".format(len(client.guilds)), inline=False) + + # Retrieve the guild log channel and log the event + log_chid = conf.bot.get("guild_log_channel") + if log_chid: + await mail(client, log_chid, embed=embed) diff --git a/bot/modules/sysadmin/status.py b/bot/modules/sysadmin/status.py new file mode 100644 index 00000000..83f02cc8 --- /dev/null +++ b/bot/modules/sysadmin/status.py @@ -0,0 +1,59 @@ +import time +import asyncio +import discord +from meta import client + +from .module import module + + +_last_update = 0 + + +async def update_status(): + # TODO: Make globally configurable and saveable + global _last_update + + if time.time() - _last_update < 30: + return + + _last_update = time.time() + + student_count = sum( + len(ch.members) + for guild in client.guilds + for ch in guild.voice_channels + ) + room_count = sum( + len([vc for vc in guild.voice_channels if vc.members]) + for guild in client.guilds + ) + status = "{} students in {} study rooms!".format(student_count, room_count) + + await client.change_presence( + activity=discord.Activity( + type=discord.ActivityType.watching, + name=status + ) + ) + + +@client.add_after_event("voice_state_update") +async def trigger_status_update(client, member, before, after): + if before.channel != after.channel: + await update_status() + + +async def _status_loop(): + while not client.is_ready(): + await asyncio.sleep(5) + while True: + try: + await update_status() + except discord.HTTPException: + pass + await asyncio.sleep(300) + + +@module.launch_task +async def launch_status_update(client): + asyncio.create_task(_status_loop()) diff --git a/config/example-bot.conf b/config/example-bot.conf index 52226759..b2fc7a48 100644 --- a/config/example-bot.conf +++ b/config/example-bot.conf @@ -1,6 +1,7 @@ [DEFAULT] log_file = bot.log log_channel = +guild_log_channel = prefix = ! token =