forked from recloudstream/cloudstream
mainApi changes
This commit is contained in:
parent
117730e9a8
commit
94561e0d5b
19 changed files with 358 additions and 325 deletions
|
@ -111,6 +111,12 @@ object APIHolder {
|
|||
}
|
||||
|
||||
var apis: List<MainAPI> = arrayListOf()
|
||||
private var apiMap: Map<String, Int>? = null
|
||||
|
||||
private fun initMap() {
|
||||
if (apiMap == null)
|
||||
apiMap = apis.mapIndexed { index, api -> api.name to index }.toMap()
|
||||
}
|
||||
|
||||
fun getApiFromName(apiName: String?): MainAPI {
|
||||
return getApiFromNameNull(apiName) ?: apis[defProvider]
|
||||
|
@ -118,11 +124,9 @@ object APIHolder {
|
|||
|
||||
fun getApiFromNameNull(apiName: String?): MainAPI? {
|
||||
if (apiName == null) return null
|
||||
for (api in allProviders) {
|
||||
if (apiName == api.name)
|
||||
return api
|
||||
}
|
||||
return null
|
||||
initMap()
|
||||
|
||||
return apiMap?.get(apiName)?.let { apis.getOrNull(it) }
|
||||
}
|
||||
|
||||
fun getApiFromUrlNull(url: String?): MainAPI? {
|
||||
|
@ -622,10 +626,65 @@ interface SearchResponse {
|
|||
val apiName: String
|
||||
var type: TvType?
|
||||
var posterUrl: String?
|
||||
var posterHeaders: Map<String, String>?
|
||||
var id: Int?
|
||||
var quality: SearchQuality?
|
||||
}
|
||||
|
||||
fun MainAPI.newMovieSearchResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
type: TvType = TvType.Movie,
|
||||
fix: Boolean = true,
|
||||
initializer: MovieSearchResponse.() -> Unit = { },
|
||||
): MovieSearchResponse {
|
||||
val builder = MovieSearchResponse(name, if (fix) fixUrl(url) else url, this.name, type)
|
||||
builder.initializer()
|
||||
|
||||
return builder
|
||||
}
|
||||
|
||||
fun MainAPI.newTvSeriesSearchResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
type: TvType = TvType.TvSeries,
|
||||
fix: Boolean = true,
|
||||
initializer: TvSeriesSearchResponse.() -> Unit = { },
|
||||
): TvSeriesSearchResponse {
|
||||
val builder = TvSeriesSearchResponse(name, if (fix) fixUrl(url) else url, this.name, type)
|
||||
builder.initializer()
|
||||
|
||||
return builder
|
||||
}
|
||||
|
||||
|
||||
fun MainAPI.newAnimeSearchResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
type: TvType = TvType.Anime,
|
||||
fix: Boolean = true,
|
||||
initializer: AnimeSearchResponse.() -> Unit = { },
|
||||
): AnimeSearchResponse {
|
||||
val builder = AnimeSearchResponse(name, if (fix) fixUrl(url) else url, this.name, type)
|
||||
builder.initializer()
|
||||
|
||||
return builder
|
||||
}
|
||||
|
||||
fun SearchResponse.addQuality(quality: String) {
|
||||
this.quality = getQualityFromString(quality)
|
||||
}
|
||||
|
||||
fun SearchResponse.addPoster(url: String?, headers: Map<String, String>? = null) {
|
||||
this.posterUrl = url
|
||||
this.posterHeaders = headers
|
||||
}
|
||||
|
||||
fun LoadResponse.addPoster(url: String?, headers: Map<String, String>? = null) {
|
||||
this.posterUrl = url
|
||||
this.posterHeaders = headers
|
||||
}
|
||||
|
||||
enum class ActorRole {
|
||||
Main,
|
||||
Supporting,
|
||||
|
@ -648,19 +707,62 @@ data class AnimeSearchResponse(
|
|||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
override var type: TvType?,
|
||||
override var type: TvType? = null,
|
||||
|
||||
override var posterUrl: String?,
|
||||
val year: Int? = null,
|
||||
val dubStatus: EnumSet<DubStatus>? = null,
|
||||
override var posterUrl: String? = null,
|
||||
var year: Int? = null,
|
||||
var dubStatus: EnumSet<DubStatus>? = null,
|
||||
|
||||
var otherName: String? = null,
|
||||
var episodes: MutableMap<DubStatus, Int> = mutableMapOf(),
|
||||
|
||||
val otherName: String? = null,
|
||||
val dubEpisodes: Int? = null,
|
||||
val subEpisodes: Int? = null,
|
||||
override var id: Int? = null,
|
||||
override var quality: SearchQuality? = null,
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
fun AnimeSearchResponse.addDubStatus(status: DubStatus, episodes: Int? = null) {
|
||||
this.dubStatus = dubStatus?.also { it.add(status) } ?: EnumSet.of(status)
|
||||
if (this.type?.isMovieType() != true)
|
||||
if (episodes != null && episodes > 0)
|
||||
this.episodes[status] = episodes
|
||||
}
|
||||
|
||||
fun AnimeSearchResponse.addDubStatus(isDub: Boolean, episodes: Int? = null) {
|
||||
addDubStatus(if (isDub) DubStatus.Dubbed else DubStatus.Subbed, episodes)
|
||||
}
|
||||
|
||||
fun AnimeSearchResponse.addDub(episodes: Int?) {
|
||||
if(episodes == null || episodes <= 0) return
|
||||
addDubStatus(DubStatus.Dubbed, episodes)
|
||||
}
|
||||
|
||||
fun AnimeSearchResponse.addSub(episodes: Int?) {
|
||||
if(episodes == null || episodes <= 0) return
|
||||
addDubStatus(DubStatus.Subbed, episodes)
|
||||
}
|
||||
|
||||
fun AnimeSearchResponse.addDubStatus(
|
||||
dubExist: Boolean,
|
||||
subExist: Boolean,
|
||||
dubEpisodes: Int? = null,
|
||||
subEpisodes: Int? = null
|
||||
) {
|
||||
if (dubExist)
|
||||
addDubStatus(DubStatus.Dubbed, dubEpisodes)
|
||||
|
||||
if (subExist)
|
||||
addDubStatus(DubStatus.Subbed, subEpisodes)
|
||||
}
|
||||
|
||||
fun AnimeSearchResponse.addDubStatus(status: String, episodes: Int? = null) {
|
||||
if (status.contains("(dub)", ignoreCase = true)) {
|
||||
addDubStatus(DubStatus.Dubbed)
|
||||
} else if (status.contains("(sub)", ignoreCase = true)) {
|
||||
addDubStatus(DubStatus.Subbed)
|
||||
}
|
||||
}
|
||||
|
||||
data class TorrentSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
|
@ -670,31 +772,34 @@ data class TorrentSearchResponse(
|
|||
override var posterUrl: String?,
|
||||
override var id: Int? = null,
|
||||
override var quality: SearchQuality? = null,
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
data class MovieSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
override var type: TvType?,
|
||||
override var type: TvType? = null,
|
||||
|
||||
override var posterUrl: String?,
|
||||
override var posterUrl: String? = null,
|
||||
val year: Int? = null,
|
||||
override var id: Int? = null,
|
||||
override var quality: SearchQuality? = null,
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
data class TvSeriesSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
override val apiName: String,
|
||||
override var type: TvType?,
|
||||
override var type: TvType? = null,
|
||||
|
||||
override var posterUrl: String?,
|
||||
val year: Int?,
|
||||
val episodes: Int?,
|
||||
override var posterUrl: String? = null,
|
||||
val year: Int? = null,
|
||||
val episodes: Int? = null,
|
||||
override var id: Int? = null,
|
||||
override var quality: SearchQuality? = null,
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
interface LoadResponse {
|
||||
|
@ -713,6 +818,7 @@ interface LoadResponse {
|
|||
var actors: List<ActorData>?
|
||||
var comingSoon: Boolean
|
||||
var syncData: MutableMap<String, String>
|
||||
var posterHeaders: Map<String, String>?
|
||||
|
||||
companion object {
|
||||
private val malIdPrefix = malApi.idPrefix
|
||||
|
@ -844,6 +950,7 @@ data class TorrentLoadResponse(
|
|||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
override var syncData: MutableMap<String, String> = mutableMapOf(),
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : LoadResponse
|
||||
|
||||
data class AnimeLoadResponse(
|
||||
|
@ -871,6 +978,7 @@ data class AnimeLoadResponse(
|
|||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
override var syncData: MutableMap<String, String> = mutableMapOf(),
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : LoadResponse
|
||||
|
||||
fun AnimeLoadResponse.addEpisodes(status: DubStatus, episodes: List<Episode>?) {
|
||||
|
@ -882,7 +990,7 @@ fun MainAPI.newAnimeLoadResponse(
|
|||
name: String,
|
||||
url: String,
|
||||
type: TvType,
|
||||
comingSoonIfNone: Boolean,
|
||||
comingSoonIfNone: Boolean = true,
|
||||
initializer: AnimeLoadResponse.() -> Unit = { },
|
||||
): AnimeLoadResponse {
|
||||
val builder = AnimeLoadResponse(name = name, url = url, apiName = this.name, type = type)
|
||||
|
@ -898,15 +1006,6 @@ fun MainAPI.newAnimeLoadResponse(
|
|||
return builder
|
||||
}
|
||||
|
||||
fun MainAPI.newAnimeLoadResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
type: TvType,
|
||||
initializer: AnimeLoadResponse.() -> Unit = { },
|
||||
): AnimeLoadResponse {
|
||||
return newAnimeLoadResponse(name, url, type, true, initializer)
|
||||
}
|
||||
|
||||
data class MovieLoadResponse(
|
||||
override var name: String,
|
||||
override var url: String,
|
||||
|
@ -926,6 +1025,7 @@ data class MovieLoadResponse(
|
|||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
override var syncData: MutableMap<String, String> = mutableMapOf(),
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : LoadResponse
|
||||
|
||||
fun <T> MainAPI.newMovieLoadResponse(
|
||||
|
@ -1046,6 +1146,7 @@ data class TvSeriesLoadResponse(
|
|||
override var actors: List<ActorData>? = null,
|
||||
override var comingSoon: Boolean = false,
|
||||
override var syncData: MutableMap<String, String> = mutableMapOf(),
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : LoadResponse
|
||||
|
||||
fun MainAPI.newTvSeriesLoadResponse(
|
||||
|
|
|
@ -14,7 +14,6 @@ import org.mozilla.javascript.Context
|
|||
import org.mozilla.javascript.Scriptable
|
||||
import java.net.URI
|
||||
import java.net.URLDecoder
|
||||
import java.util.*
|
||||
|
||||
|
||||
class AllAnimeProvider : MainAPI() {
|
||||
|
@ -88,49 +87,48 @@ class AllAnimeProvider : MainAPI() {
|
|||
@JsonProperty("data") val data: Data
|
||||
)
|
||||
|
||||
data class RandomMain (
|
||||
@JsonProperty("data" ) var data : DataRan? = DataRan()
|
||||
data class RandomMain(
|
||||
@JsonProperty("data") var data: DataRan? = DataRan()
|
||||
)
|
||||
|
||||
data class DataRan (
|
||||
@JsonProperty("queryRandomRecommendation" ) var queryRandomRecommendation : ArrayList<QueryRandomRecommendation> = arrayListOf()
|
||||
data class DataRan(
|
||||
@JsonProperty("queryRandomRecommendation") var queryRandomRecommendation: ArrayList<QueryRandomRecommendation> = arrayListOf()
|
||||
)
|
||||
|
||||
data class QueryRandomRecommendation (
|
||||
@JsonProperty("_id" ) val Id : String? = null,
|
||||
@JsonProperty("name" ) val name : String? = null,
|
||||
@JsonProperty("englishName" ) val englishName : String? = null,
|
||||
@JsonProperty("nativeName" ) val nativeName : String? = null,
|
||||
@JsonProperty("thumbnail" ) val thumbnail : String? = null,
|
||||
@JsonProperty("airedStart" ) val airedStart : String? = null,
|
||||
@JsonProperty("availableChapters" ) val availableChapters : String? = null,
|
||||
@JsonProperty("availableEpisodes" ) val availableEpisodes : String? = null,
|
||||
@JsonProperty("__typename" ) val _typename : String? = null
|
||||
data class QueryRandomRecommendation(
|
||||
@JsonProperty("_id") val Id: String? = null,
|
||||
@JsonProperty("name") val name: String? = null,
|
||||
@JsonProperty("englishName") val englishName: String? = null,
|
||||
@JsonProperty("nativeName") val nativeName: String? = null,
|
||||
@JsonProperty("thumbnail") val thumbnail: String? = null,
|
||||
@JsonProperty("airedStart") val airedStart: String? = null,
|
||||
@JsonProperty("availableChapters") val availableChapters: String? = null,
|
||||
@JsonProperty("availableEpisodes") val availableEpisodes: String? = null,
|
||||
@JsonProperty("__typename") val _typename: String? = null
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val items = ArrayList<HomePageList>()
|
||||
val urls = listOf(
|
||||
Pair("Top Anime",
|
||||
"$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%2C%22sortBy%22%3A%22Top%22%7D%2C%22limit%22%3A26%2C%22page%22%3A1%2C%22translationType%22%3A%22sub%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%229343797cc3d9e3f444e2d3b7db9a84d759b816a4d84512ea72d079f85bb96e98%22%7D%7D"),
|
||||
Pair("Animes",
|
||||
"$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%7D%2C%22limit%22%3A26%2C%22page%22%3A1%2C%22translationType%22%3A%22sub%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%229343797cc3d9e3f444e2d3b7db9a84d759b816a4d84512ea72d079f85bb96e98%22%7D%7D"),
|
||||
Pair(
|
||||
"Top Anime",
|
||||
"$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%2C%22sortBy%22%3A%22Top%22%7D%2C%22limit%22%3A26%2C%22page%22%3A1%2C%22translationType%22%3A%22sub%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%229343797cc3d9e3f444e2d3b7db9a84d759b816a4d84512ea72d079f85bb96e98%22%7D%7D"
|
||||
),
|
||||
Pair(
|
||||
"Animes",
|
||||
"$mainUrl/graphql?variables=%7B%22search%22%3A%7B%22allowAdult%22%3Afalse%7D%2C%22limit%22%3A26%2C%22page%22%3A1%2C%22translationType%22%3A%22sub%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%229343797cc3d9e3f444e2d3b7db9a84d759b816a4d84512ea72d079f85bb96e98%22%7D%7D"
|
||||
),
|
||||
)
|
||||
|
||||
val random = "$mainUrl/graphql?variables=%7B%22format%22%3A%22anime%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%2221ac672633498a3698e8f6a93ce6c2b3722b29a216dcca93363bf012c360cd54%22%7D%7D"
|
||||
val random =
|
||||
"$mainUrl/graphql?variables=%7B%22format%22%3A%22anime%22%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%2221ac672633498a3698e8f6a93ce6c2b3722b29a216dcca93363bf012c360cd54%22%7D%7D"
|
||||
val ranlink = app.get(random).text
|
||||
val jsonran = parseJson<RandomMain>(ranlink)
|
||||
val ranhome = jsonran.data?.queryRandomRecommendation?.map {
|
||||
AnimeSearchResponse(
|
||||
it.name!!,
|
||||
"$mainUrl/anime/${it.Id}",
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
it.thumbnail,
|
||||
null,
|
||||
EnumSet.of(DubStatus.Subbed, DubStatus.Dubbed),
|
||||
it.nativeName,
|
||||
)
|
||||
newAnimeSearchResponse(it.name!!,"$mainUrl/anime/${it.Id}", fix = false) {
|
||||
this.posterUrl = it.thumbnail
|
||||
this.otherName = it.nativeName
|
||||
}
|
||||
}
|
||||
|
||||
items.add(HomePageList("Random", ranhome!!))
|
||||
|
@ -144,18 +142,14 @@ class AllAnimeProvider : MainAPI() {
|
|||
!(it.availableEpisodes?.raw == 0 && it.availableEpisodes.sub == 0 && it.availableEpisodes.dub == 0)
|
||||
}
|
||||
results.map {
|
||||
home.add(AnimeSearchResponse(
|
||||
it.name,
|
||||
"$mainUrl/anime/${it.Id}",
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
it.thumbnail,
|
||||
it.airedStart?.year,
|
||||
EnumSet.of(DubStatus.Subbed, DubStatus.Dubbed),
|
||||
it.englishName,
|
||||
it.availableEpisodes?.dub,
|
||||
it.availableEpisodes?.sub
|
||||
))
|
||||
home.add(
|
||||
newAnimeSearchResponse(it.name, "$mainUrl/anime/${it.Id}", fix = false) {
|
||||
this.posterUrl = it.thumbnail
|
||||
this.year = it.airedStart?.year
|
||||
this.otherName = it.englishName
|
||||
addDub(it.availableEpisodes?.dub)
|
||||
addSub(it.availableEpisodes?.sub)
|
||||
})
|
||||
}
|
||||
items.add(HomePageList(HomeName, home))
|
||||
}
|
||||
|
@ -180,18 +174,13 @@ class AllAnimeProvider : MainAPI() {
|
|||
}
|
||||
|
||||
return results.map {
|
||||
AnimeSearchResponse(
|
||||
it.name,
|
||||
"$mainUrl/anime/${it.Id}",
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
it.thumbnail,
|
||||
it.airedStart?.year,
|
||||
EnumSet.of(DubStatus.Subbed, DubStatus.Dubbed),
|
||||
it.englishName,
|
||||
it.availableEpisodes?.dub,
|
||||
it.availableEpisodes?.sub
|
||||
)
|
||||
newAnimeSearchResponse(it.name, "$mainUrl/anime/${it.Id}", fix = false) {
|
||||
this.posterUrl = it.thumbnail
|
||||
this.year = it.airedStart?.year
|
||||
this.otherName = it.englishName
|
||||
addDub(it.availableEpisodes?.dub)
|
||||
addSub(it.availableEpisodes?.sub)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.JsUnpacker
|
||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
import org.jsoup.Jsoup
|
||||
import java.util.*
|
||||
import kotlin.math.pow
|
||||
|
||||
class AnimePaheProvider : MainAPI() {
|
||||
|
@ -84,19 +83,14 @@ class AnimePaheProvider : MainAPI() {
|
|||
try {
|
||||
val response = app.get(i.first).text
|
||||
val episodes = mapper.readValue<AnimePaheLatestReleases>(response).data.map {
|
||||
|
||||
AnimeSearchResponse(
|
||||
newAnimeSearchResponse(
|
||||
it.animeTitle,
|
||||
"https://pahe.win/a/${it.animeId}?slug=${it.animeTitle}",
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
it.snapshot,
|
||||
null,
|
||||
EnumSet.of(DubStatus.Subbed),
|
||||
null,
|
||||
null,
|
||||
it.episode
|
||||
)
|
||||
fix = false
|
||||
) {
|
||||
this.posterUrl = it.snapshot
|
||||
addDubStatus(DubStatus.Subbed, it.episode)
|
||||
}
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, episodes))
|
||||
|
@ -151,18 +145,14 @@ class AnimePaheProvider : MainAPI() {
|
|||
val data = req.let { mapper.readValue<AnimePaheSearch>(it) }
|
||||
|
||||
return data.data.map {
|
||||
AnimeSearchResponse(
|
||||
newAnimeSearchResponse(
|
||||
it.title,
|
||||
"https://pahe.win/a/${it.id}?slug=${it.title}",
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
it.poster,
|
||||
it.year,
|
||||
EnumSet.of(DubStatus.Subbed),
|
||||
null,
|
||||
null,
|
||||
it.episodes
|
||||
)
|
||||
fix = false
|
||||
) {
|
||||
this.posterUrl = it.poster
|
||||
addDubStatus(DubStatus.Subbed, it.episodes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -189,7 +179,6 @@ class AnimePaheProvider : MainAPI() {
|
|||
@JsonProperty("data") val data: List<AnimeData>
|
||||
)
|
||||
|
||||
|
||||
private suspend fun generateListOfEpisodes(link: String): ArrayList<Episode> {
|
||||
try {
|
||||
val attrs = link.split('/')
|
||||
|
|
|
@ -9,7 +9,6 @@ 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"
|
||||
|
@ -31,6 +30,7 @@ class AnimeWorldProvider : MainAPI() {
|
|||
else -> TvType.Anime
|
||||
}
|
||||
}
|
||||
|
||||
fun getStatus(t: String?): ShowStatus? {
|
||||
return when (t?.lowercase()) {
|
||||
"finito" -> ShowStatus.Completed
|
||||
|
@ -54,25 +54,20 @@ class AnimeWorldProvider : MainAPI() {
|
|||
|
||||
val statusElement = this.select("div.status") // .first()
|
||||
val dub = statusElement.select(".dub").isNotEmpty()
|
||||
val dubStatus = if (dub) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed)
|
||||
val episode = statusElement.select(".ep").text().split(' ').last().toIntOrNull()
|
||||
|
||||
val episode = if (showEpisode) statusElement.select(".ep").text().split(' ').last()
|
||||
.toIntOrNull() else null
|
||||
val type = when {
|
||||
statusElement.select(".movie").isNotEmpty() -> TvType.AnimeMovie
|
||||
statusElement.select(".ova").isNotEmpty() -> TvType.OVA
|
||||
else -> TvType.Anime
|
||||
}
|
||||
|
||||
return AnimeSearchResponse(
|
||||
title,
|
||||
url,
|
||||
name,
|
||||
type,
|
||||
poster,
|
||||
dubStatus = dubStatus,
|
||||
otherName = if (otherTitle != title) otherTitle else null,
|
||||
dubEpisodes = if (showEpisode && type != TvType.AnimeMovie && dub) episode else null,
|
||||
subEpisodes = if (showEpisode && type != TvType.AnimeMovie && !dub) episode else null
|
||||
)
|
||||
return newAnimeSearchResponse(title, url, type) {
|
||||
addDubStatus(dub, episode)
|
||||
this.otherName = otherTitle
|
||||
this.posterUrl = poster
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
|
@ -113,14 +108,17 @@ class AnimeWorldProvider : MainAPI() {
|
|||
arr[0].split(' ')[0].toIntOrNull()
|
||||
else
|
||||
arr[1].split(' ')[0].toIntOrNull()?.let {
|
||||
arr[0].removeSuffix("h").toIntOrNull()?.times(60)!!.plus(it) }
|
||||
arr[0].removeSuffix("h").toIntOrNull()?.times(60)!!.plus(it)
|
||||
}
|
||||
}
|
||||
|
||||
val document = app.get(url).document
|
||||
|
||||
val widget = document.select("div.widget.info")
|
||||
val title = widget.select(".info .title").text().removeSuffix(" (ITA)")
|
||||
val otherTitle = widget.select(".info .title").attr("data-jtitle").removeSuffix(" (ITA)")
|
||||
val description = widget.select(".desc .long").first()?.text() ?: widget.select(".desc").text()
|
||||
val description =
|
||||
widget.select(".desc .long").first()?.text() ?: widget.select(".desc").text()
|
||||
val poster = document.select(".thumb img").attr("src")
|
||||
|
||||
val type: TvType = getType(widget.select("dd").first()?.text())
|
||||
|
|
|
@ -2,8 +2,9 @@ package com.lagradost.cloudstream3.animeproviders
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import java.util.*
|
||||
|
||||
class AnimeflvnetProvider:MainAPI() {
|
||||
|
@ -13,6 +14,11 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
else if (t.contains("Película")) TvType.AnimeMovie
|
||||
else TvType.Anime
|
||||
}
|
||||
fun getDubStatus(title: String): DubStatus {
|
||||
return if (title.contains("Latino") || title.contains("Castellano"))
|
||||
DubStatus.Dubbed
|
||||
else DubStatus.Subbed
|
||||
}
|
||||
}
|
||||
override var mainUrl = "https://www3.animeflv.net"
|
||||
override var name = "Animeflv.net"
|
||||
|
@ -43,19 +49,10 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
val url = it.selectFirst("a").attr("href").replace(epRegex,"")
|
||||
.replace("ver/","anime/")
|
||||
val epNum = it.selectFirst("span.Capi").text().replace("Episodio ","").toIntOrNull()
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
fixUrl(url),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
fixUrl(poster),
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
||||
DubStatus.Dubbed
|
||||
) else EnumSet.of(DubStatus.Subbed),
|
||||
subEpisodes = epNum,
|
||||
dubEpisodes = epNum,
|
||||
)
|
||||
newAnimeSearchResponse(title, url) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title), epNum)
|
||||
}
|
||||
})
|
||||
)
|
||||
for ((url, name) in urls) {
|
||||
|
@ -64,15 +61,10 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
val home = doc.select("ul.ListAnimes li article").map {
|
||||
val title = it.selectFirst("h3.Title").text()
|
||||
val poster = it.selectFirst("figure img").attr("src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
fixUrl(it.selectFirst("a").attr("href")),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
fixUrl(poster),
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(MonoschinosProvider.getDubStatus(title))
|
||||
}
|
||||
}
|
||||
|
||||
items.add(HomePageList(name, home))
|
||||
|
|
|
@ -201,20 +201,10 @@ class GogoanimeProvider : MainAPI() {
|
|||
items.add(HomePageList(i.second, (parseRegex.findAll(html.text).map {
|
||||
val (link, epNum, title, poster) = it.destructured
|
||||
val isSub = listOf(1, 3).contains(i.first.toInt())
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
poster,
|
||||
null,
|
||||
if (isSub) EnumSet.of(DubStatus.Subbed) else EnumSet.of(
|
||||
DubStatus.Dubbed
|
||||
),
|
||||
null,
|
||||
if (!isSub) epNum.toIntOrNull() else null,
|
||||
if (isSub) epNum.toIntOrNull() else null,
|
||||
)
|
||||
newAnimeSearchResponse(title, link) {
|
||||
this.posterUrl = poster
|
||||
addDubStatus(!isSub, epNum.toIntOrNull())
|
||||
}
|
||||
}).toList()))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
|
|
|
@ -14,6 +14,12 @@ class MonoschinosProvider : MainAPI() {
|
|||
else if (t.contains("Pelicula")) TvType.AnimeMovie
|
||||
else TvType.Anime
|
||||
}
|
||||
|
||||
fun getDubStatus(title: String): DubStatus {
|
||||
return if (title.contains("Latino") || title.contains("Castellano"))
|
||||
DubStatus.Dubbed
|
||||
else DubStatus.Subbed
|
||||
}
|
||||
}
|
||||
|
||||
override var mainUrl = "https://monoschinos2.com"
|
||||
|
@ -50,19 +56,10 @@ class MonoschinosProvider : MainAPI() {
|
|||
val url = it.selectFirst("a").attr("href").replace("ver/", "anime/")
|
||||
.replace(epRegex, "sub-espanol")
|
||||
val epNum = it.selectFirst(".positioning h5").text().toIntOrNull()
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
url,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
poster,
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
||||
DubStatus.Dubbed
|
||||
) else EnumSet.of(DubStatus.Subbed),
|
||||
subEpisodes = epNum,
|
||||
dubEpisodes = epNum,
|
||||
)
|
||||
newAnimeSearchResponse(title, url) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title), epNum)
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
|
@ -71,17 +68,10 @@ class MonoschinosProvider : MainAPI() {
|
|||
val home = app.get(i.first, timeout = 120).document.select(".col-6").map {
|
||||
val title = it.selectFirst(".seristitles").text()
|
||||
val poster = it.selectFirst("img.animemainimg").attr("src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
fixUrl(it.selectFirst("a").attr("href")),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
fixUrl(poster),
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
||||
DubStatus.Dubbed
|
||||
) else EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title))
|
||||
}
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, home))
|
||||
|
|
|
@ -17,12 +17,25 @@ class NineAnimeProvider : MainAPI() {
|
|||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(TvType.Anime)
|
||||
|
||||
companion object {
|
||||
fun getDubStatus(title: String): DubStatus {
|
||||
return if (title.contains("(dub)", ignoreCase = true)) {
|
||||
DubStatus.Dubbed
|
||||
} else {
|
||||
DubStatus.Subbed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val items = listOf(
|
||||
Pair("$mainUrl/ajax/home/widget?name=trending", "Trending"),
|
||||
Pair("$mainUrl/ajax/home/widget?name=updated_all", "All"),
|
||||
Pair("$mainUrl/ajax/home/widget?name=updated_sub&page=1", "Recently Updated (SUB)"),
|
||||
Pair("$mainUrl/ajax/home/widget?name=updated_dub&page=1", "Recently Updated (DUB)"),
|
||||
Pair(
|
||||
"$mainUrl/ajax/home/widget?name=updated_dub&page=1",
|
||||
"Recently Updated (DUB)(DUB)"
|
||||
),
|
||||
Pair(
|
||||
"$mainUrl/ajax/home/widget?name=updated_chinese&page=1",
|
||||
"Recently Updated (Chinese)"
|
||||
|
@ -37,17 +50,11 @@ class NineAnimeProvider : MainAPI() {
|
|||
val title = it.selectFirst("a.name").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val poster = it.selectFirst("a.poster img").attr("src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
poster,
|
||||
null,
|
||||
if (title.contains("(DUB)") || title.contains("(Dub)")) EnumSet.of(
|
||||
DubStatus.Dubbed
|
||||
) else EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
|
||||
newAnimeSearchResponse(title, link) {
|
||||
this.posterUrl = poster
|
||||
addDubStatus(getDubStatus(title))
|
||||
}
|
||||
}
|
||||
|
||||
HomePageList(name, home)
|
||||
|
@ -206,24 +213,18 @@ class NineAnimeProvider : MainAPI() {
|
|||
Episode(link, name)
|
||||
} ?: return null
|
||||
|
||||
|
||||
val recommendations =
|
||||
doc.select("div.container aside.main section div.body ul.anime-list li")?.mapNotNull { element ->
|
||||
val recTitle = element.select("a.name").text() ?: return@mapNotNull null
|
||||
val image = element.select("a.poster img")?.attr("src")
|
||||
val recUrl = fixUrl(element.select("a").attr("href"))
|
||||
AnimeSearchResponse(
|
||||
recTitle,
|
||||
fixUrl(recUrl),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
image,
|
||||
dubStatus =
|
||||
if (recTitle.contains("(DUB)") || recTitle.contains("(Dub)")) EnumSet.of(
|
||||
DubStatus.Dubbed
|
||||
) else EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
}
|
||||
doc.select("div.container aside.main section div.body ul.anime-list li")
|
||||
?.mapNotNull { element ->
|
||||
val recTitle = element.select("a.name")?.text() ?: return@mapNotNull null
|
||||
val image = element.select("a.poster img")?.attr("src")
|
||||
val recUrl = fixUrl(element.select("a").attr("href"))
|
||||
newAnimeSearchResponse(recTitle, recUrl) {
|
||||
this.posterUrl = image
|
||||
addDubStatus(getDubStatus(recTitle))
|
||||
}
|
||||
}
|
||||
|
||||
val infodoc = doc.selectFirst("div.info .meta .col1").text()
|
||||
val tvType = if (infodoc.contains("Movie")) TvType.AnimeMovie else TvType.Anime
|
||||
val status =
|
||||
|
@ -231,13 +232,14 @@ class NineAnimeProvider : MainAPI() {
|
|||
else if (infodoc.contains("Airing")) ShowStatus.Ongoing
|
||||
else null
|
||||
val tags = doc.select("div.info .meta .col1 div:contains(Genre) a").map { it.text() }
|
||||
|
||||
return newAnimeLoadResponse(title, url, tvType) {
|
||||
posterUrl = poster
|
||||
addEpisodes(DubStatus.Subbed, episodes)
|
||||
plot = description
|
||||
this.posterUrl = poster
|
||||
this.plot = description
|
||||
this.recommendations = recommendations
|
||||
showStatus = status
|
||||
this.showStatus = status
|
||||
this.tags = tags
|
||||
addEpisodes(DubStatus.Subbed, episodes)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -260,7 +262,8 @@ class NineAnimeProvider : MainAPI() {
|
|||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val document = app.get(data).document
|
||||
val animeid = document.selectFirst("div.player-wrapper.watchpage").attr("data-id") ?: return false
|
||||
val animeid =
|
||||
document.selectFirst("div.player-wrapper.watchpage").attr("data-id") ?: return false
|
||||
val animeidencoded = encode(getVrf(animeid) ?: return false)
|
||||
|
||||
Jsoup.parse(
|
||||
|
@ -287,7 +290,7 @@ class NineAnimeProvider : MainAPI() {
|
|||
parseJson<Links>(epserver)
|
||||
} else null)?.url?.let { it1 -> getLink(it1.replace("=", "")) }
|
||||
?.replace("/embed/", "/e/")
|
||||
} catch (e : Exception) {
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
null
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ import okhttp3.Interceptor
|
|||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
import java.net.URI
|
||||
import java.util.*
|
||||
|
||||
private const val OPTIONS = "OPTIONS"
|
||||
|
||||
|
@ -52,30 +51,31 @@ class ZoroProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
val epRegex = Regex("Ep (\\d+)/")
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val href = fixUrl(this.select("a").attr("href"))
|
||||
val title = this.select("h3.film-name").text()
|
||||
/*val episodes = this.select("div.fd-infor > span.fdi-item")?.get(1)?.text()?.let { eps ->
|
||||
val dubSub = this.select(".film-poster > .tick.ltr").text()
|
||||
//val episodes = this.selectFirst(".film-poster > .tick-eps")?.text()?.toIntOrNull()
|
||||
|
||||
val dubExist = dubSub.contains("dub", ignoreCase = true)
|
||||
val subExist = dubSub.contains("sub", ignoreCase = true)
|
||||
val episodes = this.selectFirst(".film-poster > .tick.rtl > .tick-eps")?.text()?.let { eps ->
|
||||
//println("REGEX:::: $eps")
|
||||
// current episode / max episode
|
||||
val epRegex = Regex("Ep (\\d+)/")//Regex("Ep (\\d+)/(\\d+)")
|
||||
//Regex("Ep (\\d+)/(\\d+)")
|
||||
epRegex.find(eps)?.groupValues?.get(1)?.toIntOrNull()
|
||||
}*/
|
||||
}
|
||||
if (href.contains("/news/") || title.trim().equals("News", ignoreCase = true)) return null
|
||||
val posterUrl = fixUrl(this.select("img").attr("data-src"))
|
||||
val type = getType(this.select("div.fd-infor > span.fdi-item").text())
|
||||
|
||||
return AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
this@ZoroProvider.name,
|
||||
type,
|
||||
posterUrl,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
return newAnimeSearchResponse(title, href, type) {
|
||||
this.posterUrl = posterUrl
|
||||
addDubStatus(dubExist, subExist, episodes, episodes)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val html = app.get("$mainUrl/home").text
|
||||
val document = Jsoup.parse(html)
|
||||
|
@ -152,30 +152,14 @@ class ZoroProvider : MainAPI() {
|
|||
val dubExist = dubsub?.contains("DUB") ?: false
|
||||
val subExist = dubsub?.contains("SUB") ?: false || dubsub?.contains("RAW") ?: false
|
||||
|
||||
val set = if (dubExist && subExist) {
|
||||
EnumSet.of(DubStatus.Dubbed, DubStatus.Subbed)
|
||||
} else if (dubExist) {
|
||||
EnumSet.of(DubStatus.Dubbed)
|
||||
} else {
|
||||
EnumSet.of(DubStatus.Subbed)
|
||||
}
|
||||
|
||||
val tvType =
|
||||
getType(it.selectFirst(".film-detail > .fd-infor > .fdi-item")?.text().toString())
|
||||
val href = fixUrl(it.selectFirst(".film-name a").attr("href"))
|
||||
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
name,
|
||||
tvType,
|
||||
poster,
|
||||
null,
|
||||
set,
|
||||
null,
|
||||
if (dubExist) episodes else null,
|
||||
if (subExist) episodes else null,
|
||||
)
|
||||
newAnimeSearchResponse(title, href, tvType) {
|
||||
this.posterUrl = poster
|
||||
addDubStatus(dubExist, subExist, episodes, episodes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,8 +171,8 @@ class ZoroProvider : MainAPI() {
|
|||
}
|
||||
|
||||
data class ZoroSyncData(
|
||||
@JsonProperty("mal_id") val malId : String?,
|
||||
@JsonProperty("anilist_id") val aniListId : String?,
|
||||
@JsonProperty("mal_id") val malId: String?,
|
||||
@JsonProperty("anilist_id") val aniListId: String?,
|
||||
)
|
||||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
|
|
|
@ -14,6 +14,11 @@ class DoramasYTProvider : MainAPI() {
|
|||
else if (t.contains("Pelicula")) TvType.Movie
|
||||
else TvType.TvSeries
|
||||
}
|
||||
fun getDubStatus(title: String): DubStatus {
|
||||
return if (title.contains("Latino") || title.contains("Castellano"))
|
||||
DubStatus.Dubbed
|
||||
else DubStatus.Subbed
|
||||
}
|
||||
}
|
||||
|
||||
override var mainUrl = "https://doramasyt.com"
|
||||
|
@ -53,39 +58,22 @@ class DoramasYTProvider : MainAPI() {
|
|||
val url = it.selectFirst("a").attr("href").replace("ver/", "dorama/")
|
||||
.replace(epRegex, "sub-espanol")
|
||||
val epNum = it.selectFirst("h3").text().toIntOrNull()
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
url,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
poster,
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
||||
DubStatus.Dubbed
|
||||
) else EnumSet.of(DubStatus.Subbed),
|
||||
subEpisodes = epNum,
|
||||
dubEpisodes = epNum,
|
||||
)
|
||||
newAnimeSearchResponse(title,url) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title), epNum)
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
for (i in urls) {
|
||||
try {
|
||||
|
||||
val home = app.get(i.first, timeout = 120).document.select(".col-6").map {
|
||||
val title = it.selectFirst(".animedtls p").text()
|
||||
val poster = it.selectFirst(".anithumb img").attr("src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
it.selectFirst("a").attr("href"),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
poster,
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
||||
DubStatus.Dubbed
|
||||
) else EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title))
|
||||
}
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, home))
|
||||
|
|
|
@ -85,7 +85,7 @@ open class VidstreamProviderTemplate : MainAPI() {
|
|||
|
||||
val description = soup.selectFirst(".post-entry")?.text()?.trim()
|
||||
var poster: String? = null
|
||||
var year : Int? = null
|
||||
var year: Int? = null
|
||||
|
||||
val episodes =
|
||||
soup.select(".listing.items.lists > .video-block").withIndex().map { (_, li) ->
|
||||
|
@ -105,7 +105,7 @@ open class VidstreamProviderTemplate : MainAPI() {
|
|||
|
||||
val epNum = Regex("""Episode (\d+)""").find(epTitle)?.destructured?.component1()
|
||||
?.toIntOrNull()
|
||||
if(year == null) {
|
||||
if (year == null) {
|
||||
year = epDate?.split("-")?.get(0)?.toIntOrNull()
|
||||
}
|
||||
newEpisode(li.selectFirst("a").attr("href")) {
|
||||
|
@ -173,25 +173,13 @@ open class VidstreamProviderTemplate : MainAPI() {
|
|||
val isSeries = (name.contains("Season") || name.contains("Episode"))
|
||||
|
||||
if (isSeries) {
|
||||
TvSeriesSearchResponse(
|
||||
name,
|
||||
link,
|
||||
this.name,
|
||||
TvType.TvSeries,
|
||||
image,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
newTvSeriesSearchResponse(name, link) {
|
||||
posterUrl = image
|
||||
}
|
||||
} else {
|
||||
MovieSearchResponse(
|
||||
name,
|
||||
link,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
image,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
newMovieSearchResponse(name, link) {
|
||||
posterUrl = image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -770,7 +770,7 @@ class HomeFragment : Fragment() {
|
|||
|
||||
home_main_text?.text =
|
||||
random.name + if (random is AnimeSearchResponse && !random.dubStatus.isNullOrEmpty()) {
|
||||
random.dubStatus.joinToString(
|
||||
random.dubStatus?.joinToString(
|
||||
prefix = " • ",
|
||||
separator = " | "
|
||||
) { it.name }
|
||||
|
|
|
@ -710,7 +710,8 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
CastButtonFactory.setUpMediaRouteButton(act, media_route_button)
|
||||
val castContext = CastContext.getSharedInstance(act.applicationContext)
|
||||
|
||||
media_route_button?.isGone = castContext.castState == CastState.NO_DEVICES_AVAILABLE
|
||||
media_route_button?.isGone =
|
||||
castContext.castState == CastState.NO_DEVICES_AVAILABLE
|
||||
|
||||
castContext.addCastStateListener { state ->
|
||||
media_route_button?.isGone = state == CastState.NO_DEVICES_AVAILABLE
|
||||
|
@ -1299,7 +1300,6 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
}
|
||||
|
||||
observe(syncModel.syncIds) {
|
||||
println("VALUES::: $it")
|
||||
syncdata = it
|
||||
}
|
||||
|
||||
|
@ -1657,8 +1657,8 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
|
||||
val posterImageLink = d.posterUrl
|
||||
if (!posterImageLink.isNullOrEmpty()) {
|
||||
result_poster?.setImage(posterImageLink)
|
||||
result_poster_blur?.setImageBlur(posterImageLink, 10, 3)
|
||||
result_poster?.setImage(posterImageLink, d.posterHeaders)
|
||||
result_poster_blur?.setImageBlur(posterImageLink, 10, 3, d.posterHeaders)
|
||||
//Full screen view of Poster image
|
||||
if (context?.isTrueTvSettings() == false) // Poster not clickable on tv
|
||||
result_poster_holder?.setOnClickListener {
|
||||
|
|
|
@ -52,7 +52,8 @@ class SearchFragment : Fragment() {
|
|||
fun List<SearchResponse>.filterSearchResponse(): List<SearchResponse> {
|
||||
return this.filter { response ->
|
||||
if (response is AnimeSearchResponse) {
|
||||
(response.dubStatus.isNullOrEmpty()) || (response.dubStatus.any {
|
||||
val status = response.dubStatus
|
||||
(status.isNullOrEmpty()) || (status.any {
|
||||
APIRepository.dubStatusActive.contains(it)
|
||||
})
|
||||
} else {
|
||||
|
@ -225,11 +226,13 @@ class SearchFragment : Fragment() {
|
|||
}
|
||||
}.sortedBy { it.name.lowercase() }
|
||||
|
||||
val names = currentValidApis.map { if(isMultiLang) "${
|
||||
SubtitleHelper.getFlagFromIso(
|
||||
it.lang
|
||||
)?.plus(" ") ?: ""
|
||||
}${it.name}" else it.name }
|
||||
val names = currentValidApis.map {
|
||||
if (isMultiLang) "${
|
||||
SubtitleHelper.getFlagFromIso(
|
||||
it.lang
|
||||
)?.plus(" ") ?: ""
|
||||
}${it.name}" else it.name
|
||||
}
|
||||
for ((index, api) in currentValidApis.map { it.name }.withIndex()) {
|
||||
listView?.setItemChecked(index, currentSelectedApis.contains(api))
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ object SearchResultBuilder {
|
|||
textIsDub?.isVisible = false
|
||||
textIsSub?.isVisible = false
|
||||
|
||||
when(card.quality) {
|
||||
when (card.quality) {
|
||||
SearchQuality.BlueRay -> R.string.quality_blueray
|
||||
SearchQuality.Cam -> R.string.quality_cam
|
||||
SearchQuality.CamRip -> R.string.quality_cam_rip
|
||||
|
@ -75,7 +75,7 @@ object SearchResultBuilder {
|
|||
cardText?.text = card.name
|
||||
|
||||
cardView.isVisible = true
|
||||
if (!cardView.setImage(card.posterUrl)) {
|
||||
if (!cardView.setImage(card.posterUrl, card.posterHeaders)) {
|
||||
cardView.setImageResource(R.drawable.default_cover)
|
||||
}
|
||||
|
||||
|
@ -182,20 +182,24 @@ object SearchResultBuilder {
|
|||
}
|
||||
}
|
||||
is AnimeSearchResponse -> {
|
||||
if (card.dubStatus != null && card.dubStatus.size > 0) {
|
||||
if (card.dubStatus.contains(DubStatus.Dubbed)) {
|
||||
val dubStatus = card.dubStatus
|
||||
if (!dubStatus.isNullOrEmpty()) {
|
||||
if (dubStatus.contains(DubStatus.Dubbed)) {
|
||||
textIsDub?.visibility = View.VISIBLE
|
||||
}
|
||||
if (card.dubStatus.contains(DubStatus.Subbed)) {
|
||||
if (dubStatus.contains(DubStatus.Subbed)) {
|
||||
textIsSub?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
val dubEpisodes = card.episodes[DubStatus.Dubbed]
|
||||
val subEpisodes = card.episodes[DubStatus.Subbed]
|
||||
|
||||
textIsDub?.apply {
|
||||
val dubText = context.getString(R.string.app_dubbed_text)
|
||||
text = if (card.dubEpisodes != null && card.dubEpisodes > 0) {
|
||||
text = if (dubEpisodes != null && dubEpisodes > 0) {
|
||||
context.getString(R.string.app_dub_sub_episode_text_format)
|
||||
.format(dubText, card.dubEpisodes)
|
||||
.format(dubText, dubEpisodes)
|
||||
} else {
|
||||
dubText
|
||||
}
|
||||
|
@ -203,9 +207,9 @@ object SearchResultBuilder {
|
|||
|
||||
textIsSub?.apply {
|
||||
val subText = context.getString(R.string.app_subbed_text)
|
||||
text = if (card.subEpisodes != null && card.subEpisodes > 0) {
|
||||
text = if (subEpisodes != null && subEpisodes > 0) {
|
||||
context.getString(R.string.app_dub_sub_episode_text_format)
|
||||
.format(subText, card.subEpisodes)
|
||||
.format(subText, subEpisodes)
|
||||
} else {
|
||||
subText
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ class SyncSearchViewModel {
|
|||
override var type: TvType?,
|
||||
override var posterUrl: String?,
|
||||
override var id: Int?,
|
||||
override var quality: SearchQuality? = null
|
||||
override var quality: SearchQuality? = null,
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
private fun SyncAPI.SyncSearchResult.toSearchResponse(): SyncSearchResultSearchResponse {
|
||||
|
|
|
@ -43,7 +43,8 @@ object DataStoreHelper {
|
|||
@JsonProperty("type") override var type: TvType? = null,
|
||||
@JsonProperty("posterUrl") override var posterUrl: String?,
|
||||
@JsonProperty("year") val year: Int?,
|
||||
@JsonProperty("quality") override var quality: SearchQuality? = null
|
||||
@JsonProperty("quality") override var quality: SearchQuality? = null,
|
||||
@JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
data class ResumeWatchingResult(
|
||||
|
@ -60,7 +61,8 @@ object DataStoreHelper {
|
|||
@JsonProperty("episode") val episode: Int?,
|
||||
@JsonProperty("season") val season: Int?,
|
||||
@JsonProperty("isFromDownload") val isFromDownload: Boolean,
|
||||
@JsonProperty("quality") override var quality: SearchQuality? = null
|
||||
@JsonProperty("quality") override var quality: SearchQuality? = null,
|
||||
@JsonProperty("posterHeaders") override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
var currentAccount: String = "0" //TODO ACCOUNT IMPLEMENTATION
|
||||
|
|
|
@ -148,11 +148,11 @@ object UIHelper {
|
|||
return color
|
||||
}
|
||||
|
||||
fun ImageView?.setImage(url: String?): Boolean {
|
||||
fun ImageView?.setImage(url: String?, headers: Map<String, String>? = null): Boolean {
|
||||
if (this == null || url.isNullOrBlank()) return false
|
||||
return try {
|
||||
GlideApp.with(this.context)
|
||||
.load(GlideUrl(url)).transition(
|
||||
.load(GlideUrl(url) { headers ?: emptyMap() }).transition(
|
||||
DrawableTransitionOptions.withCrossFade()
|
||||
)
|
||||
.into(this)
|
||||
|
@ -163,11 +163,17 @@ object UIHelper {
|
|||
}
|
||||
}
|
||||
|
||||
fun ImageView?.setImageBlur(url: String?, radius: Int, sample: Int = 3) {
|
||||
fun ImageView?.setImageBlur(
|
||||
url: String?,
|
||||
radius: Int,
|
||||
sample: Int = 3,
|
||||
headers: Map<String, String>? = null
|
||||
) {
|
||||
if (this == null || url.isNullOrBlank()) return
|
||||
try {
|
||||
GlideApp.with(this.context)
|
||||
.load(GlideUrl(url)).apply(bitmapTransform(BlurTransformation(radius, sample)))
|
||||
.load(GlideUrl(url) { headers ?: emptyMap() })
|
||||
.apply(bitmapTransform(BlurTransformation(radius, sample)))
|
||||
.transition(
|
||||
DrawableTransitionOptions.withCrossFade()
|
||||
)
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
android:layout_height="match_parent"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/search_poster_img_des" />
|
||||
<TextView
|
||||
tools:text="@string/quality_hd"
|
||||
android:id="@+id/text_quality"
|
||||
style="@style/SearchBox"
|
||||
android:background="@drawable/type_bg_color"/>
|
||||
<!--
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
|
|
Loading…
Reference in a new issue