diff --git a/ccrole/__init__.py b/ccrole/__init__.py new file mode 100644 index 0000000..a22b3f1 --- /dev/null +++ b/ccrole/__init__.py @@ -0,0 +1,5 @@ +from .ccrole import CCRole + + +def setup(bot): + bot.add_cog(CCRole(bot)) diff --git a/ccrole/ccrole.py b/ccrole/ccrole.py index f60b26c..2ca5b91 100644 --- a/ccrole/ccrole.py +++ b/ccrole/ccrole.py @@ -1,5 +1,10 @@ +import discord +import asyncio + from discord.ext import commands -from .utils.dataIO import dataIO + +from redbot.core import Config + from .utils import checks from .utils.chat_formatting import pagify, box import os @@ -7,8 +12,10 @@ import re class CCRole: - """Custom commands - Creates commands used to display text""" + """ + Custom commands + Creates commands used to display text and adjust roles + """ def __init__(self, bot): self.bot = bot @@ -25,71 +32,116 @@ class CCRole: @checks.mod_or_permissions(administrator=True) async def ccrole_add(self, ctx, command : str): """Adds a custom command with roles""" - - server = ctx.message.server - author = ctx.message.author - msg = 'What roles should it add? (Must be comma separated) Example:\n\n' - for c, m in enumerate(self.settings[server.id]["GREETING"]): - msg += " {}. {}\n".format(c, m) - for page in pagify(msg, ['\n', ' '], shorten_by=20): - await self.bot.say("```\n{}\n```".format(page)) - answer = await self.bot.wait_for_message(timeout=120, author=author) - try: - num = int(answer.content) - choice = self.settings[server.id]["GREETING"].pop(num) - except: - await self.bot.say("That's not a number in the list :/") - return - - server = ctx.message.server command = command.lower() if command in self.bot.commands: await self.bot.say("That command is already a standard command.") return + + server = ctx.message.server + author = ctx.message.author + if server.id not in self.c_commands: self.c_commands[server.id] = {} cmdlist = self.c_commands[server.id] - if command not in cmdlist: - cmdlist[command] = text - self.c_commands[server.id] = cmdlist - dataIO.save_json(self.file_path, self.c_commands) - await self.bot.say("Custom command successfully added.") - else: - await self.bot.say("This command already exists. Use " - "`{}customcom edit` to edit it." + if command in cmdlist: + await self.bot.say("This command already exists. Delete" + "`it with {}ccrole delete` first." "".format(ctx.prefix)) + return - @customcom.command(name="edit", pass_context=True) - @checks.mod_or_permissions(administrator=True) - async def cc_edit(self, ctx, command : str, *, text): - """Edits a custom command - Example: - [p]customcom edit yourcommand Text you want - """ - server = ctx.message.server - command = command.lower() - if server.id in self.c_commands: - cmdlist = self.c_commands[server.id] - if command in cmdlist: - cmdlist[command] = text - self.c_commands[server.id] = cmdlist - dataIO.save_json(self.file_path, self.c_commands) - await self.bot.say("Custom command successfully edited.") - else: - await self.bot.say("That command doesn't exist. Use " - "`{}customcom add` to add it." - "".format(ctx.prefix)) + # Roles to add + await self.bot.say('What roles should it add? (Must be comma separated)\nSay `None` to skip adding roles') + + answer = await self.bot.wait_for_message(timeout=120, author=author) + if not answer: + await self.bot.say("Timed out, canceling") + return + arole_list = [] + if answer.content.upper()!="NONE": + arole_list = answer.content.split(",") + + try: + arole_list = [discord.utils.get(server.roles, name=role.strip(' ')).id for role in arole_list] + except: + await self.bot.say("Invalid answer, canceling") + return + + # Roles to remove + await self.bot.say('What roles should it remove? (Must be comma separated)\nSay `None` to skip removing roles') + + answer = await self.bot.wait_for_message(timeout=120, author=author) + if not answer: + await self.bot.say("Timed out, canceling") + return + + rrole_list = [] + if answer.content.upper()!="NONE": + rrole_list = answer.content.split(",") + + try: + rrole_list = [discord.utils.get(server.roles, name=role.strip(' ')).id for role in rrole_list] + except: + await self.bot.say("Invalid answer, canceling") + return + + # Roles to use + await self.bot.say('What roles are allowed to use this command? (Must be comma separated)\nSay `None` to allow all roles') + + answer = await self.bot.wait_for_message(timeout=120, author=author) + if not answer: + await self.bot.say("Timed out, canceling") + return + + prole_list = [] + if answer.content.upper()!="NONE": + prole_list = answer.content.split(",") + + try: + prole_list = [discord.utils.get(server.roles, name=role.strip(' ')).id for role in prole_list] + except: + await self.bot.say("Invalid answer, canceling") + return + + # Selfrole + await self.bot.say('Is this a targeted command?(yes/no)\nNo will make this a selfrole command') + + answer = await self.bot.wait_for_message(timeout=120, author=author) + if not answer: + await self.bot.say("Timed out, canceling") + return + + if answer.content.upper() in ["Y", "YES"]: + targeted = True + await self.bot.say("This command will be targeted") else: - await self.bot.say("There are no custom commands in this server." - " Use `{}customcom add` to start adding some." - "".format(ctx.prefix)) + targeted = False + await self.bot.say("This command will be selfrole") + + # Message to send + await self.bot.say('What message should the bot send?\nSay `None` to send the default `Success!` message') + + answer = await self.bot.wait_for_message(timeout=120, author=author) + if not answer: + await self.bot.say("Timed out, canceling") + return + text = "Success!" + if answer.content.upper()!="NONE": + text = answer.content + + # Save the command + + cmdlist[command] = {'text': text, 'aroles': arole_list, 'rroles': rrole_list, "proles": prole_list, "targeted": targeted} + + self.c_commands[server.id] = cmdlist + dataIO.save_json(self.file_path, self.c_commands) + await self.bot.say("Custom command successfully added.") - @customcom.command(name="delete", pass_context=True) + @ccrole.command(name="delete", pass_context=True) @checks.mod_or_permissions(administrator=True) - async def cc_delete(self, ctx, command : str): + async def ccrole_delete(self, ctx, command : str): """Deletes a custom command Example: - [p]customcom delete yourcommand""" + [p]ccrole delete yourcommand""" server = ctx.message.server command = command.lower() if server.id in self.c_commands: @@ -103,22 +155,22 @@ class CCRole: await self.bot.say("That command doesn't exist.") else: await self.bot.say("There are no custom commands in this server." - " Use `{}customcom add` to start adding some." + " Use `{}ccrole add` to start adding some." "".format(ctx.prefix)) - @customcom.command(name="list", pass_context=True) - async def cc_list(self, ctx): + @ccrole.command(name="list", pass_context=True) + async def ccrole_list(self, ctx): """Shows custom commands list""" server = ctx.message.server commands = self.c_commands.get(server.id, {}) if not commands: await self.bot.say("There are no custom commands in this server." - " Use `{}customcom add` to start adding some." + " Use `{}ccrole add` to start adding some." "".format(ctx.prefix)) return - commands = ", ".join([ctx.prefix + c for c in sorted(commands)]) + commands = ", ".join([ctx.prefix + c for c in sorted(commands.keys())]) commands = "Custom commands:\n\n" + commands if len(commands) < 1500: @@ -139,62 +191,95 @@ class CCRole: if server.id in self.c_commands and self.bot.user_allowed(message): cmdlist = self.c_commands[server.id] - cmd = message.content[len(prefix):] + cmd = message.content[len(prefix):].split()[0] if cmd in cmdlist: cmd = cmdlist[cmd] - cmd = self.format_cc(cmd, message) - await self.bot.send_message(message.channel, cmd) + await self.eval_cc(cmd, message) elif cmd.lower() in cmdlist: cmd = cmdlist[cmd.lower()] - cmd = self.format_cc(cmd, message) - await self.bot.send_message(message.channel, cmd) + await self.eval_cc(cmd, message) def get_prefix(self, message): for p in self.bot.settings.get_prefixes(message.server): if message.content.startswith(p): return p return False - - 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] + + async def eval_cc(self, cmd, message): + 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.server.members, mention=message.content.split()[1]) + except: + target = None + + if not target: + out_message = "This command is targeted! @mention a target\n`{} `".format(message.content.split()[0]) + + await self.bot.send_message(message.channel, out_message) + + return else: - return raw_result - return str(getattr(first, second, raw_result)) + target = message.author + + if cmd['aroles']: + arole_list = [discord.utils.get(message.server.roles, id=roleid) for roleid in cmd['aroles']] + # await self.bot.send_message(message.channel, "Adding: "+str([str(arole) for arole in arole_list])) + await self.bot.add_roles(target, *arole_list) + + await asyncio.sleep(1) + + if cmd['rroles']: + rrole_list = [discord.utils.get(message.server.roles, id=roleid) for roleid in cmd['rroles']] + # await self.bot.send_message(message.channel, "Removing: "+str([str(rrole) for rrole in rrole_list])) + await self.bot.remove_roles(target, *rrole_list) + + await self.bot.send_message(message.channel, 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)) def check_folders(): - if not os.path.exists("data/customcom"): - print("Creating data/customcom folder...") - os.makedirs("data/customcom") + if not os.path.exists("data/ccrole"): + print("Creating data/ccrole folder...") + os.makedirs("data/ccrole") def check_files(): - f = "data/customcom/commands.json" + f = "data/ccrole/commands.json" if not dataIO.is_valid_json(f): print("Creating empty commands.json...") dataIO.save_json(f, {}) diff --git a/ccrole/info.json b/ccrole/info.json index c2be724..73a1f79 100644 --- a/ccrole/info.json +++ b/ccrole/info.json @@ -1,9 +1,10 @@ { - "AUTHOR" : "Bobloy", - "INSTALL_MSG" : "Thank you for installing Custom Commands w/ Roles", - "NAME" : "CCRole", - "SHORT" : "Creates commands that adjust roles", - "DESCRIPTION" : "Creates custom commands to adjust roles and send custom messages", - "TAGS" : ["fox", "bobloy", "utilities", "tools", "roles"], - "HIDDEN" : false + "author" : ["Bobloy"], + "bot_version" : [3,0,0], + "description" : "[Incomplete] Creates custom commands to adjust roles and send custom messages", + "hidden" : false, + "install_msg" : "Thank you for installing Custom Commands w/ Roles.", + "requirements" : [], + "short" : "[Incomplete] Creates commands that adjust roles", + "tags" : ["fox", "bobloy", "utility", "tools", "roles"] } \ No newline at end of file