mirror of
https://github.com/kurbezz/discord-bot.git
synced 2025-12-06 15:15:37 +01:00
Add twitch chat
This commit is contained in:
165
Cargo.lock
generated
165
Cargo.lock
generated
@@ -410,6 +410,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"chrono",
|
"chrono",
|
||||||
"futures",
|
"futures",
|
||||||
|
"irc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"reqwest 0.12.5",
|
"reqwest 0.12.5",
|
||||||
"rustls 0.23.12",
|
"rustls 0.23.12",
|
||||||
@@ -432,6 +433,70 @@ version = "1.13.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding"
|
||||||
|
version = "0.2.33"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
|
||||||
|
dependencies = [
|
||||||
|
"encoding-index-japanese",
|
||||||
|
"encoding-index-korean",
|
||||||
|
"encoding-index-simpchinese",
|
||||||
|
"encoding-index-singlebyte",
|
||||||
|
"encoding-index-tradchinese",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding-index-japanese"
|
||||||
|
version = "1.20141219.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
|
||||||
|
dependencies = [
|
||||||
|
"encoding_index_tests",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding-index-korean"
|
||||||
|
version = "1.20141219.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
|
||||||
|
dependencies = [
|
||||||
|
"encoding_index_tests",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding-index-simpchinese"
|
||||||
|
version = "1.20141219.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
|
||||||
|
dependencies = [
|
||||||
|
"encoding_index_tests",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding-index-singlebyte"
|
||||||
|
version = "1.20141219.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
|
||||||
|
dependencies = [
|
||||||
|
"encoding_index_tests",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding-index-tradchinese"
|
||||||
|
version = "1.20141219.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
|
||||||
|
dependencies = [
|
||||||
|
"encoding_index_tests",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding_index_tests"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.34"
|
version = "0.8.34"
|
||||||
@@ -936,6 +1001,43 @@ version = "2.9.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "irc"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b59a23035df48e37386a6d03dc084fbab6ab835134bb99d081954199d7dd20df"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"encoding",
|
||||||
|
"futures-util",
|
||||||
|
"irc-proto",
|
||||||
|
"log",
|
||||||
|
"native-tls",
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tokio-native-tls",
|
||||||
|
"tokio-stream",
|
||||||
|
"tokio-util",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "irc-proto"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b5c7fb0c03989e8b31de1c91d0f625057887677e387448e7fc10a6afd4d9e1"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"encoding",
|
||||||
|
"thiserror",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
@@ -1743,6 +1845,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@@ -2076,6 +2187,17 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-stream"
|
||||||
|
version = "0.1.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-tungstenite"
|
name = "tokio-tungstenite"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
@@ -2121,6 +2243,40 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.7.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.19.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
@@ -2653,6 +2809,15 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.5.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winreg"
|
name = "winreg"
|
||||||
version = "0.50.0"
|
version = "0.50.0"
|
||||||
|
|||||||
@@ -18,3 +18,4 @@ anyhow = "1.0.86"
|
|||||||
async-trait = "0.1.81"
|
async-trait = "0.1.81"
|
||||||
tokio-tungstenite = { version = "0.23.1", features = ["rustls-tls-native-roots"] }
|
tokio-tungstenite = { version = "0.23.1", features = ["rustls-tls-native-roots"] }
|
||||||
rustls = { version = "0.23.12", features = ["ring"] }
|
rustls = { version = "0.23.12", features = ["ring"] }
|
||||||
|
irc = "1.0.0"
|
||||||
|
|||||||
79
src/twitch_handler/chat.rs
Normal file
79
src/twitch_handler/chat.rs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
use anyhow::bail;
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
use irc::client::data::Config as IrcConfig;
|
||||||
|
use irc::client::prelude::Capability as IrcCap;
|
||||||
|
use irc::client::Client as IrcClient;
|
||||||
|
use irc::client::ClientStream as IrcStream;
|
||||||
|
|
||||||
|
use super::auth;
|
||||||
|
use super::helix;
|
||||||
|
|
||||||
|
|
||||||
|
impl<T: auth::TokenStorage> helix::Client<T> {
|
||||||
|
pub async fn connect_chat(&mut self, channels: Vec<String>) -> Result<(IrcClient, IrcStream)> {
|
||||||
|
match self.validate_token().await {
|
||||||
|
Err(e) => {
|
||||||
|
println!("{e:?}");
|
||||||
|
bail!("Invalid refresh token or no internet");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let channels = channels
|
||||||
|
.into_iter()
|
||||||
|
.map(|c| {
|
||||||
|
format!(
|
||||||
|
"{0}{1}",
|
||||||
|
if c.starts_with("#") { "" } else { "#" },
|
||||||
|
c.to_lowercase()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let config = IrcConfig {
|
||||||
|
server: Some("irc.chat.twitch.tv".to_owned()),
|
||||||
|
port: Some(6697),
|
||||||
|
use_tls: Some(true),
|
||||||
|
nickname: Some(self.get_token_user_login().await?.to_lowercase().to_owned()),
|
||||||
|
password: Some(format!("oauth:{0}", self.token.access_token)),
|
||||||
|
channels: channels,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut client = match IrcClient::from_config(config).await {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
println!("{e:?}");
|
||||||
|
bail!("IrcClient::from_config failed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
match client.send_cap_req(&[
|
||||||
|
IrcCap::Custom("twitch.tv/tags"),
|
||||||
|
IrcCap::Custom("twitch.tv/commands"),
|
||||||
|
]) {
|
||||||
|
Err(e) => {
|
||||||
|
println!("{e:?}");
|
||||||
|
bail!("IrcClient.send_cap_req failed");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
match client.identify() {
|
||||||
|
Err(e) => {
|
||||||
|
println!("{e:?}");
|
||||||
|
bail!("IrcClient.identify failed");
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
|
||||||
|
let stream = match client.stream() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
println!("{e:?}");
|
||||||
|
bail!("IrcClient.stream failed");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((client, stream))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
pub mod eventsub;
|
pub mod eventsub;
|
||||||
pub mod helix;
|
pub mod helix;
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
|
pub mod chat;
|
||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
@@ -63,7 +64,7 @@ pub async fn notify_stream_online(title: String, game: String) {
|
|||||||
|
|
||||||
|
|
||||||
impl TwitchBot {
|
impl TwitchBot {
|
||||||
pub async fn start() {
|
pub async fn start_twitch_eventsub() {
|
||||||
println!("Starting Twitch bot...");
|
println!("Starting Twitch bot...");
|
||||||
|
|
||||||
let token_storage = TokenStorage {
|
let token_storage = TokenStorage {
|
||||||
@@ -103,8 +104,11 @@ impl TwitchBot {
|
|||||||
],
|
],
|
||||||
config::CONFIG.twitch_channel_id.clone()
|
config::CONFIG.twitch_channel_id.clone()
|
||||||
).await.unwrap();
|
).await.unwrap();
|
||||||
|
|
||||||
println!("Connected to Twitch EventSub...");
|
println!("Connected to Twitch EventSub...");
|
||||||
|
|
||||||
|
let (_chat_client, mut chat_stream) = client.connect_chat(vec![config::CONFIG.twitch_channel_id.clone()]).await.unwrap();
|
||||||
|
println!("Connected to Twitch Chat...");
|
||||||
|
|
||||||
client.validate_token().await.unwrap();
|
client.validate_token().await.unwrap();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
@@ -160,6 +164,15 @@ impl TwitchBot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(event) = chat_stream.next().await {
|
||||||
|
match event {
|
||||||
|
Ok(v) => {
|
||||||
|
println!("{:?}", v);
|
||||||
|
},
|
||||||
|
Err(_) => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
client.validate_token().await.unwrap();
|
client.validate_token().await.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user