def test_continuation_with_close_empty(out, parser):
    parser.parse_frame = mock.Mock()
    parser.parse_frame.return_value = [
        (0, WSMsgType.TEXT, b'line1'),
        (0, WSMsgType.CLOSE, b''),
        (1, WSMsgType.CONTINUATION, b'line2'),
    ]

    parser.feed_data(b'')
    res = out._buffer[0]
    assert res, (WSMessage(WSMsgType.CLOSE, 0, ''), 0)
    res = out._buffer[1]
    assert res == (WSMessage(WSMsgType.TEXT, 'line1line2', ''), 10)
async def test_cloud_messages_invalid_format(hass_platform_cloud_connection,
                                             config, aioclient_mock):
    hass = hass_platform_cloud_connection

    requests = ['foo']
    session = MockSession(aioclient_mock,
                          msg=[
                              WSMessage(type=WSMsgType.TEXT, extra={}, data=r)
                              for r in requests
                          ])
    manager = CloudManager(hass, config, session)

    with patch.object(manager, '_try_reconnect',
                      return_value=None) as mock_reconnect:
        await manager.connect()
        mock_reconnect.assert_called_once()

    requests = [json.dumps({'request_id': 'req', '_action': 'foo'})]
    session = MockSession(aioclient_mock,
                          msg=[
                              WSMessage(type=WSMsgType.TEXT, extra={}, data=r)
                              for r in requests
                          ])
    manager = CloudManager(hass, config, session)

    mock_reconnect.reset_mock()
    with patch.object(manager, '_try_reconnect',
                      return_value=None) as mock_reconnect:
        await manager.connect()
        mock_reconnect.assert_called_once()

    requests = [
        json.dumps({
            'request_id': 'req',
            'action': 'foo',
            'message': 'not_{_json'
        })
    ]
    session = MockSession(aioclient_mock,
                          msg=[
                              WSMessage(type=WSMsgType.TEXT, extra={}, data=r)
                              for r in requests
                          ])
    manager = CloudManager(hass, config, session)

    mock_reconnect.reset_mock()
    with patch.object(manager, '_try_reconnect',
                      return_value=None) as mock_reconnect:
        await manager.connect()
        mock_reconnect.assert_called_once()
Beispiel #3
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)}")
def test_close_frame_info(out, parser):
    parser.parse_frame = mock.Mock()
    parser.parse_frame.return_value = [(1, WSMsgType.CLOSE, b'0112345')]

    parser.feed_data(b'')
    res = out._buffer[0]
    assert res == (WSMessage(WSMsgType.CLOSE, 12337, '12345'), 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
Beispiel #6
0
    def test_listen_for_user_stream_sends_ping_message_before_ping_interval_finishes(
            self, ws_connect_mock):

        successful_login_response = {"event": "login", "code": "0", "msg": ""}

        ws_connect_mock.return_value = self.mocking_assistant.create_websocket_mock(
        )
        ws_connect_mock.return_value.receive.side_effect = [
            WSMessage(type=WSMsgType.TEXT,
                      data=json.dumps(successful_login_response),
                      extra=None),
            asyncio.TimeoutError("Test timeiout"), asyncio.CancelledError
        ]

        msg_queue = asyncio.Queue()
        self.listening_task = self.ev_loop.create_task(
            self.data_source.listen_for_user_stream(msg_queue))

        try:
            self.async_run_with_timeout(self.listening_task)
        except asyncio.CancelledError:
            pass

        sent_messages = self.mocking_assistant.text_messages_sent_through_websocket(
            websocket_mock=ws_connect_mock.return_value)

        expected_ping_message = "ping"
        self.assertEqual(expected_ping_message, sent_messages[0])
Beispiel #7
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)
Beispiel #8
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)
async def test_cloud_req_user_devices_query(hass_platform_cloud_connection,
                                            config, aioclient_mock):
    hass = hass_platform_cloud_connection
    requests = [{
        'request_id':
        'req_user_devices_query_1',
        'action':
        '/user/devices/query',
        'message':
        json.dumps({'devices': [{
            'id': 'sensor.outside_temp'
        }]})
    }, {
        'request_id':
        'req_user_devices_query_2',
        'action':
        '/user/devices/query',
        'message':
        json.dumps({'devices': [{
            'id': 'sensor.not_existed'
        }]})
    }]
    session = MockSession(aioclient_mock,
                          msg=[
                              WSMessage(type=WSMsgType.TEXT,
                                        extra={},
                                        data=json.dumps(r)) for r in requests
                          ])
    # noinspection PyTypeChecker
    manager = CloudManager(hass, config, session)
    await manager.connect()

    assert json.loads(session.ws.send_queue[0]) == {
        'request_id': 'req_user_devices_query_1',
        'payload': {
            'devices': [{
                'id':
                'sensor.outside_temp',
                'capabilities': [],
                'properties': [{
                    'type': 'devices.properties.float',
                    'state': {
                        'instance': 'temperature',
                        'value': 15.6
                    }
                }]
            }]
        }
    }
    assert json.loads(session.ws.send_queue[1]) == {
        'request_id': 'req_user_devices_query_2',
        'payload': {
            'devices': [{
                'id': 'sensor.not_existed',
                'error_code': 'DEVICE_UNREACHABLE'
            }]
        }
    }
def test_continuation(out, parser):
    parser.parse_frame = mock.Mock()
    parser.parse_frame.return_value = [(0, WSMsgType.TEXT, b'line1'),
                                       (1, WSMsgType.CONTINUATION, b'line2')]

    parser._feed_data(b'')

    res = out._buffer[0]
    assert res == (WSMessage(WSMsgType.TEXT, 'line1line2', ''), 10)
 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
async def test_ticks_pong(make_transport, make_fut):
    transp = make_transport()

    pong = WSMessage(type=WSMsgType.PONG, data=b'', extra='')
    close = WSMessage(type=WSMsgType.closing, data=b'', extra='')

    future = Future()
    future.set_result(pong)

    future2 = Future()
    future2.set_result(close)

    ws = mock.Mock()
    ws.receive.side_effect = [future, future2]

    session = transp.session

    await transp.client(ws, session)
    assert session._tick.called
Beispiel #13
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")}')
def test_close_frame_info(out, parser):
    def parse_frame(buf):
        yield
        return (1, WSMsgType.CLOSE, b'0112345')

    with mock.patch('aiohttp._ws_impl.parse_frame') as m_parse_frame:
        m_parse_frame.side_effect = parse_frame
        next(parser)
        parser.send(b'')
    res = out._buffer[0]
    assert res == (WSMessage(WSMsgType.CLOSE, 12337, '12345'), 0)
def test_continuation_with_close(out, parser):
    frames = [
        (0, WSMsgType.TEXT, b'line1'),
        (0, WSMsgType.CLOSE, build_close_frame(1002, b'test', noheader=True)),
        (1, WSMsgType.CONTINUATION, b'line2'),
    ]

    def parse_frame(buf, cont=False):
        yield
        return frames.pop(0)

    with mock.patch('aiohttp._ws_impl.parse_frame') as m_parse_frame:
        m_parse_frame.side_effect = parse_frame
        next(parser)
        parser.send(b'')
        parser.send(b'')
        parser.send(b'')
        res = out._buffer[0]
    assert res, (WSMessage(WSMsgType.CLOSE, 1002, 'test'), 0)
    res = out._buffer[1]
    assert res == (WSMessage(WSMsgType.TEXT, 'line1line2', ''), 10)
Beispiel #16
0
def test_continuation_with_ping(out, parser):
    frames = [
        (0, WSMsgType.text, b'line1'),
        (0, WSMsgType.ping, b''),
        (1, WSMsgType.continuation, b'line2'),
    ]

    def parse_frame(buf, cont=False):
        yield
        return frames.pop(0)

    with mock.patch('aiohttp._ws_impl.parse_frame') as m_parse_frame:
        m_parse_frame.side_effect = parse_frame
        next(parser)
        parser.send(b'')
        parser.send(b'')
        parser.send(b'')
    res = out._buffer[0]
    assert res == (WSMessage(WSMsgType.ping, b'', ''), 0)
    res = out._buffer[1]
    assert res == (WSMessage(WSMsgType.text, 'line1line2', ''), 10)
Beispiel #17
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)
async def test_get_message_loop(opsdroid):

    connector = ConnectorTwitch(connector_config, opsdroid=opsdroid)

    connector.websocket = amock.MagicMock()
    connector.websocket.__aiter__.return_value = [
        WSMessage(WSMsgType.TEXT, "PING", b""),
        WSMessage(WSMsgType.TEXT, ":[email protected]! JOIN #channel", b""),
        WSMessage(WSMsgType.CLOSED, "CLOSE", ""),
    ]

    connector.websocket.send_str = amock.CoroutineMock()
    connector.websocket.close = amock.CoroutineMock()
    connector._handle_message = amock.CoroutineMock()

    with pytest.raises(ConnectionError):
        await connector.get_messages_loop()

        assert connector.is_live
        assert connector.send_str.called
        assert connector.websocket.close.called
        assert connector._handle_message.called
Beispiel #19
0
async def test_frames(make_transport, make_handler):
    result = []
    handler = make_handler(result)
    transp = make_transport(handler=handler)

    empty_message = Future()
    empty_message.set_result(WSMessage(type=WSMsgType.text, data="", extra=""))

    empty_frame = Future()
    empty_frame.set_result(WSMessage(type=WSMsgType.text, data="[]", extra=""))

    single_msg_frame = Future()
    single_msg_frame.set_result(
        WSMessage(type=WSMsgType.text, data='"single_msg"', extra=""))

    multi_msg_frame = Future()
    multi_msg_frame.set_result(
        WSMessage(type=WSMsgType.text, data='["msg1", "msg2"]', extra=""))

    close_frame = Future()
    close_frame.set_result(WSMessage(type=WSMsgType.closed, data="", extra=""))

    ws = mock.Mock()
    ws.receive.side_effect = [
        empty_message,
        empty_frame,
        single_msg_frame,
        multi_msg_frame,
        close_frame,
    ]

    session = transp.session
    await transp.client(ws, session)

    assert result[0][0].data == "single_msg"
    assert result[1][0].data == "msg1"
    assert result[2][0].data == "msg2"
Beispiel #20
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)
def test_continuation(out, parser):
    cur = 0

    def parse_frame(buf, cont=False):
        nonlocal cur
        yield
        if cur == 0:
            cur = 1
            return (0, WSMsgType.TEXT, b'line1')
        else:
            return (1, WSMsgType.CONTINUATION, b'line2')

    with mock.patch('aiohttp._ws_impl.parse_frame') as m_parse_frame:
        m_parse_frame.side_effect = parse_frame
        next(parser)
        parser.send(b'')
        parser.send(b'')
    res = out._buffer[0]
    assert res == (WSMessage(WSMsgType.TEXT, 'line1line2', ''), 10)
Beispiel #22
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}')
Beispiel #23
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)}")
    def test_write_to_customer(self):
        """
        Простой тест для отправки сообщений клиенту(кастомеру). В этом случае
        все происходит довольно просто и тупо: приходит сообщение в веб-сокет
        и оно уже отправляется через шлюз непосредственно в сервис, который
        работает с этими сообщениями. при этом сообщение будет сохранено в бд
        """
        dialog = Dialog(id=123, channel=Channel.TEST)
        dialog.customer = Customer(id=1, name="Example customer")
        user = User(id=123)
        message_to_send = Message(text="example text",
                                  dialog=dialog,
                                  created_at=datetime.today())

        self.ws_mock.iter = iter([
            WSMessage(WSMsgType.TEXT,
                      json.dumps(message_to_send, cls=MessageEncoder),
                      extra={})
        ])

        gateway_mock = mock.MagicMock()

        gateways_repository = Repository()
        gateways_repository.register_gateway(dialog.channel, gateway_mock)

        handler = ChatHandler(ws=self.ws_mock,
                              dialog=dialog,
                              user=user,
                              queues_repository=self.queues_repository,
                              gateways_repository=gateways_repository,
                              messages_repository=self.messages_repository)
        self.loop.run_until_complete(handler.write_to_customer())

        # Проверяем, сохранилось ли сообщение в бд
        self.messages_repository.save.assert_called()

        gateway_mock.send_message.assert_called()
        self.assertEqual(dialog, message_to_send.dialog)
Beispiel #25
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)
Beispiel #26
0
 async def receive():
     return WSMessage(WSMsgType.TEXT, 'data', b'')
Beispiel #27
0
 async def receive():
     return WSMessage(WSMsgType.BINARY, b'data', b'')
Beispiel #28
0
 def as_websocket(self):
     return WSMessage(type=WSMsgType.TEXT,
                      data=json.dumps(asdict(self)),
                      extra=None)
Beispiel #29
0
 def function1900():
     return WSMessage(WSMsgType.BINARY, b'data', b'')
Beispiel #30
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()