From d15818649ba92b64cf4bd3836a82d0592ebed76d Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Tue, 16 Jul 2024 13:33:46 +0800 Subject: [PATCH] Recent apps --- .../Sources/AccountContext.swift | 15 +- .../Sources/ChatListSearchContainerNode.swift | 10 +- .../ChatListSearchFiltersContainerNode.swift | 4 + .../Sources/ChatListSearchListPaneNode.swift | 247 +++++++++++++++-- .../ChatListSearchPaneContainerNode.swift | 4 + submodules/TelegramApi/Sources/Api0.swift | 6 +- submodules/TelegramApi/Sources/Api25.swift | 12 + submodules/TelegramApi/Sources/Api28.swift | 44 ++-- submodules/TelegramApi/Sources/Api29.swift | 122 ++++----- submodules/TelegramApi/Sources/Api30.swift | 118 +++++---- submodules/TelegramApi/Sources/Api31.swift | 160 ++++------- submodules/TelegramApi/Sources/Api32.swift | 182 +++++++------ submodules/TelegramApi/Sources/Api33.swift | 190 ++++++-------- submodules/TelegramApi/Sources/Api34.swift | 248 ++++++++---------- submodules/TelegramApi/Sources/Api35.swift | 138 ++++++++++ submodules/TelegramApi/Sources/Api36.swift | 100 +++++++ .../SyncCore/SyncCore_Namespaces.swift | 1 + .../Peers/ChannelRecommendation.swift | 66 +++++ .../TelegramEngine/Peers/RecentPeers.swift | 58 ++++ .../Peers/TelegramEnginePeers.swift | 16 ++ 20 files changed, 1140 insertions(+), 601 deletions(-) diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index 3d464347d6..74e7e2e42a 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -714,6 +714,7 @@ public enum ChatListSearchFilter: Equatable { case chats case topics case channels + case apps case media case downloads case links @@ -731,18 +732,20 @@ public enum ChatListSearchFilter: Equatable { return 1 case .channels: return 2 - case .media: + case .apps: return 3 - case .downloads: + case .media: return 4 - case .links: + case .downloads: return 5 - case .files: + case .links: return 6 - case .music: + case .files: return 7 - case .voice: + case .music: return 8 + case .voice: + return 9 case let .peer(peerId, _, _, _): return peerId.id._internalGetInt64Value() case let .date(_, date, _): diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 8e195db6b8..3572d2f62a 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -145,6 +145,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo private var validLayout: (ContainerViewLayout, CGFloat)? private let sharedOpenStoryDisposable = MetaDisposable() + private var recentAppsDisposable: Disposable? public init(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, filter: ChatListNodePeersFilter, requestPeerType: [ReplyMarkupButtonRequestPeerType]?, location: ChatListControllerLocation, displaySearchFilters: Bool, hasDownloads: Bool, initialFilter: ChatListSearchFilter = .chats, openPeer originalOpenPeer: @escaping (EnginePeer, EnginePeer?, Int64?, Bool) -> Void, openDisabledPeer: @escaping (EnginePeer, Int64?, ChatListDisabledPeerReason) -> Void, openRecentPeerOptions: @escaping (EnginePeer) -> Void, openMessage originalOpenMessage: @escaping (EnginePeer, Int64?, EngineMessage.Id, Bool) -> Void, addContact: ((String) -> Void)?, peerContextAction: ((EnginePeer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?, CGPoint?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, navigationController: NavigationController?, parentController: @escaping () -> ViewController?) { var initialFilter = initialFilter @@ -293,6 +294,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo filterKey = .topics case .channels: filterKey = .channels + case .apps: + filterKey = .apps case .media: filterKey = .media case .downloads: @@ -347,6 +350,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo key = .topics case .channels: key = .channels + case .apps: + key = .apps case .media: key = .media case .downloads: @@ -386,7 +391,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo switch filter { case let .filter(filter): switch filter { - case .downloads, .channels: + case .downloads, .channels, .apps: return false default: return true @@ -518,6 +523,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo }) } + self.recentAppsDisposable = context.engine.peers.managedUpdatedRecentApps().startStrict() + self._ready.set(self.paneContainerNode.isReady.get() |> map { _ in Void() }) } @@ -528,6 +535,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo self.suggestedFiltersDisposable.dispose() self.shareStatusDisposable?.dispose() self.sharedOpenStoryDisposable.dispose() + self.recentAppsDisposable?.dispose() self.copyProtectionTooltipController?.dismiss() } diff --git a/submodules/ChatListUI/Sources/ChatListSearchFiltersContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchFiltersContainerNode.swift index 5a49592739..4ac67d6a96 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchFiltersContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchFiltersContainerNode.swift @@ -87,6 +87,10 @@ private final class ItemNode: ASDisplayNode { case .channels: title = presentationData.strings.ChatList_Search_FilterChannels icon = nil + case .apps: + //TODO:localize + title = "Apps" + icon = nil case .media: title = presentationData.strings.ChatList_Search_FilterMedia icon = nil diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 695a2b85ba..fa182a92d7 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -41,6 +41,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable { enum Section { case local case recommendedChannels + case popularApps } case topPeers([EnginePeer], PresentationTheme, PresentationStrings) @@ -108,7 +109,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable { animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, openStories: @escaping (EnginePeer.Id, AvatarNode) -> Void, - isChannelsTabExpanded: Bool, + isChannelsTabExpanded: Bool?, toggleChannelsTabExpanded: @escaping () -> Void ) -> ListViewItem { switch self { @@ -240,9 +241,26 @@ private enum ChatListRecentEntry: Comparable, Identifiable { if case .recommendedChannels = section { header = ChatListSearchItemHeader(type: .text(presentationData.strings.ChatList_Search_SectionRecommendedChannels, 1), theme: theme, strings: strings) } else { - header = ChatListSearchItemHeader(type: .text(presentationData.strings.ChatList_Search_SectionLocalChannels, 0), theme: theme, strings: strings, actionTitle: isChannelsTabExpanded ? presentationData.strings.ChatList_Search_SectionActionShowLess : presentationData.strings.ChatList_Search_SectionActionShowMore, action: { - toggleChannelsTabExpanded() - }) + if let isChannelsTabExpanded { + header = ChatListSearchItemHeader(type: .text(presentationData.strings.ChatList_Search_SectionLocalChannels, 0), theme: theme, strings: strings, actionTitle: isChannelsTabExpanded ? presentationData.strings.ChatList_Search_SectionActionShowLess : presentationData.strings.ChatList_Search_SectionActionShowMore, action: { + toggleChannelsTabExpanded() + }) + } else { + header = ChatListSearchItemHeader(type: .text(presentationData.strings.ChatList_Search_SectionLocalChannels, 0), theme: theme, strings: strings, actionTitle: nil, action: nil) + } + } + } else if case .apps = key { + //TODO:localize + if case .popularApps = section { + header = ChatListSearchItemHeader(type: .text("POPULAR APPS", 1), theme: theme, strings: strings) + } else { + if let isChannelsTabExpanded { + header = ChatListSearchItemHeader(type: .text("APPS YOU USE", 0), theme: theme, strings: strings, actionTitle: isChannelsTabExpanded ? presentationData.strings.ChatList_Search_SectionActionShowLess : presentationData.strings.ChatList_Search_SectionActionShowMore, action: { + toggleChannelsTabExpanded() + }) + } else { + header = ChatListSearchItemHeader(type: .text("APPS YOU USE", 0), theme: theme, strings: strings, actionTitle: nil, action: nil) + } } } else { header = ChatListSearchItemHeader(type: .recentPeers, theme: theme, strings: strings, actionTitle: strings.WebSearch_RecentSectionClear, action: { @@ -276,7 +294,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable { } }, deletePeer: deletePeer, - contextAction: key == .channels ? nil : peerContextAction.flatMap { peerContextAction in + contextAction: (key == .channels || key == .apps) ? nil : peerContextAction.flatMap { peerContextAction in return { node, gesture, location in if let chatPeer = peer.peer.peers[peer.peer.peerId] { peerContextAction(EnginePeer(chatPeer), .recentSearch, node, gesture, location) @@ -708,6 +726,8 @@ public enum ChatListSearchEntry: Comparable, Identifiable { let headerType: ChatListSearchItemHeaderType if case .channels = key { headerType = .channels + } else if case .apps = key { + headerType = .channels } else { if filter.contains(.onlyGroups) { headerType = .chats @@ -977,7 +997,7 @@ private func chatListSearchContainerPreparedRecentTransition( animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, openStories: @escaping (EnginePeer.Id, AvatarNode) -> Void, - isChannelsTabExpanded: Bool, + isChannelsTabExpanded: Bool?, toggleChannelsTabExpanded: @escaping () -> Void, isEmpty: Bool ) -> ChatListSearchContainerRecentTransition { @@ -1327,6 +1347,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { tagMask = nil case .channels: tagMask = nil + case .apps: + tagMask = nil case .media: tagMask = .photoOrVideo case .downloads: @@ -1396,7 +1418,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { self.emptyResultsAnimationNode = DefaultAnimatedStickerNodeImpl() self.emptyResultsAnimationNode.isHidden = true - if key == .channels { + if key == .channels || key == .apps { let emptyRecentTitleNode = ImmediateTextNode() emptyRecentTitleNode.displaysAsynchronously = false emptyRecentTitleNode.attributedText = NSAttributedString(string: presentationData.strings.ChatList_Search_RecommendedChannelsEmpty_Title, font: Font.semibold(17.0), textColor: self.presentationData.theme.list.freeTextColor) @@ -1409,7 +1431,12 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { emptyRecentTextNode.maximumNumberOfLines = 0 emptyRecentTextNode.textAlignment = .center emptyRecentTextNode.isHidden = true - emptyRecentTextNode.attributedText = NSAttributedString(string: presentationData.strings.ChatList_Search_RecommendedChannelsEmpty_Text, font: Font.regular(15.0), textColor: presentationData.theme.list.freeTextColor) + if key == .channels { + emptyRecentTextNode.attributedText = NSAttributedString(string: presentationData.strings.ChatList_Search_RecommendedChannelsEmpty_Text, font: Font.regular(15.0), textColor: presentationData.theme.list.freeTextColor) + } else if key == .apps { + //TODO:localize + emptyRecentTextNode.attributedText = NSAttributedString(string: "No Apps Found", font: Font.regular(15.0), textColor: presentationData.theme.list.freeTextColor) + } self.emptyRecentTextNode = emptyRecentTextNode let emptyRecentAnimationNode = DefaultAnimatedStickerNodeImpl() @@ -1575,7 +1602,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { let foundItems: Signal<([ChatListSearchEntry], Bool)?, NoError> = combineLatest(queue: .mainQueue(), searchQuery, searchOptions, downloadItems) |> mapToSignal { [weak self] query, options, downloadItems -> Signal<([ChatListSearchEntry], Bool)?, NoError> in - if query == nil && options == nil && [.chats, .topics, .channels].contains(key) { + if query == nil && options == nil && [.chats, .topics, .channels, .apps].contains(key) { let _ = currentRemotePeers.swap(nil) return .single(nil) } @@ -1900,6 +1927,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { return (peers: resultPeers, unread: unread, recentlySearchedPeerIds: Set()) } } + } else if let query, key == .apps { + let _ = query + foundLocalPeers = .single(([], [:], Set())) } else { foundLocalPeers = .single((peers: [], unread: [:], recentlySearchedPeerIds: Set())) @@ -1926,6 +1956,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { |> map { ($0.0, $0.1, false) } ) ) + } else if let query, case .apps = key { + let _ = query + foundRemotePeers = .single(([], [], false)) } else { foundRemotePeers = .single(([], [], false)) } @@ -2990,6 +3023,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { let hasRecentPeers: Signal if case .channels = key { hasRecentPeers = .single(false) + } else if case .apps = key { + hasRecentPeers = .single(false) } else { hasRecentPeers = context.engine.peers.recentPeers() |> map { value -> Bool in @@ -3005,7 +3040,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { struct RecentItems { var entries: [ChatListRecentEntry] - var isChannelsTabExpanded: Bool + var isChannelsTabExpanded: Bool? var recommendedChannelOrder: [EnginePeer.Id] var isEmpty: Bool } @@ -3094,19 +3129,19 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } } - return .single(RecentItems(entries: entries, isChannelsTabExpanded: false, recommendedChannelOrder: [], isEmpty: false)) + return .single(RecentItems(entries: entries, isChannelsTabExpanded: nil, recommendedChannelOrder: [], isEmpty: false)) } if peersFilter.contains(.excludeRecent) { - recentItems = .single(RecentItems(entries: [], isChannelsTabExpanded: false, recommendedChannelOrder: [], isEmpty: false)) + recentItems = .single(RecentItems(entries: [], isChannelsTabExpanded: nil, recommendedChannelOrder: [], isEmpty: false)) } if case .savedMessagesChats = location { - recentItems = .single(RecentItems(entries: [], isChannelsTabExpanded: false, recommendedChannelOrder: [], isEmpty: false)) + recentItems = .single(RecentItems(entries: [], isChannelsTabExpanded: nil, recommendedChannelOrder: [], isEmpty: false)) } if case .channels = key { struct LocalChannels { var peerIds: [EnginePeer.Id] - var isExpanded: Bool + var isExpanded: Bool? } let localChannels = isChannelsTabExpandedValue.get() |> mapToSignal { isChannelsTabExpanded -> Signal in @@ -3278,6 +3313,165 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { return RecentItems(entries: result, isChannelsTabExpanded: isChannelsTabExpanded, recommendedChannelOrder: recommendedChannelOrder, isEmpty: isEmpty) } } + } else if case .apps = key { + struct LocalApps { + var peerIds: [EnginePeer.Id] + var isExpanded: Bool? + } + let localApps = isChannelsTabExpandedValue.get() + |> mapToSignal { isChannelsTabExpanded -> Signal in + return context.engine.peers.recentApps() + |> map { peerIds -> LocalApps in + var isExpanded: Bool? = isChannelsTabExpanded + var peerIds = peerIds + if peerIds.count > 5 { + if !isChannelsTabExpanded { + peerIds = Array(peerIds.prefix(5)) + } + } else { + isExpanded = nil + } + return LocalApps(peerIds: peerIds, isExpanded: isExpanded) + } + } + + let remoteApps: Signal<[EnginePeer.Id]?, NoError> = context.engine.peers.recommendedAppPeerIds() + + let _ = self.context.engine.peers.requestRecommendedAppsIfNeeded().startStandalone() + + recentItems = combineLatest( + localApps, + remoteApps + ) + |> mapToSignal { localApps, remoteApps -> Signal in + var allAppIds = localApps.peerIds + + var recommendedAppOrder: [EnginePeer.Id] = [] + if let remoteApps { + for peerId in remoteApps { + if !allAppIds.contains(peerId) { + allAppIds.append(peerId) + } + recommendedAppOrder.append(peerId) + } + } + + return context.engine.data.subscribe( + EngineDataMap( + allAppIds.map { peerId -> TelegramEngine.EngineData.Item.Peer.Peer in + return TelegramEngine.EngineData.Item.Peer.Peer(id: peerId) + } + ), + EngineDataMap( + allAppIds.map { peerId -> TelegramEngine.EngineData.Item.Peer.NotificationSettings in + return TelegramEngine.EngineData.Item.Peer.NotificationSettings(id: peerId) + } + ), + EngineDataMap( + allAppIds.map { peerId -> TelegramEngine.EngineData.Item.Messages.PeerUnreadCount in + return TelegramEngine.EngineData.Item.Messages.PeerUnreadCount(id: peerId) + } + ), + EngineDataMap( + allAppIds.map { peerId -> TelegramEngine.EngineData.Item.Peer.StoryStats in + return TelegramEngine.EngineData.Item.Peer.StoryStats(id: peerId) + } + ), + EngineDataMap( + allAppIds.map { peerId -> TelegramEngine.EngineData.Item.Messages.PeerReadCounters in + return TelegramEngine.EngineData.Item.Messages.PeerReadCounters(id: peerId) + } + ), + TelegramEngine.EngineData.Item.NotificationSettings.Global() + ) + |> map { peers, notificationSettings, unreadCounts, storyStats, readCounters, globalNotificationSettings -> RecentItems in + var result: [ChatListRecentEntry] = [] + var existingIds = Set() + + for id in localApps.peerIds { + if existingIds.contains(id) { + continue + } + existingIds.insert(id) + guard let peer = peers[id], let peer else { + continue + } + let peerNotificationSettings = notificationSettings[id] + //TODO:localize + let subpeerSummary: RecentlySearchedPeerSubpeerSummary? = nil + var peerStoryStats: PeerStoryStats? + if let value = storyStats[peer.id] { + peerStoryStats = value + } + var unreadCount: Int32 = 0 + if let value = readCounters[peer.id] { + unreadCount = value.count + } + result.append(.peer( + index: result.count, + peer: RecentlySearchedPeer( + peer: RenderedPeer(peer: peer._asPeer()), + presence: nil, + notificationSettings: peerNotificationSettings.flatMap({ $0._asNotificationSettings() }), + unreadCount: unreadCount, + subpeerSummary: subpeerSummary + ), + .local, + presentationData.theme, + presentationData.strings, + presentationData.dateTimeFormat, + presentationData.nameSortOrder, + presentationData.nameDisplayOrder, + globalNotificationSettings, + peerStoryStats, + false + )) + } + if let remoteApps { + for appPeerId in remoteApps { + if existingIds.contains(appPeerId) { + continue + } + existingIds.insert(appPeerId) + guard let peer = peers[appPeerId], let peer else { + continue + } + let peerNotificationSettings = notificationSettings[appPeerId] + let subpeerSummary: RecentlySearchedPeerSubpeerSummary? = nil + var peerStoryStats: PeerStoryStats? + if let value = storyStats[peer.id] { + peerStoryStats = value + } + result.append(.peer( + index: result.count, + peer: RecentlySearchedPeer( + peer: RenderedPeer(peer: peer._asPeer()), + presence: nil, + notificationSettings: peerNotificationSettings.flatMap({ $0._asNotificationSettings() }), + unreadCount: 0, + subpeerSummary: subpeerSummary + ), + .popularApps, + presentationData.theme, + presentationData.strings, + presentationData.dateTimeFormat, + presentationData.nameSortOrder, + presentationData.nameDisplayOrder, + globalNotificationSettings, + peerStoryStats, + false + )) + } + } + + var isEmpty = false + if localApps.peerIds.isEmpty, let remoteApps, remoteApps.isEmpty { + isEmpty = true + } + + return RecentItems(entries: result, isChannelsTabExpanded: localApps.isExpanded, recommendedChannelOrder: recommendedAppOrder, isEmpty: isEmpty) + } + } } if case .chats = key, !peersFilter.contains(.excludeRecent) { @@ -3331,6 +3525,25 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { customChatNavigationStack: customChatNavigationStack )) } + } else if case .apps = key { + if let navigationController = self.navigationController { + var customChatNavigationStack: [EnginePeer.Id]? + if isRecommended { + if let recommendedChannelOrder = previousRecentItemsValue.with({ $0 })?.recommendedChannelOrder { + var customChatNavigationStackValue: [EnginePeer.Id] = [] + customChatNavigationStackValue.append(contentsOf: recommendedChannelOrder) + customChatNavigationStack = customChatNavigationStackValue + } + } + + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams( + navigationController: navigationController, + context: self.context, + chatLocation: .peer(peer), + keepStack: .always, + customChatNavigationStack: customChatNavigationStack + )) + } } else { interaction.openPeer(peer, nil, threadId, true) if threadId == nil { @@ -4000,7 +4213,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { self.enqueuedTransitions.remove(at: 0) var options = ListViewDeleteAndInsertOptions() - if isFirstTime && [.chats, .topics, .channels].contains(self.key) { + if isFirstTime && [.chats, .topics, .channels, .apps].contains(self.key) { options.insert(.PreferSynchronousDrawing) options.insert(.PreferSynchronousResourceLoading) } else if transition.animated { @@ -4073,7 +4286,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { strongSelf.emptyResultsAnimationNode.visibility = emptyResults } - var displayPlaceholder = transition.isLoading && (![.chats, .topics, .channels].contains(strongSelf.key) || (strongSelf.currentEntries?.isEmpty ?? true)) + var displayPlaceholder = transition.isLoading && (![.chats, .topics, .channels, .apps].contains(strongSelf.key) || (strongSelf.currentEntries?.isEmpty ?? true)) if strongSelf.key == .downloads { displayPlaceholder = false } @@ -4309,7 +4522,7 @@ public final class ChatListSearchShimmerNode: ASDisplayNode { let items = (0 ..< 2).compactMap { _ -> ListViewItem? in switch key { - case .chats, .topics, .channels, .downloads: + case .chats, .topics, .channels, .apps, .downloads: let message = EngineMessage( stableId: 0, stableVersion: 0, diff --git a/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift index 0b32ff7113..8605ead568 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchPaneContainerNode.swift @@ -51,6 +51,7 @@ public enum ChatListSearchPaneKey { case chats case topics case channels + case apps case media case downloads case links @@ -68,6 +69,8 @@ extension ChatListSearchPaneKey { return .topics case .channels: return .channels + case .apps: + return .apps case .media: return .media case .downloads: @@ -92,6 +95,7 @@ func defaultAvailableSearchPanes(isForum: Bool, hasDownloads: Bool) -> [ChatList result.append(.chats) } result.append(.channels) + result.append(.apps) result.append(contentsOf: [.media, .downloads, .links, .files, .music, .voice]) if !hasDownloads { diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index ed8f346cf9..2b3e37e1d4 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -921,6 +921,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-94849324] = { return Api.ThemeSettings.parse_themeSettings($0) } dict[-7173643] = { return Api.Timezone.parse_timezone($0) } dict[-305282981] = { return Api.TopPeer.parse_topPeer($0) } + dict[-39945236] = { return Api.TopPeerCategory.parse_topPeerCategoryBotsApp($0) } dict[344356834] = { return Api.TopPeerCategory.parse_topPeerCategoryBotsInline($0) } dict[-1419371685] = { return Api.TopPeerCategory.parse_topPeerCategoryBotsPM($0) } dict[371037736] = { return Api.TopPeerCategory.parse_topPeerCategoryChannels($0) } @@ -1167,6 +1168,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1284008785] = { return Api.auth.SentCodeType.parse_sentCodeTypeSmsPhrase($0) } dict[-1542017919] = { return Api.auth.SentCodeType.parse_sentCodeTypeSmsWord($0) } dict[-391678544] = { return Api.bots.BotInfo.parse_botInfo($0) } + dict[428978491] = { return Api.bots.PopularAppBots.parse_popularAppBots($0) } dict[-309659827] = { return Api.channels.AdminLogResults.parse_adminLogResults($0) } dict[-541588713] = { return Api.channels.ChannelParticipant.parse_channelParticipant($0) } dict[-1699676497] = { return Api.channels.ChannelParticipants.parse_channelParticipants($0) } @@ -1396,7 +1398,7 @@ public extension Api { return parser(reader) } else { - telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found") + telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found") return nil } } @@ -2146,6 +2148,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.bots.BotInfo: _1.serialize(buffer, boxed) + case let _1 as Api.bots.PopularAppBots: + _1.serialize(buffer, boxed) case let _1 as Api.channels.AdminLogResults: _1.serialize(buffer, boxed) case let _1 as Api.channels.ChannelParticipant: diff --git a/submodules/TelegramApi/Sources/Api25.swift b/submodules/TelegramApi/Sources/Api25.swift index 7d031ef300..ec78a2243a 100644 --- a/submodules/TelegramApi/Sources/Api25.swift +++ b/submodules/TelegramApi/Sources/Api25.swift @@ -86,6 +86,7 @@ public extension Api { } public extension Api { enum TopPeerCategory: TypeConstructorDescription { + case topPeerCategoryBotsApp case topPeerCategoryBotsInline case topPeerCategoryBotsPM case topPeerCategoryChannels @@ -97,6 +98,12 @@ public extension Api { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { + case .topPeerCategoryBotsApp: + if boxed { + buffer.appendInt32(-39945236) + } + + break case .topPeerCategoryBotsInline: if boxed { buffer.appendInt32(344356834) @@ -150,6 +157,8 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { + case .topPeerCategoryBotsApp: + return ("topPeerCategoryBotsApp", []) case .topPeerCategoryBotsInline: return ("topPeerCategoryBotsInline", []) case .topPeerCategoryBotsPM: @@ -169,6 +178,9 @@ public extension Api { } } + public static func parse_topPeerCategoryBotsApp(_ reader: BufferReader) -> TopPeerCategory? { + return Api.TopPeerCategory.topPeerCategoryBotsApp + } public static func parse_topPeerCategoryBotsInline(_ reader: BufferReader) -> TopPeerCategory? { return Api.TopPeerCategory.topPeerCategoryBotsInline } diff --git a/submodules/TelegramApi/Sources/Api28.swift b/submodules/TelegramApi/Sources/Api28.swift index 29cc8fa57a..7f9b44e542 100644 --- a/submodules/TelegramApi/Sources/Api28.swift +++ b/submodules/TelegramApi/Sources/Api28.swift @@ -920,26 +920,18 @@ public extension Api.bots { } } -public extension Api.channels { - enum AdminLogResults: TypeConstructorDescription { - case adminLogResults(events: [Api.ChannelAdminLogEvent], chats: [Api.Chat], users: [Api.User]) +public extension Api.bots { + enum PopularAppBots: TypeConstructorDescription { + case popularAppBots(flags: Int32, nextOffset: String?, users: [Api.User]) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .adminLogResults(let events, let chats, let users): + case .popularAppBots(let flags, let nextOffset, let users): if boxed { - buffer.appendInt32(-309659827) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(events.count)) - for item in events { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(chats.count)) - for item in chats { - item.serialize(buffer, true) + buffer.appendInt32(428978491) } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)} buffer.appendInt32(481674261) buffer.appendInt32(Int32(users.count)) for item in users { @@ -951,29 +943,25 @@ public extension Api.channels { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .adminLogResults(let events, let chats, let users): - return ("adminLogResults", [("events", events as Any), ("chats", chats as Any), ("users", users as Any)]) + case .popularAppBots(let flags, let nextOffset, let users): + return ("popularAppBots", [("flags", flags as Any), ("nextOffset", nextOffset as Any), ("users", users as Any)]) } } - public static func parse_adminLogResults(_ reader: BufferReader) -> AdminLogResults? { - var _1: [Api.ChannelAdminLogEvent]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChannelAdminLogEvent.self) - } - var _2: [Api.Chat]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } + public static func parse_popularAppBots(_ reader: BufferReader) -> PopularAppBots? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 0) != 0 {_2 = parseString(reader) } 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 _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.channels.AdminLogResults.adminLogResults(events: _1!, chats: _2!, users: _3!) + return Api.bots.PopularAppBots.popularAppBots(flags: _1!, nextOffset: _2, users: _3!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api29.swift b/submodules/TelegramApi/Sources/Api29.swift index 04914ae0cb..8af8e80f63 100644 --- a/submodules/TelegramApi/Sources/Api29.swift +++ b/submodules/TelegramApi/Sources/Api29.swift @@ -1,3 +1,65 @@ +public extension Api.channels { + enum AdminLogResults: TypeConstructorDescription { + case adminLogResults(events: [Api.ChannelAdminLogEvent], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .adminLogResults(let events, let chats, let users): + if boxed { + buffer.appendInt32(-309659827) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(events.count)) + for item in events { + 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 + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .adminLogResults(let events, let chats, let users): + return ("adminLogResults", [("events", events as Any), ("chats", chats as Any), ("users", users as Any)]) + } + } + + public static func parse_adminLogResults(_ reader: BufferReader) -> AdminLogResults? { + var _1: [Api.ChannelAdminLogEvent]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ChannelAdminLogEvent.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.channels.AdminLogResults.adminLogResults(events: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} public extension Api.channels { enum ChannelParticipant: TypeConstructorDescription { case channelParticipant(participant: Api.ChannelParticipant, chats: [Api.Chat], users: [Api.User]) @@ -1400,63 +1462,3 @@ public extension Api.help { } } -public extension Api.help { - enum CountryCode: TypeConstructorDescription { - case countryCode(flags: Int32, countryCode: String, prefixes: [String]?, patterns: [String]?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .countryCode(let flags, let countryCode, let prefixes, let patterns): - if boxed { - buffer.appendInt32(1107543535) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeString(countryCode, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(prefixes!.count)) - for item in prefixes! { - serializeString(item, buffer: buffer, boxed: false) - }} - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(patterns!.count)) - for item in patterns! { - serializeString(item, buffer: buffer, boxed: false) - }} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .countryCode(let flags, let countryCode, let prefixes, let patterns): - return ("countryCode", [("flags", flags as Any), ("countryCode", countryCode as Any), ("prefixes", prefixes as Any), ("patterns", patterns as Any)]) - } - } - - public static func parse_countryCode(_ reader: BufferReader) -> CountryCode? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - _2 = parseString(reader) - var _3: [String]? - if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) - } } - var _4: [String]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.help.CountryCode.countryCode(flags: _1!, countryCode: _2!, prefixes: _3, patterns: _4) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api30.swift b/submodules/TelegramApi/Sources/Api30.swift index fd1655b713..7c9e867d13 100644 --- a/submodules/TelegramApi/Sources/Api30.swift +++ b/submodules/TelegramApi/Sources/Api30.swift @@ -1,3 +1,63 @@ +public extension Api.help { + enum CountryCode: TypeConstructorDescription { + case countryCode(flags: Int32, countryCode: String, prefixes: [String]?, patterns: [String]?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .countryCode(let flags, let countryCode, let prefixes, let patterns): + if boxed { + buffer.appendInt32(1107543535) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeString(countryCode, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(prefixes!.count)) + for item in prefixes! { + serializeString(item, buffer: buffer, boxed: false) + }} + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(patterns!.count)) + for item in patterns! { + serializeString(item, buffer: buffer, boxed: false) + }} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .countryCode(let flags, let countryCode, let prefixes, let patterns): + return ("countryCode", [("flags", flags as Any), ("countryCode", countryCode as Any), ("prefixes", prefixes as Any), ("patterns", patterns as Any)]) + } + } + + public static func parse_countryCode(_ reader: BufferReader) -> CountryCode? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: [String]? + if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + } } + var _4: [String]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: -1255641564, elementType: String.self) + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil + let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.help.CountryCode.countryCode(flags: _1!, countryCode: _2!, prefixes: _3, patterns: _4) + } + else { + return nil + } + } + + } +} public extension Api.help { enum DeepLinkInfo: TypeConstructorDescription { case deepLinkInfo(flags: Int32, message: String, entities: [Api.MessageEntity]?) @@ -1232,61 +1292,3 @@ public extension Api.messages { } } -public extension Api.messages { - enum AvailableReactions: TypeConstructorDescription { - case availableReactions(hash: Int32, reactions: [Api.AvailableReaction]) - case availableReactionsNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .availableReactions(let hash, let reactions): - if boxed { - buffer.appendInt32(1989032621) - } - serializeInt32(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(reactions.count)) - for item in reactions { - item.serialize(buffer, true) - } - break - case .availableReactionsNotModified: - if boxed { - buffer.appendInt32(-1626924713) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .availableReactions(let hash, let reactions): - return ("availableReactions", [("hash", hash as Any), ("reactions", reactions as Any)]) - case .availableReactionsNotModified: - return ("availableReactionsNotModified", []) - } - } - - public static func parse_availableReactions(_ reader: BufferReader) -> AvailableReactions? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.AvailableReaction]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.AvailableReaction.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.AvailableReactions.availableReactions(hash: _1!, reactions: _2!) - } - else { - return nil - } - } - public static func parse_availableReactionsNotModified(_ reader: BufferReader) -> AvailableReactions? { - return Api.messages.AvailableReactions.availableReactionsNotModified - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api31.swift b/submodules/TelegramApi/Sources/Api31.swift index 5b9410024d..56ce04bdea 100644 --- a/submodules/TelegramApi/Sources/Api31.swift +++ b/submodules/TelegramApi/Sources/Api31.swift @@ -1,3 +1,61 @@ +public extension Api.messages { + enum AvailableReactions: TypeConstructorDescription { + case availableReactions(hash: Int32, reactions: [Api.AvailableReaction]) + case availableReactionsNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .availableReactions(let hash, let reactions): + if boxed { + buffer.appendInt32(1989032621) + } + serializeInt32(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(reactions.count)) + for item in reactions { + item.serialize(buffer, true) + } + break + case .availableReactionsNotModified: + if boxed { + buffer.appendInt32(-1626924713) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .availableReactions(let hash, let reactions): + return ("availableReactions", [("hash", hash as Any), ("reactions", reactions as Any)]) + case .availableReactionsNotModified: + return ("availableReactionsNotModified", []) + } + } + + public static func parse_availableReactions(_ reader: BufferReader) -> AvailableReactions? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.AvailableReaction]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.AvailableReaction.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.AvailableReactions.availableReactions(hash: _1!, reactions: _2!) + } + else { + return nil + } + } + public static func parse_availableReactionsNotModified(_ reader: BufferReader) -> AvailableReactions? { + return Api.messages.AvailableReactions.availableReactionsNotModified + } + + } +} public extension Api.messages { enum BotApp: TypeConstructorDescription { case botApp(flags: Int32, app: Api.BotApp) @@ -1372,105 +1430,3 @@ public extension Api.messages { } } -public extension Api.messages { - enum HistoryImportParsed: TypeConstructorDescription { - case historyImportParsed(flags: Int32, title: String?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .historyImportParsed(let flags, let title): - if boxed { - buffer.appendInt32(1578088377) - } - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 2) != 0 {serializeString(title!, buffer: buffer, boxed: false)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .historyImportParsed(let flags, let title): - return ("historyImportParsed", [("flags", flags as Any), ("title", title as Any)]) - } - } - - public static func parse_historyImportParsed(_ reader: BufferReader) -> HistoryImportParsed? { - var _1: Int32? - _1 = reader.readInt32() - var _2: String? - if Int(_1!) & Int(1 << 2) != 0 {_2 = parseString(reader) } - let _c1 = _1 != nil - let _c2 = (Int(_1!) & Int(1 << 2) == 0) || _2 != nil - if _c1 && _c2 { - return Api.messages.HistoryImportParsed.historyImportParsed(flags: _1!, title: _2) - } - else { - return nil - } - } - - } -} -public extension Api.messages { - enum InactiveChats: TypeConstructorDescription { - case inactiveChats(dates: [Int32], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inactiveChats(let dates, let chats, let users): - if boxed { - buffer.appendInt32(-1456996667) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(dates.count)) - for item in dates { - serializeInt32(item, buffer: buffer, boxed: false) - } - 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 - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inactiveChats(let dates, let chats, let users): - return ("inactiveChats", [("dates", dates as Any), ("chats", chats as Any), ("users", users as Any)]) - } - } - - public static func parse_inactiveChats(_ reader: BufferReader) -> InactiveChats? { - var _1: [Int32]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.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.messages.InactiveChats.inactiveChats(dates: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api32.swift b/submodules/TelegramApi/Sources/Api32.swift index 6cdc8ecbd8..d31e82a113 100644 --- a/submodules/TelegramApi/Sources/Api32.swift +++ b/submodules/TelegramApi/Sources/Api32.swift @@ -1,3 +1,105 @@ +public extension Api.messages { + enum HistoryImportParsed: TypeConstructorDescription { + case historyImportParsed(flags: Int32, title: String?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .historyImportParsed(let flags, let title): + if boxed { + buffer.appendInt32(1578088377) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 2) != 0 {serializeString(title!, buffer: buffer, boxed: false)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .historyImportParsed(let flags, let title): + return ("historyImportParsed", [("flags", flags as Any), ("title", title as Any)]) + } + } + + public static func parse_historyImportParsed(_ reader: BufferReader) -> HistoryImportParsed? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + if Int(_1!) & Int(1 << 2) != 0 {_2 = parseString(reader) } + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 2) == 0) || _2 != nil + if _c1 && _c2 { + return Api.messages.HistoryImportParsed.historyImportParsed(flags: _1!, title: _2) + } + else { + return nil + } + } + + } +} +public extension Api.messages { + enum InactiveChats: TypeConstructorDescription { + case inactiveChats(dates: [Int32], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inactiveChats(let dates, let chats, let users): + if boxed { + buffer.appendInt32(-1456996667) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(dates.count)) + for item in dates { + serializeInt32(item, buffer: buffer, boxed: false) + } + 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 + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inactiveChats(let dates, let chats, let users): + return ("inactiveChats", [("dates", dates as Any), ("chats", chats as Any), ("users", users as Any)]) + } + } + + public static func parse_inactiveChats(_ reader: BufferReader) -> InactiveChats? { + var _1: [Int32]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.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.messages.InactiveChats.inactiveChats(dates: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} public extension Api.messages { indirect enum InvitedUsers: TypeConstructorDescription { case invitedUsers(updates: Api.Updates, missingInvitees: [Api.MissingInvitee]) @@ -1432,83 +1534,3 @@ public extension Api.messages { } } -public extension Api.messages { - enum StickerSet: TypeConstructorDescription { - case stickerSet(set: Api.StickerSet, packs: [Api.StickerPack], keywords: [Api.StickerKeyword], documents: [Api.Document]) - case stickerSetNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .stickerSet(let set, let packs, let keywords, let documents): - if boxed { - buffer.appendInt32(1846886166) - } - set.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(packs.count)) - for item in packs { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(keywords.count)) - for item in keywords { - item.serialize(buffer, true) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(documents.count)) - for item in documents { - item.serialize(buffer, true) - } - break - case .stickerSetNotModified: - if boxed { - buffer.appendInt32(-738646805) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .stickerSet(let set, let packs, let keywords, let documents): - return ("stickerSet", [("set", set as Any), ("packs", packs as Any), ("keywords", keywords as Any), ("documents", documents as Any)]) - case .stickerSetNotModified: - return ("stickerSetNotModified", []) - } - } - - public static func parse_stickerSet(_ reader: BufferReader) -> StickerSet? { - var _1: Api.StickerSet? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.StickerSet - } - var _2: [Api.StickerPack]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerPack.self) - } - var _3: [Api.StickerKeyword]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerKeyword.self) - } - var _4: [Api.Document]? - if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.messages.StickerSet.stickerSet(set: _1!, packs: _2!, keywords: _3!, documents: _4!) - } - else { - return nil - } - } - public static func parse_stickerSetNotModified(_ reader: BufferReader) -> StickerSet? { - return Api.messages.StickerSet.stickerSetNotModified - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api33.swift b/submodules/TelegramApi/Sources/Api33.swift index b8429bdcdc..508a3b6a35 100644 --- a/submodules/TelegramApi/Sources/Api33.swift +++ b/submodules/TelegramApi/Sources/Api33.swift @@ -1,3 +1,83 @@ +public extension Api.messages { + enum StickerSet: TypeConstructorDescription { + case stickerSet(set: Api.StickerSet, packs: [Api.StickerPack], keywords: [Api.StickerKeyword], documents: [Api.Document]) + case stickerSetNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .stickerSet(let set, let packs, let keywords, let documents): + if boxed { + buffer.appendInt32(1846886166) + } + set.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(packs.count)) + for item in packs { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(keywords.count)) + for item in keywords { + item.serialize(buffer, true) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(documents.count)) + for item in documents { + item.serialize(buffer, true) + } + break + case .stickerSetNotModified: + if boxed { + buffer.appendInt32(-738646805) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .stickerSet(let set, let packs, let keywords, let documents): + return ("stickerSet", [("set", set as Any), ("packs", packs as Any), ("keywords", keywords as Any), ("documents", documents as Any)]) + case .stickerSetNotModified: + return ("stickerSetNotModified", []) + } + } + + public static func parse_stickerSet(_ reader: BufferReader) -> StickerSet? { + var _1: Api.StickerSet? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.StickerSet + } + var _2: [Api.StickerPack]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerPack.self) + } + var _3: [Api.StickerKeyword]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StickerKeyword.self) + } + var _4: [Api.Document]? + if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.messages.StickerSet.stickerSet(set: _1!, packs: _2!, keywords: _3!, documents: _4!) + } + else { + return nil + } + } + public static func parse_stickerSetNotModified(_ reader: BufferReader) -> StickerSet? { + return Api.messages.StickerSet.stickerSetNotModified + } + + } +} public extension Api.messages { enum StickerSetInstallResult: TypeConstructorDescription { case stickerSetInstallResultArchive(sets: [Api.StickerSetCovered]) @@ -1552,113 +1632,3 @@ public extension Api.phone { } } -public extension Api.phone { - enum JoinAsPeers: TypeConstructorDescription { - case joinAsPeers(peers: [Api.Peer], chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .joinAsPeers(let peers, let chats, let users): - if boxed { - buffer.appendInt32(-1343921601) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(peers.count)) - for item in peers { - 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 - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .joinAsPeers(let peers, let chats, let users): - return ("joinAsPeers", [("peers", peers as Any), ("chats", chats as Any), ("users", users as Any)]) - } - } - - public static func parse_joinAsPeers(_ reader: BufferReader) -> JoinAsPeers? { - var _1: [Api.Peer]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.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.phone.JoinAsPeers.joinAsPeers(peers: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.phone { - enum PhoneCall: TypeConstructorDescription { - case phoneCall(phoneCall: Api.PhoneCall, users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .phoneCall(let phoneCall, let users): - if boxed { - buffer.appendInt32(-326966976) - } - phoneCall.serialize(buffer, true) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .phoneCall(let phoneCall, let users): - return ("phoneCall", [("phoneCall", phoneCall as Any), ("users", users as Any)]) - } - } - - public static func parse_phoneCall(_ reader: BufferReader) -> PhoneCall? { - var _1: Api.PhoneCall? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.PhoneCall - } - var _2: [Api.User]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.phone.PhoneCall.phoneCall(phoneCall: _1!, users: _2!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api34.swift b/submodules/TelegramApi/Sources/Api34.swift index 35e2700545..1e10a978c4 100644 --- a/submodules/TelegramApi/Sources/Api34.swift +++ b/submodules/TelegramApi/Sources/Api34.swift @@ -1,3 +1,113 @@ +public extension Api.phone { + enum JoinAsPeers: TypeConstructorDescription { + case joinAsPeers(peers: [Api.Peer], chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .joinAsPeers(let peers, let chats, let users): + if boxed { + buffer.appendInt32(-1343921601) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(peers.count)) + for item in peers { + 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 + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .joinAsPeers(let peers, let chats, let users): + return ("joinAsPeers", [("peers", peers as Any), ("chats", chats as Any), ("users", users as Any)]) + } + } + + public static func parse_joinAsPeers(_ reader: BufferReader) -> JoinAsPeers? { + var _1: [Api.Peer]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Peer.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.phone.JoinAsPeers.joinAsPeers(peers: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.phone { + enum PhoneCall: TypeConstructorDescription { + case phoneCall(phoneCall: Api.PhoneCall, users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .phoneCall(let phoneCall, let users): + if boxed { + buffer.appendInt32(-326966976) + } + phoneCall.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .phoneCall(let phoneCall, let users): + return ("phoneCall", [("phoneCall", phoneCall as Any), ("users", users as Any)]) + } + } + + public static func parse_phoneCall(_ reader: BufferReader) -> PhoneCall? { + var _1: Api.PhoneCall? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.PhoneCall + } + var _2: [Api.User]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.phone.PhoneCall.phoneCall(phoneCall: _1!, users: _2!) + } + else { + return nil + } + } + + } +} public extension Api.photos { enum Photo: TypeConstructorDescription { case photo(photo: Api.Photo, users: [Api.User]) @@ -1426,141 +1536,3 @@ public extension Api.stories { } } -public extension Api.stories { - enum PeerStories: TypeConstructorDescription { - case peerStories(stories: Api.PeerStories, chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .peerStories(let stories, let chats, let users): - if boxed { - buffer.appendInt32(-890861720) - } - stories.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 - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .peerStories(let stories, let chats, let users): - return ("peerStories", [("stories", stories as Any), ("chats", chats as Any), ("users", users as Any)]) - } - } - - public static func parse_peerStories(_ reader: BufferReader) -> PeerStories? { - var _1: Api.PeerStories? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.PeerStories - } - 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.stories.PeerStories.peerStories(stories: _1!, chats: _2!, users: _3!) - } - else { - return nil - } - } - - } -} -public extension Api.stories { - enum Stories: TypeConstructorDescription { - case stories(flags: Int32, count: Int32, stories: [Api.StoryItem], pinnedToTop: [Int32]?, chats: [Api.Chat], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .stories(let flags, let count, let stories, let pinnedToTop, let chats, let users): - if boxed { - buffer.appendInt32(1673780490) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(count, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(stories.count)) - for item in stories { - item.serialize(buffer, true) - } - if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(pinnedToTop!.count)) - for item in pinnedToTop! { - serializeInt32(item, buffer: buffer, boxed: false) - }} - 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 - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .stories(let flags, let count, let stories, let pinnedToTop, let chats, let users): - return ("stories", [("flags", flags as Any), ("count", count as Any), ("stories", stories as Any), ("pinnedToTop", pinnedToTop as Any), ("chats", chats as Any), ("users", users as Any)]) - } - } - - public static func parse_stories(_ reader: BufferReader) -> Stories? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: [Api.StoryItem]? - if let _ = reader.readInt32() { - _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryItem.self) - } - var _4: [Int32]? - if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { - _4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } } - var _5: [Api.Chat]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) - } - var _6: [Api.User]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.stories.Stories.stories(flags: _1!, count: _2!, stories: _3!, pinnedToTop: _4, chats: _5!, users: _6!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api35.swift b/submodules/TelegramApi/Sources/Api35.swift index c3cabdd4c7..0e9dfa8a85 100644 --- a/submodules/TelegramApi/Sources/Api35.swift +++ b/submodules/TelegramApi/Sources/Api35.swift @@ -1,3 +1,141 @@ +public extension Api.stories { + enum PeerStories: TypeConstructorDescription { + case peerStories(stories: Api.PeerStories, chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .peerStories(let stories, let chats, let users): + if boxed { + buffer.appendInt32(-890861720) + } + stories.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 + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .peerStories(let stories, let chats, let users): + return ("peerStories", [("stories", stories as Any), ("chats", chats as Any), ("users", users as Any)]) + } + } + + public static func parse_peerStories(_ reader: BufferReader) -> PeerStories? { + var _1: Api.PeerStories? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.PeerStories + } + 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.stories.PeerStories.peerStories(stories: _1!, chats: _2!, users: _3!) + } + else { + return nil + } + } + + } +} +public extension Api.stories { + enum Stories: TypeConstructorDescription { + case stories(flags: Int32, count: Int32, stories: [Api.StoryItem], pinnedToTop: [Int32]?, chats: [Api.Chat], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .stories(let flags, let count, let stories, let pinnedToTop, let chats, let users): + if boxed { + buffer.appendInt32(1673780490) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(count, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(stories.count)) + for item in stories { + item.serialize(buffer, true) + } + if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(pinnedToTop!.count)) + for item in pinnedToTop! { + serializeInt32(item, buffer: buffer, boxed: false) + }} + 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 + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .stories(let flags, let count, let stories, let pinnedToTop, let chats, let users): + return ("stories", [("flags", flags as Any), ("count", count as Any), ("stories", stories as Any), ("pinnedToTop", pinnedToTop as Any), ("chats", chats as Any), ("users", users as Any)]) + } + } + + public static func parse_stories(_ reader: BufferReader) -> Stories? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: [Api.StoryItem]? + if let _ = reader.readInt32() { + _3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryItem.self) + } + var _4: [Int32]? + if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { + _4 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } } + var _5: [Api.Chat]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self) + } + var _6: [Api.User]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.stories.Stories.stories(flags: _1!, count: _2!, stories: _3!, pinnedToTop: _4, chats: _5!, users: _6!) + } + else { + return nil + } + } + + } +} public extension Api.stories { enum StoryReactionsList: TypeConstructorDescription { case storyReactionsList(flags: Int32, count: Int32, reactions: [Api.StoryReaction], chats: [Api.Chat], users: [Api.User], nextOffset: String?) diff --git a/submodules/TelegramApi/Sources/Api36.swift b/submodules/TelegramApi/Sources/Api36.swift index 60de7eaded..614ecb3df2 100644 --- a/submodules/TelegramApi/Sources/Api36.swift +++ b/submodules/TelegramApi/Sources/Api36.swift @@ -2200,6 +2200,22 @@ public extension Api.functions.auth { }) } } +public extension Api.functions.bots { + static func addPreviewMedia(bot: Api.InputUser, media: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1633332331) + bot.serialize(buffer, true) + media.serialize(buffer, true) + return (FunctionDescription(name: "bots.addPreviewMedia", parameters: [("bot", String(describing: bot)), ("media", String(describing: media))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageMedia? in + let reader = BufferReader(buffer) + var result: Api.MessageMedia? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.MessageMedia + } + return result + }) + } +} public extension Api.functions.bots { static func allowSendMessage(bot: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -2246,6 +2262,39 @@ public extension Api.functions.bots { }) } } +public extension Api.functions.bots { + static func deletePreviewMedia(bot: Api.InputUser, media: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1220635873) + bot.serialize(buffer, true) + media.serialize(buffer, true) + return (FunctionDescription(name: "bots.deletePreviewMedia", parameters: [("bot", String(describing: bot)), ("media", String(describing: media))]), buffer, DeserializeFunctionResponse { (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 extension Api.functions.bots { + static func editPreviewMedia(bot: Api.InputUser, media: Api.InputMedia, newMedia: Api.InputMedia) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1436441263) + bot.serialize(buffer, true) + media.serialize(buffer, true) + newMedia.serialize(buffer, true) + return (FunctionDescription(name: "bots.editPreviewMedia", parameters: [("bot", String(describing: bot)), ("media", String(describing: media)), ("newMedia", String(describing: newMedia))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageMedia? in + let reader = BufferReader(buffer) + var result: Api.MessageMedia? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.MessageMedia + } + return result + }) + } +} public extension Api.functions.bots { static func getBotCommands(scope: Api.BotCommandScope, langCode: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.BotCommand]>) { let buffer = Buffer() @@ -2294,6 +2343,37 @@ public extension Api.functions.bots { }) } } +public extension Api.functions.bots { + static func getPopularAppBots(offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1034878574) + serializeString(offset, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "bots.getPopularAppBots", parameters: [("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.bots.PopularAppBots? in + let reader = BufferReader(buffer) + var result: Api.bots.PopularAppBots? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.bots.PopularAppBots + } + return result + }) + } +} +public extension Api.functions.bots { + static func getPreviewMedias(bot: Api.InputUser) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.MessageMedia]>) { + let buffer = Buffer() + buffer.appendInt32(1720252591) + bot.serialize(buffer, true) + return (FunctionDescription(name: "bots.getPreviewMedias", parameters: [("bot", String(describing: bot))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.MessageMedia]? in + let reader = BufferReader(buffer) + var result: [Api.MessageMedia]? + if let _ = reader.readInt32() { + result = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageMedia.self) + } + return result + }) + } +} public extension Api.functions.bots { static func invokeWebViewCustomMethod(bot: Api.InputUser, customMethod: String, params: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -2311,6 +2391,26 @@ public extension Api.functions.bots { }) } } +public extension Api.functions.bots { + static func reorderPreviewMedias(bot: Api.InputUser, order: [Api.InputMedia]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1472444656) + bot.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(order.count)) + for item in order { + item.serialize(buffer, true) + } + return (FunctionDescription(name: "bots.reorderPreviewMedias", parameters: [("bot", String(describing: bot)), ("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (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 extension Api.functions.bots { static func reorderUsernames(bot: Api.InputUser, order: [String]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift index 7514260687..928ba32a69 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift @@ -134,6 +134,7 @@ public struct Namespaces { public static let availableMessageEffects: Int8 = 37 public static let cachedStarsRevenueStats: Int8 = 38 public static let cachedRevenueStats: Int8 = 39 + public static let recommendedApps: Int8 = 40 } public struct UnorderedItemList { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift index 6d186fb821..ca5df1efee 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift @@ -46,6 +46,12 @@ private func entryId(peerId: EnginePeer.Id?) -> ItemCacheEntryId { return ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.recommendedChannels, key: cacheKey) } +private func appsEntryId() -> ItemCacheEntryId { + let cacheKey = ValueBoxKey(length: 8) + cacheKey.setInt64(0, value: 0) + return ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.recommendedApps, key: cacheKey) +} + func _internal_requestRecommendedChannels(account: Account, peerId: EnginePeer.Id?, forceUpdate: Bool) -> Signal { return account.postbox.transaction { transaction -> (Peer?, Bool) in if let peerId { @@ -134,6 +140,55 @@ func _internal_requestRecommendedChannels(account: Account, peerId: EnginePeer.I } } +func _internal_requestRecommendedApps(account: Account, forceUpdate: Bool) -> Signal { + return account.postbox.transaction { transaction -> (Peer?, Bool) in + if let entry = transaction.retrieveItemCacheEntry(id: appsEntryId())?.get(CachedRecommendedChannels.self), !entry.peerIds.isEmpty && !forceUpdate { + var shouldUpdate = false + if let timestamp = entry.timestamp { + if timestamp + 60 * 60 < Int32(Date().timeIntervalSince1970) { + shouldUpdate = true + } + } else { + shouldUpdate = true + } + return (nil, shouldUpdate) + } else { + return (nil, true) + } + } + |> mapToSignal { channel, shouldUpdate in + if !shouldUpdate { + return .complete() + } + return account.network.request(Api.functions.bots.getPopularAppBots(offset: "", limit: 100)) + |> retryRequest + |> mapToSignal { result -> Signal in + return account.postbox.transaction { transaction -> [EnginePeer] in + let users: [Api.User] + let parsedPeers: AccumulatedPeers + switch result { + case let .popularAppBots(_, nextOffset, apiUsers): + let _ = nextOffset + users = apiUsers + } + parsedPeers = AccumulatedPeers(transaction: transaction, chats: [], users: users) + updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: parsedPeers) + var peers: [EnginePeer] = [] + for user in users { + if let peer = transaction.getPeer(user.peerId) { + peers.append(EnginePeer(peer)) + } + } + if let entry = CodableEntry(CachedRecommendedChannels(peerIds: peers.map(\.id), count: Int32(peers.count), isHidden: false, timestamp: Int32(Date().timeIntervalSince1970))) { + transaction.putItemCacheEntry(id: appsEntryId(), entry: entry) + } + return peers + } + |> ignoreValues + } + } +} + public struct RecommendedChannels: Equatable { public struct Channel: Equatable { public var peer: EnginePeer @@ -167,6 +222,17 @@ func _internal_recommendedChannelPeerIds(account: Account, peerId: EnginePeer.Id } } +func _internal_recommendedAppPeerIds(account: Account) -> Signal<[EnginePeer.Id]?, NoError> { + let key = PostboxViewKey.cachedItem(appsEntryId()) + return account.postbox.combinedView(keys: [key]) + |> mapToSignal { views -> Signal<[EnginePeer.Id]?, NoError> in + guard let cachedChannels = (views.views[key] as? CachedItemView)?.value?.get(CachedRecommendedChannels.self), !cachedChannels.peerIds.isEmpty else { + return .single(nil) + } + return .single(cachedChannels.peerIds) + } +} + func _internal_recommendedChannels(account: Account, peerId: EnginePeer.Id?) -> Signal { let key = PostboxViewKey.cachedItem(entryId(peerId: peerId)) return account.postbox.combinedView(keys: [key]) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/RecentPeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/RecentPeers.swift index 28598bd218..ff6c0b438f 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/RecentPeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/RecentPeers.swift @@ -12,6 +12,10 @@ func cachedRecentPeersEntryId() -> ItemCacheEntryId { return ItemCacheEntryId(collectionId: 101, key: CachedRecentPeers.cacheKey()) } +func cachedRecentAppsEntryId() -> ItemCacheEntryId { + return ItemCacheEntryId(collectionId: 102, key: CachedRecentPeers.cacheKey()) +} + public func _internal_recentPeers(accountPeerId: EnginePeer.Id, postbox: Postbox) -> Signal { let key = PostboxViewKey.cachedItem(cachedRecentPeersEntryId()) return postbox.combinedView(keys: [key]) @@ -248,3 +252,57 @@ func _internal_removeRecentlyUsedInlineBot(account: Account, peerId: PeerId) -> } } |> switchToLatest } + +public func _internal_recentApps(accountPeerId: PeerId, postbox: Postbox) -> Signal<[EnginePeer.Id], NoError> { + let key = PostboxViewKey.cachedItem(cachedRecentAppsEntryId()) + return postbox.combinedView(keys: [key]) + |> mapToSignal { views -> Signal<[EnginePeer.Id], NoError> in + if let value = (views.views[key] as? CachedItemView)?.value?.get(CachedRecentPeers.self) { + return .single(value.ids) + } else { + return .single([]) + } + } +} + +public func _internal_managedUpdatedRecentApps(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal { + let key = PostboxViewKey.cachedItem(cachedRecentAppsEntryId()) + let peersEnabled = postbox.combinedView(keys: [key]) + |> map { views -> Bool in + if let value = (views.views[key] as? CachedItemView)?.value?.get(CachedRecentPeers.self) { + return value.enabled + } else { + return true + } + } + |> distinctUntilChanged + + let updateOnce = + network.request(Api.functions.contacts.getTopPeers(flags: 1 << 16, offset: 0, limit: 50, hash: 0)) + |> `catch` { _ -> Signal in + return .complete() + } + |> mapToSignal { result -> Signal in + return postbox.transaction { transaction -> Void in + switch result { + case let .topPeers(_, _, users): + let parsedPeers = AccumulatedPeers(users: users) + updatePeers(transaction: transaction, accountPeerId: accountPeerId, peers: parsedPeers) + + if let entry = CodableEntry(CachedRecentPeers(enabled: true, ids: users.map { $0.peerId })) { + transaction.putItemCacheEntry(id: cachedRecentAppsEntryId(), entry: entry) + } + case .topPeersNotModified: + break + case .topPeersDisabled: + if let entry = CodableEntry(CachedRecentPeers(enabled: false, ids: [])) { + transaction.putItemCacheEntry(id: cachedRecentAppsEntryId(), entry: entry) + } + } + } + } + + return peersEnabled |> mapToSignal { _ -> Signal in + return updateOnce + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index 6e32017ae9..cf5e915035 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -600,6 +600,14 @@ public extension TelegramEngine { public func managedUpdatedRecentPeers() -> Signal { return _internal_managedUpdatedRecentPeers(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network) } + + public func recentApps() -> Signal<[EnginePeer.Id], NoError> { + return _internal_recentApps(accountPeerId: self.account.peerId, postbox: self.account.postbox) + } + + public func managedUpdatedRecentApps() -> Signal { + return _internal_managedUpdatedRecentApps(accountPeerId: self.account.peerId, postbox: self.account.postbox, network: self.account.network) + } public func removeRecentPeer(peerId: PeerId) -> Signal { return _internal_removeRecentPeer(account: self.account, peerId: peerId) @@ -1423,10 +1431,18 @@ public extension TelegramEngine { return _internal_requestRecommendedChannels(account: self.account, peerId: peerId, forceUpdate: forceUpdate) } + public func recommendedAppPeerIds() -> Signal<[EnginePeer.Id]?, NoError> { + return _internal_recommendedAppPeerIds(account: self.account) + } + public func requestGlobalRecommendedChannelsIfNeeded() -> Signal { return _internal_requestRecommendedChannels(account: self.account, peerId: nil, forceUpdate: false) } + public func requestRecommendedAppsIfNeeded() -> Signal { + return _internal_requestRecommendedApps(account: self.account, forceUpdate: false) + } + public func isPremiumRequiredToContact(_ peerIds: [EnginePeer.Id]) -> Signal<[EnginePeer.Id], NoError> { return _internal_updateIsPremiumRequiredToContact(account: self.account, peerIds: peerIds) }