From 2a0866ff3e382fce474c293b4d325a695844cde2 Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 28 Aug 2018 22:27:33 +0300 Subject: [PATCH] no message --- TelegramCore/Account.swift | 98 ++++++------ TelegramCore/AccountManager.swift | 143 +++++++++--------- TelegramCore/AccountState.swift | 9 +- TelegramCore/AccountStateManager.swift | 14 +- TelegramCore/Authorization.swift | 22 +-- TelegramCore/Fetch.swift | 20 ++- TelegramCore/FetchHttpResource.swift | 5 +- TelegramCore/FetchSecretFileResource.swift | 2 +- ...gedCloudChatRemoveMessagesOperations.swift | 42 +++-- TelegramCore/MultipartFetch.swift | 2 +- 10 files changed, 202 insertions(+), 155 deletions(-) diff --git a/TelegramCore/Account.swift b/TelegramCore/Account.swift index 412b33d9ef..bab9e9204a 100644 --- a/TelegramCore/Account.swift +++ b/TelegramCore/Account.swift @@ -51,18 +51,21 @@ public class AuthorizedAccountState: AccountState { } } + let isTestingEnvironment: Bool let masterDatacenterId: Int32 let peerId: PeerId let state: State? public required init(decoder: PostboxDecoder) { + self.isTestingEnvironment = decoder.decodeInt32ForKey("isTestingEnvironment", orElse: 0) != 0 self.masterDatacenterId = decoder.decodeInt32ForKey("masterDatacenterId", orElse: 0) self.peerId = PeerId(decoder.decodeInt64ForKey("peerId", orElse: 0)) self.state = decoder.decodeObjectForKey("state", decoder: { return State(decoder: $0) }) as? State } public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt32(self.isTestingEnvironment ? 1 : 0, forKey: "isTestingEnvironment") encoder.encodeInt32(self.masterDatacenterId, forKey: "masterDatacenterId") encoder.encodeInt64(self.peerId.toInt64(), forKey: "peerId") if let state = self.state { @@ -70,19 +73,20 @@ public class AuthorizedAccountState: AccountState { } } - public init(masterDatacenterId: Int32, peerId: PeerId, state: State?) { + public init(isTestingEnvironment: Bool, masterDatacenterId: Int32, peerId: PeerId, state: State?) { + self.isTestingEnvironment = isTestingEnvironment self.masterDatacenterId = masterDatacenterId self.peerId = peerId self.state = state } func changedState(_ state: State) -> AuthorizedAccountState { - return AuthorizedAccountState(masterDatacenterId: self.masterDatacenterId, peerId: self.peerId, state: state) + return AuthorizedAccountState(isTestingEnvironment: self.isTestingEnvironment, masterDatacenterId: self.masterDatacenterId, peerId: self.peerId, state: state) } public func equalsTo(_ other: AccountState) -> Bool { if let other = other as? AuthorizedAccountState { - return self.masterDatacenterId == other.masterDatacenterId && + return self.isTestingEnvironment == other.isTestingEnvironment && self.masterDatacenterId == other.masterDatacenterId && self.peerId == other.peerId && self.state == other.state } else { @@ -291,62 +295,64 @@ let telegramPostboxSeedConfiguration: SeedConfiguration = { return SeedConfiguration(initializeChatListWithHole: (topLevel: ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: Int32.max - 1)), groups: ChatListHole(index: MessageIndex(id: MessageId(peerId: PeerId(namespace: Namespaces.Peer.Empty, id: 0), namespace: Namespaces.Message.Cloud, id: 1), timestamp: 1))), initializeMessageNamespacesWithHoles: initializeMessageNamespacesWithHoles, existingMessageTags: MessageTags.all, messageTagsWithSummary: MessageTags.unseenPersonalMessage, existingGlobalMessageTags: GlobalMessageTags.all, peerNamespacesRequiringMessageTextIndex: [Namespaces.Peer.SecretChat]) }() -public func accountWithId(networkArguments: NetworkInitializationArguments, id: AccountRecordId, supplementary: Bool, rootPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal { +public func accountWithId(networkArguments: NetworkInitializationArguments, id: AccountRecordId, supplementary: Bool, rootPath: String, beginWithTestingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal { let _ = declaredEncodables let path = "\(rootPath)/\(accountRecordIdPathName(id))" let postbox = openPostbox(basePath: path + "/postbox", globalMessageIdsNamespace: Namespaces.Message.Cloud, seedConfiguration: telegramPostboxSeedConfiguration) - return postbox |> mapToSignal { result -> Signal in + return postbox + |> mapToSignal { result -> Signal in switch result { case .upgrading: return .single(.upgrading) case let .postbox(postbox): return postbox.stateView() - |> take(1) - |> mapToSignal { view -> Signal in - return postbox.transaction { transaction -> (LocalizationSettings?, ProxySettings?, NetworkSettings?) in - return (transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings, transaction.getPreferencesEntry(key: PreferencesKeys.proxySettings) as? ProxySettings, transaction.getPreferencesEntry(key: PreferencesKeys.networkSettings) as? NetworkSettings) - } |> mapToSignal { (localizationSettings, proxySettings, networkSettings) -> Signal in - let accountState = view.state - - let keychain = Keychain(get: { key in - return postbox.keychainEntryForKey(key) - }, set: { (key, data) in - postbox.setKeychainEntryForKey(key, value: data) - }, remove: { key in - postbox.removeKeychainEntryForKey(key) - }) - - if let accountState = accountState { - switch accountState { - case let unauthorizedState as UnauthorizedAccountState: - return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) - |> map { network -> AccountResult in - return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection)) - } - case let authorizedState as AuthorizedAccountState: - return postbox.transaction { transaction -> String? in - return (transaction.getPeer(authorizedState.peerId) as? TelegramUser)?.phone + |> take(1) + |> mapToSignal { view -> Signal in + return postbox.transaction { transaction -> (LocalizationSettings?, ProxySettings?, NetworkSettings?) in + return (transaction.getPreferencesEntry(key: PreferencesKeys.localizationSettings) as? LocalizationSettings, transaction.getPreferencesEntry(key: PreferencesKeys.proxySettings) as? ProxySettings, transaction.getPreferencesEntry(key: PreferencesKeys.networkSettings) as? NetworkSettings) + } + |> mapToSignal { (localizationSettings, proxySettings, networkSettings) -> Signal in + let accountState = view.state + + let keychain = Keychain(get: { key in + return postbox.keychainEntryForKey(key) + }, set: { (key, data) in + postbox.setKeychainEntryForKey(key, value: data) + }, remove: { key in + postbox.removeKeychainEntryForKey(key) + }) + + if let accountState = accountState { + switch accountState { + case let unauthorizedState as UnauthorizedAccountState: + return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(unauthorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: unauthorizedState.isTestingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) + |> map { network -> AccountResult in + return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: unauthorizedState.isTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection)) } - |> mapToSignal { phoneNumber in - return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: testingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: phoneNumber) - |> map { network -> AccountResult in - return .authorized(Account(id: id, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, peerId: authorizedState.peerId, auxiliaryMethods: auxiliaryMethods)) - } + case let authorizedState as AuthorizedAccountState: + return postbox.transaction { transaction -> String? in + return (transaction.getPeer(authorizedState.peerId) as? TelegramUser)?.phone + } + |> mapToSignal { phoneNumber in + return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: Int(authorizedState.masterDatacenterId), keychain: keychain, basePath: path, testingEnvironment: authorizedState.isTestingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: phoneNumber) + |> map { network -> AccountResult in + return .authorized(Account(id: id, basePath: path, testingEnvironment: authorizedState.isTestingEnvironment, postbox: postbox, network: network, peerId: authorizedState.peerId, auxiliaryMethods: auxiliaryMethods)) } - case _: - assertionFailure("Unexpected accountState \(accountState)") - } - } - - return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: testingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) - |> map { network -> AccountResult in - return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: testingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection)) + } + case _: + assertionFailure("Unexpected accountState \(accountState)") } } + + return initializedNetwork(arguments: networkArguments, supplementary: supplementary, datacenterId: 2, keychain: keychain, basePath: path, testingEnvironment: beginWithTestingEnvironment, languageCode: localizationSettings?.languageCode, proxySettings: proxySettings, networkSettings: networkSettings, phoneNumber: nil) + |> map { network -> AccountResult in + return .unauthorized(UnauthorizedAccount(networkArguments: networkArguments, id: id, rootPath: rootPath, basePath: path, testingEnvironment: beginWithTestingEnvironment, postbox: postbox, network: network, shouldKeepAutoConnection: shouldKeepAutoConnection)) + } } + } } } } @@ -735,10 +741,10 @@ public enum AccountNetworkState: Equatable { public final class AccountAuxiliaryMethods { public let updatePeerChatInputState: (PeerChatInterfaceState?, SynchronizeableChatInputState?) -> PeerChatInterfaceState? - public let fetchResource: (Account, MediaResource, Signal, MediaResourceFetchParameters?) -> Signal? + public let fetchResource: (Account, MediaResource, Signal, MediaResourceFetchParameters?) -> Signal? public let fetchResourceMediaReferenceHash: (MediaResource) -> Signal - public init(updatePeerChatInputState: @escaping (PeerChatInterfaceState?, SynchronizeableChatInputState?) -> PeerChatInterfaceState?, fetchResource: @escaping (Account, MediaResource, Signal, MediaResourceFetchParameters?) -> Signal?, fetchResourceMediaReferenceHash: @escaping (MediaResource) -> Signal) { + public init(updatePeerChatInputState: @escaping (PeerChatInterfaceState?, SynchronizeableChatInputState?) -> PeerChatInterfaceState?, fetchResource: @escaping (Account, MediaResource, Signal, MediaResourceFetchParameters?) -> Signal?, fetchResourceMediaReferenceHash: @escaping (MediaResource) -> Signal) { self.updatePeerChatInputState = updatePeerChatInputState self.fetchResource = fetchResource self.fetchResourceMediaReferenceHash = fetchResourceMediaReferenceHash @@ -1204,7 +1210,7 @@ public typealias FetchCachedResourceRepresentation = (_ account: Account, _ reso public typealias TransformOutgoingMessageMedia = (_ postbox: Postbox, _ network: Network, _ media: AnyMediaReference, _ userInteractive: Bool) -> Signal public func setupAccount(_ account: Account, fetchCachedResourceRepresentation: FetchCachedResourceRepresentation? = nil, transformOutgoingMessageMedia: TransformOutgoingMessageMedia? = nil) { - account.postbox.mediaBox.fetchResource = { [weak account] resource, ranges, parameters -> Signal in + account.postbox.mediaBox.fetchResource = { [weak account] resource, ranges, parameters -> Signal in if let strongAccount = account { if let result = fetchResource(account: strongAccount, resource: resource, ranges: ranges, parameters: parameters) { return result diff --git a/TelegramCore/AccountManager.swift b/TelegramCore/AccountManager.swift index 6ce5758100..e3456b67b0 100644 --- a/TelegramCore/AccountManager.swift +++ b/TelegramCore/AccountManager.swift @@ -69,60 +69,61 @@ public func temporaryAccount(manager: AccountManager, rootPath: String) -> Signa } } -public func currentAccount(networkArguments: NetworkInitializationArguments, supplementary: Bool, manager: AccountManager, rootPath: String, testingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal { - return manager.allocatedCurrentAccountId() - |> distinctUntilChanged(isEqual: { lhs, rhs in - return lhs == rhs - }) - |> mapToSignal { id -> Signal in - if let id = id { - let reload = ValuePromise(true, ignoreRepeated: false) - return reload.get() |> mapToSignal { _ -> Signal in - return accountWithId(networkArguments: networkArguments, id: id, supplementary: supplementary, rootPath: rootPath, testingEnvironment: testingEnvironment, auxiliaryMethods: auxiliaryMethods) - |> mapToSignal { accountResult -> Signal in - let postbox: Postbox - let initialKind: AccountKind - switch accountResult { - case .upgrading: - return .complete() - case let .unauthorized(account): - postbox = account.postbox - initialKind = .unauthorized - case let .authorized(account): - postbox = account.postbox - initialKind = .authorized +public func currentAccount(allocateIfNotExists: Bool, networkArguments: NetworkInitializationArguments, supplementary: Bool, manager: AccountManager, rootPath: String, beginWithTestingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal { + return manager.currentAccountId(allocateIfNotExists: allocateIfNotExists) + |> distinctUntilChanged(isEqual: { lhs, rhs in + return lhs == rhs + }) + |> mapToSignal { id -> Signal in + if let id = id { + let reload = ValuePromise(true, ignoreRepeated: false) + return reload.get() + |> mapToSignal { _ -> Signal in + return accountWithId(networkArguments: networkArguments, id: id, supplementary: supplementary, rootPath: rootPath, beginWithTestingEnvironment: beginWithTestingEnvironment, auxiliaryMethods: auxiliaryMethods) + |> mapToSignal { accountResult -> Signal in + let postbox: Postbox + let initialKind: AccountKind + switch accountResult { + case .upgrading: + return .complete() + case let .unauthorized(account): + postbox = account.postbox + initialKind = .unauthorized + case let .authorized(account): + postbox = account.postbox + initialKind = .authorized + } + let updatedKind = postbox.stateView() + |> map { view -> Bool in + let kind: AccountKind + if view.state is AuthorizedAccountState { + kind = .authorized + } else { + kind = .unauthorized } - let updatedKind = postbox.stateView() - |> map { view -> Bool in - let kind: AccountKind - if view.state is AuthorizedAccountState { - kind = .authorized - } else { - kind = .unauthorized - } - if kind != initialKind { - return true - } else { - return false - } - } - |> distinctUntilChanged - - return Signal { subscriber in - subscriber.putNext(accountResult) - - return updatedKind.start(next: { value in - if value { - reload.set(true) - } - }) + if kind != initialKind { + return true + } else { + return false } } + |> distinctUntilChanged + + return Signal { subscriber in + subscriber.putNext(accountResult) + + return updatedKind.start(next: { value in + if value { + reload.set(true) + } + }) + } } - } else { - return .single(nil) } + } else { + return .single(nil) } + } } public func logoutFromAccount(id: AccountRecordId, accountManager: AccountManager) -> Signal { @@ -234,28 +235,28 @@ public func managedCleanupAccounts(networkArguments: NetworkInitializationArgume } private func cleanupAccount(networkArguments: NetworkInitializationArguments, accountManager: AccountManager, id: AccountRecordId, rootPath: String, auxiliaryMethods: AccountAuxiliaryMethods) -> Signal { - return accountWithId(networkArguments: networkArguments, id: id, supplementary: true, rootPath: rootPath, testingEnvironment: false, auxiliaryMethods: auxiliaryMethods) - |> mapToSignal { account -> Signal in - switch account { - case .upgrading: - return .complete() - case .unauthorized: - return .complete() - case let .authorized(account): - account.shouldBeServiceTaskMaster.set(.single(.always)) - return account.network.request(Api.functions.auth.logOut()) - |> map(Optional.init) - |> `catch` { _ -> Signal in - return .single(.boolFalse) - } - |> mapToSignal { _ -> Signal in - account.shouldBeServiceTaskMaster.set(.single(.never)) - return accountManager.transaction { transaction -> Void in - transaction.updateRecord(id, { _ in - return nil - }) - } - } - } + return accountWithId(networkArguments: networkArguments, id: id, supplementary: true, rootPath: rootPath, beginWithTestingEnvironment: false, auxiliaryMethods: auxiliaryMethods) + |> mapToSignal { account -> Signal in + switch account { + case .upgrading: + return .complete() + case .unauthorized: + return .complete() + case let .authorized(account): + account.shouldBeServiceTaskMaster.set(.single(.always)) + return account.network.request(Api.functions.auth.logOut()) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(.boolFalse) + } + |> mapToSignal { _ -> Signal in + account.shouldBeServiceTaskMaster.set(.single(.never)) + return accountManager.transaction { transaction -> Void in + transaction.updateRecord(id, { _ in + return nil + }) + } + } } + } } diff --git a/TelegramCore/AccountState.swift b/TelegramCore/AccountState.swift index 1f44666468..91bd2b38ed 100644 --- a/TelegramCore/AccountState.swift +++ b/TelegramCore/AccountState.swift @@ -317,20 +317,24 @@ public enum UnauthorizedAccountStateContents: PostboxCoding, Equatable { } public final class UnauthorizedAccountState: AccountState { + public let isTestingEnvironment: Bool public let masterDatacenterId: Int32 public let contents: UnauthorizedAccountStateContents - public init(masterDatacenterId: Int32, contents: UnauthorizedAccountStateContents) { + public init(isTestingEnvironment: Bool, masterDatacenterId: Int32, contents: UnauthorizedAccountStateContents) { + self.isTestingEnvironment = isTestingEnvironment self.masterDatacenterId = masterDatacenterId self.contents = contents } public init(decoder: PostboxDecoder) { + self.isTestingEnvironment = decoder.decodeInt32ForKey("isTestingEnvironment", orElse: 0) != 0 self.masterDatacenterId = decoder.decodeInt32ForKey("dc", orElse: 0) self.contents = decoder.decodeObjectForKey("c", decoder: { UnauthorizedAccountStateContents(decoder: $0) }) as! UnauthorizedAccountStateContents } public func encode(_ encoder: PostboxEncoder) { + encoder.encodeInt32(self.isTestingEnvironment ? 1 : 0, forKey: "isTestingEnvironment") encoder.encodeInt32(self.masterDatacenterId, forKey: "dc") encoder.encodeObject(self.contents, forKey: "c") } @@ -339,6 +343,9 @@ public final class UnauthorizedAccountState: AccountState { guard let other = other as? UnauthorizedAccountState else { return false } + if self.isTestingEnvironment != other.isTestingEnvironment { + return false + } if self.masterDatacenterId != other.masterDatacenterId { return false } diff --git a/TelegramCore/AccountStateManager.swift b/TelegramCore/AccountStateManager.swift index 709452bac4..9bb9bc855f 100644 --- a/TelegramCore/AccountStateManager.swift +++ b/TelegramCore/AccountStateManager.swift @@ -145,7 +145,9 @@ public final class AccountStateManager { self.operations[self.operations.count - 1] = .collectUpdateGroups(currentGroups + groups, timeout) } else { self.operations[self.operations.count - 1] = .processUpdateGroups(currentGroups + groups) - self.startFirstOperation() + if self.operations.count == 1 { + self.startFirstOperation() + } } } } else { @@ -204,13 +206,16 @@ public final class AccountStateManager { } private func replaceOperations(with operation: AccountStateManagerOperation) { + var collectedProcessUpdateGroups: [(AccountStateManagerOperation, Bool)] = [] var collectedMessageIds: [MessageId] = [] var collectedPollCompletionSubscribers: [(Int32, ([MessageId]) -> Void)] = [] var collectedReplayAsynchronouslyBuiltFinalState: [(AccountFinalState, () -> Void)] = [] var processEvents: [(Int32, AccountFinalStateEvents)] = [] - for operation in self.operations { - switch operation { + for i in 0 ..< self.operations.count { + switch self.operations[i] { + case .processUpdateGroups: + collectedProcessUpdateGroups.append((self.operations[i], i == 0)) case let .pollCompletion(_, messageIds, subscribers): collectedMessageIds.append(contentsOf: messageIds) collectedPollCompletionSubscribers.append(contentsOf: subscribers) @@ -224,6 +229,9 @@ public final class AccountStateManager { } self.operations.removeAll() + + self.operations.append(contentsOf: collectedProcessUpdateGroups.map { $0.0 }) + self.operations.append(operation) if !collectedPollCompletionSubscribers.isEmpty || !collectedMessageIds.isEmpty { diff --git a/TelegramCore/Authorization.swift b/TelegramCore/Authorization.swift index 350cd5fab2..9c29d02a7c 100644 --- a/TelegramCore/Authorization.swift +++ b/TelegramCore/Authorization.swift @@ -64,7 +64,7 @@ public func sendAuthorizationCode(account: UnauthorizedAccount, phoneNumber: Str parsedNextType = AuthorizationCodeNextType(apiType: nextType) } - transaction.setState(UnauthorizedAccountState(masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: timeout, nextType: parsedNextType, termsOfService: termsOfService.flatMap(UnauthorizedAccountTermsOfService.init(apiTermsOfService:))))) + transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .confirmationCodeEntry(number: phoneNumber, type: SentAuthorizationCodeType(apiType: type), hash: phoneCodeHash, timeout: timeout, nextType: parsedNextType, termsOfService: termsOfService.flatMap(UnauthorizedAccountTermsOfService.init(apiTermsOfService:))))) } return account } |> mapError { _ -> AuthorizationCodeRequestError in return .generic } @@ -101,7 +101,7 @@ public func resendAuthorizationCode(account: UnauthorizedAccount) -> Signal mapError { _ -> AuthorizationCodeRequestError in return .generic } @@ -174,14 +174,14 @@ public func authorizeWithCode(account: UnauthorizedAccount, code: String) -> Sig return account.postbox.transaction { transaction -> Void in switch result { case .signUp: - transaction.setState(UnauthorizedAccountState(masterDatacenterId: account.masterDatacenterId, contents: .signUp(number: number, codeHash: hash, code: code, firstName: "", lastName: ""))) + transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .signUp(number: number, codeHash: hash, code: code, firstName: "", lastName: ""))) case let .password(hint): - transaction.setState(UnauthorizedAccountState(masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code))) + transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: hint, number: number, code: code))) case let .authorization(authorization): switch authorization { case let .authorization(_, _, user): let user = TelegramUser(user: user) - let state = AuthorizedAccountState(masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) + let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) /*transaction.updatePeersInternal([user], update: { current, peer -> Peer? in return peer })*/ @@ -227,7 +227,7 @@ public func authorizeWithPassword(account: UnauthorizedAccount, password: String switch result { case let .authorization(_, _, user): let user = TelegramUser(user: user) - let state = AuthorizedAccountState(masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) + let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) /*transaction.updatePeersInternal([user], update: { current, peer -> Peer? in return peer })*/ @@ -296,7 +296,7 @@ public func performPasswordRecovery(account: UnauthorizedAccount, code: String) switch result { case let .authorization(_, _, user): let user = TelegramUser(user: user) - let state = AuthorizedAccountState(masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) + let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) /*transaction.updatePeersInternal([user], update: { current, peer -> Peer? in return peer })*/ @@ -330,9 +330,9 @@ public func performAccountReset(account: UnauthorizedAccount) -> Signal mapError { _ in return AccountResetError.generic } @@ -369,7 +369,7 @@ public func signUpWithName(account: UnauthorizedAccount, firstName: String, last case let .authorization(_, _, user): let user = TelegramUser(user: user) let appliedState = account.postbox.transaction { transaction -> Void in - let state = AuthorizedAccountState(masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) + let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil) transaction.setState(state) } |> introduceError(SignUpError.self) @@ -413,7 +413,7 @@ public enum AuthorizationStateReset { public func resetAuthorizationState(account: UnauthorizedAccount, to value: AuthorizationStateReset) -> Signal { return account.postbox.transaction { transaction -> Void in if let state = transaction.getState() as? UnauthorizedAccountState { - transaction.setState(UnauthorizedAccountState(masterDatacenterId: state.masterDatacenterId, contents: .empty)) + transaction.setState(UnauthorizedAccountState(isTestingEnvironment: state.isTestingEnvironment, masterDatacenterId: state.masterDatacenterId, contents: .empty)) } } } diff --git a/TelegramCore/Fetch.swift b/TelegramCore/Fetch.swift index 666f5aaeb9..b8d98b014d 100644 --- a/TelegramCore/Fetch.swift +++ b/TelegramCore/Fetch.swift @@ -9,7 +9,7 @@ import SwiftSignalKit import Photos #endif -private func fetchCloudMediaLocation(account: Account, resource: TelegramMediaResource, datacenterId: Int, size: Int?, ranges: Signal, parameters: MediaResourceFetchParameters?) -> Signal { +private func fetchCloudMediaLocation(account: Account, resource: TelegramMediaResource, datacenterId: Int, size: Int?, ranges: Signal, parameters: MediaResourceFetchParameters?) -> Signal { return multipartFetch(account: account, resource: resource, datacenterId: datacenterId, size: size, ranges: ranges, parameters: parameters) } @@ -30,22 +30,28 @@ private func fetchLocalFileResource(path: String, move: Bool) -> Signal, parameters: MediaResourceFetchParameters?) -> Signal? { +func fetchResource(account: Account, resource: MediaResource, ranges: Signal, parameters: MediaResourceFetchParameters?) -> Signal? { if let _ = resource as? EmptyMediaResource { - return .single(.reset) |> then(.never()) + return .single(.reset) + |> then(.never()) } else if let secretFileResource = resource as? SecretFileMediaResource { - return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchSecretFileResource(account: account, resource: secretFileResource, ranges: ranges, parameters: parameters)) + return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false)) + |> then(fetchSecretFileResource(account: account, resource: secretFileResource, ranges: ranges, parameters: parameters)) } else if let cloudResource = resource as? TelegramMultipartFetchableResource { return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchCloudMediaLocation(account: account, resource: cloudResource, datacenterId: cloudResource.datacenterId, size: resource.size == 0 ? nil : resource.size, ranges: ranges, parameters: parameters)) } else if let webFileResource = resource as? WebFileReferenceMediaResource { return currentWebDocumentsHostDatacenterId(postbox: account.postbox, isTestingEnvironment: account.testingEnvironment) - |> mapToSignal { datacenterId -> Signal in - return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchCloudMediaLocation(account: account, resource: webFileResource, datacenterId: Int(datacenterId), size: resource.size == 0 ? nil : resource.size, ranges: ranges, parameters: parameters)) + |> introduceError(MediaResourceDataFetchError.self) + |> mapToSignal { datacenterId -> Signal in + return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false)) + |> then(fetchCloudMediaLocation(account: account, resource: webFileResource, datacenterId: Int(datacenterId), size: resource.size == 0 ? nil : resource.size, ranges: ranges, parameters: parameters)) } } else if let localFileResource = resource as? LocalFileReferenceMediaResource { return fetchLocalFileResource(path: localFileResource.localFilePath, move: localFileResource.isUniquelyReferencedTemporaryFile) + |> introduceError(MediaResourceDataFetchError.self) } else if let httpReference = resource as? HttpReferenceMediaResource { - return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false)) |> then(fetchHttpResource(url: httpReference.url)) + return .single(.dataPart(resourceOffset: 0, data: Data(), range: 0 ..< 0, complete: false)) + |> then(fetchHttpResource(url: httpReference.url)) } return nil } diff --git a/TelegramCore/FetchHttpResource.swift b/TelegramCore/FetchHttpResource.swift index 63255e03a3..22975c7464 100644 --- a/TelegramCore/FetchHttpResource.swift +++ b/TelegramCore/FetchHttpResource.swift @@ -9,7 +9,7 @@ import Foundation import MtProtoKitDynamic #endif -public func fetchHttpResource(url: String) -> Signal { +public func fetchHttpResource(url: String) -> Signal { if let url = URL(string: url) { let signal = MTHttpRequestOperation.data(forHttpUrl: url)! return Signal { subscriber in @@ -19,6 +19,9 @@ public func fetchHttpResource(url: String) -> Signal, parameters: MediaResourceFetchParameters?) -> Signal { +func fetchSecretFileResource(account: Account, resource: SecretFileMediaResource, ranges: Signal, parameters: MediaResourceFetchParameters?) -> Signal { return multipartFetch(account: account, resource: resource, datacenterId: resource.datacenterId, size: resource.size, ranges: ranges, parameters: parameters, encryptionKey: resource.key, decryptedSize: resource.decryptedSize) } diff --git a/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift b/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift index 2fa9ef782c..f904cee75b 100644 --- a/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift +++ b/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift @@ -132,49 +132,65 @@ func managedCloudChatRemoveMessagesOperations(postbox: Postbox, network: Network private func removeMessages(postbox: Postbox, network: Network, stateManager: AccountStateManager, peer: Peer, operation: CloudChatRemoveMessagesOperation) -> Signal { if peer.id.namespace == Namespaces.Peer.CloudChannel { if let inputChannel = apiInputChannel(peer) { - return network.request(Api.functions.channels.deleteMessages(channel: inputChannel, id: operation.messageIds.map { $0.id })) + var signal: Signal = .complete() + for s in stride(from: 0, to: operation.messageIds.count, by: 100) { + let ids = operation.messageIds[s ..< min(s + 100, operation.messageIds.count)] + let partSignal = network.request(Api.functions.channels.deleteMessages(channel: inputChannel, id: ids.map { $0.id })) |> map { result -> Api.messages.AffectedMessages? in return result } |> `catch` { _ in return .single(nil) } - |> mapToSignal { result in + |> mapToSignal { result -> Signal in if let result = result { switch result { - case let .affectedMessages(pts, ptsCount): - stateManager.addUpdateGroups([.updateChannelPts(channelId: peer.id.id, pts: pts, ptsCount: ptsCount)]) + case let .affectedMessages(pts, ptsCount): + stateManager.addUpdateGroups([.updateChannelPts(channelId: peer.id.id, pts: pts, ptsCount: ptsCount)]) } } return .complete() } + signal = signal + |> then(partSignal) + } + return signal } else { return .complete() } } else { - var flags:Int32 + var flags: Int32 switch operation.type { - case .forEveryone: - flags = (1 << 0) - default: - flags = 0 + case .forEveryone: + flags = (1 << 0) + default: + flags = 0 } - return network.request(Api.functions.messages.deleteMessages(flags: flags, id: operation.messageIds.map { $0.id })) + + var signal: Signal = .complete() + for s in stride(from: 0, to: operation.messageIds.count, by: 100) { + let ids = operation.messageIds[s ..< min(s + 100, operation.messageIds.count)] + let partSignal = network.request(Api.functions.messages.deleteMessages(flags: flags, id: ids.map { $0.id })) |> map { result -> Api.messages.AffectedMessages? in return result } |> `catch` { _ in return .single(nil) } - |> mapToSignal { result in + |> mapToSignal { result -> Signal in if let result = result { switch result { - case let .affectedMessages(pts, ptsCount): - stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)]) + case let .affectedMessages(pts, ptsCount): + stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)]) } } return .complete() } + + signal = signal + |> then(partSignal) + } + return signal } } diff --git a/TelegramCore/MultipartFetch.swift b/TelegramCore/MultipartFetch.swift index 264b0da155..48b3fcc38b 100644 --- a/TelegramCore/MultipartFetch.swift +++ b/TelegramCore/MultipartFetch.swift @@ -635,7 +635,7 @@ private final class MultipartFetchManager { } } -func multipartFetch(account: Account, resource: TelegramMediaResource, datacenterId: Int, size: Int?, ranges: Signal, parameters: MediaResourceFetchParameters?, encryptionKey: SecretFileEncryptionKey? = nil, decryptedSize: Int32? = nil) -> Signal { +func multipartFetch(account: Account, resource: TelegramMediaResource, datacenterId: Int, size: Int?, ranges: Signal, parameters: MediaResourceFetchParameters?, encryptionKey: SecretFileEncryptionKey? = nil, decryptedSize: Int32? = nil) -> Signal { return Signal { subscriber in let location: MultipartFetchMasterLocation if let resource = resource as? TelegramCloudMediaResource {