Sync expiration timer updates

pull/356/head
nielsandriesse 3 years ago
parent 11c899bff1
commit 2d6bf235d7

@ -2,13 +2,20 @@ import SessionUtilitiesKit
@objc(SNExpirationTimerUpdate)
public final class ExpirationTimerUpdate : ControlMessage {
/// In the case of a sync message, the public key of the person the message was targeted at.
///
/// - Note: `nil` if this isn't a sync message.
public var syncTarget: String?
public var duration: UInt32?
public override var isSelfSendValid: Bool { true }
// MARK: Initialization
public override init() { super.init() }
internal init(duration: UInt32) {
internal init(syncTarget: String?, duration: UInt32) {
super.init()
self.syncTarget = syncTarget
self.duration = duration
}
@ -21,11 +28,13 @@ public final class ExpirationTimerUpdate : ControlMessage {
// MARK: Coding
public required init?(coder: NSCoder) {
super.init(coder: coder)
if let syncTarget = coder.decodeObject(forKey: "syncTarget") as! String? { self.syncTarget = syncTarget }
if let duration = coder.decodeObject(forKey: "durationSeconds") as! UInt32? { self.duration = duration }
}
public override func encode(with coder: NSCoder) {
super.encode(with: coder)
coder.encode(syncTarget, forKey: "syncTarget")
coder.encode(duration, forKey: "durationSeconds")
}
@ -34,8 +43,9 @@ public final class ExpirationTimerUpdate : ControlMessage {
guard let dataMessageProto = proto.dataMessage else { return nil }
let isExpirationTimerUpdate = (dataMessageProto.flags & UInt32(SNProtoDataMessage.SNProtoDataMessageFlags.expirationTimerUpdate.rawValue)) != 0
guard isExpirationTimerUpdate else { return nil }
let syncTarget = dataMessageProto.syncTarget
let duration = dataMessageProto.expireTimer
return ExpirationTimerUpdate(duration: duration)
return ExpirationTimerUpdate(syncTarget: syncTarget, duration: duration)
}
public override func toProto(using transaction: YapDatabaseReadWriteTransaction) -> SNProtoContent? {
@ -46,6 +56,7 @@ public final class ExpirationTimerUpdate : ControlMessage {
let dataMessageProto = SNProtoDataMessage.builder()
dataMessageProto.setFlags(UInt32(SNProtoDataMessage.SNProtoDataMessageFlags.expirationTimerUpdate.rawValue))
dataMessageProto.setExpireTimer(duration)
if let syncTarget = syncTarget { dataMessageProto.setSyncTarget(syncTarget) }
// Group context
do {
try setGroupContextIfNeeded(on: dataMessageProto, using: transaction)
@ -67,6 +78,7 @@ public final class ExpirationTimerUpdate : ControlMessage {
public override var description: String {
"""
ExpirationTimerUpdate(
syncTarget: \(syncTarget ?? "null")
duration: \(duration?.description ?? "null")
)
"""

@ -96,13 +96,13 @@ extension MessageReceiver {
private static func handleExpirationTimerUpdate(_ message: ExpirationTimerUpdate, using transaction: Any) {
if message.duration! > 0 {
setExpirationTimer(to: message.duration!, for: message.sender!, groupPublicKey: message.groupPublicKey, using: transaction)
setExpirationTimer(to: message.duration!, for: message.sender!, syncTarget: message.syncTarget, groupPublicKey: message.groupPublicKey, using: transaction)
} else {
disableExpirationTimer(for: message.sender!, groupPublicKey: message.groupPublicKey, using: transaction)
disableExpirationTimer(for: message.sender!, syncTarget: message.syncTarget, groupPublicKey: message.groupPublicKey, using: transaction)
}
}
public static func setExpirationTimer(to duration: UInt32, for senderPublicKey: String, groupPublicKey: String?, using transaction: Any) {
public static func setExpirationTimer(to duration: UInt32, for senderPublicKey: String, syncTarget: String?, groupPublicKey: String?, using transaction: Any) {
let transaction = transaction as! YapDatabaseReadWriteTransaction
var threadOrNil: TSThread?
if let groupPublicKey = groupPublicKey {
@ -110,7 +110,7 @@ extension MessageReceiver {
let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey)
threadOrNil = TSGroupThread.fetch(uniqueId: TSGroupThread.threadId(fromGroupId: groupID), transaction: transaction)
} else {
threadOrNil = TSContactThread.getWithContactId(senderPublicKey, transaction: transaction)
threadOrNil = TSContactThread.getWithContactId(syncTarget ?? senderPublicKey, transaction: transaction)
}
guard let thread = threadOrNil else { return }
let configuration = OWSDisappearingMessagesConfiguration(threadId: thread.uniqueId!, enabled: true, durationSeconds: duration)
@ -122,7 +122,7 @@ extension MessageReceiver {
SSKEnvironment.shared.disappearingMessagesJob.startIfNecessary()
}
public static func disableExpirationTimer(for senderPublicKey: String, groupPublicKey: String?, using transaction: Any) {
public static func disableExpirationTimer(for senderPublicKey: String, syncTarget: String?, groupPublicKey: String?, using transaction: Any) {
let transaction = transaction as! YapDatabaseReadWriteTransaction
var threadOrNil: TSThread?
if let groupPublicKey = groupPublicKey {
@ -130,7 +130,7 @@ extension MessageReceiver {
let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey)
threadOrNil = TSGroupThread.fetch(uniqueId: TSGroupThread.threadId(fromGroupId: groupID), transaction: transaction)
} else {
threadOrNil = TSContactThread.getWithContactId(senderPublicKey, transaction: transaction)
threadOrNil = TSContactThread.getWithContactId(syncTarget ?? senderPublicKey, transaction: transaction)
}
guard let thread = threadOrNil else { return }
let configuration = OWSDisappearingMessagesConfiguration(threadId: thread.uniqueId!, enabled: false, durationSeconds: 24 * 60 * 60)

@ -346,33 +346,36 @@ public final class MessageSender : NSObject {
public static func handleSuccessfulMessageSend(_ message: Message, to destination: Message.Destination, isSyncMessage: Bool = false, using transaction: Any) {
let storage = SNMessagingKitConfiguration.shared.storage
let transaction = transaction as! YapDatabaseReadWriteTransaction
guard let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) else { return }
// Ignore future self-sends
Storage.shared.addReceivedMessageTimestamp(message.sentTimestamp!, using: transaction)
// Track the open group server message ID
tsMessage.openGroupServerMessageID = message.openGroupServerMessageID ?? 0
tsMessage.save(with: transaction)
if let serverID = message.openGroupServerMessageID {
storage.setIDForMessage(withServerID: serverID, to: tsMessage.uniqueId!, using: transaction)
}
// Mark the message as sent
var recipients = [ message.recipient! ]
if case .closedGroup(_) = destination, let threadID = message.threadID, // threadID should always be set at this point
let thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction), thread.isClosedGroup {
recipients = thread.groupModel.groupMemberIds
}
recipients.forEach { recipient in
tsMessage.update(withSentRecipient: recipient, wasSentByUD: true, transaction: transaction)
// Get the visible message if possible
if let tsMessage = TSOutgoingMessage.find(withTimestamp: message.sentTimestamp!) {
// Track the open group server message ID
tsMessage.openGroupServerMessageID = message.openGroupServerMessageID ?? 0
tsMessage.save(with: transaction)
if let serverID = message.openGroupServerMessageID {
storage.setIDForMessage(withServerID: serverID, to: tsMessage.uniqueId!, using: transaction)
}
// Mark the message as sent
var recipients = [ message.recipient! ]
if case .closedGroup(_) = destination, let threadID = message.threadID, // threadID should always be set at this point
let thread = TSGroupThread.fetch(uniqueId: threadID, transaction: transaction), thread.isClosedGroup {
recipients = thread.groupModel.groupMemberIds
}
recipients.forEach { recipient in
tsMessage.update(withSentRecipient: recipient, wasSentByUD: true, transaction: transaction)
}
// Start the disappearing messages timer if needed
OWSDisappearingMessagesJob.shared().startAnyExpiration(for: tsMessage, expirationStartedAt: NSDate.millisecondTimestamp(), transaction: transaction)
}
// Start the disappearing messages timer if needed
OWSDisappearingMessagesJob.shared().startAnyExpiration(for: tsMessage, expirationStartedAt: NSDate.millisecondTimestamp(), transaction: transaction)
// Sync the message if:
// it's a visible message
// it's a visible message or an expiration timer update
// the destination was a contact
// we didn't sync it already
let userPublicKey = getUserHexEncodedPublicKey()
if case .contact(let publicKey) = destination, !isSyncMessage, let message = message as? VisibleMessage {
message.syncTarget = publicKey
if case .contact(let publicKey) = destination, !isSyncMessage {
if let message = message as? VisibleMessage { message.syncTarget = publicKey }
if let message = message as? ExpirationTimerUpdate { message.syncTarget = publicKey }
// FIXME: Make this a job
sendToSnodeDestination(.contact(publicKey: userPublicKey), message: message, using: transaction, isSyncMessage: true).retainUntilComplete()
}

Loading…
Cancel
Save