forked from recloudstream/cloudstream
Switched to NiceHttp
Used !! as it was easier (with 10000 providers) + visible errors
This commit is contained in:
parent
e64a875543
commit
109e1b9f17
56 changed files with 728 additions and 1094 deletions
|
@ -105,16 +105,16 @@ dependencies {
|
|||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
|
||||
//implementation "io.karn:khttp-android:0.1.2" //okhttp instead
|
||||
implementation 'org.jsoup:jsoup:1.13.1'
|
||||
implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.12.3"
|
||||
// implementation 'org.jsoup:jsoup:1.13.1'
|
||||
// implementation "com.fasterxml.jackson.module:jackson-module-kotlin:2.12.3"
|
||||
|
||||
implementation "com.google.android.material:material:1.5.0"
|
||||
|
||||
implementation "androidx.preference:preference-ktx:1.2.0"
|
||||
|
||||
implementation 'com.github.bumptech.glide:glide:4.13.0'
|
||||
kapt 'com.github.bumptech.glide:compiler:4.13.0'
|
||||
implementation 'com.github.bumptech.glide:okhttp3-integration:4.12.0'
|
||||
implementation 'com.github.bumptech.glide:glide:4.13.1'
|
||||
kapt 'com.github.bumptech.glide:compiler:4.13.1'
|
||||
implementation 'com.github.bumptech.glide:okhttp3-integration:4.13.0'
|
||||
|
||||
implementation 'jp.wasabeef:glide-transformations:4.3.0'
|
||||
|
||||
|
@ -154,8 +154,9 @@ dependencies {
|
|||
implementation "androidx.work:work-runtime-ktx:2.7.1"
|
||||
|
||||
// Networking
|
||||
implementation "com.squareup.okhttp3:okhttp:4.9.2"
|
||||
implementation "com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.1"
|
||||
// implementation "com.squareup.okhttp3:okhttp:4.9.2"
|
||||
// implementation "com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.1"
|
||||
implementation 'com.github.Blatzar:NiceHttp:0.1.8'
|
||||
|
||||
// Util to skip the URI file fuckery 🙏
|
||||
implementation "com.github.tachiyomiorg:unifile:17bec43"
|
||||
|
|
|
@ -36,7 +36,7 @@ import com.lagradost.cloudstream3.CommonActivity.showToast
|
|||
import com.lagradost.cloudstream3.CommonActivity.updateLocale
|
||||
import com.lagradost.cloudstream3.movieproviders.NginxProvider
|
||||
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.syncproviders.OAuth2API.Companion.OAuth2Apis
|
||||
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.navigate
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||
import com.lagradost.nicehttp.Requests
|
||||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_result_swipe.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
|
@ -32,10 +32,10 @@ class AnimeFlickProvider : MainAPI() {
|
|||
val html = app.get(link).text
|
||||
val doc = Jsoup.parse(html)
|
||||
|
||||
return doc.select(".row.mt-2").map {
|
||||
val href = mainUrl + it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("h5 > a").text()
|
||||
val poster = mainUrl + it.selectFirst("img").attr("src").replace("70x110", "225x320")
|
||||
return doc.select(".row.mt-2").mapNotNull {
|
||||
val href = mainUrl + it.selectFirst("a")?.attr("href")
|
||||
val title = it.selectFirst("h5 > a")?.text() ?: return@mapNotNull null
|
||||
val poster = mainUrl + it.selectFirst("img")?.attr("src")?.replace("70x110", "225x320")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
|
@ -52,19 +52,19 @@ class AnimeFlickProvider : MainAPI() {
|
|||
val html = app.get(url).text
|
||||
val doc = Jsoup.parse(html)
|
||||
|
||||
val poster = mainUrl + doc.selectFirst("img.rounded").attr("src")
|
||||
val title = doc.selectFirst("h2.title").text()
|
||||
val poster = mainUrl + doc.selectFirst("img.rounded")?.attr("src")
|
||||
val title = doc.selectFirst("h2.title")!!.text()
|
||||
|
||||
val yearText = doc.selectFirst(".trending-year")?.text()
|
||||
val year = if (yearText != null) Regex("""(\d{4})""").find(yearText)?.destructured?.component1()
|
||||
?.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 episodes = doc.select("#collapseOne .block-space > .row > div:nth-child(2)").map {
|
||||
val name = it.selectFirst("a").text()
|
||||
val link = mainUrl + it.selectFirst("a").attr("href")
|
||||
val name = it.selectFirst("a")?.text()
|
||||
val link = mainUrl + it.selectFirst("a")?.attr("href")
|
||||
Episode(link, name)
|
||||
}.reversed()
|
||||
|
||||
|
|
|
@ -7,10 +7,10 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
|||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
||||
import com.lagradost.cloudstream3.network.AppResponse
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.JsUnpacker
|
||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
import com.lagradost.nicehttp.NiceResponse
|
||||
import org.jsoup.Jsoup
|
||||
import kotlin.math.pow
|
||||
|
||||
|
@ -242,7 +242,7 @@ class AnimePaheProvider : MainAPI() {
|
|||
val doc = Jsoup.parse(html)
|
||||
|
||||
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()
|
||||
|
||||
|
@ -263,7 +263,7 @@ class AnimePaheProvider : MainAPI() {
|
|||
"completed" -> ShowStatus.Completed
|
||||
else -> null
|
||||
}
|
||||
val synopsis = doc.selectFirst(".anime-synopsis").text()
|
||||
val synopsis = doc.selectFirst(".anime-synopsis")?.text()
|
||||
|
||||
var anilistId: Int? = null
|
||||
var malId: Int? = null
|
||||
|
@ -431,7 +431,7 @@ class AnimePaheProvider : MainAPI() {
|
|||
}
|
||||
|
||||
var responseCode = 302
|
||||
var adflyContent: AppResponse? = null
|
||||
var adflyContent: NiceResponse? = null
|
||||
var tries = 0
|
||||
|
||||
while (responseCode != 200 && tries < 20) {
|
||||
|
@ -481,7 +481,7 @@ class AnimePaheProvider : MainAPI() {
|
|||
val decrypted = decrypt(fullString, key, v1.toInt(), v2.toInt())
|
||||
val uri = KWIK_D_URL.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 tries = 0
|
||||
|
|
|
@ -6,10 +6,10 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
|||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addRating
|
||||
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.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import com.lagradost.nicehttp.NiceResponse
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class AnimeWorldProvider : MainAPI() {
|
||||
|
@ -29,7 +29,7 @@ class AnimeWorldProvider : MainAPI() {
|
|||
private val cookieRegex = Regex("$cookieName=(.+?)(\\s?);")
|
||||
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)
|
||||
return cookieRegex.find(response.text)?.let {
|
||||
val verify = it.groups[1]?.value ?: throw ErrorLoadingException("Can't bypass protection")
|
||||
|
|
|
@ -7,19 +7,21 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import java.util.*
|
||||
|
||||
class AnimeflvnetProvider:MainAPI() {
|
||||
class AnimeflvnetProvider : MainAPI() {
|
||||
companion object {
|
||||
fun getType(t: String): TvType {
|
||||
return if (t.contains("OVA") || t.contains("Especial")) TvType.OVA
|
||||
else if (t.contains("Película")) TvType.AnimeMovie
|
||||
else TvType.Anime
|
||||
}
|
||||
|
||||
fun getDubStatus(title: String): DubStatus {
|
||||
return if (title.contains("Latino") || title.contains("Castellano"))
|
||||
DubStatus.Dubbed
|
||||
else DubStatus.Subbed
|
||||
}
|
||||
}
|
||||
|
||||
override var mainUrl = "https://www3.animeflv.net"
|
||||
override var name = "Animeflv.net"
|
||||
override val lang = "es"
|
||||
|
@ -42,13 +44,14 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
items.add(
|
||||
HomePageList(
|
||||
"Últimos episodios",
|
||||
app.get(mainUrl).document.select("main.Main ul.ListEpisodios li").map {
|
||||
val title = it.selectFirst("strong.Title").text()
|
||||
val poster = it.selectFirst("span img").attr("src")
|
||||
app.get(mainUrl).document.select("main.Main ul.ListEpisodios li").mapNotNull {
|
||||
val title = it.selectFirst("strong.Title")?.text() ?: return@mapNotNull null
|
||||
val poster = it.selectFirst("span img")?.attr("src") ?: return@mapNotNull null
|
||||
val epRegex = Regex("(-(\\d+)\$)")
|
||||
val url = it.selectFirst("a").attr("href").replace(epRegex,"")
|
||||
.replace("ver/","anime/")
|
||||
val epNum = it.selectFirst("span.Capi").text().replace("Episodio ","").toIntOrNull()
|
||||
val url = it.selectFirst("a")?.attr("href")?.replace(epRegex, "")
|
||||
?.replace("ver/", "anime/") ?: return@mapNotNull null
|
||||
val epNum =
|
||||
it.selectFirst("span.Capi")?.text()?.replace("Episodio ", "")?.toIntOrNull()
|
||||
newAnimeSearchResponse(title, url) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title), epNum)
|
||||
|
@ -58,10 +61,13 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
for ((url, name) in urls) {
|
||||
try {
|
||||
val doc = app.get(url).document
|
||||
val home = doc.select("ul.ListAnimes li article").map {
|
||||
val title = it.selectFirst("h3.Title").text()
|
||||
val poster = it.selectFirst("figure img").attr("src")
|
||||
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) {
|
||||
val home = doc.select("ul.ListAnimes li article").mapNotNull {
|
||||
val title = it.selectFirst("h3.Title")?.text() ?: return@mapNotNull null
|
||||
val poster = it.selectFirst("figure img")?.attr("src") ?: return@mapNotNull null
|
||||
newAnimeSearchResponse(
|
||||
title,
|
||||
fixUrl(it.selectFirst("a")?.attr("href") ?: return@mapNotNull null)
|
||||
) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(MonoschinosProvider.getDubStatus(title))
|
||||
}
|
||||
|
@ -76,7 +82,7 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
data class SearchObject (
|
||||
data class SearchObject(
|
||||
@JsonProperty("id") val id: String,
|
||||
@JsonProperty("title") val title: String,
|
||||
@JsonProperty("type") val type: String,
|
||||
|
@ -85,33 +91,36 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
)
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val response = app.post("https://www3.animeflv.net/api/animes/search",
|
||||
data = mapOf(Pair("value",query))
|
||||
val response = app.post(
|
||||
"https://www3.animeflv.net/api/animes/search",
|
||||
data = mapOf(Pair("value", query))
|
||||
).text
|
||||
val json = parseJson<List<SearchObject>>(response)
|
||||
return json.map { searchr ->
|
||||
return json.map { searchr ->
|
||||
val title = searchr.title
|
||||
val href = "$mainUrl/anime/${searchr.slug}"
|
||||
val image = "$mainUrl/uploads/animes/covers/${searchr.id}.jpg"
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
fixUrl(image),
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
fixUrl(image),
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
|
||||
DubStatus.Subbed
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url).document
|
||||
val episodes = ArrayList<Episode>()
|
||||
val title = doc.selectFirst("h1.Title").text()
|
||||
val poster = doc.selectFirst("div.AnimeCover div.Image figure img").attr("src")
|
||||
val description = doc.selectFirst("div.Description p").text()
|
||||
val type = doc.selectFirst("span.Type").text()
|
||||
val title = doc.selectFirst("h1.Title")!!.text()
|
||||
val poster = doc.selectFirst("div.AnimeCover div.Image figure img")?.attr("src")!!
|
||||
val description = doc.selectFirst("div.Description p")?.text()
|
||||
val type = doc.selectFirst("span.Type")?.text() ?: ""
|
||||
val status = when (doc.selectFirst("p.AnmStts span")?.text()) {
|
||||
"En emision" -> ShowStatus.Ongoing
|
||||
"Finalizado" -> ShowStatus.Completed
|
||||
|
@ -126,15 +135,16 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
data.split("],").forEach {
|
||||
val epNum = it.removePrefix("[").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 link = url.replace("/anime/","/ver/")+"-$epNum"
|
||||
episodes.add( Episode(
|
||||
link,
|
||||
null,
|
||||
posterUrl = epthumb,
|
||||
episode = epNum.toIntOrNull()
|
||||
)
|
||||
val link = url.replace("/anime/", "/ver/") + "-$epNum"
|
||||
episodes.add(
|
||||
Episode(
|
||||
link,
|
||||
null,
|
||||
posterUrl = epthumb,
|
||||
episode = epNum.toIntOrNull()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +157,7 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
tags = genre
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
|
@ -154,11 +165,13 @@ class AnimeflvnetProvider:MainAPI() {
|
|||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
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("\\/", "/")
|
||||
fetchUrls(videos).map {
|
||||
it.replace("https://embedsb.com/e/","https://watchsb.com/e/")
|
||||
.replace("https://ok.ru","http://ok.ru")
|
||||
it.replace("https://embedsb.com/e/", "https://watchsb.com/e/")
|
||||
.replace("https://ok.ru", "http://ok.ru")
|
||||
}.apmap {
|
||||
loadExtractor(it, data, callback)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ package com.lagradost.cloudstream3.animeproviders
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
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.ExtractorLink
|
||||
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=week", "Trending by week"),
|
||||
Pair("$mainUrl/ajax/list/views?type=month", "Trending by month"),
|
||||
)
|
||||
|
||||
)
|
||||
|
||||
val items = ArrayList<HomePageList>()
|
||||
|
||||
for ((url, name) in urls) {
|
||||
try {
|
||||
val items = urls.mapNotNull {
|
||||
suspendSafeApiCall {
|
||||
val home = Jsoup.parse(
|
||||
parseJson<Response>(
|
||||
app.get(
|
||||
url
|
||||
it.first
|
||||
).text
|
||||
).html
|
||||
).select("div.flw-item").map {
|
||||
val title = it.selectFirst("h3.title a").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val poster = it.selectFirst("img.lazyload").attr("data-src")
|
||||
).select("div.flw-item").mapNotNull secondMap@ {
|
||||
val title = it.selectFirst("h3.title a")?.text() ?: return@secondMap null
|
||||
val link = it.selectFirst("a")?.attr("href") ?: return@secondMap null
|
||||
val poster = it.selectFirst("img.lazyload")?.attr("data-src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
link,
|
||||
|
@ -60,52 +60,50 @@ class AnimekisaProvider : MainAPI() {
|
|||
) else EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
}
|
||||
|
||||
items.add(HomePageList(name, home))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
HomePageList(name, home)
|
||||
}
|
||||
}
|
||||
|
||||
if (items.size <= 0) throw ErrorLoadingException()
|
||||
if (items.isEmpty()) throw ErrorLoadingException()
|
||||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
return app.get("$mainUrl/search/?keyword=$query").document.select("div.flw-item").map {
|
||||
val title = it.selectFirst("h3 a").text()
|
||||
val url = it.selectFirst("a.film-poster-ahref").attr("href")
|
||||
.replace("watch/", "anime/").replace(
|
||||
Regex("(-episode-(\\d+)\\/\$|-episode-(\\d+)\$|-episode-full|-episode-.*-.(\\/|))"),
|
||||
""
|
||||
return app.get("$mainUrl/search/?keyword=$query").document.select("div.flw-item")
|
||||
.mapNotNull {
|
||||
val title = it.selectFirst("h3 a")?.text() ?: ""
|
||||
val url = it.selectFirst("a.film-poster-ahref")?.attr("href")
|
||||
?.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")
|
||||
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()
|
||||
}.toList()
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url, timeout = 120).document
|
||||
val poster = doc.selectFirst(".mb-2 img").attr("src")
|
||||
?: doc.selectFirst("head meta[property=og:image]").attr("content")
|
||||
val title = doc.selectFirst("h1.heading-name a").text()
|
||||
val description = doc.selectFirst("div.description p").text().trim()
|
||||
val poster = doc.selectFirst(".mb-2 img")?.attr("src")
|
||||
?: doc.selectFirst("head meta[property=og:image]")?.attr("content")
|
||||
val title = doc.selectFirst("h1.heading-name a")!!.text()
|
||||
val description = doc.selectFirst("div.description p")?.text()?.trim()
|
||||
val genres = doc.select("div.row-line a").map { it.text() }
|
||||
val test = if (doc.selectFirst("div.dp-i-c-right").toString()
|
||||
.contains("Airing")
|
||||
) ShowStatus.Ongoing else ShowStatus.Completed
|
||||
val episodes = doc.select("div.tab-content ul li.nav-item").map {
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val episodes = doc.select("div.tab-content ul li.nav-item").mapNotNull {
|
||||
val link = it.selectFirst("a")?.attr("href") ?: return@mapNotNull null
|
||||
Episode(link)
|
||||
}
|
||||
val type = if (doc.selectFirst(".dp-i-stats").toString()
|
||||
|
|
|
@ -57,9 +57,9 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
private suspend fun parseDocumentTrending(url: String): List<SearchResponse> {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
return document.select("li > a").map {
|
||||
return document.select("li > a").mapNotNull {
|
||||
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"))
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
|
@ -79,10 +79,11 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
): List<SearchResponse> {
|
||||
val response = app.get(url).text
|
||||
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 title = it.selectFirst("> div.gridtitlek").text()
|
||||
val poster = fixUrl(it.selectFirst("> img.grid__img").attr("src"))
|
||||
val title = it.selectFirst("> div.gridtitlek")?.text() ?: return@mapNotNull null
|
||||
val poster =
|
||||
fixUrl(it.selectFirst("> img.grid__img")?.attr("src") ?: return@mapNotNull null)
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
if (trimEpisode) href.removeRange(href.lastIndexOf('/'), href.length) else href,
|
||||
|
@ -135,9 +136,9 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
val document = Jsoup.parse(response)
|
||||
val items = document.select("div.grid__item > a")
|
||||
if (items.isEmpty()) return emptyList()
|
||||
return items.map { i ->
|
||||
return items.mapNotNull { i ->
|
||||
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"))
|
||||
|
||||
if (getIsMovie(href)) {
|
||||
|
@ -164,11 +165,11 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
val document = Jsoup.parse(response)
|
||||
val items = document.select("div.resultinner > a.resulta")
|
||||
if (items.isEmpty()) return ArrayList()
|
||||
return items.map { i ->
|
||||
return items.mapNotNull { i ->
|
||||
val innerDiv = i.selectFirst("> div.result")
|
||||
val href = fixUrl(i.attr("href"))
|
||||
val img = fixUrl(innerDiv.selectFirst("> div.imgkz > img").attr("src"))
|
||||
val title = innerDiv.selectFirst("> div.titleresults").text()
|
||||
val img = fixUrl(innerDiv?.selectFirst("> div.imgkz > img")?.attr("src") ?: return@mapNotNull null)
|
||||
val title = innerDiv.selectFirst("> div.titleresults")?.text() ?: return@mapNotNull null
|
||||
|
||||
if (getIsMovie(href)) {
|
||||
MovieSearchResponse(
|
||||
|
@ -244,12 +245,13 @@ class DubbedAnimeProvider : MainAPI() {
|
|||
} else {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
val title = document.selectFirst("h4").text()
|
||||
val title = document.selectFirst("h4")!!.text()
|
||||
val descriptHeader = document.selectFirst("div.animeDescript")
|
||||
val descript = descriptHeader.selectFirst("> p").text()
|
||||
val year = descriptHeader.selectFirst("> div.distatsx > div.sroverd").text()
|
||||
.replace("Released: ", "")
|
||||
.toIntOrNull()
|
||||
val descript = descriptHeader?.selectFirst("> p")?.text()
|
||||
val year = descriptHeader?.selectFirst("> div.distatsx > div.sroverd")
|
||||
?.text()
|
||||
?.replace("Released: ", "")
|
||||
?.toIntOrNull()
|
||||
|
||||
val episodes = document.select("a.epibloks").map {
|
||||
val epTitle = it.selectFirst("> div.inwel > span.isgrxx")?.text()
|
||||
|
|
|
@ -116,7 +116,8 @@ class GogoanimeProvider : MainAPI() {
|
|||
val encryptRequestData = if (isUsingAdaptiveData) {
|
||||
// Only fetch the document if necessary
|
||||
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)
|
||||
"id=$encryptedId&alias=$id&" + headers.substringAfter("&")
|
||||
} else {
|
||||
|
@ -246,17 +247,17 @@ class GogoanimeProvider : MainAPI() {
|
|||
val html = app.get(link).text
|
||||
val doc = Jsoup.parse(html)
|
||||
|
||||
val episodes = doc.select(""".last_episodes li""").map {
|
||||
val episodes = doc.select(""".last_episodes li""").mapNotNull {
|
||||
AnimeSearchResponse(
|
||||
it.selectFirst(".name").text().replace(" (Dub)", ""),
|
||||
fixUrl(it.selectFirst(".name > a").attr("href")),
|
||||
it.selectFirst(".name")?.text()?.replace(" (Dub)", "") ?: return@mapNotNull null,
|
||||
fixUrl(it.selectFirst(".name > a")?.attr("href") ?: return@mapNotNull null),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
it.selectFirst("img").attr("src"),
|
||||
it.selectFirst("img")?.attr("src"),
|
||||
it.selectFirst(".released")?.text()?.split(":")?.getOrNull(1)?.trim()
|
||||
?.toIntOrNull(),
|
||||
if (it.selectFirst(".name").text()
|
||||
.contains("Dub")
|
||||
if (it.selectFirst(".name")?.text()
|
||||
?.contains("Dub") == true
|
||||
) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
|
||||
DubStatus.Subbed
|
||||
),
|
||||
|
@ -282,8 +283,8 @@ class GogoanimeProvider : MainAPI() {
|
|||
val doc = Jsoup.parse(html)
|
||||
|
||||
val animeBody = doc.selectFirst(".anime_info_body_bg")
|
||||
val title = animeBody.selectFirst("h1").text()
|
||||
val poster = animeBody.selectFirst("img").attr("src")
|
||||
val title = animeBody?.selectFirst("h1")!!.text()
|
||||
val poster = animeBody.selectFirst("img")?.attr("src")
|
||||
var description: String? = null
|
||||
val genre = ArrayList<String>()
|
||||
var year: Int? = null
|
||||
|
@ -292,7 +293,7 @@ class GogoanimeProvider : MainAPI() {
|
|||
var type: String? = null
|
||||
|
||||
animeBody.select("p.type").forEach { pType ->
|
||||
when (pType.selectFirst("span").text().trim()) {
|
||||
when (pType.selectFirst("span")?.text()?.trim()) {
|
||||
"Plot Summary:" -> {
|
||||
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 episodes = app.get(episodeloadApi, params = params).document.select("a").map {
|
||||
Episode(
|
||||
fixUrl(it.attr("href").trim()),
|
||||
"Episode " + it.selectFirst(".name").text().replace("EP", "").trim()
|
||||
"Episode " + it.selectFirst(".name")?.text()?.replace("EP", "")?.trim()
|
||||
)
|
||||
}.reversed()
|
||||
|
||||
|
@ -357,7 +358,7 @@ class GogoanimeProvider : MainAPI() {
|
|||
private suspend fun extractVideos(uri: String, callback: (ExtractorLink) -> Unit) {
|
||||
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(
|
||||
{
|
||||
|
|
|
@ -20,31 +20,35 @@ class KawaiifuProvider : MainAPI() {
|
|||
|
||||
val soup = Jsoup.parse(resp)
|
||||
|
||||
items.add(HomePageList("Latest Updates", soup.select(".today-update .item").map {
|
||||
val title = it.selectFirst("img").attr("alt")
|
||||
items.add(HomePageList("Latest Updates", soup.select(".today-update .item").mapNotNull {
|
||||
val title = it.selectFirst("img")?.attr("alt")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
it.selectFirst("a").attr("href"),
|
||||
title ?: return@mapNotNull null,
|
||||
it.selectFirst("a")?.attr("href") ?: return@mapNotNull null,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
it.selectFirst("img").attr("src"),
|
||||
it.selectFirst("h4 > a").attr("href").split("-").last().toIntOrNull(),
|
||||
if (title.contains("(DUB)")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed),
|
||||
it.selectFirst("img")?.attr("src"),
|
||||
it.selectFirst("h4 > a")?.attr("href")?.split("-")?.last()?.toIntOrNull(),
|
||||
if (title.contains("(DUB)")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
|
||||
DubStatus.Subbed
|
||||
),
|
||||
)
|
||||
}))
|
||||
for (section in soup.select(".section")) {
|
||||
try {
|
||||
val title = section.selectFirst(".title").text()
|
||||
val anime = section.select(".list-film > .item").map { ani ->
|
||||
val animTitle = ani.selectFirst("img").attr("alt")
|
||||
val title = section.selectFirst(".title")!!.text()
|
||||
val anime = section.select(".list-film > .item").mapNotNull { ani ->
|
||||
val animTitle = ani.selectFirst("img")?.attr("alt")
|
||||
AnimeSearchResponse(
|
||||
animTitle,
|
||||
ani.selectFirst("a").attr("href"),
|
||||
animTitle ?: return@mapNotNull null,
|
||||
ani.selectFirst("a")?.attr("href") ?: return@mapNotNull null,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
ani.selectFirst("img").attr("src"),
|
||||
ani.selectFirst(".vl-chil-date").text().toIntOrNull(),
|
||||
if (animTitle.contains("(DUB)")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed),
|
||||
ani.selectFirst("img")?.attr("src"),
|
||||
ani.selectFirst(".vl-chil-date")?.text()?.toIntOrNull(),
|
||||
if (animTitle.contains("(DUB)")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
|
||||
DubStatus.Subbed
|
||||
),
|
||||
)
|
||||
}
|
||||
items.add(HomePageList(title, anime))
|
||||
|
@ -63,11 +67,11 @@ class KawaiifuProvider : MainAPI() {
|
|||
val html = app.get(link).text
|
||||
val soup = Jsoup.parse(html)
|
||||
|
||||
return ArrayList(soup.select(".item").map {
|
||||
val year = it.selectFirst("h4 > a").attr("href").split("-").last().toIntOrNull()
|
||||
val title = it.selectFirst("img").attr("alt")
|
||||
val poster = it.selectFirst("img").attr("src")
|
||||
val uri = it.selectFirst("a").attr("href")
|
||||
return ArrayList(soup.select(".item").mapNotNull {
|
||||
val year = it.selectFirst("h4 > a")?.attr("href")?.split("-")?.last()?.toIntOrNull()
|
||||
val title = it.selectFirst("img")?.attr("alt") ?: return@mapNotNull null
|
||||
val poster = it.selectFirst("img")?.attr("src")
|
||||
val uri = it.selectFirst("a")?.attr("href") ?: return@mapNotNull null
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
uri,
|
||||
|
@ -84,22 +88,26 @@ class KawaiifuProvider : MainAPI() {
|
|||
val html = app.get(url).text
|
||||
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 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 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(
|
||||
app.get(episodesLink).text
|
||||
).selectFirst(".list-ep").select("li").map {
|
||||
).selectFirst(".list-ep")?.select("li")?.map {
|
||||
Episode(
|
||||
it.selectFirst("a").attr("href"),
|
||||
if (it.text().trim().toIntOrNull() != null) "Episode ${it.text().trim()}" else it.text().trim()
|
||||
it.selectFirst("a")!!.attr("href"),
|
||||
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) {
|
||||
this.year = year
|
||||
|
@ -119,11 +127,13 @@ class KawaiifuProvider : MainAPI() {
|
|||
val htmlSource = app.get(data).text
|
||||
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 serverName = it.selectFirst(".server-name").text()
|
||||
val episodes = it.select(".list-ep > li > a").map { episode -> Pair(episode.attr("href"), episode.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 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) {
|
||||
ep
|
||||
|
|
|
@ -50,12 +50,12 @@ class MonoschinosProvider : MainAPI() {
|
|||
HomePageList(
|
||||
"Capítulos actualizados",
|
||||
app.get(mainUrl, timeout = 120).document.select(".col-6").map {
|
||||
val title = it.selectFirst("p.animetitles").text()
|
||||
val poster = it.selectFirst(".animeimghv").attr("data-src")
|
||||
val title = it.selectFirst("p.animetitles")!!.text()
|
||||
val poster = it.selectFirst(".animeimghv")!!.attr("data-src")
|
||||
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")
|
||||
val epNum = it.selectFirst(".positioning h5").text().toIntOrNull()
|
||||
val epNum = it.selectFirst(".positioning h5")?.text()?.toIntOrNull()
|
||||
newAnimeSearchResponse(title, url) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title), epNum)
|
||||
|
@ -66,9 +66,9 @@ class MonoschinosProvider : MainAPI() {
|
|||
for (i in urls) {
|
||||
try {
|
||||
val home = app.get(i.first, timeout = 120).document.select(".col-6").map {
|
||||
val title = it.selectFirst(".seristitles").text()
|
||||
val poster = it.selectFirst("img.animemainimg").attr("src")
|
||||
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) {
|
||||
val title = it.selectFirst(".seristitles")!!.text()
|
||||
val poster = it.selectFirst("img.animemainimg")!!.attr("src")
|
||||
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a")!!.attr("href"))) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title))
|
||||
}
|
||||
|
@ -87,9 +87,9 @@ class MonoschinosProvider : MainAPI() {
|
|||
override suspend fun search(query: String): ArrayList<SearchResponse> {
|
||||
val search =
|
||||
app.get("$mainUrl/buscar?q=$query", timeout = 120).document.select(".col-6").map {
|
||||
val title = it.selectFirst(".seristitles").text()
|
||||
val href = fixUrl(it.selectFirst("a").attr("href"))
|
||||
val image = it.selectFirst("img.animemainimg").attr("src")
|
||||
val title = it.selectFirst(".seristitles")!!.text()
|
||||
val href = fixUrl(it.selectFirst("a")!!.attr("href"))
|
||||
val image = it.selectFirst("img.animemainimg")!!.attr("src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
|
@ -107,10 +107,10 @@ class MonoschinosProvider : MainAPI() {
|
|||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url, timeout = 120).document
|
||||
val poster = doc.selectFirst(".chapterpic img").attr("src")
|
||||
val title = doc.selectFirst(".chapterdetails h1").text()
|
||||
val type = doc.selectFirst("div.chapterdetls2").text()
|
||||
val description = doc.selectFirst("p.textComplete").text().replace("Ver menos", "")
|
||||
val poster = doc.selectFirst(".chapterpic img")!!.attr("src")
|
||||
val title = doc.selectFirst(".chapterdetails h1")!!.text()
|
||||
val type = doc.selectFirst("div.chapterdetls2")!!.text()
|
||||
val description = doc.selectFirst("p.textComplete")!!.text().replace("Ver menos", "")
|
||||
val genres = doc.select(".breadcrumb-item a").map { it.text() }
|
||||
val status = when (doc.selectFirst("button.btn1")?.text()) {
|
||||
"Estreno" -> ShowStatus.Ongoing
|
||||
|
@ -118,9 +118,9 @@ class MonoschinosProvider : MainAPI() {
|
|||
else -> null
|
||||
}
|
||||
val episodes = doc.select("div.col-item").map {
|
||||
val name = it.selectFirst("p.animetitles").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val epThumb = it.selectFirst(".animeimghv").attr("data-src")
|
||||
val name = it.selectFirst("p.animetitles")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
val epThumb = it.selectFirst(".animeimghv")!!.attr("data-src")
|
||||
Episode(link, name, posterUrl = epThumb)
|
||||
}
|
||||
return newAnimeLoadResponse(title, url, getType(type)) {
|
||||
|
|
|
@ -45,11 +45,11 @@ class NineAnimeProvider : MainAPI() {
|
|||
val home = Jsoup.parse(
|
||||
app.get(
|
||||
url
|
||||
).mapped<Response>().html
|
||||
).parsed<Response>().html
|
||||
).select("ul.anime-list li").map {
|
||||
val title = it.selectFirst("a.name").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val poster = it.selectFirst("a.poster img").attr("src")
|
||||
val title = it.selectFirst("a.name")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
val poster = it.selectFirst("a.poster img")!!.attr("src")
|
||||
|
||||
newAnimeSearchResponse(title, link) {
|
||||
this.posterUrl = poster
|
||||
|
@ -173,11 +173,11 @@ class NineAnimeProvider : MainAPI() {
|
|||
val url = "$mainUrl/filter?sort=title%3Aasc&keyword=$query"
|
||||
|
||||
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 =
|
||||
fixUrlNull(it.selectFirst("a").attr("href"))?.replace(Regex("(\\?ep=(\\d+)\$)"), "")
|
||||
fixUrlNull(it.selectFirst("a")!!.attr("href"))?.replace(Regex("(\\?ep=(\\d+)\$)"), "")
|
||||
?: return@mapNotNull null
|
||||
val image = it.selectFirst("a.poster img").attr("src")
|
||||
val image = it.selectFirst("a.poster img")!!.attr("src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
|
@ -199,26 +199,26 @@ class NineAnimeProvider : MainAPI() {
|
|||
override suspend fun load(url: String): LoadResponse? {
|
||||
val validUrl = url.replace("https://9anime.to", mainUrl)
|
||||
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 poster = doc.selectFirst("aside.main div.thumb div img").attr("src")
|
||||
val title = doc.selectFirst(".info .title").text()
|
||||
val description = doc.selectFirst("div.info p").text().replace("Ver menos", "").trim()
|
||||
val poster = doc.selectFirst("aside.main div.thumb div img")!!.attr("src")
|
||||
val title = doc.selectFirst(".info .title")!!.text()
|
||||
val description = doc.selectFirst("div.info p")!!.text().replace("Ver menos", "").trim()
|
||||
val episodes = Jsoup.parse(
|
||||
app.get(
|
||||
"$mainUrl/ajax/anime/servers?ep=1&id=${animeid}&vrf=$animeidencoded&ep=8&episode=&token="
|
||||
).mapped<Response>().html
|
||||
)?.select("ul.episodes li a")?.mapNotNull {
|
||||
).parsed<Response>().html
|
||||
).select("ul.episodes li a").mapNotNull {
|
||||
val link = it?.attr("href") ?: return@mapNotNull null
|
||||
val name = "Episode ${it.text()}"
|
||||
Episode(link, name)
|
||||
} ?: return null
|
||||
}
|
||||
|
||||
val recommendations =
|
||||
doc.select("div.container aside.main section div.body ul.anime-list li")
|
||||
?.mapNotNull { element ->
|
||||
val recTitle = element.select("a.name")?.text() ?: return@mapNotNull null
|
||||
val image = element.select("a.poster img")?.attr("src")
|
||||
.mapNotNull { element ->
|
||||
val recTitle = element.select("a.name").text() ?: return@mapNotNull null
|
||||
val image = element.select("a.poster img").attr("src")
|
||||
val recUrl = fixUrl(element.select("a").attr("href"))
|
||||
newAnimeSearchResponse(recTitle, recUrl) {
|
||||
this.posterUrl = image
|
||||
|
@ -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 status =
|
||||
if (infodoc.contains("Completed")) ShowStatus.Completed
|
||||
|
@ -264,13 +264,13 @@ class NineAnimeProvider : MainAPI() {
|
|||
): Boolean {
|
||||
val document = app.get(data).document
|
||||
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)
|
||||
|
||||
Jsoup.parse(
|
||||
app.get(
|
||||
"$mainUrl/ajax/anime/servers?&id=${animeid}&vrf=$animeidencoded&episode=&token="
|
||||
).mapped<Response>().html
|
||||
).parsed<Response>().html
|
||||
).select("div.body").map { element ->
|
||||
val jsonregex = Regex("(\\{.+\\}.*$data)")
|
||||
val servers = jsonregex.find(element.toString())?.value?.replace(
|
||||
|
|
|
@ -47,6 +47,7 @@ class TenshiProvider : MainAPI() {
|
|||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val items = ArrayList<HomePageList>()
|
||||
val soup = app.get(mainUrl, interceptor = ddosGuardKiller).document
|
||||
println(soup)
|
||||
for (section in soup.select("#content > section")) {
|
||||
try {
|
||||
if (section.attr("id") == "toplist-tabs") {
|
||||
|
@ -58,11 +59,11 @@ class TenshiProvider : MainAPI() {
|
|||
}
|
||||
val anime = top.select("li > a").map {
|
||||
AnimeSearchResponse(
|
||||
it.selectFirst(".thumb-title").text(),
|
||||
it.selectFirst(".thumb-title")!!.text(),
|
||||
fixUrl(it.attr("href")),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
it.selectFirst("img").attr("src"),
|
||||
it.selectFirst("img")!!.attr("src"),
|
||||
null,
|
||||
EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
|
@ -70,14 +71,14 @@ class TenshiProvider : MainAPI() {
|
|||
items.add(HomePageList(title, anime))
|
||||
}
|
||||
} else {
|
||||
val title = section.selectFirst("h2").text()
|
||||
val title = section.selectFirst("h2")!!.text()
|
||||
val anime = section.select("li > a").map {
|
||||
AnimeSearchResponse(
|
||||
it.selectFirst(".thumb-title")?.text() ?: "",
|
||||
fixUrl(it.attr("href")),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
it.selectFirst("img").attr("src"),
|
||||
it.selectFirst("img")!!.attr("src"),
|
||||
null,
|
||||
EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
|
@ -104,7 +105,7 @@ class TenshiProvider : MainAPI() {
|
|||
val items = soup.select("ul.thumb > li > a")
|
||||
return items.map {
|
||||
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")
|
||||
if (getIsMovie(href, true)) {
|
||||
MovieSearchResponse(
|
||||
|
@ -225,10 +226,10 @@ class TenshiProvider : MainAPI() {
|
|||
interceptor = ddosGuardKiller
|
||||
).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 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()
|
||||
else 1
|
||||
|
||||
|
@ -283,7 +284,7 @@ class TenshiProvider : MainAPI() {
|
|||
?.trim()
|
||||
|
||||
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()
|
||||
|
||||
addEpisodes(DubStatus.Subbed, episodes)
|
||||
|
@ -310,7 +311,6 @@ class TenshiProvider : MainAPI() {
|
|||
@JsonProperty("size") val size: Int
|
||||
)
|
||||
|
||||
val sources = ArrayList<ExtractorLink>()
|
||||
for (source in soup.select("""[aria-labelledby="mirror-dropdown"] > li > a.dropdown-item""")) {
|
||||
val release = source.text().replace("/", "").trim()
|
||||
val sourceHTML = app.get(
|
||||
|
@ -330,24 +330,24 @@ class TenshiProvider : MainAPI() {
|
|||
.replace(",}", "}")
|
||||
.replace(",]", "]")
|
||||
)
|
||||
sources.addAll(qualities.map {
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"${this.name} $release",
|
||||
fixUrl(it.src),
|
||||
this.mainUrl,
|
||||
getQualityFromName("${it.size}"),
|
||||
headers = getHeaders(
|
||||
mapOf(),
|
||||
null,
|
||||
ddosGuardKiller.savedCookiesMap.get(URI(this.mainUrl).host) ?: mapOf()
|
||||
).toMap()
|
||||
qualities.forEach {
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"${this.name} $release",
|
||||
fixUrl(it.src),
|
||||
this.mainUrl,
|
||||
getQualityFromName("${it.size}"),
|
||||
headers = getHeaders(emptyMap(),
|
||||
ddosGuardKiller.savedCookiesMap[URI(this.mainUrl).host]
|
||||
?: emptyMap()
|
||||
).toMap()
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sources.forEach(callback)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,11 +38,11 @@ class WatchCartoonOnlineProvider : MainAPI() {
|
|||
|
||||
for (item in items) {
|
||||
val header = item.selectFirst("> div.iccerceve")
|
||||
val titleHeader = header.selectFirst("> div.aramadabaslik > a")
|
||||
val title = titleHeader.text()
|
||||
val titleHeader = header!!.selectFirst("> div.aramadabaslik > a")
|
||||
val title = titleHeader!!.text()
|
||||
val href = fixUrl(titleHeader.attr("href"))
|
||||
val poster = fixUrl(header.selectFirst("> a > img").attr("src"))
|
||||
val genreText = item.selectFirst("div.cerceve-tur-ve-genre").ownText()
|
||||
val poster = fixUrl(header.selectFirst("> a > img")!!.attr("src"))
|
||||
val genreText = item.selectFirst("div.cerceve-tur-ve-genre")!!.ownText()
|
||||
if (genreText.contains("cartoon")) {
|
||||
returnValue.add(TvSeriesSearchResponse(title, href, this.name, TvType.Cartoon, poster, null, null))
|
||||
} else {
|
||||
|
@ -76,7 +76,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
|
|||
|
||||
for (item in items) {
|
||||
val titleHeader = item.selectFirst("a")
|
||||
val title = titleHeader.text()
|
||||
val title = titleHeader!!.text()
|
||||
val href = fixUrl(titleHeader.attr("href"))
|
||||
//val isDubbed = title.contains("dubbed")
|
||||
//val set: EnumSet<DubStatus> =
|
||||
|
@ -103,9 +103,9 @@ class WatchCartoonOnlineProvider : MainAPI() {
|
|||
val document = Jsoup.parse(response)
|
||||
|
||||
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 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 episodes = document.select("div#catlist-listview > ul > li > a").reversed().map {
|
||||
val text = it.text()
|
||||
|
@ -152,7 +152,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
|
|||
val title = document.selectFirst(".iltext .Apple-style-span")?.text().toString()
|
||||
val b = document.select(".iltext b")
|
||||
val description = if (b.isNotEmpty()) {
|
||||
b.last().html().split("<br>")[0]
|
||||
b.last()!!.html().split("<br>")[0]
|
||||
} else null
|
||||
|
||||
TvSeriesLoadResponse(
|
||||
|
|
|
@ -50,15 +50,15 @@ class WcoProvider : MainAPI() {
|
|||
val results = document.select("div.flw-item").map {
|
||||
val filmPoster = it.selectFirst("> div.film-poster")
|
||||
val filmDetail = it.selectFirst("> div.film-detail")
|
||||
val nameHeader = filmDetail.selectFirst("> h3.film-name > a")
|
||||
val title = nameHeader.text().replace(" (Dub)", "")
|
||||
val nameHeader = filmDetail!!.selectFirst("> h3.film-name > a")
|
||||
val title = nameHeader!!.text().replace(" (Dub)", "")
|
||||
val href =
|
||||
nameHeader.attr("href").replace("/watch/", "/anime/")
|
||||
.replace(Regex("-episode-.*"), "/")
|
||||
val isDub =
|
||||
filmPoster.selectFirst("> div.film-poster-quality")?.text()?.contains("DUB")
|
||||
filmPoster!!.selectFirst("> div.film-poster-quality")?.text()?.contains("DUB")
|
||||
?: false
|
||||
val poster = filmPoster.selectFirst("> img").attr("data-src")
|
||||
val poster = filmPoster.selectFirst("> img")!!.attr("data-src")
|
||||
val set: EnumSet<DubStatus> =
|
||||
EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed)
|
||||
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")
|
||||
if (items.isEmpty()) return ArrayList()
|
||||
return items.map { i ->
|
||||
val href = fixAnimeLink(i.selectFirst("a").attr("href"))
|
||||
val img = fixUrl(i.selectFirst("img").attr("data-src"))
|
||||
val title = i.selectFirst("img").attr("title")
|
||||
val href = fixAnimeLink(i.selectFirst("a")!!.attr("href"))
|
||||
val img = fixUrl(i.selectFirst("img")!!.attr("data-src"))
|
||||
val title = i.selectFirst("img")!!.attr("title")
|
||||
val isDub = !i.select(".pick.film-poster-quality").isEmpty()
|
||||
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()
|
||||
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) {
|
||||
MovieSearchResponse(
|
||||
|
|
|
@ -8,11 +8,11 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
|||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream
|
||||
import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.runSflixExtractorVerifierJob
|
||||
import com.lagradost.cloudstream3.network.Requests.Companion.await
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import com.lagradost.nicehttp.Requests.Companion.await
|
||||
import okhttp3.Interceptor
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
|
@ -141,7 +141,7 @@ class ZoroProvider : MainAPI() {
|
|||
return document.select(".flw-item").map {
|
||||
val title = it.selectFirst(".film-detail > .film-name > a")?.attr("title").toString()
|
||||
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 ->
|
||||
// current episode / max episode
|
||||
|
@ -154,7 +154,7 @@ class ZoroProvider : MainAPI() {
|
|||
|
||||
val tvType =
|
||||
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) {
|
||||
this.posterUrl = poster
|
||||
|
@ -327,11 +327,11 @@ class ZoroProvider : MainAPI() {
|
|||
|
||||
val servers: List<Pair<DubStatus, String>> = Jsoup.parse(
|
||||
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 {
|
||||
Pair(
|
||||
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}"
|
||||
val extractorLink = app.get(
|
||||
link,
|
||||
).mapped<RapidCloudResponse>().link
|
||||
).parsed<RapidCloudResponse>().link
|
||||
val hasLoadedExtractorLink =
|
||||
loadExtractor(extractorLink, "https://rapid-cloud.ru/", callback)
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ open class WcoStream : ExtractorApi() {
|
|||
@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>()
|
||||
|
||||
if (mapped.success) {
|
||||
|
|
|
@ -37,14 +37,14 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
for ((name, element) in urls) {
|
||||
try {
|
||||
val home = soup.select(element).map {
|
||||
val title = it.selectFirst("h2.title").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("h2.title")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
fixUrl(it.selectFirst("figure img").attr("data-src")),
|
||||
fixUrl(it.selectFirst("figure img")!!.attr("data-src")),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
|
@ -66,8 +66,8 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
val items = document.select("ul.MovieList > li > article > a")
|
||||
return items.map { item ->
|
||||
val href = item.attr("href")
|
||||
val title = item.selectFirst("> h2.Title").text()
|
||||
val img = fixUrl(item.selectFirst("> div.Image > figure > img").attr("data-src"))
|
||||
val title = item.selectFirst("> h2.Title")!!.text()
|
||||
val img = fixUrl(item.selectFirst("> div.Image > figure > img")!!.attr("data-src"))
|
||||
val type = getType(href)
|
||||
if (type == TvType.Movie) {
|
||||
MovieSearchResponse(title, href, this.name, type, img, null)
|
||||
|
@ -108,12 +108,12 @@ class AllMoviesForYouProvider : MainAPI() {
|
|||
|
||||
val document = app.get(url).document
|
||||
|
||||
val title = document.selectFirst("h1.Title").text()
|
||||
val descipt = document.selectFirst("div.Description > p").text()
|
||||
val title = document.selectFirst("h1.Title")!!.text()
|
||||
val descipt = document.selectFirst("div.Description > p")!!.text()
|
||||
val rating =
|
||||
document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toRatingInt()
|
||||
val year = document.selectFirst("span.Date")?.text()
|
||||
val duration = document.selectFirst("span.Time").text()
|
||||
val duration = document.selectFirst("span.Time")!!.text()
|
||||
val backgroundPoster =
|
||||
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 poster = episode.selectFirst("> td.MvTbImg > a > img")?.attr("data-src")
|
||||
val aName = episode.selectFirst("> td.MvTbTtl > a")
|
||||
val name = aName.text()
|
||||
val name = aName!!.text()
|
||||
val href = aName.attr("href")
|
||||
val date = episode.selectFirst("> td.MvTbTtl > span")?.text()
|
||||
|
||||
|
|
|
@ -32,16 +32,16 @@ open class BflixProvider : MainAPI() {
|
|||
)
|
||||
for ((name, element) in testa) try {
|
||||
val test = soup.select(element).map {
|
||||
val title = it.selectFirst("h3 a").text()
|
||||
val link = fixUrl(it.selectFirst("a").attr("href"))
|
||||
val qualityInfo = it.selectFirst("div.quality").text()
|
||||
val title = it.selectFirst("h3 a")!!.text()
|
||||
val link = fixUrl(it.selectFirst("a")!!.attr("href"))
|
||||
val qualityInfo = it.selectFirst("div.quality")!!.text()
|
||||
val quality = getQualityFromString(qualityInfo)
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
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,
|
||||
quality = quality
|
||||
|
@ -167,11 +167,11 @@ open class BflixProvider : MainAPI() {
|
|||
val document = Jsoup.parse(html)
|
||||
|
||||
return document.select(".filmlist div.item").map {
|
||||
val title = it.selectFirst("h3 a").text()
|
||||
val href = fixUrl(it.selectFirst("a").attr("href"))
|
||||
val image = it.selectFirst("a.poster img").attr("src")
|
||||
val title = it.selectFirst("h3 a")!!.text()
|
||||
val href = fixUrl(it.selectFirst("a")!!.attr("href"))
|
||||
val image = it.selectFirst("a.poster img")!!.attr("src")
|
||||
val isMovie = href.contains("/movie/")
|
||||
val qualityInfo = it.selectFirst("div.quality").text()
|
||||
val qualityInfo = it.selectFirst("div.quality")!!.text()
|
||||
val quality = getQualityFromString(qualityInfo)
|
||||
|
||||
if (isMovie) {
|
||||
|
@ -205,33 +205,33 @@ open class BflixProvider : MainAPI() {
|
|||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
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 title = soup.selectFirst("div.info h1").text()
|
||||
val title = soup.selectFirst("div.info h1")!!.text()
|
||||
val description = soup.selectFirst(".info .desc")?.text()?.trim()
|
||||
val poster: String? = try {
|
||||
soup.selectFirst("img.poster").attr("src")
|
||||
soup.selectFirst("img.poster")!!.attr("src")
|
||||
} 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 episodes = Jsoup.parse(
|
||||
app.get(
|
||||
"$mainUrl/ajax/film/servers?id=$movieid&vrf=$movieidencoded"
|
||||
).mapped<Response>().html
|
||||
).parsed<Response>().html
|
||||
).select("div.episode").map {
|
||||
val a = it.selectFirst("a")
|
||||
val href = fixUrl(a.attr("href"))
|
||||
val extraData = a.attr("data-kname")?.let { str ->
|
||||
val href = fixUrl(a!!.attr("href"))
|
||||
val extraData = a.attr("data-kname").let { str ->
|
||||
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||
}
|
||||
val isValid = extraData?.size == 2
|
||||
val episode = if (isValid) extraData?.getOrNull(1) else null
|
||||
val season = if (isValid) extraData?.getOrNull(0) else null
|
||||
val isValid = extraData.size == 2
|
||||
val episode = if (isValid) extraData.getOrNull(1) else null
|
||||
val season = if (isValid) extraData.getOrNull(0) else null
|
||||
|
||||
val eptitle = it.selectFirst(".episode a span.name").text()
|
||||
val secondtitle = it.selectFirst(".episode a span").text()
|
||||
val eptitle = it.selectFirst(".episode a span.name")!!.text()
|
||||
val secondtitle = it.selectFirst(".episode a span")!!.text()
|
||||
.replace(Regex("(Episode (\\d+):|Episode (\\d+)-|Episode (\\d+))"),"") ?: ""
|
||||
Episode(
|
||||
href,
|
||||
|
@ -329,7 +329,7 @@ open class BflixProvider : MainAPI() {
|
|||
): Boolean {
|
||||
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)
|
||||
Jsoup.parse(
|
||||
parseJson<Response>(
|
||||
|
|
|
@ -31,14 +31,14 @@ class CinecalidadProvider:MainAPI() {
|
|||
try {
|
||||
val soup = app.get(url).document
|
||||
val home = soup.select(".item.movies").map {
|
||||
val title = it.selectFirst("div.in_title").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("div.in_title")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
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,
|
||||
)
|
||||
|
@ -59,9 +59,9 @@ class CinecalidadProvider:MainAPI() {
|
|||
val document = app.get(url).document
|
||||
|
||||
return document.select("article").map {
|
||||
val title = it.selectFirst("div.in_title").text()
|
||||
val href = it.selectFirst("a").attr("href")
|
||||
val image = it.selectFirst(".poster.custom img").attr("data-src")
|
||||
val title = it.selectFirst("div.in_title")!!.text()
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val image = it.selectFirst(".poster.custom img")!!.attr("data-src")
|
||||
val isMovie = href.contains("/ver-pelicula/")
|
||||
|
||||
if (isMovie) {
|
||||
|
@ -91,14 +91,14 @@ class CinecalidadProvider:MainAPI() {
|
|||
override suspend fun load(url: String): LoadResponse? {
|
||||
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 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 href = li.selectFirst("a").attr("href")
|
||||
val epThumb = li.selectFirst("img.lazy").attr("data-src")
|
||||
val name = li.selectFirst(".episodiotitle a").text()
|
||||
val seasonid = li.selectFirst(".numerando").text().replace(Regex("(S|E)"),"").let { str ->
|
||||
val href = li.selectFirst("a")!!.attr("href")
|
||||
val epThumb = li.selectFirst("img.lazy")!!.attr("data-src")
|
||||
val name = li.selectFirst(".episodiotitle a")!!.text()
|
||||
val seasonid = li.selectFirst(".numerando")!!.text().replace(Regex("(S|E)"),"").let { str ->
|
||||
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||
}
|
||||
val isValid = seasonid.size == 2
|
||||
|
@ -182,7 +182,7 @@ class CinecalidadProvider:MainAPI() {
|
|||
"Sec-Fetch-Site" to "same-origin",
|
||||
"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")) {
|
||||
loadExtractor(extractedurl, mainUrl, callback)
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ class CinecalidadProvider:MainAPI() {
|
|||
"Sec-Fetch-Site" to "same-origin",
|
||||
"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")) {
|
||||
loadExtractor(extractedurl, mainUrl, callback)
|
||||
}
|
||||
|
@ -238,7 +238,7 @@ class CinecalidadProvider:MainAPI() {
|
|||
val validsub = docsub.text
|
||||
if (validsub.contains("Subtítulo") || validsub.contains("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()
|
||||
linksub.select("a.link").apmap {
|
||||
val sublink = if (data.contains("serie") || data.contains("episodio")) "${data}${it.attr("href")}"
|
||||
|
|
|
@ -30,9 +30,9 @@ class CuevanaProvider : MainAPI() {
|
|||
"Series",
|
||||
app.get("$mainUrl/serie", timeout = 120).document.select("section.home-series li")
|
||||
.map {
|
||||
val title = it.selectFirst("h2.Title").text()
|
||||
val poster = it.selectFirst("img.lazy").attr("data-src")
|
||||
val url = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("h2.Title")!!.text()
|
||||
val poster = it.selectFirst("img.lazy")!!.attr("data-src")
|
||||
val url = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
url,
|
||||
|
@ -48,14 +48,14 @@ class CuevanaProvider : MainAPI() {
|
|||
try {
|
||||
val soup = app.get(url).document
|
||||
val home = soup.select("section li.xxx.TPostMv").map {
|
||||
val title = it.selectFirst("h2.Title").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("h2.Title")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
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,
|
||||
)
|
||||
|
@ -76,9 +76,9 @@ class CuevanaProvider : MainAPI() {
|
|||
val document = app.get(url).document
|
||||
|
||||
return document.select("li.xxx.TPostMv").map {
|
||||
val title = it.selectFirst("h2.Title").text()
|
||||
val href = it.selectFirst("a").attr("href")
|
||||
val image = it.selectFirst("img.lazy").attr("data-src")
|
||||
val title = it.selectFirst("h2.Title")!!.text()
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val image = it.selectFirst("img.lazy")!!.attr("data-src")
|
||||
val isSerie = href.contains("/serie/")
|
||||
|
||||
if (isSerie) {
|
||||
|
@ -106,9 +106,9 @@ class CuevanaProvider : MainAPI() {
|
|||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
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 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 yearRegex = Regex("<span>(\\d+)</span>")
|
||||
val yearf =
|
||||
|
@ -117,9 +117,9 @@ class CuevanaProvider : MainAPI() {
|
|||
val episodes = soup.select(".all-episodes li.TPostMv article").map { li ->
|
||||
val href = li.select("a").attr("href")
|
||||
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")
|
||||
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() }
|
||||
}
|
||||
val isValid = seasonid.size == 2
|
||||
|
@ -255,7 +255,7 @@ class CuevanaProvider : MainAPI() {
|
|||
"Sec-Fetch-Site" to "same-origin",
|
||||
),
|
||||
data = mapOf(Pair("url", tomkey))
|
||||
).response.headers.values("location").apmap { loc ->
|
||||
).okhttpResponse.headers.values("location").apmap { loc ->
|
||||
if (loc.contains("goto_ddh.php")) {
|
||||
val gotoregex =
|
||||
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",
|
||||
),
|
||||
data = mapOf(Pair("url", gotolink))
|
||||
).response.headers.values("location").apmap { golink ->
|
||||
).okhttpResponse.headers.values("location").apmap { golink ->
|
||||
loadExtractor(golink, data, callback)
|
||||
}
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ class CuevanaProvider : MainAPI() {
|
|||
"Sec-Fetch-User" to "?1",
|
||||
),
|
||||
data = mapOf(Pair("h", inlink))
|
||||
).response.headers.values("location").apmap { link ->
|
||||
).okhttpResponse.headers.values("location").apmap { link ->
|
||||
loadExtractor(link, data, callback)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,12 +52,12 @@ class DoramasYTProvider : MainAPI() {
|
|||
HomePageList(
|
||||
"Capítulos actualizados",
|
||||
app.get(mainUrl, timeout = 120).document.select(".col-6").map {
|
||||
val title = it.selectFirst("p").text()
|
||||
val poster = it.selectFirst(".chapter img").attr("src")
|
||||
val title = it.selectFirst("p")!!.text()
|
||||
val poster = it.selectFirst(".chapter img")!!.attr("src")
|
||||
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")
|
||||
val epNum = it.selectFirst("h3").text().toIntOrNull()
|
||||
val epNum = it.selectFirst("h3")!!.text().toIntOrNull()
|
||||
newAnimeSearchResponse(title,url) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title), epNum)
|
||||
|
@ -68,9 +68,9 @@ class DoramasYTProvider : MainAPI() {
|
|||
for (i in urls) {
|
||||
try {
|
||||
val home = app.get(i.first, timeout = 120).document.select(".col-6").map {
|
||||
val title = it.selectFirst(".animedtls p").text()
|
||||
val poster = it.selectFirst(".anithumb img").attr("src")
|
||||
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a").attr("href"))) {
|
||||
val title = it.selectFirst(".animedtls p")!!.text()
|
||||
val poster = it.selectFirst(".anithumb img")!!.attr("src")
|
||||
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a")!!.attr("href"))) {
|
||||
this.posterUrl = fixUrl(poster)
|
||||
addDubStatus(getDubStatus(title))
|
||||
}
|
||||
|
@ -88,9 +88,9 @@ class DoramasYTProvider : MainAPI() {
|
|||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
return app.get("$mainUrl/buscar?q=$query", timeout = 120).document.select(".col-6").map {
|
||||
val title = it.selectFirst(".animedtls p").text()
|
||||
val href = it.selectFirst("a").attr("href")
|
||||
val image = it.selectFirst(".animes img").attr("src")
|
||||
val title = it.selectFirst(".animedtls p")!!.text()
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val image = it.selectFirst(".animes img")!!.attr("src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
|
@ -107,10 +107,10 @@ class DoramasYTProvider : MainAPI() {
|
|||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url, timeout = 120).document
|
||||
val poster = doc.selectFirst("div.flimimg img.img1").attr("src")
|
||||
val title = doc.selectFirst("h1").text()
|
||||
val type = doc.selectFirst("h4").text()
|
||||
val description = doc.selectFirst("p.textComplete").text().replace("Ver menos", "")
|
||||
val poster = doc.selectFirst("div.flimimg img.img1")!!.attr("src")
|
||||
val title = doc.selectFirst("h1")!!.text()
|
||||
val type = doc.selectFirst("h4")!!.text()
|
||||
val description = doc.selectFirst("p.textComplete")!!.text().replace("Ver menos", "")
|
||||
val genres = doc.select(".nobel a").map { it.text() }
|
||||
val status = when (doc.selectFirst(".state h6")?.text()) {
|
||||
"Estreno" -> ShowStatus.Ongoing
|
||||
|
@ -118,9 +118,9 @@ class DoramasYTProvider : MainAPI() {
|
|||
else -> null
|
||||
}
|
||||
val episodes = doc.select(".heromain .col-item").map {
|
||||
val name = it.selectFirst(".dtlsflim p").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val epThumb = it.selectFirst(".flimimg img.img1").attr("src")
|
||||
val name = it.selectFirst(".dtlsflim p")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
val epThumb = it.selectFirst(".flimimg img.img1")!!.attr("src")
|
||||
Episode(link, name, posterUrl = epThumb)
|
||||
}
|
||||
return newAnimeLoadResponse(title, url, getType(type)) {
|
||||
|
|
|
@ -46,7 +46,7 @@ class EgyBestProvider : MainAPI() {
|
|||
val pages = arrayListOf<HomePageList>()
|
||||
doc.select("#mainLoad div.mbox").apmap {
|
||||
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>()
|
||||
it.select(".movie").map { element ->
|
||||
list.add(element.toSearchResponse()!!)
|
||||
|
@ -87,16 +87,16 @@ class EgyBestProvider : MainAPI() {
|
|||
it.text().contains("النوع")
|
||||
}?.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 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)
|
||||
ActorData(actor = mainActor, roleString = roleString)
|
||||
}
|
||||
|
||||
return if (isMovie) {
|
||||
val recommendations = doc.select(".movies_small .movie")?.mapNotNull { element ->
|
||||
val recommendations = doc.select(".movies_small .movie").mapNotNull { element ->
|
||||
element.toSearchResponse()
|
||||
}
|
||||
|
||||
|
|
|
@ -30,14 +30,14 @@ class EntrepeliculasyseriesProvider:MainAPI() {
|
|||
try {
|
||||
val soup = app.get(url).document
|
||||
val home = soup.select("ul.list-movie li").map {
|
||||
val title = it.selectFirst("a.link-title h2").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("a.link-title h2")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
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,
|
||||
)
|
||||
|
@ -58,9 +58,9 @@ class EntrepeliculasyseriesProvider:MainAPI() {
|
|||
val document = app.get(url).document
|
||||
|
||||
return document.select("li.xxx.TPostMv").map {
|
||||
val title = it.selectFirst("h2.Title").text()
|
||||
val href = it.selectFirst("a").attr("href")
|
||||
val image = it.selectFirst("img.lazy").attr("data-src")
|
||||
val title = it.selectFirst("h2.Title")!!.text()
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val image = it.selectFirst("img.lazy")!!.attr("data-src")
|
||||
val isMovie = href.contains("/pelicula/")
|
||||
|
||||
if (isMovie) {
|
||||
|
@ -90,13 +90,13 @@ class EntrepeliculasyseriesProvider:MainAPI() {
|
|||
override suspend fun load(url: String): LoadResponse? {
|
||||
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 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 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 seasonid = li.selectFirst("span.Year").text().let { str ->
|
||||
val epThumb = li.selectFirst("div.Image img")!!.attr("data-src")
|
||||
val seasonid = li.selectFirst("span.Year")!!.text().let { str ->
|
||||
str.split("x").mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||
}
|
||||
val isValid = seasonid.size == 2
|
||||
|
@ -169,7 +169,7 @@ class EntrepeliculasyseriesProvider:MainAPI() {
|
|||
//params = mapOf(Pair("h", postkey)),
|
||||
data = mapOf(Pair("h", postkey)),
|
||||
allowRedirects = false
|
||||
).response.headers.values("location").apmap {
|
||||
).okhttpResponse.headers.values("location").apmap {
|
||||
loadExtractor(it, data, callback)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ class FilmanProvider : MainAPI() {
|
|||
val lists = document.select(".item-list,.series-list")
|
||||
val categories = ArrayList<HomePageList>()
|
||||
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 name = i.select("a[href]").attr("title")
|
||||
val href = i.select("a[href]").attr("href")
|
||||
|
@ -63,8 +63,8 @@ class FilmanProvider : MainAPI() {
|
|||
fun getVideos(type: TvType, items: Elements): List<SearchResponse> {
|
||||
return items.map { i ->
|
||||
val href = i.attr("href")
|
||||
val img = i.selectFirst("> img").attr("src").replace("/thumb/", "/big/")
|
||||
val name = i.selectFirst(".title").text()
|
||||
val img = i.selectFirst("> img")!!.attr("src").replace("/thumb/", "/big/")
|
||||
val name = i.selectFirst(".title")!!.text()
|
||||
if (type === TvType.TvSeries) {
|
||||
TvSeriesSearchResponse(
|
||||
name,
|
||||
|
@ -95,7 +95,7 @@ class FilmanProvider : MainAPI() {
|
|||
if (episodesElements.isEmpty()) {
|
||||
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 e = episode.text()
|
||||
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()
|
||||
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 link = mapper.readValue<LinkElement>(decoded).src
|
||||
loadExtractor(link, null, callback)
|
||||
|
|
|
@ -23,9 +23,9 @@ class HDMProvider : MainAPI() {
|
|||
|
||||
return items.map { i ->
|
||||
val href = i.attr("href")
|
||||
val data = i.selectFirst("> div.item")
|
||||
val img = data.selectFirst("> img").attr("src")
|
||||
val name = data.selectFirst("> div.movie-details").text()
|
||||
val data = i.selectFirst("> div.item")!!
|
||||
val img = data.selectFirst("> img")!!.attr("src")
|
||||
val name = data.selectFirst("> div.movie-details")!!.text()
|
||||
MovieSearchResponse(name, href, this.name, TvType.Movie, img, null)
|
||||
}
|
||||
}
|
||||
|
@ -57,9 +57,9 @@ class HDMProvider : MainAPI() {
|
|||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
val title = document.selectFirst("h2.movieTitle")?.text() ?: throw ErrorLoadingException("No Data Found")
|
||||
val poster = document.selectFirst("div.post-thumbnail > img").attr("src")
|
||||
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 poster = document.selectFirst("div.post-thumbnail > img")!!.attr("src")
|
||||
val descript = document.selectFirst("div.synopsis > p")!!.text()
|
||||
val year = document.select("div.movieInfoAll > div.row > div.col-md-6").getOrNull(1)?.selectFirst("> p > a")?.text()
|
||||
?.toIntOrNull()
|
||||
val data = "src/player/\\?v=(.*?)\"".toRegex().find(response)?.groupValues?.get(1) ?: return null
|
||||
|
||||
|
|
|
@ -56,10 +56,10 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
res.selectFirst("a[href][title]")
|
||||
}
|
||||
val year = Regex("""•?\s+(\d{4})\s+•""").find(
|
||||
res.selectFirst(".episodeMeta").text()
|
||||
res.selectFirst(".episodeMeta")!!.text()
|
||||
)?.destructured?.component1()?.toIntOrNull()
|
||||
|
||||
val title = aTag.attr("title")
|
||||
val title = aTag!!.attr("title")
|
||||
val href = fixUrl(aTag.attr("href"))
|
||||
searchResults[href] = TvSeriesSearchResponse(
|
||||
title,
|
||||
|
@ -98,11 +98,11 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
}
|
||||
val year =
|
||||
Regex("""•?\s+(\d{4})\s+•""").find(
|
||||
res.selectFirst(".episodeMeta").text()
|
||||
res.selectFirst(".episodeMeta")!!.text()
|
||||
)?.destructured?.component1()
|
||||
?.toIntOrNull()
|
||||
|
||||
val title = aTag.attr("title")
|
||||
val title = aTag!!.attr("title")
|
||||
val href = fixUrl(aTag.attr("href"))
|
||||
searchResults[href] = TvSeriesSearchResponse(
|
||||
title,
|
||||
|
@ -126,7 +126,7 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
val container = soup.selectFirst(".container-fluid h1")?.parent()
|
||||
val title = if (isSeries) {
|
||||
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) {
|
||||
container?.selectFirst("p")?.text()
|
||||
} else {
|
||||
|
@ -138,11 +138,11 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
|
||||
val episodes = if (isSeries) {
|
||||
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 &&
|
||||
ep.selectFirst(".episodeMeta > strong").html().contains("S")
|
||||
ep.selectFirst(".episodeMeta > strong")!!.html().contains("S")
|
||||
) {
|
||||
val split = ep.selectFirst(".episodeMeta > strong")?.text()?.split("E")
|
||||
Pair(
|
||||
|
@ -152,14 +152,14 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
} else Pair<Int?, Int?>(null, null)
|
||||
|
||||
year = Regex("""•?\s+(\d{4})\s+•""").find(
|
||||
ep.selectFirst(".episodeMeta").text()
|
||||
ep.selectFirst(".episodeMeta")!!.text()
|
||||
)?.destructured?.component1()?.toIntOrNull()
|
||||
|
||||
categories.addAll(
|
||||
ep.select(".episodeMeta > a[href*=\"/category/\"]").map { it.text().trim() })
|
||||
|
||||
newEpisode(epLink) {
|
||||
this.name = ep.selectFirst("a[title]").attr("title")
|
||||
this.name = ep.selectFirst("a[title]")!!.attr("title")
|
||||
this.season = season
|
||||
this.episode = epNum
|
||||
this.posterUrl = thumb
|
||||
|
@ -173,13 +173,13 @@ class IHaveNoTvProvider : MainAPI() {
|
|||
this.name,
|
||||
TvType.Movie,
|
||||
url,
|
||||
soup.selectFirst("[rel=\"image_src\"]").attr("href"),
|
||||
soup.selectFirst("[rel=\"image_src\"]")!!.attr("href"),
|
||||
Regex("""•?\s+(\d{4})\s+•""").find(
|
||||
soup.selectFirst(".videoDetails").text()
|
||||
soup.selectFirst(".videoDetails")!!.text()
|
||||
)?.destructured?.component1()?.toIntOrNull(),
|
||||
description,
|
||||
null,
|
||||
soup.selectFirst(".videoDetails").select("a[href*=\"/category/\"]")
|
||||
soup.selectFirst(".videoDetails")!!.select("a[href*=\"/category/\"]")
|
||||
.map { it.text().trim() }
|
||||
))
|
||||
}
|
||||
|
|
|
@ -33,17 +33,14 @@ class KdramaHoodProvider : MainAPI() {
|
|||
// Hardcoded homepage cause of site implementation
|
||||
// Recently added
|
||||
val recentlyInner = doc.selectFirst("div.peliculas")
|
||||
val recentlyAddedTitle = recentlyInner.selectFirst("h1")?.text() ?: "Recently Added"
|
||||
val recentlyAdded = recentlyInner.select("div.item_2.items > div.fit.item")?.mapNotNull {
|
||||
if (it == null) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
val recentlyAddedTitle = recentlyInner!!.selectFirst("h1")?.text() ?: "Recently Added"
|
||||
val recentlyAdded = recentlyInner.select("div.item_2.items > div.fit.item").mapNotNull {
|
||||
val innerA = it.select("div.image > a") ?: 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 title = innerData.selectFirst("h1")?.text() ?: return@mapNotNull null
|
||||
val title = innerData!!.selectFirst("h1")?.text() ?: return@mapNotNull null
|
||||
val year = try {
|
||||
val yearText = innerData.selectFirst("span.titulo_o")
|
||||
?.text()?.takeLast(11)?.trim()?.take(4) ?: ""
|
||||
|
@ -61,7 +58,7 @@ class KdramaHoodProvider : MainAPI() {
|
|||
posterUrl = image,
|
||||
year = year
|
||||
)
|
||||
}?.distinctBy { it.url } ?: listOf()
|
||||
}.distinctBy { it.url } ?: listOf()
|
||||
home.add(HomePageList(recentlyAddedTitle, recentlyAdded))
|
||||
return HomePageResponse(home.filter { it.list.isNotEmpty() })
|
||||
}
|
||||
|
@ -102,15 +99,15 @@ class KdramaHoodProvider : MainAPI() {
|
|||
val title = inner?.selectFirst("h1")?.text() ?: ""
|
||||
val poster = fixUrlNull(doc.selectFirst("meta[property=og:image]")?.attr("content")) ?: ""
|
||||
//Log.i(this.name, "Result => (poster) ${poster}")
|
||||
val info = inner.selectFirst("div#info")
|
||||
val descript = inner?.selectFirst("div.contenidotv > div > p")?.text()
|
||||
val info = inner!!.selectFirst("div#info")
|
||||
val descript = inner.selectFirst("div.contenidotv > div > p")?.text()
|
||||
val year = try {
|
||||
val startLink = "https://kdramahood.com/drama-release-year/"
|
||||
var res: Int? = null
|
||||
info.select("div.metadatac")?.forEach {
|
||||
info?.select("div.metadatac")?.forEach {
|
||||
if (res != 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)) {
|
||||
res = yearLink.substring(startLink.length).replace("/", "").toIntOrNull()
|
||||
}
|
||||
|
@ -118,13 +115,13 @@ class KdramaHoodProvider : MainAPI() {
|
|||
res
|
||||
} 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 aUrl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null
|
||||
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 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()
|
||||
MovieSearchResponse(
|
||||
url = aUrl,
|
||||
|
@ -137,7 +134,7 @@ class KdramaHoodProvider : MainAPI() {
|
|||
}
|
||||
|
||||
// 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}")
|
||||
val listOfLinks = mutableListOf<String>()
|
||||
val count = ep.select("div.numerando")?.text()?.toIntOrNull() ?: 0
|
||||
|
@ -181,10 +178,10 @@ class KdramaHoodProvider : MainAPI() {
|
|||
posterUrl = poster,
|
||||
date = null
|
||||
)
|
||||
} ?: listOf()
|
||||
}
|
||||
|
||||
//If there's only 1 episode, consider it a movie.
|
||||
if (episodeList.size == 1) {
|
||||
if (episodeList?.size == 1) {
|
||||
return MovieLoadResponse(
|
||||
name = title,
|
||||
url = url,
|
||||
|
@ -202,7 +199,7 @@ class KdramaHoodProvider : MainAPI() {
|
|||
url = url,
|
||||
apiName = this.name,
|
||||
type = TvType.AsianDrama,
|
||||
episodes = episodeList.reversed(),
|
||||
episodes = episodeList?.reversed() ?: emptyList(),
|
||||
posterUrl = poster,
|
||||
year = year,
|
||||
plot = descript,
|
||||
|
|
|
@ -118,10 +118,10 @@ class LookMovieProvider : MainAPI() {
|
|||
val items = document.select("div.flex-wrap-movielist > div.movie-item-style-1")
|
||||
return items.map { item ->
|
||||
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 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()
|
||||
if (isMovie) {
|
||||
MovieSearchResponse(
|
||||
|
@ -199,17 +199,17 @@ class LookMovieProvider : MainAPI() {
|
|||
val isMovie = url.contains("/movies/")
|
||||
|
||||
val watchHeader = document.selectFirst("div.watch-heading")
|
||||
val nameHeader = watchHeader.selectFirst("> h1.bd-hd")
|
||||
val year = nameHeader.selectFirst("> span")?.text()?.toIntOrNull()
|
||||
val nameHeader = watchHeader!!.selectFirst("> h1.bd-hd")
|
||||
val year = nameHeader!!.selectFirst("> span")?.text()?.toIntOrNull()
|
||||
val title = nameHeader.ownText()
|
||||
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 img = imgElement?.attr("style")
|
||||
var poster = if (img.isNullOrEmpty()) null else "url\\((.*?)\\)".toRegex()
|
||||
.find(img)?.groupValues?.get(1)
|
||||
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()
|
||||
.find(response)?.groupValues?.get(1)
|
||||
?.replace(" ", "")
|
||||
|
|
|
@ -88,11 +88,11 @@ class MeloMovieProvider : MainAPI() {
|
|||
|
||||
private fun serializeData(element: Element): List<MeloMovieProvider.MeloMovieLink> {
|
||||
val eps = element.select("> tbody > tr")
|
||||
val parsed = eps.map {
|
||||
val parsed = eps.mapNotNull {
|
||||
try {
|
||||
val tds = it.select("> td")
|
||||
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)
|
||||
} catch (e: Exception) {
|
||||
MeloMovieLink("", "")
|
||||
|
@ -133,13 +133,13 @@ class MeloMovieProvider : MainAPI() {
|
|||
|
||||
val imdbUrl = findUsingRegex("var imdb = \"(.*?)\"")
|
||||
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 titleInfo = document.selectFirst("div.movie_detail_title > div > div > h1")
|
||||
val title = titleInfo.ownText()
|
||||
val title = titleInfo!!.ownText()
|
||||
val year =
|
||||
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
|
||||
val serialize = document.selectFirst("table.accordion__list")
|
||||
|
@ -161,12 +161,12 @@ class MeloMovieProvider : MainAPI() {
|
|||
?: throw ErrorLoadingException("No episodes found")
|
||||
for (s in seasons) {
|
||||
val season =
|
||||
s.selectFirst("> div.card-header > button > span").text()
|
||||
s.selectFirst("> div.card-header > button > span")!!.text()
|
||||
.replace("Season: ", "").toIntOrNull()
|
||||
val localEpisodes = s.select("> div.collapse > div > div > div.accordion__card")
|
||||
for (e in localEpisodes) {
|
||||
val episode =
|
||||
e.selectFirst("> div.card-header > button > span").text()
|
||||
e.selectFirst("> div.card-header > button > span")!!.text()
|
||||
.replace("Episode: ", "").toIntOrNull()
|
||||
val links =
|
||||
e.selectFirst("> div.collapse > div > table.accordion__list") ?: continue
|
||||
|
|
|
@ -153,7 +153,7 @@ class MyCimaProvider : MainAPI() {
|
|||
if (moreButton.isNotEmpty()) {
|
||||
val n = doc.select("div.Seasons--Episodes div.Episodes--Seasons--Episodes a").size
|
||||
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(
|
||||
n,
|
||||
n + 40,
|
||||
|
@ -229,7 +229,7 @@ class MyCimaProvider : MainAPI() {
|
|||
val n =
|
||||
seasonsite.select("div.Seasons--Episodes div.Episodes--Seasons--Episodes a").size
|
||||
val totals =
|
||||
seasonsite.select("div.Episodes--Seasons--Episodes a").first().text()
|
||||
seasonsite.select("div.Episodes--Seasons--Episodes a").first()!!.text()
|
||||
.getIntFromText()
|
||||
val mEPS = arrayListOf(
|
||||
n,
|
||||
|
|
|
@ -37,13 +37,13 @@ class NginxProvider : MainAPI() {
|
|||
|
||||
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) {
|
||||
val poster = metadataDocument.selectFirst("thumb").text()
|
||||
val trailer = metadataDocument.select("trailer")?.mapNotNull {
|
||||
val poster = metadataDocument.selectFirst("thumb")!!.text()
|
||||
val trailer = metadataDocument.select("trailer").mapNotNull {
|
||||
it?.text()?.replace(
|
||||
"plugin://plugin.video.youtube/play/?video_id=",
|
||||
"https://www.youtube.com/watch?v="
|
||||
|
@ -125,7 +125,7 @@ class NginxProvider : MainAPI() {
|
|||
val epNum = nfoDocument.selectFirst("episode")?.text()?.toIntOrNull()
|
||||
val poster =
|
||||
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 date = nfoDocument.selectFirst("aired")?.text()
|
||||
val plot = nfoDocument.selectFirst("plot")?.text()
|
||||
|
|
|
@ -29,14 +29,14 @@ class PeliSmartProvider: MainAPI() {
|
|||
try {
|
||||
val soup = app.get(url).document
|
||||
val home = soup.select(".description-off").map {
|
||||
val title = it.selectFirst("h3.entry-title a").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("h3.entry-title a")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
if (link.contains("pelicula")) TvType.Movie else TvType.TvSeries,
|
||||
it.selectFirst("div img").attr("src"),
|
||||
it.selectFirst("div img")!!.attr("src"),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
|
@ -57,9 +57,9 @@ class PeliSmartProvider: MainAPI() {
|
|||
val document = app.get(url).document
|
||||
|
||||
return document.select(".description-off").map {
|
||||
val title = it.selectFirst("h3.entry-title a").text()
|
||||
val href = it.selectFirst("a").attr("href")
|
||||
val image = it.selectFirst("div img").attr("src")
|
||||
val title = it.selectFirst("h3.entry-title a")!!.text()
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val image = it.selectFirst("div img")!!.attr("src")
|
||||
val isMovie = href.contains("pelicula")
|
||||
|
||||
if (isMovie) {
|
||||
|
@ -88,13 +88,13 @@ class PeliSmartProvider: MainAPI() {
|
|||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
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 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 href = li.selectFirst("a").attr("href")
|
||||
val href = li.selectFirst("a")!!.attr("href")
|
||||
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 test = regextest.find(href)?.destructured?.component1()?.replace(Regex("(temporada-|-)"),"")
|
||||
val seasonid = test.let { str ->
|
||||
|
|
|
@ -28,14 +28,14 @@ class PelisflixProvider : MainAPI() {
|
|||
try {
|
||||
val soup = app.get(i.first).document
|
||||
val home = soup.select("article.TPost.B").map {
|
||||
val title = it.selectFirst("h2.title").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("h2.title")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
it.selectFirst("figure img").attr("data-src"),
|
||||
it.selectFirst("figure img")!!.attr("data-src"),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
|
@ -54,9 +54,9 @@ class PelisflixProvider : MainAPI() {
|
|||
val url = "$mainUrl/?s=$query"
|
||||
val doc = app.get(url).document
|
||||
return doc.select("article.TPost.B").map {
|
||||
val href = it.selectFirst("a").attr("href")
|
||||
val poster = it.selectFirst("figure img").attr("data-src")
|
||||
val name = it.selectFirst("h2.title").text()
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val poster = it.selectFirst("figure img")!!.attr("data-src")
|
||||
val name = it.selectFirst("h2.title")!!.text()
|
||||
val isMovie = href.contains("/pelicula/")
|
||||
if (isMovie) {
|
||||
MovieSearchResponse(
|
||||
|
@ -86,24 +86,24 @@ class PelisflixProvider : MainAPI() {
|
|||
|
||||
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 descRegex2 = Regex("(Actualmente.*.)")
|
||||
val descRegex3 = Regex("(.*Director:.*)")
|
||||
val descRegex4 = Regex("(.*Actores:.*)")
|
||||
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(descRegex4, "").replace(descRegex5, "")
|
||||
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 =
|
||||
document.selectFirst("div.rating-content button.like-mov span.vot_cl")?.text()
|
||||
?.toFloatOrNull()
|
||||
?.times(0)?.toInt()
|
||||
val year = document.selectFirst("span.Date")?.text()
|
||||
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
|
||||
val postercss = document.selectFirst("head").toString()
|
||||
val posterRegex =
|
||||
|
@ -137,7 +137,7 @@ class PelisflixProvider : MainAPI() {
|
|||
val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull()
|
||||
val epthumb = episode.selectFirst("img")?.attr("src")
|
||||
val aName = episode.selectFirst("> td.MvTbTtl > a")
|
||||
val name = aName.text()
|
||||
val name = aName!!.text()
|
||||
val href = aName.attr("href")
|
||||
val date = episode.selectFirst("> td.MvTbTtl > span")?.text()
|
||||
episodeList.add(
|
||||
|
@ -220,7 +220,7 @@ class PelisflixProvider : MainAPI() {
|
|||
params = mapOf(Pair("h", postkey)),
|
||||
data = mapOf(Pair("h", postkey)),
|
||||
allowRedirects = false
|
||||
).response.headers.values("location").apmap { link ->
|
||||
).okhttpResponse.headers.values("location").apmap { link ->
|
||||
val url1 = link.replace("#bu", "")
|
||||
loadExtractor(url1, data, callback)
|
||||
}
|
||||
|
|
|
@ -67,9 +67,9 @@ class PelisplusHDProvider:MainAPI() {
|
|||
val document = app.get(url).document
|
||||
|
||||
return document.select("a.Posters-link").map {
|
||||
val title = it.selectFirst(".listing-content p").text()
|
||||
val href = it.selectFirst("a").attr("href")
|
||||
val image = it.selectFirst(".Posters-img").attr("src")
|
||||
val title = it.selectFirst(".listing-content p")!!.text()
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val image = it.selectFirst(".Posters-img")!!.attr("src")
|
||||
val isMovie = href.contains("/pelicula/")
|
||||
|
||||
if (isMovie) {
|
||||
|
@ -98,12 +98,12 @@ class PelisplusHDProvider:MainAPI() {
|
|||
override suspend fun load(url: String): LoadResponse? {
|
||||
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 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 href = li.selectFirst("a").attr("href")
|
||||
val name = li.selectFirst(".btn-primary.btn-block").text()
|
||||
val href = li.selectFirst("a")!!.attr("href")
|
||||
val name = li.selectFirst(".btn-primary.btn-block")!!.text()
|
||||
val seasonid = href.replace("/capitulo/","-")
|
||||
.replace(Regex("$mainUrl/.*/.*/temporada/"),"").let { str ->
|
||||
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 tags = soup.select(".p-h-15.text-center a span.font-size-18.text-info.text-semibold")
|
||||
.map { it?.text()?.trim().toString().replace(", ","") }
|
||||
|
|
|
@ -44,11 +44,11 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
|
||||
return ArrayList(soup.select(".listing.items > .video-block").map { li ->
|
||||
// Selects the href in <a href="...">
|
||||
val href = fixUrl(li.selectFirst("a").attr("href"))
|
||||
val poster = fixUrl(li.selectFirst("img").attr("src"))
|
||||
val href = fixUrl(li.selectFirst("a")!!.attr("href"))
|
||||
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
|
||||
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.
|
||||
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 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 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
|
||||
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 aaa = regexseason.find(href)?.destructured?.component1()?.replace(Regex("(-[Tt]emporada-|[Cc]apitulo-)"),"")
|
||||
val seasonid = aaa.let { str ->
|
||||
|
@ -88,14 +88,14 @@ open class PelisplusProviderTemplate : MainAPI() {
|
|||
val isValid = seasonid?.size == 2
|
||||
val episode = if (isValid) seasonid?.getOrNull(1) else null
|
||||
val season = if (isValid) seasonid?.getOrNull(0) else null
|
||||
val epThumb = fixUrl(li.selectFirst("img").attr("src"))
|
||||
val epDate = li.selectFirst(".meta > .date").text()
|
||||
val epThumb = fixUrl(li.selectFirst("img")!!.attr("src"))
|
||||
val epDate = li.selectFirst(".meta > .date")!!.text()
|
||||
|
||||
if(year == null) {
|
||||
year = epDate?.split("-")?.get(0)?.toIntOrNull()
|
||||
}
|
||||
|
||||
newEpisode(li.selectFirst("a").attr("href")) {
|
||||
newEpisode(li.selectFirst("a")!!.attr("href")) {
|
||||
this.season = season
|
||||
this.episode = episode
|
||||
this.posterUrl = epThumb
|
||||
|
|
|
@ -29,14 +29,14 @@ class SeriesflixProvider : MainAPI() {
|
|||
try {
|
||||
val soup = app.get(i.first).document
|
||||
val home = soup.select("article.TPost.B").map {
|
||||
val title = it.selectFirst("h2.title").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("h2.title")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
it.selectFirst("figure img").attr("src"),
|
||||
it.selectFirst("figure img")!!.attr("src"),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
|
@ -55,9 +55,9 @@ class SeriesflixProvider : MainAPI() {
|
|||
val url = "$mainUrl/?s=$query"
|
||||
val doc = app.get(url).document
|
||||
return doc.select("article.TPost.B").map {
|
||||
val href = it.selectFirst("a").attr("href")
|
||||
val poster = it.selectFirst("figure img").attr("src")
|
||||
val name = it.selectFirst("h2.title").text()
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val poster = it.selectFirst("figure img")!!.attr("src")
|
||||
val name = it.selectFirst("h2.title")!!.text()
|
||||
val isMovie = href.contains("/movies/")
|
||||
if (isMovie) {
|
||||
MovieSearchResponse(
|
||||
|
@ -88,15 +88,15 @@ class SeriesflixProvider : MainAPI() {
|
|||
|
||||
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 descipt = document.selectFirst("div.Description > p").text().replace(descRegex, "")
|
||||
val descipt = document.selectFirst("div.Description > p")!!.text().replace(descRegex, "")
|
||||
val rating =
|
||||
document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toRatingInt()
|
||||
val year = document.selectFirst("span.Date")?.text()
|
||||
// ?: does not work
|
||||
val duration = try {
|
||||
document.selectFirst("span.Time").text()
|
||||
document.selectFirst("span.Time")!!.text()
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
@ -133,8 +133,8 @@ class SeriesflixProvider : MainAPI() {
|
|||
val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull()
|
||||
val epthumb = episode.selectFirst("img")?.attr("src")
|
||||
val aName = episode.selectFirst("> td.MvTbTtl > a")
|
||||
val name = aName.text()
|
||||
val href = aName.attr("href")
|
||||
val name = aName!!.text()
|
||||
val href = aName!!.attr("href")
|
||||
val date = episode.selectFirst("> td.MvTbTtl > span")?.text()
|
||||
episodeList.add(
|
||||
newEpisode(href) {
|
||||
|
@ -215,7 +215,7 @@ class SeriesflixProvider : MainAPI() {
|
|||
params = mapOf(Pair("h", postkey)),
|
||||
data = mapOf(Pair("h", postkey)),
|
||||
allowRedirects = false
|
||||
).response.headers.values("location").apmap { link ->
|
||||
).okhttpResponse.headers.values("location").apmap { link ->
|
||||
val url1 = link.replace("#bu", "")
|
||||
loadExtractor(url1, data, callback)
|
||||
}
|
||||
|
|
|
@ -10,13 +10,13 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration
|
|||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.animeproviders.ZoroProvider
|
||||
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.tryParseJson
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.M3u8Helper
|
||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
import com.lagradost.nicehttp.NiceResponse
|
||||
import kotlinx.coroutines.delay
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
|
@ -82,7 +82,7 @@ open class SflixProvider : MainAPI() {
|
|||
|
||||
val metaInfo = it.select("div.fd-infor > span.fdi-item")
|
||||
// val rating = metaInfo[0].text()
|
||||
val quality = getQualityFromString(metaInfo?.getOrNull(1)?.text())
|
||||
val quality = getQualityFromString(metaInfo.getOrNull(1)?.text())
|
||||
|
||||
if (isMovie) {
|
||||
MovieSearchResponse(
|
||||
|
@ -113,9 +113,9 @@ open class SflixProvider : MainAPI() {
|
|||
val document = app.get(url).document
|
||||
|
||||
val details = document.select("div.detail_page-watch")
|
||||
val img = details?.select("img.film-poster-img")
|
||||
val posterUrl = img?.attr("src")
|
||||
val title = img?.attr("title") ?: throw ErrorLoadingException("No Title")
|
||||
val img = details.select("img.film-poster-img")
|
||||
val posterUrl = img.attr("src")
|
||||
val title = img.attr("title") ?: throw ErrorLoadingException("No Title")
|
||||
|
||||
/*
|
||||
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()
|
||||
?.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
|
||||
when {
|
||||
type.contains("Released") -> {
|
||||
|
@ -141,17 +141,17 @@ open class SflixProvider : MainAPI() {
|
|||
)?.groupValues?.firstOrNull()?.toIntOrNull()
|
||||
}
|
||||
type.contains("Genre") -> {
|
||||
tags = element.select("a")?.mapNotNull { it.text() }
|
||||
tags = element.select("a").mapNotNull { it.text() }
|
||||
}
|
||||
type.contains("Cast") -> {
|
||||
cast = element.select("a")?.mapNotNull { it.text() }
|
||||
cast = element.select("a").mapNotNull { it.text() }
|
||||
}
|
||||
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/")
|
||||
|
||||
|
@ -164,12 +164,12 @@ open class SflixProvider : MainAPI() {
|
|||
else dataId
|
||||
|
||||
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 =
|
||||
element.select("div.film-detail > .film-name > a") ?: return@mapNotNull null
|
||||
val recUrl = fixUrlNull(titleHeader.attr("href")) ?: 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(
|
||||
recTitle,
|
||||
recUrl,
|
||||
|
@ -191,7 +191,7 @@ open class SflixProvider : MainAPI() {
|
|||
if (sourceId.isNullOrEmpty())
|
||||
sourceId = element.attr("data-linkid")
|
||||
|
||||
if (element.select("span")?.text()?.trim()?.isValidServer() == true) {
|
||||
if (element.select("span").text().trim().isValidServer()) {
|
||||
if (sourceId.isNullOrEmpty()) {
|
||||
fixUrlNull(element.attr("href"))
|
||||
} else {
|
||||
|
@ -222,7 +222,7 @@ open class SflixProvider : MainAPI() {
|
|||
var seasonItems = seasonsDocument.select("div.dropdown-menu.dropdown-menu-model > a")
|
||||
if (seasonItems.isNullOrEmpty())
|
||||
seasonItems = seasonsDocument.select("div.dropdown-menu > a.dropdown-item")
|
||||
seasonItems?.forEachIndexed { season, element ->
|
||||
seasonItems.forEachIndexed { season, element ->
|
||||
val seasonId = element.attr("data-id")
|
||||
if (seasonId.isNullOrBlank()) return@forEachIndexed
|
||||
|
||||
|
@ -243,7 +243,7 @@ open class SflixProvider : MainAPI() {
|
|||
episode++
|
||||
|
||||
val episodeNum =
|
||||
(it.select("div.episode-number")?.text()
|
||||
(it.select("div.episode-number").text()
|
||||
?: episodeTitle).let { str ->
|
||||
Regex("""\d+""").find(str)?.groupValues?.firstOrNull()
|
||||
?.toIntOrNull()
|
||||
|
@ -314,7 +314,7 @@ open class SflixProvider : MainAPI() {
|
|||
// Supported streams, they're identical
|
||||
app.get(episodesUrl).document.select("a").mapNotNull { element ->
|
||||
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/")
|
||||
} else {
|
||||
null
|
||||
|
@ -334,7 +334,7 @@ open class SflixProvider : MainAPI() {
|
|||
|
||||
val serverId = url.substringAfterLast(".")
|
||||
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
|
||||
|
||||
// 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 {
|
||||
val inner = this.selectFirst("div.film-poster")
|
||||
val img = inner.select("img")
|
||||
val img = inner!!.select("img")
|
||||
val title = img.attr("title")
|
||||
val posterUrl = img.attr("data-src") ?: img.attr("src")
|
||||
val href = fixUrl(inner.select("a").attr("href"))
|
||||
|
@ -454,11 +454,11 @@ open class SflixProvider : MainAPI() {
|
|||
* @return the data and if it is new.
|
||||
* */
|
||||
private suspend fun getUpdatedData(
|
||||
response: AppResponse,
|
||||
response: NiceResponse,
|
||||
data: PollingData,
|
||||
baseUrl: String
|
||||
): Pair<PollingData, Boolean> {
|
||||
if (!response.response.isSuccessful) {
|
||||
if (!response.okhttpResponse.isSuccessful) {
|
||||
return negotiateNewSid(baseUrl)?.let {
|
||||
it to true
|
||||
} ?: data to false
|
||||
|
@ -688,7 +688,7 @@ open class SflixProvider : MainAPI() {
|
|||
// "Cache-Control" to "no-cache",
|
||||
"TE" to "trailers"
|
||||
)
|
||||
).mapped<SourceObject>()
|
||||
).parsed<SourceObject>()
|
||||
|
||||
mapped.tracks?.forEach { track ->
|
||||
track?.toSubtitleFile()?.let { subtitleFile ->
|
||||
|
|
|
@ -28,14 +28,14 @@ class SoaptwoDayProvider:MainAPI() {
|
|||
try {
|
||||
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 title = it.selectFirst("h5 a").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("h5 a")!!.text()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
TvType.TvSeries,
|
||||
fixUrl(it.selectFirst("img").attr("src")),
|
||||
fixUrl(it.selectFirst("img")!!.attr("src")),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
|
@ -52,9 +52,9 @@ class SoaptwoDayProvider:MainAPI() {
|
|||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
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 {
|
||||
val title = it.selectFirst("h5 a").text()
|
||||
val image = fixUrl(it.selectFirst("img").attr("src"))
|
||||
val href = fixUrl(it.selectFirst("a").attr("href"))
|
||||
val title = it.selectFirst("h5 a")!!.text()
|
||||
val image = fixUrl(it.selectFirst("img")!!.attr("src"))
|
||||
val href = fixUrl(it.selectFirst("a")!!.attr("href"))
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
href,
|
||||
|
@ -80,34 +80,33 @@ class SoaptwoDayProvider:MainAPI() {
|
|||
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
|
||||
val casts = otherInfoBody?.substringAfter("Stars : ")
|
||||
?.substringBefore("Genre : ")?.let {
|
||||
Jsoup.parse(it)?.select("a")
|
||||
}?.mapNotNull {
|
||||
val castName = it?.text() ?: return@mapNotNull null
|
||||
ActorData(
|
||||
Actor(
|
||||
name = castName
|
||||
val casts = otherInfoBody.substringAfter("Stars : ")
|
||||
.substringBefore("Genre : ").let {
|
||||
Jsoup.parse(it).select("a")
|
||||
}.mapNotNull {
|
||||
val castName = it?.text() ?: return@mapNotNull null
|
||||
ActorData(
|
||||
Actor(
|
||||
name = castName
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
//Fetch year
|
||||
val year = otherInfoBody?.substringAfter("<h4>Release : </h4>")
|
||||
?.substringBefore("<div")?.let {
|
||||
val year = otherInfoBody.substringAfter("<h4>Release : </h4>")
|
||||
.substringBefore("<div").let {
|
||||
//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()
|
||||
//Fetch genres
|
||||
val genre = otherInfoBody?.substringAfter("<h4>Genre : </h4>")
|
||||
?.substringBefore("<h4>Release : </h4>")?.let {
|
||||
val genre = otherInfoBody.substringAfter("<h4>Genre : </h4>")
|
||||
.substringBefore("<h4>Release : </h4>").let {
|
||||
//Log.i(this.name, "Result => genre string: $it")
|
||||
Jsoup.parse(it)?.select("a")
|
||||
}?.mapNotNull { it?.text()?.trim() ?: return@mapNotNull null }
|
||||
Jsoup.parse(it).select("a")
|
||||
}.mapNotNull { it?.text()?.trim() ?: return@mapNotNull null }
|
||||
|
||||
val tvType = if (episodes.isEmpty()) TvType.Movie else TvType.TvSeries
|
||||
return when (tvType) {
|
||||
return when (val tvType = if (episodes.isEmpty()) TvType.Movie else TvType.TvSeries) {
|
||||
TvType.TvSeries -> {
|
||||
TvSeriesLoadResponse(
|
||||
title,
|
||||
|
@ -177,9 +176,9 @@ class SoaptwoDayProvider:MainAPI() {
|
|||
val doc = app.get(data).document
|
||||
val idplayer = doc.selectFirst("#divU")?.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 {
|
||||
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) {
|
||||
""
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ class StreamingcommunityProvider : MainAPI() {
|
|||
val document = app.get(url).document
|
||||
|
||||
val films =
|
||||
document.selectFirst("the-search-page").attr("records-json").replace(""", """"""")
|
||||
document.selectFirst("the-search-page")!!.attr("records-json").replace(""", """"""")
|
||||
|
||||
val searchresults = parseJson<List<VideoElement>>(films)
|
||||
return searchresults.map { result ->
|
||||
|
@ -289,7 +289,7 @@ class StreamingcommunityProvider : MainAPI() {
|
|||
|
||||
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 correlatidata = parseJson<List<VideoElement>>(correlatijs)
|
||||
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 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)
|
||||
|
||||
jsonEpisodes.map { seasons ->
|
||||
|
@ -365,7 +365,7 @@ class StreamingcommunityProvider : MainAPI() {
|
|||
return newTvSeriesLoadResponse(name, url, type, episodeList) {
|
||||
this.posterUrl = poster
|
||||
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.rating = (datajs.votes[0].average.toFloatOrNull()?.times(1000))?.toInt()
|
||||
this.tags = datajs.genres.map { it.name }
|
||||
|
@ -377,14 +377,14 @@ class StreamingcommunityProvider : MainAPI() {
|
|||
} else {
|
||||
|
||||
return newMovieLoadResponse(
|
||||
document.selectFirst("div > div > h1").text(),
|
||||
document.selectFirst("div > div > h1")!!.text(),
|
||||
document.select("a.play-hitzone").attr("href"),
|
||||
type,
|
||||
document.select("a.play-hitzone").attr("href")
|
||||
) {
|
||||
posterUrl = fixUrlNull(poster)
|
||||
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.tags = datajs.genres.map { it.name }
|
||||
this.duration = datajs.runtime?.toInt()
|
||||
|
|
|
@ -27,14 +27,14 @@ class TantifilmProvider : MainAPI() {
|
|||
try {
|
||||
val soup = app.get(url).document
|
||||
val home = soup.select("div.media3").map {
|
||||
val title = it.selectFirst("p").text().substringBefore("(")
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
val title = it.selectFirst("p")!!.text().substringBefore("(")
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
it.selectFirst("img").attr("src"),
|
||||
it.selectFirst("img")!!.attr("src"),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
|
@ -54,9 +54,9 @@ class TantifilmProvider : MainAPI() {
|
|||
val url = "$mainUrl/search/$queryformatted"
|
||||
val doc = app.get(url).document
|
||||
return doc.select("div.film.film-2").map {
|
||||
val href = it.selectFirst("a").attr("href")
|
||||
val poster = it.selectFirst("img").attr("src")
|
||||
val name = it.selectFirst("a").text().substringBefore("(")
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val poster = it.selectFirst("img")!!.attr("src")
|
||||
val name = it.selectFirst("a")!!.text().substringBefore("(")
|
||||
MovieSearchResponse(
|
||||
name,
|
||||
href,
|
||||
|
@ -72,30 +72,30 @@ class TantifilmProvider : MainAPI() {
|
|||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
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()
|
||||
) 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 rating =
|
||||
document.selectFirst("div.star-rating.star-rating-f > span > span")
|
||||
.attr("data-rateit-value")?.toFloatOrNull()
|
||||
document.selectFirst("div.star-rating.star-rating-f > span > span")!!
|
||||
.attr("data-rateit-value").toFloatOrNull()
|
||||
?.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() }
|
||||
if (year.length > 4) {
|
||||
year = year.dropLast(4)
|
||||
year = if (year.length > 4) {
|
||||
year.dropLast(4)
|
||||
} else {
|
||||
year = year
|
||||
year
|
||||
}
|
||||
// ?: 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 href = it.selectFirst("a").attr("href")
|
||||
val poster = it.selectFirst("img").attr("src")
|
||||
val name = it.selectFirst("a").attr("title").substringBeforeLast("(")
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
val poster = it.selectFirst("img")!!.attr("src")
|
||||
val name = it.selectFirst("a")!!.attr("title").substringBeforeLast("(")
|
||||
MovieSearchResponse(
|
||||
name,
|
||||
href,
|
||||
|
@ -111,10 +111,10 @@ class TantifilmProvider : MainAPI() {
|
|||
|
||||
if (type == TvType.TvSeries) {
|
||||
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
|
||||
videocontainer.select("nav.nav1 > select > option").forEach { element ->
|
||||
val season = element.text()?.toIntOrNull()
|
||||
val season = element.text().toIntOrNull()
|
||||
val href = element.attr("value")
|
||||
if (season != null && season > 0 && !href.isNullOrBlank()) {
|
||||
list.add(Pair(season, fixUrl(href)))
|
||||
|
@ -130,7 +130,7 @@ class TantifilmProvider : MainAPI() {
|
|||
if (episodes.isNotEmpty()) {
|
||||
episodes.forEach { episode ->
|
||||
val href = episode.attr("value")
|
||||
val epNum = episode.text()?.toIntOrNull()
|
||||
val epNum = episode.text().toIntOrNull()
|
||||
episodeList.add(
|
||||
Episode(
|
||||
href,
|
||||
|
@ -149,7 +149,7 @@ class TantifilmProvider : MainAPI() {
|
|||
type,
|
||||
episodeList,
|
||||
fixUrlNull(poster),
|
||||
year?.toIntOrNull(),
|
||||
year.toIntOrNull(),
|
||||
descipt[0],
|
||||
null,
|
||||
rating,
|
||||
|
@ -159,23 +159,21 @@ class TantifilmProvider : MainAPI() {
|
|||
recomm
|
||||
)
|
||||
} else {
|
||||
val url2 = document.selectFirst("iframe").attr("src")
|
||||
val url2 = document.selectFirst("iframe")!!.attr("src")
|
||||
val actorpagelink =
|
||||
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 Linkactor: String = if (actorpagelink.isNotEmpty()) {
|
||||
actorpagelink
|
||||
} else {
|
||||
val Linkactor: String = actorpagelink.ifEmpty {
|
||||
actorpagelink2
|
||||
}
|
||||
|
||||
val actors: List<ActorData>? = if (Linkactor.isNotEmpty()) {
|
||||
val actorpage = app.get(Linkactor + "cast/").document
|
||||
actorpage.select("article.membro-cast")?.filter {
|
||||
actorpage.select("article.membro-cast").filter {
|
||||
it.selectFirst("img")
|
||||
?.attr("src") != "https://www.filmtv.it/imgbank/DUMMY/no_portrait.jpg"
|
||||
}?.mapNotNull { it ->
|
||||
val name = it.selectFirst("div.info > h3").text()
|
||||
}.mapNotNull {
|
||||
val name = it.selectFirst("div.info > h3")!!.text()
|
||||
val image = it.selectFirst("img")?.attr("src")
|
||||
val roleString: String = if (it.selectFirst("h2")?.text() == "Regia") {
|
||||
"Regia"
|
||||
|
@ -196,7 +194,7 @@ class TantifilmProvider : MainAPI() {
|
|||
null
|
||||
}
|
||||
val tags: List<String>? = if (descipt.size == 2) {
|
||||
descipt[0].let { mutableListOf(it.substringBefore(" ")) }
|
||||
mutableListOf(descipt[0].substringBefore(" "))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
@ -212,7 +210,7 @@ class TantifilmProvider : MainAPI() {
|
|||
url2
|
||||
) {
|
||||
posterUrl = fixUrlNull(poster)
|
||||
this.year = year?.toIntOrNull()
|
||||
this.year = year.toIntOrNull()
|
||||
this.plot = plot
|
||||
this.rating = rating
|
||||
this.recommendations = recomm
|
||||
|
@ -235,7 +233,7 @@ class TantifilmProvider : MainAPI() {
|
|||
doc.select("option").map { fixUrl(it.attr("value")) }.filter { it.contains("label") }
|
||||
iframe.forEach { id ->
|
||||
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)
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -98,7 +98,7 @@ class TheFlixToProvider : MainAPI() {
|
|||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val items = ArrayList<HomePageList>()
|
||||
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")) {
|
||||
val json = parseJson<HomeJson>(scriptText)
|
||||
val homePageProps = json.props.pageProps
|
||||
|
@ -181,7 +181,7 @@ class TheFlixToProvider : MainAPI() {
|
|||
)
|
||||
urls.apmap { url ->
|
||||
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")) {
|
||||
val json = parseJson<SearchJson>(scriptText)
|
||||
val searchPageProps = json.props.pageProps.mainList
|
||||
|
@ -397,7 +397,7 @@ class TheFlixToProvider : MainAPI() {
|
|||
private suspend fun getLoadMan(url: String): LoadMain {
|
||||
val og = app.get(url, cookies = latestCookies)
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -24,15 +24,15 @@ class VMoveeProvider : MainAPI() {
|
|||
val details = item.selectFirst("> div.details")
|
||||
val imgHolder = item.selectFirst("> div.image > div.thumbnail > a")
|
||||
// val href = imgHolder.attr("href")
|
||||
val poster = imgHolder.selectFirst("> img").attr("data-lazy-src")
|
||||
val isTV = imgHolder.selectFirst("> span").text() == "TV"
|
||||
val poster = imgHolder!!.selectFirst("> img")!!.attr("data-lazy-src")
|
||||
val isTV = imgHolder.selectFirst("> span")!!.text() == "TV"
|
||||
if (isTV) continue // no TV support yet
|
||||
|
||||
val titleHolder = details.selectFirst("> div.title > a")
|
||||
val title = titleHolder.text()
|
||||
val titleHolder = details!!.selectFirst("> div.title > a")
|
||||
val title = titleHolder!!.text()
|
||||
val href = titleHolder.attr("href")
|
||||
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 descript = details.selectFirst("> div.contenido").text()
|
||||
returnValue.add(
|
||||
|
@ -114,10 +114,10 @@ class VMoveeProvider : MainAPI() {
|
|||
|
||||
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 title = data.selectFirst("> h1").text()
|
||||
val descript = document.selectFirst("div#info > div").text()
|
||||
val title = data!!.selectFirst("> h1")!!.text()
|
||||
val descript = document.selectFirst("div#info > div")!!.text()
|
||||
val id = document.select("div.starstruck").attr("data-id")
|
||||
|
||||
return MovieLoadResponse(title, url, this.name, TvType.Movie, id, poster, null, descript, null, null)
|
||||
|
|
|
@ -27,12 +27,12 @@ class VfFilmProvider : MainAPI() {
|
|||
for (item in items) {
|
||||
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")
|
||||
|
||||
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))
|
||||
}
|
||||
|
@ -73,25 +73,25 @@ class VfFilmProvider : MainAPI() {
|
|||
override suspend fun load(url: String): LoadResponse {
|
||||
val response = app.get(url).text
|
||||
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")
|
||||
|
||||
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")
|
||||
|
||||
val descript = document.selectFirst("div.Description > p").text()
|
||||
val descript = document.selectFirst("div.Description > p")!!.text()
|
||||
|
||||
val players = document.select("ul.TPlayerNv > li")
|
||||
var number_player = 0
|
||||
var found = false
|
||||
for (player in players) {
|
||||
if (player.selectFirst("> span").text() == "Vudeo") {
|
||||
if (player.selectFirst("> span")!!.text() == "Vudeo") {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
|
|
|
@ -28,15 +28,15 @@ class VfSerieProvider : MainAPI() {
|
|||
for (item in items) {
|
||||
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")
|
||||
|
||||
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
|
||||
}
|
||||
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(
|
||||
TvSeriesSearchResponse(
|
||||
|
@ -74,12 +74,12 @@ class VfSerieProvider : MainAPI() {
|
|||
val response = app.get(data).text
|
||||
val document = Jsoup.parse(response)
|
||||
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)!!
|
||||
.toInt() // the starting trembed number of the first player website, some start at 0 other at 1
|
||||
var found = false
|
||||
for (player in players) {
|
||||
if (player.selectFirst("> span").text() == "Vudeo") {
|
||||
if (player.selectFirst("> span")!!.text() == "Vudeo") {
|
||||
found = true
|
||||
break
|
||||
} else {
|
||||
|
@ -110,21 +110,21 @@ class VfSerieProvider : MainAPI() {
|
|||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
val title =
|
||||
document?.selectFirst(".Title")?.text()?.replace("Regarder Serie ", "")
|
||||
document.selectFirst(".Title")?.text()?.replace("Regarder Serie ", "")
|
||||
?.replace(" En Streaming", "")
|
||||
?: throw ErrorLoadingException("Service might be unavailable")
|
||||
|
||||
|
||||
val year = document.select("span.Date").text()?.toIntOrNull()
|
||||
val rating = document.select("span.AAIco-star").text()?.toIntOrNull()
|
||||
val year = document.select("span.Date").text().toIntOrNull()
|
||||
val rating = document.select("span.AAIco-star").text().toIntOrNull()
|
||||
|
||||
//val duration = document.select("span.Time").text()?.toIntOrNull()
|
||||
|
||||
val backgroundPoster =
|
||||
document.selectFirst("div.Image > figure > img").attr("src")
|
||||
document.selectFirst("div.Image > figure > img")!!.attr("src")
|
||||
.replace("//image", "https://image")
|
||||
|
||||
val descript = document.selectFirst("div.Description > p").text()
|
||||
val descript = document.selectFirst("div.Description > p")!!.text()
|
||||
|
||||
val list = ArrayList<Int>()
|
||||
|
||||
|
@ -149,7 +149,7 @@ class VfSerieProvider : MainAPI() {
|
|||
?.replace("//image", "https://image")
|
||||
val aName = episode.selectFirst("> td.MvTbTtl > a")
|
||||
val date = episode.selectFirst("> td.MvTbTtl > span")?.text()?.toString()
|
||||
val name = aName.text()
|
||||
val name = aName!!.text()
|
||||
val href = aName.attr("href")
|
||||
episodeList.add(
|
||||
newEpisode(href) {
|
||||
|
|
|
@ -104,11 +104,11 @@ open class VidstreamProviderTemplate : MainAPI() {
|
|||
|
||||
return ArrayList(soup.select(".listing.items > .video-block").map { li ->
|
||||
// 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")
|
||||
|
||||
// .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.
|
||||
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 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()
|
||||
|
||||
val description = soup.selectFirst(".post-entry")?.text()?.trim()
|
||||
|
@ -143,13 +143,13 @@ open class VidstreamProviderTemplate : MainAPI() {
|
|||
val episodes =
|
||||
soup.select(".listing.items.lists > .video-block").withIndex().map { (_, li) ->
|
||||
val epTitle = if (li.selectFirst(".name") != null)
|
||||
if (li.selectFirst(".name").text().contains("Episode"))
|
||||
"Episode " + li.selectFirst(".name").text().split("Episode")[1].trim()
|
||||
if (li.selectFirst(".name")!!.text().contains("Episode"))
|
||||
"Episode " + li.selectFirst(".name")!!.text().split("Episode")[1].trim()
|
||||
else
|
||||
li.selectFirst(".name").text()
|
||||
li.selectFirst(".name")!!.text()
|
||||
else ""
|
||||
val epThumb = li.selectFirst("img")?.attr("src")
|
||||
val epDate = li.selectFirst(".meta > .date").text()
|
||||
val epDate = li.selectFirst(".meta > .date")!!.text()
|
||||
|
||||
if (poster == null) {
|
||||
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()
|
||||
?.toIntOrNull()
|
||||
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.posterUrl = epThumb
|
||||
addDate(epDate)
|
||||
|
@ -215,7 +215,7 @@ open class VidstreamProviderTemplate : MainAPI() {
|
|||
urls.apmap { url ->
|
||||
val response = app.get(url, timeout = 20).text
|
||||
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.
|
||||
val title = inner.select(".widget-title").text().trim()
|
||||
val elements = inner.select(".video-block").map {
|
||||
|
|
|
@ -20,9 +20,9 @@ class FrenchStreamProvider : MainAPI() {
|
|||
val soup = app.post(link).document
|
||||
|
||||
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 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()
|
||||
if (title.contains(
|
||||
"saison",
|
||||
|
@ -54,24 +54,24 @@ class FrenchStreamProvider : MainAPI() {
|
|||
override suspend fun load(url: String): LoadResponse {
|
||||
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 description =
|
||||
soup.selectFirst("div.fdesc").text().toString()
|
||||
soup.selectFirst("div.fdesc")!!.text().toString()
|
||||
.split("streaming", ignoreCase = true)[1].replace(" : ", "")
|
||||
var poster = fixUrlNull(soup.selectFirst("div.fposter > img")?.attr("src"))
|
||||
val listEpisode = soup.select("div.elink")
|
||||
|
||||
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")
|
||||
?.mapNotNull { // all the tags like action, thriller ...; unused variable
|
||||
it?.text()
|
||||
}
|
||||
return newMovieLoadResponse(title,url,TvType.Movie,url) {
|
||||
this.posterUrl = poster
|
||||
addRating(soup.select("div.fr-count > div")?.text())
|
||||
this.year = soup.select("ul.flist-col > li")?.getOrNull(2)?.text()?.toIntOrNull()
|
||||
addRating(soup.select("div.fr-count > div").text())
|
||||
this.year = soup.select("ul.flist-col > li").getOrNull(2)?.text()?.toIntOrNull()
|
||||
this.tags = tagsList
|
||||
this.plot = description
|
||||
addTrailer(soup.selectFirst("div.fleft > span > a")?.attr("href"))
|
||||
|
@ -91,17 +91,16 @@ class FrenchStreamProvider : MainAPI() {
|
|||
|
||||
val episodes = episodeList.select("a").map { a ->
|
||||
val epNum = a.text().split("Episode")[1].trim().toIntOrNull()
|
||||
val epTitle = if (a.text()?.toString() != null)
|
||||
if (a.text().contains("Episode")) {
|
||||
val type = if ("honey" in a.attr("id")) {
|
||||
"VF"
|
||||
} else {
|
||||
"VOSTFR"
|
||||
}
|
||||
"Episode " + epNum?.toString() + " en " + type
|
||||
val epTitle = if (a.text().contains("Episode")) {
|
||||
val type = if ("honey" in a.attr("id")) {
|
||||
"VF"
|
||||
} else {
|
||||
a.text()
|
||||
} else ""
|
||||
"VOSTFR"
|
||||
}
|
||||
"Episode " + epNum?.toString() + " en " + type
|
||||
} else {
|
||||
a.text()
|
||||
}
|
||||
if (poster == null) {
|
||||
poster = a.selectFirst("div.fposter > img")?.attr("src")
|
||||
}
|
||||
|
@ -133,13 +132,14 @@ class FrenchStreamProvider : MainAPI() {
|
|||
episodeNumber: String,
|
||||
is_vf_available: Boolean,
|
||||
): String {
|
||||
if (episodeNumber == "1") {
|
||||
return if (episodeNumber == "1") {
|
||||
if (is_vf_available) { // 1 translate differently if vf is available or not
|
||||
return "FGHIJK"
|
||||
} else { return "episode033" }
|
||||
}
|
||||
else {
|
||||
return "episode" + (episodeNumber.toInt() + 32).toString()
|
||||
"FGHIJK"
|
||||
} else {
|
||||
"episode033"
|
||||
}
|
||||
} else {
|
||||
"episode" + (episodeNumber.toInt() + 32).toString()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -173,7 +173,7 @@ class FrenchStreamProvider : MainAPI() {
|
|||
val serversvf =// French version servers
|
||||
soup.select("div#$wantedEpisode > div.selink > ul.btnss $div> li")
|
||||
.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()
|
||||
if (serverUrl.isNotBlank()) {
|
||||
if (li.text().replace(" ", "").replace(" ", "").isNotBlank()) {
|
||||
|
@ -208,7 +208,7 @@ class FrenchStreamProvider : MainAPI() {
|
|||
.mapNotNull { a ->
|
||||
val serverurl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null
|
||||
val parent = a.parents()[2]
|
||||
val element = parent.selectFirst("a").text().plus(" ")
|
||||
val element = parent.selectFirst("a")!!.text().plus(" ")
|
||||
if (a.text().replace(" ", "").isNotBlank()) {
|
||||
Pair(element.plus(a.text()), fixUrl(serverurl))
|
||||
} else {
|
||||
|
@ -239,14 +239,14 @@ class FrenchStreamProvider : MainAPI() {
|
|||
val returnList = docs.mapNotNull {
|
||||
val epList = it.selectFirst("> div.sect-c.floats.clearfix") ?: return@mapNotNull null
|
||||
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 isMovieType = title.contains("Films") // if truen type is Movie
|
||||
val currentList = list.map { head ->
|
||||
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 posterUrl = img.attr("src")
|
||||
val posterUrl = img!!.attr("src")
|
||||
val name = img.attr("> div.short-title").toString()
|
||||
return@map if (isMovieType) MovieSearchResponse(
|
||||
name,
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package com.lagradost.cloudstream3.network
|
||||
|
||||
import androidx.annotation.AnyThread
|
||||
import com.lagradost.cloudstream3.USER_AGENT
|
||||
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 okhttp3.Headers
|
||||
import okhttp3.Headers.Companion.toHeaders
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
|
@ -13,14 +17,13 @@ import okhttp3.Response
|
|||
* 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
|
||||
|
||||
@AnyThread
|
||||
class DdosGuardKiller(private val alwaysBypass: Boolean) : Interceptor {
|
||||
val savedCookiesMap = mutableMapOf<String, Map<String, String>>()
|
||||
|
||||
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()
|
||||
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(
|
||||
request.newBuilder()
|
||||
.headers(headers)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
|
@ -8,6 +8,7 @@ import com.lagradost.cloudstream3.USER_AGENT
|
|||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.nicehttp.requestCreator
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.Interceptor
|
||||
|
@ -155,12 +156,12 @@ class WebViewResolver(val interceptUrl: Regex, val additionalUrls: List<Regex> =
|
|||
request.method == "GET" -> app.get(
|
||||
webViewUrl,
|
||||
headers = request.requestHeaders
|
||||
).response.toWebResourceResponse()
|
||||
).okhttpResponse.toWebResourceResponse()
|
||||
|
||||
request.method == "POST" -> app.post(
|
||||
webViewUrl,
|
||||
headers = request.requestHeaders
|
||||
).response.toWebResourceResponse()
|
||||
).okhttpResponse.toWebResourceResponse()
|
||||
else -> return@runBlocking super.shouldInterceptRequest(
|
||||
view,
|
||||
request
|
||||
|
@ -206,28 +207,17 @@ class WebViewResolver(val interceptUrl: Regex, val additionalUrls: List<Regex> =
|
|||
fun WebResourceRequest.toRequest(): Request {
|
||||
val webViewUrl = this.url.toString()
|
||||
|
||||
return when (this.method) {
|
||||
"POST" -> postRequestCreator(
|
||||
webViewUrl,
|
||||
this.requestHeaders,
|
||||
null,
|
||||
emptyMap(),
|
||||
emptyMap(),
|
||||
emptyMap<String, String>(),
|
||||
10,
|
||||
TimeUnit.MINUTES
|
||||
)
|
||||
// "GET",
|
||||
else -> getRequestCreator(
|
||||
webViewUrl,
|
||||
this.requestHeaders,
|
||||
null,
|
||||
emptyMap(),
|
||||
emptyMap(),
|
||||
10,
|
||||
TimeUnit.MINUTES
|
||||
)
|
||||
}
|
||||
return requestCreator(
|
||||
this.method,
|
||||
webViewUrl,
|
||||
this.requestHeaders,
|
||||
null,
|
||||
emptyMap(),
|
||||
emptyMap(),
|
||||
null,
|
||||
10,
|
||||
TimeUnit.MINUTES
|
||||
)
|
||||
}
|
||||
|
||||
fun Response.toWebResourceResponse(): WebResourceResponse {
|
||||
|
|
|
@ -26,7 +26,7 @@ class NyaaProvider : MainAPI() {
|
|||
if (tds.size < 2) continue
|
||||
val type = tds[0].select("> a").attr("title")
|
||||
val titleHeader = tds[1].select("> a").last()
|
||||
val href = titleHeader.attr("href")
|
||||
val href = titleHeader!!.attr("href")
|
||||
val title = titleHeader.text()
|
||||
if (title.contains("[Batch]") || !type.contains("Anime")) continue
|
||||
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 {
|
||||
val response = app.get(url).text
|
||||
val document = Jsoup.parse(response)
|
||||
val title = document.selectFirst("h3.panel-title").text()
|
||||
val description = document.selectFirst("div#torrent-description").text()
|
||||
val title = document.selectFirst("h3.panel-title")!!.text()
|
||||
val description = document.selectFirst("div#torrent-description")!!.text()
|
||||
val downloadLinks = document.select("div.panel-footer > a")
|
||||
val magnet = downloadLinks[1].attr("href")
|
||||
val torrent = downloadLinks[0].attr("href")
|
||||
|
|
|
@ -33,6 +33,7 @@ import com.lagradost.cloudstream3.R
|
|||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.network.initClient
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager
|
||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API
|
||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API.Companion.aniListApi
|
||||
|
|
|
@ -84,8 +84,8 @@ object FillerEpisodeCheck {
|
|||
val documented = Jsoup.parse(result) ?: return null
|
||||
val hashMap = HashMap<Int, Boolean>()
|
||||
documented.select("table.EpisodeList > tbody > tr").forEach {
|
||||
val type = it.selectFirst("td.Type > span").text() == "Filler"
|
||||
val episodeNumber = it.selectFirst("td.Number").text().toIntOrNull()
|
||||
val type = it.selectFirst("td.Type > span")?.text() == "Filler"
|
||||
val episodeNumber = it.selectFirst("td.Number")?.text()?.toIntOrNull()
|
||||
if (episodeNumber != null) {
|
||||
hashMap[episodeNumber] = type
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ import com.bumptech.glide.module.AppGlideModule
|
|||
import com.bumptech.glide.request.RequestOptions
|
||||
import com.bumptech.glide.signature.ObjectKey
|
||||
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
|
||||
|
||||
@GlideModule
|
||||
|
|
|
@ -79,7 +79,7 @@ object SyncUtil {
|
|||
suspend fun getUrlsFromId(id: String, type: String = "anilist") : List<String> {
|
||||
val url =
|
||||
"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()
|
||||
return pages.gogoanime.values.union(pages.nineanime.values).union(pages.twistmoe.values).mapNotNull { it.url }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue