mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
fixed sync stuff and tv stuff
This commit is contained in:
parent
10c945f497
commit
7cbdc1fc6c
24 changed files with 209 additions and 160 deletions
|
@ -13,6 +13,8 @@ import com.fasterxml.jackson.module.kotlin.KotlinModule
|
|||
import com.lagradost.cloudstream3.animeproviders.*
|
||||
import com.lagradost.cloudstream3.metaproviders.CrossTmdbProvider
|
||||
import com.lagradost.cloudstream3.movieproviders.*
|
||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.aniListApi
|
||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.malApi
|
||||
import com.lagradost.cloudstream3.ui.player.SubtitleData
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import okhttp3.Interceptor
|
||||
|
@ -119,10 +121,10 @@ object APIHolder {
|
|||
return null
|
||||
}
|
||||
|
||||
fun getApiFromUrlNull(url : String?) : MainAPI? {
|
||||
fun getApiFromUrlNull(url: String?): MainAPI? {
|
||||
if (url == null) return null
|
||||
for (api in allProviders) {
|
||||
if(url.startsWith(api.mainUrl))
|
||||
if (url.startsWith(api.mainUrl))
|
||||
return api
|
||||
}
|
||||
return null
|
||||
|
@ -397,7 +399,7 @@ abstract class MainAPI {
|
|||
}
|
||||
|
||||
/** An okhttp interceptor for used in OkHttpDataSource */
|
||||
open fun getVideoInterceptor(extractorLink: ExtractorLink) : Interceptor? {
|
||||
open fun getVideoInterceptor(extractorLink: ExtractorLink): Interceptor? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
@ -571,10 +573,10 @@ enum class SearchQuality {
|
|||
}
|
||||
|
||||
/**Add anything to here if you find a site that uses some specific naming convention*/
|
||||
fun getQualityFromString(string: String?) : SearchQuality? {
|
||||
val check = (string ?: return null).trim().lowercase().replace(" ","")
|
||||
fun getQualityFromString(string: String?): SearchQuality? {
|
||||
val check = (string ?: return null).trim().lowercase().replace(" ", "")
|
||||
|
||||
return when(check) {
|
||||
return when (check) {
|
||||
"cam" -> SearchQuality.Cam
|
||||
"camrip" -> SearchQuality.CamRip
|
||||
"hdcam" -> SearchQuality.HdCam
|
||||
|
@ -589,7 +591,7 @@ fun getQualityFromString(string: String?) : SearchQuality? {
|
|||
"telesync" -> SearchQuality.Telesync
|
||||
"ts" -> SearchQuality.Telesync
|
||||
"dvd" -> SearchQuality.DVD
|
||||
"blueray" -> SearchQuality.BlueRay
|
||||
"blueray" -> SearchQuality.BlueRay
|
||||
"bluray" -> SearchQuality.BlueRay
|
||||
"br" -> SearchQuality.BlueRay
|
||||
"standard" -> SearchQuality.SD
|
||||
|
@ -614,7 +616,7 @@ interface SearchResponse {
|
|||
var type: TvType?
|
||||
var posterUrl: String?
|
||||
var id: Int?
|
||||
var quality : SearchQuality?
|
||||
var quality: SearchQuality?
|
||||
}
|
||||
|
||||
enum class ActorRole {
|
||||
|
@ -703,8 +705,12 @@ interface LoadResponse {
|
|||
var recommendations: List<SearchResponse>?
|
||||
var actors: List<ActorData>?
|
||||
var comingSoon: Boolean
|
||||
var syncData: MutableMap<String, String>
|
||||
|
||||
companion object {
|
||||
val malIdPrefix = malApi.idPrefix
|
||||
val aniListIdPrefix = aniListApi.idPrefix
|
||||
|
||||
@JvmName("addActorNames")
|
||||
fun LoadResponse.addActors(actors: List<String>?) {
|
||||
this.actors = actors?.map { ActorData(Actor(it)) }
|
||||
|
@ -725,6 +731,30 @@ interface LoadResponse {
|
|||
this.actors = actors?.map { actor -> ActorData(actor) }
|
||||
}
|
||||
|
||||
fun LoadResponse.addMalId(id: Int?) {
|
||||
this.syncData[malIdPrefix] = (id ?: return).toString()
|
||||
}
|
||||
|
||||
fun LoadResponse.addAniListId(id: Int?) {
|
||||
this.syncData[aniListIdPrefix] = (id ?: return).toString()
|
||||
}
|
||||
|
||||
fun LoadResponse.addImdbUrl(url : String?) {
|
||||
addImdbId(imdbUrlToIdNullable(url))
|
||||
}
|
||||
|
||||
fun LoadResponse.addImdbId(id: String?) {
|
||||
// TODO add imdb sync
|
||||
}
|
||||
|
||||
fun LoadResponse.addTrackId(id: String?) {
|
||||
// TODO add trackt sync
|
||||
}
|
||||
|
||||
fun LoadResponse.addkitsuId(id: String?) {
|
||||
// TODO add kitsu sync
|
||||
}
|
||||
|
||||
fun LoadResponse.setDuration(input: String?) {
|
||||
val cleanInput = input?.trim()?.replace(" ", "") ?: return
|
||||
Regex("([0-9]*)h.*?([0-9]*)m").find(cleanInput)?.groupValues?.let { values ->
|
||||
|
@ -789,6 +819,7 @@ data class TorrentLoadResponse(
|
|||
override var recommendations: List<SearchResponse>? = null,
|
||||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
override var syncData: MutableMap<String, String> = mutableMapOf(),
|
||||
) : LoadResponse
|
||||
|
||||
data class AnimeLoadResponse(
|
||||
|
@ -802,21 +833,20 @@ data class AnimeLoadResponse(
|
|||
override var posterUrl: String? = null,
|
||||
override var year: Int? = null,
|
||||
|
||||
var episodes: HashMap<DubStatus, List<AnimeEpisode>> = hashMapOf(),
|
||||
var episodes: MutableMap<DubStatus, List<AnimeEpisode>> = mutableMapOf(),
|
||||
var showStatus: ShowStatus? = null,
|
||||
|
||||
override var plot: String? = null,
|
||||
override var tags: List<String>? = null,
|
||||
var synonyms: List<String>? = null,
|
||||
|
||||
var malId: Int? = null,
|
||||
var anilistId: Int? = null,
|
||||
override var rating: Int? = null,
|
||||
override var duration: Int? = null,
|
||||
override var trailerUrl: String? = null,
|
||||
override var recommendations: List<SearchResponse>? = null,
|
||||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
override var syncData: MutableMap<String, String> = mutableMapOf(),
|
||||
) : LoadResponse
|
||||
|
||||
fun AnimeLoadResponse.addEpisodes(status: DubStatus, episodes: List<AnimeEpisode>?) {
|
||||
|
@ -828,15 +858,15 @@ fun MainAPI.newAnimeLoadResponse(
|
|||
name: String,
|
||||
url: String,
|
||||
type: TvType,
|
||||
comingSoonIfNone : Boolean,
|
||||
comingSoonIfNone: Boolean,
|
||||
initializer: AnimeLoadResponse.() -> Unit = { },
|
||||
): AnimeLoadResponse {
|
||||
val builder = AnimeLoadResponse(name = name, url = url, apiName = this.name, type = type)
|
||||
builder.initializer()
|
||||
if(comingSoonIfNone) {
|
||||
if (comingSoonIfNone) {
|
||||
builder.comingSoon = true
|
||||
for (key in builder.episodes.keys)
|
||||
if(!builder.episodes[key].isNullOrEmpty()) {
|
||||
if (!builder.episodes[key].isNullOrEmpty()) {
|
||||
builder.comingSoon = false
|
||||
break
|
||||
}
|
||||
|
@ -864,7 +894,6 @@ data class MovieLoadResponse(
|
|||
override var year: Int? = null,
|
||||
override var plot: String? = null,
|
||||
|
||||
var imdbId: String? = null,
|
||||
override var rating: Int? = null,
|
||||
override var tags: List<String>? = null,
|
||||
override var duration: Int? = null,
|
||||
|
@ -872,6 +901,7 @@ data class MovieLoadResponse(
|
|||
override var recommendations: List<SearchResponse>? = null,
|
||||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
override var syncData: MutableMap<String, String> = mutableMapOf(),
|
||||
) : LoadResponse
|
||||
|
||||
fun MainAPI.newMovieLoadResponse(
|
||||
|
@ -916,7 +946,6 @@ data class TvSeriesLoadResponse(
|
|||
override var plot: String? = null,
|
||||
|
||||
var showStatus: ShowStatus? = null,
|
||||
var imdbId: String? = null,
|
||||
override var rating: Int? = null,
|
||||
override var tags: List<String>? = null,
|
||||
override var duration: Int? = null,
|
||||
|
@ -924,6 +953,7 @@ data class TvSeriesLoadResponse(
|
|||
override var recommendations: List<SearchResponse>? = null,
|
||||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
override var syncData: MutableMap<String, String> = mutableMapOf(),
|
||||
) : LoadResponse
|
||||
|
||||
fun MainAPI.newTvSeriesLoadResponse(
|
||||
|
@ -954,5 +984,5 @@ fun fetchUrls(text: String?): List<String> {
|
|||
return linkRegex.findAll(text).map { it.value.trim().removeSurrounding("\"") }.toList()
|
||||
}
|
||||
|
||||
fun String?.toRatingInt() : Int? =
|
||||
fun String?.toRatingInt(): Int? =
|
||||
this?.trim()?.toDoubleOrNull()?.absoluteValue?.times(1000f)?.toInt()
|
||||
|
|
|
@ -275,21 +275,26 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
if (str.contains("/${api.redirectUrl}")) {
|
||||
ioSafe {
|
||||
Log.i(TAG, "handleAppIntent $str")
|
||||
if (api.handleRedirect(str)) {
|
||||
val isSuccessful = api.handleRedirect(str)
|
||||
|
||||
if (isSuccessful) {
|
||||
Log.i(TAG, "authenticated ${api.name}")
|
||||
this.runOnUiThread {
|
||||
try {
|
||||
showToast(
|
||||
this,
|
||||
getString(R.string.authenticated_user).format(api.name)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logError(e) // format might fail
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, "failed to authenticate ${api.name}")
|
||||
}
|
||||
|
||||
this.runOnUiThread {
|
||||
try {
|
||||
showToast(
|
||||
this,
|
||||
getString(if (isSuccessful) R.string.authenticated_user else R.string.authenticated_user_fail).format(
|
||||
api.name
|
||||
)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
logError(e) // format might fail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ package com.lagradost.cloudstream3.animeproviders
|
|||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
||||
import com.lagradost.cloudstream3.network.AppResponse
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
|
@ -305,8 +307,8 @@ class AnimePaheProvider : MainAPI() {
|
|||
null
|
||||
}
|
||||
|
||||
this.malId = malId
|
||||
this.anilistId = anilistId
|
||||
addMalId(malId)
|
||||
addAniListId(anilistId)
|
||||
this.trailerUrl = trailer
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package com.lagradost.cloudstream3.animeproviders
|
||||
|
||||
import java.util.*
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.nodes.Element
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.*
|
||||
|
||||
class AnimeWorldProvider : MainAPI() {
|
||||
override var mainUrl = "https://www.animeworld.tv"
|
||||
|
@ -170,8 +172,8 @@ class AnimeWorldProvider : MainAPI() {
|
|||
showStatus = status
|
||||
plot = description
|
||||
tags = genres
|
||||
this.malId = malId
|
||||
this.anilistId = anlId
|
||||
addMalId(malId)
|
||||
addAniListId(anlId)
|
||||
this.rating = rating
|
||||
this.duration = duration
|
||||
this.trailerUrl = trailerUrl
|
||||
|
|
|
@ -4,6 +4,8 @@ import android.util.Log
|
|||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream
|
||||
import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.runSflixExtractorVerifierJob
|
||||
import com.lagradost.cloudstream3.network.Requests.Companion.await
|
||||
|
@ -291,8 +293,8 @@ class ZoroProvider : MainAPI() {
|
|||
this.tags = tags
|
||||
this.recommendations = recommendations
|
||||
this.actors = actors
|
||||
this.malId = syncData?.malId?.toIntOrNull()
|
||||
this.anilistId = syncData?.aniListId?.toIntOrNull()
|
||||
addMalId(syncData?.malId?.toIntOrNull())
|
||||
addAniListId(syncData?.aniListId?.toIntOrNull())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.lagradost.cloudstream3.metaproviders
|
|||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.uwetrottmann.tmdb2.Tmdb
|
||||
import com.uwetrottmann.tmdb2.entities.*
|
||||
|
@ -135,7 +136,8 @@ open class TmdbProvider : MainAPI() {
|
|||
}.get(Calendar.YEAR)
|
||||
}
|
||||
plot = overview
|
||||
imdbId = external_ids?.imdb_id
|
||||
addImdbId(external_ids?.imdb_id)
|
||||
|
||||
tags = genres?.mapNotNull { it.name }
|
||||
duration = episode_run_time?.average()?.toInt()
|
||||
rating = this@toLoadResponse.rating
|
||||
|
@ -163,7 +165,7 @@ open class TmdbProvider : MainAPI() {
|
|||
}.get(Calendar.YEAR)
|
||||
}
|
||||
plot = overview
|
||||
imdbId = external_ids?.imdb_id
|
||||
addImdbId(external_ids?.imdb_id)
|
||||
tags = genres?.mapNotNull { it.name }
|
||||
duration = runtime
|
||||
rating = this@toLoadResponse.rating
|
||||
|
@ -251,7 +253,8 @@ open class TmdbProvider : MainAPI() {
|
|||
val found = idRegex.find(url)
|
||||
|
||||
val isTvSeries = found?.groupValues?.getOrNull(1).equals("tv", ignoreCase = true)
|
||||
val id = found?.groupValues?.getOrNull(2)?.toIntOrNull() ?: throw ErrorLoadingException("No id found")
|
||||
val id = found?.groupValues?.getOrNull(2)?.toIntOrNull()
|
||||
?: throw ErrorLoadingException("No id found")
|
||||
|
||||
return if (useMetaLoadResponse) {
|
||||
return if (isTvSeries) {
|
||||
|
@ -263,8 +266,8 @@ open class TmdbProvider : MainAPI() {
|
|||
?.let {
|
||||
it.results?.map { res -> res.toSearchResponse() }
|
||||
}?.let { list ->
|
||||
response.recommendations = list
|
||||
}
|
||||
response.recommendations = list
|
||||
}
|
||||
|
||||
if (response.actors.isNullOrEmpty())
|
||||
tmdb.tvService().credits(id, "en-US").awaitResponse().body()?.let {
|
||||
|
|
|
@ -167,7 +167,6 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
year?.toIntOrNull(),
|
||||
descipt,
|
||||
null,
|
||||
null,
|
||||
rating
|
||||
)
|
||||
} else {
|
||||
|
|
|
@ -107,7 +107,6 @@ class AsiaFlixProvider : MainAPI() {
|
|||
synopsis,
|
||||
getStatus(tvStatus ?: ""),
|
||||
null,
|
||||
null,
|
||||
genre?.split(",")?.map { it.trim() }
|
||||
)
|
||||
}
|
||||
|
|
|
@ -286,7 +286,6 @@ open class BflixProvider() : MainAPI() {
|
|||
year?.toIntOrNull(),
|
||||
description,
|
||||
null,
|
||||
null,
|
||||
rating,
|
||||
tags,
|
||||
recommendations = recommendations,
|
||||
|
@ -303,7 +302,6 @@ open class BflixProvider() : MainAPI() {
|
|||
poster,
|
||||
year?.toIntOrNull(),
|
||||
description,
|
||||
null,
|
||||
rating,
|
||||
tags,
|
||||
recommendations = recommendations,
|
||||
|
|
|
@ -182,7 +182,6 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
)?.destructured?.component1()?.toIntOrNull(),
|
||||
description,
|
||||
null,
|
||||
null,
|
||||
soup.selectFirst(".videoDetails").select("a[href*=\"/category/\"]")
|
||||
.map { it.text().trim() }
|
||||
))
|
||||
|
@ -204,7 +203,6 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
description,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
categories.toList()
|
||||
) else (episodes?.first() as MovieLoadResponse)
|
||||
}
|
||||
|
|
|
@ -235,7 +235,6 @@ class LookMovieProvider : MainAPI() {
|
|||
poster,
|
||||
year,
|
||||
descript,
|
||||
null,
|
||||
rating
|
||||
)
|
||||
} else {
|
||||
|
@ -292,7 +291,6 @@ class LookMovieProvider : MainAPI() {
|
|||
year,
|
||||
descript,
|
||||
null,
|
||||
null,
|
||||
rating
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.lagradost.cloudstream3.movieproviders
|
|||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbUrl
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
|
@ -144,17 +145,17 @@ class MeloMovieProvider : MainAPI() {
|
|||
if (type == 1) { // MOVIE
|
||||
val serialize = document.selectFirst("table.accordion__list")
|
||||
?: throw ErrorLoadingException("No links found")
|
||||
return MovieLoadResponse(
|
||||
return newMovieLoadResponse(
|
||||
title,
|
||||
url,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
serializeData(serialize),
|
||||
poster,
|
||||
year,
|
||||
plot,
|
||||
imdbUrlToIdNullable(imdbUrl)
|
||||
)
|
||||
serializeData(serialize)
|
||||
) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = plot
|
||||
addImdbUrl(imdbUrl)
|
||||
}
|
||||
} else if (type == 2) {
|
||||
val episodes = ArrayList<TvSeriesEpisode>()
|
||||
val seasons = document.select("div.accordion__card")
|
||||
|
@ -175,18 +176,17 @@ class MeloMovieProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
episodes.reverse()
|
||||
return TvSeriesLoadResponse(
|
||||
return newTvSeriesLoadResponse(
|
||||
title,
|
||||
url,
|
||||
this.name,
|
||||
TvType.TvSeries,
|
||||
episodes,
|
||||
poster,
|
||||
year,
|
||||
plot,
|
||||
null,
|
||||
imdbUrlToIdNullable(imdbUrl)
|
||||
)
|
||||
episodes
|
||||
) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = plot
|
||||
addImdbUrl(imdbUrl)
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -163,7 +163,6 @@ class PelisflixProvider : MainAPI() {
|
|||
year?.toIntOrNull(),
|
||||
descipt2,
|
||||
null,
|
||||
null,
|
||||
rating
|
||||
)
|
||||
} else {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package com.lagradost.cloudstream3.movieproviders
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.*
|
||||
|
||||
class PelisplusHDProvider:MainAPI() {
|
||||
override var mainUrl = "https://pelisplushd.net"
|
||||
|
@ -137,7 +137,6 @@ class PelisplusHDProvider:MainAPI() {
|
|||
description,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
tags,
|
||||
)
|
||||
}
|
||||
|
@ -152,7 +151,6 @@ class PelisplusHDProvider:MainAPI() {
|
|||
year,
|
||||
description,
|
||||
null,
|
||||
null,
|
||||
tags,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -160,7 +160,6 @@ class SeriesflixProvider : MainAPI() {
|
|||
year?.toIntOrNull(),
|
||||
descipt,
|
||||
null,
|
||||
null,
|
||||
rating
|
||||
)
|
||||
} else {
|
||||
|
|
|
@ -76,7 +76,6 @@ class VfFilmProvider : MainAPI() {
|
|||
val title = document?.selectFirst("div.SubTitle")?.text()
|
||||
?: throw ErrorLoadingException("Service might be unavailable")
|
||||
|
||||
|
||||
val year = document.select("span.Date").text()?.toIntOrNull()
|
||||
|
||||
val rating = document.select("span.AAIco-star").text()
|
||||
|
@ -88,7 +87,6 @@ class VfFilmProvider : MainAPI() {
|
|||
|
||||
val descript = document.selectFirst("div.Description > p").text()
|
||||
|
||||
|
||||
val players = document.select("ul.TPlayerNv > li")
|
||||
var number_player = 0
|
||||
var found = false
|
||||
|
@ -108,17 +106,17 @@ class VfFilmProvider : MainAPI() {
|
|||
|
||||
val data = getDirect("$mainUrl/?trembed=$i&trid=$trid&trtype=1")
|
||||
|
||||
return MovieLoadResponse(
|
||||
return newMovieLoadResponse(
|
||||
title,
|
||||
url,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
data,
|
||||
poster,
|
||||
year,
|
||||
descript,
|
||||
rating,
|
||||
duration
|
||||
)
|
||||
data
|
||||
) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = descript
|
||||
//this.rating = rating
|
||||
this.duration = duration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,7 +160,6 @@ class VfSerieProvider : MainAPI() {
|
|||
year,
|
||||
descript,
|
||||
null,
|
||||
null,
|
||||
rating
|
||||
)
|
||||
}
|
||||
|
|
|
@ -78,7 +78,6 @@ class FrenchStreamProvider : MainAPI() {
|
|||
poster,
|
||||
date,
|
||||
description,
|
||||
null,
|
||||
ratingAverage,
|
||||
tagsList,
|
||||
null,
|
||||
|
|
|
@ -606,13 +606,15 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
result_recommendations_btt?.isGone = isInvalid
|
||||
result_recommendations_btt?.setOnClickListener {
|
||||
if (result_overlapping_panels?.getSelectedPanel()?.ordinal == 1) {
|
||||
result_recommendations_btt?.nextFocusDownId = R.id.result_recommendations
|
||||
result_overlapping_panels?.openEndPanel()
|
||||
} else {
|
||||
result_recommendations_btt?.nextFocusDownId = R.id.result_description
|
||||
result_overlapping_panels?.closePanels()
|
||||
}
|
||||
}
|
||||
result_overlapping_panels?.setEndPanelLockState(if (isInvalid) OverlappingPanelsLayout.LockState.CLOSE else OverlappingPanelsLayout.LockState.UNLOCKED)
|
||||
result_recommendations.post {
|
||||
result_recommendations?.post {
|
||||
rec?.let { list ->
|
||||
(result_recommendations?.adapter as SearchAdapter?)?.updateList(list)
|
||||
}
|
||||
|
@ -1337,6 +1339,7 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
result_sync_loading_shimmer?.stopShimmer()
|
||||
result_sync_loading_shimmer?.isVisible = false
|
||||
result_sync_holder?.isVisible = false
|
||||
closed = true
|
||||
}
|
||||
is Resource.Loading -> {
|
||||
result_sync_loading_shimmer?.startShimmer()
|
||||
|
@ -1420,6 +1423,10 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
}
|
||||
|
||||
result_series_parent?.isVisible = isSeriesVisible
|
||||
if (isSeriesVisible && activity?.currentFocus?.id == R.id.result_back && context?.isTrueTvSettings() == true) {
|
||||
result_resume_series_button?.requestFocus()
|
||||
}
|
||||
|
||||
if (isSeriesVisible) {
|
||||
val down = when {
|
||||
result_season_button?.isVisible == true -> result_season_button
|
||||
|
@ -1634,23 +1641,20 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
setRecommendations(d.recommendations)
|
||||
setActors(d.actors)
|
||||
|
||||
if (SettingsFragment.accountEnabled)
|
||||
if (d is AnimeLoadResponse) {
|
||||
// don't inline these variables as it will cause them to not be called
|
||||
val addedMal = setMalSync(d.malId)
|
||||
val addedAniList = setAniListSync(d.anilistId)
|
||||
if (
|
||||
addedMal
|
||||
||
|
||||
addedAniList
|
||||
) {
|
||||
syncModel.updateMetaAndUser()
|
||||
syncModel.updateSynced()
|
||||
} else {
|
||||
syncModel.addFromUrl(d.url)
|
||||
}
|
||||
if (SettingsFragment.accountEnabled) {
|
||||
var isValid = false
|
||||
for ((prefix, id) in d.syncData) {
|
||||
isValid = isValid || syncModel.addSync(prefix, id)
|
||||
}
|
||||
|
||||
if (isValid) {
|
||||
syncModel.updateMetaAndUser()
|
||||
syncModel.updateSynced()
|
||||
} else {
|
||||
syncModel.addFromUrl(d.url)
|
||||
}
|
||||
}
|
||||
|
||||
result_meta_site?.text = d.apiName
|
||||
|
||||
val posterImageLink = d.posterUrl
|
||||
|
@ -1658,28 +1662,30 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
result_poster?.setImage(posterImageLink)
|
||||
result_poster_blur?.setImageBlur(posterImageLink, 10, 3)
|
||||
//Full screen view of Poster image
|
||||
result_poster_holder?.setOnClickListener {
|
||||
try {
|
||||
context?.let { ctx ->
|
||||
val bitmap = result_poster.drawable.toBitmap()
|
||||
val sourceBuilder = AlertDialog.Builder(ctx)
|
||||
sourceBuilder.setView(R.layout.result_poster)
|
||||
if (context?.isTrueTvSettings() == false) // Poster not clickable on tv
|
||||
result_poster_holder?.setOnClickListener {
|
||||
try {
|
||||
context?.let { ctx ->
|
||||
val bitmap = result_poster.drawable.toBitmap()
|
||||
val sourceBuilder = AlertDialog.Builder(ctx)
|
||||
sourceBuilder.setView(R.layout.result_poster)
|
||||
|
||||
val sourceDialog = sourceBuilder.create()
|
||||
sourceDialog.show()
|
||||
val sourceDialog = sourceBuilder.create()
|
||||
sourceDialog.show()
|
||||
|
||||
sourceDialog.findViewById<ImageView?>(R.id.imgPoster)
|
||||
?.apply {
|
||||
setImageBitmap(bitmap)
|
||||
setOnClickListener {
|
||||
sourceDialog.dismissSafe()
|
||||
sourceDialog.findViewById<ImageView?>(R.id.imgPoster)
|
||||
?.apply {
|
||||
setImageBitmap(bitmap)
|
||||
setOnClickListener {
|
||||
sourceDialog.dismissSafe()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
result_poster?.setImageResource(R.drawable.default_cover)
|
||||
result_poster_blur?.setImageResource(R.drawable.default_cover)
|
||||
|
@ -1698,16 +1704,16 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
if (syno.length > MAX_SYNO_LENGH) {
|
||||
syno = syno.substring(0, MAX_SYNO_LENGH) + "..."
|
||||
}
|
||||
result_descript.setOnClickListener {
|
||||
result_description.setOnClickListener {
|
||||
val builder: AlertDialog.Builder =
|
||||
AlertDialog.Builder(requireContext())
|
||||
builder.setMessage(d.plot)
|
||||
.setTitle(if (d.type == TvType.Torrent) R.string.torrent_plot else R.string.result_plot)
|
||||
.show()
|
||||
}
|
||||
result_descript.text = syno
|
||||
result_description.text = syno
|
||||
} else {
|
||||
result_descript.text =
|
||||
result_description.text =
|
||||
if (d.type == TvType.Torrent) getString(R.string.torrent_no_plot) else getString(
|
||||
R.string.normal_no_plot
|
||||
)
|
||||
|
@ -1727,12 +1733,13 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
//result_tag_holder?.visibility = GONE
|
||||
} else {
|
||||
//result_tag_holder?.visibility = VISIBLE
|
||||
|
||||
val isOnTv = context?.isTrueTvSettings() == true
|
||||
for ((index, tag) in tags.withIndex()) {
|
||||
val viewBtt = layoutInflater.inflate(R.layout.result_tag, null)
|
||||
val btt = viewBtt.findViewById<MaterialButton>(R.id.result_tag_card)
|
||||
btt.text = tag
|
||||
|
||||
btt.isFocusable = !isOnTv
|
||||
btt.isClickable = !isOnTv
|
||||
result_tag?.addView(viewBtt, index)
|
||||
}
|
||||
}
|
||||
|
@ -1980,8 +1987,14 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
}
|
||||
}
|
||||
|
||||
result_meta_site?.setOnClickListener {
|
||||
it.context?.openBrowser(tempUrl)
|
||||
// bloats the navigation on tv
|
||||
if (context?.isTrueTvSettings() == false) {
|
||||
result_meta_site?.setOnClickListener {
|
||||
it.context?.openBrowser(tempUrl)
|
||||
}
|
||||
result_meta_site?.isFocusable = true
|
||||
} else {
|
||||
result_meta_site?.isFocusable = false
|
||||
}
|
||||
|
||||
if (restart || viewModel.result.value == null) {
|
||||
|
|
|
@ -65,18 +65,19 @@ class SyncViewModel : ViewModel() {
|
|||
_currentSynced.postValue(getMissing())
|
||||
}
|
||||
|
||||
fun setMalId(id: String?) : Boolean {
|
||||
if(syncIds[malApi.idPrefix] == id ?: return false) return false
|
||||
syncIds[malApi.idPrefix] = id
|
||||
Log.i(TAG, "setMalId = $id")
|
||||
fun addSync(idPrefix: String, id : String) : Boolean {
|
||||
if(syncIds[idPrefix] == id) return false
|
||||
Log.i(TAG, "addSync $idPrefix = $id")
|
||||
syncIds[idPrefix] = id
|
||||
return true
|
||||
}
|
||||
|
||||
fun setMalId(id: String?) : Boolean {
|
||||
return addSync(malApi.idPrefix,id ?: return false)
|
||||
}
|
||||
|
||||
fun setAniListId(id: String?) : Boolean {
|
||||
if(syncIds[aniListApi.idPrefix] == id ?: return false) return false
|
||||
syncIds[aniListApi.idPrefix] = id
|
||||
Log.i(TAG, "setAniListId = $id")
|
||||
return true
|
||||
return addSync(aniListApi.idPrefix,id ?: return false)
|
||||
}
|
||||
|
||||
var hasAddedFromUrl: HashSet<String> = hashSetOf()
|
||||
|
@ -164,13 +165,15 @@ class SyncViewModel : ViewModel() {
|
|||
_userDataResponse.postValue(Resource.Loading())
|
||||
var lastError: Resource<SyncAPI.SyncStatus> = Resource.Failure(false, null, null, "No data")
|
||||
for ((prefix, id) in syncIds) {
|
||||
repos.firstOrNull { it.idPrefix == prefix }?.let {
|
||||
val result = it.getStatus(id)
|
||||
if (result is Resource.Success) {
|
||||
_userDataResponse.postValue(result)
|
||||
return@launch
|
||||
} else if (result is Resource.Failure) {
|
||||
lastError = result
|
||||
repos.firstOrNull { it.idPrefix == prefix }?.let { repo ->
|
||||
if(repo.hasAccount()) {
|
||||
val result = repo.getStatus(id)
|
||||
if (result is Resource.Success) {
|
||||
_userDataResponse.postValue(result)
|
||||
return@launch
|
||||
} else if (result is Resource.Failure) {
|
||||
lastError = result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -183,13 +186,15 @@ class SyncViewModel : ViewModel() {
|
|||
_metaResponse.postValue(Resource.Loading())
|
||||
var lastError: Resource<SyncAPI.SyncResult> = Resource.Failure(false, null, null, "No data")
|
||||
for ((prefix, id) in syncIds) {
|
||||
repos.firstOrNull { it.idPrefix == prefix }?.let {
|
||||
val result = it.getResult(id)
|
||||
if (result is Resource.Success) {
|
||||
_metaResponse.postValue(result)
|
||||
return@launch
|
||||
} else if (result is Resource.Failure) {
|
||||
lastError = result
|
||||
repos.firstOrNull { it.idPrefix == prefix }?.let { repo ->
|
||||
if(repo.hasAccount()) {
|
||||
val result = repo.getResult(id)
|
||||
if (result is Resource.Success) {
|
||||
_metaResponse.postValue(result)
|
||||
return@launch
|
||||
} else if (result is Resource.Failure) {
|
||||
lastError = result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -352,7 +352,7 @@
|
|||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/result_descript"
|
||||
android:id="@+id/result_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foreground="@drawable/outline_drawable"
|
||||
|
@ -390,7 +390,7 @@
|
|||
android:minWidth="100dp"
|
||||
android:nextFocusLeft="@id/result_back"
|
||||
android:nextFocusRight="@id/result_search"
|
||||
android:nextFocusUp="@id/result_descript"
|
||||
android:nextFocusUp="@id/result_description"
|
||||
|
||||
android:nextFocusDown="@id/result_play_movie"
|
||||
android:paddingTop="0dp"
|
||||
|
@ -751,7 +751,7 @@
|
|||
android:layout_marginStart="0dp"
|
||||
android:nextFocusLeft="@id/result_episode_select"
|
||||
android:nextFocusRight="@id/result_episode_select"
|
||||
android:nextFocusUp="@id/result_descript"
|
||||
android:nextFocusUp="@id/result_description"
|
||||
android:nextFocusDown="@id/result_episodes"
|
||||
android:visibility="gone"
|
||||
tools:text="Season 1"
|
||||
|
@ -766,7 +766,7 @@
|
|||
android:nextFocusLeft="@id/result_season_button"
|
||||
android:nextFocusRight="@id/result_season_button"
|
||||
|
||||
android:nextFocusUp="@id/result_descript"
|
||||
android:nextFocusUp="@id/result_description"
|
||||
android:nextFocusDown="@id/result_episodes"
|
||||
android:visibility="gone"
|
||||
tools:text="50-100"
|
||||
|
@ -781,7 +781,7 @@
|
|||
android:nextFocusLeft="@id/result_season_button"
|
||||
android:nextFocusRight="@id/result_season_button"
|
||||
|
||||
android:nextFocusUp="@id/result_descript"
|
||||
android:nextFocusUp="@id/result_description"
|
||||
android:nextFocusDown="@id/result_episodes"
|
||||
android:visibility="gone"
|
||||
tools:text="Dubbed"
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
|
||||
<ImageView
|
||||
android:nextFocusUp="@id/result_back"
|
||||
android:nextFocusDown="@id/result_descript"
|
||||
android:nextFocusDown="@id/result_description"
|
||||
android:nextFocusLeft="@id/result_add_sync"
|
||||
android:nextFocusRight="@id/result_open_in_browser"
|
||||
|
||||
|
@ -88,7 +88,7 @@
|
|||
|
||||
<ImageView
|
||||
android:nextFocusUp="@id/result_back"
|
||||
android:nextFocusDown="@id/result_descript"
|
||||
android:nextFocusDown="@id/result_description"
|
||||
android:nextFocusLeft="@id/result_share"
|
||||
android:nextFocusRight="@id/result_search"
|
||||
|
||||
|
@ -106,7 +106,7 @@
|
|||
|
||||
<ImageView
|
||||
android:nextFocusUp="@id/result_back"
|
||||
android:nextFocusDown="@id/result_descript"
|
||||
android:nextFocusDown="@id/result_description"
|
||||
android:nextFocusLeft="@id/result_open_in_browser"
|
||||
android:nextFocusRight="@id/result_recommendations_btt"
|
||||
|
||||
|
@ -122,9 +122,10 @@
|
|||
android:contentDescription="@string/result_open_in_browser"
|
||||
app:tint="?attr/textColor" />
|
||||
<ImageView
|
||||
tools:visibility="visible"
|
||||
android:visibility="gone"
|
||||
android:nextFocusUp="@id/result_back"
|
||||
android:nextFocusDown="@id/result_descript"
|
||||
android:nextFocusDown="@id/result_description"
|
||||
android:nextFocusLeft="@id/result_search"
|
||||
android:nextFocusRight="@id/result_bookmark_button"
|
||||
|
||||
|
|
|
@ -35,14 +35,14 @@
|
|||
<item>None</item>
|
||||
<item>Google</item>
|
||||
<item>Cloudflare</item>
|
||||
<!-- <item>OpenDns</item>-->
|
||||
<!-- <item>OpenDns</item>-->
|
||||
<item>AdGuard</item>
|
||||
</array>
|
||||
<array name="dns_pref_values">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>2</item>
|
||||
<!-- <item>3</item>-->
|
||||
<!-- <item>3</item>-->
|
||||
<item>4</item>
|
||||
</array>
|
||||
|
||||
|
@ -196,7 +196,7 @@
|
|||
<item>Normal</item>
|
||||
<item>Blue</item>
|
||||
<item>Red</item>
|
||||
<item>Purple</item>
|
||||
<item>Purple</item>
|
||||
<item>Green</item>
|
||||
<item>GreenApple</item>
|
||||
<item>Banana</item>
|
||||
|
|
|
@ -401,6 +401,8 @@
|
|||
<string name="sync_total_episodes_none">/??</string>
|
||||
<string name="sync_total_episodes_some" formatted="true">/%d</string>
|
||||
<string name="authenticated_user" formatted="true">Authenticated %s</string>
|
||||
<string name="authenticated_user_fail" formatted="true">Failed to authenticate to %s</string>
|
||||
|
||||
<!-- ============ -->
|
||||
<string name="none">None</string>
|
||||
<string name="normal">Normal</string>
|
||||
|
|
Loading…
Reference in a new issue