From adb3efa746a73dfe191878a6ca491679f8318fff Mon Sep 17 00:00:00 2001 From: aikaterna Date: Sat, 8 Sep 2018 12:54:00 -0700 Subject: [PATCH] [V2 Tools] Initial commit Well, this was at least 2 years in the making. Thanks to Sitryk who did the most work on this, and thanks to Axas for writing the original find/cmd_lookup command. --- tools/info.json | 9 + tools/tools.py | 813 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 822 insertions(+) create mode 100644 tools/info.json create mode 100644 tools/tools.py diff --git a/tools/info.json b/tools/info.json new file mode 100644 index 0000000..6fd92e9 --- /dev/null +++ b/tools/info.json @@ -0,0 +1,9 @@ +{ + "AUTHOR" : "aikaterna, Sitryk, and Axas", + "INSTALL_MSG" : "Thanks for installing.", + "NAME" : "tools", + "SHORT" : "A collection of tools for mods.", + "DESCRIPTION" : "A collection of channel, user, and server tools for mods.", + "REQUIREMENTS": ["tabulate"], + "TAGS": ["tools"] +} diff --git a/tools/tools.py b/tools/tools.py new file mode 100644 index 0000000..c4cbb59 --- /dev/null +++ b/tools/tools.py @@ -0,0 +1,813 @@ +# Most of these tools are thanks to Sitryk. +# Credit for the findcog/cmd_lookup command belongs to Axas, thanks for the inspiration for +# the findcog command in Red v3. + +from discord.ext import commands +from .utils.chat_formatting import pagify, box, escape_mass_mentions +from .utils.dataIO import dataIO +from .utils import checks +from __main__ import send_cmd_help +from tabulate import tabulate +import discord +import glob +import os +import datetime +import asyncio +import discord +import random +import inspect + +ini = "```ini\n{0}\n```" + + +class Tools: + """Mod and Admin tools.""" + + def __init__(self, bot): + self.bot = bot + + @checks.mod_or_permissions(manage_messages=True) + @commands.group(pass_context=True, no_pm=True) + async def access(self, ctx): + """Check channel access.""" + if ctx.invoked_subcommand is None: + await send_cmd_help(ctx) + return + + @checks.mod_or_permissions(manage_messages=True) + @access.command(pass_context=True) + async def compare(self, ctx, user: discord.User, server: discord.Server = None): + """Compare channel access with [user]""" + author = ctx.message.author + if user is None: + return + if server is None: + server = ctx.message.server + + text_channels = [c for c in server.channels if str(c.type) == "text"] + voice_channels = [c for c in server.channels if str(c.type) == "voice"] + + author_text_channels = [ + c.name for c in text_channels if c.permissions_for(author).read_messages is True + ] + author_voice_channels = [ + c.name for c in voice_channels if c.permissions_for(author).connect is True + ] + + user_text_channels = [ + c.name for c in text_channels if c.permissions_for(user).read_messages is True + ] + user_voice_channels = [ + c.name for c in voice_channels if c.permissions_for(user).connect is True + ] + + author_only_t = set(author_text_channels) - set( + user_text_channels + ) # text channels only the author has access to + author_only_v = set(author_voice_channels) - set( + user_voice_channels + ) # voice channels only the author has access to + + user_only_t = set(user_text_channels) - set( + author_text_channels + ) # text channels only the user has access to + user_only_v = set(user_voice_channels) - set( + author_voice_channels + ) # voice channels only the user has access to + + common_t = list( + set(text_channels) - author_only_t - user_only_t + ) # text channels that author and user have in common + common_v = list( + set(voice_channels) - author_only_v - user_only_v + ) # voice channels that author and user have in common + + msg = "```ini\n" + msg += "{} [TEXT CHANNELS IN COMMON]:\n\n{}\n\n".format( + len(common_t), ", ".join([c.name for c in common_t]) + ) + msg += "{} [TEXT CHANNELS {} HAS ACCESS TO]:\n\n{}\n\n".format( + len(user_only_t), user.name.upper(), ", ".join(list(user_only_t)) + ) + msg += "{} [TEXT CHANNELS YOU HAVE ACCESS TO]:\n\n{}\n\n".format( + len(author_only_t), ", ".join(list(author_only_t)) + ) + msg += "{} [VOICE CHANNELS IN COMMON]:\n\n{}\n\n".format( + len(common_v), ", ".join([c.name for c in common_v]) + ) + msg += "{} [VOICE CHANNELS {} HAS ACCESS TO]:\n\n{}\n\n".format( + len(user_only_v), user.name.upper(), ", ".join(list(user_only_v)) + ) + msg += "{} [VOICE CHANNELS YOU HAVE ACCESS TO]:\n\n{}\n\n".format( + len(author_only_v), ", ".join(list(author_only_v)) + ) + msg += "```" + await self.bot.say(msg) + + @checks.mod_or_permissions(manage_messages=True) + @access.command(pass_context=True) + async def text(self, ctx, user: discord.Member = None, server: discord.Server = None): + """Fetch which text channels you have access to.""" + author = ctx.message.author + if server is None: + server = ctx.message.server + if user is None: + user = author + + can_access = [ + c.name + for c in server.channels + if c.permissions_for(user).read_messages == True and str(c.type) == "text" + ] + text_channels = [c.name for c in server.channels if str(c.type) == "text"] + + prefix = "You have" if user.id == author.id else user.name + " has" + msg = "```ini\n[{} access to {} out of {} text channels]\n\n".format( + prefix, len(can_access), len(text_channels) + ) + + msg += "[ACCESS]:\n{}\n\n".format(", ".join(can_access)) + msg += "[NO ACCESS]:\n{}\n```".format( + ", ".join(list(set(text_channels) - set(can_access))) + ) + await self.bot.say(msg) + + @checks.mod_or_permissions(manage_messages=True) + @access.command(pass_context=True) + async def voice(self, ctx, user: discord.Member = None, server: discord.Server = None): + """Fetch which voice channels you have access to.""" + author = ctx.message.author + if server is None: + server = ctx.message.server + if user is None: + user = author + + can_access = [ + c.name + for c in server.channels + if c.permissions_for(user).connect is True and str(c.type) == "voice" + ] + voice_channels = [c.name for c in server.channels if str(c.type) == "voice"] + + prefix = "You have" if user.id == author.id else user.name + " has" + msg = "```ini\n[{} access to {} out of {} voice channels]\n\n".format( + prefix, len(can_access), len(voice_channels) + ) + + msg += "[ACCESS]:\n{}\n\n".format(", ".join(can_access)) + msg += "[NO ACCESS]:\n{}\n```".format( + ", ".join(list(set(voice_channels) - set(can_access))) + ) + await self.bot.say(msg) + + @commands.command(pass_context=True) + @checks.admin_or_permissions(manage_server=True) + async def banlist(self, ctx): + """Displays the server's banlist.""" + try: + banlist = await self.bot.get_bans(ctx.message.server) + except discord.errors.Forbidden: + await self.bot.say("I do not have the `Ban Members` permission.") + return + bancount = len(banlist) + if bancount == 0: + banlist = "No users are banned from this server." + else: + banlist = ", ".join(map(str, banlist)) + + for page in pagify(banlist, ["\n"], shorten_by=13, page_length=2000): + await self.bot.say(box(page, "ini")) + + @commands.command(pass_context=True, no_pm=True) + async def cid(self, ctx, channel: discord.Channel = None): + """Shows the channel ID.""" + if not channel: + channel = ctx.message.channel + await self.bot.say("**#{0.name} ID:** {0.id}".format(channel)) + + @commands.command(pass_context=True) + async def cinfo(self, ctx, channel: discord.Channel = None): + """Shows channel information. Defaults to current text channel.""" + yesno = {True: "Yes", False: "No"} + if not channel: + channel = ctx.message.channel + + load = "```\nLoading channel info...```" + waiting = await self.bot.say(load) + + try: + caller = inspect.currentframe().f_back.f_code.co_name + except: + pass + + data = "```ini\n" + if caller == "whatis": + data == "[Server]: {}\n".format(channel.server.name) + data += "[Name]: {}\n".format(escape_mass_mentions(str(channel))) + data += "[ID]: {}\n".format(channel.id) + data += "[Default]: {}\n".format(yesno[channel.is_default]) + data += "[Private]: {}\n".format(yesno[channel.is_private]) + if str(channel.type) == "text" and channel.topic != "": + data += "[Topic]: {}\n".format(channel.topic) + data += "[Position]: {}\n".format(channel.position) + data += "[Created]: {} ago\n".format(self._dynamic_time(channel.created_at)) + data += "[Type]: {}\n".format(channel.type) + if str(channel.type) == "voice": + data += "[Users]: {}\n".format(len(channel.voice_members)) + data += "[User limit]: {}\n".format(channel.user_limit) + data += "[Bitrate]: {}\n".format(channel.bitrate) + data += "```" + await asyncio.sleep(2) + await self.bot.edit_message(waiting, data) + + @commands.command(pass_context=True) + @checks.is_owner() + async def ecogs(self, ctx): + """Lists status of installed cogs""" + owner_cog = self.bot.get_cog("Owner") + total_cogs = owner_cog._list_cogs() + loaded = [c.__module__.split(".")[1] for c in self.bot.cogs.values()] + unloaded = [c.split(".")[1] for c in total_cogs if c.split(".")[1] not in loaded] + if not unloaded: + unloaded = ["None"] + + items = { + 0: { + "cogs": sorted(loaded), + "msg": "**{} loaded:**\n".format(len(loaded)), + "colour": discord.Colour.dark_green(), + }, + 1: { + "cogs": sorted(unloaded), + "msg": "**{} unloaded:**\n".format(len(unloaded)), + "colour": discord.Colour.dark_red(), + }, + } + for index, em in enumerate(items): + e = discord.Embed( + description=items[index]["msg"] + ", ".join(items[index]["cogs"]), + colour=items[index]["colour"], + ) + await self.bot.say(embed=e) + + @commands.command(pass_context=True) + async def eid(self, ctx, emoji): + """Get an id for a custom emoji.""" + if emoji[0] != "<": + await self.bot.say( + "I could not an ID for this emoji, this may be because it is not a custom emoji." + ) + return + id = emoji.split(":")[2][:-1] + await self.bot.say(id) + + @checks.is_owner() + @commands.command(aliases=["find", "cmd_lookup"]) + async def findcog(self, command: str): + """Cog search by command. + This is only applicable for loaded cogs that were installed through [p]cog install.""" + try: + cog_name = self.bot.get_cog(self.bot.get_command(command).cog_name).__module__[5:] + except: + await self.bot.say( + "Either that command doesn't exist, or the cog this command belongs to wasn't added through the downloader cog." + ) + return + repos = dataIO.load_json("data/downloader/repos.json") + cog_path = ( + lambda x: "\n".join( + [ + filename + for filename in glob.iglob("data/downloader/**/*.py", recursive=True) + if "{}.py".format(x) == filename[((len("{}.py".format(x))) * -1) :] + ] + ) + )(cog_name) + if not cog_path: + await self.bot.say("This is a command that's in a cog that's not published in a repo.") + return + if os.name == "nt": + repo = cog_path.split(os.sep)[1] + else: + repo = cog_path.split(os.sep)[2] + if "url" not in repos[repo]: + with open("data/downloader/" + repo + "/.git/config", "r") as f: + url = re.findall(r"(http(s)?:\/\/[a-zA-Z0-9\:\.\-\_\/\?\=\%]*)", f.read())[0][0] + else: + url = repos[repo]["url"] + await self.bot.say( + box( + "Command name: {}\nMade by: {}\nRepo: {}\nCog Name: {}.py".format( + command, url.split("/")[3], url, cog_name + ) + ) + ) + + @checks.admin_or_permissions(manage_roles=True) + @commands.command(pass_context=True) + async def inrole(self, ctx, *, rolename): + """Check members in the role specified.""" + await self.bot.send_typing(ctx.message.channel) + role = discord.utils.find( + lambda r: r.name.lower() == rolename.lower(), ctx.message.server.roles + ) + + if role is None: + roles = [] + for r in ctx.message.server.roles: + if rolename.lower() in r.name.lower(): + roles.append(r) + + if len(roles) == 1: + role = roles[0] + elif len(roles) < 1: + await self.bot.say("no roles found") + return + else: + msg = "**Roles found with** {} **in the name.**\n\n".format(rolename) + tbul8 = [] + for num, role in enumerate(roles): + tbul8.append([num + 1, role.name]) + m1 = await self.bot.say(msg + tabulate(tbul8, tablefmt="plain")) + response = await self.bot.wait_for_message( + author=ctx.message.author, channel=ctx.message.channel, timeout=25 + ) + if response is None: + await self.bot.delete_message(m1) + return + elif response.content.isdigit(): + await self.bot.delete_message(m1) + return + else: + response = int(response.content) + + if response not in range(0, len(roles) + 1): + await self.bot.delete_message(m1) + return + elif response == 0: + await self.bot.delete_message(m1) + return + else: + role = roles[response - 1] + + if ( + role is not None + and len([m for m in ctx.message.server.members if role in m.roles]) < 50 + ): + awaiter = await self.bot.say( + embed=discord.Embed(description="Getting member names...") + ) + await asyncio.sleep(2.5) + role_member = discord.Embed( + description="**{1} users found in the {0} role.**\n".format( + role.name, len([m for m in ctx.message.server.members if role in m.roles]) + ) + ) + role_users = [m.display_name for m in ctx.message.server.members if role in m.roles] + if not role_users: + role_member.add_field(name="Users", value="None.") + else: + role_member.add_field(name="Users", value="\n".join(role_users)) + await self.bot.edit_message(awaiter, embed=role_member) + + elif len([m for m in ctx.message.server.members if role in m.roles]) > 50: + awaiter = await self.bot.say( + embed=discord.Embed(description="Getting member names...") + ) + await asyncio.sleep(2.5) + await self.bot.edit_message( + awaiter, + embed=discord.Embed( + description="List is too long for **{0}** role, **{1}** members found.\n".format( + role.name, len([m.mention for m in server.members if role in m.roles]) + ) + ), + ) + else: + embed = discord.Embed(description="Role was not found.") + await self.bot.edit_message(embed=embed) + + @commands.command(pass_context=True, no_pm=True) + @checks.mod_or_permissions(manage_messages=True) + async def newusers(self, ctx, count: int = 5, server: discord.Server = None): + """Lists the newest 5 members.""" + if server is None: + server = ctx.message.server + count = max(min(count, 25), 5) + members = sorted(server.members, key=lambda m: m.joined_at, reverse=True)[:count] + e = discord.Embed(title="New Members") + for member in members: + msg = "**Joined Server:** {} ago\n**Account created:** {} ago".format( + self._dynamic_time(member.joined_at), self._dynamic_time(member.created_at) + ) + e.add_field( + name="{0.display_name} (ID: {0.id})".format(member), value=msg, inline=False + ) + await self.bot.say(embed=e) + + @commands.command(pass_context=True, no_pm=True) + async def sid(self, ctx): + """Shows the server ID.""" + await self.bot.say("**{0.name} ID:** {0.id}".format(ctx.message.server)) + + @commands.command(pass_context=True) + @checks.mod_or_permissions(manage_messages=True) + async def userstats(self, ctx, this_server: bool = False): + """A small amount of user stats.""" + embeds = {} + if this_server: + members = set([x for x in ctx.message.server.members]) + else: + members = set([x for x in self.bot.get_all_members()]) + + items = { + 2: { + "users": len([e.name for e in members if e.status == discord.Status.idle]), + "colour": discord.Colour.orange(), + }, + 3: { + "users": len([e.name for e in members if e.status == discord.Status.dnd]), + "colour": discord.Colour.red(), + }, + 4: { + "users": len([e.name for e in members if e.status == discord.Status.offline]), + "colour": discord.Colour.dark_grey(), + }, + 1: { + "users": len([e.name for e in members if e.status == discord.Status.online]), + "colour": discord.Colour.green(), + }, + 0: { + "users": len([e.name for e in members if e.game and e.game.url]), + "colour": discord.Colour.dark_purple(), + }, + } + + for item in items: + embeds[item] = discord.Embed( + description="Users: {}".format(items[item]["users"]), colour=items[item]["colour"] + ) + for i, em in enumerate(embeds): + await self.bot.say(embed=embeds[i]) + + @commands.command(pass_context=True, no_pm=True) + async def sinfo(self, ctx, server: discord.Server = None): + """Shows server information.""" + if server is None: + server = ctx.message.server + online = str( + len( + [ + m.status + for m in server.members + if str(m.status) == "online" or str(m.status) == "idle" + ] + ) + ) + total_users = str(len(server.members)) + text_channels = [x for x in server.channels if str(x.type) == "text"] + voice_channels = [x for x in server.channels if str(x.type) == "voice"] + + load = "```\nLoading server info...```" + waiting = await self.bot.say(load) + + data = "```ini\n" + data += "[Name]: {}\n".format(server.name) + data += "[ID]: {}\n".format(server.id) + data += "[Region]: {}\n".format(server.region) + data += "[Owner]: {}\n".format(server.owner) + data += "[Users]: {}/{}\n".format(online, total_users) + data += "[Text]: {} channels\n".format(len(text_channels)) + data += "[Voice]: {} channels\n".format(len(voice_channels)) + data += "[Emojis]: {}\n".format(len(server.emojis)) + data += "[Roles]: {} \n".format(len(server.roles)) + data += "[Created]: {} ago\n```".format(self._dynamic_time(server.created_at)) + await asyncio.sleep(3) + await self.bot.edit_message(waiting, data) + + @commands.command(pass_context=True, no_pm=True) + @checks.mod_or_permissions(manage_messages=True) + async def perms(self, ctx, user: discord.Member = None): + """Fetch a specific user's permissions.""" + if user is None: + user = ctx.message.author + + perms = iter(ctx.message.channel.permissions_for(user)) + perms_we_have = "```diff\n" + perms_we_dont = "" + for x in perms: + if "True" in str(x): + perms_we_have += "+\t{0}\n".format(str(x).split("'")[1]) + else: + perms_we_dont += "-\t{0}\n".format(str(x).split("'")[1]) + await self.bot.say("{0}{1}```".format(perms_we_have, perms_we_dont)) + + @commands.command(pass_context=True) + async def rid(self, ctx, rolename): + """Shows the id of a role, use quotes on the role.""" + await self.bot.send_typing(ctx.message.channel) + if rolename is discord.Role: + role = rolename + else: + role = self._role_from_string(ctx.message.server, rolename) + if role is None: + return await self.bot.say(embed=discord.Embed(description="Cannot find role.")) + await self.bot.say( + embed=discord.Embed(description="**{}** ID: {}".format(rolename, role.id)) + ) + + @commands.command(pass_context=True) + async def rinfo(self, ctx, rolename): + """Shows role info, use quotes on the role.""" + server = ctx.message.server + colour = str(random.randint(0, 0xFFFFFF)) + colour = int(colour, 16) + await self.bot.send_typing(ctx.message.channel) + + try: + caller = inspect.currentframe().f_back.f_code.co_name + except: + pass + + if type(rolename) is not discord.Role: + role = discord.utils.find( + lambda r: r.name.lower() == rolename.lower(), ctx.message.server.roles + ) + else: + role = rolename + if role is None: + await self.bot.say("That role cannot be found.") + return + if role is not None: + perms = iter(role.permissions) + perms_we_have = "" + perms_we_dont = "" + for x in perms: + if "True" in str(x): + perms_we_have += "{0}\n".format(str(x).split("'")[1]) + else: + perms_we_dont += "{0}\n".format(str(x).split("'")[1]) + msg = discord.Embed(description="Gathering role stats...", colour=role.color) + if role.color is None: + role.color = discord.Colour(value=colour) + msg2 = await self.bot.say(embed=msg) + em = discord.Embed(colour=role.colour) + if caller == "whatis": + em.add_field(name="Server", value=role.server.name) + em.add_field(name="Role Name", value=role.name) + em.add_field(name="Created", value=self._dynamic_time(role.created_at)) + em.add_field( + name="Users in Role", + value=len([m for m in ctx.message.server.members if role in m.roles]), + ) + em.add_field(name="Id", value=role.id) + em.add_field(name="Color", value=role.color) + em.add_field(name="Position", value=role.position) + em.add_field(name="Valid Permissons", value="{}".format(perms_we_have)) + em.add_field(name="Invalid Permissons", value="{}".format(perms_we_dont)) + em.set_thumbnail(url=role.server.icon_url) + try: + await self.bot.edit_message(msg2, embed=em) + except discord.HTTPException: + perms_msg = "```diff\n" + role = discord.utils.find( + lambda r: r.name.lower() == rolename.lower(), ctx.message.server.roles + ) + if role is None: + await bot.say("That role cannot be found.") + return + if role is not None: + perms = iter(role.permissions) + perms_we_have2 = "" + perms_we_dont2 = "" + for x in perms: + if "True" in str(x): + perms_we_have2 += "+{0}\n".format(str(x).split("'")[1]) + else: + perms_we_dont2 += "-{0}\n".format(str(x).split("'")[1]) + await self.bot.say( + "{}Name: {}\nCreated: {}\nUsers in Role : {}\nId : {}\nColor : {}\nPosition : {}\nValid Perms : \n{}\nInvalid Perms : \n{}```".format( + perms_msg, + role.name, + self._dynamic_time(role.created_at), + len([m for m in server.members if role in m.roles]), + role.id, + role.color, + role.position, + perms_we_have2, + perms_we_dont2, + ) + ) + await self.bot.delete_message(msg2) + + @commands.command(pass_context=True, hidden=True) + @checks.mod_or_permissions(manage_messages=True) + async def sharedservers(self, ctx, user: discord.Member = None): + """Shows shared server info. Defaults to author.""" + author = ctx.message.author + server = ctx.message.server + if not user: + user = author + seen = len( + set( + [ + member.server.name + for member in self.bot.get_all_members() + if member.name == user.name + ] + ) + ) + sharedservers = str( + set( + [ + member.server.name + for member in self.bot.get_all_members() + if member.name == user.name + ] + ) + ) + for shared in sharedservers: + shared = "".strip("'").join(sharedservers).strip("'") + shared = shared.strip("{").strip("}") + + data = "[Servers]: {} shared\n".format(seen) + data += "[In Servers]: {}\n".format(shared) + + for page in pagify(data, ["\n"], shorten_by=13, page_length=2000): + await self.bot.say(box(page, "ini")) + + @commands.command(pass_context=True) + async def uinfo(self, ctx, user: discord.Member = None): + """Shows user information. Defaults to author.""" + if not user: + user = ctx.message.author + try: + caller = inspect.currentframe().f_back.f_code.co_name + except: + pass + roles = [x.name for x in user.roles if x.name != "@everyone"] + if not roles: + roles = ["None"] + seen = str( + len( + set( + [ + member.server.name + for member in self.bot.get_all_members() + if member.id == user.id + ] + ) + ) + ) + + load = "```\nLoading user info...```" + waiting = await self.bot.say(load) + + data = "```ini\n" + data += "[Name]: {}\n".format(escape_mass_mentions(str(user))) + data += "[Nickname]: {}\n".format(escape_mass_mentions(str(user.nick))) + data += "[ID]: {}\n".format(user.id) + data += "[Status]: {}\n".format(user.status) + data += "[Servers]: {} shared\n".format(seen) + if user.game is None: + pass + elif user.game.url is None: + data += "[Playing]: {}\n".format(escape_mass_mentions(str(user.game))) + else: + data += "[Streaming]: [{}]({})\n".format( + escape_mass_mentions(str(user.game)), escape_mass_mentions(user.game.url) + ) + passed = (ctx.message.timestamp - user.created_at).days + data += "[Created]: {} ago\n".format(self._dynamic_time(user.created_at)) + joined_at = self.fetch_joined_at(user, ctx.message.server) + if caller != "whatis": + data += "[Joined]: {} ago\n".format(self._dynamic_time(joined_at)) + data += "[Roles]: {}\n".format(", ".join(roles)) + data += "[In Voice]: {}\n".format(str(user.voice_channel)) + data += "[AFK]: {}\n".format(user.is_afk) + data += "```" + await asyncio.sleep(3) + await self.bot.edit_message(waiting, data) + + @commands.command(pass_context=True) + async def whatis(self, ctx, id): + """What is it?""" + server = ctx.message.server + channel = ctx.message.channel + author = ctx.message.author + + it_is = False + msg = False + + if server.id == id: + it_is = server + elif channel.id == id: + it_is = channel + elif author.id == id: + it_is = author + + if not it_is: + for server in self.bot.servers: + if server.id == id: + it_is = server + break + if not it_is: + for emoji in self.bot.get_all_emojis(): + if emoji.id == id: + it_is = emoji + break + if not it_is: + for server in self.bot.servers: + for role in server.roles: + if role.id == id: + it_is = role + break + if not it_is: + for member in self.bot.get_all_members(): + if member.id == id: + it_is = member + break + if not it_is: + for channel in self.bot.get_all_channels(): + if channel.id == id: + it_is = channel + break + + if not msg: + if type(it_is) == discord.Channel: + await ctx.invoke(self.cinfo, it_is) + elif type(it_is) == discord.Server: + await ctx.invoke(self.sinfo, it_is) + elif type(it_is) == discord.User or type(it_is) == discord.Member: + await ctx.invoke(self.uinfo, it_is) + elif type(it_is) == discord.Role: + await ctx.invoke(self.roleinfo, it_is) + elif type(it_is) == discord.Emoji: + await self.bot.say( + "<:{0.name}:{0.id}>\n```ini\n[NAME]: {0.name}\n[SERVER]: {0.server}\n[URL]: {0.url}```".format( + it_is + ) + ) + else: + await self.bot.say( + "I could not find anything for this ID, I do not support Message IDs" + ) + else: + await self.bot.say("```\nNothing found for this ID```") + + @staticmethod + def _dynamic_time(time): + date_join = datetime.datetime.strptime(str(time), "%Y-%m-%d %H:%M:%S.%f") + date_now = datetime.datetime.now(datetime.timezone.utc) + date_now = date_now.replace(tzinfo=None) + since_join = date_now - date_join + + m, s = divmod(int(since_join.total_seconds()), 60) + h, m = divmod(m, 60) + d, h = divmod(h, 24) + + if d > 0: + msg = "{0}d {1}h" + elif d == 0 and h > 0: + msg = "{1}h {2}m" + elif d == 0 and h == 0 and m > 0: + msg = "{2}m {3}s" + elif d == 0 and h == 0 and m == 0 and s > 0: + msg = "{3}s" + else: + msg = "" + return msg.format(d, h, m, s) + + def fetch_joined_at(self, user, server): + return user.joined_at + + def _role_from_string(self, server, rolename, roles=None): + if roles is None: + roles = server.roles + role = discord.utils.find(lambda r: r.name.lower() == rolename.lower(), roles) + return role + + +def setup(bot): + cmds = [ + "access", + "banlist", + "cid", + "cinfo", + "ecogs", + "eid", + "findcog", + "inrole", + "newusers", + "perms", + "rid", + "rinfo", + "sid", + "sinfo", + "uinfo", + "userstatst", + "whatis", + ] + for cmd in cmds: + bot.remove_command(cmd) + bot.add_cog(Tools(bot))