Compare commits
2 Commits
6dfbc4e879
...
2f535cc960
Author | SHA1 | Date | |
---|---|---|---|
2f535cc960 | |||
eaae60902d |
227
Cargo.lock
generated
227
Cargo.lock
generated
@ -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",
|
||||||
@ -890,9 +1000,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.101"
|
version = "0.9.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dda2b0f344e78efc2facf7d195d098df0dd72151b26ab98da807afc26c198dff"
|
checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@ -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",
|
||||||
|
@ -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)
|
||||||
@ -26,9 +27,9 @@ rust_socketio = { version = "0.4.4", features = ["async"], optional = true }
|
|||||||
# data
|
# data
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
chrono = "0.4.37"
|
chrono = "0.4"
|
||||||
toml = "0.8.12"
|
toml = "0.8"
|
||||||
colored = "2.1.0"
|
colored = "2.1"
|
||||||
|
|
||||||
# runtime
|
# runtime
|
||||||
tokio = { version = "1.37", features = ["full"] }
|
tokio = { version = "1.37", features = ["full"] }
|
||||||
|
@ -24,7 +24,6 @@ pub struct IcaConfig {
|
|||||||
pub filter_list: Vec<i64>,
|
pub filter_list: Vec<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct PyConfig {
|
pub struct PyConfig {
|
||||||
/// 插件路径
|
/// 插件路径
|
||||||
|
@ -1 +1,2 @@
|
|||||||
pub mod ica;
|
pub mod ica;
|
||||||
|
pub mod tailchat;
|
||||||
|
6
ica-rs/src/data_struct/tailchat.rs
Normal file
6
ica-rs/src/data_struct/tailchat.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
pub mod messages;
|
||||||
|
|
||||||
|
pub type GroupId = String;
|
||||||
|
pub type ConverseId = String;
|
||||||
|
pub type UserId = String;
|
||||||
|
pub type MessageId = String;
|
119
ica-rs/src/data_struct/tailchat/messages.rs
Normal file
119
ica-rs/src/data_struct/tailchat/messages.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::{json, Value as JsonValue};
|
||||||
|
|
||||||
|
use crate::data_struct::tailchat::{ConverseId, GroupId, MessageId, UserId};
|
||||||
|
|
||||||
|
/*{'_id': '6606b3075163504389a6fc47',
|
||||||
|
'content': '光速!(',
|
||||||
|
'author': '6602e20d7b8d10675758e36b',
|
||||||
|
'groupId': '6602e331d31fd31b04aa0693',
|
||||||
|
'converseId': '6602f785928c4254f17726b2',
|
||||||
|
'hasRecall': False,
|
||||||
|
'meta': {'mentions': []},
|
||||||
|
'reactions': [],
|
||||||
|
'createdAt': ExtType(code=0, data=b'\x00\x00\x01\x8e\x8a+TJ'),
|
||||||
|
'updatedAt': ExtType(code=0, data=b'\x00\x00\x01\x8e\x8a+TJ'),
|
||||||
|
'__v': 0} */
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct ReciveMessage {
|
||||||
|
/// 消息ID
|
||||||
|
#[serde(rename = "_id")]
|
||||||
|
pub msg_id: MessageId,
|
||||||
|
/// 消息内容
|
||||||
|
pub content: String,
|
||||||
|
/// 发送者ID
|
||||||
|
#[serde(rename = "author")]
|
||||||
|
pub sender_id: UserId,
|
||||||
|
/// 服务器ID
|
||||||
|
#[serde(rename = "groupId")]
|
||||||
|
pub group_id: GroupId,
|
||||||
|
/// 会话ID
|
||||||
|
#[serde(rename = "converseId")]
|
||||||
|
pub converse_id: ConverseId,
|
||||||
|
/// 是否有回复?
|
||||||
|
#[serde(rename = "hasRecall")]
|
||||||
|
pub has_recall: bool,
|
||||||
|
/// 暂时懒得解析这玩意
|
||||||
|
pub meta: JsonValue,
|
||||||
|
/// 也懒得解析这玩意
|
||||||
|
pub reactions: Vec<JsonValue>,
|
||||||
|
/// 创建时间
|
||||||
|
#[serde(rename = "createdAt")]
|
||||||
|
pub created_at: JsonValue,
|
||||||
|
/// 更新时间
|
||||||
|
#[serde(rename = "updatedAt")]
|
||||||
|
pub updated_at: JsonValue,
|
||||||
|
/// 未知
|
||||||
|
#[serde(rename = "__v")]
|
||||||
|
pub v: JsonValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReciveMessage {
|
||||||
|
pub fn as_reply(&self) -> ReplyMessage {
|
||||||
|
ReplyMessage {
|
||||||
|
content: self.content.clone(),
|
||||||
|
converse_id: self.converse_id.clone(),
|
||||||
|
group_id: self.group_id.clone(),
|
||||||
|
reply_id: self.msg_id.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct SendingMessage {
|
||||||
|
/// 消息内容
|
||||||
|
pub content: String,
|
||||||
|
/// 会话ID
|
||||||
|
#[serde(rename = "converseId")]
|
||||||
|
pub converse_id: ConverseId,
|
||||||
|
/// 服务器ID
|
||||||
|
#[serde(rename = "groupId")]
|
||||||
|
pub group_id: GroupId,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct ReplyMeta {
|
||||||
|
/// 被回复的人的ID (可以是多个?)
|
||||||
|
pub mentions: Vec<UserId>,
|
||||||
|
/// 被回复的消息ID
|
||||||
|
pub reply_id: MessageId,
|
||||||
|
/// 被回复的消息的发送者ID
|
||||||
|
pub reply_author: UserId,
|
||||||
|
/// 被回复的消息内容
|
||||||
|
pub reply_content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for ReplyMeta {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::ser::Serializer,
|
||||||
|
{
|
||||||
|
let reply = json! {
|
||||||
|
{
|
||||||
|
"replyId": self.reply_id,
|
||||||
|
"replyAuthor": self.reply_author,
|
||||||
|
"replyContent": self.reply_content,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut map = serde_json::Map::new();
|
||||||
|
map.insert("mentions".to_string(), serde_json::to_value(&self.mentions).unwrap());
|
||||||
|
map.insert("reply".to_string(), reply);
|
||||||
|
map.serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct ReplyMessage {
|
||||||
|
/// 消息内容
|
||||||
|
pub content: String,
|
||||||
|
/// 会话ID
|
||||||
|
#[serde(rename = "converseId")]
|
||||||
|
pub converse_id: ConverseId,
|
||||||
|
/// 服务器ID
|
||||||
|
#[serde(rename = "groupId")]
|
||||||
|
pub group_id: GroupId,
|
||||||
|
/// 回复的消息ID
|
||||||
|
#[serde(rename = "replyId")]
|
||||||
|
pub reply_id: MessageId,
|
||||||
|
}
|
@ -4,6 +4,31 @@ 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)]
|
||||||
|
pub enum PyPluginError {
|
||||||
|
/// 插件内未找到指定函数
|
||||||
|
/// 函数名, 模块名
|
||||||
|
FuncNotFound(String, String),
|
||||||
|
/// 插件内函数获取错误
|
||||||
|
/// pyerr, func_name, module_name
|
||||||
|
CouldNotGetFunc(pyo3::PyErr, String, String),
|
||||||
|
/// 插件内函数不可调用
|
||||||
|
FuncNotCallable(String, String),
|
||||||
|
/// 插件内函数调用错误
|
||||||
|
/// pyerr, func_name, module_name
|
||||||
|
FuncCallError(pyo3::PyErr, String, String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<rust_socketio::Error> for IcaError {
|
impl From<rust_socketio::Error> for IcaError {
|
||||||
@ -14,6 +39,35 @@ 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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for PyPluginError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
PyPluginError::FuncNotFound(name, module) => {
|
||||||
|
write!(f, "插件内未找到函数: {} in {}", name, module)
|
||||||
|
}
|
||||||
|
PyPluginError::CouldNotGetFunc(py_err, name, module) => {
|
||||||
|
write!(f, "插件内函数获取错误: {:#?}|{} in {}", py_err, name, module)
|
||||||
|
}
|
||||||
|
PyPluginError::FuncNotCallable(name, module) => {
|
||||||
|
write!(f, "插件内函数不可调用: {} in {}", name, module)
|
||||||
|
}
|
||||||
|
PyPluginError::FuncCallError(py_err, name, module) => {
|
||||||
|
write!(f, "插件内函数调用错误: {:#?}|{} in {}", py_err, name, module)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,6 +76,27 @@ 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for PyPluginError {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
PyPluginError::FuncNotFound(_, _) => None,
|
||||||
|
PyPluginError::CouldNotGetFunc(e, _, _) => Some(e),
|
||||||
|
PyPluginError::FuncNotCallable(_, _) => None,
|
||||||
|
PyPluginError::FuncCallError(e, _, _) => Some(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -3,13 +3,14 @@ use std::time::Duration;
|
|||||||
mod config;
|
mod config;
|
||||||
mod data_struct;
|
mod data_struct;
|
||||||
mod error;
|
mod error;
|
||||||
#[cfg(feature = "ica")]
|
|
||||||
mod ica;
|
|
||||||
// #[cfg(feature = "tailchat")]
|
|
||||||
// mod tailchat;
|
|
||||||
mod py;
|
mod py;
|
||||||
mod status;
|
mod status;
|
||||||
|
|
||||||
|
#[cfg(feature = "ica")]
|
||||||
|
mod ica;
|
||||||
|
#[cfg(feature = "tailchat")]
|
||||||
|
mod tailchat;
|
||||||
|
|
||||||
use config::BotConfig;
|
use config::BotConfig;
|
||||||
use tracing::{event, info, span, Level};
|
use tracing::{event, info, span, Level};
|
||||||
|
|
||||||
|
@ -4,12 +4,15 @@ use pyo3::prelude::*;
|
|||||||
use rust_socketio::asynchronous::Client;
|
use rust_socketio::asynchronous::Client;
|
||||||
use tracing::{debug, info, warn};
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
use crate::data_struct::ica::messages::NewMessage;
|
use crate::data_struct::{ica, tailchat};
|
||||||
use crate::data_struct::ica::MessageId;
|
use crate::error::PyPluginError;
|
||||||
use crate::py::{class, PyPlugin, PyStatus};
|
use crate::py::{class, PyPlugin, PyStatus};
|
||||||
use crate::MainStatus;
|
use crate::MainStatus;
|
||||||
|
|
||||||
pub fn get_func<'py>(py_module: &'py PyAny, path: &PathBuf, name: &'py str) -> Option<&'py PyAny> {
|
pub fn get_func<'py>(
|
||||||
|
py_module: &Bound<'py, PyAny>,
|
||||||
|
name: &'py str,
|
||||||
|
) -> Result<Bound<'py, PyAny>, PyPluginError> {
|
||||||
// 要处理的情况:
|
// 要处理的情况:
|
||||||
// 1. 有这个函数
|
// 1. 有这个函数
|
||||||
// 2. 没有这个函数
|
// 2. 没有这个函数
|
||||||
@ -20,25 +23,39 @@ pub fn get_func<'py>(py_module: &'py PyAny, path: &PathBuf, name: &'py str) -> O
|
|||||||
match py_module.getattr(name) {
|
match py_module.getattr(name) {
|
||||||
Ok(func) => {
|
Ok(func) => {
|
||||||
if func.is_callable() {
|
if func.is_callable() {
|
||||||
Some(func)
|
Ok(func)
|
||||||
} else {
|
} else {
|
||||||
warn!("function<{}>: {:#?} in {:?} is not callable", name, func, path);
|
// warn!("function<{}>: {:#?} in {:?} is not callable", name, func, path);
|
||||||
None
|
Err(PyPluginError::FuncNotCallable(
|
||||||
|
name.to_string(),
|
||||||
|
py_module.getattr("__name__").unwrap().extract::<String>().unwrap(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("failed to get function<{}> from {:?}: {:?}", name, path, e);
|
// warn!("failed to get function<{}> from {:?}: {:?}", name, path, e);
|
||||||
None
|
Err(PyPluginError::CouldNotGetFunc(
|
||||||
|
e,
|
||||||
|
name.to_string(),
|
||||||
|
py_module.getattr("__name__").unwrap().extract::<String>().unwrap(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!("no function<{}> in module {:?}", name, path);
|
// debug!("no function<{}> in module {:?}", name, path);
|
||||||
None
|
Err(PyPluginError::FuncNotFound(
|
||||||
|
name.to_string(),
|
||||||
|
py_module.getattr("__name__").unwrap().extract::<String>().unwrap(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("failed to check function<{}> from {:?}: {:?}", name, path, e);
|
// warn!("failed to check function<{}> from {:?}: {:?}", name, path, e);
|
||||||
None
|
Err(PyPluginError::CouldNotGetFunc(
|
||||||
|
e,
|
||||||
|
name.to_string(),
|
||||||
|
py_module.getattr("__name__").unwrap().extract::<String>().unwrap(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,8 +95,14 @@ 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: &NewMessage, client: &Client) {
|
pub async fn ica_new_message_py(message: &ica::messages::NewMessage, client: &Client) {
|
||||||
// 验证插件是否改变
|
// 验证插件是否改变
|
||||||
verify_plugins();
|
verify_plugins();
|
||||||
|
|
||||||
@ -91,10 +114,13 @@ pub async fn ica_new_message_py(message: &NewMessage, client: &Client) {
|
|||||||
// 甚至实际上压根不需要await这个spawn, 直接让他自己跑就好了(离谱)
|
// 甚至实际上压根不需要await这个spawn, 直接让他自己跑就好了(离谱)
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
if let Some(py_func) =
|
if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_NEW_MESSAGE_FUNC) {
|
||||||
get_func(plugin.py_module.as_ref(py), path, 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(),
|
||||||
|
path.to_string_lossy().to_string(),
|
||||||
|
);
|
||||||
warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e);
|
warn!("failed to call function<{}>: {:?}", ICA_NEW_MESSAGE_FUNC, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,7 +129,7 @@ pub async fn ica_new_message_py(message: &NewMessage, client: &Client) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn ica_delete_message_py(msg_id: MessageId, client: &Client) {
|
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();
|
||||||
@ -113,10 +139,13 @@ pub async fn ica_delete_message_py(msg_id: MessageId, client: &Client) {
|
|||||||
let args = (msg_id.clone(), client);
|
let args = (msg_id.clone(), client);
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
if let Some(py_func) =
|
if let Ok(py_func) = get_func(plugin.py_module.bind(py), ICA_DELETE_MESSAGE_FUNC) {
|
||||||
get_func(plugin.py_module.as_ref(py), path, 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,3 +153,7 @@ pub async fn ica_delete_message_py(msg_id: MessageId, client: &Client) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn tailchat_new_message_py(message: tailchat::messages::ReciveMessage, client: &Client) {
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -68,8 +68,8 @@ impl TryFrom<RawPyPlugin> for PyPlugin {
|
|||||||
};
|
};
|
||||||
let py_module = py_module.unwrap();
|
let py_module = py_module.unwrap();
|
||||||
Python::with_gil(|py| {
|
Python::with_gil(|py| {
|
||||||
let module = py_module.as_ref(py);
|
let module = py_module.bind(py);
|
||||||
if let Some(config_func) = call::get_func(module, &path, "on_config") {
|
if let Ok(config_func) = call::get_func(module, "on_config") {
|
||||||
match config_func.call0() {
|
match config_func.call0() {
|
||||||
Ok(config) => {
|
Ok(config) => {
|
||||||
if config.is_instance_of::<PyTuple>() {
|
if config.is_instance_of::<PyTuple>() {
|
||||||
@ -96,8 +96,7 @@ impl TryFrom<RawPyPlugin> for PyPlugin {
|
|||||||
};
|
};
|
||||||
match config_value {
|
match config_value {
|
||||||
Ok(config) => {
|
Ok(config) => {
|
||||||
let py_config = class::ConfigDataPy::new(config);
|
let py_config = Bound::new(py, class::ConfigDataPy::new(config)).unwrap();
|
||||||
let py_config = PyCell::new(py, py_config).unwrap();
|
|
||||||
module.setattr("CONFIG_DATA", py_config).unwrap();
|
module.setattr("CONFIG_DATA", py_config).unwrap();
|
||||||
Ok(PyPlugin {
|
Ok(PyPlugin {
|
||||||
file_path: path,
|
file_path: path,
|
||||||
@ -228,7 +227,7 @@ pub fn get_change_time(path: &Path) -> Option<SystemTime> { path.metadata().ok()
|
|||||||
|
|
||||||
pub fn py_module_from_code(content: &str, path: &Path) -> PyResult<Py<PyAny>> {
|
pub fn py_module_from_code(content: &str, path: &Path) -> PyResult<Py<PyAny>> {
|
||||||
Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
Python::with_gil(|py| -> PyResult<Py<PyAny>> {
|
||||||
let module: PyResult<Py<PyAny>> = PyModule::from_code(
|
let module: PyResult<Py<PyAny>> = PyModule::from_code_bound(
|
||||||
py,
|
py,
|
||||||
content,
|
content,
|
||||||
&path.to_string_lossy(),
|
&path.to_string_lossy(),
|
||||||
|
23
ica-rs/src/tailchat.rs
Normal file
23
ica-rs/src/tailchat.rs
Normal file
@ -0,0 +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(())
|
||||||
|
}
|
||||||
|
|
0
ica-rs/src/tailchat/events.rs
Normal file
0
ica-rs/src/tailchat/events.rs
Normal file
Loading…
Reference in New Issue
Block a user