mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 13:38:21 +00:00
Fix messageAuthorAvatar revaildation
This commit is contained in:
parent
01a434f3d9
commit
4f66986b41
@ -902,7 +902,12 @@ final class MediaReferenceRevalidationContext {
|
||||
}
|
||||
}
|
||||
|
||||
func revalidateMediaResourceReference(postbox: Postbox, network: Network, revalidationContext: MediaReferenceRevalidationContext, info: TelegramCloudMediaResourceFetchInfo, resource: MediaResource) -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> {
|
||||
struct RevalidatedMediaResource {
|
||||
let updatedResource: TelegramMediaResource
|
||||
let updatedReference: MediaResourceReference?
|
||||
}
|
||||
|
||||
func revalidateMediaResourceReference(postbox: Postbox, network: Network, revalidationContext: MediaReferenceRevalidationContext, info: TelegramCloudMediaResourceFetchInfo, resource: MediaResource) -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> {
|
||||
var updatedReference = info.reference
|
||||
if case let .media(media, resource) = updatedReference {
|
||||
if case let .message(_, mediaValue) = media {
|
||||
@ -936,22 +941,22 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
|
||||
switch media {
|
||||
case let .message(message, previousMedia):
|
||||
return revalidationContext.message(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, message: message)
|
||||
|> mapToSignal { message -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> in
|
||||
|> mapToSignal { message -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
for media in message.media {
|
||||
if let updatedResource = findUpdatedMediaResource(media: media, previousMedia: previousMedia, resource: resource) {
|
||||
return .single(updatedResource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
|
||||
}
|
||||
}
|
||||
return .fail(.generic)
|
||||
}
|
||||
case let .stickerPack(stickerPack, media):
|
||||
return revalidationContext.stickerPack(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, stickerPack: stickerPack)
|
||||
|> mapToSignal { result -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> in
|
||||
|> mapToSignal { result -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
for item in result.1 {
|
||||
if let item = item as? StickerPackItem {
|
||||
if media.id != nil && item.file.id == media.id {
|
||||
if let updatedResource = findUpdatedMediaResource(media: item.file, previousMedia: media, resource: resource) {
|
||||
return .single(updatedResource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -960,19 +965,19 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
|
||||
}
|
||||
case let .webPage(webPage, previousMedia):
|
||||
return revalidationContext.webPage(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, webPage: webPage)
|
||||
|> mapToSignal { result -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> in
|
||||
|> mapToSignal { result -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
if let updatedResource = findUpdatedMediaResource(media: result, previousMedia: previousMedia, resource: resource) {
|
||||
return .single(updatedResource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
|
||||
}
|
||||
return .fail(.generic)
|
||||
}
|
||||
case let .savedGif(media):
|
||||
return revalidationContext.savedGifs(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation)
|
||||
|> mapToSignal { result -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> in
|
||||
|> mapToSignal { result -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
for file in result {
|
||||
if media.id != nil && file.id == media.id {
|
||||
if let updatedResource = findUpdatedMediaResource(media: file, previousMedia: media, resource: resource) {
|
||||
return .single(updatedResource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -983,12 +988,12 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
|
||||
for attribute in file.attributes {
|
||||
if case let .Sticker(sticker) = attribute, let stickerPack = sticker.packReference {
|
||||
return revalidationContext.stickerPack(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, stickerPack: stickerPack)
|
||||
|> mapToSignal { result -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> in
|
||||
|> mapToSignal { result -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
for item in result.1 {
|
||||
if let item = item as? StickerPackItem {
|
||||
if media.id != nil && item.file.id == media.id {
|
||||
if let updatedResource = findUpdatedMediaResource(media: item.file, previousMedia: media, resource: resource) {
|
||||
return .single(updatedResource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1002,17 +1007,17 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
|
||||
}
|
||||
case let .avatar(peer, _):
|
||||
return revalidationContext.peer(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, peer: peer)
|
||||
|> mapToSignal { updatedPeer -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> in
|
||||
|> mapToSignal { updatedPeer -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
for representation in updatedPeer.profileImageRepresentations {
|
||||
if representation.resource.id.isEqual(to: resource.id) {
|
||||
return .single(representation.resource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: representation.resource, updatedReference: nil))
|
||||
}
|
||||
}
|
||||
if let legacyResource = resource as? CloudFileMediaResource {
|
||||
for representation in updatedPeer.profileImageRepresentations {
|
||||
if let updatedResource = representation.resource as? CloudPeerPhotoSizeMediaResource {
|
||||
if updatedResource.localId == legacyResource.localId && updatedResource.volumeId == legacyResource.volumeId {
|
||||
return .single(updatedResource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1021,19 +1026,20 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
|
||||
}
|
||||
case let .messageAuthorAvatar(message, _):
|
||||
return revalidationContext.message(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, message: message)
|
||||
|> mapToSignal { updatedMessage -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> in
|
||||
if let author = updatedMessage.author {
|
||||
for representation in author.profileImageRepresentations {
|
||||
if representation.resource.id.isEqual(to: resource.id) {
|
||||
return .single(representation.resource)
|
||||
}
|
||||
|> mapToSignal { updatedMessage -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
guard let author = updatedMessage.author, let authorReference = PeerReference(author) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
for representation in author.profileImageRepresentations {
|
||||
if representation.resource.id.isEqual(to: resource.id) {
|
||||
return .single(RevalidatedMediaResource(updatedResource: representation.resource, updatedReference: .avatar(peer: authorReference, resource: representation.resource)))
|
||||
}
|
||||
if let legacyResource = resource as? CloudFileMediaResource {
|
||||
for representation in author.profileImageRepresentations {
|
||||
if let updatedResource = representation.resource as? CloudPeerPhotoSizeMediaResource {
|
||||
if updatedResource.localId == legacyResource.localId && updatedResource.volumeId == legacyResource.volumeId {
|
||||
return .single(updatedResource)
|
||||
}
|
||||
}
|
||||
if let legacyResource = resource as? CloudFileMediaResource {
|
||||
for representation in author.profileImageRepresentations {
|
||||
if let updatedResource = representation.resource as? CloudPeerPhotoSizeMediaResource {
|
||||
if updatedResource.localId == legacyResource.localId && updatedResource.volumeId == legacyResource.volumeId {
|
||||
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: .avatar(peer: authorReference, resource: updatedResource)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1042,18 +1048,18 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
|
||||
}
|
||||
case .wallpaper:
|
||||
return revalidationContext.wallpapers(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation)
|
||||
|> mapToSignal { wallpapers -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> in
|
||||
|> mapToSignal { wallpapers -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
for wallpaper in wallpapers {
|
||||
switch wallpaper {
|
||||
case let .image(representations, _):
|
||||
for representation in representations {
|
||||
if representation.resource.id.isEqual(to: resource.id) {
|
||||
return .single(representation.resource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: representation.resource, updatedReference: nil))
|
||||
}
|
||||
}
|
||||
case let .file(_, _, _, _, _, _, _, file, _):
|
||||
if let updatedResource = findUpdatedMediaResource(media: file, previousMedia: nil, resource: resource) {
|
||||
return .single(updatedResource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
|
||||
}
|
||||
default:
|
||||
break
|
||||
@ -1063,15 +1069,15 @@ func revalidateMediaResourceReference(postbox: Postbox, network: Network, revali
|
||||
}
|
||||
case let .stickerPackThumbnail(packReference, resource):
|
||||
return revalidationContext.stickerPack(postbox: postbox, network: network, background: info.preferBackgroundReferenceRevalidation, stickerPack: packReference)
|
||||
|> mapToSignal { result -> Signal<TelegramMediaResource, RevalidateMediaReferenceError> in
|
||||
|> mapToSignal { result -> Signal<RevalidatedMediaResource, RevalidateMediaReferenceError> in
|
||||
if let thumbnail = result.0.thumbnail {
|
||||
if thumbnail.resource.id.isEqual(to: resource.id) {
|
||||
return .single(thumbnail.resource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: thumbnail.resource, updatedReference: nil))
|
||||
}
|
||||
if let legacyResource = resource as? CloudFileMediaResource {
|
||||
if let updatedResource = thumbnail.resource as? CloudStickerPackThumbnailMediaResource {
|
||||
if updatedResource.localId == legacyResource.localId && updatedResource.volumeId == legacyResource.volumeId {
|
||||
return .single(updatedResource)
|
||||
return .single(RevalidatedMediaResource(updatedResource: updatedResource, updatedReference: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,8 +64,14 @@ private enum MultipartFetchDownloadError {
|
||||
case hashesMissing
|
||||
}
|
||||
|
||||
private enum MultipartFetchGenericLocationResult {
|
||||
case none
|
||||
case location(Api.InputFileLocation)
|
||||
case revalidate
|
||||
}
|
||||
|
||||
private enum MultipartFetchMasterLocation {
|
||||
case generic(Int32, (TelegramMediaResource, Data?) -> Api.InputFileLocation?)
|
||||
case generic(Int32, (TelegramMediaResource, MediaResourceReference?, Data?) -> MultipartFetchGenericLocationResult)
|
||||
case web(Int32, Api.InputWebFileLocation)
|
||||
|
||||
var datacenterId: Int32 {
|
||||
@ -272,7 +278,7 @@ private enum MultipartFetchSource {
|
||||
case master(location: MultipartFetchMasterLocation, download: DownloadWrapper)
|
||||
case cdn(masterDatacenterId: Int32, fileToken: Data, key: Data, iv: Data, download: DownloadWrapper, masterDownload: DownloadWrapper, hashSource: MultipartCdnHashSource)
|
||||
|
||||
func request(offset: Int32, limit: Int32, tag: MediaResourceFetchTag?, resource: TelegramMediaResource, fileReference: Data?, continueInBackground: Bool) -> Signal<Data, MultipartFetchDownloadError> {
|
||||
func request(offset: Int32, limit: Int32, tag: MediaResourceFetchTag?, resource: TelegramMediaResource, resourceReference: MediaResourceReference?, fileReference: Data?, continueInBackground: Bool) -> Signal<Data, MultipartFetchDownloadError> {
|
||||
switch self {
|
||||
case .none:
|
||||
return .never()
|
||||
@ -284,36 +290,39 @@ private enum MultipartFetchSource {
|
||||
|
||||
switch location {
|
||||
case let .generic(_, location):
|
||||
if let parsedLocation = location(resource, fileReference) {
|
||||
return download.request(Api.functions.upload.getFile(location: parsedLocation, offset: offset, limit: Int32(updatedLength)), tag: tag, continueInBackground: continueInBackground)
|
||||
|> mapError { error -> MultipartFetchDownloadError in
|
||||
if error.errorDescription.hasPrefix("FILEREF_INVALID") || error.errorDescription.hasPrefix("FILE_REFERENCE_") {
|
||||
return .revalidateMediaReference
|
||||
switch location(resource, resourceReference, fileReference) {
|
||||
case .none:
|
||||
return .fail(.revalidateMediaReference)
|
||||
case .revalidate:
|
||||
return .fail(.revalidateMediaReference)
|
||||
case let .location(parsedLocation):
|
||||
return download.request(Api.functions.upload.getFile(location: parsedLocation, offset: offset, limit: Int32(updatedLength)), tag: tag, continueInBackground: continueInBackground)
|
||||
|> mapError { error -> MultipartFetchDownloadError in
|
||||
if error.errorDescription.hasPrefix("FILEREF_INVALID") || error.errorDescription.hasPrefix("FILE_REFERENCE_") {
|
||||
return .revalidateMediaReference
|
||||
}
|
||||
return .generic
|
||||
}
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<Data, MultipartFetchDownloadError> in
|
||||
switch result {
|
||||
case let .file(_, _, bytes):
|
||||
var resultData = bytes.makeData()
|
||||
if resultData.count > Int(limit) {
|
||||
resultData.count = Int(limit)
|
||||
}
|
||||
return .single(resultData)
|
||||
case let .fileCdnRedirect(dcId, fileToken, encryptionKey, encryptionIv, partHashes):
|
||||
var parsedPartHashes: [Int32: Data] = [:]
|
||||
for part in partHashes {
|
||||
switch part {
|
||||
case let .fileHash(offset, limit, bytes):
|
||||
assert(limit == 128 * 1024)
|
||||
parsedPartHashes[offset] = bytes.makeData()
|
||||
|> mapToSignal { result -> Signal<Data, MultipartFetchDownloadError> in
|
||||
switch result {
|
||||
case let .file(_, _, bytes):
|
||||
var resultData = bytes.makeData()
|
||||
if resultData.count > Int(limit) {
|
||||
resultData.count = Int(limit)
|
||||
}
|
||||
}
|
||||
return .fail(.switchToCdn(id: dcId, token: fileToken.makeData(), key: encryptionKey.makeData(), iv: encryptionIv.makeData(), partHashes: parsedPartHashes))
|
||||
return .single(resultData)
|
||||
case let .fileCdnRedirect(dcId, fileToken, encryptionKey, encryptionIv, partHashes):
|
||||
var parsedPartHashes: [Int32: Data] = [:]
|
||||
for part in partHashes {
|
||||
switch part {
|
||||
case let .fileHash(offset, limit, bytes):
|
||||
assert(limit == 128 * 1024)
|
||||
parsedPartHashes[offset] = bytes.makeData()
|
||||
}
|
||||
}
|
||||
return .fail(.switchToCdn(id: dcId, token: fileToken.makeData(), key: encryptionKey.makeData(), iv: encryptionIv.makeData(), partHashes: parsedPartHashes))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return .fail(.revalidateMediaReference)
|
||||
}
|
||||
case let .web(_, location):
|
||||
return download.request(Api.functions.upload.getWebFile(location: location, offset: offset, limit: Int32(updatedLength)), tag: tag, continueInBackground: continueInBackground)
|
||||
@ -388,6 +397,7 @@ private final class MultipartFetchManager {
|
||||
let partAlignment = 128 * 1024
|
||||
|
||||
var resource: TelegramMediaResource
|
||||
var resourceReference: MediaResourceReference?
|
||||
var fileReference: Data?
|
||||
let parameters: MediaResourceFetchParameters?
|
||||
let consumerId: Int64
|
||||
@ -440,8 +450,10 @@ private final class MultipartFetchManager {
|
||||
if let info = parameters?.info as? TelegramCloudMediaResourceFetchInfo {
|
||||
self.fileReference = info.reference.apiFileReference
|
||||
self.continueInBackground = info.continueInBackground
|
||||
self.resourceReference = info.reference
|
||||
} else {
|
||||
self.continueInBackground = false
|
||||
self.resourceReference = nil
|
||||
}
|
||||
|
||||
self.state = MultipartDownloadState(encryptionKey: encryptionKey, decryptedSize: decryptedSize)
|
||||
@ -592,7 +604,7 @@ private final class MultipartFetchManager {
|
||||
requestLimit = (requestLimit / self.partAlignment + 1) * self.partAlignment
|
||||
}
|
||||
|
||||
let part = self.source.request(offset: Int32(downloadRange.lowerBound), limit: Int32(requestLimit), tag: self.parameters?.tag, resource: self.resource, fileReference: self.fileReference, continueInBackground: self.continueInBackground)
|
||||
let part = self.source.request(offset: Int32(downloadRange.lowerBound), limit: Int32(requestLimit), tag: self.parameters?.tag, resource: self.resource, resourceReference: self.resourceReference, fileReference: self.fileReference, continueInBackground: self.continueInBackground)
|
||||
|> deliverOn(self.queue)
|
||||
let partDisposable = MetaDisposable()
|
||||
self.fetchingParts[downloadRange.lowerBound] = (downloadRange.count, partDisposable)
|
||||
@ -621,19 +633,18 @@ private final class MultipartFetchManager {
|
||||
strongSelf.revalidatingMediaReference = true
|
||||
if let info = strongSelf.parameters?.info as? TelegramCloudMediaResourceFetchInfo {
|
||||
strongSelf.revalidateMediaReferenceDisposable.set((revalidateMediaResourceReference(postbox: strongSelf.postbox, network: strongSelf.network, revalidationContext: strongSelf.revalidationContext, info: info, resource: strongSelf.resource)
|
||||
|> deliverOn(strongSelf.queue)).start(next: { validatedResource in
|
||||
|> deliverOn(strongSelf.queue)).start(next: { validationResult in
|
||||
if let strongSelf = self {
|
||||
strongSelf.revalidatingMediaReference = false
|
||||
strongSelf.revalidatedMediaReference = true
|
||||
if let validatedResource = validatedResource as? TelegramCloudMediaResourceWithFileReference, let reference = validatedResource.fileReference {
|
||||
if let validatedResource = validationResult.updatedResource as? TelegramCloudMediaResourceWithFileReference, let reference = validatedResource.fileReference {
|
||||
strongSelf.fileReference = reference
|
||||
}
|
||||
strongSelf.resource = validatedResource
|
||||
strongSelf.resource = validationResult.updatedResource
|
||||
strongSelf.resourceReference = validationResult.updatedReference
|
||||
strongSelf.checkState()
|
||||
}
|
||||
}, error: { _ in
|
||||
if let strongSelf = self {
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
Logger.shared.log("MultipartFetch", "reference invalidation requested, but no valid reference given")
|
||||
@ -680,34 +691,46 @@ func multipartFetch(postbox: Postbox, network: Network, mediaReferenceRevalidati
|
||||
if let resource = resource as? WebFileReferenceMediaResource {
|
||||
location = .web(Int32(datacenterId), resource.apiInputLocation)
|
||||
} else {
|
||||
location = .generic(Int32(datacenterId), { resource, fileReference in
|
||||
location = .generic(Int32(datacenterId), { resource, resourceReference, fileReference in
|
||||
if let resource = resource as? TelegramCloudMediaResource {
|
||||
return resource.apiInputLocation(fileReference: fileReference)
|
||||
if let location = resource.apiInputLocation(fileReference: fileReference){
|
||||
return .location(location)
|
||||
} else {
|
||||
return .none
|
||||
}
|
||||
} else if let resource = resource as? CloudPeerPhotoSizeMediaResource {
|
||||
guard let info = parameters?.info as? TelegramCloudMediaResourceFetchInfo else {
|
||||
return nil
|
||||
return .none
|
||||
}
|
||||
switch info.reference {
|
||||
switch resourceReference ?? info.reference {
|
||||
case let .avatar(peer, _):
|
||||
return resource.apiInputLocation(peerReference: peer)
|
||||
case let .messageAuthorAvatar(message, resource):
|
||||
if let location = resource.apiInputLocation(peerReference: peer) {
|
||||
return .location(location)
|
||||
} else {
|
||||
return .none
|
||||
}
|
||||
case .messageAuthorAvatar:
|
||||
|
||||
return nil
|
||||
return .revalidate
|
||||
default:
|
||||
return nil
|
||||
return .none
|
||||
}
|
||||
} else if let resource = resource as? CloudStickerPackThumbnailMediaResource {
|
||||
guard let info = parameters?.info as? TelegramCloudMediaResourceFetchInfo else {
|
||||
return nil
|
||||
return .none
|
||||
}
|
||||
switch info.reference {
|
||||
case let .stickerPackThumbnail(stickerPack, _):
|
||||
return resource.apiInputLocation(packReference: stickerPack)
|
||||
if let location = resource.apiInputLocation(packReference: stickerPack) {
|
||||
return .location(location)
|
||||
} else {
|
||||
return .none
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
return .none
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
return .none
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user