mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 19:05:20 +00:00
Make logging categories static properties of OSLog
So we can use `.<category name>` to simplify the code. Search/Replace Strategy: Search text: `category: SecureLogger.` Replace text: `category: .`
This commit is contained in:
@@ -463,7 +463,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
UserDefaults.standard.set(data, forKey: "sentReadReceipts")
|
||||
} else {
|
||||
SecureLogger.log("❌ Failed to encode read receipts for persistence",
|
||||
category: SecureLogger.session, level: .error)
|
||||
category: .session, level: .error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -562,11 +562,11 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Wait for Tor readiness before Nostr init
|
||||
let ready = await TorManager.shared.awaitReady(timeout: 60)
|
||||
guard ready else {
|
||||
SecureLogger.log("Nostr init skipped: Tor not ready", category: SecureLogger.session, level: .error)
|
||||
SecureLogger.log("Nostr init skipped: Tor not ready", category: .session, level: .error)
|
||||
return
|
||||
}
|
||||
nostrRelayManager = NostrRelayManager.shared
|
||||
SecureLogger.log("Initializing Nostr relay connections", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("Initializing Nostr relay connections", category: .session, level: .debug)
|
||||
// Connect is managed centrally on scene activation; avoid duplicate connects here
|
||||
|
||||
// Attempt to flush any queued outbox after Nostr comes online
|
||||
@@ -597,7 +597,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
uniquePeers[peer.id] = peer
|
||||
} else {
|
||||
SecureLogger.log("⚠️ Duplicate peer ID detected: \(peer.id) (\(peer.displayName))",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
}
|
||||
}
|
||||
self.peerIndex = uniquePeers
|
||||
@@ -1036,10 +1036,10 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
self.privateChats[convKey]?[idx].deliveryStatus = .delivered(to: self.displayNameForNostrPubkey(senderPubkey), at: Date())
|
||||
self.objectWillChange.send()
|
||||
SecureLogger.log("GeoDM: recv DELIVERED for mid=\(messageID.prefix(8))… from=\(senderPubkey.prefix(8))…",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
} else {
|
||||
SecureLogger.log("GeoDM: delivered ack for unknown mid=\(messageID.prefix(8))… conv=\(convKey)",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
}
|
||||
}
|
||||
case .readReceipt:
|
||||
@@ -1048,10 +1048,10 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
self.privateChats[convKey]?[idx].deliveryStatus = .read(by: self.displayNameForNostrPubkey(senderPubkey), at: Date())
|
||||
self.objectWillChange.send()
|
||||
SecureLogger.log("GeoDM: recv READ for mid=\(messageID.prefix(8))… from=\(senderPubkey.prefix(8))…",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
} else {
|
||||
SecureLogger.log("GeoDM: read ack for unknown mid=\(messageID.prefix(8))… conv=\(convKey)",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
}
|
||||
}
|
||||
case .verifyChallenge, .verifyResponse:
|
||||
@@ -1464,14 +1464,14 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
count: TransportConfig.nostrGeoRelayCount
|
||||
)
|
||||
if targetRelays.isEmpty {
|
||||
SecureLogger.log("Geo: no geohash relays available for \(ch.geohash); not sending", category: SecureLogger.session, level: .warning)
|
||||
SecureLogger.log("Geo: no geohash relays available for \(ch.geohash); not sending", category: .session, level: .warning)
|
||||
} else {
|
||||
NostrRelayManager.shared.sendEvent(event, to: targetRelays)
|
||||
}
|
||||
// Track ourselves as active participant
|
||||
self.recordGeoParticipant(pubkeyHex: identity.publicKeyHex)
|
||||
SecureLogger.log("GeoTeleport: sent geo message pub=\(identity.publicKeyHex.prefix(8))… teleported=\(LocationChannelManager.shared.teleported)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
// If we tagged this as teleported, also mark our pubkey in teleportedGeo for UI
|
||||
// Only when not in our regional set (and regional list is known)
|
||||
let hasRegional = !LocationChannelManager.shared.availableChannels.isEmpty
|
||||
@@ -1480,10 +1480,10 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
let key = identity.publicKeyHex.lowercased()
|
||||
self.teleportedGeo = self.teleportedGeo.union([key])
|
||||
SecureLogger.log("GeoTeleport: mark self teleported key=\(key.prefix(8))… total=\(self.teleportedGeo.count)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
} catch {
|
||||
SecureLogger.log("❌ Failed to send geohash message: \(error)", category: SecureLogger.session, level: .error)
|
||||
SecureLogger.log("❌ Failed to send geohash message: \(error)", category: .session, level: .error)
|
||||
self.addSystemMessage("failed to send to location channel")
|
||||
}
|
||||
}
|
||||
@@ -1510,7 +1510,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Debug: log if any empty messages are present
|
||||
let emptyMesh = messages.filter { $0.content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }.count
|
||||
if emptyMesh > 0 {
|
||||
SecureLogger.log("RenderGuard: mesh timeline contains \(emptyMesh) empty messages", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("RenderGuard: mesh timeline contains \(emptyMesh) empty messages", category: .session, level: .debug)
|
||||
}
|
||||
stopGeoParticipantsTimer()
|
||||
geohashPeople = []
|
||||
@@ -1537,7 +1537,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Debug: log if any empty messages are present post-sanitize
|
||||
let emptyGeo = messages.filter { $0.content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }.count
|
||||
if emptyGeo > 0 {
|
||||
SecureLogger.log("RenderGuard: geohash \(ch.geohash) timeline has \(emptyGeo) empty messages after sanitize", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("RenderGuard: geohash \(ch.geohash) timeline has \(emptyGeo) empty messages after sanitize", category: .session, level: .debug)
|
||||
}
|
||||
}
|
||||
// If switching to a location channel, flush any pending geohash-only system messages
|
||||
@@ -1570,7 +1570,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
if LocationChannelManager.shared.teleported && hasRegional && !inRegional {
|
||||
teleportedGeo = teleportedGeo.union([key])
|
||||
SecureLogger.log("GeoTeleport: channel switch mark self teleported key=\(key.prefix(8))… total=\(teleportedGeo.count)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
} else {
|
||||
teleportedGeo.remove(key)
|
||||
}
|
||||
@@ -1594,7 +1594,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Log incoming tags for diagnostics
|
||||
let tagSummary = event.tags.map { "[" + $0.joined(separator: ",") + "]" }.joined(separator: ",")
|
||||
SecureLogger.log("GeoTeleport: recv pub=\(event.pubkey.prefix(8))… tags=\(tagSummary)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
// Track teleport tag for participants – only our format ["t", "teleport"]
|
||||
let hasTeleportTag: Bool = event.tags.contains(where: { tag in
|
||||
tag.count >= 2 && tag[0].lowercased() == "t" && tag[1].lowercased() == "teleport"
|
||||
@@ -1612,7 +1612,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
Task { @MainActor in
|
||||
self.teleportedGeo = self.teleportedGeo.union([key])
|
||||
SecureLogger.log("GeoTeleport: mark peer teleported key=\(key.prefix(8))… total=\(self.teleportedGeo.count)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1677,7 +1677,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Log GeoDM subscribe only when Tor is ready to avoid early noise
|
||||
if TorManager.shared.isReady {
|
||||
SecureLogger.log("GeoDM: subscribing DMs pub=\(id.publicKeyHex.prefix(8))… sub=\(dmSub)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
}
|
||||
let dmFilter = NostrFilter.giftWrapsFor(pubkey: id.publicKeyHex, since: Date().addingTimeInterval(-TransportConfig.nostrDMSubscribeLookbackSeconds))
|
||||
NostrRelayManager.shared.subscribe(filter: dmFilter, id: dmSub) { [weak self] giftWrap in
|
||||
@@ -1688,11 +1688,11 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Decrypt with per-geohash identity
|
||||
guard let (content, senderPubkey, rumorTs) = try? NostrProtocol.decryptPrivateMessage(giftWrap: giftWrap, recipientIdentity: id) else {
|
||||
SecureLogger.log("GeoDM: failed decrypt giftWrap id=\(giftWrap.id.prefix(8))…",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
return
|
||||
}
|
||||
SecureLogger.log("GeoDM: decrypted gift-wrap id=\(giftWrap.id.prefix(16))... from=\(senderPubkey.prefix(8))...",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
guard content.hasPrefix("bitchat1:") else { return }
|
||||
guard let packetData = Self.base64URLDecode(String(content.dropFirst("bitchat1:".count))),
|
||||
let packet = BitchatPacket.from(packetData) else { return }
|
||||
@@ -1706,7 +1706,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
guard let pm = PrivateMessagePacket.decode(from: noisePayload.data) else { return }
|
||||
let messageId = pm.messageID
|
||||
SecureLogger.log("GeoDM: recv PM <- sender=\(senderPubkey.prefix(8))… mid=\(messageId.prefix(8))…",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
// Send delivery ACK immediately (even if duplicate), once per messageID
|
||||
if !self.sentGeoDeliveryAcks.contains(messageId) {
|
||||
let nostrTransport = NostrTransport()
|
||||
@@ -1770,10 +1770,10 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
self.privateChats[convKey]?[idx].deliveryStatus = .delivered(to: self.displayNameForNostrPubkey(senderPubkey), at: Date())
|
||||
self.objectWillChange.send()
|
||||
SecureLogger.log("GeoDM: recv DELIVERED for mid=\(messageID.prefix(8))… from=\(senderPubkey.prefix(8))…",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
} else {
|
||||
SecureLogger.log("GeoDM: delivered ack for unknown mid=\(messageID.prefix(8))… conv=\(convKey)",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
}
|
||||
}
|
||||
case .readReceipt:
|
||||
@@ -1782,10 +1782,10 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
self.privateChats[convKey]?[idx].deliveryStatus = .read(by: self.displayNameForNostrPubkey(senderPubkey), at: Date())
|
||||
self.objectWillChange.send()
|
||||
SecureLogger.log("GeoDM: recv READ for mid=\(messageID.prefix(8))… from=\(senderPubkey.prefix(8))…",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
} else {
|
||||
SecureLogger.log("GeoDM: read ack for unknown mid=\(messageID.prefix(8))… conv=\(convKey)",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
}
|
||||
}
|
||||
default:
|
||||
@@ -2153,7 +2153,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
return
|
||||
}
|
||||
SecureLogger.log("GeoDM: local send mid=\(messageID.prefix(8))… to=\(recipientHex.prefix(8))… conv=\(peerID)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
let nostrTransport = NostrTransport()
|
||||
nostrTransport.senderPeerID = meshService.myPeerID
|
||||
nostrTransport.sendPrivateMessageGeohash(content: content, toRecipientHex: recipientHex, from: id, messageID: messageID)
|
||||
@@ -2474,7 +2474,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
if hadUnreadTemp {
|
||||
unreadPrivateMessages.insert(peerID)
|
||||
SecureLogger.log("📬 Transferred unread status from temp peer IDs to \(peerID)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
}
|
||||
|
||||
if consolidatedCount > 0 {
|
||||
@@ -2482,7 +2482,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
privateChats[peerID]?.sort { $0.timestamp < $1.timestamp }
|
||||
|
||||
SecureLogger.log("📥 Consolidated \(consolidatedCount) Nostr messages from temporary peer IDs to \(peerNickname)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2497,7 +2497,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
}
|
||||
} else {
|
||||
SecureLogger.log("GeoDM: skipping mesh handshake for virtual peerID=\(peerID)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
}
|
||||
|
||||
// Delegate to private chat manager but add already-acked messages first
|
||||
@@ -2578,7 +2578,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
guard let receipt = notification.userInfo?["receipt"] as? ReadReceipt else { return }
|
||||
|
||||
SecureLogger.log("📖 Handling read receipt for message \(receipt.originalMessageID) from Nostr",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
|
||||
// Process the read receipt through the same flow as Bluetooth read receipts
|
||||
didReceiveReadReceipt(receipt)
|
||||
@@ -2604,7 +2604,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// If we have a private chat open with the old peer ID, update it to the new one
|
||||
if selectedPrivateChatPeer == oldPeerID {
|
||||
SecureLogger.log("📱 Updating private chat peer ID due to key change: \(oldPeerID) -> \(newPeerID)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
|
||||
// Transfer private chat messages to new peer ID
|
||||
if let messages = privateChats[oldPeerID] {
|
||||
@@ -2636,7 +2636,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Even if the chat isn't open, migrate any existing private chat data
|
||||
if let messages = privateChats[oldPeerID] {
|
||||
SecureLogger.log("📱 Migrating private chat messages from \(oldPeerID) to \(newPeerID)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
var chats = privateChats
|
||||
chats[newPeerID] = messages
|
||||
chats.removeValue(forKey: oldPeerID)
|
||||
@@ -2742,7 +2742,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
messageRouter.sendPrivate(screenshotMessage, to: peerID, recipientNickname: peerNickname, messageID: UUID().uuidString)
|
||||
default:
|
||||
// Don't send screenshot notification if no session exists
|
||||
SecureLogger.log("Skipping screenshot notification to \(peerID) - no established session", category: SecureLogger.security, level: .debug)
|
||||
SecureLogger.log("Skipping screenshot notification to \(peerID) - no established session", category: .security, level: .debug)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2783,14 +2783,14 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
)
|
||||
let targetRelays = GeoRelayDirectory.shared.closestRelays(toGeohash: ch.geohash, count: 5)
|
||||
if targetRelays.isEmpty {
|
||||
SecureLogger.log("Geo: no geohash relays available for \(ch.geohash); not sending", category: SecureLogger.session, level: .warning)
|
||||
SecureLogger.log("Geo: no geohash relays available for \(ch.geohash); not sending", category: .session, level: .warning)
|
||||
} else {
|
||||
NostrRelayManager.shared.sendEvent(event, to: targetRelays)
|
||||
}
|
||||
// Track ourselves as active participant
|
||||
self.recordGeoParticipant(pubkeyHex: identity.publicKeyHex)
|
||||
} catch {
|
||||
SecureLogger.log("❌ Failed to send geohash screenshot message: \(error)", category: SecureLogger.session, level: .error)
|
||||
SecureLogger.log("❌ Failed to send geohash screenshot message: \(error)", category: .session, level: .error)
|
||||
self.addSystemMessage("failed to send to location channel")
|
||||
}
|
||||
}
|
||||
@@ -2849,7 +2849,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
for (currentPeerID, currentNickname) in meshService.getPeerNicknames() {
|
||||
if currentNickname == peerNickname {
|
||||
SecureLogger.log("📖 Resolved updated peer ID for read receipt: \(peerID) -> \(currentPeerID)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
actualPeerID = currentPeerID
|
||||
break
|
||||
}
|
||||
@@ -2878,7 +2878,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
for message in messages where message.senderPeerID == peerID && !message.isRelay {
|
||||
if !sentReadReceipts.contains(message.id) {
|
||||
SecureLogger.log("GeoDM: sending READ for mid=\(message.id.prefix(8))… to=\(recipientHex.prefix(8))…",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
let nostrTransport = NostrTransport()
|
||||
nostrTransport.senderPeerID = meshService.myPeerID
|
||||
nostrTransport.sendReadReceiptGeohash(message.id, toRecipientHex: recipientHex, from: id)
|
||||
@@ -4322,14 +4322,14 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
verifiedFingerprints = SecureIdentityStateManager.shared.getVerifiedFingerprints()
|
||||
// Log snapshot for debugging persistence
|
||||
let sample = Array(verifiedFingerprints.prefix(TransportConfig.uiFingerprintSampleCount)).map { $0.prefix(8) }.joined(separator: ", ")
|
||||
SecureLogger.log("🔐 Verified loaded: \(verifiedFingerprints.count) [\(sample)]", category: SecureLogger.security, level: .info)
|
||||
SecureLogger.log("🔐 Verified loaded: \(verifiedFingerprints.count) [\(sample)]", category: .security, level: .info)
|
||||
// Also log any offline favorites and whether we consider them verified
|
||||
let offlineFavorites = unifiedPeerService.favorites.filter { !$0.isConnected }
|
||||
for fav in offlineFavorites {
|
||||
let fp = unifiedPeerService.getFingerprint(for: fav.id)
|
||||
let isVer = fp.flatMap { verifiedFingerprints.contains($0) } ?? false
|
||||
let fpShort = fp?.prefix(8) ?? "nil"
|
||||
SecureLogger.log("⭐️ Favorite offline: \(fav.nickname) fp=\(fpShort) verified=\(isVer)", category: SecureLogger.security, level: .info)
|
||||
SecureLogger.log("⭐️ Favorite offline: \(fav.nickname) fp=\(fpShort) verified=\(isVer)", category: .security, level: .info)
|
||||
}
|
||||
// Invalidate cached encryption statuses so offline favorites can show verified badges immediately
|
||||
invalidateEncryptionCache()
|
||||
@@ -4345,7 +4345,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
DispatchQueue.main.async {
|
||||
guard let self = self else { return }
|
||||
|
||||
SecureLogger.log("🔐 Authenticated: \(peerID)", category: SecureLogger.security, level: .debug)
|
||||
SecureLogger.log("🔐 Authenticated: \(peerID)", category: .security, level: .debug)
|
||||
|
||||
// Update encryption status
|
||||
if self.verifiedFingerprints.contains(fingerprint) {
|
||||
@@ -4365,7 +4365,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
let stable = keyData.hexEncodedString()
|
||||
self.shortIDToNoiseKey[peerID] = stable
|
||||
SecureLogger.log("🗺️ Mapped short peerID to Noise key for header continuity: \(peerID) -> \(stable.prefix(8))…",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
}
|
||||
|
||||
// If a QR verification is pending but not sent yet, send it now that session is authenticated
|
||||
@@ -4373,7 +4373,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
self.meshService.sendVerifyChallenge(to: peerID, noiseKeyHex: pending.noiseKeyHex, nonceA: pending.nonceA)
|
||||
pending.sent = true
|
||||
self.pendingQRVerifications[peerID] = pending
|
||||
SecureLogger.log("📤 Sent deferred verify challenge to \(peerID) after handshake", category: SecureLogger.security, level: .debug)
|
||||
SecureLogger.log("📤 Sent deferred verify challenge to \(peerID) after handshake", category: .security, level: .debug)
|
||||
}
|
||||
|
||||
// Schedule UI update
|
||||
@@ -4519,7 +4519,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
pendingQRVerifications.removeValue(forKey: peerID)
|
||||
if let fp = getFingerprint(for: peerID) {
|
||||
let short = fp.prefix(8)
|
||||
SecureLogger.log("🔐 Marking verified fingerprint: \(short)", category: SecureLogger.security, level: .info)
|
||||
SecureLogger.log("🔐 Marking verified fingerprint: \(short)", category: .security, level: .info)
|
||||
SecureIdentityStateManager.shared.setVerified(fingerprint: fp, verified: true)
|
||||
SecureIdentityStateManager.shared.forceSave()
|
||||
verifiedFingerprints.insert(fp)
|
||||
@@ -4605,7 +4605,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// MARK: - Peer Connection Events
|
||||
|
||||
func didConnectToPeer(_ peerID: String) {
|
||||
SecureLogger.log("🤝 Peer connected: \(peerID)", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("🤝 Peer connected: \(peerID)", category: .session, level: .debug)
|
||||
|
||||
// Handle all main actor work async
|
||||
Task { @MainActor in
|
||||
@@ -4623,7 +4623,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
try? await Task.sleep(nanoseconds: TransportConfig.uiAsyncMediumSleepNs) // 0.5 seconds
|
||||
meshService.sendFavoriteNotification(to: peerID, isFavorite: true)
|
||||
SecureLogger.log("📤 Resent favorite notification to reconnected peer \(peerID)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
}
|
||||
|
||||
// Force UI refresh
|
||||
@@ -4643,7 +4643,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
}
|
||||
|
||||
func didDisconnectFromPeer(_ peerID: String) {
|
||||
SecureLogger.log("👋 Peer disconnected: \(peerID)", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("👋 Peer disconnected: \(peerID)", category: .session, level: .debug)
|
||||
|
||||
// Remove ephemeral session from identity manager
|
||||
SecureIdentityStateManager.shared.removeEphemeralSession(peerID: peerID)
|
||||
@@ -4739,7 +4739,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
self.recentlySeenPeers = currentPeerSet
|
||||
NotificationService.shared.sendNetworkAvailableNotification(peerCount: meshPeers.count)
|
||||
SecureLogger.log("👥 Sent bitchatters nearby notification for \(meshPeers.count) mesh peers",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
} else {
|
||||
// No peers — immediately reset to allow next rising-edge to notify
|
||||
@@ -4749,7 +4749,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
self.networkResetTimer?.invalidate()
|
||||
self.networkResetTimer = nil
|
||||
}
|
||||
SecureLogger.log("⏳ Mesh empty — reset network notification state", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("⏳ Mesh empty — reset network notification state", category: .session, level: .debug)
|
||||
}
|
||||
|
||||
// Register ephemeral sessions for all connected peers
|
||||
@@ -4812,7 +4812,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
|
||||
if !idsToRemove.isEmpty {
|
||||
SecureLogger.log("🧹 Cleaned up \(idsToRemove.count) stale unread peer IDs",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4843,7 +4843,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
let removedCount = oldCount - sentReadReceipts.count
|
||||
if removedCount > 0 {
|
||||
SecureLogger.log("🧹 Cleaned up \(removedCount) old read receipts",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4891,7 +4891,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
nostrPublicKey = data.hexEncodedString()
|
||||
}
|
||||
} catch {
|
||||
SecureLogger.log("Failed to decode Nostr npub: \(error)", category: SecureLogger.session, level: .error)
|
||||
SecureLogger.log("Failed to decode Nostr npub: \(error)", category: .session, level: .error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5032,7 +5032,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
NostrRelayManager.shared.sendEvent(event, to: targetRelays)
|
||||
}
|
||||
} catch {
|
||||
SecureLogger.log("❌ Failed to send geohash raw message: \(error)", category: SecureLogger.session, level: .error)
|
||||
SecureLogger.log("❌ Failed to send geohash raw message: \(error)", category: .session, level: .error)
|
||||
}
|
||||
}
|
||||
return
|
||||
@@ -5048,12 +5048,12 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
@MainActor
|
||||
private func setupNostrMessageHandling() {
|
||||
guard let currentIdentity = try? NostrIdentityBridge.getCurrentNostrIdentity() else {
|
||||
SecureLogger.log("⚠️ No Nostr identity available for message handling", category: SecureLogger.session, level: .warning)
|
||||
SecureLogger.log("⚠️ No Nostr identity available for message handling", category: .session, level: .warning)
|
||||
return
|
||||
}
|
||||
|
||||
SecureLogger.log("🔑 Setting up Nostr subscription for pubkey: \(currentIdentity.publicKeyHex.prefix(16))...",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
|
||||
// Subscribe to Nostr messages
|
||||
let filter = NostrFilter.giftWrapsFor(
|
||||
@@ -5093,19 +5093,19 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
|
||||
// Expect embedded BitChat packet content
|
||||
guard content.hasPrefix("bitchat1:") else {
|
||||
SecureLogger.log("Ignoring non-embedded Nostr DM content", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("Ignoring non-embedded Nostr DM content", category: .session, level: .debug)
|
||||
return
|
||||
}
|
||||
|
||||
guard let packetData = Self.base64URLDecode(String(content.dropFirst("bitchat1:".count))),
|
||||
let packet = BitchatPacket.from(packetData) else {
|
||||
SecureLogger.log("Failed to decode embedded BitChat packet from Nostr DM", category: SecureLogger.session, level: .error)
|
||||
SecureLogger.log("Failed to decode embedded BitChat packet from Nostr DM", category: .session, level: .error)
|
||||
return
|
||||
}
|
||||
|
||||
// Only process typed noiseEncrypted envelope for private messages/receipts
|
||||
guard packet.type == MessageType.noiseEncrypted.rawValue else {
|
||||
SecureLogger.log("Unsupported embedded packet type: \(packet.type)", category: SecureLogger.session, level: .warning)
|
||||
SecureLogger.log("Unsupported embedded packet type: \(packet.type)", category: .session, level: .warning)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5119,7 +5119,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
|
||||
// Parse plaintext typed payload
|
||||
guard let noisePayload = NoisePayload.decode(packet.payload) else {
|
||||
SecureLogger.log("Failed to parse embedded NoisePayload", category: SecureLogger.session, level: .error)
|
||||
SecureLogger.log("Failed to parse embedded NoisePayload", category: .session, level: .error)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5215,14 +5215,14 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Send delivery ack via Nostr embedded
|
||||
if !wasReadBefore {
|
||||
if let key = actualSenderNoiseKey {
|
||||
SecureLogger.log("Sending DELIVERED ack for \(messageId.prefix(8))… via router", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("Sending DELIVERED ack for \(messageId.prefix(8))… via router", category: .session, level: .debug)
|
||||
messageRouter.sendDeliveryAck(messageId, to: key.hexEncodedString())
|
||||
} else if let id = try? NostrIdentityBridge.getCurrentNostrIdentity() {
|
||||
// Fallback: no Noise mapping yet — send directly to sender's Nostr pubkey
|
||||
let nt = NostrTransport()
|
||||
nt.senderPeerID = meshService.myPeerID
|
||||
nt.sendDeliveryAckGeohash(for: messageId, toRecipientHex: senderPubkey, from: id)
|
||||
SecureLogger.log("Sent DELIVERED ack directly to Nostr pub=\(senderPubkey.prefix(8))… for mid=\(messageId.prefix(8))…", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("Sent DELIVERED ack directly to Nostr pub=\(senderPubkey.prefix(8))… for mid=\(messageId.prefix(8))…", category: .session, level: .debug)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5237,7 +5237,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
if !sentReadReceipts.contains(messageId) {
|
||||
if let key = actualSenderNoiseKey {
|
||||
let receipt = ReadReceipt(originalMessageID: messageId, readerID: meshService.myPeerID, readerNickname: nickname)
|
||||
SecureLogger.log("Viewing chat; sending READ ack for \(messageId.prefix(8))… via router", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("Viewing chat; sending READ ack for \(messageId.prefix(8))… via router", category: .session, level: .debug)
|
||||
messageRouter.sendReadReceipt(receipt, to: key.hexEncodedString())
|
||||
sentReadReceipts.insert(messageId)
|
||||
} else if let id = try? NostrIdentityBridge.getCurrentNostrIdentity() {
|
||||
@@ -5245,7 +5245,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
nt.senderPeerID = meshService.myPeerID
|
||||
nt.sendReadReceiptGeohash(messageId, toRecipientHex: senderPubkey, from: id)
|
||||
sentReadReceipts.insert(messageId)
|
||||
SecureLogger.log("Viewing chat; sent READ ack directly to Nostr pub=\(senderPubkey.prefix(8))… for mid=\(messageId.prefix(8))…", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("Viewing chat; sent READ ack directly to Nostr pub=\(senderPubkey.prefix(8))… for mid=\(messageId.prefix(8))…", category: .session, level: .debug)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -5290,7 +5290,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
}
|
||||
|
||||
} catch {
|
||||
SecureLogger.log("Failed to decrypt Nostr message: \(error)", category: SecureLogger.session, level: .error)
|
||||
SecureLogger.log("Failed to decrypt Nostr message: \(error)", category: .session, level: .error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5311,7 +5311,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Parse ACK format: "ACK:TYPE:MESSAGE_ID"
|
||||
let parts = content.split(separator: ":", maxSplits: 2)
|
||||
guard parts.count >= 3 else {
|
||||
SecureLogger.log("⚠️ Invalid ACK format: \(content)", category: SecureLogger.session, level: .warning)
|
||||
SecureLogger.log("⚠️ Invalid ACK format: \(content)", category: .session, level: .warning)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5327,7 +5327,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
processedNostrAcks.insert(ackKey)
|
||||
|
||||
SecureLogger.log("📨 Received \(ackType) ACK for message \(messageId.prefix(16))... from \(senderPubkey.prefix(16))...",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
|
||||
// Verify the sender has a valid Noise key
|
||||
guard findNoiseKey(for: senderPubkey) != nil else {
|
||||
@@ -5346,12 +5346,12 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
case "READ":
|
||||
privateChats[chatPeerID]?[index].deliveryStatus = .read(by: "recipient", at: Date())
|
||||
default:
|
||||
SecureLogger.log("⚠️ Unknown ACK type: \(ackType)", category: SecureLogger.session, level: .warning)
|
||||
SecureLogger.log("⚠️ Unknown ACK type: \(ackType)", category: .session, level: .warning)
|
||||
}
|
||||
|
||||
messageFound = true
|
||||
SecureLogger.log("✅ Updated message \(messageId.prefix(16))... status to \(ackType) in chat \(chatPeerID.prefix(16))...",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
// Don't break - continue to update in all chats where this message exists
|
||||
}
|
||||
}
|
||||
@@ -5360,7 +5360,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
objectWillChange.send()
|
||||
} else {
|
||||
SecureLogger.log("⚠️ Could not find message \(messageId) to update status from ACK",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5387,7 +5387,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
if parts.count > 1 {
|
||||
nostrPubkey = String(parts[1])
|
||||
SecureLogger.log("📝 Received Nostr npub in favorite notification: \(nostrPubkey ?? "none")",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
|
||||
// Get the noise public key for this peer
|
||||
@@ -5406,7 +5406,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
|
||||
guard let finalNoiseKey = noiseKey else {
|
||||
SecureLogger.log("⚠️ Cannot get Noise key for peer \(peerID)",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5421,7 +5421,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// If they favorited us and provided their Nostr key, ensure it's stored
|
||||
if isFavorite && nostrPubkey != nil {
|
||||
SecureLogger.log("💾 Storing Nostr key association for \(senderNickname): \(nostrPubkey!.prefix(16))...",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
|
||||
// Show system message
|
||||
@@ -5533,7 +5533,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
}
|
||||
|
||||
SecureLogger.log("📬 Stored Nostr message from unknown sender \(finalSenderNickname) in temporary peer \(tempPeerID)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
|
||||
@MainActor
|
||||
@@ -5546,7 +5546,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Try to convert hex to npub
|
||||
guard let pubkeyData = Data(hexString: nostrPubkey) else {
|
||||
SecureLogger.log("⚠️ Invalid hex public key format: \(nostrPubkey.prefix(16))...",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5554,7 +5554,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
npubToMatch = try Bech32.encode(hrp: "npub", data: pubkeyData)
|
||||
} catch {
|
||||
SecureLogger.log("⚠️ Failed to convert hex to npub: \(error)",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -5565,21 +5565,21 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Compare npub format
|
||||
if storedNostrKey == npubToMatch {
|
||||
// SecureLogger.log("✅ Found Noise key for Nostr sender (npub match)",
|
||||
// category: SecureLogger.session, level: .debug)
|
||||
// category: .session, level: .debug)
|
||||
return noiseKey
|
||||
}
|
||||
|
||||
// Also try hex comparison if stored value is hex
|
||||
if !storedNostrKey.hasPrefix("npub") && storedNostrKey == nostrPubkey {
|
||||
SecureLogger.log("✅ Found Noise key for Nostr sender (hex match)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
return noiseKey
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SecureLogger.log("⚠️ No matching Noise key found for Nostr pubkey: \(nostrPubkey.prefix(16))... (tried npub: \(npubToMatch.prefix(16))...)",
|
||||
category: SecureLogger.session, level: .debug)
|
||||
category: .session, level: .debug)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5607,13 +5607,13 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
// Try mesh first for connected peers
|
||||
if meshService.isPeerConnected(peerID) {
|
||||
messageRouter.sendFavoriteNotification(to: peerID, isFavorite: isFavorite)
|
||||
SecureLogger.log("📤 Sent favorite notification via BLE to \(peerID)", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("📤 Sent favorite notification via BLE to \(peerID)", category: .session, level: .debug)
|
||||
} else if let key = noiseKey {
|
||||
// Send via Nostr for offline peers (using router)
|
||||
let recipientPeerID = key.hexEncodedString()
|
||||
messageRouter.sendFavoriteNotification(to: recipientPeerID, isFavorite: isFavorite)
|
||||
} else {
|
||||
SecureLogger.log("⚠️ Cannot send favorite notification - peer not connected and no Nostr pubkey", category: SecureLogger.session, level: .warning)
|
||||
SecureLogger.log("⚠️ Cannot send favorite notification - peer not connected and no Nostr pubkey", category: .session, level: .warning)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5704,11 +5704,11 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
} else {
|
||||
// Keep old messages in original location but don't show in UI
|
||||
SecureLogger.log("📦 Partially migrating \(recentMessages.count) of \(messages.count) messages from \(oldPeerID)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
|
||||
SecureLogger.log("📦 Migrating \(recentMessages.count) recent messages from old peer ID \(oldPeerID) to \(peerID) (fingerprint match)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
} else if currentFingerprint == nil || oldFingerprint == nil {
|
||||
// Check if this chat contains messages with this sender by nickname
|
||||
let isRelevantChat = recentMessages.contains { msg in
|
||||
@@ -5725,7 +5725,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
}
|
||||
|
||||
SecureLogger.log("📦 Migrating \(recentMessages.count) recent messages from old peer ID \(oldPeerID) to \(peerID) (nickname match)",
|
||||
category: SecureLogger.session, level: .warning)
|
||||
category: .session, level: .warning)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5765,7 +5765,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
if needsSelectedUpdate {
|
||||
selectedPrivateChatPeer = peerID
|
||||
SecureLogger.log("📱 Updated selectedPrivateChatPeer from old ID to \(peerID) during migration",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5774,11 +5774,11 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
/// Handle incoming private message
|
||||
@MainActor
|
||||
private func handlePrivateMessage(_ message: BitchatMessage) {
|
||||
SecureLogger.log("📥 handlePrivateMessage called for message from \(message.sender)", category: SecureLogger.session, level: .debug)
|
||||
SecureLogger.log("📥 handlePrivateMessage called for message from \(message.sender)", category: .session, level: .debug)
|
||||
let senderPeerID = message.senderPeerID ?? getPeerIDForNickname(message.sender)
|
||||
|
||||
guard let peerID = senderPeerID else {
|
||||
SecureLogger.log("⚠️ Could not get peer ID for sender \(message.sender)", category: SecureLogger.session, level: .warning)
|
||||
SecureLogger.log("⚠️ Could not get peer ID for sender \(message.sender)", category: .session, level: .warning)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5819,7 +5819,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
||||
privateChats.removeValue(forKey: stableKeyHex)
|
||||
|
||||
SecureLogger.log("📥 Consolidated \(nostrMessages.count) Nostr messages from stable key to ephemeral peer \(peerID)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6087,7 +6087,7 @@ private func checkForMentions(_ message: BitchatMessage) {
|
||||
|
||||
if isMentioned && message.sender != nickname {
|
||||
SecureLogger.log("🔔 Mention from \(message.sender)",
|
||||
category: SecureLogger.session, level: .info)
|
||||
category: .session, level: .info)
|
||||
NotificationService.shared.sendMentionNotification(from: message.sender, message: message.content)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user