Swiftgram/TelegramCore/UpdatesApiUtils.swift
Peter 0b96d69daa Fixed unread counter category for private channels
Added support for "contact joined" service messages
Updated password recovery API
Updated Localization APIs
Added limited contact presence polling after getDifference
2018-11-11 17:46:21 +04:00

562 lines
21 KiB
Swift

import Foundation
#if os(macOS)
import PostboxMac
#else
import Postbox
#endif
private func collectPreCachedResources(for photo: Api.Photo) -> [(MediaResource, Data)]? {
switch photo {
case let .photo(_, _, _, _, _, sizes):
for size in sizes {
switch size {
case let .photoCachedSize(_, location, _, _, bytes):
switch location {
case let .fileLocation(dcId, volumeId, localId, secret, fileReference):
let data = bytes.makeData()
let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: data.count, fileReference: fileReference.makeData())
return [(resource, data)]
default:
break
}
default:
break
}
}
return nil
default:
return nil
}
}
private func collectPreCachedResources(for document: Api.Document) -> [(MediaResource, Data)]? {
switch document {
case let .document(content):
switch content.thumb {
case let .photoCachedSize(_, location, _, _, bytes):
switch location {
case let .fileLocation(dcId, volumeId, localId, secret, fileReference):
let data = bytes.makeData()
let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: data.count, fileReference: fileReference.makeData())
return [(resource, data)]
default:
break
}
default:
break
}
default:
break
}
return nil
}
extension Api.MessageMedia {
var preCachedResources: [(MediaResource, Data)]? {
switch self {
case let .messageMediaPhoto(_, photo, _):
if let photo = photo {
return collectPreCachedResources(for: photo)
} else {
return nil
}
case let .messageMediaDocument(_, document, _):
if let document = document {
return collectPreCachedResources(for: document)
}
return nil
case let .messageMediaWebPage(webPage):
var result: [(MediaResource, Data)]?
switch webPage {
case let .webPage(content):
if let photo = content.photo {
if let photoResult = collectPreCachedResources(for: photo) {
if result == nil {
result = []
}
result!.append(contentsOf: photoResult)
}
}
if let file = content.document {
if let fileResult = collectPreCachedResources(for: file) {
if result == nil {
result = []
}
result!.append(contentsOf: fileResult)
}
}
default:
break
}
return result
default:
return nil
}
}
}
extension Api.Message {
var rawId: Int32 {
switch self {
case let .message(_, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
return id
case let .messageEmpty(id):
return id
case let .messageService(_, id, _, _, _, _, _):
return id
}
}
var id: MessageId? {
switch self {
case let .message(flags, id, fromId, toId, _, _, _, _, _, _, _, _, _, _, _, _):
let peerId: PeerId
switch toId {
case let .peerUser(userId):
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: (flags & Int32(2)) != 0 ? userId : (fromId ?? userId))
case let .peerChat(chatId):
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
case let .peerChannel(channelId):
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
}
return MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id)
case .messageEmpty:
return nil
case let .messageService(flags, id, fromId, toId, _, _, _):
let peerId: PeerId
switch toId {
case let .peerUser(userId):
peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: (flags & Int32(2)) != 0 ? userId : (fromId ?? userId))
case let .peerChat(chatId):
peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
case let .peerChannel(channelId):
peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
}
return MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id)
}
}
var timestamp: Int32? {
switch self {
case let .message(_, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _):
return date
case let .messageService(_, _, _, _, _, date, _):
return date
case .messageEmpty:
return nil
}
}
var preCachedResources: [(MediaResource, Data)]? {
switch self {
case let .message(_, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _):
return media?.preCachedResources
default:
return nil
}
}
}
extension Api.Chat {
var peerId: PeerId {
switch self {
case let .chat(_, id, _, _, _, _, _, _):
return PeerId(namespace: Namespaces.Peer.CloudGroup, id: id)
case let .chatEmpty(id):
return PeerId(namespace: Namespaces.Peer.CloudGroup, id: id)
case let .chatForbidden(id, _):
return PeerId(namespace: Namespaces.Peer.CloudGroup, id: id)
case let .channel(_, id, _, _, _, _, _, _, _, _, _, _/*feed*//*, _*/):
return PeerId(namespace: Namespaces.Peer.CloudChannel, id: id)
case let .channelForbidden(_, id, _, _, _):
return PeerId(namespace: Namespaces.Peer.CloudChannel, id: id)
}
}
}
extension Api.User {
var peerId: PeerId {
switch self {
case .user(_, let id, _, _, _, _, _, _, _, _, _, _, _):
return PeerId(namespace: Namespaces.Peer.CloudUser, id: id)
case let .userEmpty(id):
return PeerId(namespace: Namespaces.Peer.CloudUser, id: id)
}
}
}
extension Api.Peer {
var peerId: PeerId {
switch self {
case let .peerChannel(channelId):
return PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)
case let .peerChat(chatId):
return PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)
case let .peerUser(userId):
return PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)
}
}
}
extension Api.Dialog {
var peerId: PeerId? {
switch self {
case let .dialog(_, peer, _, _, _, _, _, _, _, _):
return peer.peerId
/*feed*/
/*case .dialogFeed:
return nil*/
}
}
}
extension Api.Update {
var rawMessageId: Int32? {
switch self {
case let .updateMessageID(id, _):
return id
case let .updateNewMessage(message, _, _):
return message.rawId
case let .updateNewChannelMessage(message, _, _):
return message.rawId
default:
return nil
}
}
var updatedRawMessageId: (Int64, Int32)? {
switch self {
case let .updateMessageID(id, randomId):
return (randomId, id)
default:
return nil
}
}
var messageId: MessageId? {
switch self {
case let .updateNewMessage(message, _, _):
return message.id
case let .updateNewChannelMessage(message, _, _):
return message.id
default:
return nil
}
}
var message: Api.Message? {
switch self {
case let .updateNewMessage(message, _, _):
return message
case let .updateNewChannelMessage(message, _, _):
return message
case let .updateEditMessage(message, _, _):
return message
case let .updateEditChannelMessage(message, _, _):
return message
default:
return nil
}
}
var peerIds: [PeerId] {
switch self {
case let .updateChannel(channelId):
return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)]
case let .updateChannelTooLong(_, channelId, _):
return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)]
case let .updateChatAdmins(chatId, _, _):
return [PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)]
case let .updateChatParticipantAdd(chatId, userId, inviterId, _, _):
return [PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId), PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), PeerId(namespace: Namespaces.Peer.CloudUser, id: inviterId)]
case let .updateChatParticipantAdmin(chatId, userId, _, _):
return [PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId), PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)]
case let .updateChatParticipantDelete(chatId, userId, _):
return [PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId), PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)]
case let .updateChatParticipants(participants):
switch participants {
case let .chatParticipants(chatId, _, _):
return [PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)]
case let .chatParticipantsForbidden(_, chatId, _):
return [PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)]
}
case let .updateDeleteChannelMessages(channelId, _, _, _):
return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)]
case let .updateNewChannelMessage(message, _, _):
return apiMessagePeerIds(message)
case let .updateEditChannelMessage(message, _, _):
return apiMessagePeerIds(message)
case let .updateChannelWebPage(channelId, _, _, _):
return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)]
case let .updateNewMessage(message, _, _):
return apiMessagePeerIds(message)
case let .updateEditMessage(message, _, _):
return apiMessagePeerIds(message)
case let .updateReadChannelInbox(channelId, _):
return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)]
case let .updateUserName(userId, _, _, _):
return [PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)]
case let .updateUserPhone(userId, _):
return [PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)]
case let .updateUserPhoto(userId, _, _, _):
return [PeerId(namespace: Namespaces.Peer.CloudUser, id: userId)]
case let .updateServiceNotification(_, inboxDate, _, _, _, _):
if let _ = inboxDate {
return [PeerId(namespace: Namespaces.Peer.CloudUser, id: 777000)]
} else {
return []
}
case let .updateDraftMessage(peer: peer, draft: _):
return [peer.peerId]
default:
return []
}
}
var associatedMessageIds: [MessageId]? {
switch self {
case let .updateNewMessage(message, _, _):
return apiMessageAssociatedMessageIds(message)
case let .updateNewChannelMessage(message, _, _):
return apiMessageAssociatedMessageIds(message)
case let .updateEditChannelMessage(message, _, _):
return apiMessageAssociatedMessageIds(message)
default:
break
}
return nil
}
var channelPts: Int32? {
switch self {
case let .updateNewChannelMessage(_, pts, _):
return pts
case let .updateEditChannelMessage(_, pts, _):
return pts
default:
return nil
}
}
}
extension Api.Updates {
var rawMessageIds: [Int32] {
switch self {
case let .updates(updates, _, _, _, _):
var result: [Int32] = []
for update in updates {
if let id = update.rawMessageId {
result.append(id)
}
}
return result
case let .updatesCombined(updates, _, _, _, _, _):
var result: [Int32] = []
for update in updates {
if let id = update.rawMessageId {
result.append(id)
}
}
return result
case let .updateShort(update, _):
if let id = update.rawMessageId {
return [id]
} else {
return []
}
case let .updateShortSentMessage(_, id, _, _, _, _, _):
return [id]
case .updatesTooLong:
return []
case let .updateShortMessage(_, id, _, _, _, _, _, _, _, _, _):
return [id]
case let .updateShortChatMessage(_, id, _, _, _, _, _, _, _, _, _, _):
return [id]
}
}
var messageIds: [MessageId] {
switch self {
case let .updates(updates, _, _, _, _):
var result: [MessageId] = []
for update in updates {
if let id = update.messageId {
result.append(id)
}
}
return result
case let .updatesCombined(updates, _, _, _, _, _):
var result: [MessageId] = []
for update in updates {
if let id = update.messageId {
result.append(id)
}
}
return result
case let .updateShort(update, _):
if let id = update.messageId {
return [id]
} else {
return []
}
case .updateShortSentMessage:
return []
case .updatesTooLong:
return []
case let .updateShortMessage(_, id, userId, _, _, _, _, _, _, _, _):
return [MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), namespace: Namespaces.Message.Cloud, id: id)]
case let .updateShortChatMessage(_, id, _, chatId, _, _, _, _, _, _, _, _):
return [MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId), namespace: Namespaces.Message.Cloud, id: id)]
}
}
var updatedRawMessageIds: [Int64: Int32] {
switch self {
case let .updates(updates, _, _, _, _):
var result: [Int64: Int32] = [:]
for update in updates {
if let (randomId, id) = update.updatedRawMessageId {
result[randomId] = id
}
}
return result
case let .updatesCombined(updates, _, _, _, _, _):
var result: [Int64: Int32] = [:]
for update in updates {
if let (randomId, id) = update.updatedRawMessageId {
result[randomId] = id
}
}
return result
case let .updateShort(update, _):
if let (randomId, id) = update.updatedRawMessageId {
return [randomId: id]
} else {
return [:]
}
case .updateShortSentMessage:
return [:]
case .updatesTooLong:
return [:]
case let .updateShortMessage(_, id, userId, _, _, _, _, _, _, _, _):
return [:]
case let .updateShortChatMessage(_, id, _, chatId, _, _, _, _, _, _, _, _):
return [:]
}
}
}
extension Api.Updates {
var messages: [Api.Message] {
switch self {
case let .updates(updates, _, _, _, _):
var result: [Api.Message] = []
for update in updates {
if let message = update.message {
result.append(message)
}
}
return result
case let .updatesCombined(updates, _, _, _, _, _):
var result: [Api.Message] = []
for update in updates {
if let message = update.message {
result.append(message)
}
}
return result
case let .updateShort(update, _):
if let message = update.message {
return [message]
} else {
return []
}
default:
return []
}
}
var channelPts: Int32? {
switch self {
case let .updates(updates, _, _, _, _):
var result: Int32?
for update in updates {
if let channelPts = update.channelPts {
if result == nil || channelPts > result! {
result = channelPts
}
}
}
return result
case let .updatesCombined(updates, _, _, _, _, _):
var result: Int32?
for update in updates {
if let channelPts = update.channelPts {
if result == nil || channelPts > result! {
result = channelPts
}
}
}
return result
case let .updateShort(update, _):
if let message = update.channelPts {
return channelPts
} else {
return nil
}
default:
return nil
}
}
}
extension Api.Updates {
var chats: [Api.Chat] {
switch self {
case let .updates(_, _, chats, _, _):
var result: [Api.Chat] = []
for chat in chats {
result.append(chat)
}
return result
case let .updatesCombined(_, _, chats, _, _, _):
var result: [Api.Chat] = []
for chat in chats {
result.append(chat)
}
return result
default:
return []
}
}
}
extension Api.EncryptedChat {
var peerId: PeerId {
switch self {
case let .encryptedChat(id, _, _, _, _, _, _):
return PeerId(namespace: Namespaces.Peer.SecretChat, id: id)
case let .encryptedChatDiscarded(id):
return PeerId(namespace: Namespaces.Peer.SecretChat, id: id)
case let .encryptedChatEmpty(id):
return PeerId(namespace: Namespaces.Peer.SecretChat, id: id)
case let .encryptedChatRequested(id, _, _, _, _, _):
return PeerId(namespace: Namespaces.Peer.SecretChat, id: id)
case let .encryptedChatWaiting(id, _, _, _, _):
return PeerId(namespace: Namespaces.Peer.SecretChat, id: id)
}
}
}
extension Api.EncryptedMessage {
var peerId: PeerId {
switch self {
case let .encryptedMessage(_, chatId, _, _, _):
return PeerId(namespace: Namespaces.Peer.SecretChat, id: chatId)
case let .encryptedMessageService(_, chatId, _, _):
return PeerId(namespace: Namespaces.Peer.SecretChat, id: chatId)
}
}
}