From 198839c65f8785a9043492017f4d896a0a6eb9a0 Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Tue, 20 Feb 2024 17:15:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=88=E6=98=AF=E4=B8=80=E5=A4=A7=E5=A0=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ica-rs/src/config.rs | 4 +- ica-rs/src/data_struct/messages.rs | 54 +++++---------- ica-rs/src/events.rs | 26 ++++++- ica-rs/src/main.rs | 2 +- ica-rs/src/py/class.rs | 106 +++++++++++++++++++++++++++++ ica-rs/src/{py.rs => py/mod.rs} | 2 + 6 files changed, 150 insertions(+), 44 deletions(-) create mode 100644 ica-rs/src/py/class.rs rename ica-rs/src/{py.rs => py/mod.rs} (97%) diff --git a/ica-rs/src/config.rs b/ica-rs/src/config.rs index 3c80c67..c19b7c7 100644 --- a/ica-rs/src/config.rs +++ b/ica-rs/src/config.rs @@ -2,7 +2,7 @@ use std::env; use std::fs; use serde::Deserialize; -use toml; +use toml::from_str; /// Icalingua bot 的配置 #[derive(Debug, Deserialize)] @@ -25,7 +25,7 @@ impl IcaConfig { pub fn new_from_path(config_file_path: String) -> Self { // try read config from file let config = fs::read_to_string(&config_file_path).expect("Failed to read config file"); - let ret: Self = toml::from_str(&config) + let ret: Self = from_str(&config) .expect(format!("Failed to parse config file {}", &config_file_path).as_str()); ret } diff --git a/ica-rs/src/data_struct/messages.rs b/ica-rs/src/data_struct/messages.rs index e9d07c4..8c7635c 100644 --- a/ica-rs/src/data_struct/messages.rs +++ b/ica-rs/src/data_struct/messages.rs @@ -4,7 +4,6 @@ use crate::data_struct::{MessageId, RoomId, UserId}; use chrono::NaiveDateTime; use serde::{Deserialize, Serialize}; use serde_json::Value as JsonValue; -use tracing::warn; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum At { @@ -103,33 +102,6 @@ pub struct NewMessage { } impl NewMessage { - /// export default interface Message { - /// _id: string | number - /// senderId?: number - /// username: string - /// content: string - /// code?: string - /// timestamp?: string - /// date?: string - /// role?: string - /// file?: MessageFile - /// files: MessageFile[] - /// time?: number - /// replyMessage?: Message - /// at?: boolean | 'all' - /// deleted?: boolean - /// system?: boolean - /// mirai?: MessageMirai - /// reveal?: boolean - /// flash?: boolean - /// title?: string - /// anonymousId?: number - /// anonymousflag?: string - /// hide?: boolean - /// bubble_id?: number - /// subid?: number - /// head_img?: string - /// } pub fn new_from_json(json: &JsonValue) -> Self { // room id 还是必定有的 let room_id = json["roomId"].as_i64().unwrap(); @@ -155,16 +127,19 @@ impl NewMessage { // 身份 let role = message["role"].as_str().unwrap_or("unknown"); // 文件 - let files: Vec = message["files"] - .as_array() - .unwrap_or(&Vec::new()) - .iter() - .map(|value| serde_json::from_value(value.clone()).unwrap()) - .collect(); + let value_files = message["files"].as_array().unwrap_or(&Vec::new()).to_vec(); + let mut files = Vec::with_capacity(value_files.len()); + for file in &value_files { + let file = serde_json::from_value::(file.clone()); + if let Ok(file) = file { + files.push(file); + } + } // 回复的消息 - let reply: Option = message - .get("replyMessage") - .map(|value| serde_json::from_value(value.clone()).unwrap()); + let reply: Option = match message.get("replyMessage") { + Some(value) => serde_json::from_value::(value.clone()).ok(), + None => None, + }; // At let at = At::new_from_json(&message["at"]); // 是否已撤回 @@ -178,7 +153,7 @@ impl NewMessage { // flash let flash = message["flash"].as_bool().unwrap_or(false); // "群主授予的头衔" - let title = message["title"].as_str().unwrap(); + let title = message["title"].as_str().unwrap_or(""); // anonymous id let anonymous_id = message["anonymousId"].as_i64(); // 是否已被隐藏 @@ -233,6 +208,9 @@ impl NewMessage { } } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SendMessage {} + #[cfg(test)] mod test { use serde_json::json; diff --git a/ica-rs/src/events.rs b/ica-rs/src/events.rs index 1fcf19a..2325ae7 100644 --- a/ica-rs/src/events.rs +++ b/ica-rs/src/events.rs @@ -2,9 +2,9 @@ use colored::Colorize; use rust_socketio::{Event, Payload, RawClient}; use tracing::{info, warn}; +use crate::data_struct::all_rooms::Room; use crate::data_struct::messages::NewMessage; use crate::data_struct::online_data::OnlineData; -use crate::data_struct::all_rooms::Room; use crate::py; /// 获取在线数据 @@ -53,7 +53,10 @@ pub fn update_all_room(payload: Payload, _client: RawClient) { .iter() .map(|room| Room::new_from_json(room)) .collect(); - info!("update_all_room {}", format!("{:#?}", rooms).purple()); + unsafe { + crate::ClientStatus.update_rooms(rooms.clone()); + } + info!("update_all_room {}", rooms.len()); } } } @@ -82,6 +85,20 @@ pub fn any_event(event: Event, payload: Payload, _client: RawClient) { return; } } + Event::Message => { + match payload { + Payload::Text(values) => { + if let Some(value) = values.first() { + if handled.contains(&value.as_str().unwrap()) { + return; + } + info!("收到消息 {}", value.to_string().yellow()); + } + } + _ => (), + } + return; + } _ => (), } match payload { @@ -114,7 +131,10 @@ pub fn connect_callback(payload: Payload, _client: RawClient) { Some("authRequired") => { warn!("{}", "需要登录到 icalingua!".yellow()) } - _ => (), + Some(msg) => { + warn!("未知消息 {}", msg.yellow()) + } + None => (), } } } diff --git a/ica-rs/src/main.rs b/ica-rs/src/main.rs index 61c2f14..c68c606 100644 --- a/ica-rs/src/main.rs +++ b/ica-rs/src/main.rs @@ -31,7 +31,7 @@ fn main() { .transport_type(rust_socketio::TransportType::Websocket) .on_any(events::any_event) .on("requireAuth", move |a, b| ica_singer.sign_callback(a, b)) - .on("authRequired", events::connect_callback) + .on("message", events::connect_callback) .on("authSucceed", events::connect_callback) .on("authFailed", events::connect_callback) .on("onlineData", events::get_online_data) diff --git a/ica-rs/src/py/class.rs b/ica-rs/src/py/class.rs new file mode 100644 index 0000000..87b6779 --- /dev/null +++ b/ica-rs/src/py/class.rs @@ -0,0 +1,106 @@ +use pyo3::prelude::*; + +use crate::ClientStatus; + +#[pyclass] +#[pyo3(name = "IcaStatus")] +pub struct IcaStatusPy {} + +#[pymethods] +impl IcaStatusPy { + #[new] + pub fn py_new() -> Self { + Self {} + } + + #[getter] + pub fn get_login(&self) -> bool { + unsafe { ClientStatus.login } + } + + #[getter] + pub fn get_self_id(&self) -> Option { + unsafe { + match ClientStatus.online_data.as_ref() { + Some(data) => Some(data.qqid), + None => None, + } + } + } + + #[getter] + pub fn get_nicn_name(&self) -> Option { + unsafe { + match ClientStatus.online_data.as_ref() { + Some(data) => Some(data.nick.clone()), + None => None, + } + } + } + + #[getter] + pub fn get_online(&self) -> bool { + unsafe { + match ClientStatus.online_data.as_ref() { + Some(data) => data.online, + None => false, + } + } + } + + #[getter] + pub fn get_ica_version(&self) -> Option { + unsafe { + match ClientStatus.online_data.as_ref() { + Some(data) => Some(data.icalingua_info.ica_version.clone()), + None => None, + } + } + } + + #[getter] + pub fn get_os_info(&self) -> Option { + unsafe { + match ClientStatus.online_data.as_ref() { + Some(data) => Some(data.icalingua_info.os_info.clone()), + None => None, + } + } + } + + #[getter] + pub fn get_resident_set_size(&self) -> Option { + unsafe { + match ClientStatus.online_data.as_ref() { + Some(data) => Some(data.icalingua_info.resident_set_size.clone()), + None => None, + } + } + } + + #[getter] + pub fn get_heap_used(&self) -> Option { + unsafe { + match ClientStatus.online_data.as_ref() { + Some(data) => Some(data.icalingua_info.heap_used.clone()), + None => None, + } + } + } + + #[getter] + pub fn get_load(&self) -> Option { + unsafe { + match ClientStatus.online_data.as_ref() { + Some(data) => Some(data.icalingua_info.load.clone()), + None => None, + } + } + } +} + +impl IcaStatusPy { + pub fn new() -> Self { + Self {} + } +} diff --git a/ica-rs/src/py.rs b/ica-rs/src/py/mod.rs similarity index 97% rename from ica-rs/src/py.rs rename to ica-rs/src/py/mod.rs index 698fe93..b17d6d5 100644 --- a/ica-rs/src/py.rs +++ b/ica-rs/src/py/mod.rs @@ -1,3 +1,5 @@ +pub mod class; + use pyo3::{prelude::*, types::IntoPyDict}; use tracing::{debug, info};