我知道没修好,但是先丢上来

This commit is contained in:
shenjack 2024-03-15 00:40:22 +08:00
parent 4ae11b4d4f
commit de09257249
Signed by: shenjack
GPG Key ID: 7B1134A979775551
10 changed files with 156 additions and 131 deletions

View File

@ -1,13 +1,18 @@
# python 插件路径
py_plugin_path = "/path/to/your/plugin"
py_config_path = "/path/to/your/config"
# 填写 [ica] 但不填写此项则不启用 ica
enable_ica = true # 是否启用 ica
# 填写 [matrix] 但不填写此项则不启用 matrix
enable_matrix = true # 是否启用 matrix
enable_py = true # 是否启用 python 插件
[py]
# python 插件路径
plugin_path = "/path/to/your/plugin"
config_path = "/path/to/your/config"
[ica]
private_key = "" # 与 icalingua 客户端使用的 private_key 一致

View File

@ -39,6 +39,14 @@ pub struct MatrixConfig {
pub notice_start: bool,
}
#[derive(Debug, Clone, Deserialize)]
pub struct PyConfig {
/// 插件路径
pub plugin_path: String,
/// 配置文件路径
pub config_path: String,
}
/// 主配置
#[derive(Debug, Clone, Deserialize)]
pub struct BotConfig {
@ -50,10 +58,10 @@ pub struct BotConfig {
pub enable_matrix: Option<bool>,
/// Matrix 配置
pub matrix: Option<MatrixConfig>,
/// Python 插件路径
pub py_plugin_path: Option<String>,
/// Python 配置文件路径
pub py_config_path: Option<String>,
/// 是否启用 Python 插件
pub enable_py: Option<bool>,
/// Python 插件配置
pub py: Option<PyConfig>,
}
impl BotConfig {
@ -109,5 +117,27 @@ impl BotConfig {
}
}
/// 检查是否启用 Python 插件
pub fn check_py(&self) -> bool {
match self.enable_py {
Some(enable) => {
if enable && self.py.is_none() {
warn!("enable_py 为 true 但未填写 [py] 配置\n将不启用 Python 插件");
false
} else {
true
}
}
None => {
if self.py.is_some() {
warn!("未填写 enable_py 但填写了 [py] 配置\n将不启用 Python 插件");
}
false
}
}
}
pub fn ica(&self) -> IcaConfig { self.ica.clone().expect("No ica config found") }
pub fn matrix(&self) -> MatrixConfig { self.matrix.clone().expect("No matrix config found") }
pub fn py(&self) -> PyConfig { self.py.clone().expect("No py config found") }
}

0
ica-rs/src/error.rs Normal file
View File

View File

@ -4,12 +4,13 @@ pub mod events;
use futures_util::FutureExt;
use rust_socketio::asynchronous::{Client, ClientBuilder};
use rust_socketio::{Event, Payload, TransportType};
use tracing::info;
use tracing::{event, info, Level};
use crate::config::IcaConfig;
use crate::{wrap_any_callback, wrap_callback};
pub async fn start_ica(config: &IcaConfig, stop_reciver: tokio::sync::oneshot::Receiver<()>) {
event!(Level::INFO, "ica-async-rs v{} start ica", crate::ICA_VERSION);
let socket = ClientBuilder::new(config.host.clone())
.transport_type(TransportType::Websocket)
.on_any(wrap_any_callback!(events::any_event))
@ -33,7 +34,7 @@ pub async fn start_ica(config: &IcaConfig, stop_reciver: tokio::sync::oneshot::R
if config.notice_start {
for room in config.notice_room.iter() {
let startup_msg = crate::data_struct::ica::messages::SendMessage::new(
format!("ica-async-rs bot v{}", crate::VERSION),
format!("shenbot v {}\nica-async-rs bot v{}", crate::VERSION, crate::ICA_VERSION),
*room,
None,
);

View File

@ -1,8 +1,7 @@
use crate::config::{BotConfig, IcaConfig};
use crate::data_struct::ica::all_rooms::Room;
use crate::data_struct::ica::messages::{DeleteMessage, SendMessage};
use crate::data_struct::ica::online_data::OnlineData;
use crate::ClientStatus_Global;
use crate::MainStatus;
use colored::Colorize;
use ed25519_dalek::{Signature, Signer, SigningKey};
@ -46,93 +45,6 @@ pub async fn delete_message(client: &Client, message: &DeleteMessage) -> bool {
// #[allow(dead_code)]
// pub async fn fetch_history(client: &Client, roomd_id: RoomId) -> bool { false }
#[derive(Debug, Clone)]
pub struct BotStatus {
pub login: bool,
/// currentLoadedMessagesCount
pub current_loaded_messages_count: u64,
pub online_data: Option<OnlineData>,
pub rooms: Option<Vec<Room>>,
pub config: Option<BotConfig>,
}
impl Default for BotStatus {
fn default() -> Self { Self::new() }
}
impl BotStatus {
pub fn new() -> Self {
Self {
login: false,
current_loaded_messages_count: 0,
online_data: None,
rooms: None,
config: Some(BotConfig::new_from_cli()),
}
}
#[inline]
pub fn update_online_data(online_data: OnlineData) {
unsafe {
ClientStatus_Global.online_data = Some(online_data);
}
}
#[inline]
pub fn update_rooms(rooms: Vec<Room>) {
unsafe {
ClientStatus_Global.rooms = Some(rooms);
}
}
#[inline]
pub fn update_login_status(login: bool) {
unsafe {
ClientStatus_Global.login = login;
}
}
#[inline]
pub fn update_config(config: BotConfig) {
unsafe {
ClientStatus_Global.config = Some(config);
}
}
#[inline]
pub fn update_loaded_messages_count(count: u64) {
unsafe {
ClientStatus_Global.current_loaded_messages_count = count;
}
}
#[inline]
pub fn get_login_status() -> bool { unsafe { ClientStatus_Global.login } }
#[inline]
pub fn get_rooms() -> &'static Vec<Room> {
unsafe { ClientStatus_Global.rooms.as_ref().expect("rooms should be set") }
}
#[inline]
pub fn get_loaded_messages_count() -> u64 {
unsafe { ClientStatus_Global.current_loaded_messages_count }
}
#[inline]
pub fn get_online_data() -> &'static OnlineData {
unsafe { ClientStatus_Global.online_data.as_ref().expect("online_data should be set") }
}
#[inline]
pub fn get_config() -> &'static BotConfig {
unsafe { ClientStatus_Global.config.as_ref().expect("config should be set") }
}
#[inline]
pub fn get_ica_config() -> &'static IcaConfig {
unsafe {
ClientStatus_Global
.config
.as_ref()
.expect("config should be set")
.ica
.as_ref()
.expect("ica should be set")
}
}
}
pub async fn sign_callback(payload: Payload, client: Client) {
// 获取数据
let require_data = match payload {
@ -142,15 +54,17 @@ pub async fn sign_callback(payload: Payload, client: Client) {
.expect("Payload should be Json data");
let (auth_key, version) = (&require_data[0], &require_data[1]);
debug!("auth_key: {:?}, version: {:?}", auth_key, version);
debug!("auth_key: {:?}, server_version: {:?}", auth_key, version);
let auth_key = match &require_data.first() {
Some(Value::String(auth_key)) => Some(auth_key),
_ => None,
}
.expect("auth_key should be string");
let salt = hex::decode(auth_key).expect("Got an invalid salt from the server");
// 签名
let private_key = BotStatus::get_config().ica().private_key.clone();
let private_key = MainStatus::global_config().ica().private_key.clone();
let array_key: [u8; 32] = hex::decode(private_key)
.expect("Not a vaild pub key")
.try_into()
@ -158,6 +72,7 @@ pub async fn sign_callback(payload: Payload, client: Client) {
let signing_key: SigningKey = SigningKey::from_bytes(&array_key);
let signature: Signature = signing_key.sign(salt.as_slice());
// 发送签名
let sign = signature.to_bytes().to_vec();
client.emit("auth", sign).await.expect("Faild to send signin data");
}

View File

@ -10,8 +10,7 @@ mod py;
mod status;
use config::BotConfig;
use tracing::info;
use tracing::{event, info, Level};
pub static mut MAIN_STATUS: status::BotStatus = status::BotStatus {
config: None,
@ -22,6 +21,8 @@ pub static mut MAIN_STATUS: status::BotStatus = status::BotStatus {
pub type MainStatus = status::BotStatus;
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub const ICA_VERSION: &str = "0.5.0";
pub const MATRIX_VERSION: &str = "0.1.0";
#[macro_export]
macro_rules! wrap_callback {
@ -40,13 +41,13 @@ macro_rules! wrap_any_callback {
#[tokio::main]
async fn main() {
tracing_subscriber::fmt().with_max_level(tracing::Level::DEBUG).init();
info!("ica-async-rs v{}", VERSION);
event!(Level::INFO, "shenbot-async-rs v{} main", VERSION);
// 从命令行获取 host 和 key
// 从命令行获取配置文件路径
let bot_config = BotConfig::new_from_cli();
ica::client::BotStatus::update_config(bot_config.clone());
py::init_py(&bot_config);
MainStatus::static_init(bot_config);
let bot_config = MainStatus::global_config();
py::init_py();
// 准备一个用于停止 socket 的变量
let (send, recv) = tokio::sync::oneshot::channel::<()>();

View File

@ -6,8 +6,8 @@ use tracing::{debug, info, warn};
use crate::data_struct::ica::messages::NewMessage;
use crate::data_struct::ica::MessageId;
use crate::ica::client::BotStatus;
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> {
// 要处理的情况:

View File

@ -8,8 +8,8 @@ use crate::data_struct::ica::messages::{
DeleteMessage, MessageTrait, NewMessage, ReplyMessage, SendMessage,
};
use crate::data_struct::ica::MessageId;
use crate::ica::client::{delete_message, send_message, BotStatus};
use crate::ClientStatus_Global;
use crate::ica::client::{delete_message, send_message};
use crate::MainStatus;
#[pyclass]
#[pyo3(name = "IcaStatus")]
@ -20,37 +20,47 @@ impl IcaStatusPy {
#[new]
pub fn py_new() -> Self { Self {} }
#[getter]
pub fn get_login(&self) -> bool { unsafe { ClientStatus_Global.login } }
pub fn get_qq_login(&self) -> bool { MainStatus::global_ica_status().qq_login }
#[getter]
pub fn get_online(&self) -> bool { BotStatus::get_online_data().online }
pub fn get_online(&self) -> bool { MainStatus::global_ica_status().online_status.online }
#[getter]
pub fn get_self_id(&self) -> i64 { BotStatus::get_online_data().qqid }
pub fn get_self_id(&self) -> i64 { MainStatus::global_ica_status().online_status.qqid }
#[getter]
pub fn get_nick_name(&self) -> String { BotStatus::get_online_data().nick.clone() }
pub fn get_nick_name(&self) -> String {
MainStatus::global_ica_status().online_status.nick.clone()
}
#[getter]
pub fn get_loaded_messages_count(&self) -> u64 { BotStatus::get_loaded_messages_count() }
pub fn get_loaded_messages_count(&self) -> u64 {
MainStatus::global_ica_status().current_loaded_messages_count
}
#[getter]
pub fn get_ica_version(&self) -> String {
BotStatus::get_online_data().icalingua_info.ica_version.clone()
MainStatus::global_ica_status().online_status.icalingua_info.ica_version.clone()
}
#[getter]
pub fn get_os_info(&self) -> String {
BotStatus::get_online_data().icalingua_info.os_info.clone()
MainStatus::global_ica_status().online_status.icalingua_info.os_info.clone()
}
#[getter]
pub fn get_resident_set_size(&self) -> String {
BotStatus::get_online_data().icalingua_info.resident_set_size.clone()
MainStatus::global_ica_status()
.online_status
.icalingua_info
.resident_set_size
.clone()
}
#[getter]
pub fn get_heap_used(&self) -> String {
BotStatus::get_online_data().icalingua_info.heap_used.clone()
MainStatus::global_ica_status().online_status.icalingua_info.heap_used.clone()
}
#[getter]
pub fn get_load(&self) -> String { BotStatus::get_online_data().icalingua_info.load.clone() }
pub fn get_load(&self) -> String {
MainStatus::global_ica_status().online_status.icalingua_info.load.clone()
}
}
impl Default for IcaStatusPy {
@ -197,6 +207,10 @@ impl IcaClientPy {
pub fn get_status(&self) -> IcaStatusPy { IcaStatusPy::new() }
#[getter]
pub fn get_version(&self) -> String { crate::VERSION.to_string() }
#[getter]
pub fn get_ica_version(&self) -> String { crate::ICA_VERSION.to_string() }
#[getter]
pub fn get_matrix_version(&self) -> String { crate::MATRIX_VERSION.to_string() }
pub fn debug(&self, content: String) {
debug!("{}", content);

View File

@ -7,10 +7,9 @@ use std::{collections::HashMap, path::PathBuf};
use pyo3::prelude::*;
use pyo3::types::PyTuple;
use tracing::{debug, info, warn};
use tracing::{debug, info, span, warn, Level};
use crate::config::BotConfig;
use crate::ica::client::BotStatus;
use crate::MainStatus;
#[derive(Debug, Clone)]
pub struct PyStatus {
@ -243,14 +242,20 @@ pub fn load_py_file(path: &PathBuf) -> std::io::Result<RawPyPlugin> {
Ok((path.clone(), changed_time, content))
}
pub fn init_py(config: &BotConfig) {
/// Python 侧初始化
pub fn init_py() {
// 从 全局配置中获取 python 插件路径
let span = span!(Level::INFO, "Init Python Plugin");
let enter = span.enter();
let global_config = MainStatus::global_config().py();
debug!("initing python threads");
pyo3::prepare_freethreaded_python();
if let Some(plugin_path) = &config.py_plugin_path {
let path = PathBuf::from(plugin_path);
load_py_plugins(&path);
debug!("python 插件列表: {:#?}", PyStatus::get_files());
}
let path = PathBuf::from(global_config.plugin_path);
load_py_plugins(&path);
debug!("python 插件列表: {:#?}", PyStatus::get_files());
info!("python inited")
}

View File

@ -1,15 +1,69 @@
use crate::config::BotConfig;
use crate::MAIN_STATUS;
#[derive(Debug, Clone)]
pub struct BotStatus {
pub config: Option<BotConfig>,
pub ica_status: Option<ica::MainStatus>,
pub matrix_status: Option<matrix::MainStatus>,
}
impl BotStatus {
pub fn update_static_config(config: BotConfig) {
unsafe {
MAIN_STATUS.config = Some(config);
}
}
pub fn update_ica_status(status: ica::MainStatus) {
unsafe {
MAIN_STATUS.ica_status = Some(status);
}
}
pub fn update_matrix_status(status: matrix::MainStatus) {
unsafe {
MAIN_STATUS.matrix_status = Some(status);
}
}
pub fn static_init(config: BotConfig) {
unsafe {
MAIN_STATUS.config = Some(config);
}
}
pub fn global_config() -> &'static BotConfig { unsafe { MAIN_STATUS.config.as_ref().unwrap() } }
pub fn global_ica_status() -> &'static ica::MainStatus {
unsafe { MAIN_STATUS.ica_status.as_ref().unwrap() }
}
pub fn global_matrix_status() -> &'static matrix::MainStatus {
unsafe { MAIN_STATUS.matrix_status.as_ref().unwrap() }
}
}
pub mod ica {
pub struct MainStatus {}
use crate::data_struct::ica::all_rooms::Room;
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,
}
}
pub mod matrix {
pub struct MainStatus {}
#[derive(Debug, Clone)]
pub struct MainStatus {
/// 是否启用 matrix
pub enable: bool,
}
}