Merge branch 'pr/124' into dev

This commit is contained in:
Francesco 2025-05-07 18:19:41 +02:00
commit 298bd88fd9
7 changed files with 192 additions and 166 deletions

View file

@ -18,4 +18,5 @@ struct ContinueWatchingItem: Codable, Identifiable {
let subtitles: String?
let aniListID: Int?
let module: ScrapingModule
let headers: [String:String]?
}

View file

@ -162,7 +162,7 @@ extension JSContext {
if(method != "GET")
{
// Ensure body is properly serialized
processedBody = body ? JSON.stringify(body) : null
processedBody = (body && (typeof body === 'object')) ? JSON.stringify(body) : (body || null)
}
return new Promise(function(resolve, reject) {

View file

@ -9,9 +9,9 @@ import JavaScriptCore
extension JSController {
func fetchStreamUrl(episodeUrl: String, softsub: Bool = false, module: ScrapingModule, completion: @escaping ((streams: [String]?, subtitles: [String]?)) -> Void) {
func fetchStreamUrl(episodeUrl: String, softsub: Bool = false, module: ScrapingModule, completion: @escaping ((streams: [String]?, subtitles: [String]?, sources: [[String:Any]]? )) -> Void) {
guard let url = URL(string: episodeUrl) else {
completion((nil, nil))
completion((nil, nil,nil))
return
}
@ -20,13 +20,13 @@ extension JSController {
if let error = error {
Logger.shared.log("Network error: \(error)", type: "Error")
DispatchQueue.main.async { completion((nil, nil)) }
DispatchQueue.main.async { completion((nil, nil,nil)) }
return
}
guard let data = data, let html = String(data: data, encoding: .utf8) else {
Logger.shared.log("Failed to decode HTML", type: "Error")
DispatchQueue.main.async { completion((nil, nil)) }
DispatchQueue.main.async { completion((nil, nil, nil)) }
return
}
@ -36,10 +36,21 @@ extension JSController {
if let data = resultString.data(using: .utf8) {
do {
if let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
print("JSON DATA IS \(json) 2")
var streamUrls: [String]? = nil
var subtitleUrls: [String]? = nil
if let streamsArray = json["streams"] as? [String] {
var streamUrlsAndHeaders : [[String:Any]]? = nil
if let streamSources = json["streams"] as? [[String:Any]]
{
streamUrlsAndHeaders = streamSources
Logger.shared.log("Found \(streamSources.count) streams and headers", type: "Stream")
}
else if let streamSource = json["stream"] as? [String:Any]
{
streamUrlsAndHeaders = [streamSource]
Logger.shared.log("Found single stream with headers", type: "Stream")
}
else if let streamsArray = json["streams"] as? [String] {
streamUrls = streamsArray
Logger.shared.log("Found \(streamsArray.count) streams", type: "Stream")
} else if let streamUrl = json["stream"] as? String {
@ -57,45 +68,45 @@ extension JSController {
Logger.shared.log("Starting stream with \(streamUrls?.count ?? 0) sources and \(subtitleUrls?.count ?? 0) subtitles", type: "Stream")
DispatchQueue.main.async {
completion((streamUrls, subtitleUrls))
completion((streamUrls, subtitleUrls,streamUrlsAndHeaders))
}
return
}
if let streamsArray = try? JSONSerialization.jsonObject(with: data, options: []) as? [String] {
Logger.shared.log("Starting multi-stream with \(streamsArray.count) sources", type: "Stream")
DispatchQueue.main.async { completion((streamsArray, nil)) }
DispatchQueue.main.async { completion((streamsArray, nil,nil)) }
return
}
}
}
Logger.shared.log("Starting stream from: \(resultString)", type: "Stream")
DispatchQueue.main.async { completion(([resultString], nil)) }
DispatchQueue.main.async { completion(([resultString], nil,nil)) }
} else {
Logger.shared.log("Failed to extract stream URL", type: "Error")
DispatchQueue.main.async { completion((nil, nil)) }
DispatchQueue.main.async { completion((nil, nil,nil)) }
}
}.resume()
}
func fetchStreamUrlJS(episodeUrl: String, softsub: Bool = false, module: ScrapingModule, completion: @escaping ((streams: [String]?, subtitles: [String]?)) -> Void) {
func fetchStreamUrlJS(episodeUrl: String, softsub: Bool = false, module: ScrapingModule, completion: @escaping ((streams: [String]?, subtitles: [String]?,sources: [[String:Any]]? )) -> Void) {
if let exception = context.exception {
Logger.shared.log("JavaScript exception: \(exception)", type: "Error")
completion((nil, nil))
completion((nil, nil,nil))
return
}
guard let extractStreamUrlFunction = context.objectForKeyedSubscript("extractStreamUrl") else {
Logger.shared.log("No JavaScript function extractStreamUrl found", type: "Error")
completion((nil, nil))
completion((nil, nil,nil))
return
}
let promiseValue = extractStreamUrlFunction.call(withArguments: [episodeUrl])
guard let promise = promiseValue else {
Logger.shared.log("extractStreamUrl did not return a Promise", type: "Error")
completion((nil, nil))
completion((nil, nil,nil))
return
}
@ -106,10 +117,21 @@ extension JSController {
let data = jsonString.data(using: .utf8) {
do {
if let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
print("JSON object is \(json) 1")
var streamUrls: [String]? = nil
var subtitleUrls: [String]? = nil
if let streamsArray = json["streams"] as? [String] {
var streamUrlsAndHeaders : [[String:Any]]? = nil
if let streamSources = json["streams"] as? [[String:Any]]
{
streamUrlsAndHeaders = streamSources
Logger.shared.log("Found \(streamSources.count) streams and headers", type: "Stream")
}
else if let streamSource = json["stream"] as? [String:Any]
{
streamUrlsAndHeaders = [streamSource]
Logger.shared.log("Found single stream with headers", type: "Stream")
}
else if let streamsArray = json["streams"] as? [String] {
streamUrls = streamsArray
Logger.shared.log("Found \(streamsArray.count) streams", type: "Stream")
} else if let streamUrl = json["stream"] as? String {
@ -127,14 +149,14 @@ extension JSController {
Logger.shared.log("Starting stream with \(streamUrls?.count ?? 0) sources and \(subtitleUrls?.count ?? 0) subtitles", type: "Stream")
DispatchQueue.main.async {
completion((streamUrls, subtitleUrls))
completion((streamUrls, subtitleUrls,streamUrlsAndHeaders))
}
return
}
if let streamsArray = try? JSONSerialization.jsonObject(with: data, options: []) as? [String] {
Logger.shared.log("Starting multi-stream with \(streamsArray.count) sources", type: "Stream")
DispatchQueue.main.async { completion((streamsArray, nil)) }
DispatchQueue.main.async { completion((streamsArray, nil,nil)) }
return
}
}
@ -143,14 +165,14 @@ extension JSController {
let streamUrl = result.toString()
Logger.shared.log("Starting stream from: \(streamUrl ?? "nil")", type: "Stream")
DispatchQueue.main.async {
completion((streamUrl != nil ? [streamUrl!] : nil, nil))
completion((streamUrl != nil ? [streamUrl!] : nil, nil,nil))
}
}
let catchBlock: @convention(block) (JSValue) -> Void = { error in
Logger.shared.log("Promise rejected: \(String(describing: error.toString()))", type: "Error")
DispatchQueue.main.async {
completion((nil, nil))
completion((nil, nil,nil))
}
}
@ -161,40 +183,40 @@ extension JSController {
promise.invokeMethod("catch", withArguments: [catchFunction as Any])
}
func fetchStreamUrlJSSecond(episodeUrl: String, softsub: Bool = false, module: ScrapingModule, completion: @escaping ((streams: [String]?, subtitles: [String]?)) -> Void) {
func fetchStreamUrlJSSecond(episodeUrl: String, softsub: Bool = false, module: ScrapingModule, completion: @escaping ((streams: [String]?, subtitles: [String]?,sources: [[String:Any]]? )) -> Void) {
let url = URL(string: episodeUrl)!
let task = URLSession.custom.dataTask(with: url) { [weak self] data, response, error in
guard let self = self else { return }
if let error = error {
Logger.shared.log("URLSession error: \(error.localizedDescription)", type: "Error")
DispatchQueue.main.async { completion((nil, nil)) }
DispatchQueue.main.async { completion((nil, nil,nil)) }
return
}
guard let data = data, let htmlString = String(data: data, encoding: .utf8) else {
Logger.shared.log("Failed to fetch HTML data", type: "Error")
DispatchQueue.main.async { completion((nil, nil)) }
DispatchQueue.main.async { completion((nil, nil, nil)) }
return
}
DispatchQueue.main.async {
if let exception = self.context.exception {
Logger.shared.log("JavaScript exception: \(exception)", type: "Error")
completion((nil, nil))
completion((nil, nil, nil))
return
}
guard let extractStreamUrlFunction = self.context.objectForKeyedSubscript("extractStreamUrl") else {
Logger.shared.log("No JavaScript function extractStreamUrl found", type: "Error")
completion((nil, nil))
completion((nil, nil, nil))
return
}
let promiseValue = extractStreamUrlFunction.call(withArguments: [htmlString])
guard let promise = promiseValue else {
Logger.shared.log("extractStreamUrl did not return a Promise", type: "Error")
completion((nil, nil))
completion((nil, nil, nil))
return
}
@ -205,10 +227,21 @@ extension JSController {
let data = jsonString.data(using: .utf8) {
do {
if let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
print("JSON object is \(json) 3 ")
var streamUrls: [String]? = nil
var subtitleUrls: [String]? = nil
if let streamsArray = json["streams"] as? [String] {
var streamUrlsAndHeaders : [[String:Any]]? = nil
if let streamSources = json["streams"] as? [[String:Any]]
{
streamUrlsAndHeaders = streamSources
Logger.shared.log("Found \(streamSources.count) streams and headers", type: "Stream")
}
else if let streamSource = json["stream"] as? [String:Any]
{
streamUrlsAndHeaders = [streamSource]
Logger.shared.log("Found single stream with headers", type: "Stream")
}
else if let streamsArray = json["streams"] as? [String] {
streamUrls = streamsArray
Logger.shared.log("Found \(streamsArray.count) streams", type: "Stream")
} else if let streamUrl = json["stream"] as? String {
@ -226,14 +259,14 @@ extension JSController {
Logger.shared.log("Starting stream with \(streamUrls?.count ?? 0) sources and \(subtitleUrls?.count ?? 0) subtitles", type: "Stream")
DispatchQueue.main.async {
completion((streamUrls, subtitleUrls))
completion((streamUrls, subtitleUrls, streamUrlsAndHeaders))
}
return
}
if let streamsArray = try? JSONSerialization.jsonObject(with: data, options: []) as? [String] {
Logger.shared.log("Starting multi-stream with \(streamsArray.count) sources", type: "Stream")
DispatchQueue.main.async { completion((streamsArray, nil)) }
DispatchQueue.main.async { completion((streamsArray, nil, nil)) }
return
}
}
@ -242,14 +275,14 @@ extension JSController {
let streamUrl = result.toString()
Logger.shared.log("Starting stream from: \(streamUrl ?? "nil")", type: "Stream")
DispatchQueue.main.async {
completion((streamUrl != nil ? [streamUrl!] : nil, nil))
completion((streamUrl != nil ? [streamUrl!] : nil, nil, nil))
}
}
let catchBlock: @convention(block) (JSValue) -> Void = { error in
Logger.shared.log("Promise rejected: \(String(describing: error.toString()))", type: "Error")
DispatchQueue.main.async {
completion((nil, nil))
completion((nil, nil, nil))
}
}

View file

@ -22,6 +22,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
let subtitlesURL: String?
let onWatchNext: () -> Void
let aniListID: Int
var headers: [String:String]? = nil
private var aniListUpdatedSuccessfully = false
private var aniListUpdateImpossible: Bool = false
@ -177,7 +178,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
onWatchNext: @escaping () -> Void,
subtitlesURL: String?,
aniListID: Int,
episodeImageUrl: String) {
episodeImageUrl: String,headers:[String:String]?) {
self.module = module
self.streamURL = urlString
@ -188,6 +189,7 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
self.onWatchNext = onWatchNext
self.subtitlesURL = subtitlesURL
self.aniListID = aniListID
self.headers = headers
super.init(nibName: nil, bundle: nil)
@ -196,8 +198,18 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
}
var request = URLRequest(url: url)
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Referer")
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Origin")
if let mydict = headers, !mydict.isEmpty
{
for (key,value) in mydict
{
request.addValue(value, forHTTPHeaderField: key)
}
}
else
{
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Referer")
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Origin")
}
request.addValue("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
forHTTPHeaderField: "User-Agent")
@ -1380,7 +1392,8 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
fullUrl: self.fullUrl,
subtitles: self.subtitlesURL,
aniListID: self.aniListID,
module: self.module
module: self.module,
headers: self.headers
)
ContinueWatchingManager.shared.save(item: item)
}
@ -1712,8 +1725,18 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
private func parseM3U8(url: URL, completion: @escaping () -> Void) {
var request = URLRequest(url: url)
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Referer")
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Origin")
if let mydict = headers, !mydict.isEmpty
{
for (key,value) in mydict
{
request.addValue(value, forHTTPHeaderField: key)
}
}
else
{
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Referer")
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Origin")
}
request.addValue("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
forHTTPHeaderField: "User-Agent")
@ -1799,8 +1822,18 @@ class CustomMediaPlayerViewController: UIViewController, UIGestureRecognizerDele
let wasPlaying = player.rate > 0
var request = URLRequest(url: url)
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Referer")
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Origin")
if let mydict = headers, !mydict.isEmpty
{
for (key,value) in mydict
{
request.addValue(value, forHTTPHeaderField: key)
}
}
else
{
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Referer")
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Origin")
}
request.addValue("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36",
forHTTPHeaderField: "User-Agent")

View file

@ -18,6 +18,7 @@ class VideoPlayerViewController: UIViewController {
var fullUrl: String = ""
var subtitles: String = ""
var aniListID: Int = 0
var headers: [String:String]? = nil
var episodeNumber: Int = 0
var episodeImageUrl: String = ""
@ -40,8 +41,18 @@ class VideoPlayerViewController: UIViewController {
}
var request = URLRequest(url: url)
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Referer")
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Origin")
if let mydict = headers, !mydict.isEmpty
{
for (key,value) in mydict
{
request.addValue(value, forHTTPHeaderField: key)
}
}
else
{
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Referer")
request.addValue("\(module.metadata.baseUrl)", forHTTPHeaderField: "Origin")
}
request.addValue("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36", forHTTPHeaderField: "User-Agent")
let asset = AVURLAsset(url: url, options: ["AVURLAssetHTTPHeaderFieldsKey": request.allHTTPHeaderFields ?? [:]])
@ -127,7 +138,8 @@ class VideoPlayerViewController: UIViewController {
fullUrl: self.fullUrl,
subtitles: self.subtitles,
aniListID: self.aniListID,
module: self.module
module: self.module,
headers: self.headers
)
ContinueWatchingManager.shared.save(item: item)
}

View file

@ -272,7 +272,9 @@ struct ContinueWatchingCell: View {
onWatchNext: { },
subtitlesURL: item.subtitles,
aniListID: item.aniListID ?? 0,
episodeImageUrl: item.imageUrl
episodeImageUrl: item.imageUrl,
headers: item.headers ?? nil
)
customMediaPlayer.modalPresentationStyle = .fullScreen

View file

@ -643,119 +643,41 @@ struct MediaInfoView: View {
currentStreamTitle = "Episode \(selectedEpisodeNumber)"
showStreamLoadingView = true
isFetchingEpisode = true
let completion: ((streams: [String]?, subtitles: [String]?, sources: [[String: Any]]?)) -> Void = { result in
guard self.activeFetchID == fetchID else { return }
if let streams = result.sources, !streams.isEmpty{
if streams.count > 1 {
self.showStreamSelectionAlert(streams: streams, fullURL: href, subtitles: result.subtitles?.first)
} else {
self.playStream(url: streams[0]["streamUrl"] as? String ?? "", fullURL: href, subtitles: streams[0]["subtitle"] as? String ?? "",headers: streams[0]["headers"] as! [String : String])
}
}
else if let streams = result.streams, !streams.isEmpty {
if streams.count > 1 {
self.showStreamSelectionAlert(streams: streams, fullURL: href, subtitles: result.subtitles?.first)
} else {
self.playStream(url: streams[0], fullURL: href, subtitles: result.subtitles?.first)
}
} else {
self.handleStreamFailure(error: nil)
}
DispatchQueue.main.async {
self.isFetchingEpisode = false
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
Task {
do {
let jsContent = try moduleManager.getModuleContent(module)
jsController.loadScript(jsContent)
if module.metadata.softsub == true {
if module.metadata.asyncJS == true {
jsController.fetchStreamUrlJS(episodeUrl: href, softsub: true, module: module) { result in
guard self.activeFetchID == fetchID else { return }
if let streams = result.streams, !streams.isEmpty {
if streams.count > 1 {
self.showStreamSelectionAlert(streams: streams, fullURL: href, subtitles: result.subtitles?.first)
} else {
self.playStream(url: streams[0], fullURL: href, subtitles: result.subtitles?.first)
}
} else {
self.handleStreamFailure(error: nil)
}
DispatchQueue.main.async {
self.isFetchingEpisode = false
}
}
} else if module.metadata.streamAsyncJS == true {
jsController.fetchStreamUrlJSSecond(episodeUrl: href, softsub: true, module: module) { result in
guard self.activeFetchID == fetchID else { return }
if let streams = result.streams, !streams.isEmpty {
if streams.count > 1 {
self.showStreamSelectionAlert(streams: streams, fullURL: href, subtitles: result.subtitles?.first)
} else {
self.playStream(url: streams[0], fullURL: href, subtitles: result.subtitles?.first)
}
} else {
self.handleStreamFailure(error: nil)
}
DispatchQueue.main.async {
self.isFetchingEpisode = false
}
}
} else {
jsController.fetchStreamUrl(episodeUrl: href, softsub: true, module: module) { result in
guard self.activeFetchID == fetchID else { return }
if let streams = result.streams, !streams.isEmpty {
if streams.count > 1 {
self.showStreamSelectionAlert(streams: streams, fullURL: href, subtitles: result.subtitles?.first)
} else {
self.playStream(url: streams[0], fullURL: href, subtitles: result.subtitles?.first)
}
} else {
self.handleStreamFailure(error: nil)
}
DispatchQueue.main.async {
self.isFetchingEpisode = false
}
}
}
if module.metadata.asyncJS == true {
jsController.fetchStreamUrlJS(episodeUrl: href, softsub: module.metadata.softsub == true, module: module, completion: completion)
} else if module.metadata.streamAsyncJS == true {
jsController.fetchStreamUrlJSSecond(episodeUrl: href, softsub: module.metadata.softsub == true, module: module, completion: completion)
} else {
if module.metadata.asyncJS == true {
jsController.fetchStreamUrlJS(episodeUrl: href, module: module) { result in
guard self.activeFetchID == fetchID else { return }
if let streams = result.streams, !streams.isEmpty {
if streams.count > 1 {
self.showStreamSelectionAlert(streams: streams, fullURL: href, subtitles: result.subtitles?.first)
} else {
self.playStream(url: streams[0], fullURL: href, subtitles: result.subtitles?.first)
}
} else {
self.handleStreamFailure(error: nil)
}
DispatchQueue.main.async {
self.isFetchingEpisode = false
}
}
} else if module.metadata.streamAsyncJS == true {
jsController.fetchStreamUrlJSSecond(episodeUrl: href, module: module) { result in
guard self.activeFetchID == fetchID else { return }
if let streams = result.streams, !streams.isEmpty {
if streams.count > 1 {
self.showStreamSelectionAlert(streams: streams, fullURL: href, subtitles: result.subtitles?.first)
} else {
self.playStream(url: streams[0], fullURL: href, subtitles: result.subtitles?.first)
}
} else {
self.handleStreamFailure(error: nil)
}
DispatchQueue.main.async {
self.isFetchingEpisode = false
}
}
} else {
jsController.fetchStreamUrl(episodeUrl: href, module: module) { result in
guard self.activeFetchID == fetchID else { return }
if let streams = result.streams, !streams.isEmpty {
if streams.count > 1 {
self.showStreamSelectionAlert(streams: streams, fullURL: href, subtitles: result.subtitles?.first)
} else {
self.playStream(url: streams[0], fullURL: href, subtitles: result.subtitles?.first)
}
} else {
self.handleStreamFailure(error: nil)
}
DispatchQueue.main.async {
self.isFetchingEpisode = false
}
}
}
jsController.fetchStreamUrl(episodeUrl: href, softsub: module.metadata.softsub == true, module: module, completion: completion)
}
} catch {
self.handleStreamFailure(error: error)
DispatchQueue.main.async {
@ -779,9 +701,10 @@ struct MediaInfoView: View {
self.isLoading = false
}
func showStreamSelectionAlert(streams: [String], fullURL: String, subtitles: String? = nil) {
func showStreamSelectionAlert(streams: [Any], fullURL: String, subtitles: String? = nil) {
self.isFetchingEpisode = false
self.showStreamLoadingView = false
print("MULTIPLE STREAMS \(streams)")
DispatchQueue.main.async {
let alert = UIAlertController(title: "Select Server", message: "Choose a server to play from", preferredStyle: .actionSheet)
@ -789,27 +712,46 @@ struct MediaInfoView: View {
var streamIndex = 1
while index < streams.count {
let title: String
let streamUrl: String
if index + 1 < streams.count {
if !streams[index].lowercased().contains("http") {
title = streams[index]
streamUrl = streams[index + 1]
index += 2
var title: String = ""
var streamUrl: String = ""
var headers: [String:String]? = nil
if let streams = streams as? [String]
{
if index + 1 < streams.count {
if !streams[index].lowercased().contains("http") {
title = streams[index]
streamUrl = streams[index + 1]
index += 2
} else {
title = "Stream \(streamIndex)"
streamUrl = streams[index]
index += 1
}
} else {
title = "Stream \(streamIndex)"
streamUrl = streams[index]
index += 1
}
} else {
title = "Stream \(streamIndex)"
streamUrl = streams[index]
}
else if let streams = streams as? [[String: Any]]
{
if let currTitle = streams[index]["title"] as? String
{
title = currTitle
streamUrl = (streams[index]["streamUrl"] as? String) ?? ""
}
else
{
title = "Stream \(streamIndex)"
streamUrl = (streams[index]["streamUrl"] as? String)!
}
headers = streams[index]["headers"] as? [String:String] ?? [:]
index += 1
}
alert.addAction(UIAlertAction(title: title, style: .default) { _ in
self.playStream(url: streamUrl, fullURL: fullURL, subtitles: subtitles)
self.playStream(url: streamUrl, fullURL: fullURL, subtitles: subtitles,headers: headers)
})
streamIndex += 1
@ -843,7 +785,7 @@ struct MediaInfoView: View {
}
}
func playStream(url: String, fullURL: String, subtitles: String? = nil) {
func playStream(url: String, fullURL: String, subtitles: String? = nil,headers: [String:String]? = nil) {
self.isFetchingEpisode = false
self.showStreamLoadingView = false
DispatchQueue.main.async {
@ -863,6 +805,7 @@ struct MediaInfoView: View {
scheme = "SenPlayer://x-callback-url/play?url=\(url)"
case "Default":
let videoPlayerViewController = VideoPlayerViewController(module: module)
videoPlayerViewController.headers = headers
videoPlayerViewController.streamUrl = url
videoPlayerViewController.fullUrl = fullURL
videoPlayerViewController.episodeNumber = selectedEpisodeNumber
@ -892,6 +835,7 @@ struct MediaInfoView: View {
}
let customMediaPlayer = CustomMediaPlayerViewController(
module: module,
urlString: url.absoluteString,
fullUrl: fullURL,
@ -902,7 +846,8 @@ struct MediaInfoView: View {
},
subtitlesURL: subtitles,
aniListID: itemID ?? 0,
episodeImageUrl: selectedEpisodeImage
episodeImageUrl: selectedEpisodeImage,
headers: headers ?? nil
)
customMediaPlayer.modalPresentationStyle = .fullScreen
Logger.shared.log("Opening custom media player with url: \(url)")