import Foundation import Postbox import SwiftSignalKit import TelegramApi import MtProtoKit public enum CreateSecretChatError { case generic } public func createSecretChat(account: Account, peerId: PeerId) -> Signal { return account.postbox.transaction { transaction -> Signal in if let peer = transaction.getPeer(peerId), let inputUser = apiInputUser(peer) { return validatedEncryptionConfig(postbox: account.postbox, network: account.network) |> mapError { _ -> CreateSecretChatError in return .generic } |> mapToSignal { config -> Signal in let aBytes = malloc(256)! let _ = SecRandomCopyBytes(nil, 256, aBytes.assumingMemoryBound(to: UInt8.self)) let a = MemoryBuffer(memory: aBytes, capacity: 256, length: 256, freeWhenDone: true) var gValue: Int32 = config.g.byteSwapped let g = Data(bytes: &gValue, count: 4) let p = config.p.makeData() let aData = a.makeData() let ga = MTExp(account.network.encryptionProvider, g, aData, p)! if !MTCheckIsSafeGAOrB(account.network.encryptionProvider, ga, p) { return .fail(.generic) } return account.network.request(Api.functions.messages.requestEncryption(userId: inputUser, randomId: Int32(bitPattern: arc4random()), gA: Buffer(data: ga))) |> mapError { _ -> CreateSecretChatError in return .generic } |> mapToSignal { result -> Signal in return account.postbox.transaction { transaction -> PeerId in updateSecretChat(encryptionProvider: account.network.encryptionProvider, accountPeerId: account.peerId, transaction: transaction, mediaBox: account.postbox.mediaBox, chat: result, requestData: SecretChatRequestData(g: config.g, p: config.p, a: a)) return result.peerId } |> mapError { _ -> CreateSecretChatError in return .generic } } } } else { return .fail(.generic) } } |> mapError { _ -> CreateSecretChatError in return .generic } |> switchToLatest }