Skip to content

Commit f8bba3a

Browse files
committed
Add generating viewer token to API
1 parent 8df875a commit f8bba3a

File tree

8 files changed

+109
-45
lines changed

8 files changed

+109
-45
lines changed

docker-compose-test.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ services:
1717
FJ_SECRET_KEY_BASE: "super-secret-key"
1818
FJ_SIP_IP: "127.0.0.1"
1919
FJ_COMPONENTS_USED: "rtsp file hls recording sip"
20+
FJ_BROADCASTER_URL: "http://broadcaster:4000"
21+
FJ_BROADCASTER_TOKEN: "broadcaster_token"
22+
FJ_BROADCASTER_WHIP_TOKEN: "whip_token"
2023
ports:
2124
- "5002:5002"
2225
- "49999:49999"

fishjam/_openapi_client/api/viewer/generate_token.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
from http import HTTPStatus
2-
from typing import Any, Dict, Optional, Union, cast
2+
from typing import Any, Dict, Optional, Union
33

44
import httpx
55

66
from ... import errors
77
from ...client import AuthenticatedClient, Client
88
from ...models.error import Error
9+
from ...models.viewer_token import ViewerToken
910
from ...types import Response
1011

1112

@@ -22,9 +23,10 @@ def _get_kwargs(
2223

2324
def _parse_response(
2425
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
25-
) -> Optional[Union[Error, str]]:
26+
) -> Optional[Union[Error, ViewerToken]]:
2627
if response.status_code == HTTPStatus.CREATED:
27-
response_201 = cast(str, response.json())
28+
response_201 = ViewerToken.from_dict(response.json())
29+
2830
return response_201
2931
if response.status_code == HTTPStatus.BAD_REQUEST:
3032
response_400 = Error.from_dict(response.json())
@@ -50,7 +52,7 @@ def _parse_response(
5052

5153
def _build_response(
5254
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
53-
) -> Response[Union[Error, str]]:
55+
) -> Response[Union[Error, ViewerToken]]:
5456
return Response(
5557
status_code=HTTPStatus(response.status_code),
5658
content=response.content,
@@ -63,8 +65,8 @@ def sync_detailed(
6365
room_id: str,
6466
*,
6567
client: Union[AuthenticatedClient, Client],
66-
) -> Response[Union[Error, str]]:
67-
"""Generate token for single viewer
68+
) -> Response[Union[Error, ViewerToken]]:
69+
"""Generate single broadcaster access token
6870
6971
Args:
7072
room_id (str):
@@ -74,7 +76,7 @@ def sync_detailed(
7476
httpx.TimeoutException: If the request takes longer than Client.timeout.
7577
7678
Returns:
77-
Response[Union[Error, str]]
79+
Response[Union[Error, ViewerToken]]
7880
"""
7981

8082
kwargs = _get_kwargs(
@@ -92,8 +94,8 @@ def sync(
9294
room_id: str,
9395
*,
9496
client: Union[AuthenticatedClient, Client],
95-
) -> Optional[Union[Error, str]]:
96-
"""Generate token for single viewer
97+
) -> Optional[Union[Error, ViewerToken]]:
98+
"""Generate single broadcaster access token
9799
98100
Args:
99101
room_id (str):
@@ -103,7 +105,7 @@ def sync(
103105
httpx.TimeoutException: If the request takes longer than Client.timeout.
104106
105107
Returns:
106-
Union[Error, str]
108+
Union[Error, ViewerToken]
107109
"""
108110

109111
return sync_detailed(
@@ -116,8 +118,8 @@ async def asyncio_detailed(
116118
room_id: str,
117119
*,
118120
client: Union[AuthenticatedClient, Client],
119-
) -> Response[Union[Error, str]]:
120-
"""Generate token for single viewer
121+
) -> Response[Union[Error, ViewerToken]]:
122+
"""Generate single broadcaster access token
121123
122124
Args:
123125
room_id (str):
@@ -127,7 +129,7 @@ async def asyncio_detailed(
127129
httpx.TimeoutException: If the request takes longer than Client.timeout.
128130
129131
Returns:
130-
Response[Union[Error, str]]
132+
Response[Union[Error, ViewerToken]]
131133
"""
132134

133135
kwargs = _get_kwargs(
@@ -143,8 +145,8 @@ async def asyncio(
143145
room_id: str,
144146
*,
145147
client: Union[AuthenticatedClient, Client],
146-
) -> Optional[Union[Error, str]]:
147-
"""Generate token for single viewer
148+
) -> Optional[Union[Error, ViewerToken]]:
149+
"""Generate single broadcaster access token
148150
149151
Args:
150152
room_id (str):
@@ -154,7 +156,7 @@ async def asyncio(
154156
httpx.TimeoutException: If the request takes longer than Client.timeout.
155157
156158
Returns:
157-
Union[Error, str]
159+
Union[Error, ViewerToken]
158160
"""
159161

160162
return (

fishjam/_openapi_client/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
from .track_type import TrackType
6969
from .user import User
7070
from .user_listing_response import UserListingResponse
71+
from .viewer_token import ViewerToken
7172

7273
__all__ = (
7374
"AddComponentJsonBody",
@@ -130,4 +131,5 @@
130131
"TrackType",
131132
"User",
132133
"UserListingResponse",
134+
"ViewerToken",
133135
)

fishjam/_openapi_client/models/room_config.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ class RoomConfig:
1616

1717
max_peers: Union[Unset, None, int] = UNSET
1818
"""Maximum amount of peers allowed into the room"""
19-
peer_disconnected_timeout: Union[Unset, None, int] = UNSET
20-
"""Duration (in seconds) after which the peer will be removed if it is disconnected. If not provided, this feature is disabled."""
21-
peerless_purge_timeout: Union[Unset, None, int] = UNSET
22-
"""Duration (in seconds) after which the room will be removed if no peers are connected. If not provided, this feature is disabled."""
2319
room_type: Union[Unset, RoomConfigRoomType] = RoomConfigRoomType.FULL_FEATURE
2420
"""The use-case of the room. If not provided, this defaults to full_feature."""
2521
video_codec: Union[Unset, None, RoomConfigVideoCodec] = UNSET
@@ -32,8 +28,6 @@ class RoomConfig:
3228
def to_dict(self) -> Dict[str, Any]:
3329
"""@private"""
3430
max_peers = self.max_peers
35-
peer_disconnected_timeout = self.peer_disconnected_timeout
36-
peerless_purge_timeout = self.peerless_purge_timeout
3731
room_type: Union[Unset, str] = UNSET
3832
if not isinstance(self.room_type, Unset):
3933
room_type = self.room_type.value
@@ -49,10 +43,6 @@ def to_dict(self) -> Dict[str, Any]:
4943
field_dict.update({})
5044
if max_peers is not UNSET:
5145
field_dict["maxPeers"] = max_peers
52-
if peer_disconnected_timeout is not UNSET:
53-
field_dict["peerDisconnectedTimeout"] = peer_disconnected_timeout
54-
if peerless_purge_timeout is not UNSET:
55-
field_dict["peerlessPurgeTimeout"] = peerless_purge_timeout
5646
if room_type is not UNSET:
5747
field_dict["roomType"] = room_type
5848
if video_codec is not UNSET:
@@ -68,10 +58,6 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
6858
d = src_dict.copy()
6959
max_peers = d.pop("maxPeers", UNSET)
7060

71-
peer_disconnected_timeout = d.pop("peerDisconnectedTimeout", UNSET)
72-
73-
peerless_purge_timeout = d.pop("peerlessPurgeTimeout", UNSET)
74-
7561
_room_type = d.pop("roomType", UNSET)
7662
room_type: Union[Unset, RoomConfigRoomType]
7763
if isinstance(_room_type, Unset):
@@ -92,8 +78,6 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
9278

9379
room_config = cls(
9480
max_peers=max_peers,
95-
peer_disconnected_timeout=peer_disconnected_timeout,
96-
peerless_purge_timeout=peerless_purge_timeout,
9781
room_type=room_type,
9882
video_codec=video_codec,
9983
webhook_url=webhook_url,
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from typing import Any, Dict, List, Type, TypeVar, Union
2+
3+
from attrs import define as _attrs_define
4+
from attrs import field as _attrs_field
5+
6+
from ..types import UNSET, Unset
7+
8+
T = TypeVar("T", bound="ViewerToken")
9+
10+
11+
@_attrs_define
12+
class ViewerToken:
13+
"""Token for authorizing broadcaster viewer connection"""
14+
15+
token: Union[Unset, str] = UNSET
16+
"""None"""
17+
additional_properties: Dict[str, Any] = _attrs_field(init=False, factory=dict)
18+
"""@private"""
19+
20+
def to_dict(self) -> Dict[str, Any]:
21+
"""@private"""
22+
token = self.token
23+
24+
field_dict: Dict[str, Any] = {}
25+
field_dict.update(self.additional_properties)
26+
field_dict.update({})
27+
if token is not UNSET:
28+
field_dict["token"] = token
29+
30+
return field_dict
31+
32+
@classmethod
33+
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
34+
"""@private"""
35+
d = src_dict.copy()
36+
token = d.pop("token", UNSET)
37+
38+
viewer_token = cls(
39+
token=token,
40+
)
41+
42+
viewer_token.additional_properties = d
43+
return viewer_token
44+
45+
@property
46+
def additional_keys(self) -> List[str]:
47+
"""@private"""
48+
return list(self.additional_properties.keys())
49+
50+
def __getitem__(self, key: str) -> Any:
51+
return self.additional_properties[key]
52+
53+
def __setitem__(self, key: str, value: Any) -> None:
54+
self.additional_properties[key] = value
55+
56+
def __delitem__(self, key: str) -> None:
57+
del self.additional_properties[key]
58+
59+
def __contains__(self, key: str) -> bool:
60+
return key in self.additional_properties

fishjam/api/_fishjam_client.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from fishjam._openapi_client.api.room import get_all_rooms as room_get_all_rooms
1313
from fishjam._openapi_client.api.room import get_room as room_get_room
1414
from fishjam._openapi_client.api.room import refresh_token as room_refresh_token
15+
from fishjam._openapi_client.api.viewer import generate_token as viewer_generate_token
1516
from fishjam._openapi_client.models import (
1617
AddPeerJsonBody,
1718
Peer,
@@ -23,6 +24,7 @@
2324
RoomCreateDetailsResponse,
2425
RoomDetailsResponse,
2526
RoomsListingResponse,
27+
ViewerToken,
2628
)
2729
from fishjam._openapi_client.models.peer_options_web_rtc_metadata import (
2830
PeerOptionsWebRTCMetadata,
@@ -49,16 +51,6 @@ class RoomOptions:
4951

5052
max_peers: int | None = None
5153
"""Maximum amount of peers allowed into the room"""
52-
peer_disconnected_timeout: int | None = None
53-
"""
54-
Duration (in seconds) after which the peer will be removed if it is disconnected.
55-
If not provided, this feature is disabled.
56-
"""
57-
peerless_purge_timeout: int | None = None
58-
"""
59-
Duration (in seconds) after which the room will be removed
60-
if no peers are connected. If not provided, this feature is disabled.
61-
"""
6254
video_codec: Literal["h264", "vp8"] | None = None
6355
"""Enforces video codec for each peer in the room"""
6456
webhook_url: str | None = None
@@ -126,8 +118,6 @@ def create_room(self, options: RoomOptions | None = None) -> Room:
126118

127119
config = RoomConfig(
128120
max_peers=options.max_peers,
129-
peer_disconnected_timeout=options.peer_disconnected_timeout,
130-
peerless_purge_timeout=options.peerless_purge_timeout,
131121
video_codec=codec,
132122
webhook_url=options.webhook_url,
133123
room_type=RoomConfigRoomType(options.room_type),
@@ -177,6 +167,15 @@ def refresh_peer_token(self, room_id: str, peer_id: str) -> str:
177167

178168
return response.data.token
179169

170+
def create_livestream_viewer_token(self, room_id: str) -> str:
171+
"""Generates viewer token for livestream rooms"""
172+
173+
response = cast(
174+
ViewerToken, self._request(viewer_generate_token, room_id=room_id)
175+
)
176+
177+
return response.token
178+
180179
def __parse_peer_metadata(self, metadata: dict | None) -> PeerOptionsWebRTCMetadata:
181180
peer_metadata = PeerOptionsWebRTCMetadata()
182181

tests/test_room_api.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,17 @@ def test_invalid(self, room_api: FishjamClient):
245245

246246
with pytest.raises(NotFoundError):
247247
room_api.refresh_peer_token(room.id, peer_id="invalid_peer_id")
248+
249+
250+
class TestCreateLivestreamViewerToken:
251+
def test_valid(self, room_api: FishjamClient):
252+
room = room_api.create_room(RoomOptions(room_type="broadcaster"))
253+
viewer_token = room_api.create_livestream_viewer_token(room.id)
254+
255+
assert isinstance(viewer_token, str)
256+
257+
def test_invalid(self, room_api: FishjamClient):
258+
room = room_api.create_room()
259+
260+
with pytest.raises(BadRequestError):
261+
room_api.room_api.create_livestream_viewer_token(room.id)

0 commit comments

Comments
 (0)