diff --git a/Sora/Utils/Loaders/JSController.swift b/Sora/Utils/Loaders/JSController.swift index 37c9616..66fad60 100644 --- a/Sora/Utils/Loaders/JSController.swift +++ b/Sora/Utils/Loaders/JSController.swift @@ -388,4 +388,46 @@ class JSController: ObservableObject { completion(resultItems, episodeLinks) } } + + func fetchStreamUrlJS(episodeUrl: String, completion: @escaping (String?) -> Void) { + if let exception = context.exception { + Logger.shared.log("JavaScript exception: \(exception)", type: "Error") + completion(nil) + return + } + + guard let extractStreamUrlFunction = context.objectForKeyedSubscript("extractStreamUrl") else { + Logger.shared.log("No JavaScript function extractStreamUrl found", type: "Error") + completion(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) + return + } + + let thenBlock: @convention(block) (JSValue) -> Void = { result in + let streamUrl = result.toString() + Logger.shared.log("Starting stream from: \(streamUrl ?? "nil")", type: "Stream") + DispatchQueue.main.async { + completion(streamUrl) + } + } + + let catchBlock: @convention(block) (JSValue) -> Void = { error in + Logger.shared.log("Promise rejected: \(String(describing: error.toString()))", type: "Error") + DispatchQueue.main.async { + completion(nil) + } + } + + let thenFunction = JSValue(object: thenBlock, in: context) + let catchFunction = JSValue(object: catchBlock, in: context) + + promise.invokeMethod("then", withArguments: [thenFunction as Any]) + promise.invokeMethod("catch", withArguments: [catchFunction as Any]) + } } diff --git a/Sora/Views/MediaInfoView/MediaInfoView.swift b/Sora/Views/MediaInfoView/MediaInfoView.swift index fcd7fbe..4a00de2 100644 --- a/Sora/Views/MediaInfoView/MediaInfoView.swift +++ b/Sora/Views/MediaInfoView/MediaInfoView.swift @@ -235,11 +235,20 @@ struct MediaInfoView: View { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { Task { do { + print(href) let jsContent = try moduleManager.getModuleContent(module) jsController.loadScript(jsContent) - jsController.fetchStreamUrl(episodeUrl: href) { streamUrl in - if let url = streamUrl { - playStream(url: url, fullURL: href) + if module.metadata.asyncJS == true { + jsController.fetchStreamUrlJS(episodeUrl: href) { streamUrl in + if let url = streamUrl { + playStream(url: url, fullURL: href) + } + } + } else { + jsController.fetchStreamUrl(episodeUrl: href) { streamUrl in + if let url = streamUrl { + playStream(url: url, fullURL: href) + } } } } catch { @@ -256,7 +265,7 @@ struct MediaInfoView: View { videoPlayerViewController.streamUrl = url videoPlayerViewController.fullUrl = fullURL videoPlayerViewController.modalPresentationStyle = .fullScreen - + print(url) if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let rootVC = windowScene.windows.first?.rootViewController { rootVC.present(videoPlayerViewController, animated: true, completion: nil)