Files
Swiftgram/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift
Isaac 8a99f76f93 Refactor constructor use sites for types 320-339 to struct pattern
Migrated constructors: starsSubscription, starsSubscriptionPricing,
starsTopupOption, starsTransaction, starsTransactionPeer,
statsAbsValueAndPrev, statsDateRangeDays, statsGraph, statsGraphAsync,
statsGraphError, statsGroupTopAdmin, statsGroupTopInviter,
statsGroupTopPoster, statsPercentValue, stickerKeyword, stickerPack,
stickerSet, stickerSetCovered, stickerSetFullCovered,
stickerSetMultiCovered, stickerSetNoCovered, storiesStealthMode,
storyAlbum, storyFwdHeader

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 15:06:15 +08:00

145 lines
9.3 KiB
Swift

import Foundation
import Postbox
import TelegramApi
import SwiftSignalKit
import MtProtoKit
func telegramStickerPackThumbnailRepresentationFromApiSizes(datacenterId: Int32, thumbVersion: Int32?, sizes: [Api.PhotoSize]) -> (immediateThumbnail: Data?, representations: [TelegramMediaImageRepresentation]) {
func stickerTypeHint(for type: String) -> TelegramMediaImageRepresentation.TypeHint {
switch type {
case "s":
return .generic
case "a":
return .animated
case "v":
return .video
default:
return .generic
}
}
var immediateThumbnailData: Data?
var representations: [TelegramMediaImageRepresentation] = []
for size in sizes {
switch size {
case let .photoCachedSize(photoCachedSizeData):
let (type, w, h) = (photoCachedSizeData.type, photoCachedSizeData.w, photoCachedSizeData.h)
let resource = CloudStickerPackThumbnailMediaResource(datacenterId: datacenterId, thumbVersion: thumbVersion, volumeId: nil, localId: nil)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, typeHint: stickerTypeHint(for: type)))
case let .photoSize(photoSizeData):
let (type, w, h) = (photoSizeData.type, photoSizeData.w, photoSizeData.h)
let resource = CloudStickerPackThumbnailMediaResource(datacenterId: datacenterId, thumbVersion: thumbVersion, volumeId: nil, localId: nil)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: [], immediateThumbnailData: nil, typeHint: stickerTypeHint(for: type)))
case let .photoSizeProgressive(photoSizeProgressiveData):
let (type, w, h, sizes) = (photoSizeProgressiveData.type, photoSizeProgressiveData.w, photoSizeProgressiveData.h, photoSizeProgressiveData.sizes)
let resource = CloudStickerPackThumbnailMediaResource(datacenterId: datacenterId, thumbVersion: thumbVersion, volumeId: nil, localId: nil)
representations.append(TelegramMediaImageRepresentation(dimensions: PixelDimensions(width: w, height: h), resource: resource, progressiveSizes: sizes, immediateThumbnailData: nil, typeHint: stickerTypeHint(for: type)))
case let .photoPathSize(photoPathSizeData):
let data = photoPathSizeData.bytes
immediateThumbnailData = data.makeData()
case .photoStrippedSize:
break
case .photoSizeEmpty:
break
}
}
return (immediateThumbnailData, representations)
}
extension StickerPackCollectionInfo {
convenience init(apiSet: Api.StickerSet, namespace: ItemCollectionId.Namespace) {
switch apiSet {
case let .stickerSet(stickerSetData):
let (flags, _, id, accessHash, title, shortName, thumbs, thumbDcId, thumbVersion, thumbDocumentId, count, nHash) = (stickerSetData.flags, stickerSetData.installedDate, stickerSetData.id, stickerSetData.accessHash, stickerSetData.title, stickerSetData.shortName, stickerSetData.thumbs, stickerSetData.thumbDcId, stickerSetData.thumbVersion, stickerSetData.thumbDocumentId, stickerSetData.count, stickerSetData.hash)
var setFlags: StickerPackCollectionInfoFlags = StickerPackCollectionInfoFlags()
if (flags & (1 << 2)) != 0 {
setFlags.insert(.isOfficial)
}
if (flags & (1 << 3)) != 0 {
setFlags.insert(.isMasks)
}
if (flags & (1 << 7)) != 0 {
setFlags.insert(.isEmoji)
}
if (flags & (1 << 9)) != 0 {
setFlags.insert(.isCustomTemplateEmoji)
}
if (flags & (1 << 10)) != 0 {
setFlags.insert(.isAvailableAsChannelStatus)
}
if (flags & (1 << 11)) != 0 {
setFlags.insert(.isCreator)
}
var thumbnailRepresentation: TelegramMediaImageRepresentation?
var immediateThumbnailData: Data?
if let thumbs = thumbs, let thumbDcId = thumbDcId {
let (data, representations) = telegramStickerPackThumbnailRepresentationFromApiSizes(datacenterId: thumbDcId, thumbVersion: thumbVersion, sizes: thumbs)
thumbnailRepresentation = representations.first
immediateThumbnailData = data
}
self.init(id: ItemCollectionId(namespace: namespace, id: id), flags: setFlags, accessHash: accessHash, title: title, shortName: shortName, thumbnail: thumbnailRepresentation, thumbnailFileId: thumbDocumentId, immediateThumbnailData: immediateThumbnailData, hash: nHash, count: count)
}
}
}
func _internal_stickerPacksAttachedToMedia(account: Account, media: AnyMediaReference) -> Signal<[StickerPackReference], NoError> {
let inputMedia: Api.InputStickeredMedia
let resourceReference: MediaResourceReference
if let imageReference = media.concrete(TelegramMediaImage.self), let reference = imageReference.media.reference, case let .cloud(imageId, accessHash, fileReference) = reference, let representation = largestImageRepresentation(imageReference.media.representations) {
inputMedia = .inputStickeredMediaPhoto(.init(id: Api.InputPhoto.inputPhoto(.init(id: imageId, accessHash: accessHash, fileReference: Buffer(data: fileReference ?? Data())))))
resourceReference = imageReference.resourceReference(representation.resource)
} else if let fileReference = media.concrete(TelegramMediaFile.self), let resource = fileReference.media.resource as? CloudDocumentMediaResource {
inputMedia = .inputStickeredMediaDocument(.init(id: Api.InputDocument.inputDocument(.init(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: resource.fileReference ?? Data())))))
resourceReference = fileReference.resourceReference(fileReference.media.resource)
} else {
return .single([])
}
let accountPeerId = account.peerId
return account.network.request(Api.functions.messages.getAttachedStickers(media: inputMedia))
|> `catch` { _ -> Signal<[Api.StickerSetCovered], MTRpcError> in
return revalidateMediaResourceReference(accountPeerId: accountPeerId, postbox: account.postbox, network: account.network, revalidationContext: account.mediaReferenceRevalidationContext, info: TelegramCloudMediaResourceFetchInfo(reference: resourceReference, preferBackgroundReferenceRevalidation: false, continueInBackground: false), resource: resourceReference.resource)
|> mapError { _ -> MTRpcError in
return MTRpcError(errorCode: 500, errorDescription: "Internal")
}
|> mapToSignal { reference -> Signal<[Api.StickerSetCovered], MTRpcError> in
let inputMedia: Api.InputStickeredMedia
if let resource = reference.updatedResource as? TelegramCloudMediaResourceWithFileReference, let updatedReference = resource.fileReference {
if let imageReference = media.concrete(TelegramMediaImage.self), let reference = imageReference.media.reference, case let .cloud(imageId, accessHash, _) = reference, let _ = largestImageRepresentation(imageReference.media.representations) {
inputMedia = .inputStickeredMediaPhoto(.init(id: Api.InputPhoto.inputPhoto(.init(id: imageId, accessHash: accessHash, fileReference: Buffer(data: updatedReference)))))
} else if let fileReference = media.concrete(TelegramMediaFile.self), let resource = fileReference.media.resource as? CloudDocumentMediaResource {
inputMedia = .inputStickeredMediaDocument(.init(id: Api.InputDocument.inputDocument(.init(id: resource.fileId, accessHash: resource.accessHash, fileReference: Buffer(data: updatedReference)))))
} else {
return .single([])
}
return account.network.request(Api.functions.messages.getAttachedStickers(media: inputMedia))
} else {
return .single([])
}
}
|> `catch` { _ -> Signal<[Api.StickerSetCovered], MTRpcError> in
return .single([])
}
}
|> map { result -> [StickerPackReference] in
return result.map { pack in
let set: Api.StickerSet
switch pack {
case let .stickerSetCovered(stickerSetCoveredData):
set = stickerSetCoveredData.set
case let .stickerSetMultiCovered(stickerSetMultiCoveredData):
set = stickerSetMultiCoveredData.set
case let .stickerSetFullCovered(stickerSetFullCoveredData):
set = stickerSetFullCoveredData.set
case let .stickerSetNoCovered(stickerSetNoCoveredData):
set = stickerSetNoCoveredData.set
}
let info = StickerPackCollectionInfo(apiSet: set, namespace: Namespaces.ItemCollection.CloudStickerPacks)
return .id(id: info.id.id, accessHash: info.accessHash)
}
}
|> `catch` { _ -> Signal<[StickerPackReference], NoError> in
return .single([])
}
}