session-ios/SessionMessagingKit/Open Groups/V2/OpenGroupManagerV2.swift

132 lines
7.2 KiB
Swift
Raw Normal View History

2021-03-24 02:37:33 +01:00
import PromiseKit
@objc(SNOpenGroupManagerV2)
public final class OpenGroupManagerV2 : NSObject {
private var pollers: [String:OpenGroupPollerV2] = [:]
private var isPolling = false
2021-04-07 05:18:24 +02:00
@objc public static var useV2OpenGroups = false
2021-03-24 02:37:33 +01:00
// MARK: Initialization
@objc public static let shared = OpenGroupManagerV2()
private override init() { }
// MARK: Polling
@objc public func startPolling() {
guard !isPolling else { return }
isPolling = true
let openGroups = Storage.shared.getAllV2OpenGroups()
for (_, openGroup) in openGroups {
if let poller = pollers[openGroup.id] { poller.stop() } // Should never occur
let poller = OpenGroupPollerV2(for: openGroup)
poller.startIfNeeded()
pollers[openGroup.id] = poller
}
}
@objc public func stopPolling() {
pollers.forEach { (_, openGroupPoller) in openGroupPoller.stop() }
pollers.removeAll()
}
// MARK: Adding & Removing
2021-03-25 04:17:49 +01:00
public func add(room: String, server: String, publicKey: String, using transaction: Any) -> Promise<Void> {
2021-03-24 02:37:33 +01:00
let storage = Storage.shared
2021-03-30 00:33:51 +02:00
// Clear any existing data if needed
2021-03-24 02:37:33 +01:00
storage.removeLastMessageServerID(for: room, on: server, using: transaction)
storage.removeLastDeletionServerID(for: room, on: server, using: transaction)
2021-03-26 03:28:40 +01:00
storage.removeAuthToken(for: room, on: server, using: transaction)
2021-03-30 00:33:51 +02:00
// Store the public key
2021-03-29 02:33:52 +02:00
storage.setOpenGroupPublicKey(for: server, to: publicKey, using: transaction)
2021-03-25 04:17:49 +01:00
let (promise, seal) = Promise<Void>.pending()
2021-03-26 03:28:40 +01:00
let transaction = transaction as! YapDatabaseReadWriteTransaction
2021-03-30 00:33:51 +02:00
transaction.addCompletionQueue(DispatchQueue.global(qos: .userInitiated)) {
// Get the group info
OpenGroupAPIV2.getInfo(for: room, on: server).done(on: DispatchQueue.global(qos: .userInitiated)) { info in
// Create the open group model and the thread
let openGroup = OpenGroupV2(server: server, room: room, name: info.name, publicKey: publicKey, imageID: info.imageID)
2021-03-26 03:28:40 +01:00
let groupID = LKGroupUtilities.getEncodedOpenGroupIDAsData(openGroup.id)
let model = TSGroupModel(title: openGroup.name, memberIds: [ getUserHexEncodedPublicKey() ], image: nil, groupId: groupID, groupType: .openGroup, adminIds: [])
2021-03-30 00:33:51 +02:00
// Store everything
2021-03-26 03:28:40 +01:00
storage.write(with: { transaction in
let transaction = transaction as! YapDatabaseReadWriteTransaction
let thread = TSGroupThread.getOrCreateThread(with: model, transaction: transaction)
thread.shouldThreadBeVisible = true
thread.save(with: transaction)
storage.setV2OpenGroup(openGroup, for: thread.uniqueId!, using: transaction)
}, completion: {
2021-03-30 00:33:51 +02:00
// Stop any existing poller if needed
2021-03-26 03:28:40 +01:00
if let poller = OpenGroupManagerV2.shared.pollers[openGroup.id] {
poller.stop()
OpenGroupManagerV2.shared.pollers[openGroup.id] = nil
}
2021-03-30 00:33:51 +02:00
// Start the poller
2021-03-26 03:28:40 +01:00
let poller = OpenGroupPollerV2(for: openGroup)
poller.startIfNeeded()
OpenGroupManagerV2.shared.pollers[openGroup.id] = poller
2021-03-30 00:33:51 +02:00
// Fetch the group image
OpenGroupAPIV2.getGroupImage(for: room, on: server).done(on: DispatchQueue.global(qos: .userInitiated)) { data in
storage.write { transaction in
// Update the thread
let transaction = transaction as! YapDatabaseReadWriteTransaction
let thread = TSGroupThread.getOrCreateThread(with: model, transaction: transaction)
thread.groupModel.groupImage = UIImage(data: data)
thread.save(with: transaction)
}
}.retainUntilComplete()
// Finish
2021-03-26 03:28:40 +01:00
seal.fulfill(())
})
2021-03-30 00:33:51 +02:00
}.catch(on: DispatchQueue.global(qos: .userInitiated)) { error in
2021-03-26 03:28:40 +01:00
seal.reject(error)
}
2021-03-25 04:17:49 +01:00
}
return promise
2021-03-24 02:37:33 +01:00
}
public func delete(_ openGroup: OpenGroupV2, associatedWith thread: TSThread, using transaction: YapDatabaseReadWriteTransaction) {
2021-03-30 00:33:51 +02:00
// Stop the poller if needed
2021-03-24 02:37:33 +01:00
if let poller = pollers[openGroup.id] {
poller.stop()
pollers[openGroup.id] = nil
}
2021-03-30 00:33:51 +02:00
// Remove all data
2021-03-24 02:37:33 +01:00
var messageIDs: Set<String> = []
var messageTimestamps: Set<UInt64> = []
thread.enumerateInteractions(with: transaction) { interaction, _ in
messageIDs.insert(interaction.uniqueId!)
messageTimestamps.insert(interaction.timestamp)
}
SNMessagingKitConfiguration.shared.storage.updateMessageIDCollectionByPruningMessagesWithIDs(messageIDs, using: transaction)
Storage.shared.removeReceivedMessageTimestamps(messageTimestamps, using: transaction)
Storage.shared.removeLastMessageServerID(for: openGroup.room, on: openGroup.server, using: transaction)
Storage.shared.removeLastDeletionServerID(for: openGroup.room, on: openGroup.server, using: transaction)
let _ = OpenGroupAPIV2.deleteAuthToken(for: openGroup.room, on: openGroup.server)
Storage.shared.removeOpenGroupPublicKey(for: openGroup.server, using: transaction)
thread.removeAllThreadInteractions(with: transaction)
thread.remove(with: transaction)
Storage.shared.removeV2OpenGroup(for: thread.uniqueId!, using: transaction)
}
// MARK: Convenience
public static func parseV2OpenGroup(from string: String) -> (room: String, server: String, publicKey: String)? {
guard let url = URL(string: string), let host = url.host ?? given(string.split(separator: "/").first, { String($0) }), let query = url.query else { return nil }
// Inputs that should work:
// https://sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c
// http://sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c
// sessionopengroup.co/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c (does NOT go to HTTPS)
// https://143.198.213.225:443/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c
// 143.198.213.255:80/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c
let useTLS = (url.scheme == "https")
let room = String(url.path.dropFirst()) // Drop the leading slash
let queryParts = query.split(separator: "=")
guard !room.isEmpty && !room.contains("/"), queryParts.count == 2, queryParts[0] == "public_key" else { return nil }
let publicKey = String(queryParts[1])
guard publicKey.count == 64 && Hex.isValid(publicKey) else { return nil }
var server = (useTLS ? "https://" : "http://") + host
if let port = url.port { server += ":\(port)" }
return (room: room, server: server, publicKey: publicKey)
}
2021-03-24 02:37:33 +01:00
}