diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index 64679c93bf..fb3cc499eb 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -380,6 +380,8 @@ D0AB0B941D662ECE002C78E7 /* ManagedMessageHistoryHoles.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AB0B931D662ECE002C78E7 /* ManagedMessageHistoryHoles.swift */; }; D0AB0B961D662F0B002C78E7 /* ManagedChatListHoles.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AB0B951D662F0B002C78E7 /* ManagedChatListHoles.swift */; }; D0AB0B9A1D666520002C78E7 /* ManagedSynchronizePeerReadStates.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AB0B991D666520002C78E7 /* ManagedSynchronizePeerReadStates.swift */; }; + D0AD02E31FFFA14800C1DCFF /* PeerLiveLocationsContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AD02E21FFFA14800C1DCFF /* PeerLiveLocationsContext.swift */; }; + D0AD02E41FFFA14800C1DCFF /* PeerLiveLocationsContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AD02E21FFFA14800C1DCFF /* PeerLiveLocationsContext.swift */; }; D0AF32221FAC95C20097362B /* StandaloneUploadedMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AF32211FAC95C20097362B /* StandaloneUploadedMedia.swift */; }; D0AF32231FAC95C20097362B /* StandaloneUploadedMedia.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AF32211FAC95C20097362B /* StandaloneUploadedMedia.swift */; }; D0AF32311FACEDEC0097362B /* CoreSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0AF32301FACEDEC0097362B /* CoreSettings.swift */; }; @@ -836,6 +838,7 @@ D0AB0B951D662F0B002C78E7 /* ManagedChatListHoles.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedChatListHoles.swift; sourceTree = ""; }; D0AB0B991D666520002C78E7 /* ManagedSynchronizePeerReadStates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizePeerReadStates.swift; sourceTree = ""; }; D0AC49491D7097A400AA55DA /* SSignalKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = SSignalKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D0AD02E21FFFA14800C1DCFF /* PeerLiveLocationsContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeerLiveLocationsContext.swift; sourceTree = ""; }; D0AF32211FAC95C20097362B /* StandaloneUploadedMedia.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StandaloneUploadedMedia.swift; sourceTree = ""; }; D0AF32301FACEDEC0097362B /* CoreSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreSettings.swift; sourceTree = ""; }; D0AF32341FAE8C6B0097362B /* MultipeerManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultipeerManager.swift; sourceTree = ""; }; @@ -1476,6 +1479,7 @@ D021E0E01DB5400200C6B04F /* Sticker Management */, D05A32DF1E6F096B002760B4 /* Settings */, D08CAA8A1ED81EA10000FDA8 /* Localization */, + D0AD02E61FFFA15C00C1DCFF /* Live Location */, D0AF32331FAE8C540097362B /* Multipeer */, D03B0E3A1D631E4400955575 /* Supporting Files */, D09D8C041D4FAB1D0081DBEC /* TelegramCore.h */, @@ -1493,6 +1497,14 @@ path = TelegramCoreTests; sourceTree = ""; }; + D0AD02E61FFFA15C00C1DCFF /* Live Location */ = { + isa = PBXGroup; + children = ( + D0AD02E21FFFA14800C1DCFF /* PeerLiveLocationsContext.swift */, + ); + name = "Live Location"; + sourceTree = ""; + }; D0AF32331FAE8C540097362B /* Multipeer */ = { isa = PBXGroup; children = ( @@ -1941,6 +1953,7 @@ D05452071E7B5093006EEF19 /* LoadedStickerPack.swift in Sources */, D01C7F041EFC1C49008305F1 /* DeviceContact.swift in Sources */, D0F7AB2F1DCF507E009AD9A1 /* ReplyMarkupMessageAttribute.swift in Sources */, + D0AD02E31FFFA14800C1DCFF /* PeerLiveLocationsContext.swift in Sources */, D0B843971DA7FBBC005F29E1 /* ChangePeerNotificationSettings.swift in Sources */, D0448CA21E291B14005A61A7 /* FetchSecretFileResource.swift in Sources */, D08CAA871ED81DD40000FDA8 /* LocalizationInfo.swift in Sources */, @@ -2277,6 +2290,7 @@ D0DFD5E01FCDBCFD0039B3B1 /* CachedSentMediaReferences.swift in Sources */, D0B418991D7E0580004562A4 /* TelegramMediaMap.swift in Sources */, D0561DEB1E5754FA00E6B9E9 /* ChannelAdmins.swift in Sources */, + D0AD02E41FFFA14800C1DCFF /* PeerLiveLocationsContext.swift in Sources */, D0613FCB1E60440600202CDB /* InvitationLinks.swift in Sources */, D0B844471DAB91FD005F29E1 /* ManagedServiceViews.swift in Sources */, D0F3A8A91E82CD7D00B4C64C /* UpdatePeerChatInterfaceState.swift in Sources */, diff --git a/TelegramCore/Account.swift b/TelegramCore/Account.swift index b4d043a5d9..7e8b954480 100644 --- a/TelegramCore/Account.swift +++ b/TelegramCore/Account.swift @@ -566,21 +566,11 @@ public class Account { } } - let appVersionString = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "") (\(Bundle.main.infoDictionary?["CFBundleVersion"] ?? ""))" - - #if os(macOS) - let pInfo = ProcessInfo.processInfo - let systemVersion = pInfo.operatingSystemVersionString - #else - let systemVersion = UIDevice.current.systemVersion - #endif - var appSandbox: Api.Bool = .boolFalse #if DEBUG appSandbox = .boolTrue #endif - - return network.request(Api.functions.account.registerDevice(tokenType: 1, token: tokenString, deviceModel: "iPhone", systemVersion: systemVersion, appVersion: appVersionString, appSandbox: appSandbox)) + return network.request(Api.functions.account.registerDevice(tokenType: 1, token: tokenString, appSandbox: appSandbox, otherUids: [])) |> retryRequest |> mapToSignal { _ -> Signal in return .complete() @@ -599,21 +589,12 @@ public class Account { } } - let appVersionString = "\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] ?? "") (\(Bundle.main.infoDictionary?["CFBundleVersion"] ?? ""))" - - #if os(macOS) - let pInfo = ProcessInfo.processInfo - let systemVersion = pInfo.operatingSystemVersionString - #else - let systemVersion = UIDevice.current.systemVersion - #endif - var appSandbox: Api.Bool = .boolFalse #if DEBUG appSandbox = .boolTrue #endif - return network.request(Api.functions.account.registerDevice(tokenType: 9, token: tokenString, deviceModel: "iPhone", systemVersion: systemVersion, appVersion: appVersionString, appSandbox: appSandbox)) + return network.request(Api.functions.account.registerDevice(tokenType: 9, token: tokenString, appSandbox: appSandbox, otherUids: [])) |> retryRequest |> mapToSignal { _ -> Signal in return .complete() diff --git a/TelegramCore/AccountIntermediateState.swift b/TelegramCore/AccountIntermediateState.swift index 213d818e73..cdcaa6b0d8 100644 --- a/TelegramCore/AccountIntermediateState.swift +++ b/TelegramCore/AccountIntermediateState.swift @@ -13,18 +13,18 @@ final class AccountInitialState { let state: AuthorizedAccountState.State let peerIds: Set let messageIds: Set - let channelStates: [PeerId: ChannelState] + let chatStates: [PeerId: PeerChatState] //let topCloudMessageIds: [PeerId: MessageId] let peerNotificationSettings: [PeerId: PeerNotificationSettings] let peerIdsWithNewMessages: Set let locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]] let cloudReadStates: [PeerId: PeerReadState] - init(state: AuthorizedAccountState.State, peerIds: Set, messageIds: Set, peerIdsWithNewMessages: Set, channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings], locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]], cloudReadStates: [PeerId: PeerReadState]) { + init(state: AuthorizedAccountState.State, peerIds: Set, messageIds: Set, peerIdsWithNewMessages: Set, chatStates: [PeerId: PeerChatState], peerNotificationSettings: [PeerId: PeerNotificationSettings], locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]], cloudReadStates: [PeerId: PeerReadState]) { self.state = state self.peerIds = peerIds self.messageIds = messageIds - self.channelStates = channelStates + self.chatStates = chatStates self.peerIdsWithNewMessages = peerIdsWithNewMessages self.peerNotificationSettings = peerNotificationSettings self.locallyGeneratedMessageTimestamps = locallyGeneratedMessageTimestamps @@ -98,7 +98,7 @@ struct AccountMutableState { var state: AuthorizedAccountState.State var peers: [PeerId: Peer] - var channelStates: [PeerId: ChannelState] + var chatStates: [PeerId: PeerChatState] var peerNotificationSettings: [PeerId: PeerNotificationSettings] var storedMessages: Set var readInboxMaxIds: [PeerId: MessageId] @@ -115,18 +115,18 @@ struct AccountMutableState { self.peers = initialPeers self.storedMessages = initialStoredMessages self.readInboxMaxIds = initialReadInboxMaxIds - self.channelStates = initialState.channelStates + self.chatStates = initialState.chatStates self.peerNotificationSettings = initialState.peerNotificationSettings self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp self.branchOperationIndex = 0 } - init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: ChannelState], peerNotificationSettings: [PeerId: PeerNotificationSettings], storedMessages: Set, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set], branchOperationIndex: Int) { + init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], chatStates: [PeerId: PeerChatState], peerNotificationSettings: [PeerId: PeerNotificationSettings], storedMessages: Set, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set], branchOperationIndex: Int) { self.initialState = initialState self.operations = operations self.state = state self.peers = peers - self.channelStates = channelStates + self.chatStates = chatStates self.storedMessages = storedMessages self.peerNotificationSettings = peerNotificationSettings self.readInboxMaxIds = readInboxMaxIds @@ -135,7 +135,7 @@ struct AccountMutableState { } func branch() -> AccountMutableState { - return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerNotificationSettings: self.peerNotificationSettings, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, branchOperationIndex: self.operations.count) + return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, chatStates: self.chatStates, peerNotificationSettings: self.peerNotificationSettings, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, branchOperationIndex: self.operations.count) } mutating func merge(_ other: AccountMutableState) { @@ -313,7 +313,7 @@ struct AccountMutableState { case let .UpdateState(state): self.state = state case let .UpdateChannelState(peerId, channelState): - self.channelStates[peerId] = channelState + self.chatStates[peerId] = channelState case let .UpdateNotificationSettings(subject, notificationSettings): if case let .peer(peerId) = subject { self.peerNotificationSettings[peerId] = notificationSettings diff --git a/TelegramCore/AccountStateManagementUtils.swift b/TelegramCore/AccountStateManagementUtils.swift index 12c6282b5a..27d2ee8f6b 100644 --- a/TelegramCore/AccountStateManagementUtils.swift +++ b/TelegramCore/AccountStateManagementUtils.swift @@ -258,7 +258,7 @@ private func locallyGeneratedMessageTimestampsFromDifference(_ difference: Api.u private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set, associatedMessageIds: Set, peerIdsWithNewMessages: Set, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState { var peers: [PeerId: Peer] = [:] - var channelStates: [PeerId: ChannelState] = [:] + var chatStates: [PeerId: PeerChatState] = [:] for peerId in peerIds { if let peer = modifier.getPeer(peerId) { @@ -267,7 +267,11 @@ private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set, if peerId.namespace == Namespaces.Peer.CloudChannel { if let channelState = modifier.getPeerChatState(peerId) as? ChannelState { - channelStates[peerId] = channelState + chatStates[peerId] = channelState + } + } else if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup { + if let chatState = modifier.getPeerChatState(peerId) as? RegularChatState { + chatStates[peerId] = chatState } } } @@ -312,7 +316,7 @@ private func initialStateWithPeerIds(_ modifier: Modifier, peerIds: Set, } } - return AccountMutableState(initialState: AccountInitialState(state: (modifier.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, messageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, channelStates: channelStates, peerNotificationSettings: peerNotificationSettings, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps, cloudReadStates: cloudReadStates), initialPeers: peers, initialStoredMessages: storedMessages, initialReadInboxMaxIds: readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp) + return AccountMutableState(initialState: AccountInitialState(state: (modifier.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, messageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, chatStates: chatStates, peerNotificationSettings: peerNotificationSettings, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps, cloudReadStates: cloudReadStates), initialPeers: peers, initialStoredMessages: storedMessages, initialReadInboxMaxIds: readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp) } func initialStateWithUpdateGroups(_ account: Account, groups: [UpdateGroup]) -> Signal { @@ -629,7 +633,7 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState, case let .updateChannelTooLong(_, channelId, channelPts): let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) if !channelsToPoll.contains(peerId) { - if let channelPts = channelPts, let channelState = state.channelStates[peerId], channelState.pts >= channelPts { + if let channelPts = channelPts, let channelState = state.chatStates[peerId] as? ChannelState, channelState.pts >= channelPts { Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) skip updateChannelTooLong by pts") } else { channelsToPoll.insert(peerId) @@ -637,7 +641,7 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState, } case let .updateDeleteChannelMessages(channelId, messages, pts: pts, ptsCount): let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) - if let previousState = updatedState.channelStates[peerId] { + if let previousState = updatedState.chatStates[peerId] as? ChannelState { if previousState.pts >= pts { Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) skip old delete update") } else if previousState.pts + ptsCount == pts { @@ -659,7 +663,7 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState, case let .updateEditChannelMessage(apiMessage, pts, ptsCount): if let message = StoreMessage(apiMessage: apiMessage), case let .Id(messageId) = message.id { let peerId = messageId.peerId - if let previousState = updatedState.channelStates[peerId] { + if let previousState = updatedState.chatStates[peerId] as? ChannelState { if previousState.pts >= pts { Logger.shared.log("State", "channel \(peerId) (\((updatedState.peers[peerId] as? TelegramChannel)?.title ?? "nil")) skip old edit update") } else if previousState.pts + ptsCount == pts { @@ -690,7 +694,7 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState, } case let .updateChannelWebPage(channelId, apiWebpage, pts, ptsCount): let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) - if let previousState = updatedState.channelStates[peerId] { + if let previousState = updatedState.chatStates[peerId] as? ChannelState { if previousState.pts >= pts { } else if previousState.pts + ptsCount == pts { switch apiWebpage { @@ -730,7 +734,7 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState, } case let .updateNewChannelMessage(apiMessage, pts, ptsCount): if let message = StoreMessage(apiMessage: apiMessage) { - if let previousState = updatedState.channelStates[message.id.peerId] { + if let previousState = updatedState.chatStates[message.id.peerId] as? ChannelState { if previousState.pts >= pts { Logger.shared.log("State", "channel \(message.id.peerId) (\((updatedState.peers[message.id.peerId] as? TelegramChannel)?.title ?? "nil")) skip old message \(message.id) (\(message.text))") } else if previousState.pts + ptsCount == pts { @@ -1274,16 +1278,16 @@ private func resolveMissingPeerCloudReadStates(account: Account, state: AccountM func keepPollingChannel(account: Account, peerId: PeerId, stateManager: AccountStateManager) -> Signal { return account.postbox.modify { modifier -> Signal in if let accountState = (modifier.getState() as? AuthorizedAccountState)?.state, let peer = modifier.getPeer(peerId) { - var channelStates: [PeerId: ChannelState] = [:] + var chatStates: [PeerId: PeerChatState] = [:] if let channelState = modifier.getPeerChatState(peerId) as? ChannelState { - channelStates[peerId] = channelState + chatStates[peerId] = channelState } let initialPeers: [PeerId: Peer] = [peerId: peer] var peerNotificationSettings: [PeerId: TelegramPeerNotificationSettings] = [:] if let notificationSettings = modifier.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings { peerNotificationSettings[peerId] = notificationSettings } - let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), messageIds: Set(), peerIdsWithNewMessages: Set(), channelStates: channelStates, peerNotificationSettings: peerNotificationSettings, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:]), initialPeers: initialPeers, initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:]) + let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), messageIds: Set(), peerIdsWithNewMessages: Set(), chatStates: chatStates, peerNotificationSettings: peerNotificationSettings, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:]), initialPeers: initialPeers, initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:]) return pollChannel(account, peer: peer, state: initialState) |> mapToSignal { (finalState, _, timeout) -> Signal in return resolveAssociatedMessages(account: account, state: finalState) @@ -1444,7 +1448,13 @@ private func pollChannel(_ account: Account, peer: Peer, state: AccountMutableSt #if (arch(i386) || arch(x86_64)) && os(iOS) limit = 3 #endif - return (account.network.request(Api.functions.updates.getChannelDifference(flags: 0, channel: inputChannel, filter: .channelMessagesFilterEmpty, pts: state.channelStates[peer.id]?.pts ?? 1, limit: limit)) + let pollPts: Int32 + if let channelState = state.chatStates[peer.id] as? ChannelState { + pollPts = channelState.pts + } else { + pollPts = 1 + } + return (account.network.request(Api.functions.updates.getChannelDifference(flags: 0, channel: inputChannel, filter: .channelMessagesFilterEmpty, pts: pollPts, limit: limit)) |> map { Optional($0) } |> `catch` { error -> Signal in if error.errorDescription == "CHANNEL_PRIVATE" { @@ -1462,7 +1472,7 @@ private func pollChannel(_ account: Account, peer: Peer, state: AccountMutableSt case let .channelDifference(_, pts, timeout, newMessages, otherUpdates, chats, users): apiTimeout = timeout let channelState: ChannelState - if let previousState = updatedState.channelStates[peer.id] { + if let previousState = updatedState.chatStates[peer.id] as? ChannelState { channelState = previousState.withUpdatedPts(pts) } else { channelState = ChannelState(pts: pts, invalidatedPts: nil) @@ -1543,7 +1553,7 @@ private func pollChannel(_ account: Account, peer: Peer, state: AccountMutableSt apiTimeout = timeout let channelState: ChannelState - if let previousState = updatedState.channelStates[peer.id] { + if let previousState = updatedState.chatStates[peer.id] as? ChannelState { channelState = previousState.withUpdatedPts(pts) } else { channelState = ChannelState(pts: pts, invalidatedPts: nil) @@ -1639,7 +1649,7 @@ private func verifyTransaction(_ modifier: Modifier, finalState: AccountMutableS for peerId in channelsWithUpdatedStates { let currentState = modifier.getPeerChatState(peerId) var previousStateMatches = false - let previousState = finalState.initialState.channelStates[peerId] + let previousState = finalState.initialState.chatStates[peerId] as? ChannelState if let currentState = currentState, let previousState = previousState { if currentState.equals(previousState) { previousStateMatches = true diff --git a/TelegramCore/AccountStateReset.swift b/TelegramCore/AccountStateReset.swift index 486a48f090..a4c6b3457c 100644 --- a/TelegramCore/AccountStateReset.swift +++ b/TelegramCore/AccountStateReset.swift @@ -118,7 +118,7 @@ func accountStateReset(postbox: Postbox, network: Network) -> Signal Any?] = { dict[410618194] = { return Api.InputDocument.parse_inputDocument($0) } dict[2131196633] = { return Api.contacts.ResolvedPeer.parse_resolvedPeer($0) } dict[-1771768449] = { return Api.InputMedia.parse_inputMediaEmpty($0) } - dict[-373312269] = { return Api.InputMedia.parse_inputMediaPhoto($0) } dict[-104578748] = { return Api.InputMedia.parse_inputMediaGeoPoint($0) } dict[-1494984313] = { return Api.InputMedia.parse_inputMediaContact($0) } dict[444068508] = { return Api.InputMedia.parse_inputMediaDocument($0) } @@ -295,13 +294,13 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { 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[-2114308294] = { return Api.InputMedia.parse_inputMediaPhoto($0) } dict[-186607933] = { return Api.InputMedia.parse_inputMediaInvoice($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) } dict[2072935910] = { return Api.InputPeer.parse_inputPeerUser($0) } dict[548253432] = { return Api.InputPeer.parse_inputPeerChannel($0) } - dict[888128301] = { return Api.InputPeer.parse_inputPeerFeed($0) } dict[568808380] = { return Api.upload.WebFile.parse_webFile($0) } dict[-116274796] = { return Api.Contact.parse_contact($0) } dict[-1679053127] = { return Api.BotInlineResult.parse_botInlineResult($0) } @@ -8458,7 +8457,6 @@ public struct Api { public enum InputMedia { case inputMediaEmpty - case inputMediaPhoto(id: Api.InputPhoto, caption: String) case inputMediaGeoPoint(geoPoint: Api.InputGeoPoint) case inputMediaContact(phoneNumber: String, firstName: String, lastName: String) case inputMediaDocument(id: Api.InputDocument, caption: String) @@ -8470,6 +8468,7 @@ public struct Api { 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) + case inputMediaPhoto(flags: Int32, id: Api.InputPhoto, caption: String, ttlSeconds: Int32?) case inputMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String, providerData: Api.DataJSON, startParam: String) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { @@ -8479,13 +8478,6 @@ public struct Api { buffer.appendInt32(-1771768449) } - break - case .inputMediaPhoto(let id, let caption): - if boxed { - buffer.appendInt32(-373312269) - } - id.serialize(buffer, true) - serializeString(caption, buffer: buffer, boxed: false) break case .inputMediaGeoPoint(let geoPoint): if boxed { @@ -8588,6 +8580,15 @@ public struct Api { serializeString(venueId, buffer: buffer, boxed: false) serializeString(venueType, buffer: buffer, boxed: false) break + case .inputMediaPhoto(let flags, let id, let caption, let ttlSeconds): + if boxed { + buffer.appendInt32(-2114308294) + } + serializeInt32(flags, buffer: buffer, boxed: false) + id.serialize(buffer, true) + serializeString(caption, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)} + break case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam): if boxed { buffer.appendInt32(-186607933) @@ -8608,22 +8609,6 @@ public struct Api { fileprivate static func parse_inputMediaEmpty(_ reader: BufferReader) -> InputMedia? { return Api.InputMedia.inputMediaEmpty } - fileprivate static func parse_inputMediaPhoto(_ reader: BufferReader) -> InputMedia? { - var _1: Api.InputPhoto? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputPhoto - } - var _2: String? - _2 = parseString(reader) - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.InputMedia.inputMediaPhoto(id: _1!, caption: _2!) - } - else { - return nil - } - } fileprivate static func parse_inputMediaGeoPoint(_ reader: BufferReader) -> InputMedia? { var _1: Api.InputGeoPoint? if let signature = reader.readInt32() { @@ -8836,6 +8821,28 @@ public struct Api { return nil } } + fileprivate static func parse_inputMediaPhoto(_ reader: BufferReader) -> InputMedia? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.InputPhoto? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.InputPhoto + } + var _3: String? + _3 = parseString(reader) + var _4: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.InputMedia.inputMediaPhoto(flags: _1!, id: _2!, caption: _3!, ttlSeconds: _4) + } + else { + return nil + } + } fileprivate static func parse_inputMediaInvoice(_ reader: BufferReader) -> InputMedia? { var _1: Int32? _1 = reader.readInt32() @@ -8886,7 +8893,6 @@ public struct Api { case inputPeerChat(chatId: Int32) case inputPeerUser(userId: Int32, accessHash: Int64) case inputPeerChannel(channelId: Int32, accessHash: Int64) - case inputPeerFeed(feedId: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -8922,12 +8928,6 @@ public struct Api { serializeInt32(channelId, buffer: buffer, boxed: false) serializeInt64(accessHash, buffer: buffer, boxed: false) break - case .inputPeerFeed(let feedId): - if boxed { - buffer.appendInt32(888128301) - } - serializeInt32(feedId, buffer: buffer, boxed: false) - break } } @@ -8976,17 +8976,6 @@ public struct Api { return nil } } - fileprivate static func parse_inputPeerFeed(_ reader: BufferReader) -> InputPeer? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.InputPeer.inputPeerFeed(feedId: _1!) - } - else { - return nil - } - } } @@ -20135,6 +20124,25 @@ public struct Api { }) } + public static func getDialogs(flags: Int32, feedId: Int32?, offsetDate: Int32, offsetId: Int32, offsetPeer: Api.InputPeer, limit: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.messages.Dialogs?) { + let buffer = Buffer() + buffer.appendInt32(96533218) + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 1) != 0 {serializeInt32(feedId!, buffer: buffer, boxed: false)} + serializeInt32(offsetDate, buffer: buffer, boxed: false) + serializeInt32(offsetId, buffer: buffer, boxed: false) + offsetPeer.serialize(buffer, true) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription({return "(messages.getDialogs flags: \(flags), feedId: \(String(describing: feedId)), offsetDate: \(offsetDate), offsetId: \(offsetId), offsetPeer: \(offsetPeer), limit: \(limit))"}), buffer, { (buffer: Buffer) -> Api.messages.Dialogs? in + let reader = BufferReader(buffer) + var result: Api.messages.Dialogs? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.Dialogs + } + return result + }) + } + public static func toggleDialogPin(flags: Int32, peer: Api.InputDialogPeer) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { let buffer = Buffer() buffer.appendInt32(-1489903017) @@ -20186,25 +20194,6 @@ public struct Api { return result }) } - - public static func getDialogs(flags: Int32, feedId: Int32?, offsetDate: Int32, offsetId: Int32, offsetPeer: Api.InputPeer, limit: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.messages.Dialogs?) { - let buffer = Buffer() - buffer.appendInt32(96533218) - serializeInt32(flags, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 1) != 0 {serializeInt32(feedId!, buffer: buffer, boxed: false)} - serializeInt32(offsetDate, buffer: buffer, boxed: false) - serializeInt32(offsetId, buffer: buffer, boxed: false) - offsetPeer.serialize(buffer, true) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription({return "(messages.getDialogs flags: \(flags), feedId: \(String(describing: feedId)), offsetDate: \(offsetDate), offsetId: \(offsetId), offsetPeer: \(offsetPeer), limit: \(limit))"}), buffer, { (buffer: Buffer) -> Api.messages.Dialogs? in - let reader = BufferReader(buffer) - var result: Api.messages.Dialogs? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.messages.Dialogs - } - return result - }) - } } public struct channels { public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { @@ -20539,21 +20528,6 @@ public struct Api { }) } - public static func exportMessageLink(channel: Api.InputChannel, id: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.ExportedMessageLink?) { - let buffer = Buffer() - buffer.appendInt32(-934882771) - channel.serialize(buffer, true) - serializeInt32(id, buffer: buffer, boxed: false) - return (FunctionDescription({return "(channels.exportMessageLink channel: \(channel), id: \(id))"}), buffer, { (buffer: Buffer) -> Api.ExportedMessageLink? in - let reader = BufferReader(buffer) - var result: Api.ExportedMessageLink? - if let signature = reader.readInt32() { - result = Api.parse(reader, signature: signature) as? Api.ExportedMessageLink - } - return result - }) - } - public static func toggleSignatures(channel: Api.InputChannel, enabled: Api.Bool) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Updates?) { let buffer = Buffer() buffer.appendInt32(527021574) @@ -20738,6 +20712,22 @@ public struct Api { }) } + public static func exportMessageLink(channel: Api.InputChannel, id: Int32, grouped: Api.Bool) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.ExportedMessageLink?) { + let buffer = Buffer() + buffer.appendInt32(-826838685) + channel.serialize(buffer, true) + serializeInt32(id, buffer: buffer, boxed: false) + grouped.serialize(buffer, true) + return (FunctionDescription({return "(channels.exportMessageLink channel: \(channel), id: \(id), grouped: \(grouped))"}), buffer, { (buffer: Buffer) -> Api.ExportedMessageLink? in + let reader = BufferReader(buffer) + var result: Api.ExportedMessageLink? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.ExportedMessageLink + } + return result + }) + } + public static func getFeed(flags: Int32, feedId: Int32, offsetPosition: Api.FeedPosition?, addOffset: Int32, limit: Int32, maxPosition: Api.FeedPosition?, minPosition: Api.FeedPosition?, sourcesHash: Int32, hash: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.messages.FeedMessages?) { let buffer = Buffer() buffer.appendInt32(403799538) @@ -20760,6 +20750,25 @@ public struct Api { }) } + public static func searchFeed(feedId: Int32, q: String, offsetDate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.messages.Messages?) { + let buffer = Buffer() + buffer.appendInt32(-2009967767) + serializeInt32(feedId, buffer: buffer, boxed: false) + serializeString(q, buffer: buffer, boxed: false) + serializeInt32(offsetDate, buffer: buffer, boxed: false) + offsetPeer.serialize(buffer, true) + serializeInt32(offsetId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription({return "(channels.searchFeed feedId: \(feedId), q: \(q), offsetDate: \(offsetDate), offsetPeer: \(offsetPeer), offsetId: \(offsetId), 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 static func getFeedSources(flags: Int32, feedId: Int32?, hash: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.channels.FeedSources?) { let buffer = Buffer() buffer.appendInt32(-657579154) @@ -20826,25 +20835,6 @@ public struct Api { return result }) } - - public static func searchFeed(feedId: Int32, q: String, offsetDate: Int32, offsetPeer: Api.InputPeer, offsetId: Int32, limit: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.messages.Messages?) { - let buffer = Buffer() - buffer.appendInt32(-2009967767) - serializeInt32(feedId, buffer: buffer, boxed: false) - serializeString(q, buffer: buffer, boxed: false) - serializeInt32(offsetDate, buffer: buffer, boxed: false) - offsetPeer.serialize(buffer, true) - serializeInt32(offsetId, buffer: buffer, boxed: false) - serializeInt32(limit, buffer: buffer, boxed: false) - return (FunctionDescription({return "(channels.searchFeed feedId: \(feedId), q: \(q), offsetDate: \(offsetDate), offsetPeer: \(offsetPeer), offsetId: \(offsetId), 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 payments { public static func getPaymentForm(msgId: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.payments.PaymentForm?) { @@ -21835,40 +21825,6 @@ public struct Api { } } public struct account { - public static func registerDevice(tokenType: Int32, token: String, deviceModel: String, systemVersion: String, appVersion: String, appSandbox: Api.Bool) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { - let buffer = Buffer() - buffer.appendInt32(-1568319572) - serializeInt32(tokenType, buffer: buffer, boxed: false) - serializeString(token, buffer: buffer, boxed: false) - serializeString(deviceModel, buffer: buffer, boxed: false) - serializeString(systemVersion, buffer: buffer, boxed: false) - serializeString(appVersion, buffer: buffer, boxed: false) - appSandbox.serialize(buffer, true) - return (FunctionDescription({return "(account.registerDevice tokenType: \(tokenType), token: \(token), deviceModel: \(deviceModel), systemVersion: \(systemVersion), appVersion: \(appVersion), appSandbox: \(appSandbox))"}), 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 unregisterDevice(tokenType: Int32, token: String) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { - let buffer = Buffer() - buffer.appendInt32(1707432768) - serializeInt32(tokenType, buffer: buffer, boxed: false) - serializeString(token, buffer: buffer, boxed: false) - return (FunctionDescription({return "(account.unregisterDevice tokenType: \(tokenType), token: \(token))"}), 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 updateNotifySettings(peer: Api.InputNotifyPeer, settings: Api.InputPeerNotifySettings) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { let buffer = Buffer() buffer.appendInt32(-2067899501) @@ -22237,6 +22193,47 @@ public struct Api { return result }) } + + public static func registerDevice(tokenType: Int32, token: String, appSandbox: Api.Bool, otherUids: [Int32]) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { + let buffer = Buffer() + buffer.appendInt32(1280460) + serializeInt32(tokenType, buffer: buffer, boxed: false) + serializeString(token, buffer: buffer, boxed: false) + appSandbox.serialize(buffer, true) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(otherUids.count)) + for item in otherUids { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription({return "(account.registerDevice tokenType: \(tokenType), token: \(token), appSandbox: \(appSandbox), otherUids: \(otherUids))"}), 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 unregisterDevice(tokenType: Int32, token: String, otherUids: [Int32]) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { + let buffer = Buffer() + buffer.appendInt32(813089983) + serializeInt32(tokenType, buffer: buffer, boxed: false) + serializeString(token, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(otherUids.count)) + for item in otherUids { + serializeInt32(item, buffer: buffer, boxed: false) + } + return (FunctionDescription({return "(account.unregisterDevice tokenType: \(tokenType), token: \(token), otherUids: \(otherUids))"}), 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 struct langpack { public static func getLangPack(langCode: String) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.LangPackDifference?) { diff --git a/TelegramCore/ExportMessageLink.swift b/TelegramCore/ExportMessageLink.swift index 066828718c..c6e27f41f2 100644 --- a/TelegramCore/ExportMessageLink.swift +++ b/TelegramCore/ExportMessageLink.swift @@ -13,7 +13,7 @@ public func exportMessageLink(account:Account, peerId:PeerId, messageId:MessageI return modifier.getPeer(peerId) } |> mapToSignal { peer -> Signal in if let peer = peer, let input = apiInputChannel(peer) { - return account.network.request(Api.functions.channels.exportMessageLink(channel: input, id: messageId.id)) |> mapError {_ in return } |> map { res in + return account.network.request(Api.functions.channels.exportMessageLink(channel: input, id: messageId.id, grouped: .boolTrue)) |> mapError {_ in return } |> map { res in switch res { case let .exportedMessageLink(link, _): return link diff --git a/TelegramCore/Namespaces.swift b/TelegramCore/Namespaces.swift index 2d97ea1c73..1211f7e8a1 100644 --- a/TelegramCore/Namespaces.swift +++ b/TelegramCore/Namespaces.swift @@ -81,8 +81,9 @@ public extension MessageTags { static let webPage = MessageTags(rawValue: 1 << 3) static let voiceOrInstantVideo = MessageTags(rawValue: 1 << 4) static let unseenPersonalMessage = MessageTags(rawValue: 1 << 5) + static let liveLocation = MessageTags(rawValue: 1 << 6) - static let all: MessageTags = [.photoOrVideo, .file, .music, .webPage, .voiceOrInstantVideo, .unseenPersonalMessage] + static let all: MessageTags = [.photoOrVideo, .file, .music, .webPage, .voiceOrInstantVideo, .unseenPersonalMessage, .liveLocation] } public extension GlobalMessageTags { diff --git a/TelegramCore/PeerLiveLocationsContext.swift b/TelegramCore/PeerLiveLocationsContext.swift new file mode 100644 index 0000000000..31972de9c1 --- /dev/null +++ b/TelegramCore/PeerLiveLocationsContext.swift @@ -0,0 +1,30 @@ +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac +#else + import Postbox + import SwiftSignalKit +#endif + +public func topPeerActiveLiveLocationMessages(account: Account, peerId: PeerId) -> Signal<[Message], NoError> { + return account.viewTracker.aroundMessageHistoryViewForLocation(.peer(peerId), index: .upperBound, anchorIndex: .upperBound, count: 100, fixedCombinedReadStates: nil, tagMask: .liveLocation, orderStatistics: []) + |> map { (view, _, _) -> [Message] in + let timestamp = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970) + var result: [Message] = [] + for entry in view.entries { + if case let .MessageEntry(message, _, _, _) = entry { + for media in message.media { + if let location = media as? TelegramMediaMap, let liveBroadcastingTimeout = location.liveBroadcastingTimeout { + if message.timestamp + liveBroadcastingTimeout > timestamp { + result.append(message) + } + } else { + assertionFailure() + } + } + } + } + return result + } +} diff --git a/TelegramCore/PendingMessageUploadedContent.swift b/TelegramCore/PendingMessageUploadedContent.swift index 009ce923ea..c467c907cc 100644 --- a/TelegramCore/PendingMessageUploadedContent.swift +++ b/TelegramCore/PendingMessageUploadedContent.swift @@ -64,7 +64,7 @@ func messageContentToUpload(network: Network, postbox: Postbox, auxiliaryMethods } else if let media = media.first { if let image = media as? TelegramMediaImage, let _ = largestImageRepresentation(image.representations) { if let reference = image.reference, case let .cloud(id, accessHash) = reference { - return .ready(.media(Api.InputMedia.inputMediaPhoto(id: Api.InputPhoto.inputPhoto(id: id, accessHash: accessHash), caption: text))) + return .ready(.media(Api.InputMedia.inputMediaPhoto(flags: 0, id: Api.InputPhoto.inputPhoto(id: id, accessHash: accessHash), caption: text, ttlSeconds: nil))) } else { return .upload(uploadedMediaImageContent(network: network, postbox: postbox, peerId: peerId, image: image, text: text, autoremoveAttribute: autoremoveAttribute)) } @@ -179,19 +179,20 @@ private func maybeCacheUploadedResource(postbox: Postbox, key: CachedSentMediaRe private func uploadedMediaImageContent(network: Network, postbox: Postbox, peerId: PeerId, image: TelegramMediaImage, text: String, autoremoveAttribute: AutoremoveTimeoutMessageAttribute?) -> Signal { if let largestRepresentation = largestImageRepresentation(image.representations) { - let predownloadedResource: Signal - if autoremoveAttribute == nil { - predownloadedResource = maybePredownloadedImageResource(postbox: postbox, resource: largestRepresentation.resource) - } else { - predownloadedResource = .single(.none) - } + let predownloadedResource: Signal = maybePredownloadedImageResource(postbox: postbox, resource: largestRepresentation.resource) return predownloadedResource |> mapToSignal { result -> Signal in var referenceKey: CachedSentMediaReferenceKey? switch result { case let .media(media): if let image = media as? TelegramMediaImage, let reference = image.reference, case let .cloud(id, accessHash) = reference { - return .single(.progress(1.0)) |> then(.single(.content(.media(.inputMediaPhoto(id: .inputPhoto(id: id, accessHash: accessHash), caption: text))))) + var flags: Int32 = 0 + var ttlSeconds: Int32? + if let autoremoveAttribute = autoremoveAttribute { + flags |= 1 << 1 + ttlSeconds = autoremoveAttribute.timeout + } + return .single(.progress(1.0)) |> then(.single(.content(.media(.inputMediaPhoto(flags: flags, id: .inputPhoto(id: id, accessHash: accessHash), caption: text, ttlSeconds: ttlSeconds))))) } case let .localReference(key): referenceKey = key @@ -227,7 +228,13 @@ private func uploadedMediaImageContent(network: Network, postbox: Postbox, peerI switch result { case let .messageMediaPhoto(_, photo, _, _): if let photo = photo, let mediaImage = telegramMediaImageFromApiPhoto(photo), let reference = mediaImage.reference, case let .cloud(id, accessHash) = reference { - return maybeCacheUploadedResource(postbox: postbox, key: referenceKey, result: .content(.media(.inputMediaPhoto(id: .inputPhoto(id: id, accessHash: accessHash), caption: text))), media: mediaImage) + var flags: Int32 = 0 + var ttlSeconds: Int32? + if let autoremoveAttribute = autoremoveAttribute { + flags |= 1 << 1 + ttlSeconds = autoremoveAttribute.timeout + } + return maybeCacheUploadedResource(postbox: postbox, key: referenceKey, result: .content(.media(.inputMediaPhoto(flags: flags, id: .inputPhoto(id: id, accessHash: accessHash), caption: text, ttlSeconds: ttlSeconds))), media: mediaImage) } default: break diff --git a/TelegramCore/SearchGroupMembers.swift b/TelegramCore/SearchGroupMembers.swift index 21ad2756a2..06bb145803 100644 --- a/TelegramCore/SearchGroupMembers.swift +++ b/TelegramCore/SearchGroupMembers.swift @@ -7,26 +7,38 @@ import Foundation import SwiftSignalKit #endif -public func searchGroupMembers(postbox: Postbox, network: Network, peerId: PeerId, query: String) -> Signal<[Peer], NoError> { - if peerId.namespace == Namespaces.Peer.CloudChannel && !query.isEmpty { - return channelMembers(postbox: postbox, network: network, peerId: peerId, filter: .search(query)) - |> map { participants -> [Peer] in - return participants.map { $0.peer } +private func searchLocalGroupMembers(postbox: Postbox, peerId: PeerId, query: String) -> Signal<[Peer], NoError> { + return peerParticipants(postbox: postbox, id: peerId) + |> map { peers -> [Peer] in + let normalizedQuery = query.lowercased() + + return peers.filter { peer in + if peer.indexName.matchesByTokens(normalizedQuery) { + return true } - } else { - return peerParticipants(postbox: postbox, id: peerId) - |> map { peers -> [Peer] in - let normalizedQuery = query.lowercased() - - return peers.filter { peer in - if peer.indexName.matchesByTokens(normalizedQuery) { - return true - } - if let addressName = peer.addressName, addressName.lowercased().hasPrefix(normalizedQuery) { - return true - } - return false - } + if let addressName = peer.addressName, addressName.lowercased().hasPrefix(normalizedQuery) { + return true } + return false + } + } +} + +public func searchGroupMembers(postbox: Postbox, network: Network, peerId: PeerId, query: String) -> Signal<[Peer], NoError> { + if peerId.namespace == Namespaces.Peer.CloudChannel && !query.isEmpty { + return searchLocalGroupMembers(postbox: postbox, peerId: peerId, query: query) + |> mapToSignal { local -> Signal<[Peer], NoError> in + return .single(local) + |> then(channelMembers(postbox: postbox, network: network, peerId: peerId, filter: .search(query)) + |> map { participants -> [Peer] in + var result: [Peer] = local + let existingIds = Set(local.map { $0.id }) + let filtered = participants.map({ $0.peer }).filter({ !existingIds.contains($0.id) }) + result.append(contentsOf: filtered) + return result + }) + } + } else { + return searchLocalGroupMembers(postbox: postbox, peerId: peerId, query: query) } } diff --git a/TelegramCore/Serialization.swift b/TelegramCore/Serialization.swift index 373690b932..ce0ac83adc 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 74 + return 75 } public func parseMessage(_ data: Data!) -> Any! { diff --git a/TelegramCore/StoreMessage_Telegram.swift b/TelegramCore/StoreMessage_Telegram.swift index 9661dd0e48..9d97b766f4 100644 --- a/TelegramCore/StoreMessage_Telegram.swift +++ b/TelegramCore/StoreMessage_Telegram.swift @@ -81,6 +81,8 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute], default: break } + } else if let location = attachment as? TelegramMediaMap, location.liveBroadcastingTimeout != nil { + tags.insert(.liveLocation) } } if let textEntities = textEntities, !textEntities.isEmpty && !tags.contains(.webPage) { @@ -492,6 +494,25 @@ extension StoreMessage { let attribute = TextEntitiesMessageAttribute(entities: messageTextEntitiesFromApiEntities(entities)) entitiesAttribute = attribute attributes.append(attribute) + } else { + var noEntities = false + loop: for media in medias { + switch media { + case _ as TelegramMediaImage, + _ as TelegramMediaFile, + _ as TelegramMediaContact, + _ as TelegramMediaMap: + noEntities = true + break loop + default: + break + } + } + if !noEntities { + let attribute = TextEntitiesMessageAttribute(entities: []) + entitiesAttribute = attribute + attributes.append(attribute) + } } var storeFlags = StoreMessageFlags() diff --git a/TelegramCore/TextEntitiesMessageAttribute.swift b/TelegramCore/TextEntitiesMessageAttribute.swift index 24b202c324..1d14dc8c5c 100644 --- a/TelegramCore/TextEntitiesMessageAttribute.swift +++ b/TelegramCore/TextEntitiesMessageAttribute.swift @@ -18,6 +18,7 @@ public enum MessageTextEntityType: Equatable { case Pre case TextUrl(url: String) case TextMention(peerId: PeerId) + case PhoneNumber public static func ==(lhs: MessageTextEntityType, rhs: MessageTextEntityType) -> Bool { switch lhs { @@ -93,6 +94,12 @@ public enum MessageTextEntityType: Equatable { } else { return false } + case .PhoneNumber: + if case .PhoneNumber = rhs { + return true + } else { + return false + } } } } @@ -132,6 +139,8 @@ public struct MessageTextEntity: PostboxCoding, Equatable { self.type = .TextUrl(url: decoder.decodeStringForKey("url", orElse: "")) case 11: self.type = .TextMention(peerId: PeerId(decoder.decodeInt64ForKey("peerId", orElse: 0))) + case 12: + self.type = .PhoneNumber default: self.type = .Unknown } @@ -167,6 +176,8 @@ public struct MessageTextEntity: PostboxCoding, Equatable { case let .TextMention(peerId): encoder.encodeInt32(11, forKey: "_rawValue") encoder.encodeInt64(peerId.toInt64(), forKey: "peerId") + case .PhoneNumber: + encoder.encodeInt32(12, forKey: "_rawValue") } } @@ -209,39 +220,41 @@ public class TextEntitiesMessageAttribute: MessageAttribute, Equatable { } -func apiTextAttributeEntities(_ attribute: TextEntitiesMessageAttribute, associatedPeers:SimpleDictionary) -> [Api.MessageEntity] { +func apiTextAttributeEntities(_ attribute: TextEntitiesMessageAttribute, associatedPeers: SimpleDictionary) -> [Api.MessageEntity] { var entities:[Api.MessageEntity] = [] for entity in attribute.entities { let offset:Int32 = Int32(entity.range.lowerBound) let length:Int32 = Int32(entity.range.upperBound - entity.range.lowerBound) switch entity.type { - case .Unknown: - break - case .Mention: - entities.append(.messageEntityMention(offset: offset, length: length)) - case .Hashtag: - entities.append(.messageEntityHashtag(offset: offset, length: length)) - case .BotCommand: - entities.append(.messageEntityBotCommand(offset: offset, length: length)) - case .Url: - entities.append(.messageEntityUrl(offset: offset, length: length)) - case .Email: - entities.append(.messageEntityEmail(offset: offset, length: length)) - case .Bold: - entities.append(.messageEntityBold(offset: offset, length: length)) - case .Italic: - entities.append(.messageEntityItalic(offset: offset, length: length)) - case .Code: - entities.append(.messageEntityCode(offset: offset, length: length)) - case .Pre: - entities.append(.messageEntityPre(offset: offset, length: length, language: "")) - case let .TextUrl(url): - entities.append(.messageEntityTextUrl(offset: offset, length: length, url: url)) - case let .TextMention(peerId): - if let peer = associatedPeers[peerId], let inputUser = apiInputUser(peer) { - entities.append(.inputMessageEntityMentionName(offset: offset, length: length, userId: inputUser)) - } + case .Unknown: + break + case .Mention: + entities.append(.messageEntityMention(offset: offset, length: length)) + case .Hashtag: + entities.append(.messageEntityHashtag(offset: offset, length: length)) + case .BotCommand: + entities.append(.messageEntityBotCommand(offset: offset, length: length)) + case .Url: + entities.append(.messageEntityUrl(offset: offset, length: length)) + case .Email: + entities.append(.messageEntityEmail(offset: offset, length: length)) + case .Bold: + entities.append(.messageEntityBold(offset: offset, length: length)) + case .Italic: + entities.append(.messageEntityItalic(offset: offset, length: length)) + case .Code: + entities.append(.messageEntityCode(offset: offset, length: length)) + case .Pre: + entities.append(.messageEntityPre(offset: offset, length: length, language: "")) + case let .TextUrl(url): + entities.append(.messageEntityTextUrl(offset: offset, length: length, url: url)) + case let .TextMention(peerId): + if let peer = associatedPeers[peerId], let inputUser = apiInputUser(peer) { + entities.append(.inputMessageEntityMentionName(offset: offset, length: length, userId: inputUser)) + } + case .PhoneNumber: + break } } return entities