Skip to content

Commit b3615bc

Browse files
nightfullstarjaswinder6991
authored andcommitted
DM pairing + Telegram channel improvements (nearai#17)
* feat: Implement DM pairing for channels - Introduced a new pairing system to manage direct messages from unknown senders. - Added `PairingStore` to handle pending requests and allowlist management. - Implemented CLI commands for listing and approving pairing requests. - Updated Telegram channel to utilize the new pairing logic, including workspace paths for storing pairing data. - Enhanced WASM channel integration to support pairing functionality. This feature enhances security by requiring approval for unknown senders before they can interact with the agent. * Enhance Telegram channel support with media captioning and DM pairing features - Added support for media captions in Telegram messages, allowing for richer content handling. - Updated message processing to utilize either text or caption, improving message flexibility. - Enhanced DM pairing functionality to include approval and listing capabilities for direct messages. - Updated feature parity documentation to reflect new capabilities and improvements in Telegram integration. * Update README and BUILDING_CHANNELS documentation for Telegram channel integration - Enhanced README with instructions for building and running the Telegram channel, including a note on running `./scripts/build-all.sh` for full releases. - Added detailed steps in BUILDING_CHANNELS.md for building and deploying the Telegram channel, emphasizing the need to run `./channels-src/telegram/build.sh` before building the main crate to ensure updated WASM is included. - Updated CLI module to expose a new command for pairing with store functionality. * Implement build script for Telegram channel WASM and enhance pairing error handling - Added a new `build.rs` script to automate the compilation of the Telegram channel's WASM binary from source, ensuring reproducible builds and emphasizing supply chain security by preventing committed binaries. - Updated `BUILDING_CHANNELS.md` to reflect the new build process and the importance of not committing compiled binaries. - Enhanced error handling in the pairing approval process to include rate limiting for failed attempts, improving security and user feedback. * Remove Telegram channel WASM binary file as part of the build process cleanup, ensuring no committed binaries are present in the repository.
1 parent 2185f68 commit b3615bc

22 files changed

Lines changed: 1775 additions & 130 deletions

Cargo.lock

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ aho-corasick = "1"
6767

6868
# Filesystem paths
6969
dirs = "6"
70+
fs4 = "0.6"
7071

7172
# Secrecy for sensitive values
7273
secrecy = { version = "0.10", features = ["serde"] }

FEATURE_PARITY.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ This document tracks feature parity between IronClaw (Rust implementation) and O
5959
| REPL (simple) ||| - | For testing |
6060
| WASM channels ||| - | IronClaw innovation |
6161
| WhatsApp ||| P1 | Baileys (Web) |
62-
| Telegram ||| - | WASM tool (MTProto) |
62+
| Telegram ||| - | WASM channel(MTProto), DM pairing, caption, /start, bot_username |
6363
| Discord ||| P2 | discord.js |
6464
| Signal ||| P2 | signal-cli |
6565
| Slack ||| - | WASM tool |
@@ -79,13 +79,13 @@ This document tracks feature parity between IronClaw (Rust implementation) and O
7979

8080
| Feature | OpenClaw | IronClaw | Notes |
8181
|---------|----------|----------|-------|
82-
| DM pairing codes || | Verification for unknown senders |
83-
| Allowlist/blocklist || | Per-channel access control |
82+
| DM pairing codes || | `ironclaw pairing list/approve`, host APIs |
83+
| Allowlist/blocklist || 🚧 | allow_from + pairing store |
8484
| Self-message bypass ||| Own messages skip pairing |
85-
| Mention-based activation || | Configurable patterns |
85+
| Mention-based activation || | bot_username + respond_to_all_group_messages |
8686
| Per-group tool policies ||| Allow/deny specific tools |
8787
| Thread isolation ||| Separate sessions per thread |
88-
| Per-channel media limits || | |
88+
| Per-channel media limits || 🚧 | Caption support for media; no size limits |
8989
| Typing indicators || 🚧 | TUI shows status |
9090

9191
### Owner: _Unassigned_
@@ -109,7 +109,7 @@ This document tracks feature parity between IronClaw (Rust implementation) and O
109109
| `sessions` ||| P3 | Session listing |
110110
| `memory` ||| - | Memory search CLI |
111111
| `skills` ||| P3 | Agent skills |
112-
| `pairing` || | P3 | Node pairing |
112+
| `pairing` || | - | list/approve for channel DM pairing |
113113
| `nodes` ||| P3 | Device management |
114114
| `plugins` ||| P3 | Plugin management |
115115
| `hooks` ||| P2 | Lifecycle hooks |
@@ -350,8 +350,8 @@ This document tracks feature parity between IronClaw (Rust implementation) and O
350350
| Device pairing ||| |
351351
| Tailscale identity ||| |
352352
| OAuth flows || 🚧 | NEAR AI OAuth |
353-
| DM pairing verification || | |
354-
| Allowlist/blocklist || | |
353+
| DM pairing verification || | ironclaw pairing approve, host APIs |
354+
| Allowlist/blocklist || 🚧 | allow_from + pairing store |
355355
| Per-group tool policies ||| |
356356
| Exec approvals ||| TUI overlay |
357357
| TLS 1.3 minimum ||| reqwest rustls |
@@ -397,6 +397,7 @@ This document tracks feature parity between IronClaw (Rust implementation) and O
397397
### P0 - Core (Already Done)
398398
- ✅ TUI channel with approval overlays
399399
- ✅ HTTP webhook channel
400+
- ✅ DM pairing (ironclaw pairing list/approve, host APIs)
400401
- ✅ WASM tool sandbox
401402
- ✅ Workspace/memory with hybrid search
402403
- ✅ Prompt injection defense
@@ -415,12 +416,18 @@ This document tracks feature parity between IronClaw (Rust implementation) and O
415416
- ✅ Gateway token auth
416417

417418
### P1 - High Priority
419+
- ❌ Slack channel (real implementation)
420+
- ✅ Telegram channel (WASM, DM pairing, caption, /start)
418421
- ❌ WhatsApp channel
419422
- ❌ Multi-provider failover
420423
- ❌ Hooks system (beforeInbound, beforeToolCall, etc.)
421424

422425
### P2 - Medium Priority
423-
- ❌ Media handling (images, PDFs)
426+
- ❌ Cron job scheduling
427+
- ❌ Web Control UI
428+
- ❌ WebChat channel
429+
- 🚧 Media handling (caption support; no image/PDF processing)
430+
- ❌ CLI subcommands (config, status, memory, doctor)
424431
- ❌ Ollama/local model support
425432
- ❌ Configuration hot-reload
426433
- ❌ Webhook trigger endpoint in web gateway

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ cargo build --release
8585
cargo test
8686
```
8787

88+
For **full release** (after modifying channel sources), run `./scripts/build-all.sh` to rebuild channels first.
89+
8890
### Database Setup
8991

9092
```bash
@@ -228,6 +230,9 @@ cargo test
228230
cargo test test_name
229231
```
230232

233+
- **Telegram channel**: See [docs/TELEGRAM_SETUP.md](docs/TELEGRAM_SETUP.md) for setup and DM pairing.
234+
- **Changing channel sources**: Run `./channels-src/telegram/build.sh` before `cargo build` so the updated WASM is bundled.
235+
231236
## OpenClaw Heritage
232237

233238
IronClaw is a Rust reimplementation inspired by [OpenClaw](https://github.com/openclaw/openclaw). See [FEATURE_PARITY.md](FEATURE_PARITY.md) for the complete tracking matrix.

build.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
//! Build script: compile Telegram channel WASM from source.
2+
//!
3+
//! Do not commit compiled WASM binaries — they are a supply chain risk.
4+
//! This script builds telegram.wasm from channels-src/telegram before the main crate compiles.
5+
//!
6+
//! Reproducible build:
7+
//! cargo build --release
8+
//! (build.rs invokes the channel build automatically)
9+
//!
10+
//! Prerequisites: rustup target add wasm32-wasip2, cargo install wasm-tools
11+
12+
use std::env;
13+
use std::path::PathBuf;
14+
use std::process::Command;
15+
16+
fn main() {
17+
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
18+
let root = PathBuf::from(&manifest_dir);
19+
let channel_dir = root.join("channels-src/telegram");
20+
let wasm_out = channel_dir.join("telegram.wasm");
21+
22+
// Rerun when channel source or build script changes
23+
println!("cargo:rerun-if-changed=channels-src/telegram/src");
24+
println!("cargo:rerun-if-changed=channels-src/telegram/Cargo.toml");
25+
println!("cargo:rerun-if-changed=wit/channel.wit");
26+
27+
if !channel_dir.is_dir() {
28+
return;
29+
}
30+
31+
// Build WASM module
32+
let status = match Command::new("cargo")
33+
.args([
34+
"build",
35+
"--release",
36+
"--target",
37+
"wasm32-wasip2",
38+
"--manifest-path",
39+
channel_dir.join("Cargo.toml").to_str().unwrap(),
40+
])
41+
.current_dir(&root)
42+
.status()
43+
{
44+
Ok(s) => s,
45+
Err(_) => {
46+
eprintln!(
47+
"cargo:warning=Telegram channel build failed. Run: ./channels-src/telegram/build.sh"
48+
);
49+
return;
50+
}
51+
};
52+
53+
if !status.success() {
54+
eprintln!(
55+
"cargo:warning=Telegram channel build failed. Run: ./channels-src/telegram/build.sh"
56+
);
57+
return;
58+
}
59+
60+
let raw_wasm = channel_dir.join("target/wasm32-wasip2/release/telegram_channel.wasm");
61+
if !raw_wasm.exists() {
62+
eprintln!(
63+
"cargo:warning=Telegram WASM output not found at {:?}",
64+
raw_wasm
65+
);
66+
return;
67+
}
68+
69+
// Convert to component and strip (wasm-tools)
70+
let component_ok = Command::new("wasm-tools")
71+
.args([
72+
"component",
73+
"new",
74+
raw_wasm.to_str().unwrap(),
75+
"-o",
76+
wasm_out.to_str().unwrap(),
77+
])
78+
.current_dir(&root)
79+
.status()
80+
.map(|s| s.success())
81+
.unwrap_or(false);
82+
83+
if !component_ok
84+
{
85+
// Fallback: copy raw module if wasm-tools unavailable
86+
if std::fs::copy(&raw_wasm, &wasm_out).is_err() {
87+
eprintln!(
88+
"cargo:warning=wasm-tools not found. Run: cargo install wasm-tools"
89+
);
90+
}
91+
} else {
92+
// Strip debug info (use temp file to avoid clobbering)
93+
let stripped = wasm_out.with_extension("wasm.stripped");
94+
let strip_ok = Command::new("wasm-tools")
95+
.args(["strip", wasm_out.to_str().unwrap(), "-o", stripped.to_str().unwrap()])
96+
.current_dir(&root)
97+
.status()
98+
.map(|s| s.success())
99+
.unwrap_or(false);
100+
if strip_ok
101+
{
102+
let _ = std::fs::rename(&stripped, &wasm_out);
103+
}
104+
}
105+
}

0 commit comments

Comments
 (0)