Added dictionary for adding more servers.
Updated group chat poller to take an array of groups.
This commit is contained in:
parent
201127f6c2
commit
3930891a3d
|
@ -56,6 +56,13 @@ static NSString *const kInitialViewControllerIdentifier = @"UserInitialViewContr
|
|||
static NSString *const kURLSchemeSGNLKey = @"sgnl";
|
||||
static NSString *const kURLHostVerifyPrefix = @"verify";
|
||||
|
||||
static NSString *const kChatID = @"PublicChatID";
|
||||
static NSString *const kChatType = @"PublicChatType";
|
||||
static NSString *const kChatServerURL = @"PublicChatServerURL";
|
||||
static NSString *const kChatName = @"PublicChatName";
|
||||
static NSString *const kChatClosable = @"PublicChatClosable";
|
||||
static NSString *const kChatChannelID = @"PublicChatChannelID";
|
||||
|
||||
static NSTimeInterval launchStartedAt;
|
||||
|
||||
@interface AppDelegate () <UNUserNotificationCenterDelegate>
|
||||
|
@ -1485,28 +1492,93 @@ static NSTimeInterval launchStartedAt;
|
|||
|
||||
#pragma mark - Loki
|
||||
|
||||
- (NSArray *)publicChats
|
||||
{
|
||||
return @[
|
||||
@{
|
||||
kChatID: @"chat.lokinet.org.1",
|
||||
kChatType: @"publicChat",
|
||||
kChatServerURL: LKGroupChatAPI.publicChatServer,
|
||||
kChatName: NSLocalizedString(@"Loki Public Chat", @""),
|
||||
kChatClosable: @true,
|
||||
kChatChannelID: @(LKGroupChatAPI.publicChatID),
|
||||
},
|
||||
@{
|
||||
kChatID: @"rss://loki.network/feed/",
|
||||
kChatType: @"rss",
|
||||
kChatServerURL: @"https://loki.network/feed/",
|
||||
kChatName: NSLocalizedString(@"Loki.network News", @""),
|
||||
kChatClosable: @true,
|
||||
kChatChannelID: @1,
|
||||
},
|
||||
@{
|
||||
kChatID: @"rss://loki.network/category/messenger-updates/feed/",
|
||||
kChatType: @"rss",
|
||||
kChatServerURL: @"https://loki.network/category/messenger-updates/feed/",
|
||||
kChatName: NSLocalizedString(@"Messenger updates", @""),
|
||||
kChatClosable: @false,
|
||||
kChatChannelID: @1,
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
- (void)setupPublicChatGroupsIfNeeded
|
||||
{
|
||||
NSArray *chats = [self publicChats];
|
||||
NSString *ourPublicKey = OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey;
|
||||
for (NSDictionary *chat in chats) {
|
||||
NSString *chatID = [chat objectForKey:kChatID];
|
||||
BOOL closable = [[chat objectForKey:kChatClosable] boolValue];
|
||||
|
||||
NSString *setupKey = [@"setup-" stringByAppendingString:chatID];
|
||||
if (closable) {
|
||||
BOOL isChatSetup = [NSUserDefaults.standardUserDefaults boolForKey:setupKey];
|
||||
if (isChatSetup) { continue; }
|
||||
}
|
||||
|
||||
NSString *title = [chat objectForKey:kChatName];
|
||||
NSString *serverURL = [chat objectForKey:kChatServerURL];
|
||||
|
||||
// Create the group threads
|
||||
TSGroupModel *group = [[TSGroupModel alloc] initWithTitle:title memberIds:@[ ourPublicKey, serverURL ] image:nil groupId:[chatID dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
__block TSGroupThread *thread;
|
||||
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
thread = [TSGroupThread getOrCreateThreadWithGroupModel:group transaction:transaction];
|
||||
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
|
||||
NSCalendar *calendar = NSCalendar.currentCalendar;
|
||||
[calendar setTimeZone:timeZone];
|
||||
NSDateComponents *dateComponents = [NSDateComponents new];
|
||||
[dateComponents setYear:999];
|
||||
NSDate *date = [calendar dateByAddingComponents:dateComponents toDate:[NSDate new] options:0];
|
||||
[thread updateWithMutedUntilDate:date transaction:transaction];
|
||||
}];
|
||||
|
||||
[OWSProfileManager.sharedManager addThreadToProfileWhitelist:thread];
|
||||
if (closable) {
|
||||
[NSUserDefaults.standardUserDefaults setBool:YES forKey:setupKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setUpPublicChatIfNeeded
|
||||
{
|
||||
if (self.lokiPublicChatPoller != nil) { return; }
|
||||
self.lokiPublicChatPoller = [[LKGroupChatPoller alloc] initForGroup:(NSUInteger)LKGroupChatAPI.publicChatID onServer:LKGroupChatAPI.publicChatServer];
|
||||
BOOL isPublicChatSetUp = [NSUserDefaults.standardUserDefaults boolForKey:@"isPublicChatSetUp"];
|
||||
if (isPublicChatSetUp) { return; }
|
||||
NSString *title = NSLocalizedString(@"Loki Public Chat", @"");
|
||||
NSData *groupID = [[[LKGroupChatAPI.publicChatServer stringByAppendingString:@"."] stringByAppendingString:@(LKGroupChatAPI.publicChatID).stringValue] dataUsingEncoding:NSUTF8StringEncoding];
|
||||
TSGroupModel *group = [[TSGroupModel alloc] initWithTitle:title memberIds:@[ OWSIdentityManager.sharedManager.identityKeyPair.hexEncodedPublicKey, LKGroupChatAPI.publicChatServer ] image:nil groupId:groupID];
|
||||
__block TSGroupThread *thread;
|
||||
[OWSPrimaryStorage.dbReadWriteConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
thread = [TSGroupThread getOrCreateThreadWithGroupModel:group transaction:transaction];
|
||||
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:@"UTC"];
|
||||
NSCalendar *calendar = NSCalendar.currentCalendar;
|
||||
[calendar setTimeZone:timeZone];
|
||||
NSDateComponents *dateComponents = [NSDateComponents new];
|
||||
[dateComponents setYear:999];
|
||||
NSDate *date = [calendar dateByAddingComponents:dateComponents toDate:[NSDate new] options:0];
|
||||
[thread updateWithMutedUntilDate:date transaction:transaction];
|
||||
}];
|
||||
[OWSProfileManager.sharedManager addThreadToProfileWhitelist:thread];
|
||||
[NSUserDefaults.standardUserDefaults setBool:YES forKey:@"isPublicChatSetUp"];
|
||||
static dispatch_once_t groupChatSetup;
|
||||
dispatch_once(&groupChatSetup, ^{
|
||||
[self setupPublicChatGroupsIfNeeded];
|
||||
});
|
||||
[self setupPublicChatPollersIfNeeded];
|
||||
}
|
||||
|
||||
- (void)setupPublicChatPollersIfNeeded
|
||||
{
|
||||
if (self.lokiPublicChatPoller == nil) {
|
||||
NSArray *publicChats = [[self publicChats] filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary* bindings) {
|
||||
NSDictionary *group = (NSDictionary *)object;
|
||||
NSString *chatType = [group objectForKey:kChatType];
|
||||
return [chatType isEqualToString:@"publicChat"];
|
||||
}]];
|
||||
self.lokiPublicChatPoller = [[LKGroupChatPoller alloc] initWithGroups:publicChats];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startPublicChatPollingIfNeeded
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
|
||||
private let kChatID = "PublicChatID"
|
||||
private let kChatChannelID = "PublicChatChannelID"
|
||||
private let kChatName = "PublicChatName"
|
||||
private let kServerURL = "PublicChatServerURL"
|
||||
|
||||
@objc(LKGroupChatPoller)
|
||||
public final class LokiGroupChatPoller : NSObject {
|
||||
private let group: UInt
|
||||
private let server: String
|
||||
private let groups: [[String: Any]]
|
||||
private var pollForNewMessagesTimer: Timer? = nil
|
||||
private var pollForDeletedMessagesTimer: Timer? = nil
|
||||
private var hasStarted = false
|
||||
|
@ -10,10 +14,8 @@ public final class LokiGroupChatPoller : NSObject {
|
|||
private let pollForNewMessagesInterval: TimeInterval = 4
|
||||
private let pollForDeletedMessagesInterval: TimeInterval = 120
|
||||
|
||||
@objc(initForGroup:onServer:)
|
||||
public init(for group: UInt, on server: String) {
|
||||
self.group = group
|
||||
self.server = server
|
||||
@objc public init(groups: [[String: Any]]) {
|
||||
self.groups = groups
|
||||
super.init()
|
||||
}
|
||||
|
||||
|
@ -31,30 +33,44 @@ public final class LokiGroupChatPoller : NSObject {
|
|||
}
|
||||
|
||||
private func pollForNewMessages() {
|
||||
let group = self.group
|
||||
let server = self.server
|
||||
let _ = LokiGroupChatAPI.getMessages(for: group, on: server).map { messages in
|
||||
messages.reversed().map { message in
|
||||
let id = "\(server).\(group)".data(using: String.Encoding.utf8)!
|
||||
let x1 = SSKProtoGroupContext.builder(id: id, type: .deliver)
|
||||
x1.setName(NSLocalizedString("Loki Public Chat", comment: ""))
|
||||
let x2 = SSKProtoDataMessage.builder()
|
||||
x2.setTimestamp(message.timestamp)
|
||||
x2.setGroup(try! x1.build())
|
||||
x2.setBody(message.body)
|
||||
let x3 = SSKProtoContent.builder()
|
||||
x3.setDataMessage(try! x2.build())
|
||||
let x4 = SSKProtoEnvelope.builder(type: .ciphertext, timestamp: message.timestamp)
|
||||
let senderHexEncodedPublicKey = message.hexEncodedPublicKey
|
||||
let endIndex = senderHexEncodedPublicKey.endIndex
|
||||
let cutoffIndex = senderHexEncodedPublicKey.index(endIndex, offsetBy: -8)
|
||||
let senderDisplayName = "\(message.displayName) (...\(senderHexEncodedPublicKey[cutoffIndex..<endIndex]))"
|
||||
x4.setSource(senderDisplayName)
|
||||
x4.setSourceDevice(OWSDevicePrimaryDeviceId)
|
||||
x4.setContent(try! x3.build().serializedData())
|
||||
OWSPrimaryStorage.shared().dbReadWriteConnection.readWrite { transaction in
|
||||
SSKEnvironment.shared.messageManager.throws_processEnvelope(try! x4.build(), plaintextData: try! x3.build().serializedData(), wasReceivedByUD: false, transaction: transaction)
|
||||
}
|
||||
for group in groups {
|
||||
guard let channelID = group[kChatChannelID] as? UInt, let server = group[kServerURL] as? String else {
|
||||
Logger.info("[Loki] Failed to get channel id or server url from group: \(group)")
|
||||
return
|
||||
}
|
||||
|
||||
LokiGroupChatAPI.getMessages(for: channelID, on: server).map { [weak self] messages in
|
||||
self?.handleMessages(messages: messages, group: group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func handleMessages(messages: [LokiGroupMessage], group: [String: Any]) -> Void {
|
||||
guard let groupID = group[kChatID] as? String, let groupName = group[kChatName] as? String else {
|
||||
Logger.info("[Loki] Failed to handle messages for group: \(group))")
|
||||
return
|
||||
}
|
||||
|
||||
messages.reversed().forEach { message in
|
||||
let id = groupID.data(using: String.Encoding.utf8)!
|
||||
let x1 = SSKProtoGroupContext.builder(id: id, type: .deliver)
|
||||
x1.setName(groupName)
|
||||
let x2 = SSKProtoDataMessage.builder()
|
||||
x2.setTimestamp(message.timestamp)
|
||||
x2.setGroup(try! x1.build())
|
||||
x2.setBody(message.body)
|
||||
let x3 = SSKProtoContent.builder()
|
||||
x3.setDataMessage(try! x2.build())
|
||||
let x4 = SSKProtoEnvelope.builder(type: .ciphertext, timestamp: message.timestamp)
|
||||
let senderHexEncodedPublicKey = message.hexEncodedPublicKey
|
||||
let endIndex = senderHexEncodedPublicKey.endIndex
|
||||
let cutoffIndex = senderHexEncodedPublicKey.index(endIndex, offsetBy: -8)
|
||||
let senderDisplayName = "\(message.displayName) (...\(senderHexEncodedPublicKey[cutoffIndex..<endIndex]))"
|
||||
x4.setSource(senderDisplayName)
|
||||
x4.setSourceDevice(OWSDevicePrimaryDeviceId)
|
||||
x4.setContent(try! x3.build().serializedData())
|
||||
OWSPrimaryStorage.shared().dbReadWriteConnection.readWrite { transaction in
|
||||
SSKEnvironment.shared.messageManager.throws_processEnvelope(try! x4.build(), plaintextData: try! x3.build().serializedData(), wasReceivedByUD: false, transaction: transaction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue