Example #1
0
    async def relogin(self, sleep=5, retries=None):
        self._ok = False
        unregister_session(self.qq)
        _retries = 0
        while not retries or _retries < retries:
            _retries += 1
            try:
                new_session_key = await self._auth()
                if not new_session_key:
                    raise ApiError(Code.Unavailable)

                self._session_key = new_session_key
                self._api.update_session(new_session_key)

                res = await self._api.verify(qq=self._qq)
                if not res or res.get('code') != 0:
                    raise ApiError(Code.Unavailable, "Verify failed")

                if self._enable_ws:
                    asyncio.create_task(self.set_report_ws())
                return True

            except ApiError as e:
                logger.info(
                    f'Failed to login by {e}, retry in {sleep}s or exit ...')
                await asyncio.sleep(sleep)
Example #2
0
    async def connect(self):
        retries = 0
        session_key = await self._auth()
        while not session_key and (retries < self._max_retries
                                   or self._max_retries < 0):
            retries += 1
            logger.info(
                f"Connection failed. Retrying {retries}th time in {self._retry_interval}s ..."
            )
            await asyncio.sleep(self._retry_interval)
            session_key = await self._auth()

        if not session_key:
            logger.critical(f"Connection failed. Exiting ...")
            return

        self._session_key = session_key
        self._api = api.HttpApi(self._api_root, session_key, 30)

        res = await self._api.verify(qq=self._qq)
        if not res or res.get('code') != 0:
            raise api.ApiError(api.Code.Unavailable, "Verify Failed")

        self._ok = True
        register_session(self, self.qq)

        if self._enable_ws:
            asyncio.create_task(self.set_report_ws())
        if self._enable_poll:
            asyncio.create_task(self.set_poll())
Example #3
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
Example #4
0
 async def _auth(self):
     try:
         async with aiohttp.request("POST",
                                    self._api_root + 'auth',
                                    json={'authKey':
                                          self._auth_key}) as resp:
             if 200 <= resp.status < 300:
                 result = json.loads(await resp.text())
                 logger.info(f'Login Mirai: {result}')
                 if result.get('code') == 0:
                     return result['session']
     except Exception as e:
         logger.error(e)
         return
Example #5
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))
Example #6
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
Example #7
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))
Example #8
0
 def add_service(self, service):
     self.services[service.name] = service
     logger.info(f'Succeeded to load Service "{service.key}" ')