mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2025-04-20 15:29:54 +08:00
Compare commits
No commits in common. "3ed0f5af1ef000347835b17627ed66f4cdbb0b2b" and "d6443f27bb069a7421b8fdf70ee89f9909c8b3f6" have entirely different histories.
3ed0f5af1e
...
d6443f27bb
|
@ -1,16 +1,6 @@
|
||||||
# Python 兼容版本 3.8+
|
# Python 兼容版本 3.8+
|
||||||
|
|
||||||
from typing import Optional, Callable
|
from typing import Optional
|
||||||
|
|
||||||
"""
|
|
||||||
pub type RoomId = i64;
|
|
||||||
pub type UserId = i64;
|
|
||||||
pub type MessageId = String;
|
|
||||||
"""
|
|
||||||
|
|
||||||
RoomId = int
|
|
||||||
UserId = int
|
|
||||||
MessageId = str
|
|
||||||
|
|
||||||
|
|
||||||
class IcaStatus:
|
class IcaStatus:
|
||||||
|
@ -21,7 +11,7 @@ class IcaStatus:
|
||||||
def online(self) -> bool:
|
def online(self) -> bool:
|
||||||
...
|
...
|
||||||
@property
|
@property
|
||||||
def self_id(self) -> Optional[UserId]:
|
def self_id(self) -> Optional[bool]:
|
||||||
...
|
...
|
||||||
@property
|
@property
|
||||||
def nick_name(self) -> Optional[str]:
|
def nick_name(self) -> Optional[str]:
|
||||||
|
@ -48,18 +38,7 @@ class ReplyMessage:
|
||||||
|
|
||||||
|
|
||||||
class SendMessage:
|
class SendMessage:
|
||||||
@property
|
...
|
||||||
def content(self) -> str:
|
|
||||||
...
|
|
||||||
@content.setter
|
|
||||||
def content(self, value: str) -> None:
|
|
||||||
...
|
|
||||||
def with_content(self, content: str) -> "SendMessage":
|
|
||||||
"""
|
|
||||||
为了链式调用, 返回自身
|
|
||||||
"""
|
|
||||||
self.content = content
|
|
||||||
return self
|
|
||||||
|
|
||||||
|
|
||||||
class NewMessage:
|
class NewMessage:
|
||||||
|
@ -68,13 +47,10 @@ class NewMessage:
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
...
|
...
|
||||||
@property
|
@property
|
||||||
def id(self) -> MessageId:
|
|
||||||
...
|
|
||||||
@property
|
|
||||||
def content(self) -> str:
|
def content(self) -> str:
|
||||||
...
|
...
|
||||||
@property
|
@property
|
||||||
def sender_id(self) -> UserId:
|
def sender_id(self) -> int:
|
||||||
...
|
...
|
||||||
@property
|
@property
|
||||||
def is_from_self(self) -> bool:
|
def is_from_self(self) -> bool:
|
||||||
|
@ -88,26 +64,19 @@ class IcaClient:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def send_message_a(client: "IcaClient", message: SendMessage) -> bool:
|
async def send_message_a(client: "IcaClient", message: SendMessage) -> bool:
|
||||||
"""
|
"""
|
||||||
仅作占位, 不能使用
|
仅作占位
|
||||||
(因为目前来说, rust调用 Python端没法启动一个异步运行时
|
(因为目前来说, rust调用 Python端没法启动一个异步运行时
|
||||||
所以只能 tokio::task::block_in_place 转换成同步调用)
|
所以只能 tokio::task::block_in_place 转换成同步调用)
|
||||||
"""
|
"""
|
||||||
def send_message(self, message: SendMessage) -> bool:
|
def send_message(self, message: SendMessage) -> bool:
|
||||||
...
|
...
|
||||||
def debug(self, message: str) -> None:
|
def debug(self, message: str) -> None:
|
||||||
"""向日志中输出调试信息"""
|
...
|
||||||
def info(self, message: str) -> None:
|
def info(self, message: str) -> None:
|
||||||
"""向日志中输出信息"""
|
...
|
||||||
def warn(self, message: str) -> None:
|
def warn(self, message: str) -> None:
|
||||||
"""向日志中输出警告信息"""
|
...
|
||||||
|
|
||||||
|
|
||||||
on_load = Callable[[IcaClient], None]
|
def on_message(msg: NewMessage, client: IcaClient) -> None:
|
||||||
# def on_load(client: IcaClient) -> None:
|
...
|
||||||
# ...
|
|
||||||
|
|
||||||
on_message = Callable[[NewMessage, IcaClient], None]
|
|
||||||
# def on_message(msg: NewMessage, client: IcaClient) -> None:
|
|
||||||
# ...
|
|
||||||
|
|
||||||
on_delete_message = Callable[[int, IcaClient], None]
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use crate::client::send_message;
|
use crate::client::send_message;
|
||||||
use crate::data_struct::messages::{NewMessage, ReplyMessage, SendMessage};
|
use crate::data_struct::messages::{NewMessage, ReplyMessage, SendMessage};
|
||||||
use crate::data_struct::MessageId;
|
|
||||||
use crate::ClientStatus;
|
use crate::ClientStatus;
|
||||||
|
|
||||||
#[pyclass]
|
#[pyclass]
|
||||||
|
@ -127,10 +126,7 @@ impl NewMessagePy {
|
||||||
pub fn __str__(&self) -> String {
|
pub fn __str__(&self) -> String {
|
||||||
format!("{:?}", self.msg)
|
format!("{:?}", self.msg)
|
||||||
}
|
}
|
||||||
#[getter]
|
|
||||||
pub fn get_id(&self) -> MessageId {
|
|
||||||
self.msg.msg_id.clone()
|
|
||||||
}
|
|
||||||
#[getter]
|
#[getter]
|
||||||
pub fn get_content(&self) -> String {
|
pub fn get_content(&self) -> String {
|
||||||
self.msg.content.clone()
|
self.msg.content.clone()
|
||||||
|
@ -186,20 +182,6 @@ impl SendMessagePy {
|
||||||
pub fn __str__(&self) -> String {
|
pub fn __str__(&self) -> String {
|
||||||
format!("{:?}", self.msg)
|
format!("{:?}", self.msg)
|
||||||
}
|
}
|
||||||
/// 设置消息内容
|
|
||||||
/// 用于链式调用
|
|
||||||
pub fn with_content(&mut self, content: String) -> Self {
|
|
||||||
self.msg.content = content;
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
#[getter]
|
|
||||||
pub fn get_content(&self) -> String {
|
|
||||||
self.msg.content.clone()
|
|
||||||
}
|
|
||||||
#[setter]
|
|
||||||
pub fn set_content(&mut self, content: String) {
|
|
||||||
self.msg.content = content;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SendMessagePy {
|
impl SendMessagePy {
|
||||||
|
|
|
@ -3,7 +3,6 @@ pub mod class;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use std::{collections::HashMap, path::PathBuf};
|
use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use futures_util::future::join_all;
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use rust_socketio::asynchronous::Client;
|
use rust_socketio::asynchronous::Client;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
@ -199,119 +198,41 @@ pub fn init_py(config: &IcaConfig) {
|
||||||
pub async fn new_message_py(message: &NewMessage, client: &Client) {
|
pub async fn new_message_py(message: &NewMessage, client: &Client) {
|
||||||
// 验证插件是否改变
|
// 验证插件是否改变
|
||||||
verify_plugins();
|
verify_plugins();
|
||||||
|
let cwd = std::env::current_dir().unwrap();
|
||||||
|
|
||||||
let plugins = PyStatus::get_files();
|
let plugins = PyStatus::get_files();
|
||||||
// let tasks: Vec<_> = plugins.iter().map(|(path, (_, py_module))| {
|
|
||||||
// let msg = class::NewMessagePy::new(message);
|
|
||||||
// let client = class::IcaClientPy::new(client);
|
|
||||||
// let (cancel_tx, cancel_rx) = tokio::sync::oneshot::channel();
|
|
||||||
// let task = tokio::spawn(async move {
|
|
||||||
// tokio::select! {
|
|
||||||
// _ = tokio::spawn(async move {Python::with_gil(|py| {
|
|
||||||
// let args = (msg, client);
|
|
||||||
// let async_py_func = py_module.getattr(py, "on_message");
|
|
||||||
// match async_py_func {
|
|
||||||
// Ok(async_py_func) => match async_py_func.as_ref(py).call1(args) {
|
|
||||||
// Err(e) => {
|
|
||||||
// warn!("get a PyErr when call on_message from {:?}: {:?}", path, e);
|
|
||||||
// }
|
|
||||||
// _ => (),
|
|
||||||
// },
|
|
||||||
// Err(e) => {
|
|
||||||
// warn!("failed to get on_message function: {:?}", e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// })}) => (),
|
|
||||||
// _ = cancel_rx => (),
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// (task, cancel_tx)
|
|
||||||
// }).collect();
|
|
||||||
|
|
||||||
// let timeout = tokio::time::sleep(std::time::Duration::from_secs(5));
|
|
||||||
// tokio::select! {
|
|
||||||
// _ = join_all(tasks.map(|(task, _)| task)) => (),
|
|
||||||
// _ = timeout => {
|
|
||||||
// warn!("timeout when join all tasks");
|
|
||||||
// for (_, cancel_tx) in &tasks {
|
|
||||||
// let _ = cancel_tx.send(());
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for (path, (_, py_module)) in plugins.iter() {
|
|
||||||
// let msg = class::NewMessagePy::new(message);
|
|
||||||
// let client = class::IcaClientPy::new(client);
|
|
||||||
// let task = tokio::spawn(async move {
|
|
||||||
// Python::with_gil(|py| {
|
|
||||||
// let args = (msg, client);
|
|
||||||
// let async_py_func = py_module.getattr(py, "on_message");
|
|
||||||
// match async_py_func {
|
|
||||||
// Ok(async_py_func) => match async_py_func.as_ref(py).call1(args) {
|
|
||||||
// Err(e) => {
|
|
||||||
// warn!("get a PyErr when call on_message from {:?}: {:?}", path, e);
|
|
||||||
// }
|
|
||||||
// _ => (),
|
|
||||||
// },
|
|
||||||
// Err(e) => {
|
|
||||||
// warn!("failed to get on_message function: {:?}", e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// });
|
|
||||||
// tokio::select! {
|
|
||||||
// _ = task => (),
|
|
||||||
// _ = tokio::time::sleep(std::time::Duration::from_secs(1)) => {
|
|
||||||
// warn!("timeout when join all tasks");
|
|
||||||
// // task.abort();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
let mut tasks = Vec::with_capacity(plugins.len());
|
|
||||||
for (path, (_, py_module)) in plugins.iter() {
|
for (path, (_, py_module)) in plugins.iter() {
|
||||||
let msg = class::NewMessagePy::new(message);
|
// 切换工作目录到运行的插件的位置
|
||||||
let client = class::IcaClientPy::new(client);
|
let mut goto = cwd.clone();
|
||||||
let task = tokio::spawn(async move {
|
goto.push(path.parent().unwrap());
|
||||||
Python::with_gil(|py| {
|
|
||||||
let args = (msg, client);
|
if let Err(e) = std::env::set_current_dir(&goto) {
|
||||||
let async_py_func = py_module.getattr(py, "on_message");
|
warn!("移动工作目录到 {:?} 失败 {:?} cwd: {:?}", goto, e, cwd);
|
||||||
match async_py_func {
|
}
|
||||||
Ok(async_py_func) => match async_py_func.as_ref(py).call1(args) {
|
|
||||||
|
Python::with_gil(|py| {
|
||||||
|
let msg = class::NewMessagePy::new(message);
|
||||||
|
let client = class::IcaClientPy::new(client);
|
||||||
|
let args = (msg, client);
|
||||||
|
let async_py_func = py_module.getattr(py, "on_message");
|
||||||
|
match async_py_func {
|
||||||
|
Ok(async_py_func) => {
|
||||||
|
match async_py_func.as_ref(py).call1(args) {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("get a PyErr when call on_message from {:?}: {:?}", path, e);
|
warn!("get a PyErr when call on_message from {:?}: {:?}", path, e);
|
||||||
}
|
},
|
||||||
_ => (),
|
_ => ()
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
warn!("failed to get on_message function: {:?}", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
Err(e) => {
|
||||||
|
warn!("failed to get on_message function: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
tasks.push(task);
|
|
||||||
}
|
}
|
||||||
// 等待所有的插件执行完毕
|
|
||||||
// 超时时间为 0.1 秒
|
// 最后切换回来
|
||||||
// ~~ 超时则取消所有的任务 ~~
|
if let Err(e) = std::env::set_current_dir(&cwd) {
|
||||||
// 超时就超时了……, 就让他跑着了……
|
warn!("设置工作目录{:?} 失败:{:?}", cwd, e);
|
||||||
// 主要是, 这玩意是同步的 还没法取消
|
|
||||||
let wait_time = std::time::Duration::from_millis(100);
|
|
||||||
let awaits = join_all(tasks);
|
|
||||||
let timeout = tokio::time::sleep(wait_time.clone());
|
|
||||||
let await_task = tokio::time::timeout(wait_time.clone(), awaits);
|
|
||||||
tokio::select! {
|
|
||||||
_ = await_task => (),
|
|
||||||
_ = timeout => {
|
|
||||||
warn!("timeout when join all tasks");
|
|
||||||
// for task in tasks {
|
|
||||||
// task.abort();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// match tokio::time::timeout(wait_time.clone(), awaits).await {
|
|
||||||
// Ok(_) => (),
|
|
||||||
// Err(e) => {
|
|
||||||
// warn!("timeout when join all tasks: {:?}", e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user