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

This commit is contained in:
Koen 2023-10-20 14:34:53 +02:00
commit 576b37f64c
15 changed files with 141 additions and 16 deletions

View file

@ -217,6 +217,9 @@ function pluginUpdateTestPlugin(config) {
}
function pluginLoginTestPlugin() {
return syncGET("/plugin/loginTestPlugin", {});
}//captchaLoginTestPlugin
function pluginCaptchaTestPlugin(url, html) {
return syncPOST("/plugin/captchaTestPlugin?url=" + url, {}, html);
}
function pluginLogoutTestPlugin() {
return syncGET("/plugin/logoutTestPlugin", {});

View file

@ -681,6 +681,9 @@
});
}, 1000);
},
captchaTestPlugin() {
captchaLoginTestPlugin();
},
logoutTestPlugin() {
pluginLogoutTestPlugin();
},
@ -838,6 +841,12 @@
this.Testing.lastResultError = "";
}
catch(ex) {
if(ex.plugin_type == "CaptchaRequiredException") {
let shouldCaptcha = confirm("Do you want to request captcha?");
if(shouldCaptcha) {
pluginCaptchaTestPlugin(ex.url, ex.body);
}
}
console.error("Failed to run test for " + req.title, ex);
this.Testing.lastResult = ""
if(ex.message)

View file

@ -72,6 +72,11 @@ class CaptchaRequiredException extends Error {
this.body = body;
}
}
class CriticalException extends ScriptException {
constructor(msg) {
super("CriticalException", msg);
}
}
class UnavailableException extends ScriptException {
constructor(msg) {
super("UnavailableException", msg);

View file

@ -7,6 +7,7 @@ import com.futo.platformplayer.api.media.models.comments.IPlatformComment
import com.futo.platformplayer.api.media.models.contents.IPlatformContent
import com.futo.platformplayer.api.media.models.contents.IPlatformContentDetails
import com.futo.platformplayer.api.media.structures.IPager
import com.futo.platformplayer.states.StateApp
import java.util.*
class DevJSClient : JSClient {
@ -24,6 +25,10 @@ class DevJSClient : JSClient {
_auth = auth;
_captcha = captcha;
this.devID = devID ?: UUID.randomUUID().toString().substring(0, 5);
onCaptchaException.subscribe { client, captcha ->
StateApp.instance.handleCaptchaException(client, captcha);
}
}
//TODO: Misisng auth/captcha pass on purpose?
constructor(context: Context, descriptor: SourcePluginDescriptor, script: String, auth: SourceAuth? = null, captcha: SourceCaptchaData? = null, savedState: String? = null, devID: String? = null): super(context, descriptor, savedState, script) {
@ -31,6 +36,10 @@ class DevJSClient : JSClient {
_auth = auth;
_captcha = captcha;
this.devID = devID ?: UUID.randomUUID().toString().substring(0, 5);
onCaptchaException.subscribe { client, captcha ->
StateApp.instance.handleCaptchaException(client, captcha);
}
}
fun setCaptcha(captcha: SourceCaptchaData? = null) {

View file

@ -68,7 +68,12 @@ class JSHttpClient : ManagedHttpClient {
if(cookiesToApply.size > 0) {
val cookieString = cookiesToApply.map { it.key + "=" + it.value }.joinToString("; ");
request.headers["Cookie"] = cookieString;
val existingCookies = request.headers["Cookie"];
if(!existingCookies.isNullOrEmpty())
request.headers["Cookie"] = existingCookies.trim(';') + "; " + cookieString;
else
request.headers["Cookie"] = cookieString;
}
//printTestCode(request.url, request.body, auth.headers, cookieString, request.headers.filter { !auth.headers.containsKey(it.key) });
}

View file

@ -69,9 +69,17 @@ abstract class MultiRefreshPager<T>: IRefreshPager<T>, IPager<T> {
if(pagerToAdd == null) {
if(toReplacePager != null && toReplacePager is PlaceholderPager && error != null) {
val pluginId = toReplacePager.placeholderFactory.invoke().id?.pluginId ?: "";
_currentPager = PlaceholderPager(5) {
_pagersReusable.add((PlaceholderPager(5) {
return@PlaceholderPager PlatformContentPlaceholder(pluginId, error)
} as IPager<T>;
} as IPager<T>).asReusable());
_currentPager = recreatePager(getCurrentSubPagers());
if(_currentPager is MultiParallelPager<*>)
runBlocking { (_currentPager as MultiParallelPager).initialize(); };
else if(_currentPager is MultiPager<*>)
(_currentPager as MultiPager).initialize()
onPagerChanged.emit(_currentPager);
}
return;

View file

@ -1,6 +1,7 @@
package com.futo.platformplayer.developer
import android.content.Context
import com.futo.platformplayer.activities.CaptchaActivity
import com.futo.platformplayer.activities.LoginActivity
import com.futo.platformplayer.api.http.ManagedHttpClient
import com.futo.platformplayer.api.http.server.HttpContext
@ -201,6 +202,28 @@ class DeveloperEndpoints(private val context: Context) {
context.respondCode(500, (ex::class.simpleName + ":" + ex.message) ?: "", "text/plain")
}
}
@HttpPOST("/plugin/captchaTestPlugin")
fun pluginCaptchaTestPlugin(context: HttpContext) {
val config = _testPlugin?.config as SourcePluginConfig;
val url = context.query.get("url")
val html = context.readContentString();
try {
val captchaConfig = config.captcha;
if(captchaConfig == null) {
context.respondCode(403, "This plugin doesn't support captcha");
return;
}
CaptchaActivity.showCaptcha(StateApp.instance.context, config, url, html) {
_testPluginVariables.clear();
_testPlugin = V8Plugin(StateApp.instance.context, config, null, JSHttpClient(null, null, it), JSHttpClient(null, null, it));
};
context.respondCode(200, "Captcha started");
}
catch(ex: Throwable) {
context.respondCode(500, (ex::class.simpleName + ":" + ex.message) ?: "", "text/plain")
}
}
@HttpGET("/plugin/loginTestPlugin")
fun pluginLoginTestPlugin(context: HttpContext) {
val config = _testPlugin?.config as SourcePluginConfig;

View file

@ -298,6 +298,7 @@ class V8Plugin {
private fun throwExceptionFromV8(config: IV8PluginConfig, pluginType: String, msg: String, innerEx: Exception? = null, stack: String? = null, code: String? = null) {
when(pluginType) {
"ScriptException" -> throw ScriptException(config, msg, innerEx, stack, code);
"CriticalException" -> throw ScriptCriticalException(config, msg, innerEx, stack, code);
"AgeException" -> throw ScriptAgeException(config, msg, innerEx, stack, code);
"UnavailableException" -> throw ScriptUnavailableException(config, msg, innerEx, stack, code);
"ScriptExecutionException" -> throw ScriptExecutionException(config, msg, innerEx, stack, code);

View file

@ -0,0 +1,17 @@
package com.futo.platformplayer.engine.exceptions
import com.caoccao.javet.values.reference.V8ValueObject
import com.futo.platformplayer.engine.IV8PluginConfig
import com.futo.platformplayer.getOrThrow
open class ScriptCriticalException(config: IV8PluginConfig, error: String, ex: Exception? = null, stack: String? = null, code: String? = null) : ScriptException(config, error, ex, stack, code) {
companion object {
fun fromV8(config: IV8PluginConfig, obj: V8ValueObject) : ScriptException {
return ScriptCriticalException(config, obj.getOrThrow(config, "message", "ScriptCriticalException"));
}
}
}

View file

@ -258,11 +258,17 @@ class SourceDetailFragment : MainFragment() {
}
}
val clientIfExists = StatePlugins.instance.getPlugin(config.id);
groups.add(
BigButtonGroup(c, "Management",
BigButton(c, "Uninstall", "Removes the plugin from the app", R.drawable.ic_block) {
uninstallSource();
}.withBackground(R.drawable.background_big_button_red)
}.withBackground(R.drawable.background_big_button_red),
if(clientIfExists?.captchaEncrypted != null)
BigButton(c, "Delete Captcha", "Deletes captcha for this plugin", R.drawable.ic_block) {
clientIfExists?.updateCaptcha(null);
}.withBackground(R.drawable.background_big_button_red)
else null
)
)

View file

@ -2,6 +2,7 @@ package com.futo.platformplayer.others
import android.net.Uri
import android.webkit.*
import com.futo.platformplayer.BuildConfig
import com.futo.platformplayer.api.http.ManagedHttpClient
import com.futo.platformplayer.api.media.Serializer
import com.futo.platformplayer.constructs.Event1
@ -43,6 +44,8 @@ class LoginWebViewClient : WebViewClient {
private var urlFound = false;
override fun onPageFinished(view: WebView?, url: String?) {
if(BuildConfig.DEBUG)
Logger.i(TAG, "Login Url Page: " + url);
super.onPageFinished(view, url);
onPageLoaded.emit(view, url);
}
@ -56,11 +59,29 @@ class LoginWebViewClient : WebViewClient {
return null;
}
var completionUrlExcludeQuery = false
var completionUrlToCheck = if(urlFound) null else _authConfig.completionUrl;
if(completionUrlToCheck != null) {
if(completionUrlToCheck.endsWith("?*")) {
completionUrlToCheck = completionUrlToCheck.substring(0, completionUrlToCheck.length - 2);
completionUrlExcludeQuery = true;
}
}
val domain = request.url.host;
val domainLower = request.url.host?.lowercase();
val urlString = request.url.toString();
if(_authConfig.completionUrl == null)
urlFound = true;
else urlFound = urlFound || request.url == Uri.parse(_authConfig.completionUrl);
else urlFound = urlFound || (
if(completionUrlExcludeQuery)
(if(urlString.contains("?"))
urlString.substring(0, urlString.indexOf("?")) == completionUrlToCheck
else urlString == completionUrlToCheck)
else
request.url == Uri.parse(_authConfig.completionUrl)
);
//HEADERS
if(domainLower != null) {

View file

@ -29,6 +29,7 @@ import com.futo.platformplayer.activities.CaptchaActivity
import com.futo.platformplayer.activities.IWithResultLauncher
import com.futo.platformplayer.activities.MainActivity
import com.futo.platformplayer.api.media.Serializer
import com.futo.platformplayer.api.media.platforms.js.DevJSClient
import com.futo.platformplayer.api.media.platforms.js.JSClient
import com.futo.platformplayer.api.media.platforms.js.internal.JSHttpClient
import com.futo.platformplayer.background.BackgroundWorker
@ -672,13 +673,20 @@ class StateApp {
UIDialogs.showConfirmationDialog(context, "Captcha required\nPlugin [${client.config.name}]", {
CaptchaActivity.showCaptcha(context, client.config, exception.url, exception.body) {
hasCaptchaDialog = false;
StatePlugins.instance.setPluginCaptcha(client.config.id, it);
scopeOrNull?.launch(Dispatchers.IO) {
try {
StatePlatform.instance.reloadClient(context, client.config.id);
} catch (e: Throwable) {
Logger.e(SourceDetailFragment.TAG, "Failed to reload client.", e)
return@launch;
if(client is DevJSClient) {
client.setCaptcha(it);
client.recreate(context);
}
else {
StatePlugins.instance.setPluginCaptcha(client.config.id, it);
scopeOrNull?.launch(Dispatchers.IO) {
try {
StatePlatform.instance.reloadClient(context, client.config.id);
} catch (e: Throwable) {
Logger.e(SourceDetailFragment.TAG, "Failed to reload client.", e)
return@launch;
}
}
}
}

View file

@ -16,6 +16,7 @@ import com.futo.platformplayer.constructs.Event1
import com.futo.platformplayer.constructs.Event2
import com.futo.platformplayer.engine.exceptions.PluginException
import com.futo.platformplayer.engine.exceptions.ScriptCaptchaRequiredException
import com.futo.platformplayer.engine.exceptions.ScriptCriticalException
import com.futo.platformplayer.exceptions.ChannelException
import com.futo.platformplayer.findNonRuntimeException
import com.futo.platformplayer.fragment.mainactivity.main.PolycentricProfile
@ -320,7 +321,16 @@ class StateSubscriptions {
synchronized(failedPlugins) {
//Fail all subscription calls to plugin if it has a captcha issue
if(ex.config is SourcePluginConfig && !failedPlugins.contains(ex.config.id)) {
Logger.w(TAG, "Subscriptions fetch ignoring plugin [${ex.config.name}] due to Captcha");
Logger.w(TAG, "Subscriptionsgnoring plugin [${ex.config.name}] due to Captcha");
failedPlugins.add(ex.config.id);
}
}
}
else if(ex is ScriptCriticalException) {
synchronized(failedPlugins) {
//Fail all subscription calls to plugin if it has a critical issue
if(ex.config is SourcePluginConfig && !failedPlugins.contains(ex.config.id)) {
Logger.w(TAG, "Subscriptions ignoring plugin [${ex.config.name}] due to critical exception:\n" + ex.message);
failedPlugins.add(ex.config.id);
}
}

View file

@ -14,13 +14,13 @@ class BigButtonGroup : LinearLayout {
_header = findViewById(R.id.header_title);
_buttons = findViewById(R.id.buttons);
}
constructor(context: Context, header: String, vararg buttons: BigButton) : super(context) {
constructor(context: Context, header: String, vararg buttons: BigButton?) : super(context) {
inflate(context, R.layout.big_button_group, this);
_header = findViewById(R.id.header_title);
_buttons = findViewById(R.id.buttons);
_header.text = header;
for(button in buttons)
for(button in buttons.filterNotNull())
_buttons.addView(button);
}

@ -1 +1 @@
Subproject commit d05a959174bcceb616c9f42043466e9e1258f519
Subproject commit 4ffd2a48c7ebed2c8512e092a6bae4b5447aff34