From 585f0ca3317f1d579a6ca1967cde1de18cd06b98 Mon Sep 17 00:00:00 2001 From: shenjack <3695888@qq.com> Date: Fri, 9 Aug 2024 13:37:42 +0800 Subject: [PATCH] 0.6.11 making --- Cargo.lock | 2 +- ica-rs/Cargo.toml | 2 +- ica-rs/ica_typing.py | 315 ---------------------------------------- ica-rs/src/ica.rs | 2 +- ica-rs/src/py/call.rs | 6 +- ica-rs/src/py/config.rs | 0 ica-rs/src/py/mod.rs | 68 +++++++-- ica-rs/src/tailchat.rs | 2 +- news.md | 5 + 9 files changed, 71 insertions(+), 331 deletions(-) delete mode 100644 ica-rs/ica_typing.py create mode 100644 ica-rs/src/py/config.rs diff --git a/Cargo.lock b/Cargo.lock index 5f69dc3..4e48709 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -659,7 +659,7 @@ dependencies = [ [[package]] name = "ica-rs" -version = "0.6.10" +version = "0.6.11" dependencies = [ "anyhow", "base64 0.22.1", diff --git a/ica-rs/Cargo.toml b/ica-rs/Cargo.toml index 09451a6..897a51f 100644 --- a/ica-rs/Cargo.toml +++ b/ica-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ica-rs" -version = "0.6.10" +version = "0.6.11" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/ica-rs/ica_typing.py b/ica-rs/ica_typing.py deleted file mode 100644 index 340d1ab..0000000 --- a/ica-rs/ica_typing.py +++ /dev/null @@ -1,315 +0,0 @@ -# Python 兼容版本 3.8+ - -from typing import Callable, Tuple, NewType, Optional, Union -from datetime import datetime - -""" -ica.rs -pub type RoomId = i64; -pub type UserId = i64; -pub type MessageId = String; -""" -class IcaType: - RoomId = NewType('RoomId', int) - UserId = NewType('UserId', int) - MessageId = NewType('MessageId', str) - -""" -tailchat.rs -pub type GroupId = String; -pub type ConverseId = String; -pub type UserId = String; -pub type MessageId = String; -""" -class TailchatType: - GroupId = NewType('GroupId', str) - ConverseId = NewType('ConverseId', str) - UserId = NewType('UserId', str) - MessageId = NewType('MessageId', str) - -class IcaStatus: - """ - ica状态信息 - 此类并不存储信息, 所有方法都是实时获取 - """ - @property - def qq_login(self) -> bool: - ... - @property - def online(self) -> bool: - ... - @property - def self_id(self) -> IcaType.UserId: - ... - @property - def nick_name(self) -> str: - ... - @property - def ica_version(self) -> str: - ... - @property - def os_info(self) -> str: - ... - @property - def resident_set_size(self) -> str: - ... - @property - def head_used(self) -> str: - ... - @property - def load(self) -> str: - ... - - -class IcaReplyMessage: - ... - - -class IcaSendMessage: - @property - def content(self) -> str: - ... - @content.setter - def content(self, value: str) -> None: - ... - def with_content(self, content: str) -> "IcaSendMessage": - """ - 为了链式调用, 返回自身 - """ - self.content = content - return self - def set_img(self, file: bytes, file_type: str, as_sticker: bool): - """ - 设置消息的图片 - @param file: 图片文件 (实际上是 vec) - @param file_type: 图片类型 (MIME) (image/png; image/jpeg) - @param as_sticker: 是否作为贴纸发送 - """ - - -class IcaDeleteMessage: - def __str__(self) -> str: - ... - - -class IcaNewMessage: - """ - Icalingua 接收到新消息 - """ - def reply_with(self, message: str) -> IcaSendMessage: - """回复这条消息""" - ... - def as_deleted(self) -> IcaDeleteMessage: - ... - def __str__(self) -> str: - ... - @property - def id(self) -> IcaType.MessageId: - ... - @property - def content(self) -> str: - ... - @property - def sender_id(self) -> IcaType.UserId: - ... - @property - def is_from_self(self) -> bool: - ... - @property - def is_reply(self) -> bool: - ... - @property - def is_room_msg(self) -> bool: - """是否是群聊消息""" - ... - @property - def is_chat_msg(self) -> bool: - """是否是私聊消息""" - ... - @property - def room_id(self) -> IcaType.RoomId: - """ - 如果是群聊消息, 返回 (-群号) - 如果是私聊消息, 返回 对面qq - """ - ... - - -class IcaClient: - """ - Icalingua 的客户端 - """ - # @staticmethod - # async def send_message_a(client: "IcaClient", message: SendMessage) -> bool: - # """ - # 仅作占位, 不能使用 - # (因为目前来说, rust调用 Python端没法启动一个异步运行时 - # 所以只能 tokio::task::block_in_place 转换成同步调用) - # """ - def send_message(self, message: IcaSendMessage) -> bool: - ... - def send_and_warn(self, message: IcaSendMessage) -> bool: - """发送消息, 并在日志中输出警告信息""" - self.warn(message.content) - return self.send_message(message) - def delete_message(self, message: IcaDeleteMessage) -> bool: - ... - - @property - def status(self) -> IcaStatus: - ... - @property - def version(self) -> str: - ... - @property - def startup_time(self) -> datetime: - """请注意, 此时刻为 UTC 时刻""" - ... - @property - def ica_version(self) -> str: - """shenbot ica 的版本号""" - ... - def debug(self, message: str) -> None: - """向日志中输出调试信息""" - ... - def info(self, message: str) -> None: - """向日志中输出信息""" - ... - def warn(self, message: str) -> None: - """向日志中输出警告信息""" - ... - - -class TailchatReciveMessage: - """ - Tailchat 接收到的新消息 - """ - @property - def id(self) -> TailchatType.MessageId: - ... - @property - def content(self) -> str: - ... - @property - def sender_id(self) -> TailchatType.UserId: - ... - @property - def is_from_self(self) -> bool: - ... - @property - def is_reply(self) -> bool: - ... - @property - def group_id(self) -> Optional[TailchatType.GroupId]: - ... - @property - def converse_id(self) -> TailchatType.ConverseId: - ... - def reply_with(self, message: str) -> "TailchatSendingMessage": - """回复这条消息""" - ... - def as_reply(self, message: str) -> "TailchatSendingMessage": - """回复这条消息""" - ... - - -class TailchatSendingMessage: - """ - Tailchat 将要发送的信息 - """ - @property - def content(self) -> str: - ... - @content.setter - def content(self, value: str) -> None: - ... - @property - def group_id(self) -> Optional[TailchatType.GroupId]: - ... - @group_id.setter - def group_id(self, value: Optional[TailchatType.GroupId]) -> None: - ... - @property - def converse_id(self) -> TailchatType.ConverseId: - ... - @converse_id.setter - def converse_id(self, value: TailchatType.ConverseId) -> None: - ... - def with_content(self, content: str) -> "TailchatSendingMessage": - """ - 为了链式调用, 返回自身 - """ - self.content = content - return self - def set_img(self, file: bytes, file_name: str): - """ - 设置消息的图片 - @param file: 图片文件 (实际上是 vec) - @param file_name: 图片名称 (just_img.png) - """ - - -class TailchatClient: - """ - Tailchat 的客户端 - """ - def send_message(self, message: TailchatSendingMessage) -> bool: - ... - def send_and_warn(self, message: TailchatSendingMessage) -> bool: - """发送消息, 并在日志中输出警告信息""" - self.warn(message.content) - return self.send_message(message) - @property - def version(self) -> str: - ... - @property - def tailchat_version(self) -> str: - """tailchat 的版本号""" - ... - @property - def startup_time(self) -> datetime: - """请注意, 此时刻为 UTC 时刻""" - ... - def debug(self, message: str) -> None: - """向日志中输出调试信息""" - def info(self, message: str) -> None: - """向日志中输出信息""" - def warn(self, message: str) -> None: - """向日志中输出警告信息""" - - -class ReciveMessage(TailchatReciveMessage, IcaNewMessage): - """ - 继承了两边的消息 - 只是用来类型标记, 不能实例化 - """ - def reply_with(self, message: str) -> Union["IcaReplyMessage", "TailchatSendingMessage"]: # type: ignore - ... - - -class ConfigData: - def __getitem__(self, key: str): - ... - def have_key(self, key: str) -> bool: - ... - - -on_load = Callable[[IcaClient], None] -# def on_load(client: IcaClient) -> None: -# ... - -on_ica_message = Callable[[IcaNewMessage, IcaClient], None] -# def on_message(msg: NewMessage, client: IcaClient) -> None: -# ... - -on_ica_delete_message = Callable[[IcaType.MessageId, IcaClient], None] -# def on_delete_message(msg_id: MessageId, client: IcaClient) -> None: -# ... - -on_tailchat_message = Callable[[TailchatClient, TailchatReciveMessage], None] -# def on_tailchat_message(client: TailchatClient, msg: TailchatReciveMessage) -> None: -# ... - -on_config = Callable[[None], Tuple[str, str]] - -CONFIG_DATA: ConfigData = ConfigData() diff --git a/ica-rs/src/ica.rs b/ica-rs/src/ica.rs index 19cb648..8ad6658 100644 --- a/ica-rs/src/ica.rs +++ b/ica-rs/src/ica.rs @@ -10,7 +10,7 @@ use crate::config::IcaConfig; use crate::error::{ClientResult, IcaError}; use crate::StopGetter; -const ICA_PROTOCOL_VERSION: &str = "2.12.9"; +const ICA_PROTOCOL_VERSION: &str = "2.12.11"; pub async fn start_ica(config: &IcaConfig, stop_reciver: StopGetter) -> ClientResult<(), IcaError> { let span = span!(Level::INFO, "Icalingua Client"); diff --git a/ica-rs/src/py/call.rs b/ica-rs/src/py/call.rs index 1f8ff60..9644cad 100644 --- a/ica-rs/src/py/call.rs +++ b/ica-rs/src/py/call.rs @@ -136,7 +136,7 @@ pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Cl verify_plugins(); let plugins = PyStatus::get_files(); - for (path, plugin) in plugins.iter() { + for (path, plugin) in plugins.iter().filter(|(_, plugin)| plugin.enabled) { let msg = class::ica::NewMessagePy::new(message); let client = class::ica::IcaClientPy::new(client); let args = (msg, client); @@ -149,7 +149,7 @@ pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) { verify_plugins(); let plugins = PyStatus::get_files(); - for (path, plugin) in plugins.iter() { + for (path, plugin) in plugins.iter().filter(|(_, plugin)| plugin.enabled) { let msg_id = msg_id.clone(); let client = class::ica::IcaClientPy::new(client); let args = (msg_id.clone(), client); @@ -164,7 +164,7 @@ pub async fn tailchat_new_message_py( verify_plugins(); let plugins = PyStatus::get_files(); - for (path, plugin) in plugins.iter() { + 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); let args = (msg, client); diff --git a/ica-rs/src/py/config.rs b/ica-rs/src/py/config.rs new file mode 100644 index 0000000..e69de29 diff --git a/ica-rs/src/py/mod.rs b/ica-rs/src/py/mod.rs index bf5fb0e..46d38a5 100644 --- a/ica-rs/src/py/mod.rs +++ b/ica-rs/src/py/mod.rs @@ -1,5 +1,6 @@ pub mod call; pub mod class; +pub mod config; use std::path::Path; use std::time::SystemTime; @@ -37,6 +38,7 @@ pub struct PyPlugin { pub file_path: PathBuf, pub changed_time: Option, pub py_module: Py, + pub enabled: bool, } impl PyPlugin { @@ -75,6 +77,8 @@ impl PyPlugin { } } +pub const CONFIG_DATA_NAME: &str = "CONFIG_DATA"; + impl TryFrom for PyPlugin { type Error = PyErr; fn try_from(value: RawPyPlugin) -> Result { @@ -116,13 +120,57 @@ impl TryFrom for PyPlugin { match config_value { Ok(config) => { let py_config = - Bound::new(py, class::ConfigDataPy::new(config)).unwrap(); - module.setattr("CONFIG_DATA", py_config).unwrap(); - Ok(PyPlugin { - file_path: path, - changed_time, - py_module: module.into_py(py), - }) + Bound::new(py, class::ConfigDataPy::new(config)); + if let Err(e) = py_config { + warn!("添加配置文件信息失败: {:?}", e); + return Err(e); + } + let py_config = py_config.unwrap(); + // 先判定一下原来有没有 + match module.hasattr(CONFIG_DATA_NAME) { + Ok(true) => { + // get 过来, 后面直接覆盖, 这里用于发个警告 + match module.getattr(CONFIG_DATA_NAME) { + Ok(old_config) => { + // 先判断是不是 None, 直接忽略掉 None + // 毕竟有可能有占位 + if !old_config.is_none() { + warn!( + "Python 插件 {:?} 的配置文件信息已经存在\n原始内容: {}", + path, old_config + ); + } + } + Err(e) => { + warn!( + "Python 插件 {:?} 的配置文件信息已经存在, 但获取失败:{:?}", + path, e + ); + } + } + } + _ => {} + } + match module.setattr(CONFIG_DATA_NAME, py_config) { + Ok(()) => Ok(PyPlugin { + file_path: path, + changed_time, + py_module: module.into_py(py), + enabled: true, + }), + Err(e) => { + warn!( + "Python 插件 {:?} 的配置文件信息设置失败:{:?}", + path, e + ); + Err(PyErr::new::( + format!( + "Python 插件 {:?} 的配置文件信息设置失败:{:?}", + path, e + ), + )) + } + } } Err(e) => { warn!( @@ -141,6 +189,7 @@ impl TryFrom for PyPlugin { file_path: path, changed_time, py_module: module.into_py(py), + enabled: true, }) } else { warn!( @@ -162,6 +211,7 @@ impl TryFrom for PyPlugin { file_path: path, changed_time, py_module: module.into_py(py), + enabled: true, }) } }) @@ -278,8 +328,8 @@ pub fn init_py() { debug!("initing python threads"); pyo3::prepare_freethreaded_python(); - let path = PathBuf::from(global_config.plugin_path); - load_py_plugins(&path); + let plugin_path = PathBuf::from(global_config.plugin_path); + load_py_plugins(&plugin_path); debug!("python 插件列表: {:#?}", PyStatus::get_files()); info!("python inited") diff --git a/ica-rs/src/tailchat.rs b/ica-rs/src/tailchat.rs index 3ba0da3..8c4e418 100644 --- a/ica-rs/src/tailchat.rs +++ b/ica-rs/src/tailchat.rs @@ -101,7 +101,7 @@ pub async fn start_tailchat( event!(Level::INFO, "发送启动消息到: {}|{}", con, group); let startup_msg = crate::data_struct::tailchat::messages::SendingMessage::new_without_meta( - "ica-rs 启动成功".to_string(), + format!("shenbot v{}-{} 启动成功", crate::VERSION, crate::TAILCHAT_VERSION), con.clone(), Some(group.clone()), ); diff --git a/news.md b/news.md index 5f7fa79..6600d13 100644 --- a/news.md +++ b/news.md @@ -1,5 +1,10 @@ # 更新日志 +## 0.6.11 + +- 加入了 禁用/启用 插件功能 +- 现在会在插件加载时警告你的插件原来定义了 `CONFIG_DATA` 这一项 + ## 0.6.10 - 加了点东西 (?)