diff --git a/VERSION b/VERSION index 38f77a6..e9307ca 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.1 +2.0.2 diff --git a/speechmatics/client.py b/speechmatics/client.py index 1c886dd..e695fab 100644 --- a/speechmatics/client.py +++ b/speechmatics/client.py @@ -519,6 +519,33 @@ def run_synchronously(self, *args, timeout=None, **kwargs): # pylint: disable=no-value-for-parameter asyncio.run(asyncio.wait_for(self.run(*args, **kwargs), timeout=timeout)) + async def send_message(self, msg): + """ + Sends a message to the server. + """ + if self.session_running: + assert self.websocket, "Websocket hasn't been instantiated" + try: + LOGGER.info(f"Sending msg={msg}") + await self.websocket.send(json.dumps(msg)) + except TypeError as ex: + LOGGER.info( + f"Cannot send this type of object msg={msg} as a message. Exception occurred:%s", + repr(ex), + ) + return + except websockets.exceptions.ConnectionClosedOK: + # Can occur if a timeout has closed the connection. + LOGGER.info("Cannot send from a closed websocket.") + return + except websockets.exceptions.ConnectionClosedError: + LOGGER.info("Disconnected while sending a message().") + return + else: + LOGGER.info( + f"Websocket client isn't running - Not sending the message = {msg}", + ) + async def _get_temp_token(api_key): """ diff --git a/speechmatics/models.py b/speechmatics/models.py index 07cf7ac..71384a8 100644 --- a/speechmatics/models.py +++ b/speechmatics/models.py @@ -507,6 +507,9 @@ class ClientMessageType(str, Enum): SetRecognitionConfig = "SetRecognitionConfig" """Allows the client to re-configure the recognition session.""" + GetSpeakers = "GetSpeakers" + """Allows the client to request the speakers data.""" + class ServerMessageType(str, Enum): # pylint: disable=invalid-name @@ -547,6 +550,10 @@ class ServerMessageType(str, Enum): after the server has finished sending all :py:attr:`AddTranscript` messages.""" + SpeakersResult = "SpeakersResult" + """Server response to :py:attr:`ClientMessageType.GetSpeakers`, containing + the speakers data.""" + Info = "Info" """Indicates a generic info message.""" diff --git a/tests/test_client.py b/tests/test_client.py index bcd5f64..3af03a0 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -10,6 +10,7 @@ import pytest from pytest_httpx import HTTPXMock +import websockets from speechmatics import client from speechmatics.batch_client import BatchClient from speechmatics.exceptions import ForceEndSession @@ -196,6 +197,35 @@ def test_run_synchronously_with_timeout(mock_server): ) +@pytest.mark.asyncio +@pytest.mark.parametrize( + "message", + [ + pytest.param("random_str", id="Sending pure string"), + pytest.param(243, id="Sending random number"), + pytest.param({}, id="Sending empty dict"), + pytest.param({"message": "expected"}, id="Sending dict with strs"), + pytest.param({"3232": 43}, id="Sending dict with numbers"), + ], +) +async def test_send_message(mock_server, message): + """ + Tests that the client.send_message method correctly sends the message to the server. + """ + ws_client, _, _ = default_ws_client_setup(mock_server.url) + ws_client.session_running = True + + async with websockets.connect( + mock_server.url, + ssl=ws_client.connection_settings.ssl_context, + ping_timeout=ws_client.connection_settings.ping_timeout_seconds, + max_size=None, + extra_headers=None, + ) as ws_client.websocket: + await ws_client.send_message(message) + assert message in mock_server.messages_received + + @pytest.mark.parametrize( "client_message_type, expect_received_count, expect_sent_count", [