mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-19 19:14:51 +00:00
Working video cookies
This commit is contained in:
parent
5d7dc1fdcb
commit
73dd52af28
40 changed files with 345 additions and 125 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -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
|
||||
|
|
|
@ -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());
|
|
@ -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<String, String?>? = 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 {
|
||||
|
|
|
@ -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<IPlatformContent> = 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<String, List<String>>?): IPager<IPlatformContent> = 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<PlatformAuthorLink> = 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<String, List<String>>?): IPager<IPlatformContent> = 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<IPlatformComment>();
|
||||
}
|
||||
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<IPlatformComment> {
|
||||
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
|
||||
|
|
|
@ -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<String, String?>? = 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<String>) {
|
||||
constructor(config :SourcePluginConfig, authEncrypted: String? = null, captchaEncrypted: String? = null, flags: List<String>, settings: HashMap<String, String?>? = null) {
|
||||
this.config = config;
|
||||
this.authEncrypted = authEncrypted;
|
||||
this.captchaEncrypted = captchaEncrypted;
|
||||
this.flags = flags;
|
||||
this.settings = settings ?: hashMapOf();
|
||||
}
|
||||
|
||||
fun getSettingsWithDefaults(): HashMap<String, String?> {
|
||||
|
|
|
@ -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<String, HashMap<String, String>>;
|
||||
private var _otherCookieMap: HashMap<String, HashMap<String, String>>;
|
||||
|
||||
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<String, String>, 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<String, String>();
|
||||
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<String, String>();
|
||||
_currentCookieMap[domainToUse] = newMap
|
||||
newMap;
|
||||
if ((_auth != null || _currentCookieMap.isNotEmpty())) {
|
||||
val cookieMap = if (_currentCookieMap.containsKey(domainToUse))
|
||||
_currentCookieMap[domainToUse]!!;
|
||||
else {
|
||||
val newMap = hashMapOf<String, String>();
|
||||
_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<String, String>();
|
||||
_otherCookieMap[domainToUse] = newMap
|
||||
newMap;
|
||||
}
|
||||
if (cookieMap.containsKey(cookie.first) || doAllowNewCookies)
|
||||
cookieMap[cookie.first] = cookieValue;
|
||||
}
|
||||
if(cookieMap.containsKey(cookie.first) || doAllowNewCookies)
|
||||
cookieMap[cookie.first] = cookieValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<PlatformAuthorLink>, IPager<PlatformAuthorLink> {
|
||||
|
||||
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);
|
||||
|
|
|
@ -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<V8ValueObject>("getReplies", arrayOf<Any>());
|
||||
return JSCommentPager(_config!!, _plugin!!, obj);
|
||||
val plugin = if(client is JSClient) client else throw NotImplementedError("Only implemented for JSClient");
|
||||
return JSCommentPager(_config!!, plugin, obj);
|
||||
}
|
||||
}
|
|
@ -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<IPlatformComment>, IPager<IPlatformComment> {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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<IPlatformContent>, 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);
|
||||
}
|
||||
}
|
|
@ -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<IPlatformLiveEvent>, 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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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<T> : IPager<T> {
|
||||
protected val plugin: V8Plugin;
|
||||
protected val plugin: JSClient;
|
||||
protected val config: SourcePluginConfig;
|
||||
protected var pager: V8ValueObject;
|
||||
|
||||
|
@ -21,9 +22,9 @@ abstract class JSPager<T> : IPager<T> {
|
|||
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<T> : IPager<T> {
|
|||
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<Any>());
|
||||
};
|
||||
_hasMorePages = pager.getOrDefault(config, "hasMore", "Pager", false) ?: false;
|
||||
|
|
|
@ -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<IPlatformVideo>;
|
||||
|
||||
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"));
|
||||
}
|
||||
|
||||
|
|
|
@ -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<IPlatformPlaylist>, IPager<IPlatformPlaylist> {
|
||||
|
||||
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);
|
||||
|
|
|
@ -54,6 +54,6 @@ class JSPostDetails : JSPost, IPlatformPost, IPlatformPostDetails {
|
|||
|
||||
private fun getCommentsJS(client: JSClient): JSCommentPager {
|
||||
val commentPager = _content.invoke<V8ValueObject>("getComments", arrayOf<Any>());
|
||||
return JSCommentPager(_pluginConfig, client.getUnderlyingPlugin(), commentPager);
|
||||
return JSCommentPager(_pluginConfig, client, commentPager);
|
||||
}
|
||||
}
|
|
@ -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<String, String>;
|
||||
override var headers: Map<String, String>;
|
||||
|
||||
constructor(config: IV8PluginConfig, obj: V8ValueObject) {
|
||||
val contextName = "ModifyRequestResponse";
|
||||
|
|
|
@ -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<Any>(_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 {
|
||||
|
|
|
@ -44,13 +44,14 @@ class JSVideoDetails : JSVideo, IPlatformVideoDetails {
|
|||
override val subtitles: List<ISubtitleSource>;
|
||||
|
||||
|
||||
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<V8ValueObject>(config, "dash", contextName));
|
||||
hls = JSSource.fromV8HLSNullable(config, _content.getOrThrowNullable<V8ValueObject>(config, "hls", contextName));
|
||||
live = JSSource.fromV8VideoNullable(config, _content.getOrThrowNullable<V8ValueObject>(config, "live", contextName));
|
||||
video = JSVideoSourceDescriptor.fromV8(plugin, _content.getOrThrow(config, "video", contextName));
|
||||
dash = JSSource.fromV8DashNullable(plugin, _content.getOrThrowNullable<V8ValueObject>(config, "dash", contextName));
|
||||
hls = JSSource.fromV8HLSNullable(plugin, _content.getOrThrowNullable<V8ValueObject>(config, "hls", contextName));
|
||||
live = JSSource.fromV8VideoNullable(plugin, _content.getOrThrowNullable<V8ValueObject>(config, "live", contextName));
|
||||
rating = IRating.fromV8OrDefault(config, _content.getOrDefault<V8ValueObject>(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);
|
||||
}
|
||||
}
|
|
@ -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<IPlatformVideo> {
|
||||
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<IVideoSource>;
|
||||
override val audioSources: Array<IAudioSource>;
|
||||
|
||||
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<V8ValueArray>(config, "videoSources", contextName).toArray()
|
||||
.map { JSSource.fromV8Video(config, it as V8ValueObject) }
|
||||
.map { JSSource.fromV8Video(plugin, it as V8ValueObject) }
|
||||
.toTypedArray();
|
||||
this.audioSources = obj.getOrThrow<V8ValueArray>(config, "audioSources", contextName).toArray()
|
||||
.map { JSSource.fromV8Audio(config, it as V8ValueObject) }
|
||||
.map { JSSource.fromV8Audio(plugin, it as V8ValueObject) }
|
||||
.toTypedArray();
|
||||
}
|
||||
}
|
|
@ -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<IVideoSource>;
|
||||
|
||||
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<V8ValueArray>(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}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<String, JSHttpClient> = ConcurrentHashMap();
|
||||
|
||||
|
||||
val httpClient: ManagedHttpClient get() = _client;
|
||||
val httpClientAuth: ManagedHttpClient get() = _clientAuth;
|
||||
val httpClientOthers: Map<String, JSHttpClient> get() = _clientOthers;
|
||||
|
||||
fun registerHttpClient(client: JSHttpClient) {
|
||||
synchronized(_clientOthers) {
|
||||
_clientOthers.put(client.clientId, client);
|
||||
}
|
||||
}
|
||||
|
||||
private val _runtimeLock = Object();
|
||||
var _runtime : V8Runtime? = null;
|
||||
|
|
|
@ -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<String, String>();
|
||||
@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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<String, String?>) {
|
||||
val client = StatePlatform.instance.getDevClient();
|
||||
client?.let {
|
||||
it.descriptor.settings = settings;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
fun runServer() {
|
||||
if(_server != null)
|
||||
|
|
|
@ -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<String, String?>) {
|
||||
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) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
1
app/src/unstable/assets/sources/niconico
Submodule
1
app/src/unstable/assets/sources/niconico
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit f2086dc2cf6387f692049f52cdf938313dc53654
|
|
@ -1 +1 @@
|
|||
Subproject commit 128b03c5911d414ad230afd75c35c6be5b1e87db
|
||||
Subproject commit fad5e14f84573796b3989794c35f34a1f88f03a6
|
Loading…
Add table
Reference in a new issue