Refactoring

This commit is contained in:
Ali
2021-04-18 03:10:18 +04:00
parent 4637ed672e
commit 60d959bff8
93 changed files with 221 additions and 191 deletions

View File

@@ -0,0 +1,167 @@
import Foundation
import Postbox
import TelegramApi
import SyncCore
import SwiftSignalKit
public struct AuthTransferExportedToken {
public let value: Data
public let validUntil: Int32
}
public enum ExportAuthTransferTokenError {
case generic
case limitExceeded
}
public enum ExportAuthTransferTokenResult {
case displayToken(AuthTransferExportedToken)
case changeAccountAndRetry(UnauthorizedAccount)
case loggedIn
case passwordRequested(UnauthorizedAccount)
}
func _internal_exportAuthTransferToken(accountManager: AccountManager, account: UnauthorizedAccount, otherAccountUserIds: [PeerId.Id], syncContacts: Bool) -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> {
return account.network.request(Api.functions.auth.exportLoginToken(apiId: account.networkArguments.apiId, apiHash: account.networkArguments.apiHash, exceptIds: otherAccountUserIds.map({ $0._internalGetInt32Value() })))
|> map(Optional.init)
|> `catch` { error -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in
if error.errorDescription == "SESSION_PASSWORD_NEEDED" {
return account.network.request(Api.functions.account.getPassword(), automaticFloodWait: false)
|> mapError { error -> ExportAuthTransferTokenError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else {
return .generic
}
}
|> mapToSignal { result -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in
switch result {
case let .password(password):
return account.postbox.transaction { transaction -> Api.auth.LoginToken? in
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, contents: .passwordEntry(hint: password.hint ?? "", number: nil, code: nil, suggestReset: false, syncContacts: syncContacts)))
return nil
}
|> castError(ExportAuthTransferTokenError.self)
}
}
} else {
return .fail(.generic)
}
}
|> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
guard let result = result else {
return .single(.passwordRequested(account))
}
switch result {
case let .loginToken(expires, token):
return .single(.displayToken(AuthTransferExportedToken(value: token.makeData(), validUntil: expires)))
case let .loginTokenMigrateTo(dcId, token):
let updatedAccount = account.changedMasterDatacenterId(accountManager: accountManager, masterDatacenterId: dcId)
return updatedAccount
|> castError(ExportAuthTransferTokenError.self)
|> mapToSignal { updatedAccount -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
return updatedAccount.network.request(Api.functions.auth.importLoginToken(token: token))
|> map(Optional.init)
|> `catch` { error -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in
if error.errorDescription == "SESSION_PASSWORD_NEEDED" {
return updatedAccount.network.request(Api.functions.account.getPassword(), automaticFloodWait: false)
|> mapError { error -> ExportAuthTransferTokenError in
if error.errorDescription.hasPrefix("FLOOD_WAIT") {
return .limitExceeded
} else {
return .generic
}
}
|> mapToSignal { result -> Signal<Api.auth.LoginToken?, ExportAuthTransferTokenError> in
switch result {
case let .password(password):
return updatedAccount.postbox.transaction { transaction -> Api.auth.LoginToken? in
transaction.setState(UnauthorizedAccountState(isTestingEnvironment: updatedAccount.testingEnvironment, masterDatacenterId: updatedAccount.masterDatacenterId, contents: .passwordEntry(hint: password.hint ?? "", number: nil, code: nil, suggestReset: false, syncContacts: syncContacts)))
return nil
}
|> castError(ExportAuthTransferTokenError.self)
}
}
} else {
return .fail(.generic)
}
}
|> mapToSignal { result -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
guard let result = result else {
return .single(.passwordRequested(updatedAccount))
}
switch result {
case let .loginTokenSuccess(authorization):
switch authorization {
case let .authorization(_, _, user):
return updatedAccount.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: updatedAccount.testingEnvironment, masterDatacenterId: updatedAccount.masterDatacenterId, peerId: user.id, state: nil)
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: updatedAccount.networkArguments.appVersion, syncContacts: syncContacts)
transaction.setState(state)
return accountManager.transaction { transaction -> ExportAuthTransferTokenResult in
switchToAuthorizedAccount(transaction: transaction, account: updatedAccount)
return .loggedIn
}
|> castError(ExportAuthTransferTokenError.self)
}
|> castError(ExportAuthTransferTokenError.self)
|> switchToLatest
default:
return .fail(.generic)
}
default:
return .single(.changeAccountAndRetry(updatedAccount))
}
}
}
case let .loginTokenSuccess(authorization):
switch authorization {
case let .authorization(_, _, user):
return account.postbox.transaction { transaction -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> in
let user = TelegramUser(user: user)
let state = AuthorizedAccountState(isTestingEnvironment: account.testingEnvironment, masterDatacenterId: account.masterDatacenterId, peerId: user.id, state: nil)
initializedAppSettingsAfterLogin(transaction: transaction, appVersion: account.networkArguments.appVersion, syncContacts: syncContacts)
transaction.setState(state)
return accountManager.transaction { transaction -> ExportAuthTransferTokenResult in
switchToAuthorizedAccount(transaction: transaction, account: account)
return .loggedIn
}
|> castError(ExportAuthTransferTokenError.self)
}
|> castError(ExportAuthTransferTokenError.self)
|> switchToLatest
case let .authorizationSignUpRequired:
return .fail(.generic)
}
}
}
}
public enum ApproveAuthTransferTokenError {
case generic
case invalid
case expired
case alreadyAccepted
}
public func approveAuthTransferToken(account: Account, token: Data, activeSessionsContext: ActiveSessionsContext) -> Signal<RecentAccountSession, ApproveAuthTransferTokenError> {
return account.network.request(Api.functions.auth.acceptLoginToken(token: Buffer(data: token)))
|> mapError { error -> ApproveAuthTransferTokenError in
switch error.errorDescription {
case "AUTH_TOKEN_INVALID":
return .invalid
case "AUTH_TOKEN_EXPIRED":
return .expired
case "AUTH_TOKEN_ALREADY_ACCEPTED":
return .alreadyAccepted
default:
return .generic
}
}
|> mapToSignal { authorization -> Signal<RecentAccountSession, ApproveAuthTransferTokenError> in
let session = RecentAccountSession(apiAuthorization: authorization)
activeSessionsContext.addSession(session)
return .single(session)
}
}

View File

@@ -0,0 +1,39 @@
import SwiftSignalKit
import Postbox
import TelegramApi
public extension TelegramEngineUnauthorized {
final class Auth {
private let account: UnauthorizedAccount
init(account: UnauthorizedAccount) {
self.account = account
}
public func exportAuthTransferToken(accountManager: AccountManager, otherAccountUserIds: [PeerId.Id], syncContacts: Bool) -> Signal<ExportAuthTransferTokenResult, ExportAuthTransferTokenError> {
return _internal_exportAuthTransferToken(accountManager: accountManager, account: self.account, otherAccountUserIds: otherAccountUserIds, syncContacts: syncContacts)
}
}
}
public enum DeleteAccountError {
case generic
}
public extension TelegramEngine {
final class Auth {
private let account: Account
init(account: Account) {
self.account = account
}
public func deleteAccount() -> Signal<Never, DeleteAccountError> {
return self.account.network.request(Api.functions.account.deleteAccount(reason: "GDPR"))
|> mapError { _ -> DeleteAccountError in
return .generic
}
|> ignoreValues
}
}
}

View File

@@ -0,0 +1,49 @@
import Foundation
import SwiftSignalKit
import Postbox
import TelegramApi
public struct InactiveChannel : Equatable {
public let peer: Peer
public let lastActivityDate: Int32
public let participantsCount: Int32?
init(peer: Peer, lastActivityDate: Int32, participantsCount: Int32?) {
self.peer = peer
self.lastActivityDate = lastActivityDate
self.participantsCount = participantsCount
}
public static func ==(lhs: InactiveChannel, rhs: InactiveChannel) -> Bool {
return lhs.peer.isEqual(rhs.peer) && lhs.lastActivityDate == rhs.lastActivityDate && lhs.participantsCount == rhs.participantsCount
}
}
func _internal_inactiveChannelList(network: Network) -> Signal<[InactiveChannel], NoError> {
return network.request(Api.functions.channels.getInactiveChannels())
|> retryRequest
|> map { result in
switch result {
case let .inactiveChats(dates, chats, users):
let channels = chats.compactMap {
parseTelegramGroupOrChannel(chat: $0)
}
var participantsCounts: [PeerId: Int32] = [:]
for chat in chats {
switch chat {
case let .channel(channel):
if let participantsCountValue = channel.participantsCount {
participantsCounts[chat.peerId] = channel.participantsCount
}
default:
break
}
}
var inactive: [InactiveChannel] = []
for (i, channel) in channels.enumerated() {
inactive.append(InactiveChannel(peer: channel, lastActivityDate: dates[i], participantsCount: participantsCounts[channel.id]))
}
return inactive
}
}
}

View File

@@ -8,7 +8,7 @@ public enum AddressNameValidationStatus: Equatable {
}
public extension TelegramEngine {
final class PeerNames {
final class Peers {
private let account: Account
init(account: Account) {
@@ -57,5 +57,9 @@ public extension TelegramEngine {
public func supportPeerId() -> Signal<PeerId?, NoError> {
return _internal_supportPeerId(account: self.account)
}
public func inactiveChannelList() -> Signal<[InactiveChannel], NoError> {
return _internal_inactiveChannelList(network: self.account.network)
}
}
}

View File

@@ -20,7 +20,23 @@ public final class TelegramEngine {
return Payments(account: self.account)
}()
public lazy var peerNames: PeerNames = {
return PeerNames(account: self.account)
public lazy var peers: Peers = {
return Peers(account: self.account)
}()
public lazy var auth: Auth = {
return Auth(account: self.account)
}()
}
public final class TelegramEngineUnauthorized {
public let account: UnauthorizedAccount
public init(account: UnauthorizedAccount) {
self.account = account
}
public lazy var auth: Auth = {
return Auth(account: self.account)
}()
}