livekit-api 0.4.4__tar.gz → 0.5.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {livekit-api-0.4.4 → livekit_api-0.5.1}/PKG-INFO +3 -3
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/__init__.py +2 -1
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/_service.py +11 -3
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/access_token.py +21 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/livekit_api.py +6 -0
- livekit_api-0.5.1/livekit/api/sip_service.py +134 -0
- livekit_api-0.5.1/livekit/api/version.py +1 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit_api.egg-info/PKG-INFO +3 -3
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit_api.egg-info/SOURCES.txt +1 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit_api.egg-info/requires.txt +1 -1
- {livekit-api-0.4.4 → livekit_api-0.5.1}/setup.py +2 -2
- {livekit-api-0.4.4 → livekit_api-0.5.1}/tests/test_access_token.py +4 -1
- livekit-api-0.4.4/livekit/api/version.py +0 -1
- {livekit-api-0.4.4 → livekit_api-0.5.1}/README.md +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/egress_service.py +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/ingress_service.py +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/py.typed +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/room_service.py +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/twirp_client.py +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit/api/webhook.py +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit_api.egg-info/dependency_links.txt +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/livekit_api.egg-info/top_level.txt +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/pyproject.toml +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/setup.cfg +0 -0
- {livekit-api-0.4.4 → livekit_api-0.5.1}/tests/test_webhook.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: livekit-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Python Server API for LiveKit
|
|
5
5
|
Home-page: https://github.com/livekit/python-sdks
|
|
6
6
|
License: Apache-2.0
|
|
@@ -19,13 +19,13 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.9
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
21
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
-
Requires-Python: >=3.
|
|
22
|
+
Requires-Python: >=3.9.0
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
Requires-Dist: pyjwt>=2.0.0
|
|
25
25
|
Requires-Dist: aiohttp>=3.9.0
|
|
26
26
|
Requires-Dist: protobuf>=3
|
|
27
27
|
Requires-Dist: types-protobuf<5,>=4
|
|
28
|
-
Requires-Dist: livekit-protocol<
|
|
28
|
+
Requires-Dist: livekit-protocol<2,>=0.5.1
|
|
29
29
|
|
|
30
30
|
# LiveKit Server APIs
|
|
31
31
|
|
|
@@ -21,9 +21,10 @@ from livekit.protocol.ingress import *
|
|
|
21
21
|
from livekit.protocol.models import *
|
|
22
22
|
from livekit.protocol.room import *
|
|
23
23
|
from livekit.protocol.webhook import *
|
|
24
|
+
from livekit.protocol.sip import *
|
|
24
25
|
|
|
25
26
|
from .twirp_client import TwirpError, TwirpErrorCode
|
|
26
27
|
from .livekit_api import LiveKitAPI
|
|
27
|
-
from .access_token import VideoGrants, AccessToken, TokenVerifier
|
|
28
|
+
from .access_token import VideoGrants, SIPGrants, AccessToken, TokenVerifier
|
|
28
29
|
from .webhook import WebhookReceiver
|
|
29
30
|
from .version import __version__
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from typing import Dict
|
|
2
4
|
import aiohttp
|
|
3
5
|
from abc import ABC
|
|
4
6
|
from .twirp_client import TwirpClient
|
|
5
|
-
from .access_token import AccessToken, VideoGrants
|
|
7
|
+
from .access_token import AccessToken, VideoGrants, SIPGrants
|
|
6
8
|
|
|
7
9
|
AUTHORIZATION = "authorization"
|
|
8
10
|
|
|
@@ -15,8 +17,14 @@ class Service(ABC):
|
|
|
15
17
|
self.api_key = api_key
|
|
16
18
|
self.api_secret = api_secret
|
|
17
19
|
|
|
18
|
-
def _auth_header(
|
|
19
|
-
|
|
20
|
+
def _auth_header(
|
|
21
|
+
self, grants: VideoGrants, sip: SIPGrants | None = None
|
|
22
|
+
) -> Dict[str, str]:
|
|
23
|
+
tok = AccessToken(self.api_key, self.api_secret).with_grants(grants)
|
|
24
|
+
if sip is not None:
|
|
25
|
+
tok = tok.with_sip_grants(sip)
|
|
26
|
+
|
|
27
|
+
token = tok.to_jwt()
|
|
20
28
|
|
|
21
29
|
headers = {}
|
|
22
30
|
headers[AUTHORIZATION] = "Bearer {}".format(token)
|
|
@@ -63,11 +63,20 @@ class VideoGrants:
|
|
|
63
63
|
agent: bool = False
|
|
64
64
|
|
|
65
65
|
|
|
66
|
+
@dataclasses.dataclass
|
|
67
|
+
class SIPGrants:
|
|
68
|
+
# manage sip resources
|
|
69
|
+
admin: bool = False
|
|
70
|
+
# make outbound calls
|
|
71
|
+
call: bool = False
|
|
72
|
+
|
|
73
|
+
|
|
66
74
|
@dataclasses.dataclass
|
|
67
75
|
class Claims:
|
|
68
76
|
identity: str = ""
|
|
69
77
|
name: str = ""
|
|
70
78
|
video: VideoGrants = dataclasses.field(default_factory=VideoGrants)
|
|
79
|
+
sip: SIPGrants = dataclasses.field(default_factory=SIPGrants)
|
|
71
80
|
metadata: str = ""
|
|
72
81
|
sha256: str = ""
|
|
73
82
|
|
|
@@ -100,6 +109,10 @@ class AccessToken:
|
|
|
100
109
|
self.claims.video = grants
|
|
101
110
|
return self
|
|
102
111
|
|
|
112
|
+
def with_sip_grants(self, grants: SIPGrants) -> "AccessToken":
|
|
113
|
+
self.claims.sip = grants
|
|
114
|
+
return self
|
|
115
|
+
|
|
103
116
|
def with_identity(self, identity: str) -> "AccessToken":
|
|
104
117
|
self.identity = identity
|
|
105
118
|
return self
|
|
@@ -173,10 +186,18 @@ class TokenVerifier:
|
|
|
173
186
|
}
|
|
174
187
|
video = VideoGrants(**video_dict)
|
|
175
188
|
|
|
189
|
+
sip_dict = claims.get("sip", dict())
|
|
190
|
+
sip_dict = {camel_to_snake(k): v for k, v in sip_dict.items()}
|
|
191
|
+
sip_dict = {
|
|
192
|
+
k: v for k, v in sip_dict.items() if k in SIPGrants.__dataclass_fields__
|
|
193
|
+
}
|
|
194
|
+
sip = SIPGrants(**sip_dict)
|
|
195
|
+
|
|
176
196
|
return Claims(
|
|
177
197
|
identity=claims.get("sub", ""),
|
|
178
198
|
name=claims.get("name", ""),
|
|
179
199
|
video=video,
|
|
200
|
+
sip=sip,
|
|
180
201
|
metadata=claims.get("metadata", ""),
|
|
181
202
|
sha256=claims.get("sha256", ""),
|
|
182
203
|
)
|
|
@@ -3,6 +3,7 @@ import os
|
|
|
3
3
|
from .room_service import RoomService
|
|
4
4
|
from .egress_service import EgressService
|
|
5
5
|
from .ingress_service import IngressService
|
|
6
|
+
from .sip_service import SipService
|
|
6
7
|
from typing import Optional
|
|
7
8
|
|
|
8
9
|
|
|
@@ -29,6 +30,7 @@ class LiveKitAPI:
|
|
|
29
30
|
self._room = RoomService(self._session, url, api_key, api_secret)
|
|
30
31
|
self._ingress = IngressService(self._session, url, api_key, api_secret)
|
|
31
32
|
self._egress = EgressService(self._session, url, api_key, api_secret)
|
|
33
|
+
self._sip = SipService(self._session, url, api_key, api_secret)
|
|
32
34
|
|
|
33
35
|
@property
|
|
34
36
|
def room(self):
|
|
@@ -42,5 +44,9 @@ class LiveKitAPI:
|
|
|
42
44
|
def egress(self):
|
|
43
45
|
return self._egress
|
|
44
46
|
|
|
47
|
+
@property
|
|
48
|
+
def sip(self):
|
|
49
|
+
return self._sip
|
|
50
|
+
|
|
45
51
|
async def aclose(self):
|
|
46
52
|
await self._session.close()
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import aiohttp
|
|
2
|
+
from livekit.protocol import sip as proto_sip
|
|
3
|
+
from ._service import Service
|
|
4
|
+
from .access_token import VideoGrants, SIPGrants
|
|
5
|
+
|
|
6
|
+
SVC = "SIP"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SipService(Service):
|
|
10
|
+
def __init__(
|
|
11
|
+
self, session: aiohttp.ClientSession, url: str, api_key: str, api_secret: str
|
|
12
|
+
):
|
|
13
|
+
super().__init__(session, url, api_key, api_secret)
|
|
14
|
+
|
|
15
|
+
async def create_sip_trunk(
|
|
16
|
+
self, create: proto_sip.CreateSIPTrunkRequest
|
|
17
|
+
) -> proto_sip.SIPTrunkInfo:
|
|
18
|
+
return await self._client.request(
|
|
19
|
+
SVC,
|
|
20
|
+
"CreateSIPTrunk",
|
|
21
|
+
create,
|
|
22
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
23
|
+
proto_sip.SIPTrunkInfo,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
async def create_sip_inbound_trunk(
|
|
27
|
+
self, create: proto_sip.CreateSIPInboundTrunkRequest
|
|
28
|
+
) -> proto_sip.SIPInboundTrunkInfo:
|
|
29
|
+
return await self._client.request(
|
|
30
|
+
SVC,
|
|
31
|
+
"CreateSIPInboundTrunk",
|
|
32
|
+
create,
|
|
33
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
34
|
+
proto_sip.SIPInboundTrunkInfo,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
async def create_sip_outbound_trunk(
|
|
38
|
+
self, create: proto_sip.CreateSIPOutboundTrunkRequest
|
|
39
|
+
) -> proto_sip.SIPOutboundTrunkInfo:
|
|
40
|
+
return await self._client.request(
|
|
41
|
+
SVC,
|
|
42
|
+
"CreateSIPOutboundTrunk",
|
|
43
|
+
create,
|
|
44
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
45
|
+
proto_sip.SIPOutboundTrunkInfo,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
async def list_sip_trunk(
|
|
49
|
+
self, list: proto_sip.ListSIPTrunkRequest
|
|
50
|
+
) -> proto_sip.ListSIPTrunkResponse:
|
|
51
|
+
return await self._client.request(
|
|
52
|
+
SVC,
|
|
53
|
+
"ListSIPTrunk",
|
|
54
|
+
list,
|
|
55
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
56
|
+
proto_sip.ListSIPTrunkResponse,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
async def list_sip_inbound_trunk(
|
|
60
|
+
self, list: proto_sip.ListSIPInboundTrunkRequest
|
|
61
|
+
) -> proto_sip.ListSIPInboundTrunkResponse:
|
|
62
|
+
return await self._client.request(
|
|
63
|
+
SVC,
|
|
64
|
+
"ListSIPInboundTrunk",
|
|
65
|
+
list,
|
|
66
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
67
|
+
proto_sip.ListSIPInboundTrunkResponse,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
async def list_sip_outbound_trunk(
|
|
71
|
+
self, list: proto_sip.ListSIPOutboundTrunkRequest
|
|
72
|
+
) -> proto_sip.ListSIPOutboundTrunkResponse:
|
|
73
|
+
return await self._client.request(
|
|
74
|
+
SVC,
|
|
75
|
+
"ListSIPOutboundTrunk",
|
|
76
|
+
list,
|
|
77
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
78
|
+
proto_sip.ListSIPOutboundTrunkResponse,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
async def delete_sip_trunk(
|
|
82
|
+
self, delete: proto_sip.DeleteSIPTrunkRequest
|
|
83
|
+
) -> proto_sip.SIPTrunkInfo:
|
|
84
|
+
return await self._client.request(
|
|
85
|
+
SVC,
|
|
86
|
+
"DeleteSIPTrunk",
|
|
87
|
+
delete,
|
|
88
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
89
|
+
proto_sip.SIPTrunkInfo,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
async def create_sip_dispatch_rule(
|
|
93
|
+
self, create: proto_sip.CreateSIPDispatchRuleRequest
|
|
94
|
+
) -> proto_sip.SIPDispatchRuleInfo:
|
|
95
|
+
return await self._client.request(
|
|
96
|
+
SVC,
|
|
97
|
+
"CreateSIPDispatchRule",
|
|
98
|
+
create,
|
|
99
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
100
|
+
proto_sip.SIPDispatchRuleInfo,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
async def list_sip_dispatch_rule(
|
|
104
|
+
self, list: proto_sip.ListSIPDispatchRuleRequest
|
|
105
|
+
) -> proto_sip.ListSIPDispatchRuleResponse:
|
|
106
|
+
return await self._client.request(
|
|
107
|
+
SVC,
|
|
108
|
+
"ListSIPDispatchRule",
|
|
109
|
+
list,
|
|
110
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
111
|
+
proto_sip.ListSIPDispatchRuleResponse,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
async def delete_sip_dispatch_rule(
|
|
115
|
+
self, delete: proto_sip.DeleteSIPDispatchRuleRequest
|
|
116
|
+
) -> proto_sip.SIPDispatchRuleInfo:
|
|
117
|
+
return await self._client.request(
|
|
118
|
+
SVC,
|
|
119
|
+
"DeleteSIPDispatchRule",
|
|
120
|
+
delete,
|
|
121
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(admin=True)),
|
|
122
|
+
proto_sip.SIPDispatchRuleInfo,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
async def create_sip_participant(
|
|
126
|
+
self, create: proto_sip.CreateSIPParticipantRequest
|
|
127
|
+
) -> proto_sip.SIPParticipantInfo:
|
|
128
|
+
return await self._client.request(
|
|
129
|
+
SVC,
|
|
130
|
+
"CreateSIPParticipant",
|
|
131
|
+
create,
|
|
132
|
+
self._auth_header(VideoGrants(), sip=SIPGrants(call=True)),
|
|
133
|
+
proto_sip.SIPParticipantInfo,
|
|
134
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.5.1"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: livekit-api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: Python Server API for LiveKit
|
|
5
5
|
Home-page: https://github.com/livekit/python-sdks
|
|
6
6
|
License: Apache-2.0
|
|
@@ -19,13 +19,13 @@ Classifier: Programming Language :: Python :: 3.8
|
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.9
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
21
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
|
-
Requires-Python: >=3.
|
|
22
|
+
Requires-Python: >=3.9.0
|
|
23
23
|
Description-Content-Type: text/markdown
|
|
24
24
|
Requires-Dist: pyjwt>=2.0.0
|
|
25
25
|
Requires-Dist: aiohttp>=3.9.0
|
|
26
26
|
Requires-Dist: protobuf>=3
|
|
27
27
|
Requires-Dist: types-protobuf<5,>=4
|
|
28
|
-
Requires-Dist: livekit-protocol<
|
|
28
|
+
Requires-Dist: livekit-protocol<2,>=0.5.1
|
|
29
29
|
|
|
30
30
|
# LiveKit Server APIs
|
|
31
31
|
|
|
@@ -47,13 +47,13 @@ setuptools.setup(
|
|
|
47
47
|
keywords=["webrtc", "realtime", "audio", "video", "livekit"],
|
|
48
48
|
license="Apache-2.0",
|
|
49
49
|
packages=setuptools.find_namespace_packages(include=["livekit.*"]),
|
|
50
|
-
python_requires=">=3.
|
|
50
|
+
python_requires=">=3.9.0",
|
|
51
51
|
install_requires=[
|
|
52
52
|
"pyjwt>=2.0.0",
|
|
53
53
|
"aiohttp>=3.9.0",
|
|
54
54
|
"protobuf>=3",
|
|
55
55
|
"types-protobuf>=4,<5",
|
|
56
|
-
"livekit-protocol>=0.
|
|
56
|
+
"livekit-protocol>=0.5.1,<2",
|
|
57
57
|
],
|
|
58
58
|
package_data={
|
|
59
59
|
"livekit.api": ["py.typed", "*.pyi", "**/*.pyi"],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import datetime
|
|
2
2
|
|
|
3
3
|
import pytest # type: ignore
|
|
4
|
-
from livekit.api import AccessToken, TokenVerifier, VideoGrants
|
|
4
|
+
from livekit.api import AccessToken, TokenVerifier, VideoGrants, SIPGrants
|
|
5
5
|
|
|
6
6
|
TEST_API_KEY = "myapikey"
|
|
7
7
|
TEST_API_SECRET = "thiskeyistotallyunsafe"
|
|
@@ -9,12 +9,14 @@ TEST_API_SECRET = "thiskeyistotallyunsafe"
|
|
|
9
9
|
|
|
10
10
|
def test_verify_token():
|
|
11
11
|
grants = VideoGrants(room_join=True, room="test_room")
|
|
12
|
+
sip = SIPGrants(admin=True)
|
|
12
13
|
|
|
13
14
|
token = (
|
|
14
15
|
AccessToken(TEST_API_KEY, TEST_API_SECRET)
|
|
15
16
|
.with_identity("test_identity")
|
|
16
17
|
.with_metadata("test_metadata")
|
|
17
18
|
.with_grants(grants)
|
|
19
|
+
.with_sip_grants(sip)
|
|
18
20
|
.to_jwt()
|
|
19
21
|
)
|
|
20
22
|
|
|
@@ -24,6 +26,7 @@ def test_verify_token():
|
|
|
24
26
|
assert claims.identity == "test_identity"
|
|
25
27
|
assert claims.metadata == "test_metadata"
|
|
26
28
|
assert claims.video == grants
|
|
29
|
+
assert claims.sip == sip
|
|
27
30
|
|
|
28
31
|
|
|
29
32
|
def test_verify_token_invalid():
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.4.4"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|