Update API

This commit is contained in:
Ilya Laktyushin 2026-02-05 17:27:47 +04:00
parent 5ebc55af73
commit e17c7d9859
11 changed files with 426 additions and 237 deletions

View file

@ -649,6 +649,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[681706865] = { return Api.MessageEntity.parse_messageEntityCode($0) }
dict[-925956616] = { return Api.MessageEntity.parse_messageEntityCustomEmoji($0) }
dict[1692693954] = { return Api.MessageEntity.parse_messageEntityEmail($0) }
dict[-1874147385] = { return Api.MessageEntity.parse_messageEntityFormattedDate($0) }
dict[1868782349] = { return Api.MessageEntity.parse_messageEntityHashtag($0) }
dict[-2106619040] = { return Api.MessageEntity.parse_messageEntityItalic($0) }
dict[-100378723] = { return Api.MessageEntity.parse_messageEntityMention($0) }

View file

@ -78,6 +78,18 @@ public extension Api {
self.length = length
}
}
public class Cons_messageEntityFormattedDate {
public var flags: Int32
public var offset: Int32
public var length: Int32
public var date: Int32
public init(flags: Int32, offset: Int32, length: Int32, date: Int32) {
self.flags = flags
self.offset = offset
self.length = length
self.date = date
}
}
public class Cons_messageEntityHashtag {
public var offset: Int32
public var length: Int32
@ -189,6 +201,7 @@ public extension Api {
case messageEntityCode(Cons_messageEntityCode)
case messageEntityCustomEmoji(Cons_messageEntityCustomEmoji)
case messageEntityEmail(Cons_messageEntityEmail)
case messageEntityFormattedDate(Cons_messageEntityFormattedDate)
case messageEntityHashtag(Cons_messageEntityHashtag)
case messageEntityItalic(Cons_messageEntityItalic)
case messageEntityMention(Cons_messageEntityMention)
@ -270,6 +283,15 @@ public extension Api {
serializeInt32(_data.offset, buffer: buffer, boxed: false)
serializeInt32(_data.length, buffer: buffer, boxed: false)
break
case .messageEntityFormattedDate(let _data):
if boxed {
buffer.appendInt32(-1874147385)
}
serializeInt32(_data.flags, buffer: buffer, boxed: false)
serializeInt32(_data.offset, buffer: buffer, boxed: false)
serializeInt32(_data.length, buffer: buffer, boxed: false)
serializeInt32(_data.date, buffer: buffer, boxed: false)
break
case .messageEntityHashtag(let _data):
if boxed {
buffer.appendInt32(1868782349)
@ -380,6 +402,8 @@ public extension Api {
return ("messageEntityCustomEmoji", [("offset", _data.offset as Any), ("length", _data.length as Any), ("documentId", _data.documentId as Any)])
case .messageEntityEmail(let _data):
return ("messageEntityEmail", [("offset", _data.offset as Any), ("length", _data.length as Any)])
case .messageEntityFormattedDate(let _data):
return ("messageEntityFormattedDate", [("flags", _data.flags as Any), ("offset", _data.offset as Any), ("length", _data.length as Any), ("date", _data.date as Any)])
case .messageEntityHashtag(let _data):
return ("messageEntityHashtag", [("offset", _data.offset as Any), ("length", _data.length as Any)])
case .messageEntityItalic(let _data):
@ -544,6 +568,26 @@ public extension Api {
return nil
}
}
public static func parse_messageEntityFormattedDate(_ reader: BufferReader) -> MessageEntity? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.MessageEntity.messageEntityFormattedDate(Cons_messageEntityFormattedDate(flags: _1!, offset: _2!, length: _3!, date: _4!))
}
else {
return nil
}
}
public static func parse_messageEntityHashtag(_ reader: BufferReader) -> MessageEntity? {
var _1: Int32?
_1 = reader.readInt32()

View file

@ -398,7 +398,7 @@ func textMediaAndExpirationTimerFromApiMedia(_ media: Api.MessageMedia?, _ peerI
case let .messageMediaDocument(messageMediaDocumentData):
let (flags, document, altDocuments, coverPhoto, videoTimestamp, ttlSeconds) = (messageMediaDocumentData.flags, messageMediaDocumentData.document, messageMediaDocumentData.altDocuments, messageMediaDocumentData.videoCover, messageMediaDocumentData.videoTimestamp, messageMediaDocumentData.ttlSeconds)
if let document = document {
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments, videoCover: coverPhoto) {
if let mediaFile = telegramMediaFileFromApiDocument(document, altDocuments: altDocuments, videoCover: coverPhoto, isLivePhoto: (flags & (1 << 11)) != 0) {
return (mediaFile, ttlSeconds, (flags & (1 << 3)) != 0, (flags & (1 << 4)) != 0, nil, videoTimestamp)
}
} else {
@ -785,6 +785,31 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes
case let .messageEntityCustomEmoji(messageEntityCustomEmojiData):
let (offset, length, documentId) = (messageEntityCustomEmojiData.offset, messageEntityCustomEmojiData.length, messageEntityCustomEmojiData.documentId)
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .CustomEmoji(stickerPack: nil, fileId: documentId)))
case let .messageEntityFormattedDate(messageEntityFormattedDateData):
let (flags, offset, length, date) = (messageEntityFormattedDateData.flags, messageEntityFormattedDateData.offset, messageEntityFormattedDateData.length, messageEntityFormattedDateData.date)
let format: MessageTextEntityType.DateTimeFormat
if (flags & (1 << 0)) != 0 {
format = .relative
} else {
let timeFormat: MessageTextEntityType.DateTimeFormat.TimeFormat
if (flags & (1 << 1)) != 0 {
timeFormat = .short
} else if (flags & (1 << 2)) != 0 {
timeFormat = .long
} else {
timeFormat = .short
}
let dateFormat: MessageTextEntityType.DateTimeFormat.DateFormat
if (flags & (1 << 3)) != 0 {
dateFormat = .short
} else if (flags & (1 << 4)) != 0 {
dateFormat = .long
} else {
dateFormat = .short
}
format = .full(timeFormat: timeFormat, dateFormat: dateFormat)
}
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .FormattedDate(format: format, date: date)))
}
}
return result

View file

@ -108,7 +108,7 @@ extension StickerMaskCoords {
}
}
func telegramMediaFileAttributesFromApiAttributes(_ attributes: [Api.DocumentAttribute]) -> [TelegramMediaFileAttribute] {
func telegramMediaFileAttributesFromApiAttributes(_ attributes: [Api.DocumentAttribute], isLivePhoto: Bool = false) -> [TelegramMediaFileAttribute] {
var result: [TelegramMediaFileAttribute] = []
for attribute in attributes {
switch attribute {
@ -137,6 +137,9 @@ func telegramMediaFileAttributesFromApiAttributes(_ attributes: [Api.DocumentAtt
if (flags & (1 << 3)) != 0 {
videoFlags.insert(.isSilent)
}
if isLivePhoto {
videoFlags.insert(.isLivePhoto)
}
result.append(.Video(duration: Double(duration), size: PixelDimensions(width: w, height: h), flags: videoFlags, preloadSize: preloadSize, coverTime: videoStart, videoCodec: videoCodec))
case let .documentAttributeAudio(documentAttributeAudioData):
let (flags, duration, title, performer, waveform) = (documentAttributeAudioData.flags, documentAttributeAudioData.duration, documentAttributeAudioData.title, documentAttributeAudioData.performer, documentAttributeAudioData.waveform)
@ -192,11 +195,11 @@ func telegramMediaFileThumbnailRepresentationsFromApiSizes(datacenterId: Int32,
return (immediateThumbnailData, representations)
}
func telegramMediaFileFromApiDocument(_ document: Api.Document, altDocuments: [Api.Document]?, videoCover: Api.Photo? = nil) -> TelegramMediaFile? {
func telegramMediaFileFromApiDocument(_ document: Api.Document, altDocuments: [Api.Document]?, videoCover: Api.Photo? = nil, isLivePhoto: Bool = false) -> TelegramMediaFile? {
switch document {
case let .document(documentData):
let (id, accessHash, fileReference, mimeType, size, thumbs, videoThumbs, dcId, attributes) = (documentData.id, documentData.accessHash, documentData.fileReference, documentData.mimeType, documentData.size, documentData.thumbs, documentData.videoThumbs, documentData.dcId, documentData.attributes)
var parsedAttributes = telegramMediaFileAttributesFromApiAttributes(attributes)
var parsedAttributes = telegramMediaFileAttributesFromApiAttributes(attributes, isLivePhoto: isLivePhoto)
var isSticker = false
var isAnimated = false
for attribute in parsedAttributes {
@ -238,7 +241,7 @@ func telegramMediaFileFromApiDocument(_ document: Api.Document, altDocuments: [A
alternativeRepresentations = altDocuments.compactMap { telegramMediaFileFromApiDocument($0, altDocuments: []) }
}
return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: size, fileReference: fileReference.makeData(), fileName: fileNameFromFileAttributes(parsedAttributes)), previewRepresentations: previewRepresentations, videoThumbnails: videoThumbnails, videoCover: videoCover.flatMap(telegramMediaImageFromApiPhoto), immediateThumbnailData: immediateThumbnail, mimeType: mimeType, size: size, attributes: parsedAttributes, alternativeRepresentations: alternativeRepresentations)
return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: size, fileReference: fileReference.makeData(), fileName: fileNameFromFileAttributes(parsedAttributes)), previewRepresentations: previewRepresentations, videoThumbnails: videoThumbnails, videoCover: videoCover.flatMap(telegramMediaImageFromApiPhoto), immediateThumbnailData: immediateThumbnail, mimeType: mimeType, size: size, attributes: parsedAttributes, alternativeRepresentations: alternativeRepresentations)
case .documentEmpty:
return nil
}

View file

@ -10,52 +10,72 @@ func apiEntitiesFromMessageTextEntities(_ entities: [MessageTextEntity], associa
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:
apiEntities.append(.messageEntityMention(.init(offset: offset, length: length)))
case .Hashtag:
apiEntities.append(.messageEntityHashtag(.init(offset: offset, length: length)))
case .BotCommand:
apiEntities.append(.messageEntityBotCommand(.init(offset: offset, length: length)))
case .Url:
apiEntities.append(.messageEntityUrl(.init(offset: offset, length: length)))
case .Email:
apiEntities.append(.messageEntityEmail(.init(offset: offset, length: length)))
case .Bold:
apiEntities.append(.messageEntityBold(.init(offset: offset, length: length)))
case .Italic:
apiEntities.append(.messageEntityItalic(.init(offset: offset, length: length)))
case .Code:
apiEntities.append(.messageEntityCode(.init(offset: offset, length: length)))
case let .Pre(language):
apiEntities.append(.messageEntityPre(.init(offset: offset, length: length, language: language ?? "")))
case let .TextUrl(url):
apiEntities.append(.messageEntityTextUrl(.init(offset: offset, length: length, url: url)))
case let .TextMention(peerId):
if let peer = associatedPeers[peerId], let inputUser = apiInputUser(peer) {
apiEntities.append(.inputMessageEntityMentionName(.init(offset: offset, length: length, userId: inputUser)))
case .Unknown:
break
case .Mention:
apiEntities.append(.messageEntityMention(.init(offset: offset, length: length)))
case .Hashtag:
apiEntities.append(.messageEntityHashtag(.init(offset: offset, length: length)))
case .BotCommand:
apiEntities.append(.messageEntityBotCommand(.init(offset: offset, length: length)))
case .Url:
apiEntities.append(.messageEntityUrl(.init(offset: offset, length: length)))
case .Email:
apiEntities.append(.messageEntityEmail(.init(offset: offset, length: length)))
case .Bold:
apiEntities.append(.messageEntityBold(.init(offset: offset, length: length)))
case .Italic:
apiEntities.append(.messageEntityItalic(.init(offset: offset, length: length)))
case .Code:
apiEntities.append(.messageEntityCode(.init(offset: offset, length: length)))
case let .Pre(language):
apiEntities.append(.messageEntityPre(.init(offset: offset, length: length, language: language ?? "")))
case let .TextUrl(url):
apiEntities.append(.messageEntityTextUrl(.init(offset: offset, length: length, url: url)))
case let .TextMention(peerId):
if let peer = associatedPeers[peerId], let inputUser = apiInputUser(peer) {
apiEntities.append(.inputMessageEntityMentionName(.init(offset: offset, length: length, userId: inputUser)))
}
case .PhoneNumber:
break
case .Strikethrough:
apiEntities.append(.messageEntityStrike(.init(offset: offset, length: length)))
case let .BlockQuote(isCollapsed):
var flags: Int32 = 0
if isCollapsed {
flags |= 1 << 0
}
apiEntities.append(.messageEntityBlockquote(.init(flags: flags, offset: offset, length: length)))
case .Underline:
apiEntities.append(.messageEntityUnderline(.init(offset: offset, length: length)))
case .BankCard:
apiEntities.append(.messageEntityBankCard(.init(offset: offset, length: length)))
case .Spoiler:
apiEntities.append(.messageEntitySpoiler(.init(offset: offset, length: length)))
case let .CustomEmoji(_, fileId):
apiEntities.append(.messageEntityCustomEmoji(.init(offset: offset, length: length, documentId: fileId)))
case let .FormattedDate(format, date):
var flags: Int32 = 0
switch format {
case .relative:
flags |= 1 << 0
case let .full(timeFormat, dateFormat):
switch timeFormat {
case .short:
flags |= 1 << 1
case .long:
flags |= 1 << 2
}
case .PhoneNumber:
break
case .Strikethrough:
apiEntities.append(.messageEntityStrike(.init(offset: offset, length: length)))
case let .BlockQuote(isCollapsed):
var flags: Int32 = 0
if isCollapsed {
flags |= 1 << 0
switch dateFormat {
case .short:
flags |= 1 << 3
case .long:
flags |= 1 << 4
}
apiEntities.append(.messageEntityBlockquote(.init(flags: flags, offset: offset, length: length)))
case .Underline:
apiEntities.append(.messageEntityUnderline(.init(offset: offset, length: length)))
case .BankCard:
apiEntities.append(.messageEntityBankCard(.init(offset: offset, length: length)))
case .Spoiler:
apiEntities.append(.messageEntitySpoiler(.init(offset: offset, length: length)))
case let .CustomEmoji(_, fileId):
apiEntities.append(.messageEntityCustomEmoji(.init(offset: offset, length: length, documentId: fileId)))
case .Custom:
break
}
apiEntities.append(.messageEntityFormattedDate(.init(flags: flags, offset: offset, length: length, date: date)))
case .Custom:
break
}
}

View file

@ -1169,7 +1169,7 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
if let _ = videoCoverPhoto {
flags |= 1 << 6
}
var ttlSeconds: Int32?
var videoTimestamp: Int32?
for attribute in attributes {
@ -1213,6 +1213,10 @@ private func uploadedMediaFileContent(network: Network, postbox: Postbox, auxili
flags |= 1 << 7
}
if file.isLivePhoto {
flags |= 1 << 8
}
if ttlSeconds != nil {
return .single(.content(PendingMessageUploadedContentAndReuploadInfo(content: .media(.inputMediaUploadedDocument(.init(flags: flags, file: inputFile, thumb: thumbnailFile, mimeType: file.mimeType, attributes: inputDocumentAttributesFromFileAttributes(file.attributes), stickers: stickers, videoCover: videoCoverPhoto, videoTimestamp: videoTimestamp, ttlSeconds: ttlSeconds)), text), reuploadInfo: nil, cacheReferenceKey: referenceKey)))
}

View file

@ -822,6 +822,8 @@ private func decryptedEntities73(_ entities: [MessageTextEntity]?) -> [SecretApi
break
case .CustomEmoji:
break
case .FormattedDate:
break
case .Custom:
break
}
@ -875,6 +877,8 @@ private func decryptedEntities101(_ entities: [MessageTextEntity]?) -> [SecretAp
break
case .CustomEmoji:
break
case .FormattedDate:
break
case .Custom:
break
}
@ -928,6 +932,8 @@ private func decryptedEntities144(_ entities: [MessageTextEntity]?) -> [SecretAp
result.append(.messageEntitySpoiler(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
case let .CustomEmoji(_, fileId):
result.append(.messageEntityCustomEmoji(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count), documentId: fileId))
case .FormattedDate:
break
case .Custom:
break
}

View file

@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
public class Serialization: NSObject, MTSerialization {
public func currentLayer() -> UInt {
return 222
return 225
}
public func parseMessage(_ data: Data!) -> Any! {

View file

@ -311,6 +311,7 @@ public struct TelegramMediaVideoFlags: OptionSet {
public static let instantRoundVideo = TelegramMediaVideoFlags(rawValue: 1 << 0)
public static let supportsStreaming = TelegramMediaVideoFlags(rawValue: 1 << 1)
public static let isSilent = TelegramMediaVideoFlags(rawValue: 1 << 3)
public static let isLivePhoto = TelegramMediaVideoFlags(rawValue: 1 << 4)
}
public struct StickerMaskCoords: PostboxCoding, Equatable {
@ -1060,6 +1061,15 @@ public final class TelegramMediaFile: Media, Equatable, Codable {
return false
}
public var isLivePhoto: Bool {
for attribute in self.attributes {
if case .Video(_, _, let flags, _, _, _) = attribute {
return flags.contains(.isLivePhoto)
}
}
return false
}
public var preloadSize: Int32? {
for attribute in self.attributes {
if case .Video(_, _, _, let preloadSize, _, _) = attribute {

View file

@ -4,6 +4,67 @@ import Postbox
public enum MessageTextEntityType: Equatable {
public typealias CustomEntityType = Int32
public enum DateTimeFormat: Equatable {
public enum TimeFormat: Equatable {
case short
case long
}
public enum DateFormat: Equatable {
case short
case long
}
case relative
case full(timeFormat: TimeFormat, dateFormat: DateFormat)
public init(rawValue: Int32) {
if (rawValue & (1 << 0)) != 0 {
self = .relative
} else {
let timeFormat: MessageTextEntityType.DateTimeFormat.TimeFormat
if (rawValue & (1 << 1)) != 0 {
timeFormat = .short
} else if (rawValue & (1 << 2)) != 0 {
timeFormat = .long
} else {
timeFormat = .short
}
let dateFormat: MessageTextEntityType.DateTimeFormat.DateFormat
if (rawValue & (1 << 3)) != 0 {
dateFormat = .short
} else if (rawValue & (1 << 4)) != 0 {
dateFormat = .long
} else {
dateFormat = .short
}
self = .full(timeFormat: timeFormat, dateFormat: dateFormat)
}
}
public var rawValue: Int32 {
var rawValue: Int32 = 0
switch self {
case .relative:
rawValue |= 1 << 0
case let .full(timeFormat, dateFormat):
switch timeFormat {
case .short:
rawValue |= 1 << 1
case .long:
rawValue |= 1 << 2
}
switch dateFormat {
case .short:
rawValue |= 1 << 3
case .long:
rawValue |= 1 << 4
}
}
return rawValue
}
}
case Unknown
case Mention
case Hashtag
@ -23,6 +84,7 @@ public enum MessageTextEntityType: Equatable {
case BankCard
case Spoiler
case CustomEmoji(stickerPack: StickerPackReference?, fileId: Int64)
case FormattedDate(format: DateTimeFormat, date: Int32)
case Custom(type: CustomEntityType)
}
@ -39,47 +101,49 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable {
self.range = Int(decoder.decodeInt32ForKey("start", orElse: 0)) ..< Int(decoder.decodeInt32ForKey("end", orElse: 0))
let type: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
switch type {
case 1:
self.type = .Mention
case 2:
self.type = .Hashtag
case 3:
self.type = .BotCommand
case 4:
self.type = .Url
case 5:
self.type = .Email
case 6:
self.type = .Bold
case 7:
self.type = .Italic
case 8:
self.type = .Code
case 9:
self.type = .Pre(language: decoder.decodeOptionalStringForKey("language"))
case 10:
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
case 13:
self.type = .Strikethrough
case 14:
self.type = .BlockQuote(isCollapsed: decoder.decodeBoolForKey("cl", orElse: false))
case 15:
self.type = .Underline
case 16:
self.type = .BankCard
case 17:
self.type = .Spoiler
case 18:
let stickerPack = decoder.decodeObjectForKey("s", decoder: { StickerPackReference(decoder: $0) }) as? StickerPackReference
self.type = .CustomEmoji(stickerPack: stickerPack, fileId: decoder.decodeInt64ForKey("f", orElse: 0))
case Int32.max:
self.type = .Custom(type: decoder.decodeInt32ForKey("type", orElse: 0))
default:
self.type = .Unknown
case 1:
self.type = .Mention
case 2:
self.type = .Hashtag
case 3:
self.type = .BotCommand
case 4:
self.type = .Url
case 5:
self.type = .Email
case 6:
self.type = .Bold
case 7:
self.type = .Italic
case 8:
self.type = .Code
case 9:
self.type = .Pre(language: decoder.decodeOptionalStringForKey("language"))
case 10:
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
case 13:
self.type = .Strikethrough
case 14:
self.type = .BlockQuote(isCollapsed: decoder.decodeBoolForKey("cl", orElse: false))
case 15:
self.type = .Underline
case 16:
self.type = .BankCard
case 17:
self.type = .Spoiler
case 18:
let stickerPack = decoder.decodeObjectForKey("s", decoder: { StickerPackReference(decoder: $0) }) as? StickerPackReference
self.type = .CustomEmoji(stickerPack: stickerPack, fileId: decoder.decodeInt64ForKey("f", orElse: 0))
case 19:
self.type = .FormattedDate(format: MessageTextEntityType.DateTimeFormat(rawValue: decoder.decodeInt32ForKey("format", orElse: 0)), date: decoder.decodeInt32ForKey("date", orElse: 0))
case Int32.max:
self.type = .Custom(type: decoder.decodeInt32ForKey("type", orElse: 0))
default:
self.type = .Unknown
}
}
@ -95,49 +159,51 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable {
self.range = Int(rangeStart) ..< Int(rangeEnd)
switch type {
case 1:
self.type = .Mention
case 2:
self.type = .Hashtag
case 3:
self.type = .BotCommand
case 4:
self.type = .Url
case 5:
self.type = .Email
case 6:
self.type = .Bold
case 7:
self.type = .Italic
case 8:
self.type = .Code
case 9:
self.type = .Pre(language: try? container.decodeIfPresent(String.self, forKey: "language"))
case 10:
let url = (try? container.decode(String.self, forKey: "url")) ?? ""
self.type = .TextUrl(url: url)
case 11:
let peerId = (try? container.decode(Int64.self, forKey: "peerId")) ?? 0
self.type = .TextMention(peerId: PeerId(peerId))
case 12:
self.type = .PhoneNumber
case 13:
self.type = .Strikethrough
case 14:
self.type = .BlockQuote(isCollapsed: try container.decodeIfPresent(Bool.self, forKey: "cl") ?? false)
case 15:
self.type = .Underline
case 16:
self.type = .BankCard
case 17:
self.type = .Spoiler
case 18:
self.type = .CustomEmoji(stickerPack: try container.decodeIfPresent(StickerPackReference.self, forKey: "s"), fileId: try container.decode(Int64.self, forKey: "f"))
case Int32.max:
let customType: Int32 = (try? container.decode(Int32.self, forKey: "type")) ?? 0
self.type = .Custom(type: customType)
default:
self.type = .Unknown
case 1:
self.type = .Mention
case 2:
self.type = .Hashtag
case 3:
self.type = .BotCommand
case 4:
self.type = .Url
case 5:
self.type = .Email
case 6:
self.type = .Bold
case 7:
self.type = .Italic
case 8:
self.type = .Code
case 9:
self.type = .Pre(language: try? container.decodeIfPresent(String.self, forKey: "language"))
case 10:
let url = (try? container.decode(String.self, forKey: "url")) ?? ""
self.type = .TextUrl(url: url)
case 11:
let peerId = (try? container.decode(Int64.self, forKey: "peerId")) ?? 0
self.type = .TextMention(peerId: PeerId(peerId))
case 12:
self.type = .PhoneNumber
case 13:
self.type = .Strikethrough
case 14:
self.type = .BlockQuote(isCollapsed: try container.decodeIfPresent(Bool.self, forKey: "cl") ?? false)
case 15:
self.type = .Underline
case 16:
self.type = .BankCard
case 17:
self.type = .Spoiler
case 18:
self.type = .CustomEmoji(stickerPack: try container.decodeIfPresent(StickerPackReference.self, forKey: "s"), fileId: try container.decode(Int64.self, forKey: "f"))
case 19:
self.type = .FormattedDate(format: MessageTextEntityType.DateTimeFormat(rawValue: try container.decode(Int32.self, forKey: "format")), date: try container.decode(Int32.self, forKey: "date"))
case Int32.max:
let customType: Int32 = (try? container.decode(Int32.self, forKey: "type")) ?? 0
self.type = .Custom(type: customType)
default:
self.type = .Unknown
}
}
@ -145,61 +211,65 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable {
encoder.encodeInt32(Int32(self.range.lowerBound), forKey: "start")
encoder.encodeInt32(Int32(self.range.upperBound), forKey: "end")
switch self.type {
case .Unknown:
encoder.encodeInt32(0, forKey: "_rawValue")
case .Mention:
encoder.encodeInt32(1, forKey: "_rawValue")
case .Hashtag:
encoder.encodeInt32(2, forKey: "_rawValue")
case .BotCommand:
encoder.encodeInt32(3, forKey: "_rawValue")
case .Url:
encoder.encodeInt32(4, forKey: "_rawValue")
case .Email:
encoder.encodeInt32(5, forKey: "_rawValue")
case .Bold:
encoder.encodeInt32(6, forKey: "_rawValue")
case .Italic:
encoder.encodeInt32(7, forKey: "_rawValue")
case .Code:
encoder.encodeInt32(8, forKey: "_rawValue")
case let .Pre(language):
encoder.encodeInt32(9, forKey: "_rawValue")
if let language = language {
encoder.encodeString(language, forKey: "language")
} else {
encoder.encodeNil(forKey: "language")
}
case let .TextUrl(url):
encoder.encodeInt32(10, forKey: "_rawValue")
encoder.encodeString(url, forKey: "url")
case let .TextMention(peerId):
encoder.encodeInt32(11, forKey: "_rawValue")
encoder.encodeInt64(peerId.toInt64(), forKey: "peerId")
case .PhoneNumber:
encoder.encodeInt32(12, forKey: "_rawValue")
case .Strikethrough:
encoder.encodeInt32(13, forKey: "_rawValue")
case let .BlockQuote(isCollapsed):
encoder.encodeInt32(14, forKey: "_rawValue")
encoder.encodeBool(isCollapsed, forKey: "cl")
case .Underline:
encoder.encodeInt32(15, forKey: "_rawValue")
case .BankCard:
encoder.encodeInt32(16, forKey: "_rawValue")
case .Spoiler:
encoder.encodeInt32(17, forKey: "_rawValue")
case let .CustomEmoji(stickerPack, fileId):
encoder.encodeInt32(18, forKey: "_rawValue")
if let stickerPack = stickerPack {
encoder.encodeObject(stickerPack, forKey: "s")
} else {
encoder.encodeNil(forKey: "s")
}
encoder.encodeInt64(fileId, forKey: "f")
case let .Custom(type):
encoder.encodeInt32(Int32.max, forKey: "_rawValue")
encoder.encodeInt32(type, forKey: "type")
case .Unknown:
encoder.encodeInt32(0, forKey: "_rawValue")
case .Mention:
encoder.encodeInt32(1, forKey: "_rawValue")
case .Hashtag:
encoder.encodeInt32(2, forKey: "_rawValue")
case .BotCommand:
encoder.encodeInt32(3, forKey: "_rawValue")
case .Url:
encoder.encodeInt32(4, forKey: "_rawValue")
case .Email:
encoder.encodeInt32(5, forKey: "_rawValue")
case .Bold:
encoder.encodeInt32(6, forKey: "_rawValue")
case .Italic:
encoder.encodeInt32(7, forKey: "_rawValue")
case .Code:
encoder.encodeInt32(8, forKey: "_rawValue")
case let .Pre(language):
encoder.encodeInt32(9, forKey: "_rawValue")
if let language = language {
encoder.encodeString(language, forKey: "language")
} else {
encoder.encodeNil(forKey: "language")
}
case let .TextUrl(url):
encoder.encodeInt32(10, forKey: "_rawValue")
encoder.encodeString(url, forKey: "url")
case let .TextMention(peerId):
encoder.encodeInt32(11, forKey: "_rawValue")
encoder.encodeInt64(peerId.toInt64(), forKey: "peerId")
case .PhoneNumber:
encoder.encodeInt32(12, forKey: "_rawValue")
case .Strikethrough:
encoder.encodeInt32(13, forKey: "_rawValue")
case let .BlockQuote(isCollapsed):
encoder.encodeInt32(14, forKey: "_rawValue")
encoder.encodeBool(isCollapsed, forKey: "cl")
case .Underline:
encoder.encodeInt32(15, forKey: "_rawValue")
case .BankCard:
encoder.encodeInt32(16, forKey: "_rawValue")
case .Spoiler:
encoder.encodeInt32(17, forKey: "_rawValue")
case let .CustomEmoji(stickerPack, fileId):
encoder.encodeInt32(18, forKey: "_rawValue")
if let stickerPack = stickerPack {
encoder.encodeObject(stickerPack, forKey: "s")
} else {
encoder.encodeNil(forKey: "s")
}
encoder.encodeInt64(fileId, forKey: "f")
case let .FormattedDate(format, date):
encoder.encodeInt32(19, forKey: "_rawValue")
encoder.encodeInt32(format.rawValue, forKey: "format")
encoder.encodeInt32(date, forKey: "date")
case let .Custom(type):
encoder.encodeInt32(Int32.max, forKey: "_rawValue")
encoder.encodeInt32(type, forKey: "type")
}
}
@ -209,53 +279,57 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable {
try container.encode(Int32(self.range.lowerBound), forKey: "start")
try container.encode(Int32(self.range.upperBound), forKey: "end")
switch self.type {
case .Unknown:
try container.encode(0 as Int32, forKey: "_rawValue")
case .Mention:
try container.encode(1 as Int32, forKey: "_rawValue")
case .Hashtag:
try container.encode(2 as Int32, forKey: "_rawValue")
case .BotCommand:
try container.encode(3 as Int32, forKey: "_rawValue")
case .Url:
try container.encode(4 as Int32, forKey: "_rawValue")
case .Email:
try container.encode(5 as Int32, forKey: "_rawValue")
case .Bold:
try container.encode(6 as Int32, forKey: "_rawValue")
case .Italic:
try container.encode(7 as Int32, forKey: "_rawValue")
case .Code:
try container.encode(8 as Int32, forKey: "_rawValue")
case let .Pre(language):
try container.encode(9 as Int32, forKey: "_rawValue")
try container.encodeIfPresent(language, forKey: "language")
case let .TextUrl(url):
try container.encode(10 as Int32, forKey: "_rawValue")
try container.encode(url, forKey: "url")
case let .TextMention(peerId):
try container.encode(11 as Int32, forKey: "_rawValue")
try container.encode(peerId.toInt64(), forKey: "peerId")
case .PhoneNumber:
try container.encode(12 as Int32, forKey: "_rawValue")
case .Strikethrough:
try container.encode(13 as Int32, forKey: "_rawValue")
case let .BlockQuote(isCollapsed):
try container.encode(14 as Int32, forKey: "_rawValue")
try container.encode(isCollapsed, forKey: "cl")
case .Underline:
try container.encode(15 as Int32, forKey: "_rawValue")
case .BankCard:
try container.encode(16 as Int32, forKey: "_rawValue")
case .Spoiler:
try container.encode(17 as Int32, forKey: "_rawValue")
case let .CustomEmoji(stickerPack, fileId):
try container.encode(18 as Int32, forKey: "_rawValue")
try container.encodeIfPresent(stickerPack, forKey: "s")
try container.encode(fileId, forKey: "f")
case let .Custom(type):
try container.encode(Int32.max as Int32, forKey: "_rawValue")
try container.encode(type as Int32, forKey: "type")
case .Unknown:
try container.encode(0 as Int32, forKey: "_rawValue")
case .Mention:
try container.encode(1 as Int32, forKey: "_rawValue")
case .Hashtag:
try container.encode(2 as Int32, forKey: "_rawValue")
case .BotCommand:
try container.encode(3 as Int32, forKey: "_rawValue")
case .Url:
try container.encode(4 as Int32, forKey: "_rawValue")
case .Email:
try container.encode(5 as Int32, forKey: "_rawValue")
case .Bold:
try container.encode(6 as Int32, forKey: "_rawValue")
case .Italic:
try container.encode(7 as Int32, forKey: "_rawValue")
case .Code:
try container.encode(8 as Int32, forKey: "_rawValue")
case let .Pre(language):
try container.encode(9 as Int32, forKey: "_rawValue")
try container.encodeIfPresent(language, forKey: "language")
case let .TextUrl(url):
try container.encode(10 as Int32, forKey: "_rawValue")
try container.encode(url, forKey: "url")
case let .TextMention(peerId):
try container.encode(11 as Int32, forKey: "_rawValue")
try container.encode(peerId.toInt64(), forKey: "peerId")
case .PhoneNumber:
try container.encode(12 as Int32, forKey: "_rawValue")
case .Strikethrough:
try container.encode(13 as Int32, forKey: "_rawValue")
case let .BlockQuote(isCollapsed):
try container.encode(14 as Int32, forKey: "_rawValue")
try container.encode(isCollapsed, forKey: "cl")
case .Underline:
try container.encode(15 as Int32, forKey: "_rawValue")
case .BankCard:
try container.encode(16 as Int32, forKey: "_rawValue")
case .Spoiler:
try container.encode(17 as Int32, forKey: "_rawValue")
case let .CustomEmoji(stickerPack, fileId):
try container.encode(18 as Int32, forKey: "_rawValue")
try container.encodeIfPresent(stickerPack, forKey: "s")
try container.encode(fileId, forKey: "f")
case let .FormattedDate(format, date):
try container.encode(19 as Int32, forKey: "_rawValue")
try container.encode(format.rawValue, forKey: "format")
try container.encode(date, forKey: "date")
case let .Custom(type):
try container.encode(Int32.max as Int32, forKey: "_rawValue")
try container.encode(type as Int32, forKey: "type")
}
}

View file

@ -3594,6 +3594,8 @@ private func serializeGroupCallMessage(randomId: Int64, text: String, entities:
case let .CustomEmoji(_, fileId):
entityDict["_"] = "messageEntityCustomEmoji"
entityDict["document_id"] = "\(fileId)"
case .FormattedDate:
return nil
case .Custom:
return nil
}