import Foundation import SwiftSignalKit import Postbox public typealias EngineTempBox = TempBox public typealias EngineTempBoxFile = TempBoxFile public final class EngineMediaResource: Equatable { public enum CacheTimeout { case `default` case shortLived } public struct ByteRange { public enum Priority { case `default` case elevated case maximum } public var range: Range public var priority: Priority public init(range: Range, priority: Priority) { self.range = range self.priority = priority } } public final class Fetch { public enum Result { case moveTempFile(file: TempBoxFile) } public enum Error { case generic } public let signal: () -> Signal public init(_ signal: @escaping () -> Signal) { self.signal = signal } } public final class ResourceData { public let path: String public let availableSize: Int public let isComplete: Bool public init( path: String, availableSize: Int, isComplete: Bool ) { self.path = path self.availableSize = availableSize self.isComplete = isComplete } } public struct Id: Equatable, Hashable { public var stringRepresentation: String public init(_ stringRepresentation: String) { self.stringRepresentation = stringRepresentation } public init(_ id: MediaResourceId) { self.stringRepresentation = id.stringRepresentation } } private let resource: MediaResource public init(_ resource: MediaResource) { self.resource = resource } public func _asResource() -> MediaResource { return self.resource } public var id: Id { return Id(self.resource.id) } public static func ==(lhs: EngineMediaResource, rhs: EngineMediaResource) -> Bool { return lhs.resource.isEqual(to: rhs.resource) } } public extension EngineMediaResource.ResourceData { convenience init(_ data: MediaResourceData) { self.init(path: data.path, availableSize: data.size, isComplete: data.complete) } } public extension TelegramEngine { final class Resources { private let account: Account init(account: Account) { self.account = account } public func preUpload(id: Int64, encrypt: Bool, tag: MediaResourceFetchTag?, source: Signal, onComplete: (()->Void)? = nil) { return self.account.messageMediaPreuploadManager.add(network: self.account.network, postbox: self.account.postbox, id: id, encrypt: encrypt, tag: tag, source: source, onComplete: onComplete) } public func collectCacheUsageStats(peerId: PeerId? = nil, additionalCachePaths: [String] = [], logFilesPath: String? = nil) -> Signal { return _internal_collectCacheUsageStats(account: self.account, peerId: peerId, additionalCachePaths: additionalCachePaths, logFilesPath: logFilesPath) } public func clearCachedMediaResources(mediaResourceIds: Set) -> Signal { return _internal_clearCachedMediaResources(account: self.account, mediaResourceIds: mediaResourceIds) } public func data(id: EngineMediaResource.Id, attemptSynchronously: Bool = false) -> Signal { return self.account.postbox.mediaBox.resourceData( id: MediaResourceId(id.stringRepresentation), pathExtension: nil, option: .complete(waitUntilFetchStatus: false), attemptSynchronously: attemptSynchronously ) |> map { data in return EngineMediaResource.ResourceData(data) } } public func custom(id: String, fetch: EngineMediaResource.Fetch, cacheTimeout: EngineMediaResource.CacheTimeout = .default, attemptSynchronously: Bool = false) -> Signal { let mappedKeepDuration: CachedMediaRepresentationKeepDuration switch cacheTimeout { case .default: mappedKeepDuration = .general case .shortLived: mappedKeepDuration = .shortLived } return self.account.postbox.mediaBox.customResourceData( id: id, baseResourceId: nil, pathExtension: nil, complete: true, fetch: { return Signal { subscriber in return fetch.signal().start(next: { result in let mappedResult: CachedMediaResourceRepresentationResult switch result { case let .moveTempFile(file): mappedResult = .tempFile(file) } subscriber.putNext(mappedResult) }, completed: { subscriber.putCompletion() }) } }, keepDuration: mappedKeepDuration, attemptSynchronously: attemptSynchronously ) |> map { data in return EngineMediaResource.ResourceData(data) } } public func httpData(url: String) -> Signal { return fetchHttpResource(url: url) |> mapError { _ -> EngineMediaResource.Fetch.Error in return .generic } |> mapToSignal { value -> Signal in switch value { case let .dataPart(_, data, _, _): return .single(data) default: return .complete() } } } public func cancelAllFetches(id: String) { preconditionFailure() } } }