Пример #1
0
async def handle_event(source: EventProvider, event: Event, **kwargs):
    """Handle a event received from protocol

    To avoid blocking awaiting, creating a task to run this

    :param source:
    :param event:
    :return:
    """
    if not isinstance(event, Event):
        logger.error(f'A non-event {event} passed to handle_event!')
        return

    logger.debug(f'Handling {event.type} {event}')

    res = []

    async for result in engine.forward(event=event, source=source, **kwargs):
        if isinstance(result, Exception):
            try:
                raise result
            except Exception as e:
                logger.error(f'Error handling event {event} {e}')
                logger.exception(e)
        elif result:
            res.append(result)

    return res
Пример #2
0
async def load_plugin(*,
                      module_path: str = None,
                      plugin_dir: str = None) -> Optional[Plugin]:
    """Load a Plugin by Plugin module path or Plugin directory

    :param module_path:
    :param plugin_dir:
    :return:
    """
    if not plugin_dir:
        if not module_path:
            raise ValueError()
        elif module_path.startswith('.'):
            plugin_dir = '.' + module_path.replace('.', '/')
        else:
            plugin_dir = './' + module_path.replace('.', '/')
    else:
        if plugin_dir.startswith('.'):
            module_path = plugin_dir.replace('/', '.')[1:]
        else:
            module_path = plugin_dir.replace('/', '.')

    logger.info(f'Loading Plugin {module_path} from {plugin_dir} ...')

    try:
        plugin_info_path = os.path.join(os.path.expanduser(plugin_dir),
                                        ajenga.config.PLUGIN_INFO_FILE)
        with open(plugin_info_path, encoding='utf-8') as f:
            plugin_info = json.load(f)

        if plugin_info.get('name') and get_plugin(plugin_info['name']):
            logger.error(f'Plugin {plugin_info["name"]} already exists')
            return None
        plugin = Plugin(plugin_info, path=module_path)
        set_current_plugin(plugin)
        add_plugin(plugin)
    except Exception as e:
        logger.exception(e)
        logger.error(f'Failed to load Plugin config from {plugin_dir}')
        return None

    try:
        module = importlib.import_module(module_path)
        plugin.load(module)
        add_plugin(plugin, True)
    except Exception as e:
        logger.exception(e)
        logger.error(f'Failed to load Plugin module from {module_path}')
        await unload_plugin(plugin, True)
        return None

    await meta_provider.send(MetaEvent(MetaEventType.PluginLoad,
                                       plugin=plugin))
    meta_provider.send_nowait(
        MetaEvent(MetaEventType.PluginLoaded, plugin=plugin))

    logger.info(f'Succeeded to load Plugin "{plugin.name}"')
    return plugin
Пример #3
0
def _load_service_config(service_key):
    config_file = os.path.join(_service_config_dir, f'{service_key}.json')
    if not os.path.exists(config_file):
        return {}  # config file not found, return default config.
    try:
        with open(config_file, encoding='utf8') as f:
            config = json.load(f)
            return config
    except Exception as e:
        logger.exception(e)
        return {}
Пример #4
0
    async def wrapper(self, *args, **kwargs):
        while True:
            try:
                return await func(self, *args, **kwargs)
            except ApiError as e:
                if e.code == ApiError.CODE_SESSION_FAILED:
                    logger.info('Re-login Mirai')

                    if not await self.relogin():
                        return ApiResult(Code.Unavailable)

                    if await self._api.verify(qq=self.qq):
                        logger.info('Re-login Success')
                        continue
                    else:
                        return ApiResult(Code.Unavailable)
                else:
                    return ApiResult(e.code)
            except Exception as e:
                logger.exception(e)
                return ApiResult(Code.Unspecified, message=str(e))
Пример #5
0
async def unload_plugin(key: Union[str, Plugin], forced: bool = False) -> bool:
    """Unload a Plugin

    :param key: Plugin object or module path or name
    :param forced: Forced to unload
    :return: Success or not
    """
    plugin = get_plugin(key) if isinstance(key, str) else key
    if not plugin:
        logger.warning(f"Plugin {key} not exists")
        return False

    plugin_name = plugin.name

    await meta_provider.send(
        MetaEvent(MetaEventType.PluginUnload, plugin=plugin))

    for service in plugin.services.values():
        try:
            remove_service(service)
        except Exception as e:
            logger.exception(e)
            logger.error(f'Failed to unload service "{service}", error: {e}')

    result = remove_plugin(plugin)
    if not result and not forced:
        return False

    if plugin.path:
        for module in list(
                filter(lambda x: x.startswith(plugin.path),
                       sys.modules.keys())):
            del sys.modules[module]

    meta_provider.send_nowait(
        MetaEvent(MetaEventType.PluginUnloaded, plugin=plugin))

    logger.info(f'Succeeded to unload Plugin "{plugin_name}"')
    return True
Пример #6
0
    async def wrapper(self, *args, **kwargs):
        try:
            return await func(self, *args, **kwargs)
        except Exception as e:
            logger.exception(e)
            if (not _ALLOW_RETRY):
                if isinstance(self, CQSession):
                    self.handle_event_nowait(
                        ApiNotSuccessfulEvent(func.__name__, self.qq, args,
                                              kwargs))
                return ApiResult(Code.Unspecified, message=str(e))

            logger.info("Retrying...")
            try:
                return await func(*args, **kwargs)
            except Exception as e:
                logger.exception(e)
                logger.error("Retrying failed")
                if isinstance(self, CQSession):
                    self.handle_event_nowait(
                        ApiNotSuccessfulEvent(func.__name__, self.qq, args,
                                              kwargs))
                return ApiResult(Code.Unspecified, message=str(e))