mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Secret Chats layer 101 support
This commit is contained in:
parent
0fd1a50d7f
commit
855e98f9c5
1581
submodules/TelegramApi/Sources/SecretApiLayer101.swift
Normal file
1581
submodules/TelegramApi/Sources/SecretApiLayer101.swift
Normal file
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
09E9601B22C2BE4900B13673 /* SecretApiLayer101.swift in Sources */ = {isa = PBXBuildFile; fileRef = 09E9601A22C2BE4900B13673 /* SecretApiLayer101.swift */; };
|
||||
D035732422B5C1FC00F0920D /* TelegramApi.h in Headers */ = {isa = PBXBuildFile; fileRef = D035732222B5C1FC00F0920D /* TelegramApi.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
D035733422B5C29900F0920D /* Api0.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035733022B5C29900F0920D /* Api0.swift */; };
|
||||
D035733522B5C29900F0920D /* Api2.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035733122B5C29900F0920D /* Api2.swift */; };
|
||||
@ -32,6 +33,7 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
09E9601A22C2BE4900B13673 /* SecretApiLayer101.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecretApiLayer101.swift; sourceTree = "<group>"; };
|
||||
D035731F22B5C1FC00F0920D /* TelegramApi.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TelegramApi.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D035732222B5C1FC00F0920D /* TelegramApi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TelegramApi.h; sourceTree = "<group>"; };
|
||||
D035732322B5C1FC00F0920D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
@ -94,6 +96,7 @@
|
||||
D035734522B5C9BF00F0920D /* SecretApiLayer8.swift */,
|
||||
D035734422B5C9BF00F0920D /* SecretApiLayer46.swift */,
|
||||
D035734622B5C9BF00F0920D /* SecretApiLayer73.swift */,
|
||||
09E9601A22C2BE4900B13673 /* SecretApiLayer101.swift */,
|
||||
D035733C22B5C39100F0920D /* DeserializeFunctionResponse.swift */,
|
||||
D035733A22B5C31400F0920D /* TelegramApiLogger.swift */,
|
||||
D035733822B5C2E200F0920D /* Buffer.swift */,
|
||||
@ -230,6 +233,7 @@
|
||||
D035733D22B5C39100F0920D /* DeserializeFunctionResponse.swift in Sources */,
|
||||
D035734822B5C9BF00F0920D /* SecretApiLayer8.swift in Sources */,
|
||||
D035733522B5C29900F0920D /* Api2.swift in Sources */,
|
||||
09E9601B22C2BE4900B13673 /* SecretApiLayer101.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
@ -361,6 +361,7 @@ private enum BoxedDecryptedMessage {
|
||||
case layer8(SecretApi8.DecryptedMessage)
|
||||
case layer46(SecretApi46.DecryptedMessage)
|
||||
case layer73(SecretApi73.DecryptedMessage)
|
||||
case layer101(SecretApi101.DecryptedMessage)
|
||||
|
||||
func serialize(_ buffer: Buffer, role: SecretChatRole, sequenceInfo: SecretChatOperationSequenceInfo?) {
|
||||
switch self {
|
||||
@ -405,6 +406,26 @@ private enum BoxedDecryptedMessage {
|
||||
assertionFailure()
|
||||
}
|
||||
|
||||
let _ = message.serialize(buffer, true)
|
||||
case let .layer101(message):
|
||||
buffer.appendInt32(0x1be31789)
|
||||
let randomBytes = malloc(15)!
|
||||
arc4random_buf(randomBytes, 15)
|
||||
serializeBytes(Buffer(memory: randomBytes, size: 15, capacity: 15, freeWhenDone: false), buffer: buffer, boxed: false)
|
||||
free(randomBytes)
|
||||
buffer.appendInt32(101)
|
||||
|
||||
if let sequenceInfo = sequenceInfo {
|
||||
let inSeqNo = (sequenceInfo.topReceivedOperationIndex + 1) * 2 + (role == .creator ? 0 : 1)
|
||||
let outSeqNo = sequenceInfo.operationIndex * 2 + (role == .creator ? 1 : 0)
|
||||
buffer.appendInt32(inSeqNo)
|
||||
buffer.appendInt32(outSeqNo)
|
||||
} else {
|
||||
buffer.appendInt32(0)
|
||||
buffer.appendInt32(0)
|
||||
assertionFailure()
|
||||
}
|
||||
|
||||
let _ = message.serialize(buffer, true)
|
||||
}
|
||||
}
|
||||
@ -567,6 +588,59 @@ private func decryptedAttributes73(_ attributes: [TelegramMediaFileAttribute], t
|
||||
return result
|
||||
}
|
||||
|
||||
private func decryptedAttributes101(_ attributes: [TelegramMediaFileAttribute], transaction: Transaction) -> [SecretApi101.DocumentAttribute] {
|
||||
var result: [SecretApi101.DocumentAttribute] = []
|
||||
for attribute in attributes {
|
||||
switch attribute {
|
||||
case let .FileName(fileName):
|
||||
result.append(.documentAttributeFilename(fileName: fileName))
|
||||
case .Animated:
|
||||
result.append(.documentAttributeAnimated)
|
||||
case let .Sticker(displayText, packReference, _):
|
||||
var stickerSet: SecretApi101.InputStickerSet = .inputStickerSetEmpty
|
||||
if let packReference = packReference {
|
||||
switch packReference {
|
||||
case let .name(name):
|
||||
stickerSet = .inputStickerSetShortName(shortName: name)
|
||||
case .id:
|
||||
if let (info, _, _) = cachedStickerPack(transaction: transaction, reference: packReference) {
|
||||
stickerSet = .inputStickerSetShortName(shortName: info.shortName)
|
||||
}
|
||||
}
|
||||
}
|
||||
result.append(.documentAttributeSticker(alt: displayText, stickerset: stickerSet))
|
||||
case let .ImageSize(size):
|
||||
result.append(.documentAttributeImageSize(w: Int32(size.width), h: Int32(size.height)))
|
||||
case let .Video(duration, size, videoFlags):
|
||||
var flags: Int32 = 0
|
||||
if videoFlags.contains(.instantRoundVideo) {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
result.append(.documentAttributeVideo(flags: flags, duration: Int32(duration), w: Int32(size.width), h: Int32(size.height)))
|
||||
case let .Audio(isVoice, duration, title, performer, waveform):
|
||||
var flags: Int32 = 0
|
||||
if isVoice {
|
||||
flags |= (1 << 10)
|
||||
}
|
||||
if let _ = title {
|
||||
flags |= Int32(1 << 0)
|
||||
}
|
||||
if let _ = performer {
|
||||
flags |= Int32(1 << 1)
|
||||
}
|
||||
var waveformBuffer: Buffer?
|
||||
if let waveform = waveform {
|
||||
flags |= Int32(1 << 2)
|
||||
waveformBuffer = Buffer(data: waveform.makeData())
|
||||
}
|
||||
result.append(.documentAttributeAudio(flags: flags, duration: Int32(duration), title: title, performer: performer, waveform: waveformBuffer))
|
||||
case .HasLinkedStickers:
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private func decryptedEntities73(_ entities: [MessageTextEntity]?) -> [SecretApi73.MessageEntity]? {
|
||||
guard let entities = entities else {
|
||||
return nil
|
||||
@ -614,6 +688,53 @@ private func decryptedEntities73(_ entities: [MessageTextEntity]?) -> [SecretApi
|
||||
return result
|
||||
}
|
||||
|
||||
private func decryptedEntities101(_ entities: [MessageTextEntity]?) -> [SecretApi101.MessageEntity]? {
|
||||
guard let entities = entities else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var result: [SecretApi101.MessageEntity] = []
|
||||
for entity in entities {
|
||||
switch entity.type {
|
||||
case .Unknown:
|
||||
break
|
||||
case .Mention:
|
||||
result.append(.messageEntityMention(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .Hashtag:
|
||||
result.append(.messageEntityHashtag(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .BotCommand:
|
||||
result.append(.messageEntityBotCommand(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .Url:
|
||||
result.append(.messageEntityUrl(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .Email:
|
||||
result.append(.messageEntityEmail(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .Bold:
|
||||
result.append(.messageEntityBold(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .Italic:
|
||||
result.append(.messageEntityItalic(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .Code:
|
||||
result.append(.messageEntityCode(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .Pre:
|
||||
result.append(.messageEntityPre(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count), language: ""))
|
||||
case let .TextUrl(url):
|
||||
result.append(.messageEntityTextUrl(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count), url: url))
|
||||
case .TextMention:
|
||||
break
|
||||
case .PhoneNumber:
|
||||
break
|
||||
case .Strikethrough:
|
||||
result.append(.messageEntityStrike(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .BlockQuote:
|
||||
result.append(.messageEntityBlockquote(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .Underline:
|
||||
result.append(.messageEntityUnderline(offset: Int32(entity.range.lowerBound), length: Int32(entity.range.count)))
|
||||
case .Custom:
|
||||
break
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private func boxedDecryptedMessage(transaction: Transaction, message: Message, globallyUniqueId: Int64, uploadedFile: SecretChatOutgoingFile?, thumbnailData: [MediaId: (CGSize, Data)], layer: SecretChatLayer) -> BoxedDecryptedMessage {
|
||||
let media: Media? = message.media.first
|
||||
var messageAutoremoveTimeout: Int32 = 0
|
||||
@ -691,6 +812,20 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
||||
flags |= (1 << 17)
|
||||
}
|
||||
return .layer73(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
case .layer101:
|
||||
if let _ = viaBotName {
|
||||
flags |= (1 << 11)
|
||||
}
|
||||
let decryptedEntites = entities.flatMap(decryptedEntities101)
|
||||
if let _ = decryptedEntites {
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
let decryptedMedia = SecretApi101.DecryptedMessageMedia.decryptedMessageMediaPhoto(thumb: thumb, thumbW: thumbW, thumbH: thumbH, w: Int32(largestRepresentation.dimensions.width), h: Int32(largestRepresentation.dimensions.height), size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), caption: "")
|
||||
flags |= (1 << 9)
|
||||
if message.groupingKey != nil {
|
||||
flags |= (1 << 17)
|
||||
}
|
||||
return .layer101(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
}
|
||||
} else if let file = media as? TelegramMediaFile {
|
||||
let thumbW: Int32
|
||||
@ -786,6 +921,37 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
||||
flags |= (1 << 9)
|
||||
return .layer73(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
}
|
||||
case .layer101:
|
||||
var decryptedMedia: SecretApi101.DecryptedMessageMedia?
|
||||
|
||||
if let uploadedFile = uploadedFile {
|
||||
decryptedMedia = SecretApi101.DecryptedMessageMedia.decryptedMessageMediaDocument(thumb: thumb, thumbW: thumbW, thumbH: thumbH, mimeType: file.mimeType, size: uploadedFile.size, key: Buffer(data: uploadedFile.key.aesKey), iv: Buffer(data: uploadedFile.key.aesIv), attributes: decryptedAttributes101(file.attributes, transaction: transaction), caption: "")
|
||||
} else {
|
||||
if let resource = file.resource as? CloudDocumentMediaResource, let size = file.size {
|
||||
let thumb: SecretApi101.PhotoSize
|
||||
if let smallestRepresentation = smallestImageRepresentation(file.previewRepresentations), let thumbResource = smallestRepresentation.resource as? CloudFileMediaResource {
|
||||
thumb = .photoSize(type: "s", location: .fileLocation(dcId: Int32(thumbResource.datacenterId), volumeId: thumbResource.volumeId, localId: thumbResource.localId, secret: thumbResource.secret), w: Int32(smallestRepresentation.dimensions.width), h: Int32(smallestRepresentation.dimensions.height), size: thumbResource.size.flatMap(Int32.init) ?? 0)
|
||||
} else {
|
||||
thumb = SecretApi101.PhotoSize.photoSizeEmpty(type: "s")
|
||||
}
|
||||
decryptedMedia = SecretApi101.DecryptedMessageMedia.decryptedMessageMediaExternalDocument(id: resource.fileId, accessHash: resource.accessHash, date: 0, mimeType: file.mimeType, size: Int32(size), thumb: thumb, dcId: Int32(resource.datacenterId), attributes: decryptedAttributes101(file.attributes, transaction: transaction))
|
||||
}
|
||||
}
|
||||
|
||||
if let decryptedMedia = decryptedMedia {
|
||||
if let _ = viaBotName {
|
||||
flags |= (1 << 11)
|
||||
}
|
||||
let decryptedEntites = entities.flatMap(decryptedEntities101)
|
||||
if let _ = decryptedEntites {
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
if message.groupingKey != nil {
|
||||
flags |= (1 << 17)
|
||||
}
|
||||
flags |= (1 << 9)
|
||||
return .layer101(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
}
|
||||
}
|
||||
} else if let webpage = media as? TelegramMediaWebpage {
|
||||
var url: String?
|
||||
@ -815,6 +981,17 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
||||
let decryptedMedia = SecretApi73.DecryptedMessageMedia.decryptedMessageMediaWebPage(url: url)
|
||||
flags |= (1 << 9)
|
||||
return .layer73(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
case .layer101:
|
||||
if let _ = viaBotName {
|
||||
flags |= (1 << 11)
|
||||
}
|
||||
let decryptedEntites = entities.flatMap(decryptedEntities101)
|
||||
if let _ = decryptedEntites {
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
let decryptedMedia = SecretApi101.DecryptedMessageMedia.decryptedMessageMediaWebPage(url: url)
|
||||
flags |= (1 << 9)
|
||||
return .layer101(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
}
|
||||
}
|
||||
} else if let location = media as? TelegramMediaMap {
|
||||
@ -850,6 +1027,23 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
||||
decryptedMedia = .decryptedMessageMediaGeoPoint(lat: location.latitude, long: location.longitude)
|
||||
}
|
||||
return .layer73(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
case .layer101:
|
||||
if let _ = viaBotName {
|
||||
flags |= (1 << 11)
|
||||
}
|
||||
let decryptedEntites = entities.flatMap(decryptedEntities101)
|
||||
if let _ = decryptedEntites {
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
|
||||
let decryptedMedia: SecretApi101.DecryptedMessageMedia
|
||||
flags |= (1 << 9)
|
||||
if let venue = location.venue {
|
||||
decryptedMedia = .decryptedMessageMediaVenue(lat: location.latitude, long: location.longitude, title: venue.title, address: venue.address ?? "", provider: venue.provider ?? "", venueId: venue.id ?? "")
|
||||
} else {
|
||||
decryptedMedia = .decryptedMessageMediaGeoPoint(lat: location.latitude, long: location.longitude)
|
||||
}
|
||||
return .layer101(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
}
|
||||
} else if let contact = media as? TelegramMediaContact {
|
||||
switch layer {
|
||||
@ -874,6 +1068,18 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
||||
let decryptedMedia: SecretApi73.DecryptedMessageMedia = .decryptedMessageMediaContact(phoneNumber: contact.phoneNumber, firstName: contact.firstName, lastName: contact.lastName, userId: 0)
|
||||
flags |= (1 << 9)
|
||||
return .layer73(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
case .layer101:
|
||||
if let _ = viaBotName {
|
||||
flags |= (1 << 11)
|
||||
}
|
||||
let decryptedEntites = entities.flatMap(decryptedEntities101)
|
||||
if let _ = decryptedEntites {
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
|
||||
let decryptedMedia: SecretApi101.DecryptedMessageMedia = .decryptedMessageMediaContact(phoneNumber: contact.phoneNumber, firstName: contact.firstName, lastName: contact.lastName, userId: 0)
|
||||
flags |= (1 << 9)
|
||||
return .layer101(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: decryptedMedia, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -899,6 +1105,15 @@ private func boxedDecryptedMessage(transaction: Transaction, message: Message, g
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
return .layer73(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: .decryptedMessageMediaEmpty, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
case .layer101:
|
||||
if let _ = viaBotName {
|
||||
flags |= (1 << 11)
|
||||
}
|
||||
let decryptedEntites = entities.flatMap(decryptedEntities101)
|
||||
if let _ = decryptedEntites {
|
||||
flags |= (1 << 7)
|
||||
}
|
||||
return .layer101(.decryptedMessage(flags: flags, randomId: globallyUniqueId, ttl: messageAutoremoveTimeout, message: message.text, media: .decryptedMessageMediaEmpty, entities: decryptedEntites, viaBotName: viaBotName, replyToRandomId: replyGlobalId, groupedId: message.groupingKey))
|
||||
}
|
||||
}
|
||||
|
||||
@ -916,6 +1131,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionDeleteMessages(randomIds: globallyUniqueIds)))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionDeleteMessages(randomIds: globallyUniqueIds)))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionDeleteMessages(randomIds: globallyUniqueIds)))
|
||||
}
|
||||
case let .screenshotMessages(layer, actionGloballyUniqueId, globallyUniqueIds, _):
|
||||
switch layer {
|
||||
@ -929,6 +1146,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionScreenshotMessages(randomIds: globallyUniqueIds)))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionScreenshotMessages(randomIds: globallyUniqueIds)))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionScreenshotMessages(randomIds: globallyUniqueIds)))
|
||||
}
|
||||
case let .clearHistory(layer, actionGloballyUniqueId):
|
||||
switch layer {
|
||||
@ -941,6 +1160,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionFlushHistory))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionFlushHistory))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionFlushHistory))
|
||||
}
|
||||
case let .resendOperations(layer, actionGloballyUniqueId, fromSeqNo, toSeqNo):
|
||||
switch layer {
|
||||
@ -948,6 +1169,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionResend(startSeqNo: fromSeqNo, endSeqNo: toSeqNo)))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionResend(startSeqNo: fromSeqNo, endSeqNo: toSeqNo)))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionResend(startSeqNo: fromSeqNo, endSeqNo: toSeqNo)))
|
||||
}
|
||||
case let .reportLayerSupport(layer, actionGloballyUniqueId, layerSupport):
|
||||
switch layer {
|
||||
@ -961,6 +1184,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionNotifyLayer(layer: layerSupport)))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionNotifyLayer(layer: layerSupport)))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionNotifyLayer(layer: layerSupport)))
|
||||
}
|
||||
case let .pfsRequestKey(layer, actionGloballyUniqueId, rekeySessionId, gA):
|
||||
switch layer {
|
||||
@ -968,6 +1193,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionRequestKey(exchangeId: rekeySessionId, gA: Buffer(buffer: gA))))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionRequestKey(exchangeId: rekeySessionId, gA: Buffer(buffer: gA))))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionRequestKey(exchangeId: rekeySessionId, gA: Buffer(buffer: gA))))
|
||||
}
|
||||
case let .pfsAcceptKey(layer, actionGloballyUniqueId, rekeySessionId, gB, keyFingerprint):
|
||||
switch layer {
|
||||
@ -975,6 +1202,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionAcceptKey(exchangeId: rekeySessionId, gB: Buffer(buffer: gB), keyFingerprint: keyFingerprint)))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionAcceptKey(exchangeId: rekeySessionId, gB: Buffer(buffer: gB), keyFingerprint: keyFingerprint)))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionAcceptKey(exchangeId: rekeySessionId, gB: Buffer(buffer: gB), keyFingerprint: keyFingerprint)))
|
||||
}
|
||||
case let .pfsAbortSession(layer, actionGloballyUniqueId, rekeySessionId):
|
||||
switch layer {
|
||||
@ -982,6 +1211,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionAbortKey(exchangeId: rekeySessionId)))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionAbortKey(exchangeId: rekeySessionId)))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionAbortKey(exchangeId: rekeySessionId)))
|
||||
}
|
||||
case let .pfsCommitKey(layer, actionGloballyUniqueId, rekeySessionId, keyFingerprint):
|
||||
switch layer {
|
||||
@ -989,6 +1220,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionCommitKey(exchangeId: rekeySessionId, keyFingerprint: keyFingerprint)))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionCommitKey(exchangeId: rekeySessionId, keyFingerprint: keyFingerprint)))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionCommitKey(exchangeId: rekeySessionId, keyFingerprint: keyFingerprint)))
|
||||
}
|
||||
case let .noop(layer, actionGloballyUniqueId):
|
||||
switch layer {
|
||||
@ -996,6 +1229,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionNoop))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionNoop))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionNoop))
|
||||
}
|
||||
case let .readMessageContents(layer, actionGloballyUniqueId, globallyUniqueIds):
|
||||
switch layer {
|
||||
@ -1009,6 +1244,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionReadMessages(randomIds: globallyUniqueIds)))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionReadMessages(randomIds: globallyUniqueIds)))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionReadMessages(randomIds: globallyUniqueIds)))
|
||||
}
|
||||
case let .setMessageAutoremoveTimeout(layer, actionGloballyUniqueId, timeout, _):
|
||||
switch layer {
|
||||
@ -1022,6 +1259,8 @@ private func boxedDecryptedSecretMessageAction(action: SecretMessageAction) -> B
|
||||
return .layer46(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionSetMessageTTL(ttlSeconds: timeout)))
|
||||
case .layer73:
|
||||
return .layer73(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionSetMessageTTL(ttlSeconds: timeout)))
|
||||
case .layer101:
|
||||
return .layer101(.decryptedMessageService(randomId: actionGloballyUniqueId, action: .decryptedMessageActionSetMessageTTL(ttlSeconds: timeout)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,10 @@ private func parsedServiceAction(_ operation: SecretChatIncomingDecryptedOperati
|
||||
if let parsedObject = SecretApi73.parse(Buffer(bufferNoCopy: operation.contents)), let apiMessage = parsedObject as? SecretApi73.DecryptedMessage {
|
||||
return SecretChatServiceAction(apiMessage)
|
||||
}
|
||||
case .layer101:
|
||||
if let parsedObject = SecretApi101.parse(Buffer(bufferNoCopy: operation.contents)), let apiMessage = parsedObject as? SecretApi101.DecryptedMessage {
|
||||
return SecretChatServiceAction(apiMessage)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -153,6 +157,18 @@ func processSecretChatIncomingDecryptedOperations(mediaBox: MediaBox, transactio
|
||||
} else {
|
||||
contentParsingError = true
|
||||
}
|
||||
case .layer101:
|
||||
if let parsedObject = SecretApi101.parse(Buffer(bufferNoCopy: operation.contents)), let apiMessage = parsedObject as? SecretApi101.DecryptedMessage {
|
||||
if let (parsedMessage, parsedResources) = parseMessage(peerId: peerId, authorId: updatedPeer.regularPeerId, tagLocalIndex: entry.tagLocalIndex, timestamp: operation.timestamp, apiMessage: apiMessage, file: operation.file, messageIdForGloballyUniqueMessageId: { id in
|
||||
return transaction.messageIdForGloballyUniqueMessageId(peerId: peerId, id: id)
|
||||
}) {
|
||||
message = parsedMessage
|
||||
resources = parsedResources
|
||||
}
|
||||
serviceAction = SecretChatServiceAction(apiMessage)
|
||||
} else {
|
||||
contentParsingError = true
|
||||
}
|
||||
}
|
||||
|
||||
switch updatedState.embeddedState {
|
||||
@ -214,7 +230,11 @@ func processSecretChatIncomingDecryptedOperations(mediaBox: MediaBox, transactio
|
||||
case .handshake:
|
||||
throw MessageParsingError.invalidChatState
|
||||
case .basicLayer:
|
||||
if layerSupport >= 73 {
|
||||
if layerSupport >= 101 {
|
||||
let sequenceBasedLayerState = SecretChatSequenceBasedLayerState(layerNegotiationState: SecretChatLayerNegotiationState(activeLayer: .layer101, locallyRequestedLayer: 101, remotelyRequestedLayer: layerSupport), rekeyState: nil, baseIncomingOperationIndex: entry.tagLocalIndex, baseOutgoingOperationIndex: transaction.operationLogGetNextEntryLocalIndex(peerId: peerId, tag: OperationLogTags.SecretOutgoing), topProcessedCanonicalIncomingOperationIndex: nil)
|
||||
updatedState = updatedState.withUpdatedEmbeddedState(.sequenceBasedLayer(sequenceBasedLayerState))
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer101, actionGloballyUniqueId: arc4random64(), layerSupport: 101), state: updatedState)
|
||||
} else if layerSupport >= 73 {
|
||||
let sequenceBasedLayerState = SecretChatSequenceBasedLayerState(layerNegotiationState: SecretChatLayerNegotiationState(activeLayer: .layer73, locallyRequestedLayer: 73, remotelyRequestedLayer: layerSupport), rekeyState: nil, baseIncomingOperationIndex: entry.tagLocalIndex, baseOutgoingOperationIndex: transaction.operationLogGetNextEntryLocalIndex(peerId: peerId, tag: OperationLogTags.SecretOutgoing), topProcessedCanonicalIncomingOperationIndex: nil)
|
||||
updatedState = updatedState.withUpdatedEmbeddedState(.sequenceBasedLayer(sequenceBasedLayerState))
|
||||
updatedState = addSecretChatOutgoingOperation(transaction: transaction, peerId: peerId, operation: .reportLayerSupport(layer: .layer73, actionGloballyUniqueId: arc4random64(), layerSupport: 73), state: updatedState)
|
||||
@ -455,6 +475,42 @@ extension SecretChatServiceAction {
|
||||
}
|
||||
}
|
||||
|
||||
extension SecretChatServiceAction {
|
||||
init?(_ apiMessage: SecretApi101.DecryptedMessage) {
|
||||
switch apiMessage {
|
||||
case .decryptedMessage:
|
||||
return nil
|
||||
case let .decryptedMessageService(_, action):
|
||||
switch action {
|
||||
case let .decryptedMessageActionDeleteMessages(randomIds):
|
||||
self = .deleteMessages(globallyUniqueIds: randomIds)
|
||||
case .decryptedMessageActionFlushHistory:
|
||||
self = .clearHistory
|
||||
case let .decryptedMessageActionNotifyLayer(layer):
|
||||
self = .reportLayerSupport(layer)
|
||||
case let .decryptedMessageActionReadMessages(randomIds):
|
||||
self = .markMessagesContentAsConsumed(globallyUniqueIds: randomIds)
|
||||
case .decryptedMessageActionScreenshotMessages:
|
||||
return nil
|
||||
case let .decryptedMessageActionSetMessageTTL(ttlSeconds):
|
||||
self = .setMessageAutoremoveTimeout(ttlSeconds)
|
||||
case let .decryptedMessageActionResend(startSeqNo, endSeqNo):
|
||||
self = .resendOperations(fromSeq: startSeqNo, toSeq: endSeqNo)
|
||||
case let .decryptedMessageActionRequestKey(exchangeId, gA):
|
||||
self = .rekeyAction(.pfsRequestKey(rekeySessionId: exchangeId, gA: MemoryBuffer(gA)))
|
||||
case let .decryptedMessageActionAcceptKey(exchangeId, gB, keyFingerprint):
|
||||
self = .rekeyAction(.pfsAcceptKey(rekeySessionId: exchangeId, gB: MemoryBuffer(gB), keyFingerprint: keyFingerprint))
|
||||
case let .decryptedMessageActionCommitKey(exchangeId, keyFingerprint):
|
||||
self = .rekeyAction(.pfsCommitKey(rekeySessionId: exchangeId, keyFingerprint: keyFingerprint))
|
||||
case let .decryptedMessageActionAbortKey(exchangeId):
|
||||
self = .rekeyAction(.pfsAbortSession(rekeySessionId: exchangeId))
|
||||
case .decryptedMessageActionNoop:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension StoreMessage {
|
||||
convenience init?(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32, timestamp: Int32, apiMessage: SecretApi8.DecryptedMessage, file: SecretChatFileReference?) {
|
||||
switch apiMessage {
|
||||
@ -549,6 +605,43 @@ extension TelegramMediaFileAttribute {
|
||||
}
|
||||
}
|
||||
|
||||
extension TelegramMediaFileAttribute {
|
||||
init?(_ apiAttribute: SecretApi101.DocumentAttribute) {
|
||||
switch apiAttribute {
|
||||
case .documentAttributeAnimated:
|
||||
self = .Animated
|
||||
case let .documentAttributeAudio(flags, duration, title, performer, waveform):
|
||||
let isVoice = (flags & (1 << 10)) != 0
|
||||
var waveformBuffer: MemoryBuffer?
|
||||
if let waveform = waveform {
|
||||
let memory = malloc(waveform.size)!
|
||||
memcpy(memory, waveform.data, waveform.size)
|
||||
waveformBuffer = MemoryBuffer(memory: memory, capacity: waveform.size, length: waveform.size, freeWhenDone: true)
|
||||
}
|
||||
self = .Audio(isVoice: isVoice, duration: Int(duration), title: title, performer: performer, waveform: waveformBuffer)
|
||||
case let .documentAttributeFilename(fileName):
|
||||
self = .FileName(fileName: fileName)
|
||||
case let .documentAttributeImageSize(w, h):
|
||||
self = .ImageSize(size: CGSize(width: CGFloat(w), height: CGFloat(h)))
|
||||
case let .documentAttributeSticker(alt, stickerset):
|
||||
let packReference: StickerPackReference?
|
||||
switch stickerset {
|
||||
case .inputStickerSetEmpty:
|
||||
packReference = nil
|
||||
case let .inputStickerSetShortName(shortName):
|
||||
packReference = .name(shortName)
|
||||
}
|
||||
self = .Sticker(displayText: alt, packReference: packReference, maskData: nil)
|
||||
case let .documentAttributeVideo(flags, duration, w, h):
|
||||
var videoFlags: TelegramMediaVideoFlags = []
|
||||
if (flags & (1 << 0)) != 0 {
|
||||
videoFlags.insert(.instantRoundVideo)
|
||||
}
|
||||
self = .Video(duration: Int(duration), size: CGSize(width: CGFloat(w), height: CGFloat(h)), flags: videoFlags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func parseEntities(_ entities: [SecretApi46.MessageEntity]?) -> TextEntitiesMessageAttribute {
|
||||
var result: [MessageTextEntity] = []
|
||||
if let entities = entities {
|
||||
@ -986,3 +1079,237 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func parseEntities(_ entities: [SecretApi101.MessageEntity]) -> TextEntitiesMessageAttribute {
|
||||
var result: [MessageTextEntity] = []
|
||||
for entity in entities {
|
||||
switch entity {
|
||||
case let .messageEntityMention(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Mention))
|
||||
case let .messageEntityHashtag(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Hashtag))
|
||||
case let .messageEntityBotCommand(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .BotCommand))
|
||||
case let .messageEntityUrl(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Url))
|
||||
case let .messageEntityEmail(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Email))
|
||||
case let .messageEntityBold(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Bold))
|
||||
case let .messageEntityItalic(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Italic))
|
||||
case let .messageEntityCode(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Code))
|
||||
case let .messageEntityPre(offset, length, _):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Pre))
|
||||
case let .messageEntityTextUrl(offset, length, url):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .TextUrl(url: url)))
|
||||
case let .messageEntityStrike(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Strikethrough))
|
||||
case let .messageEntityUnderline(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .Underline))
|
||||
case let .messageEntityBlockquote(offset, length):
|
||||
result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .BlockQuote))
|
||||
case .messageEntityUnknown:
|
||||
break
|
||||
}
|
||||
}
|
||||
return TextEntitiesMessageAttribute(entities: result)
|
||||
}
|
||||
|
||||
private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32, timestamp: Int32, apiMessage: SecretApi101.DecryptedMessage, file: SecretChatFileReference?, messageIdForGloballyUniqueMessageId: (Int64) -> MessageId?) -> (StoreMessage, [(MediaResource, Data)])? {
|
||||
switch apiMessage {
|
||||
case let .decryptedMessage(_, randomId, ttl, message, media, entities, viaBotName, replyToRandomId, groupedId):
|
||||
var text = message
|
||||
var parsedMedia: [Media] = []
|
||||
var attributes: [MessageAttribute] = []
|
||||
var resources: [(MediaResource, Data)] = []
|
||||
|
||||
if let entitiesAttribute = entities.flatMap(parseEntities) {
|
||||
attributes.append(entitiesAttribute)
|
||||
}
|
||||
|
||||
if let viaBotName = viaBotName, !viaBotName.isEmpty {
|
||||
attributes.append(InlineBotMessageAttribute(peerId: nil, title: viaBotName))
|
||||
}
|
||||
|
||||
if let media = media {
|
||||
switch media {
|
||||
case let .decryptedMessageMediaPhoto(thumb, thumbW, thumbH, w, h, size, key, iv, caption):
|
||||
if !caption.isEmpty {
|
||||
text = caption
|
||||
}
|
||||
if let file = file {
|
||||
var representations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(thumbW), height: CGFloat(thumbH)), resource: resource))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
representations.append(TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(w), height: CGFloat(h)), resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size)))
|
||||
let image = TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudSecretImage, id: file.id), representations: representations, immediateThumbnailData: nil, reference: nil, partialReference: nil)
|
||||
parsedMedia.append(image)
|
||||
}
|
||||
case let .decryptedMessageMediaAudio(duration, mimeType, size, key, iv):
|
||||
if let file = file {
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: [TelegramMediaFileAttribute.Audio(isVoice: true, duration: Int(duration), title: nil, performer: nil, waveform: nil)])
|
||||
parsedMedia.append(fileMedia)
|
||||
attributes.append(ConsumableContentMessageAttribute(consumed: false))
|
||||
}
|
||||
case let .decryptedMessageMediaDocument(thumb, thumbW, thumbH, mimeType, size, key, iv, decryptedAttributes, caption):
|
||||
if !caption.isEmpty {
|
||||
text = caption
|
||||
}
|
||||
if let file = file {
|
||||
var parsedAttributes: [TelegramMediaFileAttribute] = []
|
||||
for attribute in decryptedAttributes {
|
||||
if let parsedAttribute = TelegramMediaFileAttribute(attribute) {
|
||||
parsedAttributes.append(parsedAttribute)
|
||||
}
|
||||
}
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(thumbW), height: CGFloat(thumbH)), resource: resource))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: previewRepresentations, immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
|
||||
loop: for attr in parsedAttributes {
|
||||
switch attr {
|
||||
case let .Video(_, _, flags):
|
||||
if flags.contains(.instantRoundVideo) {
|
||||
attributes.append(ConsumableContentMessageAttribute(consumed: false))
|
||||
}
|
||||
break loop
|
||||
case let .Audio(isVoice, _, _, _, _):
|
||||
if isVoice {
|
||||
attributes.append(ConsumableContentMessageAttribute(consumed: false))
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
case let .decryptedMessageMediaVideo(thumb, thumbW, thumbH, duration, mimeType, w, h, size, key, iv, caption):
|
||||
if !caption.isEmpty {
|
||||
text = caption
|
||||
}
|
||||
if let file = file {
|
||||
let parsedAttributes: [TelegramMediaFileAttribute] = [.Video(duration: Int(duration), size: CGSize(width: CGFloat(w), height: CGFloat(h)), flags: []), .FileName(fileName: "video.mov")]
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
if thumb.size != 0 {
|
||||
let resource = LocalFileMediaResource(fileId: arc4random64())
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(thumbW), height: CGFloat(thumbH)), resource: resource))
|
||||
resources.append((resource, thumb.makeData()))
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudSecretFile, id: file.id), partialReference: nil, resource: file.resource(key: SecretFileEncryptionKey(aesKey: key.makeData(), aesIv: iv.makeData()), decryptedSize: size), previewRepresentations: previewRepresentations, immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
}
|
||||
case let .decryptedMessageMediaExternalDocument(id, accessHash, date, mimeType, size, thumb, dcId, attributes):
|
||||
var parsedAttributes: [TelegramMediaFileAttribute] = []
|
||||
for attribute in attributes {
|
||||
if let parsedAttribute = TelegramMediaFileAttribute(attribute) {
|
||||
parsedAttributes.append(parsedAttribute)
|
||||
}
|
||||
}
|
||||
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||
switch thumb {
|
||||
case let .photoSize(_, location, w, h, size):
|
||||
switch location {
|
||||
case let .fileLocation(dcId, volumeId, localId, secret):
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(w), height: CGFloat(h)), resource: CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: size == 0 ? nil : Int(size), fileReference: nil)))
|
||||
case .fileLocationUnavailable:
|
||||
break
|
||||
}
|
||||
case let .photoCachedSize(_, location, w, h, bytes):
|
||||
if bytes.size > 0 {
|
||||
switch location {
|
||||
case let .fileLocation(dcId, volumeId, localId, secret):
|
||||
let resource = CloudFileMediaResource(datacenterId: Int(dcId), volumeId: volumeId, localId: localId, secret: secret, size: bytes.size, fileReference: nil)
|
||||
resources.append((resource, bytes.makeData()))
|
||||
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(w), height: CGFloat(h)), resource: resource))
|
||||
case .fileLocationUnavailable:
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
let fileMedia = TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.CloudFile, id: id), partialReference: nil, resource: CloudDocumentMediaResource(datacenterId: Int(dcId), fileId: id, accessHash: accessHash, size: Int(size), fileReference: nil, fileName: nil), previewRepresentations: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int(size), attributes: parsedAttributes)
|
||||
parsedMedia.append(fileMedia)
|
||||
case let .decryptedMessageMediaWebPage(url):
|
||||
parsedMedia.append(TelegramMediaWebpage(webpageId: MediaId(namespace: Namespaces.Media.LocalWebpage, id: arc4random64()), content: .Pending(0, url)))
|
||||
case let .decryptedMessageMediaGeoPoint(lat, long):
|
||||
parsedMedia.append(TelegramMediaMap(latitude: lat, longitude: long, geoPlace: nil, venue: nil, liveBroadcastingTimeout: nil))
|
||||
case let .decryptedMessageMediaContact(phoneNumber, firstName, lastName, userId):
|
||||
parsedMedia.append(TelegramMediaContact(firstName: firstName, lastName: lastName, phoneNumber: phoneNumber, peerId: userId == 0 ? nil : PeerId(namespace: Namespaces.Peer.CloudUser, id: userId), vCardData: nil))
|
||||
case let .decryptedMessageMediaVenue(lat, long, title, address, provider, venueId):
|
||||
parsedMedia.append(TelegramMediaMap(latitude: lat, longitude: long, geoPlace: nil, venue: MapVenue(title: title, address: address, provider: provider, id: venueId, type: nil), liveBroadcastingTimeout: nil))
|
||||
case .decryptedMessageMediaEmpty:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if ttl > 0 {
|
||||
attributes.append(AutoremoveTimeoutMessageAttribute(timeout: ttl, countdownBeginTime: nil))
|
||||
}
|
||||
|
||||
var groupingKey: Int64?
|
||||
if let groupedId = groupedId {
|
||||
inner: for media in parsedMedia {
|
||||
if let _ = media as? TelegramMediaImage {
|
||||
groupingKey = groupedId
|
||||
break inner
|
||||
} else if let _ = media as? TelegramMediaFile {
|
||||
groupingKey = groupedId
|
||||
break inner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let replyToRandomId = replyToRandomId, let replyMessageId = messageIdForGloballyUniqueMessageId(replyToRandomId) {
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessageId))
|
||||
}
|
||||
|
||||
var entitiesAttribute: TextEntitiesMessageAttribute?
|
||||
for attribute in attributes {
|
||||
if let attribute = attribute as? TextEntitiesMessageAttribute {
|
||||
entitiesAttribute = attribute
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
let (tags, globalTags) = tagsForStoreMessage(incoming: true, attributes: attributes, media: parsedMedia, textEntities: entitiesAttribute?.entities)
|
||||
|
||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, groupingKey: groupingKey, timestamp: timestamp, flags: [.Incoming], tags: tags, globalTags: globalTags, localTags: [], forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: parsedMedia), resources)
|
||||
case let .decryptedMessageService(randomId, action):
|
||||
switch action {
|
||||
case .decryptedMessageActionDeleteMessages:
|
||||
return nil
|
||||
case .decryptedMessageActionFlushHistory:
|
||||
return nil
|
||||
case .decryptedMessageActionNotifyLayer:
|
||||
return nil
|
||||
case .decryptedMessageActionReadMessages:
|
||||
return nil
|
||||
case .decryptedMessageActionScreenshotMessages:
|
||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: authorId, text: "", attributes: [], media: [TelegramMediaAction(action: .historyScreenshot)]), [])
|
||||
case let .decryptedMessageActionSetMessageTTL(ttlSeconds):
|
||||
return (StoreMessage(id: MessageId(peerId: peerId, namespace: Namespaces.Message.SecretIncoming, id: tagLocalIndex), globallyUniqueId: randomId, groupingKey: nil, timestamp: timestamp, flags: [.Incoming], tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: authorId, text: "", attributes: [], media: [TelegramMediaAction(action: .messageAutoremoveTimeoutUpdated(ttlSeconds))]), [])
|
||||
case .decryptedMessageActionResend:
|
||||
return nil
|
||||
case .decryptedMessageActionRequestKey:
|
||||
return nil
|
||||
case .decryptedMessageActionAcceptKey:
|
||||
return nil
|
||||
case .decryptedMessageActionCommitKey:
|
||||
return nil
|
||||
case .decryptedMessageActionAbortKey:
|
||||
return nil
|
||||
case .decryptedMessageActionNoop:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import Foundation
|
||||
import SwiftSignalKit
|
||||
#endif
|
||||
|
||||
private let topSupportedLayer: SecretChatSequenceBasedLayer = .layer73
|
||||
private let topSupportedLayer: SecretChatSequenceBasedLayer = .layer101
|
||||
|
||||
func secretChatCommonSupportedLayer(remoteLayer: Int32) -> SecretChatSequenceBasedLayer {
|
||||
switch remoteLayer {
|
||||
@ -15,6 +15,8 @@ func secretChatCommonSupportedLayer(remoteLayer: Int32) -> SecretChatSequenceBas
|
||||
return .layer46
|
||||
case 73:
|
||||
return .layer73
|
||||
case 101:
|
||||
return .layer101
|
||||
default:
|
||||
return topSupportedLayer
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ struct SecretChatOutgoingFile: PostboxCoding {
|
||||
public enum SecretChatSequenceBasedLayer: Int32 {
|
||||
case layer46 = 46
|
||||
case layer73 = 73
|
||||
case layer101 = 101
|
||||
|
||||
var secretChatLayer: SecretChatLayer {
|
||||
switch self {
|
||||
@ -88,6 +89,8 @@ public enum SecretChatSequenceBasedLayer: Int32 {
|
||||
return .layer46
|
||||
case .layer73:
|
||||
return .layer73
|
||||
case .layer101:
|
||||
return .layer101
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ enum SecretChatLayer: Int32 {
|
||||
case layer8 = 8
|
||||
case layer46 = 46
|
||||
case layer73 = 73
|
||||
case layer101 = 101
|
||||
}
|
||||
|
||||
public struct SecretChatKeySha1Fingerprint: PostboxCoding, Equatable {
|
||||
|
@ -216,7 +216,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 102
|
||||
return 101
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
Loading…
x
Reference in New Issue
Block a user