Exemplo n.º 1
0
 async def ws_message(self):
     async with aiohttp.ClientSession() as session:
         async with session.ws_connect(
                 f"{self.baseurl}/message?sessionKey={self.session_key}"
         ) as ws_connection:
             while True:
                 try:
                     received_data = await ws_connection.receive_json()
                 except TypeError:
                     continue
                 if received_data:
                     NetworkLogger.debug("received", received_data)
                     try:
                         received_data[
                             'messageChain'] = MessageChain.parse_obj(
                                 received_data['messageChain'])
                         received_data = MessageTypes[
                             received_data['type']].parse_obj(received_data)
                     except pydantic.ValidationError:
                         SessionLogger.error(
                             f"parse failed: {received_data}")
                         traceback.print_exc()
                     else:
                         await self.queue.put(
                             InternalEvent(name=self.getEventCurrentName(
                                 type(received_data)),
                                           body=received_data))
Exemplo n.º 2
0
 async def ws_event(self):
     from mirai.event.external.enums import ExternalEvents
     async with aiohttp.ClientSession() as session:
         async with session.ws_connect(
                 f"{self.baseurl}/event?sessionKey={self.session_key}"
         ) as ws_connection:
             while True:
                 try:
                     received_data = await ws_connection.receive_json()
                 except TypeError:
                     continue
                 if received_data:
                     try:
                         if hasattr(ExternalEvents, received_data['type']):
                             received_data = \
                                 ExternalEvents[received_data['type']] \
                                     .value \
                                     .parse_obj(received_data)
                         else:
                             raise exceptions.UnknownEvent(
                                 f"a unknown event has been received, it's '{received_data['type']}'")
                     except pydantic.ValidationError:
                         SessionLogger.error(f"parse failed: {received_data}")
                         traceback.print_exc()
                     else:
                         await self.queue.put(InternalEvent(
                             name=self.getEventCurrentName(type(received_data)),
                             body=received_data
                         ))
Exemplo n.º 3
0
    def run(self, loop=None, no_polling=False, no_forever=False):
        self.checkEventBodyAnnotations()
        self.checkEventDependencies()

        loop = loop or asyncio.get_event_loop()
        self.queue = asyncio.Queue(loop=loop)
        exit_signal = False
        loop.run_until_complete(self.enable_session())
        if not no_polling:
            # check ws status
            if self.useWebsocket:
                SessionLogger.info("event receive method: websocket")
            else:
                SessionLogger.info("event receive method: http polling")

            result = loop.run_until_complete(self.checkWebsocket())
            if not result:  # we can use http, not ws.
                # should use http, but we can change it.
                if self.useWebsocket:
                    SessionLogger.warning("catched wrong config: enableWebsocket=false, we will modify it.")
                    loop.run_until_complete(self.setConfig(enableWebsocket=True))
                    loop.create_task(self.ws_event())
                    loop.create_task(self.ws_message())
                else:
                    loop.create_task(self.message_polling())
            else:  # we can use websocket, it's fine
                if self.useWebsocket:
                    loop.create_task(self.ws_event())
                    loop.create_task(self.ws_message())
                else:
                    SessionLogger.warning("catched wrong config: enableWebsocket=true, we will modify it.")
                    loop.run_until_complete(self.setConfig(enableWebsocket=False))
                    loop.create_task(self.message_polling())
            loop.create_task(self.event_runner())

        if not no_forever:
            for i in self.subroutines:
                loop.create_task(i(self))

        try:
            for start_callable in self.lifecycle['start']:
                loop.run_until_complete(self.run_func(start_callable, self))

            for around_callable in self.lifecycle['around']:
                loop.run_until_complete(self.run_func(around_callable, self))

            loop.run_forever()
        except KeyboardInterrupt:
            SessionLogger.info("catched Ctrl-C, exiting..")
        except Exception as e:
            traceback.print_exc()
        finally:
            for around_callable in self.lifecycle['around']:
                loop.run_until_complete(self.run_func(around_callable, self))

            for end_callable in self.lifecycle['end']:
                loop.run_until_complete(self.run_func(end_callable, self))

            loop.run_until_complete(self.release())
Exemplo n.º 4
0
    def run(self, loop=None):
        self.checkEventBodyAnnotations()
        self.checkEventDependencies()

        loop = loop or asyncio.get_event_loop()
        queue = asyncio.Queue(loop=loop)
        exit_signal = False
        loop.run_until_complete(self.enable_session())
        loop.create_task(self.message_polling(lambda: exit_signal, queue))
        loop.create_task(self.event_runner(lambda: exit_signal, queue))
        for i in self.run_forever_target:
            loop.create_task(i(self))

        try:
            loop.run_forever()
        except KeyboardInterrupt:
            SessionLogger.info("catched Ctrl-C, exiting..")
        finally:
            loop.run_until_complete(self.release())
            loop.run_until_complete(session.close())
Exemplo n.º 5
0
    async def ws_event_receiver(self, exit_signal, queue):
        await self.checkWebsocket(force=True)
        async with aiohttp.ClientSession() as session:
            async with session.ws_connect(
                    f"{self.baseurl}/all?sessionKey={self.session_key}"
            ) as ws_connection:
                while not exit_signal():
                    try:
                        received_data = await ws_connection.receive_json()
                    except TypeError:
                        if not exit_signal():
                            continue
                        else:
                            break
                    if received_data:
                        try:
                            if received_data['type'] in MessageTypes:
                                if 'messageChain' in received_data:
                                    received_data['messageChain'] = \
                                      MessageChain.parse_obj(received_data['messageChain'])

                                received_data = \
                                  MessageTypes[received_data['type']].parse_obj(received_data)

                            elif hasattr(ExternalEvents,
                                         received_data['type']):
                                # 判断当前项是否为 Event
                                received_data = \
                                  ExternalEvents[received_data['type']]\
                                    .value\
                                    .parse_obj(received_data)
                        except pydantic.ValidationError:
                            SessionLogger.error(
                                f"parse failed: {received_data}")
                            traceback.print_exc()
                        else:
                            await queue.put(
                                InternalEvent(name=self.getEventCurrentName(
                                    type(received_data)),
                                              body=received_data))
Exemplo n.º 6
0
  def __init__(self,
    app: Mirai,
    listen_events: List[str] = [
      "FriendMessage",
      "GroupMessage"
    ],
    command_prefix: List[str] = [">"],
    global_dependencies: List[Depend] = [],
    global_middlewares: List = []
  ):
    self.application = app
    self.listen_events = listen_events
    self.command_prefix = [re.escape(i) for i in command_prefix]

    self.global_dependencies = global_dependencies
    self.global_middlewares = global_middlewares
    if "^/" in self.command_prefix:
      SessionLogger.warn("you shouldn't use '/' as a prefix, because it's used by mirai-console...")
      SessionLogger.warn("ok, we will support '/' as a prefix in the future..")
    
    if "GroupMessage" in listen_events:
      app.receiver("GroupMessage")(self.GroupMessageListener)
    if "FriendMessage" in listen_events:
      app.receiver("FriendMessage")(self.FriendMessageListener)
Exemplo n.º 7
0
    def run(self, loop=None, no_polling=False, no_forever=False):
        self.checkEventBodyAnnotations()
        self.checkEventDependencies()

        loop = loop or asyncio.get_event_loop()
        self.queue = queue = asyncio.Queue(loop=loop)
        exit_signal = False
        loop.run_until_complete(self.enable_session())
        if not no_polling:
            if not self.useWebsocket:
                SessionLogger.warning(
                    "http's fetchMessage is disabled in mirai-api-http 1.2.1(it's a bug :P)."
                )
                SessionLogger.warning("so, you can use WebSocket.")
                SessionLogger.warning(
                    "if it throw a unexpected error, you should call the httpapi's author."
                )
                loop.create_task(
                    self.message_polling(lambda: exit_signal, queue))
            else:
                SessionLogger.warning(
                    "you are using WebSocket, it's a experimental method.")
                SessionLogger.warning(
                    "but, websocket is remember way to fetch message and event,"
                )
                SessionLogger.warning(
                    "and http's fetchMessage is disabled in mirai-api-http 1.2.1(it's a bug :P)."
                )
                SessionLogger.warning(
                    "if it throw a unexpected error, you can call the httpapi's author."
                )
                loop.create_task(
                    self.ws_event_receiver(lambda: exit_signal, queue))
            loop.create_task(self.event_runner(lambda: exit_signal, queue))

        if not no_forever:
            for i in self.subroutines:
                loop.create_task(i(self))

        try:
            loop.run_forever()
        except KeyboardInterrupt:
            SessionLogger.info("catched Ctrl-C, exiting..")
        finally:
            loop.run_until_complete(self.release())
            loop.run_until_complete(session.close())
Exemplo n.º 8
0
    async def main_entrance(self, run_body, event_context, queue):
        if isinstance(run_body, dict):
            callable_target = run_body['func']
            for depend in run_body['dependencies']:
                if not inspect.isclass(depend.func):
                    depend_func = depend.func
                elif hasattr(depend.func, "__call__"):
                    depend_func = depend.func.__call__
                else:
                    raise TypeError("must be callable.")

                await self.main_entrance(
                    {
                        "func": depend_func,
                        "middlewares": depend.middlewares,
                        "dependencies": []
                    }, event_context, queue)
        else:
            if inspect.isclass(run_body):
                if hasattr(run_body, "__call__"):
                    run_body = run_body.__call__
                else:
                    raise TypeError("must be callable.")
            else:
                callable_target = run_body

        translated_mapping = {
            **(await self.argument_compiler(callable_target, event_context)),
            **(await self.signature_checkout(callable_target, event_context, queue))
        }

        try:
            if isinstance(run_body, dict):
                middlewares = run_body.get("middlewares")
                if middlewares:
                    async_middlewares = []
                    normal_middlewares = []

                    for middleware in middlewares:
                        if all([
                                hasattr(middleware, "__aenter__"),
                                hasattr(middleware, "__aexit__")
                        ]):
                            async_middlewares.append(middleware)
                        elif all([
                                hasattr(middleware, "__enter__"),
                                hasattr(middleware, "__exit__")
                        ]):
                            normal_middlewares.append(middleware)
                        else:
                            SessionLogger.error(
                                f"threw a exception by {event_context.name}, no currect context error."
                            )
                            raise AttributeError(
                                "no a currect context object.")

                    async with contextlib.AsyncExitStack() as async_stack:
                        for async_middleware in async_middlewares:
                            SessionLogger.debug(
                                f"a event called {event_context.name}, enter a currect async context."
                            )
                            await async_stack.enter_async_context(
                                async_middleware)

                        with contextlib.ExitStack() as normal_stack:
                            for normal_middleware in normal_middlewares:
                                SessionLogger.debug(
                                    f"a event called {event_context.name}, enter a currect context."
                                )
                                normal_stack.enter_context(normal_middleware)

                            if inspect.iscoroutinefunction(callable_target):
                                return await callable_target(
                                    **translated_mapping)
                            else:
                                return callable_target(**translated_mapping)
                else:
                    if inspect.iscoroutinefunction(callable_target):
                        return await callable_target(**translated_mapping)
                    else:
                        return callable_target(**translated_mapping)
            else:
                if inspect.iscoroutinefunction(callable_target):
                    return await callable_target(**translated_mapping)
                else:
                    return callable_target(**translated_mapping)
        except (NameError, TypeError) as e:
            EventLogger.error(
                f"threw a exception by {event_context.name}, it's about Annotations Checker, please report to developer."
            )
            traceback.print_exc()
        except Exception as e:
            EventLogger.error(
                f"threw a exception by {event_context.name}, and it's {e}")
            await self.throw_exception_event(event_context, queue, e)