Added code so the 'isUserMentioned' flag should support mentions within open groups

Added the new storage methods to MockStorage
Fixed an odd bug where the 'isBackgroundPoll' flag could have been coded incorrectly preventing the MessageReceiveJob from getting processed
This commit is contained in:
Morgan Pretty 2022-06-02 16:32:05 +10:00
parent 07d1d8acee
commit cf1f1b0e1a
8 changed files with 68 additions and 10 deletions

View File

@ -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
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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
}
}

View File

@ -215,4 +215,14 @@ class MockStorage: Mock<SessionMessagingKitStorageProtocol>, 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<String> {
return accept(args: [publicKey, transaction]) as! Set<String>
}
func setReceivedCalls(to receivedCalls: Set<String>, for publicKey: String, using transaction: Any) {
accept(args: [receivedCalls, publicKey, transaction])
}
}

View File

@ -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
}