diff --git a/.pubnub.yml b/.pubnub.yml index 4359ab00..e8fba1d1 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,5 +1,5 @@ name: python -version: 9.0.0 +version: 9.1.0 schema: 1 scm: github.com/pubnub/python sdks: @@ -18,7 +18,7 @@ sdks: distributions: - distribution-type: library distribution-repository: package - package-name: pubnub-9.0.0 + package-name: pubnub-9.1.0 location: https://pypi.org/project/pubnub/ supported-platforms: supported-operating-systems: @@ -97,8 +97,8 @@ sdks: - distribution-type: library distribution-repository: git release - package-name: pubnub-9.0.0 - location: https://github.com/pubnub/python/releases/download/v9.0.0/pubnub-9.0.0.tar.gz + package-name: pubnub-9.1.0 + location: https://github.com/pubnub/python/releases/download/v9.1.0/pubnub-9.1.0.tar.gz supported-platforms: supported-operating-systems: Linux: @@ -169,6 +169,11 @@ sdks: license-url: https://github.com/aio-libs/aiohttp/blob/master/LICENSE.txt is-required: Required changelog: + - date: 2024-11-19 + version: v9.1.0 + changes: + - type: feature + text: "Add custom message type support for the following APIs: Publish, signal, share file, subscribe and history." - date: 2024-10-02 version: v9.0.0 changes: diff --git a/CHANGELOG.md b/CHANGELOG.md index 47a93256..edf3f722 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v9.1.0 +November 19 2024 + +#### Added +- Add custom message type support for the following APIs: Publish, signal, share file, subscribe and history. + ## v9.0.0 October 02 2024 diff --git a/pubnub/endpoints/fetch_messages.py b/pubnub/endpoints/fetch_messages.py index 999fc0ba..d0c3765d 100644 --- a/pubnub/endpoints/fetch_messages.py +++ b/pubnub/endpoints/fetch_messages.py @@ -33,7 +33,8 @@ class FetchMessages(Endpoint): def __init__(self, pubnub, channels: Union[str, List[str]] = None, start: int = None, end: int = None, count: int = None, include_meta: bool = None, include_message_actions: bool = None, - include_message_type: bool = None, include_uuid: bool = None, decrypt_messages: bool = False): + include_message_type: bool = None, include_uuid: bool = None, decrypt_messages: bool = False, + include_custom_message_type: bool = None): Endpoint.__init__(self, pubnub) self._channels = [] if channels: @@ -46,6 +47,7 @@ def __init__(self, pubnub, channels: Union[str, List[str]] = None, start: int = self._include_message_type = include_message_type self._include_uuid = include_uuid self._decrypt_messages = decrypt_messages + self._include_custom_message_type = include_custom_message_type def channels(self, channels: Union[str, List[str]]) -> 'FetchMessages': utils.extend_list(self._channels, channels) @@ -84,6 +86,11 @@ def include_message_type(self, include_message_type: bool) -> 'FetchMessages': self._include_message_type = include_message_type return self + def include_custom_message_type(self, include_custom_message_type: bool) -> 'FetchMessages': + assert isinstance(include_custom_message_type, bool) + self._include_custom_message_type = include_custom_message_type + return self + def include_uuid(self, include_uuid: bool) -> 'FetchMessages': assert isinstance(include_uuid, bool) self._include_uuid = include_uuid @@ -108,6 +115,9 @@ def custom_params(self): if self._include_message_type is not None: params['include_message_type'] = "true" if self._include_message_type else "false" + if self._include_custom_message_type is not None: + params['include_custom_message_type'] = "true" if self._include_custom_message_type else "false" + if self.include_message_actions and self._include_uuid is not None: params['include_uuid'] = "true" if self._include_uuid else "false" diff --git a/pubnub/endpoints/file_operations/publish_file_message.py b/pubnub/endpoints/file_operations/publish_file_message.py index cc3d2904..8a1f62e8 100644 --- a/pubnub/endpoints/file_operations/publish_file_message.py +++ b/pubnub/endpoints/file_operations/publish_file_message.py @@ -22,6 +22,7 @@ def __init__(self, pubnub): self._cipher_key = None self._replicate = None self._ptto = None + self._custom_message_type = None def meta(self, meta): self._meta = meta @@ -53,6 +54,10 @@ def file_name(self, file_name): self._file_name = file_name return self + def custom_message_type(self, custom_message_type: str) -> 'PublishFileMessage': + self._custom_message_type = custom_message_type + return self + def _encrypt_message(self, message): if self._cipher_key: return PubNubCryptodome(self._pubnub.config).encrypt(self._cipher_key, utils.write_value_as_string(message)) @@ -90,6 +95,10 @@ def custom_params(self): "ttl": self._ttl, "store": 1 if self._should_store else 0 }) + + if self._custom_message_type: + params['custom_message_type'] = utils.url_encode(self._custom_message_type) + return params def is_auth_required(self): diff --git a/pubnub/endpoints/file_operations/send_file.py b/pubnub/endpoints/file_operations/send_file.py index 52cd8f9a..c6107c0b 100644 --- a/pubnub/endpoints/file_operations/send_file.py +++ b/pubnub/endpoints/file_operations/send_file.py @@ -24,11 +24,16 @@ def __init__(self, pubnub): self._file_object = None self._replicate = None self._ptto = None + self._custom_message_type = None def file_object(self, fd): self._file_object = fd return self + def custom_message_type(self, custom_message_type: str): + self._custom_message_type = custom_message_type + return self + def build_params_callback(self): return lambda a: {} @@ -124,23 +129,24 @@ def name(self): return "Send file to S3" def sync(self): - self._file_upload_envelope = FetchFileUploadS3Data(self._pubnub).\ - channel(self._channel).\ - file_name(self._file_name).sync() + self._file_upload_envelope = FetchFileUploadS3Data(self._pubnub) \ + .channel(self._channel) \ + .file_name(self._file_name).sync() response_envelope = super(SendFileNative, self).sync() - publish_file_response = PublishFileMessage(self._pubnub).\ - channel(self._channel).\ - meta(self._meta).\ - message(self._message).\ - file_id(response_envelope.result.file_id).\ - file_name(response_envelope.result.name).\ - should_store(self._should_store).\ - ttl(self._ttl).\ - replicate(self._replicate).\ - ptto(self._ptto).\ - cipher_key(self._cipher_key).sync() + publish_file_response = PublishFileMessage(self._pubnub) \ + .channel(self._channel) \ + .meta(self._meta) \ + .message(self._message) \ + .file_id(response_envelope.result.file_id) \ + .file_name(response_envelope.result.name) \ + .should_store(self._should_store) \ + .ttl(self._ttl) \ + .replicate(self._replicate) \ + .ptto(self._ptto) \ + .custom_message_type(self._custom_message_type) \ + .cipher_key(self._cipher_key).sync() response_envelope.result.timestamp = publish_file_response.result.timestamp return response_envelope diff --git a/pubnub/endpoints/pubsub/publish.py b/pubnub/endpoints/pubsub/publish.py index 309eebc7..b78c66cc 100644 --- a/pubnub/endpoints/pubsub/publish.py +++ b/pubnub/endpoints/pubsub/publish.py @@ -29,9 +29,9 @@ class Publish(Endpoint, TimeTokenOverrideMixin): _ptto: Optional[int] _ttl: Optional[int] - def __init__(self, pubnub, channel: str = None, message: any = None, - should_store: Optional[bool] = None, use_post: Optional[bool] = None, meta: Optional[any] = None, - replicate: Optional[bool] = None, ptto: Optional[int] = None, ttl: Optional[int] = None): + def __init__(self, pubnub, channel: str = None, message: any = None, should_store: Optional[bool] = None, + use_post: Optional[bool] = None, meta: Optional[any] = None, replicate: Optional[bool] = None, + ptto: Optional[int] = None, ttl: Optional[int] = None, custom_message_type: Optional[str] = None): super(Publish, self).__init__(pubnub) self._channel = channel @@ -39,6 +39,7 @@ def __init__(self, pubnub, channel: str = None, message: any = None, self._should_store = should_store self._use_post = use_post self._meta = meta + self._custom_message_type = custom_message_type self._replicate = replicate self._ptto = ptto self._ttl = ttl @@ -70,6 +71,10 @@ def meta(self, meta: any) -> 'Publish': self._meta = meta return self + def custom_message_type(self, custom_message_type: str) -> 'Publish': + self._custom_message_type = custom_message_type + return self + def ttl(self, ttl: int) -> 'Publish': self._ttl = ttl return self @@ -105,6 +110,9 @@ def custom_params(self): if self._meta: params['meta'] = utils.write_value_as_string(self._meta) + if self._custom_message_type: + params['custom_message_type'] = utils.url_encode(self._custom_message_type) + if self._should_store is not None: if self._should_store: params["store"] = "1" diff --git a/pubnub/endpoints/signal.py b/pubnub/endpoints/signal.py index 5da675f2..3f0167c0 100644 --- a/pubnub/endpoints/signal.py +++ b/pubnub/endpoints/signal.py @@ -1,3 +1,4 @@ +from typing import Optional from pubnub import utils from pubnub.endpoints.endpoint import Endpoint from pubnub.enums import HttpMethod, PNOperationType @@ -17,10 +18,11 @@ class Signal(Endpoint): _channel: str _message: any - def __init__(self, pubnub, channel: str = None, message: any = None): + def __init__(self, pubnub, channel: str = None, message: any = None, custom_message_type: Optional[str] = None): Endpoint.__init__(self, pubnub) self._channel = channel self._message = message + self._custom_message_type = custom_message_type def channel(self, channel) -> 'Signal': self._channel = str(channel) @@ -30,6 +32,10 @@ def message(self, message) -> 'Signal': self._message = message return self + def custom_message_type(self, custom_message_type: str) -> 'Signal': + self._custom_message_type = custom_message_type + return self + def build_path(self): stringified_message = utils.write_value_as_string(self._message) msg = utils.url_encode(stringified_message) @@ -39,7 +45,11 @@ def build_path(self): ) def custom_params(self): - return {} + params = {} + if self._custom_message_type: + params['custom_message_type'] = utils.url_encode(self._custom_message_type) + + return params def http_method(self): return HttpMethod.GET diff --git a/pubnub/models/consumer/pubsub.py b/pubnub/models/consumer/pubsub.py index 047010b5..5564ee11 100644 --- a/pubnub/models/consumer/pubsub.py +++ b/pubnub/models/consumer/pubsub.py @@ -2,7 +2,8 @@ class PNMessageResult(object): - def __init__(self, message, subscription, channel, timetoken, user_metadata=None, publisher=None, error=None): + def __init__(self, message, subscription, channel, timetoken, user_metadata=None, publisher=None, + error=None, custom_message_type=None): if subscription is not None: assert isinstance(subscription, str) @@ -30,6 +31,7 @@ def __init__(self, message, subscription, channel, timetoken, user_metadata=None self.user_metadata = user_metadata self.publisher = publisher self.error = error + self.custom_message_type = custom_message_type class PNSignalMessageResult(PNMessageResult): diff --git a/pubnub/models/server/subscribe.py b/pubnub/models/server/subscribe.py index 87793a83..7bf1d194 100644 --- a/pubnub/models/server/subscribe.py +++ b/pubnub/models/server/subscribe.py @@ -30,6 +30,7 @@ def __init__(self): self.publish_metadata = None self.only_channel_subscription = False self.type = 0 + self.custom_message_type = None @classmethod def from_json(cls, json_input): @@ -49,6 +50,8 @@ def from_json(cls, json_input): message.publish_metadata = PublishMetadata.from_json(json_input['p']) if 'e' in json_input: message.type = json_input['e'] + if 'cmt' in json_input: + message.custom_message_type = json_input['cmt'] return message diff --git a/pubnub/pubnub_core.py b/pubnub/pubnub_core.py index 1e924f1a..f630acd1 100644 --- a/pubnub/pubnub_core.py +++ b/pubnub/pubnub_core.py @@ -94,7 +94,7 @@ class PubNubCore: """A base class for PubNub Python API implementations""" - SDK_VERSION = "9.0.0" + SDK_VERSION = "9.1.0" SDK_NAME = "PubNub-Python" TIMESTAMP_DIVIDER = 1000 @@ -215,12 +215,13 @@ def where_now(self, user_id: Optional[str] = None): def publish(self, channel: str = None, message: any = None, should_store: Optional[bool] = None, use_post: Optional[bool] = None, meta: Optional[any] = None, replicate: Optional[bool] = None, - ptto: Optional[int] = None, ttl: Optional[int] = None) -> Publish: + ptto: Optional[int] = None, ttl: Optional[int] = None, custom_message_type: Optional[str] = None + ) -> Publish: """ Sends a message to all channel subscribers. A successfully published message is replicated across PubNub's points of presence and sent simultaneously to all subscribed clients on a channel. """ return Publish(self, channel=channel, message=message, should_store=should_store, use_post=use_post, meta=meta, - replicate=replicate, ptto=ptto, ttl=ttl) + replicate=replicate, ptto=ptto, ttl=ttl, custom_message_type=custom_message_type) def grant(self): """ Deprecated. Use grant_token instead """ @@ -274,8 +275,8 @@ def fire(self, channel: str = None, message: any = None, use_post: Optional[bool meta: Optional[any] = None) -> Fire: return Fire(self, channel=channel, message=message, use_post=use_post, meta=meta) - def signal(self, channel: str = None, message: any = None) -> Signal: - return Signal(self, channel=channel, message=message) + def signal(self, channel: str = None, message: any = None, custom_message_type: Optional[str] = None) -> Signal: + return Signal(self, channel=channel, message=message, custom_message_type=custom_message_type) def set_uuid_metadata(self, uuid: str = None, include_custom: bool = None, custom: dict = None, include_status: bool = True, include_type: bool = True, status: str = None, type: str = None, diff --git a/setup.py b/setup.py index 7ec306e5..decc04cd 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='pubnub', - version='9.0.0', + version='9.1.0', description='PubNub Real-time push service in the cloud', author='PubNub', author_email='support@pubnub.com', diff --git a/tests/integrational/native_sync/test_file_upload.py b/tests/integrational/native_sync/test_file_upload.py index cb059a56..aba1484c 100644 --- a/tests/integrational/native_sync/test_file_upload.py +++ b/tests/integrational/native_sync/test_file_upload.py @@ -1,3 +1,4 @@ +from urllib.parse import parse_qs, urlparse import pytest from Cryptodome.Cipher import AES @@ -5,7 +6,7 @@ from pubnub.exceptions import PubNubException from pubnub.pubnub import PubNub from tests.integrational.vcr_helper import pn_vcr, pn_vcr_with_empty_body_request -from tests.helper import pnconf_file_copy, pnconf_enc_env_copy +from tests.helper import pnconf_file_copy, pnconf_enc_env_copy, pnconf_env_copy from pubnub.endpoints.file_operations.publish_file_message import PublishFileMessage from pubnub.models.consumer.file import ( PNSendFileResult, PNGetFilesResult, PNDownloadFileResult, @@ -27,14 +28,14 @@ def send_file(file_for_upload, cipher_key=None, pass_binary=False, timetoken_ove if pass_binary: fd = fd.read() - send_file_endpoint = pubnub_instance.send_file().\ - channel(CHANNEL).\ - file_name(file_for_upload.basename).\ - message({"test_message": "test"}).\ - should_store(True).\ - ttl(222).\ - file_object(fd).\ - cipher_key(cipher_key) + send_file_endpoint = pubnub_instance.send_file() \ + .channel(CHANNEL) \ + .file_name(file_for_upload.basename) \ + .message({"test_message": "test"}) \ + .should_store(True) \ + .ttl(222) \ + .file_object(fd) \ + .cipher_key(cipher_key) if timetoken_override: send_file_endpoint = send_file_endpoint.ptto(timetoken_override) @@ -67,10 +68,10 @@ def test_list_files(file_upload_test_data): def test_send_and_download_file_using_bytes_object(file_for_upload, file_upload_test_data): envelope = send_file(file_for_upload, pass_binary=True) - download_envelope = pubnub.download_file().\ - channel(CHANNEL).\ - file_id(envelope.result.file_id).\ - file_name(envelope.result.name).sync() + download_envelope = pubnub.download_file() \ + .channel(CHANNEL) \ + .file_id(envelope.result.file_id) \ + .file_name(envelope.result.name).sync() assert isinstance(download_envelope.result, PNDownloadFileResult) data = download_envelope.result.data @@ -86,11 +87,11 @@ def test_send_and_download_encrypted_file(file_for_upload, file_upload_test_data with patch("pubnub.crypto.PubNubCryptodome.get_initialization_vector", return_value="knightsofni12345"): envelope = send_file(file_for_upload, cipher_key=cipher_key) - download_envelope = pubnub.download_file().\ - channel(CHANNEL).\ - file_id(envelope.result.file_id).\ - file_name(envelope.result.name).\ - cipher_key(cipher_key).sync() + download_envelope = pubnub.download_file() \ + .channel(CHANNEL) \ + .file_id(envelope.result.file_id) \ + .file_name(envelope.result.name) \ + .cipher_key(cipher_key).sync() assert isinstance(download_envelope.result, PNDownloadFileResult) data = download_envelope.result.data @@ -115,10 +116,10 @@ def test_file_exceeded_maximum_size(file_for_upload_10mb_size): def test_delete_file(file_for_upload): envelope = send_file(file_for_upload) - delete_envelope = pubnub.delete_file().\ - channel(CHANNEL).\ - file_id(envelope.result.file_id).\ - file_name(envelope.result.name).sync() + delete_envelope = pubnub.delete_file() \ + .channel(CHANNEL) \ + .file_id(envelope.result.file_id) \ + .file_name(envelope.result.name).sync() assert isinstance(delete_envelope.result, PNDeleteFileResult) @@ -130,10 +131,10 @@ def test_delete_file(file_for_upload): def test_get_file_url(file_for_upload): envelope = send_file(file_for_upload) - file_url_envelope = pubnub.get_file_url().\ - channel(CHANNEL).\ - file_id(envelope.result.file_id).\ - file_name(envelope.result.name).sync() + file_url_envelope = pubnub.get_file_url() \ + .channel(CHANNEL) \ + .file_id(envelope.result.file_id) \ + .file_name(envelope.result.name).sync() assert isinstance(file_url_envelope.result, PNGetFileDownloadURLResult) @@ -147,10 +148,10 @@ def test_get_file_url_has_auth_key_in_url_and_signature(file_upload_test_data): pubnub.config.uuid = "files_native_sync_uuid" pubnub.config.auth_key = "test_auth_key" - file_url_envelope = pubnub.get_file_url().\ - channel(CHANNEL).\ - file_id("random_file_id").\ - file_name("random_file_name").sync() + file_url_envelope = pubnub.get_file_url() \ + .channel(CHANNEL) \ + .file_id("random_file_id") \ + .file_name("random_file_name").sync() assert "auth=test_auth_key" in file_url_envelope.status.client_request.url @@ -160,9 +161,9 @@ def test_get_file_url_has_auth_key_in_url_and_signature(file_upload_test_data): filter_query_parameters=('pnsdk',) ) def test_fetch_file_upload_s3_data(file_upload_test_data): - envelope = pubnub._fetch_file_upload_s3_data().\ - channel(CHANNEL).\ - file_name(file_upload_test_data["UPLOADED_FILENAME"]).sync() + envelope = pubnub._fetch_file_upload_s3_data() \ + .channel(CHANNEL) \ + .file_name(file_upload_test_data["UPLOADED_FILENAME"]).sync() assert isinstance(envelope.result, PNFetchFileUploadS3DataResult) @@ -172,14 +173,14 @@ def test_fetch_file_upload_s3_data(file_upload_test_data): filter_query_parameters=('pnsdk',) ) def test_publish_file_message(): - envelope = PublishFileMessage(pubnub).\ - channel(CHANNEL).\ - meta({}).\ - message({"test": "test"}).\ - file_id("2222").\ - file_name("test").\ - should_store(True).\ - ttl(222).sync() + envelope = PublishFileMessage(pubnub) \ + .channel(CHANNEL) \ + .meta({}) \ + .message({"test": "test"}) \ + .file_id("2222") \ + .file_name("test") \ + .should_store(True) \ + .ttl(222).sync() assert isinstance(envelope.result, PNPublishFileMessageResult) @@ -189,14 +190,14 @@ def test_publish_file_message(): filter_query_parameters=('pnsdk',) ) def test_publish_file_message_with_encryption(): - envelope = PublishFileMessage(pubnub).\ - channel(CHANNEL).\ - meta({}).\ - message({"test": "test"}).\ - file_id("2222").\ - file_name("test").\ - should_store(True).\ - ttl(222).sync() + envelope = PublishFileMessage(pubnub) \ + .channel(CHANNEL) \ + .meta({}) \ + .message({"test": "test"}) \ + .file_id("2222") \ + .file_name("test") \ + .should_store(True) \ + .ttl(222).sync() assert isinstance(envelope.result, PNPublishFileMessageResult) @@ -207,16 +208,16 @@ def test_publish_file_message_with_encryption(): ) def test_publish_file_message_with_overriding_time_token(): timetoken_to_override = 16057799474000000 - envelope = PublishFileMessage(pubnub).\ - channel(CHANNEL).\ - meta({}).\ - message({"test": "test"}).\ - file_id("2222").\ - file_name("test").\ - should_store(True).\ - replicate(True).\ - ptto(timetoken_to_override).\ - ttl(222).sync() + envelope = PublishFileMessage(pubnub) \ + .channel(CHANNEL) \ + .meta({}) \ + .message({"test": "test"}) \ + .file_id("2222") \ + .file_name("test") \ + .should_store(True) \ + .replicate(True) \ + .ptto(timetoken_to_override) \ + .ttl(222).sync() assert isinstance(envelope.result, PNPublishFileMessageResult) assert "ptto" in envelope.status.client_request.url @@ -244,11 +245,11 @@ def test_send_and_download_gcm_encrypted_file(file_for_upload, file_upload_test_ with patch("pubnub.crypto.PubNubCryptodome.get_initialization_vector", return_value="knightsofni12345"): envelope = send_file(file_for_upload, cipher_key=cipher_key, pubnub_instance=pubnub) - download_envelope = pubnub.download_file().\ - channel(CHANNEL).\ - file_id(envelope.result.file_id).\ - file_name(envelope.result.name).\ - cipher_key(cipher_key).sync() + download_envelope = pubnub.download_file() \ + .channel(CHANNEL) \ + .file_id(envelope.result.file_id) \ + .file_name(envelope.result.name) \ + .cipher_key(cipher_key).sync() assert isinstance(download_envelope.result, PNDownloadFileResult) data = download_envelope.result.data @@ -271,12 +272,35 @@ def test_send_and_download_encrypted_file_fallback_decode(file_for_upload, file_ with patch("pubnub.crypto.PubNubCryptodome.get_initialization_vector", return_value="knightsofni12345"): envelope = send_file(file_for_upload, cipher_key=cipher_key, pubnub_instance=pn_cbc) - download_envelope = pn_gcm.download_file().\ - channel(CHANNEL).\ - file_id(envelope.result.file_id).\ - file_name(envelope.result.name).\ - cipher_key(cipher_key).sync() + download_envelope = pn_gcm.download_file() \ + .channel(CHANNEL) \ + .file_id(envelope.result.file_id) \ + .file_name(envelope.result.name) \ + .cipher_key(cipher_key).sync() assert isinstance(download_envelope.result, PNDownloadFileResult) data = download_envelope.result.data assert data == bytes(file_upload_test_data["FILE_CONTENT"], "utf-8") + + +def test_publish_file_with_custom_type(): + with pn_vcr.use_cassette( + "tests/integrational/fixtures/native_sync/file_upload/test_publish_file_with_custom_type.json", + filter_query_parameters=('pnsdk',), serializer='pn_json') as cassette: + + pubnub = PubNub(pnconf_env_copy()) + envelope = pubnub.publish_file_message() \ + .channel(CHANNEL) \ + .message({"test": "test"}) \ + .meta({}) \ + .message({"test": "test"}) \ + .file_id("2222") \ + .file_name("test") \ + .custom_message_type("test_message").sync() + + assert isinstance(envelope.result, PNPublishFileMessageResult) + assert len(cassette) == 1 + uri = urlparse(cassette.requests[0].uri) + query = parse_qs(uri.query) + assert 'custom_message_type' in query.keys() + assert query['custom_message_type'] == ['test_message'] diff --git a/tests/integrational/native_sync/test_publish.py b/tests/integrational/native_sync/test_publish.py index 935ee02a..ea85353d 100644 --- a/tests/integrational/native_sync/test_publish.py +++ b/tests/integrational/native_sync/test_publish.py @@ -1,11 +1,12 @@ import logging import unittest +from urllib.parse import parse_qs, urlparse import pubnub from pubnub.exceptions import PubNubException from pubnub.models.consumer.pubsub import PNPublishResult from pubnub.pubnub import PubNub -from tests.helper import pnconf, pnconf_demo_copy, pnconf_enc, pnconf_file_copy +from tests.helper import pnconf, pnconf_demo_copy, pnconf_enc, pnconf_file_copy, pnconf_env from tests.integrational.vcr_helper import pn_vcr from unittest.mock import patch @@ -371,3 +372,20 @@ def test_publish_ttl_100(self): assert env.result.timetoken > 1 except PubNubException as e: self.fail(e) + + def test_publish_custom_message_type(self): + with pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/publish/publish_custom_message_type.json', + filter_query_parameters=['uuid', 'pnsdk'], serializer='pn_json') as cassette: + envelope = PubNub(pnconf_env).publish() \ + .channel("ch1") \ + .message("hi") \ + .custom_message_type('test_message') \ + .sync() + + assert isinstance(envelope.result, PNPublishResult) + assert envelope.result.timetoken > 1 + assert len(cassette) == 1 + uri = urlparse(cassette.requests[0].uri) + query = parse_qs(uri.query) + assert 'custom_message_type' in query.keys() + assert query['custom_message_type'] == ['test_message'] diff --git a/tests/integrational/native_sync/test_signal.py b/tests/integrational/native_sync/test_signal.py index 210eef20..1306674f 100644 --- a/tests/integrational/native_sync/test_signal.py +++ b/tests/integrational/native_sync/test_signal.py @@ -1,8 +1,9 @@ +from urllib.parse import parse_qs, urlparse from pubnub.pubnub import PubNub from pubnub.models.consumer.signal import PNSignalResult from pubnub.models.consumer.common import PNStatus from pubnub.structures import Envelope -from tests.helper import pnconf_demo_copy +from tests.helper import pnconf_demo_copy, pnconf_env from tests.integrational.vcr_helper import pn_vcr @@ -18,3 +19,21 @@ def test_single_channel(): assert envelope.result.timetoken == '15640049765289377' assert isinstance(envelope.result, PNSignalResult) assert isinstance(envelope.status, PNStatus) + + +def test_signal_custom_message_type(): + with pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/signal/signal_custom_message_type.json', + filter_query_parameters=['uuid', 'pnsdk'], serializer='pn_json') as cassette: + envelope = PubNub(pnconf_env).signal() \ + .channel("ch1") \ + .message("hi") \ + .custom_message_type('test_message') \ + .sync() + + assert isinstance(envelope.result, PNSignalResult) + assert int(envelope.result.timetoken) > 1 + assert len(cassette) == 1 + uri = urlparse(cassette.requests[0].uri) + query = parse_qs(uri.query) + assert 'custom_message_type' in query.keys() + assert query['custom_message_type'] == ['test_message']