Example #1
0
 def _build_resp(msg: aiohttp.WSMessage) -> WSResponse:
     if msg.type == aiohttp.WSMsgType.BINARY:
         data = msg.data
     else:
         data = msg.json()
     response = WSResponse(data)
     return response
Example #2
0
    async def handle_message(self, message: aiohttp.WSMessage):
        if message.type == aiohttp.WSMsgType.TEXT:
            data = message.json()
            self.logger.debug(f"handling:{repr(hide_secret(data))}")

            if "method" in data:
                await self.handle_method_message(data)
            else:
                if "id" in data:
                    if "error" in data:
                        if self.on_response_error:
                            await self.on_response_error()
                        else:
                            self.logger.error(f"Receive error {repr(data)}")
                    else:
                        request_id = data["id"]
                        request = self.requests.get(request_id)
                        if request:
                            await self.handle_response(request=request,
                                                       response=data)

                            del self.requests[request_id]
                        else:
                            if self.on_handle_response:
                                await self.on_handle_response(data)
                            else:
                                self.logger.warning(
                                    f"Unknown id:{request_id}, the on_handle_response event must be defined."
                                    f" Unhandled message {data}")

                else:
                    self.logger.warning(f"Unsupported message {message.data}")
        else:
            self.logger.warning(f"Unknown type of message {repr(message)}")
Example #3
0
 async def on_message(self, route: str, ws: web.WebSocketResponse, ws_msg_from_client: aiohttp.WSMessage):
     if ws_msg_from_client.type == WSMsgType.TEXT:
         msg = ws_msg_from_client.json()
         self.parent.tk(self.parent.detail_var.set, msg.get("detail"))  # Schedule on gui thread
     elif ws_msg_from_client.type == WSMsgType.CLOSE:
         # Two ways two detect a closing
         txt = self.parent.detail_var.get() + "\nDisconnected."
         self.parent.tk(self.parent.detail_var.set, txt)
Example #4
0
    async def on_message(self, message: aiohttp.WSMessage):
        # deserialize message
        data = message.json(loads=json.loads)
        serial = data.get('serial', -1)
        msg_type = data.get('type', 'call')

        assert serial >= 0

        log.debug("Acquiring lock for %s serial %s", self, serial)
        async with self._locks[serial]:
            try:
                if msg_type == 'call':
                    args, kwargs = self._prepare_args(
                        data.get('arguments', None))
                    callback = data.get('call', None)

                    if callback is None:
                        raise ValueError(
                            'Require argument "call" does\'t exist.')

                    callee = self.resolver(callback)
                    calee_is_route = hasattr(
                        callee, '__self__') and isinstance(
                            callee.__self__, WebSocketRoute)
                    if not calee_is_route:
                        a = [self]
                        a.extend(args)
                        args = a

                    result = await self._executor(
                        partial(callee, *args, **kwargs))
                    self._send(data=result, serial=serial, type='callback')

                elif msg_type == 'callback':
                    cb = self._futures.pop(serial, None)
                    cb.set_result(data.get('data', None))

                elif msg_type == 'error':
                    self._reject(data.get('serial', -1),
                                 data.get('data', None))
                    log.error('Client return error: \n\t{0}'.format(
                        data.get('data', None)))

            except Exception as e:
                log.exception(e)
                self._send(data=self._format_error(e),
                           serial=serial,
                           type='error')

            finally:

                def clean_lock():
                    log.debug("Release and delete lock for %s serial %s", self,
                              serial)
                    if serial in self._locks:
                        self._locks.pop(serial)

                self._call_later(self._CLEAN_LOCK_TIMEOUT, clean_lock)
 def _build_resp(msg: aiohttp.WSMessage) -> WSResponse:
     if msg.type == aiohttp.WSMsgType.BINARY:
         data = msg.data
     else:
         try:
             data = msg.json()
         except JSONDecodeError:
             data = msg.data
     response = WSResponse(data)
     return response
Example #6
0
async def __handle_text_message(
        _websocket: ClientWebSocketResponse, msg: WSMessage,
        event_handler: Callable[[MessageDTO], None]) -> None:
    _LOG.debug('%s: Server sent "%s"', datetime.now(), msg.data)

    json_response = msg.json()
    if 'access_id' not in json_response:
        message = MessageDTO(**json_response)
        event_handler(message)
    elif isinstance(json_response, dict):
        _LOG.info(f'Got id {json_response.get("access_id")}')
Example #7
0
    async def handle_message(self, message: aiohttp.WSMessage):
        # noinspection PyTypeChecker, PyNoneFunctionAssignment
        data = message.json(loads=loads)  # type: dict
        log.debug("Got message: %r", data)

        serial = data.get("id")

        if serial is None:
            return await self.handle_event(data)

        call_item = self._parse_message(data)
        await self._call_method(call_item)
Example #8
0
    async def on_message(self, route: str, ws: web.WebSocketResponse,
                         ws_msg_from_client: aiohttp.WSMessage):

        if ws_msg_from_client.type == WSMsgType.TEXT:
            try:
                msg = ws_msg_from_client.json()
            except Exception as ex:
                print("Error trying to make json", ex, ws_msg_from_client)
            else:
                if OAUTH2_TOKEN_KEY in msg:
                    token = msg.get(OAUTH2_TOKEN_KEY)
                    await self.queue.put(token)
                else:
                    err = msg.get("error")
                    await self.queue.put(PushbulletError(err))

                await self.queue.put(ws)
Example #9
0
def process_ws_response(response: aiohttp.WSMessage) -> Union[dict, list]:
    """A utility function to process the response from the Synse Server WebSocket API.

    Args:
        response: The WebSocket response message.

    Returns:
        The JSON response edata marshaled into its Python type (e.g., dict or list).

    Raises:
        errors.SynseError: An instance of a SynseError, wrapping any other error
        which may have occurred.
    """

    if response.type == aiohttp.WSMsgType.text:
        msg = response.json()
        if msg['event'] == 'response/error':
            log.debug(f'error response from Synse Server: {msg}')
            status = msg['data']['http_code']
            desc = msg['data'].get('description', '')
            ctx = msg['data'].get('context', 'no context available')

            err = f'{desc} [{status}]: {ctx}'
            if status == 404:
                raise errors.NotFound(err)
            elif status == 400:
                raise errors.InvalidInput(err)
            else:
                raise errors.SynseError(err)
        else:
            return msg

    elif response.type == aiohttp.WSMsgType.closed:
        raise errors.SynseError('WebSocket connection closed: {}'.format(
            response.extra))
    elif response.type == aiohttp.WSMsgType.error:
        raise errors.SynseError('WebSocket error: {} : {}'.format(
            response.data, response.extra))
    else:
        raise errors.SynseError(f'Unexpected WebSocket response: {response}')
Example #10
0
    async def handle_message(self, message: aiohttp.WSMessage):
        if message.type == aiohttp.WSMsgType.TEXT:
            data = message.json()

            if isinstance(data, list):
                channel_id = data[0]
                handler = self.channel_handlers.get(channel_id)
                if handler:
                    await handler(data, self)
                else:
                    self.logger.warning(
                        f"Can't find handler for channel_id{channel_id}, {data}"
                    )
            elif isinstance(data, dict):
                if "event" in data:
                    await self.handle_event(data)
                else:
                    self.logger.warning(f"Unknown message {message.data}")
            else:
                self.logger.warning(f"Unknown message {message.data}")
        else:
            self.logger.warning(f"Unknown type of message {repr(message)}")
Example #11
0
    async def handle_message(self, message: aiohttp.WSMessage):
        # deserialize message
        # noinspection PyNoneFunctionAssignment, PyTypeChecker
        data = message.json(loads=loads)  # type: dict

        log.debug("Response: %r", data)
        serial = data.get('id')

        if serial is None:
            return await self.handle_event(data)

        method = data.get('method')
        result = data.get('result')
        error = data.get('error')

        log.debug("Acquiring lock for %s serial %s", self, serial)
        async with self._locks[serial]:
            try:
                if 'method' in data:
                    args, kwargs = self.prepare_args(data.get('params', None))
                    return await self.handle_method(method, serial, *args,
                                                    **kwargs)
                elif 'result' in data:
                    return await self.handle_result(serial, result)
                elif 'error' in data:
                    return await self.handle_error(serial, error)
                else:
                    return await self.handle_result(serial, None)

            except Exception as e:
                log.exception(e)

                if serial:
                    await self._send(error=self._format_error(e), id=serial)
            finally:
                self._call_later(self._CLEAN_LOCK_TIMEOUT, self.__clean_lock,
                                 serial)
Example #12
0
async def on_message(ws, message: aiohttp.WSMessage):
    """
    {
      "message": {
        "data": "hello",
        "extended_data": [],
        "captions": [],
        "type": "PLAIN"
      },
      "topic": "global",
      "type": "MESSAGE"
    }
    """
    from main import bot

    hub_log.info(message)
    msg = message.json()

    type = msg['type']
    if type == 'MESSAGE':
        topic = msg['topic']
        if topic:
            # ignore topic global
            if topic == 'global':
                return

            # render message
            innter_type = msg['message']['type']
            innter_data = msg['message']['data']
            extended_data = msg['message']['extended_data'] or []
            caption = msg['message']['caption']
            preview = msg['message']['preview']
            group = False

            body = ''
            parse_mode = None
            disable_preview = not preview
            disable_notification = False

            # parse message type
            if innter_type == MESSAGE_TYPE.PLAIN.name:
                body = innter_data
            elif innter_type == MESSAGE_TYPE.MARKDOWN.name:
                body = innter_data
                parse_mode = "Markdown"
            elif innter_type == MESSAGE_TYPE.HTML.name:
                body = innter_data
                parse_mode = "HTML"
            elif innter_type == MESSAGE_TYPE.JSON.name:
                body = innter_data
            elif is_media(innter_type) or extended_data:
                body = [{
                    'type': innter_type,
                    'data': innter_data,
                    'caption': caption
                }] + extended_data  # type: list
                print(body)
                # check: all types must be photo or video
                if not all(is_media(x['type']) for x in body):
                    hub_log.warning(f"not all types are media")
                    return
            else:
                hub_log.warning(f"unprocessed type {innter_type}")

            if body:
                all_topics = DB.get_key_topics_map()
                for key, topics in all_topics.items():
                    user_id, username, chat_id = Event.parse_key(key)

                    if topic in topics:
                        try:
                            if is_media(innter_type) or extended_data:
                                # string in hub message maybe a base64 encoded bytes
                                # or http url of a image
                                media_group = [{
                                    'type':
                                    x['type'].lower(),
                                    'media':
                                    x['data'] if x['data'].startswith('http')
                                    else BytesIO(base64.b64decode(x['data'])),
                                    'caption':
                                    x['caption'],
                                } for x in body]
                                if len(media_group) > 1:
                                    await bot.send_media_group(
                                        chat_id,
                                        media_group,
                                        disable_notification=
                                        disable_notification,
                                    )
                                else:
                                    if user_id != chat_id:
                                        caption_default = f"# {topic} by {username}"
                                    else:
                                        caption_default = f'# {topic}'
                                    if caption:
                                        caption_default = (
                                            f'{caption.rstrip()}\n\n{caption_default}'
                                        )

                                    x = media_group[0]
                                    if x['type'] == 'photo':
                                        await bot.send_photo(
                                            chat_id,
                                            x['media'],
                                            caption=caption_default,
                                            parse_mode=parse_mode,
                                            disable_notification=
                                            disable_notification,
                                        )
                                    else:
                                        await bot.send_video(
                                            chat_id,
                                            x['media'],
                                            caption=caption_default,
                                            parse_mode=parse_mode,
                                            disable_notification=
                                            disable_notification,
                                        )
                            else:
                                body_with_topic = f"{body.rstrip()}\n\n# {topic}"
                                # reply in group or private chat
                                if user_id != chat_id:
                                    real_body = (
                                        f"{body_with_topic} by {username}")
                                    disable_notification = True
                                else:
                                    real_body = body_with_topic

                                await bot.send_message(
                                    chat_id,
                                    real_body,
                                    parse_mode=parse_mode,
                                    disable_web_page_preview=disable_preview,
                                    disable_notification=disable_notification,
                                )
                        except Exception as e:
                            traceback.print_exc()
Example #13
0
    async def on_message(self, message: WSMessage):
        async with self.semaphore:
            log.debug('Client %s send message: "%s"', self.id, message)

            start = self._loop.time()

            # deserialize message
            data = message.json(loads=json.loads)
            serial = data.get('serial', -1)
            msg_type = data.get('type', 'call')

            message_repr = ''

            assert serial >= 0

            log.debug("Acquiring lock for %s serial %s", self, serial)
            async with self._locks[serial]:
                try:
                    if msg_type == 'call':
                        args, kwargs = self._prepare_args(
                            data.get('arguments', None))
                        callback = data.get('call', None)

                        message_repr = "call[%s]" % callback

                        if callback is None:
                            raise ValueError(
                                'Require argument "call" does\'t exist.')

                        callee = self.resolver(callback)
                        callee_is_route = hasattr(
                            callee, '__self__') and isinstance(
                                callee.__self__, WebSocketRoute)
                        if not callee_is_route:
                            a = [self]
                            a.extend(args)
                            args = a

                        result = await self._executor(
                            partial(callee, *args, **kwargs))
                        self._send(data=result, serial=serial, type='callback')

                    elif msg_type == 'callback':
                        cb = self._futures.pop(serial, None)
                        payload = data.get('data', None)
                        cb.set_result(payload)

                        message_repr = "callback[%r]" % payload

                    elif msg_type == 'error':
                        self._reject(data.get('serial', -1),
                                     data.get('data', None))
                        log.error('Client return error: \n\t{0}'.format(
                            data.get('data', None)))

                        message_repr = "error[%r]" % data

                except Exception as e:
                    log.exception(e)
                    self._send(data=self._format_error(e),
                               serial=serial,
                               type='error')

                finally:

                    def clean_lock():
                        log.debug("Release and delete lock for %s serial %s",
                                  self, serial)
                        if serial in self._locks:
                            self._locks.pop(serial)

                    self._call_later(self._CLIENT_TIMEOUT, clean_lock)

                    response_time = self._loop.time() - start

                    if response_time > 0.001:
                        response_time = "%.3f" % response_time
                    else:
                        # loop.time() resolution is 1 ms.
                        response_time = "less then 1ms"

                    log.info("Response for client \"%s\" #%d finished %s",
                             message_repr, serial, response_time)