Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay

This commit is contained in:
Kelvin K
2025-11-25 11:30:02 -06:00
4 changed files with 48 additions and 60 deletions
@@ -153,8 +153,8 @@ open class JSClient : IPlatformClient {
_captcha = descriptor.getCaptchaData(); _captcha = descriptor.getCaptchaData();
flags = descriptor.flags.toTypedArray(); flags = descriptor.flags.toTypedArray();
_httpClient = JSHttpClient(this, null, _captcha); _httpClient = JSHttpClient(this, null, _captcha, config);
_httpClientAuth = JSHttpClient(this, _auth, _captcha); _httpClientAuth = JSHttpClient(this, _auth, _captcha, config);
_plugin = V8Plugin(context, descriptor.config, null, _httpClient, _httpClientAuth); _plugin = V8Plugin(context, descriptor.config, null, _httpClient, _httpClientAuth);
_plugin.withDependency(context, "scripts/polyfil.js"); _plugin.withDependency(context, "scripts/polyfil.js");
_plugin.withDependency(context, "scripts/source.js"); _plugin.withDependency(context, "scripts/source.js");
@@ -186,8 +186,8 @@ open class JSClient : IPlatformClient {
_captcha = descriptor.getCaptchaData(); _captcha = descriptor.getCaptchaData();
flags = descriptor.flags.toTypedArray(); flags = descriptor.flags.toTypedArray();
_httpClient = JSHttpClient(this, null, _captcha); _httpClient = JSHttpClient(this, null, _captcha, config);
_httpClientAuth = JSHttpClient(this, _auth, _captcha); _httpClientAuth = JSHttpClient(this, _auth, _captcha, config);
_plugin = V8Plugin(context, descriptor.config, script, _httpClient, _httpClientAuth); _plugin = V8Plugin(context, descriptor.config, script, _httpClient, _httpClientAuth);
_plugin.withDependency(context, "scripts/polyfil.js"); _plugin.withDependency(context, "scripts/polyfil.js");
_plugin.withDependency(context, "scripts/source.js"); _plugin.withDependency(context, "scripts/source.js");
@@ -23,6 +23,7 @@ import java.util.UUID
class JSHttpClient : ManagedHttpClient { class JSHttpClient : ManagedHttpClient {
private val _jsClient: JSClient?; private val _jsClient: JSClient?;
private val _jsConfig: SourcePluginConfig?; private val _jsConfig: SourcePluginConfig?;
val config get() = _jsConfig
private val _auth: SourceAuth?; private val _auth: SourceAuth?;
private val _captcha: SourceCaptchaData?; private val _captcha: SourceCaptchaData?;
@@ -23,10 +23,7 @@ object Libcurl {
var body: ByteArray? = null, var body: ByteArray? = null,
var impersonateTarget: String = "chrome136", var impersonateTarget: String = "chrome136",
var useBuiltInHeaders: Boolean = true, var useBuiltInHeaders: Boolean = true,
var timeoutMs: Int = 30_000, var timeoutMs: Int = 30_000
var cookieJarPath: String? = null,
var sendCookies: Boolean = true,
var persistCookies: Boolean = true,
) )
@Keep @Keep
@@ -121,12 +118,6 @@ object Libcurl {
if (slist != 0L) checkOK(ce_setopt_ptr(easy, CURLOPT.HTTPHEADER, slist)) if (slist != 0L) checkOK(ce_setopt_ptr(easy, CURLOPT.HTTPHEADER, slist))
} }
if (req.sendCookies || req.persistCookies) {
val jar = (req.cookieJarPath ?: defaultCookieJarPath())
if (req.sendCookies) checkOK(ce_setopt_str(easy, CURLOPT.COOKIEFILE, jar))
if (req.persistCookies) checkOK(ce_setopt_str(easy, CURLOPT.COOKIEJAR, jar))
}
val method = req.method val method = req.method
if (!method.equals("GET", ignoreCase = true)) { if (!method.equals("GET", ignoreCase = true)) {
checkOK(ce_setopt_str(easy, CURLOPT.CUSTOMREQUEST, method)) checkOK(ce_setopt_str(easy, CURLOPT.CUSTOMREQUEST, method))
@@ -1,5 +1,7 @@
package com.futo.platformplayer.engine.packages package com.futo.platformplayer.engine.packages
import android.net.Uri
import androidx.core.net.toUri
import com.caoccao.javet.annotations.V8Convert import com.caoccao.javet.annotations.V8Convert
import com.caoccao.javet.annotations.V8Function import com.caoccao.javet.annotations.V8Function
import com.caoccao.javet.annotations.V8Property import com.caoccao.javet.annotations.V8Property
@@ -10,9 +12,13 @@ import com.caoccao.javet.values.V8Value
import com.caoccao.javet.values.primitive.V8ValueString import com.caoccao.javet.values.primitive.V8ValueString
import com.caoccao.javet.values.reference.V8ValueTypedArray import com.caoccao.javet.values.reference.V8ValueTypedArray
import com.curlbind.Libcurl import com.curlbind.Libcurl
import com.futo.platformplayer.api.http.ManagedHttpClient
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient
import com.futo.platformplayer.engine.IV8PluginConfig import com.futo.platformplayer.engine.IV8PluginConfig
import com.futo.platformplayer.engine.V8Plugin import com.futo.platformplayer.engine.V8Plugin
import com.futo.platformplayer.engine.exceptions.ScriptException
import com.futo.platformplayer.engine.exceptions.ScriptImplementationException
import com.futo.platformplayer.engine.internal.IV8Convertable import com.futo.platformplayer.engine.internal.IV8Convertable
import com.futo.platformplayer.engine.internal.V8BindObject import com.futo.platformplayer.engine.internal.V8BindObject
import com.futo.platformplayer.logging.Logger import com.futo.platformplayer.logging.Logger
@@ -43,8 +49,8 @@ class PackageHttpImp : V8Package {
constructor(plugin: V8Plugin, config: IV8PluginConfig) : super(plugin) { constructor(plugin: V8Plugin, config: IV8PluginConfig) : super(plugin) {
_config = config _config = config
_packageClient = PackageHttpClient(this, withAuth = false) _packageClient = PackageHttpClient(this, plugin.httpClient)
_packageClientAuth = PackageHttpClient(this, withAuth = true) _packageClientAuth = PackageHttpClient(this, plugin.httpClientAuth)
} }
fun cleanup() { fun cleanup() {
@@ -95,7 +101,10 @@ class PackageHttpImp : V8Package {
@V8Function @V8Function
fun newClient(withAuth: Boolean): PackageHttpClient { fun newClient(withAuth: Boolean): PackageHttpClient {
val client = PackageHttpClient(this, withAuth) val httpClient = if(withAuth) _plugin.httpClientAuth.clone() else _plugin.httpClient.clone();
if(httpClient is JSHttpClient)
_plugin.registerHttpClient(httpClient);
val client = PackageHttpClient(this, httpClient)
client.clientId()?.let { _clients[it] = client } client.clientId()?.let { _clients[it] = client }
return client return client
} }
@@ -672,9 +681,6 @@ class PackageHttpImp : V8Package {
@Transient @Transient
private val _package: PackageHttpImp private val _package: PackageHttpImp
@Transient
private val _withAuth: Boolean
val parentConfig: IV8PluginConfig val parentConfig: IV8PluginConfig
get() = _package._config get() = _package._config
@@ -686,44 +692,21 @@ class PackageHttpImp : V8Package {
@Volatile @Volatile
private var timeoutMs: Int = 30_000 private var timeoutMs: Int = 30_000
@Volatile
private var sendCookies: Boolean = true
@Volatile
private var updateCookies: Boolean = true
@Volatile
private var allowNewCookies: Boolean = true
@Volatile
private var cookieJarPath: String? = null
@Volatile @Volatile
private var impersonateTarget: String = "chrome136" private var impersonateTarget: String = "chrome136"
@Volatile @Volatile
private var useBuiltInHeaders: Boolean = true private var useBuiltInHeaders: Boolean = true
@Transient
private val _client: ManagedHttpClient;
@V8Property @V8Property
fun clientId(): String? = _clientId fun clientId(): String? = _clientId
constructor(pack: PackageHttpImp, withAuth: Boolean) : super() { constructor(pack: PackageHttpImp, baseClient: ManagedHttpClient) : super() {
_package = pack _package = pack
_withAuth = withAuth _client = baseClient
}
private fun ensureCookieJarPath(): String {
val existing = cookieJarPath
if (existing != null) return existing
val tmp = System.getProperty("java.io.tmpdir") ?: "/data/local/tmp"
val safeName = parentConfig.name.replace(Regex("[^a-zA-Z0-9._-]"), "_")
val fileName =
if (_withAuth) "imphttp.$safeName.auth.cookies.txt" else "imphttp.$safeName.cookies.txt"
val path = if (tmp.endsWith("/")) tmp + fileName else "$tmp/$fileName"
cookieJarPath = path
return path
} }
@V8Function @V8Function
@@ -737,17 +720,18 @@ class PackageHttpImp : V8Package {
@V8Function @V8Function
fun setDoApplyCookies(apply: Boolean) { fun setDoApplyCookies(apply: Boolean) {
sendCookies = apply if(_client is JSHttpClient)
_client.doApplyCookies = apply;
} }
@V8Function @V8Function
fun setDoUpdateCookies(update: Boolean) { fun setDoUpdateCookies(update: Boolean) {
updateCookies = update if(_client is JSHttpClient)
_client.doUpdateCookies = update;
} }
@V8Function @V8Function
fun setDoAllowNewCookies(allow: Boolean) { fun setDoAllowNewCookies(allow: Boolean) {
allowNewCookies = allow if(_client is JSHttpClient)
_client.doAllowNewCookies = allow;
} }
@V8Function @V8Function
@@ -1060,18 +1044,29 @@ class PackageHttpImp : V8Package {
private fun performCurl( private fun performCurl(
method: String, method: String,
url: String, url: String,
headers: Map<String, String>, hs: Map<String, String>, //TODO: Why is this not a Map<String, List<String>>
bodyBytes: ByteArray?, bodyBytes: ByteArray?,
impersonateTargetOverride: String? = null, impersonateTargetOverride: String? = null,
useBuiltInHeadersOverride: Boolean? = null, useBuiltInHeadersOverride: Boolean? = null,
timeoutMsOverride: Int? = null timeoutMsOverride: Int? = null
): Libcurl.Response { ): Libcurl.Response {
val jar = ensureCookieJarPath() val client = _client
if (client is JSHttpClient) {
if (!(client.config?.isUrlAllowed(url) ?: false)) {
throw Exception( "Attempted to access non-whitelisted url: $url\nAdd it to your config");
}
}
val finalImpersonateTarget = impersonateTargetOverride ?: this.impersonateTarget val finalImpersonateTarget = impersonateTargetOverride ?: this.impersonateTarget
val finalUseBuiltInHeaders = useBuiltInHeadersOverride ?: this.useBuiltInHeaders val finalUseBuiltInHeaders = useBuiltInHeadersOverride ?: this.useBuiltInHeaders
val finalTimeoutMs = timeoutMsOverride ?: this.timeoutMs val finalTimeoutMs = timeoutMsOverride ?: this.timeoutMs
val uri = url.toUri()
val headers = hs.toMutableMap()
if (client is JSHttpClient) {
client.applyHeaders(uri, headers, _client.isLoggedIn, true)
}
val req = Libcurl.Request( val req = Libcurl.Request(
url = url, url = url,
method = method, method = method,
@@ -1079,12 +1074,13 @@ class PackageHttpImp : V8Package {
body = bodyBytes, body = bodyBytes,
impersonateTarget = finalImpersonateTarget, impersonateTarget = finalImpersonateTarget,
useBuiltInHeaders = finalUseBuiltInHeaders, useBuiltInHeaders = finalUseBuiltInHeaders,
timeoutMs = finalTimeoutMs, timeoutMs = finalTimeoutMs
cookieJarPath = jar,
sendCookies = sendCookies,
persistCookies = updateCookies && allowNewCookies
) )
return Libcurl.perform(req) val resp = Libcurl.perform(req)
if (client is JSHttpClient) {
client.processRequest(method, resp.status, uri, resp.headers)
}
return resp
} }
private fun executeRequest( private fun executeRequest(