eduskit 0.1.2__tar.gz → 0.1.5__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.
- {eduskit-0.1.2 → eduskit-0.1.5}/PKG-INFO +1 -1
- {eduskit-0.1.2 → eduskit-0.1.5}/eduskit/classroom.py +16 -14
- eduskit-0.1.5/eduskit/whiteboard.py +148 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/eduskit.egg-info/PKG-INFO +1 -1
- {eduskit-0.1.2 → eduskit-0.1.5}/pyproject.toml +1 -1
- {eduskit-0.1.2 → eduskit-0.1.5}/tests/test_eduskit.py +38 -0
- eduskit-0.1.2/eduskit/whiteboard.py +0 -104
- {eduskit-0.1.2 → eduskit-0.1.5}/LICENSE +0 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/README.md +0 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/eduskit/__init__.py +0 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/eduskit/errors.py +0 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/eduskit/http.py +0 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/eduskit/token.py +0 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/eduskit.egg-info/SOURCES.txt +0 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/eduskit.egg-info/dependency_links.txt +0 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/eduskit.egg-info/top_level.txt +0 -0
- {eduskit-0.1.2 → eduskit-0.1.5}/setup.cfg +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from urllib.parse import urlencode
|
|
4
|
+
|
|
3
5
|
from typing import Any
|
|
4
6
|
|
|
5
7
|
from .http import HttpTransport
|
|
@@ -42,16 +44,16 @@ class _Members:
|
|
|
42
44
|
self._http = http
|
|
43
45
|
|
|
44
46
|
def add(self, classroom_id: str, **input: Any) -> Any:
|
|
45
|
-
return self._http.request("POST",
|
|
47
|
+
return self._http.request("POST", '/v1/classrooms/members', {**(input or {}), 'classroomId': classroom_id})
|
|
46
48
|
|
|
47
49
|
def list(self, classroom_id: str) -> Any:
|
|
48
|
-
return self._http.request("GET",
|
|
50
|
+
return self._http.request("GET", '/v1/classrooms/members' + "?" + urlencode({'classroomId': classroom_id}))
|
|
49
51
|
|
|
50
52
|
def replace_students(self, classroom_id: str, **input: Any) -> Any:
|
|
51
53
|
return self._http.request(
|
|
52
54
|
"PUT",
|
|
53
|
-
|
|
54
|
-
input,
|
|
55
|
+
'/v1/classrooms/members/students',
|
|
56
|
+
{**(input or {}), 'classroomId': classroom_id},
|
|
55
57
|
)
|
|
56
58
|
|
|
57
59
|
|
|
@@ -62,14 +64,14 @@ class _Permissions:
|
|
|
62
64
|
def get(self, classroom_id: str, edu_user_id: str) -> Any:
|
|
63
65
|
return self._http.request(
|
|
64
66
|
"GET",
|
|
65
|
-
|
|
67
|
+
'/v1/classrooms/members/permissions' + "?" + urlencode({'classroomId': classroom_id, 'eduUserId': edu_user_id}),
|
|
66
68
|
)
|
|
67
69
|
|
|
68
70
|
def set(self, classroom_id: str, edu_user_id: str, **input: Any) -> Any:
|
|
69
71
|
return self._http.request(
|
|
70
72
|
"POST",
|
|
71
|
-
|
|
72
|
-
input,
|
|
73
|
+
'/v1/classrooms/members/permissions',
|
|
74
|
+
{**(input or {}), 'classroomId': classroom_id, 'eduUserId': edu_user_id},
|
|
73
75
|
)
|
|
74
76
|
|
|
75
77
|
def clear(
|
|
@@ -81,7 +83,7 @@ class _Permissions:
|
|
|
81
83
|
) -> Any:
|
|
82
84
|
return self._http.request(
|
|
83
85
|
"DELETE",
|
|
84
|
-
|
|
86
|
+
'/v1/classrooms/members/permissions' + "?" + urlencode({'classroomId': classroom_id, 'eduUserId': edu_user_id, 'permission': permission}),
|
|
85
87
|
input,
|
|
86
88
|
)
|
|
87
89
|
|
|
@@ -91,19 +93,19 @@ class _Coursewares:
|
|
|
91
93
|
self._http = http
|
|
92
94
|
|
|
93
95
|
def list(self, classroom_id: str) -> Any:
|
|
94
|
-
return self._http.request("GET",
|
|
96
|
+
return self._http.request("GET", '/v1/classrooms/coursewares' + "?" + urlencode({'classroomId': classroom_id}))
|
|
95
97
|
|
|
96
98
|
def bind(self, classroom_id: str, **input: Any) -> Any:
|
|
97
99
|
return self._http.request(
|
|
98
100
|
"POST",
|
|
99
|
-
|
|
100
|
-
input,
|
|
101
|
+
'/v1/classrooms/coursewares',
|
|
102
|
+
{**(input or {}), 'classroomId': classroom_id},
|
|
101
103
|
)
|
|
102
104
|
|
|
103
105
|
def unbind(self, classroom_id: str, **input: Any) -> Any:
|
|
104
106
|
return self._http.request(
|
|
105
107
|
"DELETE",
|
|
106
|
-
|
|
108
|
+
'/v1/classrooms/coursewares' + "?" + urlencode({'classroomId': classroom_id}),
|
|
107
109
|
input,
|
|
108
110
|
)
|
|
109
111
|
|
|
@@ -119,10 +121,10 @@ class _Classrooms:
|
|
|
119
121
|
return self._http.request("POST", "/v1/classrooms", input)
|
|
120
122
|
|
|
121
123
|
def start(self, classroom_id: str) -> Any:
|
|
122
|
-
return self._http.request("POST",
|
|
124
|
+
return self._http.request("POST", '/v1/classrooms/start', {'classroomId': classroom_id})
|
|
123
125
|
|
|
124
126
|
def end(self, classroom_id: str) -> Any:
|
|
125
|
-
return self._http.request("POST",
|
|
127
|
+
return self._http.request("POST", '/v1/classrooms/end', {'classroomId': classroom_id})
|
|
126
128
|
|
|
127
129
|
|
|
128
130
|
class _App:
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from urllib.parse import urlencode
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from .http import HttpTransport
|
|
8
|
+
from .errors import EduskitError
|
|
9
|
+
from .token import iso_time, sign_hs256
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class _Auth:
|
|
13
|
+
def __init__(self, app_id: str, app_secret: str) -> None:
|
|
14
|
+
self._app_id = app_id
|
|
15
|
+
self._app_secret = app_secret
|
|
16
|
+
|
|
17
|
+
def issue_room_token(self, **input: Any) -> Any:
|
|
18
|
+
room_id, user_id, role = input.get("roomId"), input.get("userId"), input.get("role")
|
|
19
|
+
if not room_id or not user_id or role not in ("host", "participant", "observer"):
|
|
20
|
+
raise EduskitError("roomId, userId and a valid role are required", error_code="SDK_TOKEN_INPUT_INVALID", source="whiteboard")
|
|
21
|
+
expires_in = input.get("expiresIn", 3600)
|
|
22
|
+
token, expires_at = sign_hs256(self._app_id, self._app_secret, user_id,
|
|
23
|
+
"eduskit", "eduskit-room", expires_in,
|
|
24
|
+
{"app_id": self._app_id, "room_id": room_id, "role": role, "source": "server_sdk", "access_generation": None},
|
|
25
|
+
"whiteboard")
|
|
26
|
+
return {"token": token, "appId": self._app_id, "roomId": room_id, "userId": user_id,
|
|
27
|
+
"role": role, "expiresIn": expires_in, "expiresAt": iso_time(expires_at)}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class _Recordings:
|
|
31
|
+
def __init__(self, http: HttpTransport) -> None:
|
|
32
|
+
self._http = http
|
|
33
|
+
|
|
34
|
+
def start(self, room_id: str, **input: Any) -> Any:
|
|
35
|
+
return self._http.request("POST", '/v1/rooms/recording/start', {**(input or {}), 'roomId': room_id})
|
|
36
|
+
|
|
37
|
+
def stop(self, room_id: str, **input: Any) -> Any:
|
|
38
|
+
return self._http.request("POST", '/v1/rooms/recording/stop', {**(input or {}), 'roomId': room_id})
|
|
39
|
+
|
|
40
|
+
def list(self, room_id: str) -> Any:
|
|
41
|
+
return self._http.request("GET", '/v1/rooms/recordings' + "?" + urlencode({'roomId': room_id}))
|
|
42
|
+
|
|
43
|
+
def get(self, recording_id: str) -> Any:
|
|
44
|
+
return self._http.request("GET", '/v1/recordings' + "?" + urlencode({'recordingId': recording_id}))
|
|
45
|
+
|
|
46
|
+
def register_media_asset(self, recording_id: str, **input: Any) -> Any:
|
|
47
|
+
return self._http.request(
|
|
48
|
+
"POST",
|
|
49
|
+
'/v1/recordings/media-assets',
|
|
50
|
+
{**(input or {}), 'recordingId': recording_id},
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def delete_media_asset(self, recording_id: str, asset_id: str) -> Any:
|
|
54
|
+
return self._http.request(
|
|
55
|
+
"DELETE",
|
|
56
|
+
'/v1/recordings/media-assets' + "?" + urlencode({'recordingId': recording_id, 'assetId': asset_id}),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
def enqueue_video_export(self, recording_id: str, **input: Any) -> Any:
|
|
60
|
+
return self._http.request(
|
|
61
|
+
"POST",
|
|
62
|
+
'/v1/recordings/video-exports',
|
|
63
|
+
{**(input or {}), 'recordingId': recording_id},
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def get_video_export(self, recording_id: str, job_id: str) -> Any:
|
|
67
|
+
return self._http.request(
|
|
68
|
+
"GET",
|
|
69
|
+
'/v1/recordings/video-exports' + "?" + urlencode({'recordingId': recording_id, 'jobId': job_id}),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class _Captures:
|
|
74
|
+
def __init__(self, http: HttpTransport) -> None:
|
|
75
|
+
self._http = http
|
|
76
|
+
|
|
77
|
+
def create(self, room_id: str, **input: Any) -> Any:
|
|
78
|
+
body = {"roomId": room_id, **input}
|
|
79
|
+
return self._http.request("POST", '/v1/rooms/captures', {**(body or {}), 'roomId': room_id})
|
|
80
|
+
|
|
81
|
+
def list(self, room_id: str) -> Any:
|
|
82
|
+
return self._http.request("GET", '/v1/rooms/captures' + "?" + urlencode({'roomId': room_id}))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class _Files:
|
|
86
|
+
def __init__(self, http: HttpTransport) -> None:
|
|
87
|
+
self._http = http
|
|
88
|
+
|
|
89
|
+
def convert(self, **input: Any) -> Any:
|
|
90
|
+
return self._http.request("POST", "/v1/files/convert", input)
|
|
91
|
+
|
|
92
|
+
def get_convert_job(self, job_id: str) -> Any:
|
|
93
|
+
return self._http.request("GET", '/v1/files/convert' + "?" + urlencode({'jobId': job_id}))
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class _Rooms:
|
|
97
|
+
def __init__(self, http: HttpTransport) -> None:
|
|
98
|
+
self._http = http
|
|
99
|
+
|
|
100
|
+
def schedule_private_room_writes(self, room_id: str, request_id: str, opens_at: str, closes_at: str) -> Any:
|
|
101
|
+
return self._http.request("POST", "/v1/rooms/private/write-window", {"roomId": room_id, "requestId": request_id, "opensAt": opens_at, "closesAt": closes_at})
|
|
102
|
+
|
|
103
|
+
def provision_private_room(self, room_id: str, assignment_id: str) -> Any:
|
|
104
|
+
return self._http.request("POST", "/v1/rooms/private", {"roomId": room_id, "assignmentId": assignment_id})
|
|
105
|
+
|
|
106
|
+
def initialize_private_workspace(self, room_id: str, assignment_id: str, source_snapshot_id: str | None) -> Any:
|
|
107
|
+
return self._http.request("POST", "/v1/rooms/private/initializations", {"roomId": room_id, "assignmentId": assignment_id, "sourceSnapshotId": source_snapshot_id})
|
|
108
|
+
|
|
109
|
+
def get_private_workspace_initialization(self, room_id: str) -> Any:
|
|
110
|
+
return self._http.request("POST", "/v1/rooms/private/initializations/query", {"roomId": room_id})
|
|
111
|
+
|
|
112
|
+
def change_private_room_grant(self, room_id: str, **input: Any) -> Any:
|
|
113
|
+
return self._http.request("POST", "/v1/rooms/private/grants", {**input, "roomId": room_id})
|
|
114
|
+
|
|
115
|
+
def get_private_room_access(self, room_id: str, user_id: str) -> Any:
|
|
116
|
+
return self._http.request("POST", "/v1/rooms/private/access/query", {"roomId": room_id, "userId": user_id})
|
|
117
|
+
|
|
118
|
+
def issue_private_room_token(self, room_id: str, **input: Any) -> Any:
|
|
119
|
+
return self._http.request("POST", "/v1/rooms/private/token", {**input, "roomId": room_id})
|
|
120
|
+
|
|
121
|
+
def seal_private_room(self, room_id: str) -> Any:
|
|
122
|
+
return self._http.request("POST", "/v1/rooms/private/seal", {"roomId": room_id})
|
|
123
|
+
|
|
124
|
+
def create_frozen_snapshot(self, room_id: str, snapshot_id: str) -> Any:
|
|
125
|
+
return self._http.request("POST", "/v1/rooms/private/snapshots", {"roomId": room_id, "snapshotId": snapshot_id})
|
|
126
|
+
|
|
127
|
+
def get_frozen_snapshot(self, room_id: str, snapshot_id: str) -> Any:
|
|
128
|
+
return self._http.request("POST", "/v1/rooms/private/snapshots/query", {"roomId": room_id, "snapshotId": snapshot_id})
|
|
129
|
+
|
|
130
|
+
def get_frozen_snapshot_download(self, room_id: str, snapshot_id: str) -> Any:
|
|
131
|
+
return self._http.request("POST", "/v1/rooms/private/snapshots/download", {"roomId": room_id, "snapshotId": snapshot_id})
|
|
132
|
+
|
|
133
|
+
def attach_courseware(self, room_id: str, **input: Any) -> Any:
|
|
134
|
+
return self._http.request("POST", "/v1/rooms/coursewares", {**input, "roomId": room_id})
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class WhiteboardClient:
|
|
138
|
+
def __init__(self, http: HttpTransport, *, app_id: str, app_secret: str) -> None:
|
|
139
|
+
self.auth = _Auth(app_id, app_secret)
|
|
140
|
+
self.recordings = _Recordings(http)
|
|
141
|
+
self.captures = _Captures(http)
|
|
142
|
+
self.files = _Files(http)
|
|
143
|
+
self.rooms = _Rooms(http)
|
|
144
|
+
self._http = http
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def last_trace_id(self) -> str:
|
|
148
|
+
return self._http.last_trace_id
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import base64
|
|
2
3
|
import unittest
|
|
3
4
|
|
|
4
5
|
from eduskit import Eduskit, EduskitError
|
|
@@ -22,6 +23,39 @@ def mock_fetch(body, status=200, headers=None):
|
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class EduskitTest(unittest.TestCase):
|
|
26
|
+
def test_private_room_server_routes(self):
|
|
27
|
+
fetch, calls = mock_fetch({"code": 0, "data": {"marker": "server-result"}})
|
|
28
|
+
sdk = Eduskit(whiteboard_client={"base_url": "http://wb.test", "app_id": "app_wb", "app_key": "wk", "app_secret": "ws"}, fetch=fetch)
|
|
29
|
+
rooms = sdk.whiteboard_client.rooms
|
|
30
|
+
operations = [
|
|
31
|
+
lambda: rooms.provision_private_room("room_a", "assignment_a"),
|
|
32
|
+
lambda: rooms.change_private_room_grant("room_a", userId="student_a", requestId="grant_a", expectedGeneration="9223372036854775806", action="grant", role="participant"),
|
|
33
|
+
lambda: rooms.get_private_room_access("room_a", "student_a"),
|
|
34
|
+
lambda: rooms.issue_private_room_token("room_a", userId="student_a", role="participant", expiresIn=600),
|
|
35
|
+
lambda: rooms.seal_private_room("room_a"),
|
|
36
|
+
lambda: rooms.create_frozen_snapshot("room_a", "snapshot_a"),
|
|
37
|
+
lambda: rooms.get_frozen_snapshot("room_a", "snapshot_a"),
|
|
38
|
+
lambda: rooms.get_frozen_snapshot_download("room_a", "snapshot_a"),
|
|
39
|
+
lambda: rooms.initialize_private_workspace("room_a", "assignment_a", None),
|
|
40
|
+
lambda: rooms.initialize_private_workspace("room_a", "assignment_a", "snapshot_a"),
|
|
41
|
+
lambda: rooms.get_private_workspace_initialization("room_a"),
|
|
42
|
+
lambda: rooms.schedule_private_room_writes("room_a", "window_a", "2026-10-02T00:00:00.000Z", "2026-10-02T00:10:00.000Z"),
|
|
43
|
+
]
|
|
44
|
+
for operation in operations:
|
|
45
|
+
self.assertEqual(operation(), {"marker": "server-result"})
|
|
46
|
+
expected = ["", "/grants", "/access/query", "/token", "/seal", "/snapshots", "/snapshots/query", "/snapshots/download", "/initializations", "/initializations", "/initializations/query", "/write-window"]
|
|
47
|
+
self.assertEqual([call["url"] for call in calls], ["http://wb.test/v1/rooms/private" + suffix for suffix in expected])
|
|
48
|
+
for call in calls:
|
|
49
|
+
self.assertEqual(call["method"], "POST")
|
|
50
|
+
self.assertEqual(call["body"]["roomId"], "room_a")
|
|
51
|
+
self.assertEqual(call["headers"]["x-app-key"], "wk")
|
|
52
|
+
self.assertEqual(calls[1]["body"]["expectedGeneration"], "9223372036854775806")
|
|
53
|
+
self.assertNotIn("accessGeneration", calls[3]["body"])
|
|
54
|
+
self.assertEqual(calls[8]["body"], {"roomId": "room_a", "assignmentId": "assignment_a", "sourceSnapshotId": None})
|
|
55
|
+
self.assertEqual(calls[9]["body"]["sourceSnapshotId"], "snapshot_a")
|
|
56
|
+
self.assertEqual(calls[10]["body"], {"roomId": "room_a"})
|
|
57
|
+
self.assertEqual(calls[11]["body"], {"roomId":"room_a", "requestId":"window_a", "opensAt":"2026-10-02T00:00:00.000Z", "closesAt":"2026-10-02T00:10:00.000Z"})
|
|
58
|
+
|
|
25
59
|
def test_classroom_register(self):
|
|
26
60
|
fetch, calls = mock_fetch(
|
|
27
61
|
{
|
|
@@ -56,6 +90,10 @@ class EduskitTest(unittest.TestCase):
|
|
|
56
90
|
)
|
|
57
91
|
self.assertEqual(token["appId"], "app_wb")
|
|
58
92
|
self.assertEqual(len(token["token"].split(".")), 3)
|
|
93
|
+
segment = token["token"].split(".")[1]
|
|
94
|
+
claims = json.loads(base64.urlsafe_b64decode(segment + "=" * (-len(segment) % 4)))
|
|
95
|
+
self.assertIn("access_generation", claims)
|
|
96
|
+
self.assertIsNone(claims["access_generation"])
|
|
59
97
|
self.assertEqual(calls, [])
|
|
60
98
|
|
|
61
99
|
def test_error_envelope(self):
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import Any
|
|
4
|
-
|
|
5
|
-
from .http import HttpTransport
|
|
6
|
-
from .errors import EduskitError
|
|
7
|
-
from .token import iso_time, sign_hs256
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class _Auth:
|
|
11
|
-
def __init__(self, app_id: str, app_secret: str) -> None:
|
|
12
|
-
self._app_id = app_id
|
|
13
|
-
self._app_secret = app_secret
|
|
14
|
-
|
|
15
|
-
def issue_room_token(self, **input: Any) -> Any:
|
|
16
|
-
room_id, user_id, role = input.get("roomId"), input.get("userId"), input.get("role")
|
|
17
|
-
if not room_id or not user_id or role not in ("host", "participant", "observer"):
|
|
18
|
-
raise EduskitError("roomId, userId and a valid role are required", error_code="SDK_TOKEN_INPUT_INVALID", source="whiteboard")
|
|
19
|
-
expires_in = input.get("expiresIn", 3600)
|
|
20
|
-
token, expires_at = sign_hs256(self._app_id, self._app_secret, user_id,
|
|
21
|
-
"eduskit", "eduskit-room", expires_in,
|
|
22
|
-
{"app_id": self._app_id, "room_id": room_id, "role": role, "source": "server_sdk"},
|
|
23
|
-
"whiteboard")
|
|
24
|
-
return {"token": token, "appId": self._app_id, "roomId": room_id, "userId": user_id,
|
|
25
|
-
"role": role, "expiresIn": expires_in, "expiresAt": iso_time(expires_at)}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class _Recordings:
|
|
29
|
-
def __init__(self, http: HttpTransport) -> None:
|
|
30
|
-
self._http = http
|
|
31
|
-
|
|
32
|
-
def start(self, room_id: str, **input: Any) -> Any:
|
|
33
|
-
return self._http.request("POST", f"/v1/rooms/{room_id}/recording/start", input)
|
|
34
|
-
|
|
35
|
-
def stop(self, room_id: str, **input: Any) -> Any:
|
|
36
|
-
return self._http.request("POST", f"/v1/rooms/{room_id}/recording/stop", input)
|
|
37
|
-
|
|
38
|
-
def list(self, room_id: str) -> Any:
|
|
39
|
-
return self._http.request("GET", f"/v1/rooms/{room_id}/recordings")
|
|
40
|
-
|
|
41
|
-
def get(self, recording_id: str) -> Any:
|
|
42
|
-
return self._http.request("GET", f"/v1/recordings/{recording_id}")
|
|
43
|
-
|
|
44
|
-
def register_media_asset(self, recording_id: str, **input: Any) -> Any:
|
|
45
|
-
return self._http.request(
|
|
46
|
-
"POST",
|
|
47
|
-
f"/v1/recordings/{recording_id}/media-assets",
|
|
48
|
-
input,
|
|
49
|
-
)
|
|
50
|
-
|
|
51
|
-
def delete_media_asset(self, recording_id: str, asset_id: str) -> Any:
|
|
52
|
-
return self._http.request(
|
|
53
|
-
"DELETE",
|
|
54
|
-
f"/v1/recordings/{recording_id}/media-assets/{asset_id}",
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
def enqueue_video_export(self, recording_id: str, **input: Any) -> Any:
|
|
58
|
-
return self._http.request(
|
|
59
|
-
"POST",
|
|
60
|
-
f"/v1/recordings/{recording_id}/video-exports",
|
|
61
|
-
input,
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
def get_video_export(self, recording_id: str, job_id: str) -> Any:
|
|
65
|
-
return self._http.request(
|
|
66
|
-
"GET",
|
|
67
|
-
f"/v1/recordings/{recording_id}/video-exports/{job_id}",
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
class _Captures:
|
|
72
|
-
def __init__(self, http: HttpTransport) -> None:
|
|
73
|
-
self._http = http
|
|
74
|
-
|
|
75
|
-
def create(self, room_id: str, **input: Any) -> Any:
|
|
76
|
-
body = {"roomId": room_id, **input}
|
|
77
|
-
return self._http.request("POST", f"/v1/rooms/{room_id}/captures", body)
|
|
78
|
-
|
|
79
|
-
def list(self, room_id: str) -> Any:
|
|
80
|
-
return self._http.request("GET", f"/v1/rooms/{room_id}/captures")
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
class _Files:
|
|
84
|
-
def __init__(self, http: HttpTransport) -> None:
|
|
85
|
-
self._http = http
|
|
86
|
-
|
|
87
|
-
def convert(self, **input: Any) -> Any:
|
|
88
|
-
return self._http.request("POST", "/v1/files/convert", input)
|
|
89
|
-
|
|
90
|
-
def get_convert_job(self, job_id: str) -> Any:
|
|
91
|
-
return self._http.request("GET", f"/v1/files/convert/{job_id}")
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
class WhiteboardClient:
|
|
95
|
-
def __init__(self, http: HttpTransport, *, app_id: str, app_secret: str) -> None:
|
|
96
|
-
self.auth = _Auth(app_id, app_secret)
|
|
97
|
-
self.recordings = _Recordings(http)
|
|
98
|
-
self.captures = _Captures(http)
|
|
99
|
-
self.files = _Files(http)
|
|
100
|
-
self._http = http
|
|
101
|
-
|
|
102
|
-
@property
|
|
103
|
-
def last_trace_id(self) -> str:
|
|
104
|
-
return self._http.last_trace_id
|
|
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
|