diff --git a/config-temp.toml b/config-temp.toml index 90c47d7..a124b52 100644 --- a/config-temp.toml +++ b/config-temp.toml @@ -1,13 +1,18 @@ -# python 插件路径 -py_plugin_path = "/path/to/your/plugin" -py_config_path = "/path/to/your/config" # 填写 [ica] 但不填写此项则不启用 ica enable_ica = true # 是否启用 ica # 填写 [matrix] 但不填写此项则不启用 matrix enable_matrix = true # 是否启用 matrix +enable_py = true # 是否启用 python 插件 + +[py] + +# python 插件路径 +plugin_path = "/path/to/your/plugin" +config_path = "/path/to/your/config" + [ica] private_key = "" # 与 icalingua 客户端使用的 private_key 一致 diff --git a/ica-rs/src/config.rs b/ica-rs/src/config.rs index 459bbd4..8327172 100644 --- a/ica-rs/src/config.rs +++ b/ica-rs/src/config.rs @@ -39,6 +39,14 @@ pub struct MatrixConfig { pub notice_start: bool, } +#[derive(Debug, Clone, Deserialize)] +pub struct PyConfig { + /// 插件路径 + pub plugin_path: String, + /// 配置文件路径 + pub config_path: String, +} + /// 主配置 #[derive(Debug, Clone, Deserialize)] pub struct BotConfig { @@ -50,10 +58,10 @@ pub struct BotConfig { pub enable_matrix: Option, /// Matrix 配置 pub matrix: Option, - /// Python 插件路径 - pub py_plugin_path: Option, - /// Python 配置文件路径 - pub py_config_path: Option, + /// 是否启用 Python 插件 + pub enable_py: Option, + /// Python 插件配置 + pub py: Option, } impl BotConfig { @@ -109,5 +117,27 @@ impl BotConfig { } } + /// 检查是否启用 Python 插件 + pub fn check_py(&self) -> bool { + match self.enable_py { + Some(enable) => { + if enable && self.py.is_none() { + warn!("enable_py 为 true 但未填写 [py] 配置\n将不启用 Python 插件"); + false + } else { + true + } + } + None => { + if self.py.is_some() { + warn!("未填写 enable_py 但填写了 [py] 配置\n将不启用 Python 插件"); + } + false + } + } + } + pub fn ica(&self) -> IcaConfig { self.ica.clone().expect("No ica config found") } + pub fn matrix(&self) -> MatrixConfig { self.matrix.clone().expect("No matrix config found") } + pub fn py(&self) -> PyConfig { self.py.clone().expect("No py config found") } } diff --git a/ica-rs/src/error.rs b/ica-rs/src/error.rs new file mode 100644 index 0000000..e69de29 diff --git a/ica-rs/src/ica.rs b/ica-rs/src/ica.rs index 43afaea..a77f2b4 100644 --- a/ica-rs/src/ica.rs +++ b/ica-rs/src/ica.rs @@ -4,12 +4,13 @@ pub mod events; use futures_util::FutureExt; use rust_socketio::asynchronous::{Client, ClientBuilder}; use rust_socketio::{Event, Payload, TransportType}; -use tracing::info; +use tracing::{event, info, Level}; use crate::config::IcaConfig; use crate::{wrap_any_callback, wrap_callback}; pub async fn start_ica(config: &IcaConfig, stop_reciver: tokio::sync::oneshot::Receiver<()>) { + event!(Level::INFO, "ica-async-rs v{} start ica", crate::ICA_VERSION); let socket = ClientBuilder::new(config.host.clone()) .transport_type(TransportType::Websocket) .on_any(wrap_any_callback!(events::any_event)) @@ -33,7 +34,7 @@ pub async fn start_ica(config: &IcaConfig, stop_reciver: tokio::sync::oneshot::R if config.notice_start { for room in config.notice_room.iter() { let startup_msg = crate::data_struct::ica::messages::SendMessage::new( - format!("ica-async-rs bot v{}", crate::VERSION), + format!("shenbot v {}\nica-async-rs bot v{}", crate::VERSION, crate::ICA_VERSION), *room, None, ); diff --git a/ica-rs/src/ica/client.rs b/ica-rs/src/ica/client.rs index 789f9d5..1dae7f4 100644 --- a/ica-rs/src/ica/client.rs +++ b/ica-rs/src/ica/client.rs @@ -1,8 +1,7 @@ -use crate::config::{BotConfig, IcaConfig}; use crate::data_struct::ica::all_rooms::Room; use crate::data_struct::ica::messages::{DeleteMessage, SendMessage}; use crate::data_struct::ica::online_data::OnlineData; -use crate::ClientStatus_Global; +use crate::MainStatus; use colored::Colorize; use ed25519_dalek::{Signature, Signer, SigningKey}; @@ -46,93 +45,6 @@ pub async fn delete_message(client: &Client, message: &DeleteMessage) -> bool { // #[allow(dead_code)] // pub async fn fetch_history(client: &Client, roomd_id: RoomId) -> bool { false } -#[derive(Debug, Clone)] -pub struct BotStatus { - pub login: bool, - /// currentLoadedMessagesCount - pub current_loaded_messages_count: u64, - pub online_data: Option, - pub rooms: Option>, - pub config: Option, -} - -impl Default for BotStatus { - fn default() -> Self { Self::new() } -} - -impl BotStatus { - pub fn new() -> Self { - Self { - login: false, - current_loaded_messages_count: 0, - online_data: None, - rooms: None, - config: Some(BotConfig::new_from_cli()), - } - } - - #[inline] - pub fn update_online_data(online_data: OnlineData) { - unsafe { - ClientStatus_Global.online_data = Some(online_data); - } - } - #[inline] - pub fn update_rooms(rooms: Vec) { - unsafe { - ClientStatus_Global.rooms = Some(rooms); - } - } - #[inline] - pub fn update_login_status(login: bool) { - unsafe { - ClientStatus_Global.login = login; - } - } - #[inline] - pub fn update_config(config: BotConfig) { - unsafe { - ClientStatus_Global.config = Some(config); - } - } - #[inline] - pub fn update_loaded_messages_count(count: u64) { - unsafe { - ClientStatus_Global.current_loaded_messages_count = count; - } - } - #[inline] - pub fn get_login_status() -> bool { unsafe { ClientStatus_Global.login } } - #[inline] - pub fn get_rooms() -> &'static Vec { - unsafe { ClientStatus_Global.rooms.as_ref().expect("rooms should be set") } - } - #[inline] - pub fn get_loaded_messages_count() -> u64 { - unsafe { ClientStatus_Global.current_loaded_messages_count } - } - #[inline] - pub fn get_online_data() -> &'static OnlineData { - unsafe { ClientStatus_Global.online_data.as_ref().expect("online_data should be set") } - } - #[inline] - pub fn get_config() -> &'static BotConfig { - unsafe { ClientStatus_Global.config.as_ref().expect("config should be set") } - } - #[inline] - pub fn get_ica_config() -> &'static IcaConfig { - unsafe { - ClientStatus_Global - .config - .as_ref() - .expect("config should be set") - .ica - .as_ref() - .expect("ica should be set") - } - } -} - pub async fn sign_callback(payload: Payload, client: Client) { // 获取数据 let require_data = match payload { @@ -142,15 +54,17 @@ pub async fn sign_callback(payload: Payload, client: Client) { .expect("Payload should be Json data"); let (auth_key, version) = (&require_data[0], &require_data[1]); - debug!("auth_key: {:?}, version: {:?}", auth_key, version); + debug!("auth_key: {:?}, server_version: {:?}", auth_key, version); let auth_key = match &require_data.first() { Some(Value::String(auth_key)) => Some(auth_key), _ => None, } .expect("auth_key should be string"); + let salt = hex::decode(auth_key).expect("Got an invalid salt from the server"); // 签名 - let private_key = BotStatus::get_config().ica().private_key.clone(); + let private_key = MainStatus::global_config().ica().private_key.clone(); + let array_key: [u8; 32] = hex::decode(private_key) .expect("Not a vaild pub key") .try_into() @@ -158,6 +72,7 @@ pub async fn sign_callback(payload: Payload, client: Client) { let signing_key: SigningKey = SigningKey::from_bytes(&array_key); let signature: Signature = signing_key.sign(salt.as_slice()); + // 发送签名 let sign = signature.to_bytes().to_vec(); client.emit("auth", sign).await.expect("Faild to send signin data"); } diff --git a/ica-rs/src/main.rs b/ica-rs/src/main.rs index a42940b..6023744 100644 --- a/ica-rs/src/main.rs +++ b/ica-rs/src/main.rs @@ -10,8 +10,7 @@ mod py; mod status; use config::BotConfig; -use tracing::info; - +use tracing::{event, info, Level}; pub static mut MAIN_STATUS: status::BotStatus = status::BotStatus { config: None, @@ -22,6 +21,8 @@ pub static mut MAIN_STATUS: status::BotStatus = status::BotStatus { pub type MainStatus = status::BotStatus; pub const VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const ICA_VERSION: &str = "0.5.0"; +pub const MATRIX_VERSION: &str = "0.1.0"; #[macro_export] macro_rules! wrap_callback { @@ -40,13 +41,13 @@ macro_rules! wrap_any_callback { #[tokio::main] async fn main() { tracing_subscriber::fmt().with_max_level(tracing::Level::DEBUG).init(); - info!("ica-async-rs v{}", VERSION); + event!(Level::INFO, "shenbot-async-rs v{} main", VERSION); - // 从命令行获取 host 和 key - // 从命令行获取配置文件路径 let bot_config = BotConfig::new_from_cli(); - ica::client::BotStatus::update_config(bot_config.clone()); - py::init_py(&bot_config); + MainStatus::static_init(bot_config); + let bot_config = MainStatus::global_config(); + + py::init_py(); // 准备一个用于停止 socket 的变量 let (send, recv) = tokio::sync::oneshot::channel::<()>(); diff --git a/ica-rs/src/py/call.rs b/ica-rs/src/py/call.rs index 68da9b6..89b074d 100644 --- a/ica-rs/src/py/call.rs +++ b/ica-rs/src/py/call.rs @@ -6,8 +6,8 @@ use tracing::{debug, info, warn}; use crate::data_struct::ica::messages::NewMessage; use crate::data_struct::ica::MessageId; -use crate::ica::client::BotStatus; use crate::py::{class, PyPlugin, PyStatus}; +use crate::MainStatus; pub fn get_func<'py>(py_module: &'py PyAny, path: &PathBuf, name: &'py str) -> Option<&'py PyAny> { // 要处理的情况: diff --git a/ica-rs/src/py/class.rs b/ica-rs/src/py/class.rs index cb96ed7..4b695c9 100644 --- a/ica-rs/src/py/class.rs +++ b/ica-rs/src/py/class.rs @@ -8,8 +8,8 @@ use crate::data_struct::ica::messages::{ DeleteMessage, MessageTrait, NewMessage, ReplyMessage, SendMessage, }; use crate::data_struct::ica::MessageId; -use crate::ica::client::{delete_message, send_message, BotStatus}; -use crate::ClientStatus_Global; +use crate::ica::client::{delete_message, send_message}; +use crate::MainStatus; #[pyclass] #[pyo3(name = "IcaStatus")] @@ -20,37 +20,47 @@ impl IcaStatusPy { #[new] pub fn py_new() -> Self { Self {} } #[getter] - pub fn get_login(&self) -> bool { unsafe { ClientStatus_Global.login } } + pub fn get_qq_login(&self) -> bool { MainStatus::global_ica_status().qq_login } #[getter] - pub fn get_online(&self) -> bool { BotStatus::get_online_data().online } + pub fn get_online(&self) -> bool { MainStatus::global_ica_status().online_status.online } #[getter] - pub fn get_self_id(&self) -> i64 { BotStatus::get_online_data().qqid } + pub fn get_self_id(&self) -> i64 { MainStatus::global_ica_status().online_status.qqid } #[getter] - pub fn get_nick_name(&self) -> String { BotStatus::get_online_data().nick.clone() } + pub fn get_nick_name(&self) -> String { + MainStatus::global_ica_status().online_status.nick.clone() + } #[getter] - pub fn get_loaded_messages_count(&self) -> u64 { BotStatus::get_loaded_messages_count() } + pub fn get_loaded_messages_count(&self) -> u64 { + MainStatus::global_ica_status().current_loaded_messages_count + } #[getter] pub fn get_ica_version(&self) -> String { - BotStatus::get_online_data().icalingua_info.ica_version.clone() + MainStatus::global_ica_status().online_status.icalingua_info.ica_version.clone() } #[getter] pub fn get_os_info(&self) -> String { - BotStatus::get_online_data().icalingua_info.os_info.clone() + MainStatus::global_ica_status().online_status.icalingua_info.os_info.clone() } #[getter] pub fn get_resident_set_size(&self) -> String { - BotStatus::get_online_data().icalingua_info.resident_set_size.clone() + MainStatus::global_ica_status() + .online_status + .icalingua_info + .resident_set_size + .clone() } #[getter] pub fn get_heap_used(&self) -> String { - BotStatus::get_online_data().icalingua_info.heap_used.clone() + MainStatus::global_ica_status().online_status.icalingua_info.heap_used.clone() } #[getter] - pub fn get_load(&self) -> String { BotStatus::get_online_data().icalingua_info.load.clone() } + pub fn get_load(&self) -> String { + MainStatus::global_ica_status().online_status.icalingua_info.load.clone() + } } impl Default for IcaStatusPy { @@ -197,6 +207,10 @@ impl IcaClientPy { pub fn get_status(&self) -> IcaStatusPy { IcaStatusPy::new() } #[getter] pub fn get_version(&self) -> String { crate::VERSION.to_string() } + #[getter] + pub fn get_ica_version(&self) -> String { crate::ICA_VERSION.to_string() } + #[getter] + pub fn get_matrix_version(&self) -> String { crate::MATRIX_VERSION.to_string() } pub fn debug(&self, content: String) { debug!("{}", content); diff --git a/ica-rs/src/py/mod.rs b/ica-rs/src/py/mod.rs index a6f538f..ce35ba6 100644 --- a/ica-rs/src/py/mod.rs +++ b/ica-rs/src/py/mod.rs @@ -7,10 +7,9 @@ use std::{collections::HashMap, path::PathBuf}; use pyo3::prelude::*; use pyo3::types::PyTuple; -use tracing::{debug, info, warn}; +use tracing::{debug, info, span, warn, Level}; -use crate::config::BotConfig; -use crate::ica::client::BotStatus; +use crate::MainStatus; #[derive(Debug, Clone)] pub struct PyStatus { @@ -243,14 +242,20 @@ pub fn load_py_file(path: &PathBuf) -> std::io::Result { Ok((path.clone(), changed_time, content)) } -pub fn init_py(config: &BotConfig) { +/// Python 侧初始化 +pub fn init_py() { + // 从 全局配置中获取 python 插件路径 + let span = span!(Level::INFO, "Init Python Plugin"); + let enter = span.enter(); + + let global_config = MainStatus::global_config().py(); + debug!("initing python threads"); pyo3::prepare_freethreaded_python(); - if let Some(plugin_path) = &config.py_plugin_path { - let path = PathBuf::from(plugin_path); - load_py_plugins(&path); - debug!("python 插件列表: {:#?}", PyStatus::get_files()); - } + + let path = PathBuf::from(global_config.plugin_path); + load_py_plugins(&path); + debug!("python 插件列表: {:#?}", PyStatus::get_files()); info!("python inited") } diff --git a/ica-rs/src/status.rs b/ica-rs/src/status.rs index 300b656..a5bf3fe 100644 --- a/ica-rs/src/status.rs +++ b/ica-rs/src/status.rs @@ -1,15 +1,69 @@ use crate::config::BotConfig; +use crate::MAIN_STATUS; +#[derive(Debug, Clone)] pub struct BotStatus { pub config: Option, pub ica_status: Option, pub matrix_status: Option, } +impl BotStatus { + pub fn update_static_config(config: BotConfig) { + unsafe { + MAIN_STATUS.config = Some(config); + } + } + pub fn update_ica_status(status: ica::MainStatus) { + unsafe { + MAIN_STATUS.ica_status = Some(status); + } + } + pub fn update_matrix_status(status: matrix::MainStatus) { + unsafe { + MAIN_STATUS.matrix_status = Some(status); + } + } + + pub fn static_init(config: BotConfig) { + unsafe { + MAIN_STATUS.config = Some(config); + } + } + + 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_matrix_status() -> &'static matrix::MainStatus { + unsafe { MAIN_STATUS.matrix_status.as_ref().unwrap() } + } +} + pub mod ica { - pub struct MainStatus {} + use crate::data_struct::ica::all_rooms::Room; + use crate::data_struct::ica::online_data::OnlineData; + + #[derive(Debug, Clone)] + pub struct MainStatus { + /// 是否启用 ica + pub enable: bool, + /// qq 是否登录 + pub qq_login: bool, + /// 当前已加载的消息数量 + pub current_loaded_messages_count: u64, + /// 房间数据 + pub rooms: Vec, + /// 在线数据 (Icalingua 信息) + pub online_status: OnlineData, + } } pub mod matrix { - pub struct MainStatus {} + + #[derive(Debug, Clone)] + pub struct MainStatus { + /// 是否启用 matrix + pub enable: bool, + } }