diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index e2ded194e5..d915891cbc 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -23,6 +23,8 @@ C251D7441E65E50500283EDE /* StickerSetInstallation.swift in Sources */ = {isa = PBXBuildFile; fileRef = C251D7421E65E50500283EDE /* StickerSetInstallation.swift */; }; C26A37EF1E5E0C41006977AC /* ChannelParticipants.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BB7C591E5C8074001527C3 /* ChannelParticipants.swift */; }; C2A315C01E2E776A00D89000 /* RequestStartBot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01749581E1092BC0057C89A /* RequestStartBot.swift */; }; + C2FD33E11E680E9E008D13D4 /* RequestUserPhotos.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2FD33E01E680E9E008D13D4 /* RequestUserPhotos.swift */; }; + C2FD33E21E680E9E008D13D4 /* RequestUserPhotos.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2FD33E01E680E9E008D13D4 /* RequestUserPhotos.swift */; }; D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CFF1D62255C00955575 /* ChannelState.swift */; }; D001F3E91E128A1C007A8C60 /* SecretChatState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0177B7A1DF8A16C00A5083A /* SecretChatState.swift */; }; D001F3EA1E128A1C007A8C60 /* TelegramPeerNotificationSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03121011DA57E93006A2A60 /* TelegramPeerNotificationSettings.swift */; }; @@ -439,6 +441,7 @@ C239BE961E62EE1E00C2C453 /* LoadMessagesIfNecessary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadMessagesIfNecessary.swift; sourceTree = ""; }; C239BE9B1E630CA700C2C453 /* UpdatePinnedMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatePinnedMessage.swift; sourceTree = ""; }; C251D7421E65E50500283EDE /* StickerSetInstallation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StickerSetInstallation.swift; sourceTree = ""; }; + C2FD33E01E680E9E008D13D4 /* RequestUserPhotos.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestUserPhotos.swift; sourceTree = ""; }; D003702A1DA42586004308D3 /* PhoneNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneNumber.swift; sourceTree = ""; }; D00C7CCB1E3620C30080C3D5 /* CachedChannelParticipants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CachedChannelParticipants.swift; sourceTree = ""; }; D00C7CCE1E3628180080C3D5 /* UpdateCachedChannelParticipants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateCachedChannelParticipants.swift; sourceTree = ""; }; @@ -1125,6 +1128,7 @@ C239BE9B1E630CA700C2C453 /* UpdatePinnedMessage.swift */, D0528E641E65C82400E2FEF5 /* UpdateContactName.swift */, C22EE61A1E67418000334C38 /* ToggleChannelSignatures.swift */, + C2FD33E01E680E9E008D13D4 /* RequestUserPhotos.swift */, ); name = Peers; sourceTree = ""; @@ -1467,6 +1471,7 @@ D03B0D721D631ABA00955575 /* SearchMessages.swift in Sources */, D0DC35501DE36900000195EB /* ChatContextResult.swift in Sources */, D00D97CA1E32917C00E5C2B6 /* PeerInputActivityManager.swift in Sources */, + C2FD33E11E680E9E008D13D4 /* RequestUserPhotos.swift in Sources */, D0177B7B1DF8A16C00A5083A /* SecretChatState.swift in Sources */, D0AAD1AA1E32638500D5B9DE /* ApplyMaxReadIndexInteractively.swift in Sources */, D03B0D5C1D631A6900955575 /* Download.swift in Sources */, @@ -1668,6 +1673,7 @@ D0613FCB1E60440600202CDB /* InvitationLinks.swift in Sources */, D0B844471DAB91FD005F29E1 /* ManagedServiceViews.swift in Sources */, D03C53691DAD5CA9004C17B3 /* PeerAccessRestrictionInfo.swift in Sources */, + C2FD33E21E680E9E008D13D4 /* RequestUserPhotos.swift in Sources */, D0B8440E1DAB91CD005F29E1 /* MessageUtils.swift in Sources */, D0FA8BAB1E1FB76E001E855B /* ManagedSecretChatOutgoingOperations.swift in Sources */, D0B418BA1D7E05BB004562A4 /* NetworkLogging.m in Sources */, diff --git a/TelegramCore/MessageUtils.swift b/TelegramCore/MessageUtils.swift index 93652414aa..a9541ced9e 100644 --- a/TelegramCore/MessageUtils.swift +++ b/TelegramCore/MessageUtils.swift @@ -72,3 +72,26 @@ func messagesIdsGroupedByPeerId(_ ids: Set) -> [PeerId: [MessageId]] return dict } + + +func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]) -> Message? { + guard case let .Id(id) = message.id else { + return nil + } + + var messagePeers = SimpleDictionary() + + var author: Peer? + if let authorId = message.authorId { + author = peers[authorId] + if let author = author { + messagePeers[author.id] = author + } + } + + if let peer = peers[id.peerId] { + messagePeers[peer.id] = peer + } + + return Message(stableId: 0, stableVersion: 0, id: id, globallyUniqueId: nil, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, forwardInfo: nil, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) +} diff --git a/TelegramCore/RequestUserPhotos.swift b/TelegramCore/RequestUserPhotos.swift new file mode 100644 index 0000000000..d3b5293502 --- /dev/null +++ b/TelegramCore/RequestUserPhotos.swift @@ -0,0 +1,139 @@ + +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac + import MtProtoKitMac +#else + import Postbox + import SwiftSignalKit + import MtProtoKitDynamic +#endif + + +public struct TelegramPeerPhoto { + public let image: TelegramMediaImage + public let index:Int + public let totalCount:Int +} + +public func requestPeerPhotos(account:Account, peerId:PeerId) -> Signal<[TelegramPeerPhoto], Void> { + return account.postbox.modify{ modifier -> Peer? in + return modifier.getPeer(peerId) + } |> mapToSignal { peer -> Signal<[TelegramPeerPhoto], Void> in + if let peer = peer as? TelegramUser, let inputUser = apiInputUser(peer) { + return account.network.request(Api.functions.photos.getUserPhotos(userId: inputUser, offset: 0, maxId: 0, limit: 100)) + |> map {Optional($0)} + |> mapError {_ in} + |> `catch` { + return Signal.single(nil) + } |> map { result -> [TelegramPeerPhoto] in + + if let result = result { + let totalCount:Int + let photos:[Api.Photo] + switch result { + case let .photos(data): + photos = data.photos + totalCount = photos.count + case let .photosSlice(data): + photos = data.photos + totalCount = Int(data.count) + } + + var images:[TelegramPeerPhoto] = [] + for i in 0 ..< photos.count { + let photo = photos[i] + let image:TelegramMediaImage + switch photo { + case let .photo(data): + image = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudImage, id: data.id), representations: telegramMediaImageRepresentationsFromApiSizes(data.sizes)) + case let .photoEmpty(id: id): + image = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudImage, id: id), representations: []) + } + images.append(TelegramPeerPhoto(image: image, index: i, totalCount: totalCount)) + } + + return images + } else { + return [] + } + } + + } else if let peer = peer, let inputPeer = apiInputPeer(peer) { + return account.network.request(Api.functions.messages.search(flags: 0, peer: inputPeer, q: "", filter: .inputMessagesFilterChatPhotos, minDate: 0, maxDate: 0, offset: 0, maxId: 0, limit: 1000)) |> map {Optional($0)} + |> mapError {_ in} + |> `catch` { + return Signal.single(nil) + } |> mapToSignal { result -> Signal<[TelegramPeerPhoto], Void> in + + if let result = result { + let messages: [Api.Message] + let chats: [Api.Chat] + let users: [Api.User] + switch result { + case let .channelMessages(_, _, _, apiMessages, apiChats, apiUsers): + messages = apiMessages + chats = apiChats + users = apiUsers + case let .messages(apiMessages, apiChats, apiUsers): + messages = apiMessages + chats = apiChats + users = apiUsers + case let.messagesSlice(_, apiMessages, apiChats, apiUsers): + messages = apiMessages + chats = apiChats + users = apiUsers + } + + return account.postbox.modify { modifier -> [Message] in + var peers: [PeerId: Peer] = [:] + + for user in users { + if let user = TelegramUser.merge(modifier.getPeer(user.peerId) as? TelegramUser, rhs: user) { + peers[user.id] = user + } + } + + for chat in chats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers[groupOrChannel.id] = groupOrChannel + } + } + + var renderedMessages: [Message] = [] + for message in messages { + if let message = StoreMessage(apiMessage: message), let renderedMessage = locallyRenderedMessage(message: message, peers: peers) { + renderedMessages.append(renderedMessage) + } + } + + return renderedMessages + } |> map { messages -> [TelegramPeerPhoto] in + var photos:[TelegramPeerPhoto] = [] + var index:Int = 0 + for message in messages { + if let media = message.media.first as? TelegramMediaAction { + switch media.action { + case let .photoUpdated(image): + if let image = image { + photos.append(TelegramPeerPhoto(image: image, index: index, totalCount: messages.count)) + } + default: + break + } + } + index += 1 + } + return photos + } + + } else { + return .single([]) + } + } + } else { + return .single([]) + } + } +} diff --git a/TelegramCore/SearchMessages.swift b/TelegramCore/SearchMessages.swift index 99ac57421e..f020960871 100644 --- a/TelegramCore/SearchMessages.swift +++ b/TelegramCore/SearchMessages.swift @@ -9,27 +9,6 @@ import Foundation import MtProtoKitDynamic #endif -private func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]) -> Message? { - guard case let .Id(id) = message.id else { - return nil - } - - var messagePeers = SimpleDictionary() - - var author: Peer? - if let authorId = message.authorId { - author = peers[authorId] - if let author = author { - messagePeers[author.id] = author - } - } - - if let peer = peers[id.peerId] { - messagePeers[peer.id] = peer - } - - return Message(stableId: 0, stableVersion: 0, id: id, globallyUniqueId: nil, timestamp: message.timestamp, flags: MessageFlags(message.flags), tags: message.tags, forwardInfo: nil, author: author, text: message.text, attributes: message.attributes, media: message.media, peers: messagePeers, associatedMessages: SimpleDictionary(), associatedMessageIds: []) -} public func searchMessages(account: Account, peerId: PeerId?, query: String, tagMask:MessageTags? = nil) -> Signal<[Message], NoError> { let searchResult: Signal