mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 13:25:20 +00:00
Refactor: Extract types from BitchatProtocol (#611)
* Extract BitchatMessage into a separate file * Convert `fromBinaryPayload` to `convenience init?` * Extract message dedup into an extension * Remove dead `formatMessageContent` * Minor refactor of timestamp and username formatting * Remove dead `getSenderColor` * Extract MessagePadding into a separate file * Extract BitchatPacket into a separate file * Extract ReadReceipt into a separate file * Extract NoisePayload into a separate file * Remove unnecessary import
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// ReadReceipt.swift
|
||||
// bitchat
|
||||
//
|
||||
// This is free and unencumbered software released into the public domain.
|
||||
// For more information, see <https://unlicense.org>
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct ReadReceipt: Codable {
|
||||
let originalMessageID: String
|
||||
let receiptID: String
|
||||
var readerID: String // Who read it
|
||||
let readerNickname: String
|
||||
let timestamp: Date
|
||||
|
||||
init(originalMessageID: String, readerID: String, readerNickname: String) {
|
||||
self.originalMessageID = originalMessageID
|
||||
self.receiptID = UUID().uuidString
|
||||
self.readerID = readerID
|
||||
self.readerNickname = readerNickname
|
||||
self.timestamp = Date()
|
||||
}
|
||||
|
||||
// For binary decoding
|
||||
private init(originalMessageID: String, receiptID: String, readerID: String, readerNickname: String, timestamp: Date) {
|
||||
self.originalMessageID = originalMessageID
|
||||
self.receiptID = receiptID
|
||||
self.readerID = readerID
|
||||
self.readerNickname = readerNickname
|
||||
self.timestamp = timestamp
|
||||
}
|
||||
|
||||
func encode() -> Data? {
|
||||
try? JSONEncoder().encode(self)
|
||||
}
|
||||
|
||||
static func decode(from data: Data) -> ReadReceipt? {
|
||||
try? JSONDecoder().decode(ReadReceipt.self, from: data)
|
||||
}
|
||||
|
||||
// MARK: - Binary Encoding
|
||||
|
||||
func toBinaryData() -> Data {
|
||||
var data = Data()
|
||||
data.appendUUID(originalMessageID)
|
||||
data.appendUUID(receiptID)
|
||||
// ReaderID as 8-byte hex string
|
||||
var readerData = Data()
|
||||
var tempID = readerID
|
||||
while tempID.count >= 2 && readerData.count < 8 {
|
||||
let hexByte = String(tempID.prefix(2))
|
||||
if let byte = UInt8(hexByte, radix: 16) {
|
||||
readerData.append(byte)
|
||||
}
|
||||
tempID = String(tempID.dropFirst(2))
|
||||
}
|
||||
while readerData.count < 8 {
|
||||
readerData.append(0)
|
||||
}
|
||||
data.append(readerData)
|
||||
data.appendDate(timestamp)
|
||||
data.appendString(readerNickname)
|
||||
return data
|
||||
}
|
||||
|
||||
static func fromBinaryData(_ data: Data) -> ReadReceipt? {
|
||||
// Create defensive copy
|
||||
let dataCopy = Data(data)
|
||||
|
||||
// Minimum size: 2 UUIDs (32) + readerID (8) + timestamp (8) + min nickname
|
||||
guard dataCopy.count >= 49 else { return nil }
|
||||
|
||||
var offset = 0
|
||||
|
||||
guard let originalMessageID = dataCopy.readUUID(at: &offset),
|
||||
let receiptID = dataCopy.readUUID(at: &offset) else { return nil }
|
||||
|
||||
guard let readerIDData = dataCopy.readFixedBytes(at: &offset, count: 8) else { return nil }
|
||||
let readerID = readerIDData.hexEncodedString()
|
||||
guard InputValidator.validatePeerID(readerID) else { return nil }
|
||||
|
||||
guard let timestamp = dataCopy.readDate(at: &offset),
|
||||
InputValidator.validateTimestamp(timestamp),
|
||||
let readerNicknameRaw = dataCopy.readString(at: &offset),
|
||||
let readerNickname = InputValidator.validateNickname(readerNicknameRaw) else { return nil }
|
||||
|
||||
return ReadReceipt(originalMessageID: originalMessageID,
|
||||
receiptID: receiptID,
|
||||
readerID: readerID,
|
||||
readerNickname: readerNickname,
|
||||
timestamp: timestamp)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user