tailchat support p2

This commit is contained in:
shenjack 2024-03-30 12:54:52 +08:00
parent eaae60902d
commit 2f535cc960
Signed by: shenjack
GPG Key ID: 7B1134A979775551
7 changed files with 303 additions and 30 deletions

223
Cargo.lock generated
View File

@ -499,7 +499,26 @@ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"futures-util", "futures-util",
"http", "http 0.2.12",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "h2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http 1.1.0",
"indexmap", "indexmap",
"slab", "slab",
"tokio", "tokio",
@ -542,6 +561,17 @@ dependencies = [
"itoa", "itoa",
] ]
[[package]]
name = "http"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "0.4.6" version = "0.4.6"
@ -549,7 +579,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [ dependencies = [
"bytes", "bytes",
"http", "http 0.2.12",
"pin-project-lite",
]
[[package]]
name = "http-body"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
dependencies = [
"bytes",
"http 1.1.0",
]
[[package]]
name = "http-body-util"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d"
dependencies = [
"bytes",
"futures-core",
"http 1.1.0",
"http-body 1.0.0",
"pin-project-lite", "pin-project-lite",
] ]
@ -575,9 +628,9 @@ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2", "h2 0.3.25",
"http", "http 0.2.12",
"http-body", "http-body 0.4.6",
"httparse", "httparse",
"httpdate", "httpdate",
"itoa", "itoa",
@ -589,6 +642,26 @@ dependencies = [
"want", "want",
] ]
[[package]]
name = "hyper"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"h2 0.4.3",
"http 1.1.0",
"http-body 1.0.0",
"httparse",
"itoa",
"pin-project-lite",
"smallvec",
"tokio",
"want",
]
[[package]] [[package]]
name = "hyper-tls" name = "hyper-tls"
version = "0.5.0" version = "0.5.0"
@ -596,12 +669,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [ dependencies = [
"bytes", "bytes",
"hyper", "hyper 0.14.28",
"native-tls", "native-tls",
"tokio", "tokio",
"tokio-native-tls", "tokio-native-tls",
] ]
[[package]]
name = "hyper-tls"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
dependencies = [
"bytes",
"http-body-util",
"hyper 1.2.0",
"hyper-util",
"native-tls",
"tokio",
"tokio-native-tls",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http 1.1.0",
"http-body 1.0.0",
"hyper 1.2.0",
"pin-project-lite",
"socket2",
"tokio",
"tower",
"tower-service",
"tracing",
]
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.60" version = "0.1.60"
@ -638,6 +747,7 @@ dependencies = [
"hex", "hex",
"md-5", "md-5",
"pyo3", "pyo3",
"reqwest 0.12.2",
"rust_socketio", "rust_socketio",
"serde", "serde",
"serde_json", "serde_json",
@ -935,6 +1045,26 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "pin-project"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.13" version = "0.2.13"
@ -1118,11 +1248,11 @@ dependencies = [
"encoding_rs", "encoding_rs",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2", "h2 0.3.25",
"http", "http 0.2.12",
"http-body", "http-body 0.4.6",
"hyper", "hyper 0.14.28",
"hyper-tls", "hyper-tls 0.5.0",
"ipnet", "ipnet",
"js-sys", "js-sys",
"log", "log",
@ -1149,6 +1279,48 @@ dependencies = [
"winreg", "winreg",
] ]
[[package]]
name = "reqwest"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d66674f2b6fb864665eea7a3c1ac4e3dfacd2fda83cf6f935a612e01b0e3338"
dependencies = [
"base64 0.21.7",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2 0.4.3",
"http 1.1.0",
"http-body 1.0.0",
"http-body-util",
"hyper 1.2.0",
"hyper-tls 0.6.0",
"hyper-util",
"ipnet",
"js-sys",
"log",
"mime",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper",
"system-configuration",
"tokio",
"tokio-native-tls",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"winreg",
]
[[package]] [[package]]
name = "rust_engineio" name = "rust_engineio"
version = "0.4.4" version = "0.4.4"
@ -1160,9 +1332,9 @@ dependencies = [
"base64 0.21.7", "base64 0.21.7",
"bytes", "bytes",
"futures-util", "futures-util",
"http", "http 0.2.12",
"native-tls", "native-tls",
"reqwest", "reqwest 0.11.27",
"serde", "serde",
"serde_json", "serde_json",
"thiserror", "thiserror",
@ -1657,6 +1829,28 @@ dependencies = [
"winnow", "winnow",
] ]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.2" version = "0.3.2"
@ -1669,6 +1863,7 @@ version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [ dependencies = [
"log",
"pin-project-lite", "pin-project-lite",
"tracing-attributes", "tracing-attributes",
"tracing-core", "tracing-core",
@ -1736,7 +1931,7 @@ dependencies = [
"byteorder", "byteorder",
"bytes", "bytes",
"data-encoding", "data-encoding",
"http", "http 0.2.12",
"httparse", "httparse",
"log", "log",
"native-tls", "native-tls",

View File

@ -8,7 +8,7 @@ edition = "2021"
[features] [features]
default = ["ica", "tailchat"] default = ["ica", "tailchat"]
ica = ["dep:ed25519", "dep:ed25519-dalek", "dep:hex", "dep:rust_socketio"] ica = ["dep:ed25519", "dep:ed25519-dalek", "dep:hex", "dep:rust_socketio"]
tailchat = ["dep:rust_socketio", "dep:md-5"] tailchat = ["dep:rust_socketio", "dep:md-5", "dep:reqwest"]
[dependencies] [dependencies]
@ -18,6 +18,7 @@ ed25519-dalek = { version = "2.1", optional = true }
hex = { version = "0.4", optional = true } hex = { version = "0.4", optional = true }
# tailchat # tailchat
reqwest = { version = "0.12.2", optional = true }
md-5 = { version = "0.10.6", optional = true } md-5 = { version = "0.10.6", optional = true }
# ica & tailchat (socketio) # ica & tailchat (socketio)

View File

@ -4,6 +4,16 @@ pub type ClientResult<T, E> = Result<T, E>;
pub enum IcaError { pub enum IcaError {
/// Socket IO 链接错误 /// Socket IO 链接错误
SocketIoError(rust_socketio::error::Error), SocketIoError(rust_socketio::error::Error),
/// 登录失败
LoginFailed(String),
}
#[derive(Debug)]
pub enum TailchatError {
/// Socket IO 链接错误
SocketIoError(rust_socketio::error::Error),
/// 登录失败
LoginFailed(String),
} }
#[derive(Debug)] #[derive(Debug)]
@ -29,6 +39,16 @@ impl std::fmt::Display for IcaError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
IcaError::SocketIoError(e) => write!(f, "Socket IO 链接错误: {}", e), IcaError::SocketIoError(e) => write!(f, "Socket IO 链接错误: {}", e),
IcaError::LoginFailed(e) => write!(f, "登录失败: {}", e),
}
}
}
impl std::fmt::Display for TailchatError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TailchatError::SocketIoError(e) => write!(f, "Socket IO 链接错误: {}", e),
TailchatError::LoginFailed(e) => write!(f, "登录失败: {}", e),
} }
} }
} }
@ -56,6 +76,16 @@ impl std::error::Error for IcaError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self { match self {
IcaError::SocketIoError(e) => Some(e), IcaError::SocketIoError(e) => Some(e),
IcaError::LoginFailed(_) => None,
}
}
}
impl std::error::Error for TailchatError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
TailchatError::SocketIoError(e) => Some(e),
TailchatError::LoginFailed(_) => None,
} }
} }
} }
@ -66,7 +96,7 @@ impl std::error::Error for PyPluginError {
PyPluginError::FuncNotFound(_, _) => None, PyPluginError::FuncNotFound(_, _) => None,
PyPluginError::CouldNotGetFunc(e, _, _) => Some(e), PyPluginError::CouldNotGetFunc(e, _, _) => Some(e),
PyPluginError::FuncNotCallable(_, _) => None, PyPluginError::FuncNotCallable(_, _) => None,
PyPluginError::FuncCallError(_, _) => None, PyPluginError::FuncCallError(e, _, _) => Some(e),
} }
} }
} }

View File

@ -1,4 +1,5 @@
use crate::data_struct::ica::messages::{DeleteMessage, SendMessage}; use crate::data_struct::ica::messages::{DeleteMessage, SendMessage};
use crate::error::{ClientResult, IcaError};
use crate::MainStatus; use crate::MainStatus;
use colored::Colorize; use colored::Colorize;
@ -43,24 +44,24 @@ pub async fn delete_message(client: &Client, message: &DeleteMessage) -> bool {
// #[allow(dead_code)] // #[allow(dead_code)]
// pub async fn fetch_history(client: &Client, roomd_id: RoomId) -> bool { false } // pub async fn fetch_history(client: &Client, roomd_id: RoomId) -> bool { false }
pub async fn sign_callback(payload: Payload, client: Client) { async fn inner_sign(payload: Payload, client: Client) -> ClientResult<(), IcaError> {
let span = span!(Level::INFO, "signing icalingua"); let span = span!(Level::INFO, "signing icalingua");
let _guard = span.enter(); let _guard = span.enter();
// 获取数据 // 获取数据
let require_data = match payload { let require_data = match payload {
Payload::Text(json_value) => Some(json_value), Payload::Text(json_value) => Ok(json_value),
_ => None, _ => Err(IcaError::LoginFailed("Got a invalid payload".to_string())),
} }?;
.expect("Payload should be Json data");
let (auth_key, version) = (&require_data[0], &require_data[1]); let (auth_key, version) = (&require_data[0], &require_data[1]);
debug!("auth_key: {:?}, server_version: {:?}", auth_key, version); debug!("auth_key: {:?}, server_version: {:?}", auth_key, version);
let auth_key = match &require_data.first() { let auth_key = match &require_data.first() {
Some(Value::String(auth_key)) => Some(auth_key), Some(Value::String(auth_key)) => Ok(auth_key),
_ => None, _ => Err(IcaError::LoginFailed("Got a invalid auth_key".to_string())),
} }?;
.expect("auth_key should be string");
let salt = hex::decode(auth_key).expect("Got an invalid salt from the server"); let salt = hex::decode(auth_key).expect("Got an invalid salt from the server");
// 签名 // 签名
@ -76,4 +77,11 @@ pub async fn sign_callback(payload: Payload, client: Client) {
// 发送签名 // 发送签名
let sign = signature.to_bytes().to_vec(); let sign = signature.to_bytes().to_vec();
client.emit("auth", sign).await.expect("Faild to send signin data"); client.emit("auth", sign).await.expect("Faild to send signin data");
Ok(())
}
/// 签名回调
/// 失败的时候得 panic
pub async fn sign_callback(payload: Payload, client: Client) {
inner_sign(payload, client).await.expect("Faild to sign");
} }

View File

@ -95,13 +95,19 @@ pub const ICA_DELETE_MESSAGE_FUNC: &str = "on_ica_delete_message";
pub const TAILCHAT_NEW_MESSAGE_FUNC: &str = "on_tailchat_message"; pub const TAILCHAT_NEW_MESSAGE_FUNC: &str = "on_tailchat_message";
macro_rules! call_py_func {
($args:expr, $func_name:expr, $client:expr) => {
};
}
/// 执行 new message 的 python 插件 /// 执行 new message 的 python 插件
pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Client) { pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Client) {
// 验证插件是否改变 // 验证插件是否改变
verify_plugins(); verify_plugins();
let plugins = PyStatus::get_files(); let plugins = PyStatus::get_files();
for (_path, plugin) in plugins.iter() { for (path, plugin) in plugins.iter() {
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);
@ -110,8 +116,12 @@ pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Cl
Python::with_gil(|py| { Python::with_gil(|py| {
if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_NEW_MESSAGE_FUNC) { if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_NEW_MESSAGE_FUNC) {
if let Err(e) = py_func.call1(args) { if let Err(e) = py_func.call1(args) {
let e = PyPluginError::FuncCallError(e, ICA_NEW_MESSAGE_FUNC.to_string()); let e = PyPluginError::FuncCallError(
// warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e); e,
ICA_NEW_MESSAGE_FUNC.to_string(),
path.to_string_lossy().to_string(),
);
warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e);
} }
} }
}) })
@ -123,7 +133,7 @@ pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) {
verify_plugins(); verify_plugins();
let plugins = PyStatus::get_files(); let plugins = PyStatus::get_files();
for (_path, plugin) in plugins.iter() { for (path, plugin) in plugins.iter() {
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);
@ -131,6 +141,11 @@ pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) {
Python::with_gil(|py| { Python::with_gil(|py| {
if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_DELETE_MESSAGE_FUNC) { if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_DELETE_MESSAGE_FUNC) {
if let Err(e) = py_func.call1(args) { 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); warn!("failed to call function<{}>: {:?}", ICA_DELETE_MESSAGE_FUNC, e);
} }
} }
@ -139,4 +154,6 @@ pub async fn ica_delete_message_py(msg_id: ica::MessageId, client: &Client) {
} }
} }
// pub async fn tailchat_new_message_py(message: ) pub async fn tailchat_new_message_py(message: tailchat::messages::ReciveMessage, client: &Client) {
}

View File

@ -1 +1,23 @@
pub mod events;
use futures_util::FutureExt;
use rust_socketio::asynchronous::{Client, ClientBuilder};
use rust_socketio::{Event, Payload, TransportType};
use tracing::{event, span, Level};
// use crate::config::IcaConfig;
use crate::error::{ClientResult, TailchatError};
pub async fn start_tailchat() -> ClientResult<(), TailchatError> {
let span = span!(Level::INFO, "Tailchat Client");
let _enter = span.enter();
event!(Level::INFO, "tailchat-async-rs v{} initing", crate::TAILCHAT_VERSION);
// let socket = match ClientBuilder::new() {
// };
Ok(())
}

View File