no message

This commit is contained in:
Peter 2019-04-09 16:18:57 +01:00
parent 5bce7d9dc2
commit 491e377943
12 changed files with 1363 additions and 404 deletions

View file

@ -49,6 +49,8 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
private let applyDisposable = MetaDisposable()
private let fetchedDisposable = MetaDisposable()
private var accountsPath: String?
deinit {
self.applyDisposable.dispose()
self.fetchedDisposable.dispose()
@ -85,6 +87,8 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
setupSharedLogger(logsPath)
accountsPath = rootPath
if sharedAccountContext == nil {
initializeAccountManagement()
let accountManager = AccountManager(basePath: rootPath + "/accounts-metadata")
@ -130,21 +134,15 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
}
func didReceive(_ notification: UNNotification) {
if let accountIdValue = notification.request.content.userInfo["accountId"] as? Int64, let peerIdValue = notification.request.content.userInfo["peerId"] as? Int64, let messageIdNamespace = notification.request.content.userInfo["messageId.namespace"] as? Int32, let messageIdId = notification.request.content.userInfo["messageId.id"] as? Int32, let dict = notification.request.content.userInfo["mediaInfo"] as? [String: Any] {
guard let accountsPath = self.accountsPath else {
return
}
if let accountIdValue = notification.request.content.userInfo["accountId"] as? Int64, let peerIdValue = notification.request.content.userInfo["peerId"] as? Int64, let messageIdNamespace = notification.request.content.userInfo["messageId.namespace"] as? Int32, let messageIdId = notification.request.content.userInfo["messageId.id"] as? Int32, let mediaDataString = notification.request.content.userInfo["media"] as? String, let mediaData = Data(base64Encoded: mediaDataString), let media = parseMediaData(data: mediaData) {
let messageId = MessageId(peerId: PeerId(peerIdValue), namespace: messageIdNamespace, id: messageIdId)
if let imageInfo = dict["image"] as? [String: Any] {
guard let width = imageInfo["width"] as? Int, let height = imageInfo["height"] as? Int else {
return
}
guard let thumbnailInfo = imageInfo["thumbnail"] as? [String: Any] else {
return
}
guard let fullSizeInfo = imageInfo["fullSize"] as? [String: Any] else {
return
}
let dimensions = CGSize(width: CGFloat(width), height: CGFloat(height))
if let image = media as? TelegramMediaImage, let thumbnailRepresentation = imageRepresentationLargerThan(image.representations, size: CGSize(width: 120.0, height: 120.0)), let largestRepresentation = largestImageRepresentation(image.representations) {
let dimensions = largestRepresentation.dimensions
let fittedSize = dimensions.fitted(CGSize(width: self.view.bounds.width, height: 1000.0))
self.view.frame = CGRect(origin: self.view.frame.origin, size: fittedSize)
self.preferredContentSize = fittedSize
@ -152,13 +150,15 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
self.imageDimensions = dimensions
self.updateImageLayout(boundingSize: self.view.bounds.size)
if let path = fullSizeInfo["path"] as? String, let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
let mediaBoxPath = accountsPath + "/" + accountRecordIdPathName(AccountRecordId(rawValue: accountIdValue)) + "/postbox/media"
if let data = try? Data(contentsOf: URL(fileURLWithPath: mediaBoxPath + "/\(largestRepresentation.resource.id.uniqueId)"), options: .mappedRead) {
self.imageNode.setSignal(chatMessagePhotoInternal(photoData: .single((nil, data, true)))
|> map { $0.1 })
return
}
if let path = thumbnailInfo["path"] as? String, let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
if let data = try? Data(contentsOf: URL(fileURLWithPath: mediaBoxPath + "/\(thumbnailRepresentation.resource.id.uniqueId)"), options: .mappedRead) {
self.imageNode.setSignal(chatMessagePhotoInternal(photoData: .single((data, nil, false)))
|> map { $0.1 })
}
@ -190,9 +190,7 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
}
}
} else {
if let thumbnailFileLocation = thumbnailInfo["fileLocation"] as? [AnyHashable: Any], let thumbnailResource = parseFileLocationResource(thumbnailFileLocation), let fileLocation = fullSizeInfo["fileLocation"] as? [AnyHashable: Any], let resource = parseFileLocationResource(fileLocation) {
imageReference = .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.CloudImage, id: 1), representations: [TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(width), height: CGFloat(height)).fitted(CGSize(width: 320.0, height: 320.0)), resource: thumbnailResource), TelegramMediaImageRepresentation(dimensions: CGSize(width: CGFloat(width), height: CGFloat(height)), resource: resource)], immediateThumbnailData: nil, reference: nil, partialReference: nil))
}
imageReference = .standalone(media: image)
}
return (account, imageReference)
}
@ -208,6 +206,56 @@ class NotificationViewController: UIViewController, UNNotificationContentExtensi
strongSelf.fetchedDisposable.set(standaloneChatMessagePhotoInteractiveFetched(account: accountAndImage.0, photoReference: imageReference).start())
}
}))
} else if let file = media as? TelegramMediaFile, let dimensions = file.dimensions {
guard let sharedAccountContext = sharedAccountContext else {
return
}
let fittedSize = dimensions.fitted(CGSize(width: min(300.0, self.view.bounds.width), height: 300.0))
self.view.frame = CGRect(origin: self.view.frame.origin, size: fittedSize)
self.preferredContentSize = fittedSize
self.applyDisposable.set((sharedAccountContext.activeAccounts
|> map { _, accounts, _ -> Account? in
return accounts.first(where: { $0.0 == AccountRecordId(rawValue: accountIdValue) })?.1
}
|> filter { account in
return account != nil
}
|> take(1)
|> mapToSignal { account -> Signal<(Account, FileMediaReference?), NoError> in
guard let account = account else {
return .complete()
}
return account.postbox.messageAtId(messageId)
|> take(1)
|> map { message in
var fileReference: FileMediaReference?
if let message = message {
for media in message.media {
if let file = media as? TelegramMediaFile {
fileReference = .message(message: MessageReference(message), media: file)
}
}
} else {
fileReference = .standalone(media: file)
}
return (account, fileReference)
}
}
|> deliverOnMainQueue).start(next: { [weak self] accountAndImage in
guard let strongSelf = self else {
return
}
if let fileReference = accountAndImage.1 {
if file.isSticker {
strongSelf.imageNode.setSignal(chatMessageSticker(account: accountAndImage.0, file: file, small: false))
accountAndImage.0.network.shouldExplicitelyKeepWorkerConnections.set(.single(true))
strongSelf.fetchedDisposable.set(freeMediaFileInteractiveFetched(account: accountAndImage.0, fileReference: fileReference).start())
}
}
}))
}
}
}

View file

@ -0,0 +1,834 @@
fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
var dict: [Int32 : (BufferReader) -> Any?] = [:]
dict[-1471112230] = { return $0.readInt32() }
dict[570911930] = { return $0.readInt64() }
dict[571523412] = { return $0.readDouble() }
dict[-1255641564] = { return parseString($0) }
dict[590459437] = { return Api.Photo.parse_photoEmpty($0) }
dict[-797637467] = { return Api.Photo.parse_photo($0) }
dict[236446268] = { return Api.PhotoSize.parse_photoSizeEmpty($0) }
dict[2009052699] = { return Api.PhotoSize.parse_photoSize($0) }
dict[-374917894] = { return Api.PhotoSize.parse_photoCachedSize($0) }
dict[-525288402] = { return Api.PhotoSize.parse_photoStrippedSize($0) }
dict[-1132476723] = { return Api.FileLocation.parse_fileLocationToBeDeprecated($0) }
dict[1815593308] = { return Api.DocumentAttribute.parse_documentAttributeImageSize($0) }
dict[297109817] = { return Api.DocumentAttribute.parse_documentAttributeAnimated($0) }
dict[1662637586] = { return Api.DocumentAttribute.parse_documentAttributeSticker($0) }
dict[250621158] = { return Api.DocumentAttribute.parse_documentAttributeVideo($0) }
dict[-1739392570] = { return Api.DocumentAttribute.parse_documentAttributeAudio($0) }
dict[358154344] = { return Api.DocumentAttribute.parse_documentAttributeFilename($0) }
dict[-1744710921] = { return Api.DocumentAttribute.parse_documentAttributeHasStickers($0) }
dict[-4838507] = { return Api.InputStickerSet.parse_inputStickerSetEmpty($0) }
dict[-1645763991] = { return Api.InputStickerSet.parse_inputStickerSetID($0) }
dict[-2044933984] = { return Api.InputStickerSet.parse_inputStickerSetShortName($0) }
dict[1075322878] = { return Api.InputFileLocation.parse_inputPhotoFileLocation($0) }
dict[-1160743548] = { return Api.InputFileLocation.parse_inputDocumentFileLocation($0) }
dict[-1361650766] = { return Api.MaskCoords.parse_maskCoords($0) }
dict[-1683841855] = { return Api.Document.parse_document($0) }
return dict
}()
struct Api {
static func parse(_ buffer: Buffer) -> Any? {
let reader = BufferReader(buffer)
if let signature = reader.readInt32() {
return parse(reader, signature: signature)
}
return nil
}
static func parse(_ reader: BufferReader, signature: Int32) -> Any? {
if let parser = parsers[signature] {
return parser(reader)
}
else {
//Logger.shared.log("TL", "Type constructor \(String(signature, radix: 16, uppercase: false)) not found")
return nil
}
}
static func parseVector<T>(_ reader: BufferReader, elementSignature: Int32, elementType: T.Type) -> [T]? {
if let count = reader.readInt32() {
var array = [T]()
var i: Int32 = 0
while i < count {
var signature = elementSignature
if elementSignature == 0 {
if let unboxedSignature = reader.readInt32() {
signature = unboxedSignature
}
else {
return nil
}
}
if elementType == Buffer.self {
if let item = parseBytes(reader) as? T {
array.append(item)
} else {
return nil
}
} else {
if let item = Api.parse(reader, signature: signature) as? T {
array.append(item)
}
else {
return nil
}
}
i += 1
}
return array
}
return nil
}
static func serializeObject(_ object: Any, buffer: Buffer, boxed: Swift.Bool) {
switch object {
case let _1 as Api.Photo:
_1.serialize(buffer, boxed)
case let _1 as Api.PhotoSize:
_1.serialize(buffer, boxed)
case let _1 as Api.FileLocation:
_1.serialize(buffer, boxed)
case let _1 as Api.DocumentAttribute:
_1.serialize(buffer, boxed)
case let _1 as Api.InputStickerSet:
_1.serialize(buffer, boxed)
case let _1 as Api.InputFileLocation:
_1.serialize(buffer, boxed)
case let _1 as Api.MaskCoords:
_1.serialize(buffer, boxed)
case let _1 as Api.Document:
_1.serialize(buffer, boxed)
default:
break
}
}
}
extension Api {
enum Photo: TypeConstructorDescription {
case photoEmpty(id: Int64)
case photo(flags: Int32, id: Int64, accessHash: Int64, fileReference: Buffer, date: Int32, sizes: [Api.PhotoSize], dcId: Int32)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .photoEmpty(let id):
if boxed {
buffer.appendInt32(590459437)
}
serializeInt64(id, buffer: buffer, boxed: false)
break
case .photo(let flags, let id, let accessHash, let fileReference, let date, let sizes, let dcId):
if boxed {
buffer.appendInt32(-797637467)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeBytes(fileReference, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(sizes.count))
for item in sizes {
item.serialize(buffer, true)
}
serializeInt32(dcId, buffer: buffer, boxed: false)
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .photoEmpty(let id):
return ("photoEmpty", [("id", id)])
case .photo(let flags, let id, let accessHash, let fileReference, let date, let sizes, let dcId):
return ("photo", [("flags", flags), ("id", id), ("accessHash", accessHash), ("fileReference", fileReference), ("date", date), ("sizes", sizes), ("dcId", dcId)])
}
}
static func parse_photoEmpty(_ reader: BufferReader) -> Photo? {
var _1: Int64?
_1 = reader.readInt64()
let _c1 = _1 != nil
if _c1 {
return Api.Photo.photoEmpty(id: _1!)
}
else {
return nil
}
}
static func parse_photo(_ reader: BufferReader) -> Photo? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int64?
_3 = reader.readInt64()
var _4: Buffer?
_4 = parseBytes(reader)
var _5: Int32?
_5 = reader.readInt32()
var _6: [Api.PhotoSize]?
if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PhotoSize.self)
}
var _7: Int32?
_7 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.Photo.photo(flags: _1!, id: _2!, accessHash: _3!, fileReference: _4!, date: _5!, sizes: _6!, dcId: _7!)
}
else {
return nil
}
}
}
enum PhotoSize: TypeConstructorDescription {
case photoSizeEmpty(type: String)
case photoSize(type: String, location: Api.FileLocation, w: Int32, h: Int32, size: Int32)
case photoCachedSize(type: String, location: Api.FileLocation, w: Int32, h: Int32, bytes: Buffer)
case photoStrippedSize(type: String, bytes: Buffer)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .photoSizeEmpty(let type):
if boxed {
buffer.appendInt32(236446268)
}
serializeString(type, buffer: buffer, boxed: false)
break
case .photoSize(let type, let location, let w, let h, let size):
if boxed {
buffer.appendInt32(2009052699)
}
serializeString(type, buffer: buffer, boxed: false)
location.serialize(buffer, true)
serializeInt32(w, buffer: buffer, boxed: false)
serializeInt32(h, buffer: buffer, boxed: false)
serializeInt32(size, buffer: buffer, boxed: false)
break
case .photoCachedSize(let type, let location, let w, let h, let bytes):
if boxed {
buffer.appendInt32(-374917894)
}
serializeString(type, buffer: buffer, boxed: false)
location.serialize(buffer, true)
serializeInt32(w, buffer: buffer, boxed: false)
serializeInt32(h, buffer: buffer, boxed: false)
serializeBytes(bytes, buffer: buffer, boxed: false)
break
case .photoStrippedSize(let type, let bytes):
if boxed {
buffer.appendInt32(-525288402)
}
serializeString(type, buffer: buffer, boxed: false)
serializeBytes(bytes, buffer: buffer, boxed: false)
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .photoSizeEmpty(let type):
return ("photoSizeEmpty", [("type", type)])
case .photoSize(let type, let location, let w, let h, let size):
return ("photoSize", [("type", type), ("location", location), ("w", w), ("h", h), ("size", size)])
case .photoCachedSize(let type, let location, let w, let h, let bytes):
return ("photoCachedSize", [("type", type), ("location", location), ("w", w), ("h", h), ("bytes", bytes)])
case .photoStrippedSize(let type, let bytes):
return ("photoStrippedSize", [("type", type), ("bytes", bytes)])
}
}
static func parse_photoSizeEmpty(_ reader: BufferReader) -> PhotoSize? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.PhotoSize.photoSizeEmpty(type: _1!)
}
else {
return nil
}
}
static func parse_photoSize(_ reader: BufferReader) -> PhotoSize? {
var _1: String?
_1 = parseString(reader)
var _2: Api.FileLocation?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.FileLocation
}
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
_5 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.PhotoSize.photoSize(type: _1!, location: _2!, w: _3!, h: _4!, size: _5!)
}
else {
return nil
}
}
static func parse_photoCachedSize(_ reader: BufferReader) -> PhotoSize? {
var _1: String?
_1 = parseString(reader)
var _2: Api.FileLocation?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.FileLocation
}
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
var _5: Buffer?
_5 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.PhotoSize.photoCachedSize(type: _1!, location: _2!, w: _3!, h: _4!, bytes: _5!)
}
else {
return nil
}
}
static func parse_photoStrippedSize(_ reader: BufferReader) -> PhotoSize? {
var _1: String?
_1 = parseString(reader)
var _2: Buffer?
_2 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.PhotoSize.photoStrippedSize(type: _1!, bytes: _2!)
}
else {
return nil
}
}
}
enum FileLocation: TypeConstructorDescription {
case fileLocationToBeDeprecated(volumeId: Int64, localId: Int32)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .fileLocationToBeDeprecated(let volumeId, let localId):
if boxed {
buffer.appendInt32(-1132476723)
}
serializeInt64(volumeId, buffer: buffer, boxed: false)
serializeInt32(localId, buffer: buffer, boxed: false)
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .fileLocationToBeDeprecated(let volumeId, let localId):
return ("fileLocationToBeDeprecated", [("volumeId", volumeId), ("localId", localId)])
}
}
static func parse_fileLocationToBeDeprecated(_ reader: BufferReader) -> FileLocation? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int32?
_2 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.FileLocation.fileLocationToBeDeprecated(volumeId: _1!, localId: _2!)
}
else {
return nil
}
}
}
enum DocumentAttribute: TypeConstructorDescription {
case documentAttributeImageSize(w: Int32, h: Int32)
case documentAttributeAnimated
case documentAttributeSticker(flags: Int32, alt: String, stickerset: Api.InputStickerSet, maskCoords: Api.MaskCoords?)
case documentAttributeVideo(flags: Int32, duration: Int32, w: Int32, h: Int32)
case documentAttributeAudio(flags: Int32, duration: Int32, title: String?, performer: String?, waveform: Buffer?)
case documentAttributeFilename(fileName: String)
case documentAttributeHasStickers
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .documentAttributeImageSize(let w, let h):
if boxed {
buffer.appendInt32(1815593308)
}
serializeInt32(w, buffer: buffer, boxed: false)
serializeInt32(h, buffer: buffer, boxed: false)
break
case .documentAttributeAnimated:
if boxed {
buffer.appendInt32(297109817)
}
break
case .documentAttributeSticker(let flags, let alt, let stickerset, let maskCoords):
if boxed {
buffer.appendInt32(1662637586)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(alt, buffer: buffer, boxed: false)
stickerset.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {maskCoords!.serialize(buffer, true)}
break
case .documentAttributeVideo(let flags, let duration, let w, let h):
if boxed {
buffer.appendInt32(250621158)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(duration, buffer: buffer, boxed: false)
serializeInt32(w, buffer: buffer, boxed: false)
serializeInt32(h, buffer: buffer, boxed: false)
break
case .documentAttributeAudio(let flags, let duration, let title, let performer, let waveform):
if boxed {
buffer.appendInt32(-1739392570)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(duration, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(performer!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {serializeBytes(waveform!, buffer: buffer, boxed: false)}
break
case .documentAttributeFilename(let fileName):
if boxed {
buffer.appendInt32(358154344)
}
serializeString(fileName, buffer: buffer, boxed: false)
break
case .documentAttributeHasStickers:
if boxed {
buffer.appendInt32(-1744710921)
}
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .documentAttributeImageSize(let w, let h):
return ("documentAttributeImageSize", [("w", w), ("h", h)])
case .documentAttributeAnimated:
return ("documentAttributeAnimated", [])
case .documentAttributeSticker(let flags, let alt, let stickerset, let maskCoords):
return ("documentAttributeSticker", [("flags", flags), ("alt", alt), ("stickerset", stickerset), ("maskCoords", maskCoords)])
case .documentAttributeVideo(let flags, let duration, let w, let h):
return ("documentAttributeVideo", [("flags", flags), ("duration", duration), ("w", w), ("h", h)])
case .documentAttributeAudio(let flags, let duration, let title, let performer, let waveform):
return ("documentAttributeAudio", [("flags", flags), ("duration", duration), ("title", title), ("performer", performer), ("waveform", waveform)])
case .documentAttributeFilename(let fileName):
return ("documentAttributeFilename", [("fileName", fileName)])
case .documentAttributeHasStickers:
return ("documentAttributeHasStickers", [])
}
}
static func parse_documentAttributeImageSize(_ reader: BufferReader) -> DocumentAttribute? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.DocumentAttribute.documentAttributeImageSize(w: _1!, h: _2!)
}
else {
return nil
}
}
static func parse_documentAttributeAnimated(_ reader: BufferReader) -> DocumentAttribute? {
return Api.DocumentAttribute.documentAttributeAnimated
}
static func parse_documentAttributeSticker(_ reader: BufferReader) -> DocumentAttribute? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Api.InputStickerSet?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.InputStickerSet
}
var _4: Api.MaskCoords?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.MaskCoords
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.DocumentAttribute.documentAttributeSticker(flags: _1!, alt: _2!, stickerset: _3!, maskCoords: _4)
}
else {
return nil
}
}
static func parse_documentAttributeVideo(_ reader: BufferReader) -> DocumentAttribute? {
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.DocumentAttribute.documentAttributeVideo(flags: _1!, duration: _2!, w: _3!, h: _4!)
}
else {
return nil
}
}
static func parse_documentAttributeAudio(_ reader: BufferReader) -> DocumentAttribute? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: String?
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) }
var _4: String?
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
var _5: Buffer?
if Int(_1!) & Int(1 << 2) != 0 {_5 = parseBytes(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.DocumentAttribute.documentAttributeAudio(flags: _1!, duration: _2!, title: _3, performer: _4, waveform: _5)
}
else {
return nil
}
}
static func parse_documentAttributeFilename(_ reader: BufferReader) -> DocumentAttribute? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.DocumentAttribute.documentAttributeFilename(fileName: _1!)
}
else {
return nil
}
}
static func parse_documentAttributeHasStickers(_ reader: BufferReader) -> DocumentAttribute? {
return Api.DocumentAttribute.documentAttributeHasStickers
}
}
enum InputStickerSet: TypeConstructorDescription {
case inputStickerSetEmpty
case inputStickerSetID(id: Int64, accessHash: Int64)
case inputStickerSetShortName(shortName: String)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputStickerSetEmpty:
if boxed {
buffer.appendInt32(-4838507)
}
break
case .inputStickerSetID(let id, let accessHash):
if boxed {
buffer.appendInt32(-1645763991)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
break
case .inputStickerSetShortName(let shortName):
if boxed {
buffer.appendInt32(-2044933984)
}
serializeString(shortName, buffer: buffer, boxed: false)
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputStickerSetEmpty:
return ("inputStickerSetEmpty", [])
case .inputStickerSetID(let id, let accessHash):
return ("inputStickerSetID", [("id", id), ("accessHash", accessHash)])
case .inputStickerSetShortName(let shortName):
return ("inputStickerSetShortName", [("shortName", shortName)])
}
}
static func parse_inputStickerSetEmpty(_ reader: BufferReader) -> InputStickerSet? {
return Api.InputStickerSet.inputStickerSetEmpty
}
static func parse_inputStickerSetID(_ reader: BufferReader) -> InputStickerSet? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int64?
_2 = reader.readInt64()
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputStickerSet.inputStickerSetID(id: _1!, accessHash: _2!)
}
else {
return nil
}
}
static func parse_inputStickerSetShortName(_ reader: BufferReader) -> InputStickerSet? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.InputStickerSet.inputStickerSetShortName(shortName: _1!)
}
else {
return nil
}
}
}
enum InputFileLocation: TypeConstructorDescription {
case inputPhotoFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String)
case inputDocumentFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize):
if boxed {
buffer.appendInt32(1075322878)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeBytes(fileReference, buffer: buffer, boxed: false)
serializeString(thumbSize, buffer: buffer, boxed: false)
break
case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize):
if boxed {
buffer.appendInt32(-1160743548)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeBytes(fileReference, buffer: buffer, boxed: false)
serializeString(thumbSize, buffer: buffer, boxed: false)
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize):
return ("inputPhotoFileLocation", [("id", id), ("accessHash", accessHash), ("fileReference", fileReference), ("thumbSize", thumbSize)])
case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize):
return ("inputDocumentFileLocation", [("id", id), ("accessHash", accessHash), ("fileReference", fileReference), ("thumbSize", thumbSize)])
}
}
static func parse_inputPhotoFileLocation(_ reader: BufferReader) -> InputFileLocation? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int64?
_2 = reader.readInt64()
var _3: Buffer?
_3 = parseBytes(reader)
var _4: String?
_4 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputFileLocation.inputPhotoFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!)
}
else {
return nil
}
}
static func parse_inputDocumentFileLocation(_ reader: BufferReader) -> InputFileLocation? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int64?
_2 = reader.readInt64()
var _3: Buffer?
_3 = parseBytes(reader)
var _4: String?
_4 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputFileLocation.inputDocumentFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!)
}
else {
return nil
}
}
}
enum MaskCoords: TypeConstructorDescription {
case maskCoords(n: Int32, x: Double, y: Double, zoom: Double)
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .maskCoords(let n, let x, let y, let zoom):
if boxed {
buffer.appendInt32(-1361650766)
}
serializeInt32(n, buffer: buffer, boxed: false)
serializeDouble(x, buffer: buffer, boxed: false)
serializeDouble(y, buffer: buffer, boxed: false)
serializeDouble(zoom, buffer: buffer, boxed: false)
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .maskCoords(let n, let x, let y, let zoom):
return ("maskCoords", [("n", n), ("x", x), ("y", y), ("zoom", zoom)])
}
}
static func parse_maskCoords(_ reader: BufferReader) -> MaskCoords? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Double?
_2 = reader.readDouble()
var _3: Double?
_3 = reader.readDouble()
var _4: Double?
_4 = reader.readDouble()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.MaskCoords.maskCoords(n: _1!, x: _2!, y: _3!, zoom: _4!)
}
else {
return nil
}
}
}
enum Document: TypeConstructorDescription {
case document(flags: Int32, id: Int64, accessHash: Int64, fileReference: Buffer, date: Int32, mimeType: String, size: Int32, thumbs: [Api.PhotoSize]?, dcId: Int32, attributes: [Api.DocumentAttribute])
func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .document(let flags, let id, let accessHash, let fileReference, let date, let mimeType, let size, let thumbs, let dcId, let attributes):
if boxed {
buffer.appendInt32(-1683841855)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeBytes(fileReference, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeString(mimeType, buffer: buffer, boxed: false)
serializeInt32(size, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(thumbs!.count))
for item in thumbs! {
item.serialize(buffer, true)
}}
serializeInt32(dcId, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(attributes.count))
for item in attributes {
item.serialize(buffer, true)
}
break
}
}
func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .document(let flags, let id, let accessHash, let fileReference, let date, let mimeType, let size, let thumbs, let dcId, let attributes):
return ("document", [("flags", flags), ("id", id), ("accessHash", accessHash), ("fileReference", fileReference), ("date", date), ("mimeType", mimeType), ("size", size), ("thumbs", thumbs), ("dcId", dcId), ("attributes", attributes)])
}
}
static func parse_document(_ reader: BufferReader) -> Document? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int64?
_3 = reader.readInt64()
var _4: Buffer?
_4 = parseBytes(reader)
var _5: Int32?
_5 = reader.readInt32()
var _6: String?
_6 = parseString(reader)
var _7: Int32?
_7 = reader.readInt32()
var _8: [Api.PhotoSize]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PhotoSize.self)
} }
var _9: Int32?
_9 = reader.readInt32()
var _10: [Api.DocumentAttribute]?
if let _ = reader.readInt32() {
_10 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = (Int(_1!) & Int(1 << 0) == 0) || _8 != nil
let _c9 = _9 != nil
let _c10 = _10 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
return Api.Document.document(flags: _1!, id: _2!, accessHash: _3!, fileReference: _4!, date: _5!, mimeType: _6!, size: _7!, thumbs: _8, dcId: _9!, attributes: _10!)
}
else {
return nil
}
}
}
}
extension Api {
struct functions {
}
}

View file

@ -13,264 +13,6 @@ struct ImageResource {
}
}
private final class Buffer {
var data: UnsafeMutableRawPointer?
var _size: UInt = 0
private var capacity: UInt = 0
private let freeWhenDone: Bool
var size: Int {
return Int(self._size)
}
deinit {
if self.freeWhenDone {
free(self.data)
}
}
init(memory: UnsafeMutableRawPointer?, size: Int, capacity: Int, freeWhenDone: Bool) {
self.data = memory
self._size = UInt(size)
self.capacity = UInt(capacity)
self.freeWhenDone = freeWhenDone
}
init() {
self.data = nil
self._size = 0
self.capacity = 0
self.freeWhenDone = true
}
convenience init(data: Data?) {
self.init()
if let data = data {
data.withUnsafeBytes { bytes in
self.appendBytes(bytes, length: UInt(data.count))
}
}
}
func makeData() -> Data {
return self.withUnsafeMutablePointer { pointer, size -> Data in
if let pointer = pointer {
return Data(bytes: pointer.assumingMemoryBound(to: UInt8.self), count: Int(size))
} else {
return Data()
}
}
}
var description: String {
get {
var string = ""
if let data = self.data {
var i: UInt = 0
let bytes = data.assumingMemoryBound(to: UInt8.self)
while i < _size && i < 8 {
string += String(format: "%02x", Int(bytes.advanced(by: Int(i)).pointee))
i += 1
}
if i < _size {
string += "...\(_size)b"
}
} else {
string += "<null>"
}
return string
}
}
func appendBytes(_ bytes: UnsafeRawPointer, length: UInt) {
if self.capacity < self._size + length {
self.capacity = self._size + length + 128
if self.data == nil {
self.data = malloc(Int(self.capacity))!
}
else {
self.data = realloc(self.data, Int(self.capacity))!
}
}
memcpy(self.data?.advanced(by: Int(self._size)), bytes, Int(length))
self._size += length
}
func appendBuffer(_ buffer: Buffer) {
if self.capacity < self._size + buffer._size {
self.capacity = self._size + buffer._size + 128
if self.data == nil {
self.data = malloc(Int(self.capacity))!
}
else {
self.data = realloc(self.data, Int(self.capacity))!
}
}
memcpy(self.data?.advanced(by: Int(self._size)), buffer.data, Int(buffer._size))
}
func appendInt32(_ value: Int32) {
var v = value
self.appendBytes(&v, length: 4)
}
func appendInt64(_ value: Int64) {
var v = value
self.appendBytes(&v, length: 8)
}
func appendDouble(_ value: Double) {
var v = value
self.appendBytes(&v, length: 8)
}
func withUnsafeMutablePointer<R>(_ f: (UnsafeMutableRawPointer?, UInt) -> R) -> R {
return f(self.data, self._size)
}
}
private class BufferReader {
private let buffer: Buffer
private(set) var offset: UInt = 0
init(_ buffer: Buffer) {
self.buffer = buffer
}
func reset() {
self.offset = 0
}
func skip(_ count: Int) {
self.offset = min(self.buffer._size, self.offset + UInt(count))
}
func readInt32() -> Int32? {
if self.offset + 4 <= self.buffer._size {
let value: Int32 = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Int32.self).pointee
self.offset += 4
return value
}
return nil
}
func readInt64() -> Int64? {
if self.offset + 8 <= self.buffer._size {
let value: Int64 = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Int64.self).pointee
self.offset += 8
return value
}
return nil
}
func readDouble() -> Double? {
if self.offset + 8 <= self.buffer._size {
let value: Double = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Double.self).pointee
self.offset += 8
return value
}
return nil
}
func readBytesAsInt32(_ count: Int) -> Int32? {
if count == 0 {
return 0
}
else if count > 0 && count <= 4 || self.offset + UInt(count) <= self.buffer._size {
var value: Int32 = 0
memcpy(&value, self.buffer.data?.advanced(by: Int(self.offset)), count)
self.offset += UInt(count)
return value
}
return nil
}
func readBuffer(_ count: Int) -> Buffer? {
if count >= 0 && self.offset + UInt(count) <= self.buffer._size {
let buffer = Buffer()
buffer.appendBytes((self.buffer.data?.advanced(by: Int(self.offset)))!, length: UInt(count))
self.offset += UInt(count)
return buffer
}
return nil
}
}
private func serializeBytes(_ value: Buffer, buffer: Buffer, boxed: Bool) {
if boxed {
buffer.appendInt32(-1255641564)
}
var length: Int32 = Int32(value.size)
var padding: Int32 = 0
if (length >= 254)
{
var tmp: UInt8 = 254
buffer.appendBytes(&tmp, length: 1)
buffer.appendBytes(&length, length: 3)
padding = (((length % 4) == 0 ? length : (length + 4 - (length % 4)))) - length;
}
else
{
buffer.appendBytes(&length, length: 1)
let e1 = (((length + 1) % 4) == 0 ? (length + 1) : ((length + 1) + 4 - ((length + 1) % 4)))
padding = (e1) - (length + 1)
}
if value.size != 0 {
buffer.appendBytes(value.data!, length: UInt(length))
}
var i: Int32 = 0
var tmp: UInt8 = 0
while i < padding {
buffer.appendBytes(&tmp, length: 1)
i += 1
}
}
private func roundUp(_ numToRound: Int, multiple: Int) -> Int {
if multiple == 0 {
return numToRound
}
let remainder = numToRound % multiple
if remainder == 0 {
return numToRound
}
return numToRound + multiple - remainder
}
private func parseBytes(_ reader: BufferReader) -> Buffer? {
if let tmp = reader.readBytesAsInt32(1) {
var paddingBytes: Int = 0
var length: Int = 0
if tmp == 254 {
if let len = reader.readBytesAsInt32(3) {
length = Int(len)
paddingBytes = roundUp(length, multiple: 4) - length
}
else {
return nil
}
}
else {
length = Int(tmp)
paddingBytes = roundUp(length + 1, multiple: 4) - (length + 1)
}
let buffer = reader.readBuffer(length)
reader.skip(paddingBytes)
return buffer
}
return nil
}
private class Keychain: NSObject, MTKeychain {
var dict: [String: Data] = [:]
@ -304,7 +46,7 @@ private final class ParsedFile: NSObject {
}
}
func fetchImageWithAccount(proxyConnection: AccountProxyConnection?, account: StoredAccountInfo, resource: ImageResource, completion: @escaping (Data?) -> Void) -> () -> Void {
func fetchImageWithAccount(proxyConnection: AccountProxyConnection?, account: StoredAccountInfo, inputFileLocation: Api.InputFileLocation, datacenterId: Int32, completion: @escaping (Data?) -> Void) -> () -> Void {
MTLogSetEnabled(true)
MTLogSetLoggingFunction({ str, args in
//let string = NSString(format: str! as NSString, args!)
@ -367,7 +109,7 @@ func fetchImageWithAccount(proxyConnection: AccountProxyConnection?, account: St
context.updateAuthInfoForDatacenter(withId: Int(id), authInfo: MTDatacenterAuthInfo(authKey: info.masterKey.data, authKeyId: info.masterKey.id, saltSet: [], authKeyAttributes: [:], mainTempAuthKey: nil, mediaTempAuthKey: nil))
}
let mtProto = MTProto(context: context, datacenterId: resource.datacenterId, usageCalculationInfo: nil)!
let mtProto = MTProto(context: context, datacenterId: Int(datacenterId), usageCalculationInfo: nil)!
mtProto.useTempAuthKeys = context.useTempAuthKeys
mtProto.checkForProxyConnectionIssues = false
@ -378,18 +120,12 @@ func fetchImageWithAccount(proxyConnection: AccountProxyConnection?, account: St
let buffer = Buffer()
buffer.appendInt32(-475607115) //upload.getFile
buffer.appendInt32(-539317279) //InputFileLocation.inputFileLocation
buffer.appendInt64(resource.volumeId)
buffer.appendInt32(resource.localId)
buffer.appendInt64(resource.secret)
serializeBytes(Buffer(data: resource.fileReference), buffer: buffer, boxed: false)
Api.serializeObject(inputFileLocation, buffer: buffer, boxed: true)
buffer.appendInt32(0)
buffer.appendInt32(32 * 1024)
request.setPayload(buffer.makeData(), metadata: "getFile", responseParser: { response in
request.setPayload(buffer.makeData(), metadata: "getFile", shortMetadata: "getFile", responseParser: { response in
let reader = BufferReader(Buffer(data: response))
guard let signature = reader.readInt32() else {
return ParsedFile(data: nil)

View file

@ -1,5 +1,6 @@
import Foundation
import UserNotifications
import MtProtoKitDynamic
private var sharedLogger: Logger?
@ -146,92 +147,85 @@ private final class Logger {
}
}
private func dataWithHexString(_ string: String) -> Data {
var hex = string
if hex.count % 2 != 0 {
return Data()
private func parseBase64(string: String) -> Data? {
var string = string
string = string.replacingOccurrences(of: "-", with: "+")
string = string.replacingOccurrences(of: "_", with: "/")
while string.count % 4 != 0 {
string.append("=")
}
var data = Data()
while hex.count > 0 {
let subIndex = hex.index(hex.startIndex, offsetBy: 2)
let c = String(hex[..<subIndex])
hex = String(hex[subIndex...])
var ch: UInt32 = 0
if !Scanner(string: c).scanHexInt32(&ch) {
return Data()
}
var char = UInt8(ch)
data.append(&char, count: 1)
}
return data
return Data(base64Encoded: string)
}
private func parseInt64(_ value: Any?) -> Int64? {
if let value = value as? String {
return Int64(value)
} else if let value = value as? Int64 {
return value
} else {
return nil
}
enum ParsedMediaAttachment {
case document(Api.Document)
case photo(Api.Photo)
}
private func parseInt32(_ value: Any?) -> Int32? {
if let value = value as? String {
return Int32(value)
} else if let value = value as? Int32 {
return value
} else {
private func parseAttachment(data: Data) -> (ParsedMediaAttachment, Data)? {
let reader = BufferReader(Buffer(data: data))
guard let initialSignature = reader.readInt32() else {
return nil
}
}
private func parseImageLocation(_ dict: [AnyHashable: Any]) -> (size: (width: Int32, height: Int32)?, resource: ImageResource)? {
guard let datacenterId = parseInt32(dict["dc_id"]) else {
return nil
}
guard let volumeId = parseInt64(dict["volume_id"]) else {
return nil
}
guard let localId = parseInt32(dict["local_id"]) else {
return nil
}
guard let secret = parseInt64(dict["secret"]) else {
return nil
}
var fileReference: Data?
if let fileReferenceString = dict["file_reference"] as? String {
fileReference = Data(base64Encoded: fileReferenceString)
}
var size: (Int32, Int32)?
if let width = parseInt32(dict["w"]), let height = parseInt32(dict["h"]) {
size = (width, height)
}
return (size, ImageResource(datacenterId: Int(datacenterId), volumeId: volumeId, localId: localId, secret: secret, fileReference: fileReference))
}
private func hexString(_ data: Data) -> String {
let hexString = NSMutableString()
data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in
for i in 0 ..< data.count {
hexString.appendFormat("%02x", UInt(bytes.advanced(by: i).pointee))
}
}
return hexString as String
let buffer: Buffer
if initialSignature == 0x3072cfa1 {
guard let bytes = parseBytes(reader) else {
return nil
}
guard let decompressedData = MTGzip.decompress(bytes.makeData()) else {
return nil
}
buffer = Buffer(data: decompressedData)
} else {
buffer = Buffer(data: data)
}
if let result = Api.parse(buffer) {
if let photo = result as? Api.Photo {
return (.photo(photo), buffer.makeData())
} else if let document = result as? Api.Document {
return (.document(document), buffer.makeData())
} else {
return nil
}
} else {
return nil
}
}
private func serializeImageLocation(_ resource: ImageResource) -> [AnyHashable: Any] {
var result: [AnyHashable: Any] = [:]
result["datacenterId"] = Int32(resource.datacenterId)
result["volumeId"] = resource.volumeId
result["localId"] = resource.localId
result["secret"] = resource.secret
if let fileReference = resource.fileReference {
result["fileReference"] = hexString(fileReference)
private func photoSizeDimensions(_ size: Api.PhotoSize) -> CGSize? {
switch size {
case let .photoSize(_, _, w, h, _):
return CGSize(width: CGFloat(w), height: CGFloat(h))
case let .photoCachedSize(_, _, w, h, _):
return CGSize(width: CGFloat(w), height: CGFloat(h))
default:
return nil
}
}
private func photoDimensions(_ photo: Api.Photo) -> CGSize? {
switch photo {
case let .photo(_, _, _, _, _, sizes, _):
for size in sizes.reversed() {
if let dimensions = photoSizeDimensions(size) {
return dimensions
}
}
return nil
case .photoEmpty:
return nil
}
}
private func photoSizes(_ photo: Api.Photo) -> [Api.PhotoSize] {
switch photo {
case let .photo(_, _, _, _, _, sizes, _):
return sizes
case .photoEmpty:
return []
}
return result
}
class NotificationService: UNNotificationServiceExtension {
@ -281,13 +275,8 @@ class NotificationService: UNNotificationServiceExtension {
self.bestAttemptContent = request.content.mutableCopy() as? UNMutableNotificationContent
var encryptedData: Data?
if var encryptedPayload = request.content.userInfo["p"] as? String {
encryptedPayload = encryptedPayload.replacingOccurrences(of: "-", with: "+")
encryptedPayload = encryptedPayload.replacingOccurrences(of: "_", with: "/")
while encryptedPayload.count % 4 != 0 {
encryptedPayload.append("=")
}
encryptedData = Data(base64Encoded: encryptedPayload)
if let encryptedPayload = request.content.userInfo["p"] as? String {
encryptedData = parseBase64(string: encryptedPayload)
}
Logger.shared.log("NotificationService", "received notification \(request), parsed encryptedData \(String(describing: encryptedData))")
@ -323,11 +312,13 @@ class NotificationService: UNNotificationServiceExtension {
}
}
var thumbnailImage: ImageResource?
var fullSizeImage: (size: (width: Int32, height: Int32)?, resource: ImageResource)?
if let thumbLoc = dict["media_loc"] as? [AnyHashable: Any] {
thumbnailImage = (thumbLoc["thumb"] as? [AnyHashable: Any]).flatMap(parseImageLocation)?.resource
fullSizeImage = (thumbLoc["full"] as? [AnyHashable: Any]).flatMap(parseImageLocation)
var attachment: ParsedMediaAttachment?
var attachmentData: Data?
if let attachmentDataString = dict["attachb64"] as? String, let attachmentDataValue = parseBase64(string: attachmentDataString) {
if let value = parseAttachment(data: attachmentDataValue) {
attachment = value.0
attachmentData = value.1
}
}
let imagesPath = NSTemporaryDirectory() + "aps-data"
@ -337,9 +328,57 @@ class NotificationService: UNNotificationServiceExtension {
let mediaBoxPath = accountBasePath + "/postbox/media"
let tempImagePath = thumbnailImage.flatMap({ imagesPath + "/\($0.resourceId).jpg" })
let mediaBoxThumbnailImagePath = thumbnailImage.flatMap({ mediaBoxPath + "/\($0.resourceId)" })
let mediaBoxFullSizeImagePath = fullSizeImage.flatMap({ mediaBoxPath + "/\($0.resource.resourceId)" })
var tempImagePath: String?
var mediaBoxThumbnailImagePath: String?
var inputFileLocation: (Int32, Api.InputFileLocation)?
var fetchResourceId: String?
if let attachment = attachment {
switch attachment {
case let .photo(photo):
switch photo {
case let .photo(_, id, accessHash, fileReference, _, sizes, dcId):
loop: for size in sizes {
switch size {
case let .photoSize(type, _, _, _, _):
if type == "m" {
inputFileLocation = (dcId, .inputPhotoFileLocation(id: id, accessHash: accessHash, fileReference: fileReference, thumbSize: type))
fetchResourceId = "telegram-cloud-photo-size-\(dcId)-\(id)-\(type)"
break loop
}
default:
break
}
}
case .photoEmpty:
break
}
case let .document(document):
switch document {
case let .document(_, id, accessHash, fileReference, _, _, _, thumbs, dcId, _):
if let thumbs = thumbs {
loop: for size in thumbs {
switch size {
case let .photoSize(type, _, _, _, _):
if type == "m" {
inputFileLocation = (dcId, .inputDocumentFileLocation(id: id, accessHash: accessHash, fileReference: fileReference, thumbSize: type))
fetchResourceId = "telegram-cloud-photo-size-\(dcId)-\(id)-\(type)"
break loop
}
default:
break
}
}
}
}
}
}
if let fetchResourceId = fetchResourceId {
tempImagePath = imagesPath + "/\(fetchResourceId).jpg"
mediaBoxThumbnailImagePath = mediaBoxPath + "/\(fetchResourceId).jpg"
}
if let aps = dict["aps"] as? [AnyHashable: Any] {
if let alert = aps["alert"] as? String {
@ -365,31 +404,12 @@ class NotificationService: UNNotificationServiceExtension {
}
if let category = aps["category"] as? String {
self.bestAttemptContent?.categoryIdentifier = category
if let peerId = peerId, let messageId = messageId, let thumbnailResource = thumbnailImage, let (maybeSize, resource) = fullSizeImage, let size = maybeSize {
if let peerId = peerId, let messageId = messageId, let _ = attachment, let attachmentData = attachmentData {
userInfo["peerId"] = peerId.toInt64()
userInfo["messageId.namespace"] = 0 as Int32
userInfo["messageId.id"] = messageId
var imageInfo: [String: Any] = [:]
imageInfo["width"] = Int(size.width)
imageInfo["height"] = Int(size.height)
var thumbnail: [String: Any] = [:]
if let mediaBoxThumbnailImagePath = mediaBoxThumbnailImagePath {
thumbnail["path"] = mediaBoxThumbnailImagePath
}
thumbnail["fileLocation"] = serializeImageLocation(thumbnailResource)
var fullSize: [String: Any] = [:]
if let mediaBoxFullSizeImagePath = mediaBoxFullSizeImagePath {
fullSize["path"] = mediaBoxFullSizeImagePath
}
fullSize["fileLocation"] = serializeImageLocation(resource)
imageInfo["thumbnail"] = thumbnail
imageInfo["fullSize"] = fullSize
userInfo["mediaInfo"] = ["image": imageInfo]
userInfo["media"] = attachmentData.base64EncodedString()
if category == "r" {
self.bestAttemptContent?.categoryIdentifier = "withReplyMedia"
@ -403,8 +423,8 @@ class NotificationService: UNNotificationServiceExtension {
self.bestAttemptContent?.userInfo = userInfo
self.cancelFetch?()
if let mediaBoxThumbnailImagePath = mediaBoxThumbnailImagePath, let tempImagePath = tempImagePath, let thumbnailImage = thumbnailImage {
self.cancelFetch = fetchImageWithAccount(proxyConnection: accountInfos.proxy, account: account, resource: thumbnailImage, completion: { [weak self] data in
if let mediaBoxThumbnailImagePath = mediaBoxThumbnailImagePath, let tempImagePath = tempImagePath, let (datacenterId, inputFileLocation) = inputFileLocation {
self.cancelFetch = fetchImageWithAccount(proxyConnection: accountInfos.proxy, account: account, inputFileLocation: inputFileLocation, datacenterId: datacenterId, completion: { [weak self] data in
DispatchQueue.main.async {
guard let strongSelf = self else {
return

View file

@ -0,0 +1,310 @@
import Foundation
class Buffer: CustomStringConvertible {
var data: UnsafeMutableRawPointer?
var _size: UInt = 0
private var capacity: UInt = 0
private let freeWhenDone: Bool
var size: Int {
return Int(self._size)
}
deinit {
if self.freeWhenDone {
free(self.data)
}
}
init(memory: UnsafeMutableRawPointer?, size: Int, capacity: Int, freeWhenDone: Bool) {
self.data = memory
self._size = UInt(size)
self.capacity = UInt(capacity)
self.freeWhenDone = freeWhenDone
}
init() {
self.data = nil
self._size = 0
self.capacity = 0
self.freeWhenDone = true
}
convenience init(data: Data?) {
self.init()
if let data = data {
data.withUnsafeBytes { bytes in
self.appendBytes(bytes, length: UInt(data.count))
}
}
}
func makeData() -> Data {
return self.withUnsafeMutablePointer { pointer, size -> Data in
if let pointer = pointer {
return Data(bytes: pointer.assumingMemoryBound(to: UInt8.self), count: Int(size))
} else {
return Data()
}
}
}
var description: String {
get {
var string = ""
if let data = self.data {
var i: UInt = 0
let bytes = data.assumingMemoryBound(to: UInt8.self)
while i < _size && i < 8 {
string += String(format: "%02x", Int(bytes.advanced(by: Int(i)).pointee))
i += 1
}
if i < _size {
string += "...\(_size)b"
}
} else {
string += "<null>"
}
return string
}
}
func appendBytes(_ bytes: UnsafeRawPointer, length: UInt) {
if self.capacity < self._size + length {
self.capacity = self._size + length + 128
if self.data == nil {
self.data = malloc(Int(self.capacity))!
}
else {
self.data = realloc(self.data, Int(self.capacity))!
}
}
memcpy(self.data?.advanced(by: Int(self._size)), bytes, Int(length))
self._size += length
}
func appendBuffer(_ buffer: Buffer) {
if self.capacity < self._size + buffer._size {
self.capacity = self._size + buffer._size + 128
if self.data == nil {
self.data = malloc(Int(self.capacity))!
}
else {
self.data = realloc(self.data, Int(self.capacity))!
}
}
memcpy(self.data?.advanced(by: Int(self._size)), buffer.data, Int(buffer._size))
}
func appendInt32(_ value: Int32) {
var v = value
self.appendBytes(&v, length: 4)
}
func appendInt64(_ value: Int64) {
var v = value
self.appendBytes(&v, length: 8)
}
func appendDouble(_ value: Double) {
var v = value
self.appendBytes(&v, length: 8)
}
func withUnsafeMutablePointer<R>(_ f: (UnsafeMutableRawPointer?, UInt) -> R) -> R {
return f(self.data, self._size)
}
}
class BufferReader {
private let buffer: Buffer
private(set) var offset: UInt = 0
init(_ buffer: Buffer) {
self.buffer = buffer
}
func reset() {
self.offset = 0
}
func skip(_ count: Int) {
self.offset = min(self.buffer._size, self.offset + UInt(count))
}
func readInt32() -> Int32? {
if self.offset + 4 <= self.buffer._size {
let value: Int32 = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Int32.self).pointee
self.offset += 4
return value
}
return nil
}
func readInt64() -> Int64? {
if self.offset + 8 <= self.buffer._size {
let value: Int64 = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Int64.self).pointee
self.offset += 8
return value
}
return nil
}
func readDouble() -> Double? {
if self.offset + 8 <= self.buffer._size {
let value: Double = buffer.data!.advanced(by: Int(self.offset)).assumingMemoryBound(to: Double.self).pointee
self.offset += 8
return value
}
return nil
}
func readBytesAsInt32(_ count: Int) -> Int32? {
if count == 0 {
return 0
}
else if count > 0 && count <= 4 || self.offset + UInt(count) <= self.buffer._size {
var value: Int32 = 0
memcpy(&value, self.buffer.data?.advanced(by: Int(self.offset)), count)
self.offset += UInt(count)
return value
}
return nil
}
func readBuffer(_ count: Int) -> Buffer? {
if count >= 0 && self.offset + UInt(count) <= self.buffer._size {
let buffer = Buffer()
buffer.appendBytes((self.buffer.data?.advanced(by: Int(self.offset)))!, length: UInt(count))
self.offset += UInt(count)
return buffer
}
return nil
}
func withReadBufferNoCopy<T>(_ count: Int, _ f: (Buffer) -> T) -> T? {
if count >= 0 && self.offset + UInt(count) <= self.buffer._size {
return f(Buffer(memory: self.buffer.data!.advanced(by: Int(self.offset)), size: count, capacity: count, freeWhenDone: false))
}
return nil
}
}
private func roundUp(_ numToRound: Int, multiple: Int) -> Int {
if multiple == 0 {
return numToRound
}
let remainder = numToRound % multiple
if remainder == 0 {
return numToRound
}
return numToRound + multiple - remainder
}
func parseBytes(_ reader: BufferReader) -> Buffer? {
if let tmp = reader.readBytesAsInt32(1) {
var paddingBytes: Int = 0
var length: Int = 0
if tmp == 254 {
if let len = reader.readBytesAsInt32(3) {
length = Int(len)
paddingBytes = roundUp(length, multiple: 4) - length
}
else {
return nil
}
}
else {
length = Int(tmp)
paddingBytes = roundUp(length + 1, multiple: 4) - (length + 1)
}
let buffer = reader.readBuffer(length)
reader.skip(paddingBytes)
return buffer
}
return nil
}
func parseString(_ reader: BufferReader) -> String? {
if let buffer = parseBytes(reader) {
return (NSString(data: buffer.makeData() as Data, encoding: String.Encoding.utf8.rawValue) as? String) ?? ""
}
return nil
}
protocol TypeConstructorDescription {
func descriptionFields() -> (String, [(String, Any)])
}
func serializeInt32(_ value: Int32, buffer: Buffer, boxed: Bool) {
if boxed {
buffer.appendInt32(-1471112230)
}
buffer.appendInt32(value)
}
func serializeInt64(_ value: Int64, buffer: Buffer, boxed: Bool) {
if boxed {
buffer.appendInt32(570911930)
}
buffer.appendInt64(value)
}
func serializeDouble(_ value: Double, buffer: Buffer, boxed: Bool) {
if boxed {
buffer.appendInt32(571523412)
}
buffer.appendDouble(value)
}
func serializeString(_ value: String, buffer: Buffer, boxed: Bool) {
let stringBuffer = Buffer()
let data = value.data(using: .utf8, allowLossyConversion: true) ?? Data()
data.withUnsafeBytes { bytes in
stringBuffer.appendBytes(bytes, length: UInt(data.count))
}
serializeBytes(stringBuffer, buffer: buffer, boxed: boxed)
}
func serializeBytes(_ value: Buffer, buffer: Buffer, boxed: Bool) {
if boxed {
buffer.appendInt32(-1255641564)
}
var length: Int32 = Int32(value.size)
var padding: Int32 = 0
if (length >= 254)
{
var tmp: UInt8 = 254
buffer.appendBytes(&tmp, length: 1)
buffer.appendBytes(&length, length: 3)
padding = (((length % 4) == 0 ? length : (length + 4 - (length % 4)))) - length;
}
else
{
buffer.appendBytes(&length, length: 1)
let e1 = (((length + 1) % 4) == 0 ? (length + 1) : ((length + 1) + 4 - ((length + 1) % 4)))
padding = (e1) - (length + 1)
}
if value.size != 0 {
buffer.appendBytes(value.data!, length: UInt(length))
}
var i: Int32 = 0
var tmp: UInt8 = 0
while i < padding {
buffer.appendBytes(&tmp, length: 1)
i += 1
}
}

View file

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

View file

@ -223,6 +223,8 @@
D00859B81B28189D00EAF753 /* Telegram_iOSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00859B71B28189D00EAF753 /* Telegram_iOSTests.swift */; };
D00ED75A1FE94630001F38BD /* AppIntentVocabulary.plist in Resources */ = {isa = PBXBuildFile; fileRef = D00ED7581FE94630001F38BD /* AppIntentVocabulary.plist */; };
D00ED75D1FE95287001F38BD /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D00ED75B1FE95287001F38BD /* InfoPlist.strings */; };
D015E011225CCEB300CB9E8A /* ReadBuffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015E010225CCEB300CB9E8A /* ReadBuffer.swift */; };
D015E01F225CDF5100CB9E8A /* Api0.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015E01E225CDF5000CB9E8A /* Api0.swift */; };
D01A47551F4DBED700383CC1 /* HockeySDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D01A47541F4DBED700383CC1 /* HockeySDK.framework */; };
D021D4D9219CAEDD0064BEBA /* Config-Fork.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = D021D4D8219CAEDD0064BEBA /* Config-Fork.xcconfig */; };
D02CF5FD215D9ABF00E0F56A /* UserNotifications.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0AA1A671D568BA400152314 /* UserNotifications.framework */; };
@ -928,6 +930,8 @@
D00859B71B28189D00EAF753 /* Telegram_iOSTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Telegram_iOSTests.swift; sourceTree = "<group>"; };
D00ED7591FE94630001F38BD /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = en; path = en.lproj/AppIntentVocabulary.plist; sourceTree = "<group>"; };
D00ED75C1FE95287001F38BD /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
D015E010225CCEB300CB9E8A /* ReadBuffer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadBuffer.swift; sourceTree = "<group>"; };
D015E01E225CDF5000CB9E8A /* Api0.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Api0.swift; sourceTree = "<group>"; };
D01A47521F4DBEB100383CC1 /* libHockeySDK.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libHockeySDK.a; path = "../../build/HockeySDK-iOS/Support/build/Debug-iphoneos/libHockeySDK.a"; sourceTree = "<group>"; };
D01A47541F4DBED700383CC1 /* HockeySDK.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = HockeySDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D021D4D7219CAEDD0064BEBA /* Telegram-iOS-Fork.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = "Telegram-iOS-Fork.entitlements"; sourceTree = "<group>"; };
@ -2198,6 +2202,7 @@
D0400EE31D5B912E007931CE /* NotificationService */ = {
isa = PBXGroup;
children = (
D015E01E225CDF5000CB9E8A /* Api0.swift */,
D000CAC221FB6E170011B15D /* NotificationService-AppStore.entitlements */,
D000CAC321FB6E170011B15D /* NotificationService-AppStoreLLC.entitlements */,
D000CAC121FB6E160011B15D /* NotificationService-Fork.entitlements */,
@ -2212,6 +2217,7 @@
D073E51F21FF7CE900742DDD /* Crypto.m */,
D073E52122003E1E00742DDD /* Data.swift */,
D0E2CE632227F0680084E3DD /* ManagedFile.swift */,
D015E010225CCEB300CB9E8A /* ReadBuffer.swift */,
);
path = NotificationService;
sourceTree = "<group>";
@ -3243,10 +3249,12 @@
D0ED633B21FF3EFD001D4648 /* BuildConfig.m in Sources */,
D09B79C62219C784003B1F9D /* SharedAccountInfo.swift in Sources */,
D0ED633D21FF4580001D4648 /* NotificationService.swift in Sources */,
D015E01F225CDF5100CB9E8A /* Api0.swift in Sources */,
D0ED633A21FF3EDF001D4648 /* AccountData.swift in Sources */,
D0ED634121FF4786001D4648 /* Serialization.swift in Sources */,
D073E52021FF7CE900742DDD /* Crypto.m in Sources */,
D0ED633F21FF46E4001D4648 /* ImageData.swift in Sources */,
D015E011225CCEB300CB9E8A /* ReadBuffer.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View file

@ -4218,3 +4218,6 @@ Unused sets are archived when you add more.";
"Call.Speaker" = "speaker";
"MemberSearch.BotSection" = "BOTS";
"Conversation.PrivateMessageLinkCopied" = "This link will only work for members of this chat.";
"Conversation.ErrorInaccessibleMessage" = "Unfortunately, you can't access this message. You are not a member of the chat where it was posted.";

@ -1 +1 @@
Subproject commit 4f73ace1d8b171e142c01df029488d646b27aad0
Subproject commit 596995e1811e5202d627ec27e92c298512ba745e

@ -1 +1 @@
Subproject commit 579d7f626427d0cc82209c1b2fc3be7b97eac68c
Subproject commit e0d4ca79dd2545c83577e423143dec0663c879f4

@ -1 +1 @@
Subproject commit ab41021ba7e7d73e248b30cd5b4277720311fce7
Subproject commit b91bad40fefafa57313d661c6545d12cf4069176

@ -1 +1 @@
Subproject commit 9db156296688ff0fb5afdf67aa5b3bf6c72baecb
Subproject commit f11b2bc350bd4117d25fd68481bb5ef9231e7115