diff --git a/Cargo.toml b/Cargo.toml index 0cc016c..8188989 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ duct = "0.13.6" runas = "1.1.0" csv-async = { version = "1.2.6", features = ["tokio"] } futures = "0.3.28" +twitch-irc = "5.0.1" # Windows Only [target.'cfg(windows)'.dependencies] diff --git a/dictionary.arknights.txt b/dictionary.arknights.txt index 7ef530e..e9936f2 100644 --- a/dictionary.arknights.txt +++ b/dictionary.arknights.txt @@ -53,7 +53,6 @@ げんがんこう 源岩鉱 名詞 けんじょうほうしゅ 堅城砲手 名詞 げんせき 源石 名詞 -こう 功 名詞 将進酒 こうご 句呉 地名 こうごじょう 句呉城 名詞 将進酒 こうせきびょう 鉱石病 名詞 diff --git a/dictionary.chat.txt b/dictionary.chat.txt new file mode 100644 index 0000000..f57bc9e --- /dev/null +++ b/dictionary.chat.txt @@ -0,0 +1 @@ +うさぎはかせちゃん UsagiNetwork diff --git a/src/conf/mod.rs b/src/conf/mod.rs index 05200dc..feb452b 100644 --- a/src/conf/mod.rs +++ b/src/conf/mod.rs @@ -23,6 +23,12 @@ pub enum RunWith { }, } +#[derive(Debug, Deserialize, Serialize, Clone)] +pub struct Twitch { + pub username: String, + pub channel_to: String, +} + #[derive(Debug, Deserialize, Serialize, Clone)] pub struct Conf { pub workers: Option, @@ -37,6 +43,8 @@ pub struct Conf { pub state_data_capacity: Option, pub state_data_pretty: Option, + pub twitch: Option, + #[serde(default)] pub run_with: Vec, diff --git a/src/error.rs b/src/error.rs index f2ade21..d54fa84 100644 --- a/src/error.rs +++ b/src/error.rs @@ -34,6 +34,9 @@ pub enum Error { #[error("OS-TTS エラーが発生しました: {0}")] OsTtsError(#[from] tts::Error), + + #[error("スレッド終了エラーが発生しました: {0}")] + JoinError(#[from] tokio::task::JoinError), } impl ResponseError for Error { @@ -50,6 +53,7 @@ impl ResponseError for Error { Self::SystemTimeError(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::RegexError(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::OsTtsError(_) => StatusCode::INTERNAL_SERVER_ERROR, + Self::JoinError(_) => StatusCode::INTERNAL_SERVER_ERROR, } } diff --git a/src/lib.rs b/src/lib.rs index fcfa8dc..5b1bc69 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -57,9 +57,46 @@ pub async fn run() -> Result<()> { // 共有ステートを作成 let state = State::new(&conf, audio_sink).await?; + // TODO: コード整理 + use twitch_irc::login::StaticLoginCredentials; + use twitch_irc::TwitchIRCClient; + use twitch_irc::{ClientConfig, SecureTCPTransport}; + + let config = ClientConfig::default(); + let (mut incoming_messages, client) = TwitchIRCClient::::new(config); + + let state_for_message_handler = state.clone(); + let twitch = conf.twitch.clone(); + let join_handle = tokio::spawn(async move { + if twitch.is_none() { + return; + } + let ch = twitch.unwrap().channel_to; + while let Some(message) = incoming_messages.recv().await { + match message { + twitch_irc::message::ServerMessage::Privmsg(msg) => { + log::debug!("Received message: {:?}", msg); + let m = format!("{}:{}", msg.sender.name, msg.message_text); + state_for_message_handler + .read() + .await + .push_channel_datum(ChannelDatum::new(ch.clone(), m).with_flag(ChannelDatum::FLAG_IS_FINAL)) + .await; + }, + _ => (), + } + } + }); + + if let Some(twitch) = conf.twitch.clone() { + client.join(twitch.username).unwrap(); + } + // 通常の動作モードで実行 run_services(conf, state).await?; + join_handle.await?; + Ok(()) }