diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 019d65b..5cc045b 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 3.8.1 +current_version = 3.9.0 commit = True tag = False diff --git a/CHANGES.md b/CHANGES.md index 5c25929..329a8c0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,6 @@ +# Release v3.9.0 +- Add `publisher_only` role that can be specified when generating a token. + # Release v3.8.1 - Fixed an issue with the `opentok.create_session` method diff --git a/opentok/opentok.py b/opentok/opentok.py index 47e6d2f..897ac69 100644 --- a/opentok/opentok.py +++ b/opentok/opentok.py @@ -64,6 +64,9 @@ class Roles(Enum): """A subscriber can only subscribe to streams.""" publisher = u("publisher") """A publisher can publish streams, subscribe to streams, and signal""" + publisher_only = "publisheronly" + """A client with the `publisher_only` role can only publish streams. It cannot subscribe to + other clients' streams or send signals.""" moderator = u("moderator") """In addition to the privileges granted to a publisher, a moderator can perform moderation functions, such as forcing clients to disconnect, to stop publishing streams, @@ -106,7 +109,6 @@ class ArchiveModes(Enum): class Client(object): - """Use this SDK to create tokens and interface with the server-side portion of the Opentok API. """ @@ -187,6 +189,9 @@ def generate_token( * `Roles.publisher` -- A publisher can publish streams, subscribe to streams, and signal. (This is the default value if you do not specify a role.) + * `Roles.publisher_only` -- A client with the `publisher_only` role can only publish streams. + It cannot subscribe to other clients' streams or send signals. + * `Roles.moderator` -- In addition to the privileges granted to a publisher, in clients using the OpenTok.js 2.2 library, a moderator can call the `forceUnpublish()` and `forceDisconnect()` method of the @@ -499,9 +504,7 @@ def create_session( ) ) - session_id = ( - dom.getElementsByTagName("session_id")[0].childNodes[0].nodeValue - ) + session_id = dom.getElementsByTagName("session_id")[0].childNodes[0].nodeValue return Session( self, session_id, @@ -890,9 +893,7 @@ def add_archive_stream( else: raise RequestError("An unexpected error occurred.", response.status_code) - def remove_archive_stream( - self, archive_id: str, stream_id: str - ) -> requests.Response: + def remove_archive_stream(self, archive_id: str, stream_id: str) -> requests.Response: """ This method will remove streams from the archive with removeStream. @@ -1339,9 +1340,7 @@ class names (Strings) to apply to the stream. For example: else: raise RequestError("OpenTok server error.", response.status_code) - def start_broadcast( - self, session_id, options, stream_mode=BroadcastStreamModes.auto - ): + def start_broadcast(self, session_id, options, stream_mode=BroadcastStreamModes.auto): """ Use this method to start a live streaming broadcast for an OpenTok session. This broadcasts the session to an HLS (HTTP live streaming) or to RTMP streams. To successfully start @@ -1576,9 +1575,7 @@ def add_broadcast_stream( "Your broadcast is configured with a streamMode that does not support stream manipulation." ) elif response.status_code == 409: - raise BroadcastError( - "The broadcast has already started for the session." - ) + raise BroadcastError("The broadcast has already started for the session.") else: raise RequestError("An unexpected error occurred.", response.status_code) @@ -1621,9 +1618,7 @@ def remove_broadcast_stream( "Your broadcast is configured with a streamMode that does not support stream manipulation." ) elif response.status_code == 409: - raise BroadcastError( - "The broadcast has already started for the session." - ) + raise BroadcastError("The broadcast has already started for the session.") else: raise RequestError("OpenTok server error.", response.status_code) diff --git a/opentok/version.py b/opentok/version.py index d7871bc..41f2d81 100644 --- a/opentok/version.py +++ b/opentok/version.py @@ -1,3 +1,3 @@ # see: http://legacy.python.org/dev/peps/pep-0440/#public-version-identifiers -__version__ = "3.8.1" +__version__ = "3.9.0" diff --git a/tests/test_token_generation.py b/tests/test_token_generation.py index bcc726e..6434daf 100644 --- a/tests/test_token_generation.py +++ b/tests/test_token_generation.py @@ -31,11 +31,16 @@ def test_generate_role_token(self): assert isinstance(token, text_type) assert token_decoder(token)[u("role")] == Roles.moderator.value assert token_signature_validator(token, self.api_secret) + token = self.opentok.generate_token(self.session_id, role=Roles.moderator) assert isinstance(token, text_type) assert token_decoder(token)[u("role")] == Roles.moderator.value assert token_signature_validator(token, self.api_secret) + token = self.opentok.generate_token(self.session_id, Roles.publisher_only) + assert token_decoder(token)["role"] == Roles.publisher_only.value + assert token_signature_validator(token, self.api_secret) + def test_generate_expires_token(self): # an integer is a valid argument expire_time = int(time.time()) + 100 @@ -91,15 +96,15 @@ def test_generate_no_data_token(self): @raises(TypeError) def test_does_not_generate_token_without_params(self): - token = self.opentok.generate_token() + self.opentok.generate_token() @raises(TypeError) def test_does_not_generate_token_without_session(self): - token = self.opentok.generate_token(role=Roles.subscriber) + self.opentok.generate_token(role=Roles.subscriber) @raises(OpenTokException) def test_does_not_generate_token_invalid_session(self): - token = self.opentok.generate_token(u("NOT A REAL SESSIONID")) + self.opentok.generate_token(u("NOT A REAL SESSIONID")) @raises(OpenTokException) def test_does_not_generate_token_without_api_key_match(self): @@ -107,6 +112,4 @@ def test_does_not_generate_token_without_api_key_match(self): session_id = u( "1_MX42NTQzMjF-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4" ) - token = self.opentok.generate_token(session_id) - - # TODO: all the things that raise OpenTokException + self.opentok.generate_token(session_id)