From 208c16ba4668a9ce84662fe2cbbdbddefd1bf25f Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Mon, 9 Feb 2026 23:29:31 +0100 Subject: [PATCH 01/10] Allow to call streaming status with a settings object --- example/get_meeting_livestream.py | 5 ++--- example/get_rooms.py | 2 +- example/start_meeting_livestream.py | 26 ++++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 example/start_meeting_livestream.py diff --git a/example/get_meeting_livestream.py b/example/get_meeting_livestream.py index b225fa1..a1ded34 100644 --- a/example/get_meeting_livestream.py +++ b/example/get_meeting_livestream.py @@ -9,7 +9,6 @@ MEETING_ID = os.environ["MEETING_ID"] -result = zoom_client.meeting_livestreams.get_livestream( - MEETING_ID, -) +result = zoom_client.meeting_livestreams.get_livestream(MEETING_ID) print(result) + diff --git a/example/get_rooms.py b/example/get_rooms.py index adbe573..e9192b6 100644 --- a/example/get_rooms.py +++ b/example/get_rooms.py @@ -9,7 +9,7 @@ logger = setup_logs(log_level=logging.DEBUG) -zoom_client = ZoomApiClient.init_from_dotenv(use_path=".") +zoom_client = ZoomApiClient.init_from_dotenv(use_path="/Users/rgaspar/Documents/gitprojects/zoom-python-client") parameters = RoomsListDict( type=RoomType.ZOOM_ROOM, diff --git a/example/start_meeting_livestream.py b/example/start_meeting_livestream.py new file mode 100644 index 0000000..9e93f3d --- /dev/null +++ b/example/start_meeting_livestream.py @@ -0,0 +1,26 @@ +import logging +import os + +from zoom_python_client.utils.logger import setup_logs +from zoom_python_client.zoom_api_client import ZoomApiClient + +setup_logs(log_level=logging.DEBUG) +zoom_client = ZoomApiClient.init_from_dotenv() +MEETING_ID = os.environ["MEETING_ID"] + + +result = zoom_client.meeting_livestreams.get_livestream(MEETING_ID) +print(result) + +settings = { + "active_speaker_name": False, + "display_name": "CERN_Webcast_Service", + "layout": "follow_host", + "close_caption": "embedded" + } +started = zoom_client.meeting_livestreams.update_livestream_status( + MEETING_ID, + "start", + settings=settings, +) +print(started) \ No newline at end of file From 59ae2ab443f9bb13efc63de21703e243c52e993a Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Mon, 9 Feb 2026 23:57:45 +0100 Subject: [PATCH 02/10] embedded --- .vscode/settings.json | 13 ++++------ .../meeting_livestreams_component.py | 14 +++++++++-- .../webinar_livestreams_component.py | 14 +++++++++-- zoom_python_client/zoom_api_client.py | 25 +++++++++++-------- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f0f682a..df863d7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,10 +24,7 @@ "python.analysis.inlayHints.functionReturnTypes": true, "editor.formatOnSave": true, "isort.check": true, - "isort.args": [ - "--profile", - "black" - ], + "isort.args": ["--profile", "black"], "python.testing.pytestEnabled": true, "python.testing.pytestArgs": [ "tests", @@ -38,7 +35,7 @@ ], "[python]": { "editor.codeActionsOnSave": { - "source.organizeImports": true + "source.organizeImports": "explicit" }, "editor.defaultFormatter": "ms-python.black-formatter", "editor.codeLens": true @@ -50,6 +47,6 @@ "files.exclude": { "**/__pycache__": true, "**/.pytest_cache": true, - "**/.mypy*": true, - }, -} \ No newline at end of file + "**/.mypy*": true + } +} diff --git a/zoom_python_client/client_components/meeting_livestreams/meeting_livestreams_component.py b/zoom_python_client/client_components/meeting_livestreams/meeting_livestreams_component.py index 6262c62..23734ad 100644 --- a/zoom_python_client/client_components/meeting_livestreams/meeting_livestreams_component.py +++ b/zoom_python_client/client_components/meeting_livestreams/meeting_livestreams_component.py @@ -1,5 +1,7 @@ from json import JSONDecodeError -from typing import TypedDict +from typing import Any, Dict, Optional + +from typing_extensions import NotRequired, TypedDict from zoom_python_client.zoom_auth_api.zoom_auth_api_client import ZoomAuthApiClientError from zoom_python_client.zoom_client_interface import ZoomClientInterface @@ -14,6 +16,7 @@ class LiveStreamDict(TypedDict): class LiveStreamStatusDict(TypedDict): action: str + settings: NotRequired[Dict[str, Any]] class MeetingLiveStreamsComponent: @@ -41,9 +44,16 @@ def update_livestream(self, meeting_id: str, data: LiveStreamDict) -> bool: return True return False - def update_livestream_status(self, meeting_id: str, action: str) -> bool: + def update_livestream_status( + self, + meeting_id: str, + action: str, + settings: Optional[Dict[str, Any]] = None, + ) -> bool: api_path = f"/meetings/{meeting_id}/livestream/status" data: LiveStreamStatusDict = {"action": action} + if settings is not None: + data["settings"] = settings response = self.client.make_patch_request(api_path, data) if response and response.status_code == 204: return True diff --git a/zoom_python_client/client_components/webinar_livestreams/webinar_livestreams_component.py b/zoom_python_client/client_components/webinar_livestreams/webinar_livestreams_component.py index 9f5b5c8..8702afc 100644 --- a/zoom_python_client/client_components/webinar_livestreams/webinar_livestreams_component.py +++ b/zoom_python_client/client_components/webinar_livestreams/webinar_livestreams_component.py @@ -1,5 +1,7 @@ from json import JSONDecodeError -from typing import TypedDict +from typing import Any, Dict, Optional + +from typing_extensions import NotRequired, TypedDict from zoom_python_client.zoom_auth_api.zoom_auth_api_client import ZoomAuthApiClientError from zoom_python_client.zoom_client_interface import ZoomClientInterface @@ -14,6 +16,7 @@ class LiveStreamDict(TypedDict): class LiveStreamStatusDict(TypedDict): action: str + settings: NotRequired[Dict[str, Any]] class WebinarLiveStreamsComponent: @@ -38,9 +41,16 @@ def update_livestream(self, meeting_id: str, data: LiveStreamDict) -> bool: return True return False - def update_livestream_status(self, meeting_id: str, action: str) -> bool: + def update_livestream_status( + self, + meeting_id: str, + action: str, + settings: Optional[Dict[str, Any]] = None, + ) -> bool: api_path = f"/webinars/{meeting_id}/livestream/status" data: LiveStreamStatusDict = {"action": action} + if settings is not None: + data["settings"] = settings response = self.client.make_patch_request(api_path, data) if response.status_code == 204: return True diff --git a/zoom_python_client/zoom_api_client.py b/zoom_python_client/zoom_api_client.py index ee937dd..1661ce9 100644 --- a/zoom_python_client/zoom_api_client.py +++ b/zoom_python_client/zoom_api_client.py @@ -143,17 +143,22 @@ def make_get_request( # convert parameters dict to query string query_string = self.build_query_string_from_dict(parameters) response = requests.Response() - try: - response = self.api_client.make_get_request( - api_path + query_string, headers=headers - ) + #try: + response = self.api_client.make_get_request( + api_path + query_string, headers=headers + ) # Handle 401 error from requests - except requests.exceptions.HTTPError as error: - if error.response.status_code == 401: - logger.debug( - f"Got 401 error from Zoom API Get ({error}). Retrying with a new token." - ) - response = self.retry_get_request(api_path, query_string) + #except requests.exceptions.HTTPError as error: + # if error.response.status_code == 401: + # logger.debug( + # f"Got 401 error from Zoom API Get ({error}). Retrying with a new token." + # ) + # response = self.retry_get_request(api_path, query_string) + # else: + # logger.debug( + # msg=f"Go exception {error.response.status_code} - {error.strerror}" + # ) + return response def retry_get_request(self, api_path, query_string): From 0569e9524939a1002e9caff1ed4605dcbb8509c1 Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Tue, 10 Feb 2026 23:34:38 +0100 Subject: [PATCH 03/10] revert exception handling as it was originally --- zoom_python_client/zoom_api_client.py | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/zoom_python_client/zoom_api_client.py b/zoom_python_client/zoom_api_client.py index 1661ce9..ee937dd 100644 --- a/zoom_python_client/zoom_api_client.py +++ b/zoom_python_client/zoom_api_client.py @@ -143,22 +143,17 @@ def make_get_request( # convert parameters dict to query string query_string = self.build_query_string_from_dict(parameters) response = requests.Response() - #try: - response = self.api_client.make_get_request( - api_path + query_string, headers=headers - ) + try: + response = self.api_client.make_get_request( + api_path + query_string, headers=headers + ) # Handle 401 error from requests - #except requests.exceptions.HTTPError as error: - # if error.response.status_code == 401: - # logger.debug( - # f"Got 401 error from Zoom API Get ({error}). Retrying with a new token." - # ) - # response = self.retry_get_request(api_path, query_string) - # else: - # logger.debug( - # msg=f"Go exception {error.response.status_code} - {error.strerror}" - # ) - + except requests.exceptions.HTTPError as error: + if error.response.status_code == 401: + logger.debug( + f"Got 401 error from Zoom API Get ({error}). Retrying with a new token." + ) + response = self.retry_get_request(api_path, query_string) return response def retry_get_request(self, api_path, query_string): From c913cd9efe12a71a83e8d1c6a226ca899ba57f90 Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Wed, 11 Feb 2026 16:30:12 +0100 Subject: [PATCH 04/10] small modifications needed by pre-commit --- example/get_meeting_livestream.py | 1 - example/get_rooms.py | 4 +++- example/start_meeting_livestream.py | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/example/get_meeting_livestream.py b/example/get_meeting_livestream.py index a1ded34..f4e4079 100644 --- a/example/get_meeting_livestream.py +++ b/example/get_meeting_livestream.py @@ -11,4 +11,3 @@ result = zoom_client.meeting_livestreams.get_livestream(MEETING_ID) print(result) - diff --git a/example/get_rooms.py b/example/get_rooms.py index e9192b6..725a2c4 100644 --- a/example/get_rooms.py +++ b/example/get_rooms.py @@ -9,7 +9,9 @@ logger = setup_logs(log_level=logging.DEBUG) -zoom_client = ZoomApiClient.init_from_dotenv(use_path="/Users/rgaspar/Documents/gitprojects/zoom-python-client") +zoom_client = ZoomApiClient.init_from_dotenv( + use_path="/Users/rgaspar/Documents/gitprojects/zoom-python-client" +) parameters = RoomsListDict( type=RoomType.ZOOM_ROOM, diff --git a/example/start_meeting_livestream.py b/example/start_meeting_livestream.py index 9e93f3d..a91c8e3 100644 --- a/example/start_meeting_livestream.py +++ b/example/start_meeting_livestream.py @@ -12,15 +12,15 @@ result = zoom_client.meeting_livestreams.get_livestream(MEETING_ID) print(result) -settings = { +settings = { "active_speaker_name": False, "display_name": "CERN_Webcast_Service", "layout": "follow_host", - "close_caption": "embedded" - } + "close_caption": "embedded", +} started = zoom_client.meeting_livestreams.update_livestream_status( MEETING_ID, "start", settings=settings, ) -print(started) \ No newline at end of file +print(started) From f7c90fdec4b02ab627f9fd3faaa3a7c91b36ce20 Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Wed, 11 Feb 2026 16:45:27 +0100 Subject: [PATCH 05/10] changes on files not related to the streaming change request, to make all compliant with latest versions of pre-commit --- .pre-commit-config.yaml | 8 ++++---- zoom_python_client/utils/typed_dict_parameters.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c9ed6d7..a3d4b20 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,20 +1,20 @@ repos: - repo: https://github.com/psf/black - rev: 23.3.0 + rev: 26.1.0 hooks: - id: black - repo: https://github.com/pycqa/isort - rev: 5.12.0 + rev: 7.0.0 hooks: - id: isort name: isort args: [--profile, black, --skip, migrations] - repo: https://github.com/pycqa/flake8 - rev: "6.0.0" # pick a git hash / tag to point to + rev: "7.3.0" hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy - rev: "v1.2.0" + rev: "v1.19.1" hooks: - id: mypy args: [--no-strict-optional, --ignore-missing-imports] diff --git a/zoom_python_client/utils/typed_dict_parameters.py b/zoom_python_client/utils/typed_dict_parameters.py index b958304..889762c 100644 --- a/zoom_python_client/utils/typed_dict_parameters.py +++ b/zoom_python_client/utils/typed_dict_parameters.py @@ -6,7 +6,7 @@ class DataType(TypedDict, total=False): - ... + pass def generate_parameters_dict(data: DataType) -> dict: From 5d6baeb2a846c7782f0c08f87240fc419a3a5366 Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Wed, 11 Feb 2026 17:00:49 +0100 Subject: [PATCH 06/10] changes on files not related to the streaming change request, to make all compliant with latest versions of pre-commit --- .pre-commit-config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a3d4b20..2295192 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,6 +13,7 @@ repos: rev: "7.3.0" hooks: - id: flake8 + additional_dependencies: ["pyflakes>=3.2.0"] - repo: https://github.com/pre-commit/mirrors-mypy rev: "v1.19.1" hooks: From 63f6e8b1b615ffc1d8cae8b16d23ef53526981f9 Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Wed, 11 Feb 2026 17:07:23 +0100 Subject: [PATCH 07/10] changes on files not related to the streaming change request, to make all compliant with latest versions of pre-commit --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4deb882..49c3108 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ python-dotenv==1.0.0 requests==2.31.0 -typing_extensions==4.7.1 \ No newline at end of file +typing_extensions==4.7.1 +typed-ast==1.5.5 \ No newline at end of file From 58cb968edb3fa3587d26d342130b9ce9863aae8d Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Mon, 16 Feb 2026 18:14:01 +0100 Subject: [PATCH 08/10] test case for livestream status update + doc --- README.md | 2 +- .../test_meeting_livestreams_component.py | 17 ++++++++++++++++- .../test_webinar_livestreams_component.py | 17 ++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2e452b2..c7da040 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ setup_logs(log_level=logging.DEBUG) 1. get webinar live stream 2. update webinar live stream -3. update webinar livestream status +3. update webinar livestream status - Following [Zoom documentation](https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meetingLiveStreamStatusUpdate). ### **zoom rooms**: diff --git a/tests/zoom_python_client/client_components/meeting_livestreams/test_meeting_livestreams_component.py b/tests/zoom_python_client/client_components/meeting_livestreams/test_meeting_livestreams_component.py index f724f21..0e47bea 100644 --- a/tests/zoom_python_client/client_components/meeting_livestreams/test_meeting_livestreams_component.py +++ b/tests/zoom_python_client/client_components/meeting_livestreams/test_meeting_livestreams_component.py @@ -81,14 +81,29 @@ def test_update_meeting_livestreams_component_no_response(self): @responses.activate def test_update_meeting_livestreams_status_component(self): + settings = { + "active_speaker_name": False, + "display_name": "CERN_Webcast_Service", + "layout": "follow_host", + "close_caption": "embedded", + } responses.add( responses.PATCH, "http://localhost/meetings/12345/livestream/status", status=204, + match=[ + responses.matchers.json_params_matcher( + {"action": "start", "settings": settings} + ) + ], ) zoom_client = ZoomApiClient("aaa", "bbb", "ccc", "http://localhost") component = MeetingLiveStreamsComponent(zoom_client) - result = component.update_livestream_status("12345", "start") + result = component.update_livestream_status( + "12345", + "start", + settings=settings, + ) assert result @responses.activate diff --git a/tests/zoom_python_client/client_components/webinar_livestreams/test_webinar_livestreams_component.py b/tests/zoom_python_client/client_components/webinar_livestreams/test_webinar_livestreams_component.py index 2167310..d76acc3 100644 --- a/tests/zoom_python_client/client_components/webinar_livestreams/test_webinar_livestreams_component.py +++ b/tests/zoom_python_client/client_components/webinar_livestreams/test_webinar_livestreams_component.py @@ -81,14 +81,29 @@ def test_update_webinar_livestreams_component_no_response(self): @responses.activate def test_update_webinar_livestreams_status_component(self): + settings = { + "active_speaker_name": False, + "display_name": "CERN_Webcast_Service", + "layout": "follow_host", + "close_caption": "embedded", + } responses.add( responses.PATCH, "http://localhost/webinars/12345/livestream/status", status=204, + match=[ + responses.matchers.json_params_matcher( + {"action": "start", "settings": settings} + ) + ], ) zoom_client = ZoomApiClient("aaa", "bbb", "ccc", "http://localhost") component = WebinarLiveStreamsComponent(zoom_client) - result = component.update_livestream_status("12345", "start") + result = component.update_livestream_status( + "12345", + "start", + settings=settings, + ) assert result @responses.activate From 15cfe092a86596e67e995f16045f7df742f03099 Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Mon, 16 Feb 2026 18:28:06 +0100 Subject: [PATCH 09/10] remove local path --- example/get_rooms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/get_rooms.py b/example/get_rooms.py index 725a2c4..298ac2e 100644 --- a/example/get_rooms.py +++ b/example/get_rooms.py @@ -10,7 +10,7 @@ logger = setup_logs(log_level=logging.DEBUG) zoom_client = ZoomApiClient.init_from_dotenv( - use_path="/Users/rgaspar/Documents/gitprojects/zoom-python-client" + use_path="." ) parameters = RoomsListDict( From 98c9736b3fd701daf58313a83bc6cd3a085774f9 Mon Sep 17 00:00:00 2001 From: Ruben Domingo Gaspar Aparicio Date: Tue, 17 Feb 2026 11:47:06 +0100 Subject: [PATCH 10/10] getRooms missing commit --- example/get_rooms.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/example/get_rooms.py b/example/get_rooms.py index 298ac2e..adbe573 100644 --- a/example/get_rooms.py +++ b/example/get_rooms.py @@ -9,9 +9,7 @@ logger = setup_logs(log_level=logging.DEBUG) -zoom_client = ZoomApiClient.init_from_dotenv( - use_path="." -) +zoom_client = ZoomApiClient.init_from_dotenv(use_path=".") parameters = RoomsListDict( type=RoomType.ZOOM_ROOM,