예제 #1
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
                         ))
예제 #2
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))
예제 #3
0
    async def message_polling(self, count=10):
        while True:
            await asyncio.sleep(0.5)

            try:
                result = \
                    await super().fetchMessage(count)
            except pydantic.ValidationError:
                continue
            last_length = len(result)
            latest_result = []
            while True:
                if last_length == count:
                    latest_result = await super().fetchMessage(count)
                    last_length = len(latest_result)
                    result += latest_result
                    continue
                break

            for message_index in range(len(result)):
                item = result[message_index]
                await self.queue.put(
                    InternalEvent(
                        name=self.getEventCurrentName(type(item)),
                        body=item
                    )
                )
예제 #4
0
 async def warpper(app: "Mirai"):
     try:
         return await func(app)
     except Exception as e:
         await self.queue.put(
             InternalEvent(name="UnexpectedException",
                           body=UnexpectedException(error=e,
                                                    event=None,
                                                    session=self)))
예제 #5
0
 async def throw_exception_event(self, event_context, queue, exception):
     if event_context.name != "UnexpectedException":
         #print("error: by pre:", event_context.name)
         await queue.put(
             InternalEvent(name="UnexpectedException",
                           body=UnexpectedException(error=exception,
                                                    event=event_context,
                                                    session=self)))
         EventLogger.error(
             f"threw a exception by {event_context.name}, Exception: {exception}"
         )
         traceback.print_exc()
     else:
         EventLogger.critical(
             f"threw a exception by {event_context.name}, Exception: {exception}, it's a exception handler."
         )
예제 #6
0
 async def put_exception(self, event_context, exception):
     from mirai.event.builtins import UnexpectedException
     if event_context.name != "UnexpectedException":
         if exception.__class__ in self.listening_exceptions:
             EventLogger.error(
                 f"threw a exception by {event_context.name}, Exception: {exception.__class__.__name__}, and it has been catched.")
         else:
             EventLogger.error(
                 f"threw a exception by {event_context.name}, Exception: {exception.__class__.__name__}, and it hasn't been catched!")
             traceback.print_exc()
         await self.queue.put(InternalEvent(
             name="UnexpectedException",
             body=UnexpectedException(
                 error=exception,
                 event=event_context,
                 application=self
             )
         ))
     else:
         EventLogger.critical(
             f"threw a exception in a exception handler by {event_context.name}, Exception: {exception.__class__.__name__}.")
예제 #7
0
    async def message_polling(self, exit_signal, queue, count=10):
        while not exit_signal():
            await asyncio.sleep(0.5)

            result  = \
              await super().fetchMessage(count)
            last_length = len(result)
            latest_result = []
            while True:
                if last_length == count:
                    latest_result = await super().fetchMessage(count)
                    last_length = len(latest_result)
                    result += latest_result
                    continue
                break

            for message_index in range(len(result)):
                item = result[message_index]
                await queue.put(
                    InternalEvent(name=self.getEventCurrentName(type(item)),
                                  body=item))
예제 #8
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))
예제 #9
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())
            loop.run_until_complete(
                self.queue.put(
                    InternalEvent(
                        name=self.getEventCurrentName("AppInitEvent"),
                        body={})))

        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())