fix(src/es): Some fixes for Spanish extensions (#2980)
This commit is contained in:
parent
bdeb3f1b16
commit
f8daecd5b4
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'Doramasflix'
|
||||
extClass = '.Doramasflix'
|
||||
extVersionCode = 16
|
||||
extVersionCode = 17
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
@ -0,0 +1,300 @@
|
||||
package eu.kanade.tachiyomi.animeextension.es.doramasflix
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
|
||||
// -----------------------Season models------------------------//
|
||||
@Serializable
|
||||
data class SeasonModel(
|
||||
val data: DataSeason = DataSeason(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class DataSeason(
|
||||
val listSeasons: List<ListSeason> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ListSeason(
|
||||
val slug: String,
|
||||
@SerialName("season_number")
|
||||
val seasonNumber: Long,
|
||||
@SerialName("poster_path")
|
||||
val posterPath: String?,
|
||||
@SerialName("air_date")
|
||||
val airDate: String?,
|
||||
@SerialName("serie_name")
|
||||
val serieName: String?,
|
||||
val poster: String?,
|
||||
val backdrop: String?,
|
||||
@SerialName("__typename")
|
||||
val typename: String,
|
||||
)
|
||||
|
||||
// -----------------------Episode Model------------------------//
|
||||
@Serializable
|
||||
data class EpisodeModel(
|
||||
val data: DataEpisode = DataEpisode(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class DataEpisode(
|
||||
val listEpisodes: List<ListEpisode> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class ListEpisode(
|
||||
@SerialName("_id")
|
||||
val id: String,
|
||||
val name: String?,
|
||||
val slug: String,
|
||||
@SerialName("serie_name")
|
||||
val serieName: String?,
|
||||
@SerialName("serie_name_es")
|
||||
val serieNameEs: String?,
|
||||
@SerialName("serie_id")
|
||||
val serieId: String?,
|
||||
@SerialName("still_path")
|
||||
val stillPath: String?,
|
||||
@SerialName("air_date")
|
||||
val airDate: String?,
|
||||
@SerialName("season_number")
|
||||
val seasonNumber: Long?,
|
||||
@SerialName("episode_number")
|
||||
val episodeNumber: Long?,
|
||||
// val languages: List<Any?>,
|
||||
val poster: String?,
|
||||
val backdrop: String?,
|
||||
@SerialName("__typename")
|
||||
val typename: String,
|
||||
)
|
||||
|
||||
// -----------------------Details Model------------------------//
|
||||
|
||||
data class DetailsModel(
|
||||
val props: Props,
|
||||
val page: String,
|
||||
val query: Query,
|
||||
val buildId: String,
|
||||
val isFallback: Boolean,
|
||||
val gip: Boolean,
|
||||
)
|
||||
|
||||
data class Props(
|
||||
val pageProps: PageProps,
|
||||
)
|
||||
|
||||
data class PageProps(
|
||||
val deviceType: String,
|
||||
val slug: String,
|
||||
// val apolloClient: Any?,
|
||||
val apolloState: HashMap<String, HashMap<String, JsonObject>>,
|
||||
val ssrComplete: Boolean,
|
||||
)
|
||||
|
||||
data class Query(
|
||||
val slug: String,
|
||||
)
|
||||
|
||||
// -----------------------Pagination Model------------------------//
|
||||
|
||||
@Serializable
|
||||
data class PaginationModel(
|
||||
val data: DataPagination = DataPagination(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class DataPagination(
|
||||
val paginationDorama: PaginationDorama? = null,
|
||||
val paginationMovie: PaginationDorama? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class PaginationDorama(
|
||||
val count: Long,
|
||||
val pageInfo: PageInfo,
|
||||
val items: List<Item> = emptyList(),
|
||||
@SerialName("__typename")
|
||||
val typename: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class PageInfo(
|
||||
val currentPage: Long,
|
||||
val hasNextPage: Boolean,
|
||||
val hasPreviousPage: Boolean,
|
||||
@SerialName("__typename")
|
||||
val typename: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Item(
|
||||
@SerialName("_id")
|
||||
val id: String,
|
||||
val name: String,
|
||||
@SerialName("name_es")
|
||||
val nameEs: String?,
|
||||
val slug: String,
|
||||
val cast: List<Cast> = emptyList(),
|
||||
val names: String?,
|
||||
val overview: String?,
|
||||
val languages: List<String> = emptyList(),
|
||||
@SerialName("created_by")
|
||||
val createdBy: List<CreatedBy> = emptyList(),
|
||||
val popularity: Double?,
|
||||
@SerialName("poster_path")
|
||||
val posterPath: String?,
|
||||
@SerialName("backdrop_path")
|
||||
val backdropPath: String?,
|
||||
@SerialName("first_air_date")
|
||||
val firstAirDate: String?,
|
||||
@SerialName("isTVShow")
|
||||
val isTvshow: Boolean?,
|
||||
val poster: String?,
|
||||
val backdrop: String?,
|
||||
val genres: List<Genre> = emptyList(),
|
||||
val networks: List<Network> = emptyList(),
|
||||
@SerialName("__typename")
|
||||
val typename: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Cast(
|
||||
val adult: Boolean?,
|
||||
val gender: Long?,
|
||||
val id: Long?,
|
||||
@SerialName("known_for_department")
|
||||
val knownForDepartment: String?,
|
||||
val name: String?,
|
||||
@SerialName("original_name")
|
||||
val originalName: String?,
|
||||
val popularity: Double?,
|
||||
@SerialName("profile_path")
|
||||
val profilePath: String?,
|
||||
val character: String?,
|
||||
@SerialName("credit_id")
|
||||
val creditId: String?,
|
||||
val order: Long?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class CreatedBy(
|
||||
val adult: Boolean?,
|
||||
val gender: Long?,
|
||||
val id: Long?,
|
||||
@SerialName("known_for_department")
|
||||
val knownForDepartment: String?,
|
||||
val name: String?,
|
||||
@SerialName("original_name")
|
||||
val originalName: String?,
|
||||
val popularity: Double?,
|
||||
@SerialName("profile_path")
|
||||
val profilePath: String?,
|
||||
@SerialName("credit_id")
|
||||
val creditId: String?,
|
||||
val department: String?,
|
||||
val job: String?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Genre(
|
||||
val name: String?,
|
||||
val slug: String?,
|
||||
@SerialName("__typename")
|
||||
val typename: String?,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Network(
|
||||
val name: String?,
|
||||
val slug: String?,
|
||||
@SerialName("__typename")
|
||||
val typename: String?,
|
||||
)
|
||||
|
||||
// -----------------------Search Model------------------------//
|
||||
@Serializable
|
||||
data class SearchModel(
|
||||
val data: Data = Data(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Data(
|
||||
val searchDorama: List<SearchDorama> = emptyList(),
|
||||
val searchMovie: List<SearchDorama> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class SearchDorama(
|
||||
@SerialName("_id")
|
||||
val id: String,
|
||||
val slug: String,
|
||||
val name: String,
|
||||
@SerialName("name_es")
|
||||
val nameEs: String?,
|
||||
@SerialName("poster_path")
|
||||
val posterPath: String?,
|
||||
val poster: String?,
|
||||
@SerialName("__typename")
|
||||
val typename: String,
|
||||
)
|
||||
|
||||
// -------------------------------------------------------
|
||||
@Serializable
|
||||
data class VideoModel(
|
||||
val json: JsonVideo = JsonVideo(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class JsonVideo(
|
||||
val lang: String? = "",
|
||||
val page: String? = "",
|
||||
val link: String? = "",
|
||||
val server: String? = "",
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class VideoToken(
|
||||
val link: String?,
|
||||
val server: String?,
|
||||
val app: String?,
|
||||
val iat: Long?,
|
||||
val exp: Long?,
|
||||
)
|
||||
|
||||
// ------------------------------------------------
|
||||
|
||||
@Serializable
|
||||
data class TokenModel(
|
||||
val props: PropsToken = PropsToken(),
|
||||
val page: String? = null,
|
||||
val query: QueryToken = QueryToken(),
|
||||
val buildId: String? = null,
|
||||
val isFallback: Boolean? = false,
|
||||
val isExperimentalCompile: Boolean? = false,
|
||||
val gssp: Boolean? = false,
|
||||
// val scriptLoader: List<Any?>,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class PropsToken(
|
||||
val pageProps: PagePropsToken = PagePropsToken(),
|
||||
@SerialName("__N_SSP")
|
||||
val nSsp: Boolean? = false,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class PagePropsToken(
|
||||
val token: String? = null,
|
||||
val name: String? = null,
|
||||
val app: String? = null,
|
||||
val server: String? = null,
|
||||
val iosapp: String? = null,
|
||||
val externalLink: String? = null,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class QueryToken(
|
||||
val token: String? = null,
|
||||
)
|
@ -2,9 +2,11 @@ package eu.kanade.tachiyomi.animeextension.es.doramasflix
|
||||
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import android.util.Base64
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
||||
@ -24,11 +26,12 @@ import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
|
||||
import eu.kanade.tachiyomi.lib.upstreamextractor.UpstreamExtractor
|
||||
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
|
||||
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
||||
import eu.kanade.tachiyomi.lib.vudeoextractor.VudeoExtractor
|
||||
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
@ -43,6 +46,8 @@ import okhttp3.Response
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
|
||||
@ -86,6 +91,10 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
"Fastream", "Filemoon", "StreamWish", "Okru", "Streamlare",
|
||||
"Uqload",
|
||||
)
|
||||
|
||||
private val DATE_FORMATTER by lazy {
|
||||
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||
}
|
||||
}
|
||||
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
@ -121,7 +130,8 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
document.select("script").map { el ->
|
||||
if (el.data().contains("{\"props\":{\"pageProps\":{")) {
|
||||
val apolloState = json.decodeFromString<JsonObject>(el.data())!!.jsonObject["props"]!!.jsonObject["pageProps"]!!.jsonObject["apolloState"]!!.jsonObject
|
||||
val dorama = apolloState!!.entries!!.firstOrNull()!!.value!!.jsonObject
|
||||
val dorama = apolloState!!.entries!!.firstOrNull { (key, _) -> Regex("\\b(?:Movie|Dorama):[a-zA-Z0-9]+").matches(key) }!!.value!!.jsonObject
|
||||
|
||||
val genres = try { apolloState.entries.filter { x -> x.key.contains("genres") }.joinToString { it.value.jsonObject["name"]!!.jsonPrimitive.content } } catch (_: Exception) { "" }
|
||||
val network = try { apolloState.entries.firstOrNull { x -> x.key.contains("networks") }?.value?.jsonObject?.get("name")!!.jsonPrimitive.content } catch (_: Exception) { "" }
|
||||
val artist = try { dorama["cast"]?.jsonObject?.get("json")?.jsonArray?.firstOrNull()?.jsonObject?.get("name")?.jsonPrimitive?.content } catch (_: Exception) { "" }
|
||||
@ -158,55 +168,60 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
}
|
||||
|
||||
override fun episodeListParse(response: Response): List<SEpisode> {
|
||||
val episodes = mutableListOf<SEpisode>()
|
||||
if (response.request.url.toString().contains("peliculas-online")) {
|
||||
val episode = SEpisode.create()
|
||||
episode.episode_number = 1F
|
||||
episode.name = "Película"
|
||||
episode.setUrlWithoutDomain(response.request.url.toString())
|
||||
episodes.add(episode)
|
||||
return if (response.request.url.toString().contains("peliculas-online")) {
|
||||
listOf(
|
||||
SEpisode.create().apply {
|
||||
episode_number = 1F
|
||||
name = "Película"
|
||||
setUrlWithoutDomain(response.request.url.toString())
|
||||
},
|
||||
)
|
||||
} else {
|
||||
val jsonEpisodes = mutableListOf<String>()
|
||||
val id = response.request.url.toString().substringAfter("?id=")
|
||||
val responseString = response.body.string()
|
||||
val data = json.decodeFromString<JsonObject>(responseString)!!.jsonObject["data"]!!.jsonObject
|
||||
data["listSeasons"]!!.jsonArray.forEach {
|
||||
val season = it.jsonObject["season_number"]!!.jsonPrimitive.content
|
||||
val data = json.decodeFromString<SeasonModel>(responseString).data
|
||||
|
||||
data.listSeasons.parallelCatchingFlatMapBlocking {
|
||||
val season = it.seasonNumber
|
||||
val body = (
|
||||
"{\"operationName\":\"listEpisodes\",\"variables\":{\"serie_id\":\"$id\",\"season_number\":$season},\"query\":\"query " +
|
||||
"listEpisodes(\$season_number: Float!, \$serie_id: MongoID!) {\\n listEpisodes(sort: NUMBER_ASC, filter: {type_serie: \\\"dorama\\\", " +
|
||||
"serie_id: \$serie_id, season_number: \$season_number}) {\\n _id\\n name\\n slug\\n serie_name\\n serie_name_es\\n " +
|
||||
"serie_id\\n still_path\\n air_date\\n season_number\\n episode_number\\n languages\\n poster\\n backdrop\\n __typename\\n }\\n}\\n\"}"
|
||||
).toRequestBody(mediaType)
|
||||
client.newCall(POST(apiUrl, popularRequestHeaders, body)).execute().let { resp -> jsonEpisodes.add(resp.body.string()) }
|
||||
|
||||
val episodes = client.newCall(POST(apiUrl, popularRequestHeaders, body)).execute().let { resp ->
|
||||
json.decodeFromString<EpisodeModel>(resp.body.string())
|
||||
}
|
||||
parseEpisodeListJson(episodes)
|
||||
}
|
||||
jsonEpisodes.forEach { json -> episodes.addAll(parseEpisodeListJson(json)) }
|
||||
}
|
||||
return episodes.reversed()
|
||||
}.reversed()
|
||||
}
|
||||
|
||||
private fun parseEpisodeListJson(jsonLine: String?): List<SEpisode> {
|
||||
val jsonData = jsonLine ?: return emptyList()
|
||||
val episodes = mutableListOf<SEpisode>()
|
||||
val data = json.decodeFromString<JsonObject>(jsonData)!!.jsonObject["data"]!!.jsonObject
|
||||
data["listEpisodes"]!!.jsonArray!!.map {
|
||||
val noSeason = it.jsonObject["season_number"]!!.jsonPrimitive!!.content
|
||||
val noEpisode = it.jsonObject["episode_number"]!!.jsonPrimitive!!.content
|
||||
var nameEp = it.jsonObject["name"]!!.jsonPrimitive!!.content
|
||||
nameEp = if (nameEp == "null") "- Capítulo $noEpisode" else "- $nameEp"
|
||||
val slug = it.jsonObject["slug"]!!.jsonPrimitive!!.content
|
||||
val episode = SEpisode.create()
|
||||
episode.name = "T$noSeason - E$noEpisode $nameEp"
|
||||
episode.episode_number = noEpisode.toFloat()
|
||||
episode.setUrlWithoutDomain(urlSolverByType("episode", slug))
|
||||
episodes.add(episode)
|
||||
private fun parseEpisodeListJson(episodes: EpisodeModel): List<SEpisode> {
|
||||
var isUpcoming = false
|
||||
val currentDate = Date().time
|
||||
return episodes.data.listEpisodes.mapIndexed { idx, episodeObject ->
|
||||
val dateEp = episodeObject.airDate
|
||||
val nameEp = if (episodeObject.name.isNullOrEmpty()) "- Capítulo ${episodeObject.episodeNumber}" else "- ${episodeObject.name}"
|
||||
if (dateEp != null && dateEp.toDate() > currentDate && !isUpcoming) isUpcoming = true
|
||||
|
||||
SEpisode.create().apply {
|
||||
name = "T${episodeObject.seasonNumber} - E${episodeObject.episodeNumber} $nameEp"
|
||||
episode_number = episodeObject.episodeNumber?.toFloat() ?: idx.toFloat()
|
||||
date_upload = dateEp?.toDate() ?: 0L
|
||||
scanlator = if (isUpcoming) "Próximamente..." else null
|
||||
setUrlWithoutDomain(urlSolverByType("episode", episodeObject.slug))
|
||||
}
|
||||
}
|
||||
return episodes
|
||||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): AnimesPage {
|
||||
val responseString = response.body.string()
|
||||
return parsePopularAnimeJson(responseString)
|
||||
return when {
|
||||
responseString.contains("paginationMovie") -> parsePopularJson(responseString, "movie")
|
||||
else -> parsePopularJson(responseString, "dorama")
|
||||
}
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
@ -226,7 +241,10 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
|
||||
override fun popularAnimeParse(response: Response): AnimesPage {
|
||||
val responseString = response.body.string()
|
||||
return parsePopularAnimeJson(responseString)
|
||||
return when {
|
||||
responseString.contains("paginationMovie") -> parsePopularJson(responseString, "movie")
|
||||
else -> parsePopularJson(responseString, "dorama")
|
||||
}
|
||||
}
|
||||
|
||||
private val languages = arrayOf(
|
||||
@ -248,26 +266,33 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
return languages.firstOrNull { it.first == this }?.second ?: ""
|
||||
}
|
||||
|
||||
private fun parsePopularAnimeJson(jsonLine: String?): AnimesPage {
|
||||
private fun parsePopularJson(jsonLine: String?, type: String): AnimesPage {
|
||||
val jsonData = jsonLine ?: return AnimesPage(emptyList(), false)
|
||||
val animeList = mutableListOf<SAnime>()
|
||||
val paginationDorama = json.decodeFromString<JsonObject>(jsonData)!!.jsonObject["data"]!!.jsonObject!!["paginationDorama"]!!.jsonObject
|
||||
val hasNextPage = paginationDorama["pageInfo"]!!.jsonObject["hasNextPage"]!!.jsonPrimitive!!.content!!.toBoolean()
|
||||
paginationDorama["items"]!!.jsonArray.map {
|
||||
val anime = SAnime.create()
|
||||
val genres = it.jsonObject!!["genres"]!!.jsonArray!!.joinToString { it.jsonObject["name"]!!.jsonPrimitive!!.content }
|
||||
val id = it.jsonObject!!["_id"]!!.jsonPrimitive!!.content
|
||||
val poster = it.jsonObject["poster_path"]!!.jsonPrimitive.content
|
||||
val urlImg = poster.ifEmpty { it.jsonObject!!["poster"]!!.jsonPrimitive.content }
|
||||
val data = json.decodeFromString<PaginationModel>(jsonData).data
|
||||
|
||||
anime.title = "${it.jsonObject!!["name"]!!.jsonPrimitive!!.content} (${it.jsonObject!!["name_es"]!!.jsonPrimitive!!.content})"
|
||||
anime.description = it.jsonObject!!["overview"]!!.jsonPrimitive!!.content
|
||||
anime.genre = genres
|
||||
anime.thumbnail_url = externalOrInternalImg(urlImg, true)
|
||||
anime.setUrlWithoutDomain(urlSolverByType(it.jsonObject!!["__typename"]!!.jsonPrimitive!!.content, it.jsonObject!!["slug"]!!.jsonPrimitive!!.content, id))
|
||||
animeList.add(anime)
|
||||
val pagination = when (type) {
|
||||
"dorama" -> data.paginationDorama
|
||||
"movie" -> data.paginationMovie
|
||||
else -> throw IllegalArgumentException("Tipo de dato no válido: $type")
|
||||
}
|
||||
return AnimesPage(animeList, hasNextPage)
|
||||
|
||||
val hasNextPage = pagination?.pageInfo?.hasNextPage ?: false
|
||||
val animeList = pagination?.items?.map { animeObject ->
|
||||
val urlImg = when {
|
||||
!animeObject.posterPath.isNullOrEmpty() -> animeObject.posterPath.toString()
|
||||
!animeObject.poster.isNullOrEmpty() -> animeObject.poster.toString()
|
||||
else -> ""
|
||||
}
|
||||
|
||||
SAnime.create().apply {
|
||||
title = "${animeObject.name} (${animeObject.nameEs})"
|
||||
description = animeObject.overview
|
||||
genre = animeObject.genres.joinToString { it.name ?: "" }
|
||||
thumbnail_url = externalOrInternalImg(urlImg, true)
|
||||
setUrlWithoutDomain(urlSolverByType(animeObject.typename, animeObject.slug, animeObject.id))
|
||||
}
|
||||
}
|
||||
return AnimesPage(animeList ?: emptyList(), hasNextPage)
|
||||
}
|
||||
|
||||
private fun urlSolverByType(type: String, slug: String, id: String? = ""): String {
|
||||
@ -296,45 +321,45 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
|
||||
override fun searchAnimeParse(response: Response): AnimesPage {
|
||||
val responseString = response.body.string()
|
||||
return if (responseString.contains("searchDorama")) {
|
||||
parseSearchAnimeJson(responseString)
|
||||
} else {
|
||||
parsePopularAnimeJson(responseString)
|
||||
return when {
|
||||
responseString.contains("searchDorama") -> parseSearchAnimeJson(responseString)
|
||||
responseString.contains("paginationMovie") -> parsePopularJson(responseString, "movie")
|
||||
else -> parsePopularJson(responseString, "dorama")
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseSearchAnimeJson(jsonLine: String?): AnimesPage {
|
||||
val jsonData = jsonLine ?: return AnimesPage(emptyList(), false)
|
||||
val jsonObject = json.decodeFromString<SearchModel>(jsonData).data
|
||||
|
||||
val animeList = mutableListOf<SAnime>()
|
||||
val paginationDorama = json.decodeFromString<JsonObject>(jsonData)!!.jsonObject["data"]!!.jsonObject
|
||||
paginationDorama["searchDorama"]!!.jsonArray.map {
|
||||
val anime = SAnime.create()
|
||||
val id = it.jsonObject!!["_id"]!!.jsonPrimitive!!.content
|
||||
val poster = it.jsonObject!!["poster_path"]!!.jsonPrimitive!!.content
|
||||
val urlImg = poster.ifEmpty { it.jsonObject!!["poster"]!!.jsonPrimitive!!.content }
|
||||
jsonObject.searchDorama.map { castToSAnime(it) }.also(animeList::addAll)
|
||||
jsonObject.searchMovie.map { castToSAnime(it) }.also(animeList::addAll)
|
||||
|
||||
anime.title = "${it.jsonObject!!["name"]!!.jsonPrimitive!!.content} (${it.jsonObject!!["name_es"]!!.jsonPrimitive!!.content})"
|
||||
anime.thumbnail_url = externalOrInternalImg(urlImg, true)
|
||||
anime.setUrlWithoutDomain(urlSolverByType(it.jsonObject!!["__typename"]!!.jsonPrimitive!!.content, it.jsonObject!!["slug"]!!.jsonPrimitive!!.content, id))
|
||||
animeList.add(anime)
|
||||
}
|
||||
paginationDorama["searchMovie"]!!.jsonArray.map {
|
||||
val anime = SAnime.create()
|
||||
val id = it.jsonObject!!["_id"]!!.jsonPrimitive!!.content
|
||||
val poster = it.jsonObject!!["poster_path"]!!.jsonPrimitive!!.content
|
||||
val urlImg = poster.ifEmpty { it.jsonObject!!["poster"]!!.jsonPrimitive!!.content }
|
||||
|
||||
anime.title = "${it.jsonObject!!["name"]!!.jsonPrimitive!!.content} (${it.jsonObject!!["name_es"]!!.jsonPrimitive!!.content})"
|
||||
anime.thumbnail_url = externalOrInternalImg(urlImg, true)
|
||||
anime.setUrlWithoutDomain(urlSolverByType(it.jsonObject!!["__typename"]!!.jsonPrimitive!!.content, it.jsonObject!!["slug"]!!.jsonPrimitive!!.content, id))
|
||||
animeList.add(anime)
|
||||
}
|
||||
return AnimesPage(animeList, false)
|
||||
}
|
||||
|
||||
private fun castToSAnime(animeObject: SearchDorama): SAnime {
|
||||
val urlImg = when {
|
||||
!animeObject.posterPath.isNullOrEmpty() -> animeObject.posterPath.toString()
|
||||
!animeObject.poster.isNullOrEmpty() -> animeObject.poster.toString()
|
||||
else -> ""
|
||||
}
|
||||
return SAnime.create().apply {
|
||||
title = "${animeObject.name} (${animeObject.nameEs})"
|
||||
thumbnail_url = externalOrInternalImg(urlImg, true)
|
||||
setUrlWithoutDomain(urlSolverByType(animeObject.typename, animeObject.slug, animeObject.id))
|
||||
}
|
||||
}
|
||||
|
||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
||||
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
||||
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
|
||||
|
||||
return when {
|
||||
query.isNotBlank() -> searchQueryRequest(query)
|
||||
"peliculas" in genreFilter.toUriPart() -> popularMovieRequest(page)
|
||||
"variedades" in genreFilter.toUriPart() -> popularVarietiesRequest(page)
|
||||
else -> popularAnimeRequest(page)
|
||||
}
|
||||
}
|
||||
@ -350,123 +375,148 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
return POST(apiUrl, popularRequestHeaders, body)
|
||||
}
|
||||
|
||||
private fun popularMovieRequest(page: Int): Request {
|
||||
val mediaType = "application/json; charset=utf-8".toMediaType()
|
||||
val body = (
|
||||
"{\"operationName\":\"listMovies\",\"variables\":{\"perPage\":32,\"sort\":\"CREATEDAT_DESC\",\"filter\":{},\"page\":$page},\"query\":\"query " +
|
||||
"listMovies(\$page: Int, \$perPage: Int, \$sort: SortFindManyMovieInput, \$filter: FilterFindManyMovieInput) {\\n paginationMovie(page: \$page" +
|
||||
", perPage: \$perPage, sort: \$sort, filter: \$filter) {\\n count\\n pageInfo {\\n currentPage\\n hasNextPage\\n hasPreviousPage\\n" +
|
||||
" __typename\\n }\\n items {\\n _id\\n name\\n name_es\\n slug\\n cast\\n names\\n overview\\n " +
|
||||
"languages\\n popularity\\n poster_path\\n vote_average\\n backdrop_path\\n release_date\\n runtime\\n poster\\n " +
|
||||
"backdrop\\n genres {\\n name\\n __typename\\n }\\n networks {\\n name\\n __typename\\n }\\n " +
|
||||
"__typename\\n }\\n __typename\\n }\\n}\\n\"}"
|
||||
).toRequestBody(mediaType)
|
||||
|
||||
return POST(apiUrl, popularRequestHeaders, body)
|
||||
}
|
||||
|
||||
private fun popularVarietiesRequest(page: Int): Request {
|
||||
val mediaType = "application/json; charset=utf-8".toMediaType()
|
||||
val body = (
|
||||
"{\"operationName\":\"listDoramas\",\"variables\":{\"page\":$page,\"sort\":\"CREATEDAT_DESC\",\"perPage\":32,\"filter\":{\"isTVShow\":true}},\"query\":\"query " +
|
||||
"listDoramas(\$page: Int, \$perPage: Int, \$sort: SortFindManyDoramaInput, \$filter: FilterFindManyDoramaInput) {\\n paginationDorama(page: \$page, perPage: \$perPage, " +
|
||||
"sort: \$sort, filter: \$filter) {\\n count\\n pageInfo {\\n currentPage\\n hasNextPage\\n hasPreviousPage\\n __typename\\n }\\n " +
|
||||
"items {\\n _id\\n name\\n name_es\\n slug\\n cast\\n names\\n overview\\n languages\\n created_by\\n " +
|
||||
"popularity\\n poster_path\\n vote_average\\n backdrop_path\\n first_air_date\\n episode_run_time\\n isTVShow\\n poster\\n " +
|
||||
"backdrop\\n genres {\\n name\\n slug\\n __typename\\n }\\n networks {\\n name\\n slug\\n " +
|
||||
"__typename\\n }\\n __typename\\n }\\n __typename\\n }\\n}\\n\"}"
|
||||
).toRequestBody(mediaType)
|
||||
|
||||
return POST(apiUrl, popularRequestHeaders, body)
|
||||
}
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
||||
AnimeFilter.Header("La busqueda por texto ignora el filtro"),
|
||||
GenreFilter(),
|
||||
)
|
||||
|
||||
private class GenreFilter : UriPartFilter(
|
||||
"Géneros",
|
||||
arrayOf(
|
||||
Pair("Doramas", "doramas"),
|
||||
Pair("Películas", "peliculas"),
|
||||
Pair("Variedades", "variedades"),
|
||||
),
|
||||
)
|
||||
|
||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||
AnimeFilter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||
fun toUriPart() = vals[state].second
|
||||
}
|
||||
|
||||
private fun String.toDate(): Long {
|
||||
return runCatching { DATE_FORMATTER.parse(trim())?.time }.getOrNull() ?: 0L
|
||||
}
|
||||
|
||||
override fun videoListParse(response: Response): List<Video> {
|
||||
val document = response.asJsoup()
|
||||
val videoList = mutableListOf<Video>()
|
||||
val jsonData = document.selectFirst("script:containsData({\"props\":{\"pageProps\":{)")!!.data()
|
||||
val apolloState = json.decodeFromString<JsonObject>(jsonData).jsonObject["props"]!!.jsonObject["pageProps"]!!.jsonObject["apolloState"]!!.jsonObject
|
||||
val episode = apolloState.entries.firstOrNull { x -> x.key.contains("Episode:") }!!.value.jsonObject
|
||||
val episodeItem = apolloState.entries.firstOrNull { x -> x.key.contains("Episode:") }
|
||||
|
||||
val linksOnline = episode["links_online"]!!.jsonObject["json"]!!.jsonArray
|
||||
val episode = episodeItem?.value?.jsonObject
|
||||
?: apolloState.entries.firstOrNull { (key, _) -> Regex("\\b(?:Movie|Dorama):[a-zA-Z0-9]+").matches(key) }?.value?.jsonObject
|
||||
|
||||
linksOnline.map {
|
||||
var linksOnline = episode?.get("links_online")?.jsonObject?.get("json")?.jsonArray
|
||||
val bMovies = apolloState.entries.any { x -> x.key.contains("ROOT_QUERY.getMovieLinks(") }
|
||||
|
||||
if (bMovies && linksOnline == null) {
|
||||
linksOnline = apolloState.entries.firstOrNull { x -> x.key.contains("ROOT_QUERY.getMovieLinks(") }
|
||||
?.value?.jsonObject?.get("links_online")?.jsonObject?.get("json")?.jsonArray
|
||||
}
|
||||
|
||||
return linksOnline?.parallelCatchingFlatMapBlocking {
|
||||
val link = it.jsonObject["link"]!!.jsonPrimitive.content
|
||||
val lang = it.jsonObject["lang"]?.jsonPrimitive?.content?.getLang() ?: ""
|
||||
serverVideoResolver(link, lang).also(videoList::addAll)
|
||||
}
|
||||
return videoList
|
||||
serverVideoResolver(link, lang)
|
||||
} ?: apolloState.entries.filter { x -> x.key.contains("ROOT_QUERY.listProblems(") }
|
||||
.mapNotNull { entry ->
|
||||
val server = entry.value.jsonObject["server"]?.jsonObject?.get("json")?.jsonObject
|
||||
val link = server?.get("link")?.jsonPrimitive?.content
|
||||
val lang = server?.get("lang")?.jsonPrimitive?.content?.getLang() ?: ""
|
||||
link?.let { it to lang }
|
||||
}.distinctBy { it.first }
|
||||
.parallelCatchingFlatMapBlocking { (link, lang) ->
|
||||
val finalLink = getRealLink(link)
|
||||
serverVideoResolver(finalLink, lang)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRealLink(link: String): String {
|
||||
if (!link.contains("fkplayer.xyz")) return link
|
||||
|
||||
val token = client.newCall(GET(link)).execute()
|
||||
.asJsoup().selectFirst("script:containsData({\"props\":{\"pageProps\":{)")?.data()
|
||||
?.parseTo<TokenModel>()
|
||||
|
||||
val mediaType = "application/json".toMediaType()
|
||||
val requestBody = "{\"token\":\"${token?.props?.pageProps?.token ?: token?.query?.token}\"}".toRequestBody(mediaType)
|
||||
|
||||
val headersVideo = headers.newBuilder()
|
||||
.add("origin", "https://${link.toHttpUrl().host}")
|
||||
.add("Content-Type", "application/json")
|
||||
.build()
|
||||
|
||||
val json = client.newCall(POST("https://fkplayer.xyz/api/decoding", headersVideo, requestBody))
|
||||
.execute().body.string().parseTo<VideoToken>()
|
||||
|
||||
return String(Base64.decode(json.link, Base64.DEFAULT))
|
||||
}
|
||||
|
||||
private fun serverVideoResolver(url: String, prefix: String = ""): List<Video> {
|
||||
val videoList = mutableListOf<Video>()
|
||||
val embedUrl = url.lowercase()
|
||||
try {
|
||||
if (embedUrl.contains("voe")) {
|
||||
VoeExtractor(client).videosFromUrl(url, prefix).also(videoList::addAll)
|
||||
}
|
||||
if ((embedUrl.contains("amazon") || embedUrl.contains("amz")) && !embedUrl.contains("disable")) {
|
||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
||||
if (body.select("script:containsData(var shareId)").toString().isNotBlank()) {
|
||||
val shareId = body.selectFirst("script:containsData(var shareId)")!!.data()
|
||||
.substringAfter("shareId = \"").substringBefore("\"")
|
||||
val amazonApiJson = client.newCall(GET("https://www.amazon.com/drive/v1/shares/$shareId?resourceVersion=V2&ContentType=JSON&asset=ALL"))
|
||||
.execute().asJsoup()
|
||||
val epId = amazonApiJson.toString().substringAfter("\"id\":\"").substringBefore("\"")
|
||||
val amazonApi =
|
||||
client.newCall(GET("https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId"))
|
||||
.execute().asJsoup()
|
||||
val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":").substringAfter("tempLink\":\"").substringBefore("\"")
|
||||
videoList.add(Video(videoUrl, "$prefix Amazon", videoUrl))
|
||||
}
|
||||
}
|
||||
if (embedUrl.contains("ok.ru") || embedUrl.contains("okru")) {
|
||||
OkruExtractor(client).videosFromUrl(url, prefix = "$prefix ").also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("filemoon") || embedUrl.contains("moonplayer")) {
|
||||
return when {
|
||||
"voe" in embedUrl -> VoeExtractor(client).videosFromUrl(url, " $prefix")
|
||||
"ok.ru" in embedUrl || "okru" in embedUrl -> OkruExtractor(client).videosFromUrl(url, prefix = "$prefix ")
|
||||
"filemoon" in embedUrl || "moonplayer" in embedUrl -> {
|
||||
val vidHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||
.build()
|
||||
FilemoonExtractor(client).videosFromUrl(url, prefix = "$prefix Filemoon:", headers = vidHeaders).also(videoList::addAll)
|
||||
FilemoonExtractor(client).videosFromUrl(url, prefix = "$prefix Filemoon:", headers = vidHeaders)
|
||||
}
|
||||
if (embedUrl.contains("uqload")) {
|
||||
UqloadExtractor(client).videosFromUrl(url, prefix = prefix).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("mp4upload")) {
|
||||
Mp4uploadExtractor(client).videosFromUrl(url, prefix = "$prefix ", headers = headers).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("wishembed") || embedUrl.contains("streamwish") || embedUrl.contains("strwish") || embedUrl.contains("wish")) {
|
||||
"uqload" in embedUrl -> UqloadExtractor(client).videosFromUrl(url, prefix = prefix)
|
||||
"mp4upload" in embedUrl -> Mp4uploadExtractor(client).videosFromUrl(url, prefix = "$prefix ", headers = headers)
|
||||
"doodstream" in embedUrl || "dood." in embedUrl ->
|
||||
listOf(DoodExtractor(client).videoFromUrl(url.replace("https://doodstream.com/e/", "https://dood.to/e/"), "$prefix DoodStream", false)!!)
|
||||
"streamlare" in embedUrl -> StreamlareExtractor(client).videosFromUrl(url, prefix = prefix)
|
||||
"yourupload" in embedUrl || "upload" in embedUrl -> YourUploadExtractor(client).videoFromUrl(url, headers = headers, prefix = "$prefix ")
|
||||
"wishembed" in embedUrl || "streamwish" in embedUrl || "strwish" in embedUrl || "wish" in embedUrl -> {
|
||||
val docHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://streamwish.to")
|
||||
.add("Referer", "https://streamwish.to/")
|
||||
.build()
|
||||
StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "$prefix StreamWish:$it" }).also(videoList::addAll)
|
||||
StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "$prefix StreamWish:$it" })
|
||||
}
|
||||
if (embedUrl.contains("doodstream") || embedUrl.contains("dood.")) {
|
||||
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
||||
DoodExtractor(client).videoFromUrl(url2, "$prefix DoodStream", false)?.let { videoList.add(it) }
|
||||
}
|
||||
if (embedUrl.contains("streamlare")) {
|
||||
StreamlareExtractor(client).videosFromUrl(url, prefix = prefix).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("yourupload") || embedUrl.contains("upload")) {
|
||||
YourUploadExtractor(client).videoFromUrl(url, headers = headers, prefix = "$prefix ").let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("burstcloud") || embedUrl.contains("burst")) {
|
||||
BurstCloudExtractor(client).videoFromUrl(url, headers = headers, prefix = "$prefix ").let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("fastream")) {
|
||||
FastreamExtractor(client, headers).videosFromUrl(url, prefix = "$prefix Fastream:").also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("upstream")) {
|
||||
UpstreamExtractor(client).videosFromUrl(url, prefix = "$prefix ").let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("streamtape") || embedUrl.contains("stp") || embedUrl.contains("stape")) {
|
||||
StreamTapeExtractor(client).videoFromUrl(url, quality = "$prefix StreamTape")?.let { videoList.add(it) }
|
||||
}
|
||||
if (embedUrl.contains("ahvsh") || embedUrl.contains("streamhide")) {
|
||||
StreamHideVidExtractor(client).videosFromUrl(url, "$prefix ").let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("filelions") || embedUrl.contains("lion")) {
|
||||
StreamWishExtractor(client, headers).videosFromUrl(url, videoNameGen = { "$prefix FileLions:$it" }).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("tomatomatela")) {
|
||||
runCatching {
|
||||
val mainUrl = url.substringBefore("/embed.html#").substringAfter("https://")
|
||||
val headers = headers.newBuilder()
|
||||
.set("authority", mainUrl)
|
||||
.set("accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.set("accept-language", "es-MX,es-419;q=0.9,es;q=0.8,en;q=0.7")
|
||||
.set("sec-ch-ua", "\"Chromium\";v=\"106\", \"Google Chrome\";v=\"106\", \"Not;A=Brand\";v=\"99\"")
|
||||
.set("sec-ch-ua-mobile", "?0")
|
||||
.set("sec-ch-ua-platform", "Windows")
|
||||
.set("sec-fetch-dest", "empty")
|
||||
.set("sec-fetch-mode", "cors")
|
||||
.set("sec-fetch-site", "same-origin")
|
||||
.set("x-requested-with", "XMLHttpRequest")
|
||||
.build()
|
||||
val token = url.substringAfter("/embed.html#")
|
||||
val urlRequest = "https://$mainUrl/details.php?v=$token"
|
||||
val response = client.newCall(GET(urlRequest, headers = headers)).execute().asJsoup()
|
||||
val bodyText = response.select("body").text()
|
||||
val json = json.decodeFromString<JsonObject>(bodyText)
|
||||
val status = json["status"]!!.jsonPrimitive!!.content
|
||||
val file = json["file"]!!.jsonPrimitive!!.content
|
||||
if (status == "200") { videoList.add(Video(file, "$prefix Tomatomatela", file, headers = null)) }
|
||||
}
|
||||
}
|
||||
} catch (_: Exception) { }
|
||||
return videoList
|
||||
"burstcloud" in embedUrl || "burst" in embedUrl -> BurstCloudExtractor(client).videoFromUrl(url, headers = headers, prefix = "$prefix ")
|
||||
"fastream" in embedUrl -> FastreamExtractor(client, headers).videosFromUrl(url, prefix = "$prefix Fastream:")
|
||||
"upstream" in embedUrl -> UpstreamExtractor(client).videosFromUrl(url, prefix = "$prefix ")
|
||||
"streamtape" in embedUrl || "stp" in embedUrl || "stape" in embedUrl -> listOf(StreamTapeExtractor(client).videoFromUrl(url, quality = "$prefix StreamTape")!!)
|
||||
"ahvsh" in embedUrl || "streamhide" in embedUrl -> StreamHideVidExtractor(client).videosFromUrl(url, "$prefix ")
|
||||
"filelions" in embedUrl || "lion" in embedUrl -> StreamWishExtractor(client, headers).videosFromUrl(url, videoNameGen = { "$prefix FileLions:$it" })
|
||||
"vudeo" in embedUrl || "vudea" in embedUrl -> VudeoExtractor(client).videosFromUrl(url, "$prefix ")
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
@ -532,4 +582,11 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||
}
|
||||
}.also(screen::addPreference)
|
||||
}
|
||||
private inline fun <reified T> String.parseTo(): T {
|
||||
return json.decodeFromString<T>(this)
|
||||
}
|
||||
|
||||
private inline fun <reified T> Response.parseTo(): T {
|
||||
return json.decodeFromString<T>(this.body.string())
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'LocoPelis'
|
||||
extClass = '.LocoPelis'
|
||||
extVersionCode = 20
|
||||
extVersionCode = 21
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
@ -10,4 +10,5 @@ dependencies {
|
||||
implementation(project(':lib:streamtape-extractor'))
|
||||
implementation(project(':lib:okru-extractor'))
|
||||
implementation(project(':lib:dood-extractor'))
|
||||
implementation(project(':lib:streamhidevid-extractor'))
|
||||
}
|
@ -13,9 +13,11 @@ import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
|
||||
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
|
||||
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
|
||||
import eu.kanade.tachiyomi.lib.streamhidevidextractor.StreamHideVidExtractor
|
||||
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
@ -90,35 +92,23 @@ class LocoPelis : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
override fun videoListParse(response: Response): List<Video> {
|
||||
val document = response.asJsoup()
|
||||
val videoList = mutableListOf<Video>()
|
||||
document.select(".tab_container .tab_content iframe").forEach { iframe ->
|
||||
val url = iframe.attr("src")
|
||||
val embedUrl = url.lowercase()
|
||||
if (embedUrl.contains("streamtape")) {
|
||||
val video = StreamTapeExtractor(client).videoFromUrl(url, "StreamTape")
|
||||
if (video != null) {
|
||||
videoList.add(video)
|
||||
return document.select(".tab_container .tab_content iframe").parallelCatchingFlatMapBlocking { iframe ->
|
||||
runCatching {
|
||||
val url = iframe.attr("src")
|
||||
with(url.lowercase()) {
|
||||
when {
|
||||
contains("streamtape") || contains("stp") || contains("stape")
|
||||
-> listOf(StreamTapeExtractor(client).videoFromUrl(this, quality = "StreamTape")!!)
|
||||
contains("doodstream") || contains("dood.") || contains("ds2play") || contains("doods.")
|
||||
-> listOf(DoodExtractor(client).videoFromUrl(this, "DoodStream", true)!!)
|
||||
contains("ok.ru") || contains("okru") -> OkruExtractor(client).videosFromUrl(this)
|
||||
contains("vidhide") || contains("streamhide") || contains("guccihide") || contains("streamvid")
|
||||
-> StreamHideVidExtractor(client).videosFromUrl(this)
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (embedUrl.contains("doodstream") ||
|
||||
embedUrl.contains("dood") ||
|
||||
embedUrl.contains("ds2play")
|
||||
) {
|
||||
val video = try {
|
||||
DoodExtractor(client).videoFromUrl(url, "DoodStream", true)
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
if (video != null) {
|
||||
videoList.add(video)
|
||||
}
|
||||
}
|
||||
if (embedUrl.contains("okru") || embedUrl.contains("ok.ru")) {
|
||||
val videos = OkruExtractor(client).videosFromUrl(url)
|
||||
videoList.addAll(videos)
|
||||
}
|
||||
}.getOrDefault(emptyList())
|
||||
}
|
||||
return videoList
|
||||
}
|
||||
|
||||
override fun videoListSelector() = throw UnsupportedOperationException()
|
||||
|
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'Pelisplushd'
|
||||
extClass = '.PelisplushdFactory'
|
||||
extVersionCode = 50
|
||||
extVersionCode = 51
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
@ -28,9 +28,7 @@ import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
||||
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
@ -38,7 +36,6 @@ import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
open class Pelisplushd(override val name: String, override val baseUrl: String) : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
|
||||
@ -46,8 +43,6 @@ open class Pelisplushd(override val name: String, override val baseUrl: String)
|
||||
|
||||
override val supportsLatest = false
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
}
|
||||
@ -111,161 +106,114 @@ open class Pelisplushd(override val name: String, override val baseUrl: String)
|
||||
val document = response.asJsoup()
|
||||
val videoList = mutableListOf<Video>()
|
||||
|
||||
val data = document.selectFirst("script:containsData(video[1] = )")!!.data()
|
||||
val apiUrl = data.substringAfter("video[1] = '", "").substringBefore("';", "")
|
||||
val data = document.selectFirst("script:containsData(video[1] = )")?.data()
|
||||
val apiUrl = data?.substringAfter("video[1] = '", "")?.substringBefore("';", "")
|
||||
val alternativeServers = document.select("ul.TbVideoNv.nav.nav-tabs li:not(:first-child)")
|
||||
if (apiUrl.isNotEmpty()) {
|
||||
if (!apiUrl.isNullOrEmpty()) {
|
||||
val apiResponse = client.newCall(GET(apiUrl)).execute().asJsoup()
|
||||
val encryptedList = apiResponse!!.select("#PlayerDisplay div[class*=\"OptionsLangDisp\"] div[class*=\"ODDIV\"] div[class*=\"OD\"] li")
|
||||
val regIsUrl = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)".toRegex()
|
||||
|
||||
encryptedList.forEach {
|
||||
val server = it.select("span").text()
|
||||
var url = it.attr("onclick")
|
||||
val encryptedList = apiResponse.select("#PlayerDisplay div[class*=\"OptionsLangDisp\"] div[class*=\"ODDIV\"] div[class*=\"OD\"] li")
|
||||
encryptedList.parallelCatchingFlatMapBlocking {
|
||||
val url = it.attr("onclick")
|
||||
.substringAfter("go_to_player('")
|
||||
.substringAfter("go_to_playerVast('")
|
||||
.substringBefore("?cover_url=")
|
||||
.substringBefore("')")
|
||||
.substringBefore("',")
|
||||
.substringBefore("?poster")
|
||||
.substringBefore("?c_poster=")
|
||||
.substringBefore("?thumb=")
|
||||
.substringBefore("#poster=")
|
||||
|
||||
if (!regIsUrl.containsMatchIn(url)) {
|
||||
url = String(Base64.decode(url, Base64.DEFAULT))
|
||||
val realUrl = if (!regIsUrl.containsMatchIn(url)) {
|
||||
String(Base64.decode(url, Base64.DEFAULT))
|
||||
} else if (url.contains("?data=")) {
|
||||
val apiPageSoup = client.newCall(GET(url)).execute().asJsoup()
|
||||
apiPageSoup.selectFirst("iframe")?.attr("src") ?: ""
|
||||
} else {
|
||||
url
|
||||
}
|
||||
|
||||
if (!url.contains("?data=")) {
|
||||
serverVideoResolver(url)?.forEach { video -> videoList.add(video) }
|
||||
} else {
|
||||
val apiPageSoup = client.newCall(GET(url)).execute().asJsoup()
|
||||
val realUrl = apiPageSoup.selectFirst("iframe")?.attr("src")
|
||||
if (realUrl != null) {
|
||||
serverVideoResolver(realUrl)?.forEach { video -> videoList.add(video) }
|
||||
}
|
||||
}
|
||||
}
|
||||
serverVideoResolver(realUrl)
|
||||
}.also(videoList::addAll)
|
||||
}
|
||||
|
||||
// verifier for old series
|
||||
if (!apiUrl.contains("/video/") || alternativeServers.any()) {
|
||||
document.select("ul.TbVideoNv.nav.nav-tabs li").forEach { id ->
|
||||
val serverName = id.select("a").text()
|
||||
if (!apiUrl.isNullOrEmpty() && !apiUrl.contains("/video/") || alternativeServers.any()) {
|
||||
document.select("ul.TbVideoNv.nav.nav-tabs li").parallelCatchingFlatMapBlocking { id ->
|
||||
val serverName = id.select("a").text().lowercase()
|
||||
val serverId = id.attr("data-id")
|
||||
var serverUrl = data.substringAfter("video[$serverId] = '", "").substringBefore("';", "")
|
||||
if (serverUrl.contains("api.mycdn.moe")) {
|
||||
var serverUrl = data?.substringAfter("video[$serverId] = '", "")?.substringBefore("';", "")
|
||||
if (serverUrl != null && serverUrl.contains("api.mycdn.moe")) {
|
||||
val urlId = serverUrl.substringAfter("id=")
|
||||
when (serverName.lowercase()) {
|
||||
"sbfast" -> { serverUrl = "https://sbfull.com/e/$urlId" }
|
||||
"plusto" -> { serverUrl = "https://owodeuwu.xyz/v/$urlId" }
|
||||
"doodstream" -> { serverUrl = "https://dood.to/e/$urlId" }
|
||||
"upload", "uqload" -> { serverUrl = "https://uqload.com/embed-$urlId.html" }
|
||||
serverUrl = when (serverName) {
|
||||
"sbfast" -> { "https://sbfull.com/e/$urlId" }
|
||||
"plusto" -> { "https://owodeuwu.xyz/v/$urlId" }
|
||||
"doodstream" -> { "https://dood.to/e/$urlId" }
|
||||
"upload", "uqload" -> { "https://uqload.com/embed-$urlId.html" }
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
serverVideoResolver(serverUrl)?.forEach { video -> videoList.add(video) }
|
||||
}
|
||||
|
||||
serverVideoResolver(serverUrl ?: "")
|
||||
}.also(videoList::addAll)
|
||||
}
|
||||
return videoList
|
||||
}
|
||||
|
||||
private fun serverVideoResolver(url: String): List<Video> {
|
||||
val videoList = mutableListOf<Video>()
|
||||
val embedUrl = url.lowercase()
|
||||
try {
|
||||
if (embedUrl.contains("voe")) {
|
||||
VoeExtractor(client).videosFromUrl(url).also(videoList::addAll)
|
||||
}
|
||||
if ((embedUrl.contains("amazon") || embedUrl.contains("amz")) && !embedUrl.contains("disable")) {
|
||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
||||
if (body.select("script:containsData(var shareId)").toString().isNotBlank()) {
|
||||
val shareId = body.selectFirst("script:containsData(var shareId)")!!.data()
|
||||
.substringAfter("shareId = \"").substringBefore("\"")
|
||||
val amazonApiJson = client.newCall(GET("https://www.amazon.com/drive/v1/shares/$shareId?resourceVersion=V2&ContentType=JSON&asset=ALL"))
|
||||
.execute().asJsoup()
|
||||
val epId = amazonApiJson.toString().substringAfter("\"id\":\"").substringBefore("\"")
|
||||
val amazonApi =
|
||||
client.newCall(GET("https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId"))
|
||||
.execute().asJsoup()
|
||||
val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":").substringAfter("tempLink\":\"").substringBefore("\"")
|
||||
videoList.add(Video(videoUrl, "Amazon", videoUrl))
|
||||
}
|
||||
}
|
||||
if (embedUrl.contains("ok.ru") || embedUrl.contains("okru")) {
|
||||
OkruExtractor(client).videosFromUrl(url).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("filemoon") || embedUrl.contains("moonplayer")) {
|
||||
val vidHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||
.build()
|
||||
FilemoonExtractor(client).videosFromUrl(url, prefix = "Filemoon:", headers = vidHeaders).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("uqload")) {
|
||||
UqloadExtractor(client).videosFromUrl(url).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("mp4upload")) {
|
||||
Mp4uploadExtractor(client).videosFromUrl(url, headers).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("wishembed") || embedUrl.contains("streamwish") || embedUrl.contains("strwish") || embedUrl.contains("wish")) {
|
||||
val docHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://streamwish.to")
|
||||
.add("Referer", "https://streamwish.to/")
|
||||
.build()
|
||||
StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "StreamWish:$it" }).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("doodstream") || embedUrl.contains("dood.")) {
|
||||
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
||||
DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)?.let { videoList.add(it) }
|
||||
}
|
||||
if (embedUrl.contains("streamlare")) {
|
||||
StreamlareExtractor(client).videosFromUrl(url).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("yourupload") || embedUrl.contains("upload")) {
|
||||
YourUploadExtractor(client).videoFromUrl(url, headers = headers).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("burstcloud") || embedUrl.contains("burst")) {
|
||||
BurstCloudExtractor(client).videoFromUrl(url, headers = headers).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("fastream")) {
|
||||
FastreamExtractor(client, headers).videosFromUrl(url).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("upstream")) {
|
||||
UpstreamExtractor(client).videosFromUrl(url).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("streamtape") || embedUrl.contains("stp") || embedUrl.contains("stape")) {
|
||||
StreamTapeExtractor(client).videoFromUrl(url)?.let { videoList.add(it) }
|
||||
}
|
||||
if (embedUrl.contains("ahvsh") || embedUrl.contains("streamhide")) {
|
||||
StreamHideExtractor(client).videosFromUrl(url, "StreamHide").let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("filelions") || embedUrl.contains("lion")) {
|
||||
StreamWishExtractor(client, headers).videosFromUrl(url, videoNameGen = { "FileLions:$it" }).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("tomatomatela")) {
|
||||
runCatching {
|
||||
val mainUrl = url.substringBefore("/embed.html#").substringAfter("https://")
|
||||
val headers = headers.newBuilder()
|
||||
.set("authority", mainUrl)
|
||||
.set("accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.set("accept-language", "es-MX,es-419;q=0.9,es;q=0.8,en;q=0.7")
|
||||
.set("sec-ch-ua", "\"Chromium\";v=\"106\", \"Google Chrome\";v=\"106\", \"Not;A=Brand\";v=\"99\"")
|
||||
.set("sec-ch-ua-mobile", "?0")
|
||||
.set("sec-ch-ua-platform", "Windows")
|
||||
.set("sec-fetch-dest", "empty")
|
||||
.set("sec-fetch-mode", "cors")
|
||||
.set("sec-fetch-site", "same-origin")
|
||||
.set("x-requested-with", "XMLHttpRequest")
|
||||
return runCatching {
|
||||
when {
|
||||
embedUrl.contains("voe") -> VoeExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("ok.ru") || embedUrl.contains("okru") -> OkruExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("filemoon") || embedUrl.contains("moonplayer") -> {
|
||||
val vidHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||
.build()
|
||||
val token = url.substringAfter("/embed.html#")
|
||||
val urlRequest = "https://$mainUrl/details.php?v=$token"
|
||||
val response = client.newCall(GET(urlRequest, headers = headers)).execute().asJsoup()
|
||||
val bodyText = response.select("body").text()
|
||||
val json = json.decodeFromString<JsonObject>(bodyText)
|
||||
val status = json["status"]!!.jsonPrimitive!!.content
|
||||
val file = json["file"]!!.jsonPrimitive!!.content
|
||||
if (status == "200") { videoList.add(Video(file, "Tomatomatela", file, headers = null)) }
|
||||
FilemoonExtractor(client).videosFromUrl(url, prefix = "Filemoon:", headers = vidHeaders)
|
||||
}
|
||||
!embedUrl.contains("disable") && (embedUrl.contains("amazon") || embedUrl.contains("amz")) -> {
|
||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
||||
return if (body.select("script:containsData(var shareId)").toString().isNotBlank()) {
|
||||
val shareId = body.selectFirst("script:containsData(var shareId)")!!.data()
|
||||
.substringAfter("shareId = \"").substringBefore("\"")
|
||||
val amazonApiJson = client.newCall(GET("https://www.amazon.com/drive/v1/shares/$shareId?resourceVersion=V2&ContentType=JSON&asset=ALL"))
|
||||
.execute().asJsoup()
|
||||
val epId = amazonApiJson.toString().substringAfter("\"id\":\"").substringBefore("\"")
|
||||
val amazonApi =
|
||||
client.newCall(GET("https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId"))
|
||||
.execute().asJsoup()
|
||||
val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":").substringAfter("tempLink\":\"").substringBefore("\"")
|
||||
listOf(Video(videoUrl, "Amazon", videoUrl))
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
embedUrl.contains("uqload") -> UqloadExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("mp4upload") -> Mp4uploadExtractor(client).videosFromUrl(url, headers)
|
||||
embedUrl.contains("wishembed") || embedUrl.contains("streamwish") || embedUrl.contains("strwish") || embedUrl.contains("wish") -> {
|
||||
val docHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://streamwish.to")
|
||||
.add("Referer", "https://streamwish.to/")
|
||||
.build()
|
||||
StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "StreamWish:$it" })
|
||||
}
|
||||
embedUrl.contains("doodstream") || embedUrl.contains("dood.") || embedUrl.contains("ds2play") || embedUrl.contains("doods.") -> {
|
||||
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
||||
listOf(DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)!!)
|
||||
}
|
||||
embedUrl.contains("streamlare") -> StreamlareExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("yourupload") || embedUrl.contains("upload") -> YourUploadExtractor(client).videoFromUrl(url, headers = headers)
|
||||
embedUrl.contains("burstcloud") || embedUrl.contains("burst") -> BurstCloudExtractor(client).videoFromUrl(url, headers = headers)
|
||||
embedUrl.contains("fastream") -> FastreamExtractor(client, headers).videosFromUrl(url, prefix = "Fastream:")
|
||||
embedUrl.contains("upstream") -> UpstreamExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("streamtape") || embedUrl.contains("stp") || embedUrl.contains("stape") -> listOf(StreamTapeExtractor(client).videoFromUrl(url, quality = "StreamTape")!!)
|
||||
embedUrl.contains("ahvsh") || embedUrl.contains("streamhide") || embedUrl.contains("guccihide") || embedUrl.contains("streamvid") -> StreamHideExtractor(client).videosFromUrl(url, "StreamHide")
|
||||
else -> emptyList()
|
||||
}
|
||||
} catch (_: Exception) { }
|
||||
return videoList
|
||||
}.getOrNull() ?: emptyList()
|
||||
}
|
||||
|
||||
override fun videoListSelector() = throw UnsupportedOperationException()
|
||||
|
@ -23,20 +23,15 @@ import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
||||
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class Pelisplusph(override val name: String, override val baseUrl: String) : Pelisplushd(name, baseUrl) {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
override val supportsLatest = false
|
||||
|
||||
companion object {
|
||||
@ -82,7 +77,8 @@ class Pelisplusph(override val name: String, override val baseUrl: String) : Pel
|
||||
anime.artist = p.select(".content-type ~ span").text().substringBefore(",")
|
||||
}
|
||||
}
|
||||
anime.status = if (document.location().contains("/serie/")) SAnime.UNKNOWN else SAnime.COMPLETED
|
||||
anime.status =
|
||||
if (document.location().contains("/serie/")) SAnime.UNKNOWN else SAnime.COMPLETED
|
||||
|
||||
return anime
|
||||
}
|
||||
@ -107,7 +103,9 @@ class Pelisplusph(override val name: String, override val baseUrl: String) : Pel
|
||||
index += 1
|
||||
val noEp = try {
|
||||
getNumberFromString(ep.ownText())
|
||||
} catch (_: Exception) { idx + 1 }
|
||||
} catch (_: Exception) {
|
||||
idx + 1
|
||||
}
|
||||
val episode = SEpisode.create().apply {
|
||||
episode_number = index.toFloat()
|
||||
name = "T$seasonNumber - E$noEp - ${ep.ownText()}"
|
||||
@ -132,118 +130,54 @@ class Pelisplusph(override val name: String, override val baseUrl: String) : Pel
|
||||
|
||||
override fun videoListParse(response: Response): List<Video> {
|
||||
val document = response.asJsoup()
|
||||
val videoList = mutableListOf<Video>()
|
||||
document.select("[class*=server-item-]").map {
|
||||
val langIdx = getNumberFromString(it.attr("class").substringAfter("server-item-"))
|
||||
return document.select("[class*=server-item-]").parallelCatchingFlatMapBlocking { serverItem ->
|
||||
val langIdx = getNumberFromString(serverItem.attr("class").substringAfter("server-item-"))
|
||||
val langItem = document.select("li[data-id=\"$langIdx\"] a").text()
|
||||
val lang = if (langItem.contains("Subtitulado")) "[SUB]" else if (langItem.contains("Latino")) "[LAT]" else "[CAST]"
|
||||
it.select("li.tab-video").map { servers ->
|
||||
val url = servers.attr("data-video")
|
||||
serverVideoResolver(url, lang).let { videos ->
|
||||
videoList.addAll(videos)
|
||||
}
|
||||
}
|
||||
|
||||
serverItem.select("li.tab-video").map { videoItem ->
|
||||
val url = videoItem.attr("data-video")
|
||||
serverVideoResolver(url, lang)
|
||||
}.flatten()
|
||||
}
|
||||
return videoList
|
||||
}
|
||||
|
||||
private fun serverVideoResolver(url: String, prefix: String = ""): List<Video> {
|
||||
val videoList = mutableListOf<Video>()
|
||||
val embedUrl = url.lowercase()
|
||||
try {
|
||||
if (embedUrl.contains("voe")) {
|
||||
VoeExtractor(client).videosFromUrl(url, prefix).also(videoList::addAll)
|
||||
}
|
||||
if ((embedUrl.contains("amazon") || embedUrl.contains("amz")) && !embedUrl.contains("disable")) {
|
||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
||||
if (body.select("script:containsData(var shareId)").toString().isNotBlank()) {
|
||||
val shareId = body.selectFirst("script:containsData(var shareId)")!!.data()
|
||||
.substringAfter("shareId = \"").substringBefore("\"")
|
||||
val amazonApiJson = client.newCall(GET("https://www.amazon.com/drive/v1/shares/$shareId?resourceVersion=V2&ContentType=JSON&asset=ALL"))
|
||||
.execute().asJsoup()
|
||||
val epId = amazonApiJson.toString().substringAfter("\"id\":\"").substringBefore("\"")
|
||||
val amazonApi =
|
||||
client.newCall(GET("https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId"))
|
||||
.execute().asJsoup()
|
||||
val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":").substringAfter("tempLink\":\"").substringBefore("\"")
|
||||
videoList.add(Video(videoUrl, "$prefix Amazon", videoUrl))
|
||||
}
|
||||
}
|
||||
if (embedUrl.contains("ok.ru") || embedUrl.contains("okru")) {
|
||||
OkruExtractor(client).videosFromUrl(url, prefix).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("filemoon") || embedUrl.contains("moonplayer")) {
|
||||
val vidHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||
.build()
|
||||
FilemoonExtractor(client).videosFromUrl(url, prefix = "$prefix Filemoon:", headers = vidHeaders).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("uqload")) {
|
||||
UqloadExtractor(client).videosFromUrl(url, prefix = prefix).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("mp4upload")) {
|
||||
Mp4uploadExtractor(client).videosFromUrl(url, headers, prefix = prefix).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("wishembed") || embedUrl.contains("streamwish") || embedUrl.contains("strwish") || embedUrl.contains("wish")) {
|
||||
val docHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://streamwish.to")
|
||||
.add("Referer", "https://streamwish.to/")
|
||||
.build()
|
||||
StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "$prefix StreamWish:$it" }).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("doodstream") || embedUrl.contains("dood.")) {
|
||||
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
||||
DoodExtractor(client).videoFromUrl(url2, "$prefix DoodStream", false)?.let { videoList.add(it) }
|
||||
}
|
||||
if (embedUrl.contains("streamlare")) {
|
||||
StreamlareExtractor(client).videosFromUrl(url, prefix = prefix).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("yourupload") || embedUrl.contains("upload")) {
|
||||
YourUploadExtractor(client).videoFromUrl(url, headers = headers, prefix = prefix).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("burstcloud") || embedUrl.contains("burst")) {
|
||||
BurstCloudExtractor(client).videoFromUrl(url, headers = headers, prefix = prefix).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("fastream")) {
|
||||
FastreamExtractor(client, headers).videosFromUrl(url, prefix = "$prefix Fastream:").also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("upstream")) {
|
||||
UpstreamExtractor(client).videosFromUrl(url, prefix = prefix).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("streamtape") || embedUrl.contains("stp") || embedUrl.contains("stape")) {
|
||||
StreamTapeExtractor(client).videoFromUrl(url, quality = "$prefix StreamTape")?.let { videoList.add(it) }
|
||||
}
|
||||
if (embedUrl.contains("ahvsh") || embedUrl.contains("streamhide")) {
|
||||
StreamHideExtractor(client).videosFromUrl(url, "$prefix StreamHide").let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("tomatomatela")) {
|
||||
runCatching {
|
||||
val mainUrl = url.substringBefore("/embed.html#").substringAfter("https://")
|
||||
val headers = headers.newBuilder()
|
||||
.set("authority", mainUrl)
|
||||
.set("accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.set("accept-language", "es-MX,es-419;q=0.9,es;q=0.8,en;q=0.7")
|
||||
.set("sec-ch-ua", "\"Chromium\";v=\"106\", \"Google Chrome\";v=\"106\", \"Not;A=Brand\";v=\"99\"")
|
||||
.set("sec-ch-ua-mobile", "?0")
|
||||
.set("sec-ch-ua-platform", "Windows")
|
||||
.set("sec-fetch-dest", "empty")
|
||||
.set("sec-fetch-mode", "cors")
|
||||
.set("sec-fetch-site", "same-origin")
|
||||
.set("x-requested-with", "XMLHttpRequest")
|
||||
return runCatching {
|
||||
when {
|
||||
embedUrl.contains("voe") -> VoeExtractor(client).videosFromUrl(url, prefix)
|
||||
embedUrl.contains("ok.ru") || embedUrl.contains("okru") -> OkruExtractor(client).videosFromUrl(url, prefix)
|
||||
embedUrl.contains("filemoon") || embedUrl.contains("moonplayer") -> {
|
||||
val vidHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||
.build()
|
||||
val token = url.substringAfter("/embed.html#")
|
||||
val urlRequest = "https://$mainUrl/details.php?v=$token"
|
||||
val response = client.newCall(GET(urlRequest, headers = headers)).execute().asJsoup()
|
||||
val bodyText = response.select("body").text()
|
||||
val json = json.decodeFromString<JsonObject>(bodyText)
|
||||
val status = json["status"]!!.jsonPrimitive!!.content
|
||||
val file = json["file"]!!.jsonPrimitive!!.content
|
||||
if (status == "200") { videoList.add(Video(file, "$prefix Tomatomatela", file, headers = null)) }
|
||||
FilemoonExtractor(client).videosFromUrl(url, prefix = "$prefix Filemoon:", headers = vidHeaders)
|
||||
}
|
||||
embedUrl.contains("uqload") -> UqloadExtractor(client).videosFromUrl(url, prefix = prefix)
|
||||
embedUrl.contains("mp4upload") -> Mp4uploadExtractor(client).videosFromUrl(url, headers, prefix = prefix)
|
||||
embedUrl.contains("wishembed") || embedUrl.contains("streamwish") || embedUrl.contains("strwish") || embedUrl.contains("wish") -> {
|
||||
val docHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://streamwish.to")
|
||||
.add("Referer", "https://streamwish.to/")
|
||||
.build()
|
||||
StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "$prefix StreamWish:$it" })
|
||||
}
|
||||
embedUrl.contains("doodstream") || embedUrl.contains("dood.") || embedUrl.contains("ds2play") || embedUrl.contains("doods.") -> {
|
||||
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
||||
listOf(DoodExtractor(client).videoFromUrl(url2, "$prefix DoodStream", false)!!)
|
||||
}
|
||||
embedUrl.contains("streamlare") -> StreamlareExtractor(client).videosFromUrl(url, prefix = prefix)
|
||||
embedUrl.contains("yourupload") || embedUrl.contains("upload") -> YourUploadExtractor(client).videoFromUrl(url, headers = headers, prefix = prefix)
|
||||
embedUrl.contains("burstcloud") || embedUrl.contains("burst") -> BurstCloudExtractor(client).videoFromUrl(url, headers = headers, prefix = prefix)
|
||||
embedUrl.contains("fastream") -> FastreamExtractor(client, headers).videosFromUrl(url, prefix = "$prefix Fastream:")
|
||||
embedUrl.contains("upstream") -> UpstreamExtractor(client).videosFromUrl(url, prefix = prefix)
|
||||
embedUrl.contains("streamtape") || embedUrl.contains("stp") || embedUrl.contains("stape") -> listOf(StreamTapeExtractor(client).videoFromUrl(url, quality = "$prefix StreamTape")!!)
|
||||
embedUrl.contains("ahvsh") || embedUrl.contains("streamhide") || embedUrl.contains("guccihide") || embedUrl.contains("streamvid") -> StreamHideExtractor(client).videosFromUrl(url, "$prefix StreamHide")
|
||||
else -> emptyList()
|
||||
}
|
||||
} catch (_: Exception) { }
|
||||
return videoList
|
||||
}.getOrNull() ?: emptyList()
|
||||
}
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
|
@ -21,10 +21,10 @@ import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
|
||||
import eu.kanade.tachiyomi.lib.upstreamextractor.UpstreamExtractor
|
||||
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
|
||||
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
||||
import eu.kanade.tachiyomi.lib.vudeoextractor.VudeoExtractor
|
||||
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
@ -120,7 +120,7 @@ class Pelisplusto(override val name: String, override val baseUrl: String) : Pel
|
||||
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
||||
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
|
||||
return when {
|
||||
query.isNotBlank() -> GET("$baseUrl/api/search?search=$query", headers)
|
||||
query.isNotBlank() -> GET("$baseUrl/api/search/$query", headers)
|
||||
genreFilter.state != 0 -> GET("$baseUrl/${genreFilter.toUriPart()}?page=$page")
|
||||
else -> popularAnimeRequest(page)
|
||||
}
|
||||
@ -134,30 +134,24 @@ class Pelisplusto(override val name: String, override val baseUrl: String) : Pel
|
||||
|
||||
override fun videoListParse(response: Response): List<Video> {
|
||||
val document = response.asJsoup()
|
||||
val videoList = mutableListOf<Video>()
|
||||
document.select(".bg-tabs ul li").map { it ->
|
||||
val url = String(Base64.decode(it.attr("data-server"), Base64.DEFAULT))
|
||||
if (url.contains("/player/")) {
|
||||
try {
|
||||
val script = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(window.onload)")!!.data()
|
||||
fetchUrls(script).map {
|
||||
val link = it.replace("https://sblanh.com", "https://lvturbo.com")
|
||||
.replace(Regex("([a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)=https:\\/\\/ww3.pelisplus.to.*"), "")
|
||||
serverVideoResolver(link).let { videos ->
|
||||
videoList.addAll(videos)
|
||||
}
|
||||
}
|
||||
} catch (_: Exception) {}
|
||||
} else {
|
||||
val link = url.replace("https://sblanh.com", "https://lvturbo.com")
|
||||
.replace(Regex("([a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)=https:\\/\\/ww3.pelisplus.to.*"), "")
|
||||
val regIsUrl = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)".toRegex()
|
||||
return document.select(".bg-tabs ul li").parallelCatchingFlatMapBlocking {
|
||||
val decode = String(Base64.decode(it.attr("data-server"), Base64.DEFAULT))
|
||||
|
||||
serverVideoResolver(link).let { videos ->
|
||||
videoList.addAll(videos)
|
||||
}
|
||||
}
|
||||
val url = if (!regIsUrl.containsMatchIn(decode)) {
|
||||
"$baseUrl/player/${String(Base64.encode(it.attr("data-server").toByteArray(), Base64.DEFAULT))}"
|
||||
} else { decode }
|
||||
|
||||
val videoUrl = if (url.contains("/player/")) {
|
||||
val script = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(window.onload)")?.data() ?: ""
|
||||
fetchUrls(script).firstOrNull() ?: ""
|
||||
} else {
|
||||
url
|
||||
}.replace("https://sblanh.com", "https://lvturbo.com")
|
||||
.replace(Regex("([a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)=https:\\/\\/ww3.pelisplus.to.*"), "")
|
||||
|
||||
serverVideoResolver(videoUrl)
|
||||
}
|
||||
return videoList
|
||||
}
|
||||
|
||||
override fun List<Video>.sort(): List<Video> {
|
||||
@ -173,105 +167,58 @@ class Pelisplusto(override val name: String, override val baseUrl: String) : Pel
|
||||
}
|
||||
|
||||
private fun serverVideoResolver(url: String): List<Video> {
|
||||
val videoList = mutableListOf<Video>()
|
||||
val embedUrl = url.lowercase()
|
||||
try {
|
||||
if (embedUrl.contains("voe")) {
|
||||
VoeExtractor(client).videosFromUrl(url).also(videoList::addAll)
|
||||
}
|
||||
if ((embedUrl.contains("amazon") || embedUrl.contains("amz")) && !embedUrl.contains("disable")) {
|
||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
||||
if (body.select("script:containsData(var shareId)").toString().isNotBlank()) {
|
||||
val shareId = body.selectFirst("script:containsData(var shareId)")!!.data()
|
||||
.substringAfter("shareId = \"").substringBefore("\"")
|
||||
val amazonApiJson = client.newCall(GET("https://www.amazon.com/drive/v1/shares/$shareId?resourceVersion=V2&ContentType=JSON&asset=ALL"))
|
||||
.execute().asJsoup()
|
||||
val epId = amazonApiJson.toString().substringAfter("\"id\":\"").substringBefore("\"")
|
||||
val amazonApi =
|
||||
client.newCall(GET("https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId"))
|
||||
.execute().asJsoup()
|
||||
val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":").substringAfter("tempLink\":\"").substringBefore("\"")
|
||||
videoList.add(Video(videoUrl, "Amazon", videoUrl))
|
||||
}
|
||||
}
|
||||
if (embedUrl.contains("ok.ru") || embedUrl.contains("okru")) {
|
||||
OkruExtractor(client).videosFromUrl(url).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("filemoon") || embedUrl.contains("moonplayer")) {
|
||||
val vidHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||
.build()
|
||||
FilemoonExtractor(client).videosFromUrl(url, prefix = "Filemoon:", headers = vidHeaders).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("uqload")) {
|
||||
UqloadExtractor(client).videosFromUrl(url).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("mp4upload")) {
|
||||
Mp4uploadExtractor(client).videosFromUrl(url, headers).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("wishembed") || embedUrl.contains("streamwish") || embedUrl.contains("strwish") || embedUrl.contains("wish")) {
|
||||
val docHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://streamwish.to")
|
||||
.add("Referer", "https://streamwish.to/")
|
||||
.build()
|
||||
StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "StreamWish:$it" }).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("doodstream") || embedUrl.contains("dood.")) {
|
||||
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
||||
DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)?.let { videoList.add(it) }
|
||||
}
|
||||
if (embedUrl.contains("streamlare")) {
|
||||
StreamlareExtractor(client).videosFromUrl(url).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("yourupload") || embedUrl.contains("upload")) {
|
||||
YourUploadExtractor(client).videoFromUrl(url, headers = headers).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("burstcloud") || embedUrl.contains("burst")) {
|
||||
BurstCloudExtractor(client).videoFromUrl(url, headers = headers).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("fastream")) {
|
||||
FastreamExtractor(client, headers).videosFromUrl(url).also(videoList::addAll)
|
||||
}
|
||||
if (embedUrl.contains("upstream")) {
|
||||
UpstreamExtractor(client).videosFromUrl(url).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("streamtape") || embedUrl.contains("stp") || embedUrl.contains("stape")) {
|
||||
StreamTapeExtractor(client).videoFromUrl(url)?.let { videoList.add(it) }
|
||||
}
|
||||
if (embedUrl.contains("ahvsh") || embedUrl.contains("streamhide")) {
|
||||
StreamHideExtractor(client).videosFromUrl(url, "StreamHide").let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("vudeo") || embedUrl.contains("vudea")) {
|
||||
VudeoExtractor(client).videosFromUrl(url).let { videoList.addAll(it) }
|
||||
}
|
||||
if (embedUrl.contains("tomatomatela")) {
|
||||
runCatching {
|
||||
val mainUrl = url.substringBefore("/embed.html#").substringAfter("https://")
|
||||
val headers = headers.newBuilder()
|
||||
.set("authority", mainUrl)
|
||||
.set("accept", "application/json, text/javascript, */*; q=0.01")
|
||||
.set("accept-language", "es-MX,es-419;q=0.9,es;q=0.8,en;q=0.7")
|
||||
.set("sec-ch-ua", "\"Chromium\";v=\"106\", \"Google Chrome\";v=\"106\", \"Not;A=Brand\";v=\"99\"")
|
||||
.set("sec-ch-ua-mobile", "?0")
|
||||
.set("sec-ch-ua-platform", "Windows")
|
||||
.set("sec-fetch-dest", "empty")
|
||||
.set("sec-fetch-mode", "cors")
|
||||
.set("sec-fetch-site", "same-origin")
|
||||
.set("x-requested-with", "XMLHttpRequest")
|
||||
return runCatching {
|
||||
when {
|
||||
embedUrl.contains("voe") -> VoeExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("ok.ru") || embedUrl.contains("okru") -> OkruExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("filemoon") || embedUrl.contains("moonplayer") -> {
|
||||
val vidHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||
.build()
|
||||
val token = url.substringAfter("/embed.html#")
|
||||
val urlRequest = "https://$mainUrl/details.php?v=$token"
|
||||
val response = client.newCall(GET(urlRequest, headers = headers)).execute().asJsoup()
|
||||
val bodyText = response.select("body").text()
|
||||
val json = json.decodeFromString<JsonObject>(bodyText)
|
||||
val status = json["status"]!!.jsonPrimitive!!.content
|
||||
val file = json["file"]!!.jsonPrimitive!!.content
|
||||
if (status == "200") { videoList.add(Video(file, "Tomatomatela", file, headers = null)) }
|
||||
FilemoonExtractor(client).videosFromUrl(url, prefix = "Filemoon:", headers = vidHeaders)
|
||||
}
|
||||
!embedUrl.contains("disable") && (embedUrl.contains("amazon") || embedUrl.contains("amz")) -> {
|
||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
||||
return if (body.select("script:containsData(var shareId)").toString().isNotBlank()) {
|
||||
val shareId = body.selectFirst("script:containsData(var shareId)")!!.data()
|
||||
.substringAfter("shareId = \"").substringBefore("\"")
|
||||
val amazonApiJson = client.newCall(GET("https://www.amazon.com/drive/v1/shares/$shareId?resourceVersion=V2&ContentType=JSON&asset=ALL"))
|
||||
.execute().asJsoup()
|
||||
val epId = amazonApiJson.toString().substringAfter("\"id\":\"").substringBefore("\"")
|
||||
val amazonApi =
|
||||
client.newCall(GET("https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId"))
|
||||
.execute().asJsoup()
|
||||
val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":").substringAfter("tempLink\":\"").substringBefore("\"")
|
||||
listOf(Video(videoUrl, "Amazon", videoUrl))
|
||||
} else {
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
embedUrl.contains("uqload") -> UqloadExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("mp4upload") -> Mp4uploadExtractor(client).videosFromUrl(url, headers)
|
||||
embedUrl.contains("wishembed") || embedUrl.contains("streamwish") || embedUrl.contains("strwish") || embedUrl.contains("wish") -> {
|
||||
val docHeaders = headers.newBuilder()
|
||||
.add("Origin", "https://streamwish.to")
|
||||
.add("Referer", "https://streamwish.to/")
|
||||
.build()
|
||||
StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "StreamWish:$it" })
|
||||
}
|
||||
embedUrl.contains("doodstream") || embedUrl.contains("dood.") || embedUrl.contains("ds2play") || embedUrl.contains("doods.") -> {
|
||||
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
||||
listOf(DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)!!)
|
||||
}
|
||||
embedUrl.contains("streamlare") -> StreamlareExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("yourupload") || embedUrl.contains("upload") -> YourUploadExtractor(client).videoFromUrl(url, headers = headers)
|
||||
embedUrl.contains("burstcloud") || embedUrl.contains("burst") -> BurstCloudExtractor(client).videoFromUrl(url, headers = headers)
|
||||
embedUrl.contains("fastream") -> FastreamExtractor(client, headers).videosFromUrl(url, prefix = "Fastream:")
|
||||
embedUrl.contains("upstream") -> UpstreamExtractor(client).videosFromUrl(url)
|
||||
embedUrl.contains("streamtape") || embedUrl.contains("stp") || embedUrl.contains("stape") -> listOf(StreamTapeExtractor(client).videoFromUrl(url, quality = "StreamTape")!!)
|
||||
embedUrl.contains("ahvsh") || embedUrl.contains("streamhide") || embedUrl.contains("guccihide") || embedUrl.contains("streamvid") -> StreamHideExtractor(client).videosFromUrl(url, "StreamHide")
|
||||
else -> emptyList()
|
||||
}
|
||||
} catch (_: Exception) { }
|
||||
return videoList
|
||||
}.getOrNull() ?: emptyList()
|
||||
}
|
||||
|
||||
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
||||
|
Loading…
x
Reference in New Issue
Block a user