mirror of
https://github.com/yattee/yattee.git
synced 2024-12-22 21:43:41 +00:00
Merge pull request #696 from stonerl/improved-conditional-proxying
improved conditional proxying
This commit is contained in:
commit
1ed4c20c3a
@ -56,65 +56,85 @@ extension PlayerModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func streamsWithInstance(instance _: Instance, streams: [Stream], completion: @escaping ([Stream]) -> Void) {
|
func streamsWithInstance(instance: Instance, streams: [Stream], completion: @escaping ([Stream]) -> Void) {
|
||||||
// Queue for stream processing
|
// Queue for stream processing
|
||||||
let streamProcessingQueue = DispatchQueue(label: "stream.yattee.streamProcessing.Queue", qos: .userInitiated)
|
let streamProcessingQueue = DispatchQueue(label: "stream.yattee.streamProcessing.Queue")
|
||||||
// Queue for accessing the processedStreams array
|
// Queue for accessing the processedStreams array
|
||||||
let processedStreamsQueue = DispatchQueue(label: "stream.yattee.processedStreams.Queue")
|
let processedStreamsQueue = DispatchQueue(label: "stream.yattee.processedStreams.Queue")
|
||||||
// DispatchGroup for managing multiple tasks
|
// DispatchGroup for managing multiple tasks
|
||||||
let streamProcessingGroup = DispatchGroup()
|
let streamProcessingGroup = DispatchGroup()
|
||||||
|
|
||||||
var processedStreams = [Stream]()
|
var processedStreams = [Stream]()
|
||||||
|
let instance = instance
|
||||||
|
|
||||||
|
var hasForbiddenAsset = false
|
||||||
|
var hasAllowedAsset = false
|
||||||
|
|
||||||
for stream in streams {
|
for stream in streams {
|
||||||
streamProcessingQueue.async(group: streamProcessingGroup) {
|
streamProcessingQueue.async(group: streamProcessingGroup) {
|
||||||
let forbiddenAssetTestGroup = DispatchGroup()
|
let forbiddenAssetTestGroup = DispatchGroup()
|
||||||
var hasForbiddenAsset = false
|
if !hasAllowedAsset, !hasForbiddenAsset, !instance.proxiesVideos, stream.format != Stream.Format.unknown {
|
||||||
|
|
||||||
let (nonHLSAssets, hlsURLs) = self.getAssets(from: [stream])
|
let (nonHLSAssets, hlsURLs) = self.getAssets(from: [stream])
|
||||||
|
if let firstStream = nonHLSAssets.first {
|
||||||
|
let asset = firstStream.0
|
||||||
|
let url = firstStream.1
|
||||||
|
let requestRange = firstStream.2
|
||||||
|
|
||||||
if let randomStream = nonHLSAssets.randomElement() {
|
|
||||||
let instance = randomStream.0
|
|
||||||
let asset = randomStream.1
|
|
||||||
let url = randomStream.2
|
|
||||||
let requestRange = randomStream.3
|
|
||||||
|
|
||||||
// swiftlint:disable:next shorthand_optional_binding
|
|
||||||
if let asset = asset, let instance = instance, !instance.proxiesVideos {
|
|
||||||
if instance.app == .invidious {
|
if instance.app == .invidious {
|
||||||
self.testAsset(url: url, range: requestRange, isHLS: false, forbiddenAssetTestGroup: forbiddenAssetTestGroup) { isForbidden in
|
self.testAsset(url: url, range: requestRange, isHLS: false, forbiddenAssetTestGroup: forbiddenAssetTestGroup) { status in
|
||||||
hasForbiddenAsset = isForbidden
|
switch status {
|
||||||
|
case HTTPStatus.Forbidden:
|
||||||
|
hasForbiddenAsset = true
|
||||||
|
case HTTPStatus.PartialContent:
|
||||||
|
hasAllowedAsset = true
|
||||||
|
case HTTPStatus.OK:
|
||||||
|
hasAllowedAsset = true
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if instance.app == .piped {
|
} else if instance.app == .piped {
|
||||||
self.testPipedAssets(asset: asset, requestRange: requestRange, isHLS: false, forbiddenAssetTestGroup: forbiddenAssetTestGroup) { isForbidden in
|
self.testPipedAssets(asset: asset!, requestRange: requestRange, isHLS: false, forbiddenAssetTestGroup: forbiddenAssetTestGroup) { status in
|
||||||
hasForbiddenAsset = isForbidden
|
switch status {
|
||||||
|
case HTTPStatus.Forbidden:
|
||||||
|
hasForbiddenAsset = true
|
||||||
|
case HTTPStatus.PartialContent:
|
||||||
|
hasAllowedAsset = true
|
||||||
|
case HTTPStatus.OK:
|
||||||
|
hasAllowedAsset = true
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let randomHLS = hlsURLs.randomElement() {
|
} else if let firstHLS = hlsURLs.first {
|
||||||
let instance = randomHLS.0
|
let asset = AVURLAsset(url: firstHLS)
|
||||||
let asset = AVURLAsset(url: randomHLS.1)
|
if instance.app == .piped {
|
||||||
|
self.testPipedAssets(asset: asset, requestRange: nil, isHLS: true, forbiddenAssetTestGroup: forbiddenAssetTestGroup) { status in
|
||||||
if instance?.app == .piped {
|
switch status {
|
||||||
self.testPipedAssets(asset: asset, requestRange: nil, isHLS: true, forbiddenAssetTestGroup: forbiddenAssetTestGroup) { isForbidden in
|
case HTTPStatus.Forbidden:
|
||||||
hasForbiddenAsset = isForbidden
|
hasForbiddenAsset = true
|
||||||
|
case HTTPStatus.PartialContent:
|
||||||
|
hasAllowedAsset = true
|
||||||
|
case HTTPStatus.OK:
|
||||||
|
hasAllowedAsset = true
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
forbiddenAssetTestGroup.wait()
|
forbiddenAssetTestGroup.wait()
|
||||||
|
|
||||||
// Post-processing code
|
// Post-processing code
|
||||||
if let instance = stream.instance {
|
if instance.app == .invidious, hasForbiddenAsset || instance.proxiesVideos {
|
||||||
if instance.app == .invidious {
|
|
||||||
if hasForbiddenAsset || instance.proxiesVideos {
|
|
||||||
if let audio = stream.audioAsset {
|
if let audio = stream.audioAsset {
|
||||||
stream.audioAsset = InvidiousAPI.proxiedAsset(instance: instance, asset: audio)
|
stream.audioAsset = InvidiousAPI.proxiedAsset(instance: instance, asset: audio)
|
||||||
}
|
}
|
||||||
if let video = stream.videoAsset {
|
if let video = stream.videoAsset {
|
||||||
stream.videoAsset = InvidiousAPI.proxiedAsset(instance: instance, asset: video)
|
stream.videoAsset = InvidiousAPI.proxiedAsset(instance: instance, asset: video)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if instance.app == .piped, !instance.proxiesVideos, !hasForbiddenAsset {
|
} else if instance.app == .piped, !instance.proxiesVideos, !hasForbiddenAsset {
|
||||||
if let hlsURL = stream.hlsURL {
|
if let hlsURL = stream.hlsURL {
|
||||||
PipedAPI.nonProxiedAsset(url: hlsURL) { possibleNonProxiedURL in
|
PipedAPI.nonProxiedAsset(url: hlsURL) { possibleNonProxiedURL in
|
||||||
@ -135,7 +155,6 @@ extension PlayerModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Append to processedStreams within the processedStreamsQueue
|
// Append to processedStreams within the processedStreamsQueue
|
||||||
processedStreamsQueue.sync {
|
processedStreamsQueue.sync {
|
||||||
@ -152,21 +171,21 @@ extension PlayerModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getAssets(from streams: [Stream]) -> (nonHLSAssets: [(Instance?, AVURLAsset?, URL, String?)], hlsURLs: [(Instance?, URL)]) {
|
private func getAssets(from streams: [Stream]) -> (nonHLSAssets: [(AVURLAsset?, URL, String?)], hlsURLs: [URL]) {
|
||||||
var nonHLSAssets = [(Instance?, AVURLAsset?, URL, String?)]()
|
var nonHLSAssets = [(AVURLAsset?, URL, String?)]()
|
||||||
var hlsURLs = [(Instance?, URL)]()
|
var hlsURLs = [URL]()
|
||||||
|
|
||||||
for stream in streams {
|
for stream in streams {
|
||||||
if stream.isHLS {
|
if stream.isHLS {
|
||||||
if let url = stream.hlsURL?.url {
|
if let url = stream.hlsURL?.url {
|
||||||
hlsURLs.append((stream.instance, url))
|
hlsURLs.append(url)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let asset = stream.audioAsset {
|
if let asset = stream.audioAsset {
|
||||||
nonHLSAssets.append((stream.instance, asset, asset.url, stream.requestRange))
|
nonHLSAssets.append((asset, asset.url, stream.requestRange))
|
||||||
}
|
}
|
||||||
if let asset = stream.videoAsset {
|
if let asset = stream.videoAsset {
|
||||||
nonHLSAssets.append((stream.instance, asset, asset.url, stream.requestRange))
|
nonHLSAssets.append((asset, asset.url, stream.requestRange))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,24 +193,24 @@ extension PlayerModel {
|
|||||||
return (nonHLSAssets, hlsURLs)
|
return (nonHLSAssets, hlsURLs)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func testAsset(url: URL, range: String?, isHLS: Bool, forbiddenAssetTestGroup: DispatchGroup, completion: @escaping (Bool) -> Void) {
|
private func testAsset(url: URL, range: String?, isHLS: Bool, forbiddenAssetTestGroup: DispatchGroup, completion: @escaping (Int) -> Void) {
|
||||||
// In case the range is nil, generate a random one.
|
// In case the range is nil, generate a random one.
|
||||||
let randomEnd = Int.random(in: 200 ... 800)
|
let randomEnd = Int.random(in: 200 ... 800)
|
||||||
let requestRange = range ?? "0-\(randomEnd)"
|
let requestRange = range ?? "0-\(randomEnd)"
|
||||||
|
|
||||||
forbiddenAssetTestGroup.enter()
|
forbiddenAssetTestGroup.enter()
|
||||||
URLTester.testURLResponse(url: url, range: requestRange, isHLS: isHLS) { statusCode in
|
URLTester.testURLResponse(url: url, range: requestRange, isHLS: isHLS) { statusCode in
|
||||||
completion(statusCode == HTTPStatus.Forbidden)
|
completion(statusCode)
|
||||||
forbiddenAssetTestGroup.leave()
|
forbiddenAssetTestGroup.leave()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func testPipedAssets(asset: AVURLAsset, requestRange: String?, isHLS: Bool, forbiddenAssetTestGroup: DispatchGroup, completion: @escaping (Bool) -> Void) {
|
private func testPipedAssets(asset: AVURLAsset, requestRange: String?, isHLS: Bool, forbiddenAssetTestGroup: DispatchGroup, completion: @escaping (Int) -> Void) {
|
||||||
PipedAPI.nonProxiedAsset(asset: asset) { possibleNonProxiedAsset in
|
PipedAPI.nonProxiedAsset(asset: asset) { possibleNonProxiedAsset in
|
||||||
if let nonProxiedAsset = possibleNonProxiedAsset {
|
if let nonProxiedAsset = possibleNonProxiedAsset {
|
||||||
self.testAsset(url: nonProxiedAsset.url, range: requestRange, isHLS: isHLS, forbiddenAssetTestGroup: forbiddenAssetTestGroup, completion: completion)
|
self.testAsset(url: nonProxiedAsset.url, range: requestRange, isHLS: isHLS, forbiddenAssetTestGroup: forbiddenAssetTestGroup, completion: completion)
|
||||||
} else {
|
} else {
|
||||||
completion(false)
|
completion(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user