diff --git a/.pubnub.yml b/.pubnub.yml index 009a3b5b..67a2b768 100644 --- a/.pubnub.yml +++ b/.pubnub.yml @@ -1,9 +1,18 @@ name: rust -version: 0.2.1 +version: 0.3.0 schema: 1 scm: github.com/pubnub/rust files: [] changelog: + - date: 2023-08-30 + version: 0.3.0 + changes: + - type: feature + text: "PubNub subscribe API implemented." + - type: feature + text: "PubNub presence API implemented." + - type: feature + text: "Event engine as a new method of handling connections for `subscribe` and `presence` methods implemented." - date: 2023-06-07 version: 0.2.1 changes: @@ -87,6 +96,28 @@ features: - PUBLISH-ASYNC - PUBLISH-REPLICATION-FLAG - PUBLISH-MESSAGE-TTL + subscribe: + - SUBSCRIBE-CHANNELS + - SUBSCRIBE-CHANNEL-GROUPS + - SUBSCRIBE-PRESENCE-CHANNELS + - SUBSCRIBE-PRESENCE-CHANNELS-GROUPS + - SUBSCRIBE-WITH-TIMETOKEN + - SUBSCRIBE-FILTER-EXPRESSION + - SUBSCRIBE-PUBLISHER-UUID + - SUBSCRIBE-PUBSUB-V2 + - SUBSCRIBE-SIGNAL-LISTENER + - SUBSCRIBE-MEMBERSHIP-LISTENER + - SUBSCRIBE-OBJECTS-CHANNEL-LISTENER + - SUBSCRIBE-OBJECTS-UUID-LISTENER + - SUBSCRIBE-MESSAGE-ACTIONS-LISTENER + - SUBSCRIBE-FILE-LISTENER + presence: + - PRESENCE-HERE-NOW + - PRESENCE-WHERE-NOW + - PRESENCE-SET-STATE + - PRESENCE-GET-STATE + - PRESENCE-HEARTBEAT + - PRESENCE-DELTAS supported-platforms: - version: PubNub Rust SDK platforms: diff --git a/Cargo.toml b/Cargo.toml index f04e745a..f1786602 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pubnub" -version = "0.2.1" +version = "0.3.0" edition = "2021" license = "MIT" authors = ["PubNub "] @@ -17,7 +17,7 @@ build = "build.rs" full = ["publish", "subscribe", "presence", "access", "serde", "reqwest", "aescbc", "parse_token", "blocking", "std", "tokio"] # Enables all default features -default = ["publish", "subscribe", "presence", "serde", "reqwest", "aescbc", "std", "blocking", "tokio"] +default = ["publish", "subscribe", "serde", "reqwest", "aescbc", "std", "blocking", "tokio"] # [PubNub features] @@ -64,9 +64,9 @@ extra_platforms = ["spin/portable_atomic", "dep:portable-atomic"] # [Internal features] (not intended for use outside of the library) contract_test = ["parse_token", "publish", "access"] -full_no_std = ["serde", "reqwest", "aescbc", "parse_token", "blocking", "publish", "access", "subscribe", "tokio"] -full_no_std_platform_independent = ["serde", "aescbc", "parse_token", "blocking", "publish", "access", "subscribe"] -pubnub_only = ["aescbc", "parse_token", "blocking", "publish", "access", "subscribe"] +full_no_std = ["serde", "reqwest", "aescbc", "parse_token", "blocking", "publish", "access", "subscribe", "tokio", "presence"] +full_no_std_platform_independent = ["serde", "aescbc", "parse_token", "blocking", "publish", "access", "subscribe", "presence"] +pubnub_only = ["aescbc", "parse_token", "blocking", "publish", "access", "subscribe", "presence"] mock_getrandom = ["getrandom/custom"] # TODO: temporary treated as internal until we officially release it subscribe = ["dep:futures"] diff --git a/README.md b/README.md index fe8d2687..370bec9c 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,11 @@ Add `pubnub` to your Rust project in the `Cargo.toml` file: ```toml # default features [dependencies] -pubnub = "0.2.1" +pubnub = "0.3.0" # all features [dependencies] -pubnub = { version = "0.2.1", features = ["full"] } +pubnub = { version = "0.3.0", features = ["full"] } ``` ### Example @@ -48,21 +48,66 @@ Try the following sample code to get up and running quickly! ```rust use pubnub::{Keyset, PubNubClientBuilder}; +use pubnub::dx::subscribe::{SubscribeStreamEvent, Update}; +use futures::StreamExt; +use tokio::time::sleep; +use std::time::Duration; +use serde_json; #[tokio::main] async fn main() -> Result<(), Box> { let publish_key = "my_publish_key"; let subscribe_key = "my_subscribe_key"; - let client = PubNubClientBuilder::with_reqwest_transport() - .with_keyset(Keyset { - subscribe_key, - publish_key: Some(publish_key), - secret_key: None, - }) - .with_user_id("user_id") - .build()?; - + .with_keyset(Keyset { + subscribe_key, + publish_key: Some(publish_key), + secret_key: None, + }) + .with_user_id("user_id") + .build()?; + println!("PubNub instance created"); + + let subscription = client + .subscribe() + .channels(["my_channel".into()].to_vec()) + .execute()?; + + println!("Subscribed to channel"); + + // Launch a new task to print out each received message + tokio::spawn(subscription.stream().for_each(|event| async move { + match event { + SubscribeStreamEvent::Update(update) => { + match update { + Update::Message(message) | Update::Signal(message) => { + // Silently log if UTF-8 conversion fails + if let Ok(utf8_message) = String::from_utf8(message.data.clone()) { + if let Ok(cleaned) = serde_json::from_str::(&utf8_message) { + println!("message: {}", cleaned); + } + } + } + Update::Presence(presence) => { + println!("presence: {:?}", presence) + } + Update::Object(object) => { + println!("object: {:?}", object) + } + Update::MessageAction(action) => { + println!("message action: {:?}", action) + } + Update::File(file) => { + println!("file: {:?}", file) + } + } + } + SubscribeStreamEvent::Status(status) => println!("\nstatus: {:?}", status), + } + })); + + sleep(Duration::from_secs(1)).await; + // Send a message to the channel client .publish_message("hello world!") .channel("my_channel") @@ -70,6 +115,8 @@ async fn main() -> Result<(), Box> { .execute() .await?; + sleep(Duration::from_secs(10)).await; + Ok(()) } ``` @@ -83,22 +130,25 @@ The `pubnub` crate is split into multiple features. You can enable or disable th ```toml # only blocking and access + default features [dependencies] -pubnub = { version = "0.2.1", features = ["blocking", "access"] } +pubnub = { version = "0.3.0", features = ["blocking", "access"] } # only parse_token + default features [dependencies] -pubnub = { version = "0.2.1", features = ["parse_token"] } +pubnub = { version = "0.3.0", features = ["parse_token"] } ``` ### Available features | Feature name | Description | Available PubNub APIs | | :------------ | :---------- | :------------- | -| `full` | Enables all non-conflicting features | Configuration, Publish, Access Manager, Parse Token | -| `default` | Enables default features: `publish`, `serde`, `reqwest`, `aescbc`, `std` | Configuration, Publish | +| `full` | Enables all non-conflicting features | Configuration, Publish, Subscribe, Access Manager, Parse Token, Presence | +| `default` | Enables default features: `publish`, `subscribe`, `serde`, `reqwest`, `aescbc`, `std` | Configuration, Publish, Subscribe | | `publish` | Enables Publish API | Configuration, Publish | | `access` | Enables Access Manager API | Configuration, Access Manager | | `parse_token` | Enables parsing Access Manager tokens | Configuration, Parse Token | +| `subscribe` | Enables Subscribe API | Configuration, Subscribe | +| `presence` | Enables Presence API | Configuration, Presence | +| `tokio` | Enables the [tokio](https://tokio.rs/) asynchronous runtime for Subscribe and Presence APIs | n/a | | `serde` | Uses [serde](https://github.com/serde-rs/serde) for serialization | n/a | | `reqwest` | Uses [reqwest](https://github.com/seanmonstar/reqwest) as a transport layer | n/a | | `blocking` | Enables blocking executions of APIs | n/a | @@ -121,7 +171,7 @@ features and enable the ones you need, for example: ```toml [dependencies] -pubnub = { version = "0.2.1", default-features = false, features = ["serde", "publish", +pubnub = { version = "0.3.0", default-features = false, features = ["serde", "publish", "blocking"] } ``` @@ -135,8 +185,10 @@ some parts of the `alloc::sync` module, which is also not supported in certain ` Some SDK features aren't supported in a `no_std` environment: -* partially `access` module (because of lack timestamp support) +* partially `access` module (because of lack of timestamp support) * partially `reqwest` transport (because of the reqwest implementation details) +* partially `subscribe` module (because of the spawning tasks and time dependence) +* partially `presence` module (because of the spawning tasks and time dependence) * `std` feature (because of the `std` library) We depend on a random number generator to generate data for debugging purposes. diff --git a/src/lib.rs b/src/lib.rs index 09c4b486..4bc31308 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,11 +38,11 @@ //! ```toml //! # default features //! [dependencies] -//! pubnub = "0.2.1" +//! pubnub = "0.3.0" //! //! # all features //! [dependencies] -//! pubnub = { version = "0.2.1", features = ["full"] } +//! pubnub = { version = "0.3.0", features = ["full"] } //! ``` //! //! ### Example @@ -133,22 +133,25 @@ //! ```toml //! # only blocking and access + default features //! [dependencies] -//! pubnub = { version = "0.2.1", features = ["blocking", "access"] } +//! pubnub = { version = "0.3.0", features = ["blocking", "access"] } //! //! # only parse_token + default features //! [dependencies] -//! pubnub = { version = "0.2.1", features = ["parse_token"] } +//! pubnub = { version = "0.3.0", features = ["parse_token"] } //! ``` //! //! ### Available features //! //! | Feature name | Description | Available PubNub APIs | //! | :------------ | :---------- | :------------- | -//! | `full` | Enables all non-conflicting features | Configuration, Publish, Access Manager, Parse Token | -//! | `default` | Enables default features: `publish`, `serde`, `reqwest`, `aescbc`, `std` | Configuration, Publish | +//! | `full` | Enables all non-conflicting features | Configuration, Publish, Subscribe, Access Manager, Parse Token, Presence | +//! | `default` | Enables default features: `publish`, `subscribe`, `serde`, `reqwest`, `aescbc`, `std` | Configuration, Publish, Subscribe | //! | `publish` | Enables Publish API | Configuration, Publish | //! | `access` | Enables Access Manager API | Configuration, Access Manager | //! | `parse_token` | Enables parsing Access Manager tokens | Configuration, Parse Token | +//! | `subscribe` | Enables Subscribe API | Configuration, Subscribe | +//! | `presence` | Enables Presence API | Configuration, Presence | +//! | `tokio` | Enables the [tokio](https://tokio.rs/) asynchronous runtime for Subscribe and Presence APIs | n/a | //! | `serde` | Uses [serde](https://github.com/serde-rs/serde) for serialization | n/a | //! | `reqwest` | Uses [reqwest](https://github.com/seanmonstar/reqwest) as a transport layer | n/a | //! | `blocking` | Enables blocking executions of APIs | n/a | @@ -171,7 +174,7 @@ //! //! ```toml //! [dependencies] -//! pubnub = { version = "0.2.1", default-features = false, features = ["serde", "publish", +//! pubnub = { version = "0.3.0", default-features = false, features = ["serde", "publish", //! "blocking"] } //! ``` //! @@ -185,8 +188,10 @@ //! //! Some SDK features aren't supported in a `no_std` environment: //! -//! * partially `access` module (because of lack timestamp support) +//! * partially `access` module (because of lack of timestamp support) //! * partially `reqwest` transport (because of the reqwest implementation details) +//! * partially `subscribe` module (because of the spawning tasks and time dependence) +//! * partially `presence` module (because of the spawning tasks and time dependence) //! * `std` feature (because of the `std` library) //! //! We depend on a random number generator to generate data for debugging purposes.