From e4662ecdc99aa6b3da09bf13bb75a741c8359612 Mon Sep 17 00:00:00 2001 From: Karol Konkol Date: Tue, 23 Jun 2026 00:36:24 +0200 Subject: [PATCH 1/3] Update moq api --- fishjam/_openapi_client/models/moq_token.py | 16 ++++++++-------- fishjam/api/_fishjam_client.py | 6 +++--- pyproject.toml | 2 +- uv.lock | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/fishjam/_openapi_client/models/moq_token.py b/fishjam/_openapi_client/models/moq_token.py index d1f04d9..0aa5620 100644 --- a/fishjam/_openapi_client/models/moq_token.py +++ b/fishjam/_openapi_client/models/moq_token.py @@ -11,23 +11,23 @@ @_attrs_define class MoqToken: - """Token for authorizing a MoQ relay connection + """Connection details for a MoQ relay client Attributes: - token (str): JWT token for MoQ relay Example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb290IjoiZmlzaGphbSIsInB1d - CI6WyJteS1zdHJlYW0iXSwiZ2V0IjpbXSwiaWF0IjoxNzEzMzYwMDAwLCJleHAiOjE3MTMzNjM2MDB9.abc123. + url (str): Relay connection URL with the JWT embedded as a `?jwt=` query parameter. Pass directly to a MoQ + client SDK. Example: https://relay.fishjam.io/abc123?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.... """ - token: str + url: str additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: - token = self.token + url = self.url field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({ - "token": token, + "url": url, }) return field_dict @@ -35,10 +35,10 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - token = d.pop("token") + url = d.pop("url") moq_token = cls( - token=token, + url=url, ) moq_token.additional_properties = d diff --git a/fishjam/api/_fishjam_client.py b/fishjam/api/_fishjam_client.py index a2f612f..4bbd4da 100644 --- a/fishjam/api/_fishjam_client.py +++ b/fishjam/api/_fishjam_client.py @@ -420,14 +420,14 @@ def create_moq_token( publish_path: str | None = None, subscribe_path: str | None = None, ) -> str: - """Generates a MoQ token. + """Generates a MoQ relay connection URL. Args: publish_path: Path the token grants publish access to. subscribe_path: Path the token grants subscribe access to. Returns: - str: The generated token. + str: The relay connection URL with the JWT embedded as a ``?jwt=`` query parameter. """ config = MoqTokenConfig( publish_path=publish_path, subscribe_path=subscribe_path @@ -437,7 +437,7 @@ def create_moq_token( self._request(moq_create_token, body=config), ) - return response.token + return response.url def subscribe_peer(self, room_id: str, peer_id: str, target_peer_id: str): """Subscribes a peer to all tracks of another peer. diff --git a/pyproject.toml b/pyproject.toml index 0aaf55c..e3d3a7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "fishjam-server-sdk" -version = "0.28.0" +version = "0.28.1" description = "Python server SDK for the Fishjam" authors = [{ name = "Fishjam Team", email = "contact@fishjam.io" }] requires-python = ">=3.10" diff --git a/uv.lock b/uv.lock index 799e891..906df31 100644 --- a/uv.lock +++ b/uv.lock @@ -679,7 +679,7 @@ wheels = [ [[package]] name = "fishjam-server-sdk" -version = "0.28.0" +version = "0.28.1" source = { editable = "." } dependencies = [ { name = "aenum" }, From d415f14bfc1cfd986c28b3b6fa6e50f93f5bc4e4 Mon Sep 17 00:00:00 2001 From: Karol Konkol Date: Tue, 23 Jun 2026 00:44:21 +0200 Subject: [PATCH 2/3] Fix lint warnings --- fishjam/api/_fishjam_client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fishjam/api/_fishjam_client.py b/fishjam/api/_fishjam_client.py index 4bbd4da..b0c0c3e 100644 --- a/fishjam/api/_fishjam_client.py +++ b/fishjam/api/_fishjam_client.py @@ -427,7 +427,8 @@ def create_moq_token( subscribe_path: Path the token grants subscribe access to. Returns: - str: The relay connection URL with the JWT embedded as a ``?jwt=`` query parameter. + str: The relay connection URL with the JWT embedded + as a ``?jwt=`` query parameter. """ config = MoqTokenConfig( publish_path=publish_path, subscribe_path=subscribe_path From 02d8dbc050eddb640416c6069fce7fb00858ebd0 Mon Sep 17 00:00:00 2001 From: Karol Konkol Date: Tue, 23 Jun 2026 12:14:34 +0200 Subject: [PATCH 3/3] Update moq api --- fishjam/__init__.py | 2 + ...eate_moq_token.py => create_moq_access.py} | 54 +++++++++---------- fishjam/_openapi_client/models/__init__.py | 8 +-- .../models/{moq_token.py => moq_access.py} | 34 +++++++----- ...q_token_config.py => moq_access_config.py} | 10 ++-- fishjam/api/_fishjam_client.py | 29 +++++----- tests/test_room_api.py | 25 +++++---- 7 files changed, 91 insertions(+), 71 deletions(-) rename fishjam/_openapi_client/api/mo_q/{create_moq_token.py => create_moq_access.py} (76%) rename fishjam/_openapi_client/models/{moq_token.py => moq_access.py} (54%) rename fishjam/_openapi_client/models/{moq_token_config.py => moq_access_config.py} (92%) diff --git a/fishjam/__init__.py b/fishjam/__init__.py index f1e1a71..f55fdc4 100644 --- a/fishjam/__init__.py +++ b/fishjam/__init__.py @@ -18,6 +18,7 @@ AgentOptions, AgentOutputOptions, FishjamClient, + MoqAccess, Peer, PeerOptions, PeerOptionsVapi, @@ -41,6 +42,7 @@ "AgentOutputOptions", "Room", "Peer", + "MoqAccess", "MissingFishjamIdError", "InvalidFishjamCredentialsError", "events", diff --git a/fishjam/_openapi_client/api/mo_q/create_moq_token.py b/fishjam/_openapi_client/api/mo_q/create_moq_access.py similarity index 76% rename from fishjam/_openapi_client/api/mo_q/create_moq_token.py rename to fishjam/_openapi_client/api/mo_q/create_moq_access.py index 0b148cb..be0b70d 100644 --- a/fishjam/_openapi_client/api/mo_q/create_moq_token.py +++ b/fishjam/_openapi_client/api/mo_q/create_moq_access.py @@ -6,20 +6,20 @@ from ... import errors from ...client import AuthenticatedClient, Client from ...models.error import Error -from ...models.moq_token import MoqToken -from ...models.moq_token_config import MoqTokenConfig +from ...models.moq_access import MoqAccess +from ...models.moq_access_config import MoqAccessConfig from ...types import UNSET, Response, Unset def _get_kwargs( *, - body: MoqTokenConfig | Unset = UNSET, + body: MoqAccessConfig | Unset = UNSET, ) -> dict[str, Any]: headers: dict[str, Any] = {} _kwargs: dict[str, Any] = { "method": "post", - "url": "/moq/token", + "url": "/moq/access", } if not isinstance(body, Unset): @@ -33,9 +33,9 @@ def _get_kwargs( def _parse_response( *, client: AuthenticatedClient | Client, response: httpx.Response -) -> Error | MoqToken | None: +) -> Error | MoqAccess | None: if response.status_code == 200: - response_200 = MoqToken.from_dict(response.json()) + response_200 = MoqAccess.from_dict(response.json()) return response_200 @@ -62,7 +62,7 @@ def _parse_response( def _build_response( *, client: AuthenticatedClient | Client, response: httpx.Response -) -> Response[Error | MoqToken]: +) -> Response[Error | MoqAccess]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -74,21 +74,21 @@ def _build_response( def sync_detailed( *, client: AuthenticatedClient, - body: MoqTokenConfig | Unset = UNSET, -) -> Response[Error | MoqToken]: - """Create a MoQ token + body: MoqAccessConfig | Unset = UNSET, +) -> Response[Error | MoqAccess]: + """Create MoQ access Issue a short-lived JWT for a Media over QUIC client. Args: - body (MoqTokenConfig | Unset): MoQ token configuration + body (MoqAccessConfig | Unset): MoQ access configuration Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Error | MoqToken] + Response[Error | MoqAccess] """ kwargs = _get_kwargs( @@ -105,21 +105,21 @@ def sync_detailed( def sync( *, client: AuthenticatedClient, - body: MoqTokenConfig | Unset = UNSET, -) -> Error | MoqToken | None: - """Create a MoQ token + body: MoqAccessConfig | Unset = UNSET, +) -> Error | MoqAccess | None: + """Create MoQ access Issue a short-lived JWT for a Media over QUIC client. Args: - body (MoqTokenConfig | Unset): MoQ token configuration + body (MoqAccessConfig | Unset): MoQ access configuration Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Error | MoqToken + Error | MoqAccess """ return sync_detailed( @@ -131,21 +131,21 @@ def sync( async def asyncio_detailed( *, client: AuthenticatedClient, - body: MoqTokenConfig | Unset = UNSET, -) -> Response[Error | MoqToken]: - """Create a MoQ token + body: MoqAccessConfig | Unset = UNSET, +) -> Response[Error | MoqAccess]: + """Create MoQ access Issue a short-lived JWT for a Media over QUIC client. Args: - body (MoqTokenConfig | Unset): MoQ token configuration + body (MoqAccessConfig | Unset): MoQ access configuration Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Error | MoqToken] + Response[Error | MoqAccess] """ kwargs = _get_kwargs( @@ -160,21 +160,21 @@ async def asyncio_detailed( async def asyncio( *, client: AuthenticatedClient, - body: MoqTokenConfig | Unset = UNSET, -) -> Error | MoqToken | None: - """Create a MoQ token + body: MoqAccessConfig | Unset = UNSET, +) -> Error | MoqAccess | None: + """Create MoQ access Issue a short-lived JWT for a Media over QUIC client. Args: - body (MoqTokenConfig | Unset): MoQ token configuration + body (MoqAccessConfig | Unset): MoQ access configuration Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Error | MoqToken + Error | MoqAccess """ return ( diff --git a/fishjam/_openapi_client/models/__init__.py b/fishjam/_openapi_client/models/__init__.py index 74df98f..622e2a5 100644 --- a/fishjam/_openapi_client/models/__init__.py +++ b/fishjam/_openapi_client/models/__init__.py @@ -5,8 +5,8 @@ from .audio_sample_rate import AudioSampleRate from .composition_info import CompositionInfo from .error import Error -from .moq_token import MoqToken -from .moq_token_config import MoqTokenConfig +from .moq_access import MoqAccess +from .moq_access_config import MoqAccessConfig from .peer import Peer from .peer_config import PeerConfig from .peer_details_response import PeerDetailsResponse @@ -54,8 +54,8 @@ "AudioSampleRate", "CompositionInfo", "Error", - "MoqToken", - "MoqTokenConfig", + "MoqAccess", + "MoqAccessConfig", "Peer", "PeerConfig", "PeerDetailsResponse", diff --git a/fishjam/_openapi_client/models/moq_token.py b/fishjam/_openapi_client/models/moq_access.py similarity index 54% rename from fishjam/_openapi_client/models/moq_token.py rename to fishjam/_openapi_client/models/moq_access.py index 0aa5620..bcdfda4 100644 --- a/fishjam/_openapi_client/models/moq_token.py +++ b/fishjam/_openapi_client/models/moq_access.py @@ -6,28 +6,35 @@ from attrs import define as _attrs_define from attrs import field as _attrs_field -T = TypeVar("T", bound="MoqToken") +T = TypeVar("T", bound="MoqAccess") @_attrs_define -class MoqToken: +class MoqAccess: """Connection details for a MoQ relay client Attributes: - url (str): Relay connection URL with the JWT embedded as a `?jwt=` query parameter. Pass directly to a MoQ - client SDK. Example: https://relay.fishjam.io/abc123?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.... + connection_url (str): Relay connection URL with the JWT embedded as a `?jwt=` query parameter. Pass directly to + a MoQ client SDK. Example: https://relay.fishjam.io/abc123?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.... + token (str): JWT authorizing the MoQ relay connection, also embedded in `connection_url` Example: eyJhbGciOiJIUz + I1NiIsInR5cCI6IkpXVCJ9.eyJyb290IjoiZmlzaGphbSIsInB1dCI6WyJteS1zdHJlYW0iXSwiZ2V0IjpbXSwiaWF0IjoxNzEzMzYwMDAwLCJle + HAiOjE3MTMzNjM2MDB9.abc123. """ - url: str + connection_url: str + token: str additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: - url = self.url + connection_url = self.connection_url + + token = self.token field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({ - "url": url, + "connection_url": connection_url, + "token": token, }) return field_dict @@ -35,14 +42,17 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - url = d.pop("url") + connection_url = d.pop("connection_url") + + token = d.pop("token") - moq_token = cls( - url=url, + moq_access = cls( + connection_url=connection_url, + token=token, ) - moq_token.additional_properties = d - return moq_token + moq_access.additional_properties = d + return moq_access @property def additional_keys(self) -> list[str]: diff --git a/fishjam/_openapi_client/models/moq_token_config.py b/fishjam/_openapi_client/models/moq_access_config.py similarity index 92% rename from fishjam/_openapi_client/models/moq_token_config.py rename to fishjam/_openapi_client/models/moq_access_config.py index fd46900..ee64e4e 100644 --- a/fishjam/_openapi_client/models/moq_token_config.py +++ b/fishjam/_openapi_client/models/moq_access_config.py @@ -7,12 +7,12 @@ from ..types import UNSET, Unset -T = TypeVar("T", bound="MoqTokenConfig") +T = TypeVar("T", bound="MoqAccessConfig") @_attrs_define -class MoqTokenConfig: - """MoQ token configuration +class MoqAccessConfig: + """MoQ access configuration Attributes: publish_path (None | str | Unset): Path under the root the token grants publish access to Example: my-stream. @@ -68,9 +68,9 @@ def _parse_subscribe_path(data: object) -> None | str | Unset: subscribe_path = _parse_subscribe_path(d.pop("subscribePath", UNSET)) - moq_token_config = cls( + moq_access_config = cls( publish_path=publish_path, subscribe_path=subscribe_path, ) - return moq_token_config + return moq_access_config diff --git a/fishjam/api/_fishjam_client.py b/fishjam/api/_fishjam_client.py index b0c0c3e..5f165cb 100644 --- a/fishjam/api/_fishjam_client.py +++ b/fishjam/api/_fishjam_client.py @@ -8,7 +8,7 @@ validate_credentials as credentials_validate_credentials, ) from fishjam._openapi_client.api.mo_q import ( - create_moq_token as moq_create_token, + create_moq_access as moq_create_access, ) from fishjam._openapi_client.api.rooms import add_peer as room_add_peer from fishjam._openapi_client.api.rooms import create_room as room_create_room @@ -29,8 +29,8 @@ AgentOutput, AudioFormat, AudioSampleRate, - MoqToken, - MoqTokenConfig, + MoqAccess, + MoqAccessConfig, Peer, PeerConfig, PeerDetailsResponse, @@ -415,30 +415,31 @@ def create_livestream_streamer_token(self, room_id: str) -> str: return response.token - def create_moq_token( + def create_moq_access( self, publish_path: str | None = None, subscribe_path: str | None = None, - ) -> str: - """Generates a MoQ relay connection URL. + ) -> MoqAccess: + """Generates MoQ relay connection details. Args: - publish_path: Path the token grants publish access to. - subscribe_path: Path the token grants subscribe access to. + publish_path: Path the access grants publish access to. + subscribe_path: Path the access grants subscribe access to. Returns: - str: The relay connection URL with the JWT embedded - as a ``?jwt=`` query parameter. + MoqAccess: The relay connection details, containing the + ``connection_url`` (with the JWT embedded as a ``?jwt=`` query + parameter) and the ``token`` itself. """ - config = MoqTokenConfig( + config = MoqAccessConfig( publish_path=publish_path, subscribe_path=subscribe_path ) response = cast( - MoqToken, - self._request(moq_create_token, body=config), + MoqAccess, + self._request(moq_create_access, body=config), ) - return response.url + return response def subscribe_peer(self, room_id: str, peer_id: str, target_peer_id: str): """Subscribes a peer to all tracks of another peer. diff --git a/tests/test_room_api.py b/tests/test_room_api.py index d010e2f..186b902 100644 --- a/tests/test_room_api.py +++ b/tests/test_room_api.py @@ -5,6 +5,7 @@ from fishjam import ( FishjamClient, + MoqAccess, Peer, PeerOptions, PeerOptionsVapi, @@ -313,30 +314,36 @@ def test_invalid(self, room_api: FishjamClient): room_api.create_livestream_streamer_token(room.id) -class TestCreateMoqToken: +class TestCreateMoqAccess: def test_no_params(self, room_api: FishjamClient): with pytest.raises(BadRequestError): - room_api.create_moq_token() + room_api.create_moq_access() def test_valid_publish(self, room_api: FishjamClient): - token = room_api.create_moq_token(publish_path="test-stream") + access = room_api.create_moq_access(publish_path="test-stream") - assert isinstance(token, str) + assert isinstance(access, MoqAccess) + assert isinstance(access.connection_url, str) + assert isinstance(access.token, str) def test_valid_subscribe(self, room_api: FishjamClient): - token = room_api.create_moq_token(subscribe_path="test-stream") + access = room_api.create_moq_access(subscribe_path="test-stream") - assert isinstance(token, str) + assert isinstance(access, MoqAccess) + assert isinstance(access.connection_url, str) + assert isinstance(access.token, str) def test_valid_both(self, room_api: FishjamClient): - token = room_api.create_moq_token( + access = room_api.create_moq_access( publish_path="test-stream", subscribe_path="test-stream" ) - assert isinstance(token, str) + assert isinstance(access, MoqAccess) + assert isinstance(access.connection_url, str) + assert isinstance(access.token, str) def test_unauthorized(self): room_api = FishjamClient(FISHJAM_ID, "invalid") with pytest.raises(UnauthorizedError): - room_api.create_moq_token(publish_path="test-stream") + room_api.create_moq_access(publish_path="test-stream")