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") | ||||||
|  |  | ||||||
|  | @ -14,12 +14,14 @@ class AnimeflvnetProvider:MainAPI() { | ||||||
|             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)) | ||||||
|                     } |                     } | ||||||
|  | @ -85,7 +91,8 @@ 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( | ||||||
|  |             "https://www3.animeflv.net/api/animes/search", | ||||||
|             data = mapOf(Pair("value", query)) |             data = mapOf(Pair("value", query)) | ||||||
|         ).text |         ).text | ||||||
|         val json = parseJson<List<SearchObject>>(response) |         val json = parseJson<List<SearchObject>>(response) | ||||||
|  | @ -100,7 +107,9 @@ class AnimeflvnetProvider:MainAPI() { | ||||||
|                 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 | ||||||
|  |                 ), | ||||||
|             ) |             ) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -108,10 +117,10 @@ class AnimeflvnetProvider:MainAPI() { | ||||||
|     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,10 +135,11 @@ 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( | ||||||
|  |                         Episode( | ||||||
|                             link, |                             link, | ||||||
|                             null, |                             null, | ||||||
|                             posterUrl = epthumb, |                             posterUrl = epthumb, | ||||||
|  | @ -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,7 +165,9 @@ 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/") | ||||||
|  |  | ||||||
|  | @ -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 = ArrayList<HomePageList>() |         val items = urls.mapNotNull  { | ||||||
| 
 |             suspendSafeApiCall { | ||||||
|         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,26 +60,24 @@ 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") | ||||||
|  |                     ?.replace("watch/", "anime/")?.replace( | ||||||
|                         Regex("(-episode-(\\d+)\\/\$|-episode-(\\d+)\$|-episode-full|-episode-.*-.(\\/|))"), |                         Regex("(-episode-(\\d+)\\/\$|-episode-(\\d+)\$|-episode-full|-episode-.*-.(\\/|))"), | ||||||
|                         "" |                         "" | ||||||
|                 ) |                     ) ?: return@mapNotNull null | ||||||
|             val poster = it.selectFirst(".film-poster img").attr("data-src") |                 val poster = it.selectFirst(".film-poster img")?.attr("data-src") | ||||||
|                 AnimeSearchResponse( |                 AnimeSearchResponse( | ||||||
|                     title, |                     title, | ||||||
|                     url, |                     url, | ||||||
|  | @ -96,16 +94,16 @@ class AnimekisaProvider : 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(".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 { | ||||||
|  |                     callback.invoke( | ||||||
|                         ExtractorLink( |                         ExtractorLink( | ||||||
|                             this.name, |                             this.name, | ||||||
|                             "${this.name} $release", |                             "${this.name} $release", | ||||||
|                             fixUrl(it.src), |                             fixUrl(it.src), | ||||||
|                             this.mainUrl, |                             this.mainUrl, | ||||||
|                             getQualityFromName("${it.size}"), |                             getQualityFromName("${it.size}"), | ||||||
|                         headers = getHeaders( |                             headers = getHeaders(emptyMap(), | ||||||
|                             mapOf(), |                                 ddosGuardKiller.savedCookiesMap[URI(this.mainUrl).host] | ||||||
|                             null, |                                     ?: emptyMap() | ||||||
|                             ddosGuardKiller.savedCookiesMap.get(URI(this.mainUrl).host) ?: mapOf() |  | ||||||
|                             ).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,12 +80,12 @@ 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( | ||||||
|  | @ -94,20 +94,19 @@ class SoaptwoDayProvider:MainAPI() { | ||||||
|                 ) |                 ) | ||||||
|             } |             } | ||||||
|         //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,8 +91,7 @@ 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 { |                     } else { | ||||||
|  | @ -101,7 +100,7 @@ class FrenchStreamProvider : MainAPI() { | ||||||
|                     "Episode " + epNum?.toString() + " en " + type |                     "Episode " + epNum?.toString() + " en " + type | ||||||
|                 } else { |                 } else { | ||||||
|                     a.text() |                     a.text() | ||||||
|                     } else "" |                 } | ||||||
|                 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 { |         } else { | ||||||
|             return "episode" + (episodeNumber.toInt() + 32).toString() |             "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,7 +17,6 @@ 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>>() | ||||||
|  | @ -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,29 +207,18 @@ 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>(), |  | ||||||
|                 10, |  | ||||||
|                 TimeUnit.MINUTES |  | ||||||
|             ) |  | ||||||
| //            "GET", |  | ||||||
|             else -> getRequestCreator( |  | ||||||
|                 webViewUrl, |  | ||||||
|                 this.requestHeaders, |  | ||||||
|             null, |             null, | ||||||
|                 emptyMap(), |  | ||||||
|                 emptyMap(), |  | ||||||
|             10, |             10, | ||||||
|             TimeUnit.MINUTES |             TimeUnit.MINUTES | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     fun Response.toWebResourceResponse(): WebResourceResponse { |     fun Response.toWebResourceResponse(): WebResourceResponse { | ||||||
|         val contentTypeValue = this.header("Content-Type") |         val contentTypeValue = this.header("Content-Type") | ||||||
|  |  | ||||||
|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue