diff --git a/Cargo.lock b/Cargo.lock index 4e48709..d6df514 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -675,6 +675,7 @@ dependencies = [ "rust_socketio", "serde", "serde_json", + "thiserror", "tokio", "toml", "tracing", @@ -1557,18 +1558,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", diff --git a/ica-rs/Cargo.toml b/ica-rs/Cargo.toml index 897a51f..4079a8d 100644 --- a/ica-rs/Cargo.toml +++ b/ica-rs/Cargo.toml @@ -50,3 +50,4 @@ anyhow = { version = "1.0", features = ["backtrace"] } # log tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["time"] } +thiserror = "1.0.63" diff --git a/ica-rs/src/error.rs b/ica-rs/src/error.rs index 27e338a..58051f4 100644 --- a/ica-rs/src/error.rs +++ b/ica-rs/src/error.rs @@ -1,3 +1,5 @@ +// use thiserror::Error; + pub type ClientResult = Result; #[derive(Debug)] diff --git a/ica-rs/src/ica.rs b/ica-rs/src/ica.rs index 3ddd0fb..2e7bbb6 100644 --- a/ica-rs/src/ica.rs +++ b/ica-rs/src/ica.rs @@ -10,7 +10,8 @@ use crate::config::IcaConfig; use crate::error::{ClientResult, IcaError}; use crate::StopGetter; -const ICA_PROTOCOL_VERSION: &str = "2.12.12"; +/// icalingua 客户端的兼容版本号 +pub const ICA_PROTOCOL_VERSION: &str = "2.12.12"; pub async fn start_ica(config: &IcaConfig, stop_reciver: StopGetter) -> ClientResult<(), IcaError> { let span = span!(Level::INFO, "Icalingua Client"); @@ -80,7 +81,7 @@ pub async fn start_ica(config: &IcaConfig, stop_reciver: StopGetter) -> ClientRe event!(Level::INFO, "socketio client stopped"); Ok(()) } else { - event!(Level::ERROR, "socketio client stopped with error: {:?}", inner_e); + event!(Level::ERROR, "socketio 客户端出现了 Error: {:?}", inner_e); Err(IcaError::SocketIoError( rust_socketio::Error::IncompleteResponseFromEngineIo(inner_e), )) diff --git a/ica-rs/src/ica/client.rs b/ica-rs/src/ica/client.rs index 079dc6d..2bd6892 100644 --- a/ica-rs/src/ica/client.rs +++ b/ica-rs/src/ica/client.rs @@ -7,7 +7,7 @@ use ed25519_dalek::{Signature, Signer, SigningKey}; use rust_socketio::asynchronous::Client; use rust_socketio::Payload; use serde_json::Value; -use tracing::{debug, info, span, warn, event, Level}; +use tracing::{debug, event, span, warn, Level}; /// "安全" 的 发送一条消息 pub async fn send_message(client: &Client, message: &SendMessage) -> bool { @@ -56,7 +56,12 @@ async fn inner_sign(payload: Payload, client: Client) -> ClientResult<(), IcaErr let (auth_key, version) = (&require_data[0], &require_data[1]); - event!(Level::INFO, "服务器发过来的待签名key: {:?}, 服务端版本号: {:?}", auth_key, version); + event!( + Level::INFO, + "服务器发过来的待签名key: {:?}, 服务端版本号: {:?}", + auth_key, + version + ); // 判定和自己的兼容版本号是否 一致 let server_protocol_version = version .get("protocolVersion") diff --git a/ica-rs/src/ica/events.rs b/ica-rs/src/ica/events.rs index 1892605..d5709f0 100644 --- a/ica-rs/src/ica/events.rs +++ b/ica-rs/src/ica/events.rs @@ -25,8 +25,6 @@ pub async fn get_online_data(payload: Payload, _client: Client) { pub async fn add_message(payload: Payload, client: Client) { if let Payload::Text(values) = payload { if let Some(value) = values.first() { - let span = span!(Level::INFO, "ica new_msg"); - let _enter = span.enter(); let message: NewMessage = serde_json::from_value(value.clone()).unwrap(); // 检测是否在过滤列表内 if MainStatus::global_config().ica().filter_list.contains(&message.msg.sender_id) { @@ -184,7 +182,7 @@ pub async fn connect_callback(payload: Payload, _client: Client) { Some(msg) => { event!(Level::INFO, "{}{}", "未知消息".yellow(), msg); } - None => (), + _ => (), } } } diff --git a/ica-rs/src/py/call.rs b/ica-rs/src/py/call.rs index 9644cad..0a96f17 100644 --- a/ica-rs/src/py/call.rs +++ b/ica-rs/src/py/call.rs @@ -135,7 +135,7 @@ pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Cl // 验证插件是否改变 verify_plugins(); - let plugins = PyStatus::get_files(); + let plugins = PyStatus::get_map(); for (path, plugin) in plugins.iter().filter(|(_, plugin)| plugin.enabled) { let msg = class::ica::NewMessagePy::new(message); let client = class::ica::IcaClientPy::new(client); @@ -148,7 +148,7 @@ pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Cl pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) { verify_plugins(); - let plugins = PyStatus::get_files(); + let plugins = PyStatus::get_map(); for (path, plugin) in plugins.iter().filter(|(_, plugin)| plugin.enabled) { let msg_id = msg_id.clone(); let client = class::ica::IcaClientPy::new(client); @@ -163,7 +163,7 @@ pub async fn tailchat_new_message_py( ) { verify_plugins(); - let plugins = PyStatus::get_files(); + let plugins = PyStatus::get_map(); for (path, plugin) in plugins.iter().filter(|(_, plugin)| plugin.enabled) { let msg = class::tailchat::TailchatReceiveMessagePy::from_recive_message(message); let client = class::tailchat::TailchatClientPy::new(client); diff --git a/ica-rs/src/py/config.rs b/ica-rs/src/py/config.rs index e69de29..8b13789 100644 --- a/ica-rs/src/py/config.rs +++ b/ica-rs/src/py/config.rs @@ -0,0 +1 @@ + diff --git a/ica-rs/src/py/mod.rs b/ica-rs/src/py/mod.rs index 46d38a5..c0ed960 100644 --- a/ica-rs/src/py/mod.rs +++ b/ica-rs/src/py/mod.rs @@ -2,6 +2,7 @@ pub mod call; pub mod class; pub mod config; +use std::fmt::Display; use std::path::Path; use std::time::SystemTime; use std::{collections::HashMap, path::PathBuf}; @@ -9,18 +10,65 @@ use std::{collections::HashMap, path::PathBuf}; use colored::Colorize; use pyo3::prelude::*; use pyo3::types::PyTuple; -use tracing::{debug, info, span, warn, Level}; +use tracing::{debug, event, info, span, warn, Level}; use crate::MainStatus; #[derive(Debug, Clone)] pub struct PyStatus { - pub files: Option>, + pub files: Option, } -pub type PyPluginData = HashMap; +pub type PyPlugins = HashMap; pub type RawPyPlugin = (PathBuf, Option, String); +impl PyStatus { + pub fn init() { + unsafe { + if PYSTATUS.files.is_none() { + PYSTATUS.files = Some(HashMap::new()); + } + } + } + + pub fn add_file(path: PathBuf, plugin: PyPlugin) { Self::get_mut_map().insert(path, plugin); } + + pub fn verify_file(path: &PathBuf) -> bool { + Self::get_map().get(path).map_or(false, |plugin| plugin.verifiy()) + } + + fn get_map() -> &'static PyPlugins { + unsafe { + match PYSTATUS.files.as_ref() { + Some(files) => files, + None => { + Self::init(); + PYSTATUS.files.as_ref().unwrap() + } + } + } + } + + fn get_mut_map() -> &'static mut PyPlugins { + unsafe { + match PYSTATUS.files.as_mut() { + Some(files) => files, + None => { + Self::init(); + PYSTATUS.files.as_mut().unwrap() + } + } + } + } + + pub fn list_plugins() -> Vec { Self::get_map().keys().cloned().collect() } + + pub fn display() -> String { + let map = Self::get_map(); + format!("Python 插件 {{ {} }}", (",".join(map.keys().map(|x| x.to_string())))) + } +} + pub fn get_py_err_traceback(py_err: &PyErr) -> String { Python::with_gil(|py| match py_err.traceback_bound(py) { Some(traceback) => match traceback.format() { @@ -218,56 +266,15 @@ impl TryFrom for PyPlugin { } } -impl PyStatus { - pub fn get_files() -> &'static PyPluginData { - unsafe { - match PYSTATUS.files.as_ref() { - Some(files) => files, - None => { - PYSTATUS.files = Some(HashMap::new()); - PYSTATUS.files.as_ref().unwrap() - } - } - } - } - - pub fn add_file(path: PathBuf, plugin: PyPlugin) { - unsafe { - match PYSTATUS.files.as_mut() { - Some(files) => { - files.insert(path, plugin); - } - None => { - let mut files: PyPluginData = HashMap::new(); - files.insert(path, plugin); - PYSTATUS.files = Some(files); - } - } - } - } - - pub fn verify_file(path: &PathBuf) -> bool { - unsafe { - match PYSTATUS.files.as_ref() { - Some(files) => match files.get(path) { - Some(plugin) => plugin.verifiy(), - None => false, - }, - None => false, - } - } - } -} - pub static mut PYSTATUS: PyStatus = PyStatus { files: None }; pub fn load_py_plugins(path: &PathBuf) { if path.exists() { - info!("finding plugins in: {:?}", path); + event!(Level::INFO, "finding plugins in: {:?}", path); // 搜索所有的 py 文件 和 文件夹单层下面的 py 文件 match path.read_dir() { Err(e) => { - warn!("failed to read plugin path: {:?}", e); + event!(Level::WARN, "failed to read plugin path: {:?}", e); } Ok(dir) => { for entry in dir { @@ -284,12 +291,13 @@ pub fn load_py_plugins(path: &PathBuf) { } } } else { - warn!("plugin path not exists: {:?}", path); + event!(Level::WARN, "插件加载目录不存在: {:?}", path); } - info!( + event!( + Level::INFO, "python 插件目录: {:?} 加载完成, 加载到 {} 个插件", path, - PyStatus::get_files().len() + PyStatus::get_map().len() ); } @@ -325,12 +333,12 @@ pub fn init_py() { let global_config = MainStatus::global_config().py(); - debug!("initing python threads"); + event!(Level::INFO, "正在初始化 python"); pyo3::prepare_freethreaded_python(); let plugin_path = PathBuf::from(global_config.plugin_path); load_py_plugins(&plugin_path); - debug!("python 插件列表: {:#?}", PyStatus::get_files()); + event!(Level::DEBUG, "python 插件列表: {}", PyStatus::display()); info!("python inited") }