mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2024-11-23 04:31:05 +08:00
进行一个pre 刀耕火种的修改
This commit is contained in:
parent
75832bfa2e
commit
86c19bc3db
59
Cargo.lock
generated
59
Cargo.lock
generated
|
@ -504,9 +504,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.6"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205"
|
checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -587,9 +587,9 @@ checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "1.5.0"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a"
|
checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
|
@ -682,7 +682,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ica-rs"
|
name = "ica-rs"
|
||||||
version = "0.7.4"
|
version = "0.8.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
@ -698,7 +698,6 @@ dependencies = [
|
||||||
"rust_socketio",
|
"rust_socketio",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 2.0.3",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"toml",
|
"toml",
|
||||||
"toml_edit",
|
"toml_edit",
|
||||||
|
@ -878,9 +877,9 @@ checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
|
@ -1180,9 +1179,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.89"
|
version = "1.0.91"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
checksum = "307e3004becf10f5a6e0d59d20f3cd28231b0e0827a96cd3e0ce6d14bc1e4bb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
@ -1377,7 +1376,7 @@ dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 1.0.69",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-tungstenite",
|
"tokio-tungstenite",
|
||||||
"tungstenite",
|
"tungstenite",
|
||||||
|
@ -1402,7 +1401,7 @@ dependencies = [
|
||||||
"rust_engineio",
|
"rust_engineio",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 1.0.69",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
@ -1687,9 +1686,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.87"
|
version = "2.0.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
|
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1698,9 +1697,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sync_wrapper"
|
name = "sync_wrapper"
|
||||||
version = "1.0.1"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
|
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
]
|
]
|
||||||
|
@ -1762,16 +1761,7 @@ version = "1.0.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl 1.0.69",
|
"thiserror-impl",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "2.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl 2.0.3",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1785,17 +1775,6 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "2.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.8"
|
version = "1.1.8"
|
||||||
|
@ -2043,7 +2022,7 @@ dependencies = [
|
||||||
"native-tls",
|
"native-tls",
|
||||||
"rand",
|
"rand",
|
||||||
"sha1",
|
"sha1",
|
||||||
"thiserror 1.0.69",
|
"thiserror",
|
||||||
"url",
|
"url",
|
||||||
"utf-8",
|
"utf-8",
|
||||||
]
|
]
|
||||||
|
@ -2062,9 +2041,9 @@ checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.13"
|
version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unindent"
|
name = "unindent"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "ica-rs"
|
name = "ica-rs"
|
||||||
version = "0.7.4"
|
version = "0.8.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
@ -51,4 +51,3 @@ anyhow = { version = "1.0", features = ["backtrace"] }
|
||||||
# log
|
# log
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["time"] }
|
tracing-subscriber = { version = "0.3.18", features = ["time"] }
|
||||||
thiserror = "2.0"
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
|
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use rust_socketio::asynchronous::{Client, ClientBuilder};
|
use rust_socketio::asynchronous::{Client, ClientBuilder};
|
||||||
use rust_socketio::{async_any_callback, async_callback};
|
use rust_socketio::{async_any_callback, async_callback};
|
||||||
use rust_socketio::{Event, Payload, TransportType};
|
use rust_socketio::{Event, Payload, TransportType};
|
||||||
|
@ -11,7 +13,33 @@ use crate::error::{ClientResult, IcaError};
|
||||||
use crate::{version_str, StopGetter};
|
use crate::{version_str, StopGetter};
|
||||||
|
|
||||||
/// icalingua 客户端的兼容版本号
|
/// icalingua 客户端的兼容版本号
|
||||||
pub const ICA_PROTOCOL_VERSION: &str = "2.12.23";
|
pub const ICA_PROTOCOL_VERSION: &str = "2.12.24";
|
||||||
|
|
||||||
|
mod status {
|
||||||
|
use crate::data_struct::ica::all_rooms::Room;
|
||||||
|
pub 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<Room>,
|
||||||
|
/// 在线数据 (Icalingua 信息)
|
||||||
|
pub online_status: OnlineData,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MainStatus {
|
||||||
|
pub fn update_rooms(&mut self, room: Vec<Room>) { self.rooms = room; }
|
||||||
|
pub fn update_online_status(&mut self, status: OnlineData) { self.online_status = status; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ICA_STATUS: OnceLock<status::MainStatus> = OnceLock::new();
|
||||||
|
|
||||||
pub async fn start_ica(config: &IcaConfig, stop_reciver: StopGetter) -> ClientResult<(), IcaError> {
|
pub async fn start_ica(config: &IcaConfig, stop_reciver: StopGetter) -> ClientResult<(), IcaError> {
|
||||||
let span = span!(Level::INFO, "Icalingua Client");
|
let span = span!(Level::INFO, "Icalingua Client");
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::data_struct::ica::all_rooms::Room;
|
||||||
use crate::data_struct::ica::messages::{Message, MessageTrait, NewMessage};
|
use crate::data_struct::ica::messages::{Message, MessageTrait, NewMessage};
|
||||||
use crate::data_struct::ica::online_data::OnlineData;
|
use crate::data_struct::ica::online_data::OnlineData;
|
||||||
use crate::ica::client::send_message;
|
use crate::ica::client::send_message;
|
||||||
use crate::{client_id, help_msg, py, version_str, MainStatus, VERSION};
|
use crate::{client_id, help_msg, py, version_str, MainStatus, VERSION, start_up_time};
|
||||||
|
|
||||||
/// 获取在线数据
|
/// 获取在线数据
|
||||||
pub async fn get_online_data(payload: Payload, _client: Client) {
|
pub async fn get_online_data(payload: Payload, _client: Client) {
|
||||||
|
@ -55,6 +55,16 @@ pub async fn add_message(payload: Payload, client: Client) {
|
||||||
let reply = message.reply_with(&help_msg());
|
let reply = message.reply_with(&help_msg());
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
|
// else if message.content() == "/bot-uptime" {
|
||||||
|
// let duration = match start_up_time().elapsed() {
|
||||||
|
// Ok(d) => format!("{:?}", d),
|
||||||
|
// Err(e) => format!("出问题啦 {:?}", e),
|
||||||
|
// };
|
||||||
|
// let reply = message.reply_with(&format!(
|
||||||
|
// "shenbot 已运行: {}", duration
|
||||||
|
// ));
|
||||||
|
// send_message(&client, &reply).await;
|
||||||
|
// }
|
||||||
if MainStatus::global_config().ica().admin_list.contains(&message.sender_id()) {
|
if MainStatus::global_config().ica().admin_list.contains(&message.sender_id()) {
|
||||||
// admin 区
|
// admin 区
|
||||||
// 先判定是否为 admin
|
// 先判定是否为 admin
|
||||||
|
@ -63,7 +73,7 @@ pub async fn add_message(payload: Payload, client: Client) {
|
||||||
// 尝试获取后面的信息
|
// 尝试获取后面的信息
|
||||||
if let Some((_, name)) = message.content().split_once(" ") {
|
if let Some((_, name)) = message.content().split_once(" ") {
|
||||||
let path_name = PathBuf::from(name);
|
let path_name = PathBuf::from(name);
|
||||||
match py::PyStatus::get_status(&path_name) {
|
match py::PyStatus::get().get_status(&path_name) {
|
||||||
None => {
|
None => {
|
||||||
let reply = message.reply_with("未找到插件");
|
let reply = message.reply_with("未找到插件");
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
|
@ -73,7 +83,7 @@ pub async fn add_message(payload: Payload, client: Client) {
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
Some(false) => {
|
Some(false) => {
|
||||||
py::PyStatus::set_status(&path_name, true);
|
py::PyStatus::get_mut().set_status(&path_name, true);
|
||||||
let reply = message.reply_with("启用插件完成");
|
let reply = message.reply_with("启用插件完成");
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
|
@ -83,7 +93,7 @@ pub async fn add_message(payload: Payload, client: Client) {
|
||||||
{
|
{
|
||||||
if let Some((_, name)) = message.content().split_once(" ") {
|
if let Some((_, name)) = message.content().split_once(" ") {
|
||||||
let path_name = PathBuf::from(name);
|
let path_name = PathBuf::from(name);
|
||||||
match py::PyStatus::get_status(&path_name) {
|
match py::PyStatus::get().get_status(&path_name) {
|
||||||
None => {
|
None => {
|
||||||
let reply = message.reply_with("未找到插件");
|
let reply = message.reply_with("未找到插件");
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
|
@ -93,7 +103,7 @@ pub async fn add_message(payload: Payload, client: Client) {
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
Some(true) => {
|
Some(true) => {
|
||||||
py::PyStatus::set_status(&path_name, false);
|
py::PyStatus::get_mut().set_status(&path_name, false);
|
||||||
let reply = message.reply_with("禁用插件完成");
|
let reply = message.reply_with("禁用插件完成");
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,17 +65,17 @@ pub fn verify_and_reload_plugins() {
|
||||||
let plugin_path = MainStatus::global_config().py().plugin_path.clone();
|
let plugin_path = MainStatus::global_config().py().plugin_path.clone();
|
||||||
|
|
||||||
// 先检查是否有插件被删除
|
// 先检查是否有插件被删除
|
||||||
for path in PyStatus::get_map_mut().keys() {
|
for path in PyStatus::get().files.keys() {
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
event!(Level::INFO, "Python 插件: {:?} 已被删除", path);
|
event!(Level::INFO, "Python 插件: {:?} 已被删除", path);
|
||||||
PyStatus::delete_file(path);
|
PyStatus::get_mut().delete_file(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for entry in std::fs::read_dir(plugin_path).unwrap().flatten() {
|
for entry in std::fs::read_dir(plugin_path).unwrap().flatten() {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if let Some(ext) = path.extension() {
|
if let Some(ext) = path.extension() {
|
||||||
if ext == "py" && !PyStatus::verify_file(&path) {
|
if ext == "py" && !PyStatus::get().verify_file(&path) {
|
||||||
need_reload_files.push(path);
|
need_reload_files.push(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,15 +85,15 @@ pub fn verify_and_reload_plugins() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
event!(Level::INFO, "更改列表: {:?}", need_reload_files);
|
event!(Level::INFO, "更改列表: {:?}", need_reload_files);
|
||||||
let exist_plugins = PyStatus::get_map_mut();
|
let plugins = PyStatus::get_mut();
|
||||||
for reload_file in need_reload_files {
|
for reload_file in need_reload_files {
|
||||||
if let Some(plugin) = exist_plugins.get_mut(&reload_file) {
|
if let Some(plugin) = plugins.files.get_mut(&reload_file) {
|
||||||
plugin.reload_from_file();
|
plugin.reload_from_file();
|
||||||
event!(Level::INFO, "重载 Python 插件: {:?} 完成", reload_file);
|
event!(Level::INFO, "重载 Python 插件: {:?} 完成", reload_file);
|
||||||
} else {
|
} else {
|
||||||
match PyPlugin::new_from_path(&reload_file) {
|
match PyPlugin::new_from_path(&reload_file) {
|
||||||
Some(plugin) => {
|
Some(plugin) => {
|
||||||
PyStatus::add_file(reload_file.clone(), plugin);
|
plugins.add_file(reload_file.clone(), plugin);
|
||||||
info!("加载 Python 插件: {:?} 完成", reload_file);
|
info!("加载 Python 插件: {:?} 完成", reload_file);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -149,8 +149,8 @@ pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Cl
|
||||||
// 验证插件是否改变
|
// 验证插件是否改变
|
||||||
verify_and_reload_plugins();
|
verify_and_reload_plugins();
|
||||||
|
|
||||||
let plugins = PyStatus::get_map();
|
let plugins = PyStatus::get();
|
||||||
for (path, plugin) in plugins.iter().filter(|(_, plugin)| plugin.enabled) {
|
for (path, plugin) in plugins.files.iter().filter(|(_, plugin)| plugin.enabled) {
|
||||||
let msg = class::ica::NewMessagePy::new(message);
|
let msg = class::ica::NewMessagePy::new(message);
|
||||||
let client = class::ica::IcaClientPy::new(client);
|
let client = class::ica::IcaClientPy::new(client);
|
||||||
let args = (msg, client);
|
let args = (msg, client);
|
||||||
|
@ -162,8 +162,8 @@ pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Cl
|
||||||
pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) {
|
pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) {
|
||||||
verify_and_reload_plugins();
|
verify_and_reload_plugins();
|
||||||
|
|
||||||
let plugins = PyStatus::get_map();
|
let plugins = PyStatus::get();
|
||||||
for (path, plugin) in plugins.iter().filter(|(_, plugin)| plugin.enabled) {
|
for (path, plugin) in plugins.files.iter().filter(|(_, plugin)| plugin.enabled) {
|
||||||
let msg_id = msg_id.clone();
|
let msg_id = msg_id.clone();
|
||||||
let client = class::ica::IcaClientPy::new(client);
|
let client = class::ica::IcaClientPy::new(client);
|
||||||
let args = (msg_id.clone(), client);
|
let args = (msg_id.clone(), client);
|
||||||
|
@ -177,8 +177,8 @@ pub async fn tailchat_new_message_py(
|
||||||
) {
|
) {
|
||||||
verify_and_reload_plugins();
|
verify_and_reload_plugins();
|
||||||
|
|
||||||
let plugins = PyStatus::get_map();
|
let plugins = PyStatus::get();
|
||||||
for (path, plugin) in plugins.iter().filter(|(_, plugin)| plugin.enabled) {
|
for (path, plugin) in plugins.files.iter().filter(|(_, plugin)| plugin.enabled) {
|
||||||
let msg = class::tailchat::TailchatReceiveMessagePy::from_recive_message(message);
|
let msg = class::tailchat::TailchatReceiveMessagePy::from_recive_message(message);
|
||||||
let client = class::tailchat::TailchatClientPy::new(client);
|
let client = class::tailchat::TailchatClientPy::new(client);
|
||||||
let args = (msg, client);
|
let args = (msg, client);
|
||||||
|
|
|
@ -2,9 +2,9 @@ pub mod ica;
|
||||||
pub mod tailchat;
|
pub mod tailchat;
|
||||||
|
|
||||||
use pyo3::{
|
use pyo3::{
|
||||||
pyclass, pymethods, IntoPyObject, Bound,
|
pyclass, pymethods,
|
||||||
PyAny, PyRef,
|
|
||||||
types::{PyBool, PyString},
|
types::{PyBool, PyString},
|
||||||
|
Bound, IntoPyObject, PyAny, PyRef,
|
||||||
};
|
};
|
||||||
use toml::Value as TomlValue;
|
use toml::Value as TomlValue;
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ impl ConfigDataPy {
|
||||||
pub fn __getitem__(self_: PyRef<'_, Self>, key: String) -> Option<Bound<PyAny>> {
|
pub fn __getitem__(self_: PyRef<'_, Self>, key: String) -> Option<Bound<PyAny>> {
|
||||||
match self_.data.get(&key) {
|
match self_.data.get(&key) {
|
||||||
Some(value) => match value {
|
Some(value) => match value {
|
||||||
// TomlValue::String(s) => Some(s.into_pyobject(self_.py()).unwrap().as_any().as_unbound().to_owned()),
|
|
||||||
TomlValue::String(s) => Some(PyString::new(self_.py(), s).into_any()),
|
TomlValue::String(s) => Some(PyString::new(self_.py(), s).into_any()),
|
||||||
TomlValue::Integer(i) => Some(i.into_pyobject(self_.py()).unwrap().into_any()),
|
TomlValue::Integer(i) => Some(i.into_pyobject(self_.py()).unwrap().into_any()),
|
||||||
TomlValue::Float(f) => Some(f.into_pyobject(self_.py()).unwrap().into_any()),
|
TomlValue::Float(f) => Some(f.into_pyobject(self_.py()).unwrap().into_any()),
|
||||||
|
|
|
@ -116,9 +116,9 @@ impl PluginConfigFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_status_from_config(&mut self) {
|
pub fn sync_status_from_config(&mut self) {
|
||||||
let plugins = PyStatus::get_map_mut();
|
let plugins = PyStatus::get_mut();
|
||||||
self.verify_and_init();
|
self.verify_and_init();
|
||||||
plugins.iter_mut().for_each(|(path, status)| {
|
plugins.files.iter_mut().for_each(|(path, status)| {
|
||||||
let config_status = self.get_status(path);
|
let config_status = self.get_status(path);
|
||||||
event!(Level::INFO, "插件状态: {:?} {} -> {}", path, status.enabled, config_status);
|
event!(Level::INFO, "插件状态: {:?} {} -> {}", path, status.enabled, config_status);
|
||||||
status.enabled = config_status;
|
status.enabled = config_status;
|
||||||
|
@ -126,11 +126,11 @@ impl PluginConfigFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync_status_to_config(&mut self) {
|
pub fn sync_status_to_config(&mut self) {
|
||||||
let plugins = PyStatus::get_map();
|
let plugins = PyStatus::get();
|
||||||
self.verify_and_init();
|
self.verify_and_init();
|
||||||
let table = self.data.get_mut(CONFIG_KEY).unwrap().as_table_mut().unwrap();
|
let table = self.data.get_mut(CONFIG_KEY).unwrap().as_table_mut().unwrap();
|
||||||
table.clear();
|
table.clear();
|
||||||
plugins.iter().for_each(|(path, status)| {
|
plugins.files.iter().for_each(|(path, status)| {
|
||||||
table.insert(path.to_str().unwrap(), value(status.enabled));
|
table.insert(path.to_str().unwrap(), value(status.enabled));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ pub mod config;
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::sync::OnceLock;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
|
@ -16,116 +17,65 @@ use crate::MainStatus;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PyStatus {
|
pub struct PyStatus {
|
||||||
pub files: Option<PyPlugins>,
|
pub files: PyPlugins,
|
||||||
pub config: Option<config::PluginConfigFile>,
|
pub config: config::PluginConfigFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PyPlugins = HashMap<PathBuf, PyPlugin>;
|
pub type PyPlugins = HashMap<PathBuf, PyPlugin>;
|
||||||
pub type RawPyPlugin = (PathBuf, Option<SystemTime>, String);
|
pub type RawPyPlugin = (PathBuf, Option<SystemTime>, String);
|
||||||
|
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
static mut PyPluginStatus: OnceLock<PyStatus> = OnceLock::new();
|
||||||
|
|
||||||
impl PyStatus {
|
impl PyStatus {
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
unsafe {
|
let plugin_path = MainStatus::global_config().py().plugin_path.clone();
|
||||||
if PYSTATUS.files.is_none() {
|
|
||||||
PYSTATUS.files = Some(HashMap::new());
|
|
||||||
}
|
|
||||||
if PYSTATUS.config.is_none() {
|
|
||||||
let plugin_path = MainStatus::global_config().py().config_path.clone();
|
|
||||||
let mut config =
|
let mut config =
|
||||||
config::PluginConfigFile::from_config_path(&PathBuf::from(plugin_path))
|
config::PluginConfigFile::from_config_path(&PathBuf::from(plugin_path)).unwrap();
|
||||||
.unwrap();
|
|
||||||
config.verify_and_init();
|
config.verify_and_init();
|
||||||
PYSTATUS.config = Some(config);
|
let status = PyStatus {
|
||||||
}
|
files: HashMap::new(),
|
||||||
}
|
config,
|
||||||
|
};
|
||||||
|
let _ = unsafe { PyPluginStatus.get_or_init(|| status) };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_file(path: PathBuf, plugin: PyPlugin) { Self::get_map_mut().insert(path, plugin); }
|
pub fn get() -> &'static PyStatus { unsafe { PyPluginStatus.get().unwrap() } }
|
||||||
|
|
||||||
|
pub fn get_mut() -> &'static mut PyStatus { unsafe { PyPluginStatus.get_mut().unwrap() } }
|
||||||
|
|
||||||
|
pub fn add_file(&mut self, path: PathBuf, plugin: PyPlugin) { self.files.insert(path, plugin); }
|
||||||
|
|
||||||
/// 删除一个插件
|
/// 删除一个插件
|
||||||
pub fn delete_file(path: &PathBuf) -> Option<PyPlugin> { Self::get_map_mut().remove(path) }
|
pub fn delete_file(&mut self, path: &PathBuf) -> Option<PyPlugin> { self.files.remove(path) }
|
||||||
|
|
||||||
pub fn verify_file(path: &PathBuf) -> bool {
|
pub fn verify_file(&self, path: &PathBuf) -> bool {
|
||||||
Self::get_map().get(path).is_some_and(|plugin| plugin.verifiy())
|
self.files.get(path).is_some_and(|plugin| plugin.verifiy())
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_map() -> &'static PyPlugins {
|
|
||||||
unsafe {
|
|
||||||
let ptr = &raw const PYSTATUS.files;
|
|
||||||
let ptr = &*ptr;
|
|
||||||
match ptr.as_ref() {
|
|
||||||
Some(files) => files,
|
|
||||||
None => {
|
|
||||||
Self::init();
|
|
||||||
ptr.as_ref().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_map_mut() -> &'static mut PyPlugins {
|
|
||||||
unsafe {
|
|
||||||
let ptr = &raw mut PYSTATUS.files;
|
|
||||||
let ptr = &mut *ptr;
|
|
||||||
match ptr {
|
|
||||||
Some(files) => files,
|
|
||||||
None => {
|
|
||||||
Self::init();
|
|
||||||
ptr.as_mut().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_config() -> &'static config::PluginConfigFile {
|
|
||||||
unsafe {
|
|
||||||
let ptr = &raw const PYSTATUS.config;
|
|
||||||
let ptr = &*ptr;
|
|
||||||
match ptr {
|
|
||||||
Some(config) => config,
|
|
||||||
None => {
|
|
||||||
Self::init();
|
|
||||||
ptr.as_ref().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_config_mut() -> &'static mut config::PluginConfigFile {
|
|
||||||
unsafe {
|
|
||||||
let ptr = &raw mut PYSTATUS.config;
|
|
||||||
let ptr = &mut *ptr;
|
|
||||||
match ptr {
|
|
||||||
Some(config) => config,
|
|
||||||
None => {
|
|
||||||
Self::init();
|
|
||||||
ptr.as_mut().unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取某个插件的状态
|
/// 获取某个插件的状态
|
||||||
/// 以 config 优先
|
/// 以 config 优先
|
||||||
pub fn get_status(path: &PathBuf) -> Option<bool> {
|
pub fn get_status(&self, path: &PathBuf) -> Option<bool> {
|
||||||
Self::get_config_mut().sync_status_from_config();
|
self.files.get(path).map(|plugin| plugin.enabled)
|
||||||
Self::get_map().get(path).map(|plugin| plugin.enabled)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_status(path: &Path, status: bool) {
|
pub fn sync_status(&mut self) {
|
||||||
let cfg = Self::get_config_mut();
|
self.config.sync_status_from_config();
|
||||||
cfg.set_status(path, status);
|
}
|
||||||
let map = Self::get_map_mut();
|
|
||||||
if let Some(plugin) = map.get_mut(path) {
|
pub fn set_status(&mut self, path: &Path, status: bool) {
|
||||||
|
self.config.set_status(path, status);
|
||||||
|
if let Some(plugin) = self.files.get_mut(path) {
|
||||||
plugin.enabled = status;
|
plugin.enabled = status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn display() -> String {
|
pub fn display() -> String {
|
||||||
let map = Self::get_map();
|
|
||||||
format!(
|
format!(
|
||||||
"Python 插件 {{ {} }}",
|
"Python 插件 {{ {} }}",
|
||||||
map.iter()
|
Self::get()
|
||||||
|
.files
|
||||||
|
.iter()
|
||||||
.map(|(k, v)| format!("{:?}-{}", k, v.enabled))
|
.map(|(k, v)| format!("{:?}-{}", k, v.enabled))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join("\n")
|
.join("\n")
|
||||||
|
@ -185,7 +135,7 @@ impl PyPlugin {
|
||||||
Ok(plugin) => {
|
Ok(plugin) => {
|
||||||
self.py_module = plugin.py_module;
|
self.py_module = plugin.py_module;
|
||||||
self.changed_time = plugin.changed_time;
|
self.changed_time = plugin.changed_time;
|
||||||
self.enabled = PyStatus::get_config().get_status(self.file_path.as_path());
|
self.enabled = PyStatus::get().config.get_status(self.file_path.as_path());
|
||||||
event!(Level::INFO, "更新 Python 插件文件 {:?} 完成", self.file_path);
|
event!(Level::INFO, "更新 Python 插件文件 {:?} 完成", self.file_path);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -356,12 +306,8 @@ impl TryFrom<RawPyPlugin> for PyPlugin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub static mut PYSTATUS: PyStatus = PyStatus {
|
|
||||||
files: None,
|
|
||||||
config: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn load_py_plugins(path: &PathBuf) {
|
pub fn load_py_plugins(path: &PathBuf) {
|
||||||
|
let plugins = PyStatus::get_mut();
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
event!(Level::INFO, "找到位于 {:?} 的插件", path);
|
event!(Level::INFO, "找到位于 {:?} 的插件", path);
|
||||||
// 搜索所有的 py 文件 和 文件夹单层下面的 py 文件
|
// 搜索所有的 py 文件 和 文件夹单层下面的 py 文件
|
||||||
|
@ -376,7 +322,7 @@ pub fn load_py_plugins(path: &PathBuf) {
|
||||||
if let Some(ext) = path.extension() {
|
if let Some(ext) = path.extension() {
|
||||||
if ext == "py" {
|
if ext == "py" {
|
||||||
if let Some(plugin) = PyPlugin::new_from_path(&path) {
|
if let Some(plugin) = PyPlugin::new_from_path(&path) {
|
||||||
PyStatus::add_file(path, plugin);
|
plugins.add_file(path, plugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,12 +332,12 @@ pub fn load_py_plugins(path: &PathBuf) {
|
||||||
} else {
|
} else {
|
||||||
event!(Level::WARN, "插件加载目录不存在: {:?}", path);
|
event!(Level::WARN, "插件加载目录不存在: {:?}", path);
|
||||||
}
|
}
|
||||||
PyStatus::get_config_mut().sync_status_from_config();
|
plugins.config.sync_status_from_config();
|
||||||
event!(
|
event!(
|
||||||
Level::INFO,
|
Level::INFO,
|
||||||
"python 插件目录: {:?} 加载完成, 加载到 {} 个插件",
|
"python 插件目录: {:?} 加载完成, 加载到 {} 个插件",
|
||||||
path,
|
path,
|
||||||
PyStatus::get_map().len()
|
plugins.files.len()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -403,7 +349,9 @@ pub fn py_module_from_code(content: &str, path: &Path) -> PyResult<Py<PyAny>> {
|
||||||
py,
|
py,
|
||||||
CString::new(content).unwrap().as_c_str(),
|
CString::new(content).unwrap().as_c_str(),
|
||||||
CString::new(path.to_string_lossy().as_bytes()).unwrap().as_c_str(),
|
CString::new(path.to_string_lossy().as_bytes()).unwrap().as_c_str(),
|
||||||
CString::new(path.file_name().unwrap().to_string_lossy().as_bytes()).unwrap().as_c_str(),
|
CString::new(path.file_name().unwrap().to_string_lossy().as_bytes())
|
||||||
|
.unwrap()
|
||||||
|
.as_c_str(),
|
||||||
// !!!! 请注意, 一定要给他一个名字, cpython 会自动把后面的重名模块覆盖掉前面的
|
// !!!! 请注意, 一定要给他一个名字, cpython 会自动把后面的重名模块覆盖掉前面的
|
||||||
)
|
)
|
||||||
.map(|module| module.into());
|
.map(|module| module.into());
|
||||||
|
@ -439,8 +387,9 @@ pub fn init_py() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post_py() -> anyhow::Result<()> {
|
pub fn post_py() -> anyhow::Result<()> {
|
||||||
PyStatus::get_config_mut().sync_status_to_config();
|
PyStatus::get_mut().config.sync_status_to_config();
|
||||||
PyStatus::get_config()
|
PyStatus::get()
|
||||||
|
.config
|
||||||
.write_to_file(&PathBuf::from(MainStatus::global_config().py().config_path))?;
|
.write_to_file(&PathBuf::from(MainStatus::global_config().py().config_path))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,9 @@ use tracing::{event, info, Level};
|
||||||
use crate::data_struct::tailchat::messages::ReceiveMessage;
|
use crate::data_struct::tailchat::messages::ReceiveMessage;
|
||||||
use crate::data_struct::tailchat::status::{BotStatus, UpdateDMConverse};
|
use crate::data_struct::tailchat::status::{BotStatus, UpdateDMConverse};
|
||||||
use crate::tailchat::client::{emit_join_room, send_message};
|
use crate::tailchat::client::{emit_join_room, send_message};
|
||||||
use crate::{client_id, help_msg, py, version_str, MainStatus, VERSION};
|
use crate::py::PyStatus;
|
||||||
|
use crate::py::call::tailchat_new_message_py;
|
||||||
|
use crate::{client_id, help_msg, version_str, MainStatus, VERSION, start_up_time};
|
||||||
|
|
||||||
/// 所有
|
/// 所有
|
||||||
pub async fn any_event(event: Event, payload: Payload, _client: Client, _status: Arc<BotStatus>) {
|
pub async fn any_event(event: Event, payload: Payload, _client: Client, _status: Arc<BotStatus>) {
|
||||||
|
@ -86,7 +88,7 @@ pub async fn on_message(payload: Payload, client: Client, _status: Arc<BotStatus
|
||||||
VERSION,
|
VERSION,
|
||||||
client_id(),
|
client_id(),
|
||||||
if MainStatus::global_config().check_py() {
|
if MainStatus::global_config().check_py() {
|
||||||
py::PyStatus::display()
|
PyStatus::display()
|
||||||
} else {
|
} else {
|
||||||
"未启用 Python 插件".to_string()
|
"未启用 Python 插件".to_string()
|
||||||
}
|
}
|
||||||
|
@ -96,6 +98,16 @@ pub async fn on_message(payload: Payload, client: Client, _status: Arc<BotStatus
|
||||||
let reply = message.reply_with(&help_msg());
|
let reply = message.reply_with(&help_msg());
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
|
// else if message.content == "/bot-uptime" {
|
||||||
|
// let duration = match start_up_time().elapsed() {
|
||||||
|
// Ok(d) => format!("{:?}", d),
|
||||||
|
// Err(e) => format!("出问题啦 {:?}", e),
|
||||||
|
// };
|
||||||
|
// let reply = message.reply_with(&format!(
|
||||||
|
// "shenbot 已运行: {}", duration
|
||||||
|
// ));
|
||||||
|
// send_message(&client, &reply).await;
|
||||||
|
// }
|
||||||
if MainStatus::global_config().tailchat().admin_list.contains(&message.sender_id) {
|
if MainStatus::global_config().tailchat().admin_list.contains(&message.sender_id) {
|
||||||
// admin 区
|
// admin 区
|
||||||
let client_id = client_id();
|
let client_id = client_id();
|
||||||
|
@ -104,7 +116,7 @@ pub async fn on_message(payload: Payload, client: Client, _status: Arc<BotStatus
|
||||||
// 尝试获取后面的信息
|
// 尝试获取后面的信息
|
||||||
if let Some((_, name)) = message.content.split_once(" ") {
|
if let Some((_, name)) = message.content.split_once(" ") {
|
||||||
let path_name = PathBuf::from(name);
|
let path_name = PathBuf::from(name);
|
||||||
match py::PyStatus::get_status(&path_name) {
|
match PyStatus::get().get_status(&path_name) {
|
||||||
None => {
|
None => {
|
||||||
let reply = message.reply_with("未找到插件");
|
let reply = message.reply_with("未找到插件");
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
|
@ -114,7 +126,7 @@ pub async fn on_message(payload: Payload, client: Client, _status: Arc<BotStatus
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
Some(false) => {
|
Some(false) => {
|
||||||
py::PyStatus::set_status(&path_name, true);
|
PyStatus::get_mut().set_status(&path_name, true);
|
||||||
let reply = message.reply_with("启用插件完成");
|
let reply = message.reply_with("启用插件完成");
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
|
@ -123,7 +135,7 @@ pub async fn on_message(payload: Payload, client: Client, _status: Arc<BotStatus
|
||||||
} else if message.content.starts_with(&format!("/bot-disable-{}", client_id)) {
|
} else if message.content.starts_with(&format!("/bot-disable-{}", client_id)) {
|
||||||
if let Some((_, name)) = message.content.split_once(" ") {
|
if let Some((_, name)) = message.content.split_once(" ") {
|
||||||
let path_name = PathBuf::from(name);
|
let path_name = PathBuf::from(name);
|
||||||
match py::PyStatus::get_status(&path_name) {
|
match PyStatus::get().get_status(&path_name) {
|
||||||
None => {
|
None => {
|
||||||
let reply = message.reply_with("未找到插件");
|
let reply = message.reply_with("未找到插件");
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
|
@ -133,7 +145,7 @@ pub async fn on_message(payload: Payload, client: Client, _status: Arc<BotStatus
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
Some(true) => {
|
Some(true) => {
|
||||||
py::PyStatus::set_status(&path_name, false);
|
PyStatus::get_mut().set_status(&path_name, false);
|
||||||
let reply = message.reply_with("禁用插件完成");
|
let reply = message.reply_with("禁用插件完成");
|
||||||
send_message(&client, &reply).await;
|
send_message(&client, &reply).await;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +154,7 @@ pub async fn on_message(payload: Payload, client: Client, _status: Arc<BotStatus
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
py::call::tailchat_new_message_py(&message, &client).await;
|
tailchat_new_message_py(&message, &client).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user