mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-06 20:54:04 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/TelegramCore
This commit is contained in:
commit
d708bd4e2b
@ -222,8 +222,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[367766557] = { return Api.ChannelParticipant.parse_channelParticipant($0) }
|
||||
dict[-1557620115] = { return Api.ChannelParticipant.parse_channelParticipantSelf($0) }
|
||||
dict[-471670279] = { return Api.ChannelParticipant.parse_channelParticipantCreator($0) }
|
||||
dict[1674301556] = { return Api.ChannelParticipant.parse_channelParticipantAdmin($0) }
|
||||
dict[470789295] = { return Api.ChannelParticipant.parse_channelParticipantBanned($0) }
|
||||
dict[1571450403] = { return Api.ChannelParticipant.parse_channelParticipantAdmin($0) }
|
||||
dict[471043349] = { return Api.contacts.Blocked.parse_blocked($0) }
|
||||
dict[-1878523231] = { return Api.contacts.Blocked.parse_blockedSlice($0) }
|
||||
dict[-55902537] = { return Api.InputDialogPeer.parse_inputDialogPeer($0) }
|
||||
|
@ -5489,8 +5489,8 @@ extension Api {
|
||||
case channelParticipant(userId: Int32, date: Int32)
|
||||
case channelParticipantSelf(userId: Int32, inviterId: Int32, date: Int32)
|
||||
case channelParticipantCreator(userId: Int32)
|
||||
case channelParticipantAdmin(flags: Int32, userId: Int32, inviterId: Int32, promotedBy: Int32, date: Int32, adminRights: Api.ChatAdminRights)
|
||||
case channelParticipantBanned(flags: Int32, userId: Int32, kickedBy: Int32, date: Int32, bannedRights: Api.ChatBannedRights)
|
||||
case channelParticipantAdmin(flags: Int32, userId: Int32, inviterId: Int32?, promotedBy: Int32, date: Int32, adminRights: Api.ChatAdminRights)
|
||||
|
||||
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -5515,17 +5515,6 @@ extension Api {
|
||||
}
|
||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .channelParticipantAdmin(let flags, let userId, let inviterId, let promotedBy, let date, let adminRights):
|
||||
if boxed {
|
||||
buffer.appendInt32(1674301556)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||
serializeInt32(inviterId, buffer: buffer, boxed: false)
|
||||
serializeInt32(promotedBy, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
adminRights.serialize(buffer, true)
|
||||
break
|
||||
case .channelParticipantBanned(let flags, let userId, let kickedBy, let date, let bannedRights):
|
||||
if boxed {
|
||||
buffer.appendInt32(470789295)
|
||||
@ -5536,6 +5525,17 @@ extension Api {
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
bannedRights.serialize(buffer, true)
|
||||
break
|
||||
case .channelParticipantAdmin(let flags, let userId, let inviterId, let promotedBy, let date, let adminRights):
|
||||
if boxed {
|
||||
buffer.appendInt32(1571450403)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(inviterId!, buffer: buffer, boxed: false)}
|
||||
serializeInt32(promotedBy, buffer: buffer, boxed: false)
|
||||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
adminRights.serialize(buffer, true)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -5547,10 +5547,10 @@ extension Api {
|
||||
return ("channelParticipantSelf", [("userId", userId), ("inviterId", inviterId), ("date", date)])
|
||||
case .channelParticipantCreator(let userId):
|
||||
return ("channelParticipantCreator", [("userId", userId)])
|
||||
case .channelParticipantAdmin(let flags, let userId, let inviterId, let promotedBy, let date, let adminRights):
|
||||
return ("channelParticipantAdmin", [("flags", flags), ("userId", userId), ("inviterId", inviterId), ("promotedBy", promotedBy), ("date", date), ("adminRights", adminRights)])
|
||||
case .channelParticipantBanned(let flags, let userId, let kickedBy, let date, let bannedRights):
|
||||
return ("channelParticipantBanned", [("flags", flags), ("userId", userId), ("kickedBy", kickedBy), ("date", date), ("bannedRights", bannedRights)])
|
||||
case .channelParticipantAdmin(let flags, let userId, let inviterId, let promotedBy, let date, let adminRights):
|
||||
return ("channelParticipantAdmin", [("flags", flags), ("userId", userId), ("inviterId", inviterId), ("promotedBy", promotedBy), ("date", date), ("adminRights", adminRights)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -5596,34 +5596,6 @@ extension Api {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
static func parse_channelParticipantAdmin(_ reader: BufferReader) -> ChannelParticipant? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Api.ChatAdminRights?
|
||||
if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.ChannelParticipant.channelParticipantAdmin(flags: _1!, userId: _2!, inviterId: _3!, promotedBy: _4!, date: _5!, adminRights: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
static func parse_channelParticipantBanned(_ reader: BufferReader) -> ChannelParticipant? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
@ -5649,6 +5621,34 @@ extension Api {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
static func parse_channelParticipantAdmin(_ reader: BufferReader) -> ChannelParticipant? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
if Int(_1!) & Int(1 << 1) != 0 {_3 = reader.readInt32() }
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Api.ChatAdminRights?
|
||||
if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||
return Api.ChannelParticipant.channelParticipantAdmin(flags: _1!, userId: _2!, inviterId: _3, promotedBy: _4!, date: _5!, adminRights: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
enum InputDialogPeer: TypeConstructorDescription {
|
||||
|
@ -1547,20 +1547,6 @@ extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
static func exportChatInvite(chatId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ExportedChatInvite>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(2106086025)
|
||||
serializeInt32(chatId, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("chatId", chatId)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.ExportedChatInvite?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
static func checkChatInvite(hash: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ChatInvite>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1051570619)
|
||||
@ -2796,6 +2782,20 @@ extension Api {
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
static func exportChatInvite(peer: Api.InputPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ExportedChatInvite>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(234312524)
|
||||
peer.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("peer", peer)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.ExportedChatInvite?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
struct channels {
|
||||
static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
@ -3053,20 +3053,6 @@ extension Api {
|
||||
})
|
||||
}
|
||||
|
||||
static func exportInvite(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ExportedChatInvite>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-950663035)
|
||||
channel.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "channels.exportInvite", parameters: [("channel", channel)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.ExportedChatInvite?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
static func deleteChannel(channel: Api.InputChannel) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1072619549)
|
||||
|
@ -36,8 +36,8 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
|
||||
var role: TelegramGroupRole = .member
|
||||
if (flags & (1 << 0)) != 0 {
|
||||
role = .creator
|
||||
} else if adminRights != nil {
|
||||
//role = .admin
|
||||
} else if let adminRights = adminRights {
|
||||
role = .admin(TelegramChatAdminRights(apiAdminRights: adminRights))
|
||||
}
|
||||
if (flags & (1 << 5)) != 0 {
|
||||
groupFlags.insert(.deactivated)
|
||||
|
@ -504,7 +504,7 @@ final class TelegramCloudMediaResourceFetchInfo: MediaResourceFetchInfo {
|
||||
}
|
||||
}
|
||||
|
||||
public func fetchedMediaResource(postbox: Postbox, reference: MediaResourceReference, range: (Range<Int>, MediaBoxFetchPriority)? = nil, statsCategory: MediaResourceStatsCategory = .generic, reportResultStatus: Bool = false, preferBackgroundReferenceRevalidation: Bool = false, continueInBackground: Bool = false) -> Signal<FetchResourceSourceType, NoError> {
|
||||
public func fetchedMediaResource(postbox: Postbox, reference: MediaResourceReference, range: (Range<Int>, MediaBoxFetchPriority)? = nil, statsCategory: MediaResourceStatsCategory = .generic, reportResultStatus: Bool = false, preferBackgroundReferenceRevalidation: Bool = false, continueInBackground: Bool = false) -> Signal<FetchResourceSourceType, FetchResourceError> {
|
||||
if let (range, priority) = range {
|
||||
return postbox.mediaBox.fetchedResourceData(reference.resource, in: range, priority: priority, parameters: MediaResourceFetchParameters(tag: TelegramMediaResourceFetchTag(statsCategory: statsCategory), info: TelegramCloudMediaResourceFetchInfo(reference: reference, preferBackgroundReferenceRevalidation: preferBackgroundReferenceRevalidation, continueInBackground: continueInBackground)))
|
||||
|> map { _ in .local }
|
||||
|
@ -11,45 +11,45 @@ import Foundation
|
||||
|
||||
public func ensuredExistingPeerExportedInvitation(account: Account, peerId: PeerId, revokeExisted: Bool = false) -> Signal<Void, NoError> {
|
||||
return account.postbox.transaction { transaction -> Signal<Void, NoError> in
|
||||
if let peer = transaction.getPeer(peerId) {
|
||||
if let channel = peer as? TelegramChannel, let inputChannel = apiInputChannel(channel) {
|
||||
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
if let _ = peer as? TelegramChannel {
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, cachedData.exportedInvitation != nil && !revokeExisted {
|
||||
return .complete()
|
||||
} else {
|
||||
return account.network.request(Api.functions.channels.exportInvite(channel: inputChannel))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if let invitation = ExportedInvitation(apiExportedInvite: result) {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedChannelData {
|
||||
return current.withUpdatedExportedInvitation(invitation)
|
||||
} else {
|
||||
return CachedChannelData().withUpdatedExportedInvitation(invitation)
|
||||
}
|
||||
})
|
||||
}
|
||||
return account.network.request(Api.functions.messages.exportChatInvite(peer: inputPeer))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if let invitation = ExportedInvitation(apiExportedInvite: result) {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedChannelData {
|
||||
return current.withUpdatedExportedInvitation(invitation)
|
||||
} else {
|
||||
return CachedChannelData().withUpdatedExportedInvitation(invitation)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
} else if let _ = peer as? TelegramGroup {
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedGroupData, cachedData.exportedInvitation != nil && !revokeExisted {
|
||||
return .complete()
|
||||
} else {
|
||||
return account.network.request(Api.functions.messages.exportChatInvite(chatId: group.id.id))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if let invitation = ExportedInvitation(apiExportedInvite: result) {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedGroupData {
|
||||
return current.withUpdatedExportedInvitation(invitation)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
}
|
||||
return account.network.request(Api.functions.messages.exportChatInvite(peer: inputPeer))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
return account.postbox.transaction { transaction -> Void in
|
||||
if let invitation = ExportedInvitation(apiExportedInvite: result) {
|
||||
transaction.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in
|
||||
if let current = current as? CachedGroupData {
|
||||
return current.withUpdatedExportedInvitation(invitation)
|
||||
} else {
|
||||
return current
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -391,7 +391,7 @@ func multipartUpload(network: Network, postbox: Postbox, source: MultipartUpload
|
||||
|
||||
let dataSignal: Signal<MultipartUploadData, NoError>
|
||||
let headerSize: Int32
|
||||
let fetchedResource: Signal<Void, NoError>
|
||||
let fetchedResource: Signal<Void, FetchResourceError>
|
||||
switch source {
|
||||
case let .resource(resource):
|
||||
dataSignal = postbox.mediaBox.resourceData(resource.resource, option: .incremental(waitUntilFetchStatus: true)) |> map { MultipartUploadData.resourceData($0) }
|
||||
@ -454,7 +454,9 @@ func multipartUpload(network: Network, postbox: Postbox, source: MultipartUpload
|
||||
|
||||
manager.start()
|
||||
|
||||
let fetchedResourceDisposable = fetchedResource.start()
|
||||
let fetchedResourceDisposable = fetchedResource.start(error: { _ in
|
||||
subscriber.putError(.generic)
|
||||
})
|
||||
|
||||
return ActionDisposable {
|
||||
manager.cancel()
|
||||
|
@ -189,7 +189,9 @@ private func maybePredownloadedImageResource(postbox: Postbox, peerId: PeerId, r
|
||||
}
|
||||
}
|
||||
})
|
||||
let fetched = postbox.mediaBox.fetchedResource(resource, parameters: nil).start()
|
||||
let fetched = postbox.mediaBox.fetchedResource(resource, parameters: nil).start(error: { _ in
|
||||
subscriber.putError(.generic)
|
||||
})
|
||||
|
||||
return ActionDisposable {
|
||||
data.dispose()
|
||||
@ -609,7 +611,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
|
||||
|
||||
var thumbnailFile: Api.InputFile?
|
||||
if case let .file(file) = thumbnail {
|
||||
//thumbnailFile = file
|
||||
thumbnailFile = file
|
||||
}
|
||||
|
||||
if let _ = thumbnailFile {
|
||||
|
@ -15,18 +15,173 @@ public enum SearchMessagesLocation: Equatable {
|
||||
case peer(peerId: PeerId, fromId: PeerId?, tags: MessageTags?)
|
||||
}
|
||||
|
||||
public func searchMessages(account: Account, location: SearchMessagesLocation, query: String, lowerBound: MessageIndex? = nil, limit: Int32 = 100) -> Signal<([Message], [PeerId : CombinedPeerReadState], Int32), NoError> {
|
||||
let remoteSearchResult: Signal<Api.messages.Messages?, NoError>
|
||||
private struct SearchMessagesPeerState: Equatable {
|
||||
let messages: [Message]
|
||||
let readStates: [PeerId: CombinedPeerReadState]
|
||||
let totalCount: Int32
|
||||
let completed: Bool
|
||||
|
||||
static func ==(lhs: SearchMessagesPeerState, rhs: SearchMessagesPeerState) -> Bool {
|
||||
if lhs.totalCount != rhs.totalCount {
|
||||
return false
|
||||
}
|
||||
if lhs.completed != rhs.completed {
|
||||
return false
|
||||
}
|
||||
if lhs.messages.count != rhs.messages.count {
|
||||
return false
|
||||
}
|
||||
for i in 0 ..< lhs.messages.count {
|
||||
if lhs.messages[i].id != rhs.messages[i].id {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public struct SearchMessagesResult {
|
||||
public let messages: [Message]
|
||||
public let readStates: [PeerId: CombinedPeerReadState]
|
||||
public let totalCount: Int32
|
||||
public let completed: Bool
|
||||
}
|
||||
|
||||
public struct SearchMessagesState: Equatable {
|
||||
fileprivate let main: SearchMessagesPeerState
|
||||
fileprivate let additional: SearchMessagesPeerState?
|
||||
}
|
||||
|
||||
private func mergedState(transaction: Transaction, state: SearchMessagesPeerState?, result: Api.messages.Messages?) -> SearchMessagesPeerState? {
|
||||
guard let result = result else {
|
||||
return state
|
||||
}
|
||||
let messages: [Api.Message]
|
||||
let chats: [Api.Chat]
|
||||
let users: [Api.User]
|
||||
let totalCount: Int32
|
||||
switch result {
|
||||
case let .channelMessages(_, _, count, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
totalCount = count
|
||||
case let .messages(apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
totalCount = Int32(messages.count)
|
||||
case let .messagesSlice(_, count, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
totalCount = count
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
chats = []
|
||||
users = []
|
||||
totalCount = 0
|
||||
}
|
||||
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
|
||||
for user in users {
|
||||
if let user = TelegramUser.merge(transaction.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 peerIdsSet: Set<PeerId> = Set()
|
||||
var readStates: [PeerId: CombinedPeerReadState] = [:]
|
||||
|
||||
var renderedMessages: [Message] = []
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message), let renderedMessage = locallyRenderedMessage(message: message, peers: peers) {
|
||||
renderedMessages.append(renderedMessage)
|
||||
peerIdsSet.insert(message.id.peerId)
|
||||
}
|
||||
}
|
||||
|
||||
for peerId in peerIdsSet {
|
||||
if let readState = transaction.getCombinedPeerReadState(peerId) {
|
||||
readStates[peerId] = readState
|
||||
}
|
||||
}
|
||||
|
||||
renderedMessages.sort(by: { lhs, rhs in
|
||||
return MessageIndex(lhs) > MessageIndex(rhs)
|
||||
})
|
||||
|
||||
let completed = renderedMessages.isEmpty
|
||||
if let previous = state {
|
||||
var currentIds = Set<MessageId>()
|
||||
var mergedMessages: [Message] = []
|
||||
for message in previous.messages {
|
||||
if currentIds.contains(message.id) {
|
||||
continue
|
||||
}
|
||||
currentIds.insert(message.id)
|
||||
mergedMessages.append(message)
|
||||
}
|
||||
for message in renderedMessages {
|
||||
if currentIds.contains(message.id) {
|
||||
continue
|
||||
}
|
||||
currentIds.insert(message.id)
|
||||
mergedMessages.append(message)
|
||||
}
|
||||
mergedMessages.sort(by: { lhs, rhs in
|
||||
return MessageIndex(lhs) > MessageIndex(rhs)
|
||||
})
|
||||
return SearchMessagesPeerState(messages: mergedMessages, readStates: readStates, totalCount: completed ? Int32(mergedMessages.count) : totalCount, completed: completed)
|
||||
} else {
|
||||
return SearchMessagesPeerState(messages: renderedMessages, readStates: readStates, totalCount: completed ? Int32(renderedMessages.count) : totalCount, completed: completed)
|
||||
}
|
||||
}
|
||||
|
||||
private func mergedResult(_ state: SearchMessagesState) -> SearchMessagesResult {
|
||||
var messages: [Message] = state.main.messages
|
||||
if let additional = state.additional {
|
||||
if state.main.completed {
|
||||
messages.append(contentsOf: additional.messages)
|
||||
} else if let lastMessage = state.main.messages.last {
|
||||
let earliestIndex = MessageIndex(lastMessage)
|
||||
messages.append(contentsOf: additional.messages.filter({ MessageIndex($0) > earliestIndex }))
|
||||
}
|
||||
}
|
||||
messages.sort(by: { lhs, rhs in
|
||||
return MessageIndex(lhs) > MessageIndex(rhs)
|
||||
})
|
||||
|
||||
var readStates: [PeerId: CombinedPeerReadState] = [:]
|
||||
for message in messages {
|
||||
let readState = state.main.readStates[message.id.peerId] ?? state.additional?.readStates[message.id.peerId]
|
||||
if let readState = readState {
|
||||
readStates[message.id.peerId] = readState
|
||||
}
|
||||
}
|
||||
|
||||
return SearchMessagesResult(messages: messages, readStates: readStates, totalCount: state.main.totalCount + (state.additional?.totalCount ?? 0), completed: state.main.completed && (state.additional?.completed ?? true))
|
||||
}
|
||||
|
||||
public func searchMessages(account: Account, location: SearchMessagesLocation, query: String, state: SearchMessagesState?, limit: Int32 = 100) -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> {
|
||||
let remoteSearchResult: Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError>
|
||||
switch location {
|
||||
case let .peer(peerId, fromId, tags):
|
||||
if peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
return account.postbox.transaction { transaction -> ([Message], [PeerId : CombinedPeerReadState], Int32) in
|
||||
var readStates: [PeerId : CombinedPeerReadState] = [:]
|
||||
return account.postbox.transaction { transaction -> (SearchMessagesResult, SearchMessagesState) in
|
||||
var readStates: [PeerId: CombinedPeerReadState] = [:]
|
||||
if let readState = transaction.getCombinedPeerReadState(peerId) {
|
||||
readStates[peerId] = readState
|
||||
}
|
||||
let result = transaction.searchMessages(peerId: peerId, query: query, tags: tags)
|
||||
return (result, readStates, Int32(result.count))
|
||||
return (SearchMessagesResult(messages: result, readStates: readStates, totalCount: Int32(result.count), completed: true), SearchMessagesState(main: SearchMessagesPeerState(messages: [], readStates: [:], totalCount: 0, completed: true), additional: nil))
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,134 +200,114 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
|
||||
} else {
|
||||
filter = .inputMessagesFilterEmpty
|
||||
}
|
||||
|
||||
remoteSearchResult = account.postbox.transaction { transaction -> (peer: Peer?, from: Peer?) in
|
||||
if let fromId = fromId {
|
||||
return (peer: transaction.getPeer(peerId), from: transaction.getPeer(fromId))
|
||||
remoteSearchResult = account.postbox.transaction { transaction -> (peer: Peer, additionalPeer: Peer?, from: Peer?)? in
|
||||
guard let peer = transaction.getPeer(peerId) else {
|
||||
return nil
|
||||
}
|
||||
return (peer: transaction.getPeer(peerId), from: nil)
|
||||
var additionalPeer: Peer?
|
||||
if let _ = peer as? TelegramChannel, let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, let migrationReference = cachedData.migrationReference {
|
||||
additionalPeer = transaction.getPeer(migrationReference.maxMessageId.peerId)
|
||||
}
|
||||
if let fromId = fromId {
|
||||
return (peer: peer, additionalPeer: additionalPeer, from: transaction.getPeer(fromId))
|
||||
}
|
||||
return (peer: peer, additionalPeer: additionalPeer, from: nil)
|
||||
}
|
||||
|> mapToSignal { values -> Signal<Api.messages.Messages?, NoError> in
|
||||
if let peer = values.peer, let inputPeer = apiInputPeer(peer) {
|
||||
var fromInputUser: Api.InputUser? = nil
|
||||
var flags: Int32 = 0
|
||||
if let from = values.from {
|
||||
fromInputUser = apiInputUser(from)
|
||||
if let _ = fromInputUser {
|
||||
flags |= (1 << 0)
|
||||
}
|
||||
|> mapToSignal { values -> Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError> in
|
||||
guard let values = values else {
|
||||
return .single((nil, nil))
|
||||
}
|
||||
let peer = values.peer
|
||||
guard let inputPeer = apiInputPeer(peer) else {
|
||||
return .single((nil, nil))
|
||||
}
|
||||
var fromInputUser: Api.InputUser? = nil
|
||||
var flags: Int32 = 0
|
||||
if let from = values.from {
|
||||
fromInputUser = apiInputUser(from)
|
||||
if let _ = fromInputUser {
|
||||
flags |= (1 << 0)
|
||||
}
|
||||
return account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: query, fromId: fromInputUser, filter: filter, minDate: 0, maxDate: Int32.max - 1, offsetId: lowerBound?.id.id ?? 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
||||
}
|
||||
let peerMessages: Signal<Api.messages.Messages?, NoError>
|
||||
if let completed = state?.main.completed, completed {
|
||||
peerMessages = .single(nil)
|
||||
} else {
|
||||
let lowerBound = state?.main.messages.last.flatMap(MessageIndex.init)
|
||||
peerMessages = account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: query, fromId: fromInputUser, filter: filter, minDate: 0, maxDate: Int32.max - 1, offsetId: lowerBound?.id.id ?? 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
} else {
|
||||
return .never()
|
||||
}
|
||||
let additionalPeerMessages: Signal<Api.messages.Messages?, NoError>
|
||||
if let inputPeer = values.additionalPeer.flatMap(apiInputPeer) {
|
||||
let mainCompleted = state?.main.completed ?? false
|
||||
let hasAdditional = state?.additional != nil
|
||||
if let completed = state?.additional?.completed, completed {
|
||||
additionalPeerMessages = .single(nil)
|
||||
} else if mainCompleted || !hasAdditional {
|
||||
let lowerBound = state?.additional?.messages.last.flatMap(MessageIndex.init)
|
||||
additionalPeerMessages = account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: query, fromId: fromInputUser, filter: filter, minDate: 0, maxDate: Int32.max - 1, offsetId: lowerBound?.id.id ?? 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
} else {
|
||||
additionalPeerMessages = .single(nil)
|
||||
}
|
||||
} else {
|
||||
additionalPeerMessages = .single(nil)
|
||||
}
|
||||
return combineLatest(peerMessages, additionalPeerMessages)
|
||||
}
|
||||
case let .group(groupId):
|
||||
/*feed*/
|
||||
remoteSearchResult = .single(nil)
|
||||
remoteSearchResult = .single((nil, nil))
|
||||
/*remoteSearchResult = account.network.request(Api.functions.channels.searchFeed(feedId: groupId.rawValue, q: query, offsetDate: 0, offsetPeer: Api.InputPeer.inputPeerEmpty, offsetId: 0, limit: 64), automaticFloodWait: false)
|
||||
|> mapError { _ in } |> map(Optional.init)*/
|
||||
case .general:
|
||||
remoteSearchResult = account.postbox.transaction { transaction -> Api.InputPeer in
|
||||
remoteSearchResult = account.postbox.transaction { transaction -> (MessageIndex?, Api.InputPeer) in
|
||||
var lowerBound: MessageIndex?
|
||||
if let state = state, let message = state.main.messages.last {
|
||||
lowerBound = MessageIndex(message)
|
||||
}
|
||||
if let lowerBound = lowerBound, let peer = transaction.getPeer(lowerBound.id.peerId), let inputPeer = apiInputPeer(peer) {
|
||||
return inputPeer
|
||||
return (lowerBound, inputPeer)
|
||||
} else {
|
||||
return .inputPeerEmpty
|
||||
return (lowerBound, .inputPeerEmpty)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { inputPeer in
|
||||
|> mapToSignal { (lowerBound, inputPeer) in
|
||||
account.network.request(Api.functions.messages.searchGlobal(q: query, offsetDate: lowerBound?.timestamp ?? 0, offsetPeer: inputPeer, offsetId: lowerBound?.id.id ?? 0, limit: limit), automaticFloodWait: false)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
|
||||
return .single(nil)
|
||||
|> map { result -> (Api.messages.Messages?, Api.messages.Messages?) in
|
||||
return (result, nil)
|
||||
}
|
||||
|> `catch` { _ -> Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError> in
|
||||
return .single((nil, nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let processedSearchResult = remoteSearchResult
|
||||
|> mapToSignal { result -> Signal<([Message], [PeerId: CombinedPeerReadState], Int32), NoError> in
|
||||
guard let result = result else {
|
||||
return .single(([], [:], 0))
|
||||
}
|
||||
|
||||
//assert(false)
|
||||
let messages: [Api.Message]
|
||||
let chats: [Api.Chat]
|
||||
let users: [Api.User]
|
||||
let totalCount: Int32
|
||||
switch result {
|
||||
case let .channelMessages(_, _, count, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
totalCount = count
|
||||
case let .messages(apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
totalCount = Int32(messages.count)
|
||||
case let .messagesSlice(_, count, apiMessages, apiChats, apiUsers):
|
||||
messages = apiMessages
|
||||
chats = apiChats
|
||||
users = apiUsers
|
||||
totalCount = count
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
chats = []
|
||||
users = []
|
||||
totalCount = 0
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> ([Message], [PeerId : CombinedPeerReadState], Int32) in
|
||||
var peers: [PeerId: Peer] = [:]
|
||||
|
||||
for user in users {
|
||||
if let user = TelegramUser.merge(transaction.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 peerIdsSet: Set<PeerId> = Set()
|
||||
var readStates:[PeerId : CombinedPeerReadState] = [:]
|
||||
|
||||
var renderedMessages: [Message] = []
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message), let renderedMessage = locallyRenderedMessage(message: message, peers: peers) {
|
||||
renderedMessages.append(renderedMessage)
|
||||
peerIdsSet.insert(message.id.peerId)
|
||||
}
|
||||
}
|
||||
|
||||
for peerId in peerIdsSet {
|
||||
if let readState = transaction.getCombinedPeerReadState(peerId) {
|
||||
readStates[peerId] = readState
|
||||
}
|
||||
}
|
||||
|
||||
if case .general = location {
|
||||
return remoteSearchResult
|
||||
|> mapToSignal { result, additionalResult -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> in
|
||||
return account.postbox.transaction { transaction -> (SearchMessagesResult, SearchMessagesState) in
|
||||
var additional: SearchMessagesPeerState? = mergedState(transaction: transaction, state: state?.additional, result: additionalResult)
|
||||
if state?.additional == nil, case .general = location {
|
||||
let secretMessages = transaction.searchMessages(peerId: nil, query: query, tags: nil)
|
||||
renderedMessages.append(contentsOf: secretMessages)
|
||||
var readStates: [PeerId: CombinedPeerReadState] = [:]
|
||||
for message in secretMessages {
|
||||
if let readState = transaction.getCombinedPeerReadState(message.id.peerId) {
|
||||
readStates[message.id.peerId] = readState
|
||||
}
|
||||
}
|
||||
additional = SearchMessagesPeerState(messages: secretMessages, readStates: readStates, totalCount: Int32(secretMessages.count), completed: true)
|
||||
}
|
||||
|
||||
renderedMessages.sort(by: { lhs, rhs in
|
||||
return MessageIndex(lhs) > MessageIndex(rhs)
|
||||
})
|
||||
|
||||
return (renderedMessages, readStates, totalCount)
|
||||
let updatedState = SearchMessagesState(main: mergedState(transaction: transaction, state: state?.main, result: result) ?? SearchMessagesPeerState(messages: [], readStates: [:], totalCount: 0, completed: true), additional: additional)
|
||||
return (mergedResult(updatedState), updatedState)
|
||||
}
|
||||
}
|
||||
|
||||
return processedSearchResult
|
||||
}
|
||||
|
||||
public func downloadMessage(postbox: Postbox, network: Network, messageId: MessageId) -> Signal<Message?, NoError> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user