mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2025-04-20 11:39:54 +08:00
146 lines
4.8 KiB
Rust
146 lines
4.8 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use pyo3::prelude::*;
|
|
use rust_socketio::asynchronous::Client;
|
|
use tracing::{debug, info, warn};
|
|
|
|
use crate::data_struct::ica::messages::NewMessage;
|
|
use crate::data_struct::ica::MessageId;
|
|
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> {
|
|
// 要处理的情况:
|
|
// 1. 有这个函数
|
|
// 2. 没有这个函数
|
|
// 3. 函数不是 Callable
|
|
match py_module.hasattr(name) {
|
|
Ok(contain) => {
|
|
if contain {
|
|
match py_module.getattr(name) {
|
|
Ok(func) => {
|
|
if func.is_callable() {
|
|
Some(func)
|
|
} else {
|
|
warn!("function<{}>: {:#?} in {:?} is not callable", name, func, path);
|
|
None
|
|
}
|
|
}
|
|
Err(e) => {
|
|
warn!("failed to get function<{}> from {:?}: {:?}", name, path, e);
|
|
None
|
|
}
|
|
}
|
|
} else {
|
|
debug!("no function<{}> in module {:?}", name, path);
|
|
None
|
|
}
|
|
}
|
|
Err(e) => {
|
|
warn!("failed to check function<{}> from {:?}: {:?}", name, path, e);
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn verify_plugins() {
|
|
let mut need_reload_files: Vec<PathBuf> = Vec::new();
|
|
let plugin_path = MainStatus::global_config().py().plugin_path.clone();
|
|
|
|
for entry in std::fs::read_dir(plugin_path).unwrap().flatten() {
|
|
let path = entry.path();
|
|
if let Some(ext) = path.extension() {
|
|
if ext == "py" && !PyStatus::verify_file(&path) {
|
|
need_reload_files.push(path);
|
|
}
|
|
}
|
|
}
|
|
|
|
if need_reload_files.is_empty() {
|
|
return;
|
|
}
|
|
info!("file change list: {:?}", need_reload_files);
|
|
for reload_file in need_reload_files {
|
|
match PyPlugin::new_from_path(&reload_file) {
|
|
Some(plugin) => {
|
|
PyStatus::add_file(reload_file.clone(), plugin);
|
|
info!("重载 Python 插件: {:?}", reload_file);
|
|
}
|
|
None => {
|
|
warn!("重载 Python 插件: {:?} 失败", reload_file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub const ICA_NEW_MESSAGE_FUNC: &str = "on_ica_message";
|
|
pub const ICA_DELETE_MESSAGE_FUNC: &str = "on_ica_delete_message";
|
|
|
|
pub const MATRIX_NEW_MESSAGE_FUNC: &str = "on_matrix_message";
|
|
|
|
/// 执行 new message 的 python 插件
|
|
pub async fn ica_new_message_py(message: &NewMessage, client: &Client) {
|
|
// 验证插件是否改变
|
|
verify_plugins();
|
|
|
|
let plugins = PyStatus::get_files();
|
|
for (path, plugin) in plugins.iter() {
|
|
let msg = class::ica::NewMessagePy::new(message);
|
|
let client = class::ica::IcaClientPy::new(client);
|
|
let args = (msg, client);
|
|
// 甚至实际上压根不需要await这个spawn, 直接让他自己跑就好了(离谱)
|
|
tokio::spawn(async move {
|
|
Python::with_gil(|py| {
|
|
if let Some(py_func) =
|
|
get_func(plugin.py_module.as_ref(py), path, ICA_NEW_MESSAGE_FUNC)
|
|
{
|
|
if let Err(e) = py_func.call1(args) {
|
|
warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e);
|
|
}
|
|
}
|
|
})
|
|
});
|
|
}
|
|
}
|
|
|
|
pub async fn ica_delete_message_py(msg_id: MessageId, client: &Client) {
|
|
verify_plugins();
|
|
|
|
let plugins = PyStatus::get_files();
|
|
for (path, plugin) in plugins.iter() {
|
|
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 Some(py_func) =
|
|
get_func(plugin.py_module.as_ref(py), path, ICA_DELETE_MESSAGE_FUNC)
|
|
{
|
|
if let Err(e) = py_func.call1(args) {
|
|
warn!("failed to call function<{}>: {:?}", ICA_DELETE_MESSAGE_FUNC, e);
|
|
}
|
|
}
|
|
})
|
|
});
|
|
}
|
|
}
|
|
|
|
pub async fn matrix_new_message_py() {
|
|
verify_plugins();
|
|
|
|
let plugins = PyStatus::get_files();
|
|
for (path, plugin) in plugins.iter() {
|
|
tokio::spawn(async move {
|
|
Python::with_gil(|py| {
|
|
if let Some(py_func) =
|
|
get_func(plugin.py_module.as_ref(py), path, MATRIX_NEW_MESSAGE_FUNC)
|
|
{
|
|
if let Err(e) = py_func.call0() {
|
|
warn!("failed to call function<{}>: {:?}", MATRIX_NEW_MESSAGE_FUNC, e);
|
|
}
|
|
}
|
|
})
|
|
});
|
|
}
|
|
}
|