Add recieved time to packet display. Closes #238.

This commit is contained in:
Jack Kingsman
2026-04-30 19:07:50 -07:00
parent d0e02a42f8
commit e76d922752
7 changed files with 68 additions and 45 deletions

View File

@@ -448,6 +448,8 @@ class RawPacketDecryptedInfo(BaseModel):
sender: str | None = None
channel_key: str | None = None
contact_key: str | None = None
sender_timestamp: int | None = None
message: str | None = None
class RawPacketBroadcast(BaseModel):

View File

@@ -366,6 +366,8 @@ async def process_raw_packet(
sender=result["sender"],
channel_key=result.get("channel_key"),
contact_key=result.get("contact_key"),
sender_timestamp=result.get("sender_timestamp"),
message=result.get("message"),
)
if result["decrypted"]
else None,
@@ -428,6 +430,8 @@ async def _process_group_text(
"sender": decrypted.sender,
"message_id": msg_id, # None if duplicate, msg_id if new
"channel_key": channel.key,
"sender_timestamp": decrypted.timestamp,
"message": decrypted.message,
}
# Couldn't decrypt with any known key
@@ -694,6 +698,8 @@ async def _process_direct_message(
"sender": contact.name or contact.public_key[:12],
"message_id": msg_id,
"contact_key": contact.public_key,
"sender_timestamp": result.timestamp,
"message": result.message,
}
# Couldn't decrypt with any known contact

View File

@@ -128,11 +128,15 @@ async def get_raw_packet(packet_id: int) -> RawPacketDetail:
sender=message.sender_name,
channel_key=message.conversation_key,
contact_key=message.sender_key,
sender_timestamp=message.sender_timestamp,
message=message.text,
)
else:
decrypted_info = RawPacketDecryptedInfo(
sender=message.sender_name,
contact_key=message.conversation_key,
sender_timestamp=message.sender_timestamp,
message=message.text,
)
return RawPacketDetail(

View File

@@ -94,6 +94,8 @@ describe('buildRawPacketStatsSnapshot', () => {
sender: 'Alpha',
channel_key: null,
contact_key: '0a'.repeat(32),
sender_timestamp: null,
message: null,
},
};

View File

@@ -343,6 +343,8 @@ export interface RawPacket {
sender: string | null;
channel_key: string | null;
contact_key: string | null;
sender_timestamp: number | null;
message: string | null;
} | null;
}

View File

@@ -324,51 +324,56 @@ export function inspectRawPacketWithOptions(
createPacketField('payload', `payload-${index}`, segment, structure.payload.startByte)
);
const enrichedPayloadFields =
decoded?.isValid && decoded.payloadType === PayloadType.GroupText && decoded.payload.decoded
? payloadFields.map((field) => {
if (field.name !== 'Ciphertext') {
return field;
}
const payload = decoded.payload.decoded as {
decrypted?: { timestamp?: number; flags?: number; sender?: string; message?: string };
};
if (!payload.decrypted?.message) {
return field;
}
const detailLines = [
payload.decrypted.timestamp != null
? `Timestamp: ${formatUnixTimestamp(payload.decrypted.timestamp)}`
: null,
payload.decrypted.flags != null
? `Flags: 0x${payload.decrypted.flags.toString(16).padStart(2, '0')}`
: null,
payload.decrypted.sender ? `Sender: ${payload.decrypted.sender}` : null,
`Message: ${payload.decrypted.message}`,
].filter((line): line is string => line !== null);
return {
...field,
description: describeCiphertextStructure(
decoded.payloadType,
field.endByte - field.startByte + 1,
field.description
),
decryptedMessage: detailLines.join('\n'),
};
})
: payloadFields.map((field) => {
if (!decoded?.isValid || field.name !== 'Ciphertext') {
return field;
}
return {
...field,
description: describeCiphertextStructure(
decoded.payloadType,
field.endByte - field.startByte + 1,
field.description
),
};
});
const enrichedPayloadFields = payloadFields.map((field) => {
if (!decoded?.isValid || field.name !== 'Ciphertext') {
return field;
}
const withStructure = {
...field,
description: describeCiphertextStructure(
decoded.payloadType,
field.endByte - field.startByte + 1,
field.description
),
};
// GroupText: client-side decoder has the decrypted content
if (decoded.payloadType === PayloadType.GroupText && decoded.payload.decoded) {
const payload = decoded.payload.decoded as {
decrypted?: { timestamp?: number; flags?: number; sender?: string; message?: string };
};
if (!payload.decrypted?.message) {
return withStructure;
}
const detailLines = [
payload.decrypted.timestamp != null
? `Sent (packet): ${formatUnixTimestamp(payload.decrypted.timestamp)}`
: null,
payload.decrypted.flags != null
? `Flags: 0x${payload.decrypted.flags.toString(16).padStart(2, '0')}`
: null,
payload.decrypted.sender ? `Sender: ${payload.decrypted.sender}` : null,
`Message: ${payload.decrypted.message}`,
].filter((line): line is string => line !== null);
return { ...withStructure, decryptedMessage: detailLines.join('\n') };
}
// TextMessage (DM): server-side decryption via decrypted_info
if (decoded.payloadType === PayloadType.TextMessage && packet.decrypted_info?.message) {
const info = packet.decrypted_info;
const detailLines = [
info.sender_timestamp != null
? `Sent (packet): ${formatUnixTimestamp(info.sender_timestamp)}`
: null,
info.sender ? `Sender: ${info.sender}` : null,
`Message: ${info.message}`,
].filter((line): line is string => line !== null);
return { ...withStructure, decryptedMessage: detailLines.join('\n') };
}
return withStructure;
});
return {
decoded,

View File

@@ -95,6 +95,8 @@ class TestGetRawPacket:
"sender": "Alice",
"channel_key": channel_key,
"contact_key": None,
"sender_timestamp": 1700000000,
"message": "Alice: hello",
}