v0.0.34: fix bot sendMessage — store per-bot numeric ID reverse mapping
Per-bot numeric IDs (privacy feature) broke sendMessage because the reverse lookup couldn't find the fingerprint from the per-bot hash. Fix: store numid:<numeric_id> → fingerprint in tokens tree when generating updates. resolve_chat_id checks this mapping first. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
10
warzone/Cargo.lock
generated
10
warzone/Cargo.lock
generated
@@ -2956,7 +2956,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "warzone-client"
|
||||
version = "0.0.33"
|
||||
version = "0.0.34"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"argon2",
|
||||
@@ -2989,7 +2989,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "warzone-mule"
|
||||
version = "0.0.33"
|
||||
version = "0.0.34"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
@@ -2998,7 +2998,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "warzone-protocol"
|
||||
version = "0.0.33"
|
||||
version = "0.0.34"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bincode",
|
||||
@@ -3023,7 +3023,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "warzone-server"
|
||||
version = "0.0.33"
|
||||
version = "0.0.34"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
@@ -3053,7 +3053,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "warzone-wasm"
|
||||
version = "0.0.33"
|
||||
version = "0.0.34"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"bincode",
|
||||
|
||||
@@ -9,7 +9,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.0.33"
|
||||
version = "0.0.34"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
rust-version = "1.75"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "warzone-protocol"
|
||||
version = "0.0.33"
|
||||
version = "0.0.34"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
description = "Core crypto & wire protocol for featherChat (Warzone messenger)"
|
||||
|
||||
@@ -101,6 +101,12 @@ fn resolve_chat_id(state: &AppState, chat_id: &serde_json::Value) -> Option<Stri
|
||||
}
|
||||
serde_json::Value::Number(n) => {
|
||||
let num = n.as_i64().unwrap_or(0);
|
||||
// Look up per-bot numeric ID reverse mapping
|
||||
let numid_key = format!("numid:{}", num);
|
||||
if let Some(fp_bytes) = state.db.tokens.get(numid_key.as_bytes()).ok().flatten() {
|
||||
return Some(String::from_utf8_lossy(&fp_bytes).to_string());
|
||||
}
|
||||
// Fallback: scan all keys with global hash (legacy)
|
||||
for item in state.db.keys.iter().flatten() {
|
||||
let key_str = String::from_utf8_lossy(&item.0).to_string();
|
||||
if !key_str.contains(':') && key_str.len() == 32 {
|
||||
@@ -188,9 +194,9 @@ pub async fn try_bot_webhook(state: &AppState, to_fp: &str, message: &[u8]) -> b
|
||||
let update = if let Ok(wire) =
|
||||
bincode::deserialize::<warzone_protocol::message::WireMessage>(message)
|
||||
{
|
||||
wire_message_to_update(&wire, message, &token)
|
||||
wire_message_to_update(state, &wire, message, &token)
|
||||
} else if let Ok(bot_msg) = serde_json::from_slice::<serde_json::Value>(message) {
|
||||
bot_json_to_update(&bot_msg, &token)
|
||||
bot_json_to_update(state, &bot_msg, &token)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -515,9 +521,9 @@ fn migrate_raw_queue(state: &AppState, bot_fp: &str, bot_token: &str) {
|
||||
let update = if let Ok(wire) =
|
||||
bincode::deserialize::<warzone_protocol::message::WireMessage>(&value)
|
||||
{
|
||||
wire_message_to_update(&wire, &value, bot_token)
|
||||
wire_message_to_update(state, &wire, &value, bot_token)
|
||||
} else if let Ok(bot_msg) = serde_json::from_slice::<serde_json::Value>(&value) {
|
||||
bot_json_to_update(&bot_msg, bot_token)
|
||||
bot_json_to_update(state, &bot_msg, bot_token)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -533,8 +539,15 @@ fn migrate_raw_queue(state: &AppState, bot_fp: &str, bot_token: &str) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Store a per-bot numeric ID → fingerprint reverse mapping.
|
||||
fn store_numid_mapping(state: &AppState, numeric_id: i64, fingerprint: &str) {
|
||||
let key = format!("numid:{}", numeric_id);
|
||||
let _ = state.db.tokens.insert(key.as_bytes(), fingerprint.as_bytes());
|
||||
}
|
||||
|
||||
/// Convert a `WireMessage` into a Telegram-style update JSON (without update_id).
|
||||
fn wire_message_to_update(
|
||||
state: &AppState,
|
||||
wire: &warzone_protocol::message::WireMessage,
|
||||
raw_bytes: &[u8],
|
||||
bot_token: &str,
|
||||
@@ -546,7 +559,7 @@ fn wire_message_to_update(
|
||||
..
|
||||
} => {
|
||||
let raw_b64 = base64::engine::general_purpose::STANDARD.encode(raw_bytes);
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(sender_fingerprint, bot_token);
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(sender_fingerprint, bot_token); store_numid_mapping(state, numeric, sender_fingerprint);
|
||||
Some(serde_json::json!({
|
||||
"message": {
|
||||
"message_id": id,
|
||||
@@ -571,7 +584,7 @@ fn wire_message_to_update(
|
||||
..
|
||||
} => {
|
||||
let raw_b64 = base64::engine::general_purpose::STANDARD.encode(raw_bytes);
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(sender_fingerprint, bot_token);
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(sender_fingerprint, bot_token); store_numid_mapping(state, numeric, sender_fingerprint);
|
||||
Some(serde_json::json!({
|
||||
"message": {
|
||||
"message_id": id,
|
||||
@@ -597,7 +610,7 @@ fn wire_message_to_update(
|
||||
payload,
|
||||
..
|
||||
} => {
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(sender_fingerprint, bot_token);
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(sender_fingerprint, bot_token); store_numid_mapping(state, numeric, sender_fingerprint);
|
||||
Some(serde_json::json!({
|
||||
"message": {
|
||||
"message_id": id,
|
||||
@@ -626,7 +639,7 @@ fn wire_message_to_update(
|
||||
file_size,
|
||||
..
|
||||
} => {
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(sender_fingerprint, bot_token);
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(sender_fingerprint, bot_token); store_numid_mapping(state, numeric, sender_fingerprint);
|
||||
Some(serde_json::json!({
|
||||
"message": {
|
||||
"message_id": id,
|
||||
@@ -654,12 +667,12 @@ fn wire_message_to_update(
|
||||
}
|
||||
|
||||
/// Convert a plaintext bot JSON message into a Telegram-style update (without update_id).
|
||||
fn bot_json_to_update(bot_msg: &serde_json::Value, bot_token: &str) -> Option<serde_json::Value> {
|
||||
fn bot_json_to_update(state: &AppState, bot_msg: &serde_json::Value, bot_token: &str) -> Option<serde_json::Value> {
|
||||
let msg_type = bot_msg.get("type").and_then(|v| v.as_str())?;
|
||||
match msg_type {
|
||||
"bot_message" => {
|
||||
let from_fp = bot_msg.get("from").and_then(|v| v.as_str()).unwrap_or("");
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(from_fp, bot_token);
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(from_fp, bot_token); store_numid_mapping(state, numeric, from_fp);
|
||||
Some(serde_json::json!({
|
||||
"message": {
|
||||
"message_id": bot_msg.get("id").and_then(|v| v.as_str()).unwrap_or(""),
|
||||
@@ -678,7 +691,7 @@ fn bot_json_to_update(bot_msg: &serde_json::Value, bot_token: &str) -> Option<se
|
||||
}
|
||||
"callback_query" => {
|
||||
let from_fp = bot_msg.get("from").and_then(|v| v.as_str()).unwrap_or("");
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(from_fp, bot_token);
|
||||
let numeric = crate::routes::resolve::fp_to_numeric_id_for_bot(from_fp, bot_token); store_numid_mapping(state, numeric, from_fp);
|
||||
Some(serde_json::json!({
|
||||
"callback_query": {
|
||||
"id": bot_msg.get("id").and_then(|v| v.as_str()).unwrap_or(""),
|
||||
|
||||
@@ -50,7 +50,7 @@ async fn pwa_manifest() -> impl IntoResponse {
|
||||
|
||||
async fn service_worker() -> impl IntoResponse {
|
||||
([(header::CONTENT_TYPE, "application/javascript")], r##"
|
||||
const CACHE = 'wz-v15';
|
||||
const CACHE = 'wz-v16';
|
||||
const SHELL = ['/', '/wasm/warzone_wasm.js', '/wasm/warzone_wasm_bg.wasm', '/icon.svg', '/manifest.json'];
|
||||
|
||||
self.addEventListener('install', e => {
|
||||
@@ -251,7 +251,7 @@ let pollTimer = null;
|
||||
let ws = null; // WebSocket connection
|
||||
let wasmReady = false;
|
||||
|
||||
const VERSION = '0.0.33';
|
||||
const VERSION = '0.0.34';
|
||||
let DEBUG = true; // toggle with /debug command
|
||||
|
||||
// ── Receipt tracking ──
|
||||
|
||||
Reference in New Issue
Block a user