From 95dcf38d060cd7b63bd70924869bead07c16d300 Mon Sep 17 00:00:00 2001 From: MarekWo Date: Sun, 1 Mar 2026 13:36:37 +0100 Subject: [PATCH] fix(v2): Handle bytes expected_ack from meshcore + DM prefix matching - Convert bytes to hex string for expected_ack and pkt_payload via _to_str() - Support pubkey prefix matching in get_dm_messages() (LIKE for short keys) - Fixes "Object of type bytes is not JSON serializable" error on DM view Co-Authored-By: Claude Opus 4.6 --- app/database.py | 13 ++++++++++--- app/device_manager.py | 20 +++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/app/database.py b/app/database.py index fd3cb01..77600d6 100644 --- a/app/database.py +++ b/app/database.py @@ -291,13 +291,20 @@ class Database: offset: int = 0) -> List[Dict]: contact_pubkey = contact_pubkey.lower() with self._connect() as conn: + # Support both full key and prefix matching + if len(contact_pubkey) < 64: + condition = "contact_pubkey LIKE ?" + param = contact_pubkey + '%' + else: + condition = "contact_pubkey = ?" + param = contact_pubkey rows = conn.execute( - """SELECT * FROM ( + f"""SELECT * FROM ( SELECT * FROM direct_messages - WHERE contact_pubkey = ? + WHERE {condition} ORDER BY timestamp DESC LIMIT ? OFFSET ? ) ORDER BY timestamp ASC""", - (contact_pubkey, limit, offset) + (param, limit, offset) ).fetchall() return [dict(r) for r in rows] diff --git a/app/device_manager.py b/app/device_manager.py index 40fe6b2..14f3443 100644 --- a/app/device_manager.py +++ b/app/device_manager.py @@ -16,6 +16,15 @@ from typing import Optional, Any, Dict, List logger = logging.getLogger(__name__) +def _to_str(val) -> str: + """Convert bytes or other types to string. Used for expected_ack, pkt_payload, etc.""" + if val is None: + return '' + if isinstance(val, bytes): + return val.hex() + return str(val) + + class DeviceManager: """ Manages MeshCore device connection. @@ -346,7 +355,7 @@ class DeviceManager: """Handle confirmation that our message was sent.""" try: data = getattr(event, 'payload', {}) - expected_ack = data.get('expected_ack', '') + expected_ack = _to_str(data.get('expected_ack')) msg_type = data.get('txt_type', 0) # txt_type 0 = DM, 1 = channel @@ -361,7 +370,7 @@ class DeviceManager: """Handle ACK (delivery confirmation for DM).""" try: data = getattr(event, 'payload', {}) - expected_ack = data.get('expected_ack', '') + expected_ack = _to_str(data.get('expected_ack')) if expected_ack: self.db.insert_ack( @@ -510,20 +519,21 @@ class DeviceManager: # Store sent DM in database ts = int(time.time()) event_data = getattr(event, 'payload', {}) + ack = _to_str(event_data.get('expected_ack')) dm_id = self.db.insert_direct_message( contact_pubkey=recipient_pubkey.lower(), direction='out', content=text, timestamp=ts, - expected_ack=event_data.get('expected_ack'), - pkt_payload=event_data.get('pkt_payload'), + expected_ack=ack or None, + pkt_payload=_to_str(event_data.get('pkt_payload')) or None, ) return { 'success': True, 'message': 'DM sent', 'id': dm_id, - 'expected_ack': event_data.get('expected_ack', ''), + 'expected_ack': ack, } except Exception as e: