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