Frozen account improvements

This commit is contained in:
Ilya Laktyushin 2025-03-19 14:39:39 +04:00
parent 344bbb4fcd
commit ef3eb05d69
13 changed files with 138 additions and 49 deletions

View File

@ -139,7 +139,7 @@ public func retry<T, E>(_ delayIncrement: Double, maxDelay: Double, onQueue queu
}
}
public func retry<T, E>(retryOnError: @escaping (E) -> Bool, delayIncrement: Double, maxDelay: Double, maxRetries: Int, onQueue queue: Queue) -> (_ signal: Signal<T, E>) -> Signal<T, E> {
public func retry<T, E>(retryOnError: @escaping (E) -> Bool, delayIncrement: Double, maxDelay: Double, maxRetries: Int?, onQueue queue: Queue) -> (_ signal: Signal<T, E>) -> Signal<T, E> {
return { signal in
return Signal { subscriber in
let shouldRetry = Atomic(value: true)
@ -161,7 +161,7 @@ public func retry<T, E>(retryOnError: @escaping (E) -> Bool, delayIncrement: Dou
return (min(maxDelay, value + delayIncrement), count + 1)
}
if count >= maxRetries {
if let maxRetries, count >= maxRetries {
subscriber.putError(error)
} else {
let time: DispatchTime = DispatchTime.now() + Double(delay)

View File

@ -1224,6 +1224,20 @@ public func retryRequest<T>(signal: Signal<T, MTRpcError>) -> Signal<T, NoError>
|> retry(0.2, maxDelay: 5.0, onQueue: Queue.concurrentDefaultQueue())
}
public func retryRequestIfNotFrozen<T>(signal: Signal<T, MTRpcError>) -> Signal<T?, NoError> {
return signal
|> retry(retryOnError: { error in
if error.errorDescription == "FROZEN_METHOD_INVALID" {
return false
}
return true
}, delayIncrement: 0.2, maxDelay: 5.0, maxRetries: nil, onQueue: .concurrentDefaultQueue())
|> map(Optional.init)
|> `catch` { _ in
return .single(nil)
}
}
class Keychain: NSObject, MTKeychain {
let get: (String) -> Data?
let set: (String, Data) -> Void

View File

@ -241,8 +241,7 @@ func fetchChatList(accountPeerId: PeerId, postbox: Postbox, network: Network, lo
folderId = groupId.rawValue
}
additionalPinnedChats = network.request(Api.functions.messages.getPinnedDialogs(folderId: folderId))
|> retryRequest
|> map(Optional.init)
|> retryRequestIfNotFrozen
} else {
additionalPinnedChats = .single(nil)
}

View File

@ -8,8 +8,11 @@ import MtProtoKit
func managedAutodownloadSettingsUpdates(accountManager: AccountManager<TelegramAccountManagerTypes>, network: Network) -> Signal<Void, NoError> {
let poll = Signal<Void, NoError> { subscriber in
return (network.request(Api.functions.account.getAutoDownloadSettings())
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<Void, NoError> in
guard let result else {
return .complete()
}
return updateAutodownloadSettingsInteractively(accountManager: accountManager, { _ -> AutodownloadSettings in
return AutodownloadSettings(apiAutodownloadSettings: result)
})

View File

@ -9,7 +9,7 @@ func managedConfigurationUpdates(accountManager: AccountManager<TelegramAccountM
let poll = Signal<Void, NoError> { subscriber in
return (combineLatest(
network.request(Api.functions.help.getConfig()) |> retryRequest,
network.request(Api.functions.messages.getDefaultHistoryTTL()) |> retryRequest
network.request(Api.functions.messages.getDefaultHistoryTTL()) |> retryRequestIfNotFrozen
)
|> mapToSignal { result, defaultHistoryTtl -> Signal<Void, NoError> in
return postbox.transaction { transaction -> Signal<Void, NoError> in
@ -83,6 +83,8 @@ func managedConfigurationUpdates(accountManager: AccountManager<TelegramAccountM
} else {
messageAutoremoveSeconds = nil
}
default:
messageAutoremoveSeconds = nil
}
updateGlobalMessageAutoremoveTimeoutSettings(transaction: transaction, { settings in
var settings = settings

View File

@ -21,7 +21,7 @@ public func updateGlobalNotificationSettingsInteractively(postbox: Postbox, _ f:
public func resetPeerNotificationSettings(network: Network) -> Signal<Void, NoError> {
return network.request(Api.functions.account.resetNotifySettings())
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { _ in return Signal<Void, NoError>.complete() }
}
@ -113,8 +113,11 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
let reactions = network.request(Api.functions.account.getReactionsNotifySettings())
return combineLatest(chats, users, channels, contactsJoinedMuted, reactions)
|> retryRequest
|> map { chats, users, channels, contactsJoinedMuted, reactions in
|> retryRequestIfNotFrozen
|> mapToSignal { data in
guard let (chats, users, channels, contactsJoinedMuted, reactions) = data else {
return .complete()
}
let chatsSettings: MessageNotificationSettings
switch chats {
case let .peerNotifySettings(_, showPreviews, _, muteUntil, iosSound, _, desktopSound, storiesMuted, storiesHideSender, storiesIosSound, _, storiesDesktopSound):
@ -306,7 +309,7 @@ private func fetchedNotificationSettings(network: Network) -> Signal<GlobalNotif
)
}
return GlobalNotificationSettingsSet(privateChats: userSettings, groupChats: chatsSettings, channels: channelSettings, reactionSettings: reactionSettings, contactsJoined: contactsJoinedMuted == .boolFalse)
return .single(GlobalNotificationSettingsSet(privateChats: userSettings, groupChats: chatsSettings, channels: channelSettings, reactionSettings: reactionSettings, contactsJoined: contactsJoinedMuted == .boolFalse))
}
}

View File

@ -45,8 +45,11 @@ private func managedRecentMedia(postbox: Postbox, network: Network, collectionId
func managedRecentStickers(postbox: Postbox, network: Network, forceFetch: Bool = false) -> Signal<Void, NoError> {
return managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudRecentStickers, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: forceFetch, fetch: { hash in
return network.request(Api.functions.messages.getRecentStickers(flags: 0, hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .recentStickersNotModified:
return .single(nil)
@ -68,8 +71,11 @@ func managedRecentStickers(postbox: Postbox, network: Network, forceFetch: Bool
func managedRecentGifs(postbox: Postbox, network: Network, forceFetch: Bool = false) -> Signal<Void, NoError> {
return managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudRecentGifs, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: forceFetch, fetch: { hash in
return network.request(Api.functions.messages.getSavedGifs(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .savedGifsNotModified:
return .single(nil)
@ -91,8 +97,11 @@ func managedRecentGifs(postbox: Postbox, network: Network, forceFetch: Bool = fa
func managedSavedStickers(postbox: Postbox, network: Network, forceFetch: Bool = false) -> Signal<Void, NoError> {
return managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudSavedStickers, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: true, forceFetch: forceFetch, fetch: { hash in
return network.request(Api.functions.messages.getFavedStickers(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .favedStickersNotModified:
return .single(nil)
@ -133,8 +142,11 @@ func managedSavedStickers(postbox: Postbox, network: Network, forceFetch: Bool =
func managedGreetingStickers(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudGreetingStickers, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.messages.getStickers(emoticon: "👋⭐️", hash: 0))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .stickersNotModified:
return .single(nil)
@ -157,8 +169,11 @@ func managedGreetingStickers(postbox: Postbox, network: Network) -> Signal<Void,
func managedPremiumStickers(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudPremiumStickers, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.messages.getStickers(emoticon: "⭐️⭐️", hash: 0))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .stickersNotModified:
return .single(nil)
@ -181,8 +196,11 @@ func managedPremiumStickers(postbox: Postbox, network: Network) -> Signal<Void,
func managedAllPremiumStickers(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudAllPremiumStickers, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.messages.getStickers(emoticon: "📂⭐️", hash: 0))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .stickersNotModified:
return .single(nil)
@ -205,8 +223,11 @@ func managedAllPremiumStickers(postbox: Postbox, network: Network) -> Signal<Voi
func managedRecentStatusEmoji(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudRecentStatusEmoji, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.account.getRecentEmojiStatuses(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .emojiStatusesNotModified:
return .single(nil)
@ -235,8 +256,11 @@ func managedRecentStatusEmoji(postbox: Postbox, network: Network) -> Signal<Void
func managedFeaturedStatusEmoji(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudFeaturedStatusEmoji, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.account.getDefaultEmojiStatuses(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .emojiStatusesNotModified:
return .single(nil)
@ -265,8 +289,11 @@ func managedFeaturedStatusEmoji(postbox: Postbox, network: Network) -> Signal<Vo
func managedFeaturedChannelStatusEmoji(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudFeaturedChannelStatusEmoji, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.account.getChannelDefaultEmojiStatuses(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .emojiStatusesNotModified:
return .single(nil)
@ -295,8 +322,11 @@ func managedFeaturedChannelStatusEmoji(postbox: Postbox, network: Network) -> Si
func managedUniqueStarGifts(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudUniqueStarGifts, extractItemId: { RecentStarGiftItemId($0).id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.account.getCollectibleEmojiStatuses(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .emojiStatusesNotModified:
return .single(nil)
@ -345,8 +375,11 @@ func managedUniqueStarGifts(accountPeerId: PeerId, postbox: Postbox, network: Ne
func managedProfilePhotoEmoji(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudFeaturedProfilePhotoEmoji, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.account.getDefaultProfilePhotoEmojis(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .emojiListNotModified:
return .single(nil)
@ -373,8 +406,11 @@ func managedProfilePhotoEmoji(postbox: Postbox, network: Network) -> Signal<Void
func managedGroupPhotoEmoji(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudFeaturedGroupPhotoEmoji, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.account.getDefaultGroupPhotoEmojis(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .emojiListNotModified:
return .single(nil)
@ -401,8 +437,11 @@ func managedGroupPhotoEmoji(postbox: Postbox, network: Network) -> Signal<Void,
func managedBackgroundIconEmoji(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudFeaturedBackgroundIconEmoji, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.account.getDefaultBackgroundEmojis(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .emojiListNotModified:
return .single(nil)
@ -429,8 +468,11 @@ func managedBackgroundIconEmoji(postbox: Postbox, network: Network) -> Signal<Vo
func managedDisabledChannelStatusIconEmoji(postbox: Postbox, network: Network) -> Signal<Void, NoError> {
let poll = managedRecentMedia(postbox: postbox, network: network, collectionId: Namespaces.OrderedItemList.CloudDisabledChannelStatusEmoji, extractItemId: { RecentMediaItemId($0).mediaId.id }, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.account.getChannelRestrictedStatusEmojis(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .emojiListNotModified:
return .single(nil)
@ -466,8 +508,11 @@ func managedRecentReactions(postbox: Postbox, network: Network) -> Signal<Void,
}
}, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.messages.getRecentReactions(limit: 100, hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .reactionsNotModified:
return .single(nil)
@ -523,8 +568,11 @@ func managedTopReactions(postbox: Postbox, network: Network) -> Signal<Void, NoE
}
}, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.messages.getTopReactions(limit: 32, hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .reactionsNotModified:
return .single(nil)
@ -580,8 +628,11 @@ func managedDefaultTagReactions(postbox: Postbox, network: Network) -> Signal<Vo
}
}, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.messages.getDefaultTagReactions(hash: hash))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<[OrderedItemListEntry]?, NoError> in
guard let result else {
return .single(nil)
}
switch result {
case .reactionsNotModified:
return .single(nil)

View File

@ -479,10 +479,13 @@ private func continueSynchronizeInstalledStickerPacks(transaction: Transaction,
}
let sequence = request
|> retryRequest
|> retryRequestIfNotFrozen
|> mapError { _ -> SynchronizeInstalledStickerPacksError in
}
|> mapToSignal { result -> Signal<Void, SynchronizeInstalledStickerPacksError> in
guard let result else {
return .complete()
}
return postbox.transaction { transaction -> Signal<Void, SynchronizeInstalledStickerPacksError> in
let checkLocalCollectionInfos = transaction.getItemCollectionsInfos(namespace: collectionNamespace).map { $0.1 as! StickerPackCollectionInfo }
if checkLocalCollectionInfos != localCollectionInfos {

View File

@ -129,8 +129,11 @@ private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox,
}
return network.request(Api.functions.messages.getPinnedDialogs(folderId: groupId.rawValue))
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { dialogs -> Signal<Void, NoError> in
guard let dialogs else {
return .complete()
}
return postbox.transaction { transaction -> Signal<Void, NoError> in
var storeMessages: [StoreMessage] = []
var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:]

View File

@ -114,8 +114,11 @@ func _internal_updateBirthday(account: Account, birthday: TelegramBirthday?) ->
func managedContactBirthdays(stateManager: AccountStateManager) -> Signal<Never, NoError> {
let poll = stateManager.network.request(Api.functions.contacts.getBirthdays())
|> retryRequest
|> retryRequestIfNotFrozen
|> mapToSignal { result -> Signal<Never, NoError> in
guard let result else {
return .complete()
}
return stateManager.postbox.transaction { transaction -> Void in
if case let .contactBirthdays(contactBirthdays, users) = result {
updatePeers(transaction: transaction, accountPeerId: stateManager.accountPeerId, peers: AccumulatedPeers(users: users))

View File

@ -151,7 +151,7 @@ func _internal_updateRecentPeersEnabled(postbox: Postbox, network: Network, enab
func _internal_managedRecentlyUsedInlineBots(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal<Void, NoError> {
let remotePeers = network.request(Api.functions.contacts.getTopPeers(flags: 1 << 2, offset: 0, limit: 16, hash: 0))
|> retryRequest
|> retryRequestIfNotFrozen
|> map { result -> (AccumulatedPeers, [(PeerId, Double)])? in
switch result {
case .topPeersDisabled:
@ -174,6 +174,8 @@ func _internal_managedRecentlyUsedInlineBots(postbox: Postbox, network: Network,
return (parsedPeers, peersWithRating)
case .topPeersNotModified:
break
default:
break
}
return (AccumulatedPeers(), [])
}

View File

@ -5,8 +5,11 @@ import SwiftSignalKit
func requestRecentAccountSessions(account: Account) -> Signal<([RecentAccountSession], Int32), NoError> {
return account.network.request(Api.functions.account.getAuthorizations())
|> retryRequest
|> retryRequestIfNotFrozen
|> map { result -> ([RecentAccountSession], Int32) in
guard let result else {
return ([], 1)
}
var sessions: [RecentAccountSession] = []
var ttlDays: Int32 = 1
switch result {

View File

@ -22,25 +22,28 @@ public struct WebAuthorization : Equatable {
func webSessions(network: Network) -> Signal<([WebAuthorization], [PeerId: Peer]), NoError> {
return network.request(Api.functions.account.getWebAuthorizations())
|> retryRequest
|> map { result -> ([WebAuthorization], [PeerId : Peer]) in
var sessions: [WebAuthorization] = []
var peers:[PeerId : Peer] = [:]
switch result {
case let .webAuthorizations(authorizations, users):
for authorization in authorizations {
switch authorization {
case let .webAuthorization(hash, botId, domain, browser, platform, dateCreated, dateActive, ip, region):
sessions.append(WebAuthorization(hash: hash, botId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), domain: domain, browser: browser, platform: platform, dateCreated: dateCreated, dateActive: dateActive, ip: ip, region: region))
}
}
for user in users {
let peer = TelegramUser(user: user)
peers[peer.id] = peer
|> retryRequestIfNotFrozen
|> map { result -> ([WebAuthorization], [PeerId : Peer]) in
guard let result else {
return ([], [:])
}
var sessions: [WebAuthorization] = []
var peers:[PeerId : Peer] = [:]
switch result {
case let .webAuthorizations(authorizations, users):
for authorization in authorizations {
switch authorization {
case let .webAuthorization(hash, botId, domain, browser, platform, dateCreated, dateActive, ip, region):
sessions.append(WebAuthorization(hash: hash, botId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(botId)), domain: domain, browser: browser, platform: platform, dateCreated: dateCreated, dateActive: dateActive, ip: ip, region: region))
}
}
return (sessions, peers)
for user in users {
let peer = TelegramUser(user: user)
peers[peer.id] = peer
}
}
return (sessions, peers)
}
}