Signal-iOS/SignalServiceKit/Messages/ProfileKeyMessage.swift
2026-01-28 12:50:04 -06:00

93 lines
2.9 KiB
Swift

//
// Copyright 2026 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
public import LibSignalClient
@objc(OWSProfileKeyMessage)
public final class ProfileKeyMessage: TransientOutgoingMessage {
let profileKey: ProfileKey?
public init(
thread: TSContactThread,
profileKey: ProfileKey,
tx: DBReadTransaction,
) {
self.profileKey = profileKey
super.init(
outgoingMessageWith: TSOutgoingMessageBuilder.outgoingMessageBuilder(thread: thread),
additionalRecipients: [],
explicitRecipients: [],
skippedRecipients: [],
transaction: tx,
)
}
override public class var supportsSecureCoding: Bool { true }
override public func encode(with coder: NSCoder) {
super.encode(with: coder)
if let profileKey {
coder.encode(profileKey.serialize(), forKey: "profileKey")
}
}
public required init?(coder: NSCoder) {
self.profileKey = (coder.decodeObject(of: NSData.self, forKey: "profileKey") as Data?).flatMap { try? ProfileKey(contents: $0) }
super.init(coder: coder)
}
override public var hash: Int {
var hasher = Hasher()
hasher.combine(super.hash)
hasher.combine(profileKey?.serialize())
return hasher.finalize()
}
override public func isEqual(_ object: Any?) -> Bool {
guard let object = object as? Self else { return false }
guard super.isEqual(object) else { return false }
guard self.profileKey?.serialize() == object.profileKey?.serialize() else { return false }
return true
}
override public func shouldSyncTranscript() -> Bool {
return false
}
override public func buildDataMessage(_ thread: TSThread, transaction: DBReadTransaction) -> SSKProtoDataMessage? {
let builder = self.dataMessageBuilder(with: thread, transaction: transaction)
guard let builder else {
owsFailDebug("could not build protobuf")
return nil
}
builder.setTimestamp(self.timestamp)
ProtoUtils.addLocalProfileKeyIfNecessary(
forThread: thread,
profileKeySnapshot: self.profileKey,
dataMessageBuilder: builder,
transaction: transaction,
)
builder.setFlags(UInt32(SSKProtoDataMessageFlags.profileKeyUpdate.rawValue))
let dataProto: SSKProtoDataMessage
do {
dataProto = try builder.build()
} catch {
owsFailDebug("could not build protobuf: \(error)")
return nil
}
if dataProto.profileKey == nil {
// If we couldn't include the profile key, drop it.
Logger.warn("Dropping profile key message without a profile key")
return nil
}
return dataProto
}
override public var contentHint: SealedSenderContentHint { .implicit }
}