diff --git a/ica-rs/src/config.rs b/ica-rs/src/config.rs index 12dbd25..4c0f4de 100644 --- a/ica-rs/src/config.rs +++ b/ica-rs/src/config.rs @@ -113,6 +113,26 @@ impl BotConfig { } } + /// 检查是否启用 Tailchat + pub fn check_tailchat(&self) -> bool { + match self.enable_tailchat { + Some(enable) => { + if enable && self.tailchat.is_none() { + warn!("enable_tailchat 为 true 但未填写 [tailchat] 配置\n将不启用 Tailchat"); + false + } else { + true + } + } + None => { + if self.tailchat.is_some() { + warn!("未填写 enable_tailchat 但填写了 [tailchat] 配置\n将不启用 Tailchat"); + } + false + } + } + } + /// 检查是否启用 Python 插件 pub fn check_py(&self) -> bool { match self.enable_py { @@ -134,5 +154,6 @@ impl BotConfig { } pub fn ica(&self) -> IcaConfig { self.ica.clone().expect("No ica config found") } + pub fn tailchat(&self) -> TailchatConfig { self.tailchat.clone().expect("No tailchat config found") } pub fn py(&self) -> PyConfig { self.py.clone().expect("No py config found") } } diff --git a/ica-rs/src/main.rs b/ica-rs/src/main.rs index da8af32..bcf5d0c 100644 --- a/ica-rs/src/main.rs +++ b/ica-rs/src/main.rs @@ -17,6 +17,7 @@ use tracing::{event, info, span, Level}; pub static mut MAIN_STATUS: status::BotStatus = status::BotStatus { config: None, ica_status: None, + tailchat_status: None, }; pub type MainStatus = status::BotStatus; @@ -80,6 +81,18 @@ async fn main() { event!(Level::INFO, "未启用 ica"); } + let (tailchat_send, tailchat_recv) = tokio::sync::oneshot::channel::<()>(); + + if bot_config.check_tailchat() { + event!(Level::INFO, "启动 Tailchat"); + let config = bot_config.tailchat(); + tokio::spawn(async move { + tailchat::start_tailchat(config, tailchat_recv).await.unwrap(); + }); + } else { + event!(Level::INFO, "未启用 Tailchat"); + } + tokio::time::sleep(Duration::from_secs(2)).await; // 等待一个输入 info!("Press any key to exit"); @@ -87,6 +100,7 @@ async fn main() { std::io::stdin().read_line(&mut input).unwrap(); ica_send.send(()).ok(); + tailchat_send.send(()).ok(); info!("Disconnected"); } diff --git a/ica-rs/src/py/call.rs b/ica-rs/src/py/call.rs index 9a6005f..95e8eb8 100644 --- a/ica-rs/src/py/call.rs +++ b/ica-rs/src/py/call.rs @@ -169,7 +169,7 @@ pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) { } } -pub async fn tailchat_new_message_py(message: tailchat::messages::ReciveMessage, client: &Client) { +pub async fn tailchat_new_message_py(message: &tailchat::messages::ReciveMessage, client: &Client) { verify_plugins(); let plugins = PyStatus::get_files(); diff --git a/ica-rs/src/status.rs b/ica-rs/src/status.rs index d776875..eecc728 100644 --- a/ica-rs/src/status.rs +++ b/ica-rs/src/status.rs @@ -5,6 +5,7 @@ use crate::MAIN_STATUS; pub struct BotStatus { pub config: Option, pub ica_status: Option, + pub tailchat_status: Option, } impl BotStatus { @@ -18,6 +19,11 @@ impl BotStatus { MAIN_STATUS.ica_status = Some(status); } } + pub fn update_tailchat_status(status: tailchat::MainStatus) { + unsafe { + MAIN_STATUS.tailchat_status = Some(status); + } + } pub fn static_init(config: BotConfig) { unsafe { @@ -33,13 +39,20 @@ impl BotStatus { } pub fn global_config() -> &'static BotConfig { unsafe { MAIN_STATUS.config.as_ref().unwrap() } } + pub fn global_ica_status() -> &'static ica::MainStatus { unsafe { MAIN_STATUS.ica_status.as_ref().unwrap() } } + pub fn global_tailchat_status() -> &'static tailchat::MainStatus { + unsafe { MAIN_STATUS.tailchat_status.as_ref().unwrap() } + } pub fn global_ica_status_mut() -> &'static mut ica::MainStatus { unsafe { MAIN_STATUS.ica_status.as_mut().unwrap() } } + pub fn global_tailchat_status_mut() -> &'static mut tailchat::MainStatus { + unsafe { MAIN_STATUS.tailchat_status.as_mut().unwrap() } + } } pub mod ica { @@ -65,3 +78,34 @@ pub mod ica { pub fn update_online_status(&mut self, status: OnlineData) { self.online_status = status; } } } + + +pub mod tailchat { + use crate::data_struct::tailchat::UserId; + + #[derive(Debug, Clone)] + pub struct MainStatus { + /// 是否启用 tailchat + pub enable: bool, + /// 是否登录 + pub login: bool, + /// 用户 ID + pub user_id: UserId, + /// 昵称 + pub nick_name: String, + /// 邮箱 + pub email: String, + /// JWT Token + pub jwt_token: String, + /// avatar + pub avatar: String, + } + + impl MainStatus { + pub fn update_user_id(&mut self, user_id: UserId) { self.user_id = user_id; } + pub fn update_nick_name(&mut self, nick_name: String) { self.nick_name = nick_name; } + pub fn update_email(&mut self, email: String) { self.email = email; } + pub fn update_jwt_token(&mut self, jwt_token: String) { self.jwt_token = jwt_token; } + pub fn update_avatar(&mut self, avatar: String) { self.avatar = avatar; } + } +} diff --git a/ica-rs/src/tailchat.rs b/ica-rs/src/tailchat.rs index 4a60844..1ccfdb3 100644 --- a/ica-rs/src/tailchat.rs +++ b/ica-rs/src/tailchat.rs @@ -1,27 +1,55 @@ pub mod events; use futures_util::FutureExt; -use reqwest::ClientBuilder as reqwest_ClientBuilder; +use md5::{Digest, Md5}; +use reqwest::{Body, ClientBuilder as reqwest_ClientBuilder}; use rust_socketio::asynchronous::{Client, ClientBuilder}; use rust_socketio::{Event, Payload, TransportType}; +use serde_json::json; use tracing::{event, span, Level}; -// use crate::config::IcaConfig; +use crate::config::TailchatConfig; use crate::error::{ClientResult, TailchatError}; +use crate::StopGetter; -pub async fn start_tailchat() -> ClientResult<(), TailchatError> { +pub async fn start_tailchat( + config: TailchatConfig, + stop_receiver: StopGetter, +) -> ClientResult<(), TailchatError> { let span = span!(Level::INFO, "Tailchat Client"); let _enter = span.enter(); event!(Level::INFO, "tailchat-async-rs v{} initing", crate::TAILCHAT_VERSION); - let tailchat_req = reqwest_ClientBuilder::new().build()?; + let mut hasher = Md5::new(); + hasher.update(config.app_id.as_bytes()); + hasher.update(config.app_secret.as_bytes()); - // tailchat_req.get("http://localhost:8080").send().await?; + let token = format!("{:x}", hasher.finalize()); - // let socket = match ClientBuilder::new() { + let mut header_map = reqwest::header::HeaderMap::new(); + header_map.append("Content-Type", "application/json".parse().unwrap()); - // }; + let client = reqwest_ClientBuilder::new().default_headers(header_map).build()?; + let status = match client + .post(&format!("{}/api/openapi/bot/login", config.host)) + .body(json!{{"appId": config.app_id, "token": token}}.to_string()) + .send() + .await + { + Ok(resp) => { + if resp.status().is_success() { + let body = resp.text().await?; + event!(Level::INFO, "login success: {}", body); + body + } else { + Err(TailchatError::LoginFailed(resp.text().await?)) + } + } + Err(e) => return Err(TailchatError::LoginFailed(e.to_string())), + }; + // notify:chat.message.delete + // notify:chat.message.add Ok(()) }