diff --git a/.pubnub.yml b/.pubnub.yml index 97cb33283..bae1bca85 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,9 +1,9 @@ name: kotlin -version: 10.1.0 +version: 10.2.0 schema: 1 scm: github.com/pubnub/kotlin files: - - build/libs/pubnub-kotlin-10.1.0-all.jar + - build/libs/pubnub-kotlin-10.2.0-all.jar sdks: - type: library @@ -23,8 +23,8 @@ sdks: - distribution-type: library distribution-repository: maven - package-name: pubnub-kotlin-10.1.0 - location: https://repo.maven.apache.org/maven2/com/pubnub/pubnub-kotlin/10.1.0/pubnub-kotlin-10.1.0.jar + package-name: pubnub-kotlin-10.2.0 + location: https://repo.maven.apache.org/maven2/com/pubnub/pubnub-kotlin/10.2.0/pubnub-kotlin-10.2.0.jar supported-platforms: supported-operating-systems: Android: @@ -114,6 +114,11 @@ sdks: license-url: https://www.apache.org/licenses/LICENSE-2.0.txt is-required: Required changelog: + - date: 2024-11-18 + version: v10.2.0 + changes: + - type: feature + text: "Publish, signal, share file, subscribe, and history." - date: 2024-11-06 version: v10.1.0 changes: diff --git a/CHANGELOG.md b/CHANGELOG.md index 55e27169a..364a49886 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## v10.2.0 +November 18 2024 + +#### Added +- Publish, signal, share file, subscribe, and history. + ## v10.1.0 November 06 2024 diff --git a/README.md b/README.md index d766e3f62..4fdca81e1 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ You will need the publish and subscribe keys to authenticate your app. Get your com.pubnub pubnub-kotlin - 10.1.0 + 10.2.0 ``` diff --git a/gradle.properties b/gradle.properties index 15cb17336..9d7c5d551 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,7 +18,7 @@ RELEASE_SIGNING_ENABLED=true SONATYPE_HOST=DEFAULT SONATYPE_AUTOMATIC_RELEASE=false GROUP=com.pubnub -VERSION_NAME=10.1.0 +VERSION_NAME=10.2.0 POM_PACKAGING=jar POM_NAME=PubNub SDK diff --git a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/PubNub.kt b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/PubNub.kt index 18ff6532b..7f14c4bae 100644 --- a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/PubNub.kt +++ b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/PubNub.kt @@ -57,6 +57,7 @@ import com.pubnub.api.java.v2.PNConfiguration import com.pubnub.api.java.v2.callbacks.EventEmitter import com.pubnub.api.java.v2.callbacks.StatusEmitter import com.pubnub.api.java.v2.endpoints.pubsub.PublishBuilder +import com.pubnub.api.java.v2.endpoints.pubsub.SignalBuilder import com.pubnub.api.java.v2.entities.Channel import com.pubnub.api.java.v2.entities.ChannelGroup import com.pubnub.api.java.v2.entities.ChannelMetadata @@ -183,6 +184,10 @@ interface PubNub : EventEmitter, StatusEmitter { * if more than 100 messages meet the timetoken values. * */ + @Deprecated( + level = DeprecationLevel.WARNING, + message = "Use fetchMessages() instead", + ) fun history(): History /** @@ -319,6 +324,11 @@ interface PubNub : EventEmitter, StatusEmitter { * The message argument can contain any JSON serializable data, including: Objects, Arrays, Integers and Strings. * Data should not contain special Java/Kotlin classes or functions as these will not serialize. * String content can include any single-byte or multi-byte UTF-8 character. + * + * @param message The payload + * @param channel The channel to publish message to. + * + * @return [PublishBuilder] */ fun publish(message: Any, channel: String): PublishBuilder @@ -360,8 +370,13 @@ interface PubNub : EventEmitter, StatusEmitter { * By default, signals are limited to a message payload size of 30 bytes. * This limit applies only to the payload, and not to the URI or headers. * If you require a larger payload size, please [contact support](mailto:support@pubnub.com). + * + * @param message The payload + * @param channel The channel to signal message to. + * + * @return [SignalBuilder] */ - fun signal(message: Any, channel: String): com.pubnub.api.endpoints.pubsub.Signal + fun signal(message: Any, channel: String): SignalBuilder /** * Send a signal to all subscribers of a channel. diff --git a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/FetchMessages.java b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/FetchMessages.java index a577a20c4..bded0ec68 100644 --- a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/FetchMessages.java +++ b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/FetchMessages.java @@ -18,4 +18,6 @@ public interface FetchMessages extends Endpoint { FetchMessages includeMessageType(boolean includeMessageType); FetchMessages includeUUID(boolean includeUUID); + + FetchMessages includeCustomMessageType(boolean includeCustomMessageType); } diff --git a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/files/PublishFileMessage.java b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/files/PublishFileMessage.java index 2cb4e8852..6106d5ff2 100644 --- a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/files/PublishFileMessage.java +++ b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/files/PublishFileMessage.java @@ -15,6 +15,8 @@ public interface PublishFileMessage extends Endpoint PublishFileMessage shouldStore(Boolean shouldStore); + PublishFileMessage customMessageType(String customMessageType); + interface Builder extends BuilderSteps.ChannelStep>> { } diff --git a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/files/SendFile.java b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/files/SendFile.java index 3c8cb048a..6bcafa54f 100644 --- a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/files/SendFile.java +++ b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/files/SendFile.java @@ -17,6 +17,8 @@ public interface SendFile extends ExtendedRemoteAction { SendFile cipherKey(String cipherKey); + SendFile customMessageType(String customMessageType); + interface Builder extends BuilderSteps.ChannelStep>> { } diff --git a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/pubsub/Publish.java b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/pubsub/Publish.java index cbd0fafec..fcb9f5e66 100644 --- a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/pubsub/Publish.java +++ b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/endpoints/pubsub/Publish.java @@ -17,4 +17,6 @@ public interface Publish extends Endpoint { Publish replicate(boolean replicate); Publish ttl(Integer ttl); + + Publish customMessageType(String type); } diff --git a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/endpoints/pubsub/PublishBuilder.java b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/endpoints/pubsub/PublishBuilder.java index 92c13dac2..4fb3670ea 100644 --- a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/endpoints/pubsub/PublishBuilder.java +++ b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/endpoints/pubsub/PublishBuilder.java @@ -3,14 +3,63 @@ import com.pubnub.api.java.endpoints.Endpoint; import com.pubnub.api.models.consumer.PNPublishResult; +/** + * Interface representing a builder for configuring a publish operation. + * This interface extends {@link Endpoint} to provide a fluent API for setting various parameters + * for the publish request. + */ public interface PublishBuilder extends Endpoint { + /** + * Specifies whether the message should be stored in the history of the channel. + * + * @param shouldStore Boolean indicating whether to store the message (true) or not (false). If not specified, then the history configuration of the key is used. + * @return The current instance of {@code PublishBuilder} for method chaining. + */ PublishBuilder shouldStore(Boolean shouldStore); + /** + * Configures the publish request to use the POST HTTP method instead of GET. + * + * @param usePOST Boolean indicating whether to use POST (true) or GET (false) for the request. Default is `false` + * @return The current instance of {@code PublishBuilder} for method chaining. + */ PublishBuilder usePOST(boolean usePOST); + /** + * Sets the metadata to be sent along with the message. + * Metadata can be any custom object. + * + * @param meta Metadata object which can be used with the filtering ability. + * @return The current instance of {@code PublishBuilder} for method chaining. + */ PublishBuilder meta(Object meta); + + /** + * Specifies whether the message should be replicated across datacenters. + * + * @param replicate Boolean indicating whether to replicate the message (true) or not (false). Default is true. + * @return The current instance of {@code PublishBuilder} for method chaining. + */ PublishBuilder replicate(boolean replicate); + /** + * Sets the time-to-live (TTL) in Message Persistence. + * If shouldStore = true, and ttl = 0, the message is stored with no expiry time. + * If shouldStore = true and ttl = X (X is an Integer value), the message is stored with an expiry time of X hours. + * If shouldStore = false, the ttl parameter is ignored. + * If ttl is not specified, then expiration of the message defaults back to the expiry value for the key. + * + * @param ttl The TTL value in minutes for the message. + * @return The current instance of {@code PublishBuilder} for method chaining. + */ PublishBuilder ttl(Integer ttl); + + /** + * Specifies a custom message type for the message. + * + * @param customMessageType The custom message type as a string. + * @return The current instance of {@code PublishBuilder} for method chaining. + */ + PublishBuilder customMessageType(String customMessageType); } diff --git a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/endpoints/pubsub/SignalBuilder.java b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/endpoints/pubsub/SignalBuilder.java index 321ef9edd..962d09e91 100644 --- a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/endpoints/pubsub/SignalBuilder.java +++ b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/endpoints/pubsub/SignalBuilder.java @@ -1,6 +1,19 @@ package com.pubnub.api.java.v2.endpoints.pubsub; -import com.pubnub.api.java.endpoints.pubsub.Signal; +import com.pubnub.api.java.endpoints.Endpoint; +import com.pubnub.api.models.consumer.PNPublishResult; -public interface SignalBuilder extends Signal { +/** + * Interface representing a builder for configuring a signal operation. + * This interface extends {@link Endpoint} to provide a fluent API for setting parameters + * for the signal request. + */ +public interface SignalBuilder extends Endpoint { + /** + * Specifies a custom message type for the signal. + * + * @param customMessageType The custom message type as a string. + * @return The current instance of {@code SignalBuilder} for method chaining. + */ + SignalBuilder customMessageType(String customMessageType); } diff --git a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/entities/Channel.kt b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/entities/Channel.kt index 12055d8cf..5e2c44ca5 100644 --- a/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/entities/Channel.kt +++ b/pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/v2/entities/Channel.kt @@ -1,7 +1,7 @@ package com.pubnub.api.java.v2.entities -import com.pubnub.api.endpoints.pubsub.Signal import com.pubnub.api.java.v2.endpoints.pubsub.PublishBuilder +import com.pubnub.api.java.v2.endpoints.pubsub.SignalBuilder import com.pubnub.api.java.v2.subscriptions.Subscription import com.pubnub.api.v2.subscriptions.SubscriptionOptions @@ -90,6 +90,7 @@ interface Channel : Subscribable { * - If `shouldStore = false`, the `ttl` parameter is ignored. * - If ttl isn't specified, then expiration of the message defaults * back to the expiry value for the key. + * @param customMessageType The custom type associated with the message. */ fun publish(message: Any): PublishBuilder @@ -101,8 +102,9 @@ interface Channel : Subscribable { * If you require a larger payload size, please [contact support](mailto:support@pubnub.com). * * @param message The payload which will be serialized and sent. + * @param customMessageType The custom type associated with the message. */ - fun signal(message: Any): Signal + fun signal(message: Any): SignalBuilder /** * Send a message to PubNub Functions Event Handlers. diff --git a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/FilesIntegrationTests.java b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/FilesIntegrationTests.java index dac93d77e..e18160007 100644 --- a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/FilesIntegrationTests.java +++ b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/FilesIntegrationTests.java @@ -46,6 +46,7 @@ public void doItAllFilesTest(boolean withCipher) throws PubNubException, Interru String channel = randomChannel(); String content = "This is content"; String message = "This is message"; + String customMessageType = "myType01-_"; String meta = "This is meta"; String fileName = "fileName" + channel + ".txt"; CountDownLatch connectedLatch = new CountDownLatch(1); @@ -61,7 +62,7 @@ public void status(@NotNull PubNub pubnub, @NotNull PNStatus pnStatus) { @Override public void file(@NotNull PubNub pubnub, @NotNull PNFileEventResult pnFileEventResult) { - if (pnFileEventResult.getFile().getName().equals(fileName)) { + if (pnFileEventResult.getFile().getName().equals(fileName) && pnFileEventResult.getCustomMessageType().equals(customMessageType)) { fileEventReceived.countDown(); } } @@ -79,6 +80,7 @@ public void file(@NotNull PubNub pubnub, @NotNull PNFileEventResult pnFileEventR .fileName(fileName) .inputStream(is) .message(message) + .customMessageType(customMessageType) .meta(meta) .sync(); } diff --git a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/HistoryIntegrationTest.java b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/HistoryIntegrationTest.java index fcfbd9d4b..4d1619c9e 100644 --- a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/HistoryIntegrationTest.java +++ b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/HistoryIntegrationTest.java @@ -121,12 +121,14 @@ public void testHistorySingleChannel_Meta_Timetoken() throws PubNubException { @Test public void testFetchSingleChannel() throws PubNubException { final String expectedChannelName = random(); + final String customMessageType = "myType_" + random(); - publishMixed(pubNub, 10, expectedChannelName); + publishMixed(pubNub, 10, expectedChannelName, customMessageType); final PNFetchMessagesResult fetchMessagesResult = pubNub.fetchMessages() .channels(Collections.singletonList(expectedChannelName)) .maximumPerChannel(25) + .includeCustomMessageType(true) .sync(); pause(3); @@ -137,6 +139,7 @@ public void testFetchSingleChannel() throws PubNubException { assertNotNull(messageItem.getTimetoken()); assertNull(messageItem.getMeta()); assertNull(messageItem.getActions()); + assertEquals(customMessageType, messageItem.getCustomMessageType()); } } @@ -168,8 +171,9 @@ public void testFetchSingleChannel_Meta() throws PubNubException { @Test public void testFetchSingleChannel_Actions() throws PubNubException { final String expectedChannelName = random(); + final String customMessageType = "myType_" + random(); - final List results = publishMixed(pubNub, 120, expectedChannelName); + final List results = publishMixed(pubNub, 120, expectedChannelName, customMessageType); pubNub.addMessageAction() .channel(expectedChannelName) @@ -184,6 +188,7 @@ public void testFetchSingleChannel_Actions() throws PubNubException { .maximumPerChannel(25) .includeMessageActions(true) .includeMeta(false) + .includeCustomMessageType(true) .sync(); assert fetchMessagesResult != null; @@ -196,6 +201,7 @@ public void testFetchSingleChannel_Actions() throws PubNubException { } else { assertTrue(messageItem.getActions().isEmpty()); } + assertEquals(customMessageType, messageItem.getCustomMessageType()); } } diff --git a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/PublishFileMessageIntegrationTest.java b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/PublishFileMessageIntegrationTest.java new file mode 100644 index 000000000..bdd222d15 --- /dev/null +++ b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/PublishFileMessageIntegrationTest.java @@ -0,0 +1,24 @@ +package com.pubnub.api.integration; + +import com.pubnub.api.PubNubException; +import com.pubnub.api.integration.util.BaseIntegrationTest; +import com.pubnub.api.models.consumer.files.PNPublishFileMessageResult; +import org.junit.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class PublishFileMessageIntegrationTest extends BaseIntegrationTest { + + @Test + public void can_publishFileMessage() throws PubNubException { + PNPublishFileMessageResult publishFileMessageResult = pubNub.publishFileMessage() + .channel("whatever") + .fileName("whatever") + .fileId("whatever") + .message("whatever") + .customMessageType("my-Custom") + .sync(); + + assertNotNull(publishFileMessageResult.getTimetoken()); + } +} diff --git a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/PublishIntegrationTests.java b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/PublishIntegrationTests.java index b79524f62..f89a56baf 100644 --- a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/PublishIntegrationTests.java +++ b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/PublishIntegrationTests.java @@ -12,6 +12,7 @@ import com.pubnub.api.java.callbacks.SubscribeCallback; import com.pubnub.api.java.v2.PNConfiguration; import com.pubnub.api.java.v2.PNConfigurationOverride; +import com.pubnub.api.java.v2.callbacks.StatusListener; import com.pubnub.api.java.v2.entities.Channel; import com.pubnub.api.java.v2.subscriptions.Subscription; import com.pubnub.api.models.consumer.PNPublishResult; @@ -31,6 +32,11 @@ import org.junit.Test; import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -58,8 +64,9 @@ public void testPublishMessage() throws PubNubException { final AtomicBoolean success = new AtomicBoolean(); final String expectedChannel = randomChannel(); final JsonObject messagePayload = generateMessage(pubNub); + final String customMessageType = "myType"; - pubNub.publish(messagePayload, expectedChannel).shouldStore(true).usePOST(true).async((result) -> { + pubNub.publish(messagePayload, expectedChannel).shouldStore(true).usePOST(true).customMessageType(customMessageType).async((result) -> { assertFalse(result.isFailure()); success.set(true); }); @@ -70,6 +77,7 @@ public void testPublishMessage() throws PubNubException { pubNub.publish() .message(messagePayload) .channel(expectedChannel) + .customMessageType(customMessageType) .async((result) -> { assertFalse(result.isFailure()); success.set(true); @@ -256,6 +264,7 @@ public void testReceiveMessage() { final AtomicBoolean success = new AtomicBoolean(); final String expectedChannel = randomChannel(); final JsonObject messagePayload = generateMessage(pubNub); + final String customMessageType = "myCustomType01"; final PubNub observer = getPubNub(); @@ -268,6 +277,7 @@ public void status(@NotNull PubNub pubnub, @NotNull PNStatus status) { observer.publish() .message(messagePayload) .channel(expectedChannel) + .customMessageType(customMessageType) .async((result) -> assertFalse(result.isFailure())); } } @@ -278,6 +288,7 @@ public void message(@NotNull PubNub pubnub, @NotNull PNMessageResult message) { assertEquals(expectedChannel, message.getChannel()); assertEquals(observer.getConfiguration().getUserId().getValue(), message.getPublisher()); assertEquals(messagePayload, message.getMessage()); + assertEquals(customMessageType, message.getCustomMessageType()); success.set(true); } @@ -702,4 +713,35 @@ public void message(@NotNull PubNub pubnub, @NotNull PNMessageResult pnMessageRe .with() .untilAtomic(count, IsEqual.equalTo(2)); } + + @Test + public void testPublishMessageWithCustomMessageType() throws InterruptedException, ExecutionException, TimeoutException, PubNubException { + String expectedChannelName = randomChannel(); + Channel channel = pubNub.channel(expectedChannelName); + String expectedCustomMessageType = "thisIsType"; + CountDownLatch connected = new CountDownLatch(1); + CompletableFuture receivedMessageFuture = new CompletableFuture(); + + Subscription subscription = channel.subscription(); + subscription.setOnMessage(pnMessageResult -> receivedMessageFuture.complete(pnMessageResult)); + pubNub.addListener(new StatusListener() { + @Override + public void status(@NotNull PubNub pubnub, @NotNull PNStatus status) { + if (status.getCategory() == PNStatusCategory.PNConnectedCategory && + status.getAffectedChannels().contains(expectedChannelName) + ) { + connected.countDown(); + } + } + }); + + subscription.subscribe(); + assertTrue(connected.await(10, TimeUnit.SECONDS)); + + channel.publish("message").customMessageType(expectedCustomMessageType).sync(); + + PNMessageResult message = (PNMessageResult) receivedMessageFuture.get(10, TimeUnit.SECONDS); + + assertEquals(expectedCustomMessageType, message.getCustomMessageType()); + } } diff --git a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/SignalIntegrationTests.java b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/SignalIntegrationTests.java index 07ec64262..13f945902 100644 --- a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/SignalIntegrationTests.java +++ b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/SignalIntegrationTests.java @@ -56,8 +56,9 @@ public void testPublishSignalMessageAsync() { public void testPublishSignalMessageSync() throws PubNubException { final String expectedChannel = randomChannel(); final String expectedPayload = RandomGenerator.newValue(5); + final String customMessageType = "myt_ype-"; - final PNPublishResult signalResult = pubNub.signal(expectedPayload, expectedChannel).sync(); + final PNPublishResult signalResult = pubNub.signal(expectedPayload, expectedChannel).customMessageType(customMessageType).sync(); assertNotNull(signalResult); } @@ -68,6 +69,7 @@ public void testReceiveSignalMessage() { final String expectedChannel = randomChannel(); final String expectedPayload = RandomGenerator.newValue(5); + final String expectedCustomMessageType = "myCustomType"; final com.pubnub.api.java.PubNub observerClient = getPubNub(); @@ -78,9 +80,8 @@ public void testReceiveSignalMessage() { public void status(@NotNull com.pubnub.api.java.PubNub pubnub, @NotNull PNStatus status) { if (status.getCategory() == PNStatusCategory.PNConnectedCategory) { if (status.getAffectedChannels().contains(expectedChannel)) { - pubNub.signal() - .message(expectedPayload) - .channel(expectedChannel) + pubNub.signal(expectedPayload, expectedChannel) + .customMessageType(expectedCustomMessageType) .async((result) -> { assertFalse(result.isFailure()); assertNotNull(result); @@ -94,6 +95,7 @@ public void signal(@NotNull com.pubnub.api.java.PubNub pubnub, @NotNull PNSignal assertEquals(pubNub.getConfiguration().getUserId().getValue(), signal.getPublisher()); assertEquals(expectedChannel, signal.getChannel()); assertEquals(expectedPayload, new Gson().fromJson(signal.getMessage(), String.class)); + assertEquals(expectedCustomMessageType, signal.getCustomMessageType()); success.set(true); } }); diff --git a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/util/Utils.java b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/util/Utils.java index 510b12d5a..c8e185e7c 100644 --- a/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/util/Utils.java +++ b/pubnub-gson/pubnub-gson-impl/src/integrationTest/java/com/pubnub/api/integration/util/Utils.java @@ -63,12 +63,21 @@ public static String randomChannel() { // } public static List publishMixed(PubNub pubnub, int count, String channel) { + String customMessageType = null; + return publishMixed(pubnub, count, channel, customMessageType); + } + + public static List publishMixed(PubNub pubnub, int count, String channel, String customMessageType) { final List list = new ArrayList<>(); for (int i = 0; i < count; i++) { final Publish publishBuilder = pubnub.publish() .channel(channel) .message(String.valueOf(i).concat("_msg")) .shouldStore(true); + if(customMessageType != null){ + publishBuilder.customMessageType(customMessageType); + } + if (i % 2 == 0) { publishBuilder.meta(generateMap()); } else if (i % 3 == 0) { diff --git a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/PubNubForJavaImpl.kt b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/PubNubForJavaImpl.kt index 099af69c5..1dbd6e9d2 100644 --- a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/PubNubForJavaImpl.kt +++ b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/PubNubForJavaImpl.kt @@ -57,6 +57,7 @@ import com.pubnub.api.java.v2.PNConfiguration import com.pubnub.api.java.v2.callbacks.EventListener import com.pubnub.api.java.v2.callbacks.StatusListener import com.pubnub.api.java.v2.endpoints.pubsub.PublishBuilder +import com.pubnub.api.java.v2.endpoints.pubsub.SignalBuilder import com.pubnub.internal.PubNubImpl import com.pubnub.internal.java.builder.PresenceBuilderImpl import com.pubnub.internal.java.builder.SubscribeBuilderImpl @@ -218,8 +219,8 @@ open class PubNubForJavaImpl(configuration: PNConfiguration) : return SignalImpl(this) } - override fun signal(message: Any, channel: String): com.pubnub.api.endpoints.pubsub.Signal { - return super.signal(channel, message) + override fun signal(message: Any, channel: String): SignalBuilder { + return SignalImpl(this).message(message).channel(channel) as SignalBuilder } override fun listChannelsForChannelGroup(): AllChannelsChannelGroup { diff --git a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/FetchMessagesImpl.java b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/FetchMessagesImpl.java index a82bf9319..254a96c00 100644 --- a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/FetchMessagesImpl.java +++ b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/FetchMessagesImpl.java @@ -35,6 +35,7 @@ public class FetchMessagesImpl extends PassthroughEndpoint createRemoteAction() { includeUUID, includeMeta, includeMessageActions, - includeMessageType + includeMessageType, + includeCustomMessageType ); } diff --git a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/files/PublishFileMessageImpl.java b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/files/PublishFileMessageImpl.java index 7e6bd6f6d..6c9e9e5f4 100644 --- a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/files/PublishFileMessageImpl.java +++ b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/files/PublishFileMessageImpl.java @@ -26,6 +26,8 @@ public class PublishFileMessageImpl extends PassthroughEndpoint createRemoteAction() { message, meta, ttl, - shouldStore + shouldStore, + customMessageType ); } diff --git a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/files/SendFileImpl.java b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/files/SendFileImpl.java index 0b97a9273..92e92dd75 100644 --- a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/files/SendFileImpl.java +++ b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/files/SendFileImpl.java @@ -31,6 +31,8 @@ public class SendFileImpl extends PassthroughRemoteAction im private Boolean shouldStore; @Setter private String cipherKey; + @Setter + private String customMessageType; public SendFileImpl(PubNub pubnub, String channel, String fileName, InputStream inputStream) { super(pubnub); @@ -50,7 +52,8 @@ protected ExtendedRemoteAction createRemoteAction() { meta, ttl, shouldStore, - cipherKey + cipherKey, + customMessageType ); } diff --git a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/pubsub/PublishImpl.java b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/pubsub/PublishImpl.java index 8b9062c56..976d005d4 100644 --- a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/pubsub/PublishImpl.java +++ b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/pubsub/PublishImpl.java @@ -23,6 +23,7 @@ public class PublishImpl extends PassthroughEndpoint implements private Object meta; private boolean replicate; private Integer ttl; + private String customMessageType; public PublishImpl(PubNub pubnub) { super(pubnub); @@ -39,7 +40,8 @@ protected Endpoint createRemoteAction() { shouldStore, usePOST, replicate, - ttl + ttl, + customMessageType ); } diff --git a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/pubsub/SignalImpl.java b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/pubsub/SignalImpl.java index b7030eb59..e48eb8fd9 100644 --- a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/pubsub/SignalImpl.java +++ b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/endpoints/pubsub/SignalImpl.java @@ -18,6 +18,7 @@ public class SignalImpl extends PassthroughEndpoint implements private Object message; private String channel; + private String customMessageType; public SignalImpl(PubNub pubnub) { super(pubnub); @@ -26,7 +27,7 @@ public SignalImpl(PubNub pubnub) { @Override @NotNull protected Endpoint createRemoteAction() { - return pubnub.signal(channel, message); + return pubnub.signal(channel, message, customMessageType); } @Override diff --git a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/v2/entities/ChannelImpl.kt b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/v2/entities/ChannelImpl.kt index e16b2138b..f9ab72f85 100644 --- a/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/v2/entities/ChannelImpl.kt +++ b/pubnub-gson/pubnub-gson-impl/src/main/java/com/pubnub/internal/java/v2/entities/ChannelImpl.kt @@ -1,7 +1,7 @@ package com.pubnub.internal.java.v2.entities -import com.pubnub.api.endpoints.pubsub.Signal import com.pubnub.api.java.v2.endpoints.pubsub.PublishBuilder +import com.pubnub.api.java.v2.endpoints.pubsub.SignalBuilder import com.pubnub.api.v2.subscriptions.EmptyOptions import com.pubnub.api.v2.subscriptions.SubscriptionOptions import com.pubnub.internal.java.PubNubForJavaImpl @@ -23,7 +23,7 @@ class ChannelImpl(private val pubnub: PubNubForJavaImpl, channelName: ChannelNam return pubnub.publish(message, name) } - override fun signal(message: Any): Signal { + override fun signal(message: Any): SignalBuilder { return pubnub.signal(message, name) } diff --git a/pubnub-kotlin/pubnub-kotlin-api/config/ktlint/baseline.xml b/pubnub-kotlin/pubnub-kotlin-api/config/ktlint/baseline.xml index 4c9e89d48..fc6e16e1b 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/config/ktlint/baseline.xml +++ b/pubnub-kotlin/pubnub-kotlin-api/config/ktlint/baseline.xml @@ -10,25 +10,20 @@ - - - - - - - - - - - - + + + + + + + + + + - - - - - + + @@ -37,11 +32,11 @@ + + + - - - @@ -73,5 +68,10 @@ + + + + + diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/PubNubImpl.kt b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/PubNubImpl.kt index 65815b093..33990ead4 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/PubNubImpl.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/PubNubImpl.kt @@ -195,7 +195,8 @@ class PubNubImpl(private val pubNubObjC: KMPPubNub) : PubNub { shouldStore: Boolean?, usePost: Boolean, replicate: Boolean, - ttl: Int? + ttl: Int?, + customMessageType: String?, ): Publish { return PublishImpl( pubnub = pubNubObjC, @@ -203,7 +204,8 @@ class PubNubImpl(private val pubNubObjC: KMPPubNub) : PubNub { message = message, meta = meta, shouldStore = shouldStore, - ttl = ttl + ttl = ttl, + customMessageType = customMessageType ) } @@ -215,15 +217,17 @@ class PubNubImpl(private val pubNubObjC: KMPPubNub) : PubNub { message = message, meta = meta, shouldStore = false, - ttl = 0 + ttl = 0, + customMessageType = null ) } - override fun signal(channel: String, message: Any): Signal { + override fun signal(channel: String, message: Any, customMessageType: String?): Signal { return SignalImpl( pubnub = pubNubObjC, channel = channel, - message = message + message = message, + customMessageType = customMessageType ) } @@ -305,7 +309,8 @@ class PubNubImpl(private val pubNubObjC: KMPPubNub) : PubNub { includeUUID: Boolean, includeMeta: Boolean, includeMessageActions: Boolean, - includeMessageType: Boolean + includeMessageType: Boolean, + includeCustomMessageType: Boolean ): FetchMessages { return FetchMessagesImpl( pubnub = pubNubObjC, @@ -314,7 +319,8 @@ class PubNubImpl(private val pubNubObjC: KMPPubNub) : PubNub { includeUUID = includeUUID, includeMeta = includeMeta, includeMessageActions = includeMessageActions, - includeMessageType = includeMessageType + includeMessageType = includeMessageType, + includeCustomMessageType = includeCustomMessageType ) } @@ -776,7 +782,8 @@ class PubNubImpl(private val pubNubObjC: KMPPubNub) : PubNub { message: Any?, meta: Any?, ttl: Int?, - shouldStore: Boolean? + shouldStore: Boolean?, + customMessageType: String? ): PublishFileMessage { return PublishFileMessageImpl( pubnub = pubNubObjC, @@ -786,7 +793,8 @@ class PubNubImpl(private val pubNubObjC: KMPPubNub) : PubNub { message = message, meta = meta, ttl = ttl, - shouldStore = shouldStore + shouldStore = shouldStore, + customMessageType = customMessageType ) } @@ -881,7 +889,8 @@ class PubNubImpl(private val pubNubObjC: KMPPubNub) : PubNub { meta: Any?, ttl: Int?, shouldStore: Boolean?, - cipherKey: String? + cipherKey: String?, + customMessageType: String? ): SendFile { return SendFileImpl( pubnub = pubNubObjC, @@ -891,7 +900,8 @@ class PubNubImpl(private val pubNubObjC: KMPPubNub) : PubNub { message = message, meta = meta, ttl = ttl, - shouldStore = shouldStore + shouldStore = shouldStore, + customMessageType = customMessageType ) } diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/FetchMessages.ios.kt b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/FetchMessages.ios.kt index eed1f07d6..3a5dfb1c3 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/FetchMessages.ios.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/FetchMessages.ios.kt @@ -32,7 +32,8 @@ open class FetchMessagesImpl( private val includeUUID: Boolean, private val includeMeta: Boolean, private val includeMessageActions: Boolean, - private val includeMessageType: Boolean + private val includeMessageType: Boolean, + private val includeCustomMessageType: Boolean ) : FetchMessages { override fun async(callback: Consumer>) { pubnub.fetchMessagesFrom( @@ -41,6 +42,7 @@ open class FetchMessagesImpl( includeMeta = includeMeta, includeMessageActions = includeMessageActions, includeMessageType = includeMessageType, +// includeCustomMessageType = includeCustomMessageType, // todo page = KMPBoundedPage( start = page.start?.let { NSNumber(long = it) }, end = page.end?.let { NSNumber(long = it) }, diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/files/PublishFileMessage.ios.kt b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/files/PublishFileMessage.ios.kt index 4109c3cb9..da8d834b2 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/files/PublishFileMessage.ios.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/files/PublishFileMessage.ios.kt @@ -25,7 +25,8 @@ class PublishFileMessageImpl( private val message: Any?, private val meta: Any?, private val ttl: Int?, - private val shouldStore: Boolean? + private val shouldStore: Boolean?, + private val customMessageType: String? ) : PublishFileMessage { override fun async(callback: Consumer>) { pubnub.publishFileMessageWithChannel( @@ -36,6 +37,7 @@ class PublishFileMessageImpl( meta = meta, ttl = ttl?.let { NSNumber(it) }, shouldStore = shouldStore?.let { NSNumber(bool = it) }, +// customMessageType = customMessageType, // todo ask Kuba onSuccess = callback.onSuccessHandler { PNPublishFileMessageResult(it.toLong()) }, onFailure = callback.onFailureHandler() ) diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/files/SendFile.ios.kt b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/files/SendFile.ios.kt index bc944a013..0474a3702 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/files/SendFile.ios.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/files/SendFile.ios.kt @@ -36,6 +36,7 @@ class SendFileImpl( private val meta: Any?, private val ttl: Int?, private val shouldStore: Boolean?, + private val customMessageType: String? ) : SendFile { override fun async(callback: Consumer>) { mapContent(inputStream)?.let { content -> @@ -47,6 +48,7 @@ class SendFileImpl( meta = meta, ttl = ttl?.let { NSNumber(it) }, shouldStore = shouldStore?.let { NSNumber(it) }, +// customMessageType = customMessageType, // todo ask Kuba onSuccess = callback.onSuccessHandler2 { uploadedFile, timetoken -> PNFileUploadResult( status = 200, diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/pubsub/Publish.ios.kt b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/pubsub/Publish.ios.kt index 468d91acd..dde9772bd 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/pubsub/Publish.ios.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/pubsub/Publish.ios.kt @@ -23,7 +23,8 @@ class PublishImpl( private val message: Any, private val meta: Any?, private val shouldStore: Boolean?, - private val ttl: Int? + private val ttl: Int?, + private val customMessageType: String? ) : Publish { override fun async(callback: Consumer>) { pubnub.publishWithChannel( @@ -32,6 +33,7 @@ class PublishImpl( meta = meta, shouldStore = shouldStore?.let { NSNumber(bool = it) }, ttl = ttl?.let { NSNumber(it) }, +// customMessageType = customMessageType, // todo, ask Kuba onSuccess = callback.onSuccessHandler { PNPublishResult(it.toLong()) }, onFailure = callback.onFailureHandler() ) diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/pubsub/Signal.ios.kt b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/pubsub/Signal.ios.kt index 2ee512318..eb889bf36 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/pubsub/Signal.ios.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/api/endpoints/pubsub/Signal.ios.kt @@ -13,12 +13,14 @@ import kotlinx.cinterop.ExperimentalForeignApi class SignalImpl( private val pubnub: KMPPubNub, private val channel: String, - private val message: Any + private val message: Any, + private val customMessageType: String?, ) : Signal { override fun async(callback: Consumer>) { pubnub.signalWithChannel( channel = channel, message = message, +// customeMessageType = customMessageType, //todo, ask Kuba onSuccess = callback.onSuccessHandler { PNPublishResult(it.toLong()) }, onFailure = callback.onFailureHandler() ) diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/internal/entities/ChannelImpl.kt b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/internal/entities/ChannelImpl.kt index 59fe410f5..97f3bfd19 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/internal/entities/ChannelImpl.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/appleMain/kotlin/com/pubnub/internal/entities/ChannelImpl.kt @@ -24,12 +24,13 @@ class ChannelImpl( shouldStore: Boolean, usePost: Boolean, replicate: Boolean, - ttl: Int? + ttl: Int?, + customMessageType: String? ): Publish { TODO("Not yet implemented") } - override fun signal(message: Any): Signal { + override fun signal(message: Any, customMessageType: String?): Signal { TODO("Not yet implemented") } @@ -44,7 +45,8 @@ class ChannelImpl( meta: Any?, ttl: Int?, shouldStore: Boolean?, - cipherKey: String? + cipherKey: String?, + customMessageType: String? ): SendFile { TODO("Not yet implemented") } diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/PubNub.kt b/pubnub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/PubNub.kt index 9cc4de4e1..c00bc671d 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/PubNub.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/PubNub.kt @@ -93,6 +93,7 @@ expect interface PubNub { usePost: Boolean = false, replicate: Boolean = true, ttl: Int? = null, + customMessageType: String? = null, ): Publish fun fire( @@ -105,6 +106,7 @@ expect interface PubNub { fun signal( channel: String, message: Any, + customMessageType: String? = null, ): Signal fun getSubscribedChannels(): List @@ -148,6 +150,7 @@ expect interface PubNub { includeMeta: Boolean = false, includeMessageActions: Boolean = false, includeMessageType: Boolean = true, + includeCustomMessageType: Boolean = false ): FetchMessages fun deleteMessages( @@ -419,6 +422,7 @@ expect interface PubNub { ttl: Int? = null, shouldStore: Boolean? = null, cipherKey: String? = null, + customMessageType: String? = null ): SendFile fun downloadFile( @@ -442,6 +446,7 @@ expect interface PubNub { meta: Any? = null, ttl: Int? = null, shouldStore: Boolean? = null, + customMessageType: String? = null ): PublishFileMessage fun subscribe( diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/v2/entities/Channel.kt b/pubnub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/v2/entities/Channel.kt index 82762f387..5316db1aa 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/v2/entities/Channel.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/v2/entities/Channel.kt @@ -83,6 +83,7 @@ interface Channel : Subscribable { * - If `shouldStore = false`, the `ttl` parameter is ignored. * - If ttl isn't specified, then expiration of the message defaults * back to the expiry value for the key. + * @param customMessageType The custom type associated with the message. */ fun publish( message: Any, @@ -90,7 +91,8 @@ interface Channel : Subscribable { shouldStore: Boolean = true, usePost: Boolean = false, replicate: Boolean = true, - ttl: Int? = null + ttl: Int? = null, + customMessageType: String? = null ): Publish /** @@ -101,8 +103,9 @@ interface Channel : Subscribable { * If you require a larger payload size, please [contact support](mailto:support@pubnub.com). * * @param message The payload which will be serialized and sent. + * @param customMessageType The custom type associated with the message. */ - fun signal(message: Any): Signal + fun signal(message: Any, customMessageType: String? = null): Signal /** * Send a message to PubNub Functions Event Handlers. @@ -163,6 +166,7 @@ interface Channel : Subscribable { * @param shouldStore Store in history. * If not specified, then the history configuration of the key is used. * @param cipherKey Key to be used to encrypt uploaded data. + * @param customMessageType The custom type associated with the message. */ fun sendFile( fileName: String, @@ -171,7 +175,8 @@ interface Channel : Subscribable { meta: Any? = null, ttl: Int? = null, shouldStore: Boolean? = null, - cipherKey: String? = null + cipherKey: String? = null, + customMessageType: String? = null ): SendFile /** diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/commonTest/kotlin/com/pubnub/test/integration/PublishTest.kt b/pubnub-kotlin/pubnub-kotlin-api/src/commonTest/kotlin/com/pubnub/test/integration/PublishTest.kt index 1b7a81b53..d44b67506 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/commonTest/kotlin/com/pubnub/test/integration/PublishTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/commonTest/kotlin/com/pubnub/test/integration/PublishTest.kt @@ -33,14 +33,14 @@ class PublishTest : BaseIntegrationTest() { @Test fun can_publish_message_string() = runTest { - val result = pubnub.publish(channel, "some message").await() + val result = pubnub.publish(channel = channel, message = "some message", customMessageType = "myCustomType").await() assertTrue { result.timetoken > 0 } } @Test fun can_signal() = runTest { - val result = pubnub.signal(channel, "some message").await() + val result = pubnub.signal(channel = channel, message = "some message", customMessageType = "myCustomType").await() assertTrue { result.timetoken > 0 } } diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/Pubnub.d.kt b/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/Pubnub.d.kt index 89176585a..ca1772c48 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/Pubnub.d.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/Pubnub.d.kt @@ -510,6 +510,7 @@ open external class PubNub(config: Any /* UUID | UserId */) { var sendByPost: Boolean? var meta: Any? var ttl: Number? + var customMessageType: String? } interface PublishResponse { @@ -519,6 +520,7 @@ open external class PubNub(config: Any /* UUID | UserId */) { interface SignalParameters { var message: Any var channel: String + var customMessageType: String? } interface SignalResponse { @@ -559,6 +561,7 @@ open external class PubNub(config: Any /* UUID | UserId */) { var includeUUID: Boolean? var includeMeta: Boolean? var includeMessageActions: Boolean? + var includeCustomMessageType: Boolean? } interface Action { @@ -936,6 +939,7 @@ open external class PubNub(config: Any /* UUID | UserId */) { var ttl: Number? var meta: Any? + var customMessageType: String? } interface StreamFileInput { @@ -980,6 +984,7 @@ open external class PubNub(config: Any /* UUID | UserId */) { var ttl: Number? var meta: Any? + var customMessageType: String? } interface UploadedFile { diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/com/pubnub/api/PubNubImpl.kt b/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/com/pubnub/api/PubNubImpl.kt index a3f2a473a..91d0ffe05 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/com/pubnub/api/PubNubImpl.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/com/pubnub/api/PubNubImpl.kt @@ -175,7 +175,8 @@ class PubNubImpl(val jsPubNub: PubNubJs) : PubNub { shouldStore: Boolean?, usePost: Boolean, replicate: Boolean, - ttl: Int? + ttl: Int?, + customMessageType: String?, ): Publish { return PublishImpl( jsPubNub, @@ -186,6 +187,7 @@ class PubNubImpl(val jsPubNub: PubNubJs) : PubNub { this.meta = meta?.adjustCollectionTypes() this.sendByPost = usePost this.ttl = ttl + this.customMessageType = customMessageType } ) } @@ -202,12 +204,13 @@ class PubNubImpl(val jsPubNub: PubNubJs) : PubNub { ) } - override fun signal(channel: String, message: Any): Signal { + override fun signal(channel: String, message: Any, customMessageType: String?): Signal { return SignalImpl( jsPubNub, createJsObject { this.message = message.adjustCollectionTypes() this.channel = channel + this.customMessageType = customMessageType } ) } @@ -294,7 +297,8 @@ class PubNubImpl(val jsPubNub: PubNubJs) : PubNub { includeUUID: Boolean, includeMeta: Boolean, includeMessageActions: Boolean, - includeMessageType: Boolean + includeMessageType: Boolean, + includeCustomMessageType: Boolean ): FetchMessages { return FetchMessagesImpl( jsPubNub, @@ -309,6 +313,7 @@ class PubNubImpl(val jsPubNub: PubNubJs) : PubNub { this.includeMessageActions = includeMessageActions this.includeMessageType = includeMessageType this.stringifiedTimeToken = true + this.includeCustomMessageType = includeCustomMessageType } ) } @@ -972,7 +977,8 @@ class PubNubImpl(val jsPubNub: PubNubJs) : PubNub { message: Any?, meta: Any?, ttl: Int?, - shouldStore: Boolean? + shouldStore: Boolean?, + customMessageType: String? ): PublishFileMessage { return PublishFileMessageImpl( jsPubNub, @@ -984,6 +990,7 @@ class PubNubImpl(val jsPubNub: PubNubJs) : PubNub { this.meta = meta?.adjustCollectionTypes() this.ttl = ttl this.storeInHistory = shouldStore + this.customMessageType = customMessageType } ) } @@ -1106,7 +1113,8 @@ class PubNubImpl(val jsPubNub: PubNubJs) : PubNub { meta: Any?, ttl: Int?, shouldStore: Boolean?, - cipherKey: String? + cipherKey: String?, + customMessageType: String? ): SendFile { return SendFileImpl( jsPubNub, @@ -1118,6 +1126,7 @@ class PubNubImpl(val jsPubNub: PubNubJs) : PubNub { this.ttl = ttl this.storeInHistory = shouldStore this.cipherKey = cipherKey + this.customMessageType = customMessageType } ) } diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/com/pubnub/internal/v2/entities/ChannelImpl.kt b/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/com/pubnub/internal/v2/entities/ChannelImpl.kt index 689c958bf..5dd38cc07 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/com/pubnub/internal/v2/entities/ChannelImpl.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/jsMain/kotlin/com/pubnub/internal/v2/entities/ChannelImpl.kt @@ -20,12 +20,13 @@ class ChannelImpl(private val jsChannel: dynamic) : Channel { shouldStore: Boolean, usePost: Boolean, replicate: Boolean, - ttl: Int? + ttl: Int?, + customMessageType: String?, ): Publish { TODO("Not yet implemented") } - override fun signal(message: Any): Signal { + override fun signal(message: Any, customMessageType: String?): Signal { TODO("Not yet implemented") } @@ -40,7 +41,8 @@ class ChannelImpl(private val jsChannel: dynamic) : Channel { meta: Any?, ttl: Int?, shouldStore: Boolean?, - cipherKey: String? + cipherKey: String?, + customMessageType: String? ): SendFile { TODO("Not yet implemented") } diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/PubNub.kt b/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/PubNub.kt index 2efad0254..09514e4d3 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/PubNub.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/PubNub.kt @@ -380,6 +380,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { * - If `shouldStore = false`, the `ttl` parameter is ignored. * - If ttl isn't specified, then expiration of the message defaults * back to the expiry value for the key. + * @param customMessageType The custom type associated with the message. */ actual fun publish( channel: String, @@ -389,6 +390,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { usePost: Boolean, replicate: Boolean, ttl: Int?, + customMessageType: String?, ): Publish /** @@ -463,10 +465,12 @@ actual interface PubNub : StatusEmitter, EventEmitter { * * @param channel The channel which the signal will be sent to. * @param message The payload which will be serialized and sent. + * @param customMessageType The custom type associated with the message. */ actual fun signal( channel: String, message: Any, + customMessageType: String?, ): Signal /** @@ -590,6 +594,10 @@ actual interface PubNub : StatusEmitter, EventEmitter { * @param includeMeta Whether to include message metadata in response. * Defaults to `false`. */ + @Deprecated( + level = DeprecationLevel.WARNING, + message = "Use fetchMessages(List, PNBoundedPage, Boolean, Boolean, Boolean, Boolean, Boolean) instead", + ) fun history( channel: String, start: Long? = null, @@ -645,7 +653,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { "com.pubnub.api.models.consumer.PNBoundedPage", ), level = DeprecationLevel.WARNING, - message = "Use fetchMessages(String, PNBoundedPage, Boolean, Boolean, Boolean) instead", + message = "Use fetchMessages(List, PNBoundedPage, Boolean, Boolean, Boolean, Boolean, Boolean) instead", ) fun fetchMessages( channels: List, @@ -655,6 +663,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { includeMeta: Boolean = false, includeMessageActions: Boolean = false, includeMessageType: Boolean = true, + includeCustomMessageType: Boolean = false ): FetchMessages /** @@ -691,6 +700,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { * Defaults to `false`. * @param includeMessageType Whether to include message type in response. * Defaults to `false`. + * @param includeCustomMessageType Whether to include custom message type in response. Default to `false` */ actual fun fetchMessages( channels: List, @@ -699,6 +709,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { includeMeta: Boolean, includeMessageActions: Boolean, includeMessageType: Boolean, + includeCustomMessageType: Boolean ): FetchMessages /** @@ -1615,6 +1626,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { * If not specified, then the history configuration of the key is used. * @param cipherKey Key to be used to encrypt uploaded data. If not provided, * cipherKey in @see [PNConfiguration] will be used, if provided. + * @param customMessageType The custom type associated with the message. */ actual fun sendFile( channel: String, @@ -1625,6 +1637,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { ttl: Int?, shouldStore: Boolean?, cipherKey: String?, + customMessageType: String?, ): SendFile /** @@ -1704,7 +1717,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { * back to the expiry value for the key. * @param shouldStore Store in history. * If not specified, then the history configuration of the key is used. - * + * @param customMessageType The custom type associated with the message. */ actual fun publishFileMessage( channel: String, @@ -1714,6 +1727,7 @@ actual interface PubNub : StatusEmitter, EventEmitter { meta: Any?, ttl: Int?, shouldStore: Boolean?, + customMessageType: String?, ): PublishFileMessage /** diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/FetchMessages.kt b/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/FetchMessages.kt index 461e0478f..62042ae4c 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/FetchMessages.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/FetchMessages.kt @@ -14,4 +14,5 @@ actual interface FetchMessages : Endpoint { val includeMeta: Boolean val includeMessageActions: Boolean val includeMessageType: Boolean + val includeCustomMessageType: Boolean } diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/pubsub/Publish.kt b/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/pubsub/Publish.kt index adc729da5..aeb6676c2 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/pubsub/Publish.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/pubsub/Publish.kt @@ -14,4 +14,5 @@ actual interface Publish : Endpoint { val usePost: Boolean val replicate: Boolean val ttl: Int? + val customMessageType: String? } diff --git a/pubnub-kotlin/pubnub-kotlin-api/src/nonJvm/kotlin/com/pubnub/api/PubNub.nonJvm.kt b/pubnub-kotlin/pubnub-kotlin-api/src/nonJvm/kotlin/com/pubnub/api/PubNub.nonJvm.kt index d1e949d57..bce6cf199 100644 --- a/pubnub-kotlin/pubnub-kotlin-api/src/nonJvm/kotlin/com/pubnub/api/PubNub.nonJvm.kt +++ b/pubnub-kotlin/pubnub-kotlin-api/src/nonJvm/kotlin/com/pubnub/api/PubNub.nonJvm.kt @@ -95,7 +95,7 @@ actual interface PubNub { usePost: Boolean ): Publish - actual fun signal(channel: String, message: Any): Signal + actual fun signal(channel: String, message: Any, customMessageType: String?): Signal actual fun getSubscribedChannels(): List @@ -137,7 +137,8 @@ actual interface PubNub { includeUUID: Boolean, includeMeta: Boolean, includeMessageActions: Boolean, - includeMessageType: Boolean + includeMessageType: Boolean, + includeCustomMessageType: Boolean ): FetchMessages actual fun deleteMessages( @@ -373,7 +374,8 @@ actual interface PubNub { meta: Any?, ttl: Int?, shouldStore: Boolean?, - cipherKey: String? + cipherKey: String?, + customMessageType: String? ): SendFile actual fun downloadFile( @@ -396,7 +398,8 @@ actual interface PubNub { message: Any?, meta: Any?, ttl: Int?, - shouldStore: Boolean? + shouldStore: Boolean?, + customMessageType: String? ): PublishFileMessage actual fun subscribe( @@ -445,5 +448,6 @@ actual interface PubNub { usePost: Boolean, replicate: Boolean, ttl: Int?, + customMessageType: String? ): Publish } diff --git a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/history/PNFetchMessage.kt b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/history/PNFetchMessage.kt index 2874ba2f0..6970b1b84 100644 --- a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/history/PNFetchMessage.kt +++ b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/history/PNFetchMessage.kt @@ -42,6 +42,7 @@ data class PNFetchMessageItem( val actions: Map>>? = null, val messageType: HistoryMessageType?, val error: PubNubError? = null, + val customMessageType: String? = null ) { // for compatibility with legacy Java SDK class Action(uuid: String, actionTimetoken: Long) : diff --git a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/history/PNHistoryResult.kt b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/history/PNHistoryResult.kt index aa0f1b512..bddd74889 100644 --- a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/history/PNHistoryResult.kt +++ b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/history/PNHistoryResult.kt @@ -36,4 +36,5 @@ data class PNHistoryItemResult( val timetoken: Long? = null, val meta: JsonElement? = null, val error: PubNubError? = null, + val customMessageType: String? = null ) diff --git a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/MessageResult.kt b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/MessageResult.kt index 1bb614d2b..aaeca33f5 100644 --- a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/MessageResult.kt +++ b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/MessageResult.kt @@ -7,4 +7,5 @@ import com.pubnub.api.JsonElement */ interface MessageResult : PubSubResult { val message: JsonElement + val customMessageType: String? } diff --git a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/PNMessageResult.kt b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/PNMessageResult.kt index 3a42c0c2f..cc216ff5f 100644 --- a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/PNMessageResult.kt +++ b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/PNMessageResult.kt @@ -9,6 +9,7 @@ import com.pubnub.api.PubNubError class PNMessageResult( private val basePubSubResult: PubSubResult, override val message: JsonElement, + override val customMessageType: String? = null, val error: PubNubError? = null, ) : MessageResult, PubSubResult by basePubSubResult { override fun equals(other: Any?): Boolean { diff --git a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/PNSignalResult.kt b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/PNSignalResult.kt index 90362ad42..b878489de 100644 --- a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/PNSignalResult.kt +++ b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/PNSignalResult.kt @@ -8,4 +8,5 @@ import com.pubnub.api.JsonElement data class PNSignalResult( private val basePubSubResult: PubSubResult, override val message: JsonElement, + override val customMessageType: String? = null, ) : MessageResult, PubSubResult by basePubSubResult diff --git a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/files/PNFileEventResult.kt b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/files/PNFileEventResult.kt index 0af2c12a7..2e99a11e3 100644 --- a/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/files/PNFileEventResult.kt +++ b/pubnub-kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/models/consumer/pubsub/files/PNFileEventResult.kt @@ -15,6 +15,7 @@ class PNFileEventResult( val jsonMessage: JsonElement, override val subscription: String? = null, val error: PubNubError? = null, + val customMessageType: String? = null ) : PNEvent { override fun equals(other: Any?): Boolean { if (this === other) { @@ -44,6 +45,9 @@ class PNFileEventResult( if (file != other.file) { return false } + if (customMessageType != other.customMessageType) { + return false + } if (jsonMessage != other.jsonMessage) { return false } @@ -66,6 +70,7 @@ class PNFileEventResult( result = 31 * result + jsonMessage.hashCode() result = 31 * result + (subscription?.hashCode() ?: 0) result = 31 * result + (error?.hashCode() ?: 0) + result = 31 * result + (customMessageType?.hashCode() ?: 0) return result } } diff --git a/pubnub-kotlin/pubnub-kotlin-core-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/pubsub/Signal.kt b/pubnub-kotlin/pubnub-kotlin-core-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/pubsub/Signal.kt index 688958801..85db5d5e4 100644 --- a/pubnub-kotlin/pubnub-kotlin-core-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/pubsub/Signal.kt +++ b/pubnub-kotlin/pubnub-kotlin-core-api/src/jvmMain/kotlin/com/pubnub/api/endpoints/pubsub/Signal.kt @@ -9,4 +9,5 @@ import com.pubnub.api.models.consumer.PNPublishResult actual interface Signal : Endpoint { val channel: String val message: Any + val customMessageType: String? } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/config/ktlint/baseline.xml b/pubnub-kotlin/pubnub-kotlin-impl/config/ktlint/baseline.xml index 27851b1e1..22344ac9b 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/config/ktlint/baseline.xml +++ b/pubnub-kotlin/pubnub-kotlin-impl/config/ktlint/baseline.xml @@ -1,5 +1,15 @@ + + + + + + + + + + @@ -65,6 +75,9 @@ + + + @@ -111,6 +124,12 @@ + + + + + + @@ -120,14 +139,8 @@ - - - - - - - - + + diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/FilesIntegrationTest.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/FilesIntegrationTest.kt index 93326fad3..49be08ec4 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/FilesIntegrationTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/FilesIntegrationTest.kt @@ -9,11 +9,13 @@ import com.pubnub.api.models.consumer.files.PNFileUploadResult import com.pubnub.api.models.consumer.pubsub.files.PNFileEventResult import com.pubnub.test.CommonUtils.randomChannel import org.junit.Assert +import org.junit.Assert.assertEquals import org.junit.Test import java.io.ByteArrayInputStream import java.io.InputStream import java.nio.charset.StandardCharsets import java.util.Scanner +import java.util.concurrent.CompletableFuture import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicReference @@ -38,14 +40,25 @@ class FilesIntegrationTest : BaseIntegrationTest() { val message = "This is message" val meta = "This is meta" val content = "This is content" + val customMessageType = "MyCustom-Type_" + val receiveFileEventFuture = CompletableFuture() val channel = pubnub.channel(channelName) + + val subscription = channel.subscription() + subscription.onFile = { fileEvent: PNFileEventResult -> + receiveFileEventFuture.complete(fileEvent) + } + subscription.subscribe() + Thread.sleep(1000) + ByteArrayInputStream(content.toByteArray(StandardCharsets.UTF_8)).use { channel.sendFile( fileName = fileName, inputStream = it, message = message, meta = meta, + customMessageType = customMessageType ).async { result -> result.onSuccess { sendFileResultReference.set(it) @@ -59,6 +72,9 @@ class FilesIntegrationTest : BaseIntegrationTest() { return } + val fileEvent = receiveFileEventFuture.get(10, TimeUnit.SECONDS) + assertEquals(customMessageType, fileEvent.customMessageType) + val sendFileResult = sendFileResultReference.get() if (sendFileResult == null) { Assert.fail() @@ -77,6 +93,7 @@ class FilesIntegrationTest : BaseIntegrationTest() { val content = "This is content" val message = "This is message" val meta = "This is meta" + val customMessageType = "MyCustomType" val fileName = "fileName$channel.txt" val fileSent = CountDownLatch(1) pubnub.subscribe(channels = listOf(channel)) @@ -88,6 +105,7 @@ class FilesIntegrationTest : BaseIntegrationTest() { inputStream = it, message = message, meta = meta, + customMessageType = customMessageType ).async { result -> result.onSuccess { sendResultReference.set(it) @@ -123,6 +141,7 @@ class FilesIntegrationTest : BaseIntegrationTest() { val message = "This is message" val meta = "This is meta" val fileName = "fileName$channel.txt" + val customMessageType = "myCustomType" val connectedLatch = CountDownLatch(1) val fileEventReceived = CountDownLatch(1) pubnub.addListener( @@ -140,7 +159,7 @@ class FilesIntegrationTest : BaseIntegrationTest() { pubnub: PubNub, result: PNFileEventResult, ) { - if (result.file.name == fileName) { + if (result.file.name == fileName && result.customMessageType == customMessageType) { fileEventReceived.countDown() } } @@ -156,6 +175,7 @@ class FilesIntegrationTest : BaseIntegrationTest() { inputStream = it, message = message, meta = meta, + customMessageType = customMessageType ).sync() } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/HistoryIntegrationTest.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/HistoryIntegrationTest.kt index 8439ce8be..f89d045af 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/HistoryIntegrationTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/HistoryIntegrationTest.kt @@ -13,6 +13,7 @@ import com.pubnub.api.models.consumer.message_actions.PNMessageAction import com.pubnub.test.CommonUtils import com.pubnub.test.CommonUtils.emoji import com.pubnub.test.CommonUtils.randomChannel +import com.pubnub.test.CommonUtils.randomNumeric import org.awaitility.kotlin.await import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.aMapWithSize @@ -94,8 +95,8 @@ class HistoryIntegrationTest : BaseIntegrationTest() { historyResult = pubNubWithCrypto.history( channel = channel, - includeMeta = true, includeTimetoken = true, + includeMeta = true, ).sync() assertNotNull(historyResult) @@ -122,6 +123,7 @@ class HistoryIntegrationTest : BaseIntegrationTest() { val expectedMessage = CommonUtils.generatePayload() val expectedAction = "reaction" val expectedActionValue = emoji() + val expectedCustomMessageType = "pncustom-_Type_${randomNumeric()}" val result = pubnub.publish( @@ -130,6 +132,7 @@ class HistoryIntegrationTest : BaseIntegrationTest() { meta = expectedMeta, shouldStore = true, ttl = 60, + customMessageType = expectedCustomMessageType ).sync() val actionResult = @@ -157,6 +160,7 @@ class HistoryIntegrationTest : BaseIntegrationTest() { includeMessageType = true, includeUUID = true, channels = listOf(channel), + includeCustomMessageType = true ).sync() assertNotNull(fetchResult) assertThat(fetchResult?.channels, aMapWithSize(not(0))) @@ -182,6 +186,7 @@ class HistoryIntegrationTest : BaseIntegrationTest() { ), ), ), + customMessageType = expectedCustomMessageType ) val expectedChannelsResponse: Map> = @@ -202,6 +207,7 @@ class HistoryIntegrationTest : BaseIntegrationTest() { includeMessageType = true, includeUUID = true, channels = listOf(channel), + includeCustomMessageType = true ).sync() assertEquals( @@ -226,6 +232,7 @@ class HistoryIntegrationTest : BaseIntegrationTest() { val channel = randomChannel() val expectedMeta = JsonObject().also { it.add("thisIsMeta", JsonPrimitive("thisIsMetaValue")) } val expectedMessage = CommonUtils.generatePayload() + val expectedCustomMessageType = "customType_${randomNumeric()}" val result = pubnub.publish( @@ -234,6 +241,7 @@ class HistoryIntegrationTest : BaseIntegrationTest() { meta = expectedMeta, shouldStore = true, ttl = 60, + customMessageType = expectedCustomMessageType ).sync() var fetchResult: PNFetchMessagesResult? = null @@ -250,6 +258,7 @@ class HistoryIntegrationTest : BaseIntegrationTest() { includeMessageType = true, includeUUID = true, channels = listOf(channel), + includeCustomMessageType = true ).sync() assertNotNull(fetchResult) assertThat(fetchResult?.channels, aMapWithSize(not(0))) @@ -264,6 +273,7 @@ class HistoryIntegrationTest : BaseIntegrationTest() { messageType = HistoryMessageType.Message, actions = emptyMap>>(), error = PubNubError.CRYPTO_IS_CONFIGURED_BUT_MESSAGE_IS_NOT_ENCRYPTED, + customMessageType = expectedCustomMessageType ) val expectedChannelsResponse: Map> = diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/MessageActionsIntegrationTest.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/MessageActionsIntegrationTest.kt index 21dfe7fb0..ba0bb48c5 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/MessageActionsIntegrationTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/MessageActionsIntegrationTest.kt @@ -380,6 +380,7 @@ class MessageActionsIntegrationTest : BaseIntegrationTest() { val fetchMessagesResultWithActions: PNFetchMessagesResult = pubnub.fetchMessages( channels = Collections.singletonList(expectedChannel), + page = PNBoundedPage(limit = 25), includeMeta = true, includeMessageActions = true, ).sync() @@ -423,6 +424,7 @@ class MessageActionsIntegrationTest : BaseIntegrationTest() { val fetchMessagesResultNoActions: PNFetchMessagesResult = pubnub.fetchMessages( channels = listOf(expectedChannel), + page = PNBoundedPage(limit = 25), ).sync() fetchMessagesResultNoActions.channels.forEach { (_: String?, pnFetchMessageItems: List) -> pnFetchMessageItems.forEach( diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/PublishFileMessageIntegrationTests.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/PublishFileMessageIntegrationTests.kt new file mode 100644 index 000000000..1cc5800ad --- /dev/null +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/PublishFileMessageIntegrationTests.kt @@ -0,0 +1,22 @@ +package com.pubnub.api.integration + +import com.pubnub.api.models.consumer.files.PNPublishFileMessageResult +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Test + +class PublishFileMessageIntegrationTests : BaseIntegrationTest() { + @Test + fun can_publishFileMessage() { + val publishFileMessageResult: PNPublishFileMessageResult = pubnub.publishFileMessage( + channel = "whatever", + fileName = "whatever", + fileId = "whatever", + message = "whatever", + meta = "whatever", + ttl = 1, + shouldStore = true, + customMessageType = "myCustom-Messag_e" + ).sync() + assertNotNull(publishFileMessageResult.timetoken) + } +} diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/PublishIntegrationTests.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/PublishIntegrationTests.kt index b664a0e61..30257b662 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/PublishIntegrationTests.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/PublishIntegrationTests.kt @@ -8,10 +8,13 @@ import com.pubnub.api.callbacks.SubscribeCallback import com.pubnub.api.crypto.CryptoModule import com.pubnub.api.enums.PNStatusCategory import com.pubnub.api.models.consumer.PNBoundedPage +import com.pubnub.api.models.consumer.PNPublishResult import com.pubnub.api.models.consumer.PNStatus import com.pubnub.api.models.consumer.pubsub.PNMessageResult import com.pubnub.api.v2.PNConfigurationOverride import com.pubnub.api.v2.callbacks.EventListener +import com.pubnub.api.v2.callbacks.Result +import com.pubnub.api.v2.callbacks.StatusListener import com.pubnub.api.v2.callbacks.getOrThrow import com.pubnub.api.v2.entities.Channel import com.pubnub.api.v2.subscriptions.SubscriptionCursor @@ -39,6 +42,8 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Test +import java.util.concurrent.CompletableFuture +import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicInteger @@ -57,6 +62,7 @@ class PublishIntegrationTests : BaseIntegrationTest() { pubnub.publish( channel = expectedChannel, message = generatePayload(), + customMessageType = "myType" ).await { result -> assertFalse(result.isFailure) assertTrue(result.getOrThrow().timetoken > 0) @@ -111,8 +117,8 @@ class PublishIntegrationTests : BaseIntegrationTest() { } pubnub.history( - count = 1, channel = expectedChannel, + count = 1, ).asyncRetry { result -> assertFalse(result.isFailure) assertEquals(0, result.getOrThrow().messages.size) @@ -365,7 +371,8 @@ class PublishIntegrationTests : BaseIntegrationTest() { override fun status( pubnub: PubNub, pnStatus: PNStatus, - ) {} + ) { + } override fun message( pubnub: PubNub, @@ -397,7 +404,8 @@ class PublishIntegrationTests : BaseIntegrationTest() { override fun status( pubnub: PubNub, pnStatus: PNStatus, - ) {} + ) { + } override fun message( pubnub: PubNub, @@ -487,7 +495,8 @@ class PublishIntegrationTests : BaseIntegrationTest() { override fun status( pubnub: PubNub, pnStatus: PNStatus, - ) {} + ) { + } override fun message( pubnub: PubNub, @@ -523,7 +532,8 @@ class PublishIntegrationTests : BaseIntegrationTest() { override fun status( pubnub: PubNub, pnStatus: PNStatus, - ) {} + ) { + } override fun message( pubnub: PubNub, @@ -566,7 +576,8 @@ class PublishIntegrationTests : BaseIntegrationTest() { override fun status( pubnub: PubNub, pnStatus: PNStatus, - ) {} + ) { + } override fun message( pubnub: PubNub, @@ -831,7 +842,8 @@ class PublishIntegrationTests : BaseIntegrationTest() { channel.publish(message = "My message").sync() channel.signal(message = "My signal").sync() - channel.fire(message = "My Fire").sync() // fire will not be delivered to listener only to PubNub Functions Event Handlers + channel.fire(message = "My Fire") + .sync() // fire will not be delivered to listener only to PubNub Functions Event Handlers Awaitility.await() .atMost(DEFAULT_LISTEN_DURATION.toLong(), TimeUnit.SECONDS) @@ -840,4 +852,39 @@ class PublishIntegrationTests : BaseIntegrationTest() { .atMost(DEFAULT_LISTEN_DURATION.toLong(), TimeUnit.SECONDS) .untilAtomic(signalReceived, Matchers.equalTo(true)) } + + @Test + fun testPublishMessageWithCustomMessageType() { + val expectedChannelName = randomChannel() + val channel = pubnub.channel(expectedChannelName) + val expectedCustomMessageType = "thisIsType" + val connected = CountDownLatch(1) + val receivedMessageFuture = CompletableFuture() + + val subscription = channel.subscription() + subscription.onMessage = { pnMessageResult: PNMessageResult -> + receivedMessageFuture.complete(pnMessageResult) + } + pubnub.addListener(object : StatusListener { + override fun status(pubnub: PubNub, status: PNStatus) { + if (status.category == PNStatusCategory.PNConnectedCategory && + status.affectedChannels.contains(expectedChannelName) + ) { + connected.countDown() + } + } + }) + + subscription.subscribe() + assertTrue(connected.await(10, TimeUnit.SECONDS)) + + channel.publish( + message = generatePayload(), + customMessageType = expectedCustomMessageType + ).sync() + + val message: PNMessageResult = receivedMessageFuture.get(10, TimeUnit.SECONDS) + + assertEquals(expectedCustomMessageType, message.customMessageType) + } } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/SignalIntegrationTests.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/SignalIntegrationTests.kt index c5672adfc..a2dcb8886 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/SignalIntegrationTests.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/integrationTest/kotlin/com/pubnub/api/integration/SignalIntegrationTests.kt @@ -16,17 +16,20 @@ import org.junit.Test class SignalIntegrationTests : BaseIntegrationTest() { lateinit var expectedChannel: String lateinit var expectedPayload: String + lateinit var expectedCustomMessageType: String override fun onBefore() { expectedChannel = randomChannel() expectedPayload = randomValue(5) + expectedCustomMessageType = randomValue(5) } @Test fun testPublishSignalMessageAsync() { pubnub.signal( - message = expectedPayload, channel = expectedChannel, + message = expectedPayload, + customMessageType = expectedCustomMessageType, ).await { result -> assertFalse(result.isFailure) assertTrue(result.getOrThrow().timetoken > 0) @@ -36,8 +39,9 @@ class SignalIntegrationTests : BaseIntegrationTest() { @Test fun testPublishSignalMessageSync() { pubnub.signal( - message = expectedPayload, channel = expectedChannel, + message = expectedPayload, + customMessageType = expectedCustomMessageType, ).sync() } @@ -47,13 +51,15 @@ class SignalIntegrationTests : BaseIntegrationTest() { pubnub.test { subscribe(expectedChannel) observerClient.signal( - message = expectedPayload, channel = expectedChannel, + message = expectedPayload, + customMessageType = expectedCustomMessageType, ).sync() val pnSignalResult = nextEvent() assertEquals(observerClient.configuration.userId.value, pnSignalResult.publisher) assertEquals(expectedChannel, pnSignalResult.channel) assertEquals(expectedPayload, Gson().fromJson(pnSignalResult.message, String::class.java)) + assertEquals(expectedCustomMessageType, pnSignalResult.customMessageType) } } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/PubNubImpl.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/PubNubImpl.kt index b3dddcc4f..7707eae24 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/PubNubImpl.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/PubNubImpl.kt @@ -338,6 +338,7 @@ open class PubNubImpl( usePost: Boolean, replicate: Boolean, ttl: Int?, + customMessageType: String?, ): Publish = PublishEndpoint( pubnub = this, @@ -348,6 +349,7 @@ open class PubNubImpl( usePost = usePost, replicate = replicate, ttl = ttl, + customMessageType = customMessageType ) override fun fire(channel: String, message: Any, meta: Any?, usePost: Boolean): Publish = publish( @@ -374,7 +376,8 @@ open class PubNubImpl( override fun signal( channel: String, message: Any, - ): Signal = SignalEndpoint(pubnub = this, channel = channel, message = message) + customMessageType: String?, + ): Signal = SignalEndpoint(pubnub = this, channel = channel, message = message, customMessageType = customMessageType) override fun addPushNotificationsOnChannels( pushType: PNPushType, @@ -468,6 +471,7 @@ open class PubNubImpl( includeMeta: Boolean, includeMessageActions: Boolean, includeMessageType: Boolean, + includeCustomMessageType: Boolean ): FetchMessages { return FetchMessagesEndpoint( pubnub = this, @@ -477,6 +481,7 @@ open class PubNubImpl( includeMeta = includeMeta, includeMessageActions = includeMessageActions, includeMessageType = includeMessageType, + includeCustomMessageType = includeCustomMessageType ) } @@ -994,13 +999,15 @@ open class PubNubImpl( includeMeta: Boolean, includeMessageActions: Boolean, includeMessageType: Boolean, + includeCustomMessageType: Boolean ): FetchMessages = fetchMessages( channels = channels, page = PNBoundedPage(start = start, end = end, limit = maximumPerChannel), includeUUID = true, includeMeta = includeMeta, includeMessageActions = includeMessageActions, - includeMessageType = includeMessageType + includeMessageType = includeMessageType, + includeCustomMessageType = includeCustomMessageType ) @Deprecated( @@ -1241,6 +1248,7 @@ open class PubNubImpl( ttl: Int?, shouldStore: Boolean?, cipherKey: String?, + customMessageType: String?, ): SendFile { val cryptoModule = if (cipherKey != null) { @@ -1256,6 +1264,7 @@ open class PubNubImpl( meta = meta, ttl = ttl, shouldStore = shouldStore, + customMessageType = customMessageType, executorService = retrofitManager.getTransactionClientExecutorService() ?: Executors.newSingleThreadExecutor(), @@ -1335,6 +1344,7 @@ open class PubNubImpl( meta: Any?, ttl: Int?, shouldStore: Boolean?, + customMessageType: String?, ): PublishFileMessage { return PublishFileMessageEndpoint( pubNub = this, @@ -1345,6 +1355,7 @@ open class PubNubImpl( meta = meta, ttl = ttl, shouldStore = shouldStore, + customMessageType = customMessageType ) } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/FetchMessagesEndpoint.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/FetchMessagesEndpoint.kt index 9681b7371..4dde3cd41 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/FetchMessagesEndpoint.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/FetchMessagesEndpoint.kt @@ -15,6 +15,7 @@ import com.pubnub.internal.extension.limit import com.pubnub.internal.extension.nonPositiveToNull import com.pubnub.internal.extension.tryDecryptMessage import com.pubnub.internal.models.server.FetchMessagesEnvelope +import com.pubnub.internal.models.server.history.ServerFetchMessageItem import com.pubnub.internal.toCsv import retrofit2.Call import retrofit2.Response @@ -27,10 +28,11 @@ class FetchMessagesEndpoint internal constructor( pubnub: PubNubImpl, override val channels: List, override val page: PNBoundedPage, - override val includeUUID: Boolean, - override val includeMeta: Boolean, - override val includeMessageActions: Boolean, - override val includeMessageType: Boolean, + override val includeUUID: Boolean = false, + override val includeMeta: Boolean = false, + override val includeMessageActions: Boolean = false, + override val includeMessageType: Boolean = false, + override val includeCustomMessageType: Boolean = false ) : EndpointCore(pubnub), FetchMessages { internal companion object { private const val SINGLE_CHANNEL_DEFAULT_MESSAGES = 100 @@ -40,6 +42,8 @@ class FetchMessagesEndpoint internal constructor( private const val DEFAULT_MESSAGES_WITH_ACTIONS = 25 private const val MAX_MESSAGES_WITH_ACTIONS = 25 internal const val INCLUDE_MESSAGE_TYPE_QUERY_PARAM = "include_message_type" + private const val INCLUDE_CUSTOM_MESSAGE_TYPE = "include_custom_message_type" + internal fun effectiveMax( maximumPerChannel: Int?, @@ -95,7 +99,7 @@ class FetchMessagesEndpoint internal constructor( val body = input.body()!! val channelsMap = body.channels.mapValues { (_, value) -> - value.map { serverMessageItem -> + value.map { serverMessageItem: ServerFetchMessageItem -> val (newMessage, error) = serverMessageItem.message.tryDecryptMessage( configuration.cryptoModule, @@ -119,6 +123,7 @@ class FetchMessagesEndpoint internal constructor( } else { null }, + customMessageType = serverMessageItem.customMessageType, error = error, ) } @@ -147,5 +152,6 @@ class FetchMessagesEndpoint internal constructor( if (includeMeta) { queryParams["include_meta"] = "true" } + queryParams[INCLUDE_CUSTOM_MESSAGE_TYPE] = includeCustomMessageType.toString() } } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/files/PublishFileMessageEndpoint.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/files/PublishFileMessageEndpoint.kt index db7c45f67..46d30e764 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/files/PublishFileMessageEndpoint.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/files/PublishFileMessageEndpoint.kt @@ -11,6 +11,7 @@ import com.pubnub.api.retry.RetryableEndpointGroup import com.pubnub.internal.EndpointCore import com.pubnub.internal.PubNubImpl import com.pubnub.internal.crypto.encryptString +import com.pubnub.internal.endpoints.pubsub.PublishEndpoint.Companion.CUSTOM_MESSAGE_TYPE_QUERY_PARAM import com.pubnub.internal.extension.numericString import com.pubnub.internal.extension.quoted import com.pubnub.internal.models.server.files.FileUploadNotification @@ -28,6 +29,7 @@ open class PublishFileMessageEndpoint( private val meta: Any? = null, private val ttl: Int? = null, private val shouldStore: Boolean? = null, + private val customMessageType: String? = null, pubNub: PubNubImpl, ) : EndpointCore, PNPublishFileMessageResult>(pubNub), PublishFileMessage { private val pnFile = PNBaseFile(fileId, fileName) @@ -49,6 +51,7 @@ open class PublishFileMessageEndpoint( } shouldStore?.numericString?.let { queryParams["store"] = it } ttl?.let { queryParams["ttl"] = it.toString() } + customMessageType?.let { queryParams[CUSTOM_MESSAGE_TYPE_QUERY_PARAM] = it } return retrofitManager.filesService.notifyAboutFileUpload( configuration.publishKey, @@ -88,6 +91,7 @@ open class PublishFileMessageEndpoint( meta: Any? = null, ttl: Int? = null, shouldStore: Boolean? = null, + customMessageType: String? = null ): ExtendedRemoteAction { return PublishFileMessageEndpoint( channel = channel, @@ -97,6 +101,7 @@ open class PublishFileMessageEndpoint( meta = meta, ttl = ttl, shouldStore = shouldStore, + customMessageType = customMessageType, pubNub = pubNub, ) } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/files/SendFileEndpoint.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/files/SendFileEndpoint.kt index 6bc5a2c05..b6e0c0e21 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/files/SendFileEndpoint.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/files/SendFileEndpoint.kt @@ -33,6 +33,7 @@ class SendFileEndpoint internal constructor( private val meta: Any? = null, private val ttl: Int? = null, private val shouldStore: Boolean? = null, + private val customMessageType: String? = null, private val fileMessagePublishRetryLimit: Int, private val executorService: ExecutorService, generateUploadUrlFactory: GenerateUploadUrlEndpoint.Factory, @@ -106,6 +107,7 @@ class SendFileEndpoint internal constructor( meta = meta, ttl = ttl, shouldStore = shouldStore, + customMessageType = customMessageType, ), fileMessagePublishRetryLimit, executorService, diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/pubsub/PublishEndpoint.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/pubsub/PublishEndpoint.kt index c1a6a9ab3..f8cc1db44 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/pubsub/PublishEndpoint.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/pubsub/PublishEndpoint.kt @@ -27,7 +27,12 @@ class PublishEndpoint internal constructor( override val usePost: Boolean = false, override val replicate: Boolean = true, override val ttl: Int? = null, + override val customMessageType: String? = null ) : EndpointCore, PNPublishResult>(pubnub), Publish { + companion object { + internal const val CUSTOM_MESSAGE_TYPE_QUERY_PARAM = "custom_message_type" + } + override fun validateParams() { super.validateParams() if (channel.isBlank()) { @@ -83,16 +88,13 @@ class PublishEndpoint internal constructor( * @param queryParams hashMap to add parameters */ private fun addQueryParams(queryParams: MutableMap) { - meta?.run { queryParams["meta"] = pubnub.mapper.toJson(this) } - - shouldStore?.run { queryParams["store"] = this.numericString } - - ttl?.run { queryParams["ttl"] = this.toString() } - + meta?.let { queryParams["meta"] = pubnub.mapper.toJson(it) } + shouldStore?.let { queryParams["store"] = it.numericString } + ttl?.let { queryParams["ttl"] = it.toString() } if (!replicate) { queryParams["norep"] = true.valueString } - + customMessageType?.let { queryParams[CUSTOM_MESSAGE_TYPE_QUERY_PARAM] = it } queryParams["seqn"] = pubnub.publishSequenceManager.nextSequence().toString() } // endregion diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/pubsub/SignalEndpoint.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/pubsub/SignalEndpoint.kt index 823c49b84..d65d5a6ec 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/pubsub/SignalEndpoint.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/endpoints/pubsub/SignalEndpoint.kt @@ -18,7 +18,12 @@ class SignalEndpoint internal constructor( pubnub: PubNubImpl, override val channel: String, override val message: Any, + override val customMessageType: String? = null ) : EndpointCore, PNPublishResult>(pubnub), Signal { + companion object { + private const val CUSTOM_MESSAGE_TYPE_QUERY_PARAM = "custom_message_type" + } + override fun validateParams() { super.validateParams() if (channel.isBlank()) { @@ -29,6 +34,10 @@ class SignalEndpoint internal constructor( override fun getAffectedChannels() = listOf(channel) override fun doWork(queryParams: HashMap): Call> { + customMessageType?.let { customMessageTypeNotNull -> + queryParams[CUSTOM_MESSAGE_TYPE_QUERY_PARAM] = customMessageTypeNotNull + } + return retrofitManager.signalService.signal( pubKey = configuration.publishKey, subKey = configuration.subscribeKey, diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/models/server/SubscribeMessage.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/models/server/SubscribeMessage.kt index 8caa8e381..037094a4a 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/models/server/SubscribeMessage.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/models/server/SubscribeMessage.kt @@ -5,7 +5,7 @@ import com.google.gson.annotations.SerializedName import com.pubnub.internal.workers.SubscribeMessageProcessor.Companion.TYPE_FILES import com.pubnub.internal.workers.SubscribeMessageProcessor.Companion.TYPE_MESSAGE -class SubscribeMessage( +data class SubscribeMessage( @SerializedName("a") internal val shard: String?, @SerializedName("b") @@ -28,6 +28,8 @@ class SubscribeMessage( internal val userMetadata: JsonElement?, @SerializedName("e") internal val type: Int?, + @SerializedName("cmt") + internal val customMessageType: String?, ) { fun supportsEncryption() = type in arrayOf(null, TYPE_MESSAGE, TYPE_FILES) } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/models/server/history/ServerFetchMessageItem.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/models/server/history/ServerFetchMessageItem.kt index 7cd8468d0..7811bd505 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/models/server/history/ServerFetchMessageItem.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/models/server/history/ServerFetchMessageItem.kt @@ -12,4 +12,6 @@ data class ServerFetchMessageItem( val actions: Map>>? = null, @SerializedName("message_type") val messageType: Int?, + @SerializedName("custom_message_type") + val customMessageType: String? ) diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/v2/entities/ChannelImpl.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/v2/entities/ChannelImpl.kt index b1889522c..8e4258a0a 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/v2/entities/ChannelImpl.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/v2/entities/ChannelImpl.kt @@ -77,13 +77,14 @@ open class ChannelImpl(val pubNubImpl: PubNubImpl, val channelName: ChannelName) shouldStore: Boolean, usePost: Boolean, replicate: Boolean, - ttl: Int? + ttl: Int?, + customMessageType: String? ): Publish { - return pubNubImpl.publish(channelName.id, message, meta, shouldStore, usePost, replicate, ttl) + return pubNubImpl.publish(channelName.id, message, meta, shouldStore, usePost, replicate, ttl, customMessageType) } - override fun signal(message: Any): Signal { - return pubNubImpl.signal(channelName.id, message) + override fun signal(message: Any, customMessageType: String?): Signal { + return pubNubImpl.signal(channelName.id, message, customMessageType) } override fun fire(message: Any, meta: Any?, usePost: Boolean, ttl: Int?): Publish { @@ -97,9 +98,10 @@ open class ChannelImpl(val pubNubImpl: PubNubImpl, val channelName: ChannelName) meta: Any?, ttl: Int?, shouldStore: Boolean?, - cipherKey: String? + cipherKey: String?, + customMessageType: String? ): SendFile { - return pubNubImpl.sendFile(channelName.id, fileName, inputStream, message, meta, ttl, shouldStore, cipherKey) + return pubNubImpl.sendFile(channelName.id, fileName, inputStream, message, meta, ttl, shouldStore, cipherKey, customMessageType) } override fun deleteFile( diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/workers/SubscribeMessageProcessor.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/workers/SubscribeMessageProcessor.kt index b39d08fab..dd3021eef 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/workers/SubscribeMessageProcessor.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/main/kotlin/com/pubnub/internal/workers/SubscribeMessageProcessor.kt @@ -95,6 +95,7 @@ internal class SubscribeMessageProcessor( if (extractedMessage == null) { log.debug("unable to parse payload on #processIncomingMessages") } + val customMessageType = message.customMessageType val result = BasePubSubResult( @@ -107,15 +108,15 @@ internal class SubscribeMessageProcessor( return when (message.type) { null -> { - PNMessageResult(result, extractedMessage!!, error) + PNMessageResult(result, extractedMessage!!, customMessageType, error) } TYPE_MESSAGE -> { - PNMessageResult(result, extractedMessage!!, error) + PNMessageResult(result, extractedMessage!!, customMessageType, error) } TYPE_SIGNAL -> { - PNSignalResult(result, extractedMessage!!) + PNSignalResult(result, extractedMessage!!, customMessageType) } TYPE_OBJECT -> { @@ -167,6 +168,7 @@ internal class SubscribeMessageProcessor( fileUploadNotification.message?.let { pubnub.mapper.toJsonTree(it) } ?: JsonNull.INSTANCE, error = error, + customMessageType = customMessageType, ) } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/PubNubImplTest.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/PubNubImplTest.kt index 2e295ffaa..1a7897f19 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/PubNubImplTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/PubNubImplTest.kt @@ -56,7 +56,7 @@ class PubNubImplTest : BaseTest() { fun getVersionAndTimeStamp() { val version = PubNubImpl.SDK_VERSION val timeStamp = PubNubImpl.timestamp() - assertEquals("10.1.0", version) + assertEquals("10.2.0", version) assertTrue(timeStamp > 0) } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/files/SendFileTest.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/files/SendFileTest.kt index 7bf735c51..9156c261d 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/files/SendFileTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/files/SendFileTest.kt @@ -49,7 +49,7 @@ class SendFileTest : TestsWithFiles { every { sendFileToS3Factory.create(any(), any(), any()) } returns TestRemoteAction.successful(Unit) val publishFileMessage: PublishFileMessageEndpoint = AlwaysSuccessfulPublishFileMessage.create(publishFileMessageResult, getPubNubMock()) - every { publishFileMessageFactory.create(any(), any(), any()) } returns publishFileMessage + every { publishFileMessageFactory.create(any(), any(), any(), any(), any(), any(), any(), any()) } returns publishFileMessage // when val result: PNFileUploadResult? = @@ -76,7 +76,7 @@ class SendFileTest : TestsWithFiles { every { sendFileToS3Factory.create(any(), any(), any()) } returns TestRemoteAction.successful(Unit) val publishFileMessage: PublishFileMessageEndpoint = AlwaysSuccessfulPublishFileMessage.create(publishFileMessageResult, getPubNubMock()) - every { publishFileMessageFactory.create(any(), any(), any()) } returns publishFileMessage + every { publishFileMessageFactory.create(any(), any(), any(), any(), any(), any(), any(), any()) } returns publishFileMessage inputStream().use { inputStream -> sendFile( channel, @@ -114,7 +114,7 @@ class SendFileTest : TestsWithFiles { getPubNubMock(), ), ) - every { publishFileMessageFactory.create(any(), any(), any()) } returns publishFileMessage + every { publishFileMessageFactory.create(any(), any(), any(), any(), any(), any(), any(), any()) } returns publishFileMessage inputStream().use { inputStream -> sendFile( channel, @@ -155,7 +155,7 @@ class SendFileTest : TestsWithFiles { getPubNubMock(), ), ) - every { publishFileMessageFactory.create(any(), any(), any()) } returns publishFileMessage + every { publishFileMessageFactory.create(any(), any(), any(), any(), any(), any(), any(), any()) } returns publishFileMessage // when val result: PNFileUploadResult? = @@ -193,6 +193,7 @@ class SendFileTest : TestsWithFiles { return SendFileEndpoint( channel = channel, fileName = fileName, + customMessageType = "myCustomMessageType01a", inputStream = inputStream, generateUploadUrlFactory = generateUploadUrlFactory, publishFileMessageFactory = publishFileMessageFactory, @@ -263,6 +264,7 @@ class SendFileTest : TestsWithFiles { channel = "channel", fileName = "fileName", fileId = "fileId", + customMessageType = "myCustomType", pubNub = pubNub, ) { @Throws(PubNubException::class) diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/history/FetchMessagesCoreEndpointTest.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/history/FetchMessagesCoreEndpointTest.kt index c3b5f10cb..2294fac28 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/history/FetchMessagesCoreEndpointTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/history/FetchMessagesCoreEndpointTest.kt @@ -7,6 +7,8 @@ import com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor import com.github.tomakehurst.wiremock.client.WireMock.stubFor import com.github.tomakehurst.wiremock.client.WireMock.urlMatching import com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo +import com.github.tomakehurst.wiremock.client.WireMock.urlPathMatching +import com.github.tomakehurst.wiremock.matching.EqualToPattern import com.pubnub.api.crypto.CryptoModule import com.pubnub.api.legacy.BaseTest import com.pubnub.api.models.consumer.PNBoundedPage @@ -452,6 +454,7 @@ class FetchMessagesCoreEndpointTest : BaseTest() { pubnub.fetchMessages( channels = listOf(channel), + page = PNBoundedPage(limit = 25), includeMessageType = true, ).sync() @@ -477,6 +480,7 @@ class FetchMessagesCoreEndpointTest : BaseTest() { pubnub.fetchMessages( channels = listOf(channel), + page = PNBoundedPage(limit = 25), ).sync() val requests = findAll(getRequestedFor(urlMatching("/.*"))) @@ -502,6 +506,7 @@ class FetchMessagesCoreEndpointTest : BaseTest() { val response = pubnub.fetchMessages( channels = listOf(channel), + page = PNBoundedPage(limit = 25), includeMessageType = true, ).sync() @@ -511,6 +516,39 @@ class FetchMessagesCoreEndpointTest : BaseTest() { ) } + @Test + fun testCustomMessageTypesAreProperlyDeserialized() { + val customMessageType01 = "myCustomType01" + val customMessageType02 = "myCustomType02" + stubFor( + get( + urlPathMatching("/v3/history/sub-key/mySubscribeKey/channel/$channel.*") + ).withQueryParam("include_custom_message_type", EqualToPattern("true")) + .willReturn( + aResponse().withBody( + responseWithMessagesForChannelWithCustomMessageType(channel, customMessageType01, customMessageType02), + ) + ) + ) + + val response = + pubnub.fetchMessages( + channels = listOf(channel), + page = PNBoundedPage(limit = 25), + includeMessageType = true, + includeCustomMessageType = true + ).sync() + + assertThat( + response.channels.values.flatMap { items -> items.map { it.messageType } }, + contains(HistoryMessageType.Message, HistoryMessageType.File), + ) + assertThat( + response.channels.values.flatMap { items -> items.map { it.customMessageType } }, + contains(customMessageType01, customMessageType02), + ) + } + private fun randomInt(max: Int): Int = nextInt(max) + 1 private fun responseWithOneMessageForChannel(channel: String): String { @@ -554,4 +592,30 @@ class FetchMessagesCoreEndpointTest : BaseTest() { } """.trimIndent() } + + private fun responseWithMessagesForChannelWithCustomMessageType(channel: String, customMessageType01: String, customMessageType02: String): String { + return """ + { + "status": 200, + "error": false, + "error_message": "", + "channels": { + "$channel": [ + { + "message": "thisIsMessage1", + "timetoken": "14797423056306675", + "message_type": 0, + "custom_message_type":"myCustomType01" + }, + { + "message": "thisIsMessage2", + "timetoken": "14797423056306676", + "message_type": 4, + "custom_message_type":"myCustomType02" + } + ] + } + } + """.trimIndent() + } } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/history/HistoryCoreEndpointTest.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/history/HistoryCoreEndpointTest.kt index 76c843094..79d0654ae 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/history/HistoryCoreEndpointTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/history/HistoryCoreEndpointTest.kt @@ -468,10 +468,10 @@ class HistoryCoreEndpointTest : BaseTest() { val result = pubnub.history( channel = "niceChannel", - count = 5, - reverse = true, start = 1L, end = 2L, + count = 5, + reverse = true, includeTimetoken = true, ).sync() diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/pubsub/PublishTest.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/pubsub/PublishTest.kt index a7ef671cc..bdd70e204 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/pubsub/PublishTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/pubsub/PublishTest.kt @@ -11,12 +11,17 @@ import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor import com.github.tomakehurst.wiremock.client.WireMock.stubFor import com.github.tomakehurst.wiremock.client.WireMock.urlMatching import com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo +import com.pubnub.api.PubNub import com.pubnub.api.PubNubError import com.pubnub.api.PubNubException +import com.pubnub.api.callbacks.SubscribeCallback import com.pubnub.api.crypto.CryptoModule import com.pubnub.api.legacy.BaseTest +import com.pubnub.api.models.consumer.PNStatus +import com.pubnub.api.models.consumer.pubsub.PNMessageResult import com.pubnub.test.CommonUtils.assertPnException import com.pubnub.test.CommonUtils.failTest +import com.pubnub.test.listen import org.awaitility.Awaitility import org.hamcrest.core.IsEqual import org.json.JSONArray @@ -26,6 +31,7 @@ import org.junit.Assert.assertFalse import org.junit.Test import java.nio.charset.Charset import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicInteger class PublishTest : BaseTest() { @@ -59,6 +65,7 @@ class PublishTest : BaseTest() { channel = "coolChannel", message = "hi", replicate = false, + customMessageType = "myCustomType" ).sync() val requests = findAll(getRequestedFor(urlMatching("/.*"))) @@ -97,6 +104,7 @@ class PublishTest : BaseTest() { channel = "coolChannel", message = "hi", replicate = false, + customMessageType = "myCustomType" ).sync() val requests = findAll(getRequestedFor(urlMatching("/.*"))) @@ -537,4 +545,71 @@ class PublishTest : BaseTest() { assertEquals("0", requests[0].queryParameter("store").firstValue()) assertFalse(requests[0].queryParameter("ttl").isPresent) } + + @Test + fun testPublishSuccessReceive() { + val channelName = "coolChannel" + val message = "hello" + val uuid = "uuid" + val customMessageType = "myCustomMessageType" + stubFor( + get(urlMatching("/v2/subscribe/mySubscribeKey/coolChannel/0.*")) + .willReturn( + aResponse().withBody( + """ + { + "m": [ + { + "c": "$channelName", + "f": "0", + "i": "$uuid", + "d": "$message", + "e": 0, + "p": { + "t": 1000, + "r": 1 + }, + "k": "mySubscribeKey", + "b": "$channelName", + "cmt" : "$customMessageType" + } + ], + "t": { + "r": "56", + "t": 1000 + } + } + """.trimIndent(), + ), + ), + ) + + val success = AtomicBoolean() + + pubnub.addListener( + object : SubscribeCallback() { + override fun message( + pubnub: PubNub, + pnMessageResult: PNMessageResult, + ) { + assertEquals(channelName, pnMessageResult.channel) + assertEquals(message, pnMessageResult.message.asString) + assertEquals(uuid, pnMessageResult.publisher) + assertEquals(customMessageType, pnMessageResult.customMessageType) + success.set(true) + } + + override fun status( + pubnub: PubNub, + pnStatus: PNStatus, + ) {} + }, + ) + + pubnub.subscribe( + channels = listOf("coolChannel"), + ) + + success.listen() + } } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/pubsub/SignalTest.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/pubsub/SignalTest.kt index 35e34a551..650d65c2e 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/pubsub/SignalTest.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/api/legacy/endpoints/pubsub/SignalTest.kt @@ -12,10 +12,7 @@ import com.pubnub.api.PubNubException import com.pubnub.api.callbacks.SubscribeCallback import com.pubnub.api.legacy.BaseTest import com.pubnub.api.models.consumer.PNStatus -import com.pubnub.api.models.consumer.pubsub.PNMessageResult -import com.pubnub.api.models.consumer.pubsub.PNPresenceEventResult import com.pubnub.api.models.consumer.pubsub.PNSignalResult -import com.pubnub.api.models.consumer.pubsub.message_actions.PNMessageActionResult import com.pubnub.test.CommonUtils.assertPnException import com.pubnub.test.listen import okhttp3.HttpUrl.Companion.toHttpUrlOrNull @@ -102,6 +99,10 @@ class SignalTest : BaseTest() { @Test fun testSignalSuccessReceive() { + val channelName = "coolChannel" + val message = "hello" + val uuid = "uuid" + val customMessageType = "myCustomMessageType" stubFor( get(urlMatching("/v2/subscribe/mySubscribeKey/coolChannel/0.*")) .willReturn( @@ -110,17 +111,18 @@ class SignalTest : BaseTest() { { "m": [ { - "c": "coolChannel", + "c": "$channelName", "f": "0", - "i": "uuid", - "d": "hello", + "i": "$uuid", + "d": "$message", "e": 1, "p": { "t": 1000, "r": 1 }, "k": "mySubscribeKey", - "b": "coolChannel" + "b": "$channelName", + "cmt" : "$customMessageType" } ], "t": { @@ -141,9 +143,10 @@ class SignalTest : BaseTest() { pubnub: PubNub, pnSignalResult: PNSignalResult, ) { - assertEquals("coolChannel", pnSignalResult.channel) - assertEquals("hello", pnSignalResult.message.asString) - assertEquals("uuid", pnSignalResult.publisher) + assertEquals(channelName, pnSignalResult.channel) + assertEquals(message, pnSignalResult.message.asString) + assertEquals(uuid, pnSignalResult.publisher) + assertEquals(customMessageType, pnSignalResult.customMessageType) success.set(true) } @@ -151,21 +154,6 @@ class SignalTest : BaseTest() { pubnub: PubNub, pnStatus: PNStatus, ) {} - - override fun message( - pubnub: PubNub, - pnMessageResult: PNMessageResult, - ) {} - - override fun presence( - pubnub: PubNub, - pnPresenceEventResult: PNPresenceEventResult, - ) {} - - override fun messageAction( - pubnub: PubNub, - pnMessageActionResult: PNMessageActionResult, - ) {} }, ) @@ -182,6 +170,7 @@ class SignalTest : BaseTest() { pubnub.signal( channel = " ", message = UUID.randomUUID().toString(), + customMessageType = "myType" ).sync() throw RuntimeException() } catch (e: PubNubException) { diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/file/WhenSteps.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/file/WhenSteps.kt new file mode 100644 index 000000000..448493eb4 --- /dev/null +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/file/WhenSteps.kt @@ -0,0 +1,27 @@ +package com.pubnub.contract.file + +import com.pubnub.api.PubNubException +import com.pubnub.contract.state.World +import io.cucumber.java.en.When +import java.io.ByteArrayInputStream +import java.nio.charset.StandardCharsets + +class WhenSteps(private val world: World) { + @When("I send a file with {string} customMessageType") + fun i_send_file_with_customMessageType(customMessageType: String) { + try { + world.pubnub.sendFile( + channel = "whatever", + fileName = "whatever", + inputStream = ByteArrayInputStream("whatever".toByteArray(StandardCharsets.UTF_8)), + message = "whatever", + customMessageType = customMessageType + ).sync().let { + world.responseStatus = 200 + } + } catch (ex: PubNubException) { + world.responseStatus = ex.statusCode + world.pnException = ex + } + } +} diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/history/state/HistoryState.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/history/state/HistoryState.kt new file mode 100644 index 000000000..5808c8846 --- /dev/null +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/history/state/HistoryState.kt @@ -0,0 +1,7 @@ +package com.pubnub.contract.history.state + +import com.pubnub.api.models.consumer.history.PNFetchMessagesResult + +class HistoryState { + var messages: PNFetchMessagesResult? = null +} diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/history/step/WhenSteps.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/history/step/WhenSteps.kt new file mode 100644 index 000000000..52ee314a7 --- /dev/null +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/history/step/WhenSteps.kt @@ -0,0 +1,98 @@ +package com.pubnub.contract.history.step + +import com.pubnub.api.PubNubException +import com.pubnub.api.models.consumer.history.HistoryMessageType +import com.pubnub.contract.history.state.HistoryState +import com.pubnub.contract.state.World +import io.cucumber.java.en.Then +import io.cucumber.java.en.When +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.contains +import org.junit.jupiter.api.Assertions.assertEquals + +class WhenSteps(private val world: World, private val historyState: HistoryState) { + @When("I fetch message history with messageType for {string} channel") + fun i_fetch_message_history_with_messageType_for_channel(channelName: String) { + try { + historyState.messages = world.pubnub.fetchMessages( + channels = listOf(channelName), + includeMessageType = true, // default is true but to emphasize + ).sync() + world.responseStatus = 200 + } catch (ex: PubNubException) { + world.responseStatus = ex.statusCode + world.pnException = ex + } + } + + @When("I fetch message history with customMessageType for {string} channel") + fun i_fetch_message_history_with_customMessageType_for_channel(channelName: String) { + try { + historyState.messages = world.pubnub.fetchMessages( + channels = listOf(channelName), + includeCustomMessageType = true + ).sync() + world.responseStatus = 200 + } catch (ex: PubNubException) { + world.responseStatus = ex.statusCode + world.pnException = ex + } + } + + @When("I fetch message history with {string} set to {string} for {string} channel") + fun i_fetch_message_history_with_includeCustomMessageType_set_to_false_for_channel( + customMessageTypeName: String, + customMessageTypeValue: String, + channelName: String + ) { + try { + historyState.messages = world.pubnub.fetchMessages( + channels = listOf(channelName), + includeCustomMessageType = customMessageTypeValue.toBoolean() + ).sync() + world.responseStatus = 200 + } catch (ex: PubNubException) { + world.responseStatus = ex.statusCode + world.pnException = ex + } + } + + @Then("history response contains messages without customMessageType") + fun history_response_contains_messages_without_customMessageType() { + val messagesWithoutCustomMessageType = + historyState.messages!!.channels["some-channel"]?.filter { message -> message.customMessageType == null } + ?.toList()!! + assertEquals(2, messagesWithoutCustomMessageType.size) + } + + @Then("history response contains messages with {string} and {string} message types") + fun history_response_contains_messages_with_message_type( + messageTypeOfFirstMessage: String, + messageTypeOfSecondMessage: String + ) { + val historyMessageTypesInResponse: List = + historyState.messages!!.channels.values.flatMap { message -> message.map { it.messageType } } + + assertThat( + historyMessageTypesInResponse, + contains( + HistoryMessageType.of(messageTypeOfFirstMessage.toInt()), + HistoryMessageType.of(messageTypeOfSecondMessage.toInt()) + ) + ) + } + + @Then("history response contains messages with {string} and {string} types") + fun history_response_contains_messages_with_customMessageType( + customMessageTypeOfFirstMessage: String, + customMessageTypeOfSecondMessage: String + ) { + val customMessageTypesInResponse: List = + historyState.messages!!.channels.values.flatMap { message -> message.map { it.customMessageType } } + + assertThat( + customMessageTypesInResponse, + contains(customMessageTypeOfFirstMessage, customMessageTypeOfSecondMessage), + ) + } +} diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/publish/WhenSteps.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/publish/WhenSteps.kt new file mode 100644 index 000000000..98512fbd2 --- /dev/null +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/publish/WhenSteps.kt @@ -0,0 +1,23 @@ +package com.pubnub.contract.publish + +import com.pubnub.api.PubNubException +import com.pubnub.contract.state.World +import io.cucumber.java.en.When + +class WhenSteps(private val world: World) { + @When("I publish message with {string} customMessageType") + fun i_publish_message_with_custom_message_type(customMessageType: String) { + try { + world.pubnub.publish( + channel = "whatever", + message = "whatever", + customMessageType = customMessageType + ).sync().let { + world.responseStatus = 200 + } + } catch (ex: PubNubException) { + world.responseStatus = ex.statusCode + world.pnException = ex + } + } +} diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/signal/WhenSteps.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/signal/WhenSteps.kt new file mode 100644 index 000000000..ef839c434 --- /dev/null +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/signal/WhenSteps.kt @@ -0,0 +1,23 @@ +package com.pubnub.contract.signal + +import com.pubnub.api.PubNubException +import com.pubnub.contract.state.World +import io.cucumber.java.en.When + +class WhenSteps(private val world: World) { + @When("I send a signal with {string} customMessageType") + fun i_send_signal_with_custom_message_type(customMessageType: String) { + try { + world.pubnub.signal( + channel = "whatever", + message = "whatever", + customMessageType = customMessageType + ).sync().let { + world.responseStatus = 200 + } + } catch (ex: PubNubException) { + world.responseStatus = ex.statusCode + world.pnException = ex + } + } +} diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/step/KeysetStep.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/step/KeysetStep.kt index e22e21465..99ff0c096 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/step/KeysetStep.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/step/KeysetStep.kt @@ -47,4 +47,20 @@ class KeysetStep(private val world: World) { fun the_demo_keyset_with_Presence_EE_enabled() { the_demo_keyset_with_event_engine_enabled() } + + @Given("the demo keyset") + fun the_demo_keyset() { + MatcherAssert.assertThat(ContractTestConfig.pubKey, Matchers.notNullValue()) + MatcherAssert.assertThat(ContractTestConfig.subKey, Matchers.notNullValue()) + + world.configuration.apply { + subscribeKey = ContractTestConfig.subKey + publishKey = ContractTestConfig.pubKey + } + } + + @Given("the demo keyset with enabled storage") + fun the_demo_keyset_with_enabled_storage() { + the_demo_keyset() + } } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/step/ThenSteps.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/step/ThenSteps.kt index b06d54586..aeeee09a1 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/step/ThenSteps.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/step/ThenSteps.kt @@ -4,6 +4,7 @@ import com.pubnub.contract.state.World import io.cucumber.java.en.Then import org.json.JSONObject import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull import org.junit.Assert.assertTrue @@ -15,6 +16,12 @@ class ThenSteps(private val world: World) { ) fun an_error_is_returned() { assertNotNull(world.pnException) + assertNotEquals(200, world.responseStatus) + } + + @Then("I receive an error response") + fun i_receive_an_error_response() { + an_error_is_returned() } @Then("the result is successful") diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/subscribe/eventEngine/step/EventEngineSteps.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/subscribe/eventEngine/step/EventEngineSteps.kt index c74890edb..00e110a7c 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/subscribe/eventEngine/step/EventEngineSteps.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/contract/subscribe/eventEngine/step/EventEngineSteps.kt @@ -17,8 +17,9 @@ import io.cucumber.java.en.Then import io.cucumber.java.en.When import org.awaitility.kotlin.await import org.hamcrest.CoreMatchers +import org.hamcrest.CoreMatchers.`is` import org.hamcrest.MatcherAssert -import org.hamcrest.Matchers +import org.junit.jupiter.api.Assertions.assertTrue import java.util.concurrent.TimeUnit import kotlin.time.Duration.Companion.milliseconds @@ -88,6 +89,11 @@ class EventEngineSteps(private val state: EventEngineState) { state.pubnub.subscribe(channels = listOf(state.channelName)) } + @When("I subscribe to {string} channel") + fun i_subscribe_to_channel(channelId: String) { + i_subscribe() + } + @When("I subscribe with timetoken {long}") fun i_subscribe_with_timetoken(timetoken: Long) { state.pubnub.addListener( @@ -159,11 +165,31 @@ class EventEngineSteps(private val state: EventEngineState) { } } + @Then("I receive 2 messages in my subscribe response") + fun i_receive_2_messages_in_my_subscribe_response() { + await.pollInterval(50, TimeUnit.MILLISECONDS).atMost(2, TimeUnit.SECONDS).untilAsserted { + MatcherAssert.assertThat( + state.messagesList.size, + `is`(2) + ) + } + } + + @Then("response contains messages with {string} and {string} types") + fun response_contains_messages_with_customMessageType(customMessageType01: String, customMessageType02: String) { + await.pollInterval(50, TimeUnit.MILLISECONDS).atMost(500, TimeUnit.MILLISECONDS).untilAsserted { + val messageList = state.messagesList as List + val customMessageTypeList = messageList.map { message -> message.customMessageType }.toList() + assertTrue(customMessageTypeList.contains(customMessageType01)) + assertTrue(customMessageTypeList.contains(customMessageType02)) + } + } + @Then("I observe the following:") fun i_observe_the_following(dataTable: DataTable) { await.pollInterval(50, TimeUnit.MILLISECONDS).atMost(500, TimeUnit.MILLISECONDS).untilAsserted { val expectedNames = dataTable.asMaps().map { it["type"] to it["name"] }.toList() - MatcherAssert.assertThat(state.subscribeQueuedElements, Matchers.`is`(expectedNames)) + MatcherAssert.assertThat(state.subscribeQueuedElements, `is`(expectedNames)) } } diff --git a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/internal/suite/history/v2/HistoryMetaTestSuite.kt b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/internal/suite/history/v2/HistoryMetaTestSuite.kt index b9625a7cd..ce1cf2ec8 100644 --- a/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/internal/suite/history/v2/HistoryMetaTestSuite.kt +++ b/pubnub-kotlin/pubnub-kotlin-impl/src/test/kotlin/com/pubnub/internal/suite/history/v2/HistoryMetaTestSuite.kt @@ -22,8 +22,8 @@ class HistoryMetaTestSuite : com.pubnub.internal.suite.CoreEndpointTestSuite Unit = { }, @@ -192,9 +207,24 @@ class SubscribeMessageProcessorTest( ) private fun message(messageJson: JsonElement): String { - return "{\"a\":\"2\",\"f\":0,\"i\":\"client-2bdc6006-1b48-45e4-9c09-9cc4c5ac5e8c\",\"s\":1,\"p\":{\"t\":\"17000393136828867\",\"r\":43},\"k\":\"sub-c-33f55052-190b-11e6-bfbc-02ee2ddab7fe\",\"c\":\"ch_cxnysctxlw\",\"d\":$messageJson,\"b\":\"ch_cxnysctxlw\"}" + return "{\"a\":\"2\",\"f\":0,\"i\":\"client-2bdc6006-1b48-45e4-9c09-9cc4c5ac5e8c\",\"s\":1,\"p\":{\"t\":\"17000393136828867\",\"r\":43},\"k\":\"sub-c-33f55052-190b-11e6-bfbc-02ee2ddab7fe\",\"c\":\"ch_cxnysctxlw\",\"d\":$messageJson,\"b\":\"ch_cxnysctxlw\", \"cmt\":\"customMessageTypeLala\"}" } private fun fileMessage(messageJson: String) = - """{"a":"0","f":0,"e":4,"i":"client-52774e6f-2f4e-4915-aefd-e8bb75cd2e7d","p":{"t":"16632349939765880","r":43},"k":"sub-c-4b1dbfef-2fa9-495f-a316-2b634063083d","c":"ch_1663234993171_F4FC4F460F","u":"This is meta","d":{"message":$messageJson,"file":{"id":"30ce0095-3c50-4cdc-a626-bf402d233731","name":"fileNamech_1663234993171_F4FC4F460F.txt"}}}""" + """{"a":"0","f":0,"e":4,"i":"client-52774e6f-2f4e-4915-aefd-e8bb75cd2e7d","p":{"t":"16632349939765880","r":43},"k":"sub-c-4b1dbfef-2fa9-495f-a316-2b634063083d","c":"ch_1663234993171_F4FC4F460F","u":"This is meta","d":{"message":$messageJson,"file":{"id":"30ce0095-3c50-4cdc-a626-bf402d233731","name":"fileNamech_1663234993171_F4FC4F460F.txt"}}, "cmt":"customMessageTypeLala"}""" + + private fun subscribeMessage() = SubscribeMessage( + shard = "4", + flags = "0", + publishMetaData = PublishMetaData(16710463855524468, 21), + channel = "testChannel", + type = null, + customMessageType = null, + subscriptionMatch = null, + issuingClientId = null, + subscribeKey = "demo", + originationMetadata = null, + payload = JsonPrimitive("message"), + userMetadata = null + ) }