From c5cdd63d7ed6f1657802f9acde7966a7258cd827 Mon Sep 17 00:00:00 2001 From: agessaman Date: Tue, 22 Sep 2026 16:56:12 -0700 Subject: [PATCH] fix(web_viewer): store packet hash on captured channel messages Decoded packet_stream rows had no way back to the original packet, so alternate routes could not be joined. The hash is already on routing_info; keep it in the existing JSON blob. --- modules/web_viewer/integration.py | 6 +++++ tests/test_web_viewer_integration.py | 36 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/modules/web_viewer/integration.py b/modules/web_viewer/integration.py index bc00608..348612f 100644 --- a/modules/web_viewer/integration.py +++ b/modules/web_viewer/integration.py @@ -594,6 +594,12 @@ class BotIntegration: 'path': getattr(message, 'path', ''), 'is_dm': bool(getattr(message, 'is_dm', False)), } + routing_info = getattr(message, 'routing_info', None) or {} + if not isinstance(routing_info, dict): + routing_info = {} + packet_hash = routing_info.get('packet_hash') + if packet_hash and str(packet_hash).strip('0'): + data['packet_hash'] = packet_hash self._insert_packet_stream_row(json.dumps(data), 'message', "channel message") except Exception as e: self.bot.logger.debug(f"Error storing channel message for web viewer: {e}") diff --git a/tests/test_web_viewer_integration.py b/tests/test_web_viewer_integration.py index a909263..79ad7c6 100644 --- a/tests/test_web_viewer_integration.py +++ b/tests/test_web_viewer_integration.py @@ -364,10 +364,46 @@ class TestCaptureChannelMessage: msg.hops = 0 msg.path = "" msg.is_dm = True + msg.routing_info = None bi.capture_channel_message(msg) ts, data, _, *_dims = bi._write_queue.get_nowait() parsed = json.loads(data) assert parsed["is_dm"] is True + assert "packet_hash" not in parsed + + def test_stores_packet_hash_from_routing_info(self): + """#270: message rows carry packet_hash so routes can link back to the packet.""" + bi = _make_bot_integration() + msg = MeshMessage( + content="hello", + sender_id="aa", + channel="general", + hops=1, + is_dm=False, + routing_info={"packet_hash": "ABCDEF0123456789", "path_length": 1}, + ) + bi.capture_channel_message(msg) + _, data, row_type, *_dims = bi._write_queue.get_nowait() + assert row_type == "message" + parsed = json.loads(data) + assert parsed["packet_hash"] == "ABCDEF0123456789" + + def test_omits_missing_or_all_zero_packet_hash(self): + """#270: do not invent a hash when routing_info lacks a real one.""" + bi = _make_bot_integration() + for routing_info in (None, {}, {"packet_hash": ""}, {"packet_hash": "0000000000000000"}): + msg = MeshMessage( + content="hello", + sender_id="aa", + channel="general", + hops=0, + is_dm=False, + routing_info=routing_info, + ) + bi.capture_channel_message(msg) + _, data, _, *_dims = bi._write_queue.get_nowait() + parsed = json.loads(data) + assert "packet_hash" not in parsed, routing_info # ---------------------------------------------------------------------------