From 7db1158dd715bda8512f2227585ebcdcc79ca03f Mon Sep 17 00:00:00 2001 From: SnowyJaguar1034 <51423344+SnowyJaguar1034@users.noreply.github.com> Date: Sun, 23 May 2021 01:11:58 +0100 Subject: [PATCH 1/6] Added Help Command to KoalaBot.Py I added an embedded help command to the KoalaBot.py file. I added it here (for now) because I am still working on making it a paginator. I ran into an issue when installing DiscordUtils from https://pypi.org/project/DiscordUtils/ as my machine failed to install PyNacl several times which delayed the process of importing the pagination. As I was stuck fo a while with the pagination I started working on an Info.py cog which will be its own pr. --- cogs/KoalaBot.py | 221 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 cogs/KoalaBot.py diff --git a/cogs/KoalaBot.py b/cogs/KoalaBot.py new file mode 100644 index 00000000..d5ecaa5c --- /dev/null +++ b/cogs/KoalaBot.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python + +""" +Koala Bot Base Code +Run this to start the Bot + +Commented using reStructuredText (reST) +""" +__author__ = "Jack Draper, Kieran Allinson, Viraj Shah," \ + " Anan Venkatesh, Harry Nelson, Robert Slawik, Rurda Malik, Stefan Cooper" +__copyright__ = "Copyright (c) 2020 KoalaBot" +__credits__ = ["Jack Draper", "Kieran Allinson", "Viraj Shah", + "Anan Venkatesh", "Harry Nelson", "Robert Slawik", "Rurda Malik", "Stefan Cooper"] +__license__ = "MIT License" +__version__ = "0.0.3" +__maintainer__ = "Jack Draper, Kieran Allinson, Viraj Shah" +__email__ = "koalabotuk@gmail.com" +__status__ = "Development" # "Prototype", "Development", or "Production" + +# Futures + +# Built-in/Generic Imports +import os +import logging +from typing import Counter + +# Libs +import discord +from discord.ext import commands, menus +from dotenv import load_dotenv +from collections import OrderedDict, deque, Counter + +# Own modules +from utils.KoalaDBManager import KoalaDBManager as DBManager +from utils.KoalaUtils import error_embed + +# Constants +logging.basicConfig(filename='KoalaBot.log') +load_dotenv() +BOT_TOKEN = os.environ['DISCORD_TOKEN'] +BOT_OWNER = os.environ.get('BOT_OWNER') +DB_KEY = os.environ.get('SQLITE_KEY', "2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99") +COMMAND_PREFIX = "k!" +STREAMING_URL = "https://twitch.tv/jaydwee" +COGS_DIR = "cogs" +KOALA_PLUG = " koalabot.uk" # Added to every presence change, do not alter +TEST_USER = "TestUser#0001" # Test user for dpytest +TEST_BOT_USER = "FakeApp#0001" # Test bot user for dpytest +DATABASE_PATH = "Koala.db" +KOALA_GREEN = discord.Colour.from_rgb(0, 170, 110) +PERMISSION_ERROR_TEXT = "This guild does not have this extension enabled, go to http://koalabot.uk, " \ + "or use `k!help enableExt` to enable it" +KOALA_IMAGE_URL = "https://cdn.discordapp.com/attachments/737280260541907015/752024535985029240/discord1.png" + +# Help Command configuration +attributes = { + 'name': "help", + 'aliases': ["HELP", "helps", "HELPS", "hell", "HELL", "h", "H", "command", "COMMAND", "commands", "COMMANDS", "how", "HOW", "com", "COM", "c", "C", "Koala", "kola", "KOALA"], + 'cooldown': commands.Cooldown(1, 5.0, commands.BucketType.user) # Lets users run the help command once every 5 seconds to reduce spam +} +# During declaration +# help_object = commands.HelpCommand(command_attrs = attributes) # Needs the following to be added to the COMMAND_PREFIX sections: help_command = help_object + +# OR through attribute assignment +help_object = commands.MinimalHelpCommand() # HelpCommand +help_object.command_attrs = attributes + +# Variables +started = False +if discord.__version__ != "1.3.4": + logging.info("Intents Enabled") + intent = discord.Intents.default() + intent.members = True + intent.guilds = True + intent.messages = True + client = commands.Bot(command_prefix = COMMAND_PREFIX, intents=intent, help_command=help_object) +else: + logging.info("discord.py v1.3.4: Intents Disabled") + client = commands.Bot(command_prefix=COMMAND_PREFIX, help_command = help_object) +database_manager = DBManager(DATABASE_PATH, DB_KEY) +logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s') +logger = logging.getLogger('discord') +is_dpytest = False + +# pip3 install --no-binary :all: pynacl +# pip install DiscordUtils +class HelpCom(commands.MinimalHelpCommand): # HelpCommand + def get_command_signature(self, command): + """Method to return a commands name and signature""" + return '%s%s %s' % (self.clean_prefix, command.qualified_name, command.signature) + + async def send_bot_help(self, mapping): + embed = discord.Embed(title="Koala Bot Help Menu", url = "https://koalabot.uk/", description="Koala bot is a open source project developed by university students throughout the UK aiming to help grow University society's to new heights!", color = 0x00aa6e) + embed.add_field(name = "Extensions", value = "Koala bot has many amazing functions called extensions. This makes it easy to mange which features you want enabled at any one time. You can find all of the commands to mange the extensions below.", inline = False) + + for cog, commands in mapping.items(): + filtered = await self.filter_commands(commands, sort = True) + command_signatures = [self.get_command_signature(c) for c in filtered] + if command_signatures: + cog_name = getattr(cog, "qualified_name", "Core") + embed.add_field(name = cog_name, value = "\n".join(command_signatures), inline = False) + + channel = self.get_destination() + await channel.send(embed = embed) + + async def send_pages(self): + destination = self.get_destination() + for page in self.paginator.pages: + embed = discord.Embed(description = page) + await destination.send(embed = embed) + +client.help_command = HelpCom() + +"""@client.command(help = "Shows all bot's command usage in the server on a sorted list.", + aliases = ["br", "brrrr", "botranks", "botpos", "botposition", "botpositions"]) +async def botrank(ctx, bot: discord.Member): + pass""" + + + +def is_owner(ctx): + """ + A command used to check if the user of a command is the owner, or the testing bot + e.g. @commands.check(KoalaBot.is_owner) + :param ctx: The context of the message + :return: True if owner or test, False otherwise + """ + if is_dm_channel(ctx): + return False + elif BOT_OWNER is not None: + return ctx.author.id == int(BOT_OWNER) or is_dpytest + else: + return client.is_owner(ctx.author) or is_dpytest + + +def is_admin(ctx): + """ + A command used to check if the user of a command is the admin, or the testing bot + e.g. @commands.check(KoalaBot.is_admin) + :param ctx: The context of the message + :return: True if admin or test, False otherwise + """ + if is_dm_channel(ctx): + return False + else: + return ctx.author.guild_permissions.administrator or is_dpytest + + +def is_dm_channel(ctx): + return isinstance(ctx.channel, discord.channel.DMChannel) + + +def is_guild_channel(ctx): + return ctx.guild is not None + + +def load_all_cogs(): + """ + Loads all cogs in COGS_DIR into the client + """ + UNRELEASED = [] + + for filename in os.listdir(COGS_DIR): + if filename.endswith('.py') and filename not in UNRELEASED: + client.load_extension(COGS_DIR.replace("/", ".") + f'.{filename[:-3]}') + + +def get_channel_from_id(id): + return client.get_channel(id=id) + + +async def dm_group_message(members: [discord.Member], message: str): + """ + DMs members in a list of members + :param members: list of members to DM + :param message: The message to send to the group + :return: how many were dm'ed successfully. + """ + count = 0 + for member in members: + try: + await member.send(message) + count = count + 1 + except Exception: # In case of user dms being closed + pass + return count + + +def check_guild_has_ext(ctx, extension_id): + """ + A check for if a guild has a given koala extension + :param ctx: A discord context + :param extension_id: The koala extension ID + :return: True if has ext + """ + if is_dm_channel(ctx): + return False + if (not database_manager.extension_enabled(ctx.message.guild.id, extension_id)) and (not is_dpytest): + raise PermissionError(PERMISSION_ERROR_TEXT) + return True + + +@client.event +async def on_command_error(ctx, error): + if isinstance(error, commands.MissingRequiredArgument): + await ctx.send(embed=error_embed(description=error)) + elif isinstance(error, commands.CommandInvokeError): + await ctx.send(embed=error_embed(description=error.original)) + elif isinstance(error, commands.CommandOnCooldown): + await ctx.send(embed=error_embed(description=f"{ctx.author.mention}, this command is still on cooldown for " + f"{str(error.retry_after)}s.")) + else: + await ctx.send(embed=error_embed(description=error)) + + +if __name__ == "__main__": # pragma: no cover + os.system("title " + "KoalaBot") + database_manager.create_base_tables() + load_all_cogs() + # Starts bot using the given BOT_ID + client.run(BOT_TOKEN) From c9eae96eac8a38f8d7b79b25106ae5bc6bfb711c Mon Sep 17 00:00:00 2001 From: SnowyJaguar1034 <51423344+SnowyJaguar1034@users.noreply.github.com> Date: Sun, 23 May 2021 01:55:10 +0100 Subject: [PATCH 2/6] Unnecessary troubleshooting comments removed Just removed some comments I had added to help me work through the process of troubleshooting my pip setup --- KoalaBot.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/KoalaBot.py b/KoalaBot.py index bdb1171d..5d54407e 100644 --- a/KoalaBot.py +++ b/KoalaBot.py @@ -22,11 +22,14 @@ # Built-in/Generic Imports import os import logging +from typing import Counter # Libs import discord -from discord.ext import commands +import DiscordUtils +from discord.ext import commands, menus from dotenv import load_dotenv +from collections import OrderedDict, deque, Counter # Own modules from utils.KoalaDBManager import KoalaDBManager as DBManager @@ -49,6 +52,20 @@ PERMISSION_ERROR_TEXT = "This guild does not have this extension enabled, go to http://koalabot.uk, " \ "or use `k!help enableExt` to enable it" KOALA_IMAGE_URL = "https://cdn.discordapp.com/attachments/737280260541907015/752024535985029240/discord1.png" + +# Help Command configuration +attributes = { + 'name': "help", + 'aliases': ["HELP", "helps", "HELPS", "hell", "HELL", "h", "H", "command", "COMMAND", "commands", "COMMANDS", "how", "HOW", "com", "COM", "c", "C", "Koala", "kola", "KOALA"], + 'cooldown': commands.Cooldown(1, 5.0, commands.BucketType.user) # Lets users run the help command once every 5 seconds to reduce spam +} +# During declaration +# help_object = commands.HelpCommand(command_attrs = attributes) # Needs the following to be added to the COMMAND_PREFIX sections: help_command = help_object + +# OR through attribute assignment +help_object = commands.MinimalHelpCommand() # HelpCommand +help_object.command_attrs = attributes + # Variables started = False if discord.__version__ != "1.3.4": @@ -57,16 +74,63 @@ intent.members = True intent.guilds = True intent.messages = True - client = commands.Bot(command_prefix=COMMAND_PREFIX, intents=intent) + client = commands.Bot(command_prefix = COMMAND_PREFIX, intents=intent, help_command=help_object) else: logging.info("discord.py v1.3.4: Intents Disabled") - client = commands.Bot(command_prefix=COMMAND_PREFIX) + client = commands.Bot(command_prefix=COMMAND_PREFIX, help_command = help_object) database_manager = DBManager(DATABASE_PATH, DB_KEY) logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s') logger = logging.getLogger('discord') is_dpytest = False +class HelpCom(commands.MinimalHelpCommand): # HelpCommand + def get_command_signature(self, command): + """Method to return a commands name and signature""" + return '%s%s %s' % (self.clean_prefix, command.qualified_name, command.signature) + + async def send_bot_help(self, mapping): + embed = discord.Embed(title="Koala Bot Help Menu", url = "https://koalabot.uk/", description="Koala bot is a open source project developed by university students throughout the UK aiming to help grow University society's to new heights!", color = 0x00aa6e) + embed.add_field(name = "Extensions", value = "Koala bot has many amazing functions called extensions. This makes it easy to mange which features you want enabled at any one time. You can find all of the commands to mange the extensions below.", inline = False) + + for cog, commands in mapping.items(): + filtered = await self.filter_commands(commands, sort = True) + command_signatures = [self.get_command_signature(c) for c in filtered] + if command_signatures: + cog_name = getattr(cog, "qualified_name", "Core") + embed.add_field(name = cog_name, value = "\n".join(command_signatures), inline = False) + + channel = self.get_destination() + await channel.send(embed = embed) + + async def send_pages(self): + destination = self.get_destination() + for page in self.paginator.pages: + embed = discord.Embed(description = page) + await destination.send(embed = embed) + @client.command() + async def paginate(ctx): + embed1 = discord.Embed(color=ctx.author.color).add_field(name="Example", value="Page 1") + embed2 = discord.Embed(color=ctx.author.color).add_field(name="Example", value="Page 2") + embed3 = discord.Embed(color=ctx.author.color).add_field(name="Example", value="Page 3") + paginator = DiscordUtils.Pagination.CustomEmbedPaginator(ctx) + paginator.add_reaction('⏮️', "first") + paginator.add_reaction('⏪', "back") + paginator.add_reaction('🔐', "lock") + paginator.add_reaction('⏩', "next") + paginator.add_reaction('⏭️', "last") + embeds = [embed1, embed2, embed3] + await paginator.run(embeds) + +client.help_command = HelpCom() + +"""@client.command(help = "Shows all bot's command usage in the server on a sorted list.", + aliases = ["br", "brrrr", "botranks", "botpos", "botposition", "botpositions"]) +async def botrank(ctx, bot: discord.Member): + pass""" + + + def is_owner(ctx): """ A command used to check if the user of a command is the owner, or the testing bot From 4440ad6a6087d4638f1ebc131f5e4aa1cb5adccf Mon Sep 17 00:00:00 2001 From: SnowyJaguar1034 <51423344+SnowyJaguar1034@users.noreply.github.com> Date: Sun, 23 May 2021 02:00:53 +0100 Subject: [PATCH 3/6] Added KoalaBot.py to cogs by accident, removing it --- cogs/KoalaBot.py | 221 ----------------------------------------------- 1 file changed, 221 deletions(-) delete mode 100644 cogs/KoalaBot.py diff --git a/cogs/KoalaBot.py b/cogs/KoalaBot.py deleted file mode 100644 index d5ecaa5c..00000000 --- a/cogs/KoalaBot.py +++ /dev/null @@ -1,221 +0,0 @@ -#!/usr/bin/env python - -""" -Koala Bot Base Code -Run this to start the Bot - -Commented using reStructuredText (reST) -""" -__author__ = "Jack Draper, Kieran Allinson, Viraj Shah," \ - " Anan Venkatesh, Harry Nelson, Robert Slawik, Rurda Malik, Stefan Cooper" -__copyright__ = "Copyright (c) 2020 KoalaBot" -__credits__ = ["Jack Draper", "Kieran Allinson", "Viraj Shah", - "Anan Venkatesh", "Harry Nelson", "Robert Slawik", "Rurda Malik", "Stefan Cooper"] -__license__ = "MIT License" -__version__ = "0.0.3" -__maintainer__ = "Jack Draper, Kieran Allinson, Viraj Shah" -__email__ = "koalabotuk@gmail.com" -__status__ = "Development" # "Prototype", "Development", or "Production" - -# Futures - -# Built-in/Generic Imports -import os -import logging -from typing import Counter - -# Libs -import discord -from discord.ext import commands, menus -from dotenv import load_dotenv -from collections import OrderedDict, deque, Counter - -# Own modules -from utils.KoalaDBManager import KoalaDBManager as DBManager -from utils.KoalaUtils import error_embed - -# Constants -logging.basicConfig(filename='KoalaBot.log') -load_dotenv() -BOT_TOKEN = os.environ['DISCORD_TOKEN'] -BOT_OWNER = os.environ.get('BOT_OWNER') -DB_KEY = os.environ.get('SQLITE_KEY', "2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99") -COMMAND_PREFIX = "k!" -STREAMING_URL = "https://twitch.tv/jaydwee" -COGS_DIR = "cogs" -KOALA_PLUG = " koalabot.uk" # Added to every presence change, do not alter -TEST_USER = "TestUser#0001" # Test user for dpytest -TEST_BOT_USER = "FakeApp#0001" # Test bot user for dpytest -DATABASE_PATH = "Koala.db" -KOALA_GREEN = discord.Colour.from_rgb(0, 170, 110) -PERMISSION_ERROR_TEXT = "This guild does not have this extension enabled, go to http://koalabot.uk, " \ - "or use `k!help enableExt` to enable it" -KOALA_IMAGE_URL = "https://cdn.discordapp.com/attachments/737280260541907015/752024535985029240/discord1.png" - -# Help Command configuration -attributes = { - 'name': "help", - 'aliases': ["HELP", "helps", "HELPS", "hell", "HELL", "h", "H", "command", "COMMAND", "commands", "COMMANDS", "how", "HOW", "com", "COM", "c", "C", "Koala", "kola", "KOALA"], - 'cooldown': commands.Cooldown(1, 5.0, commands.BucketType.user) # Lets users run the help command once every 5 seconds to reduce spam -} -# During declaration -# help_object = commands.HelpCommand(command_attrs = attributes) # Needs the following to be added to the COMMAND_PREFIX sections: help_command = help_object - -# OR through attribute assignment -help_object = commands.MinimalHelpCommand() # HelpCommand -help_object.command_attrs = attributes - -# Variables -started = False -if discord.__version__ != "1.3.4": - logging.info("Intents Enabled") - intent = discord.Intents.default() - intent.members = True - intent.guilds = True - intent.messages = True - client = commands.Bot(command_prefix = COMMAND_PREFIX, intents=intent, help_command=help_object) -else: - logging.info("discord.py v1.3.4: Intents Disabled") - client = commands.Bot(command_prefix=COMMAND_PREFIX, help_command = help_object) -database_manager = DBManager(DATABASE_PATH, DB_KEY) -logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s') -logger = logging.getLogger('discord') -is_dpytest = False - -# pip3 install --no-binary :all: pynacl -# pip install DiscordUtils -class HelpCom(commands.MinimalHelpCommand): # HelpCommand - def get_command_signature(self, command): - """Method to return a commands name and signature""" - return '%s%s %s' % (self.clean_prefix, command.qualified_name, command.signature) - - async def send_bot_help(self, mapping): - embed = discord.Embed(title="Koala Bot Help Menu", url = "https://koalabot.uk/", description="Koala bot is a open source project developed by university students throughout the UK aiming to help grow University society's to new heights!", color = 0x00aa6e) - embed.add_field(name = "Extensions", value = "Koala bot has many amazing functions called extensions. This makes it easy to mange which features you want enabled at any one time. You can find all of the commands to mange the extensions below.", inline = False) - - for cog, commands in mapping.items(): - filtered = await self.filter_commands(commands, sort = True) - command_signatures = [self.get_command_signature(c) for c in filtered] - if command_signatures: - cog_name = getattr(cog, "qualified_name", "Core") - embed.add_field(name = cog_name, value = "\n".join(command_signatures), inline = False) - - channel = self.get_destination() - await channel.send(embed = embed) - - async def send_pages(self): - destination = self.get_destination() - for page in self.paginator.pages: - embed = discord.Embed(description = page) - await destination.send(embed = embed) - -client.help_command = HelpCom() - -"""@client.command(help = "Shows all bot's command usage in the server on a sorted list.", - aliases = ["br", "brrrr", "botranks", "botpos", "botposition", "botpositions"]) -async def botrank(ctx, bot: discord.Member): - pass""" - - - -def is_owner(ctx): - """ - A command used to check if the user of a command is the owner, or the testing bot - e.g. @commands.check(KoalaBot.is_owner) - :param ctx: The context of the message - :return: True if owner or test, False otherwise - """ - if is_dm_channel(ctx): - return False - elif BOT_OWNER is not None: - return ctx.author.id == int(BOT_OWNER) or is_dpytest - else: - return client.is_owner(ctx.author) or is_dpytest - - -def is_admin(ctx): - """ - A command used to check if the user of a command is the admin, or the testing bot - e.g. @commands.check(KoalaBot.is_admin) - :param ctx: The context of the message - :return: True if admin or test, False otherwise - """ - if is_dm_channel(ctx): - return False - else: - return ctx.author.guild_permissions.administrator or is_dpytest - - -def is_dm_channel(ctx): - return isinstance(ctx.channel, discord.channel.DMChannel) - - -def is_guild_channel(ctx): - return ctx.guild is not None - - -def load_all_cogs(): - """ - Loads all cogs in COGS_DIR into the client - """ - UNRELEASED = [] - - for filename in os.listdir(COGS_DIR): - if filename.endswith('.py') and filename not in UNRELEASED: - client.load_extension(COGS_DIR.replace("/", ".") + f'.{filename[:-3]}') - - -def get_channel_from_id(id): - return client.get_channel(id=id) - - -async def dm_group_message(members: [discord.Member], message: str): - """ - DMs members in a list of members - :param members: list of members to DM - :param message: The message to send to the group - :return: how many were dm'ed successfully. - """ - count = 0 - for member in members: - try: - await member.send(message) - count = count + 1 - except Exception: # In case of user dms being closed - pass - return count - - -def check_guild_has_ext(ctx, extension_id): - """ - A check for if a guild has a given koala extension - :param ctx: A discord context - :param extension_id: The koala extension ID - :return: True if has ext - """ - if is_dm_channel(ctx): - return False - if (not database_manager.extension_enabled(ctx.message.guild.id, extension_id)) and (not is_dpytest): - raise PermissionError(PERMISSION_ERROR_TEXT) - return True - - -@client.event -async def on_command_error(ctx, error): - if isinstance(error, commands.MissingRequiredArgument): - await ctx.send(embed=error_embed(description=error)) - elif isinstance(error, commands.CommandInvokeError): - await ctx.send(embed=error_embed(description=error.original)) - elif isinstance(error, commands.CommandOnCooldown): - await ctx.send(embed=error_embed(description=f"{ctx.author.mention}, this command is still on cooldown for " - f"{str(error.retry_after)}s.")) - else: - await ctx.send(embed=error_embed(description=error)) - - -if __name__ == "__main__": # pragma: no cover - os.system("title " + "KoalaBot") - database_manager.create_base_tables() - load_all_cogs() - # Starts bot using the given BOT_ID - client.run(BOT_TOKEN) From 0c5f3e5a5ace76dff17adb3893e3e57053b6d8bd Mon Sep 17 00:00:00 2001 From: SnowyJaguar1034 <51423344+SnowyJaguar1034@users.noreply.github.com> Date: Sun, 23 May 2021 02:01:41 +0100 Subject: [PATCH 4/6] Added Help Command to KoalaBot.Py I added an embedded help command to the KoalaBot.py file. I added it here (for now) because I am still working on making it a paginator. I ran into an issue when installing DiscordUtils from https://pypi.org/project/DiscordUtils/ as my machine failed to install PyNacl several times which delayed the process of importing the pagination. As I was stuck fo a while with the pagination I started working on an Info.py cog which will be its own pr. From 428e676f0c24276c7ad5d8a01cf34c4a80c3057c Mon Sep 17 00:00:00 2001 From: SnowyJaguar1034 <51423344+SnowyJaguar1034@users.noreply.github.com> Date: Sun, 23 May 2021 02:02:54 +0100 Subject: [PATCH 5/6] Added Help Command to KoalaBot.Py I added an embedded help command to the KoalaBot.py file. I added it here (for now) because I am still working on making it a paginator. I ran into an issue when installing DiscordUtils from https://pypi.org/project/DiscordUtils/ as my machine failed to install PyNacl several times which delayed the process of importing the pagination. As I was stuck fo a while with the pagination I started working on an Info.py cog which will be its own pr. From 840a5e30476492c60157687804a2445903279207 Mon Sep 17 00:00:00 2001 From: SnowyJaguar1034 <51423344+SnowyJaguar1034@users.noreply.github.com> Date: Sun, 23 May 2021 02:09:25 +0100 Subject: [PATCH 6/6] Added a Info.py cog This cog currently retrieves User Information, server Information, and User permissions (both server-wide and for specific channels). I am also going to be adding in role information and channel information. I might also throw in a stats command altho I'm unsure on that one. --- cogs/Info.py | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 cogs/Info.py diff --git a/cogs/Info.py b/cogs/Info.py new file mode 100644 index 00000000..316995c0 --- /dev/null +++ b/cogs/Info.py @@ -0,0 +1,184 @@ +# Discord-ext-menu is needed, it can be installed via python -m pip install -U git+https://github.com/Rapptz/discord-ext-menus +import discord, KoalaBot, os +from discord.ext import commands, menus +from utils import KoalaDBManager +from collections import OrderedDict, deque, Counter +""" +KoalaBot Info Commands +Contains: userinfo, serverinfo, roleinfo and channelinfo +Author: SnowyJaguar#1034 +""" + +class Info(commands.Cog): + def __init__(self, client): + self.client = client + """ + Initialises local variables + :param bot: The bot client for this cog + """ + def perm_format(self, perm): + return perm.replace("_", " ").replace("guild", "server").title() + + @commands.command(aliases=["user-info", "userinfo", "memberinfo", "member-info"]) + async def whois(self, ctx, *, member : discord.Member=None): + guild = ctx.guild + member = member or ctx.author + key_perms = ["administrator", "manage_guild", "manage_roles", "manage_channels", "manage_messages", "manage_webhooks", "manage_nicknames", "manage_emojis", "kick_members", "mention_everyone"] + has_key = [perm for perm in key_perms if getattr(member.guild_permissions, perm)] + roles = member.roles[1:] + user = ctx.author + roles.reverse() + + if not roles: + + try: + embed = discord.Embed(colour = member.color, timestamp = ctx.message.created_at, description = member.mention) + embed = discord.Embed(title = f"{member.name}#{member.discriminator}", description = f"Status: **{member.status}**\n*{member.activity.name}*") + embed.set_author(name = f"{member.id}", icon_url = member.avatar_url) + embed.set_thumbnail(url = member.avatar_url) + embed.set_footer(text = f'{user.name}#{member.discriminator} | {user.id}') + + embed.add_field(name = "Joined Server:", value = member.joined_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = False) + embed.add_field(name = "Avatar", value = f"[Link]({member.avatar_url_as(static_format='png')})", inline = True) + embed.add_field(name = "Joined Discord:", value = member.created_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = f'Roles: 0', value = "None", inline = False) + + await ctx.send(embed = embed) + + except: + embed = discord.Embed(colour=member.color, timestamp=ctx.message.created_at, description=member.mention) + embed = discord.Embed(title = f"{member.name}#{member.discriminator}", description = f"Status: **{member.status}**") + embed.set_author(name = f"{member.id}", icon_url = member.avatar_url) + embed.set_thumbnail(url = member.avatar_url) + embed.set_footer(text = f'{user.name}#{member.discriminator} | {user.id}') + + embed.add_field(name = "Joined Server:", value = member.joined_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = "Avatar", value = f"[Link]({member.avatar_url_as(static_format='png')})", inline = True) + embed.add_field(name="Joined Discord:", value = member.created_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = f'Roles: 0', value = "None", inline = False) + await ctx.send(embed = embed) + return + if not has_key: + try: + embed = discord.Embed(colour = member.color, timestamp = ctx.message.created_at, description = member.mention) + embed = discord.Embed(title = f"{member.name}#{member.discriminator}", description = f"Status: **{member.status}**\n*{member.activity.name}*") + embed.set_author(name = f"{member.id}", icon_url = member.avatar_url) + embed.set_thumbnail(url = member.avatar_url) + embed.set_footer(text = f'{user.name}#{member.discriminator} | {user.id}') + + embed.add_field(name = "Joined Server:", value = member.joined_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = False) + embed.add_field(name = "Avatar", value = f"[Link]({member.avatar_url_as(static_format='png')})", inline = True) + embed.add_field(name = "Joined Discord:", value = member.created_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = f'Roles: {len(roles)}', value = " ".join([role.mention for role in roles]), inline = False) + await ctx.send(embed = embed) + + except: + + embed = discord.Embed(colour=member.color, timestamp=ctx.message.created_at, description=member.mention) + embed = discord.Embed(title = f"{member.name}#{member.discriminator}", description = f"Status: **{member.status}**") + embed.set_author(name = f"{member.id}", icon_url = member.avatar_url) + embed.set_thumbnail(url = member.avatar_url) + embed.set_footer(text = f'{user.name}#{member.discriminator} | {user.id}') + + embed.add_field(name = "Joined Server:", value = member.joined_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = "Avatar", value = f"[Link]({member.avatar_url_as(static_format='png')})", inline = True) + embed.add_field(name = "Joined Discord:", value=member.created_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = "Avatar", value=f"[Link]({member.avatar_url_as(static_format='png')})") + embed.add_field(name = f'Roles: {len(roles)}', value = " ".join([role.mention for role in roles]), inline = False) + await ctx.send(embed = embed) + return + if roles: + try: + embed = discord.Embed(colour = member.color, timestamp = ctx.message.created_at, description = member.mention) + embed = discord.Embed(title = f"{member.name}#{member.discriminator}", description = f"Status: **{member.status}**\n*{member.activity.name}*") + embed.set_author(name = f"{member.id}", icon_url = member.avatar_url) + embed.set_thumbnail(url = member.avatar_url) + embed.set_footer(text = f'{user.name}#{member.discriminator} | {user.id}') + + embed.add_field(name = "Joined Server:", value = member.joined_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = "Avatar", value = f"[Link]({member.avatar_url_as(static_format='png')})", inline = True) + embed.add_field(name = "Joined Discord:", value = member.created_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = f'Roles: {len(roles)}', value = " ".join([role.mention for role in roles]), inline = False) + embed.add_field(name = f'Core permissions', value = ", ".join(has_key).replace("_"," ").title(), inline = False) + await ctx.send(embed = embed) + + except: + embed = discord.Embed(colour = member.color, timestamp = ctx.message.created_at, description = member.mention) + embed = discord.Embed(title = f"{member.name}#{member.discriminator}", description = f"Status: **{member.status}**", color = 0x00aa6e) + embed.set_author(name = f"{member.id}", icon_url = member.avatar_url) + embed.set_thumbnail(url = member.avatar_url) + embed.set_footer(text = f'{user.name}#{user.discriminator} | {user.id}') + + embed.add_field(name = "Joined Server:", value = member.joined_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = "Avatar", value = f"[Link]({member.avatar_url_as(static_format='png')})") + embed.add_field(name = "Joined Discord:", value = member.created_at.strftime("%a, %b %w, %Y %I:%M %p"), inline = True) + embed.add_field(name = f'Roles: {len(roles)}', value = " ".join([role.mention for role in roles]), inline = False) + embed.add_field(name = f'Core permissions', value = ", ".join(has_key).replace("_"," ").title(), inline = False) + await ctx.send(embed = embed) + return + + @whois.error + async def whois_error(self, ctx, error): + if isinstance(error, commands.MemberNotFound): + embed = discord.Embed(description = f"<:error_1:840895769207898112> Couldn't find that user ", color = discord.Color.red()) + await ctx.send(embed = embed) + else: + print(error) + + @commands.command(aliases=["guildinfo", "serverstats", "guildstats", "server-info", "guild-info", "server-stats", "guild-stats"]) + async def serverinfo(self, ctx): + guild = ctx.guild + emoji_stats = Counter() + for emoji in guild.emojis: + if emoji.animated: + emoji_stats['animated'] += 1 + emoji_stats['animated_disabled'] += not emoji.available + else: + emoji_stats['regular'] += 1 + emoji_stats['disabled'] += not emoji.available + + fmt = f'Regular: {emoji_stats["regular"]}/{guild.emoji_limit} | Animated: {emoji_stats["animated"]}/{guild.emoji_limit}'\ + + if emoji_stats['disabled'] or emoji_stats['animated_disabled']: + fmt = f'{fmt}Disabled: {emoji_stats["disabled"]} regular, {emoji_stats["animated_disabled"]} animated\n' + + fmt = f'{fmt} | Total Emojis: {len(guild.emojis)}/{guild.emoji_limit*2}' + + embed = discord.Embed(title = f"{guild.name}", description = f"Server created on {guild.created_at.strftime('%a, %b %w, %Y %I:%M %p')}", color = 0x00aa6e) + embed.set_author(name = f"{guild.id}", icon_url = guild.icon_url) + embed.set_thumbnail(url = guild.icon_url) + # Cluster related Information for if/when the bot gets clustered. + #if ctx.guild: + #embed.set_footer(text = f"Cluster: {self.cluster} | Shard: {ctx.guild.shard_id + 1}") + #else: + #embed.set_footer(text = f"Cluster: {self.cluster} | Shard: {self.shard_count}") + embed.add_field(name = "Owner", value = f"{guild.owner.name}#{guild.owner.discriminator}" if guild.owner_id else "Unknown") + embed.add_field(name = "Icon", value = f"[Link]({guild.icon_url_as(static_format='png')})" if guild.icon else "*Not set*") + embed.add_field(name = "Region", value = guild.region.name.title()) + embed.add_field(name = "\nEmotes", value = fmt, inline = False) + embed.add_field(name = "Members", value = guild.member_count, inline = True) + embed.add_field(name = "Channels", value = len(guild.channels), inline = True) + embed.add_field(name = "Roles", value = len(guild.roles), inline = True) + embed.add_field(name = "Server Boosts", value = (guild.premium_subscription_count), inline = True) + embed.add_field(name = "Server Boost Level", value = (guild.premium_tier), inline = True) + await ctx.send(embed = embed) + + @commands.command(description = "Show a member's permission in a channel when specified.", usage = "permissions [channel]", aliases = ["perms"]) + async def permissions(self, ctx, member: discord.Member = None, channel: discord.TextChannel = None): + channel = channel or ctx.channel + if member is None: + member = ctx.author + permissions = channel.permissions_for(member) + embed = discord.Embed(title = "Permission Information", colour = 0x00aa6e) + embed.set_author(name = f"{member.name}#{member.discriminator}", icon_url = member.avatar_url) + embed.add_field(name = "Allowed", value = ", ".join([self.perm_format(name) for name, value in permissions if value]), inline = False) + embed.add_field(name = "Denied", value = ", ".join([self.perm_format(name) for name, value in permissions if not value]), inline = False) + await ctx.send(embed = embed) + +def setup(bot: KoalaBot) -> None: + """ + Load this cog to the KoalaBot. + :param bot: the bot client for KoalaBot + """ + bot.add_cog(Info(bot)) + print("Info is ready") \ No newline at end of file