From fb673aa1845cb1d69b02f467fb309f68c92d59ed Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Wed, 2 Oct 2019 12:39:18 +0530 Subject: [PATCH 1/3] done working on source command.Did it as said in the issue.Also added the cog in __main__.py --- bot/__main__.py | 1 + bot/cogs/source.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 bot/cogs/source.py diff --git a/bot/__main__.py b/bot/__main__.py index f256937349..46270096c4 100644 --- a/bot/__main__.py +++ b/bot/__main__.py @@ -52,6 +52,7 @@ bot.load_extension("bot.cogs.verification") # Feature cogs +bot.load_extension("bot.cogs.source") bot.load_extension("bot.cogs.alias") bot.load_extension("bot.cogs.defcon") bot.load_extension("bot.cogs.eval") diff --git a/bot/cogs/source.py b/bot/cogs/source.py new file mode 100644 index 0000000000..ab23c6645c --- /dev/null +++ b/bot/cogs/source.py @@ -0,0 +1,65 @@ +import inspect +import logging + +import discord +from discord.ext import commands + +from bot import constants + + +logger = logging.getLogger(__name__) + + +class Source(commands.Cog): + """Send source code url for a specific command.""" + + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + + @commands.command(name="source") + async def command_source(self, ctx: commands.Context, command_name: str = None) -> None: + """View the source of a command.""" + if command_name is None: + return await ctx.send("> https://github.com/python-discord/bot") + + command = self.bot.get_command(command_name) + if command is None: + return await ctx.send("No such command found.") + + url = self.get_command_url(command) + + prefix = constants.Bot.prefix + + embed = discord.Embed(colour=discord.Colour.red()) + embed.title = "Command Source" + embed.description = f"**{command.name.capitalize()}**\n" + embed.description += f"`{prefix}{command.name}`\n\n {url}" + + await ctx.send(embed=embed) + + @staticmethod + def get_command_url(command: commands.Command) -> str: + """Make up the url for the source of the command.""" + # Get the source code + src_code_object = command.callback.__code__ + + # Get module name and replace . with / + module_name = command.callback.__module__ + module_name = module_name.replace(".", "/") + ".py" + + # Get line number and set last line number + lines_list, starting_line_no = inspect.getsourcelines(src_code_object) + lines = len(lines_list) + last_line_no = starting_line_no + lines - 1 + + # Make up the url and return + base_url = "https://github.com/python-discord/bot/tree/master/" + final_url = f"<{base_url}{module_name}#L{starting_line_no}-L{last_line_no}>" + + return final_url + + +def setup(bot: commands.Bot) -> None: + """Load the cog.""" + bot.add_cog(Source(bot)) + logger.info("Source Cog loaded.") From e30400f3c2eafc5b7622d894dbad54715c5795fa Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Thu, 3 Oct 2019 13:28:20 +0530 Subject: [PATCH 2/3] better url generation and also supports subcommands now. --- bot/cogs/source.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/bot/cogs/source.py b/bot/cogs/source.py index ab23c6645c..feffc35768 100644 --- a/bot/cogs/source.py +++ b/bot/cogs/source.py @@ -5,7 +5,7 @@ from discord.ext import commands from bot import constants - +from bot.decorators import in_channel logger = logging.getLogger(__name__) @@ -16,15 +16,23 @@ class Source(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot = bot + @in_channel(constants.Channels.bot) @commands.command(name="source") - async def command_source(self, ctx: commands.Context, command_name: str = None) -> None: + async def command_source(self, ctx: commands.Context, command_name: str = None, sub_command: str = None) -> None: """View the source of a command.""" if command_name is None: - return await ctx.send("> https://github.com/python-discord/bot") + await ctx.send("> https://github.com/python-discord/bot") + return + + if sub_command: + await ctx.send(sub_command) + command = self.bot.get_command(f"{command_name} {sub_command}") + else: + command = self.bot.get_command(command_name) - command = self.bot.get_command(command_name) if command is None: - return await ctx.send("No such command found.") + await ctx.send("No such command found.") + return url = self.get_command_url(command) @@ -42,19 +50,26 @@ def get_command_url(command: commands.Command) -> str: """Make up the url for the source of the command.""" # Get the source code src_code_object = command.callback.__code__ - - # Get module name and replace . with / - module_name = command.callback.__module__ - module_name = module_name.replace(".", "/") + ".py" + file_path = src_code_object.co_filename[5:] # Get line number and set last line number lines_list, starting_line_no = inspect.getsourcelines(src_code_object) lines = len(lines_list) + + # Get module + module_name = command.callback.__module__ + module_name = module_name.replace(".", "/") + ".py" + last_line_no = starting_line_no + lines - 1 # Make up the url and return base_url = "https://github.com/python-discord/bot/tree/master/" - final_url = f"<{base_url}{module_name}#L{starting_line_no}-L{last_line_no}>" + + # use the module name if the file path goes into the decorators. + if file_path == "bot/decorators.py": + final_url = f"{base_url}{module_name}#L{starting_line_no}-L{last_line_no}" + else: + final_url = f"{base_url}{file_path}#L{starting_line_no}-L{last_line_no}" return final_url From 0004dcc8e0f7bb01fbc45fef2cf21c668800052c Mon Sep 17 00:00:00 2001 From: RohanJnr Date: Fri, 4 Oct 2019 21:19:47 +0530 Subject: [PATCH 3/3] made suggestions as per suggestions and hard coded url for help command. --- bot/cogs/source.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/bot/cogs/source.py b/bot/cogs/source.py index feffc35768..98a06fc5f3 100644 --- a/bot/cogs/source.py +++ b/bot/cogs/source.py @@ -1,5 +1,6 @@ import inspect import logging +import os import discord from discord.ext import commands @@ -18,30 +19,29 @@ def __init__(self, bot: commands.Bot) -> None: @in_channel(constants.Channels.bot) @commands.command(name="source") - async def command_source(self, ctx: commands.Context, command_name: str = None, sub_command: str = None) -> None: + async def command_source(self, ctx: commands.Context, *, command_name: str = None) -> None: """View the source of a command.""" if command_name is None: await ctx.send("> https://github.com/python-discord/bot") return - if sub_command: - await ctx.send(sub_command) - command = self.bot.get_command(f"{command_name} {sub_command}") - else: - command = self.bot.get_command(command_name) - + command = self.bot.get_command(command_name) if command is None: await ctx.send("No such command found.") return - url = self.get_command_url(command) + if command.name == "help": + url = "https://github.com/python-discord/bot/blob/master/bot/cogs/help.py#L475-L490" + + else: + url = self.get_command_url(command) prefix = constants.Bot.prefix embed = discord.Embed(colour=discord.Colour.red()) embed.title = "Command Source" embed.description = f"**{command.name.capitalize()}**\n" - embed.description += f"`{prefix}{command.name}`\n\n {url}" + embed.description += f"`{prefix}{command.qualified_name}`\n\n {url}" await ctx.send(embed=embed) @@ -49,11 +49,14 @@ async def command_source(self, ctx: commands.Context, command_name: str = None, def get_command_url(command: commands.Command) -> str: """Make up the url for the source of the command.""" # Get the source code - src_code_object = command.callback.__code__ - file_path = src_code_object.co_filename[5:] + src = command.callback.__code__ + file_name = src.co_filename + + # get the file path + file_path = os.path.relpath(file_name).replace('\\', '/') # Get line number and set last line number - lines_list, starting_line_no = inspect.getsourcelines(src_code_object) + lines_list, starting_line_no = inspect.getsourcelines(src) lines = len(lines_list) # Get module @@ -66,7 +69,7 @@ def get_command_url(command: commands.Command) -> str: base_url = "https://github.com/python-discord/bot/tree/master/" # use the module name if the file path goes into the decorators. - if file_path == "bot/decorators.py": + if "bot/decorators.py" in file_path: final_url = f"{base_url}{module_name}#L{starting_line_no}-L{last_line_no}" else: final_url = f"{base_url}{file_path}#L{starting_line_no}-L{last_line_no}"