diff --git a/Session/Notifications/AppNotifications.swift b/Session/Notifications/AppNotifications.swift index a39574cce..0698b0118 100644 --- a/Session/Notifications/AppNotifications.swift +++ b/Session/Notifications/AppNotifications.swift @@ -197,7 +197,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { // Don't fire the notification if the current user isn't mentioned // and isOnlyNotifyingForMentions is on. - if let groupThread = thread as? TSGroupThread, groupThread.isOnlyNotifyingForMentions && !incomingMessage.isUserMentioned { + if let groupThread = thread as? TSGroupThread, groupThread.isOnlyNotifyingForMentions && !incomingMessage.isUserMentioned(with: transaction) { return } diff --git a/SessionMessagingKit/Database/TSDatabaseView.m b/SessionMessagingKit/Database/TSDatabaseView.m index ec47b53b7..7f78ac4e0 100644 --- a/SessionMessagingKit/Database/TSDatabaseView.m +++ b/SessionMessagingKit/Database/TSDatabaseView.m @@ -140,7 +140,7 @@ NSString *const TSLazyRestoreAttachmentsGroup = @"TSLazyRestoreAttachmentsGroup" YapDatabaseReadTransaction *transaction, NSString *collection, NSString *key, id object) { if ([object isKindOfClass:[TSIncomingMessage class]]) { TSIncomingMessage *message = (TSIncomingMessage *)object; - if (!message.wasRead && message.isUserMentioned) { + if (!message.wasRead && [message isUserMentionedWithTransaction: transaction]) { return message.uniqueThreadId; } } diff --git a/SessionMessagingKit/Jobs/MessageReceiveJob.swift b/SessionMessagingKit/Jobs/MessageReceiveJob.swift index 16827b0de..6b3944b98 100644 --- a/SessionMessagingKit/Jobs/MessageReceiveJob.swift +++ b/SessionMessagingKit/Jobs/MessageReceiveJob.swift @@ -31,13 +31,12 @@ public final class MessageReceiveJob : NSObject, Job, NSCoding { // NSObject/NSC // MARK: Coding public init?(coder: NSCoder) { guard let data = coder.decodeObject(forKey: "data") as! Data?, - let id = coder.decodeObject(forKey: "id") as! String?, - let isBackgroundPoll = coder.decodeObject(forKey: "isBackgroundPoll") as! Bool? else { return nil } + let id = coder.decodeObject(forKey: "id") as! String? else { return nil } self.data = data self.serverHash = coder.decodeObject(forKey: "serverHash") as! String? self.openGroupMessageServerID = coder.decodeObject(forKey: "openGroupMessageServerID") as! UInt64? self.openGroupID = coder.decodeObject(forKey: "openGroupID") as! String? - self.isBackgroundPoll = isBackgroundPoll + self.isBackgroundPoll = ((coder.decodeObject(forKey: "isBackgroundPoll") as? Bool) ?? false) self.id = id self.failureCount = coder.decodeObject(forKey: "failureCount") as! UInt? ?? 0 } diff --git a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.h b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.h index c965ff51b..a1aef0933 100644 --- a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.h +++ b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.h @@ -14,8 +14,6 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) BOOL wasReceivedByUD; -@property (nonatomic, readonly) BOOL isUserMentioned; - @property (nonatomic, readonly, nullable) NSString *notificationIdentifier; - (instancetype)initMessageWithTimestamp:(uint64_t)timestamp @@ -91,6 +89,8 @@ NS_ASSUME_NONNULL_BEGIN - (void)setNotificationIdentifier:(NSString * _Nullable)notificationIdentifier transaction:(YapDatabaseReadWriteTransaction *)transaction; +- (BOOL)isUserMentionedWithTransaction:(YapDatabaseReadTransaction *)transaction; + @end NS_ASSUME_NONNULL_END diff --git a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m index a6578df0c..25ece9ca0 100644 --- a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m +++ b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m @@ -121,10 +121,42 @@ NS_ASSUME_NONNULL_BEGIN return self.isExpiringMessage; } -- (BOOL)isUserMentioned +- (BOOL)isUserMentionedWithTransaction:(YapDatabaseReadTransaction *)transaction { NSString *userPublicKey = [SNGeneralUtilities getUserPublicKey]; - return (self.body != nil && [self.body containsString:[NSString stringWithFormat:@"@%@", userPublicKey]]) || (self.quotedMessage != nil && [self.quotedMessage.authorId isEqualToString:userPublicKey]); + NSArray *publicKeysToCheck = @[userPublicKey]; + TSThread *thread = [self threadWithTransaction:transaction]; + + if (thread != nil) { + BOOL isOpenGroupThread = (thread.isGroupThread && ((TSGroupThread *)thread).isOpenGroup); + + if (isOpenGroupThread) { + SNOpenGroupV2 *openGroup = [[LKStorage shared] getOpenGroupForThreadID:self.uniqueThreadId]; + + if (openGroup != nil) { + NSString *openGroupPublicKey = [SNBlindingUtils userBlindedIdFor:openGroup.publicKey]; + + if (openGroupPublicKey != nil) { + publicKeysToCheck = [publicKeysToCheck arrayByAddingObject:openGroupPublicKey]; + } + } + } + } + + BOOL userMentioned = false; + + for (NSString *publicKey in publicKeysToCheck) { + userMentioned = ( + (self.body != nil && [self.body containsString:[NSString stringWithFormat:@"@%@", publicKey]]) || + (self.quotedMessage != nil && [self.quotedMessage.authorId isEqualToString:publicKey]) + ); + + if (userMentioned == true) { + break; + } + } + + return userMentioned; } - (void)setNotificationIdentifier:(NSString * _Nullable)notificationIdentifier transaction:(nonnull YapDatabaseReadWriteTransaction *)transaction diff --git a/SessionMessagingKit/Utilities/Sodium+Utilities.swift b/SessionMessagingKit/Utilities/Sodium+Utilities.swift index feddd0df4..de0ea0ac0 100644 --- a/SessionMessagingKit/Utilities/Sodium+Utilities.swift +++ b/SessionMessagingKit/Utilities/Sodium+Utilities.swift @@ -311,3 +311,20 @@ extension AeadXChaCha20Poly1305IetfType { return authenticatedCipherText } } + +// MARK: - Objective-C Support + +@objc public class SNBlindingUtils: NSObject { + @objc public static func userBlindedId(for openGroupPublicKey: String) -> String? { + let sodium: Sodium = Sodium() + + guard let userEd25519KeyPair = Storage.shared.getUserED25519KeyPair() else { + return nil + } + guard let blindedKeyPair = sodium.blindedKeyPair(serverPublicKey: openGroupPublicKey, edKeyPair: userEd25519KeyPair, genericHash: sodium.genericHash) else { + return nil + } + + return SessionId(.blinded, publicKey: blindedKeyPair.publicKey).hexString + } +} diff --git a/SessionMessagingKitTests/_TestUtilities/MockStorage.swift b/SessionMessagingKitTests/_TestUtilities/MockStorage.swift index de0bdcb19..4f6b46c0f 100644 --- a/SessionMessagingKitTests/_TestUtilities/MockStorage.swift +++ b/SessionMessagingKitTests/_TestUtilities/MockStorage.swift @@ -215,4 +215,14 @@ class MockStorage: Mock, SessionMessagingKit func persist(_ stream: TSAttachmentStream, associatedWith tsIncomingMessageID: String, using transaction: Any) { accept(args: [stream, tsIncomingMessageID, transaction]) } + + // MARK: - Calls + + func getReceivedCalls(for publicKey: String, using transaction: Any) -> Set { + return accept(args: [publicKey, transaction]) as! Set + } + + func setReceivedCalls(to receivedCalls: Set, for publicKey: String, using transaction: Any) { + accept(args: [receivedCalls, publicKey, transaction]) + } } diff --git a/SessionNotificationServiceExtension/NSENotificationPresenter.swift b/SessionNotificationServiceExtension/NSENotificationPresenter.swift index c19184a5d..081204ed5 100644 --- a/SessionNotificationServiceExtension/NSENotificationPresenter.swift +++ b/SessionNotificationServiceExtension/NSENotificationPresenter.swift @@ -46,7 +46,7 @@ public class NSENotificationPresenter: NSObject, NotificationsProtocol { var notificationTitle = senderName if let group = thread as? TSGroupThread { - if group.isOnlyNotifyingForMentions && !incomingMessage.isUserMentioned { + if group.isOnlyNotifyingForMentions && !incomingMessage.isUserMentioned(with: transaction) { // Ignore PNs if the group is set to only notify for mentions return }