From b3e2da9df602f36256e075f4b08b248377e440a8 Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Sat, 30 Mar 2024 14:24:19 +0800 Subject: [PATCH] tailchat p3 --- ica-rs/ica_typing.py | 47 ++++++++++++++------ ica-rs/src/config.rs | 33 ++++++++++++-- ica-rs/src/error.rs | 12 +++++ ica-rs/src/ica/client.rs | 2 +- ica-rs/src/py/call.rs | 82 ++++++++++++++++++++++------------- ica-rs/src/py/mod.rs | 3 +- ica-rs/src/tailchat.rs | 10 +++-- ica-rs/src/tailchat/events.rs | 1 + 8 files changed, 138 insertions(+), 52 deletions(-) diff --git a/ica-rs/ica_typing.py b/ica-rs/ica_typing.py index 4a2b824..95ca56e 100644 --- a/ica-rs/ica_typing.py +++ b/ica-rs/ica_typing.py @@ -2,16 +2,30 @@ from typing import Callable, Tuple + """ +ica.rs pub type RoomId = i64; pub type UserId = i64; pub type MessageId = String; """ +class IcaType: + RoomId = int + UserId = int + MessageId = str -RoomId = int -UserId = int -MessageId = str - +""" +tailchat.rs +pub type GroupId = String; +pub type ConverseId = String; +pub type UserId = String; +pub type MessageId = String; +""" +class TailchatType: + GroupId = str + ConverseId = str + UserId = str + MessageId = str class IcaStatus: """ @@ -25,7 +39,7 @@ class IcaStatus: def online(self) -> bool: ... @property - def self_id(self) -> UserId: + def self_id(self) -> IcaType.UserId: ... @property def nick_name(self) -> str: @@ -82,13 +96,13 @@ class IcaNewMessage: def __str__(self) -> str: ... @property - def id(self) -> MessageId: + def id(self) -> IcaType.MessageId: ... @property def content(self) -> str: ... @property - def sender_id(self) -> UserId: + def sender_id(self) -> IcaType.UserId: ... @property def is_from_self(self) -> bool: @@ -103,7 +117,7 @@ class IcaNewMessage: def is_chat_msg(self) -> bool: """是否是私聊消息""" @property - def room_id(self) -> RoomId: + def room_id(self) -> IcaType.RoomId: """ 如果是群聊消息, 返回 (-群号) 如果是私聊消息, 返回 对面qq @@ -148,10 +162,17 @@ class IcaClient: """向日志中输出警告信息""" -class MatrixClient: +class TailchatClient: """ - Matrix 的客户端 + Tailchat 的客户端 """ + + def debug(self, message: str) -> None: + """向日志中输出调试信息""" + def info(self, message: str) -> None: + """向日志中输出信息""" + def warn(self, message: str) -> None: + """向日志中输出警告信息""" class ConfigData: @@ -169,12 +190,12 @@ on_ica_message = Callable[[IcaNewMessage, IcaClient], None] # def on_message(msg: NewMessage, client: IcaClient) -> None: # ... -on_ica_delete_message = Callable[[MessageId, IcaClient], None] +on_ica_delete_message = Callable[[IcaType.MessageId, IcaClient], None] # def on_delete_message(msg_id: MessageId, client: IcaClient) -> None: # ... -# TODO: Matrix adapter -on_matrix_message = Callable[[], None] +# TODO: Tailchat adapter +on_tailchat_message = Callable[[], None] on_config = Callable[[None], Tuple[str, str]] diff --git a/ica-rs/src/config.rs b/ica-rs/src/config.rs index dda3de3..12dbd25 100644 --- a/ica-rs/src/config.rs +++ b/ica-rs/src/config.rs @@ -5,6 +5,8 @@ use serde::Deserialize; use toml::from_str; use tracing::warn; +use crate::data_struct::{ica, tailchat}; + /// Icalingua bot 的配置 #[derive(Debug, Clone, Deserialize)] pub struct IcaConfig { @@ -13,15 +15,33 @@ pub struct IcaConfig { /// icalingua 服务器地址 pub host: String, /// bot 的 qq - pub self_id: u64, + pub self_id: ica::UserId, /// 提醒的房间 - pub notice_room: Vec, + pub notice_room: Vec, /// 是否提醒 pub notice_start: bool, /// 管理员列表 - pub admin_list: Vec, + pub admin_list: Vec, /// 过滤列表 - pub filter_list: Vec, + pub filter_list: Vec, +} + +#[derive(Debug, Clone, Deserialize)] +pub struct TailchatConfig { + /// 服务器地址 + pub host: String, + /// 机器人 App ID + pub app_id: String, + /// 机器人 App Secret + pub app_secret: String, + /// 提醒的房间 + pub notice_room: Vec<(tailchat::GroupId, tailchat::ConverseId)>, + /// 是否提醒 + pub notice_start: bool, + /// 管理员列表 + pub admin_list: Vec, + /// 过滤列表 + pub filter_list: Vec, } #[derive(Debug, Clone, Deserialize)] @@ -40,6 +60,11 @@ pub struct BotConfig { /// Ica 配置 pub ica: Option, + /// 是否启用 Tailchat + pub enable_tailchat: Option, + /// Tailchat 配置 + pub tailchat: Option, + /// 是否启用 Python 插件 pub enable_py: Option, /// Python 插件配置 diff --git a/ica-rs/src/error.rs b/ica-rs/src/error.rs index e87225b..27e338a 100644 --- a/ica-rs/src/error.rs +++ b/ica-rs/src/error.rs @@ -12,6 +12,8 @@ pub enum IcaError { pub enum TailchatError { /// Socket IO 链接错误 SocketIoError(rust_socketio::error::Error), + /// reqwest 相关错误 + ReqwestError(reqwest::Error), /// 登录失败 LoginFailed(String), } @@ -35,6 +37,14 @@ impl From for IcaError { fn from(e: rust_socketio::Error) -> Self { IcaError::SocketIoError(e) } } +impl From for TailchatError { + fn from(e: rust_socketio::Error) -> Self { TailchatError::SocketIoError(e) } +} + +impl From for TailchatError { + fn from(e: reqwest::Error) -> Self { TailchatError::ReqwestError(e) } +} + impl std::fmt::Display for IcaError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -48,6 +58,7 @@ impl std::fmt::Display for TailchatError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { TailchatError::SocketIoError(e) => write!(f, "Socket IO 链接错误: {}", e), + TailchatError::ReqwestError(e) => write!(f, "Reqwest 错误: {}", e), TailchatError::LoginFailed(e) => write!(f, "登录失败: {}", e), } } @@ -85,6 +96,7 @@ impl std::error::Error for TailchatError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { TailchatError::SocketIoError(e) => Some(e), + TailchatError::ReqwestError(e) => Some(e), TailchatError::LoginFailed(_) => None, } } diff --git a/ica-rs/src/ica/client.rs b/ica-rs/src/ica/client.rs index f7ab959..4ebb7ca 100644 --- a/ica-rs/src/ica/client.rs +++ b/ica-rs/src/ica/client.rs @@ -57,7 +57,7 @@ async fn inner_sign(payload: Payload, client: Client) -> ClientResult<(), IcaErr let (auth_key, version) = (&require_data[0], &require_data[1]); debug!("auth_key: {:?}, server_version: {:?}", auth_key, version); - + let auth_key = match &require_data.first() { Some(Value::String(auth_key)) => Ok(auth_key), _ => Err(IcaError::LoginFailed("Got a invalid auth_key".to_string())), diff --git a/ica-rs/src/py/call.rs b/ica-rs/src/py/call.rs index fc4dbb3..9a6005f 100644 --- a/ica-rs/src/py/call.rs +++ b/ica-rs/src/py/call.rs @@ -96,8 +96,21 @@ pub const ICA_DELETE_MESSAGE_FUNC: &str = "on_ica_delete_message"; pub const TAILCHAT_NEW_MESSAGE_FUNC: &str = "on_tailchat_message"; macro_rules! call_py_func { - ($args:expr, $func_name:expr, $client:expr) => { - + ($args:expr, $plugin:expr, $plugin_path:expr, $func_name:expr, $client:expr) => { + tokio::spawn(async move { + Python::with_gil(|py| { + if let Ok(py_func) = get_func($plugin.py_module.bind(py), $func_name) { + if let Err(e) = py_func.call1($args) { + let e = PyPluginError::FuncCallError( + e, + $func_name.to_string(), + $plugin_path.to_string_lossy().to_string(), + ); + warn!("failed to call function<{}>: {:?}", $func_name, e); + } + } + }) + }) }; } @@ -112,20 +125,21 @@ pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Cl let client = class::ica::IcaClientPy::new(client); let args = (msg, client); // 甚至实际上压根不需要await这个spawn, 直接让他自己跑就好了(离谱) - tokio::spawn(async move { - Python::with_gil(|py| { - if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_NEW_MESSAGE_FUNC) { - if let Err(e) = py_func.call1(args) { - let e = PyPluginError::FuncCallError( - e, - ICA_NEW_MESSAGE_FUNC.to_string(), - path.to_string_lossy().to_string(), - ); - warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e); - } - } - }) - }); + call_py_func!(args, plugin, path, ICA_NEW_MESSAGE_FUNC, client); + // tokio::spawn(async move { + // Python::with_gil(|py| { + // if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_NEW_MESSAGE_FUNC) { + // if let Err(e) = py_func.call1(args) { + // let e = PyPluginError::FuncCallError( + // e, + // ICA_NEW_MESSAGE_FUNC.to_string(), + // path.to_string_lossy().to_string(), + // ); + // warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e); + // } + // } + // }) + // }); } } @@ -137,23 +151,31 @@ pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) { let msg_id = msg_id.clone(); let client = class::ica::IcaClientPy::new(client); let args = (msg_id.clone(), client); - tokio::spawn(async move { - Python::with_gil(|py| { - if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_DELETE_MESSAGE_FUNC) { - if let Err(e) = py_func.call1(args) { - let e = PyPluginError::FuncCallError( - e, - ICA_DELETE_MESSAGE_FUNC.to_string(), - path.to_string_lossy().to_string(), - ); - warn!("failed to call function<{}>: {:?}", ICA_DELETE_MESSAGE_FUNC, e); - } - } - }) - }); + call_py_func!(args, plugin, path, ICA_DELETE_MESSAGE_FUNC, client); + // tokio::spawn(async move { + // Python::with_gil(|py| { + // if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_DELETE_MESSAGE_FUNC) { + // if let Err(e) = py_func.call1(args) { + // let e = PyPluginError::FuncCallError( + // e, + // ICA_DELETE_MESSAGE_FUNC.to_string(), + // path.to_string_lossy().to_string(), + // ); + // warn!("failed to call function<{}>: {:?}", ICA_DELETE_MESSAGE_FUNC, e); + // } + // } + // }) + // }); } } pub async fn tailchat_new_message_py(message: tailchat::messages::ReciveMessage, client: &Client) { + verify_plugins(); + let plugins = PyStatus::get_files(); + for (path, plugin) in plugins.iter() { + // let msg = class::tailchat:: + let args = (); + call_py_func!(args, plugin, path, TAILCHAT_NEW_MESSAGE_FUNC, client); + } } diff --git a/ica-rs/src/py/mod.rs b/ica-rs/src/py/mod.rs index f50bae1..90f1296 100644 --- a/ica-rs/src/py/mod.rs +++ b/ica-rs/src/py/mod.rs @@ -96,7 +96,8 @@ impl TryFrom for PyPlugin { }; match config_value { Ok(config) => { - let py_config = Bound::new(py, class::ConfigDataPy::new(config)).unwrap(); + let py_config = + Bound::new(py, class::ConfigDataPy::new(config)).unwrap(); module.setattr("CONFIG_DATA", py_config).unwrap(); Ok(PyPlugin { file_path: path, diff --git a/ica-rs/src/tailchat.rs b/ica-rs/src/tailchat.rs index 239581e..4a60844 100644 --- a/ica-rs/src/tailchat.rs +++ b/ica-rs/src/tailchat.rs @@ -1,6 +1,7 @@ pub mod events; use futures_util::FutureExt; +use reqwest::ClientBuilder as reqwest_ClientBuilder; use rust_socketio::asynchronous::{Client, ClientBuilder}; use rust_socketio::{Event, Payload, TransportType}; use tracing::{event, span, Level}; @@ -14,10 +15,13 @@ pub async fn start_tailchat() -> ClientResult<(), TailchatError> { event!(Level::INFO, "tailchat-async-rs v{} initing", crate::TAILCHAT_VERSION); + let tailchat_req = reqwest_ClientBuilder::new().build()?; + + // tailchat_req.get("http://localhost:8080").send().await?; + // let socket = match ClientBuilder::new() { - + // }; - + Ok(()) } - diff --git a/ica-rs/src/tailchat/events.rs b/ica-rs/src/tailchat/events.rs index e69de29..8b13789 100644 --- a/ica-rs/src/tailchat/events.rs +++ b/ica-rs/src/tailchat/events.rs @@ -0,0 +1 @@ +