From e95ff9a7fafd355f510a70ac37cd40267b182cfe Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sun, 26 Sep 2021 03:08:34 -0400 Subject: [PATCH] try to connect over websockets (400) --- Cargo.lock | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 6 +- src/main.rs | 67 +++++++++++++++++++- 3 files changed, 245 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89be8f6a85..74002cbdb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,12 +83,27 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "bytes" version = "1.1.0" @@ -107,6 +122,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "winapi", +] + [[package]] name = "core-foundation" version = "0.9.1" @@ -123,6 +150,24 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +[[package]] +name = "cpufeatures" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + [[package]] name = "displaydoc" version = "0.2.3" @@ -298,6 +343,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.3" @@ -553,6 +608,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.13.0" @@ -569,6 +643,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + [[package]] name = "openssl" version = "0.10.36" @@ -608,6 +688,26 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pin-project" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.7" @@ -805,6 +905,19 @@ dependencies = [ "webpki", ] +[[package]] +name = "rustls" +version = "0.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" +dependencies = [ + "base64 0.13.0", + "log", + "ring", + "sct", + "webpki", +] + [[package]] name = "ryu" version = "1.0.5" @@ -917,6 +1030,19 @@ dependencies = [ "serde", ] +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest", + "opaque-debug", +] + [[package]] name = "slab" version = "0.4.4" @@ -1046,6 +1172,20 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8" +dependencies = [ + "futures-util", + "log", + "pin-project", + "rustls 0.19.1", + "tokio", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.6.8" @@ -1101,18 +1241,39 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "tungstenite" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5" +dependencies = [ + "base64 0.13.0", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand", + "sha-1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "twitch-tts-desktop-client" version = "0.0.0" dependencies = [ "anyhow", "easyenv", + "futures-util", "log", "reqwest", - "rustls", + "rustls 0.18.1", "serde", "serde_derive", "tokio", + "tokio-tungstenite", "toml", "twitch_api2", "twitch_oauth2", @@ -1126,6 +1287,7 @@ checksum = "003e4481fa1bc7cf6587dd212a4ce5f3b69dee893c9f7fdf8a0ed7149f470f1b" dependencies = [ "aliri_braid", "async-trait", + "chrono", "displaydoc", "futures", "http", @@ -1175,6 +1337,12 @@ dependencies = [ "syn", ] +[[package]] +name = "typenum" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" + [[package]] name = "unicode-bidi" version = "0.3.6" @@ -1214,6 +1382,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index cff34fa515..314ec03f88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ path = "src/main.rs" # Crypto rustls = "0.18" +tokio-tungstenite = { version = "0.15.0", features = ["rustls"] } # Serialization serde = "1.0.130" @@ -31,11 +32,12 @@ toml = "0.5.8" #twitch_oauth2 = "0.4.1" #twitch_api2 = "0.5.0" #twitch_oauth2 = "0.5.0" -twitch_api2 = { version = "0.6.0-rc.2", features = ["helix", "reqwest_client"] } +# NB "unsupported" pubsub features may disappear from the Twitch API at any time. It's an unofficial API. +twitch_api2 = { version = "0.6.0-rc.2", features = ["helix", "reqwest_client", "pubsub", "chrono", "unsupported"] } twitch_oauth2 = "0.6.0-rc.2" reqwest = { version = "0.11.4" } tokio = { version = "1.10.0", features = ["rt-multi-thread", "macros"] } - +futures-util = "0.3.17" # Utils anyhow = "1.0.44" diff --git a/src/main.rs b/src/main.rs index ad37c70cec..55a54ea592 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,20 @@ extern crate twitch_api2; +use futures_util::{SinkExt, StreamExt}; extern crate reqwest; +use crate::twitch::secrets::TwitchSecrets; use crate::util::anyhow_result::AnyhowResult; use twitch_api2::TwitchClient; use twitch_api2::helix::channels::GetChannelInformationRequest; +use twitch_api2::pubsub; use twitch_oauth2::{AppAccessToken, Scope, TwitchToken, tokens::errors::AppAccessTokenError, ClientId, ClientSecret}; -use crate::twitch::secrets::TwitchSecrets; +use twitch_api2::pubsub::Topic; + +use tokio_tungstenite::{ + connect_async, + tungstenite::{Error as TungsteniteError, Result as TungsteniteResult}, +}; +use reqwest::Url; pub mod twitch; pub mod util; @@ -51,5 +60,61 @@ async fn run() -> AnyhowResult<()> { &client.helix.req_get(req, &token).await?.data.unwrap().title ); + + // Want this: + // twitch_api2::pubsub::channel_bits::BitsEventData + + + + /*// We want to subscribe to moderator actions on channel with id 1234 + // as if we were a user with id 4321 that is moderator on the channel. + let chat_mod_actions = pubsub::moderation::ChatModeratorActions { + user_id: 4321, + channel_id: 1234, + } + .into_topic();*/ + + // Listen to follows as well + let follows = pubsub::following::Following { channel_id: 1234 }.into_topic(); + let topics = [follows]; + // Create the topic command to send to twitch + let command = pubsub::listen_command( + &topics, + "authtoken", + "random nonce string", + )?; + + println!("Pubsub command: {:?}", command); + + // Send the message with your favorite websocket client + //send_command(command).unwrap(); + // To parse the websocket messages, use pubsub::Response::parse + + let url = Url::parse("wss://pubsub-edge.twitch.tv")?; + + println!("Connecting..."); + + let (mut socket, _response) = + connect_async(url).await?; + + println!("Connected!"); + + let msg = socket.next().await.expect("Can't fetch case count")?; + socket.close(None).await?; + + let text = msg.into_text()?; + println!("Text: {}", text); + Ok(()) +} + + +async fn get_case_count() -> TungsteniteResult { + let (mut socket, _) = connect_async( + Url::parse("ws://localhost:9001/getCaseCount").expect("Can't connect to case count URL"), + ) + .await?; + let msg = socket.next().await.expect("Can't fetch case count")?; + socket.close(None).await?; + Ok(msg.into_text()?.parse::().expect("Can't parse case count")) } \ No newline at end of file