diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/AdhocRequestModifier.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/AdhocRequestModifier.kt new file mode 100644 index 0000000000000000000000000000000000000000..ea250ae450db058a52164ac4c77788356fcf028a --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/AdhocRequestModifier.kt @@ -0,0 +1,14 @@ +package com.futo.platformplayer.api.media.models.modifier + +class AdhocRequestModifier: IRequestModifier { + val _handler: (String, Map<String,String>)->IRequest; + override var allowByteSkip: Boolean = false; + + constructor(modifyReq: (String, Map<String,String>)->IRequest) { + _handler = modifyReq; + } + + override fun modifyRequest(url: String, headers: Map<String, String>): IRequest { + return _handler(url, headers); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/IModifierOptions.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/IModifierOptions.kt new file mode 100644 index 0000000000000000000000000000000000000000..1a7e4ce6b0933395be00b23224d6ae779f8608e4 --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/IModifierOptions.kt @@ -0,0 +1,6 @@ +package com.futo.platformplayer.api.media.models.modifier + +interface IModifierOptions { + val applyAuthClient: String?; + val applyCookieClient: String?; +} \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/IRequest.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/IRequest.kt new file mode 100644 index 0000000000000000000000000000000000000000..43cd502c1ba495e247e77bcd1e661117329d991c --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/IRequest.kt @@ -0,0 +1,6 @@ +package com.futo.platformplayer.api.media.models.modifier + +interface IRequest { + val url: String?; + val headers: Map<String, String>; +} \ No newline at end of file diff --git a/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/IRequestModifier.kt b/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/IRequestModifier.kt new file mode 100644 index 0000000000000000000000000000000000000000..f15ee4771eba3fe9f6bd517d86b8a966a1acad31 --- /dev/null +++ b/app/src/main/java/com/futo/platformplayer/api/media/models/modifier/IRequestModifier.kt @@ -0,0 +1,7 @@ +package com.futo.platformplayer.api.media.models.modifier + + +interface IRequestModifier { + var allowByteSkip: Boolean; + fun modifyRequest(url: String, headers: Map<String, String>): IRequest +} \ No newline at end of file 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 3175201afed6ceba917104c9ec1ab62551b59527..8496dfc788b40a331c0eb7291d201c0c059585da 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 @@ -57,11 +57,6 @@ 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<String, String>, applyAuth: Boolean = false, applyOtherCookies: Boolean = false) { val domain = url.host!!.lowercase(); 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 21b0a5de642298442cec7894a66f4ff53592af37..1a9ef32b4fd0218e8bde298ff41b13b9ab0542f5 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 @@ -1,18 +1,81 @@ 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.models.modifier.IModifierOptions +import com.futo.platformplayer.api.media.models.modifier.IRequest +import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig -import com.futo.platformplayer.getOrThrow -import com.futo.platformplayer.logging.Logger +import com.futo.platformplayer.getOrDefault @kotlinx.serialization.Serializable -class JSRequest : JSRequestModifier.IRequest { - override val url: String; - override var headers: Map<String, String>; +class JSRequest : IRequest { + private val _v8Url: String?; + private val _v8Headers: Map<String, String>?; + private val _v8Options: Options?; - constructor(config: IV8PluginConfig, obj: V8ValueObject) { + override var url: String? = null; + override lateinit var headers: Map<String, String>; + + constructor(plugin: JSClient, url: String?, headers: Map<String, String>?, options: Options?, originalUrl: String?, originalHeaders: Map<String, String>?) { + _v8Url = url; + _v8Headers = headers; + _v8Options = options; + initialize(plugin, originalUrl, originalHeaders); + } + constructor(plugin: JSClient, obj: V8ValueObject, originalUrl: String?, originalHeaders: Map<String, String>?) { val contextName = "ModifyRequestResponse"; - url = obj.getOrThrow(config, "url", contextName); - headers = obj.getOrThrow(config, "headers", contextName); + val config = plugin.config; + _v8Url = obj.getOrDefault<String>(config, "url", contextName, null); + _v8Headers = obj.getOrDefault<Map<String, String>>(config, "headers", contextName, null); + _v8Options = obj.getOrDefault<V8ValueObject>(config, "options", "JSRequestModifier.options", null)?.let { + Options(config, it); + } + initialize(plugin, originalUrl, originalHeaders); + } + + private fun initialize(plugin: JSClient, originalUrl: String?, originalHeaders: Map<String, String>?) { + val config = plugin.config; + url = _v8Url ?: originalUrl; + headers = _v8Headers ?: originalHeaders ?: mapOf(); + + if(_v8Options != null) { + if(_v8Options.applyCookieClient != null && url != null) { + val client = plugin.getHttpClientById(_v8Options.applyCookieClient); + if(client != null) { + val toModifyHeaders = headers.toMutableMap(); + client.applyHeaders(Uri.parse(url), toModifyHeaders, false, true); + headers = toModifyHeaders; + } + } + if(_v8Options.applyAuthClient != null && url != null) { + val client = plugin.getHttpClientById(_v8Options.applyAuthClient); + if(client != null) { + val toModifyHeaders = headers.toMutableMap(); + client.applyHeaders(Uri.parse(url), toModifyHeaders, true, false); + headers = toModifyHeaders; + } + } + } + } + + fun modify(plugin: JSClient, originalUrl: String?, originalHeaders: Map<String, String>?): JSRequest { + return JSRequest(plugin, _v8Url, _v8Headers, _v8Options, originalUrl, originalHeaders); + } + + + @kotlinx.serialization.Serializable + class Options: IModifierOptions { + override val applyAuthClient: String?; + override val applyCookieClient: String?; + + constructor(config: IV8PluginConfig, obj: V8ValueObject) { + applyAuthClient = obj.getOrDefault(config, "applyAuthClient", "JSRequestModifier.options.applyAuthClient", null); + applyCookieClient = obj.getOrDefault(config, "applyCookieClient", "JSRequestModifier.options.applyCookieClient", null); + } + } + + companion object { + } } \ No newline at end of file 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 d05ef048cbcb795daa518094a3050b5392d26d69..cffbb4743aea52a9e288430113e2fc3bc26b0c87 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 @@ -2,6 +2,8 @@ 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.models.modifier.IRequest +import com.futo.platformplayer.api.media.models.modifier.IRequestModifier import com.futo.platformplayer.api.media.platforms.js.JSClient import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.engine.V8Plugin @@ -10,11 +12,11 @@ import com.futo.platformplayer.getOrDefault import com.futo.platformplayer.getOrNull import com.futo.platformplayer.getOrThrow -class JSRequestModifier { +class JSRequestModifier: IRequestModifier { private val _plugin: JSClient; private val _config: IV8PluginConfig; private var _modifier: V8ValueObject; - val allowByteSkip: Boolean; + override var allowByteSkip: Boolean; constructor(plugin: JSClient, modifier: V8ValueObject) { this._plugin = plugin; @@ -28,7 +30,7 @@ class JSRequestModifier { throw ScriptImplementationException(config, "RequestModifier is missing modifyRequest", null); } - fun modifyRequest(url: String, headers: Map<String, String>): IRequest { + override fun modifyRequest(url: String, headers: Map<String, String>): IRequest { if (_modifier.isClosed) { return Request(url, headers); } @@ -37,35 +39,10 @@ class JSRequestModifier { _modifier.invoke("modifyRequest", url, headers); } 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; - } - } - } + val req = JSRequest(_plugin, result, url, headers); return req; } - interface IRequest { - val url: String; - val headers: Map<String, String>; - } data class Request(override val url: String, override val headers: Map<String, String>) : IRequest; } \ No newline at end of file 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 a6ae5a7c26067eafd319c3dec85a9142c92c3d08..14bed433c14f4773c5ca36cbbe3752eff6927e1c 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 @@ -4,12 +4,16 @@ package com.futo.platformplayer.api.media.platforms.js.models.sources import com.caoccao.javet.values.V8Value import com.caoccao.javet.values.reference.V8ValueObject +import com.futo.platformplayer.api.media.models.modifier.AdhocRequestModifier +import com.futo.platformplayer.api.media.models.modifier.IRequestModifier 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.JSRequest import com.futo.platformplayer.api.media.platforms.js.models.JSRequestModifier import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.engine.V8Plugin +import com.futo.platformplayer.getOrDefault import com.futo.platformplayer.orNull import com.futo.platformplayer.views.video.datasources.JSHttpDataSource import com.google.android.exoplayer2.upstream.DefaultHttpDataSource @@ -20,6 +24,7 @@ abstract class JSSource { protected val _config: IV8PluginConfig; protected val _obj: V8ValueObject; val hasRequestModifier: Boolean; + private val _requestModifier: JSRequest?; val type : String; @@ -29,10 +34,18 @@ abstract class JSSource { this._obj = obj; this.type = type; - hasRequestModifier = obj.has("getRequestModifier"); + _requestModifier = obj.getOrDefault<V8ValueObject>(_config, "requestModifier", "JSSource.requestModifier", null)?.let { + JSRequest(plugin, it, null, null); + } + hasRequestModifier = _requestModifier != null || obj.has("getRequestModifier"); } - fun getRequestModifier(): JSRequestModifier? { + fun getRequestModifier(): IRequestModifier? { + if(_requestModifier != null) + return AdhocRequestModifier { url, headers -> + return@AdhocRequestModifier _requestModifier.modify(_plugin, url, headers); + }; + if (!hasRequestModifier || _obj.isClosed) { return null; } diff --git a/app/src/main/java/com/futo/platformplayer/views/video/datasources/JSHttpDataSource.java b/app/src/main/java/com/futo/platformplayer/views/video/datasources/JSHttpDataSource.java index 00a49cf85d8c89f0b6d5f95fb61ea28cdc7a5b12..c6d14cebe7c2cf8c2586113192475bf117a94e05 100644 --- a/app/src/main/java/com/futo/platformplayer/views/video/datasources/JSHttpDataSource.java +++ b/app/src/main/java/com/futo/platformplayer/views/video/datasources/JSHttpDataSource.java @@ -9,6 +9,8 @@ import android.net.Uri; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import com.futo.platformplayer.api.media.models.modifier.IRequest; +import com.futo.platformplayer.api.media.models.modifier.IRequestModifier; import com.futo.platformplayer.api.media.platforms.js.models.JSRequestModifier; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.PlaybackException; @@ -57,7 +59,7 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource { private int readTimeoutMs; private boolean allowCrossProtocolRedirects; private boolean keepPostFor302Redirects; - @Nullable private JSRequestModifier requestModifier = null; + @Nullable private IRequestModifier requestModifier = null; /** Creates an instance. */ public Factory() { @@ -80,7 +82,7 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource { * @param requestModifier The request modifier that will be used, or {@code null} to use no request modifier * @return This factory. */ - public Factory setRequestModifier(@Nullable JSRequestModifier requestModifier) { + public Factory setRequestModifier(@Nullable IRequestModifier requestModifier) { this.requestModifier = requestModifier; return this; } @@ -225,7 +227,7 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource { private int responseCode; private long bytesToRead; private long bytesRead; - @Nullable private JSRequestModifier requestModifier; + @Nullable private IRequestModifier requestModifier; private JSHttpDataSource( @Nullable String userAgent, @@ -235,7 +237,7 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource { @Nullable RequestProperties defaultRequestProperties, @Nullable Predicate<String> contentTypePredicate, boolean keepPostFor302Redirects, - @Nullable JSRequestModifier requestModifier) { + @Nullable IRequestModifier requestModifier) { super(/* isNetwork= */ true); this.userAgent = userAgent; this.connectTimeoutMillis = connectTimeoutMillis; @@ -571,8 +573,9 @@ public class JSHttpDataSource extends BaseDataSource implements HttpDataSource { String requestUrl = url.toString(); if (requestModifier != null) { - JSRequestModifier.IRequest result = requestModifier.modifyRequest(requestUrl, requestHeaders); - requestUrl = result.getUrl(); + IRequest result = requestModifier.modifyRequest(requestUrl, requestHeaders); + String modifiedUrl = result.getUrl(); + requestUrl = (modifiedUrl != null) ? modifiedUrl : requestUrl; requestHeaders = result.getHeaders(); } diff --git a/app/src/unstable/assets/sources/niconico b/app/src/unstable/assets/sources/niconico index f2086dc2cf6387f692049f52cdf938313dc53654..f031e10d3852dd7138f2ed312c5e74466f23da32 160000 --- a/app/src/unstable/assets/sources/niconico +++ b/app/src/unstable/assets/sources/niconico @@ -1 +1 @@ -Subproject commit f2086dc2cf6387f692049f52cdf938313dc53654 +Subproject commit f031e10d3852dd7138f2ed312c5e74466f23da32 diff --git a/app/src/unstable/assets/sources/youtube b/app/src/unstable/assets/sources/youtube index fad5e14f84573796b3989794c35f34a1f88f03a6..d41cc8e848891ef8e949e6d49384b754e7c305c7 160000 --- a/app/src/unstable/assets/sources/youtube +++ b/app/src/unstable/assets/sources/youtube @@ -1 +1 @@ -Subproject commit fad5e14f84573796b3989794c35f34a1f88f03a6 +Subproject commit d41cc8e848891ef8e949e6d49384b754e7c305c7