This commit is contained in:
overtake 2019-05-14 19:30:30 +02:00
commit 67b6ac79c9
3 changed files with 175 additions and 113 deletions

View File

@ -350,7 +350,7 @@ public func accountTransaction<T>(rootPath: String, id: AccountRecordId, encrypt
} }
} }
public func accountWithId(accountManager: AccountManager, networkArguments: NetworkInitializationArguments, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, supplementary: Bool, rootPath: String, beginWithTestingEnvironment: Bool, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<AccountResult, NoError> { public func accountWithId(accountManager: AccountManager, networkArguments: NetworkInitializationArguments, id: AccountRecordId, encryptionParameters: ValueBoxEncryptionParameters, supplementary: Bool, rootPath: String, beginWithTestingEnvironment: Bool, backupData: AccountBackupData?, auxiliaryMethods: AccountAuxiliaryMethods, shouldKeepAutoConnection: Bool = true) -> Signal<AccountResult, NoError> {
let path = "\(rootPath)/\(accountRecordIdPathName(id))" let path = "\(rootPath)/\(accountRecordIdPathName(id))"
let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters) let postbox = openPostbox(basePath: path + "/postbox", seedConfiguration: telegramPostboxSeedConfiguration, encryptionParameters: encryptionParameters)
@ -366,7 +366,18 @@ public func accountWithId(accountManager: AccountManager, networkArguments: Netw
} }
|> mapToSignal { localizationSettings, proxySettings -> Signal<AccountResult, NoError> in |> mapToSignal { localizationSettings, proxySettings -> Signal<AccountResult, NoError> in
return postbox.transaction { transaction -> (PostboxCoding?, LocalizationSettings?, ProxySettings?, NetworkSettings?) in return postbox.transaction { transaction -> (PostboxCoding?, LocalizationSettings?, ProxySettings?, NetworkSettings?) in
return (transaction.getState(), localizationSettings, proxySettings, transaction.getPreferencesEntry(key: PreferencesKeys.networkSettings) as? NetworkSettings) var state = transaction.getState()
if state == nil, let backupData = backupData {
let backupState = AuthorizedAccountState(isTestingEnvironment: beginWithTestingEnvironment, masterDatacenterId: backupData.masterDatacenterId, peerId: PeerId(backupData.peerId), state: nil)
state = backupState
let dict = NSMutableDictionary()
dict.setObject(MTDatacenterAuthInfo(authKey: backupData.masterDatacenterKey, authKeyId: backupData.masterDatacenterKeyId, saltSet: [], authKeyAttributes: [:], mainTempAuthKey: nil, mediaTempAuthKey: nil), forKey: backupData.masterDatacenterId as NSNumber)
let data = NSKeyedArchiver.archivedData(withRootObject: dict)
transaction.setState(backupState)
transaction.setKeychainEntry(data, forKey: "persistent:datacenterAuthInfoById")
}
return (state, localizationSettings, proxySettings, transaction.getPreferencesEntry(key: PreferencesKeys.networkSettings) as? NetworkSettings)
} }
|> mapToSignal { (accountState, localizationSettings, proxySettings, networkSettings) -> Signal<AccountResult, NoError> in |> mapToSignal { (accountState, localizationSettings, proxySettings, networkSettings) -> Signal<AccountResult, NoError> in
let keychain = makeExclusiveKeychain(id: id, postbox: postbox) let keychain = makeExclusiveKeychain(id: id, postbox: postbox)
@ -911,6 +922,62 @@ public func decryptedNotificationPayload(account: Account, data: Data) -> Signal
} }
} }
public struct AccountBackupData: Codable, Equatable {
public var masterDatacenterId: Int32
public var peerId: Int64
public var masterDatacenterKey: Data
public var masterDatacenterKeyId: Int64
}
public final class AccountBackupDataAttribute: AccountRecordAttribute, Equatable {
public let data: AccountBackupData
public init(data: AccountBackupData) {
self.data = data
}
public init(decoder: PostboxDecoder) {
self.data = try! JSONDecoder().decode(AccountBackupData.self, from: decoder.decodeDataForKey("data")!)
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeData(try! JSONEncoder().encode(self.data), forKey: "data")
}
public static func ==(lhs: AccountBackupDataAttribute, rhs: AccountBackupDataAttribute) -> Bool {
return lhs.data == rhs.data
}
public func isEqual(to: AccountRecordAttribute) -> Bool {
if let to = to as? AccountBackupDataAttribute {
return self == to
} else {
return false
}
}
}
public func accountBackupData(postbox: Postbox) -> Signal<AccountBackupData?, NoError> {
return postbox.transaction { transaction -> AccountBackupData? in
guard let state = transaction.getState() as? AuthorizedAccountState else {
return nil
}
guard let authInfoData = transaction.keychainEntryForKey("persistent:datacenterAuthInfoById") else {
return nil
}
guard let authInfo = NSKeyedUnarchiver.unarchiveObject(with: authInfoData) as? NSDictionary else {
return nil
}
guard let datacenterAuthInfo = authInfo.object(forKey: state.masterDatacenterId as NSNumber) as? MTDatacenterAuthInfo else {
return nil
}
guard let authKey = datacenterAuthInfo.authKey else {
return nil
}
return AccountBackupData(masterDatacenterId: state.masterDatacenterId, peerId: state.peerId.toInt64(), masterDatacenterKey: authKey, masterDatacenterKeyId: datacenterAuthInfo.authKeyId)
}
}
public class Account { public class Account {
public let id: AccountRecordId public let id: AccountRecordId
public let basePath: String public let basePath: String

View File

@ -139,6 +139,7 @@ private var declaredEncodables: Void = {
declareEncodable(CloudDocumentSizeMediaResource.self, f: { CloudDocumentSizeMediaResource(decoder: $0) }) declareEncodable(CloudDocumentSizeMediaResource.self, f: { CloudDocumentSizeMediaResource(decoder: $0) })
declareEncodable(CloudPeerPhotoSizeMediaResource.self, f: { CloudPeerPhotoSizeMediaResource(decoder: $0) }) declareEncodable(CloudPeerPhotoSizeMediaResource.self, f: { CloudPeerPhotoSizeMediaResource(decoder: $0) })
declareEncodable(CloudStickerPackThumbnailMediaResource.self, f: { CloudStickerPackThumbnailMediaResource(decoder: $0) }) declareEncodable(CloudStickerPackThumbnailMediaResource.self, f: { CloudStickerPackThumbnailMediaResource(decoder: $0) })
declareEncodable(AccountBackupDataAttribute.self, f: { AccountBackupDataAttribute(decoder: $0) })
return return
}() }()
@ -219,7 +220,7 @@ public func currentAccount(allocateIfNotExists: Bool, networkArguments: NetworkI
return false return false
} }
}) })
return accountWithId(accountManager: manager, networkArguments: networkArguments, id: record.0, encryptionParameters: encryptionParameters, supplementary: supplementary, rootPath: rootPath, beginWithTestingEnvironment: beginWithTestingEnvironment, auxiliaryMethods: auxiliaryMethods) return accountWithId(accountManager: manager, networkArguments: networkArguments, id: record.0, encryptionParameters: encryptionParameters, supplementary: supplementary, rootPath: rootPath, beginWithTestingEnvironment: beginWithTestingEnvironment, backupData: nil, auxiliaryMethods: auxiliaryMethods)
|> mapToSignal { accountResult -> Signal<AccountResult?, NoError> in |> mapToSignal { accountResult -> Signal<AccountResult?, NoError> in
let postbox: Postbox let postbox: Postbox
let initialKind: AccountKind let initialKind: AccountKind
@ -385,7 +386,7 @@ private func cleanupAccount(networkArguments: NetworkInitializationArguments, ac
return false return false
} }
}) })
return accountWithId(accountManager: accountManager, networkArguments: networkArguments, id: id, encryptionParameters: encryptionParameters, supplementary: true, rootPath: rootPath, beginWithTestingEnvironment: beginWithTestingEnvironment, auxiliaryMethods: auxiliaryMethods) return accountWithId(accountManager: accountManager, networkArguments: networkArguments, id: id, encryptionParameters: encryptionParameters, supplementary: true, rootPath: rootPath, beginWithTestingEnvironment: beginWithTestingEnvironment, backupData: nil, auxiliaryMethods: auxiliaryMethods)
|> mapToSignal { account -> Signal<Void, NoError> in |> mapToSignal { account -> Signal<Void, NoError> in
switch account { switch account {
case .upgrading: case .upgrading:

View File

@ -316,6 +316,7 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
switch historyState { switch historyState {
case let .channel(peerId, _): case let .channel(peerId, _):
let hash = hashForMessages(previousMessages, withChannelIds: false) let hash = hashForMessages(previousMessages, withChannelIds: false)
Logger.shared.log("HistoryValidation", "validate batch for \(peerId): \(previousMessages.map({ $0.id }))")
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
let requestSignal: Signal<Api.messages.Messages, MTRpcError> let requestSignal: Signal<Api.messages.Messages, MTRpcError>
if let tag = tag { if let tag = tag {
@ -358,34 +359,6 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
} else { } else {
return .complete() return .complete()
} }
/*case let .group(groupId, _):
signal = .single(.notModified)
let hash = hashForMessages(previousMessages, withChannelIds: true)
let upperIndex = MessageIndex(previousMessages[previousMessages.count - 1])
let minIndex = MessageIndex(previousMessages[0]).predecessor()
let upperInputPeer: Api.Peer = groupBoundaryPeer(upperIndex.id.peerId, accountPeerId: accountPeerId)
let lowerInputPeer: Api.Peer = groupBoundaryPeer(minIndex.id.peerId, accountPeerId: accountPeerId)
var flags: Int32 = 0
flags |= (1 << 0)
let offsetPosition: Api.FeedPosition = .feedPosition(date: upperIndex.timestamp, peer: upperInputPeer, id: upperIndex.id.id)
let addOffset: Int32 = -1
let minPosition: Api.FeedPosition = .feedPosition(date: minIndex.timestamp, peer: lowerInputPeer, id: minIndex.id.id)
flags |= (1 << 0)
flags |= (1 << 2)
signal = network.request(Api.functions.channels.getFeed(flags: flags, feedId: groupId.rawValue, offsetPosition: offsetPosition, addOffset: addOffset, limit: 200, maxPosition: nil, minPosition: minPosition, hash: hash))
|> map { result -> ValidatedMessages in
switch result {
case let .feedMessages(_, _, _, _, messages, chats, users):
return .messages(messages, chats, users, nil)
case .feedMessagesNotModified:
return .notModified
}
}*/
} }
return signal return signal
@ -394,8 +367,9 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
return .single(nil) return .single(nil)
} }
|> mapToSignal { result -> Signal<Void, NoError> in |> mapToSignal { result -> Signal<Void, NoError> in
return postbox.transaction { transaction -> Void in guard let result = result else {
if let result = result { return .complete()
}
switch result { switch result {
case let .messages(messages, chats, users, channelPts): case let .messages(messages, chats, users, channelPts):
var storeMessages: [StoreMessage] = [] var storeMessages: [StoreMessage] = []
@ -408,23 +382,66 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts)) attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
} }
switch historyState {
case .channel:
break
/*case let .group(_, groupState):
attributes.append(PeerGroupMessageStateVersionAttribute(stateIndex: groupState.stateIndex))*/
}
storeMessages.append(storeMessage.withUpdatedAttributes(attributes)) storeMessages.append(storeMessage.withUpdatedAttributes(attributes))
} }
} }
/*if case .group = historyState { var validMessageIds = Set<MessageId>()
let prevHash = hashForMessages(previousMessages, withChannelIds: true) for message in storeMessages {
let updatedHash = hashForMessages(storeMessages, withChannelIds: true) if case let .Id(id) = message.id {
print("\(updatedHash) != \(prevHash)") validMessageIds.insert(id)
}*/ }
}
var maybeRemovedMessageIds: [MessageId] = []
for id in previous.keys {
if !validMessageIds.contains(id) {
maybeRemovedMessageIds.append(id)
}
}
let actuallyRemovedMessagesSignal: Signal<Set<MessageId>, NoError>
if maybeRemovedMessageIds.isEmpty {
actuallyRemovedMessagesSignal = .single(Set())
} else {
actuallyRemovedMessagesSignal = postbox.transaction { transaction -> Signal<Set<MessageId>, NoError> in
switch historyState {
case let .channel(peerId, _):
if let inputChannel = transaction.getPeer(peerId).flatMap(apiInputChannel) {
return network.request(Api.functions.channels.getMessages(channel: inputChannel, id: maybeRemovedMessageIds.map({ Api.InputMessage.inputMessageID(id: $0.id) })))
|> map { result -> Set<MessageId> in
let apiMessages: [Api.Message]
switch result {
case let .channelMessages(_, _, _, messages, _, _):
apiMessages = messages
case let .messages(messages, _, _):
apiMessages = messages
case let .messagesSlice(_, _, messages, _, _):
apiMessages = messages
case .messagesNotModified:
return Set()
}
var ids = Set<MessageId>()
for message in apiMessages {
if let id = message.id {
ids.insert(id)
}
}
return ids
}
|> `catch` { _ -> Signal<Set<MessageId>, NoError> in
return .single(Set(maybeRemovedMessageIds))
}
}
}
return .single(Set(maybeRemovedMessageIds))
}
|> switchToLatest
}
return actuallyRemovedMessagesSignal
|> mapToSignal { removedMessageIds -> Signal<Void, NoError> in
return postbox.transaction { transaction -> Void in
var validMessageIds = Set<MessageId>() var validMessageIds = Set<MessageId>()
for message in storeMessages { for message in storeMessages {
if case let .Id(id) = message.id { if case let .Id(id) = message.id {
@ -470,22 +487,7 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts)) attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts))
} }
switch historyState { let updatedFlags = StoreMessageFlags(currentMessage.flags)
case .channel:
break
/*case let .group(_, groupState):
for i in (0 ..< attributes.count).reversed() {
if let _ = attributes[i] as? PeerGroupMessageStateVersionAttribute {
attributes.remove(at: i)
}
}
attributes.append(PeerGroupMessageStateVersionAttribute(stateIndex: groupState.stateIndex))*/
}
var updatedFlags = StoreMessageFlags(currentMessage.flags)
/*if case .group = historyState {
updatedFlags.insert(.CanBeGroupedIntoFeed)
}*/
return .update(StoreMessage(id: message.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: updatedFlags, tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) return .update(StoreMessage(id: message.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: updatedFlags, tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
} }
@ -493,9 +495,6 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
if previous[id] == nil { if previous[id] == nil {
print("\(id) missing") print("\(id) missing")
/*if case let .group(groupId, _) = historyState {
let _ = transaction.addMessagesToGroupFeedIndex(groupId: groupId, ids: [id])
}*/
} }
} else { } else {
let _ = transaction.addMessages([message], location: .Random) let _ = transaction.addMessages([message], location: .Random)
@ -503,7 +502,7 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
} }
} }
for id in previous.keys { for id in removedMessageIds {
if !validMessageIds.contains(id) { if !validMessageIds.contains(id) {
if let tag = tag { if let tag = tag {
transaction.updateMessage(id, update: { currentMessage in transaction.updateMessage(id, update: { currentMessage in
@ -519,13 +518,15 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
switch historyState { switch historyState {
case .channel: case .channel:
deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [id]) deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: [id])
/*case let .group(groupId, _): Logger.shared.log("HistoryValidation", "deleting message \(id) in \(id.peerId)")
transaction.removeMessagesFromGroupFeedIndex(groupId: groupId, ids: [id])*/ }
}
} }
} }
} }
} }
case .notModified: case .notModified:
return postbox.transaction { transaction -> Void in
for id in previous.keys { for id in previous.keys {
transaction.updateMessage(id, update: { currentMessage in transaction.updateMessage(id, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo? var storeForwardInfo: StoreMessageForwardInfo?
@ -539,17 +540,11 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
if let _ = attributes[i] as? ChannelMessageStateVersionAttribute { if let _ = attributes[i] as? ChannelMessageStateVersionAttribute {
attributes.remove(at: i) attributes.remove(at: i)
} }
/*case .group:
if let _ = attributes[i] as? PeerGroupMessageStateVersionAttribute {
attributes.remove(at: i)
}*/
} }
} }
switch historyState { switch historyState {
case let .channel(_, channelState): case let .channel(_, channelState):
attributes.append(ChannelMessageStateVersionAttribute(pts: channelState.pts)) attributes.append(ChannelMessageStateVersionAttribute(pts: channelState.pts))
/*case let .group(_, groupState):
attributes.append(PeerGroupMessageStateVersionAttribute(stateIndex: groupState.stateIndex))*/
} }
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media))
}) })
@ -557,6 +552,5 @@ private func validateBatch(postbox: Postbox, network: Network, accountPeerId: Pe
} }
} }
} }
}
} |> switchToLatest } |> switchToLatest
} }