mirror of
http://shenjack.top:5100/shenjack/icalingua-python-bot.git
synced 2024-11-23 12:41:05 +08:00
p1
This commit is contained in:
parent
a606db5cb0
commit
ca9033a23f
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -3,6 +3,7 @@ env*
|
|||
|
||||
config.toml
|
||||
|
||||
.idea
|
||||
*.pyc
|
||||
*__pycache__/
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use serde_json::{json, Value as JsonValue};
|
|||
use crate::data_struct::tailchat::{ConverseId, GroupId, MessageId, UserId};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct ReciveMessage {
|
||||
pub struct ReceiveMessage {
|
||||
/// 消息ID
|
||||
#[serde(rename = "_id")]
|
||||
pub msg_id: MessageId,
|
||||
|
@ -27,7 +27,7 @@ pub struct ReciveMessage {
|
|||
pub has_recall: bool,
|
||||
/// 暂时懒得解析这玩意
|
||||
/// 准确来说是不确定内容, 毕竟没细看 API
|
||||
pub meta: JsonValue,
|
||||
pub meta: Option<JsonValue>,
|
||||
/// 也懒得解析这玩意
|
||||
pub reactions: Vec<JsonValue>,
|
||||
/// 创建时间
|
||||
|
@ -38,8 +38,14 @@ pub struct ReciveMessage {
|
|||
pub updated_at: String,
|
||||
}
|
||||
|
||||
impl ReciveMessage {
|
||||
pub fn is_reply(&self) -> bool { self.meta.get("reply").is_some() }
|
||||
impl ReceiveMessage {
|
||||
pub fn is_reply(&self) -> bool {
|
||||
if let Some(meta) = &self.meta {
|
||||
meta.get("reply").is_some()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// 创建一个对这条消息的回复
|
||||
pub fn as_reply(&self) -> SendingMessage {
|
||||
|
@ -62,7 +68,7 @@ impl ReciveMessage {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for ReciveMessage {
|
||||
impl Display for ReceiveMessage {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
// msgid|groupid-converseid|senderid|content
|
||||
write!(
|
||||
|
@ -90,6 +96,8 @@ pub struct SendingMessage {
|
|||
/// 消息内容
|
||||
///
|
||||
/// 其实还有个 plain, 就是不知道干啥的
|
||||
///
|
||||
/// [img height=1329 width=1918]{BACKEND}/static/files/6602e20d7b8d10675758e36b/8db505b87bdf9fb309467abcec4d8e2a.png[/img]
|
||||
pub content: String,
|
||||
/// 会话ID
|
||||
#[serde(rename = "converseId")]
|
||||
|
@ -99,6 +107,9 @@ pub struct SendingMessage {
|
|||
pub group_id: Option<GroupId>,
|
||||
/// 消息的元数据
|
||||
pub meta: Option<ReplyMeta>,
|
||||
/// 额外携带的文件
|
||||
#[serde(skip)]
|
||||
pub file: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl SendingMessage {
|
||||
|
@ -113,6 +124,7 @@ impl SendingMessage {
|
|||
converse_id,
|
||||
group_id,
|
||||
meta,
|
||||
file: None,
|
||||
}
|
||||
}
|
||||
pub fn new_without_meta(
|
||||
|
@ -125,8 +137,13 @@ impl SendingMessage {
|
|||
converse_id,
|
||||
group_id,
|
||||
meta: None,
|
||||
file: None,
|
||||
}
|
||||
}
|
||||
pub fn contain_file(&self) -> bool { self.file.is_some() }
|
||||
|
||||
pub fn add_img(&mut self, file: Vec<u8>, ) { self.file = Some(file); }
|
||||
|
||||
pub fn as_value(&self) -> JsonValue { serde_json::to_value(self).unwrap() }
|
||||
}
|
||||
|
||||
|
@ -143,7 +160,7 @@ pub struct ReplyMeta {
|
|||
}
|
||||
|
||||
impl ReplyMeta {
|
||||
pub fn from_recive_message(msg: &ReciveMessage) -> Self {
|
||||
pub fn from_recive_message(msg: &ReceiveMessage) -> Self {
|
||||
Self {
|
||||
mentions: vec![msg.sender_id.clone()],
|
||||
reply_id: msg.msg_id.clone(),
|
||||
|
|
|
@ -33,32 +33,18 @@ pub struct UpdateDMConverse {
|
|||
pub updated_at: String,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub type Writeable<T> = Arc<RwLock<T>>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BotStatus {
|
||||
user_id: Writeable<UserId>,
|
||||
user_id: UserId,
|
||||
}
|
||||
|
||||
impl BotStatus {
|
||||
pub fn new(user_id: UserId) -> Self {
|
||||
Self {
|
||||
user_id: Arc::new(RwLock::new(user_id)),
|
||||
}
|
||||
}
|
||||
pub fn new(user_id: UserId) -> Self { Self { user_id } }
|
||||
|
||||
pub async fn get_user_id(&self) -> UserId { self.user_id.read().await.clone() }
|
||||
|
||||
pub fn block_get_user_id(&self) -> UserId {
|
||||
tokio::task::block_in_place(|| {
|
||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||
rt.block_on(self.get_user_id())
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn set_user_id(&self, user_id: UserId) {
|
||||
self.user_id.write().await.clone_from(&user_id);
|
||||
}
|
||||
pub fn get_user_id(&self) -> UserId { self.user_id.clone() }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -31,7 +31,7 @@ pub async fn add_message(payload: Payload, client: Client) {
|
|||
return;
|
||||
}
|
||||
|
||||
info!("add_message {}", message.to_string().cyan());
|
||||
event!(Level::INFO, "add_message {}", message.to_string().cyan());
|
||||
// 就在这里处理掉最基本的消息
|
||||
// 之后的处理交给插件
|
||||
if !message.is_from_self() && !message.is_reply() {
|
||||
|
@ -68,7 +68,7 @@ pub async fn delete_message(payload: Payload, client: Client) {
|
|||
// 消息 id
|
||||
if let Some(value) = values.first() {
|
||||
if let Some(msg_id) = value.as_str() {
|
||||
info!("delete_message {}", msg_id.to_string().yellow());
|
||||
event!(Level::INFO, "delete_message {}", msg_id.to_string().yellow());
|
||||
|
||||
py::call::ica_delete_message_py(msg_id.to_string(), &client).await;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ pub const VERSION: &str = env!("CARGO_PKG_VERSION");
|
|||
pub const ICA_VERSION: &str = "1.6.0";
|
||||
pub const TAILCHAT_VERSION: &str = "1.1.0";
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! async_callback_with_state {
|
||||
($f:expr, $state:expr) => {{
|
||||
use futures_util::FutureExt;
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use pyo3::prelude::*;
|
||||
use rust_socketio::asynchronous::Client;
|
||||
use tracing::{info, warn};
|
||||
use tracing::{event, info, warn, Level};
|
||||
|
||||
use crate::data_struct::tailchat::status::BotStatus;
|
||||
use crate::data_struct::{ica, tailchat};
|
||||
use crate::error::PyPluginError;
|
||||
use crate::py::{class, PyPlugin, PyStatus};
|
||||
|
@ -106,7 +108,7 @@ macro_rules! call_py_func {
|
|||
$func_name.to_string(),
|
||||
$plugin_path.to_string_lossy().to_string(),
|
||||
);
|
||||
warn!("failed to call function<{}>: {:?}", $func_name, e);
|
||||
event!(Level::WARN, "failed to call function<{}>: {:?}", $func_name, e);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -126,20 +128,6 @@ pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Cl
|
|||
let args = (msg, client);
|
||||
// 甚至实际上压根不需要await这个spawn, 直接让他自己跑就好了(离谱)
|
||||
call_py_func!(args, plugin, path, ICA_NEW_MESSAGE_FUNC, client);
|
||||
// tokio::spawn(async move {
|
||||
// Python::with_gil(|py| {
|
||||
// if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_NEW_MESSAGE_FUNC) {
|
||||
// if let Err(e) = py_func.call1(args) {
|
||||
// let e = PyPluginError::FuncCallError(
|
||||
// e,
|
||||
// ICA_NEW_MESSAGE_FUNC.to_string(),
|
||||
// path.to_string_lossy().to_string(),
|
||||
// );
|
||||
// warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e);
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,29 +140,19 @@ pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) {
|
|||
let client = class::ica::IcaClientPy::new(client);
|
||||
let args = (msg_id.clone(), client);
|
||||
call_py_func!(args, plugin, path, ICA_DELETE_MESSAGE_FUNC, client);
|
||||
// tokio::spawn(async move {
|
||||
// Python::with_gil(|py| {
|
||||
// if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_DELETE_MESSAGE_FUNC) {
|
||||
// if let Err(e) = py_func.call1(args) {
|
||||
// let e = PyPluginError::FuncCallError(
|
||||
// e,
|
||||
// ICA_DELETE_MESSAGE_FUNC.to_string(),
|
||||
// path.to_string_lossy().to_string(),
|
||||
// );
|
||||
// warn!("failed to call function<{}>: {:?}", ICA_DELETE_MESSAGE_FUNC, e);
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// });
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn tailchat_new_message_py(message: &tailchat::messages::ReciveMessage, client: &Client) {
|
||||
pub async fn tailchat_new_message_py(
|
||||
message: &tailchat::messages::ReceiveMessage,
|
||||
client: &Client,
|
||||
status: Arc<BotStatus>,
|
||||
) {
|
||||
verify_plugins();
|
||||
|
||||
let plugins = PyStatus::get_files();
|
||||
for (path, plugin) in plugins.iter() {
|
||||
let msg = class::tailchat::TailchatReciveMessagePy::from_recive_message(message);
|
||||
let msg = class::tailchat::TailchatReceiveMessagePy::from_recive_message(message);
|
||||
let client = class::tailchat::TailchatClientPy::new(client);
|
||||
let args = (msg, client);
|
||||
call_py_func!(args, plugin, path, TAILCHAT_NEW_MESSAGE_FUNC, client);
|
||||
|
|
|
@ -3,7 +3,7 @@ use pyo3::prelude::*;
|
|||
use rust_socketio::asynchronous::Client;
|
||||
use tracing::{debug, info, warn};
|
||||
|
||||
use crate::data_struct::tailchat::messages::{ReciveMessage, SendingMessage};
|
||||
use crate::data_struct::tailchat::messages::{ReceiveMessage, SendingMessage};
|
||||
use crate::data_struct::tailchat::{ConverseId, GroupId, MessageId, UserId};
|
||||
use crate::tailchat::client::send_message;
|
||||
|
||||
|
@ -27,13 +27,13 @@ impl TailchatClientPy {
|
|||
pub struct TailchatStatusPy {}
|
||||
|
||||
#[pyclass]
|
||||
#[pyo3(name = "TailchatReciveMessage")]
|
||||
pub struct TailchatReciveMessagePy {
|
||||
pub message: ReciveMessage,
|
||||
#[pyo3(name = "TailchatReceiveMessage")]
|
||||
pub struct TailchatReceiveMessagePy {
|
||||
pub message: ReceiveMessage,
|
||||
}
|
||||
|
||||
impl TailchatReciveMessagePy {
|
||||
pub fn from_recive_message(msg: &ReciveMessage) -> Self {
|
||||
impl TailchatReceiveMessagePy {
|
||||
pub fn from_recive_message(msg: &ReceiveMessage) -> Self {
|
||||
Self {
|
||||
message: msg.clone(),
|
||||
}
|
||||
|
@ -76,7 +76,7 @@ impl TailchatClientPy {
|
|||
}
|
||||
|
||||
#[pymethods]
|
||||
impl TailchatReciveMessagePy {
|
||||
impl TailchatReceiveMessagePy {
|
||||
#[getter]
|
||||
pub fn get_is_reply(&self) -> bool { self.message.is_reply() }
|
||||
#[getter]
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
pub mod client;
|
||||
pub mod events;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use colored::Colorize;
|
||||
use md5::{Digest, Md5};
|
||||
use reqwest::ClientBuilder as reqwest_ClientBuilder;
|
||||
|
@ -11,9 +13,9 @@ use serde_json::{json, Value};
|
|||
use tracing::{event, span, Level};
|
||||
|
||||
use crate::config::TailchatConfig;
|
||||
use crate::data_struct::tailchat::status::LoginData;
|
||||
use crate::data_struct::tailchat::status::{BotStatus, LoginData};
|
||||
use crate::error::{ClientResult, TailchatError};
|
||||
use crate::StopGetter;
|
||||
use crate::{async_callback_with_state, StopGetter};
|
||||
|
||||
pub async fn start_tailchat(
|
||||
config: TailchatConfig,
|
||||
|
@ -60,11 +62,17 @@ pub async fn start_tailchat(
|
|||
Err(e) => return Err(TailchatError::LoginFailed(e.to_string())),
|
||||
};
|
||||
|
||||
let sharded_status = BotStatus::new(status.user_id.clone());
|
||||
let sharded_status = Arc::new(sharded_status);
|
||||
|
||||
let socket = ClientBuilder::new(config.host)
|
||||
.auth(json!({"token": status.jwt.clone()}))
|
||||
.transport_type(TransportType::Websocket)
|
||||
.on_any(async_any_callback!(events::any_event))
|
||||
.on("notify:chat.message.add", async_callback!(events::on_message))
|
||||
.on(
|
||||
"notify:chat.message.add",
|
||||
async_callback_with_state!(events::on_message, sharded_status.clone()),
|
||||
)
|
||||
.on("notify:chat.message.delete", async_callback!(events::on_msg_delete))
|
||||
.on(
|
||||
"notify:chat.converse.updateDMConverse",
|
||||
|
|
|
@ -8,6 +8,10 @@ use serde_json::{json, Value};
|
|||
use tracing::{debug, info, warn};
|
||||
|
||||
pub async fn send_message(client: &Client, message: &SendingMessage) -> bool {
|
||||
if message.contain_file() {
|
||||
// 处理文件
|
||||
|
||||
}
|
||||
let value: Value = message.as_value();
|
||||
match client.emit("chat.message.sendMessage", value).await {
|
||||
Ok(_) => {
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use colored::Colorize;
|
||||
use rust_socketio::asynchronous::Client;
|
||||
use rust_socketio::{Event, Payload};
|
||||
use tracing::info;
|
||||
|
||||
use crate::data_struct::tailchat::messages::ReciveMessage;
|
||||
use crate::data_struct::tailchat::status::UpdateDMConverse;
|
||||
use crate::data_struct::tailchat::messages::ReceiveMessage;
|
||||
use crate::data_struct::tailchat::status::{BotStatus, UpdateDMConverse};
|
||||
use crate::tailchat::client::{emit_join_room, send_message};
|
||||
|
||||
/// 所有
|
||||
|
@ -60,10 +62,10 @@ pub async fn any_event(event: Event, payload: Payload, _client: Client) {
|
|||
}
|
||||
|
||||
#[allow(clippy::collapsible_if)]
|
||||
pub async fn on_message(payload: Payload, client: Client) {
|
||||
pub async fn on_message(payload: Payload, client: Client, status: Arc<BotStatus>) {
|
||||
if let Payload::Text(values) = payload {
|
||||
if let Some(value) = values.first() {
|
||||
let message: ReciveMessage = match serde_json::from_value(value.clone()) {
|
||||
let message: ReceiveMessage = match serde_json::from_value(value.clone()) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
info!("tailchat_msg {}", value.to_string().red());
|
||||
|
@ -83,7 +85,7 @@ pub async fn on_message(payload: Payload, client: Client) {
|
|||
send_message(&client, &reply).await;
|
||||
}
|
||||
}
|
||||
crate::py::call::tailchat_new_message_py(&message, &client).await;
|
||||
crate::py::call::tailchat_new_message_py(&message, &client, status.clone()).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user