mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Dedupe incoming messags
// FREEBIE
This commit is contained in:
parent
d6e1e81a8a
commit
975726e022
12 changed files with 260 additions and 12 deletions
|
@ -1,4 +1,6 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSYapDatabaseObject.h"
|
||||
#import <Mantle/MTLJSONAdapter.h>
|
||||
|
@ -22,6 +24,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
*/
|
||||
+ (void)replaceAll:(NSArray<OWSDevice *> *)devices;
|
||||
|
||||
/**
|
||||
* The id of the device currently running this application
|
||||
*/
|
||||
+ (uint32_t)currentDeviceId;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param transaction
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSDevice.h"
|
||||
#import "NSDate+millisecondTimeStamp.h"
|
||||
|
@ -10,7 +12,7 @@
|
|||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
static MTLValueTransformer *_millisecondTimestampToDateTransformer;
|
||||
static int const OWSDevicePrimaryDeviceId = 1;
|
||||
static uint32_t const OWSDevicePrimaryDeviceId = 1;
|
||||
|
||||
@interface OWSDevice ()
|
||||
|
||||
|
@ -108,6 +110,13 @@ static int const OWSDevicePrimaryDeviceId = 1;
|
|||
return _millisecondTimestampToDateTransformer;
|
||||
}
|
||||
|
||||
+ (uint32_t)currentDeviceId
|
||||
{
|
||||
// Someday it may be possible to have a non-primary iOS device, but for now
|
||||
// any iOS device must be the primary device.
|
||||
return OWSDevicePrimaryDeviceId;
|
||||
}
|
||||
|
||||
- (BOOL)isPrimaryDevice
|
||||
{
|
||||
return self.deviceId == OWSDevicePrimaryDeviceId;
|
||||
|
|
|
@ -23,6 +23,8 @@ extern NSString *const TSIncomingMessageWasReadOnThisDeviceNotification;
|
|||
* Thread to which the message belongs
|
||||
* @param authorId
|
||||
* Signal ID (i.e. e164) of the user who sent the message
|
||||
* @param sourceDeviceId
|
||||
* Numeric ID of the device used to send the message. Used to detect duplicate messages.
|
||||
* @param body
|
||||
* Body of the message
|
||||
*
|
||||
|
@ -31,6 +33,7 @@ extern NSString *const TSIncomingMessageWasReadOnThisDeviceNotification;
|
|||
- (instancetype)initWithTimestamp:(uint64_t)timestamp
|
||||
inThread:(TSThread *)thread
|
||||
authorId:(NSString *)authorId
|
||||
sourceDeviceId:(uint32_t)sourceDeviceId
|
||||
messageBody:(nullable NSString *)body;
|
||||
|
||||
/**
|
||||
|
@ -42,6 +45,8 @@ extern NSString *const TSIncomingMessageWasReadOnThisDeviceNotification;
|
|||
* Thread to which the message belongs
|
||||
* @param authorId
|
||||
* Signal ID (i.e. e164) of the user who sent the message
|
||||
* @param sourceDeviceId
|
||||
* Numeric ID of the device used to send the message. Used to detect duplicate messages.
|
||||
* @param body
|
||||
* Body of the message
|
||||
* @param attachmentIds
|
||||
|
@ -52,6 +57,7 @@ extern NSString *const TSIncomingMessageWasReadOnThisDeviceNotification;
|
|||
- (instancetype)initWithTimestamp:(uint64_t)timestamp
|
||||
inThread:(TSThread *)thread
|
||||
authorId:(NSString *)authorId
|
||||
sourceDeviceId:(uint32_t)sourceDeviceId
|
||||
messageBody:(nullable NSString *)body
|
||||
attachmentIds:(NSArray<NSString *> *)attachmentIds;
|
||||
|
||||
|
@ -64,6 +70,8 @@ extern NSString *const TSIncomingMessageWasReadOnThisDeviceNotification;
|
|||
* Thread to which the message belongs
|
||||
* @param authorId
|
||||
* Signal ID (i.e. e164) of the user who sent the message
|
||||
* @param sourceDeviceId
|
||||
* Numeric ID of the device used to send the message. Used to detect duplicate messages.
|
||||
* @param body
|
||||
* Body of the message
|
||||
* @param attachmentIds
|
||||
|
@ -76,6 +84,7 @@ extern NSString *const TSIncomingMessageWasReadOnThisDeviceNotification;
|
|||
- (instancetype)initWithTimestamp:(uint64_t)timestamp
|
||||
inThread:(TSThread *)thread
|
||||
authorId:(NSString *)authorId
|
||||
sourceDeviceId:(uint32_t)sourceDeviceId
|
||||
messageBody:(nullable NSString *)body
|
||||
attachmentIds:(NSArray<NSString *> *)attachmentIds
|
||||
expiresInSeconds:(uint32_t)expiresInSeconds NS_DESIGNATED_INITIALIZER;
|
||||
|
@ -120,6 +129,7 @@ extern NSString *const TSIncomingMessageWasReadOnThisDeviceNotification;
|
|||
+ (nullable instancetype)findMessageWithAuthorId:(NSString *)authorId timestamp:(uint64_t)timestamp;
|
||||
|
||||
@property (nonatomic, readonly) NSString *authorId;
|
||||
@property (nonatomic, readonly) UInt32 sourceDeviceId;
|
||||
@property (nonatomic, readonly, getter=wasRead) BOOL read;
|
||||
|
||||
/*
|
||||
|
|
|
@ -22,20 +22,28 @@ NSString *const TSIncomingMessageWasReadOnThisDeviceNotification = @"TSIncomingM
|
|||
- (instancetype)initWithTimestamp:(uint64_t)timestamp
|
||||
inThread:(TSThread *)thread
|
||||
authorId:(NSString *)authorId
|
||||
sourceDeviceId:(uint32_t)sourceDeviceId
|
||||
messageBody:(nullable NSString *)body
|
||||
{
|
||||
return [self initWithTimestamp:timestamp inThread:thread authorId:authorId messageBody:body attachmentIds:@[]];
|
||||
return [self initWithTimestamp:timestamp
|
||||
inThread:thread
|
||||
authorId:authorId
|
||||
sourceDeviceId:sourceDeviceId
|
||||
messageBody:body
|
||||
attachmentIds:@[]];
|
||||
}
|
||||
|
||||
- (instancetype)initWithTimestamp:(uint64_t)timestamp
|
||||
inThread:(TSThread *)thread
|
||||
authorId:(NSString *)authorId
|
||||
sourceDeviceId:(uint32_t)sourceDeviceId
|
||||
messageBody:(nullable NSString *)body
|
||||
attachmentIds:(NSArray<NSString *> *)attachmentIds
|
||||
{
|
||||
return [self initWithTimestamp:timestamp
|
||||
inThread:thread
|
||||
authorId:authorId
|
||||
sourceDeviceId:sourceDeviceId
|
||||
messageBody:body
|
||||
attachmentIds:attachmentIds
|
||||
expiresInSeconds:0];
|
||||
|
@ -44,6 +52,7 @@ NSString *const TSIncomingMessageWasReadOnThisDeviceNotification = @"TSIncomingM
|
|||
- (instancetype)initWithTimestamp:(uint64_t)timestamp
|
||||
inThread:(TSThread *)thread
|
||||
authorId:(NSString *)authorId
|
||||
sourceDeviceId:(uint32_t)sourceDeviceId
|
||||
messageBody:(nullable NSString *)body
|
||||
attachmentIds:(NSArray<NSString *> *)attachmentIds
|
||||
expiresInSeconds:(uint32_t)expiresInSeconds
|
||||
|
@ -60,6 +69,7 @@ NSString *const TSIncomingMessageWasReadOnThisDeviceNotification = @"TSIncomingM
|
|||
}
|
||||
|
||||
_authorId = authorId;
|
||||
_sourceDeviceId = sourceDeviceId;
|
||||
_read = NO;
|
||||
|
||||
OWSAssert(self.receivedAtDate);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#import "OWSMessageSender.h"
|
||||
#import "ContactsUpdater.h"
|
||||
#import "NSData+messagePadding.h"
|
||||
#import "OWSDevice.h"
|
||||
#import "OWSDisappearingMessagesJob.h"
|
||||
#import "OWSError.h"
|
||||
#import "OWSLegacyMessageServiceParams.h"
|
||||
|
@ -622,6 +623,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
|
|||
[[TSIncomingMessage alloc] initWithTimestamp:(outgoingMessage.timestamp + 1)
|
||||
inThread:cThread
|
||||
authorId:[cThread contactIdentifier]
|
||||
sourceDeviceId:[OWSDevice currentDeviceId]
|
||||
messageBody:outgoingMessage.body
|
||||
attachmentIds:outgoingMessage.attachmentIds
|
||||
expiresInSeconds:outgoingMessage.expiresInSeconds];
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#import "OWSDisappearingMessagesConfiguration.h"
|
||||
#import "OWSDisappearingMessagesJob.h"
|
||||
#import "OWSError.h"
|
||||
#import "OWSIncomingMessageFinder.h"
|
||||
#import "OWSIncomingSentMessageTranscript.h"
|
||||
#import "OWSMessageSender.h"
|
||||
#import "OWSReadReceiptsProcessor.h"
|
||||
|
@ -46,6 +47,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
@property (nonatomic, readonly) TSStorageManager *storageManager;
|
||||
@property (nonatomic, readonly) OWSMessageSender *messageSender;
|
||||
@property (nonatomic, readonly) OWSDisappearingMessagesJob *disappearingMessagesJob;
|
||||
@property (nonatomic, readonly) OWSIncomingMessageFinder *incomingMessageFinder;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -102,6 +104,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
|
||||
_dbConnection = storageManager.newDatabaseConnection;
|
||||
_disappearingMessagesJob = [[OWSDisappearingMessagesJob alloc] initWithStorageManager:storageManager];
|
||||
_incomingMessageFinder = [[OWSIncomingMessageFinder alloc] initWithDatabase:storageManager.database];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -281,6 +284,15 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
- (void)handleEnvelope:(OWSSignalServiceProtosEnvelope *)envelope plaintextData:(NSData *)plaintextData
|
||||
{
|
||||
OWSAssert([NSThread isMainThread]);
|
||||
|
||||
BOOL duplicateEnvelope = [self.incomingMessageFinder existsMessageWithTimestamp:envelope.timestamp
|
||||
sourceId:envelope.source
|
||||
sourceDeviceId:envelope.sourceDevice];
|
||||
if (duplicateEnvelope) {
|
||||
DDLogInfo(@"%@ Ignoring previously received envelope with timestamp: %llu", self.tag, envelope.timestamp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (envelope.hasContent) {
|
||||
OWSSignalServiceProtosContent *content = [OWSSignalServiceProtosContent parseFromData:plaintextData];
|
||||
if (content.hasSyncMessage) {
|
||||
|
@ -290,7 +302,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
} else if (content.hasCallMessage) {
|
||||
[self handleIncomingEnvelope:envelope withCallMessage:content.callMessage];
|
||||
} else {
|
||||
DDLogWarn(@"%@ Ignoring envelope.Content with no known payload", self.tag);
|
||||
DDLogWarn(@"%@ Ignoring envelope. Content with no known payload", self.tag);
|
||||
}
|
||||
} else if (envelope.hasLegacyMessage) { // DEPRECATED - Remove after all clients have been upgraded.
|
||||
OWSSignalServiceProtosDataMessage *dataMessage =
|
||||
|
@ -611,6 +623,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timestamp
|
||||
inThread:gThread
|
||||
authorId:envelope.source
|
||||
sourceDeviceId:envelope.sourceDevice
|
||||
messageBody:body
|
||||
attachmentIds:attachmentIds
|
||||
expiresInSeconds:dataMessage.expireTimer];
|
||||
|
@ -632,6 +645,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:timestamp
|
||||
inThread:cThread
|
||||
authorId:[cThread contactIdentifier]
|
||||
sourceDeviceId:envelope.sourceDevice
|
||||
messageBody:body
|
||||
attachmentIds:attachmentIds
|
||||
expiresInSeconds:dataMessage.expireTimer];
|
||||
|
@ -658,12 +672,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
textMessage = [[TSIncomingMessage alloc] initWithTimestamp:textMessageTimestamp
|
||||
inThread:gThread
|
||||
authorId:envelope.source
|
||||
sourceDeviceId:envelope.sourceDevice
|
||||
messageBody:body];
|
||||
} else {
|
||||
TSContactThread *cThread = (TSContactThread *)thread;
|
||||
textMessage = [[TSIncomingMessage alloc] initWithTimestamp:textMessageTimestamp
|
||||
inThread:cThread
|
||||
authorId:[cThread contactIdentifier]
|
||||
sourceDeviceId:envelope.sourceDevice
|
||||
messageBody:body];
|
||||
}
|
||||
textMessage.expiresInSeconds = dataMessage.expireTimer;
|
||||
|
|
28
src/Storage/OWSIncomingMessageFinder.h
Normal file
28
src/Storage/OWSIncomingMessageFinder.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class YapDatabase;
|
||||
@class YapDatabaseReadTransaction;
|
||||
|
||||
@interface OWSIncomingMessageFinder : NSObject
|
||||
|
||||
- (instancetype)initWithDatabase:(YapDatabase *)database NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
/**
|
||||
* Must be called before using this finder.
|
||||
*/
|
||||
- (void)asyncRegisterExtension;
|
||||
|
||||
/**
|
||||
* Detects existance of a duplicate incoming message.
|
||||
*/
|
||||
- (BOOL)existsMessageWithTimestamp:(uint64_t)timestamp
|
||||
sourceId:(NSString *)sourceId
|
||||
sourceDeviceId:(uint32_t)sourceDeviceId;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
156
src/Storage/OWSIncomingMessageFinder.m
Normal file
156
src/Storage/OWSIncomingMessageFinder.m
Normal file
|
@ -0,0 +1,156 @@
|
|||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSIncomingMessageFinder.h"
|
||||
#import "TSIncomingMessage.h"
|
||||
#import "TSStorageManager.h"
|
||||
#import <YapDatabase/YapDatabase.h>
|
||||
#import <YapDatabase/YapDatabaseSecondaryIndex.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NSString *const OWSIncomingMessageFinderExtensionName = @"OWSIncomingMessageFinderExtensionName";
|
||||
|
||||
NSString *const OWSIncomingMessageFinderColumnTimestamp = @"OWSIncomingMessageFinderColumnTimestamp";
|
||||
NSString *const OWSIncomingMessageFinderColumnSourceId = @"OWSIncomingMessageFinderColumnSourceId";
|
||||
NSString *const OWSIncomingMessageFinderColumnSourceDeviceId = @"OWSIncomingMessageFinderColumnSourceDeviceId";
|
||||
|
||||
@interface OWSIncomingMessageFinder ()
|
||||
|
||||
@property (nonatomic, readonly) YapDatabase *database;
|
||||
@property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
|
||||
@property (nonatomic, readonly) BOOL isExtensionRegistered;
|
||||
|
||||
@end
|
||||
|
||||
@implementation OWSIncomingMessageFinder
|
||||
|
||||
@synthesize dbConnection = _dbConnection;
|
||||
|
||||
#pragma mark - init
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
OWSAssert([TSStorageManager sharedManager].database != nil);
|
||||
|
||||
return [self initWithDatabase:[TSStorageManager sharedManager].database];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDatabase:(YapDatabase *)database
|
||||
{
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_database = database;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - properties
|
||||
|
||||
- (YapDatabaseConnection *)dbConnection
|
||||
{
|
||||
@synchronized (self) {
|
||||
if (!_dbConnection) {
|
||||
_dbConnection = self.database.newConnection;
|
||||
}
|
||||
}
|
||||
return _dbConnection;
|
||||
}
|
||||
|
||||
#pragma mark - YAP integration
|
||||
|
||||
- (YapDatabaseSecondaryIndex *)indexExtension
|
||||
{
|
||||
YapDatabaseSecondaryIndexSetup *setup = [YapDatabaseSecondaryIndexSetup new];
|
||||
|
||||
[setup addColumn:OWSIncomingMessageFinderColumnTimestamp withType:YapDatabaseSecondaryIndexTypeInteger];
|
||||
[setup addColumn:OWSIncomingMessageFinderColumnSourceId withType:YapDatabaseSecondaryIndexTypeText];
|
||||
[setup addColumn:OWSIncomingMessageFinderColumnSourceDeviceId withType:YapDatabaseSecondaryIndexTypeInteger];
|
||||
|
||||
YapDatabaseSecondaryIndexWithObjectBlock block = ^(YapDatabaseReadTransaction *transaction,
|
||||
NSMutableDictionary *dict,
|
||||
NSString *collection,
|
||||
NSString *key,
|
||||
id object) {
|
||||
if ([object isKindOfClass:[TSIncomingMessage class]]) {
|
||||
TSIncomingMessage *incomingMessage = (TSIncomingMessage *)object;
|
||||
|
||||
[dict setObject:@(incomingMessage.timestamp) forKey:OWSIncomingMessageFinderColumnTimestamp];
|
||||
[dict setObject:incomingMessage.authorId forKey:OWSIncomingMessageFinderColumnSourceId];
|
||||
[dict setObject:@(incomingMessage.sourceDeviceId) forKey:OWSIncomingMessageFinderColumnSourceDeviceId];
|
||||
}
|
||||
};
|
||||
|
||||
YapDatabaseSecondaryIndexHandler *handler = [YapDatabaseSecondaryIndexHandler withObjectBlock:block];
|
||||
|
||||
return [[YapDatabaseSecondaryIndex alloc] initWithSetup:setup handler:handler];
|
||||
}
|
||||
|
||||
- (void)asyncRegisterExtension
|
||||
{
|
||||
DDLogInfo(@"%@ registering async.", self.tag);
|
||||
[self.database registerExtension:self.indexExtension withName:OWSIncomingMessageFinderExtensionName];
|
||||
}
|
||||
|
||||
- (void)registerExtension
|
||||
{
|
||||
OWSAssert(NO);
|
||||
DDLogError(@"%@ registering SYNC. We should prefer async when possible.", self.tag);
|
||||
[self.database registerExtension:self.indexExtension withName:OWSIncomingMessageFinderExtensionName];
|
||||
}
|
||||
|
||||
#pragma mark - instance methods
|
||||
|
||||
- (BOOL)existsMessageWithTimestamp:(uint64_t)timestamp
|
||||
sourceId:(NSString *)sourceId
|
||||
sourceDeviceId:(uint32_t)sourceDeviceId
|
||||
{
|
||||
if (![self.database registeredExtension:OWSIncomingMessageFinderExtensionName]) {
|
||||
DDLogError(@"%@ in %s but extension is not registered", self.tag, __PRETTY_FUNCTION__);
|
||||
OWSAssert(NO);
|
||||
|
||||
// we should be initializing this at startup rather than have an unexpectedly slow lazy setup at random.
|
||||
[self registerExtension];
|
||||
}
|
||||
|
||||
NSString *queryFormat = [NSString stringWithFormat:@"WHERE %@ = ? AND %@ = ? AND %@ = ?",
|
||||
OWSIncomingMessageFinderColumnTimestamp,
|
||||
OWSIncomingMessageFinderColumnSourceId,
|
||||
OWSIncomingMessageFinderColumnSourceDeviceId];
|
||||
// YapDatabaseQuery params must be objects
|
||||
YapDatabaseQuery *query = [YapDatabaseQuery queryWithFormat:queryFormat, @(timestamp), sourceId, @(sourceDeviceId)];
|
||||
|
||||
__block NSUInteger count;
|
||||
__block BOOL success;
|
||||
|
||||
[self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) {
|
||||
success = [[transaction ext:OWSIncomingMessageFinderExtensionName] getNumberOfRows:&count matchingQuery:query];
|
||||
}];
|
||||
|
||||
if (!success) {
|
||||
OWSAssert(NO);
|
||||
return NO;
|
||||
}
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
#pragma mark - Logging
|
||||
|
||||
+ (NSString *)tag
|
||||
{
|
||||
return [NSString stringWithFormat:@"[%@]", self.class];
|
||||
}
|
||||
|
||||
- (NSString *)tag
|
||||
{
|
||||
return self.class.tag;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -7,6 +7,7 @@
|
|||
#import "OWSAnalytics.h"
|
||||
#import "OWSDisappearingMessagesFinder.h"
|
||||
#import "OWSFailedMessagesJob.h"
|
||||
#import "OWSIncomingMessageFinder.h"
|
||||
#import "OWSReadReceipt.h"
|
||||
#import "SignalRecipient.h"
|
||||
#import "TSAttachmentStream.h"
|
||||
|
@ -197,6 +198,7 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass";
|
|||
[self.database registerExtension:[TSDatabaseSecondaryIndexes registerTimeStampIndex] withName:@"idx"];
|
||||
|
||||
// Register extensions which aren't essential for rendering threads async
|
||||
[[OWSIncomingMessageFinder new] asyncRegisterExtension];
|
||||
[TSDatabaseView asyncRegisterSecondaryDevicesDatabaseView];
|
||||
[OWSReadReceipt asyncRegisterIndexOnSenderIdAndTimestampWithDatabase:self.database];
|
||||
OWSDisappearingMessagesFinder *finder = [[OWSDisappearingMessagesFinder alloc] initWithStorageManager:self];
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TSAttachmentStream.h"
|
||||
#import "TSContactThread.h"
|
||||
|
@ -38,6 +40,7 @@
|
|||
TSIncomingMessage *incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:10000
|
||||
inThread:thread
|
||||
authorId:@"fake-author-id"
|
||||
sourceDeviceId:1
|
||||
messageBody:@"Incoming message body"];
|
||||
[incomingMessage save];
|
||||
|
||||
|
@ -74,6 +77,7 @@
|
|||
[[TSIncomingMessage alloc] initWithTimestamp:10000
|
||||
inThread:thread
|
||||
authorId:@"fake-author-id"
|
||||
sourceDeviceId:1
|
||||
messageBody:@"incoming message body"
|
||||
attachmentIds:[NSMutableArray arrayWithObject:incomingAttachment.uniqueId]];
|
||||
[incomingMessage save];
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
// Copyright © 2016 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "OWSOrphanedDataCleaner.h"
|
||||
#import "TSAttachmentStream.h"
|
||||
|
@ -45,6 +47,7 @@
|
|||
TSIncomingMessage *incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:1
|
||||
inThread:unsavedThread
|
||||
authorId:@"fake-author-id"
|
||||
sourceDeviceId:1
|
||||
messageBody:@"footch"];
|
||||
[incomingMessage save];
|
||||
XCTAssertEqual(1, [TSIncomingMessage numberOfKeysInCollection]);
|
||||
|
@ -61,6 +64,7 @@
|
|||
TSIncomingMessage *incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:1
|
||||
inThread:savedThread
|
||||
authorId:@"fake-author-id"
|
||||
sourceDeviceId:1
|
||||
messageBody:@"footch"];
|
||||
[incomingMessage save];
|
||||
XCTAssertEqual(1, [TSIncomingMessage numberOfKeysInCollection]);
|
||||
|
@ -99,6 +103,7 @@
|
|||
TSIncomingMessage *incomingMessage = [[TSIncomingMessage alloc] initWithTimestamp:1
|
||||
inThread:savedThread
|
||||
authorId:@"fake-author-id"
|
||||
sourceDeviceId:1
|
||||
messageBody:@"footch"
|
||||
attachmentIds:@[ attachmentStream.uniqueId ]];
|
||||
[incomingMessage save];
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
//
|
||||
// TSMessageStorageTests.m
|
||||
// TextSecureKit
|
||||
//
|
||||
// Created by Frederic Jacobs on 16/11/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
@ -102,6 +98,7 @@
|
|||
TSIncomingMessage *newMessage = [[TSIncomingMessage alloc] initWithTimestamp:timestamp
|
||||
inThread:self.thread
|
||||
authorId:[self.thread contactIdentifier]
|
||||
sourceDeviceId:1
|
||||
messageBody:body];
|
||||
[[TSStorageManager sharedManager].newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[newMessage saveWithTransaction:transaction];
|
||||
|
@ -126,6 +123,7 @@
|
|||
TSIncomingMessage *newMessage = [[TSIncomingMessage alloc] initWithTimestamp:i
|
||||
inThread:self.thread
|
||||
authorId:[self.thread contactIdentifier]
|
||||
sourceDeviceId:1
|
||||
messageBody:body];
|
||||
[messages addObject:newMessage];
|
||||
[newMessage save];
|
||||
|
@ -174,6 +172,7 @@
|
|||
TSIncomingMessage *newMessage = [[TSIncomingMessage alloc] initWithTimestamp:i
|
||||
inThread:thread
|
||||
authorId:@"Ed"
|
||||
sourceDeviceId:1
|
||||
messageBody:body];
|
||||
[newMessage save];
|
||||
[messages addObject:newMessage];
|
||||
|
|
Loading…
Reference in a new issue