diff --git a/.gitmodules b/.gitmodules index 3c5b4994..1db1e78b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -61,3 +61,6 @@ [submodule "dep/futopay"] path = dep/futopay url = ../futopayclientlibraries.git +[submodule "app/src/unstable/assets/sources/niconico"] + path = app/src/unstable/assets/sources/niconico + url = git@gitlab.futo.org:videostreaming/plugins/niconico.git diff --git a/app/src/main/java/com/futo/platformplayer/Extensions_Content.kt b/app/src/main/java/com/futo/platformplayer/Extensions_Content.kt index 39944ee5..d05db15c 100644 --- a/app/src/main/java/com/futo/platformplayer/Extensions_Content.kt +++ b/app/src/main/java/com/futo/platformplayer/Extensions_Content.kt @@ -5,11 +5,23 @@ import com.futo.platformplayer.api.media.models.streams.VideoUnMuxedSourceDescri import com.futo.platformplayer.api.media.models.streams.sources.IAudioSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoSource import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails +import com.futo.platformplayer.api.media.platforms.js.models.sources.JSSource import com.futo.platformplayer.helpers.VideoHelper +import com.futo.platformplayer.views.video.datasources.JSHttpDataSource +import com.google.android.exoplayer2.upstream.DefaultHttpDataSource +import com.google.android.exoplayer2.upstream.HttpDataSource fun IPlatformVideoDetails.isDownloadable(): Boolean = VideoHelper.isDownloadable(this); fun IVideoSource.isDownloadable(): Boolean = VideoHelper.isDownloadable(this); fun IAudioSource.isDownloadable(): Boolean = VideoHelper.isDownloadable(this); +fun JSSource.getHttpDataSourceFactory(): HttpDataSource.Factory { + val requestModifier = getRequestModifier(); + return if (requestModifier != null) { + JSHttpDataSource.Factory().setRequestModifier(requestModifier); + } else { + DefaultHttpDataSource.Factory(); + } +} fun IVideoSourceDescriptor.hasAnySource(): Boolean = this.videoSources.any() || (this is VideoUnMuxedSourceDescriptor && this.audioSources.any()); \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/DevJSClient.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/DevJSClient.kt index 1b929293..47dfb1cb 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/DevJSClient.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/DevJSClient.kt @@ -20,7 +20,7 @@ class DevJSClient : JSClient { val devID: String; - constructor(context: Context, config: SourcePluginConfig, script: String, auth: SourceAuth? = null, captcha: SourceCaptchaData? = null, devID: String? = null): super(context, SourcePluginDescriptor(config, auth?.toEncrypted(), captcha?.toEncrypted(), listOf("DEV")), null, script) { + constructor(context: Context, config: SourcePluginConfig, script: String, auth: SourceAuth? = null, captcha: SourceCaptchaData? = null, devID: String? = null, settings: HashMap? = null): super(context, SourcePluginDescriptor(config, auth?.toEncrypted(), captcha?.toEncrypted(), listOf("DEV"), settings), null, script) { _devScript = script; _auth = auth; _captcha = captcha; @@ -49,7 +49,7 @@ class DevJSClient : JSClient { _auth = auth; } fun recreate(context: Context): DevJSClient { - return DevJSClient(context, config, _devScript, _auth, _captcha, devID); + return DevJSClient(context, config, _devScript, _auth, _captcha, devID, descriptor.settings); } override fun getCopy(): JSClient { diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt index f5f72686..7106f02f 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/JSClient.kt @@ -7,6 +7,7 @@ import com.caoccao.javet.values.primitive.V8ValueInteger import com.caoccao.javet.values.primitive.V8ValueString import com.caoccao.javet.values.reference.V8ValueArray import com.caoccao.javet.values.reference.V8ValueObject +import com.futo.platformplayer.api.http.ManagedHttpClient import com.futo.platformplayer.api.media.IPlatformClient import com.futo.platformplayer.api.media.PlatformClientCapabilities import com.futo.platformplayer.api.media.models.PlatformAuthorLink @@ -67,8 +68,8 @@ open class JSClient : IPlatformClient { var descriptor: SourcePluginDescriptor private set; - private val _client: JSHttpClient; - private val _clientAuth: JSHttpClient?; + private val _httpClient: JSHttpClient; + private val _httpClientAuth: JSHttpClient?; private var _searchCapabilities: ResultCapabilities? = null; private var _searchChannelContentsCapabilities: ResultCapabilities? = null; private var _channelCapabilities: ResultCapabilities? = null; @@ -131,9 +132,9 @@ open class JSClient : IPlatformClient { _captcha = descriptor.getCaptchaData(); flags = descriptor.flags.toTypedArray(); - _client = JSHttpClient(this, null, _captcha); - _clientAuth = JSHttpClient(this, _auth, _captcha); - _plugin = V8Plugin(context, descriptor.config, null, _client, _clientAuth); + _httpClient = JSHttpClient(this, null, _captcha); + _httpClientAuth = JSHttpClient(this, _auth, _captcha); + _plugin = V8Plugin(context, descriptor.config, null, _httpClient, _httpClientAuth); _plugin.withDependency(context, "scripts/polyfil.js"); _plugin.withDependency(context, "scripts/source.js"); @@ -160,9 +161,9 @@ open class JSClient : IPlatformClient { _captcha = descriptor.getCaptchaData(); flags = descriptor.flags.toTypedArray(); - _client = JSHttpClient(this, null, _captcha); - _clientAuth = JSHttpClient(this, _auth, _captcha); - _plugin = V8Plugin(context, descriptor.config, script, _client, _clientAuth); + _httpClient = JSHttpClient(this, null, _captcha); + _httpClientAuth = JSHttpClient(this, _auth, _captcha); + _plugin = V8Plugin(context, descriptor.config, script, _httpClient, _httpClientAuth); _plugin.withDependency(context, "scripts/polyfil.js"); _plugin.withDependency(context, "scripts/source.js"); _plugin.withScript(script); @@ -181,6 +182,13 @@ open class JSClient : IPlatformClient { fun getUnderlyingPlugin(): V8Plugin { return _plugin; } + fun getHttpClientById(id: String): JSHttpClient? { + if(_httpClient.clientId == id) + return _httpClient; + if(_httpClientAuth?.clientId == id) + return _httpClientAuth; + return plugin.httpClientOthers[id]; + } override fun initialize() { Logger.i(TAG, "Plugin [${config.name}] initializing"); @@ -254,7 +262,7 @@ open class JSClient : IPlatformClient { @JSDocs(2, "source.getHome()", "Gets the HomeFeed of the platform") override fun getHome(): IPager = isBusyWith { ensureEnabled(); - return@isBusyWith JSContentPager(config, plugin, + return@isBusyWith JSContentPager(config, this, plugin.executeTyped("source.getHome()")); } @@ -292,7 +300,7 @@ open class JSClient : IPlatformClient { @JSDocsParameter("channelId", "(optional) Channel id to search in") override fun search(query: String, type: String?, order: String?, filters: Map>?): IPager = isBusyWith { ensureEnabled(); - return@isBusyWith JSContentPager(config, plugin, + return@isBusyWith JSContentPager(config, this, plugin.executeTyped("source.search(${Json.encodeToString(query)}, ${Json.encodeToString(type)}, ${Json.encodeToString(order)}, ${Json.encodeToString(filters)})")); } @@ -316,7 +324,7 @@ open class JSClient : IPlatformClient { if(!capabilities.hasSearchChannelContents) throw IllegalStateException("This plugin does not support channel search"); - return@isBusyWith JSContentPager(config, plugin, + return@isBusyWith JSContentPager(config, this, plugin.executeTyped("source.searchChannelContents(${Json.encodeToString(channelUrl)}, ${Json.encodeToString(query)}, ${Json.encodeToString(type)}, ${Json.encodeToString(order)}, ${Json.encodeToString(filters)})")); } @@ -325,7 +333,7 @@ open class JSClient : IPlatformClient { @JSDocsParameter("query", "Query that channels should match") override fun searchChannels(query: String): IPager = isBusyWith { ensureEnabled(); - return@isBusyWith JSChannelPager(config, plugin, + return@isBusyWith JSChannelPager(config, this, plugin.executeTyped("source.searchChannels(${Json.encodeToString(query)})")); } @@ -372,7 +380,7 @@ open class JSClient : IPlatformClient { @JSDocsParameter("filters", "(optional) Filters to apply on contents") override fun getChannelContents(channelUrl: String, type: String?, order: String?, filters: Map>?): IPager = isBusyWith { ensureEnabled(); - return@isBusyWith JSContentPager(config, plugin, + return@isBusyWith JSContentPager(config, this, plugin.executeTyped("source.getChannelContents(${Json.encodeToString(channelUrl)}, ${Json.encodeToString(type)}, ${Json.encodeToString(order)}, ${Json.encodeToString(filters)})")); } @@ -438,7 +446,7 @@ open class JSClient : IPlatformClient { @JSDocsParameter("url", "A content url (this platform)") override fun getContentDetails(url: String): IPlatformContentDetails = isBusyWith { ensureEnabled(); - return@isBusyWith IJSContentDetails.fromV8(config, + return@isBusyWith IJSContentDetails.fromV8(this, plugin.executeTyped("source.getContentDetails(${Json.encodeToString(url)})")); } @@ -476,13 +484,13 @@ open class JSClient : IPlatformClient { if (pager !is V8ValueObject) { //TODO: Maybe solve this better return@isBusyWith EmptyPager(); } - return@isBusyWith JSCommentPager(config, plugin, pager); + return@isBusyWith JSCommentPager(config, this, pager); } @JSDocs(17, "source.getSubComments(comment)", "Gets replies for a given comment") @JSDocsParameter("comment", "Comment object that was returned by getComments") override fun getSubComments(comment: IPlatformComment): IPager { ensureEnabled(); - return comment.getReplies(this) ?: JSCommentPager(config, plugin, + return comment.getReplies(this) ?: JSCommentPager(config, this, plugin.executeTyped("source.getSubComments(${Json.encodeToString(comment as JSComment)})")); } @@ -501,7 +509,7 @@ open class JSClient : IPlatformClient { if(!capabilities.hasGetLiveEvents) return@isBusyWith null; ensureEnabled(); - return@isBusyWith JSLiveEventPager(config, plugin, + return@isBusyWith JSLiveEventPager(config, this, plugin.executeTyped("source.getLiveEvents(${Json.encodeToString(url)})")); } @JSDocs(19, "source.searchPlaylists(query)", "Searches for playlists on the platform") @@ -514,7 +522,7 @@ open class JSClient : IPlatformClient { ensureEnabled(); if(!capabilities.hasSearchPlaylists) throw IllegalStateException("This plugin does not support playlist search"); - return@isBusyWith JSContentPager(config, plugin, plugin.executeTyped("source.searchPlaylists(${Json.encodeToString(query)}, ${Json.encodeToString(type)}, ${Json.encodeToString(order)}, ${Json.encodeToString(filters)})")); + return@isBusyWith JSContentPager(config, this, plugin.executeTyped("source.searchPlaylists(${Json.encodeToString(query)}, ${Json.encodeToString(type)}, ${Json.encodeToString(order)}, ${Json.encodeToString(filters)})")); } @JSOptional @JSDocs(20, "source.isPlaylistUrl(url)", "Validates if a playlist url is for this platform") @@ -530,7 +538,7 @@ open class JSClient : IPlatformClient { @JSDocsParameter("url", "Url of playlist") override fun getPlaylist(url: String): IPlatformPlaylistDetails = isBusyWith { ensureEnabled(); - return@isBusyWith JSPlaylistDetails(plugin, plugin.config as SourcePluginConfig, plugin.executeTyped("source.getPlaylist(${Json.encodeToString(url)})")); + return@isBusyWith JSPlaylistDetails(this, plugin.config as SourcePluginConfig, plugin.executeTyped("source.getPlaylist(${Json.encodeToString(url)})")); } @JSOptional diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginDescriptor.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginDescriptor.kt index 5833295e..e6a49777 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginDescriptor.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/SourcePluginDescriptor.kt @@ -26,17 +26,19 @@ class SourcePluginDescriptor { @kotlinx.serialization.Transient val onCaptchaChanged = Event0(); - constructor(config :SourcePluginConfig, authEncrypted: String? = null, captchaEncrypted: String? = null) { + constructor(config :SourcePluginConfig, authEncrypted: String? = null, captchaEncrypted: String? = null, settings: HashMap? = null) { this.config = config; this.authEncrypted = authEncrypted; this.captchaEncrypted = captchaEncrypted; this.flags = listOf(); + this.settings = settings ?: hashMapOf(); } - constructor(config :SourcePluginConfig, authEncrypted: String? = null, captchaEncrypted: String? = null, flags: List) { + constructor(config :SourcePluginConfig, authEncrypted: String? = null, captchaEncrypted: String? = null, flags: List, settings: HashMap? = null) { this.config = config; this.authEncrypted = authEncrypted; this.captchaEncrypted = captchaEncrypted; this.flags = flags; + this.settings = settings ?: hashMapOf(); } fun getSettingsWithDefaults(): HashMap { diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt index 05df143f..3175201a 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/internal/JSHttpClient.kt @@ -1,12 +1,16 @@ package com.futo.platformplayer.api.media.platforms.js.internal +import android.net.Uri import com.futo.platformplayer.api.http.ManagedHttpClient import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourceAuth import com.futo.platformplayer.api.media.platforms.js.SourceCaptchaData import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig +import com.futo.platformplayer.api.media.platforms.js.models.JSRequest +import com.futo.platformplayer.api.media.platforms.js.models.JSRequestModifier import com.futo.platformplayer.engine.exceptions.ScriptImplementationException import com.futo.platformplayer.matchesDomain +import java.util.UUID class JSHttpClient : ManagedHttpClient { private val _jsClient: JSClient?; @@ -14,12 +18,15 @@ class JSHttpClient : ManagedHttpClient { private val _auth: SourceAuth?; private val _captcha: SourceCaptchaData?; + val clientId = UUID.randomUUID().toString(); + var doUpdateCookies: Boolean = true; var doApplyCookies: Boolean = true; var doAllowNewCookies: Boolean = true; val isLoggedIn: Boolean get() = _auth != null; private var _currentCookieMap: HashMap>; + private var _otherCookieMap: HashMap>; constructor(jsClient: JSClient?, auth: SourceAuth? = null, captcha: SourceCaptchaData? = null, config: SourcePluginConfig? = null) : super() { _jsClient = jsClient; @@ -28,6 +35,7 @@ class JSHttpClient : ManagedHttpClient { _captcha = captcha; _currentCookieMap = hashMapOf(); + _otherCookieMap = hashMapOf(); if(!auth?.cookieMap.isNullOrEmpty()) { for(domainCookies in auth!!.cookieMap!!) _currentCookieMap.put(domainCookies.key, HashMap(domainCookies.value)); @@ -49,6 +57,50 @@ class JSHttpClient : ManagedHttpClient { return newClient; } + fun applyRequest(req: JSRequestModifier.Request) { + + + } + + //TODO: Use this in beforeRequest to remove dup code + fun applyHeaders(url: Uri, headers: MutableMap, applyAuth: Boolean = false, applyOtherCookies: Boolean = false) { + val domain = url.host!!.lowercase(); + val auth = _auth; + if (applyAuth && auth != null) { + //TODO: Possibly add doApplyHeaders + for (header in auth.headers.filter { domain.matchesDomain(it.key) }.flatMap { it.value.entries }) + headers.put(header.key, header.value); + } + + if(doApplyCookies && (applyAuth || applyOtherCookies)) { + val cookiesToApply = hashMapOf(); + if(applyOtherCookies) + synchronized(_otherCookieMap) { + for(cookie in _otherCookieMap + .filter { domain.matchesDomain(it.key) } + .flatMap { it.value.toList() }) + cookiesToApply[cookie.first] = cookie.second; + } + if(applyAuth) + synchronized(_currentCookieMap) { + for(cookie in _currentCookieMap + .filter { domain.matchesDomain(it.key) } + .flatMap { it.value.toList() }) + cookiesToApply[cookie.first] = cookie.second; + }; + + if(cookiesToApply.size > 0) { + val cookieString = cookiesToApply.map { it.key + "=" + it.value }.joinToString("; "); + + val existingCookies = headers["Cookie"]; + if(!existingCookies.isNullOrEmpty()) + headers.put("Cookie", existingCookies.trim(';') + "; " + cookieString); + else + headers.put("Cookie", cookieString); + } + } + } + override fun beforeRequest(request: okhttp3.Request): okhttp3.Request { val domain = request.url.host.lowercase(); val auth = _auth; @@ -101,10 +153,10 @@ class JSHttpClient : ManagedHttpClient { val defaultCookieDomain = "." + domainParts.drop(domainParts.size - 2).joinToString("."); for (header in resp.headers) { - if ((_auth != null || _currentCookieMap.isNotEmpty()) && header.first.lowercase() == "set-cookie") { + if(header.first.lowercase() == "set-cookie") { + var domainToUse = domain; val cookie = cookieStringToPair(header.second); var cookieValue = cookie.second; - var domainToUse = domain; if (cookie.first.isNotEmpty() && cookie.second.isNotEmpty()) { val cookieParts = cookie.second.split(";"); @@ -124,17 +176,33 @@ class JSHttpClient : ManagedHttpClient { domainToUse = if (cookieVariables.containsKey("domain")) cookieVariables["domain"]!!.lowercase(); else defaultCookieDomain; + //TODO: Make sure this has no negative effect besides apply cookies to root domain + if(!domainToUse.startsWith(".")) + domainToUse = ".${domainToUse}"; } - val cookieMap = if (_currentCookieMap.containsKey(domainToUse)) - _currentCookieMap[domainToUse]!!; - else { - val newMap = hashMapOf(); - _currentCookieMap[domainToUse] = newMap - newMap; + if ((_auth != null || _currentCookieMap.isNotEmpty())) { + val cookieMap = if (_currentCookieMap.containsKey(domainToUse)) + _currentCookieMap[domainToUse]!!; + else { + val newMap = hashMapOf(); + _currentCookieMap[domainToUse] = newMap + newMap; + } + if (cookieMap.containsKey(cookie.first) || doAllowNewCookies) + cookieMap[cookie.first] = cookieValue; + } + else { + val cookieMap = if (_otherCookieMap.containsKey(domainToUse)) + _otherCookieMap[domainToUse]!!; + else { + val newMap = hashMapOf(); + _otherCookieMap[domainToUse] = newMap + newMap; + } + if (cookieMap.containsKey(cookie.first) || doAllowNewCookies) + cookieMap[cookie.first] = cookieValue; } - if(cookieMap.containsKey(cookie.first) || doAllowNewCookies) - cookieMap[cookie.first] = cookieValue; } } } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/IJSContent.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/IJSContent.kt index 09da4562..a6a15fb6 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/IJSContent.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/IJSContent.kt @@ -3,6 +3,7 @@ package com.futo.platformplayer.api.media.platforms.js.models import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.contents.ContentType import com.futo.platformplayer.api.media.models.contents.IPlatformContent +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.getOrDefault import com.futo.platformplayer.getOrThrow @@ -10,13 +11,14 @@ import com.futo.platformplayer.getOrThrow interface IJSContent: IPlatformContent { companion object { - fun fromV8(config: SourcePluginConfig, obj: V8ValueObject): IPlatformContent { + fun fromV8(plugin: JSClient, obj: V8ValueObject): IPlatformContent { + val config = plugin.config; val type: Int = obj.getOrThrow(config, "contentType", "ContentItem"); val pluginType: String? = obj.getOrDefault(config, "plugin_type", "ContentItem", null); //TODO: Temporary workaround for intercepting details in lists if(pluginType != null && pluginType.endsWith("Details")) - return IJSContentDetails.fromV8(config, obj); + return IJSContentDetails.fromV8(plugin, obj); return when(ContentType.fromInt(type)) { ContentType.MEDIA -> JSVideo(config, obj); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/IJSContentDetails.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/IJSContentDetails.kt index fad34868..6ec2fd98 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/IJSContentDetails.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/IJSContentDetails.kt @@ -4,17 +4,18 @@ import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.contents.ContentType import com.futo.platformplayer.api.media.models.contents.IPlatformContent import com.futo.platformplayer.api.media.models.contents.IPlatformContentDetails +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.getOrThrow interface IJSContentDetails: IPlatformContent { companion object { - fun fromV8(config: SourcePluginConfig, obj: V8ValueObject): IPlatformContentDetails { - val type: Int = obj.getOrThrow(config, "contentType", "ContentDetails"); + fun fromV8(plugin: JSClient, obj: V8ValueObject): IPlatformContentDetails { + val type: Int = obj.getOrThrow(plugin.config, "contentType", "ContentDetails"); return when(ContentType.fromInt(type)) { - ContentType.MEDIA -> JSVideoDetails(config, obj); - ContentType.POST -> JSPostDetails(config, obj); + ContentType.MEDIA -> JSVideoDetails(plugin, obj); + ContentType.POST -> JSPostDetails(plugin.config, obj); else -> throw NotImplementedError("Unknown content type ${type}"); } } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSChannelPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSChannelPager.kt index 01253896..683c64af 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSChannelPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSChannelPager.kt @@ -2,13 +2,14 @@ package com.futo.platformplayer.api.media.platforms.js.models import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.PlatformAuthorLink +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.structures.IPager import com.futo.platformplayer.engine.V8Plugin class JSChannelPager : JSPager, IPager { - constructor(config: SourcePluginConfig, plugin: V8Plugin, pager: V8ValueObject) : super(config, plugin, pager) {} + constructor(config: SourcePluginConfig, plugin: JSClient, pager: V8ValueObject) : super(config, plugin, pager) {} override fun convertResult(obj: V8ValueObject): PlatformAuthorLink { return PlatformAuthorLink.fromV8(config, obj); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSComment.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSComment.kt index 04146582..ab847b6b 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSComment.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSComment.kt @@ -5,6 +5,7 @@ import com.futo.platformplayer.api.media.IPlatformClient import com.futo.platformplayer.api.media.models.PlatformAuthorLink import com.futo.platformplayer.api.media.models.comments.IPlatformComment import com.futo.platformplayer.api.media.models.ratings.IRating +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.structures.IPager import com.futo.platformplayer.engine.V8Plugin @@ -60,6 +61,7 @@ class JSComment : IPlatformComment { return null; val obj = _comment!!.invoke("getReplies", arrayOf()); - return JSCommentPager(_config!!, _plugin!!, obj); + val plugin = if(client is JSClient) client else throw NotImplementedError("Only implemented for JSClient"); + return JSCommentPager(_config!!, plugin, obj); } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSCommentPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSCommentPager.kt index 13d44fe9..94205d35 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSCommentPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSCommentPager.kt @@ -2,15 +2,16 @@ package com.futo.platformplayer.api.media.platforms.js.models import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.comments.IPlatformComment +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.structures.IPager import com.futo.platformplayer.engine.V8Plugin class JSCommentPager : JSPager, IPager { - constructor(config: SourcePluginConfig, plugin: V8Plugin, pager: V8ValueObject) : super(config, plugin, pager) { } + constructor(config: SourcePluginConfig, plugin: JSClient, pager: V8ValueObject) : super(config, plugin, pager) { } override fun convertResult(obj: V8ValueObject): IPlatformComment { - return JSComment(config, plugin, obj); + return JSComment(config, plugin.getUnderlyingPlugin(), obj); } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSContentPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSContentPager.kt index f7a8fbbc..490fa7c4 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSContentPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSContentPager.kt @@ -3,15 +3,16 @@ package com.futo.platformplayer.api.media.platforms.js.models import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.IPluginSourced import com.futo.platformplayer.api.media.models.contents.IPlatformContent +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.engine.V8Plugin class JSContentPager : JSPager, IPluginSourced { override val sourceConfig: SourcePluginConfig get() = config; - constructor(config: SourcePluginConfig, plugin: V8Plugin, pager: V8ValueObject) : super(config, plugin, pager) {} + constructor(config: SourcePluginConfig, plugin: JSClient, pager: V8ValueObject) : super(config, plugin, pager) {} override fun convertResult(obj: V8ValueObject): IPlatformContent { - return IJSContent.fromV8(config, obj); + return IJSContent.fromV8(plugin, obj); } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSLiveEventPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSLiveEventPager.kt index 1d8ead85..27731fea 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSLiveEventPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSLiveEventPager.kt @@ -2,6 +2,7 @@ package com.futo.platformplayer.api.media.platforms.js.models import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.live.IPlatformLiveEvent +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.structures.IPlatformLiveEventPager import com.futo.platformplayer.engine.V8Plugin @@ -10,7 +11,7 @@ import com.futo.platformplayer.getOrThrow class JSLiveEventPager : JSPager, IPlatformLiveEventPager { override var nextRequest: Int; - constructor(config: SourcePluginConfig, plugin: V8Plugin, pager: V8ValueObject) : super(config, plugin, pager) { + constructor(config: SourcePluginConfig, plugin: JSClient, pager: V8ValueObject) : super(config, plugin, pager) { nextRequest = pager.getOrThrow(config, "nextRequest", "LiveEventPager"); } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPager.kt index 831cc93d..a7672823 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPager.kt @@ -4,6 +4,7 @@ import android.os.Looper import com.caoccao.javet.values.reference.V8ValueArray import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.BuildConfig +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.structures.IPager import com.futo.platformplayer.engine.V8Plugin @@ -12,7 +13,7 @@ import com.futo.platformplayer.getOrThrow import com.futo.platformplayer.warnIfMainThread abstract class JSPager : IPager { - protected val plugin: V8Plugin; + protected val plugin: JSClient; protected val config: SourcePluginConfig; protected var pager: V8ValueObject; @@ -21,9 +22,9 @@ abstract class JSPager : IPager { private var _hasMorePages: Boolean = false; //private var _morePagesWasFalse: Boolean = false; - val isAvailable get() = plugin._runtime?.let { !it.isClosed && !it.isDead } ?: false; + val isAvailable get() = plugin.getUnderlyingPlugin()._runtime?.let { !it.isClosed && !it.isDead } ?: false; - constructor(config: SourcePluginConfig, plugin: V8Plugin, pager: V8ValueObject) { + constructor(config: SourcePluginConfig, plugin: JSClient, pager: V8ValueObject) { this.plugin = plugin; this.pager = pager; this.config = config; @@ -43,7 +44,7 @@ abstract class JSPager : IPager { override fun nextPage() { warnIfMainThread("JSPager.nextPage"); - pager = plugin.catchScriptErrors("[${plugin.config.name}] JSPager", "pager.nextPage()") { + pager = plugin.getUnderlyingPlugin().catchScriptErrors("[${plugin.config.name}] JSPager", "pager.nextPage()") { pager.invoke("nextPage", arrayOf()); }; _hasMorePages = pager.getOrDefault(config, "hasMore", "Pager", false) ?: false; diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaylistDetails.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaylistDetails.kt index 97b3f29b..cbd4e013 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaylistDetails.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaylistDetails.kt @@ -4,6 +4,7 @@ import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.playlists.IPlatformPlaylistDetails import com.futo.platformplayer.api.media.models.video.IPlatformVideo import com.futo.platformplayer.api.media.models.video.SerializedPlatformVideo +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.structures.IPager import com.futo.platformplayer.engine.V8Plugin @@ -13,7 +14,7 @@ import com.futo.platformplayer.models.Playlist class JSPlaylistDetails: JSPlaylist, IPlatformPlaylistDetails { override val contents: IPager; - constructor(plugin: V8Plugin, config: SourcePluginConfig, obj: V8ValueObject): super(config, obj) { + constructor(plugin: JSClient, config: SourcePluginConfig, obj: V8ValueObject): super(config, obj) { contents = JSVideoPager(config, plugin, obj.getOrThrow(config, "contents", "PlaylistDetails")); } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaylistPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaylistPager.kt index a0df057b..151bfe2a 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaylistPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPlaylistPager.kt @@ -2,13 +2,14 @@ package com.futo.platformplayer.api.media.platforms.js.models import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.playlists.IPlatformPlaylist +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.structures.IPager import com.futo.platformplayer.engine.V8Plugin class JSPlaylistPager : JSPager, IPager { - constructor(config: SourcePluginConfig, plugin: V8Plugin, pager: V8ValueObject) : super(config, plugin, pager) {} + constructor(config: SourcePluginConfig, plugin: JSClient, pager: V8ValueObject) : super(config, plugin, pager) {} override fun convertResult(obj: V8ValueObject): IPlatformPlaylist { return JSPlaylist(config, obj); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPostDetails.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPostDetails.kt index e8982889..bc455fcc 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPostDetails.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSPostDetails.kt @@ -54,6 +54,6 @@ class JSPostDetails : JSPost, IPlatformPost, IPlatformPostDetails { private fun getCommentsJS(client: JSClient): JSCommentPager { val commentPager = _content.invoke("getComments", arrayOf()); - return JSCommentPager(_pluginConfig, client.getUnderlyingPlugin(), commentPager); + return JSCommentPager(_pluginConfig, client, commentPager); } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequest.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequest.kt index 960982bf..21b0a5de 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequest.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequest.kt @@ -8,7 +8,7 @@ import com.futo.platformplayer.logging.Logger @kotlinx.serialization.Serializable class JSRequest : JSRequestModifier.IRequest { override val url: String; - override val headers: Map; + override var headers: Map; constructor(config: IV8PluginConfig, obj: V8ValueObject) { val contextName = "ModifyRequestResponse"; diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequestModifier.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequestModifier.kt index 0d71057a..d05ef048 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequestModifier.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSRequestModifier.kt @@ -1,19 +1,26 @@ package com.futo.platformplayer.api.media.platforms.js.models +import android.net.Uri import com.caoccao.javet.values.reference.V8ValueObject +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.engine.exceptions.ScriptImplementationException +import com.futo.platformplayer.getOrDefault import com.futo.platformplayer.getOrNull +import com.futo.platformplayer.getOrThrow class JSRequestModifier { + private val _plugin: JSClient; private val _config: IV8PluginConfig; private var _modifier: V8ValueObject; val allowByteSkip: Boolean; - constructor(config: IV8PluginConfig, modifier: V8ValueObject) { + constructor(plugin: JSClient, modifier: V8ValueObject) { + this._plugin = plugin; this._modifier = modifier; - this._config = config; + this._config = plugin.config; + val config = plugin.config; allowByteSkip = modifier.getOrNull(config, "allowByteSkip", "JSRequestModifier") ?: true; @@ -28,9 +35,31 @@ class JSRequestModifier { val result = V8Plugin.catchScriptErrors(_config, "[${_config.name}] JSRequestModifier", "builder.modifyRequest()") { _modifier.invoke("modifyRequest", url, headers); - }; + } as V8ValueObject; - return JSRequest(_config, result as V8ValueObject); + val req = JSRequest(_config, result); + val options: V8ValueObject? = result.getOrDefault(_config, "options", "JSRequestModifier.options", null); + if(options != null) { + if(options.has("applyCookieClient")) { + val clientId: String = options.getOrThrow(_config, "applyCookieClient", "JSRequestModifier.options.applyCookieClient", false) + val client = _plugin.getHttpClientById(clientId); + if(client != null) { + val toModifyHeaders = req.headers.toMutableMap(); + client.applyHeaders(Uri.parse(req.url), toModifyHeaders, false, true); + req.headers = toModifyHeaders; + } + } + if(options.has("applyAuthClient")) { + val clientId: String = options.getOrThrow(_config, "applyAuthClient", "JSRequestModifier.options.applyAuthClient", false) + val client = _plugin.getHttpClientById(clientId); + if(client != null) { + val toModifyHeaders = req.headers.toMutableMap(); + client.applyHeaders(Uri.parse(req.url), toModifyHeaders, true, false); + req.headers = toModifyHeaders; + } + } + } + return req; } interface IRequest { diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSVideoDetails.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSVideoDetails.kt index 815452ee..83137f23 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSVideoDetails.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSVideoDetails.kt @@ -44,13 +44,14 @@ class JSVideoDetails : JSVideo, IPlatformVideoDetails { override val subtitles: List; - constructor(config: SourcePluginConfig, obj: V8ValueObject) : super(config, obj) { + constructor(plugin: JSClient, obj: V8ValueObject) : super(plugin.config, obj) { val contextName = "VideoDetails"; + val config = plugin.config; description = _content.getOrThrow(config, "description", contextName); - video = JSVideoSourceDescriptor.fromV8(config, _content.getOrThrow(config, "video", contextName)); - dash = JSSource.fromV8DashNullable(config, _content.getOrThrowNullable(config, "dash", contextName)); - hls = JSSource.fromV8HLSNullable(config, _content.getOrThrowNullable(config, "hls", contextName)); - live = JSSource.fromV8VideoNullable(config, _content.getOrThrowNullable(config, "live", contextName)); + video = JSVideoSourceDescriptor.fromV8(plugin, _content.getOrThrow(config, "video", contextName)); + dash = JSSource.fromV8DashNullable(plugin, _content.getOrThrowNullable(config, "dash", contextName)); + hls = JSSource.fromV8HLSNullable(plugin, _content.getOrThrowNullable(config, "hls", contextName)); + live = JSSource.fromV8VideoNullable(plugin, _content.getOrThrowNullable(config, "live", contextName)); rating = IRating.fromV8OrDefault(config, _content.getOrDefault(config, "rating", contextName, null), RatingLikes(0)); if(!_content.has("subtitles")) @@ -105,6 +106,6 @@ class JSVideoDetails : JSVideo, IPlatformVideoDetails { if (commentPager !is V8ValueObject) //TODO: Maybe handle this better? return null; - return JSCommentPager(_pluginConfig, client.getUnderlyingPlugin(), commentPager); + return JSCommentPager(_pluginConfig, client, commentPager); } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSVideoPager.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSVideoPager.kt index 1cc24a2d..89117138 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSVideoPager.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/JSVideoPager.kt @@ -2,12 +2,13 @@ package com.futo.platformplayer.api.media.platforms.js.models import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.video.IPlatformVideo +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.engine.V8Plugin class JSVideoPager : JSPager { - constructor(config: SourcePluginConfig, plugin: V8Plugin, pager: V8ValueObject) : super(config, plugin, pager) {} + constructor(config: SourcePluginConfig, plugin: JSClient, pager: V8ValueObject) : super(config, plugin, pager) {} override fun convertResult(obj: V8ValueObject): IPlatformVideo { return JSVideo(config, obj); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlSource.kt index 39d80032..09de1f35 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioUrlSource.kt @@ -2,7 +2,9 @@ package com.futo.platformplayer.api.media.platforms.js.models.sources import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlSource +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrDefault import com.futo.platformplayer.getOrThrow @@ -19,8 +21,9 @@ open class JSAudioUrlSource : IAudioUrlSource, JSSource { override var priority: Boolean = false; - constructor(config: IV8PluginConfig, obj: V8ValueObject) : super(TYPE_AUDIOURL, config, obj) { + constructor(plugin: JSClient, obj: V8ValueObject) : super(TYPE_AUDIOURL, plugin, obj) { val contextName = "AudioUrlSource"; + val config = plugin.config; bitrate = _obj.getOrThrow(config, "bitrate", contextName); container = _obj.getOrThrow(config, "container", contextName); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioWithMetadataSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioWithMetadataSource.kt index 9eafafee..42eeffce 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioWithMetadataSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSAudioWithMetadataSource.kt @@ -3,7 +3,9 @@ package com.futo.platformplayer.api.media.platforms.js.models.sources import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.sources.other.IStreamMetaDataSource import com.futo.platformplayer.api.media.models.streams.sources.other.StreamMetaData +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrDefault class JSAudioUrlRangeSource : JSAudioUrlSource, IStreamMetaDataSource { @@ -22,8 +24,9 @@ class JSAudioUrlRangeSource : JSAudioUrlSource, IStreamMetaDataSource { && indexEnd != null) StreamMetaData(initStart, initEnd, indexStart, indexEnd) else null; - constructor(config: IV8PluginConfig, obj: V8ValueObject) : super(config, obj) { + constructor(plugin: JSClient, obj: V8ValueObject) : super(plugin, obj) { val contextName = "JSAudioUrlRangeSource"; + val config = plugin.config; itagId = _obj.getOrDefault(config, "itagId", contextName, null); initStart = _obj.getOrDefault(config, "initStart", contextName, null); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestSource.kt index 4f50cbf6..3070a2d4 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSDashManifestSource.kt @@ -3,7 +3,9 @@ package com.futo.platformplayer.api.media.platforms.js.models.sources import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.sources.IDashManifestSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrNull import com.futo.platformplayer.getOrThrow @@ -19,9 +21,9 @@ class JSDashManifestSource : IVideoUrlSource, IDashManifestSource, JSSource { override var priority: Boolean = false; - constructor(config: IV8PluginConfig, obj: V8ValueObject) : super(TYPE_DASH, config, obj) { + constructor(plugin: JSClient, obj: V8ValueObject) : super(TYPE_DASH, plugin, obj) { val contextName = "DashSource"; - + val config = plugin.config; name = _obj.getOrThrow(config, "name", contextName); url = _obj.getOrThrow(config, "url", contextName); duration = _obj.getOrThrow(config, "duration", contextName); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSHLSManifestAudioSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSHLSManifestAudioSource.kt index 8636cbb8..41948802 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSHLSManifestAudioSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSHLSManifestAudioSource.kt @@ -4,7 +4,9 @@ import com.caoccao.javet.values.V8Value import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.sources.IAudioUrlSource import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestAudioSource +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrNull import com.futo.platformplayer.getOrThrow import com.futo.platformplayer.orNull @@ -20,8 +22,9 @@ class JSHLSManifestAudioSource : IHLSManifestAudioSource, JSSource { override var priority: Boolean = false; - constructor(config: IV8PluginConfig, obj: V8ValueObject) : super(TYPE_HLS, config, obj) { + constructor(plugin: JSClient, obj: V8ValueObject) : super(TYPE_HLS, plugin, obj) { val contextName = "HLSAudioSource"; + val config = plugin.config; name = _obj.getOrThrow(config, "name", contextName); url = _obj.getOrThrow(config, "url", contextName); @@ -33,7 +36,7 @@ class JSHLSManifestAudioSource : IHLSManifestAudioSource, JSSource { companion object { - fun fromV8HLSNullable(config: IV8PluginConfig, obj: V8Value?) : JSHLSManifestAudioSource? = obj.orNull { fromV8HLS(config, it as V8ValueObject) }; - fun fromV8HLS(config: IV8PluginConfig, obj: V8ValueObject) : JSHLSManifestAudioSource = JSHLSManifestAudioSource(config, obj); + fun fromV8HLSNullable(plugin: JSClient, obj: V8Value?) : JSHLSManifestAudioSource? = obj.orNull { fromV8HLS(plugin, it as V8ValueObject) }; + fun fromV8HLS(plugin: JSClient, obj: V8ValueObject) : JSHLSManifestAudioSource = JSHLSManifestAudioSource(plugin, obj); } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSHLSManifestSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSHLSManifestSource.kt index 8c785c17..606d107c 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSHLSManifestSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSHLSManifestSource.kt @@ -3,7 +3,9 @@ package com.futo.platformplayer.api.media.platforms.js.models.sources import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.sources.IHLSManifestSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrNull import com.futo.platformplayer.getOrThrow @@ -19,8 +21,9 @@ class JSHLSManifestSource : IHLSManifestSource, JSSource { override var priority: Boolean = false; - constructor(config: IV8PluginConfig, obj: V8ValueObject) : super(TYPE_HLS, config, obj) { + constructor(plugin: JSClient, obj: V8ValueObject) : super(TYPE_HLS, plugin, obj) { val contextName = "HLSSource"; + val config = plugin.config; name = _obj.getOrThrow(config, "name", contextName); url = _obj.getOrThrow(config, "url", contextName); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt index fb7f05dd..a6ae5a7c 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSSource.kt @@ -6,6 +6,7 @@ import com.caoccao.javet.values.V8Value import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.sources.IAudioSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoSource +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.models.JSRequestModifier import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.engine.V8Plugin @@ -15,22 +16,24 @@ import com.google.android.exoplayer2.upstream.DefaultHttpDataSource import com.google.android.exoplayer2.upstream.HttpDataSource abstract class JSSource { + protected val _plugin: JSClient; protected val _config: IV8PluginConfig; protected val _obj: V8ValueObject; - private val _hasRequestModifier: Boolean; + val hasRequestModifier: Boolean; val type : String; - constructor(type: String, config: IV8PluginConfig, obj: V8ValueObject) { - this._config = config; + constructor(type: String, plugin: JSClient, obj: V8ValueObject) { + this._plugin = plugin; + this._config = plugin.config; this._obj = obj; this.type = type; - _hasRequestModifier = obj.has("getRequestModifier"); + hasRequestModifier = obj.has("getRequestModifier"); } fun getRequestModifier(): JSRequestModifier? { - if (!_hasRequestModifier || _obj.isClosed) { + if (!hasRequestModifier || _obj.isClosed) { return null; } @@ -42,16 +45,7 @@ abstract class JSSource { return null; } - return JSRequestModifier(_config, result) - } - - fun getHttpDataSourceFactory(): HttpDataSource.Factory { - val requestModifier = getRequestModifier(); - return if (requestModifier != null) { - JSHttpDataSource.Factory().setRequestModifier(requestModifier); - } else { - DefaultHttpDataSource.Factory(); - } + return JSRequestModifier(_plugin, result) } companion object { @@ -62,28 +56,28 @@ abstract class JSSource { const val TYPE_DASH = "DashSource"; const val TYPE_HLS = "HLSSource"; - fun fromV8VideoNullable(config: IV8PluginConfig, obj: V8Value?) : IVideoSource? = obj.orNull { fromV8Video(config, it as V8ValueObject) }; - fun fromV8Video(config: IV8PluginConfig, obj: V8ValueObject) : IVideoSource { + fun fromV8VideoNullable(plugin: JSClient, obj: V8Value?) : IVideoSource? = obj.orNull { fromV8Video(plugin, it as V8ValueObject) }; + fun fromV8Video(plugin: JSClient, obj: V8ValueObject) : IVideoSource { val type = obj.getString("plugin_type"); return when(type) { - TYPE_VIDEOURL -> JSVideoUrlSource(config, obj); - TYPE_VIDEO_WITH_METADATA -> JSVideoUrlRangeSource(config, obj); - TYPE_HLS -> fromV8HLS(config, obj); - TYPE_DASH -> fromV8Dash(config, obj); + TYPE_VIDEOURL -> JSVideoUrlSource(plugin, obj); + TYPE_VIDEO_WITH_METADATA -> JSVideoUrlRangeSource(plugin, obj); + TYPE_HLS -> fromV8HLS(plugin, obj); + TYPE_DASH -> fromV8Dash(plugin, obj); else -> throw NotImplementedError("Unknown type ${type}"); } } - fun fromV8DashNullable(config: IV8PluginConfig, obj: V8Value?) : JSDashManifestSource? = obj.orNull { fromV8Dash(config, it as V8ValueObject) }; - fun fromV8Dash(config: IV8PluginConfig, obj: V8ValueObject) : JSDashManifestSource = JSDashManifestSource(config, obj); - fun fromV8HLSNullable(config: IV8PluginConfig, obj: V8Value?) : JSHLSManifestSource? = obj.orNull { fromV8HLS(config, it as V8ValueObject) }; - fun fromV8HLS(config: IV8PluginConfig, obj: V8ValueObject) : JSHLSManifestSource = JSHLSManifestSource(config, obj); + fun fromV8DashNullable(plugin: JSClient, obj: V8Value?) : JSDashManifestSource? = obj.orNull { fromV8Dash(plugin, it as V8ValueObject) }; + fun fromV8Dash(plugin: JSClient, obj: V8ValueObject) : JSDashManifestSource = JSDashManifestSource(plugin, obj); + fun fromV8HLSNullable(plugin: JSClient, obj: V8Value?) : JSHLSManifestSource? = obj.orNull { fromV8HLS(plugin, it as V8ValueObject) }; + fun fromV8HLS(plugin: JSClient, obj: V8ValueObject) : JSHLSManifestSource = JSHLSManifestSource(plugin, obj); - fun fromV8Audio(config: IV8PluginConfig, obj: V8ValueObject) : IAudioSource { + fun fromV8Audio(plugin: JSClient, obj: V8ValueObject) : IAudioSource { val type = obj.getString("plugin_type"); return when(type) { - TYPE_HLS -> JSHLSManifestAudioSource.fromV8HLS(config, obj); - TYPE_AUDIOURL -> JSAudioUrlSource(config, obj); - TYPE_AUDIO_WITH_METADATA -> JSAudioUrlRangeSource(config, obj); + TYPE_HLS -> JSHLSManifestAudioSource.fromV8HLS(plugin, obj); + TYPE_AUDIOURL -> JSAudioUrlSource(plugin, obj); + TYPE_AUDIO_WITH_METADATA -> JSAudioUrlRangeSource(plugin, obj); else -> throw NotImplementedError("Unknown type ${type}"); } } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSUnMuxVideoSourceDescriptor.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSUnMuxVideoSourceDescriptor.kt index 08d4911d..035f5fb6 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSUnMuxVideoSourceDescriptor.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSUnMuxVideoSourceDescriptor.kt @@ -5,6 +5,7 @@ import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.VideoUnMuxedSourceDescriptor import com.futo.platformplayer.api.media.models.streams.sources.IAudioSource import com.futo.platformplayer.api.media.models.streams.sources.IVideoSource +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.getOrThrow @@ -15,15 +16,16 @@ class JSUnMuxVideoSourceDescriptor: VideoUnMuxedSourceDescriptor { override val videoSources: Array; override val audioSources: Array; - constructor(config: IV8PluginConfig, obj: V8ValueObject) { + constructor(plugin: JSClient, obj: V8ValueObject) { this._obj = obj; + val config = plugin.config; val contextName = "UnMuxVideoSource" this.isUnMuxed = obj.getOrThrow(config, "isUnMuxed", contextName); this.videoSources = obj.getOrThrow(config, "videoSources", contextName).toArray() - .map { JSSource.fromV8Video(config, it as V8ValueObject) } + .map { JSSource.fromV8Video(plugin, it as V8ValueObject) } .toTypedArray(); this.audioSources = obj.getOrThrow(config, "audioSources", contextName).toArray() - .map { JSSource.fromV8Audio(config, it as V8ValueObject) } + .map { JSSource.fromV8Audio(plugin, it as V8ValueObject) } .toTypedArray(); } } \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoSourceDescriptor.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoSourceDescriptor.kt index 463100b0..131a5794 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoSourceDescriptor.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoSourceDescriptor.kt @@ -5,7 +5,9 @@ import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.IVideoSourceDescriptor import com.futo.platformplayer.api.media.models.streams.VideoMuxedSourceDescriptor import com.futo.platformplayer.api.media.models.streams.sources.IVideoSource +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrThrow class JSVideoSourceDescriptor: VideoMuxedSourceDescriptor { @@ -14,12 +16,13 @@ class JSVideoSourceDescriptor: VideoMuxedSourceDescriptor { override val isUnMuxed: Boolean; override val videoSources: Array; - constructor(config: IV8PluginConfig, obj: V8ValueObject) { + constructor(plugin: JSClient, obj: V8ValueObject) { this._obj = obj; + val config = plugin.config; val contextName = "VideoSourceDescriptor"; this.isUnMuxed = obj.getOrThrow(config, "isUnMuxed", contextName); this.videoSources = obj.getOrThrow(config, "videoSources", contextName).toArray() - .map { JSSource.fromV8Video(config, it as V8ValueObject) } + .map { JSSource.fromV8Video(plugin, it as V8ValueObject) } .toTypedArray(); } @@ -28,11 +31,11 @@ class JSVideoSourceDescriptor: VideoMuxedSourceDescriptor { const val TYPE_UNMUXED = "UnMuxVideoSourceDescriptor"; - fun fromV8(config: IV8PluginConfig, obj: V8ValueObject) : IVideoSourceDescriptor { + fun fromV8(plugin: JSClient, obj: V8ValueObject) : IVideoSourceDescriptor { val type = obj.getString("plugin_type") return when(type) { - TYPE_MUXED -> JSVideoSourceDescriptor(config, obj); - TYPE_UNMUXED -> JSUnMuxVideoSourceDescriptor(config, obj); + TYPE_MUXED -> JSVideoSourceDescriptor(plugin, obj); + TYPE_UNMUXED -> JSUnMuxVideoSourceDescriptor(plugin, obj); else -> throw NotImplementedError("Unknown type: ${type}"); } } diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlSource.kt index a4fbf0e8..66246f56 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoUrlSource.kt @@ -2,7 +2,9 @@ package com.futo.platformplayer.api.media.platforms.js.models.sources import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrNull import com.futo.platformplayer.getOrThrow @@ -18,8 +20,9 @@ open class JSVideoUrlSource : IVideoUrlSource, JSSource { override var priority: Boolean = false; - constructor(config: IV8PluginConfig, obj: V8ValueObject): super(TYPE_VIDEOURL, config, obj) { + constructor(plugin: JSClient, obj: V8ValueObject): super(TYPE_VIDEOURL, plugin, obj) { val contextName = "JSVideoUrlSource"; + val config = plugin.config; width = _obj.getOrThrow(config, "width", contextName); height = _obj.getOrThrow(config, "height", contextName); diff --git a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoWithMetadataSource.kt b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoWithMetadataSource.kt index 90b6edee..0e86c2fc 100644 --- a/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoWithMetadataSource.kt +++ b/app/src/main/java/com/futo/platformplayer/api/media/platforms/js/models/sources/JSVideoWithMetadataSource.kt @@ -3,7 +3,9 @@ package com.futo.platformplayer.api.media.platforms.js.models.sources import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.media.models.streams.sources.other.IStreamMetaDataSource import com.futo.platformplayer.api.media.models.streams.sources.other.StreamMetaData +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig +import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.getOrDefault class JSVideoUrlRangeSource : JSVideoUrlSource, IStreamMetaDataSource { @@ -21,8 +23,9 @@ class JSVideoUrlRangeSource : JSVideoUrlSource, IStreamMetaDataSource { && indexEnd != null) StreamMetaData(initStart, initEnd, indexStart, indexEnd) else null; - constructor(config: IV8PluginConfig, obj: V8ValueObject) : super(config, obj) { + constructor(plugin: JSClient, obj: V8ValueObject) : super(plugin, obj) { val contextName = "JSVideoUrlRangeSource"; + val config = plugin.config; itagId = _obj.getOrDefault(config, "itagId", contextName, null); initStart = _obj.getOrDefault(config, "initStart", contextName, null); diff --git a/app/src/main/java/com/futo/platformplayer/engine/V8Plugin.kt b/app/src/main/java/com/futo/platformplayer/engine/V8Plugin.kt index 95ad1b3a..8b7c08da 100644 --- a/app/src/main/java/com/futo/platformplayer/engine/V8Plugin.kt +++ b/app/src/main/java/com/futo/platformplayer/engine/V8Plugin.kt @@ -11,6 +11,7 @@ import com.caoccao.javet.values.primitive.V8ValueInteger import com.caoccao.javet.values.primitive.V8ValueString import com.caoccao.javet.values.reference.V8ValueObject import com.futo.platformplayer.api.http.ManagedHttpClient +import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient import com.futo.platformplayer.constructs.Event1 import com.futo.platformplayer.engine.exceptions.NoInternetException import com.futo.platformplayer.engine.exceptions.PluginEngineStoppedException @@ -34,15 +35,24 @@ import com.futo.platformplayer.getOrThrow import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.states.StateAssets import com.futo.platformplayer.warnIfMainThread +import java.util.concurrent.ConcurrentHashMap class V8Plugin { val config: IV8PluginConfig; private val _client: ManagedHttpClient; private val _clientAuth: ManagedHttpClient; + private val _clientOthers: ConcurrentHashMap = ConcurrentHashMap(); val httpClient: ManagedHttpClient get() = _client; val httpClientAuth: ManagedHttpClient get() = _clientAuth; + val httpClientOthers: Map get() = _clientOthers; + + fun registerHttpClient(client: JSHttpClient) { + synchronized(_clientOthers) { + _clientOthers.put(client.clientId, client); + } + } private val _runtimeLock = Object(); var _runtime : V8Runtime? = null; diff --git a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt index 68a74202..937e2d23 100644 --- a/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt +++ b/app/src/main/java/com/futo/platformplayer/engine/packages/PackageHttp.kt @@ -45,7 +45,12 @@ class PackageHttp: V8Package { @V8Function fun newClient(withAuth: Boolean): PackageHttpClient { - return PackageHttpClient(this, if(withAuth) _clientAuth.clone() else _client.clone()); + val httpClient = if(withAuth) _clientAuth.clone() else _client.clone(); + if(httpClient is JSHttpClient) + _plugin.registerHttpClient(httpClient); + val client = PackageHttpClient(this, httpClient); + + return client; } @V8Function fun getDefaultClient(withAuth: Boolean): PackageHttpClient { @@ -187,10 +192,19 @@ class PackageHttp: V8Package { @Transient private val _defaultHeaders = mutableMapOf(); + @Transient + private val _clientId: String?; + + @V8Property + fun clientId(): String? { + return _clientId; + } + constructor(pack: PackageHttp, baseClient: ManagedHttpClient): super() { _package = pack; _client = baseClient; + _clientId = if(_client is JSHttpClient) _client.clientId else null; } @V8Function diff --git a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SourceDetailFragment.kt b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SourceDetailFragment.kt index a28e8016..3af3f01d 100644 --- a/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SourceDetailFragment.kt +++ b/app/src/main/java/com/futo/platformplayer/fragment/mainactivity/main/SourceDetailFragment.kt @@ -23,6 +23,7 @@ import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.states.StateApp +import com.futo.platformplayer.states.StateDeveloper import com.futo.platformplayer.states.StatePlatform import com.futo.platformplayer.states.StatePlugins import com.futo.platformplayer.views.buttons.BigButton @@ -294,7 +295,9 @@ class SourceDetailFragment : MainFragment() { } } - val clientIfExists = StatePlugins.instance.getPlugin(config.id); + val clientIfExists = if(config.id != StateDeveloper.DEV_ID) + StatePlugins.instance.getPlugin(config.id); + else null; groups.add( BigButtonGroup(c, context.getString(R.string.management), BigButton(c, context.getString(R.string.uninstall), context.getString(R.string.removes_the_plugin_from_the_app), R.drawable.ic_block) { diff --git a/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt b/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt index f2866441..1972c166 100644 --- a/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt +++ b/app/src/main/java/com/futo/platformplayer/helpers/VideoHelper.kt @@ -14,6 +14,7 @@ import com.futo.platformplayer.api.media.models.streams.sources.IVideoUrlSource import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails import com.futo.platformplayer.api.media.platforms.js.models.sources.JSAudioUrlRangeSource import com.futo.platformplayer.api.media.platforms.js.models.sources.JSVideoUrlRangeSource +import com.futo.platformplayer.getHttpDataSourceFactory import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.others.Language import com.google.android.exoplayer2.MediaItem diff --git a/app/src/main/java/com/futo/platformplayer/states/StateDeveloper.kt b/app/src/main/java/com/futo/platformplayer/states/StateDeveloper.kt index 8d9ceff6..7b6628e6 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StateDeveloper.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StateDeveloper.kt @@ -1,5 +1,6 @@ package com.futo.platformplayer.states +import android.content.Context import com.futo.platformplayer.UIDialogs import com.futo.platformplayer.api.http.server.ManagedHttpServer import com.futo.platformplayer.developer.DeveloperEndpoints @@ -93,6 +94,13 @@ class StateDeveloper { } } + fun setDevClientSettings(settings: HashMap) { + val client = StatePlatform.instance.getDevClient(); + client?.let { + it.descriptor.settings = settings; + }; + } + fun runServer() { if(_server != null) diff --git a/app/src/main/java/com/futo/platformplayer/states/StatePlugins.kt b/app/src/main/java/com/futo/platformplayer/states/StatePlugins.kt index 85b16fd0..2f08937d 100644 --- a/app/src/main/java/com/futo/platformplayer/states/StatePlugins.kt +++ b/app/src/main/java/com/futo/platformplayer/states/StatePlugins.kt @@ -10,6 +10,7 @@ import com.futo.platformplayer.api.media.platforms.js.SourceAuth import com.futo.platformplayer.api.media.platforms.js.SourceCaptchaData import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.platforms.js.SourcePluginDescriptor +import com.futo.platformplayer.developer.DeveloperEndpoints import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.models.ImageVariable import com.futo.platformplayer.stores.FragmentedStorage @@ -411,6 +412,16 @@ class StatePlugins { fun setPluginSettings(id: String, map: Map) { val newSettings = HashMap(map); + if(id == StateDeveloper.DEV_ID) + { + val decConfig = StatePlatform.instance.getDevClient()?.config ?: return; + for(setting in decConfig.settings) { + if(!newSettings.containsKey(setting.variableOrName) || newSettings[setting.variableOrName] == null) + newSettings[setting.variableOrName] = setting.default; + } + StateDeveloper.instance.setDevClientSettings(newSettings); + return; + } val plugin = getPlugin(id); if(plugin != null) { diff --git a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt index 9a23b935..b8cd89ef 100644 --- a/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt +++ b/app/src/main/java/com/futo/platformplayer/views/video/FutoVideoPlayerBase.kt @@ -22,8 +22,10 @@ import com.futo.platformplayer.api.media.models.subtitles.ISubtitleSource import com.futo.platformplayer.api.media.models.video.IPlatformVideoDetails import com.futo.platformplayer.api.media.platforms.js.models.sources.JSAudioUrlRangeSource import com.futo.platformplayer.api.media.platforms.js.models.sources.JSHLSManifestAudioSource +import com.futo.platformplayer.api.media.platforms.js.models.sources.JSSource import com.futo.platformplayer.api.media.platforms.js.models.sources.JSVideoUrlRangeSource import com.futo.platformplayer.constructs.Event1 +import com.futo.platformplayer.getHttpDataSourceFactory import com.futo.platformplayer.helpers.VideoHelper import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.states.StateApp @@ -399,20 +401,29 @@ abstract class FutoVideoPlayerBase : RelativeLayout { } private fun swapVideoSourceUrl(videoSource: IVideoUrlSource) { Logger.i(TAG, "Loading VideoSource [Url]"); - _lastVideoMediaSource = ProgressiveMediaSource.Factory(DefaultHttpDataSource.Factory() - .setUserAgent(DEFAULT_USER_AGENT)) + val dataSource = if(videoSource is JSSource && videoSource.hasRequestModifier) + videoSource.getHttpDataSourceFactory() + else + DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT); + _lastVideoMediaSource = ProgressiveMediaSource.Factory(dataSource) .createMediaSource(MediaItem.fromUri(videoSource.getVideoUrl())); } private fun swapVideoSourceDash(videoSource: IDashManifestSource) { Logger.i(TAG, "Loading VideoSource [Dash]"); - _lastVideoMediaSource = DashMediaSource.Factory(DefaultHttpDataSource.Factory() - .setUserAgent(DEFAULT_USER_AGENT)) + val dataSource = if(videoSource is JSSource && videoSource.hasRequestModifier) + videoSource.getHttpDataSourceFactory() + else + DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT); + _lastVideoMediaSource = DashMediaSource.Factory(dataSource) .createMediaSource(MediaItem.fromUri(videoSource.url)) } private fun swapVideoSourceHLS(videoSource: IHLSManifestSource) { Logger.i(TAG, "Loading VideoSource [HLS]"); - _lastVideoMediaSource = HlsMediaSource.Factory(DefaultHttpDataSource.Factory() - .setUserAgent(DEFAULT_USER_AGENT)) + val dataSource = if(videoSource is JSSource && videoSource.hasRequestModifier) + videoSource.getHttpDataSourceFactory() + else + DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT); + _lastVideoMediaSource = HlsMediaSource.Factory(dataSource) .createMediaSource(MediaItem.fromUri(videoSource.url)); } @@ -446,14 +457,20 @@ abstract class FutoVideoPlayerBase : RelativeLayout { } private fun swapAudioSourceUrl(audioSource: IAudioUrlSource) { Logger.i(TAG, "Loading AudioSource [Url]"); - _lastAudioMediaSource = ProgressiveMediaSource.Factory(DefaultHttpDataSource.Factory() - .setUserAgent(DEFAULT_USER_AGENT)) + val dataSource = if(audioSource is JSSource && audioSource.hasRequestModifier) + audioSource.getHttpDataSourceFactory() + else + DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT); + _lastAudioMediaSource = ProgressiveMediaSource.Factory(dataSource) .createMediaSource(MediaItem.fromUri(audioSource.getAudioUrl())); } private fun swapAudioSourceHLS(audioSource: IHLSManifestAudioSource) { Logger.i(TAG, "Loading AudioSource [HLS]"); - _lastAudioMediaSource = HlsMediaSource.Factory(DefaultHttpDataSource.Factory() - .setUserAgent(DEFAULT_USER_AGENT)) + val dataSource = if(audioSource is JSSource && audioSource.hasRequestModifier) + audioSource.getHttpDataSourceFactory() + else + DefaultHttpDataSource.Factory().setUserAgent(DEFAULT_USER_AGENT); + _lastAudioMediaSource = HlsMediaSource.Factory(dataSource) .createMediaSource(MediaItem.fromUri(audioSource.url)); } diff --git a/app/src/unstable/assets/sources/niconico b/app/src/unstable/assets/sources/niconico new file mode 160000 index 00000000..f2086dc2 --- /dev/null +++ b/app/src/unstable/assets/sources/niconico @@ -0,0 +1 @@ +Subproject commit f2086dc2cf6387f692049f52cdf938313dc53654 diff --git a/app/src/unstable/assets/sources/youtube b/app/src/unstable/assets/sources/youtube index 128b03c5..fad5e14f 160000 --- a/app/src/unstable/assets/sources/youtube +++ b/app/src/unstable/assets/sources/youtube @@ -1 +1 @@ -Subproject commit 128b03c5911d414ad230afd75c35c6be5b1e87db +Subproject commit fad5e14f84573796b3989794c35f34a1f88f03a6