Ejemplo n.º 1
0
    def post(self, row_id, **options):
        args = self.post_parser.parse_args()

        try:
            new_state = int(args["new_state"])
        except (ValueError, KeyError):
            return {"error": "Invalid `new_state` parameter."}, 400

        with DBManager.create_session_scope() as db_session:
            row = db_session.query(Module).filter_by(id=row_id).one_or_none()

            if not row:
                return {"error": "Module with this ID not found"}, 404

            if validate_module(row_id) is False:
                return {"error": "cannot modify module"}, 400

            row.enabled = True if new_state == 1 else False
            db_session.commit()
            payload = {"id": row.id, "new_state": row.enabled}
            AdminLogManager.post(
                "Module toggled",
                options["user"].discord_id,
                "Enabled" if row.enabled else "Disabled",
                row.id,
            )
            SocketClientManager.send("module.update", payload)
            return {"success": "successful toggle", "new_state": new_state}
Ejemplo n.º 2
0
    def add_alias(bot, author, channel, message, args):
        """Dispatch method for adding aliases to already-existing commands.
        Usage: !add alias EXISTING_ALIAS NEW_ALIAS_1 NEW_ALIAS_2 ...
        """

        if message:
            message = message.replace("!", "").lower()
            # Make sure we got both an existing alias and at least one new alias
            message_parts = message.split()
            if len(message_parts) < 2:
                bot.private_message(
                    author, "Usage: !add alias existingalias newalias")
                return False

            existing_alias = message_parts[0]
            new_aliases = re.split(r"\|| ", " ".join(message_parts[1:]))
            added_aliases = []
            already_used_aliases = []

            if existing_alias not in bot.commands:
                bot.private_message(
                    author, f'No command called "{existing_alias}" found')
                return False

            command = bot.commands[existing_alias]

            # error out on commands that are not from the DB, e.g. module commands like !8ball that cannot have
            # aliases registered. (command.command and command.data are None on those commands)
            if command.data is None or command.command is None:
                bot.private_message(
                    author, "That command cannot have aliases added to.")
                return False

            for alias in set(new_aliases):
                if alias in bot.commands:
                    already_used_aliases.append(alias)
                else:
                    added_aliases.append(alias)
                    bot.commands[alias] = command

            if len(added_aliases) > 0:
                new_aliases = f"{command.command}|{'|'.join(added_aliases)}"
                bot.commands.edit_command(command, command=new_aliases)

                bot.private_message(
                    author,
                    f"Successfully added the aliases {', '.join(added_aliases)} to {existing_alias}",
                )
                log_msg = f"The aliases {', '.join(added_aliases)} has been added to {existing_alias}"
                AdminLogManager.add_entry("Alias added", str(author.id),
                                          log_msg)
            if len(already_used_aliases) > 0:
                bot.private_message(
                    author,
                    f"The following aliases were already in use: {', '.join(already_used_aliases)}",
                )
        else:
            bot.private_message(author,
                                "Usage: !add alias existingalias newalias")
Ejemplo n.º 3
0
    async def edit_funccommand(bot, author, channel, message, args):
        """Dispatch method for editing function commands.
        Usage: !edit funccommand ALIAS [options] CALLBACK
        See greenbot/managers/command.py parse_command_arguments for available options
        """

        if message:
            # Make sure we got both an alias and a response
            message_parts = message.split(" ")
            if len(message_parts) < 2:
                await bot.private_message(
                    author,
                    "Usage: !edit funccommand ALIAS [options] [CALLBACK]")
                return False

            options, response = bot.commands.parse_command_arguments(
                message_parts[1:])

            options["edited_by"] = str(author.id)

            if options is False:
                await bot.private_message(author, "Invalid command")
                return False

            alias = message_parts[0].replace("!", "").lower()
            type = "reply"
            if options["privatemessage"] is True:
                type = "privatemessage"
            elif options["reply"] is True:
                type = "reply"

            options["action"] = {
                "type": type,
                "message": None,
                "functions": response,
            }

            if "channels" in options:
                options["channels"] = json.dumps(options["channels"])

            command = bot.commands.get(alias, None)

            if command is None:
                await bot.private_message(
                    author,
                    f"No command found with the alias {alias}. Did you mean to create the command? If so, use !add funccommand instead.",
                )
                return False

            bot.commands.edit_command(command, **options)
            await bot.private_message(
                author, f"Updated the command (ID: {command.id})")
            AdminLogManager.add_entry(
                "Command edited",
                str(author.id),
                f"The !{command.command.split('|')[0]} command has been updated",
            )
Ejemplo n.º 4
0
    async def remove_alias(bot, author, channel, message, args):
        """Dispatch method for removing aliases from a command.
        Usage: !remove alias EXISTING_ALIAS_1"""
        if message:
            aliases = re.split(r"\|| ", message.lower())
            if len(aliases) < 1:
                await bot.private_message(
                    author,
                    "Usage: !remove alias EXISTING_ALIAS_1|EXISTING_ALIAS_2|..."
                )
                return False
            for alias in aliases:
                if alias not in bot.commands:
                    await bot.private_message(
                        author,
                        f"{alias} is not currently an alias",
                    )
                    continue

                command = bot.commands[alias]

                # error out on commands that are not from the DB, e.g. module commands like !8ball that cannot have
                # aliases registered. (command.command and command.data are None on those commands)
                if command.data is None or command.command is None:
                    await bot.private_message(
                        author,
                        f"That command, {alias}, cannot have aliases removed from."
                    )
                    continue

                current_aliases = command.aliases
                current_aliases.remove(alias)

                if len(current_aliases) == 0:
                    await bot.private_message(
                        author,
                        f"{alias} is the only remaining alias for this command and can't be removed.",
                    )
                    continue

                new_aliases = "|".join(current_aliases)
                bot.commands.edit_command(command,
                                          command=new_aliases.replace(
                                              command.group, ""))

                del bot.commands[alias]
                log_msg = (
                    f"The alias {alias} has been removed from {new_aliases.split('|')[0]}"
                )
                AdminLogManager.add_entry("Alias removed", str(author.id),
                                          log_msg)

                await bot.private_message(
                    author, f"Successfully removed aliase {alias}.")
            else:
                await bot.private_message(
                    author, "Usage: !remove alias EXISTINGALIAS")
Ejemplo n.º 5
0
    async def add_funccommand(bot, author, channel, message, args):
        """Dispatch method for creating function commands.
        Usage: !add funccommand ALIAS [options] CALLBACK
        See greenbot/managers/command.py parse_command_arguments for available options
        """

        if message:
            # Make sure we got both an alias and a response
            message_parts = message.split(" ")
            if len(message_parts) < 2:
                await bot.private_message(
                    author, "Usage: !add funccommand ALIAS [options] CALLBACK")
                return False

            options, response = bot.commands.parse_command_arguments(
                message_parts[1:])

            options["added_by"] = str(author.id)

            if options is False:
                await bot.private_message(author, "Invalid command")
                return False

            alias_str = message_parts[0].replace("!", "").lower()
            type = "reply"
            if options["privatemessage"] is True:
                type = "privatemessage"
            elif options["reply"] is True:
                type = "reply"
            action = {
                "type": type,
                "message": None,
                "functions": response,
            }

            if "channels" in options:
                options["channels"] = json.dumps(options["channels"])

            command, new_command, alias_matched = bot.commands.create_command(
                alias_str, action=action, **options)
            if new_command is True:
                await bot.private_message(
                    author, f"Added your command (ID: {command.id})")
                AdminLogManager.add_entry(
                    "Command created",
                    str(author.id),
                    f"The !{command.command.split('|')[0]} command has been created",
                )
                return True

            # At least one alias is already in use, notify the user to use !edit command instead
            await bot.private_message(
                author,
                f"The alias {alias_matched} is already in use. To edit that command, use !edit command instead of !add funccommand.",
            )
            return False
Ejemplo n.º 6
0
    def remove_alias(bot, author, channel, message, args):
        """Dispatch method for removing aliases from a command.
        Usage: !remove alias EXISTING_ALIAS_1 EXISTING_ALIAS_2"""
        if message:
            aliases = re.split(r"\|| ", message.lower())
            if len(aliases) < 1:
                bot.private_message(author,
                                    "Usage: !remove alias EXISTINGALIAS")
                return False

            num_removed = 0
            commands_not_found = []
            for alias in aliases:
                if alias not in bot.commands:
                    commands_not_found.append(alias)
                    continue

                command = bot.commands[alias]

                # error out on commands that are not from the DB, e.g. module commands like !8ball that cannot have
                # aliases registered. (command.command and command.data are None on those commands)
                if command.data is None or command.command is None:
                    bot.private_message(
                        author,
                        "That command cannot have aliases removed from.")
                    return False

                current_aliases = command.command.split("|")
                current_aliases.remove(alias)

                if len(current_aliases) == 0:
                    bot.private_message(
                        author,
                        f"{alias} is the only remaining alias for this command and can't be removed.",
                    )
                    continue

                new_aliases = "|".join(current_aliases)
                bot.commands.edit_command(command, command=new_aliases)

                num_removed += 1
                del bot.commands[alias]
                log_msg = f"The alias {alias} has been removed from {new_aliases.split('|')[0]}"
                AdminLogManager.add_entry("Alias removed", str(author.id),
                                          log_msg)

            whisper_str = ""
            if num_removed > 0:
                whisper_str = f"Successfully removed {num_removed} aliases."
            if len(commands_not_found) > 0:
                whisper_str += f" Aliases {', '.join(commands_not_found)} not found"
            if len(whisper_str) > 0:
                bot.private_message(author, whisper_str)
        else:
            bot.private_message(author, "Usage: !remove alias EXISTINGALIAS")
Ejemplo n.º 7
0
 def get(self, timer_id, **options):
     with DBManager.create_session_scope() as db_session:
         timer = db_session.query(Timer).filter_by(
             id=timer_id).one_or_none()
         if timer is None:
             return {"error": "Invalid timer ID"}, 404
         AdminLogManager.post("Timer removed", options["user"].discord_id,
                              timer.name)
         db_session.delete(timer)
         SocketClientManager.send("timer.remove", {"id": timer.id})
         return {"success": "good job"}
Ejemplo n.º 8
0
    def add_link_whitelist(self, bot, source, message, **rest):
        parts = message.split(" ")
        try:
            for link in parts:
                self.whitelist_url(link)
                AdminLogManager.post("Whitelist link added", source.discord_id, link)
        except:
            log.exception("Unhandled exception in add_link")
            bot.whisper(source, "Some error occurred white adding your links")
            return False

        bot.whisper(source, "Successfully added your links")
Ejemplo n.º 9
0
    async def remove_command(bot, author, channel, message, args):
        if message:
            id = None
            command = None
            try:
                id = int(message)
            except Exception:
                pass

            if id is None:
                split = message.split(" ")
                potential_cmd = "".join(split[:1]).lower().replace("!", "")
                if potential_cmd in bot.commands:
                    command = bot.commands[potential_cmd]
                potential_cmd += (" " + split[1]) if len(split) > 1 else ""
                if potential_cmd in bot.commands:
                    command = bot.commands[potential_cmd]
            else:
                for key, check_command in bot.commands.items():
                    if check_command.id == id:
                        command = check_command
                        break

            if command is None:
                await bot.private_message(
                    author, "No command with the given parameters found")
                return False

            if command.id == -1:
                await bot.private_message(
                    author,
                    "That command is an internal command, it cannot be removed."
                )
                return False

            if args["user_level"] < 1500:
                if command.action is not None and not command.action.type == "message":
                    await bot.private_message(
                        author,
                        "That command is not a normal command, it cannot be removed by you.",
                    )
                    return False

            await bot.private_message(
                author, f"Successfully removed command with id {command.id}")
            log_msg = f"The !{command.aliases[0]} command has been removed"
            AdminLogManager.add_entry("Command removed", str(author.id),
                                      log_msg)
            bot.commands.remove_command(command)
        else:
            await bot.private_message(
                author, "Usage: !remove command (COMMAND_ID|COMMAND_ALIAS)")
Ejemplo n.º 10
0
 def get(self, banphrase_id, **options):
     with DBManager.create_session_scope() as db_session:
         banphrase = (
             db_session.query(Banphrase).filter_by(id=banphrase_id).one_or_none()
         )
         if banphrase is None:
             return {"error": "Invalid banphrase ID"}, 404
         AdminLogManager.post(
             "Banphrase removed", options["user"].discord_id, banphrase.id, banphrase.phrase
         )
         db_session.delete(banphrase)
         db_session.delete(banphrase.data)
         SocketClientManager.send("banphrase.remove", {"id": banphrase.id})
         return {"success": "good job"}, 200
Ejemplo n.º 11
0
    def add_link_blacklist(self, bot, source, message, **rest):
        options, new_links = self.parse_link_blacklist_arguments(message)

        if new_links:
            parts = new_links.split(" ")
            try:
                for link in parts:
                    if len(link) > 1:
                        self.blacklist_url(link, **options)
                        AdminLogManager.post("Blacklist link added", source.discord_id, link)
                bot.whisper(source, "Successfully added your links")
                return True
            except:
                log.exception("Unhandled exception in add_link_blacklist")
                bot.whisper(source, "Some error occurred while adding your links")
                return False
        else:
            bot.whisper(source, "Usage: !add link blacklist LINK")
            return False
Ejemplo n.º 12
0
 def get(self, command_id, **options):
     with DBManager.create_session_scope() as db_session:
         command = db_session.query(Command).filter_by(
             id=command_id).one_or_none()
         if command is None:
             return {"error": "Invalid command ID"}, 404
         if command.level > options["user"].level or (
                 command.action.functions and options["user"].level < 1500):
             return {"error": "Unauthorized"}, 403
         log_msg = f"The !{command.command.split('|')[0]} command has been removed"
         AdminLogManager.add_entry("Command removed",
                                   options["user"].discord_id, log_msg)
         db_session.delete(command.data)
         db_session.delete(command)
     if (SocketClientManager.send("command.remove",
                                  {"command_id": command_id}) is True):
         return {"success": "good job"}, 200
     else:
         return {"error": "could not push update"}, 500
Ejemplo n.º 13
0
    def remove_link_whitelist(self, bot, source, message, **rest):
        if not message:
            bot.whisper(source, "Usage: !remove link whitelist ID")
            return False

        id = None
        try:
            id = int(message)
        except ValueError:
            pass

        link = self.db_session.query(WhitelistedLink).filter_by(id=id).one_or_none()

        if link:
            self.whitelisted_links.remove(link)
            self.db_session.delete(link)
            self.db_session.commit()
        else:
            bot.whisper(source, "No link with the given id found")
            return False

        AdminLogManager.post("Whitelist link removed", source.discord_id, link.domain)
        bot.whisper(source, f"Successfully removed whitelisted link with id {link.id}")
Ejemplo n.º 14
0
    def timers_create(**options):
        session.pop("timer_created_id", None)
        session.pop("timer_edited_id", None)
        if request.method != "POST":
            return render_template("admin/create_timer.html")
        id = None
        try:
            if "id" in request.form:
                id = int(request.form["id"])
            name = request.form["name"].strip()
            interval_online = int(request.form["interval_online"])
            interval_offline = int(request.form["interval_offline"])
            message_type = request.form["message_type"]
            message = request.form["message"].strip()
        except (KeyError, ValueError):
            abort(403)

        if interval_online < 0 or interval_offline < 0:
            abort(403)

        if message_type not in ["say", "me"]:
            abort(403)

        if not message:
            abort(403)

        user = options.get("user", None)

        if user is None:
            abort(403)

        options = {
            "name": name,
            "interval_online": interval_online,
            "interval_offline": interval_offline,
        }

        action = {"type": message_type, "message": message}
        options["action"] = action

        if id is None:
            timer = Timer(**options)

        with DBManager.create_session_scope(expire_on_commit=False) as db_session:
            if id is not None:
                timer = db_session.query(Timer).filter_by(id=id).one_or_none()
                if timer is None:
                    return redirect("/admin/timers/", 303)

                old_message = ""
                new_message = ""
                try:
                    old_message = timer.action.response
                    new_message = action["message"]
                except:
                    pass

                timer.set(**options)

                if old_message and old_message != new_message:
                    log_msg = f'Timer "{timer.name}" has been updated from "{old_message}" to "{new_message}"'
                else:
                    log_msg = f'Timer "{timer.name}" has been updated'

                AdminLogManager.add_entry(
                    "Timer edited",
                    user.discord_id,
                    log_msg,
                    data={"old_message": old_message, "new_message": new_message},
                )
            else:
                db_session.add(timer)
                AdminLogManager.post("Timer added", user.discord_id, timer.name)

        SocketClientManager.send("timer.update", {"id": timer.id})
        if id is None:
            session["timer_created_id"] = timer.id
        else:
            session["timer_edited_id"] = timer.id
        return redirect("/admin/timers/", 303)
Ejemplo n.º 15
0
    def cmd_module(bot, author, channel, message, whisper, args):
        module_manager = bot.module_manager

        if not message:
            return

        msg_args = message.split(" ")
        if len(msg_args) < 1:
            return

        sub_command = msg_args[0].lower()

        if sub_command == "list":
            messages = split_into_chunks_with_prefix(
                [{
                    "prefix": "Available modules:",
                    "parts":
                    [module.ID for module in module_manager.all_modules],
                }],
                " ",
                default="No modules available.",
            )

            for message in messages:
                if whisper:
                    bot.private_message(author, message)
                    continue
                bot.say(channel, message)
        elif sub_command == "disable":
            if len(msg_args) < 2:
                return
            module_id = msg_args[1].lower()

            module = module_manager.get_module(module_id)
            if not module:
                if whisper:
                    bot.private_message(
                        author, f"No module with the id {module_id} found")
                    return
                bot.say(channel, f"No module with the id {module_id} found")
                return

            if module.MODULE_TYPE > ModuleType.TYPE_NORMAL:
                if whisper:
                    bot.private_message(
                        author, f"Unable to disable module {module_id}")
                    return
                bot.say(channel, f"Unable to disable module {module_id}")
                return

            if not module_manager.disable_module(module_id):
                if whisper:
                    bot.private_message(
                        author,
                        f"Unable to disable module {module_id}, maybe it's not enabled?",
                    )
                    return
                bot.say(
                    channel,
                    f"Unable to disable module {module_id}, maybe it's not enabled?",
                )
                return

            # Rebuild command cache
            bot.commands.rebuild()

            with DBManager.create_session_scope() as db_session:
                db_module = db_session.query(Module).filter_by(
                    id=module_id).one()
                db_module.enabled = False

            AdminLogManager.post("Module toggled", source.discord_id,
                                 "Disabled", module_id)
            if whisper:
                bot.private_message(author, f"Disabled module {module_id}")
                return

            bot.say(channel, f"Disabled module {module_id}")

        elif sub_command == "enable":
            if len(msg_args) < 2:
                return
            module_id = msg_args[1].lower()

            module = module_manager.get_module(module_id)
            if not module:
                if whisper:
                    bot.private_message(
                        author, f"No module with the id {module_id} found")
                    return
                bot.say(channel, f"No module with the id {module_id} found")
                return

            if module.MODULE_TYPE > ModuleType.TYPE_NORMAL:
                if whisper:
                    bot.private_message(
                        author, f"Unable to enable module {module_id}")
                    return
                bot.say(channel, f"Unable to enable module {module_id}")
                return

            if not module_manager.enable_module(module_id):
                if whisper:
                    bot.private_message(
                        author,
                        f"Unable to enable module {module_id}, maybe it's already enabled?",
                    )
                    return
                bot.say(
                    channel,
                    f"Unable to enable module {module_id}, maybe it's already enabled?",
                )
                return

            # Rebuild command cache
            bot.commands.rebuild()

            with DBManager.create_session_scope() as db_session:
                db_module = db_session.query(Module).filter_by(
                    id=module_id).one()
                db_module.enabled = True

            AdminLogManager.post("Module toggled", source.discord_id,
                                 "Enabled", module_id)

            if whisper:
                bot.private_message(author, "Enabled module {module_id}")
                return
            bot.say(channel, "Enabled module {module_id}")
Ejemplo n.º 16
0
    async def edit_command(bot, author, channel, message, args):
        """Dispatch method for editing commands.
        Usage: !edit command "ALIAS" [options] RESPONSE
        See greenbot/managers/command.py parse_command_arguments for available options
        """

        if message:
            # Make sure we got both an alias and a response
            search = re.compile(r"\"([^\"]+)\" (.*)").search(message)
            alias = search.group(1).replace("!", "").lower()
            message_parts = search.group(2).split()
            if not alias or not message_parts:
                await bot.private_message(
                    author, "Usage: !add command \"ALIAS\" [options] RESPONSE")
                return False

            options, response = bot.commands.parse_command_arguments(
                message_parts)

            options["edited_by"] = str(author.id)

            if options is False:
                await bot.private_message(author, "Invalid command")
                return False

            type = "reply"
            if options["privatemessage"] is True:
                type = "privatemessage"
            elif options["reply"] is True:
                type = "reply"
            action = {"type": type, "message": response}

            command = bot.commands.get(alias, None)

            if command is None:
                await bot.private_message(
                    author,
                    f"No command found with the alias {alias}. Did you mean to create the command? If so, use !add command instead.",
                )
                return False

            old_message = ""
            new_message = ""

            if len(action["message"]) > 0:
                options["action"] = action
                old_message = command.action.response
                new_message = action["message"]
            elif not type == command.action.subtype:
                options["action"] = {
                    "type": type,
                    "message": command.action.response
                }

            if "channels" in options:
                options["channels"] = json.dumps(options["channels"])

            bot.commands.edit_command(command, **options)
            await bot.private_message(
                author, f"Updated the command (ID: {command.id})")

            if len(new_message) > 0:
                log_msg = f'The !{command.aliases[0]} command has been updated from "{old_message}" to "{new_message}"'
            else:
                log_msg = (
                    f"The !{command.aliases[0]} command has been updated")

            AdminLogManager.add_entry(
                "Command edited",
                str(author.id),
                log_msg,
                data={
                    "old_message": old_message,
                    "new_message": new_message
                },
            )
Ejemplo n.º 17
0
    def post(self, command_id, **extra_args):
        args = greenbot.utils.remove_none_values(self.post_parser.parse_args())
        if len(args) == 0:
            return {"error": "Missing parameter to edit."}, 400

        valid_names = [
            "enabled",
            "level",
            "delay_all",
            "delay_user",
            "cost",
            "can_execute_with_whisper",
            "sub_only",
        ]

        valid_action_names = ["type", "message", "functions"]

        with DBManager.create_session_scope() as db_session:
            command = (db_session.query(Command).options(
                joinedload(Command.data).joinedload(
                    CommandData.user)).filter_by(id=command_id).one_or_none())
            if command is None:
                return {"error": "Invalid command ID"}, 404
            if command.level > extra_args["user"].level:
                return {"error": "Unauthorized"}, 403
            parsed_action = json.loads(command.action_json)
            options = {"edited_by": extra_args["user"].discord_id}

            for key in args:
                if key.startswith("data_"):
                    name = key[5:]
                    value = args[key]

                    if name.startswith("action_"):
                        name = name[7:]
                        if (name in valid_action_names
                                and name in parsed_action
                                and command.action.type == "message"):
                            value_type = type(parsed_action[name])
                            if value_type is bool:
                                parsed_value = True if value == "1" else False
                            elif value_type is int:
                                try:
                                    parsed_value = int(value)
                                except ValueError:
                                    continue
                            else:
                                parsed_value = value
                            if name == "type":
                                parsed_value = (
                                    "privatemessage" if parsed_value
                                    == "Private Message" else "reply")
                            if name == "functions":
                                if extra_args["user"].level < 1500:
                                    continue
                            parsed_action[name] = parsed_value
                        command.action_json = json.dumps(parsed_action)
                    else:
                        if name in valid_names:
                            value_type = type(getattr(command, name))
                            if value_type is bool:
                                parsed_value = True if value == "1" else False
                            elif value_type is int:
                                try:
                                    parsed_value = int(value)
                                except ValueError:
                                    continue
                            else:
                                parsed_value = value
                            options[name] = parsed_value

            aj = json.loads(command.action_json)
            old_message = ""
            new_message = ""
            try:
                old_message = command.action.response
                new_message = aj["message"]
            except:
                pass
            command.set(**options)
            command.data.set(**options)

            if old_message and len(
                    old_message) > 0 and old_message != new_message:
                log_msg = f'The !{command.aliases[0]} command has been updated from "{old_message}" to "{new_message}"'
            else:
                log_msg = (
                    f"The !{command.aliases[0]} command has been updated")

            AdminLogManager.add_entry(
                "Command edited",
                extra_args["user"].discord_id,
                log_msg,
                data={
                    "old_message": old_message,
                    "new_message": new_message
                },
            )

        if (SocketClientManager.send("command.update",
                                     {"command_id": command_id}) is True):
            return {"success": "good job"}, 200
        else:
            return {"error": "could not push update"}, 500
Ejemplo n.º 18
0
    def banphrases_create(**options):
        session.pop("banphrase_created_id", None)
        session.pop("banphrase_edited_id", None)
        if request.method == "POST":
            id = None
            try:
                if "id" in request.form:
                    id = int(request.form["id"])
                name = request.form["name"].strip()
                permanent = request.form.get("permanent", "off")
                warning = request.form.get("warning", "off")
                notify = request.form.get("notify", "off")
                case_sensitive = request.form.get("case_sensitive", "off")
                sub_immunity = request.form.get("sub_immunity", "off")
                remove_accents = request.form.get("remove_accents", "off")
                length = int(request.form["length"])
                phrase = request.form["phrase"]
                operator = request.form["operator"].strip().lower()
            except (KeyError, ValueError):
                abort(403)

            permanent = permanent == "on"
            warning = warning == "on"
            notify = notify == "on"
            case_sensitive = case_sensitive == "on"
            sub_immunity = sub_immunity == "on"
            remove_accents = remove_accents == "on"

            if not name:
                abort(403)

            if not phrase:
                abort(403)

            if length < 0 or length > 1209600:
                abort(403)

            valid_operators = [
                "contains", "startswith", "endswith", "exact", "regex"
            ]
            if operator not in valid_operators:
                abort(403)

            user = options.get("user", None)

            if user is None:
                abort(403)

            options = {
                "name": name,
                "phrase": phrase,
                "permanent": permanent,
                "warning": warning,
                "notify": notify,
                "case_sensitive": case_sensitive,
                "sub_immunity": sub_immunity,
                "remove_accents": remove_accents,
                "length": length,
                "added_by": user.discord_id,
                "edited_by": user.discord_id,
                "operator": operator,
            }

            if id is None:
                banphrase = Banphrase(**options)
                banphrase.data = BanphraseData(banphrase.id,
                                               added_by=options["added_by"])

            with DBManager.create_session_scope(
                    expire_on_commit=False) as db_session:
                if id is not None:
                    banphrase = (db_session.query(Banphrase).options(
                        joinedload(
                            Banphrase.data)).filter_by(id=id).one_or_none())
                    if banphrase is None:
                        return redirect("/admin/banphrases/", 303)
                    banphrase.set(**options)
                    banphrase.data.set(edited_by=options["edited_by"])
                    log.info(
                        f"Updated banphrase ID {banphrase.id} by user ID {options['edited_by']}"
                    )
                    AdminLogManager.post("Banphrase edited", user.discord_id,
                                         banphrase.id, banphrase.phrase)
                else:
                    db_session.add(banphrase)
                    db_session.add(banphrase.data)
                    db_session.flush()
                    log.info(
                        f"Added a new banphrase by user ID {options['added_by']}"
                    )
                    AdminLogManager.post("Banphrase added", user.discord_id,
                                         banphrase.id, banphrase.phrase)

            SocketClientManager.send("banphrase.update", {"id": banphrase.id})
            if id is None:
                session["banphrase_created_id"] = banphrase.id
            else:
                session["banphrase_edited_id"] = banphrase.id
            return redirect("/admin/banphrases/", 303)
        else:
            return render_template("admin/create_banphrase.html")
Ejemplo n.º 19
0
    def edit_command(bot, author, channel, message, args):
        """Dispatch method for editing commands.
        Usage: !edit command ALIAS [options] RESPONSE
        See greenbot/managers/command.py parse_command_arguments for available options
        """

        if message:
            # Make sure we got both an alias and a response
            message_parts = message.split()
            if len(message_parts) < 2:
                bot.private_message(
                    author, "Usage: !add command ALIAS [options] RESPONSE")
                return False

            options, response = bot.commands.parse_command_arguments(
                message_parts[1:])

            options["edited_by"] = str(author.id)

            if "functions" in options:
                del options["functions"]

            if options is False:
                bot.private_message(author, "Invalid command")
                return False

            alias = message_parts[0].replace("!", "").lower()
            type = "reply"
            if options["privatemessage"] is True:
                type = "privatemessage"
            elif options["reply"] is True:
                type = "reply"
            action = {"type": type, "message": response}

            command = bot.commands.get(alias, None)

            if command is None:
                bot.private_message(
                    author,
                    f"No command found with the alias {alias}. Did you mean to create the command? If so, use !add command instead.",
                )
                return False

            old_message = ""
            new_message = ""

            if len(action["message"]) > 0:
                options["action"] = action
                old_message = command.action.response
                new_message = action["message"]
            elif not type == command.action.subtype:
                options["action"] = {
                    "type": type,
                    "message": command.action.response
                }
            bot.commands.edit_command(command, **options)
            bot.private_message(author,
                                f"Updated the command (ID: {command.id})")

            if len(new_message) > 0:
                log_msg = f'The !{command.command.split("|")[0]} command has been updated from "{old_message}" to "{new_message}"'
            else:
                log_msg = (
                    f"The !{command.command.split('|')[0]} command has been updated"
                )

            AdminLogManager.add_entry(
                "Command edited",
                str(author.id),
                log_msg,
                data={
                    "old_message": old_message,
                    "new_message": new_message
                },
            )
Ejemplo n.º 20
0
    def commands_create(**options):
        session.pop("command_created_id", None)
        session.pop("command_edited_id", None)
        if request.method != "POST":
            return render_template("admin/create_command.html")

        if "aliases" not in request.form:
            abort(403)
        alias_str = request.form.get("aliases", "").replace("!", "").lower()
        delay_all = request.form.get("cd", Command.DEFAULT_CD_ALL)
        delay_user = request.form.get("usercd", Command.DEFAULT_CD_USER)
        level = request.form.get("level", Command.DEFAULT_LEVEL)
        cost = request.form.get("cost", 0)

        try:
            delay_all = int(delay_all)
            delay_user = int(delay_user)
            level = int(level)
            cost = int(cost)
        except ValueError:
            abort(403)

        if not alias_str:
            abort(403)
        if delay_all < 0 or delay_all > 9999:
            abort(403)
        if delay_user < 0 or delay_user > 9999:
            abort(403)
        if level < 0 or level > 2000:
            abort(403)
        if cost < 0 or cost > 9999999:
            abort(403)

        user = options.get("user", None)

        if user is None:
            abort(403)

        options = {
            "delay_all": delay_all,
            "delay_user": delay_user,
            "level": level,
            "cost": cost,
            "added_by": user.discord_id,
        }

        valid_action_types = ["reply", "privatemessage"]
        action_type = request.form.get("type").lower()
        if action_type not in valid_action_types:
            abort(403)

        response = request.form.get("response", "")
        log.info(user.level)
        functions = (
            request.form.get("functions", "").split(" ") if user.level >= 1500 else []
        )
        log.info(functions)

        action = {"type": action_type, "message": response, "functions": functions}
        options["action"] = action

        command_manager = greenbot.managers.command.CommandManager(
            socket_manager=None, module_manager=ModuleManager(None).load(), bot=None
        ).load(enabled=None)

        command_aliases = []

        for alias, command in command_manager.items():
            command_aliases.append(alias)
            if command.command and len(command.command) > 0:
                command_aliases.extend(command.command.split("|"))

        command_aliases = set(command_aliases)

        alias_str = alias_str.replace(" ", "").replace("!", "").lower()
        alias_list = alias_str.split("|")

        alias_list = [alias for alias in alias_list if len(alias) > 0]

        if not alias_list:
            return render_template("admin/create_command_fail.html")
        for alias in alias_list:
            if alias in command_aliases:
                return render_template("admin/create_command_fail.html")

        alias_str = "|".join(alias_list)

        command = Command(command=alias_str, **options)
        command.data = CommandData(command.id, **options)
        log_msg = f"The !{command.command.split('|')[0]} command has been created"
        AdminLogManager.add_entry("Command created", user.discord_id, log_msg)
        with DBManager.create_session_scope(expire_on_commit=False) as db_session:
            db_session.add(command)
            db_session.add(command.data)
            db_session.commit()
            db_session.expunge(command)
            db_session.expunge(command.data)

        SocketClientManager.send("command.update", {"command_id": command.id})
        session["command_created_id"] = command.id
        return redirect("/admin/commands/", 303)
Ejemplo n.º 21
0
    def modules_edit(module_id, **options):
        module_manager = ModuleManager(None).load(do_reload=False)
        current_module = find(lambda m: m.ID == module_id,
                              module_manager.all_modules)

        user = options["user"]

        if user.level < current_module.CONFIGURE_LEVEL:
            return (
                render_template(
                    "errors/403.html",
                    extra_message=
                    "You do not have permission to configure this module.",
                ),
                403,
            )

        if current_module is None:
            return render_template("admin/module_404.html"), 404

        sub_modules = []
        for module in module_manager.all_modules:
            module.db_module = None

        with DBManager.create_session_scope() as db_session:
            for db_module in db_session.query(Module):
                module = find(lambda m: m.ID == db_module.id,
                              module_manager.all_modules)
                if module:
                    module.db_module = db_module
                    if module.PARENT_MODULE == current_module.__class__:
                        sub_modules.append(module)

            if current_module.db_module is None:
                return render_template("admin/module_404.html"), 404

            if request.method != "POST":
                settings = None
                try:
                    settings = json.loads(current_module.db_module.settings)
                except (TypeError, ValueError):
                    pass
                current_module.load(settings=settings)

                return render_template(
                    "admin/configure_module.html",
                    module=current_module,
                    sub_modules=sub_modules,
                )

            form_values = {key: value for key, value in request.form.items()}
            res = current_module.parse_settings(**form_values)
            if res is False:
                return render_template("admin/module_404.html"), 404

            current_module.db_module.settings = json.dumps(res)
            db_session.commit()

            settings = None
            try:
                settings = json.loads(current_module.db_module.settings)
            except (TypeError, ValueError):
                pass
            current_module.load(settings=settings)

            payload = {"id": current_module.db_module.id}

            SocketClientManager.send("module.update", payload)

            AdminLogManager.post("Module edited", user.discord_id,
                                 current_module.NAME)

            return render_template(
                "admin/configure_module.html",
                module=current_module,
                sub_modules=sub_modules,
            )