fix(src/es): Some fixes for Spanish extensions (#2980)
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
ext {
|
ext {
|
||||||
extName = 'Doramasflix'
|
extName = 'Doramasflix'
|
||||||
extClass = '.Doramasflix'
|
extClass = '.Doramasflix'
|
||||||
extVersionCode = 16
|
extVersionCode = 17
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
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.app.Application
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.util.Base64
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
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.AnimeFilterList
|
||||||
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
import eu.kanade.tachiyomi.animesource.model.AnimesPage
|
||||||
import eu.kanade.tachiyomi.animesource.model.SAnime
|
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.upstreamextractor.UpstreamExtractor
|
||||||
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
|
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
|
||||||
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
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.lib.youruploadextractor.YourUploadExtractor
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
import eu.kanade.tachiyomi.network.POST
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
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.Json
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.jsonArray
|
import kotlinx.serialization.json.jsonArray
|
||||||
@ -43,6 +46,8 @@ import okhttp3.Response
|
|||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
||||||
|
|
||||||
@ -86,6 +91,10 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
"Fastream", "Filemoon", "StreamWish", "Okru", "Streamlare",
|
"Fastream", "Filemoon", "StreamWish", "Okru", "Streamlare",
|
||||||
"Uqload",
|
"Uqload",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val DATE_FORMATTER by lazy {
|
||||||
|
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
private val preferences: SharedPreferences by lazy {
|
||||||
@ -121,7 +130,8 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
document.select("script").map { el ->
|
document.select("script").map { el ->
|
||||||
if (el.data().contains("{\"props\":{\"pageProps\":{")) {
|
if (el.data().contains("{\"props\":{\"pageProps\":{")) {
|
||||||
val apolloState = json.decodeFromString<JsonObject>(el.data())!!.jsonObject["props"]!!.jsonObject["pageProps"]!!.jsonObject["apolloState"]!!.jsonObject
|
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 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 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) { "" }
|
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> {
|
override fun episodeListParse(response: Response): List<SEpisode> {
|
||||||
val episodes = mutableListOf<SEpisode>()
|
return if (response.request.url.toString().contains("peliculas-online")) {
|
||||||
if (response.request.url.toString().contains("peliculas-online")) {
|
listOf(
|
||||||
val episode = SEpisode.create()
|
SEpisode.create().apply {
|
||||||
episode.episode_number = 1F
|
episode_number = 1F
|
||||||
episode.name = "Película"
|
name = "Película"
|
||||||
episode.setUrlWithoutDomain(response.request.url.toString())
|
setUrlWithoutDomain(response.request.url.toString())
|
||||||
episodes.add(episode)
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
val jsonEpisodes = mutableListOf<String>()
|
|
||||||
val id = response.request.url.toString().substringAfter("?id=")
|
val id = response.request.url.toString().substringAfter("?id=")
|
||||||
val responseString = response.body.string()
|
val responseString = response.body.string()
|
||||||
val data = json.decodeFromString<JsonObject>(responseString)!!.jsonObject["data"]!!.jsonObject
|
val data = json.decodeFromString<SeasonModel>(responseString).data
|
||||||
data["listSeasons"]!!.jsonArray.forEach {
|
|
||||||
val season = it.jsonObject["season_number"]!!.jsonPrimitive.content
|
data.listSeasons.parallelCatchingFlatMapBlocking {
|
||||||
|
val season = it.seasonNumber
|
||||||
val body = (
|
val body = (
|
||||||
"{\"operationName\":\"listEpisodes\",\"variables\":{\"serie_id\":\"$id\",\"season_number\":$season},\"query\":\"query " +
|
"{\"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\\\", " +
|
"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: \$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\"}"
|
"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)
|
).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)) }
|
}.reversed()
|
||||||
}
|
|
||||||
return episodes.reversed()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseEpisodeListJson(jsonLine: String?): List<SEpisode> {
|
private fun parseEpisodeListJson(episodes: EpisodeModel): List<SEpisode> {
|
||||||
val jsonData = jsonLine ?: return emptyList()
|
var isUpcoming = false
|
||||||
val episodes = mutableListOf<SEpisode>()
|
val currentDate = Date().time
|
||||||
val data = json.decodeFromString<JsonObject>(jsonData)!!.jsonObject["data"]!!.jsonObject
|
return episodes.data.listEpisodes.mapIndexed { idx, episodeObject ->
|
||||||
data["listEpisodes"]!!.jsonArray!!.map {
|
val dateEp = episodeObject.airDate
|
||||||
val noSeason = it.jsonObject["season_number"]!!.jsonPrimitive!!.content
|
val nameEp = if (episodeObject.name.isNullOrEmpty()) "- Capítulo ${episodeObject.episodeNumber}" else "- ${episodeObject.name}"
|
||||||
val noEpisode = it.jsonObject["episode_number"]!!.jsonPrimitive!!.content
|
if (dateEp != null && dateEp.toDate() > currentDate && !isUpcoming) isUpcoming = true
|
||||||
var nameEp = it.jsonObject["name"]!!.jsonPrimitive!!.content
|
|
||||||
nameEp = if (nameEp == "null") "- Capítulo $noEpisode" else "- $nameEp"
|
SEpisode.create().apply {
|
||||||
val slug = it.jsonObject["slug"]!!.jsonPrimitive!!.content
|
name = "T${episodeObject.seasonNumber} - E${episodeObject.episodeNumber} $nameEp"
|
||||||
val episode = SEpisode.create()
|
episode_number = episodeObject.episodeNumber?.toFloat() ?: idx.toFloat()
|
||||||
episode.name = "T$noSeason - E$noEpisode $nameEp"
|
date_upload = dateEp?.toDate() ?: 0L
|
||||||
episode.episode_number = noEpisode.toFloat()
|
scanlator = if (isUpcoming) "Próximamente..." else null
|
||||||
episode.setUrlWithoutDomain(urlSolverByType("episode", slug))
|
setUrlWithoutDomain(urlSolverByType("episode", episodeObject.slug))
|
||||||
episodes.add(episode)
|
}
|
||||||
}
|
}
|
||||||
return episodes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response): AnimesPage {
|
override fun latestUpdatesParse(response: Response): AnimesPage {
|
||||||
val responseString = response.body.string()
|
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 {
|
override fun latestUpdatesRequest(page: Int): Request {
|
||||||
@ -226,7 +241,10 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
|
|
||||||
override fun popularAnimeParse(response: Response): AnimesPage {
|
override fun popularAnimeParse(response: Response): AnimesPage {
|
||||||
val responseString = response.body.string()
|
val responseString = response.body.string()
|
||||||
return parsePopularAnimeJson(responseString)
|
return when {
|
||||||
|
responseString.contains("paginationMovie") -> parsePopularJson(responseString, "movie")
|
||||||
|
else -> parsePopularJson(responseString, "dorama")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val languages = arrayOf(
|
private val languages = arrayOf(
|
||||||
@ -248,26 +266,33 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
return languages.firstOrNull { it.first == this }?.second ?: ""
|
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 jsonData = jsonLine ?: return AnimesPage(emptyList(), false)
|
||||||
val animeList = mutableListOf<SAnime>()
|
val data = json.decodeFromString<PaginationModel>(jsonData).data
|
||||||
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 }
|
|
||||||
|
|
||||||
anime.title = "${it.jsonObject!!["name"]!!.jsonPrimitive!!.content} (${it.jsonObject!!["name_es"]!!.jsonPrimitive!!.content})"
|
val pagination = when (type) {
|
||||||
anime.description = it.jsonObject!!["overview"]!!.jsonPrimitive!!.content
|
"dorama" -> data.paginationDorama
|
||||||
anime.genre = genres
|
"movie" -> data.paginationMovie
|
||||||
anime.thumbnail_url = externalOrInternalImg(urlImg, true)
|
else -> throw IllegalArgumentException("Tipo de dato no válido: $type")
|
||||||
anime.setUrlWithoutDomain(urlSolverByType(it.jsonObject!!["__typename"]!!.jsonPrimitive!!.content, it.jsonObject!!["slug"]!!.jsonPrimitive!!.content, id))
|
|
||||||
animeList.add(anime)
|
|
||||||
}
|
}
|
||||||
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 {
|
private fun urlSolverByType(type: String, slug: String, id: String? = ""): String {
|
||||||
@ -296,45 +321,45 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
|
|
||||||
override fun searchAnimeParse(response: Response): AnimesPage {
|
override fun searchAnimeParse(response: Response): AnimesPage {
|
||||||
val responseString = response.body.string()
|
val responseString = response.body.string()
|
||||||
return if (responseString.contains("searchDorama")) {
|
return when {
|
||||||
parseSearchAnimeJson(responseString)
|
responseString.contains("searchDorama") -> parseSearchAnimeJson(responseString)
|
||||||
} else {
|
responseString.contains("paginationMovie") -> parsePopularJson(responseString, "movie")
|
||||||
parsePopularAnimeJson(responseString)
|
else -> parsePopularJson(responseString, "dorama")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseSearchAnimeJson(jsonLine: String?): AnimesPage {
|
private fun parseSearchAnimeJson(jsonLine: String?): AnimesPage {
|
||||||
val jsonData = jsonLine ?: return AnimesPage(emptyList(), false)
|
val jsonData = jsonLine ?: return AnimesPage(emptyList(), false)
|
||||||
|
val jsonObject = json.decodeFromString<SearchModel>(jsonData).data
|
||||||
|
|
||||||
val animeList = mutableListOf<SAnime>()
|
val animeList = mutableListOf<SAnime>()
|
||||||
val paginationDorama = json.decodeFromString<JsonObject>(jsonData)!!.jsonObject["data"]!!.jsonObject
|
jsonObject.searchDorama.map { castToSAnime(it) }.also(animeList::addAll)
|
||||||
paginationDorama["searchDorama"]!!.jsonArray.map {
|
jsonObject.searchMovie.map { castToSAnime(it) }.also(animeList::addAll)
|
||||||
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)
|
|
||||||
}
|
|
||||||
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)
|
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 {
|
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 {
|
return when {
|
||||||
query.isNotBlank() -> searchQueryRequest(query)
|
query.isNotBlank() -> searchQueryRequest(query)
|
||||||
|
"peliculas" in genreFilter.toUriPart() -> popularMovieRequest(page)
|
||||||
|
"variedades" in genreFilter.toUriPart() -> popularVarietiesRequest(page)
|
||||||
else -> popularAnimeRequest(page)
|
else -> popularAnimeRequest(page)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -350,123 +375,148 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
return POST(apiUrl, popularRequestHeaders, body)
|
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> {
|
override fun videoListParse(response: Response): List<Video> {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
val videoList = mutableListOf<Video>()
|
|
||||||
val jsonData = document.selectFirst("script:containsData({\"props\":{\"pageProps\":{)")!!.data()
|
val jsonData = document.selectFirst("script:containsData({\"props\":{\"pageProps\":{)")!!.data()
|
||||||
val apolloState = json.decodeFromString<JsonObject>(jsonData).jsonObject["props"]!!.jsonObject["pageProps"]!!.jsonObject["apolloState"]!!.jsonObject
|
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 link = it.jsonObject["link"]!!.jsonPrimitive.content
|
||||||
val lang = it.jsonObject["lang"]?.jsonPrimitive?.content?.getLang() ?: ""
|
val lang = it.jsonObject["lang"]?.jsonPrimitive?.content?.getLang() ?: ""
|
||||||
serverVideoResolver(link, lang).also(videoList::addAll)
|
serverVideoResolver(link, lang)
|
||||||
}
|
} ?: apolloState.entries.filter { x -> x.key.contains("ROOT_QUERY.listProblems(") }
|
||||||
return videoList
|
.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> {
|
private fun serverVideoResolver(url: String, prefix: String = ""): List<Video> {
|
||||||
val videoList = mutableListOf<Video>()
|
|
||||||
val embedUrl = url.lowercase()
|
val embedUrl = url.lowercase()
|
||||||
try {
|
return when {
|
||||||
if (embedUrl.contains("voe")) {
|
"voe" in embedUrl -> VoeExtractor(client).videosFromUrl(url, " $prefix")
|
||||||
VoeExtractor(client).videosFromUrl(url, prefix).also(videoList::addAll)
|
"ok.ru" in embedUrl || "okru" in embedUrl -> OkruExtractor(client).videosFromUrl(url, prefix = "$prefix ")
|
||||||
}
|
"filemoon" in embedUrl || "moonplayer" in embedUrl -> {
|
||||||
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")) {
|
|
||||||
val vidHeaders = headers.newBuilder()
|
val vidHeaders = headers.newBuilder()
|
||||||
.add("Origin", "https://${url.toHttpUrl().host}")
|
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||||
.add("Referer", "https://${url.toHttpUrl().host}/")
|
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||||
.build()
|
.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")) {
|
"uqload" in embedUrl -> UqloadExtractor(client).videosFromUrl(url, prefix = prefix)
|
||||||
UqloadExtractor(client).videosFromUrl(url, prefix = prefix).also(videoList::addAll)
|
"mp4upload" in embedUrl -> Mp4uploadExtractor(client).videosFromUrl(url, prefix = "$prefix ", headers = headers)
|
||||||
}
|
"doodstream" in embedUrl || "dood." in embedUrl ->
|
||||||
if (embedUrl.contains("mp4upload")) {
|
listOf(DoodExtractor(client).videoFromUrl(url.replace("https://doodstream.com/e/", "https://dood.to/e/"), "$prefix DoodStream", false)!!)
|
||||||
Mp4uploadExtractor(client).videosFromUrl(url, prefix = "$prefix ", headers = headers).let { videoList.addAll(it) }
|
"streamlare" in embedUrl -> StreamlareExtractor(client).videosFromUrl(url, prefix = prefix)
|
||||||
}
|
"yourupload" in embedUrl || "upload" in embedUrl -> YourUploadExtractor(client).videoFromUrl(url, headers = headers, prefix = "$prefix ")
|
||||||
if (embedUrl.contains("wishembed") || embedUrl.contains("streamwish") || embedUrl.contains("strwish") || embedUrl.contains("wish")) {
|
"wishembed" in embedUrl || "streamwish" in embedUrl || "strwish" in embedUrl || "wish" in embedUrl -> {
|
||||||
val docHeaders = headers.newBuilder()
|
val docHeaders = headers.newBuilder()
|
||||||
.add("Origin", "https://streamwish.to")
|
.add("Origin", "https://streamwish.to")
|
||||||
.add("Referer", "https://streamwish.to/")
|
.add("Referer", "https://streamwish.to/")
|
||||||
.build()
|
.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.")) {
|
"burstcloud" in embedUrl || "burst" in embedUrl -> BurstCloudExtractor(client).videoFromUrl(url, headers = headers, prefix = "$prefix ")
|
||||||
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
"fastream" in embedUrl -> FastreamExtractor(client, headers).videosFromUrl(url, prefix = "$prefix Fastream:")
|
||||||
DoodExtractor(client).videoFromUrl(url2, "$prefix DoodStream", false)?.let { videoList.add(it) }
|
"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")!!)
|
||||||
if (embedUrl.contains("streamlare")) {
|
"ahvsh" in embedUrl || "streamhide" in embedUrl -> StreamHideVidExtractor(client).videosFromUrl(url, "$prefix ")
|
||||||
StreamlareExtractor(client).videosFromUrl(url, prefix = prefix).let { videoList.addAll(it) }
|
"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 ")
|
||||||
if (embedUrl.contains("yourupload") || embedUrl.contains("upload")) {
|
else -> emptyList()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun List<Video>.sort(): List<Video> {
|
override fun List<Video>.sort(): List<Video> {
|
||||||
@ -532,4 +582,11 @@ class Doramasflix : ConfigurableAnimeSource, AnimeHttpSource() {
|
|||||||
}
|
}
|
||||||
}.also(screen::addPreference)
|
}.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 {
|
ext {
|
||||||
extName = 'LocoPelis'
|
extName = 'LocoPelis'
|
||||||
extClass = '.LocoPelis'
|
extClass = '.LocoPelis'
|
||||||
extVersionCode = 20
|
extVersionCode = 21
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
@ -10,4 +10,5 @@ dependencies {
|
|||||||
implementation(project(':lib:streamtape-extractor'))
|
implementation(project(':lib:streamtape-extractor'))
|
||||||
implementation(project(':lib:okru-extractor'))
|
implementation(project(':lib:okru-extractor'))
|
||||||
implementation(project(':lib:dood-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.animesource.online.ParsedAnimeHttpSource
|
||||||
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
|
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
|
||||||
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
|
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.lib.streamtapeextractor.StreamTapeExtractor
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
@ -90,35 +92,23 @@ class LocoPelis : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
|
|
||||||
override fun videoListParse(response: Response): List<Video> {
|
override fun videoListParse(response: Response): List<Video> {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
val videoList = mutableListOf<Video>()
|
return document.select(".tab_container .tab_content iframe").parallelCatchingFlatMapBlocking { iframe ->
|
||||||
document.select(".tab_container .tab_content iframe").forEach { iframe ->
|
runCatching {
|
||||||
val url = iframe.attr("src")
|
val url = iframe.attr("src")
|
||||||
val embedUrl = url.lowercase()
|
with(url.lowercase()) {
|
||||||
if (embedUrl.contains("streamtape")) {
|
when {
|
||||||
val video = StreamTapeExtractor(client).videoFromUrl(url, "StreamTape")
|
contains("streamtape") || contains("stp") || contains("stape")
|
||||||
if (video != null) {
|
-> listOf(StreamTapeExtractor(client).videoFromUrl(this, quality = "StreamTape")!!)
|
||||||
videoList.add(video)
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}.getOrDefault(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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return videoList
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun videoListSelector() = throw UnsupportedOperationException()
|
override fun videoListSelector() = throw UnsupportedOperationException()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
ext {
|
ext {
|
||||||
extName = 'Pelisplushd'
|
extName = 'Pelisplushd'
|
||||||
extClass = '.PelisplushdFactory'
|
extClass = '.PelisplushdFactory'
|
||||||
extVersionCode = 50
|
extVersionCode = 51
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
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.lib.youruploadextractor.YourUploadExtractor
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import kotlinx.serialization.json.Json
|
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
|
||||||
import kotlinx.serialization.json.JsonObject
|
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
@ -38,7 +36,6 @@ import org.jsoup.nodes.Document
|
|||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
|
|
||||||
open class Pelisplushd(override val name: String, override val baseUrl: String) : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
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
|
override val supportsLatest = false
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
|
||||||
|
|
||||||
val preferences: SharedPreferences by lazy {
|
val preferences: SharedPreferences by lazy {
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
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 document = response.asJsoup()
|
||||||
val videoList = mutableListOf<Video>()
|
val videoList = mutableListOf<Video>()
|
||||||
|
|
||||||
val data = document.selectFirst("script:containsData(video[1] = )")!!.data()
|
val data = document.selectFirst("script:containsData(video[1] = )")?.data()
|
||||||
val apiUrl = data.substringAfter("video[1] = '", "").substringBefore("';", "")
|
val apiUrl = data?.substringAfter("video[1] = '", "")?.substringBefore("';", "")
|
||||||
val alternativeServers = document.select("ul.TbVideoNv.nav.nav-tabs li:not(:first-child)")
|
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 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()
|
val regIsUrl = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)".toRegex()
|
||||||
|
val encryptedList = apiResponse.select("#PlayerDisplay div[class*=\"OptionsLangDisp\"] div[class*=\"ODDIV\"] div[class*=\"OD\"] li")
|
||||||
encryptedList.forEach {
|
encryptedList.parallelCatchingFlatMapBlocking {
|
||||||
val server = it.select("span").text()
|
val url = it.attr("onclick")
|
||||||
var url = it.attr("onclick")
|
|
||||||
.substringAfter("go_to_player('")
|
.substringAfter("go_to_player('")
|
||||||
|
.substringAfter("go_to_playerVast('")
|
||||||
.substringBefore("?cover_url=")
|
.substringBefore("?cover_url=")
|
||||||
.substringBefore("')")
|
.substringBefore("')")
|
||||||
.substringBefore("',")
|
.substringBefore("',")
|
||||||
.substringBefore("?poster")
|
.substringBefore("?poster")
|
||||||
|
.substringBefore("?c_poster=")
|
||||||
|
.substringBefore("?thumb=")
|
||||||
.substringBefore("#poster=")
|
.substringBefore("#poster=")
|
||||||
|
|
||||||
if (!regIsUrl.containsMatchIn(url)) {
|
val realUrl = if (!regIsUrl.containsMatchIn(url)) {
|
||||||
url = String(Base64.decode(url, Base64.DEFAULT))
|
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(realUrl)
|
||||||
serverVideoResolver(url)?.forEach { video -> videoList.add(video) }
|
}.also(videoList::addAll)
|
||||||
} 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) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifier for old series
|
// verifier for old series
|
||||||
if (!apiUrl.contains("/video/") || alternativeServers.any()) {
|
if (!apiUrl.isNullOrEmpty() && !apiUrl.contains("/video/") || alternativeServers.any()) {
|
||||||
document.select("ul.TbVideoNv.nav.nav-tabs li").forEach { id ->
|
document.select("ul.TbVideoNv.nav.nav-tabs li").parallelCatchingFlatMapBlocking { id ->
|
||||||
val serverName = id.select("a").text()
|
val serverName = id.select("a").text().lowercase()
|
||||||
val serverId = id.attr("data-id")
|
val serverId = id.attr("data-id")
|
||||||
var serverUrl = data.substringAfter("video[$serverId] = '", "").substringBefore("';", "")
|
var serverUrl = data?.substringAfter("video[$serverId] = '", "")?.substringBefore("';", "")
|
||||||
if (serverUrl.contains("api.mycdn.moe")) {
|
if (serverUrl != null && serverUrl.contains("api.mycdn.moe")) {
|
||||||
val urlId = serverUrl.substringAfter("id=")
|
val urlId = serverUrl.substringAfter("id=")
|
||||||
when (serverName.lowercase()) {
|
serverUrl = when (serverName) {
|
||||||
"sbfast" -> { serverUrl = "https://sbfull.com/e/$urlId" }
|
"sbfast" -> { "https://sbfull.com/e/$urlId" }
|
||||||
"plusto" -> { serverUrl = "https://owodeuwu.xyz/v/$urlId" }
|
"plusto" -> { "https://owodeuwu.xyz/v/$urlId" }
|
||||||
"doodstream" -> { serverUrl = "https://dood.to/e/$urlId" }
|
"doodstream" -> { "https://dood.to/e/$urlId" }
|
||||||
"upload", "uqload" -> { serverUrl = "https://uqload.com/embed-$urlId.html" }
|
"upload", "uqload" -> { "https://uqload.com/embed-$urlId.html" }
|
||||||
|
else -> ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serverVideoResolver(serverUrl)?.forEach { video -> videoList.add(video) }
|
|
||||||
}
|
serverVideoResolver(serverUrl ?: "")
|
||||||
|
}.also(videoList::addAll)
|
||||||
}
|
}
|
||||||
return videoList
|
return videoList
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun serverVideoResolver(url: String): List<Video> {
|
private fun serverVideoResolver(url: String): List<Video> {
|
||||||
val videoList = mutableListOf<Video>()
|
|
||||||
val embedUrl = url.lowercase()
|
val embedUrl = url.lowercase()
|
||||||
try {
|
return runCatching {
|
||||||
if (embedUrl.contains("voe")) {
|
when {
|
||||||
VoeExtractor(client).videosFromUrl(url).also(videoList::addAll)
|
embedUrl.contains("voe") -> VoeExtractor(client).videosFromUrl(url)
|
||||||
}
|
embedUrl.contains("ok.ru") || embedUrl.contains("okru") -> OkruExtractor(client).videosFromUrl(url)
|
||||||
if ((embedUrl.contains("amazon") || embedUrl.contains("amz")) && !embedUrl.contains("disable")) {
|
embedUrl.contains("filemoon") || embedUrl.contains("moonplayer") -> {
|
||||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
val vidHeaders = headers.newBuilder()
|
||||||
if (body.select("script:containsData(var shareId)").toString().isNotBlank()) {
|
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||||
val shareId = body.selectFirst("script:containsData(var shareId)")!!.data()
|
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||||
.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")
|
|
||||||
.build()
|
.build()
|
||||||
val token = url.substringAfter("/embed.html#")
|
FilemoonExtractor(client).videosFromUrl(url, prefix = "Filemoon:", headers = vidHeaders)
|
||||||
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)) }
|
|
||||||
}
|
}
|
||||||
|
!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) { }
|
}.getOrNull() ?: emptyList()
|
||||||
return videoList
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun videoListSelector() = throw UnsupportedOperationException()
|
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.lib.youruploadextractor.YourUploadExtractor
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import kotlinx.serialization.json.Json
|
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
|
||||||
import kotlinx.serialization.json.JsonObject
|
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
|
|
||||||
class Pelisplusph(override val name: String, override val baseUrl: String) : Pelisplushd(name, baseUrl) {
|
class Pelisplusph(override val name: String, override val baseUrl: String) : Pelisplushd(name, baseUrl) {
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
|
||||||
|
|
||||||
override val supportsLatest = false
|
override val supportsLatest = false
|
||||||
|
|
||||||
companion object {
|
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.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
|
return anime
|
||||||
}
|
}
|
||||||
@ -107,7 +103,9 @@ class Pelisplusph(override val name: String, override val baseUrl: String) : Pel
|
|||||||
index += 1
|
index += 1
|
||||||
val noEp = try {
|
val noEp = try {
|
||||||
getNumberFromString(ep.ownText())
|
getNumberFromString(ep.ownText())
|
||||||
} catch (_: Exception) { idx + 1 }
|
} catch (_: Exception) {
|
||||||
|
idx + 1
|
||||||
|
}
|
||||||
val episode = SEpisode.create().apply {
|
val episode = SEpisode.create().apply {
|
||||||
episode_number = index.toFloat()
|
episode_number = index.toFloat()
|
||||||
name = "T$seasonNumber - E$noEp - ${ep.ownText()}"
|
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> {
|
override fun videoListParse(response: Response): List<Video> {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
val videoList = mutableListOf<Video>()
|
return document.select("[class*=server-item-]").parallelCatchingFlatMapBlocking { serverItem ->
|
||||||
document.select("[class*=server-item-]").map {
|
val langIdx = getNumberFromString(serverItem.attr("class").substringAfter("server-item-"))
|
||||||
val langIdx = getNumberFromString(it.attr("class").substringAfter("server-item-"))
|
|
||||||
val langItem = document.select("li[data-id=\"$langIdx\"] a").text()
|
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]"
|
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")
|
serverItem.select("li.tab-video").map { videoItem ->
|
||||||
serverVideoResolver(url, lang).let { videos ->
|
val url = videoItem.attr("data-video")
|
||||||
videoList.addAll(videos)
|
serverVideoResolver(url, lang)
|
||||||
}
|
}.flatten()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return videoList
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun serverVideoResolver(url: String, prefix: String = ""): List<Video> {
|
private fun serverVideoResolver(url: String, prefix: String = ""): List<Video> {
|
||||||
val videoList = mutableListOf<Video>()
|
|
||||||
val embedUrl = url.lowercase()
|
val embedUrl = url.lowercase()
|
||||||
try {
|
return runCatching {
|
||||||
if (embedUrl.contains("voe")) {
|
when {
|
||||||
VoeExtractor(client).videosFromUrl(url, prefix).also(videoList::addAll)
|
embedUrl.contains("voe") -> VoeExtractor(client).videosFromUrl(url, prefix)
|
||||||
}
|
embedUrl.contains("ok.ru") || embedUrl.contains("okru") -> OkruExtractor(client).videosFromUrl(url, prefix)
|
||||||
if ((embedUrl.contains("amazon") || embedUrl.contains("amz")) && !embedUrl.contains("disable")) {
|
embedUrl.contains("filemoon") || embedUrl.contains("moonplayer") -> {
|
||||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
val vidHeaders = headers.newBuilder()
|
||||||
if (body.select("script:containsData(var shareId)").toString().isNotBlank()) {
|
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||||
val shareId = body.selectFirst("script:containsData(var shareId)")!!.data()
|
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||||
.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")
|
|
||||||
.build()
|
.build()
|
||||||
val token = url.substringAfter("/embed.html#")
|
FilemoonExtractor(client).videosFromUrl(url, prefix = "$prefix Filemoon:", headers = vidHeaders)
|
||||||
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)) }
|
|
||||||
}
|
}
|
||||||
|
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) { }
|
}.getOrNull() ?: emptyList()
|
||||||
return videoList
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun List<Video>.sort(): List<Video> {
|
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.upstreamextractor.UpstreamExtractor
|
||||||
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
|
import eu.kanade.tachiyomi.lib.uqloadextractor.UqloadExtractor
|
||||||
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
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.lib.youruploadextractor.YourUploadExtractor
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
import kotlinx.serialization.json.jsonArray
|
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 filterList = if (filters.isEmpty()) getFilterList() else filters
|
||||||
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
|
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
|
||||||
return when {
|
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")
|
genreFilter.state != 0 -> GET("$baseUrl/${genreFilter.toUriPart()}?page=$page")
|
||||||
else -> popularAnimeRequest(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> {
|
override fun videoListParse(response: Response): List<Video> {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
val videoList = mutableListOf<Video>()
|
val regIsUrl = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)".toRegex()
|
||||||
document.select(".bg-tabs ul li").map { it ->
|
return document.select(".bg-tabs ul li").parallelCatchingFlatMapBlocking {
|
||||||
val url = String(Base64.decode(it.attr("data-server"), Base64.DEFAULT))
|
val decode = 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.*"), "")
|
|
||||||
|
|
||||||
serverVideoResolver(link).let { videos ->
|
val url = if (!regIsUrl.containsMatchIn(decode)) {
|
||||||
videoList.addAll(videos)
|
"$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> {
|
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> {
|
private fun serverVideoResolver(url: String): List<Video> {
|
||||||
val videoList = mutableListOf<Video>()
|
|
||||||
val embedUrl = url.lowercase()
|
val embedUrl = url.lowercase()
|
||||||
try {
|
return runCatching {
|
||||||
if (embedUrl.contains("voe")) {
|
when {
|
||||||
VoeExtractor(client).videosFromUrl(url).also(videoList::addAll)
|
embedUrl.contains("voe") -> VoeExtractor(client).videosFromUrl(url)
|
||||||
}
|
embedUrl.contains("ok.ru") || embedUrl.contains("okru") -> OkruExtractor(client).videosFromUrl(url)
|
||||||
if ((embedUrl.contains("amazon") || embedUrl.contains("amz")) && !embedUrl.contains("disable")) {
|
embedUrl.contains("filemoon") || embedUrl.contains("moonplayer") -> {
|
||||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
val vidHeaders = headers.newBuilder()
|
||||||
if (body.select("script:containsData(var shareId)").toString().isNotBlank()) {
|
.add("Origin", "https://${url.toHttpUrl().host}")
|
||||||
val shareId = body.selectFirst("script:containsData(var shareId)")!!.data()
|
.add("Referer", "https://${url.toHttpUrl().host}/")
|
||||||
.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")
|
|
||||||
.build()
|
.build()
|
||||||
val token = url.substringAfter("/embed.html#")
|
FilemoonExtractor(client).videosFromUrl(url, prefix = "Filemoon:", headers = vidHeaders)
|
||||||
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)) }
|
|
||||||
}
|
}
|
||||||
|
!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) { }
|
}.getOrNull() ?: emptyList()
|
||||||
return videoList
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
||||||
|
Reference in New Issue
Block a user