Switched to NiceHttp

Used !! as it was easier (with 10000 providers)
+ visible errors
This commit is contained in:
Blatzar 2022-05-02 18:58:27 +02:00
parent e64a875543
commit 109e1b9f17
56 changed files with 728 additions and 1094 deletions

View file

@ -105,16 +105,16 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
//implementation "io.karn:khttp-android:0.1.2" //okhttp instead //implementation "io.karn:khttp-android:0.1.2" //okhttp instead
implementation 'org.jsoup:jsoup:1.13.1' // implementation 'org.jsoup:jsoup:1.13.1'
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.12.3" // implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.12.3"
implementation "com.google.android.material:material:1.5.0" implementation "com.google.android.material:material:1.5.0"
implementation "androidx.preference:preference-ktx:1.2.0" implementation "androidx.preference:preference-ktx:1.2.0"
implementation 'com.github.bumptech.glide:glide:4.13.0' implementation 'com.github.bumptech.glide:glide:4.13.1'
kapt 'com.github.bumptech.glide:compiler:4.13.0' kapt 'com.github.bumptech.glide:compiler:4.13.1'
implementation 'com.github.bumptech.glide:okhttp3-integration:4.12.0' implementation 'com.github.bumptech.glide:okhttp3-integration:4.13.0'
implementation 'jp.wasabeef:glide-transformations:4.3.0' implementation 'jp.wasabeef:glide-transformations:4.3.0'
@ -154,8 +154,9 @@ dependencies {
implementation "androidx.work:work-runtime-ktx:2.7.1" implementation "androidx.work:work-runtime-ktx:2.7.1"
// Networking // Networking
implementation "com.squareup.okhttp3:okhttp:4.9.2" // implementation "com.squareup.okhttp3:okhttp:4.9.2"
implementation "com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.1" // implementation "com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.1"
implementation 'com.github.Blatzar:NiceHttp:0.1.8'
// Util to skip the URI file fuckery 🙏 // Util to skip the URI file fuckery 🙏
implementation "com.github.tachiyomiorg:unifile:17bec43" implementation "com.github.tachiyomiorg:unifile:17bec43"

View file

@ -36,7 +36,7 @@ import com.lagradost.cloudstream3.CommonActivity.showToast
import com.lagradost.cloudstream3.CommonActivity.updateLocale import com.lagradost.cloudstream3.CommonActivity.updateLocale
import com.lagradost.cloudstream3.movieproviders.NginxProvider import com.lagradost.cloudstream3.movieproviders.NginxProvider
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.network.Requests import com.lagradost.cloudstream3.network.initClient
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.OAuth2Apis import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.OAuth2Apis
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.OAuth2accountApis import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.OAuth2accountApis
@ -65,6 +65,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.getResourceColor
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
import com.lagradost.cloudstream3.utils.UIHelper.navigate import com.lagradost.cloudstream3.utils.UIHelper.navigate
import com.lagradost.cloudstream3.utils.UIHelper.requestRW import com.lagradost.cloudstream3.utils.UIHelper.requestRW
import com.lagradost.nicehttp.Requests
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_result_swipe.* import kotlinx.android.synthetic.main.fragment_result_swipe.*
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers

View file

@ -32,10 +32,10 @@ class AnimeFlickProvider : MainAPI() {
val html = app.get(link).text val html = app.get(link).text
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
return doc.select(".row.mt-2").map { return doc.select(".row.mt-2").mapNotNull {
val href = mainUrl + it.selectFirst("a").attr("href") val href = mainUrl + it.selectFirst("a")?.attr("href")
val title = it.selectFirst("h5 > a").text() val title = it.selectFirst("h5 > a")?.text() ?: return@mapNotNull null
val poster = mainUrl + it.selectFirst("img").attr("src").replace("70x110", "225x320") val poster = mainUrl + it.selectFirst("img")?.attr("src")?.replace("70x110", "225x320")
AnimeSearchResponse( AnimeSearchResponse(
title, title,
href, href,
@ -52,19 +52,19 @@ class AnimeFlickProvider : MainAPI() {
val html = app.get(url).text val html = app.get(url).text
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
val poster = mainUrl + doc.selectFirst("img.rounded").attr("src") val poster = mainUrl + doc.selectFirst("img.rounded")?.attr("src")
val title = doc.selectFirst("h2.title").text() val title = doc.selectFirst("h2.title")!!.text()
val yearText = doc.selectFirst(".trending-year")?.text() val yearText = doc.selectFirst(".trending-year")?.text()
val year = if (yearText != null) Regex("""(\d{4})""").find(yearText)?.destructured?.component1() val year = if (yearText != null) Regex("""(\d{4})""").find(yearText)?.destructured?.component1()
?.toIntOrNull() else null ?.toIntOrNull() else null
val description = doc.selectFirst("p").text() val description = doc.selectFirst("p")?.text()
val genres = doc.select("a[href*=\"genre-\"]").map { it.text() } val genres = doc.select("a[href*=\"genre-\"]").map { it.text() }
val episodes = doc.select("#collapseOne .block-space > .row > div:nth-child(2)").map { val episodes = doc.select("#collapseOne .block-space > .row > div:nth-child(2)").map {
val name = it.selectFirst("a").text() val name = it.selectFirst("a")?.text()
val link = mainUrl + it.selectFirst("a").attr("href") val link = mainUrl + it.selectFirst("a")?.attr("href")
Episode(link, name) Episode(link, name)
}.reversed() }.reversed()

View file

@ -7,10 +7,10 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import com.lagradost.cloudstream3.network.AppResponse
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.JsUnpacker import com.lagradost.cloudstream3.utils.JsUnpacker
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.nicehttp.NiceResponse
import org.jsoup.Jsoup import org.jsoup.Jsoup
import kotlin.math.pow import kotlin.math.pow
@ -242,7 +242,7 @@ class AnimePaheProvider : MainAPI() {
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
val japTitle = doc.selectFirst("h2.japanese")?.text() val japTitle = doc.selectFirst("h2.japanese")?.text()
val poster = doc.selectFirst(".anime-poster a").attr("href") val poster = doc.selectFirst(".anime-poster a")?.attr("href")
val tvType = doc.selectFirst("""a[href*="/anime/type/"]""")?.text() val tvType = doc.selectFirst("""a[href*="/anime/type/"]""")?.text()
@ -263,7 +263,7 @@ class AnimePaheProvider : MainAPI() {
"completed" -> ShowStatus.Completed "completed" -> ShowStatus.Completed
else -> null else -> null
} }
val synopsis = doc.selectFirst(".anime-synopsis").text() val synopsis = doc.selectFirst(".anime-synopsis")?.text()
var anilistId: Int? = null var anilistId: Int? = null
var malId: Int? = null var malId: Int? = null
@ -431,7 +431,7 @@ class AnimePaheProvider : MainAPI() {
} }
var responseCode = 302 var responseCode = 302
var adflyContent: AppResponse? = null var adflyContent: NiceResponse? = null
var tries = 0 var tries = 0
while (responseCode != 200 && tries < 20) { while (responseCode != 200 && tries < 20) {
@ -481,7 +481,7 @@ class AnimePaheProvider : MainAPI() {
val decrypted = decrypt(fullString, key, v1.toInt(), v2.toInt()) val decrypted = decrypt(fullString, key, v1.toInt(), v2.toInt())
val uri = KWIK_D_URL.find(decrypted)!!.destructured.component1() val uri = KWIK_D_URL.find(decrypted)!!.destructured.component1()
val tok = KWIK_D_TOKEN.find(decrypted)!!.destructured.component1() val tok = KWIK_D_TOKEN.find(decrypted)!!.destructured.component1()
var content: AppResponse? = null var content: NiceResponse? = null
var code = 419 var code = 419
var tries = 0 var tries = 0

View file

@ -6,10 +6,10 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
import com.lagradost.cloudstream3.LoadResponse.Companion.addRating import com.lagradost.cloudstream3.LoadResponse.Companion.addRating
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.network.AppResponse
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.nicehttp.NiceResponse
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
class AnimeWorldProvider : MainAPI() { class AnimeWorldProvider : MainAPI() {
@ -29,7 +29,7 @@ class AnimeWorldProvider : MainAPI() {
private val cookieRegex = Regex("$cookieName=(.+?)(\\s?);") private val cookieRegex = Regex("$cookieName=(.+?)(\\s?);")
private val cookies = mutableMapOf(cookieName to "") private val cookies = mutableMapOf(cookieName to "")
private suspend fun request(url: String): AppResponse { private suspend fun request(url: String): NiceResponse {
val response = app.get(url, cookies = cookies) val response = app.get(url, cookies = cookies)
return cookieRegex.find(response.text)?.let { return cookieRegex.find(response.text)?.let {
val verify = it.groups[1]?.value ?: throw ErrorLoadingException("Can't bypass protection") val verify = it.groups[1]?.value ?: throw ErrorLoadingException("Can't bypass protection")

View file

@ -7,19 +7,21 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import java.util.* import java.util.*
class AnimeflvnetProvider:MainAPI() { class AnimeflvnetProvider : MainAPI() {
companion object { companion object {
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA") || t.contains("Especial")) TvType.OVA return if (t.contains("OVA") || t.contains("Especial")) TvType.OVA
else if (t.contains("Película")) TvType.AnimeMovie else if (t.contains("Película")) TvType.AnimeMovie
else TvType.Anime else TvType.Anime
} }
fun getDubStatus(title: String): DubStatus { fun getDubStatus(title: String): DubStatus {
return if (title.contains("Latino") || title.contains("Castellano")) return if (title.contains("Latino") || title.contains("Castellano"))
DubStatus.Dubbed DubStatus.Dubbed
else DubStatus.Subbed else DubStatus.Subbed
} }
} }
override var mainUrl = "https://www3.animeflv.net" override var mainUrl = "https://www3.animeflv.net"
override var name = "Animeflv.net" override var name = "Animeflv.net"
override val lang = "es" override val lang = "es"
@ -42,13 +44,14 @@ class AnimeflvnetProvider:MainAPI() {
items.add( items.add(
HomePageList( HomePageList(
"Últimos episodios", "Últimos episodios",
app.get(mainUrl).document.select("main.Main ul.ListEpisodios li").map { app.get(mainUrl).document.select("main.Main ul.ListEpisodios li").mapNotNull {
val title = it.selectFirst("strong.Title").text() val title = it.selectFirst("strong.Title")?.text() ?: return@mapNotNull null
val poster = it.selectFirst("span img").attr("src") val poster = it.selectFirst("span img")?.attr("src") ?: return@mapNotNull null
val epRegex = Regex("(-(\\d+)\$)") val epRegex = Regex("(-(\\d+)\$)")
val url = it.selectFirst("a").attr("href").replace(epRegex,"") val url = it.selectFirst("a")?.attr("href")?.replace(epRegex, "")
.replace("ver/","anime/") ?.replace("ver/", "anime/") ?: return@mapNotNull null
val epNum = it.selectFirst("span.Capi").text().replace("Episodio ","").toIntOrNull() val epNum =
it.selectFirst("span.Capi")?.text()?.replace("Episodio ", "")?.toIntOrNull()
newAnimeSearchResponse(title, url) { newAnimeSearchResponse(title, url) {
this.posterUrl = fixUrl(poster) this.posterUrl = fixUrl(poster)
addDubStatus(getDubStatus(title), epNum) addDubStatus(getDubStatus(title), epNum)
@ -58,10 +61,13 @@ class AnimeflvnetProvider:MainAPI() {
for ((url, name) in urls) { for ((url, name) in urls) {
try { try {
val doc = app.get(url).document val doc = app.get(url).document
val home = doc.select("ul.ListAnimes li article").map { val home = doc.select("ul.ListAnimes li article").mapNotNull {
val title = it.selectFirst("h3.Title").text() val title = it.selectFirst("h3.Title")?.text() ?: return@mapNotNull null
val poster = it.selectFirst("figure img").attr("src") val poster = it.selectFirst("figure img")?.attr("src") ?: return@mapNotNull null
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) { newAnimeSearchResponse(
title,
fixUrl(it.selectFirst("a")?.attr("href") ?: return@mapNotNull null)
) {
this.posterUrl = fixUrl(poster) this.posterUrl = fixUrl(poster)
addDubStatus(MonoschinosProvider.getDubStatus(title)) addDubStatus(MonoschinosProvider.getDubStatus(title))
} }
@ -76,7 +82,7 @@ class AnimeflvnetProvider:MainAPI() {
return HomePageResponse(items) return HomePageResponse(items)
} }
data class SearchObject ( data class SearchObject(
@JsonProperty("id") val id: String, @JsonProperty("id") val id: String,
@JsonProperty("title") val title: String, @JsonProperty("title") val title: String,
@JsonProperty("type") val type: String, @JsonProperty("type") val type: String,
@ -85,33 +91,36 @@ class AnimeflvnetProvider:MainAPI() {
) )
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val response = app.post("https://www3.animeflv.net/api/animes/search", val response = app.post(
data = mapOf(Pair("value",query)) "https://www3.animeflv.net/api/animes/search",
data = mapOf(Pair("value", query))
).text ).text
val json = parseJson<List<SearchObject>>(response) val json = parseJson<List<SearchObject>>(response)
return json.map { searchr -> return json.map { searchr ->
val title = searchr.title val title = searchr.title
val href = "$mainUrl/anime/${searchr.slug}" val href = "$mainUrl/anime/${searchr.slug}"
val image = "$mainUrl/uploads/animes/covers/${searchr.id}.jpg" val image = "$mainUrl/uploads/animes/covers/${searchr.id}.jpg"
AnimeSearchResponse( AnimeSearchResponse(
title, title,
href, href,
this.name, this.name,
TvType.Anime, TvType.Anime,
fixUrl(image), fixUrl(image),
null, null,
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed), if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
) DubStatus.Subbed
),
)
} }
} }
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val doc = app.get(url).document val doc = app.get(url).document
val episodes = ArrayList<Episode>() val episodes = ArrayList<Episode>()
val title = doc.selectFirst("h1.Title").text() val title = doc.selectFirst("h1.Title")!!.text()
val poster = doc.selectFirst("div.AnimeCover div.Image figure img").attr("src") val poster = doc.selectFirst("div.AnimeCover div.Image figure img")?.attr("src")!!
val description = doc.selectFirst("div.Description p").text() val description = doc.selectFirst("div.Description p")?.text()
val type = doc.selectFirst("span.Type").text() val type = doc.selectFirst("span.Type")?.text() ?: ""
val status = when (doc.selectFirst("p.AnmStts span")?.text()) { val status = when (doc.selectFirst("p.AnmStts span")?.text()) {
"En emision" -> ShowStatus.Ongoing "En emision" -> ShowStatus.Ongoing
"Finalizado" -> ShowStatus.Completed "Finalizado" -> ShowStatus.Completed
@ -126,15 +135,16 @@ class AnimeflvnetProvider:MainAPI() {
data.split("],").forEach { data.split("],").forEach {
val epNum = it.removePrefix("[").substringBefore(",") val epNum = it.removePrefix("[").substringBefore(",")
// val epthumbid = it.removePrefix("[").substringAfter(",").substringBefore("]") // val epthumbid = it.removePrefix("[").substringAfter(",").substringBefore("]")
val animeid = doc.selectFirst("div.Strs.RateIt").attr("data-id") val animeid = doc.selectFirst("div.Strs.RateIt")?.attr("data-id")
val epthumb = "https://cdn.animeflv.net/screenshots/$animeid/$epNum/th_3.jpg" val epthumb = "https://cdn.animeflv.net/screenshots/$animeid/$epNum/th_3.jpg"
val link = url.replace("/anime/","/ver/")+"-$epNum" val link = url.replace("/anime/", "/ver/") + "-$epNum"
episodes.add( Episode( episodes.add(
link, Episode(
null, link,
posterUrl = epthumb, null,
episode = epNum.toIntOrNull() posterUrl = epthumb,
) episode = epNum.toIntOrNull()
)
) )
} }
} }
@ -147,6 +157,7 @@ class AnimeflvnetProvider:MainAPI() {
tags = genre tags = genre
} }
} }
override suspend fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
@ -154,11 +165,13 @@ class AnimeflvnetProvider:MainAPI() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
app.get(data).document.select("script").apmap { script -> app.get(data).document.select("script").apmap { script ->
if (script.data().contains("var videos = {") || script.data().contains("var anime_id =") || script.data().contains("server")) { if (script.data().contains("var videos = {") || script.data()
.contains("var anime_id =") || script.data().contains("server")
) {
val videos = script.data().replace("\\/", "/") val videos = script.data().replace("\\/", "/")
fetchUrls(videos).map { fetchUrls(videos).map {
it.replace("https://embedsb.com/e/","https://watchsb.com/e/") it.replace("https://embedsb.com/e/", "https://watchsb.com/e/")
.replace("https://ok.ru","http://ok.ru") .replace("https://ok.ru", "http://ok.ru")
}.apmap { }.apmap {
loadExtractor(it, data, callback) loadExtractor(it, data, callback)
} }

View file

@ -2,6 +2,9 @@ package com.lagradost.cloudstream3.animeproviders
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
@ -31,23 +34,20 @@ class AnimekisaProvider : MainAPI() {
Pair("$mainUrl/ajax/list/views?type=day", "Trending now"), Pair("$mainUrl/ajax/list/views?type=day", "Trending now"),
Pair("$mainUrl/ajax/list/views?type=week", "Trending by week"), Pair("$mainUrl/ajax/list/views?type=week", "Trending by week"),
Pair("$mainUrl/ajax/list/views?type=month", "Trending by month"), Pair("$mainUrl/ajax/list/views?type=month", "Trending by month"),
)
) val items = urls.mapNotNull {
suspendSafeApiCall {
val items = ArrayList<HomePageList>()
for ((url, name) in urls) {
try {
val home = Jsoup.parse( val home = Jsoup.parse(
parseJson<Response>( parseJson<Response>(
app.get( app.get(
url it.first
).text ).text
).html ).html
).select("div.flw-item").map { ).select("div.flw-item").mapNotNull secondMap@ {
val title = it.selectFirst("h3.title a").text() val title = it.selectFirst("h3.title a")?.text() ?: return@secondMap null
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")?.attr("href") ?: return@secondMap null
val poster = it.selectFirst("img.lazyload").attr("data-src") val poster = it.selectFirst("img.lazyload")?.attr("data-src")
AnimeSearchResponse( AnimeSearchResponse(
title, title,
link, link,
@ -60,52 +60,50 @@ class AnimekisaProvider : MainAPI() {
) else EnumSet.of(DubStatus.Subbed), ) else EnumSet.of(DubStatus.Subbed),
) )
} }
HomePageList(name, home)
items.add(HomePageList(name, home))
} catch (e: Exception) {
e.printStackTrace()
} }
} }
if (items.size <= 0) throw ErrorLoadingException() if (items.isEmpty()) throw ErrorLoadingException()
return HomePageResponse(items) return HomePageResponse(items)
} }
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
return app.get("$mainUrl/search/?keyword=$query").document.select("div.flw-item").map { return app.get("$mainUrl/search/?keyword=$query").document.select("div.flw-item")
val title = it.selectFirst("h3 a").text() .mapNotNull {
val url = it.selectFirst("a.film-poster-ahref").attr("href") val title = it.selectFirst("h3 a")?.text() ?: ""
.replace("watch/", "anime/").replace( val url = it.selectFirst("a.film-poster-ahref")?.attr("href")
Regex("(-episode-(\\d+)\\/\$|-episode-(\\d+)\$|-episode-full|-episode-.*-.(\\/|))"), ?.replace("watch/", "anime/")?.replace(
"" Regex("(-episode-(\\d+)\\/\$|-episode-(\\d+)\$|-episode-full|-episode-.*-.(\\/|))"),
""
) ?: return@mapNotNull null
val poster = it.selectFirst(".film-poster img")?.attr("data-src")
AnimeSearchResponse(
title,
url,
this.name,
TvType.Anime,
poster,
null,
if (title.contains("(DUB)") || title.contains("(Dub)")) EnumSet.of(
DubStatus.Dubbed
) else EnumSet.of(DubStatus.Subbed),
) )
val poster = it.selectFirst(".film-poster img").attr("data-src") }.toList()
AnimeSearchResponse(
title,
url,
this.name,
TvType.Anime,
poster,
null,
if (title.contains("(DUB)") || title.contains("(Dub)")) EnumSet.of(
DubStatus.Dubbed
) else EnumSet.of(DubStatus.Subbed),
)
}.toList()
} }
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val doc = app.get(url, timeout = 120).document val doc = app.get(url, timeout = 120).document
val poster = doc.selectFirst(".mb-2 img").attr("src") val poster = doc.selectFirst(".mb-2 img")?.attr("src")
?: doc.selectFirst("head meta[property=og:image]").attr("content") ?: doc.selectFirst("head meta[property=og:image]")?.attr("content")
val title = doc.selectFirst("h1.heading-name a").text() val title = doc.selectFirst("h1.heading-name a")!!.text()
val description = doc.selectFirst("div.description p").text().trim() val description = doc.selectFirst("div.description p")?.text()?.trim()
val genres = doc.select("div.row-line a").map { it.text() } val genres = doc.select("div.row-line a").map { it.text() }
val test = if (doc.selectFirst("div.dp-i-c-right").toString() val test = if (doc.selectFirst("div.dp-i-c-right").toString()
.contains("Airing") .contains("Airing")
) ShowStatus.Ongoing else ShowStatus.Completed ) ShowStatus.Ongoing else ShowStatus.Completed
val episodes = doc.select("div.tab-content ul li.nav-item").map { val episodes = doc.select("div.tab-content ul li.nav-item").mapNotNull {
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")?.attr("href") ?: return@mapNotNull null
Episode(link) Episode(link)
} }
val type = if (doc.selectFirst(".dp-i-stats").toString() val type = if (doc.selectFirst(".dp-i-stats").toString()

View file

@ -57,9 +57,9 @@ class DubbedAnimeProvider : MainAPI() {
private suspend fun parseDocumentTrending(url: String): List<SearchResponse> { private suspend fun parseDocumentTrending(url: String): List<SearchResponse> {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
return document.select("li > a").map { return document.select("li > a").mapNotNull {
val href = fixUrl(it.attr("href")) val href = fixUrl(it.attr("href"))
val title = it.selectFirst("> div > div.cittx").text() val title = it.selectFirst("> div > div.cittx")?.text() ?: return@mapNotNull null
val poster = fixUrlNull(it.selectFirst("> div > div.imghddde > img")?.attr("src")) val poster = fixUrlNull(it.selectFirst("> div > div.imghddde > img")?.attr("src"))
AnimeSearchResponse( AnimeSearchResponse(
title, title,
@ -79,10 +79,11 @@ class DubbedAnimeProvider : MainAPI() {
): List<SearchResponse> { ): List<SearchResponse> {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
return document.select("a.grid__link").map { return document.select("a.grid__link").mapNotNull {
val href = fixUrl(it.attr("href")) val href = fixUrl(it.attr("href"))
val title = it.selectFirst("> div.gridtitlek").text() val title = it.selectFirst("> div.gridtitlek")?.text() ?: return@mapNotNull null
val poster = fixUrl(it.selectFirst("> img.grid__img").attr("src")) val poster =
fixUrl(it.selectFirst("> img.grid__img")?.attr("src") ?: return@mapNotNull null)
AnimeSearchResponse( AnimeSearchResponse(
title, title,
if (trimEpisode) href.removeRange(href.lastIndexOf('/'), href.length) else href, if (trimEpisode) href.removeRange(href.lastIndexOf('/'), href.length) else href,
@ -135,9 +136,9 @@ class DubbedAnimeProvider : MainAPI() {
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val items = document.select("div.grid__item > a") val items = document.select("div.grid__item > a")
if (items.isEmpty()) return emptyList() if (items.isEmpty()) return emptyList()
return items.map { i -> return items.mapNotNull { i ->
val href = fixUrl(i.attr("href")) val href = fixUrl(i.attr("href"))
val title = i.selectFirst("div.gridtitlek").text() val title = i.selectFirst("div.gridtitlek")?.text() ?: return@mapNotNull null
val img = fixUrlNull(i.selectFirst("img.grid__img")?.attr("src")) val img = fixUrlNull(i.selectFirst("img.grid__img")?.attr("src"))
if (getIsMovie(href)) { if (getIsMovie(href)) {
@ -164,11 +165,11 @@ class DubbedAnimeProvider : MainAPI() {
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val items = document.select("div.resultinner > a.resulta") val items = document.select("div.resultinner > a.resulta")
if (items.isEmpty()) return ArrayList() if (items.isEmpty()) return ArrayList()
return items.map { i -> return items.mapNotNull { i ->
val innerDiv = i.selectFirst("> div.result") val innerDiv = i.selectFirst("> div.result")
val href = fixUrl(i.attr("href")) val href = fixUrl(i.attr("href"))
val img = fixUrl(innerDiv.selectFirst("> div.imgkz > img").attr("src")) val img = fixUrl(innerDiv?.selectFirst("> div.imgkz > img")?.attr("src") ?: return@mapNotNull null)
val title = innerDiv.selectFirst("> div.titleresults").text() val title = innerDiv.selectFirst("> div.titleresults")?.text() ?: return@mapNotNull null
if (getIsMovie(href)) { if (getIsMovie(href)) {
MovieSearchResponse( MovieSearchResponse(
@ -244,12 +245,13 @@ class DubbedAnimeProvider : MainAPI() {
} else { } else {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val title = document.selectFirst("h4").text() val title = document.selectFirst("h4")!!.text()
val descriptHeader = document.selectFirst("div.animeDescript") val descriptHeader = document.selectFirst("div.animeDescript")
val descript = descriptHeader.selectFirst("> p").text() val descript = descriptHeader?.selectFirst("> p")?.text()
val year = descriptHeader.selectFirst("> div.distatsx > div.sroverd").text() val year = descriptHeader?.selectFirst("> div.distatsx > div.sroverd")
.replace("Released: ", "") ?.text()
.toIntOrNull() ?.replace("Released: ", "")
?.toIntOrNull()
val episodes = document.select("a.epibloks").map { val episodes = document.select("a.epibloks").map {
val epTitle = it.selectFirst("> div.inwel > span.isgrxx")?.text() val epTitle = it.selectFirst("> div.inwel > span.isgrxx")?.text()

View file

@ -116,7 +116,8 @@ class GogoanimeProvider : MainAPI() {
val encryptRequestData = if (isUsingAdaptiveData) { val encryptRequestData = if (isUsingAdaptiveData) {
// Only fetch the document if necessary // Only fetch the document if necessary
val realDocument = document ?: app.get(iframeUrl).document val realDocument = document ?: app.get(iframeUrl).document
val dataEncrypted = realDocument.select("script[data-name='episode']").attr("data-value") val dataEncrypted =
realDocument.select("script[data-name='episode']").attr("data-value")
val headers = cryptoHandler(dataEncrypted, foundIv, foundKey, false) val headers = cryptoHandler(dataEncrypted, foundIv, foundKey, false)
"id=$encryptedId&alias=$id&" + headers.substringAfter("&") "id=$encryptedId&alias=$id&" + headers.substringAfter("&")
} else { } else {
@ -246,17 +247,17 @@ class GogoanimeProvider : MainAPI() {
val html = app.get(link).text val html = app.get(link).text
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
val episodes = doc.select(""".last_episodes li""").map { val episodes = doc.select(""".last_episodes li""").mapNotNull {
AnimeSearchResponse( AnimeSearchResponse(
it.selectFirst(".name").text().replace(" (Dub)", ""), it.selectFirst(".name")?.text()?.replace(" (Dub)", "") ?: return@mapNotNull null,
fixUrl(it.selectFirst(".name > a").attr("href")), fixUrl(it.selectFirst(".name > a")?.attr("href") ?: return@mapNotNull null),
this.name, this.name,
TvType.Anime, TvType.Anime,
it.selectFirst("img").attr("src"), it.selectFirst("img")?.attr("src"),
it.selectFirst(".released")?.text()?.split(":")?.getOrNull(1)?.trim() it.selectFirst(".released")?.text()?.split(":")?.getOrNull(1)?.trim()
?.toIntOrNull(), ?.toIntOrNull(),
if (it.selectFirst(".name").text() if (it.selectFirst(".name")?.text()
.contains("Dub") ?.contains("Dub") == true
) EnumSet.of(DubStatus.Dubbed) else EnumSet.of( ) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
DubStatus.Subbed DubStatus.Subbed
), ),
@ -282,8 +283,8 @@ class GogoanimeProvider : MainAPI() {
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
val animeBody = doc.selectFirst(".anime_info_body_bg") val animeBody = doc.selectFirst(".anime_info_body_bg")
val title = animeBody.selectFirst("h1").text() val title = animeBody?.selectFirst("h1")!!.text()
val poster = animeBody.selectFirst("img").attr("src") val poster = animeBody.selectFirst("img")?.attr("src")
var description: String? = null var description: String? = null
val genre = ArrayList<String>() val genre = ArrayList<String>()
var year: Int? = null var year: Int? = null
@ -292,7 +293,7 @@ class GogoanimeProvider : MainAPI() {
var type: String? = null var type: String? = null
animeBody.select("p.type").forEach { pType -> animeBody.select("p.type").forEach { pType ->
when (pType.selectFirst("span").text().trim()) { when (pType.selectFirst("span")?.text()?.trim()) {
"Plot Summary:" -> { "Plot Summary:" -> {
description = pType.text().replace("Plot Summary:", "").trim() description = pType.text().replace("Plot Summary:", "").trim()
} }
@ -316,13 +317,13 @@ class GogoanimeProvider : MainAPI() {
} }
} }
val animeId = doc.selectFirst("#movie_id").attr("value") val animeId = doc.selectFirst("#movie_id")!!.attr("value")
val params = mapOf("ep_start" to "0", "ep_end" to "2000", "id" to animeId) val params = mapOf("ep_start" to "0", "ep_end" to "2000", "id" to animeId)
val episodes = app.get(episodeloadApi, params = params).document.select("a").map { val episodes = app.get(episodeloadApi, params = params).document.select("a").map {
Episode( Episode(
fixUrl(it.attr("href").trim()), fixUrl(it.attr("href").trim()),
"Episode " + it.selectFirst(".name").text().replace("EP", "").trim() "Episode " + it.selectFirst(".name")?.text()?.replace("EP", "")?.trim()
) )
}.reversed() }.reversed()
@ -357,7 +358,7 @@ class GogoanimeProvider : MainAPI() {
private suspend fun extractVideos(uri: String, callback: (ExtractorLink) -> Unit) { private suspend fun extractVideos(uri: String, callback: (ExtractorLink) -> Unit) {
val doc = app.get(uri).document val doc = app.get(uri).document
val iframe = fixUrlNull(doc.selectFirst("div.play-video > iframe").attr("src")) ?: return val iframe = fixUrlNull(doc.selectFirst("div.play-video > iframe")?.attr("src")) ?: return
argamap( argamap(
{ {

View file

@ -20,31 +20,35 @@ class KawaiifuProvider : MainAPI() {
val soup = Jsoup.parse(resp) val soup = Jsoup.parse(resp)
items.add(HomePageList("Latest Updates", soup.select(".today-update .item").map { items.add(HomePageList("Latest Updates", soup.select(".today-update .item").mapNotNull {
val title = it.selectFirst("img").attr("alt") val title = it.selectFirst("img")?.attr("alt")
AnimeSearchResponse( AnimeSearchResponse(
title, title ?: return@mapNotNull null,
it.selectFirst("a").attr("href"), it.selectFirst("a")?.attr("href") ?: return@mapNotNull null,
this.name, this.name,
TvType.Anime, TvType.Anime,
it.selectFirst("img").attr("src"), it.selectFirst("img")?.attr("src"),
it.selectFirst("h4 > a").attr("href").split("-").last().toIntOrNull(), it.selectFirst("h4 > a")?.attr("href")?.split("-")?.last()?.toIntOrNull(),
if (title.contains("(DUB)")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed), if (title.contains("(DUB)")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
DubStatus.Subbed
),
) )
})) }))
for (section in soup.select(".section")) { for (section in soup.select(".section")) {
try { try {
val title = section.selectFirst(".title").text() val title = section.selectFirst(".title")!!.text()
val anime = section.select(".list-film > .item").map { ani -> val anime = section.select(".list-film > .item").mapNotNull { ani ->
val animTitle = ani.selectFirst("img").attr("alt") val animTitle = ani.selectFirst("img")?.attr("alt")
AnimeSearchResponse( AnimeSearchResponse(
animTitle, animTitle ?: return@mapNotNull null,
ani.selectFirst("a").attr("href"), ani.selectFirst("a")?.attr("href") ?: return@mapNotNull null,
this.name, this.name,
TvType.Anime, TvType.Anime,
ani.selectFirst("img").attr("src"), ani.selectFirst("img")?.attr("src"),
ani.selectFirst(".vl-chil-date").text().toIntOrNull(), ani.selectFirst(".vl-chil-date")?.text()?.toIntOrNull(),
if (animTitle.contains("(DUB)")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed), if (animTitle.contains("(DUB)")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
DubStatus.Subbed
),
) )
} }
items.add(HomePageList(title, anime)) items.add(HomePageList(title, anime))
@ -63,11 +67,11 @@ class KawaiifuProvider : MainAPI() {
val html = app.get(link).text val html = app.get(link).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
return ArrayList(soup.select(".item").map { return ArrayList(soup.select(".item").mapNotNull {
val year = it.selectFirst("h4 > a").attr("href").split("-").last().toIntOrNull() val year = it.selectFirst("h4 > a")?.attr("href")?.split("-")?.last()?.toIntOrNull()
val title = it.selectFirst("img").attr("alt") val title = it.selectFirst("img")?.attr("alt") ?: return@mapNotNull null
val poster = it.selectFirst("img").attr("src") val poster = it.selectFirst("img")?.attr("src")
val uri = it.selectFirst("a").attr("href") val uri = it.selectFirst("a")?.attr("href") ?: return@mapNotNull null
AnimeSearchResponse( AnimeSearchResponse(
title, title,
uri, uri,
@ -84,22 +88,26 @@ class KawaiifuProvider : MainAPI() {
val html = app.get(url).text val html = app.get(url).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
val title = soup.selectFirst(".title").text() val title = soup.selectFirst(".title")!!.text()
val tags = soup.select(".table a[href*=\"/tag/\"]").map { tag -> tag.text() } val tags = soup.select(".table a[href*=\"/tag/\"]").map { tag -> tag.text() }
val description = soup.select(".sub-desc p") val description = soup.select(".sub-desc p")
.filter { it.select("strong").isEmpty() && it.select("iframe").isEmpty() }.joinToString("\n") { it.text() } .filter { it.select("strong").isEmpty() && it.select("iframe").isEmpty() }
.joinToString("\n") { it.text() }
val year = url.split("/").filter { it.contains("-") }[0].split("-")[1].toIntOrNull() val year = url.split("/").filter { it.contains("-") }[0].split("-")[1].toIntOrNull()
val episodesLink = soup.selectFirst("a[href*=\".html-episode\"]").attr("href") ?: throw ErrorLoadingException("Error getting episode list") val episodesLink = soup.selectFirst("a[href*=\".html-episode\"]")?.attr("href")
?: throw ErrorLoadingException("Error getting episode list")
val episodes = Jsoup.parse( val episodes = Jsoup.parse(
app.get(episodesLink).text app.get(episodesLink).text
).selectFirst(".list-ep").select("li").map { ).selectFirst(".list-ep")?.select("li")?.map {
Episode( Episode(
it.selectFirst("a").attr("href"), it.selectFirst("a")!!.attr("href"),
if (it.text().trim().toIntOrNull() != null) "Episode ${it.text().trim()}" else it.text().trim() if (it.text().trim().toIntOrNull() != null) "Episode ${
it.text().trim()
}" else it.text().trim()
) )
} }
val poster = soup.selectFirst("a.thumb > img").attr("src") val poster = soup.selectFirst("a.thumb > img")?.attr("src")
return newAnimeLoadResponse(title, url, TvType.Anime) { return newAnimeLoadResponse(title, url, TvType.Anime) {
this.year = year this.year = year
@ -119,11 +127,13 @@ class KawaiifuProvider : MainAPI() {
val htmlSource = app.get(data).text val htmlSource = app.get(data).text
val soupa = Jsoup.parse(htmlSource) val soupa = Jsoup.parse(htmlSource)
val episodeNum = if (data.contains("ep=")) data.split("ep=")[1].split("&")[0].toIntOrNull() else null val episodeNum =
if (data.contains("ep=")) data.split("ep=")[1].split("&")[0].toIntOrNull() else null
val servers = soupa.select(".list-server").map { val servers = soupa.select(".list-server").map {
val serverName = it.selectFirst(".server-name").text() val serverName = it.selectFirst(".server-name")!!.text()
val episodes = it.select(".list-ep > li > a").map { episode -> Pair(episode.attr("href"), episode.text()) } val episodes = it.select(".list-ep > li > a")
.map { episode -> Pair(episode.attr("href"), episode.text()) }
val episode = if (episodeNum == null) episodes[0] else episodes.mapNotNull { ep -> val episode = if (episodeNum == null) episodes[0] else episodes.mapNotNull { ep ->
if ((if (ep.first.contains("ep=")) ep.first.split("ep=")[1].split("&")[0].toIntOrNull() else null) == episodeNum) { if ((if (ep.first.contains("ep=")) ep.first.split("ep=")[1].split("&")[0].toIntOrNull() else null) == episodeNum) {
ep ep

View file

@ -50,12 +50,12 @@ class MonoschinosProvider : MainAPI() {
HomePageList( HomePageList(
"Capítulos actualizados", "Capítulos actualizados",
app.get(mainUrl, timeout = 120).document.select(".col-6").map { app.get(mainUrl, timeout = 120).document.select(".col-6").map {
val title = it.selectFirst("p.animetitles").text() val title = it.selectFirst("p.animetitles")!!.text()
val poster = it.selectFirst(".animeimghv").attr("data-src") val poster = it.selectFirst(".animeimghv")!!.attr("data-src")
val epRegex = Regex("episodio-(\\d+)") val epRegex = Regex("episodio-(\\d+)")
val url = it.selectFirst("a").attr("href").replace("ver/", "anime/") val url = it.selectFirst("a")?.attr("href")!!.replace("ver/", "anime/")
.replace(epRegex, "sub-espanol") .replace(epRegex, "sub-espanol")
val epNum = it.selectFirst(".positioning h5").text().toIntOrNull() val epNum = it.selectFirst(".positioning h5")?.text()?.toIntOrNull()
newAnimeSearchResponse(title, url) { newAnimeSearchResponse(title, url) {
this.posterUrl = fixUrl(poster) this.posterUrl = fixUrl(poster)
addDubStatus(getDubStatus(title), epNum) addDubStatus(getDubStatus(title), epNum)
@ -66,9 +66,9 @@ class MonoschinosProvider : MainAPI() {
for (i in urls) { for (i in urls) {
try { try {
val home = app.get(i.first, timeout = 120).document.select(".col-6").map { val home = app.get(i.first, timeout = 120).document.select(".col-6").map {
val title = it.selectFirst(".seristitles").text() val title = it.selectFirst(".seristitles")!!.text()
val poster = it.selectFirst("img.animemainimg").attr("src") val poster = it.selectFirst("img.animemainimg")!!.attr("src")
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) { newAnimeSearchResponse(title, fixUrl(it.selectFirst("a")!!.attr("href"))) {
this.posterUrl = fixUrl(poster) this.posterUrl = fixUrl(poster)
addDubStatus(getDubStatus(title)) addDubStatus(getDubStatus(title))
} }
@ -87,9 +87,9 @@ class MonoschinosProvider : MainAPI() {
override suspend fun search(query: String): ArrayList<SearchResponse> { override suspend fun search(query: String): ArrayList<SearchResponse> {
val search = val search =
app.get("$mainUrl/buscar?q=$query", timeout = 120).document.select(".col-6").map { app.get("$mainUrl/buscar?q=$query", timeout = 120).document.select(".col-6").map {
val title = it.selectFirst(".seristitles").text() val title = it.selectFirst(".seristitles")!!.text()
val href = fixUrl(it.selectFirst("a").attr("href")) val href = fixUrl(it.selectFirst("a")!!.attr("href"))
val image = it.selectFirst("img.animemainimg").attr("src") val image = it.selectFirst("img.animemainimg")!!.attr("src")
AnimeSearchResponse( AnimeSearchResponse(
title, title,
href, href,
@ -107,10 +107,10 @@ class MonoschinosProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val doc = app.get(url, timeout = 120).document val doc = app.get(url, timeout = 120).document
val poster = doc.selectFirst(".chapterpic img").attr("src") val poster = doc.selectFirst(".chapterpic img")!!.attr("src")
val title = doc.selectFirst(".chapterdetails h1").text() val title = doc.selectFirst(".chapterdetails h1")!!.text()
val type = doc.selectFirst("div.chapterdetls2").text() val type = doc.selectFirst("div.chapterdetls2")!!.text()
val description = doc.selectFirst("p.textComplete").text().replace("Ver menos", "") val description = doc.selectFirst("p.textComplete")!!.text().replace("Ver menos", "")
val genres = doc.select(".breadcrumb-item a").map { it.text() } val genres = doc.select(".breadcrumb-item a").map { it.text() }
val status = when (doc.selectFirst("button.btn1")?.text()) { val status = when (doc.selectFirst("button.btn1")?.text()) {
"Estreno" -> ShowStatus.Ongoing "Estreno" -> ShowStatus.Ongoing
@ -118,9 +118,9 @@ class MonoschinosProvider : MainAPI() {
else -> null else -> null
} }
val episodes = doc.select("div.col-item").map { val episodes = doc.select("div.col-item").map {
val name = it.selectFirst("p.animetitles").text() val name = it.selectFirst("p.animetitles")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
val epThumb = it.selectFirst(".animeimghv").attr("data-src") val epThumb = it.selectFirst(".animeimghv")!!.attr("data-src")
Episode(link, name, posterUrl = epThumb) Episode(link, name, posterUrl = epThumb)
} }
return newAnimeLoadResponse(title, url, getType(type)) { return newAnimeLoadResponse(title, url, getType(type)) {

View file

@ -45,11 +45,11 @@ class NineAnimeProvider : MainAPI() {
val home = Jsoup.parse( val home = Jsoup.parse(
app.get( app.get(
url url
).mapped<Response>().html ).parsed<Response>().html
).select("ul.anime-list li").map { ).select("ul.anime-list li").map {
val title = it.selectFirst("a.name").text() val title = it.selectFirst("a.name")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
val poster = it.selectFirst("a.poster img").attr("src") val poster = it.selectFirst("a.poster img")!!.attr("src")
newAnimeSearchResponse(title, link) { newAnimeSearchResponse(title, link) {
this.posterUrl = poster this.posterUrl = poster
@ -173,11 +173,11 @@ class NineAnimeProvider : MainAPI() {
val url = "$mainUrl/filter?sort=title%3Aasc&keyword=$query" val url = "$mainUrl/filter?sort=title%3Aasc&keyword=$query"
return app.get(url).document.select("ul.anime-list li").mapNotNull { return app.get(url).document.select("ul.anime-list li").mapNotNull {
val title = it.selectFirst("a.name").text() val title = it.selectFirst("a.name")!!.text()
val href = val href =
fixUrlNull(it.selectFirst("a").attr("href"))?.replace(Regex("(\\?ep=(\\d+)\$)"), "") fixUrlNull(it.selectFirst("a")!!.attr("href"))?.replace(Regex("(\\?ep=(\\d+)\$)"), "")
?: return@mapNotNull null ?: return@mapNotNull null
val image = it.selectFirst("a.poster img").attr("src") val image = it.selectFirst("a.poster img")!!.attr("src")
AnimeSearchResponse( AnimeSearchResponse(
title, title,
href, href,
@ -199,26 +199,26 @@ class NineAnimeProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val validUrl = url.replace("https://9anime.to", mainUrl) val validUrl = url.replace("https://9anime.to", mainUrl)
val doc = app.get(validUrl).document val doc = app.get(validUrl).document
val animeid = doc.selectFirst("div.player-wrapper.watchpage").attr("data-id") ?: return null val animeid = doc.selectFirst("div.player-wrapper.watchpage")!!.attr("data-id") ?: return null
val animeidencoded = encode(getVrf(animeid) ?: return null) val animeidencoded = encode(getVrf(animeid) ?: return null)
val poster = doc.selectFirst("aside.main div.thumb div img").attr("src") val poster = doc.selectFirst("aside.main div.thumb div img")!!.attr("src")
val title = doc.selectFirst(".info .title").text() val title = doc.selectFirst(".info .title")!!.text()
val description = doc.selectFirst("div.info p").text().replace("Ver menos", "").trim() val description = doc.selectFirst("div.info p")!!.text().replace("Ver menos", "").trim()
val episodes = Jsoup.parse( val episodes = Jsoup.parse(
app.get( app.get(
"$mainUrl/ajax/anime/servers?ep=1&id=${animeid}&vrf=$animeidencoded&ep=8&episode=&token=" "$mainUrl/ajax/anime/servers?ep=1&id=${animeid}&vrf=$animeidencoded&ep=8&episode=&token="
).mapped<Response>().html ).parsed<Response>().html
)?.select("ul.episodes li a")?.mapNotNull { ).select("ul.episodes li a").mapNotNull {
val link = it?.attr("href") ?: return@mapNotNull null val link = it?.attr("href") ?: return@mapNotNull null
val name = "Episode ${it.text()}" val name = "Episode ${it.text()}"
Episode(link, name) Episode(link, name)
} ?: return null }
val recommendations = val recommendations =
doc.select("div.container aside.main section div.body ul.anime-list li") doc.select("div.container aside.main section div.body ul.anime-list li")
?.mapNotNull { element -> .mapNotNull { element ->
val recTitle = element.select("a.name")?.text() ?: return@mapNotNull null val recTitle = element.select("a.name").text() ?: return@mapNotNull null
val image = element.select("a.poster img")?.attr("src") val image = element.select("a.poster img").attr("src")
val recUrl = fixUrl(element.select("a").attr("href")) val recUrl = fixUrl(element.select("a").attr("href"))
newAnimeSearchResponse(recTitle, recUrl) { newAnimeSearchResponse(recTitle, recUrl) {
this.posterUrl = image this.posterUrl = image
@ -226,7 +226,7 @@ class NineAnimeProvider : MainAPI() {
} }
} }
val infodoc = doc.selectFirst("div.info .meta .col1").text() val infodoc = doc.selectFirst("div.info .meta .col1")!!.text()
val tvType = if (infodoc.contains("Movie")) TvType.AnimeMovie else TvType.Anime val tvType = if (infodoc.contains("Movie")) TvType.AnimeMovie else TvType.Anime
val status = val status =
if (infodoc.contains("Completed")) ShowStatus.Completed if (infodoc.contains("Completed")) ShowStatus.Completed
@ -264,13 +264,13 @@ class NineAnimeProvider : MainAPI() {
): Boolean { ): Boolean {
val document = app.get(data).document val document = app.get(data).document
val animeid = val animeid =
document.selectFirst("div.player-wrapper.watchpage").attr("data-id") ?: return false document.selectFirst("div.player-wrapper.watchpage")!!.attr("data-id") ?: return false
val animeidencoded = encode(getVrf(animeid) ?: return false) val animeidencoded = encode(getVrf(animeid) ?: return false)
Jsoup.parse( Jsoup.parse(
app.get( app.get(
"$mainUrl/ajax/anime/servers?&id=${animeid}&vrf=$animeidencoded&episode=&token=" "$mainUrl/ajax/anime/servers?&id=${animeid}&vrf=$animeidencoded&episode=&token="
).mapped<Response>().html ).parsed<Response>().html
).select("div.body").map { element -> ).select("div.body").map { element ->
val jsonregex = Regex("(\\{.+\\}.*$data)") val jsonregex = Regex("(\\{.+\\}.*$data)")
val servers = jsonregex.find(element.toString())?.value?.replace( val servers = jsonregex.find(element.toString())?.value?.replace(

View file

@ -47,6 +47,7 @@ class TenshiProvider : MainAPI() {
override suspend fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val items = ArrayList<HomePageList>() val items = ArrayList<HomePageList>()
val soup = app.get(mainUrl, interceptor = ddosGuardKiller).document val soup = app.get(mainUrl, interceptor = ddosGuardKiller).document
println(soup)
for (section in soup.select("#content > section")) { for (section in soup.select("#content > section")) {
try { try {
if (section.attr("id") == "toplist-tabs") { if (section.attr("id") == "toplist-tabs") {
@ -58,11 +59,11 @@ class TenshiProvider : MainAPI() {
} }
val anime = top.select("li > a").map { val anime = top.select("li > a").map {
AnimeSearchResponse( AnimeSearchResponse(
it.selectFirst(".thumb-title").text(), it.selectFirst(".thumb-title")!!.text(),
fixUrl(it.attr("href")), fixUrl(it.attr("href")),
this.name, this.name,
TvType.Anime, TvType.Anime,
it.selectFirst("img").attr("src"), it.selectFirst("img")!!.attr("src"),
null, null,
EnumSet.of(DubStatus.Subbed), EnumSet.of(DubStatus.Subbed),
) )
@ -70,14 +71,14 @@ class TenshiProvider : MainAPI() {
items.add(HomePageList(title, anime)) items.add(HomePageList(title, anime))
} }
} else { } else {
val title = section.selectFirst("h2").text() val title = section.selectFirst("h2")!!.text()
val anime = section.select("li > a").map { val anime = section.select("li > a").map {
AnimeSearchResponse( AnimeSearchResponse(
it.selectFirst(".thumb-title")?.text() ?: "", it.selectFirst(".thumb-title")?.text() ?: "",
fixUrl(it.attr("href")), fixUrl(it.attr("href")),
this.name, this.name,
TvType.Anime, TvType.Anime,
it.selectFirst("img").attr("src"), it.selectFirst("img")!!.attr("src"),
null, null,
EnumSet.of(DubStatus.Subbed), EnumSet.of(DubStatus.Subbed),
) )
@ -104,7 +105,7 @@ class TenshiProvider : MainAPI() {
val items = soup.select("ul.thumb > li > a") val items = soup.select("ul.thumb > li > a")
return items.map { return items.map {
val href = fixUrl(it.attr("href")) val href = fixUrl(it.attr("href"))
val img = fixUrl(it.selectFirst("img").attr("src")) val img = fixUrl(it.selectFirst("img")!!.attr("src"))
val title = it.attr("title") val title = it.attr("title")
if (getIsMovie(href, true)) { if (getIsMovie(href, true)) {
MovieSearchResponse( MovieSearchResponse(
@ -225,10 +226,10 @@ class TenshiProvider : MainAPI() {
interceptor = ddosGuardKiller interceptor = ddosGuardKiller
).document ).document
val canonicalTitle = document.selectFirst("header.entry-header > h1.mb-3").text().trim() val canonicalTitle = document.selectFirst("header.entry-header > h1.mb-3")!!.text().trim()
val episodeNodes = document.select("li[class*=\"episode\"] > a").toMutableList() val episodeNodes = document.select("li[class*=\"episode\"] > a").toMutableList()
val totalEpisodePages = if (document.select(".pagination").size > 0) val totalEpisodePages = if (document.select(".pagination").size > 0)
document.select(".pagination .page-item a.page-link:not([rel])").last().text() document.select(".pagination .page-item a.page-link:not([rel])").last()!!.text()
.toIntOrNull() .toIntOrNull()
else 1 else 1
@ -283,7 +284,7 @@ class TenshiProvider : MainAPI() {
?.trim() ?.trim()
val pattern = Regex("(\\d{4})") val pattern = Regex("(\\d{4})")
val yearText = document.selectFirst("li.release-date .value").text() val yearText = document.selectFirst("li.release-date .value")!!.text()
year = pattern.find(yearText)?.groupValues?.get(1)?.toIntOrNull() year = pattern.find(yearText)?.groupValues?.get(1)?.toIntOrNull()
addEpisodes(DubStatus.Subbed, episodes) addEpisodes(DubStatus.Subbed, episodes)
@ -310,7 +311,6 @@ class TenshiProvider : MainAPI() {
@JsonProperty("size") val size: Int @JsonProperty("size") val size: Int
) )
val sources = ArrayList<ExtractorLink>()
for (source in soup.select("""[aria-labelledby="mirror-dropdown"] > li > a.dropdown-item""")) { for (source in soup.select("""[aria-labelledby="mirror-dropdown"] > li > a.dropdown-item""")) {
val release = source.text().replace("/", "").trim() val release = source.text().replace("/", "").trim()
val sourceHTML = app.get( val sourceHTML = app.get(
@ -330,24 +330,24 @@ class TenshiProvider : MainAPI() {
.replace(",}", "}") .replace(",}", "}")
.replace(",]", "]") .replace(",]", "]")
) )
sources.addAll(qualities.map { qualities.forEach {
ExtractorLink( callback.invoke(
this.name, ExtractorLink(
"${this.name} $release", this.name,
fixUrl(it.src), "${this.name} $release",
this.mainUrl, fixUrl(it.src),
getQualityFromName("${it.size}"), this.mainUrl,
headers = getHeaders( getQualityFromName("${it.size}"),
mapOf(), headers = getHeaders(emptyMap(),
null, ddosGuardKiller.savedCookiesMap[URI(this.mainUrl).host]
ddosGuardKiller.savedCookiesMap.get(URI(this.mainUrl).host) ?: mapOf() ?: emptyMap()
).toMap() ).toMap()
)
) )
}) }
} }
} }
sources.forEach(callback)
return true return true
} }
} }

View file

@ -38,11 +38,11 @@ class WatchCartoonOnlineProvider : MainAPI() {
for (item in items) { for (item in items) {
val header = item.selectFirst("> div.iccerceve") val header = item.selectFirst("> div.iccerceve")
val titleHeader = header.selectFirst("> div.aramadabaslik > a") val titleHeader = header!!.selectFirst("> div.aramadabaslik > a")
val title = titleHeader.text() val title = titleHeader!!.text()
val href = fixUrl(titleHeader.attr("href")) val href = fixUrl(titleHeader.attr("href"))
val poster = fixUrl(header.selectFirst("> a > img").attr("src")) val poster = fixUrl(header.selectFirst("> a > img")!!.attr("src"))
val genreText = item.selectFirst("div.cerceve-tur-ve-genre").ownText() val genreText = item.selectFirst("div.cerceve-tur-ve-genre")!!.ownText()
if (genreText.contains("cartoon")) { if (genreText.contains("cartoon")) {
returnValue.add(TvSeriesSearchResponse(title, href, this.name, TvType.Cartoon, poster, null, null)) returnValue.add(TvSeriesSearchResponse(title, href, this.name, TvType.Cartoon, poster, null, null))
} else { } else {
@ -76,7 +76,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
for (item in items) { for (item in items) {
val titleHeader = item.selectFirst("a") val titleHeader = item.selectFirst("a")
val title = titleHeader.text() val title = titleHeader!!.text()
val href = fixUrl(titleHeader.attr("href")) val href = fixUrl(titleHeader.attr("href"))
//val isDubbed = title.contains("dubbed") //val isDubbed = title.contains("dubbed")
//val set: EnumSet<DubStatus> = //val set: EnumSet<DubStatus> =
@ -103,9 +103,9 @@ class WatchCartoonOnlineProvider : MainAPI() {
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
return if (!isMovie) { return if (!isMovie) {
val title = document.selectFirst("td.vsbaslik > h2").text() val title = document.selectFirst("td.vsbaslik > h2")!!.text()
val poster = fixUrlNull(document.selectFirst("div#cat-img-desc > div > img")?.attr("src")) val poster = fixUrlNull(document.selectFirst("div#cat-img-desc > div > img")?.attr("src"))
val plot = document.selectFirst("div.iltext").text() val plot = document.selectFirst("div.iltext")!!.text()
val genres = document.select("div#cat-genre > div.wcobtn > a").map { it.text() } val genres = document.select("div#cat-genre > div.wcobtn > a").map { it.text() }
val episodes = document.select("div#catlist-listview > ul > li > a").reversed().map { val episodes = document.select("div#catlist-listview > ul > li > a").reversed().map {
val text = it.text() val text = it.text()
@ -152,7 +152,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
val title = document.selectFirst(".iltext .Apple-style-span")?.text().toString() val title = document.selectFirst(".iltext .Apple-style-span")?.text().toString()
val b = document.select(".iltext b") val b = document.select(".iltext b")
val description = if (b.isNotEmpty()) { val description = if (b.isNotEmpty()) {
b.last().html().split("<br>")[0] b.last()!!.html().split("<br>")[0]
} else null } else null
TvSeriesLoadResponse( TvSeriesLoadResponse(

View file

@ -50,15 +50,15 @@ class WcoProvider : MainAPI() {
val results = document.select("div.flw-item").map { val results = document.select("div.flw-item").map {
val filmPoster = it.selectFirst("> div.film-poster") val filmPoster = it.selectFirst("> div.film-poster")
val filmDetail = it.selectFirst("> div.film-detail") val filmDetail = it.selectFirst("> div.film-detail")
val nameHeader = filmDetail.selectFirst("> h3.film-name > a") val nameHeader = filmDetail!!.selectFirst("> h3.film-name > a")
val title = nameHeader.text().replace(" (Dub)", "") val title = nameHeader!!.text().replace(" (Dub)", "")
val href = val href =
nameHeader.attr("href").replace("/watch/", "/anime/") nameHeader.attr("href").replace("/watch/", "/anime/")
.replace(Regex("-episode-.*"), "/") .replace(Regex("-episode-.*"), "/")
val isDub = val isDub =
filmPoster.selectFirst("> div.film-poster-quality")?.text()?.contains("DUB") filmPoster!!.selectFirst("> div.film-poster-quality")?.text()?.contains("DUB")
?: false ?: false
val poster = filmPoster.selectFirst("> img").attr("data-src") val poster = filmPoster.selectFirst("> img")!!.attr("data-src")
val set: EnumSet<DubStatus> = val set: EnumSet<DubStatus> =
EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed) EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed)
AnimeSearchResponse(title, href, this.name, TvType.Anime, poster, null, set) AnimeSearchResponse(title, href, this.name, TvType.Anime, poster, null, set)
@ -83,15 +83,15 @@ class WcoProvider : MainAPI() {
val items = soup.select(".film_list-wrap > .flw-item") val items = soup.select(".film_list-wrap > .flw-item")
if (items.isEmpty()) return ArrayList() if (items.isEmpty()) return ArrayList()
return items.map { i -> return items.map { i ->
val href = fixAnimeLink(i.selectFirst("a").attr("href")) val href = fixAnimeLink(i.selectFirst("a")!!.attr("href"))
val img = fixUrl(i.selectFirst("img").attr("data-src")) val img = fixUrl(i.selectFirst("img")!!.attr("data-src"))
val title = i.selectFirst("img").attr("title") val title = i.selectFirst("img")!!.attr("title")
val isDub = !i.select(".pick.film-poster-quality").isEmpty() val isDub = !i.select(".pick.film-poster-quality").isEmpty()
val year = val year =
i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(1)").text() i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(1)")!!.text()
.toIntOrNull() .toIntOrNull()
val type = val type =
i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(3)").text() i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(3)")!!.text()
if (getType(type) == TvType.AnimeMovie) { if (getType(type) == TvType.AnimeMovie) {
MovieSearchResponse( MovieSearchResponse(

View file

@ -8,11 +8,11 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream
import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.runSflixExtractorVerifierJob import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.runSflixExtractorVerifierJob
import com.lagradost.cloudstream3.network.Requests.Companion.await
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import com.lagradost.nicehttp.Requests.Companion.await
import okhttp3.Interceptor import okhttp3.Interceptor
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
@ -141,7 +141,7 @@ class ZoroProvider : MainAPI() {
return document.select(".flw-item").map { return document.select(".flw-item").map {
val title = it.selectFirst(".film-detail > .film-name > a")?.attr("title").toString() val title = it.selectFirst(".film-detail > .film-name > a")?.attr("title").toString()
val filmPoster = it.selectFirst(".film-poster") val filmPoster = it.selectFirst(".film-poster")
val poster = filmPoster.selectFirst("img")?.attr("data-src") val poster = filmPoster!!.selectFirst("img")?.attr("data-src")
val episodes = filmPoster.selectFirst("div.rtl > div.tick-eps")?.text()?.let { eps -> val episodes = filmPoster.selectFirst("div.rtl > div.tick-eps")?.text()?.let { eps ->
// current episode / max episode // current episode / max episode
@ -154,7 +154,7 @@ class ZoroProvider : MainAPI() {
val tvType = val tvType =
getType(it.selectFirst(".film-detail > .fd-infor > .fdi-item")?.text().toString()) getType(it.selectFirst(".film-detail > .fd-infor > .fdi-item")?.text().toString())
val href = fixUrl(it.selectFirst(".film-name a").attr("href")) val href = fixUrl(it.selectFirst(".film-name a")!!.attr("href"))
newAnimeSearchResponse(title, href, tvType) { newAnimeSearchResponse(title, href, tvType) {
this.posterUrl = poster this.posterUrl = poster
@ -327,11 +327,11 @@ class ZoroProvider : MainAPI() {
val servers: List<Pair<DubStatus, String>> = Jsoup.parse( val servers: List<Pair<DubStatus, String>> = Jsoup.parse(
app.get("$mainUrl/ajax/v2/episode/servers?episodeId=" + data.split("=")[1]) app.get("$mainUrl/ajax/v2/episode/servers?episodeId=" + data.split("=")[1])
.mapped<Response>().html .parsed<Response>().html
).select(".server-item[data-type][data-id]").map { ).select(".server-item[data-type][data-id]").map {
Pair( Pair(
if (it.attr("data-type") == "sub") DubStatus.Subbed else DubStatus.Dubbed, if (it.attr("data-type") == "sub") DubStatus.Subbed else DubStatus.Dubbed,
it.attr("data-id")!! it.attr("data-id")
) )
} }
@ -344,7 +344,7 @@ class ZoroProvider : MainAPI() {
"$mainUrl/ajax/v2/episode/sources?id=${it.second}" "$mainUrl/ajax/v2/episode/sources?id=${it.second}"
val extractorLink = app.get( val extractorLink = app.get(
link, link,
).mapped<RapidCloudResponse>().link ).parsed<RapidCloudResponse>().link
val hasLoadedExtractorLink = val hasLoadedExtractorLink =
loadExtractor(extractorLink, "https://rapid-cloud.ru/", callback) loadExtractor(extractorLink, "https://rapid-cloud.ru/", callback)

View file

@ -77,7 +77,7 @@ open class WcoStream : ExtractorApi() {
@JsonProperty("media") val media: Media @JsonProperty("media") val media: Media
) )
val mapped = app.get(apiLink, headers = mapOf("Referer" to referrer)).mapped<WcoResponse>() val mapped = app.get(apiLink, headers = mapOf("Referer" to referrer)).parsed<WcoResponse>()
val sources = mutableListOf<ExtractorLink>() val sources = mutableListOf<ExtractorLink>()
if (mapped.success) { if (mapped.success) {

View file

@ -37,14 +37,14 @@ class AllMoviesForYouProvider : MainAPI() {
for ((name, element) in urls) { for ((name, element) in urls) {
try { try {
val home = soup.select(element).map { val home = soup.select(element).map {
val title = it.selectFirst("h2.title").text() val title = it.selectFirst("h2.title")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
TvType.Movie, TvType.Movie,
fixUrl(it.selectFirst("figure img").attr("data-src")), fixUrl(it.selectFirst("figure img")!!.attr("data-src")),
null, null,
null, null,
) )
@ -66,8 +66,8 @@ class AllMoviesForYouProvider : MainAPI() {
val items = document.select("ul.MovieList > li > article > a") val items = document.select("ul.MovieList > li > article > a")
return items.map { item -> return items.map { item ->
val href = item.attr("href") val href = item.attr("href")
val title = item.selectFirst("> h2.Title").text() val title = item.selectFirst("> h2.Title")!!.text()
val img = fixUrl(item.selectFirst("> div.Image > figure > img").attr("data-src")) val img = fixUrl(item.selectFirst("> div.Image > figure > img")!!.attr("data-src"))
val type = getType(href) val type = getType(href)
if (type == TvType.Movie) { if (type == TvType.Movie) {
MovieSearchResponse(title, href, this.name, type, img, null) MovieSearchResponse(title, href, this.name, type, img, null)
@ -108,12 +108,12 @@ class AllMoviesForYouProvider : MainAPI() {
val document = app.get(url).document val document = app.get(url).document
val title = document.selectFirst("h1.Title").text() val title = document.selectFirst("h1.Title")!!.text()
val descipt = document.selectFirst("div.Description > p").text() val descipt = document.selectFirst("div.Description > p")!!.text()
val rating = val rating =
document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toRatingInt() document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toRatingInt()
val year = document.selectFirst("span.Date")?.text() val year = document.selectFirst("span.Date")?.text()
val duration = document.selectFirst("span.Time").text() val duration = document.selectFirst("span.Time")!!.text()
val backgroundPoster = val backgroundPoster =
fixUrlNull(document.selectFirst("div.Image > figure > img")?.attr("data-src")) fixUrlNull(document.selectFirst("div.Image > figure > img")?.attr("data-src"))
@ -140,7 +140,7 @@ class AllMoviesForYouProvider : MainAPI() {
val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull() val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull()
val poster = episode.selectFirst("> td.MvTbImg > a > img")?.attr("data-src") val poster = episode.selectFirst("> td.MvTbImg > a > img")?.attr("data-src")
val aName = episode.selectFirst("> td.MvTbTtl > a") val aName = episode.selectFirst("> td.MvTbTtl > a")
val name = aName.text() val name = aName!!.text()
val href = aName.attr("href") val href = aName.attr("href")
val date = episode.selectFirst("> td.MvTbTtl > span")?.text() val date = episode.selectFirst("> td.MvTbTtl > span")?.text()

View file

@ -32,16 +32,16 @@ open class BflixProvider : MainAPI() {
) )
for ((name, element) in testa) try { for ((name, element) in testa) try {
val test = soup.select(element).map { val test = soup.select(element).map {
val title = it.selectFirst("h3 a").text() val title = it.selectFirst("h3 a")!!.text()
val link = fixUrl(it.selectFirst("a").attr("href")) val link = fixUrl(it.selectFirst("a")!!.attr("href"))
val qualityInfo = it.selectFirst("div.quality").text() val qualityInfo = it.selectFirst("div.quality")!!.text()
val quality = getQualityFromString(qualityInfo) val quality = getQualityFromString(qualityInfo)
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
if (link.contains("/movie/")) TvType.Movie else TvType.TvSeries, if (link.contains("/movie/")) TvType.Movie else TvType.TvSeries,
it.selectFirst("a.poster img").attr("src"), it.selectFirst("a.poster img")!!.attr("src"),
null, null,
null, null,
quality = quality quality = quality
@ -167,11 +167,11 @@ open class BflixProvider : MainAPI() {
val document = Jsoup.parse(html) val document = Jsoup.parse(html)
return document.select(".filmlist div.item").map { return document.select(".filmlist div.item").map {
val title = it.selectFirst("h3 a").text() val title = it.selectFirst("h3 a")!!.text()
val href = fixUrl(it.selectFirst("a").attr("href")) val href = fixUrl(it.selectFirst("a")!!.attr("href"))
val image = it.selectFirst("a.poster img").attr("src") val image = it.selectFirst("a.poster img")!!.attr("src")
val isMovie = href.contains("/movie/") val isMovie = href.contains("/movie/")
val qualityInfo = it.selectFirst("div.quality").text() val qualityInfo = it.selectFirst("div.quality")!!.text()
val quality = getQualityFromString(qualityInfo) val quality = getQualityFromString(qualityInfo)
if (isMovie) { if (isMovie) {
@ -205,33 +205,33 @@ open class BflixProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val soup = app.get(url).document val soup = app.get(url).document
val movieid = soup.selectFirst("div#watch").attr("data-id") val movieid = soup.selectFirst("div#watch")!!.attr("data-id")
val movieidencoded = encode(getVrf(movieid) ?: return null) val movieidencoded = encode(getVrf(movieid) ?: return null)
val title = soup.selectFirst("div.info h1").text() val title = soup.selectFirst("div.info h1")!!.text()
val description = soup.selectFirst(".info .desc")?.text()?.trim() val description = soup.selectFirst(".info .desc")?.text()?.trim()
val poster: String? = try { val poster: String? = try {
soup.selectFirst("img.poster").attr("src") soup.selectFirst("img.poster")!!.attr("src")
} catch (e: Exception) { } catch (e: Exception) {
soup.selectFirst(".info .poster img").attr("src") soup.selectFirst(".info .poster img")!!.attr("src")
} }
val tags = soup.select("div.info .meta div:contains(Genre) a").map { it.text() } val tags = soup.select("div.info .meta div:contains(Genre) a").map { it.text() }
val episodes = Jsoup.parse( val episodes = Jsoup.parse(
app.get( app.get(
"$mainUrl/ajax/film/servers?id=$movieid&vrf=$movieidencoded" "$mainUrl/ajax/film/servers?id=$movieid&vrf=$movieidencoded"
).mapped<Response>().html ).parsed<Response>().html
).select("div.episode").map { ).select("div.episode").map {
val a = it.selectFirst("a") val a = it.selectFirst("a")
val href = fixUrl(a.attr("href")) val href = fixUrl(a!!.attr("href"))
val extraData = a.attr("data-kname")?.let { str -> val extraData = a.attr("data-kname").let { str ->
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() } str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
} }
val isValid = extraData?.size == 2 val isValid = extraData.size == 2
val episode = if (isValid) extraData?.getOrNull(1) else null val episode = if (isValid) extraData.getOrNull(1) else null
val season = if (isValid) extraData?.getOrNull(0) else null val season = if (isValid) extraData.getOrNull(0) else null
val eptitle = it.selectFirst(".episode a span.name").text() val eptitle = it.selectFirst(".episode a span.name")!!.text()
val secondtitle = it.selectFirst(".episode a span").text() val secondtitle = it.selectFirst(".episode a span")!!.text()
.replace(Regex("(Episode (\\d+):|Episode (\\d+)-|Episode (\\d+))"),"") ?: "" .replace(Regex("(Episode (\\d+):|Episode (\\d+)-|Episode (\\d+))"),"") ?: ""
Episode( Episode(
href, href,
@ -329,7 +329,7 @@ open class BflixProvider : MainAPI() {
): Boolean { ): Boolean {
val soup = app.get(data).document val soup = app.get(data).document
val movieid = encode(soup.selectFirst("div#watch").attr("data-id") ?: return false) val movieid = encode(soup.selectFirst("div#watch")?.attr("data-id") ?: return false)
val movieidencoded = encode(getVrf(movieid!!) ?: return false) val movieidencoded = encode(getVrf(movieid!!) ?: return false)
Jsoup.parse( Jsoup.parse(
parseJson<Response>( parseJson<Response>(

View file

@ -31,14 +31,14 @@ class CinecalidadProvider:MainAPI() {
try { try {
val soup = app.get(url).document val soup = app.get(url).document
val home = soup.select(".item.movies").map { val home = soup.select(".item.movies").map {
val title = it.selectFirst("div.in_title").text() val title = it.selectFirst("div.in_title")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
if (link.contains("/ver-pelicula/")) TvType.Movie else TvType.TvSeries, if (link.contains("/ver-pelicula/")) TvType.Movie else TvType.TvSeries,
it.selectFirst(".poster.custom img").attr("data-src"), it.selectFirst(".poster.custom img")!!.attr("data-src"),
null, null,
null, null,
) )
@ -59,9 +59,9 @@ class CinecalidadProvider:MainAPI() {
val document = app.get(url).document val document = app.get(url).document
return document.select("article").map { return document.select("article").map {
val title = it.selectFirst("div.in_title").text() val title = it.selectFirst("div.in_title")!!.text()
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val image = it.selectFirst(".poster.custom img").attr("data-src") val image = it.selectFirst(".poster.custom img")!!.attr("data-src")
val isMovie = href.contains("/ver-pelicula/") val isMovie = href.contains("/ver-pelicula/")
if (isMovie) { if (isMovie) {
@ -91,14 +91,14 @@ class CinecalidadProvider:MainAPI() {
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val soup = app.get(url, timeout = 120).document val soup = app.get(url, timeout = 120).document
val title = soup.selectFirst(".single_left h1").text() val title = soup.selectFirst(".single_left h1")!!.text()
val description = soup.selectFirst("div.single_left table tbody tr td p")?.text()?.trim() val description = soup.selectFirst("div.single_left table tbody tr td p")?.text()?.trim()
val poster: String? = soup.selectFirst(".alignnone").attr("data-src") val poster: String? = soup.selectFirst(".alignnone")!!.attr("data-src")
val episodes = soup.select("div.se-c div.se-a ul.episodios li").map { li -> val episodes = soup.select("div.se-c div.se-a ul.episodios li").map { li ->
val href = li.selectFirst("a").attr("href") val href = li.selectFirst("a")!!.attr("href")
val epThumb = li.selectFirst("img.lazy").attr("data-src") val epThumb = li.selectFirst("img.lazy")!!.attr("data-src")
val name = li.selectFirst(".episodiotitle a").text() val name = li.selectFirst(".episodiotitle a")!!.text()
val seasonid = li.selectFirst(".numerando").text().replace(Regex("(S|E)"),"").let { str -> val seasonid = li.selectFirst(".numerando")!!.text().replace(Regex("(S|E)"),"").let { str ->
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() } str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
} }
val isValid = seasonid.size == 2 val isValid = seasonid.size == 2
@ -182,7 +182,7 @@ class CinecalidadProvider:MainAPI() {
"Sec-Fetch-Site" to "same-origin", "Sec-Fetch-Site" to "same-origin",
"Sec-Fetch-User" to "?1", "Sec-Fetch-User" to "?1",
), ),
allowRedirects = false).response.headers.values("location").apmap { extractedurl -> allowRedirects = false).okhttpResponse.headers.values("location").apmap { extractedurl ->
if (extractedurl.contains("cinestart")) { if (extractedurl.contains("cinestart")) {
loadExtractor(extractedurl, mainUrl, callback) loadExtractor(extractedurl, mainUrl, callback)
} }
@ -221,7 +221,7 @@ class CinecalidadProvider:MainAPI() {
"Sec-Fetch-Site" to "same-origin", "Sec-Fetch-Site" to "same-origin",
"Sec-Fetch-User" to "?1", "Sec-Fetch-User" to "?1",
), ),
allowRedirects = false).response.headers.values("location").apmap { extractedurl -> allowRedirects = false).okhttpResponse.headers.values("location").apmap { extractedurl ->
if (extractedurl.contains("cinestart")) { if (extractedurl.contains("cinestart")) {
loadExtractor(extractedurl, mainUrl, callback) loadExtractor(extractedurl, mainUrl, callback)
} }
@ -238,7 +238,7 @@ class CinecalidadProvider:MainAPI() {
val validsub = docsub.text val validsub = docsub.text
if (validsub.contains("Subtítulo") || validsub.contains("Forzados")) { if (validsub.contains("Subtítulo") || validsub.contains("Forzados")) {
val langregex = Regex("(Subtítulo.*\$|Forzados.*\$)") val langregex = Regex("(Subtítulo.*\$|Forzados.*\$)")
val langdoc = linksub.selectFirst("div.titulo h3").text() val langdoc = linksub.selectFirst("div.titulo h3")!!.text()
val reallang = langregex.find(langdoc)?.destructured?.component1() val reallang = langregex.find(langdoc)?.destructured?.component1()
linksub.select("a.link").apmap { linksub.select("a.link").apmap {
val sublink = if (data.contains("serie") || data.contains("episodio")) "${data}${it.attr("href")}" val sublink = if (data.contains("serie") || data.contains("episodio")) "${data}${it.attr("href")}"

View file

@ -30,9 +30,9 @@ class CuevanaProvider : MainAPI() {
"Series", "Series",
app.get("$mainUrl/serie", timeout = 120).document.select("section.home-series li") app.get("$mainUrl/serie", timeout = 120).document.select("section.home-series li")
.map { .map {
val title = it.selectFirst("h2.Title").text() val title = it.selectFirst("h2.Title")!!.text()
val poster = it.selectFirst("img.lazy").attr("data-src") val poster = it.selectFirst("img.lazy")!!.attr("data-src")
val url = it.selectFirst("a").attr("href") val url = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
url, url,
@ -48,14 +48,14 @@ class CuevanaProvider : MainAPI() {
try { try {
val soup = app.get(url).document val soup = app.get(url).document
val home = soup.select("section li.xxx.TPostMv").map { val home = soup.select("section li.xxx.TPostMv").map {
val title = it.selectFirst("h2.Title").text() val title = it.selectFirst("h2.Title")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
if (link.contains("/pelicula/")) TvType.Movie else TvType.TvSeries, if (link.contains("/pelicula/")) TvType.Movie else TvType.TvSeries,
it.selectFirst("img.lazy").attr("data-src"), it.selectFirst("img.lazy")!!.attr("data-src"),
null, null,
null, null,
) )
@ -76,9 +76,9 @@ class CuevanaProvider : MainAPI() {
val document = app.get(url).document val document = app.get(url).document
return document.select("li.xxx.TPostMv").map { return document.select("li.xxx.TPostMv").map {
val title = it.selectFirst("h2.Title").text() val title = it.selectFirst("h2.Title")!!.text()
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val image = it.selectFirst("img.lazy").attr("data-src") val image = it.selectFirst("img.lazy")!!.attr("data-src")
val isSerie = href.contains("/serie/") val isSerie = href.contains("/serie/")
if (isSerie) { if (isSerie) {
@ -106,9 +106,9 @@ class CuevanaProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val soup = app.get(url, timeout = 120).document val soup = app.get(url, timeout = 120).document
val title = soup.selectFirst("h1.Title").text() val title = soup.selectFirst("h1.Title")!!.text()
val description = soup.selectFirst(".Description p")?.text()?.trim() val description = soup.selectFirst(".Description p")?.text()?.trim()
val poster: String? = soup.selectFirst(".movtv-info div.Image img").attr("data-src") val poster: String? = soup.selectFirst(".movtv-info div.Image img")!!.attr("data-src")
val year1 = soup.selectFirst("footer p.meta").toString() val year1 = soup.selectFirst("footer p.meta").toString()
val yearRegex = Regex("<span>(\\d+)</span>") val yearRegex = Regex("<span>(\\d+)</span>")
val yearf = val yearf =
@ -117,9 +117,9 @@ class CuevanaProvider : MainAPI() {
val episodes = soup.select(".all-episodes li.TPostMv article").map { li -> val episodes = soup.select(".all-episodes li.TPostMv article").map { li ->
val href = li.select("a").attr("href") val href = li.select("a").attr("href")
val epThumb = val epThumb =
li.selectFirst("div.Image img").attr("data-src") ?: li.selectFirst("img.lazy") li.selectFirst("div.Image img")?.attr("data-src") ?: li.selectFirst("img.lazy")!!
.attr("data-srcc") .attr("data-srcc")
val seasonid = li.selectFirst("span.Year").text().let { str -> val seasonid = li.selectFirst("span.Year")!!.text().let { str ->
str.split("x").mapNotNull { subStr -> subStr.toIntOrNull() } str.split("x").mapNotNull { subStr -> subStr.toIntOrNull() }
} }
val isValid = seasonid.size == 2 val isValid = seasonid.size == 2
@ -255,7 +255,7 @@ class CuevanaProvider : MainAPI() {
"Sec-Fetch-Site" to "same-origin", "Sec-Fetch-Site" to "same-origin",
), ),
data = mapOf(Pair("url", tomkey)) data = mapOf(Pair("url", tomkey))
).response.headers.values("location").apmap { loc -> ).okhttpResponse.headers.values("location").apmap { loc ->
if (loc.contains("goto_ddh.php")) { if (loc.contains("goto_ddh.php")) {
val gotoregex = val gotoregex =
Regex("(\\/\\/api.cuevana3.me\\/ir\\/goto_ddh.php\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)") Regex("(\\/\\/api.cuevana3.me\\/ir\\/goto_ddh.php\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
@ -280,7 +280,7 @@ class CuevanaProvider : MainAPI() {
"Sec-Fetch-Site" to "same-origin", "Sec-Fetch-Site" to "same-origin",
), ),
data = mapOf(Pair("url", gotolink)) data = mapOf(Pair("url", gotolink))
).response.headers.values("location").apmap { golink -> ).okhttpResponse.headers.values("location").apmap { golink ->
loadExtractor(golink, data, callback) loadExtractor(golink, data, callback)
} }
} }
@ -310,7 +310,7 @@ class CuevanaProvider : MainAPI() {
"Sec-Fetch-User" to "?1", "Sec-Fetch-User" to "?1",
), ),
data = mapOf(Pair("h", inlink)) data = mapOf(Pair("h", inlink))
).response.headers.values("location").apmap { link -> ).okhttpResponse.headers.values("location").apmap { link ->
loadExtractor(link, data, callback) loadExtractor(link, data, callback)
} }
} }

View file

@ -52,12 +52,12 @@ class DoramasYTProvider : MainAPI() {
HomePageList( HomePageList(
"Capítulos actualizados", "Capítulos actualizados",
app.get(mainUrl, timeout = 120).document.select(".col-6").map { app.get(mainUrl, timeout = 120).document.select(".col-6").map {
val title = it.selectFirst("p").text() val title = it.selectFirst("p")!!.text()
val poster = it.selectFirst(".chapter img").attr("src") val poster = it.selectFirst(".chapter img")!!.attr("src")
val epRegex = Regex("episodio-(\\d+)") val epRegex = Regex("episodio-(\\d+)")
val url = it.selectFirst("a").attr("href").replace("ver/", "dorama/") val url = it.selectFirst("a")!!.attr("href").replace("ver/", "dorama/")
.replace(epRegex, "sub-espanol") .replace(epRegex, "sub-espanol")
val epNum = it.selectFirst("h3").text().toIntOrNull() val epNum = it.selectFirst("h3")!!.text().toIntOrNull()
newAnimeSearchResponse(title,url) { newAnimeSearchResponse(title,url) {
this.posterUrl = fixUrl(poster) this.posterUrl = fixUrl(poster)
addDubStatus(getDubStatus(title), epNum) addDubStatus(getDubStatus(title), epNum)
@ -68,9 +68,9 @@ class DoramasYTProvider : MainAPI() {
for (i in urls) { for (i in urls) {
try { try {
val home = app.get(i.first, timeout = 120).document.select(".col-6").map { val home = app.get(i.first, timeout = 120).document.select(".col-6").map {
val title = it.selectFirst(".animedtls p").text() val title = it.selectFirst(".animedtls p")!!.text()
val poster = it.selectFirst(".anithumb img").attr("src") val poster = it.selectFirst(".anithumb img")!!.attr("src")
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) { newAnimeSearchResponse(title, fixUrl(it.selectFirst("a")!!.attr("href"))) {
this.posterUrl = fixUrl(poster) this.posterUrl = fixUrl(poster)
addDubStatus(getDubStatus(title)) addDubStatus(getDubStatus(title))
} }
@ -88,9 +88,9 @@ class DoramasYTProvider : MainAPI() {
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
return app.get("$mainUrl/buscar?q=$query", timeout = 120).document.select(".col-6").map { return app.get("$mainUrl/buscar?q=$query", timeout = 120).document.select(".col-6").map {
val title = it.selectFirst(".animedtls p").text() val title = it.selectFirst(".animedtls p")!!.text()
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val image = it.selectFirst(".animes img").attr("src") val image = it.selectFirst(".animes img")!!.attr("src")
AnimeSearchResponse( AnimeSearchResponse(
title, title,
href, href,
@ -107,10 +107,10 @@ class DoramasYTProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val doc = app.get(url, timeout = 120).document val doc = app.get(url, timeout = 120).document
val poster = doc.selectFirst("div.flimimg img.img1").attr("src") val poster = doc.selectFirst("div.flimimg img.img1")!!.attr("src")
val title = doc.selectFirst("h1").text() val title = doc.selectFirst("h1")!!.text()
val type = doc.selectFirst("h4").text() val type = doc.selectFirst("h4")!!.text()
val description = doc.selectFirst("p.textComplete").text().replace("Ver menos", "") val description = doc.selectFirst("p.textComplete")!!.text().replace("Ver menos", "")
val genres = doc.select(".nobel a").map { it.text() } val genres = doc.select(".nobel a").map { it.text() }
val status = when (doc.selectFirst(".state h6")?.text()) { val status = when (doc.selectFirst(".state h6")?.text()) {
"Estreno" -> ShowStatus.Ongoing "Estreno" -> ShowStatus.Ongoing
@ -118,9 +118,9 @@ class DoramasYTProvider : MainAPI() {
else -> null else -> null
} }
val episodes = doc.select(".heromain .col-item").map { val episodes = doc.select(".heromain .col-item").map {
val name = it.selectFirst(".dtlsflim p").text() val name = it.selectFirst(".dtlsflim p")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
val epThumb = it.selectFirst(".flimimg img.img1").attr("src") val epThumb = it.selectFirst(".flimimg img.img1")!!.attr("src")
Episode(link, name, posterUrl = epThumb) Episode(link, name, posterUrl = epThumb)
} }
return newAnimeLoadResponse(title, url, getType(type)) { return newAnimeLoadResponse(title, url, getType(type)) {

View file

@ -46,7 +46,7 @@ class EgyBestProvider : MainAPI() {
val pages = arrayListOf<HomePageList>() val pages = arrayListOf<HomePageList>()
doc.select("#mainLoad div.mbox").apmap { doc.select("#mainLoad div.mbox").apmap {
val name = it.select(".bdb.pda > strong").text() val name = it.select(".bdb.pda > strong").text()
if (it.select(".movie").first().attr("href").contains("season-(.....)|ep-(.....)".toRegex())) return@apmap if (it.select(".movie").first()?.attr("href")?.contains("season-(.....)|ep-(.....)".toRegex()) == true) return@apmap
val list = arrayListOf<SearchResponse>() val list = arrayListOf<SearchResponse>()
it.select(".movie").map { element -> it.select(".movie").map { element ->
list.add(element.toSearchResponse()!!) list.add(element.toSearchResponse()!!)
@ -87,16 +87,16 @@ class EgyBestProvider : MainAPI() {
it.text().contains("النوع") it.text().contains("النوع")
}?.select("a")?.map { it.text() } }?.select("a")?.map { it.text() }
val actors = doc.select("div.cast_list .cast_item")?.mapNotNull { val actors = doc.select("div.cast_list .cast_item").mapNotNull {
val name = it.selectFirst("div > a > img")?.attr("alt") ?: return@mapNotNull null val name = it.selectFirst("div > a > img")?.attr("alt") ?: return@mapNotNull null
val image = it.selectFirst("div > a > img")?.attr("src") ?: return@mapNotNull null val image = it.selectFirst("div > a > img")?.attr("src") ?: return@mapNotNull null
val roleString = it.selectFirst("div > span").text() val roleString = it.selectFirst("div > span")!!.text()
val mainActor = Actor(name, image) val mainActor = Actor(name, image)
ActorData(actor = mainActor, roleString = roleString) ActorData(actor = mainActor, roleString = roleString)
} }
return if (isMovie) { return if (isMovie) {
val recommendations = doc.select(".movies_small .movie")?.mapNotNull { element -> val recommendations = doc.select(".movies_small .movie").mapNotNull { element ->
element.toSearchResponse() element.toSearchResponse()
} }

View file

@ -30,14 +30,14 @@ class EntrepeliculasyseriesProvider:MainAPI() {
try { try {
val soup = app.get(url).document val soup = app.get(url).document
val home = soup.select("ul.list-movie li").map { val home = soup.select("ul.list-movie li").map {
val title = it.selectFirst("a.link-title h2").text() val title = it.selectFirst("a.link-title h2")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
if (link.contains("/pelicula/")) TvType.Movie else TvType.TvSeries, if (link.contains("/pelicula/")) TvType.Movie else TvType.TvSeries,
it.selectFirst("a.poster img").attr("src"), it.selectFirst("a.poster img")!!.attr("src"),
null, null,
null, null,
) )
@ -58,9 +58,9 @@ class EntrepeliculasyseriesProvider:MainAPI() {
val document = app.get(url).document val document = app.get(url).document
return document.select("li.xxx.TPostMv").map { return document.select("li.xxx.TPostMv").map {
val title = it.selectFirst("h2.Title").text() val title = it.selectFirst("h2.Title")!!.text()
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val image = it.selectFirst("img.lazy").attr("data-src") val image = it.selectFirst("img.lazy")!!.attr("data-src")
val isMovie = href.contains("/pelicula/") val isMovie = href.contains("/pelicula/")
if (isMovie) { if (isMovie) {
@ -90,13 +90,13 @@ class EntrepeliculasyseriesProvider:MainAPI() {
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val soup = app.get(url, timeout = 120).document val soup = app.get(url, timeout = 120).document
val title = soup.selectFirst("h1.title-post").text() val title = soup.selectFirst("h1.title-post")!!.text()
val description = soup.selectFirst("p.text-content:nth-child(3)")?.text()?.trim() val description = soup.selectFirst("p.text-content:nth-child(3)")?.text()?.trim()
val poster: String? = soup.selectFirst("article.TPost img.lazy").attr("data-src") val poster: String? = soup.selectFirst("article.TPost img.lazy")!!.attr("data-src")
val episodes = soup.select(".TPostMv article").map { li -> val episodes = soup.select(".TPostMv article").map { li ->
val href = (li.select("a") ?: li.select(".C a") ?: li.select("article a")).attr("href") val href = (li.select("a") ?: li.select(".C a") ?: li.select("article a")).attr("href")
val epThumb = li.selectFirst("div.Image img").attr("data-src") val epThumb = li.selectFirst("div.Image img")!!.attr("data-src")
val seasonid = li.selectFirst("span.Year").text().let { str -> val seasonid = li.selectFirst("span.Year")!!.text().let { str ->
str.split("x").mapNotNull { subStr -> subStr.toIntOrNull() } str.split("x").mapNotNull { subStr -> subStr.toIntOrNull() }
} }
val isValid = seasonid.size == 2 val isValid = seasonid.size == 2
@ -169,7 +169,7 @@ class EntrepeliculasyseriesProvider:MainAPI() {
//params = mapOf(Pair("h", postkey)), //params = mapOf(Pair("h", postkey)),
data = mapOf(Pair("h", postkey)), data = mapOf(Pair("h", postkey)),
allowRedirects = false allowRedirects = false
).response.headers.values("location").apmap { ).okhttpResponse.headers.values("location").apmap {
loadExtractor(it, data, callback) loadExtractor(it, data, callback)
} }
} }

View file

@ -24,7 +24,7 @@ class FilmanProvider : MainAPI() {
val lists = document.select(".item-list,.series-list") val lists = document.select(".item-list,.series-list")
val categories = ArrayList<HomePageList>() val categories = ArrayList<HomePageList>()
for (l in lists) { for (l in lists) {
val title = l.parent().select("h3").text() val title = l.parent()!!.select("h3").text()
val items = l.select(".poster").map { i -> val items = l.select(".poster").map { i ->
val name = i.select("a[href]").attr("title") val name = i.select("a[href]").attr("title")
val href = i.select("a[href]").attr("href") val href = i.select("a[href]").attr("href")
@ -63,8 +63,8 @@ class FilmanProvider : MainAPI() {
fun getVideos(type: TvType, items: Elements): List<SearchResponse> { fun getVideos(type: TvType, items: Elements): List<SearchResponse> {
return items.map { i -> return items.map { i ->
val href = i.attr("href") val href = i.attr("href")
val img = i.selectFirst("> img").attr("src").replace("/thumb/", "/big/") val img = i.selectFirst("> img")!!.attr("src").replace("/thumb/", "/big/")
val name = i.selectFirst(".title").text() val name = i.selectFirst(".title")!!.text()
if (type === TvType.TvSeries) { if (type === TvType.TvSeries) {
TvSeriesSearchResponse( TvSeriesSearchResponse(
name, name,
@ -95,7 +95,7 @@ class FilmanProvider : MainAPI() {
if (episodesElements.isEmpty()) { if (episodesElements.isEmpty()) {
return MovieLoadResponse(title, url, name, TvType.Movie, data, posterUrl, year, plot) return MovieLoadResponse(title, url, name, TvType.Movie, data, posterUrl, year, plot)
} }
title = document.selectFirst(".info").parent().select("h2").text() title = document.selectFirst(".info")?.parent()?.select("h2")?.text() ?: ""
val episodes = episodesElements.mapNotNull { episode -> val episodes = episodesElements.mapNotNull { episode ->
val e = episode.text() val e = episode.text()
val regex = Regex("""\[s(\d{1,3})e(\d{1,3})]""").find(e) ?: return@mapNotNull null val regex = Regex("""\[s(\d{1,3})e(\d{1,3})]""").find(e) ?: return@mapNotNull null
@ -130,7 +130,7 @@ class FilmanProvider : MainAPI() {
app.get(data).document.select("#links").first() app.get(data).document.select("#links").first()
else Jsoup.parse(data) else Jsoup.parse(data)
document.select(".link-to-video")?.apmap { item -> document?.select(".link-to-video")?.apmap { item ->
val decoded = base64Decode(item.select("a").attr("data-iframe")) val decoded = base64Decode(item.select("a").attr("data-iframe"))
val link = mapper.readValue<LinkElement>(decoded).src val link = mapper.readValue<LinkElement>(decoded).src
loadExtractor(link, null, callback) loadExtractor(link, null, callback)

View file

@ -23,9 +23,9 @@ class HDMProvider : MainAPI() {
return items.map { i -> return items.map { i ->
val href = i.attr("href") val href = i.attr("href")
val data = i.selectFirst("> div.item") val data = i.selectFirst("> div.item")!!
val img = data.selectFirst("> img").attr("src") val img = data.selectFirst("> img")!!.attr("src")
val name = data.selectFirst("> div.movie-details").text() val name = data.selectFirst("> div.movie-details")!!.text()
MovieSearchResponse(name, href, this.name, TvType.Movie, img, null) MovieSearchResponse(name, href, this.name, TvType.Movie, img, null)
} }
} }
@ -57,9 +57,9 @@ class HDMProvider : MainAPI() {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val title = document.selectFirst("h2.movieTitle")?.text() ?: throw ErrorLoadingException("No Data Found") val title = document.selectFirst("h2.movieTitle")?.text() ?: throw ErrorLoadingException("No Data Found")
val poster = document.selectFirst("div.post-thumbnail > img").attr("src") val poster = document.selectFirst("div.post-thumbnail > img")!!.attr("src")
val descript = document.selectFirst("div.synopsis > p").text() val descript = document.selectFirst("div.synopsis > p")!!.text()
val year = document.select("div.movieInfoAll > div.row > div.col-md-6")?.get(1)?.selectFirst("> p > a")?.text() val year = document.select("div.movieInfoAll > div.row > div.col-md-6").getOrNull(1)?.selectFirst("> p > a")?.text()
?.toIntOrNull() ?.toIntOrNull()
val data = "src/player/\\?v=(.*?)\"".toRegex().find(response)?.groupValues?.get(1) ?: return null val data = "src/player/\\?v=(.*?)\"".toRegex().find(response)?.groupValues?.get(1) ?: return null

View file

@ -56,10 +56,10 @@ class IHaveNoTvProvider : MainAPI() {
res.selectFirst("a[href][title]") res.selectFirst("a[href][title]")
} }
val year = Regex("""•?\s+(\d{4})\s+•""").find( val year = Regex("""•?\s+(\d{4})\s+•""").find(
res.selectFirst(".episodeMeta").text() res.selectFirst(".episodeMeta")!!.text()
)?.destructured?.component1()?.toIntOrNull() )?.destructured?.component1()?.toIntOrNull()
val title = aTag.attr("title") val title = aTag!!.attr("title")
val href = fixUrl(aTag.attr("href")) val href = fixUrl(aTag.attr("href"))
searchResults[href] = TvSeriesSearchResponse( searchResults[href] = TvSeriesSearchResponse(
title, title,
@ -98,11 +98,11 @@ class IHaveNoTvProvider : MainAPI() {
} }
val year = val year =
Regex("""•?\s+(\d{4})\s+•""").find( Regex("""•?\s+(\d{4})\s+•""").find(
res.selectFirst(".episodeMeta").text() res.selectFirst(".episodeMeta")!!.text()
)?.destructured?.component1() )?.destructured?.component1()
?.toIntOrNull() ?.toIntOrNull()
val title = aTag.attr("title") val title = aTag!!.attr("title")
val href = fixUrl(aTag.attr("href")) val href = fixUrl(aTag.attr("href"))
searchResults[href] = TvSeriesSearchResponse( searchResults[href] = TvSeriesSearchResponse(
title, title,
@ -126,7 +126,7 @@ class IHaveNoTvProvider : MainAPI() {
val container = soup.selectFirst(".container-fluid h1")?.parent() val container = soup.selectFirst(".container-fluid h1")?.parent()
val title = if (isSeries) { val title = if (isSeries) {
container?.selectFirst("h1")?.text()?.split("")?.firstOrNull().toString() container?.selectFirst("h1")?.text()?.split("")?.firstOrNull().toString()
} else soup.selectFirst(".videoDetails").selectFirst("strong")?.text().toString() } else soup.selectFirst(".videoDetails")!!.selectFirst("strong")?.text().toString()
val description = if (isSeries) { val description = if (isSeries) {
container?.selectFirst("p")?.text() container?.selectFirst("p")?.text()
} else { } else {
@ -138,11 +138,11 @@ class IHaveNoTvProvider : MainAPI() {
val episodes = if (isSeries) { val episodes = if (isSeries) {
container?.select(".episode")?.map { ep -> container?.select(".episode")?.map { ep ->
val thumb = ep.selectFirst("img").attr("src") val thumb = ep.selectFirst("img")!!.attr("src")
val epLink = fixUrl(ep.selectFirst("a[title]").attr("href")) val epLink = fixUrl(ep.selectFirst("a[title]")!!.attr("href"))
val (season, epNum) = if (ep.selectFirst(".episodeMeta > strong") != null && val (season, epNum) = if (ep.selectFirst(".episodeMeta > strong") != null &&
ep.selectFirst(".episodeMeta > strong").html().contains("S") ep.selectFirst(".episodeMeta > strong")!!.html().contains("S")
) { ) {
val split = ep.selectFirst(".episodeMeta > strong")?.text()?.split("E") val split = ep.selectFirst(".episodeMeta > strong")?.text()?.split("E")
Pair( Pair(
@ -152,14 +152,14 @@ class IHaveNoTvProvider : MainAPI() {
} else Pair<Int?, Int?>(null, null) } else Pair<Int?, Int?>(null, null)
year = Regex("""•?\s+(\d{4})\s+•""").find( year = Regex("""•?\s+(\d{4})\s+•""").find(
ep.selectFirst(".episodeMeta").text() ep.selectFirst(".episodeMeta")!!.text()
)?.destructured?.component1()?.toIntOrNull() )?.destructured?.component1()?.toIntOrNull()
categories.addAll( categories.addAll(
ep.select(".episodeMeta > a[href*=\"/category/\"]").map { it.text().trim() }) ep.select(".episodeMeta > a[href*=\"/category/\"]").map { it.text().trim() })
newEpisode(epLink) { newEpisode(epLink) {
this.name = ep.selectFirst("a[title]").attr("title") this.name = ep.selectFirst("a[title]")!!.attr("title")
this.season = season this.season = season
this.episode = epNum this.episode = epNum
this.posterUrl = thumb this.posterUrl = thumb
@ -173,13 +173,13 @@ class IHaveNoTvProvider : MainAPI() {
this.name, this.name,
TvType.Movie, TvType.Movie,
url, url,
soup.selectFirst("[rel=\"image_src\"]").attr("href"), soup.selectFirst("[rel=\"image_src\"]")!!.attr("href"),
Regex("""•?\s+(\d{4})\s+•""").find( Regex("""•?\s+(\d{4})\s+•""").find(
soup.selectFirst(".videoDetails").text() soup.selectFirst(".videoDetails")!!.text()
)?.destructured?.component1()?.toIntOrNull(), )?.destructured?.component1()?.toIntOrNull(),
description, description,
null, null,
soup.selectFirst(".videoDetails").select("a[href*=\"/category/\"]") soup.selectFirst(".videoDetails")!!.select("a[href*=\"/category/\"]")
.map { it.text().trim() } .map { it.text().trim() }
)) ))
} }

View file

@ -33,17 +33,14 @@ class KdramaHoodProvider : MainAPI() {
// Hardcoded homepage cause of site implementation // Hardcoded homepage cause of site implementation
// Recently added // Recently added
val recentlyInner = doc.selectFirst("div.peliculas") val recentlyInner = doc.selectFirst("div.peliculas")
val recentlyAddedTitle = recentlyInner.selectFirst("h1")?.text() ?: "Recently Added" val recentlyAddedTitle = recentlyInner!!.selectFirst("h1")?.text() ?: "Recently Added"
val recentlyAdded = recentlyInner.select("div.item_2.items > div.fit.item")?.mapNotNull { val recentlyAdded = recentlyInner.select("div.item_2.items > div.fit.item").mapNotNull {
if (it == null) {
return@mapNotNull null
}
val innerA = it.select("div.image > a") ?: return@mapNotNull null val innerA = it.select("div.image > a") ?: return@mapNotNull null
val link = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null val link = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
val image = fixUrlNull(innerA.select("img")?.attr("src")) val image = fixUrlNull(innerA.select("img").attr("src"))
val innerData = it.selectFirst("div.data") val innerData = it.selectFirst("div.data")
val title = innerData.selectFirst("h1")?.text() ?: return@mapNotNull null val title = innerData!!.selectFirst("h1")?.text() ?: return@mapNotNull null
val year = try { val year = try {
val yearText = innerData.selectFirst("span.titulo_o") val yearText = innerData.selectFirst("span.titulo_o")
?.text()?.takeLast(11)?.trim()?.take(4) ?: "" ?.text()?.takeLast(11)?.trim()?.take(4) ?: ""
@ -61,7 +58,7 @@ class KdramaHoodProvider : MainAPI() {
posterUrl = image, posterUrl = image,
year = year year = year
) )
}?.distinctBy { it.url } ?: listOf() }.distinctBy { it.url } ?: listOf()
home.add(HomePageList(recentlyAddedTitle, recentlyAdded)) home.add(HomePageList(recentlyAddedTitle, recentlyAdded))
return HomePageResponse(home.filter { it.list.isNotEmpty() }) return HomePageResponse(home.filter { it.list.isNotEmpty() })
} }
@ -102,15 +99,15 @@ class KdramaHoodProvider : MainAPI() {
val title = inner?.selectFirst("h1")?.text() ?: "" val title = inner?.selectFirst("h1")?.text() ?: ""
val poster = fixUrlNull(doc.selectFirst("meta[property=og:image]")?.attr("content")) ?: "" val poster = fixUrlNull(doc.selectFirst("meta[property=og:image]")?.attr("content")) ?: ""
//Log.i(this.name, "Result => (poster) ${poster}") //Log.i(this.name, "Result => (poster) ${poster}")
val info = inner.selectFirst("div#info") val info = inner!!.selectFirst("div#info")
val descript = inner?.selectFirst("div.contenidotv > div > p")?.text() val descript = inner.selectFirst("div.contenidotv > div > p")?.text()
val year = try { val year = try {
val startLink = "https://kdramahood.com/drama-release-year/" val startLink = "https://kdramahood.com/drama-release-year/"
var res: Int? = null var res: Int? = null
info.select("div.metadatac")?.forEach { info?.select("div.metadatac")?.forEach {
if (res != null) { return@forEach } if (res != null) { return@forEach }
if (it == null) { return@forEach } if (it == null) { return@forEach }
val yearLink = it.select("a")?.attr("href") ?: return@forEach val yearLink = it.select("a").attr("href") ?: return@forEach
if (yearLink.startsWith(startLink)) { if (yearLink.startsWith(startLink)) {
res = yearLink.substring(startLink.length).replace("/", "").toIntOrNull() res = yearLink.substring(startLink.length).replace("/", "").toIntOrNull()
} }
@ -118,13 +115,13 @@ class KdramaHoodProvider : MainAPI() {
res res
} catch (e: Exception) { null } } catch (e: Exception) { null }
val recs = doc.select("div.sidebartv > div.tvitemrel")?.mapNotNull { val recs = doc.select("div.sidebartv > div.tvitemrel").mapNotNull {
val a = it?.select("a") ?: return@mapNotNull null val a = it?.select("a") ?: return@mapNotNull null
val aUrl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null val aUrl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null
val aImg = a.select("img") val aImg = a.select("img")
val aCover = fixUrlNull(aImg?.attr("src")) ?: fixUrlNull(aImg?.attr("data-src")) val aCover = fixUrlNull(aImg.attr("src")) ?: fixUrlNull(aImg.attr("data-src"))
val aNameYear = a.select("div.datatvrel") ?: return@mapNotNull null val aNameYear = a.select("div.datatvrel") ?: return@mapNotNull null
val aName = aNameYear.select("h4")?.text() ?: aImg?.attr("alt") ?: return@mapNotNull null val aName = aNameYear.select("h4").text() ?: aImg.attr("alt") ?: return@mapNotNull null
val aYear = aName.trim().takeLast(5).removeSuffix(")").toIntOrNull() val aYear = aName.trim().takeLast(5).removeSuffix(")").toIntOrNull()
MovieSearchResponse( MovieSearchResponse(
url = aUrl, url = aUrl,
@ -137,7 +134,7 @@ class KdramaHoodProvider : MainAPI() {
} }
// Episodes Links // Episodes Links
val episodeList = inner?.select("ul.episodios > li")?.mapNotNull { ep -> val episodeList = inner.select("ul.episodios > li")?.mapNotNull { ep ->
//Log.i(this.name, "Result => (ep) ${ep}") //Log.i(this.name, "Result => (ep) ${ep}")
val listOfLinks = mutableListOf<String>() val listOfLinks = mutableListOf<String>()
val count = ep.select("div.numerando")?.text()?.toIntOrNull() ?: 0 val count = ep.select("div.numerando")?.text()?.toIntOrNull() ?: 0
@ -181,10 +178,10 @@ class KdramaHoodProvider : MainAPI() {
posterUrl = poster, posterUrl = poster,
date = null date = null
) )
} ?: listOf() }
//If there's only 1 episode, consider it a movie. //If there's only 1 episode, consider it a movie.
if (episodeList.size == 1) { if (episodeList?.size == 1) {
return MovieLoadResponse( return MovieLoadResponse(
name = title, name = title,
url = url, url = url,
@ -202,7 +199,7 @@ class KdramaHoodProvider : MainAPI() {
url = url, url = url,
apiName = this.name, apiName = this.name,
type = TvType.AsianDrama, type = TvType.AsianDrama,
episodes = episodeList.reversed(), episodes = episodeList?.reversed() ?: emptyList(),
posterUrl = poster, posterUrl = poster,
year = year, year = year,
plot = descript, plot = descript,

View file

@ -118,10 +118,10 @@ class LookMovieProvider : MainAPI() {
val items = document.select("div.flex-wrap-movielist > div.movie-item-style-1") val items = document.select("div.flex-wrap-movielist > div.movie-item-style-1")
return items.map { item -> return items.map { item ->
val titleHolder = item.selectFirst("> div.mv-item-infor > h6 > a") val titleHolder = item.selectFirst("> div.mv-item-infor > h6 > a")
val href = fixUrl(titleHolder.attr("href")) val href = fixUrl(titleHolder!!.attr("href"))
val name = titleHolder.text() val name = titleHolder.text()
val posterHolder = item.selectFirst("> div.image__placeholder > a") val posterHolder = item.selectFirst("> div.image__placeholder > a")
val poster = posterHolder.selectFirst("> img")?.attr("data-src") val poster = posterHolder!!.selectFirst("> img")?.attr("data-src")
val year = posterHolder.selectFirst("> p.year")?.text()?.toIntOrNull() val year = posterHolder.selectFirst("> p.year")?.text()?.toIntOrNull()
if (isMovie) { if (isMovie) {
MovieSearchResponse( MovieSearchResponse(
@ -199,17 +199,17 @@ class LookMovieProvider : MainAPI() {
val isMovie = url.contains("/movies/") val isMovie = url.contains("/movies/")
val watchHeader = document.selectFirst("div.watch-heading") val watchHeader = document.selectFirst("div.watch-heading")
val nameHeader = watchHeader.selectFirst("> h1.bd-hd") val nameHeader = watchHeader!!.selectFirst("> h1.bd-hd")
val year = nameHeader.selectFirst("> span")?.text()?.toIntOrNull() val year = nameHeader!!.selectFirst("> span")?.text()?.toIntOrNull()
val title = nameHeader.ownText() val title = nameHeader.ownText()
val rating = val rating =
parseRating(watchHeader.selectFirst("> div.movie-rate > div.rate > p > span").text()) parseRating(watchHeader.selectFirst("> div.movie-rate > div.rate > p > span")!!.text())
val imgElement = document.selectFirst("div.movie-img > p.movie__poster") val imgElement = document.selectFirst("div.movie-img > p.movie__poster")
val img = imgElement?.attr("style") val img = imgElement?.attr("style")
var poster = if (img.isNullOrEmpty()) null else "url\\((.*?)\\)".toRegex() var poster = if (img.isNullOrEmpty()) null else "url\\((.*?)\\)".toRegex()
.find(img)?.groupValues?.get(1) .find(img)?.groupValues?.get(1)
if (poster.isNullOrEmpty()) poster = imgElement?.attr("data-background-image") if (poster.isNullOrEmpty()) poster = imgElement?.attr("data-background-image")
val descript = document.selectFirst("p.description-short").text() val descript = document.selectFirst("p.description-short")!!.text()
val id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex() val id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex()
.find(response)?.groupValues?.get(1) .find(response)?.groupValues?.get(1)
?.replace(" ", "") ?.replace(" ", "")

View file

@ -88,11 +88,11 @@ class MeloMovieProvider : MainAPI() {
private fun serializeData(element: Element): List<MeloMovieProvider.MeloMovieLink> { private fun serializeData(element: Element): List<MeloMovieProvider.MeloMovieLink> {
val eps = element.select("> tbody > tr") val eps = element.select("> tbody > tr")
val parsed = eps.map { val parsed = eps.mapNotNull {
try { try {
val tds = it.select("> td") val tds = it.select("> td")
val name = tds[if (tds.size == 5) 1 else 0].text() val name = tds[if (tds.size == 5) 1 else 0].text()
val url = fixUrl(tds.last().selectFirst("> a").attr("data-lnk").replace(" ", "%20")) val url = fixUrl(tds.last()!!.selectFirst("> a")!!.attr("data-lnk").replace(" ", "%20"))
MeloMovieLink(name, url) MeloMovieLink(name, url)
} catch (e: Exception) { } catch (e: Exception) {
MeloMovieLink("", "") MeloMovieLink("", "")
@ -133,13 +133,13 @@ class MeloMovieProvider : MainAPI() {
val imdbUrl = findUsingRegex("var imdb = \"(.*?)\"") val imdbUrl = findUsingRegex("var imdb = \"(.*?)\"")
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val poster = document.selectFirst("img.img-fluid").attr("src") val poster = document.selectFirst("img.img-fluid")!!.attr("src")
val type = findUsingRegex("var posttype = ([0-9]*)")?.toInt() ?: return null val type = findUsingRegex("var posttype = ([0-9]*)")?.toInt() ?: return null
val titleInfo = document.selectFirst("div.movie_detail_title > div > div > h1") val titleInfo = document.selectFirst("div.movie_detail_title > div > div > h1")
val title = titleInfo.ownText() val title = titleInfo!!.ownText()
val year = val year =
titleInfo.selectFirst("> a")?.text()?.replace("(", "")?.replace(")", "")?.toIntOrNull() titleInfo.selectFirst("> a")?.text()?.replace("(", "")?.replace(")", "")?.toIntOrNull()
val plot = document.selectFirst("div.col-lg-12 > p").text() val plot = document.selectFirst("div.col-lg-12 > p")!!.text()
if (type == 1) { // MOVIE if (type == 1) { // MOVIE
val serialize = document.selectFirst("table.accordion__list") val serialize = document.selectFirst("table.accordion__list")
@ -161,12 +161,12 @@ class MeloMovieProvider : MainAPI() {
?: throw ErrorLoadingException("No episodes found") ?: throw ErrorLoadingException("No episodes found")
for (s in seasons) { for (s in seasons) {
val season = val season =
s.selectFirst("> div.card-header > button > span").text() s.selectFirst("> div.card-header > button > span")!!.text()
.replace("Season: ", "").toIntOrNull() .replace("Season: ", "").toIntOrNull()
val localEpisodes = s.select("> div.collapse > div > div > div.accordion__card") val localEpisodes = s.select("> div.collapse > div > div > div.accordion__card")
for (e in localEpisodes) { for (e in localEpisodes) {
val episode = val episode =
e.selectFirst("> div.card-header > button > span").text() e.selectFirst("> div.card-header > button > span")!!.text()
.replace("Episode: ", "").toIntOrNull() .replace("Episode: ", "").toIntOrNull()
val links = val links =
e.selectFirst("> div.collapse > div > table.accordion__list") ?: continue e.selectFirst("> div.collapse > div > table.accordion__list") ?: continue

View file

@ -153,7 +153,7 @@ class MyCimaProvider : MainAPI() {
if (moreButton.isNotEmpty()) { if (moreButton.isNotEmpty()) {
val n = doc.select("div.Seasons--Episodes div.Episodes--Seasons--Episodes a").size val n = doc.select("div.Seasons--Episodes div.Episodes--Seasons--Episodes a").size
val totals = val totals =
doc.select("div.Episodes--Seasons--Episodes a").first().text().getIntFromText() doc.select("div.Episodes--Seasons--Episodes a").first()!!.text().getIntFromText()
val mEPS = arrayListOf( val mEPS = arrayListOf(
n, n,
n + 40, n + 40,
@ -229,7 +229,7 @@ class MyCimaProvider : MainAPI() {
val n = val n =
seasonsite.select("div.Seasons--Episodes div.Episodes--Seasons--Episodes a").size seasonsite.select("div.Seasons--Episodes div.Episodes--Seasons--Episodes a").size
val totals = val totals =
seasonsite.select("div.Episodes--Seasons--Episodes a").first().text() seasonsite.select("div.Episodes--Seasons--Episodes a").first()!!.text()
.getIntFromText() .getIntFromText()
val mEPS = arrayListOf( val mEPS = arrayListOf(
n, n,

View file

@ -37,13 +37,13 @@ class NginxProvider : MainAPI() {
val isMovie = !nfoUrl.contains("tvshow.nfo") val isMovie = !nfoUrl.contains("tvshow.nfo")
val title = metadataDocument.selectFirst("title").text() val title = metadataDocument.selectFirst("title")!!.text()
val description = metadataDocument.selectFirst("plot").text() val description = metadataDocument.selectFirst("plot")!!.text()
if (isMovie) { if (isMovie) {
val poster = metadataDocument.selectFirst("thumb").text() val poster = metadataDocument.selectFirst("thumb")!!.text()
val trailer = metadataDocument.select("trailer")?.mapNotNull { val trailer = metadataDocument.select("trailer").mapNotNull {
it?.text()?.replace( it?.text()?.replace(
"plugin://plugin.video.youtube/play/?video_id=", "plugin://plugin.video.youtube/play/?video_id=",
"https://www.youtube.com/watch?v=" "https://www.youtube.com/watch?v="
@ -125,7 +125,7 @@ class NginxProvider : MainAPI() {
val epNum = nfoDocument.selectFirst("episode")?.text()?.toIntOrNull() val epNum = nfoDocument.selectFirst("episode")?.text()?.toIntOrNull()
val poster = val poster =
seasonString + episode.attr("href").replace(".nfo", "-thumb.jpg") seasonString + episode.attr("href").replace(".nfo", "-thumb.jpg")
val name = nfoDocument.selectFirst("title").text() val name = nfoDocument.selectFirst("title")!!.text()
// val seasonInt = nfoDocument.selectFirst("season").text().toIntOrNull() // val seasonInt = nfoDocument.selectFirst("season").text().toIntOrNull()
val date = nfoDocument.selectFirst("aired")?.text() val date = nfoDocument.selectFirst("aired")?.text()
val plot = nfoDocument.selectFirst("plot")?.text() val plot = nfoDocument.selectFirst("plot")?.text()

View file

@ -29,14 +29,14 @@ class PeliSmartProvider: MainAPI() {
try { try {
val soup = app.get(url).document val soup = app.get(url).document
val home = soup.select(".description-off").map { val home = soup.select(".description-off").map {
val title = it.selectFirst("h3.entry-title a").text() val title = it.selectFirst("h3.entry-title a")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
if (link.contains("pelicula")) TvType.Movie else TvType.TvSeries, if (link.contains("pelicula")) TvType.Movie else TvType.TvSeries,
it.selectFirst("div img").attr("src"), it.selectFirst("div img")!!.attr("src"),
null, null,
null, null,
) )
@ -57,9 +57,9 @@ class PeliSmartProvider: MainAPI() {
val document = app.get(url).document val document = app.get(url).document
return document.select(".description-off").map { return document.select(".description-off").map {
val title = it.selectFirst("h3.entry-title a").text() val title = it.selectFirst("h3.entry-title a")!!.text()
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val image = it.selectFirst("div img").attr("src") val image = it.selectFirst("div img")!!.attr("src")
val isMovie = href.contains("pelicula") val isMovie = href.contains("pelicula")
if (isMovie) { if (isMovie) {
@ -88,13 +88,13 @@ class PeliSmartProvider: MainAPI() {
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val soup = app.get(url, timeout = 120).document val soup = app.get(url, timeout = 120).document
val title = soup.selectFirst(".wpb_wrapper h1").text() val title = soup.selectFirst(".wpb_wrapper h1")!!.text()
val description = soup.selectFirst("div.wpb_wrapper p")?.text()?.trim() val description = soup.selectFirst("div.wpb_wrapper p")?.text()?.trim()
val poster: String? = soup.selectFirst(".vc_single_image-img").attr("src") val poster: String? = soup.selectFirst(".vc_single_image-img")!!.attr("src")
val episodes = soup.select("div.vc_tta-panel-body div a").map { li -> val episodes = soup.select("div.vc_tta-panel-body div a").map { li ->
val href = li.selectFirst("a").attr("href") val href = li.selectFirst("a")!!.attr("href")
val preregex = Regex("(\\d+)\\. ") val preregex = Regex("(\\d+)\\. ")
val name = li.selectFirst("a").text().replace(preregex,"") val name = li.selectFirst("a")!!.text().replace(preregex,"")
val regextest = Regex("(temporada-(\\d+)-capitulo-(\\d+)|temporada-(\\d+)-episodio-(\\d+))") val regextest = Regex("(temporada-(\\d+)-capitulo-(\\d+)|temporada-(\\d+)-episodio-(\\d+))")
val test = regextest.find(href)?.destructured?.component1()?.replace(Regex("(temporada-|-)"),"") val test = regextest.find(href)?.destructured?.component1()?.replace(Regex("(temporada-|-)"),"")
val seasonid = test.let { str -> val seasonid = test.let { str ->

View file

@ -28,14 +28,14 @@ class PelisflixProvider : MainAPI() {
try { try {
val soup = app.get(i.first).document val soup = app.get(i.first).document
val home = soup.select("article.TPost.B").map { val home = soup.select("article.TPost.B").map {
val title = it.selectFirst("h2.title").text() val title = it.selectFirst("h2.title")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
TvType.Movie, TvType.Movie,
it.selectFirst("figure img").attr("data-src"), it.selectFirst("figure img")!!.attr("data-src"),
null, null,
null, null,
) )
@ -54,9 +54,9 @@ class PelisflixProvider : MainAPI() {
val url = "$mainUrl/?s=$query" val url = "$mainUrl/?s=$query"
val doc = app.get(url).document val doc = app.get(url).document
return doc.select("article.TPost.B").map { return doc.select("article.TPost.B").map {
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val poster = it.selectFirst("figure img").attr("data-src") val poster = it.selectFirst("figure img")!!.attr("data-src")
val name = it.selectFirst("h2.title").text() val name = it.selectFirst("h2.title")!!.text()
val isMovie = href.contains("/pelicula/") val isMovie = href.contains("/pelicula/")
if (isMovie) { if (isMovie) {
MovieSearchResponse( MovieSearchResponse(
@ -86,24 +86,24 @@ class PelisflixProvider : MainAPI() {
val document = app.get(url).document val document = app.get(url).document
val title = document.selectFirst("h1.Title").text() val title = document.selectFirst("h1.Title")!!.text()
val descRegex = Regex("(.Recuerda.*Pelisflix.+)") val descRegex = Regex("(.Recuerda.*Pelisflix.+)")
val descRegex2 = Regex("(Actualmente.*.)") val descRegex2 = Regex("(Actualmente.*.)")
val descRegex3 = Regex("(.*Director:.*)") val descRegex3 = Regex("(.*Director:.*)")
val descRegex4 = Regex("(.*Actores:.*)") val descRegex4 = Regex("(.*Actores:.*)")
val descRegex5 = Regex("(Ver.*(\\)|)((\\d+).))") val descRegex5 = Regex("(Ver.*(\\)|)((\\d+).))")
val descipt = document.selectFirst("div.Description").text().replace(descRegex, "") val descipt = document.selectFirst("div.Description")!!.text().replace(descRegex, "")
.replace(descRegex2, "").replace(descRegex3, "") .replace(descRegex2, "").replace(descRegex3, "")
.replace(descRegex4, "").replace(descRegex5, "") .replace(descRegex4, "").replace(descRegex5, "")
val desc2Regex = Regex("(G(e|é)nero:.*..)") val desc2Regex = Regex("(G(e|é)nero:.*..)")
val descipt2 = document.selectFirst("div.Description").text().replace(desc2Regex, "") val descipt2 = document.selectFirst("div.Description")!!.text().replace(desc2Regex, "")
val rating = val rating =
document.selectFirst("div.rating-content button.like-mov span.vot_cl")?.text() document.selectFirst("div.rating-content button.like-mov span.vot_cl")?.text()
?.toFloatOrNull() ?.toFloatOrNull()
?.times(0)?.toInt() ?.times(0)?.toInt()
val year = document.selectFirst("span.Date")?.text() val year = document.selectFirst("span.Date")?.text()
val duration = val duration =
if (type == TvType.Movie) document.selectFirst(".Container .Container span.Time") if (type == TvType.Movie) document.selectFirst(".Container .Container span.Time")!!
.text() else null .text() else null
val postercss = document.selectFirst("head").toString() val postercss = document.selectFirst("head").toString()
val posterRegex = val posterRegex =
@ -137,7 +137,7 @@ class PelisflixProvider : MainAPI() {
val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull() val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull()
val epthumb = episode.selectFirst("img")?.attr("src") val epthumb = episode.selectFirst("img")?.attr("src")
val aName = episode.selectFirst("> td.MvTbTtl > a") val aName = episode.selectFirst("> td.MvTbTtl > a")
val name = aName.text() val name = aName!!.text()
val href = aName.attr("href") val href = aName.attr("href")
val date = episode.selectFirst("> td.MvTbTtl > span")?.text() val date = episode.selectFirst("> td.MvTbTtl > span")?.text()
episodeList.add( episodeList.add(
@ -220,7 +220,7 @@ class PelisflixProvider : MainAPI() {
params = mapOf(Pair("h", postkey)), params = mapOf(Pair("h", postkey)),
data = mapOf(Pair("h", postkey)), data = mapOf(Pair("h", postkey)),
allowRedirects = false allowRedirects = false
).response.headers.values("location").apmap { link -> ).okhttpResponse.headers.values("location").apmap { link ->
val url1 = link.replace("#bu", "") val url1 = link.replace("#bu", "")
loadExtractor(url1, data, callback) loadExtractor(url1, data, callback)
} }

View file

@ -67,9 +67,9 @@ class PelisplusHDProvider:MainAPI() {
val document = app.get(url).document val document = app.get(url).document
return document.select("a.Posters-link").map { return document.select("a.Posters-link").map {
val title = it.selectFirst(".listing-content p").text() val title = it.selectFirst(".listing-content p")!!.text()
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val image = it.selectFirst(".Posters-img").attr("src") val image = it.selectFirst(".Posters-img")!!.attr("src")
val isMovie = href.contains("/pelicula/") val isMovie = href.contains("/pelicula/")
if (isMovie) { if (isMovie) {
@ -98,12 +98,12 @@ class PelisplusHDProvider:MainAPI() {
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val soup = app.get(url, timeout = 120).document val soup = app.get(url, timeout = 120).document
val title = soup.selectFirst(".m-b-5").text() val title = soup.selectFirst(".m-b-5")!!.text()
val description = soup.selectFirst("div.text-large")?.text()?.trim() val description = soup.selectFirst("div.text-large")?.text()?.trim()
val poster: String? = soup.selectFirst(".img-fluid").attr("src") val poster: String? = soup.selectFirst(".img-fluid")!!.attr("src")
val episodes = soup.select("div.tab-pane .btn").map { li -> val episodes = soup.select("div.tab-pane .btn").map { li ->
val href = li.selectFirst("a").attr("href") val href = li.selectFirst("a")!!.attr("href")
val name = li.selectFirst(".btn-primary.btn-block").text() val name = li.selectFirst(".btn-primary.btn-block")!!.text()
val seasonid = href.replace("/capitulo/","-") val seasonid = href.replace("/capitulo/","-")
.replace(Regex("$mainUrl/.*/.*/temporada/"),"").let { str -> .replace(Regex("$mainUrl/.*/.*/temporada/"),"").let { str ->
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() } str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
@ -119,7 +119,7 @@ class PelisplusHDProvider:MainAPI() {
) )
} }
val year = soup.selectFirst(".p-r-15 .text-semibold").text().toIntOrNull() val year = soup.selectFirst(".p-r-15 .text-semibold")!!.text().toIntOrNull()
val tvType = if (url.contains("/pelicula/")) TvType.Movie else TvType.TvSeries val tvType = if (url.contains("/pelicula/")) TvType.Movie else TvType.TvSeries
val tags = soup.select(".p-h-15.text-center a span.font-size-18.text-info.text-semibold") val tags = soup.select(".p-h-15.text-center a span.font-size-18.text-info.text-semibold")
.map { it?.text()?.trim().toString().replace(", ","") } .map { it?.text()?.trim().toString().replace(", ","") }

View file

@ -44,11 +44,11 @@ open class PelisplusProviderTemplate : MainAPI() {
return ArrayList(soup.select(".listing.items > .video-block").map { li -> return ArrayList(soup.select(".listing.items > .video-block").map { li ->
// Selects the href in <a href="..."> // Selects the href in <a href="...">
val href = fixUrl(li.selectFirst("a").attr("href")) val href = fixUrl(li.selectFirst("a")!!.attr("href"))
val poster = fixUrl(li.selectFirst("img").attr("src")) val poster = fixUrl(li.selectFirst("img")!!.attr("src"))
// .text() selects all the text in the element, be careful about doing this while too high up in the html hierarchy // .text() selects all the text in the element, be careful about doing this while too high up in the html hierarchy
val title = cleanName(li.selectFirst(".name").text()) val title = cleanName(li.selectFirst(".name")!!.text())
// Use get(0) and toIntOrNull() to prevent any possible crashes, [0] or toInt() will error the search on unexpected values. // Use get(0) and toIntOrNull() to prevent any possible crashes, [0] or toInt() will error the search on unexpected values.
val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull() val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull()
@ -73,13 +73,13 @@ open class PelisplusProviderTemplate : MainAPI() {
val html = app.get(url).text val html = app.get(url).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
val title = cleanName(soup.selectFirst("h1,h2,h3").text()) val title = cleanName(soup.selectFirst("h1,h2,h3")!!.text())
val description = soup.selectFirst(".post-entry")?.text()?.trim() val description = soup.selectFirst(".post-entry")?.text()?.trim()
val poster = soup.selectFirst("head meta[property=og:image]").attr("content") val poster = soup.selectFirst("head meta[property=og:image]")!!.attr("content")
var year : Int? = null var year : Int? = null
val episodes = soup.select(".listing.items.lists > .video-block").map { li -> val episodes = soup.select(".listing.items.lists > .video-block").map { li ->
val href = fixUrl(li.selectFirst("a").attr("href")) val href = fixUrl(li.selectFirst("a")!!.attr("href"))
val regexseason = Regex("(-[Tt]emporada-(\\d+)-[Cc]apitulo-(\\d+))") val regexseason = Regex("(-[Tt]emporada-(\\d+)-[Cc]apitulo-(\\d+))")
val aaa = regexseason.find(href)?.destructured?.component1()?.replace(Regex("(-[Tt]emporada-|[Cc]apitulo-)"),"") val aaa = regexseason.find(href)?.destructured?.component1()?.replace(Regex("(-[Tt]emporada-|[Cc]apitulo-)"),"")
val seasonid = aaa.let { str -> val seasonid = aaa.let { str ->
@ -88,14 +88,14 @@ open class PelisplusProviderTemplate : MainAPI() {
val isValid = seasonid?.size == 2 val isValid = seasonid?.size == 2
val episode = if (isValid) seasonid?.getOrNull(1) else null val episode = if (isValid) seasonid?.getOrNull(1) else null
val season = if (isValid) seasonid?.getOrNull(0) else null val season = if (isValid) seasonid?.getOrNull(0) else null
val epThumb = fixUrl(li.selectFirst("img").attr("src")) val epThumb = fixUrl(li.selectFirst("img")!!.attr("src"))
val epDate = li.selectFirst(".meta > .date").text() val epDate = li.selectFirst(".meta > .date")!!.text()
if(year == null) { if(year == null) {
year = epDate?.split("-")?.get(0)?.toIntOrNull() year = epDate?.split("-")?.get(0)?.toIntOrNull()
} }
newEpisode(li.selectFirst("a").attr("href")) { newEpisode(li.selectFirst("a")!!.attr("href")) {
this.season = season this.season = season
this.episode = episode this.episode = episode
this.posterUrl = epThumb this.posterUrl = epThumb

View file

@ -29,14 +29,14 @@ class SeriesflixProvider : MainAPI() {
try { try {
val soup = app.get(i.first).document val soup = app.get(i.first).document
val home = soup.select("article.TPost.B").map { val home = soup.select("article.TPost.B").map {
val title = it.selectFirst("h2.title").text() val title = it.selectFirst("h2.title")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
TvType.Movie, TvType.Movie,
it.selectFirst("figure img").attr("src"), it.selectFirst("figure img")!!.attr("src"),
null, null,
null, null,
) )
@ -55,9 +55,9 @@ class SeriesflixProvider : MainAPI() {
val url = "$mainUrl/?s=$query" val url = "$mainUrl/?s=$query"
val doc = app.get(url).document val doc = app.get(url).document
return doc.select("article.TPost.B").map { return doc.select("article.TPost.B").map {
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val poster = it.selectFirst("figure img").attr("src") val poster = it.selectFirst("figure img")!!.attr("src")
val name = it.selectFirst("h2.title").text() val name = it.selectFirst("h2.title")!!.text()
val isMovie = href.contains("/movies/") val isMovie = href.contains("/movies/")
if (isMovie) { if (isMovie) {
MovieSearchResponse( MovieSearchResponse(
@ -88,15 +88,15 @@ class SeriesflixProvider : MainAPI() {
val document = app.get(url).document val document = app.get(url).document
val title = document.selectFirst("h1.Title").text() val title = document.selectFirst("h1.Title")!!.text()
val descRegex = Regex("(Recuerda.*Seriesflix.)") val descRegex = Regex("(Recuerda.*Seriesflix.)")
val descipt = document.selectFirst("div.Description > p").text().replace(descRegex, "") val descipt = document.selectFirst("div.Description > p")!!.text().replace(descRegex, "")
val rating = val rating =
document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toRatingInt() document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toRatingInt()
val year = document.selectFirst("span.Date")?.text() val year = document.selectFirst("span.Date")?.text()
// ?: does not work // ?: does not work
val duration = try { val duration = try {
document.selectFirst("span.Time").text() document.selectFirst("span.Time")!!.text()
} catch (e: Exception) { } catch (e: Exception) {
null null
} }
@ -133,8 +133,8 @@ class SeriesflixProvider : MainAPI() {
val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull() val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull()
val epthumb = episode.selectFirst("img")?.attr("src") val epthumb = episode.selectFirst("img")?.attr("src")
val aName = episode.selectFirst("> td.MvTbTtl > a") val aName = episode.selectFirst("> td.MvTbTtl > a")
val name = aName.text() val name = aName!!.text()
val href = aName.attr("href") val href = aName!!.attr("href")
val date = episode.selectFirst("> td.MvTbTtl > span")?.text() val date = episode.selectFirst("> td.MvTbTtl > span")?.text()
episodeList.add( episodeList.add(
newEpisode(href) { newEpisode(href) {
@ -215,7 +215,7 @@ class SeriesflixProvider : MainAPI() {
params = mapOf(Pair("h", postkey)), params = mapOf(Pair("h", postkey)),
data = mapOf(Pair("h", postkey)), data = mapOf(Pair("h", postkey)),
allowRedirects = false allowRedirects = false
).response.headers.values("location").apmap { link -> ).okhttpResponse.headers.values("location").apmap { link ->
val url1 = link.replace("#bu", "") val url1 = link.replace("#bu", "")
loadExtractor(url1, data, callback) loadExtractor(url1, data, callback)
} }

View file

@ -10,13 +10,13 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.animeproviders.ZoroProvider import com.lagradost.cloudstream3.animeproviders.ZoroProvider
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import com.lagradost.cloudstream3.network.AppResponse
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.nicehttp.NiceResponse
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
@ -82,7 +82,7 @@ open class SflixProvider : MainAPI() {
val metaInfo = it.select("div.fd-infor > span.fdi-item") val metaInfo = it.select("div.fd-infor > span.fdi-item")
// val rating = metaInfo[0].text() // val rating = metaInfo[0].text()
val quality = getQualityFromString(metaInfo?.getOrNull(1)?.text()) val quality = getQualityFromString(metaInfo.getOrNull(1)?.text())
if (isMovie) { if (isMovie) {
MovieSearchResponse( MovieSearchResponse(
@ -113,9 +113,9 @@ open class SflixProvider : MainAPI() {
val document = app.get(url).document val document = app.get(url).document
val details = document.select("div.detail_page-watch") val details = document.select("div.detail_page-watch")
val img = details?.select("img.film-poster-img") val img = details.select("img.film-poster-img")
val posterUrl = img?.attr("src") val posterUrl = img.attr("src")
val title = img?.attr("title") ?: throw ErrorLoadingException("No Title") val title = img.attr("title") ?: throw ErrorLoadingException("No Title")
/* /*
val year = Regex("""[Rr]eleased:\s*(\d{4})""").find( val year = Regex("""[Rr]eleased:\s*(\d{4})""").find(
@ -132,7 +132,7 @@ open class SflixProvider : MainAPI() {
val rating = document.selectFirst(".fs-item > .imdb")?.text()?.trim() val rating = document.selectFirst(".fs-item > .imdb")?.text()?.trim()
?.removePrefix("IMDB:")?.toRatingInt() ?.removePrefix("IMDB:")?.toRatingInt()
document.select("div.elements > .row > div > .row-line")?.forEach { element -> document.select("div.elements > .row > div > .row-line").forEach { element ->
val type = element?.select(".type")?.text() ?: return@forEach val type = element?.select(".type")?.text() ?: return@forEach
when { when {
type.contains("Released") -> { type.contains("Released") -> {
@ -141,17 +141,17 @@ open class SflixProvider : MainAPI() {
)?.groupValues?.firstOrNull()?.toIntOrNull() )?.groupValues?.firstOrNull()?.toIntOrNull()
} }
type.contains("Genre") -> { type.contains("Genre") -> {
tags = element.select("a")?.mapNotNull { it.text() } tags = element.select("a").mapNotNull { it.text() }
} }
type.contains("Cast") -> { type.contains("Cast") -> {
cast = element.select("a")?.mapNotNull { it.text() } cast = element.select("a").mapNotNull { it.text() }
} }
type.contains("Duration") -> { type.contains("Duration") -> {
duration = duration ?: element.ownText()?.trim() duration = duration ?: element.ownText().trim()
} }
} }
} }
val plot = details.select("div.description")?.text()?.replace("Overview:", "")?.trim() val plot = details.select("div.description").text().replace("Overview:", "").trim()
val isMovie = url.contains("/movie/") val isMovie = url.contains("/movie/")
@ -164,12 +164,12 @@ open class SflixProvider : MainAPI() {
else dataId else dataId
val recommendations = val recommendations =
document.select("div.film_list-wrap > div.flw-item")?.mapNotNull { element -> document.select("div.film_list-wrap > div.flw-item").mapNotNull { element ->
val titleHeader = val titleHeader =
element.select("div.film-detail > .film-name > a") ?: return@mapNotNull null element.select("div.film-detail > .film-name > a") ?: return@mapNotNull null
val recUrl = fixUrlNull(titleHeader.attr("href")) ?: return@mapNotNull null val recUrl = fixUrlNull(titleHeader.attr("href")) ?: return@mapNotNull null
val recTitle = titleHeader.text() ?: return@mapNotNull null val recTitle = titleHeader.text() ?: return@mapNotNull null
val poster = element.select("div.film-poster > img")?.attr("data-src") val poster = element.select("div.film-poster > img").attr("data-src")
MovieSearchResponse( MovieSearchResponse(
recTitle, recTitle,
recUrl, recUrl,
@ -191,7 +191,7 @@ open class SflixProvider : MainAPI() {
if (sourceId.isNullOrEmpty()) if (sourceId.isNullOrEmpty())
sourceId = element.attr("data-linkid") sourceId = element.attr("data-linkid")
if (element.select("span")?.text()?.trim()?.isValidServer() == true) { if (element.select("span").text().trim().isValidServer()) {
if (sourceId.isNullOrEmpty()) { if (sourceId.isNullOrEmpty()) {
fixUrlNull(element.attr("href")) fixUrlNull(element.attr("href"))
} else { } else {
@ -222,7 +222,7 @@ open class SflixProvider : MainAPI() {
var seasonItems = seasonsDocument.select("div.dropdown-menu.dropdown-menu-model > a") var seasonItems = seasonsDocument.select("div.dropdown-menu.dropdown-menu-model > a")
if (seasonItems.isNullOrEmpty()) if (seasonItems.isNullOrEmpty())
seasonItems = seasonsDocument.select("div.dropdown-menu > a.dropdown-item") seasonItems = seasonsDocument.select("div.dropdown-menu > a.dropdown-item")
seasonItems?.forEachIndexed { season, element -> seasonItems.forEachIndexed { season, element ->
val seasonId = element.attr("data-id") val seasonId = element.attr("data-id")
if (seasonId.isNullOrBlank()) return@forEachIndexed if (seasonId.isNullOrBlank()) return@forEachIndexed
@ -243,7 +243,7 @@ open class SflixProvider : MainAPI() {
episode++ episode++
val episodeNum = val episodeNum =
(it.select("div.episode-number")?.text() (it.select("div.episode-number").text()
?: episodeTitle).let { str -> ?: episodeTitle).let { str ->
Regex("""\d+""").find(str)?.groupValues?.firstOrNull() Regex("""\d+""").find(str)?.groupValues?.firstOrNull()
?.toIntOrNull() ?.toIntOrNull()
@ -314,7 +314,7 @@ open class SflixProvider : MainAPI() {
// Supported streams, they're identical // Supported streams, they're identical
app.get(episodesUrl).document.select("a").mapNotNull { element -> app.get(episodesUrl).document.select("a").mapNotNull { element ->
val id = element?.attr("data-id") ?: return@mapNotNull null val id = element?.attr("data-id") ?: return@mapNotNull null
if (element.select("span")?.text()?.trim()?.isValidServer() == true) { if (element.select("span").text().trim().isValidServer()) {
"$prefix.$id".replace("/tv/", "/watch-tv/") "$prefix.$id".replace("/tv/", "/watch-tv/")
} else { } else {
null null
@ -334,7 +334,7 @@ open class SflixProvider : MainAPI() {
val serverId = url.substringAfterLast(".") val serverId = url.substringAfterLast(".")
val iframeLink = val iframeLink =
app.get("${this.mainUrl}/ajax/get_link/$serverId").mapped<IframeJson>().link app.get("${this.mainUrl}/ajax/get_link/$serverId").parsed<IframeJson>().link
?: return@suspendSafeApiCall ?: return@suspendSafeApiCall
// Some smarter ws11 or w10 selection might be required in the future. // Some smarter ws11 or w10 selection might be required in the future.
@ -354,7 +354,7 @@ open class SflixProvider : MainAPI() {
private fun Element.toSearchResult(): SearchResponse { private fun Element.toSearchResult(): SearchResponse {
val inner = this.selectFirst("div.film-poster") val inner = this.selectFirst("div.film-poster")
val img = inner.select("img") val img = inner!!.select("img")
val title = img.attr("title") val title = img.attr("title")
val posterUrl = img.attr("data-src") ?: img.attr("src") val posterUrl = img.attr("data-src") ?: img.attr("src")
val href = fixUrl(inner.select("a").attr("href")) val href = fixUrl(inner.select("a").attr("href"))
@ -454,11 +454,11 @@ open class SflixProvider : MainAPI() {
* @return the data and if it is new. * @return the data and if it is new.
* */ * */
private suspend fun getUpdatedData( private suspend fun getUpdatedData(
response: AppResponse, response: NiceResponse,
data: PollingData, data: PollingData,
baseUrl: String baseUrl: String
): Pair<PollingData, Boolean> { ): Pair<PollingData, Boolean> {
if (!response.response.isSuccessful) { if (!response.okhttpResponse.isSuccessful) {
return negotiateNewSid(baseUrl)?.let { return negotiateNewSid(baseUrl)?.let {
it to true it to true
} ?: data to false } ?: data to false
@ -688,7 +688,7 @@ open class SflixProvider : MainAPI() {
// "Cache-Control" to "no-cache", // "Cache-Control" to "no-cache",
"TE" to "trailers" "TE" to "trailers"
) )
).mapped<SourceObject>() ).parsed<SourceObject>()
mapped.tracks?.forEach { track -> mapped.tracks?.forEach { track ->
track?.toSubtitleFile()?.let { subtitleFile -> track?.toSubtitleFile()?.let { subtitleFile ->

View file

@ -28,14 +28,14 @@ class SoaptwoDayProvider:MainAPI() {
try { try {
val soup = app.get(url).document val soup = app.get(url).document
val home = soup.select("div.container div.row div.col-sm-12.col-lg-12 div.row div.col-sm-12.col-lg-12 .col-xs-6").map { val home = soup.select("div.container div.row div.col-sm-12.col-lg-12 div.row div.col-sm-12.col-lg-12 .col-xs-6").map {
val title = it.selectFirst("h5 a").text() val title = it.selectFirst("h5 a")!!.text()
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
TvType.TvSeries, TvType.TvSeries,
fixUrl(it.selectFirst("img").attr("src")), fixUrl(it.selectFirst("img")!!.attr("src")),
null, null,
null, null,
) )
@ -52,9 +52,9 @@ class SoaptwoDayProvider:MainAPI() {
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val doc = app.get("$mainUrl/search/keyword/$query").document val doc = app.get("$mainUrl/search/keyword/$query").document
return doc.select("div.container div.row div.col-sm-12.col-lg-12 div.row div.col-sm-12.col-lg-12 .col-xs-6").map { return doc.select("div.container div.row div.col-sm-12.col-lg-12 div.row div.col-sm-12.col-lg-12 .col-xs-6").map {
val title = it.selectFirst("h5 a").text() val title = it.selectFirst("h5 a")!!.text()
val image = fixUrl(it.selectFirst("img").attr("src")) val image = fixUrl(it.selectFirst("img")!!.attr("src"))
val href = fixUrl(it.selectFirst("a").attr("href")) val href = fixUrl(it.selectFirst("a")!!.attr("href"))
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
href, href,
@ -80,34 +80,33 @@ class SoaptwoDayProvider:MainAPI() {
data = link data = link
) )
} }
val otherInfoBody = soup.select("div.col-sm-8 div.panel-body")?.toString() val otherInfoBody = soup.select("div.col-sm-8 div.panel-body").toString()
//Fetch casts //Fetch casts
val casts = otherInfoBody?.substringAfter("Stars : ") val casts = otherInfoBody.substringAfter("Stars : ")
?.substringBefore("Genre : ")?.let { .substringBefore("Genre : ").let {
Jsoup.parse(it)?.select("a") Jsoup.parse(it).select("a")
}?.mapNotNull { }.mapNotNull {
val castName = it?.text() ?: return@mapNotNull null val castName = it?.text() ?: return@mapNotNull null
ActorData( ActorData(
Actor( Actor(
name = castName name = castName
)
) )
) }
}
//Fetch year //Fetch year
val year = otherInfoBody?.substringAfter("<h4>Release : </h4>") val year = otherInfoBody.substringAfter("<h4>Release : </h4>")
?.substringBefore("<div")?.let { .substringBefore("<div").let {
//Log.i(this.name, "Result => year string: $it") //Log.i(this.name, "Result => year string: $it")
Jsoup.parse(it)?.select("p")?.get(1) Jsoup.parse(it).select("p")[1]
}?.text()?.take(4)?.toIntOrNull() }?.text()?.take(4)?.toIntOrNull()
//Fetch genres //Fetch genres
val genre = otherInfoBody?.substringAfter("<h4>Genre : </h4>") val genre = otherInfoBody.substringAfter("<h4>Genre : </h4>")
?.substringBefore("<h4>Release : </h4>")?.let { .substringBefore("<h4>Release : </h4>").let {
//Log.i(this.name, "Result => genre string: $it") //Log.i(this.name, "Result => genre string: $it")
Jsoup.parse(it)?.select("a") Jsoup.parse(it).select("a")
}?.mapNotNull { it?.text()?.trim() ?: return@mapNotNull null } }.mapNotNull { it?.text()?.trim() ?: return@mapNotNull null }
val tvType = if (episodes.isEmpty()) TvType.Movie else TvType.TvSeries return when (val tvType = if (episodes.isEmpty()) TvType.Movie else TvType.TvSeries) {
return when (tvType) {
TvType.TvSeries -> { TvType.TvSeries -> {
TvSeriesLoadResponse( TvSeriesLoadResponse(
title, title,
@ -177,9 +176,9 @@ class SoaptwoDayProvider:MainAPI() {
val doc = app.get(data).document val doc = app.get(data).document
val idplayer = doc.selectFirst("#divU")?.text() val idplayer = doc.selectFirst("#divU")?.text()
val idplayer2 = doc.selectFirst("#divP")?.text() val idplayer2 = doc.selectFirst("#divP")?.text()
val movieid = doc.selectFirst("div.row input#hId").attr("value") val movieid = doc.selectFirst("div.row input#hId")!!.attr("value")
val tvType = try { val tvType = try {
doc.selectFirst(".col-md-5 > div:nth-child(1) > div:nth-child(1) > img").attr("src") ?: "" doc.selectFirst(".col-md-5 > div:nth-child(1) > div:nth-child(1) > img")!!.attr("src") ?: ""
} catch (e: Exception) { } catch (e: Exception) {
"" ""
} }

View file

@ -224,7 +224,7 @@ class StreamingcommunityProvider : MainAPI() {
val document = app.get(url).document val document = app.get(url).document
val films = val films =
document.selectFirst("the-search-page").attr("records-json").replace("&quot;", """"""") document.selectFirst("the-search-page")!!.attr("records-json").replace("&quot;", """"""")
val searchresults = parseJson<List<VideoElement>>(films) val searchresults = parseJson<List<VideoElement>>(films)
return searchresults.map { result -> return searchresults.map { result ->
@ -289,7 +289,7 @@ class StreamingcommunityProvider : MainAPI() {
val year = datajs.releaseDate.substringBefore("-") val year = datajs.releaseDate.substringBefore("-")
val correlatijs = document.selectFirst("slider-title").attr("titles-json") val correlatijs = document.selectFirst("slider-title")!!.attr("titles-json")
val listacorr = mutableListOf<MovieSearchResponse>() val listacorr = mutableListOf<MovieSearchResponse>()
val correlatidata = parseJson<List<VideoElement>>(correlatijs) val correlatidata = parseJson<List<VideoElement>>(correlatijs)
val number : Int = if (correlatidata.size<=15) {correlatidata.size} else correlatidata.size-15 val number : Int = if (correlatidata.size<=15) {correlatidata.size} else correlatidata.size-15
@ -332,7 +332,7 @@ class StreamingcommunityProvider : MainAPI() {
val episodeList = arrayListOf<Episode>() val episodeList = arrayListOf<Episode>()
val episodes = val episodes =
Html.fromHtml(document.selectFirst("season-select").attr("seasons")).toString() Html.fromHtml(document.selectFirst("season-select")!!.attr("seasons")).toString()
val jsonEpisodes = parseJson<List<Season>>(episodes) val jsonEpisodes = parseJson<List<Season>>(episodes)
jsonEpisodes.map { seasons -> jsonEpisodes.map { seasons ->
@ -365,7 +365,7 @@ class StreamingcommunityProvider : MainAPI() {
return newTvSeriesLoadResponse(name, url, type, episodeList) { return newTvSeriesLoadResponse(name, url, type, episodeList) {
this.posterUrl = poster this.posterUrl = poster
this.year = year.filter { it.isDigit() }.toInt() this.year = year.filter { it.isDigit() }.toInt()
this.plot = document.selectFirst("div.plot-wrap > p").text() this.plot = document.selectFirst("div.plot-wrap > p")!!.text()
this.duration = datajs.runtime?.toInt() this.duration = datajs.runtime?.toInt()
this.rating = (datajs.votes[0].average.toFloatOrNull()?.times(1000))?.toInt() this.rating = (datajs.votes[0].average.toFloatOrNull()?.times(1000))?.toInt()
this.tags = datajs.genres.map { it.name } this.tags = datajs.genres.map { it.name }
@ -377,14 +377,14 @@ class StreamingcommunityProvider : MainAPI() {
} else { } else {
return newMovieLoadResponse( return newMovieLoadResponse(
document.selectFirst("div > div > h1").text(), document.selectFirst("div > div > h1")!!.text(),
document.select("a.play-hitzone").attr("href"), document.select("a.play-hitzone").attr("href"),
type, type,
document.select("a.play-hitzone").attr("href") document.select("a.play-hitzone").attr("href")
) { ) {
posterUrl = fixUrlNull(poster) posterUrl = fixUrlNull(poster)
this.year = year.filter { it.isDigit() }.toInt() this.year = year.filter { it.isDigit() }.toInt()
this.plot = document.selectFirst("p.plot").text() this.plot = document.selectFirst("p.plot")!!.text()
this.rating = datajs.votes[0].average.toFloatOrNull()?.times(1000)?.toInt() this.rating = datajs.votes[0].average.toFloatOrNull()?.times(1000)?.toInt()
this.tags = datajs.genres.map { it.name } this.tags = datajs.genres.map { it.name }
this.duration = datajs.runtime?.toInt() this.duration = datajs.runtime?.toInt()

View file

@ -27,14 +27,14 @@ class TantifilmProvider : MainAPI() {
try { try {
val soup = app.get(url).document val soup = app.get(url).document
val home = soup.select("div.media3").map { val home = soup.select("div.media3").map {
val title = it.selectFirst("p").text().substringBefore("(") val title = it.selectFirst("p")!!.text().substringBefore("(")
val link = it.selectFirst("a").attr("href") val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse( TvSeriesSearchResponse(
title, title,
link, link,
this.name, this.name,
TvType.Movie, TvType.Movie,
it.selectFirst("img").attr("src"), it.selectFirst("img")!!.attr("src"),
null, null,
null, null,
) )
@ -54,9 +54,9 @@ class TantifilmProvider : MainAPI() {
val url = "$mainUrl/search/$queryformatted" val url = "$mainUrl/search/$queryformatted"
val doc = app.get(url).document val doc = app.get(url).document
return doc.select("div.film.film-2").map { return doc.select("div.film.film-2").map {
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val poster = it.selectFirst("img").attr("src") val poster = it.selectFirst("img")!!.attr("src")
val name = it.selectFirst("a").text().substringBefore("(") val name = it.selectFirst("a")!!.text().substringBefore("(")
MovieSearchResponse( MovieSearchResponse(
name, name,
href, href,
@ -72,30 +72,30 @@ class TantifilmProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document val document = app.get(url).document
val type = if (document.selectFirst("div.category-film").text().contains("Serie") val type = if (document.selectFirst("div.category-film")!!.text().contains("Serie")
.not() .not()
) TvType.Movie else TvType.TvSeries ) TvType.Movie else TvType.TvSeries
val title = document.selectFirst("div.title-film-left").text().substringBefore("(") val title = document.selectFirst("div.title-film-left")!!.text().substringBefore("(")
val descipt = document.select("div.content-left-film > p").map { it.text() } val descipt = document.select("div.content-left-film > p").map { it.text() }
val rating = val rating =
document.selectFirst("div.star-rating.star-rating-f > span > span") document.selectFirst("div.star-rating.star-rating-f > span > span")!!
.attr("data-rateit-value")?.toFloatOrNull() .attr("data-rateit-value").toFloatOrNull()
?.times(2857)?.toInt()?.let { minOf(it, 10000) } ?.times(2857)?.toInt()?.let { minOf(it, 10000) }
var year = document.selectFirst("div.title-film-left").text().substringAfter("(") var year = document.selectFirst("div.title-film-left")!!.text().substringAfter("(")
.filter { it.isDigit() } .filter { it.isDigit() }
if (year.length > 4) { year = if (year.length > 4) {
year = year.dropLast(4) year.dropLast(4)
} else { } else {
year = year year
} }
// ?: does not wor // ?: does not wor
val poster = document.selectFirst("div.image-right-film > img").attr("src") val poster = document.selectFirst("div.image-right-film > img")!!.attr("src")
val recomm = document.select("div.mediaWrap.mediaWrapAlt.recomended_videos").map { val recomm = document.select("div.mediaWrap.mediaWrapAlt.recomended_videos").map {
val href = it.selectFirst("a").attr("href") val href = it.selectFirst("a")!!.attr("href")
val poster = it.selectFirst("img").attr("src") val poster = it.selectFirst("img")!!.attr("src")
val name = it.selectFirst("a").attr("title").substringBeforeLast("(") val name = it.selectFirst("a")!!.attr("title").substringBeforeLast("(")
MovieSearchResponse( MovieSearchResponse(
name, name,
href, href,
@ -111,10 +111,10 @@ class TantifilmProvider : MainAPI() {
if (type == TvType.TvSeries) { if (type == TvType.TvSeries) {
val list = ArrayList<Pair<Int, String>>() val list = ArrayList<Pair<Int, String>>()
val urlvideocontainer = document.selectFirst("iframe").attr("src") val urlvideocontainer = document.selectFirst("iframe")!!.attr("src")
val videocontainer = app.get(urlvideocontainer).document val videocontainer = app.get(urlvideocontainer).document
videocontainer.select("nav.nav1 > select > option").forEach { element -> videocontainer.select("nav.nav1 > select > option").forEach { element ->
val season = element.text()?.toIntOrNull() val season = element.text().toIntOrNull()
val href = element.attr("value") val href = element.attr("value")
if (season != null && season > 0 && !href.isNullOrBlank()) { if (season != null && season > 0 && !href.isNullOrBlank()) {
list.add(Pair(season, fixUrl(href))) list.add(Pair(season, fixUrl(href)))
@ -130,7 +130,7 @@ class TantifilmProvider : MainAPI() {
if (episodes.isNotEmpty()) { if (episodes.isNotEmpty()) {
episodes.forEach { episode -> episodes.forEach { episode ->
val href = episode.attr("value") val href = episode.attr("value")
val epNum = episode.text()?.toIntOrNull() val epNum = episode.text().toIntOrNull()
episodeList.add( episodeList.add(
Episode( Episode(
href, href,
@ -149,7 +149,7 @@ class TantifilmProvider : MainAPI() {
type, type,
episodeList, episodeList,
fixUrlNull(poster), fixUrlNull(poster),
year?.toIntOrNull(), year.toIntOrNull(),
descipt[0], descipt[0],
null, null,
rating, rating,
@ -159,23 +159,21 @@ class TantifilmProvider : MainAPI() {
recomm recomm
) )
} else { } else {
val url2 = document.selectFirst("iframe").attr("src") val url2 = document.selectFirst("iframe")!!.attr("src")
val actorpagelink = val actorpagelink =
document.select("div.content-left-film > p:nth-child(2) > a").attr("href") document.select("div.content-left-film > p:nth-child(2) > a").attr("href")
val actorpagelink2 = document.select("div.content-left-film > p > a").attr("href") val actorpagelink2 = document.select("div.content-left-film > p > a").attr("href")
val Linkactor: String = if (actorpagelink.isNotEmpty()) { val Linkactor: String = actorpagelink.ifEmpty {
actorpagelink
} else {
actorpagelink2 actorpagelink2
} }
val actors: List<ActorData>? = if (Linkactor.isNotEmpty()) { val actors: List<ActorData>? = if (Linkactor.isNotEmpty()) {
val actorpage = app.get(Linkactor + "cast/").document val actorpage = app.get(Linkactor + "cast/").document
actorpage.select("article.membro-cast")?.filter { actorpage.select("article.membro-cast").filter {
it.selectFirst("img") it.selectFirst("img")
?.attr("src") != "https://www.filmtv.it/imgbank/DUMMY/no_portrait.jpg" ?.attr("src") != "https://www.filmtv.it/imgbank/DUMMY/no_portrait.jpg"
}?.mapNotNull { it -> }.mapNotNull {
val name = it.selectFirst("div.info > h3").text() val name = it.selectFirst("div.info > h3")!!.text()
val image = it.selectFirst("img")?.attr("src") val image = it.selectFirst("img")?.attr("src")
val roleString: String = if (it.selectFirst("h2")?.text() == "Regia") { val roleString: String = if (it.selectFirst("h2")?.text() == "Regia") {
"Regia" "Regia"
@ -196,7 +194,7 @@ class TantifilmProvider : MainAPI() {
null null
} }
val tags: List<String>? = if (descipt.size == 2) { val tags: List<String>? = if (descipt.size == 2) {
descipt[0].let { mutableListOf(it.substringBefore(" ")) } mutableListOf(descipt[0].substringBefore(" "))
} else { } else {
null null
} }
@ -212,7 +210,7 @@ class TantifilmProvider : MainAPI() {
url2 url2
) { ) {
posterUrl = fixUrlNull(poster) posterUrl = fixUrlNull(poster)
this.year = year?.toIntOrNull() this.year = year.toIntOrNull()
this.plot = plot this.plot = plot
this.rating = rating this.rating = rating
this.recommendations = recomm this.recommendations = recomm
@ -235,7 +233,7 @@ class TantifilmProvider : MainAPI() {
doc.select("option").map { fixUrl(it.attr("value")) }.filter { it.contains("label") } doc.select("option").map { fixUrl(it.attr("value")) }.filter { it.contains("label") }
iframe.forEach { id -> iframe.forEach { id ->
val doc2 = app.get(id).document val doc2 = app.get(id).document
val id2 = app.get(doc2.selectFirst("iframe").attr("src")).url val id2 = app.get(doc2.selectFirst("iframe")!!.attr("src")).url
loadExtractor(id2, data, callback) loadExtractor(id2, data, callback)
} }
return true return true

View file

@ -98,7 +98,7 @@ class TheFlixToProvider : MainAPI() {
override suspend fun getMainPage(): HomePageResponse { override suspend fun getMainPage(): HomePageResponse {
val items = ArrayList<HomePageList>() val items = ArrayList<HomePageList>()
val doc = app.get(mainUrl).document val doc = app.get(mainUrl).document
val scriptText = doc.selectFirst("script[type=application/json]").data() val scriptText = doc.selectFirst("script[type=application/json]")!!.data()
if (scriptText.contains("moviesListTrending")) { if (scriptText.contains("moviesListTrending")) {
val json = parseJson<HomeJson>(scriptText) val json = parseJson<HomeJson>(scriptText)
val homePageProps = json.props.pageProps val homePageProps = json.props.pageProps
@ -181,7 +181,7 @@ class TheFlixToProvider : MainAPI() {
) )
urls.apmap { url -> urls.apmap { url ->
val doc = app.get(url).document val doc = app.get(url).document
val scriptText = doc.selectFirst("script[type=application/json]").data() val scriptText = doc.selectFirst("script[type=application/json]")!!.data()
if (scriptText.contains("pageProps")) { if (scriptText.contains("pageProps")) {
val json = parseJson<SearchJson>(scriptText) val json = parseJson<SearchJson>(scriptText)
val searchPageProps = json.props.pageProps.mainList val searchPageProps = json.props.pageProps.mainList
@ -397,7 +397,7 @@ class TheFlixToProvider : MainAPI() {
private suspend fun getLoadMan(url: String): LoadMain { private suspend fun getLoadMan(url: String): LoadMain {
val og = app.get(url, cookies = latestCookies) val og = app.get(url, cookies = latestCookies)
val soup = og.document val soup = og.document
val script = soup.selectFirst("script[type=application/json]").data() val script = soup.selectFirst("script[type=application/json]")!!.data()
return parseJson(script) return parseJson(script)
} }

View file

@ -24,15 +24,15 @@ class VMoveeProvider : MainAPI() {
val details = item.selectFirst("> div.details") val details = item.selectFirst("> div.details")
val imgHolder = item.selectFirst("> div.image > div.thumbnail > a") val imgHolder = item.selectFirst("> div.image > div.thumbnail > a")
// val href = imgHolder.attr("href") // val href = imgHolder.attr("href")
val poster = imgHolder.selectFirst("> img").attr("data-lazy-src") val poster = imgHolder!!.selectFirst("> img")!!.attr("data-lazy-src")
val isTV = imgHolder.selectFirst("> span").text() == "TV" val isTV = imgHolder.selectFirst("> span")!!.text() == "TV"
if (isTV) continue // no TV support yet if (isTV) continue // no TV support yet
val titleHolder = details.selectFirst("> div.title > a") val titleHolder = details!!.selectFirst("> div.title > a")
val title = titleHolder.text() val title = titleHolder!!.text()
val href = titleHolder.attr("href") val href = titleHolder.attr("href")
val meta = details.selectFirst("> div.meta") val meta = details.selectFirst("> div.meta")
val year = meta.selectFirst("> span.year").text().toIntOrNull() val year = meta!!.selectFirst("> span.year")!!.text().toIntOrNull()
// val rating = parseRating(meta.selectFirst("> span.rating").text().replace("IMDb ", "")) // val rating = parseRating(meta.selectFirst("> span.rating").text().replace("IMDb ", ""))
// val descript = details.selectFirst("> div.contenido").text() // val descript = details.selectFirst("> div.contenido").text()
returnValue.add( returnValue.add(
@ -114,10 +114,10 @@ class VMoveeProvider : MainAPI() {
val sheader = document.selectFirst("div.sheader") val sheader = document.selectFirst("div.sheader")
val poster = sheader.selectFirst("> div.poster > img").attr("data-lazy-src") val poster = sheader!!.selectFirst("> div.poster > img")!!.attr("data-lazy-src")
val data = sheader.selectFirst("> div.data") val data = sheader.selectFirst("> div.data")
val title = data.selectFirst("> h1").text() val title = data!!.selectFirst("> h1")!!.text()
val descript = document.selectFirst("div#info > div").text() val descript = document.selectFirst("div#info > div")!!.text()
val id = document.select("div.starstruck").attr("data-id") val id = document.select("div.starstruck").attr("data-id")
return MovieLoadResponse(title, url, this.name, TvType.Movie, id, poster, null, descript, null, null) return MovieLoadResponse(title, url, this.name, TvType.Movie, id, poster, null, descript, null, null)

View file

@ -27,12 +27,12 @@ class VfFilmProvider : MainAPI() {
for (item in items) { for (item in items) {
val href = item.attr("href") val href = item.attr("href")
val poster = item.selectFirst("> div.Image > figure > img").attr("src") val poster = item.selectFirst("> div.Image > figure > img")!!.attr("src")
.replace("//image", "https://image") .replace("//image", "https://image")
val name = item.selectFirst("> h3.Title").text() val name = item.selectFirst("> h3.Title")!!.text()
val year = item.selectFirst("> span.Year").text()?.toIntOrNull() val year = item.selectFirst("> span.Year")!!.text().toIntOrNull()
returnValue.add(MovieSearchResponse(name, href, this.name, TvType.Movie, poster, year)) returnValue.add(MovieSearchResponse(name, href, this.name, TvType.Movie, poster, year))
} }
@ -73,25 +73,25 @@ class VfFilmProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val title = document?.selectFirst("div.SubTitle")?.text() val title = document.selectFirst("div.SubTitle")?.text()
?: throw ErrorLoadingException("Service might be unavailable") ?: throw ErrorLoadingException("Service might be unavailable")
val year = document.select("span.Date").text()?.toIntOrNull() val year = document.select("span.Date").text().toIntOrNull()
val rating = document.select("span.AAIco-star").text() // val rating = document.select("span.AAIco-star").text()
val duration = document.select("span.Time").text()?.toIntOrNull() val duration = document.select("span.Time").text().toIntOrNull()
val poster = document.selectFirst("div.Image > figure > img").attr("src") val poster = document.selectFirst("div.Image > figure > img")!!.attr("src")
.replace("//image", "https://image") .replace("//image", "https://image")
val descript = document.selectFirst("div.Description > p").text() val descript = document.selectFirst("div.Description > p")!!.text()
val players = document.select("ul.TPlayerNv > li") val players = document.select("ul.TPlayerNv > li")
var number_player = 0 var number_player = 0
var found = false var found = false
for (player in players) { for (player in players) {
if (player.selectFirst("> span").text() == "Vudeo") { if (player.selectFirst("> span")!!.text() == "Vudeo") {
found = true found = true
break break
} else { } else {

View file

@ -28,15 +28,15 @@ class VfSerieProvider : MainAPI() {
for (item in items) { for (item in items) {
val href = item.attr("href") val href = item.attr("href")
val poster = item.selectFirst("> div.Image > figure > img").attr("src") val poster = item.selectFirst("> div.Image > figure > img")!!.attr("src")
.replace("//image", "https://image") .replace("//image", "https://image")
if (poster == "$mainUrl/wp-content/themes/toroplay/img/cnt/noimg-thumbnail.png") { // if the poster is missing (the item is just a redirect to something like https://vf-serie.org/series-tv/) if (poster == "$mainUrl/wp-content/themes/toroplay/img/cnt/noimg-thumbnail.png") { // if the poster is missing (the item is just a redirect to something like https://vf-serie.org/series-tv/)
continue continue
} }
val name = item.selectFirst("> h3.Title").text() val name = item.selectFirst("> h3.Title")!!.text()
val year = item.selectFirst("> span.Year").text()?.toIntOrNull() val year = item.selectFirst("> span.Year")!!.text().toIntOrNull()
returnValue.add( returnValue.add(
TvSeriesSearchResponse( TvSeriesSearchResponse(
@ -74,12 +74,12 @@ class VfSerieProvider : MainAPI() {
val response = app.get(data).text val response = app.get(data).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val players = document.select("ul.TPlayerNv > li") val players = document.select("ul.TPlayerNv > li")
val trembedUrl = document.selectFirst("div.TPlayerTb > iframe").attr("src") val trembedUrl = document.selectFirst("div.TPlayerTb > iframe")!!.attr("src")
var numberPlayer = Regex(".*trembed=(.*?)&").find(trembedUrl)?.groupValues?.get(1)!! var numberPlayer = Regex(".*trembed=(.*?)&").find(trembedUrl)?.groupValues?.get(1)!!
.toInt() // the starting trembed number of the first player website, some start at 0 other at 1 .toInt() // the starting trembed number of the first player website, some start at 0 other at 1
var found = false var found = false
for (player in players) { for (player in players) {
if (player.selectFirst("> span").text() == "Vudeo") { if (player.selectFirst("> span")!!.text() == "Vudeo") {
found = true found = true
break break
} else { } else {
@ -110,21 +110,21 @@ class VfSerieProvider : MainAPI() {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val title = val title =
document?.selectFirst(".Title")?.text()?.replace("Regarder Serie ", "") document.selectFirst(".Title")?.text()?.replace("Regarder Serie ", "")
?.replace(" En Streaming", "") ?.replace(" En Streaming", "")
?: throw ErrorLoadingException("Service might be unavailable") ?: throw ErrorLoadingException("Service might be unavailable")
val year = document.select("span.Date").text()?.toIntOrNull() val year = document.select("span.Date").text().toIntOrNull()
val rating = document.select("span.AAIco-star").text()?.toIntOrNull() val rating = document.select("span.AAIco-star").text().toIntOrNull()
//val duration = document.select("span.Time").text()?.toIntOrNull() //val duration = document.select("span.Time").text()?.toIntOrNull()
val backgroundPoster = val backgroundPoster =
document.selectFirst("div.Image > figure > img").attr("src") document.selectFirst("div.Image > figure > img")!!.attr("src")
.replace("//image", "https://image") .replace("//image", "https://image")
val descript = document.selectFirst("div.Description > p").text() val descript = document.selectFirst("div.Description > p")!!.text()
val list = ArrayList<Int>() val list = ArrayList<Int>()
@ -149,7 +149,7 @@ class VfSerieProvider : MainAPI() {
?.replace("//image", "https://image") ?.replace("//image", "https://image")
val aName = episode.selectFirst("> td.MvTbTtl > a") val aName = episode.selectFirst("> td.MvTbTtl > a")
val date = episode.selectFirst("> td.MvTbTtl > span")?.text()?.toString() val date = episode.selectFirst("> td.MvTbTtl > span")?.text()?.toString()
val name = aName.text() val name = aName!!.text()
val href = aName.attr("href") val href = aName.attr("href")
episodeList.add( episodeList.add(
newEpisode(href) { newEpisode(href) {

View file

@ -104,11 +104,11 @@ open class VidstreamProviderTemplate : MainAPI() {
return ArrayList(soup.select(".listing.items > .video-block").map { li -> return ArrayList(soup.select(".listing.items > .video-block").map { li ->
// Selects the href in <a href="..."> // Selects the href in <a href="...">
val href = fixUrl(li.selectFirst("a").attr("href")) val href = fixUrl(li.selectFirst("a")!!.attr("href"))
val poster = li.selectFirst("img")?.attr("src") val poster = li.selectFirst("img")?.attr("src")
// .text() selects all the text in the element, be careful about doing this while too high up in the html hierarchy // .text() selects all the text in the element, be careful about doing this while too high up in the html hierarchy
val title = li.selectFirst(".name").text() val title = li.selectFirst(".name")!!.text()
// Use get(0) and toIntOrNull() to prevent any possible crashes, [0] or toInt() will error the search on unexpected values. // Use get(0) and toIntOrNull() to prevent any possible crashes, [0] or toInt() will error the search on unexpected values.
val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull() val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull()
@ -133,7 +133,7 @@ open class VidstreamProviderTemplate : MainAPI() {
val html = app.get(url).text val html = app.get(url).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
var title = soup.selectFirst("h1,h2,h3").text() var title = soup.selectFirst("h1,h2,h3")!!.text()
title = if (!title.contains("Episode")) title else title.split("Episode")[0].trim() title = if (!title.contains("Episode")) title else title.split("Episode")[0].trim()
val description = soup.selectFirst(".post-entry")?.text()?.trim() val description = soup.selectFirst(".post-entry")?.text()?.trim()
@ -143,13 +143,13 @@ open class VidstreamProviderTemplate : MainAPI() {
val episodes = val episodes =
soup.select(".listing.items.lists > .video-block").withIndex().map { (_, li) -> soup.select(".listing.items.lists > .video-block").withIndex().map { (_, li) ->
val epTitle = if (li.selectFirst(".name") != null) val epTitle = if (li.selectFirst(".name") != null)
if (li.selectFirst(".name").text().contains("Episode")) if (li.selectFirst(".name")!!.text().contains("Episode"))
"Episode " + li.selectFirst(".name").text().split("Episode")[1].trim() "Episode " + li.selectFirst(".name")!!.text().split("Episode")[1].trim()
else else
li.selectFirst(".name").text() li.selectFirst(".name")!!.text()
else "" else ""
val epThumb = li.selectFirst("img")?.attr("src") val epThumb = li.selectFirst("img")?.attr("src")
val epDate = li.selectFirst(".meta > .date").text() val epDate = li.selectFirst(".meta > .date")!!.text()
if (poster == null) { if (poster == null) {
poster = li.selectFirst("img")?.attr("onerror")?.split("=")?.get(1) poster = li.selectFirst("img")?.attr("onerror")?.split("=")?.get(1)
@ -159,9 +159,9 @@ open class VidstreamProviderTemplate : MainAPI() {
val epNum = Regex("""Episode (\d+)""").find(epTitle)?.destructured?.component1() val epNum = Regex("""Episode (\d+)""").find(epTitle)?.destructured?.component1()
?.toIntOrNull() ?.toIntOrNull()
if (year == null) { if (year == null) {
year = epDate?.split("-")?.get(0)?.toIntOrNull() year = epDate.split("-")[0].toIntOrNull()
} }
newEpisode(li.selectFirst("a").attr("href")) { newEpisode(li.selectFirst("a")!!.attr("href")) {
this.episode = epNum this.episode = epNum
this.posterUrl = epThumb this.posterUrl = epThumb
addDate(epDate) addDate(epDate)
@ -215,7 +215,7 @@ open class VidstreamProviderTemplate : MainAPI() {
urls.apmap { url -> urls.apmap { url ->
val response = app.get(url, timeout = 20).text val response = app.get(url, timeout = 20).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
document.select("div.main-inner")?.forEach { inner -> document.select("div.main-inner").forEach { inner ->
// Always trim your text unless you want the risk of spaces at the start or end. // Always trim your text unless you want the risk of spaces at the start or end.
val title = inner.select(".widget-title").text().trim() val title = inner.select(".widget-title").text().trim()
val elements = inner.select(".video-block").map { val elements = inner.select(".video-block").map {

View file

@ -20,9 +20,9 @@ class FrenchStreamProvider : MainAPI() {
val soup = app.post(link).document val soup = app.post(link).document
return soup.select("div.short-in.nl").map { li -> return soup.select("div.short-in.nl").map { li ->
val href = fixUrl(li.selectFirst("a.short-poster").attr("href")) val href = fixUrl(li.selectFirst("a.short-poster")!!.attr("href"))
val poster = li.selectFirst("img")?.attr("src") val poster = li.selectFirst("img")?.attr("src")
val title = li.selectFirst("> a.short-poster").text().toString().replace(". ", "") val title = li.selectFirst("> a.short-poster")!!.text().toString().replace(". ", "")
val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull() val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull()
if (title.contains( if (title.contains(
"saison", "saison",
@ -54,24 +54,24 @@ class FrenchStreamProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val soup = app.get(url).document val soup = app.get(url).document
val title = soup.selectFirst("h1#s-title").text().toString() val title = soup.selectFirst("h1#s-title")!!.text().toString()
val isMovie = !title.contains("saison", ignoreCase = true) val isMovie = !title.contains("saison", ignoreCase = true)
val description = val description =
soup.selectFirst("div.fdesc").text().toString() soup.selectFirst("div.fdesc")!!.text().toString()
.split("streaming", ignoreCase = true)[1].replace(" : ", "") .split("streaming", ignoreCase = true)[1].replace(" : ", "")
var poster = fixUrlNull(soup.selectFirst("div.fposter > img")?.attr("src")) var poster = fixUrlNull(soup.selectFirst("div.fposter > img")?.attr("src"))
val listEpisode = soup.select("div.elink") val listEpisode = soup.select("div.elink")
if (isMovie) { if (isMovie) {
val tags = soup.select("ul.flist-col > li")?.getOrNull(1) val tags = soup.select("ul.flist-col > li").getOrNull(1)
val tagsList = tags?.select("a") val tagsList = tags?.select("a")
?.mapNotNull { // all the tags like action, thriller ...; unused variable ?.mapNotNull { // all the tags like action, thriller ...; unused variable
it?.text() it?.text()
} }
return newMovieLoadResponse(title,url,TvType.Movie,url) { return newMovieLoadResponse(title,url,TvType.Movie,url) {
this.posterUrl = poster this.posterUrl = poster
addRating(soup.select("div.fr-count > div")?.text()) addRating(soup.select("div.fr-count > div").text())
this.year = soup.select("ul.flist-col > li")?.getOrNull(2)?.text()?.toIntOrNull() this.year = soup.select("ul.flist-col > li").getOrNull(2)?.text()?.toIntOrNull()
this.tags = tagsList this.tags = tagsList
this.plot = description this.plot = description
addTrailer(soup.selectFirst("div.fleft > span > a")?.attr("href")) addTrailer(soup.selectFirst("div.fleft > span > a")?.attr("href"))
@ -91,17 +91,16 @@ class FrenchStreamProvider : MainAPI() {
val episodes = episodeList.select("a").map { a -> val episodes = episodeList.select("a").map { a ->
val epNum = a.text().split("Episode")[1].trim().toIntOrNull() val epNum = a.text().split("Episode")[1].trim().toIntOrNull()
val epTitle = if (a.text()?.toString() != null) val epTitle = if (a.text().contains("Episode")) {
if (a.text().contains("Episode")) { val type = if ("honey" in a.attr("id")) {
val type = if ("honey" in a.attr("id")) { "VF"
"VF"
} else {
"VOSTFR"
}
"Episode " + epNum?.toString() + " en " + type
} else { } else {
a.text() "VOSTFR"
} else "" }
"Episode " + epNum?.toString() + " en " + type
} else {
a.text()
}
if (poster == null) { if (poster == null) {
poster = a.selectFirst("div.fposter > img")?.attr("src") poster = a.selectFirst("div.fposter > img")?.attr("src")
} }
@ -133,13 +132,14 @@ class FrenchStreamProvider : MainAPI() {
episodeNumber: String, episodeNumber: String,
is_vf_available: Boolean, is_vf_available: Boolean,
): String { ): String {
if (episodeNumber == "1") { return if (episodeNumber == "1") {
if (is_vf_available) { // 1 translate differently if vf is available or not if (is_vf_available) { // 1 translate differently if vf is available or not
return "FGHIJK" "FGHIJK"
} else { return "episode033" } } else {
} "episode033"
else { }
return "episode" + (episodeNumber.toInt() + 32).toString() } else {
"episode" + (episodeNumber.toInt() + 32).toString()
} }
} }
@ -173,7 +173,7 @@ class FrenchStreamProvider : MainAPI() {
val serversvf =// French version servers val serversvf =// French version servers
soup.select("div#$wantedEpisode > div.selink > ul.btnss $div> li") soup.select("div#$wantedEpisode > div.selink > ul.btnss $div> li")
.mapNotNull { li -> // list of all french version servers .mapNotNull { li -> // list of all french version servers
val serverUrl = fixUrl(li.selectFirst("a").attr("href")) val serverUrl = fixUrl(li.selectFirst("a")!!.attr("href"))
// val litext = li.text() // val litext = li.text()
if (serverUrl.isNotBlank()) { if (serverUrl.isNotBlank()) {
if (li.text().replace("&nbsp;", "").replace(" ", "").isNotBlank()) { if (li.text().replace("&nbsp;", "").replace(" ", "").isNotBlank()) {
@ -208,7 +208,7 @@ class FrenchStreamProvider : MainAPI() {
.mapNotNull { a -> .mapNotNull { a ->
val serverurl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null val serverurl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null
val parent = a.parents()[2] val parent = a.parents()[2]
val element = parent.selectFirst("a").text().plus(" ") val element = parent.selectFirst("a")!!.text().plus(" ")
if (a.text().replace("&nbsp;", "").isNotBlank()) { if (a.text().replace("&nbsp;", "").isNotBlank()) {
Pair(element.plus(a.text()), fixUrl(serverurl)) Pair(element.plus(a.text()), fixUrl(serverurl))
} else { } else {
@ -239,14 +239,14 @@ class FrenchStreamProvider : MainAPI() {
val returnList = docs.mapNotNull { val returnList = docs.mapNotNull {
val epList = it.selectFirst("> div.sect-c.floats.clearfix") ?: return@mapNotNull null val epList = it.selectFirst("> div.sect-c.floats.clearfix") ?: return@mapNotNull null
val title = val title =
it.selectFirst("> div.sect-t.fx-row.icon-r > div.st-left > a.st-capt").text() it.selectFirst("> div.sect-t.fx-row.icon-r > div.st-left > a.st-capt")!!.text()
val list = epList.select("> div.short") val list = epList.select("> div.short")
val isMovieType = title.contains("Films") // if truen type is Movie val isMovieType = title.contains("Films") // if truen type is Movie
val currentList = list.map { head -> val currentList = list.map { head ->
val hrefItem = head.selectFirst("> div.short-in.nl > a") val hrefItem = head.selectFirst("> div.short-in.nl > a")
val href = fixUrl(hrefItem.attr("href")) val href = fixUrl(hrefItem!!.attr("href"))
val img = hrefItem.selectFirst("> img") val img = hrefItem.selectFirst("> img")
val posterUrl = img.attr("src") val posterUrl = img!!.attr("src")
val name = img.attr("> div.short-title").toString() val name = img.attr("> div.short-title").toString()
return@map if (isMovieType) MovieSearchResponse( return@map if (isMovieType) MovieSearchResponse(
name, name,

View file

@ -1,9 +1,13 @@
package com.lagradost.cloudstream3.network package com.lagradost.cloudstream3.network
import androidx.annotation.AnyThread import androidx.annotation.AnyThread
import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.network.Requests.Companion.await import com.lagradost.nicehttp.Requests.Companion.await
import com.lagradost.nicehttp.getCookies
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.Headers
import okhttp3.Headers.Companion.toHeaders
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@ -13,14 +17,13 @@ import okhttp3.Response
* If false it will only try to get cookies when a request returns 403 * If false it will only try to get cookies when a request returns 403
* */ * */
// As seen in https://github.com/anime-dl/anime-downloader/blob/master/anime_downloader/sites/erairaws.py // As seen in https://github.com/anime-dl/anime-downloader/blob/master/anime_downloader/sites/erairaws.py
@AnyThread @AnyThread
class DdosGuardKiller(private val alwaysBypass: Boolean) : Interceptor { class DdosGuardKiller(private val alwaysBypass: Boolean) : Interceptor {
val savedCookiesMap = mutableMapOf<String, Map<String, String>>() val savedCookiesMap = mutableMapOf<String, Map<String, String>>()
private var ddosBypassPath: String? = null private var ddosBypassPath: String? = null
override fun intercept(chain: Interceptor.Chain): Response = runBlocking { override fun intercept(chain: Interceptor.Chain): Response = runBlocking {
val request = chain.request() val request = chain.request()
if (alwaysBypass) return@runBlocking bypassDdosGuard(request) if (alwaysBypass) return@runBlocking bypassDdosGuard(request)
@ -46,7 +49,7 @@ class DdosGuardKiller(private val alwaysBypass: Boolean) : Interceptor {
} }
} }
val headers = getHeaders(request.headers.toMap(), null, cookies + request.cookies) val headers = getHeaders(request.headers.toMap(), cookies + request.cookies)
return app.baseClient.newCall( return app.baseClient.newCall(
request.newBuilder() request.newBuilder()
.headers(headers) .headers(headers)

View file

@ -1,449 +0,0 @@
package com.lagradost.cloudstream3.network
import android.annotation.SuppressLint
import android.content.Context
import android.util.Log
import androidx.preference.PreferenceManager
import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mapper
import kotlinx.coroutines.CancellableContinuation
import kotlinx.coroutines.CompletionHandler
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.*
import okhttp3.Headers.Companion.toHeaders
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.io.File
import java.io.IOException
import java.net.URI
import java.security.SecureRandom
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager
import kotlin.coroutines.resumeWithException
class Session(
client: OkHttpClient = app.baseClient
) : Requests() {
init {
this.baseClient = client
.newBuilder()
.cookieJar(CustomCookieJar())
.build()
}
inner class CustomCookieJar : CookieJar {
private var cookies = mapOf<String, Cookie>()
override fun loadForRequest(url: HttpUrl): List<Cookie> {
return this.cookies.values.toList()
}
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
this.cookies += cookies.map { it.name to it }
}
}
}
private const val DEFAULT_TIME = 10
private val DEFAULT_TIME_UNIT = TimeUnit.MINUTES
private const val DEFAULT_USER_AGENT = USER_AGENT
private val DEFAULT_HEADERS = mapOf("user-agent" to DEFAULT_USER_AGENT)
private val DEFAULT_DATA: Map<String, String> = mapOf()
private val DEFAULT_COOKIES: Map<String, String> = mapOf()
private val DEFAULT_REFERER: String? = null
/** WARNING! CAN ONLY BE READ ONCE */
val Response.text: String
get() {
return this.body?.string() ?: ""
}
val Response.url: String
get() {
return this.request.url.toString()
}
fun Headers.getCookies(cookieKey: String): Map<String, String> {
val cookieList =
this.filter { it.first.equals(cookieKey, ignoreCase = true) }
.getOrNull(0)?.second?.split(";")
return cookieList?.associate {
val split = it.split("=")
(split.getOrNull(0)?.trim() ?: "") to (split.getOrNull(1)?.trim() ?: "")
}?.filter { it.key.isNotBlank() && it.value.isNotBlank() } ?: mapOf()
}
val Response.cookies: Map<String, String>
get() {
return this.headers.getCookies("set-cookie")
}
val Request.cookies: Map<String, String>
get() {
return this.headers.getCookies("Cookie")
}
class AppResponse(
val response: Response
) {
/** Lazy, initialized on use. */
val text by lazy { response.text }
val url by lazy { response.url }
val cookies by lazy { response.cookies }
val body by lazy { response.body }
val code = response.code
val headers = response.headers
val document: Document by lazy { Jsoup.parse(text) }
/** Same as using mapper.readValue<T>() */
inline fun <reified T : Any> mapped(): T {
return mapper.readValue(this.text)
}
}
private fun getData(data: Any?): RequestBody {
return when (data) {
null -> FormBody.Builder().build()
is Map<*, *> -> {
val builder = FormBody.Builder()
data.forEach {
if (it.key is String && it.value is String)
builder.add(it.key as String, it.value as String)
}
builder.build()
}
else ->
data.toString().toRequestBody("text/plain;charset=UTF-8".toMediaTypeOrNull())
}
}
// https://github.com, id=test -> https://github.com?id=test
private fun appendUri(uri: String, appendQuery: String): String {
val oldUri = URI(uri)
return URI(
oldUri.scheme,
oldUri.authority,
oldUri.path,
if (oldUri.query == null) appendQuery else oldUri.query + "&" + appendQuery,
oldUri.fragment
).toString()
}
// Can probably be done recursively
private fun addParamsToUrl(url: String, params: Map<String, String?>): String {
var appendedUrl = url
params.forEach {
it.value?.let { value ->
appendedUrl = appendUri(appendedUrl, "${it.key}=${value}")
}
}
return appendedUrl
}
private fun getCache(cacheTime: Int, cacheUnit: TimeUnit): CacheControl {
return CacheControl.Builder().maxStale(cacheTime, cacheUnit).build()
}
/**
* Referer > Set headers > Set cookies > Default headers > Default Cookies
*/
fun getHeaders(
headers: Map<String, String>,
referer: String?,
cookie: Map<String, String>
): Headers {
val refererMap = (referer ?: DEFAULT_REFERER)?.let { mapOf("referer" to it) } ?: mapOf()
val cookieHeaders = (DEFAULT_COOKIES + cookie)
val cookieMap =
if (cookieHeaders.isNotEmpty()) mapOf(
"Cookie" to cookieHeaders.entries.joinToString(" ") {
"${it.key}=${it.value};"
}) else mapOf()
val tempHeaders = (DEFAULT_HEADERS + headers + cookieMap + refererMap)
return tempHeaders.toHeaders()
}
fun postRequestCreator(
url: String,
headers: Map<String, String> = emptyMap(),
referer: String? = null,
params: Map<String, String> = emptyMap(),
cookies: Map<String, String> = emptyMap(),
data: Any? = DEFAULT_DATA,
cacheTime: Int = DEFAULT_TIME,
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT
): Request {
return Request.Builder()
.url(addParamsToUrl(url, params))
.cacheControl(getCache(cacheTime, cacheUnit))
.headers(getHeaders(headers, referer, cookies))
.post(getData(data))
.build()
}
fun getRequestCreator(
url: String,
headers: Map<String, String> = emptyMap(),
referer: String? = null,
params: Map<String, String> = emptyMap(),
cookies: Map<String, String> = emptyMap(),
cacheTime: Int = DEFAULT_TIME,
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT
): Request {
return Request.Builder()
.url(addParamsToUrl(url, params))
.cacheControl(getCache(cacheTime, cacheUnit))
.headers(getHeaders(headers, referer, cookies))
.build()
}
fun putRequestCreator(
url: String,
headers: Map<String, String>,
referer: String?,
params: Map<String, String?>,
cookies: Map<String, String>,
data: Map<String, String?>,
cacheTime: Int,
cacheUnit: TimeUnit
): Request {
return Request.Builder()
.url(addParamsToUrl(url, params))
.cacheControl(getCache(cacheTime, cacheUnit))
.headers(getHeaders(headers, referer, cookies))
.put(getData(data))
.build()
}
fun optionsRequestCreator(
url: String,
headers: Map<String, String>,
referer: String?,
params: Map<String, String?>,
cookies: Map<String, String>,
data: Map<String, String?>,
cacheTime: Int,
cacheUnit: TimeUnit
): Request {
return Request.Builder()
.url(addParamsToUrl(url, params))
.cacheControl(getCache(cacheTime, cacheUnit))
.headers(getHeaders(headers, referer, cookies))
.method("OPTIONS", getData(data))
.build()
}
// https://stackoverflow.com/a/59322754
// Issues with Akwam otherwise
fun OkHttpClient.Builder.ignoreAllSSLErrors(): OkHttpClient.Builder {
val naiveTrustManager = @SuppressLint("CustomX509TrustManager")
object : X509TrustManager {
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
override fun checkClientTrusted(certs: Array<X509Certificate>, authType: String) = Unit
override fun checkServerTrusted(certs: Array<X509Certificate>, authType: String) = Unit
}
val insecureSocketFactory = SSLContext.getInstance("TLSv1.2").apply {
val trustAllCerts = arrayOf<TrustManager>(naiveTrustManager)
init(null, trustAllCerts, SecureRandom())
}.socketFactory
sslSocketFactory(insecureSocketFactory, naiveTrustManager)
hostnameVerifier { _, _ -> true }
return this
}
open class Requests {
var baseClient = OkHttpClient()
fun initClient(context: Context): OkHttpClient {
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
val dns = settingsManager.getInt(context.getString(R.string.dns_pref), 0)
baseClient = OkHttpClient.Builder()
.followRedirects(true)
.followSslRedirects(true)
.ignoreAllSSLErrors()
.cache(
// Note that you need to add a ResponseInterceptor to make this 100% active.
// The server response dictates if and when stuff should be cached.
Cache(
directory = File(context.cacheDir, "http_cache"),
maxSize = 50L * 1024L * 1024L // 50 MiB
)
).apply {
when (dns) {
1 -> addGoogleDns()
2 -> addCloudFlareDns()
// 3 -> addOpenDns()
4 -> addAdGuardDns()
}
}
// Needs to be build as otherwise the other builders will change this object
.build()
return baseClient
}
class ContinuationCallback(
private val call: Call,
private val continuation: CancellableContinuation<Response>
) : Callback, CompletionHandler {
@ExperimentalCoroutinesApi
override fun onResponse(call: Call, response: Response) {
continuation.resume(response, null)
}
override fun onFailure(call: Call, e: IOException) {
if (!call.isCanceled()) {
continuation.resumeWithException(e)
}
}
override fun invoke(cause: Throwable?) {
try {
call.cancel()
} catch (_: Throwable) {
}
}
}
companion object {
suspend inline fun Call.await(): Response {
return suspendCancellableCoroutine { continuation ->
val callback = ContinuationCallback(this, continuation)
enqueue(callback)
continuation.invokeOnCancellation(callback)
}
}
}
suspend fun get(
url: String,
headers: Map<String, String> = emptyMap(),
referer: String? = null,
params: Map<String, String> = emptyMap(),
cookies: Map<String, String> = emptyMap(),
allowRedirects: Boolean = true,
cacheTime: Int = DEFAULT_TIME,
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
timeout: Long = 0L,
interceptor: Interceptor? = null,
): AppResponse {
Log.i("GET", url)
val client = baseClient
.newBuilder()
.followRedirects(allowRedirects)
.followSslRedirects(allowRedirects)
.callTimeout(timeout, TimeUnit.SECONDS)
if (timeout > 0)
client
.connectTimeout(timeout, TimeUnit.SECONDS)
.readTimeout(timeout, TimeUnit.SECONDS)
if (interceptor != null) client.addInterceptor(interceptor)
val request =
getRequestCreator(url, headers, referer, params, cookies, cacheTime, cacheUnit)
val response = client.build().newCall(request).await()
return AppResponse(response)
}
fun executeRequest(request: Request): AppResponse {
return AppResponse(baseClient.newCall(request).execute())
}
suspend fun post(
url: String,
headers: Map<String, String> = mapOf(),
referer: String? = null,
params: Map<String, String> = mapOf(),
cookies: Map<String, String> = mapOf(),
data: Any? = DEFAULT_DATA,
allowRedirects: Boolean = true,
cacheTime: Int = DEFAULT_TIME,
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
timeout: Long = 0L,
): AppResponse {
Log.i("POST", url)
val client = baseClient
.newBuilder()
.followRedirects(allowRedirects)
.followSslRedirects(allowRedirects)
.callTimeout(timeout, TimeUnit.SECONDS)
.build()
val request =
postRequestCreator(url, headers, referer, params, cookies, data, cacheTime, cacheUnit)
val response = client.newCall(request).await()
return AppResponse(response)
}
suspend fun options(
url: String,
headers: Map<String, String> = mapOf(),
referer: String? = null,
params: Map<String, String> = mapOf(),
cookies: Map<String, String> = mapOf(),
data: Map<String, String?> = DEFAULT_DATA,
allowRedirects: Boolean = true,
cacheTime: Int = DEFAULT_TIME,
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
timeout: Long = 0L
): AppResponse {
Log.i("OPTIONS", url)
val client = baseClient
.newBuilder()
.followRedirects(allowRedirects)
.followSslRedirects(allowRedirects)
.callTimeout(timeout, TimeUnit.SECONDS)
.build()
val request =
optionsRequestCreator(
url,
headers,
referer,
params,
cookies,
data,
cacheTime,
cacheUnit
)
val response = client.newCall(request).await()
return AppResponse(response)
}
suspend fun put(
url: String,
headers: Map<String, String> = mapOf(),
referer: String? = null,
params: Map<String, String> = mapOf(),
cookies: Map<String, String> = mapOf(),
data: Map<String, String?> = DEFAULT_DATA,
allowRedirects: Boolean = true,
cacheTime: Int = DEFAULT_TIME,
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
timeout: Long = 0L
): AppResponse {
Log.i("PUT", url)
val client = baseClient
.newBuilder()
.followRedirects(allowRedirects)
.followSslRedirects(allowRedirects)
.callTimeout(timeout, TimeUnit.SECONDS)
.build()
val request =
putRequestCreator(url, headers, referer, params, cookies, data, cacheTime, cacheUnit)
val response = client.newCall(request).await()
return AppResponse(response)
}
}

View file

@ -0,0 +1,68 @@
package com.lagradost.cloudstream3.network
import android.content.Context
import androidx.preference.PreferenceManager
import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.nicehttp.Requests
import com.lagradost.nicehttp.getCookies
import com.lagradost.nicehttp.ignoreAllSSLErrors
import okhttp3.Cache
import okhttp3.Headers
import okhttp3.Headers.Companion.toHeaders
import okhttp3.OkHttpClient
import okhttp3.Request
import java.io.File
import java.util.concurrent.TimeUnit
fun Requests.initClient(context: Context): OkHttpClient {
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
val dns = settingsManager.getInt(context.getString(R.string.dns_pref), 0)
baseClient = OkHttpClient.Builder()
.followRedirects(true)
.followSslRedirects(true)
.ignoreAllSSLErrors()
.cache(
// Note that you need to add a ResponseInterceptor to make this 100% active.
// The server response dictates if and when stuff should be cached.
Cache(
directory = File(context.cacheDir, "http_cache"),
maxSize = 50L * 1024L * 1024L // 50 MiB
)
).apply {
when (dns) {
1 -> addGoogleDns()
2 -> addCloudFlareDns()
// 3 -> addOpenDns()
4 -> addAdGuardDns()
}
}
// Needs to be build as otherwise the other builders will change this object
.build()
return baseClient
}
val Request.cookies: Map<String, String>
get() {
return this.headers.getCookies("Cookie")
}
private val DEFAULT_HEADERS = mapOf("user-agent" to USER_AGENT)
/**
* Set headers > Set cookies > Default headers > Default Cookies
* TODO REMOVE AND REPLACE WITH NICEHTTP
*/
fun getHeaders(
headers: Map<String, String>,
cookie: Map<String, String>
): Headers {
val cookieMap =
if (cookie.isNotEmpty()) mapOf(
"Cookie" to cookie.entries.joinToString(" ") {
"${it.key}=${it.value};"
}) else mapOf()
val tempHeaders = (DEFAULT_HEADERS + headers + cookieMap)
return tempHeaders.toHeaders()
}

View file

@ -8,6 +8,7 @@ import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.Coroutines.main
import com.lagradost.nicehttp.requestCreator
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import okhttp3.Interceptor import okhttp3.Interceptor
@ -155,12 +156,12 @@ class WebViewResolver(val interceptUrl: Regex, val additionalUrls: List<Regex> =
request.method == "GET" -> app.get( request.method == "GET" -> app.get(
webViewUrl, webViewUrl,
headers = request.requestHeaders headers = request.requestHeaders
).response.toWebResourceResponse() ).okhttpResponse.toWebResourceResponse()
request.method == "POST" -> app.post( request.method == "POST" -> app.post(
webViewUrl, webViewUrl,
headers = request.requestHeaders headers = request.requestHeaders
).response.toWebResourceResponse() ).okhttpResponse.toWebResourceResponse()
else -> return@runBlocking super.shouldInterceptRequest( else -> return@runBlocking super.shouldInterceptRequest(
view, view,
request request
@ -206,28 +207,17 @@ class WebViewResolver(val interceptUrl: Regex, val additionalUrls: List<Regex> =
fun WebResourceRequest.toRequest(): Request { fun WebResourceRequest.toRequest(): Request {
val webViewUrl = this.url.toString() val webViewUrl = this.url.toString()
return when (this.method) { return requestCreator(
"POST" -> postRequestCreator( this.method,
webViewUrl, webViewUrl,
this.requestHeaders, this.requestHeaders,
null, null,
emptyMap(), emptyMap(),
emptyMap(), emptyMap(),
emptyMap<String, String>(), null,
10, 10,
TimeUnit.MINUTES TimeUnit.MINUTES
) )
// "GET",
else -> getRequestCreator(
webViewUrl,
this.requestHeaders,
null,
emptyMap(),
emptyMap(),
10,
TimeUnit.MINUTES
)
}
} }
fun Response.toWebResourceResponse(): WebResourceResponse { fun Response.toWebResourceResponse(): WebResourceResponse {

View file

@ -26,7 +26,7 @@ class NyaaProvider : MainAPI() {
if (tds.size < 2) continue if (tds.size < 2) continue
val type = tds[0].select("> a").attr("title") val type = tds[0].select("> a").attr("title")
val titleHeader = tds[1].select("> a").last() val titleHeader = tds[1].select("> a").last()
val href = titleHeader.attr("href") val href = titleHeader!!.attr("href")
val title = titleHeader.text() val title = titleHeader.text()
if (title.contains("[Batch]") || !type.contains("Anime")) continue if (title.contains("[Batch]") || !type.contains("Anime")) continue
returnValues.add(TorrentSearchResponse(title, fixUrl(href), this.name, TvType.Torrent, null)) returnValues.add(TorrentSearchResponse(title, fixUrl(href), this.name, TvType.Torrent, null))
@ -38,8 +38,8 @@ class NyaaProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val response = app.get(url).text val response = app.get(url).text
val document = Jsoup.parse(response) val document = Jsoup.parse(response)
val title = document.selectFirst("h3.panel-title").text() val title = document.selectFirst("h3.panel-title")!!.text()
val description = document.selectFirst("div#torrent-description").text() val description = document.selectFirst("div#torrent-description")!!.text()
val downloadLinks = document.select("div.panel-footer > a") val downloadLinks = document.select("div.panel-footer > a")
val magnet = downloadLinks[1].attr("href") val magnet = downloadLinks[1].attr("href")
val torrent = downloadLinks[0].attr("href") val torrent = downloadLinks[0].attr("href")

View file

@ -33,6 +33,7 @@ import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.network.initClient
import com.lagradost.cloudstream3.syncproviders.AccountManager import com.lagradost.cloudstream3.syncproviders.AccountManager
import com.lagradost.cloudstream3.syncproviders.OAuth2API import com.lagradost.cloudstream3.syncproviders.OAuth2API
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.aniListApi import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.aniListApi

View file

@ -84,8 +84,8 @@ object FillerEpisodeCheck {
val documented = Jsoup.parse(result) ?: return null val documented = Jsoup.parse(result) ?: return null
val hashMap = HashMap<Int, Boolean>() val hashMap = HashMap<Int, Boolean>()
documented.select("table.EpisodeList > tbody > tr").forEach { documented.select("table.EpisodeList > tbody > tr").forEach {
val type = it.selectFirst("td.Type > span").text() == "Filler" val type = it.selectFirst("td.Type > span")?.text() == "Filler"
val episodeNumber = it.selectFirst("td.Number").text().toIntOrNull() val episodeNumber = it.selectFirst("td.Number")?.text()?.toIntOrNull()
if (episodeNumber != null) { if (episodeNumber != null) {
hashMap[episodeNumber] = type hashMap[episodeNumber] = type
} }

View file

@ -13,7 +13,8 @@ import com.bumptech.glide.module.AppGlideModule
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.signature.ObjectKey import com.bumptech.glide.signature.ObjectKey
import com.lagradost.cloudstream3.network.DdosGuardKiller import com.lagradost.cloudstream3.network.DdosGuardKiller
import com.lagradost.cloudstream3.network.Requests import com.lagradost.cloudstream3.network.initClient
import com.lagradost.nicehttp.Requests
import java.io.InputStream import java.io.InputStream
@GlideModule @GlideModule

View file

@ -79,7 +79,7 @@ object SyncUtil {
suspend fun getUrlsFromId(id: String, type: String = "anilist") : List<String> { suspend fun getUrlsFromId(id: String, type: String = "anilist") : List<String> {
val url = val url =
"https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/$type/anime/$id.json" "https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/$type/anime/$id.json"
val response = app.get(url, cacheTime = 1, cacheUnit = TimeUnit.DAYS).mapped<SyncPage>() val response = app.get(url, cacheTime = 1, cacheUnit = TimeUnit.DAYS).parsed<SyncPage>()
val pages = response.pages ?: return emptyList() val pages = response.pages ?: return emptyList()
return pages.gogoanime.values.union(pages.nineanime.values).union(pages.twistmoe.values).mapNotNull { it.url } return pages.gogoanime.values.union(pages.nineanime.values).union(pages.twistmoe.values).mapNotNull { it.url }
} }