perf(build): gate Matrix channel for faster iteration
This commit is contained in:
parent
87dcda638c
commit
05404c6e7a
9 changed files with 135 additions and 60 deletions
44
Cargo.lock
generated
44
Cargo.lock
generated
|
|
@ -408,7 +408,7 @@ dependencies = [
|
||||||
"sha1",
|
"sha1",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-tungstenite 0.28.0",
|
"tokio-tungstenite",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
|
|
@ -6004,9 +6004,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-tungstenite"
|
name = "tokio-tungstenite"
|
||||||
version = "0.24.0"
|
version = "0.28.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9"
|
checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"log",
|
"log",
|
||||||
|
|
@ -6014,22 +6014,10 @@ dependencies = [
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tungstenite 0.24.0",
|
"tungstenite",
|
||||||
"webpki-roots 0.26.11",
|
"webpki-roots 0.26.11",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-tungstenite"
|
|
||||||
version = "0.28.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857"
|
|
||||||
dependencies = [
|
|
||||||
"futures-util",
|
|
||||||
"log",
|
|
||||||
"tokio",
|
|
||||||
"tungstenite 0.28.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.18"
|
version = "0.7.18"
|
||||||
|
|
@ -6333,26 +6321,6 @@ version = "0.25.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
|
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tungstenite"
|
|
||||||
version = "0.24.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder",
|
|
||||||
"bytes",
|
|
||||||
"data-encoding",
|
|
||||||
"http 1.4.0",
|
|
||||||
"httparse",
|
|
||||||
"log",
|
|
||||||
"rand 0.8.5",
|
|
||||||
"rustls",
|
|
||||||
"rustls-pki-types",
|
|
||||||
"sha1",
|
|
||||||
"thiserror 1.0.69",
|
|
||||||
"utf-8",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tungstenite"
|
name = "tungstenite"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
|
|
@ -6365,6 +6333,8 @@ dependencies = [
|
||||||
"httparse",
|
"httparse",
|
||||||
"log",
|
"log",
|
||||||
"rand 0.9.2",
|
"rand 0.9.2",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pki-types",
|
||||||
"sha1",
|
"sha1",
|
||||||
"thiserror 2.0.18",
|
"thiserror 2.0.18",
|
||||||
"utf-8",
|
"utf-8",
|
||||||
|
|
@ -7747,7 +7717,7 @@ dependencies = [
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tokio-serial",
|
"tokio-serial",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-tungstenite 0.24.0",
|
"tokio-tungstenite",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"toml 1.0.1+spec-1.1.0",
|
"toml 1.0.1+spec-1.1.0",
|
||||||
"tower",
|
"tower",
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ tokio-util = { version = "0.7", default-features = false }
|
||||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "blocking", "multipart", "stream", "socks"] }
|
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "blocking", "multipart", "stream", "socks"] }
|
||||||
|
|
||||||
# Matrix client + E2EE decryption
|
# Matrix client + E2EE decryption
|
||||||
matrix-sdk = { version = "0.16", default-features = false, features = ["e2e-encryption", "rustls-tls", "markdown"] }
|
matrix-sdk = { version = "0.16", optional = true, default-features = false, features = ["e2e-encryption", "rustls-tls", "markdown"] }
|
||||||
|
|
||||||
# Serialization
|
# Serialization
|
||||||
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
||||||
|
|
@ -103,8 +103,8 @@ console = "0.16"
|
||||||
# Hardware discovery (device path globbing)
|
# Hardware discovery (device path globbing)
|
||||||
glob = "0.3"
|
glob = "0.3"
|
||||||
|
|
||||||
# Discord WebSocket gateway
|
# WebSocket client channels (Discord/Lark/DingTalk)
|
||||||
tokio-tungstenite = { version = "0.24", features = ["rustls-tls-webpki-roots"] }
|
tokio-tungstenite = { version = "0.28", features = ["rustls-tls-webpki-roots"] }
|
||||||
futures-util = { version = "0.3", default-features = false, features = ["sink"] }
|
futures-util = { version = "0.3", default-features = false, features = ["sink"] }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
regex = "1.10"
|
regex = "1.10"
|
||||||
|
|
@ -158,8 +158,9 @@ rppal = { version = "0.22", optional = true }
|
||||||
landlock = { version = "0.4", optional = true }
|
landlock = { version = "0.4", optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["hardware"]
|
default = ["hardware", "channel-matrix"]
|
||||||
hardware = ["nusb", "tokio-serial"]
|
hardware = ["nusb", "tokio-serial"]
|
||||||
|
channel-matrix = ["dep:matrix-sdk"]
|
||||||
peripheral-rpi = ["rppal"]
|
peripheral-rpi = ["rppal"]
|
||||||
# Browser backend feature alias used by cfg(feature = "browser-native")
|
# Browser backend feature alias used by cfg(feature = "browser-native")
|
||||||
browser-native = ["dep:fantoccini"]
|
browser-native = ["dep:fantoccini"]
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,25 @@ Operational notes:
|
||||||
|
|
||||||
## Channel Matrix
|
## Channel Matrix
|
||||||
|
|
||||||
|
### Build Feature Toggle (`channel-matrix`)
|
||||||
|
|
||||||
|
Matrix support is controlled at compile time by the `channel-matrix` Cargo feature.
|
||||||
|
|
||||||
|
- Default builds include Matrix support (`default = ["hardware", "channel-matrix"]`).
|
||||||
|
- For faster local iteration when Matrix is not needed:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo check --no-default-features --features hardware
|
||||||
|
```
|
||||||
|
|
||||||
|
- To explicitly enable Matrix support in custom feature sets:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo check --no-default-features --features hardware,channel-matrix
|
||||||
|
```
|
||||||
|
|
||||||
|
If `[channels_config.matrix]` is present but the binary was built without `channel-matrix`, `zeroclaw channel list`, `zeroclaw channel doctor`, and `zeroclaw channel start` will log that Matrix is intentionally skipped for this build.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 2. Delivery Modes at a Glance
|
## 2. Delivery Modes at a Glance
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
This guide focuses on common setup/runtime failures and fast resolution paths.
|
This guide focuses on common setup/runtime failures and fast resolution paths.
|
||||||
|
|
||||||
Last verified: **February 18, 2026**.
|
Last verified: **February 19, 2026**.
|
||||||
|
|
||||||
## Installation / Bootstrap
|
## Installation / Bootstrap
|
||||||
|
|
||||||
|
|
@ -32,6 +32,51 @@ Fix:
|
||||||
./bootstrap.sh --install-system-deps
|
./bootstrap.sh --install-system-deps
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Build is very slow or appears stuck
|
||||||
|
|
||||||
|
Symptoms:
|
||||||
|
|
||||||
|
- `cargo check` / `cargo build` appears stuck at `Checking zeroclaw` for a long time
|
||||||
|
- repeated `Blocking waiting for file lock on package cache` or `build directory`
|
||||||
|
|
||||||
|
Why this happens in ZeroClaw:
|
||||||
|
|
||||||
|
- Matrix E2EE stack (`matrix-sdk`, `ruma`, `vodozemac`) is large and expensive to type-check.
|
||||||
|
- TLS + crypto native build scripts (`aws-lc-sys`, `ring`) add noticeable compile time.
|
||||||
|
- `rusqlite` with bundled SQLite compiles C code locally.
|
||||||
|
- Running multiple cargo jobs/worktrees in parallel causes lock contention.
|
||||||
|
|
||||||
|
Fast checks:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo check --timings
|
||||||
|
cargo tree -d
|
||||||
|
```
|
||||||
|
|
||||||
|
The timing report is written to `target/cargo-timings/cargo-timing.html`.
|
||||||
|
|
||||||
|
Faster local iteration (when Matrix channel is not needed):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo check --no-default-features --features hardware
|
||||||
|
```
|
||||||
|
|
||||||
|
This skips `channel-matrix` and can significantly reduce compile time.
|
||||||
|
|
||||||
|
To build with Matrix support explicitly enabled:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo check --no-default-features --features hardware,channel-matrix
|
||||||
|
```
|
||||||
|
|
||||||
|
Lock-contention mitigation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pgrep -af "cargo (check|build|test)|cargo check|cargo build|cargo test"
|
||||||
|
```
|
||||||
|
|
||||||
|
Stop unrelated cargo jobs before running your own build.
|
||||||
|
|
||||||
### `zeroclaw` command not found after install
|
### `zeroclaw` command not found after install
|
||||||
|
|
||||||
Symptom:
|
Symptom:
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ impl Channel for DingTalkChannel {
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let frame: serde_json::Value = match serde_json::from_str(&msg) {
|
let frame: serde_json::Value = match serde_json::from_str(msg.as_ref()) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => continue,
|
Err(_) => continue,
|
||||||
};
|
};
|
||||||
|
|
@ -195,7 +195,7 @@ impl Channel for DingTalkChannel {
|
||||||
"data": "",
|
"data": "",
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Err(e) = write.send(Message::Text(pong.to_string())).await {
|
if let Err(e) = write.send(Message::Text(pong.to_string().into())).await {
|
||||||
tracing::warn!("DingTalk: failed to send pong: {e}");
|
tracing::warn!("DingTalk: failed to send pong: {e}");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -262,7 +262,7 @@ impl Channel for DingTalkChannel {
|
||||||
"message": "OK",
|
"message": "OK",
|
||||||
"data": "",
|
"data": "",
|
||||||
});
|
});
|
||||||
let _ = write.send(Message::Text(ack.to_string())).await;
|
let _ = write.send(Message::Text(ack.to_string().into())).await;
|
||||||
|
|
||||||
let channel_msg = ChannelMessage {
|
let channel_msg = ChannelMessage {
|
||||||
id: Uuid::new_v4().to_string(),
|
id: Uuid::new_v4().to_string(),
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,9 @@ impl Channel for DiscordChannel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
write.send(Message::Text(identify.to_string())).await?;
|
write
|
||||||
|
.send(Message::Text(identify.to_string().into()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
tracing::info!("Discord: connected and identified");
|
tracing::info!("Discord: connected and identified");
|
||||||
|
|
||||||
|
|
@ -301,7 +303,7 @@ impl Channel for DiscordChannel {
|
||||||
_ = hb_rx.recv() => {
|
_ = hb_rx.recv() => {
|
||||||
let d = if sequence >= 0 { json!(sequence) } else { json!(null) };
|
let d = if sequence >= 0 { json!(sequence) } else { json!(null) };
|
||||||
let hb = json!({"op": 1, "d": d});
|
let hb = json!({"op": 1, "d": d});
|
||||||
if write.send(Message::Text(hb.to_string())).await.is_err() {
|
if write.send(Message::Text(hb.to_string().into())).await.is_err() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -312,7 +314,7 @@ impl Channel for DiscordChannel {
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let event: serde_json::Value = match serde_json::from_str(&msg) {
|
let event: serde_json::Value = match serde_json::from_str(msg.as_ref()) {
|
||||||
Ok(e) => e,
|
Ok(e) => e,
|
||||||
Err(_) => continue,
|
Err(_) => continue,
|
||||||
};
|
};
|
||||||
|
|
@ -329,7 +331,7 @@ impl Channel for DiscordChannel {
|
||||||
1 => {
|
1 => {
|
||||||
let d = if sequence >= 0 { json!(sequence) } else { json!(null) };
|
let d = if sequence >= 0 { json!(sequence) } else { json!(null) };
|
||||||
let hb = json!({"op": 1, "d": d});
|
let hb = json!({"op": 1, "d": d});
|
||||||
if write.send(Message::Text(hb.to_string())).await.is_err() {
|
if write.send(Message::Text(hb.to_string().into())).await.is_err() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -288,7 +288,7 @@ impl LarkChannel {
|
||||||
payload: None,
|
payload: None,
|
||||||
};
|
};
|
||||||
if write
|
if write
|
||||||
.send(WsMsg::Binary(initial_ping.encode_to_vec()))
|
.send(WsMsg::Binary(initial_ping.encode_to_vec().into()))
|
||||||
.await
|
.await
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
|
|
@ -309,7 +309,7 @@ impl LarkChannel {
|
||||||
headers: vec![PbHeader { key: "type".into(), value: "ping".into() }],
|
headers: vec![PbHeader { key: "type".into(), value: "ping".into() }],
|
||||||
payload: None,
|
payload: None,
|
||||||
};
|
};
|
||||||
if write.send(WsMsg::Binary(ping.encode_to_vec())).await.is_err() {
|
if write.send(WsMsg::Binary(ping.encode_to_vec().into())).await.is_err() {
|
||||||
tracing::warn!("Lark: ping failed, reconnecting");
|
tracing::warn!("Lark: ping failed, reconnecting");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -378,7 +378,7 @@ impl LarkChannel {
|
||||||
let mut ack = frame.clone();
|
let mut ack = frame.clone();
|
||||||
ack.payload = Some(br#"{"code":200,"headers":{},"data":[]}"#.to_vec());
|
ack.payload = Some(br#"{"code":200,"headers":{},"data":[]}"#.to_vec());
|
||||||
ack.headers.push(PbHeader { key: "biz_rt".into(), value: "0".into() });
|
ack.headers.push(PbHeader { key: "biz_rt".into(), value: "0".into() });
|
||||||
let _ = write.send(WsMsg::Binary(ack.encode_to_vec())).await;
|
let _ = write.send(WsMsg::Binary(ack.encode_to_vec().into())).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fragment reassembly
|
// Fragment reassembly
|
||||||
|
|
@ -917,9 +917,11 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn lark_ws_activity_refreshes_heartbeat_watchdog() {
|
fn lark_ws_activity_refreshes_heartbeat_watchdog() {
|
||||||
assert!(should_refresh_last_recv(&WsMsg::Binary(vec![1, 2, 3])));
|
assert!(should_refresh_last_recv(&WsMsg::Binary(
|
||||||
assert!(should_refresh_last_recv(&WsMsg::Ping(vec![9, 9])));
|
vec![1, 2, 3].into()
|
||||||
assert!(should_refresh_last_recv(&WsMsg::Pong(vec![8, 8])));
|
)));
|
||||||
|
assert!(should_refresh_last_recv(&WsMsg::Ping(vec![9, 9].into())));
|
||||||
|
assert!(should_refresh_last_recv(&WsMsg::Pong(vec![8, 8].into())));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ pub mod imessage;
|
||||||
pub mod irc;
|
pub mod irc;
|
||||||
pub mod lark;
|
pub mod lark;
|
||||||
pub mod linq;
|
pub mod linq;
|
||||||
|
#[cfg(feature = "channel-matrix")]
|
||||||
pub mod matrix;
|
pub mod matrix;
|
||||||
pub mod mattermost;
|
pub mod mattermost;
|
||||||
pub mod qq;
|
pub mod qq;
|
||||||
|
|
@ -27,6 +28,7 @@ pub use imessage::IMessageChannel;
|
||||||
pub use irc::IrcChannel;
|
pub use irc::IrcChannel;
|
||||||
pub use lark::LarkChannel;
|
pub use lark::LarkChannel;
|
||||||
pub use linq::LinqChannel;
|
pub use linq::LinqChannel;
|
||||||
|
#[cfg(feature = "channel-matrix")]
|
||||||
pub use matrix::MatrixChannel;
|
pub use matrix::MatrixChannel;
|
||||||
pub use mattermost::MattermostChannel;
|
pub use mattermost::MattermostChannel;
|
||||||
pub use qq::QQChannel;
|
pub use qq::QQChannel;
|
||||||
|
|
@ -1389,7 +1391,10 @@ pub async fn handle_command(command: crate::ChannelCommands, config: &Config) ->
|
||||||
("Mattermost", config.channels_config.mattermost.is_some()),
|
("Mattermost", config.channels_config.mattermost.is_some()),
|
||||||
("Webhook", config.channels_config.webhook.is_some()),
|
("Webhook", config.channels_config.webhook.is_some()),
|
||||||
("iMessage", config.channels_config.imessage.is_some()),
|
("iMessage", config.channels_config.imessage.is_some()),
|
||||||
("Matrix", config.channels_config.matrix.is_some()),
|
(
|
||||||
|
"Matrix",
|
||||||
|
cfg!(feature = "channel-matrix") && config.channels_config.matrix.is_some(),
|
||||||
|
),
|
||||||
("Signal", config.channels_config.signal.is_some()),
|
("Signal", config.channels_config.signal.is_some()),
|
||||||
("WhatsApp", config.channels_config.whatsapp.is_some()),
|
("WhatsApp", config.channels_config.whatsapp.is_some()),
|
||||||
("Linq", config.channels_config.linq.is_some()),
|
("Linq", config.channels_config.linq.is_some()),
|
||||||
|
|
@ -1401,6 +1406,11 @@ pub async fn handle_command(command: crate::ChannelCommands, config: &Config) ->
|
||||||
] {
|
] {
|
||||||
println!(" {} {name}", if configured { "✅" } else { "❌" });
|
println!(" {} {name}", if configured { "✅" } else { "❌" });
|
||||||
}
|
}
|
||||||
|
if !cfg!(feature = "channel-matrix") {
|
||||||
|
println!(
|
||||||
|
" ℹ️ Matrix channel support is disabled in this build (enable `channel-matrix`)."
|
||||||
|
);
|
||||||
|
}
|
||||||
println!("\nTo start channels: zeroclaw channel start");
|
println!("\nTo start channels: zeroclaw channel start");
|
||||||
println!("To check health: zeroclaw channel doctor");
|
println!("To check health: zeroclaw channel doctor");
|
||||||
println!("To configure: zeroclaw onboard");
|
println!("To configure: zeroclaw onboard");
|
||||||
|
|
@ -1489,6 +1499,7 @@ pub async fn doctor_channels(config: Config) -> Result<()> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "channel-matrix")]
|
||||||
if let Some(ref mx) = config.channels_config.matrix {
|
if let Some(ref mx) = config.channels_config.matrix {
|
||||||
channels.push((
|
channels.push((
|
||||||
"Matrix",
|
"Matrix",
|
||||||
|
|
@ -1503,6 +1514,13 @@ pub async fn doctor_channels(config: Config) -> Result<()> {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "channel-matrix"))]
|
||||||
|
if config.channels_config.matrix.is_some() {
|
||||||
|
tracing::warn!(
|
||||||
|
"Matrix channel is configured but this build was compiled without `channel-matrix`; skipping Matrix health check."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(ref sig) = config.channels_config.signal {
|
if let Some(ref sig) = config.channels_config.signal {
|
||||||
channels.push((
|
channels.push((
|
||||||
"Signal",
|
"Signal",
|
||||||
|
|
@ -1864,6 +1882,7 @@ pub async fn start_channels(config: Config) -> Result<()> {
|
||||||
channels.push(Arc::new(IMessageChannel::new(im.allowed_contacts.clone())));
|
channels.push(Arc::new(IMessageChannel::new(im.allowed_contacts.clone())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "channel-matrix")]
|
||||||
if let Some(ref mx) = config.channels_config.matrix {
|
if let Some(ref mx) = config.channels_config.matrix {
|
||||||
channels.push(Arc::new(MatrixChannel::new_with_session_hint(
|
channels.push(Arc::new(MatrixChannel::new_with_session_hint(
|
||||||
mx.homeserver.clone(),
|
mx.homeserver.clone(),
|
||||||
|
|
@ -1875,6 +1894,13 @@ pub async fn start_channels(config: Config) -> Result<()> {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "channel-matrix"))]
|
||||||
|
if config.channels_config.matrix.is_some() {
|
||||||
|
tracing::warn!(
|
||||||
|
"Matrix channel is configured but this build was compiled without `channel-matrix`; skipping Matrix runtime startup."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(ref sig) = config.channels_config.signal {
|
if let Some(ref sig) = config.channels_config.signal {
|
||||||
channels.push(Arc::new(SignalChannel::new(
|
channels.push(Arc::new(SignalChannel::new(
|
||||||
sig.http_url.clone(),
|
sig.http_url.clone(),
|
||||||
|
|
|
||||||
|
|
@ -263,7 +263,9 @@ impl Channel for QQChannel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
write.send(Message::Text(identify.to_string())).await?;
|
write
|
||||||
|
.send(Message::Text(identify.to_string().into()))
|
||||||
|
.await?;
|
||||||
|
|
||||||
tracing::info!("QQ: connected and identified");
|
tracing::info!("QQ: connected and identified");
|
||||||
|
|
||||||
|
|
@ -287,7 +289,11 @@ impl Channel for QQChannel {
|
||||||
_ = hb_rx.recv() => {
|
_ = hb_rx.recv() => {
|
||||||
let d = if sequence >= 0 { json!(sequence) } else { json!(null) };
|
let d = if sequence >= 0 { json!(sequence) } else { json!(null) };
|
||||||
let hb = json!({"op": 1, "d": d});
|
let hb = json!({"op": 1, "d": d});
|
||||||
if write.send(Message::Text(hb.to_string())).await.is_err() {
|
if write
|
||||||
|
.send(Message::Text(hb.to_string().into()))
|
||||||
|
.await
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -298,7 +304,7 @@ impl Channel for QQChannel {
|
||||||
_ => continue,
|
_ => continue,
|
||||||
};
|
};
|
||||||
|
|
||||||
let event: serde_json::Value = match serde_json::from_str(&msg) {
|
let event: serde_json::Value = match serde_json::from_str(msg.as_ref()) {
|
||||||
Ok(e) => e,
|
Ok(e) => e,
|
||||||
Err(_) => continue,
|
Err(_) => continue,
|
||||||
};
|
};
|
||||||
|
|
@ -315,7 +321,11 @@ impl Channel for QQChannel {
|
||||||
1 => {
|
1 => {
|
||||||
let d = if sequence >= 0 { json!(sequence) } else { json!(null) };
|
let d = if sequence >= 0 { json!(sequence) } else { json!(null) };
|
||||||
let hb = json!({"op": 1, "d": d});
|
let hb = json!({"op": 1, "d": d});
|
||||||
if write.send(Message::Text(hb.to_string())).await.is_err() {
|
if write
|
||||||
|
.send(Message::Text(hb.to_string().into()))
|
||||||
|
.await
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue