From 054a8422a08a8415d551b2a5f9e00dfe9be893b2 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 8 May 2018 10:34:34 -0400 Subject: [PATCH 1/6] Text eval And pep8 nonsense --- ccrole/ccrole.py | 206 ++++++++++++++++++++++++----------------------- 1 file changed, 106 insertions(+), 100 deletions(-) diff --git a/ccrole/ccrole.py b/ccrole/ccrole.py index 38cff39..f3f8eb7 100644 --- a/ccrole/ccrole.py +++ b/ccrole/ccrole.py @@ -1,13 +1,10 @@ -import discord -import asyncio +import asyncio +import re +import discord from discord.ext import commands - from redbot.core import Config, checks - from redbot.core.utils.chat_formatting import pagify, box -import os -import re class CCRole: @@ -20,12 +17,11 @@ class CCRole: self.bot = bot self.config = Config.get_conf(self, identifier=9999114111108101) default_guild = { - "cmdlist" : {}, + "cmdlist": {}, "settings": {} } - - self.config.register_guild(**default_guild) + self.config.register_guild(**default_guild) @commands.group(no_pm=True) async def ccrole(self, ctx): @@ -35,7 +31,7 @@ class CCRole: @ccrole.command(name="add") @checks.mod_or_permissions(administrator=True) - async def ccrole_add(self, ctx, command : str): + async def ccrole_add(self, ctx, command: str): """Adds a custom command with roles""" command = command.lower() if command in self.bot.all_commands: @@ -45,125 +41,136 @@ class CCRole: guild = ctx.guild author = ctx.author channel = ctx.channel - - cmdlist = self.config.guild(ctx.guild).cmdlist - + + cmdlist = self.config.guild(guild).cmdlist + if await cmdlist.get_raw(command, default=None): await ctx.send("This command already exists. Delete it with `{}ccrole delete` first.".format(ctx.prefix)) return # Roles to add await ctx.send('What roles should it add? (Must be **comma separated**)\nSay `None` to skip adding roles') - + def check(m): - return m.author == author and m.channel==channel - + return m.author == author and m.channel == channel + try: answer = await self.bot.wait_for('message', timeout=120, check=check) except asyncio.TimeoutError: await ctx.send("Timed out, canceling") - + return + arole_list = [] - if answer.content.upper()!="NONE": + if answer.content.upper() != "NONE": arole_list = await self._get_roles_from_content(ctx, answer.content) if arole_list is None: await ctx.send("Invalid answer, canceling") return - + # Roles to remove await ctx.send('What roles should it remove? (Must be comma separated)\nSay `None` to skip removing roles') try: answer = await self.bot.wait_for('message', timeout=120, check=check) except asyncio.TimeoutError: await ctx.send("Timed out, canceling") - + return + rrole_list = [] - if answer.content.upper()!="NONE": + if answer.content.upper() != "NONE": rrole_list = await self._get_roles_from_content(ctx, answer.content) if rrole_list is None: await ctx.send("Invalid answer, canceling") return - + # Roles to use - await ctx.send('What roles are allowed to use this command? (Must be comma separated)\nSay `None` to allow all roles') - + await ctx.send( + 'What roles are allowed to use this command? (Must be comma separated)\nSay `None` to allow all roles') + try: answer = await self.bot.wait_for('message', timeout=120, check=check) except asyncio.TimeoutError: await ctx.send("Timed out, canceling") - + return + prole_list = [] - if answer.content.upper()!="NONE": + if answer.content.upper() != "NONE": prole_list = await self._get_roles_from_content(ctx, answer.content) if prole_list is None: await ctx.send("Invalid answer, canceling") return - + # Selfrole await ctx.send('Is this a targeted command?(yes/no)\nNo will make this a selfrole command') - + try: answer = await self.bot.wait_for('message', timeout=120, check=check) except asyncio.TimeoutError: await ctx.send("Timed out, canceling") - + return + if answer.content.upper() in ["Y", "YES"]: targeted = True await ctx.send("This command will be **`targeted`**") else: targeted = False await ctx.send("This command will be **`selfrole`**") - + # Message to send - await ctx.send('What message should the bot say when using this command?\nSay `None` to send the default `Success!` message') - + await ctx.send( + 'What message should the bot say when using this command?\n' + 'Say `None` to send the default `Success!` message') + try: answer = await self.bot.wait_for('message', timeout=120, check=check) except asyncio.TimeoutError: await ctx.send("Timed out, canceling") + return + text = "Success!" - if answer.content.upper()!="NONE": + if answer.content.upper() != "NONE": text = answer.content # Save the command - + out = {'text': text, 'aroles': arole_list, 'rroles': rrole_list, "proles": prole_list, "targeted": targeted} - + await cmdlist.set_raw(command, value=out) - + ctx.send("Custom Command **`{}`** successfully added".format(command)) - + @ccrole.command(name="delete") @checks.mod_or_permissions(administrator=True) - async def ccrole_delete(self, ctx, command : str): + async def ccrole_delete(self, ctx, command: str): """Deletes a custom command Example: [p]ccrole delete yourcommand""" guild = ctx.guild command = command.lower() - if not await self.config.guild(ctx.guild).cmdlist.get_raw(command, default=None): + if not await self.config.guild(guild).cmdlist.get_raw(command, default=None): await ctx.send("That command doesn't exist") else: - await self.config.guild(ctx.guild).cmdlist.set_raw(command, value=None) + await self.config.guild(guild).cmdlist.set_raw(command, value=None) await ctx.send("Custom command successfully deleted.") @ccrole.command(name="list") async def ccrole_list(self, ctx): """Shows custom commands list""" guild = ctx.guild - commands = await self.config.guild(ctx.guild).cmdlist() + cmd_list = await self.config.guild(guild).cmdlist() - if not commands: - await ctx.send("There are no custom commands in this server. Use `{}ccrole add` to start adding some.".format(ctx.prefix)) + if not cmd_list: + await ctx.send( + "There are no custom commands in this server. Use `{}ccrole add` to start adding some.".format( + ctx.prefix)) return - commands = ", ".join([ctx.prefix + c for c in sorted(commands.keys())]) - commands = "Custom commands:\n\n" + commands + cmd_list = ", ".join([ctx.prefix + c for c in sorted(cmd_list.keys())]) + cmd_list = "Custom commands:\n\n" + cmd_list - if len(commands) < 1500: - await ctx.send(box(commands)) + if len(cmd_list) < 1500: + await ctx.send(box(cmd_list)) else: - for page in pagify(commands, delims=[" ", "\n"]): + for page in pagify(cmd_list, delims=[" ", "\n"]): await ctx.author.send(box(page)) await ctx.send("Command list DM'd") @@ -177,24 +184,22 @@ class CCRole: except ValueError: return - cmdlist = self.config.guild(guild).cmdlist - cmd = message.content[len(prefix):].split()[0] - cmd = await cmdlist.get_raw(cmd.lower(), default=None) - - if cmd: + cmd = message.content[len(prefix):].split()[0].lower() + cmd = await cmdlist.get_raw(cmd, default=None) + + if cmd is not None: await self.eval_cc(cmd, message) - + async def _get_roles_from_content(self, ctx, content): content_list = content.split(",") - role_list = [] try: role_list = [discord.utils.get(ctx.guild.roles, name=role.strip(' ')).id for role in content_list] - except: + except (discord.HTTPException, AttributeError): # None.id is attribute error return None else: return role_list - + async def get_prefix(self, message: discord.Message) -> str: """ Borrowed from alias cog @@ -214,27 +219,26 @@ class CCRole: if content.startswith(p): return p raise ValueError - + async def eval_cc(self, cmd, message): """Does all the work""" if cmd['proles'] and not (set(role.id for role in message.author.roles) & set(cmd['proles'])): return # Not authorized, do nothing - + if cmd['targeted']: try: target = discord.utils.get(message.guild.members, mention=message.content.split()[1]) - except: + except IndexError: # .split() return list of len<2 target = None - + if not target: - out_message = "This command is targeted! @mention a target\n`{} `".format(message.content.split()[0]) - + out_message = "This custom command is targeted! @mention a target\n`{} `".format( + message.content.split()[0]) await message.channel.send(out_message) - return else: target = message.author - + if cmd['aroles']: arole_list = [discord.utils.get(message.guild.roles, id=roleid) for roleid in cmd['aroles']] # await self.bot.send_message(message.channel, "Adding: "+str([str(arole) for arole in arole_list])) @@ -243,7 +247,7 @@ class CCRole: except discord.Forbidden: await message.channel.send("Permission error: Unable to add roles") await asyncio.sleep(1) - + if cmd['rroles']: rrole_list = [discord.utils.get(message.guild.roles, id=roleid) for roleid in cmd['rroles']] # await self.bot.send_message(message.channel, "Removing: "+str([str(rrole) for rrole in rrole_list])) @@ -251,37 +255,39 @@ class CCRole: await target.remove_roles(*rrole_list) except discord.Forbidden: await message.channel.send("Permission error: Unable to remove roles") - await message.channel.send(cmd['text']) - - # {'text': text, 'aroles': arole_list, 'rroles': rrole_list, "proles", prole_list, "targeted": targeted} - - # def format_cc(self, command, message): - # results = re.findall("\{([^}]+)\}", command) - # for result in results: - # param = self.transform_parameter(result, message) - # command = command.replace("{" + result + "}", param) - # return command - - # def transform_parameter(self, result, message): - # """ - # For security reasons only specific objects are allowed - # Internals are ignored - # """ - # raw_result = "{" + result + "}" - # objects = { - # "message" : message, - # "author" : message.author, - # "channel" : message.channel, - # "server" : message.server - # } - # if result in objects: - # return str(objects[result]) - # try: - # first, second = result.split(".") - # except ValueError: - # return raw_result - # if first in objects and not second.startswith("_"): - # first = objects[first] - # else: - # return raw_result - # return str(getattr(first, second, raw_result)) \ No newline at end of file + + out_message = self.format_cc(cmd, message, target) + await message.channel.send(out_message) + + def format_cc(self, cmd, message, target): + out = cmd['text'] + results = re.findall("{([^}]+)\}", out) + for result in results: + param = self.transform_parameter(result, message, target) + out = out.replace("{" + result + "}", param) + return out + + def transform_parameter(self, result, message, target): + """ + For security reasons only specific objects are allowed + Internals are ignored + """ + raw_result = "{" + result + "}" + objects = { + "message": message, + "author": message.author, + "channel": message.channel, + "server": message.server, + "target": target + } + if result in objects: + return str(objects[result]) + try: + first, second = result.split(".") + except ValueError: + return raw_result + if first in objects and not second.startswith("_"): + first = objects[first] + else: + return raw_result + return str(getattr(first, second, raw_result)) From 5bff294b5957ae400475131e0620d9f3b468cea3 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 8 May 2018 10:38:27 -0400 Subject: [PATCH 2/6] Forgot an await --- ccrole/ccrole.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccrole/ccrole.py b/ccrole/ccrole.py index f3f8eb7..6a3fda5 100644 --- a/ccrole/ccrole.py +++ b/ccrole/ccrole.py @@ -136,7 +136,7 @@ class CCRole: await cmdlist.set_raw(command, value=out) - ctx.send("Custom Command **`{}`** successfully added".format(command)) + await ctx.send("Custom Command **`{}`** successfully added".format(command)) @ccrole.command(name="delete") @checks.mod_or_permissions(administrator=True) From 58979fc3aa2773d5ddfd34ead93ba68557f4f939 Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 8 May 2018 10:39:45 -0400 Subject: [PATCH 3/6] Almost forgot this is V3 --- ccrole/ccrole.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ccrole/ccrole.py b/ccrole/ccrole.py index 6a3fda5..721825b 100644 --- a/ccrole/ccrole.py +++ b/ccrole/ccrole.py @@ -277,7 +277,8 @@ class CCRole: "message": message, "author": message.author, "channel": message.channel, - "server": message.server, + "server": message.guild, + "guild": message.guild, "target": target } if result in objects: From cc89d07480eb15efca312d403a40ba95837febce Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 8 May 2018 10:46:22 -0400 Subject: [PATCH 4/6] More details --- ccrole/ccrole.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ccrole/ccrole.py b/ccrole/ccrole.py index 721825b..4d3222c 100644 --- a/ccrole/ccrole.py +++ b/ccrole/ccrole.py @@ -25,14 +25,19 @@ class CCRole: @commands.group(no_pm=True) async def ccrole(self, ctx): - """Custom commands management""" + """Custom commands management with roles + + Highly customizable custom commands with role management.""" if not ctx.invoked_subcommand: await ctx.send_help() @ccrole.command(name="add") @checks.mod_or_permissions(administrator=True) async def ccrole_add(self, ctx, command: str): - """Adds a custom command with roles""" + """Adds a custom command with roles + + When adding text, put arguments in `{}` to eval them + Options: `{author}`, `{target}`, `{server}`, `{channel}`, `{message}`""" command = command.lower() if command in self.bot.all_commands: await ctx.send("That command is already a standard command.") @@ -118,7 +123,9 @@ class CCRole: # Message to send await ctx.send( 'What message should the bot say when using this command?\n' - 'Say `None` to send the default `Success!` message') + 'Say `None` to send the default `Success!` message\n' + 'Eval Options: `{author}`, `{target}`, `{server}`, `{channel}`, `{message}`\n' + 'For example: `Welcome {target.mention} to {server.name}!`') try: answer = await self.bot.wait_for('message', timeout=120, check=check) From 44784a34bc711aa07ad342ec6aec296784207ecf Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 8 May 2018 11:36:29 -0400 Subject: [PATCH 5/6] ccrole details --- ccrole/ccrole.py | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/ccrole/ccrole.py b/ccrole/ccrole.py index 4d3222c..59ead55 100644 --- a/ccrole/ccrole.py +++ b/ccrole/ccrole.py @@ -149,8 +149,9 @@ class CCRole: @checks.mod_or_permissions(administrator=True) async def ccrole_delete(self, ctx, command: str): """Deletes a custom command + Example: - [p]ccrole delete yourcommand""" + `[p]ccrole delete yourcommand`""" guild = ctx.guild command = command.lower() if not await self.config.guild(guild).cmdlist.get_raw(command, default=None): @@ -159,6 +160,32 @@ class CCRole: await self.config.guild(guild).cmdlist.set_raw(command, value=None) await ctx.send("Custom command successfully deleted.") + @ccrole.command(name="details") + async def ccrole_details(self, ctx, command: str): + """Provide details about passed custom command""" + guild = ctx.guild + command = command.lower() + cmd = await self.config.guild(guild).cmdlist.get_raw(command, default=None) + if cmd is None: + await ctx.send("That command doesn't exist") + return + + embed = discord.Embed(title=command, + description="{} custom command".format("Targeted" if cmd['targeted'] else "Non-Targeted")) + + def process_roles(role_list): + if not role_list: + return "None" + return ", ".join([discord.utils.get(ctx.guild.roles, id=roleid).name for roleid in role_list]) + + embed.add_field(name="Text", value="```{}```".format(cmd['text'])) + embed.add_field(name="Adds Roles", value=process_roles(cmd['aroles']), inline=True) + embed.add_field(name="Removes Roles", value=process_roles(cmd['rroles']), inline=True) + embed.add_field(name="Role Restrictions", value=process_roles(cmd['proles']), inline=True) + + await ctx.send(embed=embed) + + @ccrole.command(name="list") async def ccrole_list(self, ctx): """Shows custom commands list""" @@ -174,7 +201,7 @@ class CCRole: cmd_list = ", ".join([ctx.prefix + c for c in sorted(cmd_list.keys())]) cmd_list = "Custom commands:\n\n" + cmd_list - if len(cmd_list) < 1500: + if len(cmd_list) < 1500: # I'm allowed to have arbitrary numbers for when it's too much to dm dammit await ctx.send(box(cmd_list)) else: for page in pagify(cmd_list, delims=[" ", "\n"]): From 75e8ee13b22e6000596c7da33795c8814e605b2a Mon Sep 17 00:00:00 2001 From: Unknown Date: Tue, 8 May 2018 11:54:07 -0400 Subject: [PATCH 6/6] Better defaults --- ccrole/ccrole.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ccrole/ccrole.py b/ccrole/ccrole.py index 59ead55..2459b6e 100644 --- a/ccrole/ccrole.py +++ b/ccrole/ccrole.py @@ -47,9 +47,9 @@ class CCRole: author = ctx.author channel = ctx.channel - cmdlist = self.config.guild(guild).cmdlist + cmd_list = self.config.guild(guild).cmdlist - if await cmdlist.get_raw(command, default=None): + if await cmd_list.get_raw(command, default=None): await ctx.send("This command already exists. Delete it with `{}ccrole delete` first.".format(ctx.prefix)) return @@ -141,7 +141,7 @@ class CCRole: out = {'text': text, 'aroles': arole_list, 'rroles': rrole_list, "proles": prole_list, "targeted": targeted} - await cmdlist.set_raw(command, value=out) + await cmd_list.set_raw(command, value=out) await ctx.send("Custom Command **`{}`** successfully added".format(command)) @@ -185,13 +185,12 @@ class CCRole: await ctx.send(embed=embed) - @ccrole.command(name="list") async def ccrole_list(self, ctx): """Shows custom commands list""" guild = ctx.guild cmd_list = await self.config.guild(guild).cmdlist() - + cmd_list = {k: v for k,v in cmd_list.items() if v} if not cmd_list: await ctx.send( "There are no custom commands in this server. Use `{}ccrole add` to start adding some.".format(