no message

This commit is contained in:
Peter 2017-07-17 20:41:58 +03:00
parent d8a8f02331
commit cef934468e
4 changed files with 191 additions and 64 deletions

View File

@ -533,6 +533,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1892568281] = { return Api.MessageAction.parse_messageActionPaymentSentMe($0) } dict[-1892568281] = { return Api.MessageAction.parse_messageActionPaymentSentMe($0) }
dict[1080663248] = { return Api.MessageAction.parse_messageActionPaymentSent($0) } dict[1080663248] = { return Api.MessageAction.parse_messageActionPaymentSent($0) }
dict[-2132731265] = { return Api.MessageAction.parse_messageActionPhoneCall($0) } dict[-2132731265] = { return Api.MessageAction.parse_messageActionPhoneCall($0) }
dict[1200788123] = { return Api.MessageAction.parse_messageActionScreenshotTaken($0) }
dict[1399245077] = { return Api.PhoneCall.parse_phoneCallEmpty($0) } dict[1399245077] = { return Api.PhoneCall.parse_phoneCallEmpty($0) }
dict[462375633] = { return Api.PhoneCall.parse_phoneCallWaiting($0) } dict[462375633] = { return Api.PhoneCall.parse_phoneCallWaiting($0) }
dict[-2089411356] = { return Api.PhoneCall.parse_phoneCallRequested($0) } dict[-2089411356] = { return Api.PhoneCall.parse_phoneCallRequested($0) }
@ -15357,6 +15358,7 @@ public struct Api {
case messageActionPaymentSentMe(flags: Int32, currency: String, totalAmount: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, charge: Api.PaymentCharge) case messageActionPaymentSentMe(flags: Int32, currency: String, totalAmount: Int64, payload: Buffer, info: Api.PaymentRequestedInfo?, shippingOptionId: String?, charge: Api.PaymentCharge)
case messageActionPaymentSent(currency: String, totalAmount: Int64) case messageActionPaymentSent(currency: String, totalAmount: Int64)
case messageActionPhoneCall(flags: Int32, callId: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?) case messageActionPhoneCall(flags: Int32, callId: Int64, reason: Api.PhoneCallDiscardReason?, duration: Int32?)
case messageActionScreenshotTaken
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) -> Swift.Bool { public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) -> Swift.Bool {
switch self { switch self {
@ -15482,6 +15484,12 @@ public struct Api {
serializeInt64(callId, buffer: buffer, boxed: false) serializeInt64(callId, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {reason!.serialize(buffer, true)} if Int(flags) & Int(1 << 0) != 0 {reason!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 1) != 0 {serializeInt32(duration!, buffer: buffer, boxed: false)}
break
case .messageActionScreenshotTaken:
if boxed {
buffer.appendInt32(1200788123)
}
break break
} }
return true return true
@ -15693,6 +15701,9 @@ public struct Api {
return nil return nil
} }
} }
fileprivate static func parse_messageActionScreenshotTaken(_ reader: BufferReader) -> MessageAction? {
return Api.MessageAction.messageActionScreenshotTaken
}
public var description: String { public var description: String {
get { get {
@ -15731,6 +15742,8 @@ public struct Api {
return "(messageActionPaymentSent currency: \(currency), totalAmount: \(totalAmount))" return "(messageActionPaymentSent currency: \(currency), totalAmount: \(totalAmount))"
case .messageActionPhoneCall(let flags, let callId, let reason, let duration): case .messageActionPhoneCall(let flags, let callId, let reason, let duration):
return "(messageActionPhoneCall flags: \(flags), callId: \(callId), reason: \(reason), duration: \(duration))" return "(messageActionPhoneCall flags: \(flags), callId: \(callId), reason: \(reason), duration: \(duration))"
case .messageActionScreenshotTaken:
return "(messageActionScreenshotTaken)"
} }
} }
} }
@ -21436,6 +21449,22 @@ public struct Api {
return result return result
}) })
} }
public static func sendScreenshotNotification(peer: Api.InputPeer, replyToMsgId: Int32, randomId: Int64) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Updates?) {
let buffer = Buffer()
buffer.appendInt32(-914493408)
peer.serialize(buffer, true)
serializeInt32(replyToMsgId, buffer: buffer, boxed: false)
serializeInt64(randomId, buffer: buffer, boxed: false)
return (FunctionDescription({return "(messages.sendScreenshotNotification peer: \(peer), replyToMsgId: \(replyToMsgId), randomId: \(randomId))"}), buffer, { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Updates
}
return result
})
}
} }
public struct channels { public struct channels {
public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) {
@ -22835,16 +22864,16 @@ public struct Api {
}) })
} }
public static func reuploadCdnFile(fileToken: Buffer, requestToken: Buffer) -> (CustomStringConvertible, Buffer, (Buffer) -> Api.Bool?) { public static func reuploadCdnFile(fileToken: Buffer, requestToken: Buffer) -> (CustomStringConvertible, Buffer, (Buffer) -> [Api.CdnFileHash]?) {
let buffer = Buffer() let buffer = Buffer()
buffer.appendInt32(779755552) buffer.appendInt32(452533257)
serializeBytes(fileToken, buffer: buffer, boxed: false) serializeBytes(fileToken, buffer: buffer, boxed: false)
serializeBytes(requestToken, buffer: buffer, boxed: false) serializeBytes(requestToken, buffer: buffer, boxed: false)
return (FunctionDescription({return "(upload.reuploadCdnFile fileToken: \(fileToken), requestToken: \(requestToken))"}), buffer, { (buffer: Buffer) -> Api.Bool? in return (FunctionDescription({return "(upload.reuploadCdnFile fileToken: \(fileToken), requestToken: \(requestToken))"}), buffer, { (buffer: Buffer) -> [Api.CdnFileHash]? in
let reader = BufferReader(buffer) let reader = BufferReader(buffer)
var result: Api.Bool? var result: [Api.CdnFileHash]?
if let signature = reader.readInt32() { if let _ = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool result = Api.parseVector(reader, elementSignature: 0, elementType: Api.CdnFileHash.self)
} }
return result return result
}) })

View File

@ -127,60 +127,162 @@ private func roundUp(_ value: Int, to multiple: Int) -> Int {
return value + multiple - remainder return value + multiple - remainder
} }
private final class MultipartCdnHashSourceState { private let dataHashLength: Int32 = 128 * 1024
private var hashes: [Int32: Data]
private var requestOffsetAndDisposable: (Int32, Disposable)?
private var requestedOffsets = Set<Int32>()
init(hashes: [Int32: Data]) {
self.hashes = hashes
}
func dispose() -> Disposable? {
let disposable = self.requestOffsetAndDisposable?.1
self.requestOffsetAndDisposable = nil
return disposable
}
func get(offset: Int32) -> (Data?, MetaDisposable?) {
if let data = self.hashes[offset] {
return (data, nil)
} else {
requestedOffsets.insert(offset)
if self.requestOffsetAndDisposable == nil {
let disposable = MetaDisposable()
self.requestOffsetAndDisposable = (offset, disposable)
return (nil, disposable)
} else {
return (nil, nil)
}
}
}
func add(requestedOffset: Int32, addedHashes: [Int32: Data]) -> (Int32, MetaDisposable)? {
return nil
}
}
private final class MultipartCdnHashSource { private final class MultipartCdnHashSource {
private let state: Atomic<MultipartCdnHashSourceState> private let queue: Queue
private let fileToken: Data
private let masterDownload: DownloadWrapper private let masterDownload: DownloadWrapper
init(hashes: [Int32: Data], masterDownload: DownloadWrapper) { private var knownUpperBound: Int32
self.state = Atomic(value: MultipartCdnHashSourceState(hashes: hashes)) private var hashes: [Int32: Data]
private var requestOffsetAndDisposable: (Int32, Disposable)?
private var requestedUpperBound: Int32?
private var subscribers = Bag<(Int32, Int32, ([Int32: Data]) -> Void)>()
init(queue: Queue, fileToken: Data, hashes: [Int32: Data], masterDownload: DownloadWrapper) {
assert(queue.isCurrent())
self.queue = queue
self.fileToken = fileToken
self.masterDownload = masterDownload self.masterDownload = masterDownload
self.hashes = hashes
var knownUpperBound: Int32 = 0
/*for (offset, _) in hashes {
assert(offset % dataHashLength == 0)
knownUpperBound = max(knownUpperBound, offset + dataHashLength)
}*/
self.knownUpperBound = knownUpperBound
} }
deinit { deinit {
let disposable = self.state.with { assert(self.queue.isCurrent())
return $0.dispose()
} self.requestOffsetAndDisposable?.1.dispose()
disposable?.dispose()
} }
func get(offset: Int32) -> Signal<Data, MultipartFetchDownloadError> { private func take(offset: Int32, limit: Int32) -> [Int32: Data]? {
return .never() assert(offset % dataHashLength == 0)
assert(limit % dataHashLength == 0)
var result: [Int32: Data] = [:]
var localOffset: Int32 = 0
while localOffset < limit {
if let hash = self.hashes[offset + localOffset] {
result[offset + localOffset] = hash
} else {
return nil
}
localOffset += dataHashLength
}
return result
}
func get(offset: Int32, limit: Int32) -> Signal<[Int32: Data], MultipartFetchDownloadError> {
assert(self.queue.isCurrent())
let queue = self.queue
return Signal { [weak self] subscriber in
let disposable = MetaDisposable()
queue.async {
if let strongSelf = self {
if let result = strongSelf.take(offset: offset, limit: limit) {
subscriber.putNext(result)
subscriber.putCompletion()
} else {
let index = strongSelf.subscribers.add((offset, limit, { result in
subscriber.putNext(result)
subscriber.putCompletion()
}))
disposable.set(ActionDisposable {
queue.async {
if let strongSelf = self {
strongSelf.subscribers.remove(index)
}
}
})
if let requestedUpperBound = strongSelf.requestedUpperBound {
strongSelf.requestedUpperBound = max(requestedUpperBound, offset + limit)
} else {
strongSelf.requestedUpperBound = offset + limit
}
if strongSelf.requestOffsetAndDisposable == nil {
strongSelf.requestMore()
} else {
if let requestedUpperBound = strongSelf.requestedUpperBound {
strongSelf.requestedUpperBound = max(requestedUpperBound, offset + limit)
} else {
strongSelf.requestedUpperBound = offset + limit
}
}
}
}
}
return disposable
}
}
private func requestMore() {
assert(self.queue.isCurrent())
let requestOffset = self.knownUpperBound
let disposable = MetaDisposable()
self.requestOffsetAndDisposable = (requestOffset, disposable)
let queue = self.queue
let fileToken = self.fileToken
disposable.set((self.masterDownload.get() |> mapToSignal { download -> Signal<[Int32: Data], NoError> in
return download.request(Api.functions.upload.getCdnFileHashes(fileToken: Buffer(data: fileToken), offset: requestOffset))
|> map { partHashes -> [Int32: Data] in
var parsedPartHashes: [Int32: Data] = [:]
for part in partHashes {
switch part {
case let .cdnFileHash(offset, limit, bytes):
assert(limit == 128 * 1024)
parsedPartHashes[offset] = bytes.makeData()
}
}
return parsedPartHashes
}
|> `catch` { _ -> Signal<[Int32: Data], NoError> in
return .single([:])
}
} |> deliverOn(queue)).start(next: { [weak self] result in
if let strongSelf = self {
if strongSelf.requestOffsetAndDisposable?.0 == requestOffset {
strongSelf.requestOffsetAndDisposable = nil
for (hashOffset, hashData) in result {
assert(hashOffset % dataHashLength == 0)
strongSelf.knownUpperBound = max(strongSelf.knownUpperBound, hashOffset + dataHashLength)
strongSelf.hashes[hashOffset] = hashData
}
for (index, item) in strongSelf.subscribers.copyItemsWithIndices() {
let (offset, limit, subscriber) = item
if let data = strongSelf.take(offset: offset, limit: limit) {
strongSelf.subscribers.remove(index)
subscriber(data)
}
}
if let requestedUpperBound = strongSelf.requestedUpperBound, requestedUpperBound > strongSelf.knownUpperBound {
strongSelf.requestMore()
}
} else {
assertionFailure()
}
}
}))
} }
} }
@ -274,7 +376,7 @@ private enum MultipartFetchSource {
} }
} }
} }
return combineLatest(part, hashSource.get(offset: offset)) return combineLatest(part, hashSource.get(offset: offset, limit: limit))
|> mapToSignal { partData, hashData -> Signal<Data, MultipartFetchDownloadError> in |> mapToSignal { partData, hashData -> Signal<Data, MultipartFetchDownloadError> in
return .single(partData) return .single(partData)
} }
@ -285,6 +387,7 @@ private enum MultipartFetchSource {
private final class MultipartFetchManager { private final class MultipartFetchManager {
let parallelParts: Int let parallelParts: Int
let defaultPartSize = 128 * 1024 let defaultPartSize = 128 * 1024
let partAlignment = 128 * 1024
let queue = Queue() let queue = Queue()
@ -314,7 +417,6 @@ private final class MultipartFetchManager {
self.completeSize = size self.completeSize = size
if let size = size { if let size = size {
if size <= range.lowerBound { if size <= range.lowerBound {
//assertionFailure()
self.range = range self.range = range
self.parallelParts = 0 self.parallelParts = 0
} else { } else {
@ -433,7 +535,7 @@ private final class MultipartFetchManager {
case let .switchToCdn(id, token, key, iv, partHashes): case let .switchToCdn(id, token, key, iv, partHashes):
switch strongSelf.source { switch strongSelf.source {
case let .master(location, download): case let .master(location, download):
strongSelf.source = .cdn(masterDatacenterId: location.datacenterId, fileToken: token, key: key, iv: iv, download: DownloadWrapper(id: id, cdn: true, take: strongSelf.takeDownloader), masterDownload: download, hashSource: MultipartCdnHashSource(hashes: partHashes, masterDownload: download)) strongSelf.source = .cdn(masterDatacenterId: location.datacenterId, fileToken: token, key: key, iv: iv, download: DownloadWrapper(id: id, cdn: true, take: strongSelf.takeDownloader), masterDownload: download, hashSource: MultipartCdnHashSource(queue: strongSelf.queue, fileToken: token, hashes: partHashes, masterDownload: download))
strongSelf.checkState() strongSelf.checkState()
case .cdn, .none: case .cdn, .none:
break break
@ -445,13 +547,13 @@ private final class MultipartFetchManager {
case let .cdn(_, fileToken, _, _, _, masterDownload, _): case let .cdn(_, fileToken, _, _, _, masterDownload, _):
if !strongSelf.reuploadingToCdn { if !strongSelf.reuploadingToCdn {
strongSelf.reuploadingToCdn = true strongSelf.reuploadingToCdn = true
let reupload: Signal<Api.Bool, NoError> = masterDownload.get() |> mapToSignal { download -> Signal<Api.Bool, NoError> in let reupload: Signal<[Api.CdnFileHash], NoError> = masterDownload.get() |> mapToSignal { download -> Signal<[Api.CdnFileHash], NoError> in
return download.request(Api.functions.upload.reuploadCdnFile(fileToken: Buffer(data: fileToken), requestToken: Buffer(data: token))) return download.request(Api.functions.upload.reuploadCdnFile(fileToken: Buffer(data: fileToken), requestToken: Buffer(data: token)))
|> `catch` { _ -> Signal<Api.Bool, NoError> in |> `catch` { _ -> Signal<[Api.CdnFileHash], NoError> in
return .single(.boolFalse) return .single([])
} }
} }
strongSelf.reuploadToCdnDisposable.set((reupload |> deliverOn(strongSelf.queue)).start(next: { result in strongSelf.reuploadToCdnDisposable.set((reupload |> deliverOn(strongSelf.queue)).start(next: { _ in
if let strongSelf = self { if let strongSelf = self {
strongSelf.reuploadingToCdn = false strongSelf.reuploadingToCdn = false
strongSelf.checkState() strongSelf.checkState()

View File

@ -185,7 +185,7 @@ extension Api.Message {
} }
switch action { switch action {
case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionHistoryClear, .messageActionGameScore: case .messageActionChannelCreate, .messageActionChatDeletePhoto, .messageActionChatEditPhoto, .messageActionChatEditTitle, .messageActionEmpty, .messageActionPinMessage, .messageActionHistoryClear, .messageActionGameScore, .messageActionPaymentSent, .messageActionPaymentSentMe, .messageActionPhoneCall, .messageActionScreenshotTaken:
break break
case let .messageActionChannelMigrateFrom(_, chatId): case let .messageActionChannelMigrateFrom(_, chatId):
result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId)) result.append(PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId))
@ -203,12 +203,6 @@ extension Api.Message {
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: inviterId)) result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: inviterId))
case let .messageActionChatMigrateTo(channelId): case let .messageActionChatMigrateTo(channelId):
result.append(PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)) result.append(PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId))
case let .messageActionPhoneCall(flags, callId, reason, duration):
break
case let .messageActionPaymentSent(currency, totalAmount):
break
case .messageActionPaymentSentMe:
break
} }
return result return result

View File

@ -328,6 +328,8 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
return TelegramMediaAction(action: .paymentSent(currency: currency, totalAmount: totalAmount)) return TelegramMediaAction(action: .paymentSent(currency: currency, totalAmount: totalAmount))
case .messageActionPaymentSentMe: case .messageActionPaymentSentMe:
return nil return nil
case .messageActionScreenshotTaken:
return TelegramMediaAction(action: .historyScreenshot)
} }
} }