diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index cbafd53561..b0a681b123 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -129,6 +129,8 @@ D0223A991EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0223A971EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift */; }; D0223A9B1EA5654D00211D94 /* TelegramMediaResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0223A9A1EA5654D00211D94 /* TelegramMediaResource.swift */; }; D0223A9C1EA5654D00211D94 /* TelegramMediaResource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0223A9A1EA5654D00211D94 /* TelegramMediaResource.swift */; }; + D02395D61F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02395D51F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift */; }; + D02395D71F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02395D51F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift */; }; D02ABC7B1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02ABC7A1E30058F00CAE539 /* DeleteMessagesInteractively.swift */; }; D02ABC7C1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02ABC7A1E30058F00CAE539 /* DeleteMessagesInteractively.swift */; }; D02ABC7E1E3109F000CAE539 /* CloudChatRemoveMessagesOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02ABC7D1E3109F000CAE539 /* CloudChatRemoveMessagesOperation.swift */; }; @@ -206,6 +208,10 @@ D03C53741DAD5CA9004C17B3 /* CachedChannelData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B843841DA6EDC4005F29E1 /* CachedChannelData.swift */; }; D03C53751DAD5CA9004C17B3 /* TelegramUserPresence.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B844521DAC0773005F29E1 /* TelegramUserPresence.swift */; }; D03C53771DAFF20F004C17B3 /* MultipartUpload.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03C53761DAFF20F004C17B3 /* MultipartUpload.swift */; }; + D03DC9101F82E344001D584C /* AccountStateReset.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03DC90F1F82E344001D584C /* AccountStateReset.swift */; }; + D03DC9111F82E344001D584C /* AccountStateReset.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03DC90F1F82E344001D584C /* AccountStateReset.swift */; }; + D03DC9131F82F89D001D584C /* RegularChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03DC9121F82F89D001D584C /* RegularChatState.swift */; }; + D03DC9141F82F89D001D584C /* RegularChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03DC9121F82F89D001D584C /* RegularChatState.swift */; }; D03E5E0C1E55E02D0029569A /* LoggedOutAccountAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03E5E0B1E55E02D0029569A /* LoggedOutAccountAttribute.swift */; }; D03E5E0D1E55E02D0029569A /* LoggedOutAccountAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03E5E0B1E55E02D0029569A /* LoggedOutAccountAttribute.swift */; }; D041E3F51E535464008C24B4 /* AddPeerMember.swift in Sources */ = {isa = PBXBuildFile; fileRef = D041E3F41E535464008C24B4 /* AddPeerMember.swift */; }; @@ -648,6 +654,7 @@ D021E0E11DB5401A00C6B04F /* StickerManagement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StickerManagement.swift; sourceTree = ""; }; D0223A971EA564BD00211D94 /* MediaResourceNetworkStatsTag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaResourceNetworkStatsTag.swift; sourceTree = ""; }; D0223A9A1EA5654D00211D94 /* TelegramMediaResource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TelegramMediaResource.swift; sourceTree = ""; }; + D02395D51F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelHistoryAvailabilitySettings.swift; sourceTree = ""; }; D02ABC7A1E30058F00CAE539 /* DeleteMessagesInteractively.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeleteMessagesInteractively.swift; sourceTree = ""; }; D02ABC7D1E3109F000CAE539 /* CloudChatRemoveMessagesOperation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CloudChatRemoveMessagesOperation.swift; sourceTree = ""; }; D02ABC801E310E5D00CAE539 /* ManagedCloudChatRemoveMessagesOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedCloudChatRemoveMessagesOperations.swift; sourceTree = ""; }; @@ -713,6 +720,8 @@ D03B0E691D63283000955575 /* libwebp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libwebp.a; path = "third-party/libwebp/lib/libwebp.a"; sourceTree = ""; }; D03B0E6B1D63283C00955575 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; D03C53761DAFF20F004C17B3 /* MultipartUpload.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultipartUpload.swift; sourceTree = ""; }; + D03DC90F1F82E344001D584C /* AccountStateReset.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountStateReset.swift; sourceTree = ""; }; + D03DC9121F82F89D001D584C /* RegularChatState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegularChatState.swift; sourceTree = ""; }; D03E5E0B1E55E02D0029569A /* LoggedOutAccountAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoggedOutAccountAttribute.swift; sourceTree = ""; }; D041E3F41E535464008C24B4 /* AddPeerMember.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddPeerMember.swift; sourceTree = ""; }; D041E3F71E535A88008C24B4 /* RemovePeerMember.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RemovePeerMember.swift; sourceTree = ""; }; @@ -1153,12 +1162,14 @@ isa = PBXGroup; children = ( D03B0CFF1D62255C00955575 /* ChannelState.swift */, + D03DC9121F82F89D001D584C /* RegularChatState.swift */, D03121011DA57E93006A2A60 /* TelegramPeerNotificationSettings.swift */, D03B0D001D62255C00955575 /* EnqueueMessage.swift */, D03B0D011D62255C00955575 /* Holes.swift */, D017495D1E118F790057C89A /* AccountStateManager.swift */, D017495F1E118FC30057C89A /* AccountIntermediateState.swift */, D03B0D031D62255C00955575 /* AccountStateManagementUtils.swift */, + D03DC90F1F82E344001D584C /* AccountStateReset.swift */, D03B0D041D62255C00955575 /* SynchronizePeerReadState.swift */, D03B0D051D62255C00955575 /* UpdateGroup.swift */, D03B0D061D62255C00955575 /* UpdateMessageService.swift */, @@ -1492,6 +1503,7 @@ C230BEB51EE9A3760029586C /* ChannelAdminEventLogs.swift */, D0A472B51F4CBE8B00E0EEDA /* LoadedPeer.swift */, D0DA1D311F7043D50034E892 /* ManagedPendingPeerNotificationSettings.swift */, + D02395D51F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift */, ); name = Peers; sourceTree = ""; @@ -1814,6 +1826,7 @@ D0E23DDA1E806F7700B9B6D2 /* ManagedSynchronizeMarkFeaturedStickerPacksAsSeenOperations.swift in Sources */, D049EAD81E43DAD200A2CD3A /* ManagedRecentStickers.swift in Sources */, D0448C991E268F9A005A61A7 /* SecretApiLayer46.swift in Sources */, + D03DC9131F82F89D001D584C /* RegularChatState.swift in Sources */, D0613FCF1E60520700202CDB /* ChannelMembers.swift in Sources */, C2366C891E4F40480097CCFF /* SupportPeerId.swift in Sources */, D05A32E11E6F0982002760B4 /* UpdatedAccountPrivacySettings.swift in Sources */, @@ -1837,6 +1850,7 @@ C2FD33E41E687BF1008D13D4 /* PeerPhotoUpdater.swift in Sources */, D0B843B51DA7FF30005F29E1 /* NBMetadataCore.m in Sources */, D03B0CD61D62245300955575 /* TelegramUser.swift in Sources */, + D02395D61F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift in Sources */, D019B1CC1E2E3B6A00F80DB3 /* SecretChatRekeySession.swift in Sources */, D03B0CD91D62245B00955575 /* PeerUtils.swift in Sources */, D053B41B1F18DEF500E2D58A /* TelegramMediaExpiredContent.swift in Sources */, @@ -1905,6 +1919,7 @@ D03B0D5C1D631A6900955575 /* Download.swift in Sources */, D0C27B421F4B58C000A4E170 /* PeerSpecificStickerPack.swift in Sources */, D01749591E1092BC0057C89A /* RequestStartBot.swift in Sources */, + D03DC9101F82E344001D584C /* AccountStateReset.swift in Sources */, D01B27A21E394D8B0022A4C0 /* PrivacySettings.swift in Sources */, D0223A9B1EA5654D00211D94 /* TelegramMediaResource.swift in Sources */, D017495E1E118F790057C89A /* AccountStateManager.swift in Sources */, @@ -2011,6 +2026,7 @@ D0F7B1EA1E045C87007EB8A5 /* ChangePeerNotificationSettings.swift in Sources */, D0B418A71D7E0592004562A4 /* Fetch.swift in Sources */, D02ABC7C1E30058F00CAE539 /* DeleteMessagesInteractively.swift in Sources */, + D03DC9111F82E344001D584C /* AccountStateReset.swift in Sources */, D050F2111E48AB0600988324 /* InteractivePhoneFormatter.swift in Sources */, D050F2631E4A5AEB00988324 /* SynchronizePinnedChatsOperation.swift in Sources */, D0B418B81D7E05A6004562A4 /* ContactManagement.swift in Sources */, @@ -2075,6 +2091,7 @@ D0BEAF611E54ACF900BD963D /* AccountManager.swift in Sources */, D0F3CC791DDE2859008148FA /* SearchMessages.swift in Sources */, D0B8442B1DAB91E0005F29E1 /* NBMetadataCore.m in Sources */, + D03DC9141F82F89D001D584C /* RegularChatState.swift in Sources */, D00C7CD01E3628180080C3D5 /* UpdateCachedChannelParticipants.swift in Sources */, D0F3A8A61E82C94C00B4C64C /* SynchronizeableChatInputState.swift in Sources */, D00BDA1A1EE593D600C64C5E /* TelegramChannelAdminRights.swift in Sources */, @@ -2193,6 +2210,7 @@ D03C53741DAD5CA9004C17B3 /* CachedChannelData.swift in Sources */, D0B418861D7E056D004562A4 /* Namespaces.swift in Sources */, D05A32E51E6F0B2E002760B4 /* RecentAccountSessions.swift in Sources */, + D02395D71F8D09A50070F5C2 /* ChannelHistoryAvailabilitySettings.swift in Sources */, D0F7B1E41E045C7B007EB8A5 /* InstantPage.swift in Sources */, D03E5E0D1E55E02D0029569A /* LoggedOutAccountAttribute.swift in Sources */, D0B418AD1D7E0597004562A4 /* Serialization.swift in Sources */, diff --git a/TelegramCore/Account.swift b/TelegramCore/Account.swift index 3ee02ddbfa..108eaf25b8 100644 --- a/TelegramCore/Account.swift +++ b/TelegramCore/Account.swift @@ -173,6 +173,7 @@ private var declaredEncodables: Void = { declareEncodable(TelegramMediaFileAttribute.self, f: { TelegramMediaFileAttribute(decoder: $0) }) declareEncodable(CloudFileMediaResource.self, f: { CloudFileMediaResource(decoder: $0) }) declareEncodable(ChannelState.self, f: { ChannelState(decoder: $0) }) + declareEncodable(RegularChatState.self, f: { RegularChatState(decoder: $0) }) declareEncodable(InlineBotMessageAttribute.self, f: { InlineBotMessageAttribute(decoder: $0) }) declareEncodable(TextEntitiesMessageAttribute.self, f: { TextEntitiesMessageAttribute(decoder: $0) }) declareEncodable(ReplyMessageAttribute.self, f: { ReplyMessageAttribute(decoder: $0) }) @@ -748,7 +749,7 @@ public func setupAccount(_ account: Account, fetchCachedResourceRepresentation: account.transformOutgoingMessageMedia = transformOutgoingMessageMedia account.pendingMessageManager.transformOutgoingMessageMedia = transformOutgoingMessageMedia - account.managedContactsDisposable.set(manageContacts(network: account.network, postbox: account.postbox).start()) + account.managedContactsDisposable.set(manageContacts(network: account.network, postbox: account.postbox, accountPeerId: account.peerId).start()) account.managedStickerPacksDisposable.set(manageStickerPacks(network: account.network, postbox: account.postbox).start()) /*account.network.request(Api.functions.help.getScheme(version: 0)).start(next: { result in diff --git a/TelegramCore/AccountIntermediateState.swift b/TelegramCore/AccountIntermediateState.swift index 16a44bddf8..417ecb3cef 100644 --- a/TelegramCore/AccountIntermediateState.swift +++ b/TelegramCore/AccountIntermediateState.swift @@ -84,6 +84,7 @@ enum AccountStateMutationOperation { case UpdateChatInputState(PeerId, SynchronizeableChatInputState?) case UpdateCall(Api.PhoneCall) case UpdateLangPack(Api.LangPackDifference?) + case UpdateMinAvailableMessage(MessageId) } struct AccountMutableState { @@ -220,6 +221,10 @@ struct AccountMutableState { self.addOperation(.UpdateLangPack(difference)) } + mutating func updateMinAvailableMessage(_ id: MessageId) { + self.addOperation(.UpdateMinAvailableMessage(id)) + } + mutating func mergeUsers(_ users: [Api.User]) { self.addOperation(.MergeApiUsers(users)) @@ -286,7 +291,7 @@ struct AccountMutableState { mutating func addOperation(_ operation: AccountStateMutationOperation) { switch operation { - case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadOutbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack: + case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .ReadOutbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage: break case let .AddMessages(messages, _): for message in messages { diff --git a/TelegramCore/AccountStateManagementUtils.swift b/TelegramCore/AccountStateManagementUtils.swift index dea5ba2ab4..1f136cfec9 100644 --- a/TelegramCore/AccountStateManagementUtils.swift +++ b/TelegramCore/AccountStateManagementUtils.swift @@ -443,7 +443,7 @@ func finalStateWithUpdateGroups(_ account: Account, state: AccountMutableState, } } - return finalStateWithUpdates(account: account, state: updatedState, updates: collectedUpdates, shouldPoll: hadReset, missingUpdates: !ptsUpdatesAfterHole.isEmpty || !qtsUpdatesAfterHole.isEmpty || !seqGroupsAfterHole.isEmpty) + return finalStateWithUpdates(account: account, state: updatedState, updates: collectedUpdates, shouldPoll: hadReset, missingUpdates: !ptsUpdatesAfterHole.isEmpty || !qtsUpdatesAfterHole.isEmpty || !seqGroupsAfterHole.isEmpty, shouldResetChannels: true) } func finalStateWithDifference(account: Account, state: AccountMutableState, difference: Api.updates.Difference) -> Signal { @@ -501,7 +501,7 @@ func finalStateWithDifference(account: Account, state: AccountMutableState, diff updatedState.addSecretMessages(encryptedMessages) } - return finalStateWithUpdates(account: account, state: updatedState, updates: updates, shouldPoll: false, missingUpdates: false) + return finalStateWithUpdates(account: account, state: updatedState, updates: updates, shouldPoll: false, missingUpdates: false, shouldResetChannels: true) } private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] { @@ -552,6 +552,13 @@ private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] { } else { updatesByChannel[peerId]!.append(update) } + case let .updateChannelAvailableMessages(channelId, _): + let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) + if updatesByChannel[peerId] == nil { + updatesByChannel[peerId] = [update] + } else { + updatesByChannel[peerId]!.append(update) + } default: result.append(update) } @@ -602,7 +609,7 @@ private func sortedUpdates(_ updates: [Api.Update]) -> [Api.Update] { return result } -private func finalStateWithUpdates(account: Account, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool) -> Signal { +private func finalStateWithUpdates(account: Account, state: AccountMutableState, updates: [Api.Update], shouldPoll: Bool, missingUpdates: Bool, shouldResetChannels: Bool) -> Signal { var updatedState = state var channelsToPoll = Set() @@ -694,6 +701,9 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState, channelsToPoll.insert(peerId) } } + case let .updateChannelAvailableMessages(channelId, minId): + let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) + updatedState.updateMinAvailableMessage(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: minId)) case let .updateDeleteMessages(messages, _, _): updatedState.deleteMessagesWithGlobalIds(messages) case let .updateEditMessage(apiMessage, _, _): @@ -1023,21 +1033,49 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState, } var pollChannelSignals: [Signal<(AccountMutableState, Bool, Int32?), NoError>] = [] - for peerId in channelsToPoll { - if let peer = updatedState.peers[peerId] { - pollChannelSignals.append(pollChannel(account, peer: peer, state: updatedState.branch())) + if channelsToPoll.isEmpty { + pollChannelSignals = [] + } else if shouldResetChannels { + var channelPeers: [Peer] = [] + for peerId in channelsToPoll { + if let peer = updatedState.peers[peerId] { + channelPeers.append(peer) + } else { + Logger.shared.log("State", "can't reset channel \(peerId): no peer found") + } + } + if !channelPeers.isEmpty { + let resetSignal = resetChannels(account, peers: channelPeers, state: updatedState) + |> map { resultState -> (AccountMutableState, Bool, Int32?) in + return (resultState, true, nil) + } + pollChannelSignals = [resetSignal] } else { - Logger.shared.log("State", "can't poll channel \(peerId): no peer found") + pollChannelSignals = [] + } + } else { + for peerId in channelsToPoll { + if let peer = updatedState.peers[peerId] { + pollChannelSignals.append(pollChannel(account, peer: peer, state: updatedState.branch())) + } else { + Logger.shared.log("State", "can't poll channel \(peerId): no peer found") + } } } return combineLatest(pollChannelSignals) |> mapToSignal { states -> Signal in - var finalState = updatedState + var finalState: AccountMutableState = updatedState var hadError = false - for (state, success, _) in states { - finalState.merge(state) - if !success { - hadError = true + + if shouldResetChannels && states.count != 0 { + assert(states.count == 1) + finalState = states[0].0 + } else { + for (state, success, _) in states { + finalState.merge(state) + if !success { + hadError = true + } } } return resolveAssociatedMessages(account: account, state: finalState) @@ -1237,6 +1275,127 @@ func keepPollingChannel(account: Account, peerId: PeerId, stateManager: AccountS } |> switchToLatest |> restart } +private func resetChannels(_ account: Account, peers: [Peer], state: AccountMutableState) -> Signal { + var inputPeers: [Api.InputPeer] = [] + for peer in peers { + if let inputPeer = apiInputPeer(peer) { + inputPeers.append(inputPeer) + } + } + return account.network.request(Api.functions.messages.getPeerDialogs(peers: inputPeers)) + |> retryRequest + |> map { result -> AccountMutableState in + var updatedState = state + + var dialogsChats: [Api.Chat] = [] + var dialogsUsers: [Api.User] = [] + + var storeMessages: [StoreMessage] = [] + var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:] + var mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary] = [:] + var channelStates: [PeerId: ChannelState] = [:] + var notificationSettings: [PeerId: PeerNotificationSettings] = [:] + + switch result { + case let .peerDialogs(dialogs, messages, chats, users, _): + dialogsChats.append(contentsOf: chats) + dialogsUsers.append(contentsOf: users) + + for dialog in dialogs { + let apiPeer: Api.Peer + let apiReadInboxMaxId: Int32 + let apiReadOutboxMaxId: Int32 + let apiTopMessage: Int32 + let apiUnreadCount: Int32 + let apiUnreadMentionsCount: Int32 + var apiChannelPts: Int32? + let apiNotificationSettings: Api.PeerNotifySettings + switch dialog { + case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, peerNotificationSettings, pts, _): + apiPeer = peer + apiTopMessage = topMessage + apiReadInboxMaxId = readInboxMaxId + apiReadOutboxMaxId = readOutboxMaxId + apiUnreadCount = unreadCount + apiUnreadMentionsCount = unreadMentionsCount + apiNotificationSettings = peerNotificationSettings + apiChannelPts = pts + } + + let peerId: PeerId + switch apiPeer { + case let .peerUser(userId): + peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + case let .peerChat(chatId): + peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId) + case let .peerChannel(channelId): + peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) + } + + if readStates[peerId] == nil { + readStates[peerId] = [:] + } + readStates[peerId]![Namespaces.Message.Cloud] = .idBased(maxIncomingReadId: apiReadInboxMaxId, maxOutgoingReadId: apiReadOutboxMaxId, maxKnownId: apiTopMessage, count: apiUnreadCount) + + if apiTopMessage != 0 { + mentionTagSummaries[peerId] = MessageHistoryTagNamespaceSummary(version: 1, count: apiUnreadMentionsCount, range: MessageHistoryTagNamespaceCountValidityRange(maxId: apiTopMessage)) + } + + if let apiChannelPts = apiChannelPts { + channelStates[peerId] = ChannelState(pts: apiChannelPts, invalidatedPts: apiChannelPts) + } + + notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings) + } + + for message in messages { + if let storeMessage = StoreMessage(apiMessage: message) { + storeMessages.append(storeMessage) + } + } + } + + updatedState.mergeChats(dialogsChats) + updatedState.mergeUsers(dialogsUsers) + + for message in storeMessages { + if case let .Id(id) = message.id { + updatedState.addHole(MessageId(peerId: id.peerId, namespace: Namespaces.Message.Cloud, id: Int32.max)) + } + } + + updatedState.addMessages(storeMessages, location: .UpperHistoryBlock) + + for (peerId, peerReadStates) in readStates { + for (namespace, state) in peerReadStates { + switch state { + case let .idBased(maxIncomingReadId, maxOutgoingReadId, maxKnownId, count): + updatedState.resetReadState(peerId, namespace: namespace, maxIncomingReadId: maxIncomingReadId, maxOutgoingReadId: maxOutgoingReadId, maxKnownId: maxKnownId, count: count) + default: + assertionFailure() + break + } + } + } + + for (peerId, tagSummary) in mentionTagSummaries { + updatedState.resetMessageTagSummary(peerId, namespace: Namespaces.Message.Cloud, count: tagSummary.count, range: tagSummary.range) + } + + for (peerId, channelState) in channelStates { + updatedState.updateChannelState(peerId, state: channelState) + } + + for (peerId, settings) in notificationSettings { + updatedState.updateNotificationSettings(.peer(peerId), notificationSettings: settings) + } + + // TODO: delete messages later than top + + return updatedState + } +} + private func pollChannel(_ account: Account, peer: Peer, state: AccountMutableState) -> Signal<(AccountMutableState, Bool, Int32?), NoError> { if let inputChannel = apiInputChannel(peer) { var limit: Int32 = 20 @@ -1322,6 +1481,18 @@ private func pollChannel(_ account: Account, peer: Peer, state: AccountMutableSt updatedState.updateMedia(webpage.webpageId, media: webpage) } } + case let .updateChannelAvailableMessages(_, minId): + let messageId = MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: minId) + updatedState.updateMinAvailableMessage(messageId) + updatedState.updateCachedPeerData(peer.id, { current in + let previous: CachedChannelData + if let current = current as? CachedChannelData { + previous = current + } else { + previous = CachedChannelData() + } + return previous.withUpdatedMinAvailableMessageId(messageId) + }) default: break } @@ -1472,7 +1643,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation]) var currentAddMessages: OptimizeAddMessagesState? for operation in operations { switch operation { - case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ResetReadState, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack: + case .AddHole, .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ResetReadState, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedPeerIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage: if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty { result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location)) } @@ -1545,6 +1716,8 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, modifier: Modif modifier.deleteMessagesWithGlobalIds(ids) case let .DeleteMessages(ids): modifier.deleteMessages(ids) + case let .UpdateMinAvailableMessage(id): + modifier.deleteMessagesInRange(peerId: id.peerId, namespace: id.namespace, minId: 1, maxId: id.id) case let .EditMessage(id, message): modifier.updateMessage(id, update: { _ in .update(message) }) case let .UpdateMedia(id, media): diff --git a/TelegramCore/AccountStateManager.swift b/TelegramCore/AccountStateManager.swift index d1aff26e7a..0b1895e349 100644 --- a/TelegramCore/AccountStateManager.swift +++ b/TelegramCore/AccountStateManager.swift @@ -247,30 +247,37 @@ public final class AccountStateManager { |> take(1) |> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in if let authorizedState = state.state { - let request = account.network.request(Api.functions.updates.getDifference(flags: 0, pts: authorizedState.pts, ptsTotalLimit: nil, date: authorizedState.date, qts: authorizedState.qts)) + let request = account.network.request(Api.functions.updates.getDifference(flags: 0 << 0, pts: authorizedState.pts, ptsTotalLimit: 1000, date: authorizedState.date, qts: authorizedState.qts)) |> retryRequest return request |> mapToSignal { difference -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in - return initialStateWithDifference(account, difference: difference) - |> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in - if state.initialState.state != authorizedState { - Logger.shared.log("State", "pollDifference initial state \(authorizedState) != current state \(state.initialState.state)") - return .single((nil, nil)) - } else { - return finalStateWithDifference(account: account, state: state, difference: difference) - |> mapToSignal { finalState -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in - if !finalState.state.preCachedResources.isEmpty { - for (resource, data) in finalState.state.preCachedResources { - account.postbox.mediaBox.storeResourceData(resource.id, data: data) - } + switch difference { + case .differenceTooLong: + return accountStateReset(postbox: account.postbox, network: account.network) |> mapToSignal { _ -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in + return .complete() + } |> then(.single((nil, nil))) + default: + return initialStateWithDifference(account, difference: difference) + |> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in + if state.initialState.state != authorizedState { + Logger.shared.log("State", "pollDifference initial state \(authorizedState) != current state \(state.initialState.state)") + return .single((nil, nil)) + } else { + return finalStateWithDifference(account: account, state: state, difference: difference) + |> mapToSignal { finalState -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in + if !finalState.state.preCachedResources.isEmpty { + for (resource, data) in finalState.state.preCachedResources { + account.postbox.mediaBox.storeResourceData(resource.id, data: data) + } + } + return account.postbox.modify { modifier -> (Api.updates.Difference?, AccountReplayedFinalState?) in + if let replayedState = replayFinalState(accountPeerId: accountPeerId, mediaBox: mediaBox, modifier: modifier, auxiliaryMethods: auxiliaryMethods, finalState: finalState) { + return (difference, replayedState) + } else { + return (nil, nil) + } + } } - return account.postbox.modify { modifier -> (Api.updates.Difference?, AccountReplayedFinalState?) in - if let replayedState = replayFinalState(accountPeerId: accountPeerId, mediaBox: mediaBox, modifier: modifier, auxiliaryMethods: auxiliaryMethods, finalState: finalState) { - return (difference, replayedState) - } else { - return (nil, nil) - } - } - } + } } } } @@ -685,11 +692,20 @@ public func messageForNotification(modifier: Modifier, id: MessageId, alwaysRetu Logger.shared.log("AccountStateManager", "notification message doesn't exist") return (nil, false, .bundledModern(id: 0), false) } - + var notify = true var sound: PeerMessageSound = .bundledModern(id: 0) + var muted = false var displayContents = true + for attribute in message.attributes { + if let attribute = attribute as? NotificationInfoMessageAttribute { + if attribute.flags.contains(.muted) { + muted = true + } + } + } + let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970) var notificationPeerId = id.peerId @@ -731,13 +747,17 @@ public func messageForNotification(modifier: Modifier, id: MessageId, alwaysRetu } else { sound = notificationSettings.messageSound } - if !defaultNotify { + /*if !defaultNotify { notify = false - } + }*/ } else { Logger.shared.log("AccountStateManager", "notification settings for \(notificationPeerId) are undefined") } + if muted { + sound = .none + } + if let channel = message.peers[message.id.peerId] as? TelegramChannel { switch channel.participationStatus { case .kicked, .left: diff --git a/TelegramCore/AccountStateReset.swift b/TelegramCore/AccountStateReset.swift new file mode 100644 index 0000000000..a0b73fae16 --- /dev/null +++ b/TelegramCore/AccountStateReset.swift @@ -0,0 +1,237 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac + import MtProtoKitMac +#else + import Postbox + import SwiftSignalKit + import MtProtoKitDynamic +#endif + +func accountStateReset(postbox: Postbox, network: Network) -> Signal { + let pinnedChats: Signal = network.request(Api.functions.messages.getPinnedDialogs()) + |> retryRequest + let state: Signal = + network.request(Api.functions.updates.getState()) + |> retryRequest + + return combineLatest(network.request(Api.functions.messages.getDialogs(flags: 0, offsetDate: 0, offsetId: 0, offsetPeer: .inputPeerEmpty, limit: 100)) + |> retryRequest, pinnedChats, state) + |> mapToSignal { result, pinnedChats, state -> Signal in + var dialogsDialogs: [Api.Dialog] = [] + var dialogsMessages: [Api.Message] = [] + var dialogsChats: [Api.Chat] = [] + var dialogsUsers: [Api.User] = [] + + var holeExists = false + + switch result { + case let .dialogs(dialogs, messages, chats, users): + dialogsDialogs = dialogs + dialogsMessages = messages + dialogsChats = chats + dialogsUsers = users + case let .dialogsSlice(_, dialogs, messages, chats, users): + dialogsDialogs = dialogs + dialogsMessages = messages + dialogsChats = chats + dialogsUsers = users + holeExists = true + } + + let replacePinnedPeerIds: [PeerId] + switch pinnedChats { + case let .peerDialogs(apiDialogs, apiMessages, apiChats, apiUsers, _): + dialogsDialogs.append(contentsOf: apiDialogs) + dialogsMessages.append(contentsOf: apiMessages) + dialogsChats.append(contentsOf: apiChats) + dialogsUsers.append(contentsOf: apiUsers) + + var peerIds: [PeerId] = [] + + for dialog in apiDialogs { + let apiPeer: Api.Peer + switch dialog { + case let .dialog(_, peer, _, _, _, _, _, _, _, _): + apiPeer = peer + } + + let peerId = apiPeer.peerId + + peerIds.append(peerId) + } + + replacePinnedPeerIds = peerIds + } + + var replacementHole: ChatListHole? + var storeMessages: [StoreMessage] = [] + var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:] + var mentionTagSummaries: [PeerId: MessageHistoryTagNamespaceSummary] = [:] + var chatStates: [PeerId: PeerChatState] = [:] + var notificationSettings: [PeerId: PeerNotificationSettings] = [:] + + var topMesageIds: [PeerId: MessageId] = [:] + + for dialog in dialogsDialogs { + let apiPeer: Api.Peer + let apiReadInboxMaxId: Int32 + let apiReadOutboxMaxId: Int32 + let apiTopMessage: Int32 + let apiUnreadCount: Int32 + let apiUnreadMentionsCount: Int32 + var apiChannelPts: Int32? + let apiNotificationSettings: Api.PeerNotifySettings + switch dialog { + case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, peerNotificationSettings, pts, _): + apiPeer = peer + apiTopMessage = topMessage + apiReadInboxMaxId = readInboxMaxId + apiReadOutboxMaxId = readOutboxMaxId + apiUnreadCount = unreadCount + apiUnreadMentionsCount = unreadMentionsCount + apiNotificationSettings = peerNotificationSettings + apiChannelPts = pts + } + + let peerId: PeerId + switch apiPeer { + case let .peerUser(userId): + peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + case let .peerChat(chatId): + peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId) + case let .peerChannel(channelId): + peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) + } + + if readStates[peerId] == nil { + readStates[peerId] = [:] + } + readStates[peerId]![Namespaces.Message.Cloud] = .idBased(maxIncomingReadId: apiReadInboxMaxId, maxOutgoingReadId: apiReadOutboxMaxId, maxKnownId: apiTopMessage, count: apiUnreadCount) + + if apiTopMessage != 0 { + mentionTagSummaries[peerId] = MessageHistoryTagNamespaceSummary(version: 1, count: apiUnreadMentionsCount, range: MessageHistoryTagNamespaceCountValidityRange(maxId: apiTopMessage)) + topMesageIds[peerId] = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: apiTopMessage) + } + + if let apiChannelPts = apiChannelPts { + chatStates[peerId] = ChannelState(pts: apiChannelPts, invalidatedPts: apiChannelPts) + } else { + switch state { + case let .state(pts, _, _, _, _): + chatStates[peerId] = RegularChatState(invalidatedPts: pts) + } + } + + notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings) + } + + for message in dialogsMessages { + if let storeMessage = StoreMessage(apiMessage: message) { + storeMessages.append(storeMessage) + } + } + + if holeExists { + for dialog in dialogsDialogs { + switch dialog { + case let .dialog(flags, peer, topMessage, _, _, _, _, _, _, _): + let isPinned = (flags & (1 << 2)) != 0 + + if !isPinned { + var timestamp: Int32? + for message in storeMessages { + if case let .Id(id) = message.id, id.id == topMessage { + timestamp = message.timestamp + } + } + + if let timestamp = timestamp { + let index = MessageIndex(id: MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: topMessage - 1), timestamp: timestamp) + if (replacementHole == nil || replacementHole!.index > index) { + replacementHole = ChatListHole(index: index) + } + } + } + } + } + } + + var peers: [Peer] = [] + var peerPresences: [PeerId: PeerPresence] = [:] + for chat in dialogsChats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers.append(groupOrChannel) + } + } + for user in dialogsUsers { + let telegramUser = TelegramUser(user: user) + peers.append(telegramUser) + if let presence = TelegramUserPresence(apiUser: user) { + peerPresences[telegramUser.id] = presence + } + } + + return postbox.modify { modifier -> Void in + modifier.resetChatList(replacementHole: replacementHole) + + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in + return updated + }) + modifier.updatePeerPresences(peerPresences) + + modifier.updateCurrentPeerNotificationSettings(notificationSettings) + + var allPeersWithMessages = Set() + for message in storeMessages { + if !allPeersWithMessages.contains(message.id.peerId) { + allPeersWithMessages.insert(message.id.peerId) + } + } + + for (_, messageId) in topMesageIds { + if messageId.id > 1 { + var skipHole = false + if let localTopId = modifier.getTopMesssageIndex(peerId: messageId.peerId, namespace: messageId.namespace)?.id { + if localTopId >= messageId { + skipHole = true + } + } + if !skipHole { + modifier.addHole(MessageId(peerId: messageId.peerId, namespace: messageId.namespace, id: messageId.id - 1)) + } + } + } + + let _ = modifier.addMessages(storeMessages, location: .UpperHistoryBlock) + + modifier.resetIncomingReadStates(readStates) + + for (peerId, chatState) in chatStates { + if let chatState = chatState as? ChannelState { + if let current = modifier.getPeerChatState(peerId) as? ChannelState { + modifier.setPeerChatState(peerId, state: current.withUpdatedPts(chatState.pts)) + } else { + modifier.setPeerChatState(peerId, state: chatState) + } + } else { + modifier.setPeerChatState(peerId, state: chatState) + } + } + + modifier.setPinnedPeerIds(replacePinnedPeerIds) + + for (peerId, summary) in mentionTagSummaries { + modifier.replaceMessageTagSummary(peerId: peerId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: summary.count, maxId: summary.range.maxId) + } + + if let currentState = modifier.getState() as? AuthorizedAccountState, let embeddedState = currentState.state { + switch state { + case let .state(pts, _, _, seq, _): + modifier.setState(currentState.changedState(AuthorizedAccountState.State(pts: pts, qts: embeddedState.qts, date: embeddedState.date, seq: seq))) + } + } + } + } +} diff --git a/TelegramCore/Api.swift b/TelegramCore/Api.swift index 40d1421fa3..4dfe629f8d 100644 --- a/TelegramCore/Api.swift +++ b/TelegramCore/Api.swift @@ -21,7 +21,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-206066487] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) } dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) } dict[771925524] = { return Api.ChatFull.parse_chatFull($0) } - dict[401891279] = { return Api.ChatFull.parse_channelFull($0) } + dict[1991201921] = { return Api.ChatFull.parse_channelFull($0) } dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) } dict[-636267638] = { return Api.ChatParticipant.parse_chatParticipantCreator($0) } dict[-489233354] = { return Api.ChatParticipant.parse_chatParticipantAdmin($0) } @@ -65,7 +65,13 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-613092008] = { return Api.ChatInvite.parse_chatInvite($0) } dict[1678812626] = { return Api.StickerSetCovered.parse_stickerSetCovered($0) } dict[872932635] = { return Api.StickerSetCovered.parse_stickerSetMultiCovered($0) } + dict[1189204285] = { return Api.RecentMeUrl.parse_recentMeUrlUnknown($0) } + dict[-1917045962] = { return Api.RecentMeUrl.parse_recentMeUrlUser($0) } + dict[-1608834311] = { return Api.RecentMeUrl.parse_recentMeUrlChat($0) } + dict[-347535331] = { return Api.RecentMeUrl.parse_recentMeUrlChatInvite($0) } + dict[-1140172836] = { return Api.RecentMeUrl.parse_recentMeUrlStickerSet($0) } dict[-177282392] = { return Api.channels.ChannelParticipants.parse_channelParticipants($0) } + dict[-266911767] = { return Api.channels.ChannelParticipants.parse_channelParticipantsNotModified($0) } dict[-599948721] = { return Api.RichText.parse_textEmpty($0) } dict[1950782688] = { return Api.RichText.parse_textPlain($0) } dict[1730456516] = { return Api.RichText.parse_textBold($0) } @@ -201,6 +207,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-451831443] = { return Api.Update.parse_updateFavedStickers($0) } dict[-1987495099] = { return Api.Update.parse_updateChannelReadMessagesContents($0) } dict[1887741886] = { return Api.Update.parse_updateContactsReset($0) } + dict[1893427255] = { return Api.Update.parse_updateChannelAvailableMessages($0) } dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) } dict[367766557] = { return Api.ChannelParticipant.parse_channelParticipant($0) } dict[-1557620115] = { return Api.ChannelParticipant.parse_channelParticipantSelf($0) } @@ -265,7 +272,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1798033689] = { return Api.ChannelMessagesFilter.parse_channelMessagesFilterEmpty($0) } dict[-847783593] = { return Api.ChannelMessagesFilter.parse_channelMessagesFilter($0) } dict[326715557] = { return Api.auth.PasswordRecovery.parse_passwordRecovery($0) } - dict[-858565059] = { return Api.messages.BotResults.parse_botResults($0) } + dict[-1803769784] = { return Api.messages.BotResults.parse_botResults($0) } dict[1928391342] = { return Api.InputDocument.parse_inputDocumentEmpty($0) } dict[410618194] = { return Api.InputDocument.parse_inputDocument($0) } dict[2131196633] = { return Api.contacts.ResolvedPeer.parse_resolvedPeer($0) } @@ -274,7 +281,6 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-104578748] = { return Api.InputMedia.parse_inputMediaGeoPoint($0) } dict[-1494984313] = { return Api.InputMedia.parse_inputMediaContact($0) } dict[444068508] = { return Api.InputMedia.parse_inputMediaDocument($0) } - dict[673687578] = { return Api.InputMedia.parse_inputMediaVenue($0) } dict[1212395773] = { return Api.InputMedia.parse_inputMediaGifExternal($0) } dict[-1252045032] = { return Api.InputMedia.parse_inputMediaPhotoExternal($0) } dict[-437690244] = { return Api.InputMedia.parse_inputMediaDocumentExternal($0) } @@ -282,6 +288,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1844103547] = { return Api.InputMedia.parse_inputMediaInvoice($0) } dict[792191537] = { return Api.InputMedia.parse_inputMediaUploadedPhoto($0) } dict[-476700163] = { return Api.InputMedia.parse_inputMediaUploadedDocument($0) } + dict[2065305999] = { return Api.InputMedia.parse_inputMediaGeoLive($0) } + dict[-1052959727] = { return Api.InputMedia.parse_inputMediaVenue($0) } dict[2134579434] = { return Api.InputPeer.parse_inputPeerEmpty($0) } dict[2107670217] = { return Api.InputPeer.parse_inputPeerSelf($0) } dict[396093539] = { return Api.InputPeer.parse_inputPeerChat($0) } @@ -319,6 +327,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-422036098] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantToggleBan($0) } dict[-714643696] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionParticipantToggleAdmin($0) } dict[-1312568665] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionChangeStickerSet($0) } + dict[1599903217] = { return Api.ChannelAdminLogEventAction.parse_channelAdminLogEventActionTogglePreHistoryHidden($0) } dict[-543777747] = { return Api.auth.ExportedAuthorization.parse_exportedAuthorization($0) } dict[-1269012015] = { return Api.messages.AffectedHistory.parse_affectedHistory($0) } dict[-2037289493] = { return Api.account.PasswordInputSettings.parse_passwordInputSettings($0) } @@ -345,6 +354,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1335282456] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyStatusTimestamp($0) } dict[-1107622874] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyChatInvite($0) } dict[-88417185] = { return Api.InputPrivacyKey.parse_inputPrivacyKeyPhoneCall($0) } + dict[235081943] = { return Api.help.RecentMeUrls.parse_recentMeUrls($0) } dict[-1606526075] = { return Api.ReplyMarkup.parse_replyKeyboardHide($0) } dict[-200242528] = { return Api.ReplyMarkup.parse_replyKeyboardForceReply($0) } dict[889353612] = { return Api.ReplyMarkup.parse_replyKeyboardMarkup($0) } @@ -365,7 +375,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[182649427] = { return Api.MessageRange.parse_messageRange($0) } dict[946083368] = { return Api.messages.StickerSetInstallResult.parse_stickerSetInstallResultSuccess($0) } dict[904138920] = { return Api.messages.StickerSetInstallResult.parse_stickerSetInstallResultArchive($0) } - dict[-1913424220] = { return Api.Config.parse_config($0) } + dict[-1669068444] = { return Api.Config.parse_config($0) } dict[-75283823] = { return Api.TopPeerCategoryPeers.parse_topPeerCategoryPeers($0) } dict[-1107729093] = { return Api.Game.parse_game($0) } dict[-1032140601] = { return Api.BotCommand.parse_botCommand($0) } @@ -400,11 +410,12 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1585262393] = { return Api.MessageMedia.parse_messageMediaContact($0) } dict[-1618676578] = { return Api.MessageMedia.parse_messageMediaUnsupported($0) } dict[-1557277184] = { return Api.MessageMedia.parse_messageMediaWebPage($0) } - dict[2031269663] = { return Api.MessageMedia.parse_messageMediaVenue($0) } dict[-38694904] = { return Api.MessageMedia.parse_messageMediaGame($0) } dict[-2074799289] = { return Api.MessageMedia.parse_messageMediaInvoice($0) } dict[-1256047857] = { return Api.MessageMedia.parse_messageMediaPhoto($0) } dict[2084836563] = { return Api.MessageMedia.parse_messageMediaDocument($0) } + dict[2084316681] = { return Api.MessageMedia.parse_messageMediaGeoLive($0) } + dict[784356159] = { return Api.MessageMedia.parse_messageMediaVenue($0) } dict[-842892769] = { return Api.PaymentSavedCredentials.parse_paymentSavedCredentialsCard($0) } dict[1450380236] = { return Api.Null.parse_null($0) } dict[1923290508] = { return Api.auth.CodeType.parse_codeTypeSms($0) } @@ -448,6 +459,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1061556205] = { return Api.ChatParticipants.parse_chatParticipants($0) } dict[-1056001329] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentialsSaved($0) } dict[873977640] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentials($0) } + dict[178373535] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentialsApplePay($0) } + dict[2035705766] = { return Api.InputPaymentCredentials.parse_inputPaymentCredentialsAndroidPay($0) } dict[-1239335713] = { return Api.ShippingOption.parse_shippingOption($0) } dict[512535275] = { return Api.PostAddress.parse_postAddress($0) } dict[2104790276] = { return Api.DataJSON.parse_dataJSON($0) } @@ -490,6 +503,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1253451181] = { return Api.MessagesFilter.parse_inputMessagesFilterRoundVideo($0) } dict[-1040652646] = { return Api.MessagesFilter.parse_inputMessagesFilterMyMentions($0) } dict[1187706024] = { return Api.MessagesFilter.parse_inputMessagesFilterMyMentionsUnread($0) } + dict[-419271411] = { return Api.MessagesFilter.parse_inputMessagesFilterGeo($0) } + dict[-530392189] = { return Api.MessagesFilter.parse_inputMessagesFilterContacts($0) } dict[364538944] = { return Api.messages.Dialogs.parse_dialogs($0) } dict[1910543603] = { return Api.messages.Dialogs.parse_dialogsSlice($0) } dict[-290921362] = { return Api.upload.CdnFile.parse_cdnFileReuploadNeeded($0) } @@ -542,6 +557,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1080663248] = { return Api.MessageAction.parse_messageActionPaymentSent($0) } dict[-2132731265] = { return Api.MessageAction.parse_messageActionPhoneCall($0) } dict[1200788123] = { return Api.MessageAction.parse_messageActionScreenshotTaken($0) } + dict[-85549226] = { return Api.MessageAction.parse_messageActionCustomAction($0) } dict[1399245077] = { return Api.PhoneCall.parse_phoneCallEmpty($0) } dict[462375633] = { return Api.PhoneCall.parse_phoneCallWaiting($0) } dict[-2089411356] = { return Api.PhoneCall.parse_phoneCallRequested($0) } @@ -676,6 +692,8 @@ public struct Api { _1.serialize(buffer, boxed) case let _1 as Api.StickerSetCovered: _1.serialize(buffer, boxed) + case let _1 as Api.RecentMeUrl: + _1.serialize(buffer, boxed) case let _1 as Api.channels.ChannelParticipants: _1.serialize(buffer, boxed) case let _1 as Api.RichText: @@ -834,6 +852,8 @@ public struct Api { _1.serialize(buffer, boxed) case let _1 as Api.InputPrivacyKey: _1.serialize(buffer, boxed) + case let _1 as Api.help.RecentMeUrls: + _1.serialize(buffer, boxed) case let _1 as Api.ReplyMarkup: _1.serialize(buffer, boxed) case let _1 as Api.HighScore: @@ -1285,13 +1305,13 @@ public struct Api { } public enum BotResults { - case botResults(flags: Int32, queryId: Int64, nextOffset: String?, switchPm: Api.InlineBotSwitchPM?, results: [Api.BotInlineResult], cacheTime: Int32) + case botResults(flags: Int32, queryId: Int64, nextOffset: String?, switchPm: Api.InlineBotSwitchPM?, results: [Api.BotInlineResult], cacheTime: Int32, users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .botResults(let flags, let queryId, let nextOffset, let switchPm, let results, let cacheTime): + case .botResults(let flags, let queryId, let nextOffset, let switchPm, let results, let cacheTime, let users): if boxed { - buffer.appendInt32(-858565059) + buffer.appendInt32(-1803769784) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt64(queryId, buffer: buffer, boxed: false) @@ -1303,6 +1323,11 @@ public struct Api { item.serialize(buffer, true) } serializeInt32(cacheTime, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } break } } @@ -1324,14 +1349,19 @@ public struct Api { } var _6: Int32? _6 = reader.readInt32() + var _7: [Api.User]? + if let _ = reader.readInt32() { + _7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil let _c5 = _5 != nil let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.messages.BotResults.botResults(flags: _1!, queryId: _2!, nextOffset: _3, switchPm: _4, results: _5!, cacheTime: _6!) + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.messages.BotResults.botResults(flags: _1!, queryId: _2!, nextOffset: _3, switchPm: _4, results: _5!, cacheTime: _6!, users: _7!) } else { return nil @@ -2389,7 +2419,7 @@ public struct Api { public enum ChatFull { case chatFull(id: Int32, participants: Api.ChatParticipants, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo]) - case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?) + case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -2408,9 +2438,9 @@ public struct Api { item.serialize(buffer, true) } break - case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset): + case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId): if boxed { - buffer.appendInt32(401891279) + buffer.appendInt32(1991201921) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(id, buffer: buffer, boxed: false) @@ -2434,6 +2464,7 @@ public struct Api { if Int(flags) & Int(1 << 4) != 0 {serializeInt32(migratedFromMaxId!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 5) != 0 {serializeInt32(pinnedMsgId!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 8) != 0 {stickerset!.serialize(buffer, true)} + if Int(flags) & Int(1 << 9) != 0 {serializeInt32(availableMinId!, buffer: buffer, boxed: false)} break } } @@ -2521,6 +2552,8 @@ public struct Api { if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() { _18 = Api.parse(reader, signature: signature) as? Api.StickerSet } } + var _19: Int32? + if Int(_1!) & Int(1 << 9) != 0 {_19 = reader.readInt32() } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil @@ -2539,8 +2572,9 @@ public struct Api { let _c16 = (Int(_1!) & Int(1 << 4) == 0) || _16 != nil let _c17 = (Int(_1!) & Int(1 << 5) == 0) || _17 != nil let _c18 = (Int(_1!) & Int(1 << 8) == 0) || _18 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 { - return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, readInboxMaxId: _8!, readOutboxMaxId: _9!, unreadCount: _10!, chatPhoto: _11!, notifySettings: _12!, exportedInvite: _13!, botInfo: _14!, migratedFromChatId: _15, migratedFromMaxId: _16, pinnedMsgId: _17, stickerset: _18) + let _c19 = (Int(_1!) & Int(1 << 9) == 0) || _19 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 { + return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, readInboxMaxId: _8!, readOutboxMaxId: _9!, unreadCount: _10!, chatPhoto: _11!, notifySettings: _12!, exportedInvite: _13!, botInfo: _14!, migratedFromChatId: _15, migratedFromMaxId: _16, pinnedMsgId: _17, stickerset: _18, availableMinId: _19) } else { return nil @@ -3635,6 +3669,126 @@ public struct Api { } + public enum RecentMeUrl { + case recentMeUrlUnknown(url: String) + case recentMeUrlUser(url: String, userId: Int32) + case recentMeUrlChat(url: String, chatId: Int32) + case recentMeUrlChatInvite(url: String, chatInvite: Api.ChatInvite) + case recentMeUrlStickerSet(url: String, set: Api.StickerSetCovered) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .recentMeUrlUnknown(let url): + if boxed { + buffer.appendInt32(1189204285) + } + serializeString(url, buffer: buffer, boxed: false) + break + case .recentMeUrlUser(let url, let userId): + if boxed { + buffer.appendInt32(-1917045962) + } + serializeString(url, buffer: buffer, boxed: false) + serializeInt32(userId, buffer: buffer, boxed: false) + break + case .recentMeUrlChat(let url, let chatId): + if boxed { + buffer.appendInt32(-1608834311) + } + serializeString(url, buffer: buffer, boxed: false) + serializeInt32(chatId, buffer: buffer, boxed: false) + break + case .recentMeUrlChatInvite(let url, let chatInvite): + if boxed { + buffer.appendInt32(-347535331) + } + serializeString(url, buffer: buffer, boxed: false) + chatInvite.serialize(buffer, true) + break + case .recentMeUrlStickerSet(let url, let set): + if boxed { + buffer.appendInt32(-1140172836) + } + serializeString(url, buffer: buffer, boxed: false) + set.serialize(buffer, true) + break + } + } + + fileprivate static func parse_recentMeUrlUnknown(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.RecentMeUrl.recentMeUrlUnknown(url: _1!) + } + else { + return nil + } + } + fileprivate static func parse_recentMeUrlUser(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.RecentMeUrl.recentMeUrlUser(url: _1!, userId: _2!) + } + else { + return nil + } + } + fileprivate static func parse_recentMeUrlChat(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.RecentMeUrl.recentMeUrlChat(url: _1!, chatId: _2!) + } + else { + return nil + } + } + fileprivate static func parse_recentMeUrlChatInvite(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) + var _2: Api.ChatInvite? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.ChatInvite + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.RecentMeUrl.recentMeUrlChatInvite(url: _1!, chatInvite: _2!) + } + else { + return nil + } + } + fileprivate static func parse_recentMeUrlStickerSet(_ reader: BufferReader) -> RecentMeUrl? { + var _1: String? + _1 = parseString(reader) + var _2: Api.StickerSetCovered? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.StickerSetCovered + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.RecentMeUrl.recentMeUrlStickerSet(url: _1!, set: _2!) + } + else { + return nil + } + } + + } + public indirect enum RichText { case textEmpty case textPlain(text: String) @@ -4845,6 +4999,7 @@ public struct Api { case updateFavedStickers case updateChannelReadMessagesContents(channelId: Int32, messages: [Int32]) case updateContactsReset + case updateChannelAvailableMessages(channelId: Int32, availableMinId: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -5384,6 +5539,13 @@ public struct Api { buffer.appendInt32(1887741886) } + break + case .updateChannelAvailableMessages(let channelId, let availableMinId): + if boxed { + buffer.appendInt32(1893427255) + } + serializeInt32(channelId, buffer: buffer, boxed: false) + serializeInt32(availableMinId, buffer: buffer, boxed: false) break } } @@ -6462,6 +6624,20 @@ public struct Api { fileprivate static func parse_updateContactsReset(_ reader: BufferReader) -> Update? { return Api.Update.updateContactsReset } + fileprivate static func parse_updateChannelAvailableMessages(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.Update.updateChannelAvailableMessages(channelId: _1!, availableMinId: _2!) + } + else { + return nil + } + } } @@ -7969,7 +8145,6 @@ public struct Api { case inputMediaGeoPoint(geoPoint: Api.InputGeoPoint) case inputMediaContact(phoneNumber: String, firstName: String, lastName: String) case inputMediaDocument(id: Api.InputDocument, caption: String) - case inputMediaVenue(geoPoint: Api.InputGeoPoint, title: String, address: String, provider: String, venueId: String) case inputMediaGifExternal(url: String, q: String) case inputMediaPhotoExternal(url: String, caption: String) case inputMediaDocumentExternal(url: String, caption: String) @@ -7977,6 +8152,8 @@ public struct Api { case inputMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String, startParam: String) case inputMediaUploadedPhoto(flags: Int32, file: Api.InputFile, caption: String, stickers: [Api.InputDocument]?, ttlSeconds: Int32?) case inputMediaUploadedDocument(flags: Int32, file: Api.InputFile, thumb: Api.InputFile?, mimeType: String, attributes: [Api.DocumentAttribute], caption: String, stickers: [Api.InputDocument]?, ttlSeconds: Int32?) + case inputMediaGeoLive(geoPoint: Api.InputGeoPoint, period: Int32) + case inputMediaVenue(geoPoint: Api.InputGeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -8014,16 +8191,6 @@ public struct Api { id.serialize(buffer, true) serializeString(caption, buffer: buffer, boxed: false) break - case .inputMediaVenue(let geoPoint, let title, let address, let provider, let venueId): - if boxed { - buffer.appendInt32(673687578) - } - geoPoint.serialize(buffer, true) - serializeString(title, buffer: buffer, boxed: false) - serializeString(address, buffer: buffer, boxed: false) - serializeString(provider, buffer: buffer, boxed: false) - serializeString(venueId, buffer: buffer, boxed: false) - break case .inputMediaGifExternal(let url, let q): if boxed { buffer.appendInt32(1212395773) @@ -8099,6 +8266,24 @@ public struct Api { }} if Int(flags) & Int(1 << 1) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)} break + case .inputMediaGeoLive(let geoPoint, let period): + if boxed { + buffer.appendInt32(2065305999) + } + geoPoint.serialize(buffer, true) + serializeInt32(period, buffer: buffer, boxed: false) + break + case .inputMediaVenue(let geoPoint, let title, let address, let provider, let venueId, let venueType): + if boxed { + buffer.appendInt32(-1052959727) + } + geoPoint.serialize(buffer, true) + serializeString(title, buffer: buffer, boxed: false) + serializeString(address, buffer: buffer, boxed: false) + serializeString(provider, buffer: buffer, boxed: false) + serializeString(venueId, buffer: buffer, boxed: false) + serializeString(venueType, buffer: buffer, boxed: false) + break } } @@ -8167,31 +8352,6 @@ public struct Api { return nil } } - fileprivate static func parse_inputMediaVenue(_ reader: BufferReader) -> InputMedia? { - var _1: Api.InputGeoPoint? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint - } - var _2: String? - _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: String? - _5 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.InputMedia.inputMediaVenue(geoPoint: _1!, title: _2!, address: _3!, provider: _4!, venueId: _5!) - } - else { - return nil - } - } fileprivate static func parse_inputMediaGifExternal(_ reader: BufferReader) -> InputMedia? { var _1: String? _1 = parseString(reader) @@ -8350,6 +8510,50 @@ public struct Api { return nil } } + fileprivate static func parse_inputMediaGeoLive(_ reader: BufferReader) -> InputMedia? { + var _1: Api.InputGeoPoint? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.InputMedia.inputMediaGeoLive(geoPoint: _1!, period: _2!) + } + else { + return nil + } + } + fileprivate static func parse_inputMediaVenue(_ reader: BufferReader) -> InputMedia? { + var _1: Api.InputGeoPoint? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint + } + var _2: String? + _2 = parseString(reader) + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: String? + _5 = parseString(reader) + var _6: String? + _6 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.InputMedia.inputMediaVenue(geoPoint: _1!, title: _2!, address: _3!, provider: _4!, venueId: _5!, venueType: _6!) + } + else { + return nil + } + } } @@ -8723,6 +8927,7 @@ public struct Api { case channelAdminLogEventActionParticipantToggleBan(prevParticipant: Api.ChannelParticipant, newParticipant: Api.ChannelParticipant) case channelAdminLogEventActionParticipantToggleAdmin(prevParticipant: Api.ChannelParticipant, newParticipant: Api.ChannelParticipant) case channelAdminLogEventActionChangeStickerSet(prevStickerset: Api.InputStickerSet, newStickerset: Api.InputStickerSet) + case channelAdminLogEventActionTogglePreHistoryHidden(newValue: Api.Bool) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -8824,6 +9029,12 @@ public struct Api { prevStickerset.serialize(buffer, true) newStickerset.serialize(buffer, true) break + case .channelAdminLogEventActionTogglePreHistoryHidden(let newValue): + if boxed { + buffer.appendInt32(1599903217) + } + newValue.serialize(buffer, true) + break } } @@ -9030,6 +9241,19 @@ public struct Api { return nil } } + fileprivate static func parse_channelAdminLogEventActionTogglePreHistoryHidden(_ reader: BufferReader) -> ChannelAdminLogEventAction? { + var _1: Api.Bool? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.Bool + } + let _c1 = _1 != nil + if _c1 { + return Api.ChannelAdminLogEventAction.channelAdminLogEventActionTogglePreHistoryHidden(newValue: _1!) + } + else { + return nil + } + } } @@ -9880,13 +10104,13 @@ public struct Api { } public enum Config { - case config(flags: Int32, date: Int32, expires: Int32, testMode: Api.Bool, thisDc: Int32, dcOptions: [Api.DcOption], chatSizeMax: Int32, megagroupSizeMax: Int32, forwardedCountMax: Int32, onlineUpdatePeriodMs: Int32, offlineBlurTimeoutMs: Int32, offlineIdleTimeoutMs: Int32, onlineCloudTimeoutMs: Int32, notifyCloudDelayMs: Int32, notifyDefaultDelayMs: Int32, chatBigSize: Int32, pushChatPeriodMs: Int32, pushChatLimit: Int32, savedGifsLimit: Int32, editTimeLimit: Int32, ratingEDecay: Int32, stickersRecentLimit: Int32, stickersFavedLimit: Int32, tmpSessions: Int32?, pinnedDialogsCountMax: Int32, callReceiveTimeoutMs: Int32, callRingTimeoutMs: Int32, callConnectTimeoutMs: Int32, callPacketTimeoutMs: Int32, meUrlPrefix: String, suggestedLangCode: String?, langPackVersion: Int32?, disabledFeatures: [Api.DisabledFeature]) + case config(flags: Int32, date: Int32, expires: Int32, testMode: Api.Bool, thisDc: Int32, dcOptions: [Api.DcOption], chatSizeMax: Int32, megagroupSizeMax: Int32, forwardedCountMax: Int32, onlineUpdatePeriodMs: Int32, offlineBlurTimeoutMs: Int32, offlineIdleTimeoutMs: Int32, onlineCloudTimeoutMs: Int32, notifyCloudDelayMs: Int32, notifyDefaultDelayMs: Int32, chatBigSize: Int32, pushChatPeriodMs: Int32, pushChatLimit: Int32, savedGifsLimit: Int32, editTimeLimit: Int32, ratingEDecay: Int32, stickersRecentLimit: Int32, stickersFavedLimit: Int32, channelsReadMediaPeriod: Int32, tmpSessions: Int32?, pinnedDialogsCountMax: Int32, callReceiveTimeoutMs: Int32, callRingTimeoutMs: Int32, callConnectTimeoutMs: Int32, callPacketTimeoutMs: Int32, meUrlPrefix: String, suggestedLangCode: String?, langPackVersion: Int32?, disabledFeatures: [Api.DisabledFeature]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .config(let flags, let date, let expires, let testMode, let thisDc, let dcOptions, let chatSizeMax, let megagroupSizeMax, let forwardedCountMax, let onlineUpdatePeriodMs, let offlineBlurTimeoutMs, let offlineIdleTimeoutMs, let onlineCloudTimeoutMs, let notifyCloudDelayMs, let notifyDefaultDelayMs, let chatBigSize, let pushChatPeriodMs, let pushChatLimit, let savedGifsLimit, let editTimeLimit, let ratingEDecay, let stickersRecentLimit, let stickersFavedLimit, let tmpSessions, let pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, let suggestedLangCode, let langPackVersion, let disabledFeatures): + case .config(let flags, let date, let expires, let testMode, let thisDc, let dcOptions, let chatSizeMax, let megagroupSizeMax, let forwardedCountMax, let onlineUpdatePeriodMs, let offlineBlurTimeoutMs, let offlineIdleTimeoutMs, let onlineCloudTimeoutMs, let notifyCloudDelayMs, let notifyDefaultDelayMs, let chatBigSize, let pushChatPeriodMs, let pushChatLimit, let savedGifsLimit, let editTimeLimit, let ratingEDecay, let stickersRecentLimit, let stickersFavedLimit, let channelsReadMediaPeriod, let tmpSessions, let pinnedDialogsCountMax, let callReceiveTimeoutMs, let callRingTimeoutMs, let callConnectTimeoutMs, let callPacketTimeoutMs, let meUrlPrefix, let suggestedLangCode, let langPackVersion, let disabledFeatures): if boxed { - buffer.appendInt32(-1913424220) + buffer.appendInt32(-1669068444) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(date, buffer: buffer, boxed: false) @@ -9915,6 +10139,7 @@ public struct Api { serializeInt32(ratingEDecay, buffer: buffer, boxed: false) serializeInt32(stickersRecentLimit, buffer: buffer, boxed: false) serializeInt32(stickersFavedLimit, buffer: buffer, boxed: false) + serializeInt32(channelsReadMediaPeriod, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 0) != 0 {serializeInt32(tmpSessions!, buffer: buffer, boxed: false)} serializeInt32(pinnedDialogsCountMax, buffer: buffer, boxed: false) serializeInt32(callReceiveTimeoutMs, buffer: buffer, boxed: false) @@ -9985,9 +10210,9 @@ public struct Api { var _23: Int32? _23 = reader.readInt32() var _24: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_24 = reader.readInt32() } + _24 = reader.readInt32() var _25: Int32? - _25 = reader.readInt32() + if Int(_1!) & Int(1 << 0) != 0 {_25 = reader.readInt32() } var _26: Int32? _26 = reader.readInt32() var _27: Int32? @@ -9996,15 +10221,17 @@ public struct Api { _28 = reader.readInt32() var _29: Int32? _29 = reader.readInt32() - var _30: String? - _30 = parseString(reader) + var _30: Int32? + _30 = reader.readInt32() var _31: String? - if Int(_1!) & Int(1 << 2) != 0 {_31 = parseString(reader) } - var _32: Int32? - if Int(_1!) & Int(1 << 2) != 0 {_32 = reader.readInt32() } - var _33: [Api.DisabledFeature]? + _31 = parseString(reader) + var _32: String? + if Int(_1!) & Int(1 << 2) != 0 {_32 = parseString(reader) } + var _33: Int32? + if Int(_1!) & Int(1 << 2) != 0 {_33 = reader.readInt32() } + var _34: [Api.DisabledFeature]? if let _ = reader.readInt32() { - _33 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DisabledFeature.self) + _34 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DisabledFeature.self) } let _c1 = _1 != nil let _c2 = _2 != nil @@ -10029,18 +10256,19 @@ public struct Api { let _c21 = _21 != nil let _c22 = _22 != nil let _c23 = _23 != nil - let _c24 = (Int(_1!) & Int(1 << 0) == 0) || _24 != nil - let _c25 = _25 != nil + let _c24 = _24 != nil + let _c25 = (Int(_1!) & Int(1 << 0) == 0) || _25 != nil let _c26 = _26 != nil let _c27 = _27 != nil let _c28 = _28 != nil let _c29 = _29 != nil let _c30 = _30 != nil - let _c31 = (Int(_1!) & Int(1 << 2) == 0) || _31 != nil + let _c31 = _31 != nil let _c32 = (Int(_1!) & Int(1 << 2) == 0) || _32 != nil - let _c33 = _33 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 { - return Api.Config.config(flags: _1!, date: _2!, expires: _3!, testMode: _4!, thisDc: _5!, dcOptions: _6!, chatSizeMax: _7!, megagroupSizeMax: _8!, forwardedCountMax: _9!, onlineUpdatePeriodMs: _10!, offlineBlurTimeoutMs: _11!, offlineIdleTimeoutMs: _12!, onlineCloudTimeoutMs: _13!, notifyCloudDelayMs: _14!, notifyDefaultDelayMs: _15!, chatBigSize: _16!, pushChatPeriodMs: _17!, pushChatLimit: _18!, savedGifsLimit: _19!, editTimeLimit: _20!, ratingEDecay: _21!, stickersRecentLimit: _22!, stickersFavedLimit: _23!, tmpSessions: _24, pinnedDialogsCountMax: _25!, callReceiveTimeoutMs: _26!, callRingTimeoutMs: _27!, callConnectTimeoutMs: _28!, callPacketTimeoutMs: _29!, meUrlPrefix: _30!, suggestedLangCode: _31, langPackVersion: _32, disabledFeatures: _33!) + let _c33 = (Int(_1!) & Int(1 << 2) == 0) || _33 != nil + let _c34 = _34 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 && _c34 { + return Api.Config.config(flags: _1!, date: _2!, expires: _3!, testMode: _4!, thisDc: _5!, dcOptions: _6!, chatSizeMax: _7!, megagroupSizeMax: _8!, forwardedCountMax: _9!, onlineUpdatePeriodMs: _10!, offlineBlurTimeoutMs: _11!, offlineIdleTimeoutMs: _12!, onlineCloudTimeoutMs: _13!, notifyCloudDelayMs: _14!, notifyDefaultDelayMs: _15!, chatBigSize: _16!, pushChatPeriodMs: _17!, pushChatLimit: _18!, savedGifsLimit: _19!, editTimeLimit: _20!, ratingEDecay: _21!, stickersRecentLimit: _22!, stickersFavedLimit: _23!, channelsReadMediaPeriod: _24!, tmpSessions: _25, pinnedDialogsCountMax: _26!, callReceiveTimeoutMs: _27!, callRingTimeoutMs: _28!, callConnectTimeoutMs: _29!, callPacketTimeoutMs: _30!, meUrlPrefix: _31!, suggestedLangCode: _32, langPackVersion: _33, disabledFeatures: _34!) } else { return nil @@ -10891,11 +11119,12 @@ public struct Api { case messageMediaContact(phoneNumber: String, firstName: String, lastName: String, userId: Int32) case messageMediaUnsupported case messageMediaWebPage(webpage: Api.WebPage) - case messageMediaVenue(geo: Api.GeoPoint, title: String, address: String, provider: String, venueId: String) case messageMediaGame(game: Api.Game) case messageMediaInvoice(flags: Int32, title: String, description: String, photo: Api.WebDocument?, receiptMsgId: Int32?, currency: String, totalAmount: Int64, startParam: String) case messageMediaPhoto(flags: Int32, photo: Api.Photo?, caption: String?, ttlSeconds: Int32?) case messageMediaDocument(flags: Int32, document: Api.Document?, caption: String?, ttlSeconds: Int32?) + case messageMediaGeoLive(geo: Api.GeoPoint, period: Int32) + case messageMediaVenue(geo: Api.GeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -10932,16 +11161,6 @@ public struct Api { } webpage.serialize(buffer, true) break - case .messageMediaVenue(let geo, let title, let address, let provider, let venueId): - if boxed { - buffer.appendInt32(2031269663) - } - geo.serialize(buffer, true) - serializeString(title, buffer: buffer, boxed: false) - serializeString(address, buffer: buffer, boxed: false) - serializeString(provider, buffer: buffer, boxed: false) - serializeString(venueId, buffer: buffer, boxed: false) - break case .messageMediaGame(let game): if boxed { buffer.appendInt32(-38694904) @@ -10979,6 +11198,24 @@ public struct Api { if Int(flags) & Int(1 << 1) != 0 {serializeString(caption!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 2) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)} break + case .messageMediaGeoLive(let geo, let period): + if boxed { + buffer.appendInt32(2084316681) + } + geo.serialize(buffer, true) + serializeInt32(period, buffer: buffer, boxed: false) + break + case .messageMediaVenue(let geo, let title, let address, let provider, let venueId, let venueType): + if boxed { + buffer.appendInt32(784356159) + } + geo.serialize(buffer, true) + serializeString(title, buffer: buffer, boxed: false) + serializeString(address, buffer: buffer, boxed: false) + serializeString(provider, buffer: buffer, boxed: false) + serializeString(venueId, buffer: buffer, boxed: false) + serializeString(venueType, buffer: buffer, boxed: false) + break } } @@ -11034,31 +11271,6 @@ public struct Api { return nil } } - fileprivate static func parse_messageMediaVenue(_ reader: BufferReader) -> MessageMedia? { - var _1: Api.GeoPoint? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.GeoPoint - } - var _2: String? - _2 = parseString(reader) - var _3: String? - _3 = parseString(reader) - var _4: String? - _4 = parseString(reader) - var _5: String? - _5 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 { - return Api.MessageMedia.messageMediaVenue(geo: _1!, title: _2!, address: _3!, provider: _4!, venueId: _5!) - } - else { - return nil - } - } fileprivate static func parse_messageMediaGame(_ reader: BufferReader) -> MessageMedia? { var _1: Api.Game? if let signature = reader.readInt32() { @@ -11150,6 +11362,50 @@ public struct Api { return nil } } + fileprivate static func parse_messageMediaGeoLive(_ reader: BufferReader) -> MessageMedia? { + var _1: Api.GeoPoint? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.GeoPoint + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.MessageMedia.messageMediaGeoLive(geo: _1!, period: _2!) + } + else { + return nil + } + } + fileprivate static func parse_messageMediaVenue(_ reader: BufferReader) -> MessageMedia? { + var _1: Api.GeoPoint? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.GeoPoint + } + var _2: String? + _2 = parseString(reader) + var _3: String? + _3 = parseString(reader) + var _4: String? + _4 = parseString(reader) + var _5: String? + _5 = parseString(reader) + var _6: String? + _6 = parseString(reader) + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.MessageMedia.messageMediaVenue(geo: _1!, title: _2!, address: _3!, provider: _4!, venueId: _5!, venueType: _6!) + } + else { + return nil + } + } } @@ -12122,6 +12378,8 @@ public struct Api { public enum InputPaymentCredentials { case inputPaymentCredentialsSaved(id: String, tmpPassword: Buffer) case inputPaymentCredentials(flags: Int32, data: Api.DataJSON) + case inputPaymentCredentialsApplePay(paymentData: Api.DataJSON) + case inputPaymentCredentialsAndroidPay(paymentToken: Api.DataJSON) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -12139,6 +12397,18 @@ public struct Api { serializeInt32(flags, buffer: buffer, boxed: false) data.serialize(buffer, true) break + case .inputPaymentCredentialsApplePay(let paymentData): + if boxed { + buffer.appendInt32(178373535) + } + paymentData.serialize(buffer, true) + break + case .inputPaymentCredentialsAndroidPay(let paymentToken): + if boxed { + buffer.appendInt32(2035705766) + } + paymentToken.serialize(buffer, true) + break } } @@ -12172,6 +12442,32 @@ public struct Api { return nil } } + fileprivate static func parse_inputPaymentCredentialsApplePay(_ reader: BufferReader) -> InputPaymentCredentials? { + var _1: Api.DataJSON? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.DataJSON + } + let _c1 = _1 != nil + if _c1 { + return Api.InputPaymentCredentials.inputPaymentCredentialsApplePay(paymentData: _1!) + } + else { + return nil + } + } + fileprivate static func parse_inputPaymentCredentialsAndroidPay(_ reader: BufferReader) -> InputPaymentCredentials? { + var _1: Api.DataJSON? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.DataJSON + } + let _c1 = _1 != nil + if _c1 { + return Api.InputPaymentCredentials.inputPaymentCredentialsAndroidPay(paymentToken: _1!) + } + else { + return nil + } + } } @@ -12740,6 +13036,8 @@ public struct Api { case inputMessagesFilterRoundVideo case inputMessagesFilterMyMentions case inputMessagesFilterMyMentionsUnread + case inputMessagesFilterGeo + case inputMessagesFilterContacts public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -12838,6 +13136,18 @@ public struct Api { buffer.appendInt32(1187706024) } + break + case .inputMessagesFilterGeo: + if boxed { + buffer.appendInt32(-419271411) + } + + break + case .inputMessagesFilterContacts: + if boxed { + buffer.appendInt32(-530392189) + } + break } } @@ -12898,6 +13208,12 @@ public struct Api { fileprivate static func parse_inputMessagesFilterMyMentionsUnread(_ reader: BufferReader) -> MessagesFilter? { return Api.MessagesFilter.inputMessagesFilterMyMentionsUnread } + fileprivate static func parse_inputMessagesFilterGeo(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterGeo + } + fileprivate static func parse_inputMessagesFilterContacts(_ reader: BufferReader) -> MessagesFilter? { + return Api.MessagesFilter.inputMessagesFilterContacts + } } @@ -13654,6 +13970,7 @@ public struct Api { case messageActionPaymentSent(currency: String, totalAmount: Int64) case messageActionPhoneCall(flags: Int32, callId: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?) case messageActionScreenshotTaken + case messageActionCustomAction(message: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -13785,6 +14102,12 @@ public struct Api { buffer.appendInt32(1200788123) } + break + case .messageActionCustomAction(let message): + if boxed { + buffer.appendInt32(-85549226) + } + serializeString(message, buffer: buffer, boxed: false) break } } @@ -13998,6 +14321,17 @@ public struct Api { fileprivate static func parse_messageActionScreenshotTaken(_ reader: BufferReader) -> MessageAction? { return Api.MessageAction.messageActionScreenshotTaken } + fileprivate static func parse_messageActionCustomAction(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.MessageAction.messageActionCustomAction(message: _1!) + } + else { + return nil + } + } } @@ -15274,6 +15608,7 @@ public struct Api { public struct channels { public enum ChannelParticipants { case channelParticipants(count: Int32, participants: [Api.ChannelParticipant], users: [Api.User]) + case channelParticipantsNotModified public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -15292,6 +15627,12 @@ public struct Api { for item in users { item.serialize(buffer, true) } + break + case .channelParticipantsNotModified: + if boxed { + buffer.appendInt32(-266911767) + } + break } } @@ -15317,6 +15658,9 @@ public struct Api { return nil } } + fileprivate static func parse_channelParticipantsNotModified(_ reader: BufferReader) -> ChannelParticipants? { + return Api.channels.ChannelParticipants.channelParticipantsNotModified + } } @@ -16496,6 +16840,60 @@ public struct Api { } + public enum RecentMeUrls { + case recentMeUrls(urls: [Api.RecentMeUrl], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .recentMeUrls(let urls, let chats, let users): + if boxed { + buffer.appendInt32(235081943) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(urls.count)) + for item in urls { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(chats.count)) + for item in chats { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + break + } + } + + fileprivate static func parse_recentMeUrls(_ reader: BufferReader) -> RecentMeUrls? { + var _1: [Api.RecentMeUrl]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RecentMeUrl.self) + } + var _2: [Api.Chat]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _3: [Api.User]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.help.RecentMeUrls.recentMeUrls(urls: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } + public enum Support { case support(phoneNumber: String, user: Api.User) @@ -19148,6 +19546,52 @@ public struct Api { return result }) } + + public static func readMentions(peer: Api.InputPeer) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.messages.AffectedHistory?) { + let buffer = Buffer() + buffer.appendInt32(251759059) + peer.serialize(buffer, true) + return (FunctionDescription({return "(messages.readMentions peer: \(peer))"}), buffer, { (buffer: Buffer) -> Api.messages.AffectedHistory? in + let reader = BufferReader(buffer) + var result: Api.messages.AffectedHistory? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.AffectedHistory + } + return result + }) + } + + public static func editGeoLive(flags: Int32, peer: Api.InputPeer, id: Int32, geoPoint: Api.InputGeoPoint?) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Updates?) { + let buffer = Buffer() + buffer.appendInt32(-1701695410) + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {geoPoint!.serialize(buffer, true)} + return (FunctionDescription({return "(messages.editGeoLive flags: \(flags), peer: \(peer), id: \(id), geoPoint: \(String(describing: geoPoint)))"}), buffer, { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } + + public static func getRecentLocations(peer: Api.InputPeer, limit: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.messages.Messages?) { + let buffer = Buffer() + buffer.appendInt32(613691874) + peer.serialize(buffer, true) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription({return "(messages.getRecentLocations peer: \(peer), limit: \(limit))"}), buffer, { (buffer: Buffer) -> Api.messages.Messages? in + let reader = BufferReader(buffer) + var result: Api.messages.Messages? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Messages + } + return result + }) + } } public struct channels { public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { @@ -19238,23 +19682,6 @@ public struct Api { }) } - public static func getParticipants(channel: Api.InputChannel, filter: Api.ChannelParticipantsFilter, offset: Int32, limit: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.channels.ChannelParticipants?) { - let buffer = Buffer() - buffer.appendInt32(618237842) - channel.serialize(buffer, true) - filter.serialize(buffer, true) - serializeInt32(offset, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription({return "(channels.getParticipants channel: \(channel), filter: \(filter), offset: \(offset), limit: \(limit))"}), buffer, { (buffer: Buffer) -> Api.channels.ChannelParticipants? in - let reader = BufferReader(buffer) - var result: Api.channels.ChannelParticipants? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.channels.ChannelParticipants - } - return result - }) - } - public static func getParticipant(channel: Api.InputChannel, userId: Api.InputUser) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.channels.ChannelParticipant?) { let buffer = Buffer() buffer.appendInt32(1416484774) @@ -19649,6 +20076,54 @@ public struct Api { return result }) } + + public static func deleteHistory(channel: Api.InputChannel, maxId: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { + let buffer = Buffer() + buffer.appendInt32(-1355375294) + channel.serialize(buffer, true) + serializeInt32(maxId, buffer: buffer, boxed: false) + return (FunctionDescription({return "(channels.deleteHistory channel: \(channel), maxId: \(maxId))"}), buffer, { (buffer: Buffer) -> Api.Bool? in + let reader = BufferReader(buffer) + var result: Api.Bool? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Bool + } + return result + }) + } + + public static func togglePreHistoryHidden(channel: Api.InputChannel, enabled: Api.Bool) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Updates?) { + let buffer = Buffer() + buffer.appendInt32(-356796084) + channel.serialize(buffer, true) + enabled.serialize(buffer, true) + return (FunctionDescription({return "(channels.togglePreHistoryHidden channel: \(channel), enabled: \(enabled))"}), buffer, { (buffer: Buffer) -> Api.Updates? in + let reader = BufferReader(buffer) + var result: Api.Updates? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.Updates + } + return result + }) + } + + public static func getParticipants(channel: Api.InputChannel, filter: Api.ChannelParticipantsFilter, offset: Int32, limit: Int32, hash: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.channels.ChannelParticipants?) { + let buffer = Buffer() + buffer.appendInt32(306054633) + channel.serialize(buffer, true) + filter.serialize(buffer, true) + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + serializeInt32(hash, buffer: buffer, boxed: false) + return (FunctionDescription({return "(channels.getParticipants channel: \(channel), filter: \(filter), offset: \(offset), limit: \(limit), hash: \(hash))"}), buffer, { (buffer: Buffer) -> Api.channels.ChannelParticipants? in + let reader = BufferReader(buffer) + var result: Api.channels.ChannelParticipants? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.channels.ChannelParticipants + } + return result + }) + } } public struct payments { public static func getPaymentForm(msgId: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.payments.PaymentForm?) { @@ -20460,6 +20935,20 @@ public struct Api { return result }) } + + public static func getRecentMeUrls(referer: String) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.help.RecentMeUrls?) { + let buffer = Buffer() + buffer.appendInt32(1036054804) + serializeString(referer, buffer: buffer, boxed: false) + return (FunctionDescription({return "(help.getRecentMeUrls referer: \(referer))"}), buffer, { (buffer: Buffer) -> Api.help.RecentMeUrls? in + let reader = BufferReader(buffer) + var result: Api.help.RecentMeUrls? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.help.RecentMeUrls + } + return result + }) + } } public struct updates { public static func getState() -> (CustomStringConvertible, Buffer, (Buffer) -> Api.updates.State?) { diff --git a/TelegramCore/CachedChannelData.swift b/TelegramCore/CachedChannelData.swift index 376fd24853..d28b9cb1b9 100644 --- a/TelegramCore/CachedChannelData.swift +++ b/TelegramCore/CachedChannelData.swift @@ -19,6 +19,7 @@ public struct CachedChannelFlags: OptionSet { public static let canDisplayParticipants = CachedChannelFlags(rawValue: 1 << 0) public static let canChangeUsername = CachedChannelFlags(rawValue: 1 << 1) public static let canSetStickerSet = CachedChannelFlags(rawValue: 1 << 2) + public static let preHistoryEnabled = CachedChannelFlags(rawValue: 1 << 3) } public struct CachedChannelParticipantsSummary: PostboxCoding, Equatable { @@ -111,6 +112,7 @@ public final class CachedChannelData: CachedPeerData { public let reportStatus: PeerReportStatus public let pinnedMessageId: MessageId? public let stickerPack: StickerPackCollectionInfo? + public let minAvailableMessageId: MessageId? public let peerIds: Set public let messageIds: Set @@ -127,9 +129,10 @@ public final class CachedChannelData: CachedPeerData { self.peerIds = Set() self.messageIds = Set() self.stickerPack = nil + self.minAvailableMessageId = nil } - init(flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], topParticipants: CachedChannelParticipants?, reportStatus: PeerReportStatus, pinnedMessageId: MessageId?, stickerPack: StickerPackCollectionInfo?) { + init(flags: CachedChannelFlags, about: String?, participantsSummary: CachedChannelParticipantsSummary, exportedInvitation: ExportedInvitation?, botInfos: [CachedPeerBotInfo], topParticipants: CachedChannelParticipants?, reportStatus: PeerReportStatus, pinnedMessageId: MessageId?, stickerPack: StickerPackCollectionInfo?, minAvailableMessageId: MessageId?) { self.flags = flags self.about = about self.participantsSummary = participantsSummary @@ -139,6 +142,7 @@ public final class CachedChannelData: CachedPeerData { self.reportStatus = reportStatus self.pinnedMessageId = pinnedMessageId self.stickerPack = stickerPack + self.minAvailableMessageId = minAvailableMessageId var peerIds = Set() if let topParticipants = topParticipants { @@ -159,39 +163,43 @@ public final class CachedChannelData: CachedPeerData { } func withUpdatedFlags(_ flags: CachedChannelFlags) -> CachedChannelData { - return CachedChannelData(flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack) + return CachedChannelData(flags: flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId) } func withUpdatedAbout(_ about: String?) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack) + return CachedChannelData(flags: self.flags, about: about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId) } func withUpdatedParticipantsSummary(_ participantsSummary: CachedChannelParticipantsSummary) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack) + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId) } func withUpdatedExportedInvitation(_ exportedInvitation: ExportedInvitation?) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack) + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId) } func withUpdatedBotInfos(_ botInfos: [CachedPeerBotInfo]) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack) + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId) } func withUpdatedTopParticipants(_ topParticipants: CachedChannelParticipants?) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack) + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId) } func withUpdatedReportStatus(_ reportStatus: PeerReportStatus) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack) + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId) } func withUpdatedPinnedMessageId(_ pinnedMessageId: MessageId?) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack) + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: self.minAvailableMessageId) } func withUpdatedStickerPack(_ stickerPack: StickerPackCollectionInfo?) -> CachedChannelData { - return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack) + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: stickerPack, minAvailableMessageId: self.minAvailableMessageId) + } + + func withUpdatedMinAvailableMessageId(_ minAvailableMessageId: MessageId?) -> CachedChannelData { + return CachedChannelData(flags: self.flags, about: self.about, participantsSummary: self.participantsSummary, exportedInvitation: self.exportedInvitation, botInfos: self.botInfos, topParticipants: self.topParticipants, reportStatus: self.reportStatus, pinnedMessageId: self.pinnedMessageId, stickerPack: self.stickerPack, minAvailableMessageId: minAvailableMessageId) } public init(decoder: PostboxDecoder) { @@ -215,6 +223,12 @@ public final class CachedChannelData: CachedPeerData { self.stickerPack = nil } + if let minAvailableMessagePeerId = decoder.decodeOptionalInt64ForKey("ma.p"), let minAvailableMessageNamespace = decoder.decodeOptionalInt32ForKey("ma.n"), let minAvailableMessageId = decoder.decodeOptionalInt32ForKey("ma.i") { + self.minAvailableMessageId = MessageId(peerId: PeerId(minAvailableMessagePeerId), namespace: minAvailableMessageNamespace, id: minAvailableMessageId) + } else { + self.minAvailableMessageId = nil + } + if let topParticipants = self.topParticipants { for participant in topParticipants.participants { peerIds.insert(participant.peerId) @@ -267,6 +281,15 @@ public final class CachedChannelData: CachedPeerData { } else { encoder.encodeNil(forKey: "sp") } + if let minAvailableMessageId = self.minAvailableMessageId { + encoder.encodeInt64(minAvailableMessageId.peerId.toInt64(), forKey: "ma.p") + encoder.encodeInt32(minAvailableMessageId.namespace, forKey: "ma.n") + encoder.encodeInt32(minAvailableMessageId.id, forKey: "ma.i") + } else { + encoder.encodeNil(forKey: "ma.p") + encoder.encodeNil(forKey: "ma.n") + encoder.encodeNil(forKey: "ma.i") + } } public func isEqual(to: CachedPeerData) -> Bool { @@ -310,6 +333,10 @@ public final class CachedChannelData: CachedPeerData { return false } + if other.minAvailableMessageId != self.minAvailableMessageId { + return false + } + return true } } diff --git a/TelegramCore/ChannelAdminEventLogs.swift b/TelegramCore/ChannelAdminEventLogs.swift index 24775f6690..8a5944f6cb 100644 --- a/TelegramCore/ChannelAdminEventLogs.swift +++ b/TelegramCore/ChannelAdminEventLogs.swift @@ -37,6 +37,7 @@ public enum AdminLogEventAction { case participantToggleBan(prev: RenderedChannelParticipant, new: RenderedChannelParticipant) case participantToggleAdmin(prev: RenderedChannelParticipant, new: RenderedChannelParticipant) case changeStickerPack(prev: StickerPackReference?, new: StickerPackReference?) + case togglePreHistoryHidden(Bool) } public enum ChannelAdminLogEventError { @@ -176,6 +177,8 @@ public func channelAdminLogEvents(_ account:Account, peerId:PeerId, maxId:AdminL } case let .channelAdminLogEventActionChangeStickerSet(prevStickerset, newStickerset): action = .changeStickerPack(prev: StickerPackReference(apiInputSet: prevStickerset), new: StickerPackReference(apiInputSet: newStickerset)) + case let .channelAdminLogEventActionTogglePreHistoryHidden(value): + action = .togglePreHistoryHidden(value == .boolTrue) } let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) if let action = action { diff --git a/TelegramCore/ChannelAdmins.swift b/TelegramCore/ChannelAdmins.swift index 16b5fe0422..a47cd5505b 100644 --- a/TelegramCore/ChannelAdmins.swift +++ b/TelegramCore/ChannelAdmins.swift @@ -12,7 +12,7 @@ import Foundation public func channelAdmins(account: Account, peerId: PeerId) -> Signal<[RenderedChannelParticipant], NoError> { return account.postbox.modify { modifier -> Signal<[RenderedChannelParticipant], NoError> in if let peer = modifier.getPeer(peerId), let inputChannel = apiInputChannel(peer) { - return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 100)) + return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 100, hash: 0)) |> retryRequest |> mapToSignal { result -> Signal<[RenderedChannelParticipant], NoError> in switch result { @@ -46,6 +46,8 @@ public func channelAdmins(account: Account, peerId: PeerId) -> Signal<[RenderedC }) return items } + case .channelParticipantsNotModified: + return .single([]) } } } else { diff --git a/TelegramCore/ChannelBlacklist.swift b/TelegramCore/ChannelBlacklist.swift index 2f23562e23..538fde556e 100644 --- a/TelegramCore/ChannelBlacklist.swift +++ b/TelegramCore/ChannelBlacklist.swift @@ -24,7 +24,7 @@ private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: Cha case .banned: apiFilter = .channelParticipantsKicked(q: "") } - return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: apiFilter, offset: 0, limit: 100)) + return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: apiFilter, offset: 0, limit: 100, hash: 0)) |> retryRequest |> map { result -> [RenderedChannelParticipant] in var items: [RenderedChannelParticipant] = [] @@ -40,12 +40,15 @@ private func fetchChannelBlacklist(account: Account, peerId: PeerId, filter: Cha } } - for participant in CachedChannelParticipants(apiParticipants: participants).participants { - if let peer = peers[participant.peerId] { - items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presences: presences)) - } + for participant in CachedChannelParticipants(apiParticipants: participants).participants { + if let peer = peers[participant.peerId] { + items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presences: presences)) + } - } + } + case .channelParticipantsNotModified: + assertionFailure() + break } return items } diff --git a/TelegramCore/ChannelHistoryAvailabilitySettings.swift b/TelegramCore/ChannelHistoryAvailabilitySettings.swift new file mode 100644 index 0000000000..2ecee1bb82 --- /dev/null +++ b/TelegramCore/ChannelHistoryAvailabilitySettings.swift @@ -0,0 +1,35 @@ +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac +#else + import Postbox + import SwiftSignalKit +#endif + +public func updateChannelHistoryAvailabilitySettingsInteractively(postbox: Postbox, network: Network, peerId: PeerId, historyAvailableForNewMembers: Bool) -> Signal { + return postbox.modify { modifier -> Signal in + if let peer = modifier.getPeer(peerId), let inputChannel = apiInputChannel(peer) { + return network.request(Api.functions.channels.togglePreHistoryHidden(channel: inputChannel, enabled: historyAvailableForNewMembers ? .boolTrue : .boolFalse)) + |> retryRequest + |> mapToSignal { _ -> Signal in + return postbox.modify { modifier -> Void in + modifier.updatePeerCachedData(peerIds: [peerId], update: { peerId, currentData in + if let currentData = currentData as? CachedChannelData { + var flags = currentData.flags + if historyAvailableForNewMembers { + flags.insert(.preHistoryEnabled) + } else { + flags.remove(.preHistoryEnabled) + } + return currentData.withUpdatedFlags(flags) + } else { + return currentData + } + }) + } + } + } else { + return .complete() + } + } |> switchToLatest +} diff --git a/TelegramCore/ChannelMembers.swift b/TelegramCore/ChannelMembers.swift index 4beddd0764..d31a5e8322 100644 --- a/TelegramCore/ChannelMembers.swift +++ b/TelegramCore/ChannelMembers.swift @@ -24,28 +24,30 @@ public func channelMembers(account: Account, peerId: PeerId, filter: ChannelMemb case let .search(query): apiFilter = .channelParticipantsSearch(q: query) } - return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: apiFilter, offset: 0, limit: 100)) + return account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: apiFilter, offset: 0, limit: 100, hash: 0)) |> retryRequest |> map { result -> [RenderedChannelParticipant] in var items: [RenderedChannelParticipant] = [] switch result { - case let .channelParticipants(_, participants, users): - var peers: [PeerId: Peer] = [:] - var presences:[PeerId: PeerPresence] = [:] - for user in users { - let peer = TelegramUser(user: user) - peers[peer.id] = peer - if let presence = TelegramUserPresence(apiUser: user) { - presences[peer.id] = presence - } - } - - for participant in CachedChannelParticipants(apiParticipants: participants).participants { - if let peer = peers[participant.peerId] { - items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presences: presences)) + case let .channelParticipants(_, participants, users): + var peers: [PeerId: Peer] = [:] + var presences:[PeerId: PeerPresence] = [:] + for user in users { + let peer = TelegramUser(user: user) + peers[peer.id] = peer + if let presence = TelegramUserPresence(apiUser: user) { + presences[peer.id] = presence + } } - } + for participant in CachedChannelParticipants(apiParticipants: participants).participants { + if let peer = peers[participant.peerId] { + items.append(RenderedChannelParticipant(participant: participant, peer: peer, peers: peers, presences: presences)) + } + + } + case .channelParticipantsNotModified: + break } return items } diff --git a/TelegramCore/ChannelParticipants.swift b/TelegramCore/ChannelParticipants.swift index a36d2bf28e..4ce2b2ed9a 100644 --- a/TelegramCore/ChannelParticipants.swift +++ b/TelegramCore/ChannelParticipants.swift @@ -29,10 +29,10 @@ public struct RenderedChannelParticipant: Equatable { func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signal { return account.postbox.modify { modifier -> Signal in if let peer = modifier.getPeer(peerId), let inputChannel = apiInputChannel(peer) { - let admins = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 0)) - let members = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsRecent, offset: 0, limit: 0)) - let banned = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsBanned(q: ""), offset: 0, limit: 0)) - let kicked = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsKicked(q: ""), offset: 0, limit: 0)) + let admins = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsAdmins, offset: 0, limit: 0, hash: 0)) + let members = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsRecent, offset: 0, limit: 0, hash: 0)) + let banned = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsBanned(q: ""), offset: 0, limit: 0, hash: 0)) + let kicked = account.network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsKicked(q: ""), offset: 0, limit: 0, hash: 0)) return combineLatest(admins, members, banned, kicked) |> mapToSignal { admins, members, banned, kicked -> Signal in return account.postbox.modify { modifier -> Void in @@ -42,21 +42,33 @@ func updateChannelParticipantsSummary(account: Account, peerId: PeerId) -> Signa switch admins { case let .channelParticipants(count, _, _): adminCount = count + case .channelParticipantsNotModified: + assertionFailure() + adminCount = 0 } let memberCount: Int32 switch members { case let .channelParticipants(count, _, _): memberCount = count + case .channelParticipantsNotModified: + assertionFailure() + memberCount = 0 } let bannedCount: Int32 switch banned { case let .channelParticipants(count, _, _): bannedCount = count + case .channelParticipantsNotModified: + assertionFailure() + bannedCount = 0 } let kickedCount: Int32 switch kicked { case let .channelParticipants(count, _, _): kickedCount = count + case .channelParticipantsNotModified: + assertionFailure() + kickedCount = 0 } return current.withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: memberCount, adminCount: adminCount, bannedCount: bannedCount, kickedCount: kickedCount)) } diff --git a/TelegramCore/ChatContextResult.swift b/TelegramCore/ChatContextResult.swift index 9e6b0eae8c..29256e0afd 100644 --- a/TelegramCore/ChatContextResult.swift +++ b/TelegramCore/ChatContextResult.swift @@ -341,14 +341,14 @@ extension ChatContextResultMessage { } self = .text(text: message, entities: parsedEntities, disableUrlPreview: (flags & (1 << 0)) != 0, replyMarkup: parsedReplyMarkup) case let .botInlineMessageMediaGeo(_, geo, replyMarkup): - let media = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil) + let media = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: nil) var parsedReplyMarkup: ReplyMarkupMessageAttribute? if let replyMarkup = replyMarkup { parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup) } self = .mapLocation(media: media, replyMarkup: parsedReplyMarkup) case let .botInlineMessageMediaVenue(_, geo, title, address, provider, venueId, replyMarkup): - let media = telegramMediaMapFromApiGeoPoint(geo, title: title, address: address, provider: provider, venueId: venueId) + let media = telegramMediaMapFromApiGeoPoint(geo, title: title, address: address, provider: provider, venueId: venueId, venueType: nil, liveBroadcastingTimeout: nil) var parsedReplyMarkup: ReplyMarkupMessageAttribute? if let replyMarkup = replyMarkup { parsedReplyMarkup = ReplyMarkupMessageAttribute(apiMarkup: replyMarkup) @@ -400,7 +400,7 @@ extension ChatContextResultSwitchPeer { extension ChatContextResultCollection { convenience init(apiResults: Api.messages.BotResults, botId: PeerId) { switch apiResults { - case let .botResults(flags, queryId, nextOffset, switchPm, results, cacheTime): + case let .botResults(flags, queryId, nextOffset, switchPm, results, cacheTime, users): var switchPeer: ChatContextResultSwitchPeer? if let switchPm = switchPm { switchPeer = ChatContextResultSwitchPeer(apiSwitchPeer: switchPm) diff --git a/TelegramCore/ContactManagement.swift b/TelegramCore/ContactManagement.swift index 03f3bfcd85..aaff10c51b 100644 --- a/TelegramCore/ContactManagement.swift +++ b/TelegramCore/ContactManagement.swift @@ -50,17 +50,18 @@ private func hashForCountAndIds(count: Int32, ids: [Int32]) -> Int32 { let low = UInt32(bitPattern: id) acc = (acc &* 20261) &+ low } - return Int32(bitPattern: acc % UInt32(0x7FFFFFFF)) + return Int32(bitPattern: acc & UInt32(0x7FFFFFFF)) } -func manageContacts(network: Network, postbox: Postbox) -> Signal { +func manageContacts(network: Network, postbox: Postbox, accountPeerId: PeerId) -> Signal { #if DEBUG return .never() #endif let initialContactPeerIdsHash = postbox.contactPeerIdsView() |> take(1) |> map { view -> Int32 in - let sortedUserIds = Set(view.peerIds.filter({ $0.namespace == Namespaces.Peer.CloudUser }).map({ $0.id })).sorted() + let peerIds = Set(view.peerIds.filter({ $0.namespace == Namespaces.Peer.CloudUser })) + let sortedUserIds = peerIds.map({ $0.id }).sorted() return hashForCountAndIds(count: view.remoteTotalCount, ids: sortedUserIds) } @@ -87,9 +88,9 @@ func manageContacts(network: Network, postbox: Postbox) -> Signal return appliedUpdatedPeers } -public func addContactPeerInteractively(account: Account, peerId: PeerId) -> Signal { +public func addContactPeerInteractively(account: Account, peerId: PeerId, phone: String?) -> Signal { return account.postbox.modify { modifier -> Signal in - if let peer = modifier.getPeer(peerId) as? TelegramUser, let phone = peer.phone, !phone.isEmpty { + if let peer = modifier.getPeer(peerId) as? TelegramUser, let phone = phone ?? peer.phone, !phone.isEmpty { return account.network.request(Api.functions.contacts.importContacts(contacts: [Api.InputContact.inputPhoneContact(clientId: 1, phone: phone, firstName: peer.firstName ?? "", lastName: peer.lastName ?? "")])) |> map { Optional($0) } |> `catch` { _ -> Signal in diff --git a/TelegramCore/DeleteMessagesInteractively.swift b/TelegramCore/DeleteMessagesInteractively.swift index a77166cbdd..7a5f975218 100644 --- a/TelegramCore/DeleteMessagesInteractively.swift +++ b/TelegramCore/DeleteMessagesInteractively.swift @@ -59,9 +59,16 @@ public func deleteMessagesInteractively(postbox: Postbox, messageIds: [MessageId public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId) -> Signal { return postbox.modify { modifier -> Void in - if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup { + if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel { + var topTimestamp: Int32? + if let topIndex = modifier.getTopMesssageIndex(peerId: peerId, namespace: Namespaces.Message.Cloud) { + topTimestamp = topIndex.timestamp + } cloudChatAddClearHistoryOperation(modifier: modifier, peerId: peerId) modifier.clearHistory(peerId) + if let topTimestamp = topTimestamp { + updatePeerChatInclusionWithMinTimestamp(modifier: modifier, id: peerId, minTimestamp: topTimestamp) + } } else if peerId.namespace == Namespaces.Peer.SecretChat { modifier.clearHistory(peerId) @@ -87,9 +94,8 @@ public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId) -> Signa } } -public func clearAuthorHistory(account: Account, peerId: PeerId, memberId:PeerId) -> Signal { +public func clearAuthorHistory(account: Account, peerId: PeerId, memberId: PeerId) -> Signal { return account.postbox.modify { modifier -> Signal in - if let peer = modifier.getPeer(peerId), let memberPeer = modifier.getPeer(memberId), let inputChannel = apiInputChannel(peer), let inputUser = apiInputUser(memberPeer) { let signal = account.network.request(Api.functions.channels.deleteUserHistory(channel: inputChannel, userId: inputUser)) diff --git a/TelegramCore/Holes.swift b/TelegramCore/Holes.swift index 142b8948d2..99b268f5c8 100644 --- a/TelegramCore/Holes.swift +++ b/TelegramCore/Holes.swift @@ -335,7 +335,7 @@ func fetchChatListHole(network: Network, postbox: Postbox, hole: ChatListHole) - readStates[peerId]![Namespaces.Message.Cloud] = .idBased(maxIncomingReadId: apiReadInboxMaxId, maxOutgoingReadId: apiReadOutboxMaxId, maxKnownId: apiTopMessage, count: apiUnreadCount) if apiTopMessage != 0 { - mentionTagSummaries[peerId] = MessageHistoryTagNamespaceSummary(version: 1, count: 0, range: MessageHistoryTagNamespaceCountValidityRange(maxId: apiTopMessage)) + mentionTagSummaries[peerId] = MessageHistoryTagNamespaceSummary(version: 1, count: apiUnreadMentionsCount, range: MessageHistoryTagNamespaceCountValidityRange(maxId: apiTopMessage)) } notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings) diff --git a/TelegramCore/Localizations.swift b/TelegramCore/Localizations.swift index a4485c3cc4..cff84f0cd9 100644 --- a/TelegramCore/Localizations.swift +++ b/TelegramCore/Localizations.swift @@ -12,8 +12,8 @@ public func currentlySuggestedLocalization(network: Network, extractKeys: [Strin |> retryRequest |> mapToSignal { result -> Signal in switch result { - //config flags:# date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int phonecalls_enabled:flags.1?true call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string suggested_lang_code:flags.2?string lang_pack_version:flags.2?int disabled_features:Vector = Config; - case let .config(flags, _, _, _, _, _, chatSizeMax, megagroupSizeMax, forwardedCountMax, onlineUpdatePeriodMs, offlineBlurTimeoutMs, offlineIdleTimeoutMs, onlineCloudTimeoutMs, notifyCloudDelayMs, notifyDefaultDelayMs, chatBigSize, pushChatPeriodMs, pushChatLimit, savedGifsLimit, editTimeLimit, ratingEDecay, stickersRecentLimit, stickersFavedLimit, _, pinnedDialogsCountMax, callReceiveTimeoutMs, callRingTimeoutMs, callConnectTimeoutMs, callPacketTimeoutMs, meUrlPrefix, suggestedLangCode, _, disabledFeatures): + //config flags:# date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int phonecalls_enabled:flags.1?true call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string suggested_lang_code:flags.2?string lang_pack_version:flags.2?int disabled_features:Vector = Config; + case let .config(flags, _, _, _, _, _, chatSizeMax, megagroupSizeMax, forwardedCountMax, onlineUpdatePeriodMs, offlineBlurTimeoutMs, offlineIdleTimeoutMs, onlineCloudTimeoutMs, notifyCloudDelayMs, notifyDefaultDelayMs, chatBigSize, pushChatPeriodMs, pushChatLimit, savedGifsLimit, editTimeLimit, ratingEDecay, stickersRecentLimit, stickersFavedLimit, channelsReadMediaPeriod, _, pinnedDialogsCountMax, callReceiveTimeoutMs, callRingTimeoutMs, callConnectTimeoutMs, callPacketTimeoutMs, meUrlPrefix, suggestedLangCode, _, disabledFeatures): if let suggestedLangCode = suggestedLangCode { return suggestedLocalizationInfo(network: network, languageCode: suggestedLangCode, extractKeys: extractKeys) |> map { Optional($0) } } else { @@ -92,7 +92,7 @@ public func downloadLocalization(network: Network, languageCode: String) -> Sign public func downoadAndApplyLocalization(postbox: Postbox, network: Network, languageCode: String) -> Signal { return downloadLocalization(network: network, languageCode: languageCode) |> mapToSignal { language -> Signal in - return postbox.modify { modifier -> Void in + return postbox.modify { modifier -> Signal in modifier.updatePreferencesEntry(key: PreferencesKeys.localizationSettings, { _ in return LocalizationSettings(languageCode: languageCode, localization: language) }) @@ -100,6 +100,14 @@ public func downoadAndApplyLocalization(postbox: Postbox, network: Network, lang network.context.updateApiEnvironment { current in return current?.withUpdatedLangPackCode(languageCode) } - } + + return network.request(Api.functions.help.test()) + |> `catch` { _ -> Signal in + return .complete() + } + |> mapToSignal { _ -> Signal in + return .complete() + } + } |> switchToLatest } } diff --git a/TelegramCore/Log.swift b/TelegramCore/Log.swift index b7f6747e43..c17c568c5e 100644 --- a/TelegramCore/Log.swift +++ b/TelegramCore/Log.swift @@ -82,6 +82,7 @@ public final class Logger { public init(basePath: String) { self.basePath = basePath + //self.logToConsole = false } public func collectLogs() -> Signal<[(String, String)], NoError> { diff --git a/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift b/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift index e3472971ff..ac6da4b7c7 100644 --- a/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift +++ b/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift @@ -309,6 +309,14 @@ private func clearHistory(modifier: Modifier, postbox: Postbox, network: Network } else { return .complete() } + } else if peer.id.namespace == Namespaces.Peer.CloudChannel, let inputChannel = apiInputChannel(peer) { + return network.request(Api.functions.channels.deleteHistory(channel: inputChannel, maxId: operation.topMessageId.id)) + |> `catch` { _ -> Signal in + return .single(.boolFalse) + } + |> mapToSignal { _ -> Signal in + return .complete() + } } else { assertionFailure() return .complete() diff --git a/TelegramCore/ManagedConfigurationUpdates.swift b/TelegramCore/ManagedConfigurationUpdates.swift index e0f76baee0..b20432a5b9 100644 --- a/TelegramCore/ManagedConfigurationUpdates.swift +++ b/TelegramCore/ManagedConfigurationUpdates.swift @@ -9,12 +9,14 @@ import Foundation import MtProtoKitDynamic #endif +//config flags:# date:int expires:int test_mode:Bool this_dc:int dc_options:Vector chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int chat_big_size:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int phonecalls_enabled:flags.1?true call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string suggested_lang_code:flags.2?string lang_pack_version:flags.2?int disabled_features:Vector = Config; + func managedConfigurationUpdates(postbox: Postbox, network: Network) -> Signal { let poll = Signal { subscriber in return (network.request(Api.functions.help.getConfig()) |> retryRequest |> mapToSignal { result -> Signal in return postbox.modify { modifier -> Void in switch result { - case let .config(_, _, _, _, _, dcOptions, chatSizeMax, megagroupSizeMax, forwardedCountMax, _, _, _, onlineCloudTimeoutMs, notifyCloudDelayMs, notifyDefaultDelayMs, chatBigSize, pushChatPeriodMs, pushChatLimit, savedGifsLimit, editTimeLimit, ratingEDecay, stickersRecentLimit, stickersFavedLimit, tmpSessions, pinnedDialogsCountMax, callReceiveTimeoutMs, callRingTimeoutMs, callConnectTimeoutMs, callPacketTimeoutMs, meUrlPrefix, suggestedLangCode, langPackVersion, disabledFeatures): + case let .config(_, _, _, _, _, dcOptions, chatSizeMax, megagroupSizeMax, forwardedCountMax, _, _, _, onlineCloudTimeoutMs, notifyCloudDelayMs, notifyDefaultDelayMs, chatBigSize, pushChatPeriodMs, pushChatLimit, savedGifsLimit, editTimeLimit, ratingEDecay, stickersRecentLimit, stickersFavedLimit, channelsReadMediaPeriod, tmpSessions, pinnedDialogsCountMax, callReceiveTimeoutMs, callRingTimeoutMs, callConnectTimeoutMs, callPacketTimeoutMs, meUrlPrefix, suggestedLangCode, langPackVersion, disabledFeatures): var addressList: [Int: [MTDatacenterAddress]] = [:] for option in dcOptions { switch option { diff --git a/TelegramCore/ManagedRecentStickers.swift b/TelegramCore/ManagedRecentStickers.swift index 5eca4563e2..8db19ad575 100644 --- a/TelegramCore/ManagedRecentStickers.swift +++ b/TelegramCore/ManagedRecentStickers.swift @@ -17,7 +17,7 @@ private func hashForIds(_ ids: [Int64]) -> Int32 { acc = (acc &* 20261) &+ high acc = (acc &* 20261) &+ low } - return Int32(bitPattern: acc % UInt32(0x7FFFFFFF)) + return Int32(bitPattern: acc & UInt32(0x7FFFFFFF)) } private func managedRecentMedia(postbox: Postbox, network: Network, collectionId: Int32, reverseHashOrder: Bool, fetch: @escaping (Int32) -> Signal<[OrderedItemListEntry]?, NoError>) -> Signal { diff --git a/TelegramCore/ManagedSynchronizeInstalledStickerPacksOperations.swift b/TelegramCore/ManagedSynchronizeInstalledStickerPacksOperations.swift index 0c1f356a35..e70a6e9648 100644 --- a/TelegramCore/ManagedSynchronizeInstalledStickerPacksOperations.swift +++ b/TelegramCore/ManagedSynchronizeInstalledStickerPacksOperations.swift @@ -128,7 +128,7 @@ private func hashForStickerPackInfos(_ infos: [StickerPackCollectionInfo]) -> In acc = UInt32(bitPattern: Int32(bitPattern: acc &* UInt32(20261)) &+ info.hash) } - return Int32(bitPattern: acc % 0x7FFFFFFF) + return Int32(bitPattern: acc & 0x7FFFFFFF) } private enum SynchronizeInstalledStickerPacksError { diff --git a/TelegramCore/NotificationInfoMessageAttribute.swift b/TelegramCore/NotificationInfoMessageAttribute.swift index 2d5b0e678d..6be45cb692 100644 --- a/TelegramCore/NotificationInfoMessageAttribute.swift +++ b/TelegramCore/NotificationInfoMessageAttribute.swift @@ -5,9 +5,7 @@ import Foundation import Postbox #endif - - -public struct NotificationInfoMessageAttributeFlags : OptionSet { +public struct NotificationInfoMessageAttributeFlags: OptionSet { public var rawValue: Int32 public init(rawValue: Int32) { @@ -24,8 +22,8 @@ public struct NotificationInfoMessageAttributeFlags : OptionSet { } public class NotificationInfoMessageAttribute: MessageAttribute { - - public let flags:NotificationInfoMessageAttributeFlags + public let flags: NotificationInfoMessageAttributeFlags + public init(flags: NotificationInfoMessageAttributeFlags) { self.flags = flags } diff --git a/TelegramCore/PeerUtils.swift b/TelegramCore/PeerUtils.swift index c7100689e3..25826a2072 100644 --- a/TelegramCore/PeerUtils.swift +++ b/TelegramCore/PeerUtils.swift @@ -42,7 +42,7 @@ public extension Peer { switch self { case let user as TelegramUser: return user.username - case let _ as TelegramGroup: + case _ as TelegramGroup: return nil case let channel as TelegramChannel: return channel.username diff --git a/TelegramCore/PendingMessageUploadedContent.swift b/TelegramCore/PendingMessageUploadedContent.swift index f5b6812b4c..780069ce4e 100644 --- a/TelegramCore/PendingMessageUploadedContent.swift +++ b/TelegramCore/PendingMessageUploadedContent.swift @@ -74,7 +74,7 @@ func messageContentToUpload(network: Network, postbox: Postbox, transformOutgoin } else if let map = media as? TelegramMediaMap { let input: Api.InputMedia if let venue = map.venue { - input = .inputMediaVenue(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude), title: venue.title, address: venue.address ?? "", provider: venue.provider ?? "", venueId: venue.id ?? "") + input = .inputMediaVenue(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude), title: venue.title, address: venue.address ?? "", provider: venue.provider ?? "", venueId: venue.id ?? "", venueType: venue.type ?? "") } else { input = .inputMediaGeoPoint(geoPoint: Api.InputGeoPoint.inputGeoPoint(lat: map.latitude, long: map.longitude)) } diff --git a/TelegramCore/RegularChatState.swift b/TelegramCore/RegularChatState.swift new file mode 100644 index 0000000000..4d2ebea322 --- /dev/null +++ b/TelegramCore/RegularChatState.swift @@ -0,0 +1,41 @@ +import Foundation +#if os(macOS) + import PostboxMac +#else + import Postbox +#endif + +final class RegularChatState: PeerChatState, Equatable { + let invalidatedPts: Int32? + + init(invalidatedPts: Int32?) { + self.invalidatedPts = invalidatedPts + } + + init(decoder: PostboxDecoder) { + self.invalidatedPts = decoder.decodeOptionalInt32ForKey("ipts") + } + + func encode(_ encoder: PostboxEncoder) { + if let invalidatedPts = self.invalidatedPts { + encoder.encodeInt32(invalidatedPts, forKey: "ipts") + } else { + encoder.encodeNil(forKey: "ipts") + } + } + + func withUpdatedInvalidatedPts(_ invalidatedPts: Int32?) -> RegularChatState { + return RegularChatState(invalidatedPts: invalidatedPts) + } + + func equals(_ other: PeerChatState) -> Bool { + if let other = other as? RegularChatState, other == self { + return true + } + return false + } + + static func ==(lhs: RegularChatState, rhs: RegularChatState) -> Bool { + return lhs.invalidatedPts == rhs.invalidatedPts + } +} diff --git a/TelegramCore/Serialization.swift b/TelegramCore/Serialization.swift index 52e92e8576..64642b4ef9 100644 --- a/TelegramCore/Serialization.swift +++ b/TelegramCore/Serialization.swift @@ -20,7 +20,7 @@ public class BoxedMessage: NSObject { public class Serialization: NSObject, MTSerialization { public func currentLayer() -> UInt { - return 71 + return 72 } public func parseMessage(_ data: Data!) -> Any! { @@ -56,7 +56,7 @@ public class Serialization: NSObject, MTSerialization { return { response -> MTDatacenterAddressListData! in if let config = parse(Buffer(data: response)) { switch config { - case let .config(_, _, _, _, _, dcOptions, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .config(_, _, _, _, _, dcOptions, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): var addressDict: [NSNumber: [Any]] = [:] for option in dcOptions { switch option { diff --git a/TelegramCore/StickerManagement.swift b/TelegramCore/StickerManagement.swift index 69d7c3183e..32ea8bdf8d 100644 --- a/TelegramCore/StickerManagement.swift +++ b/TelegramCore/StickerManagement.swift @@ -18,7 +18,7 @@ private func hashForIdsReverse(_ ids: [Int64]) -> Int32 { acc = (acc &* 20261) &+ high acc = (acc &* 20261) &+ low } - return Int32(bitPattern: acc % UInt32(0x7FFFFFFF)) + return Int32(bitPattern: acc & UInt32(0x7FFFFFFF)) } func manageStickerPacks(network: Network, postbox: Postbox) -> Signal { diff --git a/TelegramCore/StoreMessage_Telegram.swift b/TelegramCore/StoreMessage_Telegram.swift index 0a73535239..4596e3c613 100644 --- a/TelegramCore/StoreMessage_Telegram.swift +++ b/TelegramCore/StoreMessage_Telegram.swift @@ -201,7 +201,7 @@ extension Api.Message { } switch action { - case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken: + case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken, .messageActionCustomAction: break case let .messageActionChannelMigrateFrom(_, chatId): result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)) @@ -278,10 +278,13 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI let mediaContact = TelegramMediaContact(firstName: firstName, lastName: lastName, phoneNumber: phoneNumber, peerId: contactPeerId) return (nil, mediaContact, nil) case let .messageMediaGeo(geo): - let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil) + let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: nil) return (nil, mediaMap, nil) - case let .messageMediaVenue(geo, title, address, provider, venueId): - let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: title, address: address, provider: provider, venueId: venueId) + case let .messageMediaVenue(geo, title, address, provider, venueId, venueType): + let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: title, address: address, provider: provider, venueId: venueId, venueType: venueType, liveBroadcastingTimeout: nil) + return (nil, mediaMap, nil) + case let .messageMediaGeoLive(geo, period): + let mediaMap = telegramMediaMapFromApiGeoPoint(geo, title: nil, address: nil, provider: nil, venueId: nil, venueType: nil, liveBroadcastingTimeout: period) return (nil, mediaMap, nil) case let .messageMediaDocument(_, document, caption, ttlSeconds): if let document = document { @@ -505,6 +508,9 @@ extension StoreMessage { case .messageEmpty: return nil case let .messageService(flags, id, fromId, toId, replyToMsgId, date, action): + if case .messageActionHistoryClear = action { + return nil + } let peerId: PeerId var authorId: PeerId? switch toId { diff --git a/TelegramCore/TelegramMediaAction.swift b/TelegramCore/TelegramMediaAction.swift index a5a31174b6..28ce632c7f 100644 --- a/TelegramCore/TelegramMediaAction.swift +++ b/TelegramCore/TelegramMediaAction.swift @@ -29,6 +29,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { case gameScore(gameId: Int64, score: Int32) case phoneCall(callId: Int64, discardReason: PhoneCallDiscardReason?, duration: Int32?) case paymentSent(currency: String, totalAmount: Int64) + case customText(text: String) + public init(decoder: PostboxDecoder) { let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0) switch rawValue { @@ -66,7 +68,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { self = .phoneCall(callId: decoder.decodeInt64ForKey("i", orElse: 0), discardReason: discardReason, duration: decoder.decodeInt32ForKey("d", orElse: 0)) case 15: self = .paymentSent(currency: decoder.decodeStringForKey("currency", orElse: ""), totalAmount: decoder.decodeInt64ForKey("ta", orElse: 0)) - + case 16: + self = .customText(text: decoder.decodeStringForKey("text", orElse: "")) default: self = .unknown } @@ -137,6 +140,9 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { } else { encoder.encodeNil(forKey: "d") } + case let .customText(text): + encoder.encodeInt32(16, forKey: "_rawValue") + encoder.encodeString(text, forKey: "text") } } @@ -256,6 +262,12 @@ public func ==(lhs: TelegramMediaActionType, rhs: TelegramMediaActionType) -> Bo } else { return false } + case let .customText(text): + if case .customText(text) = rhs { + return true + } else { + return false + } } return false } @@ -330,6 +342,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe return nil case .messageActionScreenshotTaken: return TelegramMediaAction(action: .historyScreenshot) + case let .messageActionCustomAction(message): + return TelegramMediaAction(action: .customText(text: message)) } } diff --git a/TelegramCore/TelegramMediaMap.swift b/TelegramCore/TelegramMediaMap.swift index d791f7b37f..814b10dcba 100644 --- a/TelegramCore/TelegramMediaMap.swift +++ b/TelegramCore/TelegramMediaMap.swift @@ -5,7 +5,7 @@ import Foundation import Postbox #endif -public final class NamedGeoPlace: PostboxCoding { +public final class NamedGeoPlace: PostboxCoding, Equatable { public let country: String? public let state: String? public let city: String? @@ -49,19 +49,40 @@ public final class NamedGeoPlace: PostboxCoding { encoder.encodeString(street, forKey: "gp_str") } } + + public static func ==(lhs: NamedGeoPlace, rhs: NamedGeoPlace) -> Bool { + if lhs.country != rhs.country { + return false + } + if lhs.state != rhs.state { + return false + } + if lhs.city != rhs.city { + return false + } + if lhs.district != rhs.district { + return false + } + if lhs.street != rhs.street { + return false + } + return true + } } -public final class MapVenue: PostboxCoding { +public final class MapVenue: PostboxCoding, Equatable { public let title: String public let address: String? public let provider: String? public let id: String? + public let type: String? - public init(title: String, address: String?, provider: String?, id: String?) { + public init(title: String, address: String?, provider: String?, id: String?, type: String?) { self.title = title self.address = address self.provider = provider self.id = id + self.type = type } public init(decoder: PostboxDecoder) { @@ -69,6 +90,7 @@ public final class MapVenue: PostboxCoding { self.address = decoder.decodeOptionalStringForKey("ad") self.provider = decoder.decodeOptionalStringForKey("pr") self.id = decoder.decodeOptionalStringForKey("id") + self.type = decoder.decodeOptionalStringForKey("ty") } public func encode(_ encoder: PostboxEncoder) { @@ -76,13 +98,40 @@ public final class MapVenue: PostboxCoding { if let address = self.address { encoder.encodeString(address, forKey: "ad") + } else { + encoder.encodeNil(forKey: "ad") } if let provider = self.provider { encoder.encodeString(provider, forKey: "pr") + } else { + encoder.encodeNil(forKey: "pr") } if let id = self.id { encoder.encodeString(id, forKey: "id") + } else { + encoder.encodeNil(forKey: "id") } + if let type = self.type { + encoder.encodeString(type, forKey: "ty") + } else { + encoder.encodeNil(forKey: "ty") + } + } + + public static func ==(lhs: MapVenue, rhs: MapVenue) -> Bool { + if lhs.address != rhs.address { + return false + } + if lhs.provider != rhs.provider { + return false + } + if lhs.id != rhs.id { + return false + } + if lhs.type != rhs.type { + return false + } + return true } } @@ -91,15 +140,17 @@ public final class TelegramMediaMap: Media { public let longitude: Double public let geoPlace: NamedGeoPlace? public let venue: MapVenue? + public let liveBroadcastingTimeout: Int32? public let id: MediaId? = nil public let peerIds: [PeerId] = [] - public init(latitude: Double, longitude: Double, geoPlace: NamedGeoPlace?, venue: MapVenue?) { + public init(latitude: Double, longitude: Double, geoPlace: NamedGeoPlace?, venue: MapVenue?, liveBroadcastingTimeout: Int32?) { self.latitude = latitude self.longitude = longitude self.geoPlace = geoPlace self.venue = venue + self.liveBroadcastingTimeout = liveBroadcastingTimeout } public init(decoder: PostboxDecoder) { @@ -107,6 +158,7 @@ public final class TelegramMediaMap: Media { self.longitude = decoder.decodeDoubleForKey("lo", orElse: 0.0) self.geoPlace = decoder.decodeObjectForKey("gp", decoder: { NamedGeoPlace(decoder: $0) }) as? NamedGeoPlace self.venue = decoder.decodeObjectForKey("ve", decoder: { MapVenue(decoder: $0) }) as? MapVenue + self.liveBroadcastingTimeout = decoder.decodeOptionalInt32ForKey("bt") } public func encode(_ encoder: PostboxEncoder) { @@ -114,31 +166,50 @@ public final class TelegramMediaMap: Media { encoder.encodeDouble(self.longitude, forKey: "lo") if let geoPlace = self.geoPlace { encoder.encodeObject(geoPlace, forKey: "gp") + } else { + encoder.encodeNil(forKey: "gp") } if let venue = self.venue { encoder.encodeObject(venue, forKey: "ve") + } else { + encoder.encodeNil(forKey: "ve") + } + if let liveBroadcastingTimeout = self.liveBroadcastingTimeout { + encoder.encodeInt32(liveBroadcastingTimeout, forKey: "bt") + } else { + encoder.encodeNil(forKey: "bt") } } public func isEqual(_ other: Media) -> Bool { if let other = other as? TelegramMediaMap { - if self.latitude == other.latitude && self.longitude == other.longitude { - return true + if self.latitude != other.latitude || self.longitude != other.longitude { + return false } + if self.geoPlace != other.geoPlace { + return false + } + if self.venue != other.venue { + return false + } + if self.liveBroadcastingTimeout != other.liveBroadcastingTimeout { + return false + } + return true } return false } } -public func telegramMediaMapFromApiGeoPoint(_ geo: Api.GeoPoint, title: String?, address: String?, provider: String?, venueId: String?) -> TelegramMediaMap { +public func telegramMediaMapFromApiGeoPoint(_ geo: Api.GeoPoint, title: String?, address: String?, provider: String?, venueId: String?, venueType: String?, liveBroadcastingTimeout: Int32?) -> TelegramMediaMap { var venue: MapVenue? if let title = title { - venue = MapVenue(title: title, address: address, provider: provider, id: venueId) + venue = MapVenue(title: title, address: address, provider: provider, id: venueId, type: venueType) } switch geo { case let .geoPoint(long, lat): - return TelegramMediaMap(latitude: lat, longitude: long, geoPlace: nil, venue: venue) + return TelegramMediaMap(latitude: lat, longitude: long, geoPlace: nil, venue: venue, liveBroadcastingTimeout: liveBroadcastingTimeout) case .geoPointEmpty: - return TelegramMediaMap(latitude: 0.0, longitude: 0.0, geoPlace: nil, venue: venue) + return TelegramMediaMap(latitude: 0.0, longitude: 0.0, geoPlace: nil, venue: venue, liveBroadcastingTimeout: liveBroadcastingTimeout) } } diff --git a/TelegramCore/UpdateCachedChannelParticipants.swift b/TelegramCore/UpdateCachedChannelParticipants.swift index def1f657bf..1629b67324 100644 --- a/TelegramCore/UpdateCachedChannelParticipants.swift +++ b/TelegramCore/UpdateCachedChannelParticipants.swift @@ -11,7 +11,7 @@ func fetchAndUpdateCachedParticipants(peerId: PeerId, network: Network, postbox: return postbox.loadedPeerWithId(peerId) |> mapToSignal { peer -> Signal in if let inputChannel = apiInputChannel(peer) { - return network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsRecent, offset: 0, limit: 200)) + return network.request(Api.functions.channels.getParticipants(channel: inputChannel, filter: .channelParticipantsRecent, offset: 0, limit: 200, hash: 0)) |> retryRequest |> mapToSignal { result -> Signal in return postbox.modify { modifier -> Void in @@ -42,6 +42,8 @@ func fetchAndUpdateCachedParticipants(peerId: PeerId, network: Network, postbox: return currentData } }) + case .channelParticipantsNotModified: + break } } } diff --git a/TelegramCore/UpdateCachedPeerData.swift b/TelegramCore/UpdateCachedPeerData.swift index 4790b9b14b..cabc424f08 100644 --- a/TelegramCore/UpdateCachedPeerData.swift +++ b/TelegramCore/UpdateCachedPeerData.swift @@ -213,14 +213,14 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos switch result { case let .chatFull(fullChat, chats, users): switch fullChat { - case let .channelFull(_, _, _, _, _, _, _, _, _, _, _, notifySettings, _, _, _, _, _, _): + case let .channelFull(_, _, _, _, _, _, _, _, _, _, _, notifySettings, _, _, _, _, _, _, _): modifier.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)]) case .chatFull: break } switch fullChat { - case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet): + case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId): var channelFlags = CachedChannelFlags() if (flags & (1 << 3)) != 0 { channelFlags.insert(.canDisplayParticipants) @@ -246,6 +246,15 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos pinnedMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: pinnedMsgId) } + var minAvailableMessageId: MessageId? + if let minAvailableMsgId = minAvailableMsgId { + minAvailableMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: minAvailableMsgId) + + if let pinnedMsgId = pinnedMsgId, pinnedMsgId < minAvailableMsgId { + pinnedMessageId = nil + } + } + var peers: [Peer] = [] var peerPresences: [PeerId: PeerPresence] = [:] for chat in chats { @@ -281,6 +290,7 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos return StickerPackCollectionInfo(apiSet: apiSet, namespace: namespace) } + var minAvailableMessageIdUpdated = false modifier.updatePeerCachedData(peerIds: [peerId], update: { _, current in let previous: CachedChannelData if let current = current as? CachedChannelData { @@ -289,6 +299,8 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos previous = CachedChannelData() } + minAvailableMessageIdUpdated = previous.minAvailableMessageId != minAvailableMessageId + return previous.withUpdatedFlags(channelFlags) .withUpdatedAbout(about) .withUpdatedParticipantsSummary(CachedChannelParticipantsSummary(memberCount: participantsCount, adminCount: adminsCount, bannedCount: bannedCount, kickedCount: kickedCount)) @@ -296,7 +308,12 @@ func fetchAndUpdateCachedPeerData(peerId: PeerId, network: Network, postbox: Pos .withUpdatedBotInfos(botInfos) .withUpdatedPinnedMessageId(pinnedMessageId) .withUpdatedStickerPack(stickerPack) + .withUpdatedMinAvailableMessageId(minAvailableMessageId) }) + + if let minAvailableMessageId = minAvailableMessageId, minAvailableMessageIdUpdated { + modifier.deleteMessagesInRange(peerId: peerId, namespace: minAvailableMessageId.namespace, minId: 1, maxId: minAvailableMessageId.id) + } case .chatFull: break } diff --git a/TelegramCore/UpdatePeers.swift b/TelegramCore/UpdatePeers.swift index 338a20e5ea..3087b62f6a 100644 --- a/TelegramCore/UpdatePeers.swift +++ b/TelegramCore/UpdatePeers.swift @@ -5,6 +5,20 @@ import Foundation import Postbox #endif +func updatePeerChatInclusionWithMinTimestamp(modifier: Modifier, id: PeerId, minTimestamp: Int32) { + let currentInclusion = modifier.getPeerChatListInclusion(id) + var updatedInclusion: PeerChatListInclusion? + switch currentInclusion { + case .ifHasMessages, .ifHasMessagesOrOneOf: + updatedInclusion = currentInclusion.withSetIfHasMessagesOrMaxMinTimestamp(minTimestamp) + default: + break + } + if let updatedInclusion = updatedInclusion { + modifier.updatePeerChatListInclusion(id, inclusion: updatedInclusion) + } +} + public func updatePeers(modifier: Modifier, peers: [Peer], update: (Peer?, Peer) -> Peer?) { modifier.updatePeersInternal(peers, update: { previous, updated in let peerId = updated.id