diff --git a/ica-rs/src/py/class.rs b/ica-rs/src/py/class.rs index 5113712..62ec382 100644 --- a/ica-rs/src/py/class.rs +++ b/ica-rs/src/py/class.rs @@ -1,352 +1,16 @@ +pub mod config; pub mod ica; +pub mod schdule; pub mod tailchat; -use std::collections::HashMap; - use pyo3::{ pyclass, pymethods, pymodule, - types::{ - PyAnyMethods, PyBool, PyBoolMethods, PyDict, PyDictMethods, PyFloat, PyInt, PyList, - PyListMethods, PyModule, PyModuleMethods, PyString, PyStringMethods, PyTypeMethods, - }, + types::{PyBool, PyModule, PyModuleMethods, PyString}, Bound, IntoPyObject, PyAny, PyRef, PyResult, }; use toml::Value as TomlValue; use tracing::{event, Level}; -#[derive(Debug, Clone)] -pub enum ConfigItem { - None, - String(String), - Int(i64), - Float(f64), - Bool(bool), - Array(Vec), - Table(HashMap), -} - -#[derive(Clone, Debug)] -#[pyclass] -#[pyo3(name = "ConfigItem")] -pub struct ConfigItemPy { - pub item: ConfigItem, - pub default_value: ConfigItem, -} - -impl ConfigItemPy { - pub fn new(item: ConfigItem, default_value: ConfigItem) -> Self { - Self { - item, - default_value, - } - } - - pub fn new_uninit(default_value: ConfigItem) -> Self { - Self { - item: ConfigItem::None, - default_value, - } - } -} - -#[derive(Clone)] -#[pyclass] -#[pyo3(name = "ConfigStorage")] -pub struct ConfigStoragePy { - pub keys: HashMap, -} - -/// Storage 里允许的最大层级深度 -/// -/// 我也不知道为啥就突然有这玩意了( -pub const MAX_CFG_DEPTH: usize = 10; - -fn parse_py_string(obj: &Bound<'_, PyAny>) -> PyResult { - let py_str = obj.downcast::()?; - let value = py_str.to_str()?; - Ok(value.to_string()) -} - -fn parse_py_bool(obj: &Bound<'_, PyAny>) -> PyResult { - let py_bool = obj.downcast::()?; - Ok(py_bool.is_true()) -} - -fn parse_py_int(obj: &Bound<'_, PyAny>) -> PyResult { - let py_int = obj.downcast::()?; - py_int.extract::() -} - -fn parse_py_float(obj: &Bound<'_, PyAny>) -> PyResult { - let py_float = obj.downcast::()?; - py_float.extract::() -} - -impl ConfigStoragePy { - /// 递归 list 解析配置 - /// - /// 用个 Result 来标记递归过深 - fn parse_py_list( - args: &Bound<'_, PyList>, - list: &mut Vec, - current_deepth: usize, - ) -> Result<(), usize> { - if current_deepth > MAX_CFG_DEPTH { - return Err(current_deepth); - } else { - for value in args.iter() { - // 匹配 item - let value_type = value.get_type(); - if value_type.is_instance_of::() { - let py_dict = value.downcast::().unwrap(); - let mut new_map = HashMap::new(); - match Self::parse_py_dict(py_dict, &mut new_map, current_deepth + 1) { - Ok(_) => { - list.push(ConfigItemPy::new_uninit(ConfigItem::Table(new_map))); - } - Err(e) => { - event!( - Level::WARN, - "value(dict) 解析时出现错误: {}\nraw: {}", - e, - value - ); - } - } - } else if value_type.is_instance_of::() { - let py_list = value.downcast::().unwrap(); - let mut new_list = Vec::new(); - match Self::parse_py_list(py_list, &mut new_list, current_deepth + 1) { - Ok(_) => { - list.push(ConfigItemPy::new_uninit(ConfigItem::Array(new_list))); - } - Err(e) => { - event!( - Level::WARN, - "value(list) 解析时出现错误: {}\nraw: {}", - e, - value - ); - } - } - } else if value_type.is_instance_of::() { - match parse_py_string(&value) { - Ok(value) => { - list.push(ConfigItemPy::new_uninit(ConfigItem::String(value))); - } - Err(e) => { - event!( - Level::WARN, - "value(string) 解析时出现错误: {}\nraw: {}", - e, - value - ); - } - } - } else if value_type.is_instance_of::() { - match parse_py_bool(&value) { - Ok(value) => { - list.push(ConfigItemPy::new_uninit(ConfigItem::Bool(value))); - } - Err(e) => { - event!( - Level::WARN, - "value(bool) 解析时出现错误: {}\nraw: {}", - e, - value - ); - } - } - } else if value_type.is_instance_of::() { - match parse_py_int(&value) { - Ok(value) => { - list.push(ConfigItemPy::new_uninit(ConfigItem::Int(value))); - } - Err(e) => { - event!(Level::WARN, "value(int) 解析时出现错误: {}\nraw: {}", e, value); - } - } - } else if value_type.is_instance_of::() { - match parse_py_float(&value) { - Ok(value) => { - list.push(ConfigItemPy::new_uninit(ConfigItem::Float(value))); - } - Err(e) => { - event!( - Level::WARN, - "value(float) 解析时出现错误: {}\nraw: {}", - e, - value - ); - } - } - } else { - // 先丢个 warning 出去 - match value_type.name() { - Ok(type_name) => { - event!( - Level::WARN, - "value 为不支持的 {} 类型\nraw: {}", - type_name, - value - ) - } - Err(e) => { - event!( - Level::WARN, - "value 为不支持的类型 (获取类型名失败: {})\nraw: {}", - e, - value - ) - } - } - } - } - } - Ok(()) - } - - /// 递归 dict 解析配置 - /// - /// 用个 Result 来标记递归过深 - fn parse_py_dict( - kwargs: &Bound<'_, PyDict>, - map: &mut HashMap, - current_deepth: usize, - ) -> Result<(), usize> { - if current_deepth > MAX_CFG_DEPTH { - Err(current_deepth) - } else { - for (key, value) in kwargs.iter() { - if let Ok(name) = key.downcast::() { - let name = name.to_string(); - // 匹配 item - let value_type = value.get_type(); - if value_type.is_instance_of::() { - let py_dict = value.downcast::().unwrap(); - let mut new_map = HashMap::new(); - match Self::parse_py_dict(py_dict, &mut new_map, current_deepth + 1) { - Ok(_) => { - map.insert( - name.clone(), - ConfigItemPy::new_uninit(ConfigItem::Table(new_map)), - ); - } - Err(e) => { - event!(Level::WARN, "value(dict) {} 解析时出现错误: {}", name, e); - } - } - } else if value_type.is_instance_of::() { - let py_list = value.downcast::().unwrap(); - let mut new_list = Vec::new(); - match Self::parse_py_list(py_list, &mut new_list, current_deepth + 1) { - Ok(_) => { - map.insert( - name.clone(), - ConfigItemPy::new_uninit(ConfigItem::Array(new_list)), - ); - } - Err(e) => { - event!(Level::WARN, "value(list) {} 解析时出现错误: {}", name, e); - } - } - } else if value_type.is_instance_of::() { - match parse_py_string(&value) { - Ok(value) => { - map.insert( - name.clone(), - ConfigItemPy::new_uninit(ConfigItem::String(value)), - ); - } - Err(e) => { - event!(Level::WARN, "value(string) {} 解析时出现错误: {}", name, e); - } - } - } else if value_type.is_instance_of::() { - match parse_py_bool(&value) { - Ok(value) => { - map.insert( - name.clone(), - ConfigItemPy::new_uninit(ConfigItem::Bool(value)), - ); - } - Err(e) => { - event!(Level::WARN, "value(bool) {} 解析时出现错误: {}", name, e); - } - } - } else if value_type.is_instance_of::() { - match parse_py_int(&value) { - Ok(value) => { - map.insert( - name.clone(), - ConfigItemPy::new_uninit(ConfigItem::Int(value)), - ); - } - Err(e) => { - event!(Level::WARN, "value(int) {} 解析时出现错误: {}", name, e); - } - } - } else if value_type.is_instance_of::() { - match parse_py_float(&value) { - Ok(value) => { - map.insert( - name.clone(), - ConfigItemPy::new_uninit(ConfigItem::Float(value)), - ); - } - Err(e) => { - event!(Level::WARN, "value(float) {} 解析时出现错误: {}", name, e); - } - } - } else { - // 先丢个 warning 出去 - match value_type.name() { - Ok(type_name) => { - event!(Level::WARN, "value {} 为不支持的 {} 类型", name, type_name) - } - Err(e) => event!( - Level::WARN, - "value {} 为不支持的类型 (获取类型名失败: {})", - name, - e - ), - } - continue; - } - } - } - Ok(()) - } - } -} - -#[pymethods] -impl ConfigStoragePy { - #[new] - #[pyo3(signature = (**kwargs))] - pub fn new(kwargs: Option<&Bound<'_, PyDict>>) -> PyResult { - match kwargs { - Some(kwargs) => { - let mut keys = HashMap::new(); - // 解析 kwargs - Self::parse_py_dict(kwargs, &mut keys, 0).map_err(|e| { - event!(Level::ERROR, "配置解析过深: {}", e); - pyo3::exceptions::PyValueError::new_err(format!("配置解析过深: {}", e)) - })?; - // 解析完成 - Ok(Self { keys }) - } - None => Ok(Self { - keys: HashMap::new(), - }), - } - } - - #[getter] - /// 获取最大允许的层级深度 - pub fn get_max_allowed_depth(&self) -> usize { MAX_CFG_DEPTH } -} - #[derive(Clone)] #[pyclass] #[pyo3(name = "ConfigData")] @@ -392,7 +56,7 @@ impl ConfigDataPy { #[pyo3(name = "shenbot_api")] fn rs_api_module(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; - m.add_class::()?; + m.add_class::()?; Ok(()) } diff --git a/ica-rs/src/py/class/config.rs b/ica-rs/src/py/class/config.rs new file mode 100644 index 0000000..b6a4b3c --- /dev/null +++ b/ica-rs/src/py/class/config.rs @@ -0,0 +1,344 @@ +use std::collections::HashMap; + +use pyo3::{ + pyclass, pymethods, + types::{ + PyAnyMethods, PyBool, PyBoolMethods, PyDict, PyDictMethods, PyFloat, PyInt, PyList, + PyListMethods, PyString, PyStringMethods, PyTypeMethods, + }, + Bound, PyAny, PyResult, +}; +use tracing::{event, Level}; + +#[derive(Debug, Clone)] +pub enum ConfigItem { + None, + String(String), + Int(i64), + Float(f64), + Bool(bool), + Array(Vec), + Table(HashMap), +} + +#[derive(Clone, Debug)] +#[pyclass] +#[pyo3(name = "ConfigItem")] +pub struct ConfigItemPy { + pub item: ConfigItem, + pub default_value: ConfigItem, +} + +impl ConfigItemPy { + pub fn new(item: ConfigItem, default_value: ConfigItem) -> Self { + Self { + item, + default_value, + } + } + + pub fn new_uninit(default_value: ConfigItem) -> Self { + Self { + item: ConfigItem::None, + default_value, + } + } +} + +#[derive(Clone)] +#[pyclass] +#[pyo3(name = "ConfigStorage")] +pub struct ConfigStoragePy { + pub keys: HashMap, +} + +/// Storage 里允许的最大层级深度 +/// +/// 我也不知道为啥就突然有这玩意了( +pub const MAX_CFG_DEPTH: usize = 10; + +fn parse_py_string(obj: &Bound<'_, PyAny>) -> PyResult { + let py_str = obj.downcast::()?; + let value = py_str.to_str()?; + Ok(value.to_string()) +} + +fn parse_py_bool(obj: &Bound<'_, PyAny>) -> PyResult { + let py_bool = obj.downcast::()?; + Ok(py_bool.is_true()) +} + +fn parse_py_int(obj: &Bound<'_, PyAny>) -> PyResult { + let py_int = obj.downcast::()?; + py_int.extract::() +} + +fn parse_py_float(obj: &Bound<'_, PyAny>) -> PyResult { + let py_float = obj.downcast::()?; + py_float.extract::() +} + +impl ConfigStoragePy { + /// 递归 list 解析配置 + /// + /// 用个 Result 来标记递归过深 + fn parse_py_list( + args: &Bound<'_, PyList>, + list: &mut Vec, + current_deepth: usize, + ) -> Result<(), usize> { + if current_deepth > MAX_CFG_DEPTH { + return Err(current_deepth); + } else { + for value in args.iter() { + // 匹配 item + let value_type = value.get_type(); + if value_type.is_instance_of::() { + let py_dict = value.downcast::().unwrap(); + let mut new_map = HashMap::new(); + match Self::parse_py_dict(py_dict, &mut new_map, current_deepth + 1) { + Ok(_) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Table(new_map))); + } + Err(e) => { + event!( + Level::WARN, + "value(dict) 解析时出现错误: {}\nraw: {}", + e, + value + ); + } + } + } else if value_type.is_instance_of::() { + let py_list = value.downcast::().unwrap(); + let mut new_list = Vec::new(); + match Self::parse_py_list(py_list, &mut new_list, current_deepth + 1) { + Ok(_) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Array(new_list))); + } + Err(e) => { + event!( + Level::WARN, + "value(list) 解析时出现错误: {}\nraw: {}", + e, + value + ); + } + } + } else if value_type.is_instance_of::() { + match parse_py_string(&value) { + Ok(value) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::String(value))); + } + Err(e) => { + event!( + Level::WARN, + "value(string) 解析时出现错误: {}\nraw: {}", + e, + value + ); + } + } + } else if value_type.is_instance_of::() { + match parse_py_bool(&value) { + Ok(value) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Bool(value))); + } + Err(e) => { + event!( + Level::WARN, + "value(bool) 解析时出现错误: {}\nraw: {}", + e, + value + ); + } + } + } else if value_type.is_instance_of::() { + match parse_py_int(&value) { + Ok(value) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Int(value))); + } + Err(e) => { + event!(Level::WARN, "value(int) 解析时出现错误: {}\nraw: {}", e, value); + } + } + } else if value_type.is_instance_of::() { + match parse_py_float(&value) { + Ok(value) => { + list.push(ConfigItemPy::new_uninit(ConfigItem::Float(value))); + } + Err(e) => { + event!( + Level::WARN, + "value(float) 解析时出现错误: {}\nraw: {}", + e, + value + ); + } + } + } else { + // 先丢个 warning 出去 + match value_type.name() { + Ok(type_name) => { + event!( + Level::WARN, + "value 为不支持的 {} 类型\nraw: {}", + type_name, + value + ) + } + Err(e) => { + event!( + Level::WARN, + "value 为不支持的类型 (获取类型名失败: {})\nraw: {}", + e, + value + ) + } + } + } + } + } + Ok(()) + } + + /// 递归 dict 解析配置 + /// + /// 用个 Result 来标记递归过深 + fn parse_py_dict( + kwargs: &Bound<'_, PyDict>, + map: &mut HashMap, + current_deepth: usize, + ) -> Result<(), usize> { + if current_deepth > MAX_CFG_DEPTH { + Err(current_deepth) + } else { + for (key, value) in kwargs.iter() { + if let Ok(name) = key.downcast::() { + let name = name.to_string(); + // 匹配 item + let value_type = value.get_type(); + if value_type.is_instance_of::() { + let py_dict = value.downcast::().unwrap(); + let mut new_map = HashMap::new(); + match Self::parse_py_dict(py_dict, &mut new_map, current_deepth + 1) { + Ok(_) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Table(new_map)), + ); + } + Err(e) => { + event!(Level::WARN, "value(dict) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + let py_list = value.downcast::().unwrap(); + let mut new_list = Vec::new(); + match Self::parse_py_list(py_list, &mut new_list, current_deepth + 1) { + Ok(_) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Array(new_list)), + ); + } + Err(e) => { + event!(Level::WARN, "value(list) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_string(&value) { + Ok(value) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::String(value)), + ); + } + Err(e) => { + event!(Level::WARN, "value(string) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_bool(&value) { + Ok(value) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Bool(value)), + ); + } + Err(e) => { + event!(Level::WARN, "value(bool) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_int(&value) { + Ok(value) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Int(value)), + ); + } + Err(e) => { + event!(Level::WARN, "value(int) {} 解析时出现错误: {}", name, e); + } + } + } else if value_type.is_instance_of::() { + match parse_py_float(&value) { + Ok(value) => { + map.insert( + name.clone(), + ConfigItemPy::new_uninit(ConfigItem::Float(value)), + ); + } + Err(e) => { + event!(Level::WARN, "value(float) {} 解析时出现错误: {}", name, e); + } + } + } else { + // 先丢个 warning 出去 + match value_type.name() { + Ok(type_name) => { + event!(Level::WARN, "value {} 为不支持的 {} 类型", name, type_name) + } + Err(e) => event!( + Level::WARN, + "value {} 为不支持的类型 (获取类型名失败: {})", + name, + e + ), + } + continue; + } + } + } + Ok(()) + } + } +} + +#[pymethods] +impl ConfigStoragePy { + #[new] + #[pyo3(signature = (**kwargs))] + pub fn new(kwargs: Option<&Bound<'_, PyDict>>) -> PyResult { + match kwargs { + Some(kwargs) => { + let mut keys = HashMap::new(); + // 解析 kwargs + Self::parse_py_dict(kwargs, &mut keys, 0).map_err(|e| { + event!(Level::ERROR, "配置解析过深: {}", e); + pyo3::exceptions::PyValueError::new_err(format!("配置解析过深: {}", e)) + })?; + // 解析完成 + Ok(Self { keys }) + } + None => Ok(Self { + keys: HashMap::new(), + }), + } + } + + #[getter] + /// 获取最大允许的层级深度 + pub fn get_max_allowed_depth(&self) -> usize { MAX_CFG_DEPTH } +} diff --git a/ica-rs/src/py/class/schdule.rs b/ica-rs/src/py/class/schdule.rs new file mode 100644 index 0000000..46be576 --- /dev/null +++ b/ica-rs/src/py/class/schdule.rs @@ -0,0 +1,23 @@ +use pyo3::{pyclass, pymethods, types::PyFunction, Bound, Py, PyAny, PyTraverseError, PyVisit}; +use tracing::{event, Level}; + +#[derive(Clone, Debug)] +#[pyclass] +#[pyo3(name = "Scheduler")] +/// 用于计划任务的类 +/// +/// 给 Python 侧使用 +pub struct SchedulerPy { + /// 回调函数 + /// + /// 你最好不要把他清理掉 + pub callback: Py, +} + +#[pymethods] +impl SchedulerPy { + fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> { + visit.call(&self.callback)?; + Ok(()) + } +}