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