mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-07 09:13:04 +02:00
Add on-receive packet analyzer for canonical copy. Closes #97.
This commit is contained in:
@@ -331,6 +331,12 @@ class MessageRepository:
|
||||
@staticmethod
|
||||
def _row_to_message(row: Any) -> Message:
|
||||
"""Convert a database row to a Message model."""
|
||||
packet_id = None
|
||||
if hasattr(row, "keys"):
|
||||
row_keys = row.keys()
|
||||
if "packet_id" in row_keys:
|
||||
packet_id = row["packet_id"]
|
||||
|
||||
return Message(
|
||||
id=row["id"],
|
||||
type=row["type"],
|
||||
@@ -345,6 +351,14 @@ class MessageRepository:
|
||||
outgoing=bool(row["outgoing"]),
|
||||
acked=row["acked"],
|
||||
sender_name=row["sender_name"],
|
||||
packet_id=packet_id,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _message_select(message_alias: str = "messages") -> str:
|
||||
return (
|
||||
f"{message_alias}.*, "
|
||||
f"(SELECT MIN(id) FROM raw_packets WHERE message_id = {message_alias}.id) AS packet_id"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -363,7 +377,7 @@ class MessageRepository:
|
||||
) -> list[Message]:
|
||||
search_query = MessageRepository._parse_search_query(q) if q else None
|
||||
query = (
|
||||
"SELECT messages.* FROM messages "
|
||||
f"SELECT {MessageRepository._message_select('messages')} FROM messages "
|
||||
"LEFT JOIN contacts ON messages.type = 'PRIV' "
|
||||
"AND LOWER(messages.conversation_key) = LOWER(contacts.public_key) "
|
||||
"LEFT JOIN channels ON messages.type = 'CHAN' "
|
||||
@@ -470,7 +484,8 @@ class MessageRepository:
|
||||
|
||||
# 1. Get the target message (must satisfy filters if provided)
|
||||
target_cursor = await db.conn.execute(
|
||||
f"SELECT * FROM messages WHERE id = ? AND {where_sql}",
|
||||
f"SELECT {MessageRepository._message_select('messages')} "
|
||||
f"FROM messages WHERE id = ? AND {where_sql}",
|
||||
(message_id, *base_params),
|
||||
)
|
||||
target_row = await target_cursor.fetchone()
|
||||
@@ -481,7 +496,7 @@ class MessageRepository:
|
||||
|
||||
# 2. Get context_size+1 messages before target (DESC)
|
||||
before_query = f"""
|
||||
SELECT * FROM messages WHERE {where_sql}
|
||||
SELECT {MessageRepository._message_select("messages")} FROM messages WHERE {where_sql}
|
||||
AND (received_at < ? OR (received_at = ? AND id < ?))
|
||||
ORDER BY received_at DESC, id DESC LIMIT ?
|
||||
"""
|
||||
@@ -500,7 +515,7 @@ class MessageRepository:
|
||||
|
||||
# 3. Get context_size+1 messages after target (ASC)
|
||||
after_query = f"""
|
||||
SELECT * FROM messages WHERE {where_sql}
|
||||
SELECT {MessageRepository._message_select("messages")} FROM messages WHERE {where_sql}
|
||||
AND (received_at > ? OR (received_at = ? AND id > ?))
|
||||
ORDER BY received_at ASC, id ASC LIMIT ?
|
||||
"""
|
||||
@@ -545,7 +560,7 @@ class MessageRepository:
|
||||
async def get_by_id(message_id: int) -> "Message | None":
|
||||
"""Look up a message by its ID."""
|
||||
cursor = await db.conn.execute(
|
||||
"SELECT * FROM messages WHERE id = ?",
|
||||
f"SELECT {MessageRepository._message_select('messages')} FROM messages WHERE id = ?",
|
||||
(message_id,),
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
@@ -570,7 +585,9 @@ class MessageRepository:
|
||||
) -> "Message | None":
|
||||
"""Look up a message by its unique content fields."""
|
||||
query = """
|
||||
SELECT * FROM messages
|
||||
SELECT messages.*,
|
||||
(SELECT MIN(id) FROM raw_packets WHERE message_id = messages.id) AS packet_id
|
||||
FROM messages
|
||||
WHERE type = ? AND conversation_key = ? AND text = ?
|
||||
AND (sender_timestamp = ? OR (sender_timestamp IS NULL AND ? IS NULL))
|
||||
"""
|
||||
|
||||
@@ -121,6 +121,18 @@ class RawPacketRepository:
|
||||
return None
|
||||
return row["message_id"]
|
||||
|
||||
@staticmethod
|
||||
async def get_by_id(packet_id: int) -> tuple[int, bytes, int, int | None] | None:
|
||||
"""Return a raw packet row as (id, data, timestamp, message_id)."""
|
||||
cursor = await db.conn.execute(
|
||||
"SELECT id, data, timestamp, message_id FROM raw_packets WHERE id = ?",
|
||||
(packet_id,),
|
||||
)
|
||||
row = await cursor.fetchone()
|
||||
if not row:
|
||||
return None
|
||||
return (row["id"], bytes(row["data"]), row["timestamp"], row["message_id"])
|
||||
|
||||
@staticmethod
|
||||
async def prune_old_undecrypted(max_age_days: int) -> int:
|
||||
"""Delete undecrypted packets older than max_age_days. Returns count deleted."""
|
||||
|
||||
Reference in New Issue
Block a user