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