Ejemplo n.º 1
0
def _initialize(bot):
    bot.spawn_lock = asyncio.Lock()
    config = bot.get_config_option("spawn")
    if not config:
        return

    cmds = config.get("commands")

    # override the load logic and register our commands directly
    for cmd in cmds:
        command.register(_spawn, admin=True, final=True, name=cmd)

    logger.info("spawn - %s", ", ".join(['*' + cmd for cmd in cmds]))
    plugins.register_admin_command(list(cmds))
Ejemplo n.º 2
0
def _initialize(bot):
    bot.spawn_lock = asyncio.Lock()
    config = bot.get_config_option("spawn")
    if not config:
        return

    cmds = config.get("commands")

    # override the load logic and register our commands directly
    for cmd in cmds:
        command.register(_spawn, admin=True, final=True, name=cmd)

    logger.info("spawn - %s", ", ".join(['*' + cmd for cmd in cmds]))
    plugins.register_admin_command(list(cmds))
Ejemplo n.º 3
0
def _initialize(bot):
    bot.spawn_lock = asyncio.Lock()
    config = bot.get_config_option("spawn")
    if not config:
        return

    cmds = config.get("commands")

    # override the load logic and register our commands directly
    get_location = False
    for cmd, cnf in cmds.items():
        command.register(_spawn, admin=True, final=True, name=cmd)
        if cnf.get("allow_location"):
            get_location = True

    logger.info("spawn - %s", ", ".join(['*' + cmd for cmd in cmds]))
    plugins.register_admin_command(list(cmds))

    if get_location:
        global _MAP_MATCH
        _MAP_MATCH = re.compile(config.get("map_regex", _MAP_REGEX), re.IGNORECASE|re.MULTILINE)
        plugins.register_handler(_location_handler, type="message")
Ejemplo n.º 4
0
def _initialize(bot):
    bot.spawn_lock = asyncio.Lock()
    config = bot.get_config_option("spawn")
    if not config:
        return

    cmds = config.get("commands")

    # override the load logic and register our commands directly
    get_location = False
    for cmd, cnf in cmds.items():
        command.register(_spawn, admin=True, final=True, name=cmd)
        if cnf.get("allow_location"):
            get_location = True

    logger.info("spawn - %s", ", ".join(['*' + cmd for cmd in cmds]))
    plugins.register_admin_command(list(cmds))

    if get_location:
        global _MAP_MATCH
        _MAP_MATCH = re.compile(config.get("map_regex", _MAP_REGEX), re.IGNORECASE|re.MULTILINE)
        plugins.register_handler(_location_handler, type="message")
Ejemplo n.º 5
0
def load(bot, module_path, module_name=None):
    """loads a single plugin-like object as identified by module_path, and initialise it"""

    if module_name is None:
        module_name = module_path.split(".")[-1]

    if module_path in tracking.list:
        raise RuntimeError("{} already loaded".format(module_path))

    tracking.start({"module": module_name, "module.path": module_path})

    try:
        if module_path in sys.modules:
            importlib.reload(sys.modules[module_path])
            logger.debug("reloading {}".format(module_path))

        else:
            importlib.import_module(module_path)
            logger.debug("importing {}".format(module_path))

    except Exception as e:
        logger.exception(
            "EXCEPTION during plugin import: {}".format(module_path))
        return

    if hasattr(sys.modules[module_path], 'hangups'):
        logger.info("{} has legacy hangups reference".format(module_name))
        setattr(sys.modules[module_path], 'hangups', hangups_shim)

    public_functions = [
        o for o in getmembers(sys.modules[module_path], isfunction)
    ]

    candidate_commands = []
    """pass 1: run optional callable: _initialise, _initialize
    * performs house-keeping tasks (e.g. migration, tear-up, pre-init, etc)
    * registers user and/or admin commands
    """
    available_commands = False  # default: ALL
    try:
        for function_name, the_function in public_functions:
            if function_name == "_initialise" or function_name == "_initialize":
                """accepted function signatures:
                CURRENT
                version >= 2.4 | function()
                version >= 2.4 | function(bot) - parameter must be named "bot"
                LEGACY
                version <= 2.4 | function(handlers, bot)
                ancient        | function(handlers)
                """
                _expected = list(inspect.signature(the_function).parameters)
                if len(_expected) == 0:
                    the_function()
                    _return = []
                elif len(_expected) == 1 and _expected[0] == "bot":
                    the_function(bot)
                    _return = []
                else:
                    try:
                        # legacy support, pre-2.4
                        logger.info(
                            "[LEGACY] upgrade {1}.{0}(handlers, bot) to {0}(bot) and use bot._handlers internally"
                            .format(the_function.__name__, module_path))

                        _return = the_function(bot._handlers, bot)
                    except TypeError as e:
                        # DEPRECATED: ancient plugins
                        logger.warning(
                            "[DEPRECATED] upgrade {1}.{0}(handlers) to {0}(bot) and use bot._handlers internally"
                            .format(the_function.__name__, module_path))

                        _return = the_function(bot._handlers)
                if type(_return) is list:
                    available_commands = _return
            elif function_name.startswith("_"):
                pass
            else:
                candidate_commands.append((function_name, the_function))
        if available_commands is False:
            # implicit init, legacy support: assume all candidate_commands are user-available
            register_user_command([
                function_name for function_name, function in candidate_commands
            ])
        elif available_commands is []:
            # explicit init, no user-available commands
            pass
        else:
            # explicit init, legacy support: _initialise() returned user-available commands
            register_user_command(available_commands)
    except Exception as e:
        logger.exception(
            "EXCEPTION during plugin init: {}".format(module_path))
        return  # skip this, attempt next plugin
    """
    pass 2: register filtered functions
    tracking.current() and the CommandDispatcher registers might be out of sync if a 
    combination of decorators and register_user_command/register_admin_command is used since
    decorators execute immediately upon import
    """
    plugin_tracking = tracking.current()

    explicit_admin_commands = plugin_tracking["commands"]["admin"]
    all_commands = plugin_tracking["commands"]["all"]
    registered_commands = []
    for function_name, the_function in candidate_commands:
        if function_name in all_commands:
            is_admin = False
            text_function_name = function_name
            if function_name in explicit_admin_commands:
                is_admin = True
                text_function_name = "*" + text_function_name

            command.register(the_function, admin=is_admin, final=True)

            registered_commands.append(text_function_name)

    if registered_commands:
        logger.info("{} - {}".format(module_name,
                                     ", ".join(registered_commands)))
    else:
        logger.info("{} - no commands".format(module_name))

    tracking.end()

    return True
Ejemplo n.º 6
0
def load(bot, module_path, module_name=None):
    """loads a single plugin-like object as identified by module_path, and initialise it"""

    if module_name is None:
        module_name = module_path.split(".")[-1]

    if module_path in tracking.list:
        raise RuntimeError("{} already loaded".format(module_path))

    tracking.start({ "module": module_name, "module.path": module_path })

    try:
        if module_path in sys.modules:
            importlib.reload(sys.modules[module_path])
            logger.debug("reloading {}".format(module_path))

        else:
            importlib.import_module(module_path)
            logger.debug("importing {}".format(module_path))

    except Exception as e:
        logger.exception("EXCEPTION during plugin import: {}".format(module_path))
        return

    public_functions = [o for o in getmembers(sys.modules[module_path], isfunction)]

    candidate_commands = []

    """pass 1: run optional callable: _initialise, _initialize
    * performs house-keeping tasks (e.g. migration, tear-up, pre-init, etc)
    * registers user and/or admin commands
    """
    available_commands = False # default: ALL
    try:
        for function_name, the_function in public_functions:
            if function_name ==  "_initialise" or function_name ==  "_initialize":
                """accepted function signatures:
                CURRENT
                version >= 2.4 | function()
                version >= 2.4 | function(bot) - parameter must be named "bot"
                LEGACY
                version <= 2.4 | function(handlers, bot)
                ancient        | function(handlers)
                """
                _expected = list(inspect.signature(the_function).parameters)
                if len(_expected) == 0:
                    the_function()
                    _return = []
                elif len(_expected) == 1 and _expected[0] == "bot":
                    the_function(bot)
                    _return = []
                else:
                    try:
                        # legacy support, pre-2.4
                        logger.info("[LEGACY] upgrade {1}.{0}(handlers, bot) to {0}(bot) and use bot._handlers internally"
                            .format(the_function.__name__, module_path))

                        _return = the_function(bot._handlers, bot)
                    except TypeError as e:
                        # DEPRECATED: ancient plugins
                        logger.warning("[DEPRECATED] upgrade {1}.{0}(handlers) to {0}(bot) and use bot._handlers internally"
                            .format(the_function.__name__, module_path))

                        _return = the_function(bot._handlers)
                if type(_return) is list:
                    available_commands = _return
            elif function_name.startswith("_"):
                pass
            else:
                candidate_commands.append((function_name, the_function))
        if available_commands is False:
            # implicit init, legacy support: assume all candidate_commands are user-available
            register_user_command([function_name for function_name, function in candidate_commands])
        elif available_commands is []:
            # explicit init, no user-available commands
            pass
        else:
            # explicit init, legacy support: _initialise() returned user-available commands
            register_user_command(available_commands)
    except Exception as e:
        logger.exception("EXCEPTION during plugin init: {}".format(module_path))
        return # skip this, attempt next plugin

    """
    pass 2: register filtered functions
    tracking.current() and the CommandDispatcher registers might be out of sync if a 
    combination of decorators and register_user_command/register_admin_command is used since
    decorators execute immediately upon import
    """
    plugin_tracking = tracking.current()

    explicit_admin_commands = plugin_tracking["commands"]["admin"]
    all_commands = plugin_tracking["commands"]["all"]
    registered_commands = []
    for function_name, the_function in candidate_commands:
        if function_name in all_commands:
            is_admin = False
            text_function_name = function_name
            if function_name in explicit_admin_commands:
                is_admin = True
                text_function_name = "*" + text_function_name

            command.register(the_function, admin=is_admin, final=True)

            registered_commands.append(text_function_name)

    if registered_commands:
        logger.info("{} - {}".format(module_name, ", ".join(registered_commands)))
    else:
        logger.info("{} - no commands".format(module_name))

    tracking.end()

    return True
Ejemplo n.º 7
0
async def load(bot, module_path, module_name=None):
    """loads a single plugin-like object as identified by module_path

    Args:
        bot: HangupsBot instance
        module_path: string, python import style relative to the main script
        module_name: string, custom name

    Returns:
        boolean, True if the plugin was loaded successfully

    Raises:
        AssertionError: the plugin is already loaded
    """
    module_name = module_name or module_path.split(".")[-1]

    assert module_path not in tracking.list

    await tracking.start({"module": module_name, "module.path": module_path})

    if not load_module(module_path):
        tracking.end()
        return False

    setattr(sys.modules[module_path], 'print', utils.print_to_logger)
    if hasattr(sys.modules[module_path], "hangups_shim"):
        logger.info("%s has legacy hangups reference", module_name)

    public_functions = list(getmembers(sys.modules[module_path], isfunction))

    candidate_commands = []

    # run optional callable _initialise or _initialize and cature
    try:
        for function_name, the_function in public_functions:
            if function_name not in ("_initialise", "_initialize"):
                if not function_name.startswith("_"):
                    # skip private functions
                    candidate_commands.append(
                        (function_name.lower(), the_function))
                continue

            # accepted function signatures:
            # coro/function()
            # coro/function(bot) - parameter must be named "bot"
            expected = list(inspect.signature(the_function).parameters)
            if len(expected) > 1 or (expected and expected[0] != "bot"):
                # plugin not updated since v2.4
                logger.warning("%s of %s does not comply with the current "
                               "initialize standard!",
                               function_name, module_path)
                continue

            result = the_function(bot) if expected else the_function()
            if asyncio.iscoroutinefunction(the_function):
                await result

    except:             # capture all Exceptions   # pylint: disable=bare-except
        logger.exception("error on plugin init: %s", module_path)
        return False

    # register filtered functions
    # tracking.current and the CommandDispatcher might be out of sync if a
    #  combination of decorators and register_{admin, user}_command
    #  is used since decorators execute immediately upon import
    plugin_tracking = tracking.current

    explicit_admin_commands = plugin_tracking["commands"]["admin"]
    all_commands = plugin_tracking["commands"]["all"]
    registered_commands = []

    for function_name, the_function in candidate_commands:
        if function_name not in all_commands:
            continue

        is_admin = False
        text_function_name = function_name
        if function_name in explicit_admin_commands:
            is_admin = True
            text_function_name = "*" + text_function_name

        command.register(the_function, admin=is_admin, final=True)

        registered_commands.append(text_function_name)

    logger.debug("%s - %s", module_name,
                 ", ".join(registered_commands) or "no commands")

    tracking.end()
    return True
Ejemplo n.º 8
0
    def _load_plugins(self):
        plugin_list = self.get_config_option('plugins')
        if plugin_list is None:
            print(_("HangupsBot: config.plugins is not defined, using ALL"))
            plugin_path = os.path.dirname(os.path.realpath(sys.argv[0])) + os.sep + "plugins"
            plugin_list = [ os.path.splitext(f)[0]  # take only base name (no extension)...
                for f in os.listdir(plugin_path)    # ...by iterating through each node in the plugin_path...
                    if os.path.isfile(os.path.join(plugin_path,f))
                        and not f.startswith(("_", ".")) # ...that does not start with _ .
                        and f.endswith(".py")] # ...and must end with .py

        for module in plugin_list:
            module_path = "plugins.{}".format(module)

            try:
                exec("import {}".format(module_path))
            except Exception as e:
                message = "{} @ {}".format(e, module_path)
                print(_("EXCEPTION during plugin import: {}").format(message))
                logging.exception(message)
                continue

            print(_("plugin: {}").format(module))
            public_functions = [o for o in getmembers(sys.modules[module_path], isfunction)]

            candidate_commands = []

            """
            pass 1: run _initialise()/_initialize() and filter out "hidden" functions

            legacy notice:
            older plugins will return a list of user-available functions via _initialise/_initialize().
            this LEGACY behaviour will continue to be supported. however, it is HIGHLY RECOMMENDED to
            use register_user_command(<LIST command_names>) and register_admin_command(<LIST command_names>)
            for better security
            """
            available_commands = False # default: ALL
            try:
                self._handlers.plugin_preinit_stats((module, module_path))
                for function_name, the_function in public_functions:
                    if function_name ==  "_initialise" or function_name ==  "_initialize":
                        try:
                            _return = the_function(self._handlers, bot=self)
                        except TypeError as e:
                            # implement legacy support for plugins that don't support the bot reference
                            _return = the_function(self._handlers)
                        if type(_return) is list:
                            available_commands = _return
                    elif function_name.startswith("_"):
                        pass
                    else:
                        candidate_commands.append((function_name, the_function))
                if available_commands is False:
                    # implicit init, legacy support: assume all candidate_commands are user-available
                    self._handlers.register_user_command([function_name for function_name, function in candidate_commands])
                elif available_commands is []:
                    # explicit init, no user-available commands
                    pass
                else:
                    # explicit init, legacy support: _initialise() returned user-available commands
                    self._handlers.register_user_command(available_commands)
            except Exception as e:
                message = "{} @ {}".format(e, module_path)
                print(_("EXCEPTION during plugin init: {}").format(message))
                logging.exception(message)
                continue # skip this, attempt next plugin

            """
            pass 2: register filtered functions
            """
            plugin_tracking = self._handlers.plugin_get_stats()
            explicit_admin_commands = plugin_tracking["commands"]["admin"]
            all_commands = plugin_tracking["commands"]["all"]
            registered_commands = []
            for function_name, the_function in candidate_commands:
                if function_name in all_commands:
                    command.register(the_function)
                    text_function_name = function_name
                    if function_name in explicit_admin_commands:
                        text_function_name = "*" + text_function_name
                    registered_commands.append(text_function_name)

            if registered_commands:
                print(_("added: {}").format(", ".join(registered_commands)))

        self._handlers.all_plugins_loaded()
Ejemplo n.º 9
0
    def _load_plugins(self):
        plugin_list = self.get_config_option('plugins')
        if plugin_list is None:
            print(_("HangupsBot: config.plugins is not defined, using ALL"))
            plugin_path = os.path.dirname(os.path.realpath(sys.argv[0])) + os.sep + "plugins"
            plugin_list = [ os.path.splitext(f)[0]  # take only base name (no extension)...
                for f in os.listdir(plugin_path)    # ...by iterating through each node in the plugin_path...
                    if os.path.isfile(os.path.join(plugin_path,f))
                        and not f.startswith(("_", ".")) # ...that does not start with _ .
                        and f.endswith(".py")] # ...and must end with .py

        for module in plugin_list:
            module_path = "plugins.{}".format(module)

            try:
                exec("import {}".format(module_path))
            except Exception as e:
                message = "{} @ {}".format(e, module_path)
                print(_("EXCEPTION during plugin import: {}").format(message))
                logging.exception(message)
                continue

            print(_("plugin: {}").format(module))
            public_functions = [o for o in getmembers(sys.modules[module_path], isfunction)]

            candidate_commands = []

            """
            pass 1: run _initialise()/_initialize() and filter out "hidden" functions

            legacy notice:
            older plugins will return a list of user-available functions via _initialise/_initialize().
            this LEGACY behaviour will continue to be supported. however, it is HIGHLY RECOMMENDED to
            use register_user_command(<LIST command_names>) and register_admin_command(<LIST command_names>)
            for better security
            """
            available_commands = False # default: ALL
            try:
                self._handlers.plugin_preinit_stats((module, module_path))
                for function_name, the_function in public_functions:
                    if function_name ==  "_initialise" or function_name ==  "_initialize":
                        try:
                            _return = the_function(self._handlers, bot=self)
                        except TypeError as e:
                            # implement legacy support for plugins that don't support the bot reference
                            _return = the_function(self._handlers)
                        if type(_return) is list:
                            available_commands = _return
                    elif function_name.startswith("_"):
                        pass
                    else:
                        candidate_commands.append((function_name, the_function))
                if available_commands is False:
                    # implicit init, legacy support: assume all candidate_commands are user-available
                    self._handlers.register_user_command([function_name for function_name, function in candidate_commands])
                elif available_commands is []:
                    # explicit init, no user-available commands
                    pass
                else:
                    # explicit init, legacy support: _initialise() returned user-available commands
                    self._handlers.register_user_command(available_commands)
            except Exception as e:
                message = "{} @ {}".format(e, module_path)
                print(_("EXCEPTION during plugin init: {}").format(message))
                logging.exception(message)
                continue # skip this, attempt next plugin

            """
            pass 2: register filtered functions
            """
            plugin_tracking = self._handlers.plugin_get_stats()
            explicit_admin_commands = plugin_tracking["commands"]["admin"]
            all_commands = plugin_tracking["commands"]["all"]
            registered_commands = []
            for function_name, the_function in candidate_commands:
                if function_name in all_commands:
                    command.register(the_function)
                    text_function_name = function_name
                    if function_name in explicit_admin_commands:
                        text_function_name = "*" + text_function_name
                    registered_commands.append(text_function_name)

            if registered_commands:
                print(_("added: {}").format(", ".join(registered_commands)))

        self._handlers.all_plugins_loaded()