v0.0.27: TG-compatible bots — plaintext send, numeric IDs, webhooks, BotFather
Bot compatibility: - Clients send plaintext bot_message to bot aliases (no E2E encryption) - Numeric chat_id: fp_to_numeric_id() deterministic hash, accept string/number - Webhook delivery: POST updates to bot's webhook URL (async, fire-and-forget) - getUpdates timeout raised to 50s (was 30, TG uses 50) - parse_mode HTML rendered in web client - E2E bot registration: optional seed + bundle for encrypted bot sessions BotFather + instance control: - --enable-bots CLI flag (default: disabled) - BotFather auto-created on first start (@botfather alias) - Bot ownership: owner fingerprint stored in bot_info - All bot endpoints return 403 when disabled Bot Bridge: - tools/bot-bridge.py: TG-compatible proxy for unmodified TG bots - Translates chat_id int↔string, proxies getUpdates/sendMessage - README with python-telegram-bot and Telegraf examples Test fixes: - Updated tests for ETH address display in header/messages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,20 @@ use axum::{
|
||||
use crate::errors::AppResult;
|
||||
use crate::state::AppState;
|
||||
|
||||
/// Convert a fingerprint hex string to a stable i64 ID (for Telegram compatibility).
|
||||
/// Uses first 8 bytes of the fingerprint as a positive i64.
|
||||
pub fn fp_to_numeric_id(fp: &str) -> i64 {
|
||||
let clean: String = fp.chars().filter(|c| c.is_ascii_hexdigit()).take(16).collect();
|
||||
let bytes = hex::decode(&clean).unwrap_or_default();
|
||||
if bytes.len() >= 8 {
|
||||
let mut arr = [0u8; 8];
|
||||
arr.copy_from_slice(&bytes[..8]);
|
||||
i64::from_be_bytes(arr) & 0x7FFFFFFFFFFFFFFF // ensure positive
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn routes() -> Router<AppState> {
|
||||
Router::new().route("/resolve/:address", get(resolve_address))
|
||||
}
|
||||
@@ -27,6 +41,7 @@ async fn resolve_address(
|
||||
return Ok(Json(serde_json::json!({
|
||||
"address": address,
|
||||
"fingerprint": fp,
|
||||
"numeric_id": fp_to_numeric_id(&fp),
|
||||
"type": "eth",
|
||||
})));
|
||||
}
|
||||
@@ -40,6 +55,7 @@ async fn resolve_address(
|
||||
return Ok(Json(serde_json::json!({
|
||||
"address": address,
|
||||
"fingerprint": fp,
|
||||
"numeric_id": fp_to_numeric_id(fp),
|
||||
"type": "eth",
|
||||
"federated": true,
|
||||
})));
|
||||
@@ -61,6 +77,7 @@ async fn resolve_address(
|
||||
return Ok(Json(serde_json::json!({
|
||||
"address": address,
|
||||
"fingerprint": fp,
|
||||
"numeric_id": fp_to_numeric_id(&fp),
|
||||
"type": "alias",
|
||||
})));
|
||||
}
|
||||
@@ -70,6 +87,7 @@ async fn resolve_address(
|
||||
return Ok(Json(serde_json::json!({
|
||||
"address": address,
|
||||
"fingerprint": fp,
|
||||
"numeric_id": fp_to_numeric_id(&fp),
|
||||
"type": "alias",
|
||||
"federated": true,
|
||||
})));
|
||||
@@ -93,6 +111,7 @@ async fn resolve_address(
|
||||
return Ok(Json(serde_json::json!({
|
||||
"address": address,
|
||||
"fingerprint": fp,
|
||||
"numeric_id": fp_to_numeric_id(&fp),
|
||||
"eth_address": eth,
|
||||
"type": "fingerprint",
|
||||
})));
|
||||
|
||||
Reference in New Issue
Block a user