mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	
							parent
							
								
									1948a2c2d9
								
							
						
					
					
						commit
						3a78f41aad
					
				
					 36 changed files with 547 additions and 246 deletions
				
			
		|  | @ -5,6 +5,7 @@ import android.content.Context | |||
| import android.widget.Toast | ||||
| import com.google.auto.service.AutoService | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.network.post | ||||
| import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread | ||||
| import org.acra.ReportField | ||||
| import org.acra.config.CoreConfiguration | ||||
|  | @ -27,7 +28,7 @@ class CustomReportSender : ReportSender { | |||
| 
 | ||||
|         thread { // to not run it on main thread | ||||
|             normalSafeApiCall { | ||||
|                 val post = khttp.post(url, data = data) | ||||
|                 val post = post(url, data = data) | ||||
|                 println("Report response: $post") | ||||
|             } | ||||
|         } | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| package com.lagradost.cloudstream3.animeproviders | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
| import com.lagradost.cloudstream3.utils.extractorApis | ||||
|  | @ -36,7 +38,7 @@ class AnimeFlickProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): ArrayList<SearchResponse> { | ||||
|         val link = "https://animeflick.net/search.php?search=$query" | ||||
|         val html = khttp.get(link).text | ||||
|         val html = get(link).text | ||||
|         val doc = Jsoup.parse(html) | ||||
| 
 | ||||
|         return ArrayList(doc.select(".row.mt-2").map { | ||||
|  | @ -59,7 +61,7 @@ class AnimeFlickProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val html = khttp.get(url).text | ||||
|         val html = get(url).text | ||||
|         val doc = Jsoup.parse(html) | ||||
| 
 | ||||
|         val poster = mainUrl + doc.selectFirst("img.rounded").attr("src") | ||||
|  | @ -101,7 +103,7 @@ class AnimeFlickProvider : MainAPI() { | |||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ): Boolean { | ||||
|         val html = khttp.get(data).text | ||||
|         val html = get(data).text | ||||
| 
 | ||||
|         val episodeRegex = Regex("""(https://.*?\.mp4)""") | ||||
|         val links = episodeRegex.findAll(html).map { | ||||
|  |  | |||
|  | @ -1,12 +1,13 @@ | |||
| package com.lagradost.cloudstream3.animeproviders | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.* | ||||
| import khttp.structures.cookie.CookieJar | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.network.* | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import okhttp3.Response | ||||
| import org.jsoup.Jsoup | ||||
| import java.util.* | ||||
| import kotlin.collections.ArrayList | ||||
|  | @ -15,7 +16,7 @@ class AnimePaheProvider : MainAPI() { | |||
|     companion object { | ||||
|         const val MAIN_URL = "https://animepahe.com" | ||||
| 
 | ||||
|         var cookies = CookieJar() | ||||
|         var cookies: Map<String, String> = mapOf() | ||||
|         private fun getType(t: String): TvType { | ||||
|             return if (t.contains("OVA") || t.contains("Special")) TvType.ONA | ||||
|             else if (t.contains("Movie")) TvType.AnimeMovie | ||||
|  | @ -23,9 +24,9 @@ class AnimePaheProvider : MainAPI() { | |||
|         } | ||||
| 
 | ||||
|         fun generateSession(): Boolean { | ||||
|             if (cookies.entries.size != 0) return true | ||||
|             if (cookies.isNotEmpty()) return true | ||||
|             return try { | ||||
|                 val response = khttp.get("$MAIN_URL/") | ||||
|                 val response = get("$MAIN_URL/") | ||||
|                 cookies = response.cookies | ||||
|                 true | ||||
|             } catch (e: Exception) { | ||||
|  | @ -82,8 +83,8 @@ class AnimePaheProvider : MainAPI() { | |||
|         val items = ArrayList<HomePageList>() | ||||
|         for (i in urls) { | ||||
|             try { | ||||
|                 val response = khttp.get(i.first) | ||||
|                 val episodes = mapper.readValue<AnimePaheLatestReleases>(response.text).data.map { | ||||
|                 val response = get(i.first).text | ||||
|                 val episodes = mapper.readValue<AnimePaheLatestReleases>(response).data.map { | ||||
| 
 | ||||
|                     AnimeSearchResponse( | ||||
|                         it.animeTitle, | ||||
|  | @ -132,8 +133,8 @@ class AnimePaheProvider : MainAPI() { | |||
|         val url = "$mainUrl/api?m=search&l=8&q=$title" | ||||
|         val headers = mapOf("referer" to "$mainUrl/") | ||||
| 
 | ||||
|         val req = khttp.get(url, headers = headers) | ||||
|         val data = req.let { mapper.readValue<AnimePaheSearch>(it.text) } | ||||
|         val req = get(url, headers = headers).text | ||||
|         val data = req.let { mapper.readValue<AnimePaheSearch>(it) } | ||||
|         for (anime in data.data) { | ||||
|             if (anime.id == animeId) { | ||||
|                 return "https://animepahe.com/anime/${anime.session}" | ||||
|  | @ -147,8 +148,8 @@ class AnimePaheProvider : MainAPI() { | |||
|         val url = "$mainUrl/api?m=search&l=8&q=$query" | ||||
|         val headers = mapOf("referer" to "$mainUrl/") | ||||
| 
 | ||||
|         val req = khttp.get(url, headers = headers) | ||||
|         val data = req.let { mapper.readValue<AnimePaheSearch>(it.text) } | ||||
|         val req = get(url, headers = headers).text | ||||
|         val data = req.let { mapper.readValue<AnimePaheSearch>(it) } | ||||
| 
 | ||||
|         return ArrayList(data.data.map { | ||||
|             AnimeSearchResponse( | ||||
|  | @ -198,8 +199,8 @@ class AnimePaheProvider : MainAPI() { | |||
|             val uri = "$mainUrl/api?m=release&id=$id&sort=episode_asc&page=1" | ||||
|             val headers = mapOf("referer" to "$mainUrl/") | ||||
| 
 | ||||
|             val req = khttp.get(uri, headers = headers) | ||||
|             val data = req.let { mapper.readValue<AnimePaheAnimeData>(it.text) } | ||||
|             val req = get(uri, headers = headers).text | ||||
|             val data = req.let { mapper.readValue<AnimePaheAnimeData>(it) } | ||||
| 
 | ||||
|             val lastPage = data.lastPage | ||||
|             val perPage = data.perPage | ||||
|  | @ -257,7 +258,7 @@ class AnimePaheProvider : MainAPI() { | |||
|             val (animeId, animeTitle) = regex.find(url)!!.destructured | ||||
|             val link = getAnimeByIdAndTitle(animeTitle, animeId.toInt())!! | ||||
| 
 | ||||
|             val html = khttp.get(link).text | ||||
|             val html = get(link).text | ||||
|             val doc = Jsoup.parse(html) | ||||
| 
 | ||||
|             val japTitle = doc.selectFirst("h2.japanese")?.text() | ||||
|  | @ -454,17 +455,17 @@ class AnimePaheProvider : MainAPI() { | |||
|         } | ||||
| 
 | ||||
|         var responseCode = 302 | ||||
|         var adflyContent: khttp.responses.Response? = null | ||||
|         var adflyContent: Response? = null | ||||
|         var tries = 0 | ||||
| 
 | ||||
|         while (responseCode != 200 && tries < 20) { | ||||
|             adflyContent = khttp.get( | ||||
|                 khttp.get(adflyUri, cookies = cookies, allowRedirects = false).headers.getValue("location"), | ||||
|             adflyContent = get( | ||||
|                 get(adflyUri, cookies = cookies, allowRedirects = false).url, | ||||
|                 cookies = cookies, | ||||
|                 allowRedirects = false | ||||
|             ) | ||||
|             cookies.putAll(adflyContent.cookies.toMap()) | ||||
|             responseCode = adflyContent.statusCode | ||||
|             cookies = cookies + adflyContent.cookies | ||||
|             responseCode = adflyContent.code | ||||
|             ++tries | ||||
|         } | ||||
|         if (tries > 19) { | ||||
|  | @ -475,33 +476,33 @@ class AnimePaheProvider : MainAPI() { | |||
| 
 | ||||
|     private fun getStreamUrlFromKwik(adflyUri: String): String { | ||||
|         val fContent = | ||||
|             khttp.get(bypassAdfly(adflyUri), headers = mapOf("referer" to "https://kwik.cx/"), cookies = cookies) | ||||
|         cookies.putAll(fContent.cookies.toMap()) | ||||
|             get(bypassAdfly(adflyUri), headers = mapOf("referer" to "https://kwik.cx/"), cookies = cookies) | ||||
|         cookies = cookies + fContent.cookies | ||||
| 
 | ||||
|         val (fullString, key, v1, v2) = KWIK_PARAMS_RE.find(fContent.text)!!.destructured | ||||
|         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: khttp.responses.Response? = null | ||||
|         var content: Response? = null | ||||
| 
 | ||||
|         var code = 419 | ||||
|         var tries = 0 | ||||
| 
 | ||||
|         while (code != 302 && tries < 20) { | ||||
|             content = khttp.post( | ||||
|             content = post( | ||||
|                 uri, | ||||
|                 allowRedirects = false, | ||||
|                 data = mapOf("_token" to tok), | ||||
|                 headers = mapOf("referer" to fContent.url), | ||||
|                 cookies = cookieStrToMap(fContent.headers.getValue("set-cookie").replace("path=/,", "")) | ||||
|                 cookies = fContent.cookies | ||||
|             ) | ||||
|             code = content.statusCode | ||||
|             code = content.code | ||||
|             ++tries | ||||
|         } | ||||
|         if (tries > 19) { | ||||
|             throw Exception("Failed to extract the stream uri from kwik.") | ||||
|         } | ||||
|         return content?.headers?.getValue("location").toString() | ||||
|         return content?.headers?.values("location").toString() | ||||
|     } | ||||
| 
 | ||||
|     private fun extractVideoLinks(episodeLink: String): List<ExtractorLink> { | ||||
|  | @ -516,8 +517,8 @@ class AnimePaheProvider : MainAPI() { | |||
|             link = link.replace(regex, "") | ||||
| 
 | ||||
| 
 | ||||
|             val req = khttp.get(link, headers = headers) | ||||
|             val jsonResponse = req.let { mapper.readValue<AnimePaheAnimeData>(it.text) } | ||||
|             val req = get(link, headers = headers).text | ||||
|             val jsonResponse = req.let { mapper.readValue<AnimePaheAnimeData>(it) } | ||||
|             val ep = ((jsonResponse.data.map { | ||||
|                 if (it.episode == episodeNum) { | ||||
|                     it | ||||
|  | @ -527,8 +528,8 @@ class AnimePaheProvider : MainAPI() { | |||
|             }).filterNotNull())[0] | ||||
|             link = "$mainUrl/api?m=links&id=${ep.animeId}&session=${ep.session}&p=kwik" | ||||
|         } | ||||
|         val req = khttp.get(link, headers = headers) | ||||
|         val data = mapper.readValue<AnimePaheEpisodeLoadLinks>(req.text) | ||||
|         val req = get(link, headers = headers).text | ||||
|         val data = mapper.readValue<AnimePaheEpisodeLoadLinks>(req) | ||||
| 
 | ||||
|         val qualities = ArrayList<ExtractorLink>() | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,6 +5,8 @@ import com.fasterxml.jackson.module.kotlin.readValue | |||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.APIHolder.unixTime | ||||
| import com.lagradost.cloudstream3.APIHolder.unixTimeMS | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import org.jsoup.Jsoup | ||||
|  | @ -61,8 +63,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
|     ) | ||||
| 
 | ||||
|     private fun parseDocumentTrending(url: String): List<SearchResponse> { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         return document.select("li > a").map { | ||||
|             val href = fixUrl(it.attr("href")) | ||||
|             val title = it.selectFirst("> div > div.cittx").text() | ||||
|  | @ -83,8 +85,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     private fun parseDocument(url: String, trimEpisode: Boolean = false): List<SearchResponse> { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         return document.select("a.grid__link").map { | ||||
|             val href = fixUrl(it.attr("href")) | ||||
|             val title = it.selectFirst("> div.gridtitlek").text() | ||||
|  | @ -124,10 +126,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
|     private fun getAnimeEpisode(slug: String, isMovie: Boolean): EpisodeInfo { | ||||
|         val url = | ||||
|             mainUrl + (if (isMovie) "/movies/jsonMovie" else "/xz/v3/jsonEpi") + ".php?slug=$slug&_=$unixTime" | ||||
|         val response = khttp.get(url) | ||||
|         println(response.text) | ||||
|         val mapped = mapper.readValue<QueryEpisodeResultRoot>(response.text) | ||||
| 
 | ||||
|         val response = get(url).text | ||||
|         val mapped = mapper.readValue<QueryEpisodeResultRoot>(response) | ||||
|         return mapped.result.anime.first() | ||||
|     } | ||||
| 
 | ||||
|  | @ -142,8 +142,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
| 
 | ||||
|     override fun quickSearch(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=$unixTime" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val items = document.select("div.grid__item > a") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|  | @ -177,8 +177,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/search/$query" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val items = document.select("div.resultinner > a.resulta") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|  | @ -229,9 +229,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
|         }.toList()) | ||||
|         for (hl in hls) { | ||||
|             try { | ||||
|                 val sources = khttp.get("$mainUrl/xz/api/playeri.php?url=$hl&_=$unixTime") | ||||
|                 val txt = sources.text | ||||
|                 val find = "src=\"(.*?)\".*?label=\"(.*?)\"".toRegex().find(txt) | ||||
|                 val sources = get("$mainUrl/xz/api/playeri.php?url=$hl&_=$unixTime").text | ||||
|                 val find = "src=\"(.*?)\".*?label=\"(.*?)\"".toRegex().find(sources) | ||||
|                 if (find != null) { | ||||
|                     val quality = find.groupValues[2] | ||||
|                     callback.invoke( | ||||
|  | @ -268,8 +267,8 @@ class DubbedAnimeProvider : MainAPI() { | |||
|                 null | ||||
|             ) | ||||
|         } else { | ||||
|             val response = khttp.get(url) | ||||
|             val document = Jsoup.parse(response.text) | ||||
|             val response = get(url).text | ||||
|             val document = Jsoup.parse(response) | ||||
|             val title = document.selectFirst("h4").text() | ||||
|             val descriptHeader = document.selectFirst("div.animeDescript") | ||||
|             val descript = descriptHeader.selectFirst("> p").text() | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| package com.lagradost.cloudstream3.animeproviders | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.network.url | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.extractorApis | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
|  | @ -67,7 +70,7 @@ class GogoanimeProvider : MainAPI() { | |||
|         for (i in urls) { | ||||
|             try { | ||||
|                 val params = mapOf("page" to "1", "type" to i.first) | ||||
|                 val html = khttp.get("https://ajax.gogo-load.com/ajax/page-recent-release.html", headers=headers, params=params).text | ||||
|                 val html = get("https://ajax.gogo-load.com/ajax/page-recent-release.html", headers=headers, params=params).text | ||||
|                 items.add(HomePageList(i.second, (parseRegex.findAll(html).map { | ||||
|                     val (link, epNum, title, poster) = it.destructured | ||||
|                     AnimeSearchResponse( | ||||
|  | @ -93,7 +96,7 @@ class GogoanimeProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): ArrayList<SearchResponse> { | ||||
|         val link = "$mainUrl/search.html?keyword=$query" | ||||
|         val html = khttp.get(link).text | ||||
|         val html = get(link).text | ||||
|         val doc = Jsoup.parse(html) | ||||
| 
 | ||||
|         val episodes = doc.select(""".last_episodes li""").map { | ||||
|  | @ -126,7 +129,7 @@ class GogoanimeProvider : MainAPI() { | |||
|     override fun load(url: String): LoadResponse { | ||||
|         val link = getProperAnimeLink(url) | ||||
|         val episodeloadApi = "https://ajax.gogo-load.com/ajax/load-list-episode" | ||||
|         val html = khttp.get(link).text | ||||
|         val html = get(link).text | ||||
|         val doc = Jsoup.parse(html) | ||||
| 
 | ||||
|         val animeBody = doc.selectFirst(".anime_info_body_bg") | ||||
|  | @ -166,7 +169,7 @@ class GogoanimeProvider : MainAPI() { | |||
| 
 | ||||
|         val animeId = doc.selectFirst("#movie_id").attr("value") | ||||
|         val params = mapOf("ep_start" to "0", "ep_end" to "2000", "id" to animeId) | ||||
|         val responseHTML = khttp.get(episodeloadApi, params=params).text | ||||
|         val responseHTML = get(episodeloadApi, params=params).text | ||||
|         val epiDoc = Jsoup.parse(responseHTML) | ||||
|         val episodes = epiDoc.select("a").map { | ||||
|             AnimeEpisode( | ||||
|  | @ -195,13 +198,13 @@ class GogoanimeProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     private fun extractVideos(uri: String): List<ExtractorLink> { | ||||
|         val html = khttp.get(uri).text | ||||
|         val html = get(uri).text | ||||
|         val doc = Jsoup.parse(html) | ||||
| 
 | ||||
|         val iframe = "https:" + doc.selectFirst("div.play-video > iframe").attr("src") | ||||
|         val link = iframe.replace("streaming.php", "download") | ||||
| 
 | ||||
|         val page = khttp.get(link, headers = mapOf("Referer" to iframe)) | ||||
|         val page = get(link, headers = mapOf("Referer" to iframe)) | ||||
|         val pageDoc = Jsoup.parse(page.text) | ||||
| 
 | ||||
|         return pageDoc.select(".dowload > a").map { | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| package com.lagradost.cloudstream3.animeproviders | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import org.jsoup.Jsoup | ||||
|  | @ -23,7 +25,9 @@ class KawaiifuProvider : MainAPI() { | |||
| 
 | ||||
|     override fun getMainPage(): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val soup = Jsoup.parse(khttp.get(mainUrl).text) | ||||
|         val resp = get(mainUrl).text | ||||
|         println("RESP $resp") | ||||
|         val soup = Jsoup.parse(resp) | ||||
| 
 | ||||
|         items.add(HomePageList("Latest Updates", soup.select(".today-update .item").map { | ||||
|          val title = it.selectFirst("img").attr("alt") | ||||
|  | @ -71,7 +75,7 @@ class KawaiifuProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): ArrayList<SearchResponse> { | ||||
|         val link = "$mainUrl/search-movie?keyword=${query}" | ||||
|         val html = khttp.get(link).text | ||||
|         val html = get(link).text | ||||
|         val soup = Jsoup.parse(html) | ||||
| 
 | ||||
|         return ArrayList(soup.select(".item").map { | ||||
|  | @ -95,7 +99,7 @@ class KawaiifuProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val html = khttp.get(url).text | ||||
|         val html = get(url).text | ||||
|         val soup = Jsoup.parse(html) | ||||
| 
 | ||||
|         val title = soup.selectFirst(".title").text() | ||||
|  | @ -104,7 +108,7 @@ class KawaiifuProvider : MainAPI() { | |||
|             .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 episodes = Jsoup.parse( | ||||
|             khttp.get( | ||||
|             get( | ||||
|                 soup.selectFirst("a[href*=\".html-episode\"]").attr("href") | ||||
|             ).text | ||||
|         ).selectFirst(".list-ep").select("li").map { | ||||
|  | @ -140,7 +144,7 @@ class KawaiifuProvider : MainAPI() { | |||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ): Boolean { | ||||
|         val htmlSource = khttp.get(data).text | ||||
|         val htmlSource = get(data).text | ||||
|         val soupa = Jsoup.parse(htmlSource) | ||||
| 
 | ||||
|         val episodeNum = if (data.contains("ep=")) data.split("ep=")[1].split("&")[0].toIntOrNull() else null | ||||
|  | @ -159,7 +163,7 @@ class KawaiifuProvider : MainAPI() { | |||
|                 val sources = soupa.select("video > source").map { source -> Pair(source.attr("src"), source.attr("data-quality")) } | ||||
|                 Triple(it.first, sources, it.second.second) | ||||
|             } else { | ||||
|                 val html = khttp.get(it.second.first).text | ||||
|                 val html = get(it.second.first).text | ||||
|                 val soup = Jsoup.parse(html) | ||||
| 
 | ||||
|                 val sources = soup.select("video > source").map { source -> Pair(source.attr("src"), source.attr("data-quality")) } | ||||
|  |  | |||
|  | @ -4,9 +4,11 @@ import android.annotation.SuppressLint | |||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.cookies | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import khttp.structures.cookie.CookieJar | ||||
| import org.jsoup.Jsoup | ||||
| import org.jsoup.nodes.Document | ||||
| import java.text.SimpleDateFormat | ||||
|  | @ -15,7 +17,7 @@ import java.util.* | |||
| class TenshiProvider : MainAPI() { | ||||
|     companion object { | ||||
|         var token: String? = null | ||||
|         var cookie: CookieJar? = null | ||||
|         var cookie: Map<String, String> = mapOf() | ||||
| 
 | ||||
|         fun getType(t: String): TvType { | ||||
|             return if (t.contains("OVA") || t.contains("Special")) TvType.ONA | ||||
|  | @ -32,14 +34,14 @@ class TenshiProvider : MainAPI() { | |||
|         get() = false | ||||
|     override val hasMainPage: Boolean | ||||
|         get() = true | ||||
|      | ||||
|      | ||||
| 
 | ||||
| 
 | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         get() = setOf(TvType.Anime, TvType.AnimeMovie, TvType.ONA) | ||||
| 
 | ||||
|     private fun loadToken(): Boolean { | ||||
|         return try { | ||||
|             val response = khttp.get(mainUrl) | ||||
|             val response = get(mainUrl) | ||||
|             cookie = response.cookies | ||||
|             val document = Jsoup.parse(response.text) | ||||
|             token = document.selectFirst("""meta[name="csrf-token"]""").attr("content") | ||||
|  | @ -48,10 +50,10 @@ class TenshiProvider : MainAPI() { | |||
|             false | ||||
|         } | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     override fun getMainPage(): HomePageResponse { | ||||
|         val items = ArrayList<HomePageList>() | ||||
|         val soup = Jsoup.parse(khttp.get(mainUrl).text) | ||||
|         val soup = Jsoup.parse(get(mainUrl).text) | ||||
|         for (section in soup.select("#content > section")) { | ||||
|             try { | ||||
|                 if (section.attr("id") == "toplist-tabs") { | ||||
|  | @ -95,7 +97,7 @@ class TenshiProvider : MainAPI() { | |||
|                 e.printStackTrace() | ||||
|             } | ||||
|         } | ||||
|         if(items.size <= 0) throw ErrorLoadingException() | ||||
|         if (items.size <= 0) throw ErrorLoadingException() | ||||
|         return HomePageResponse(items) | ||||
|     } | ||||
| 
 | ||||
|  | @ -149,7 +151,7 @@ class TenshiProvider : MainAPI() { | |||
|                 dateString.replace("th ", " ").replace("st ", " ").replace("nd ", " ").replace("rd ", " ") | ||||
|             ) ?: return null | ||||
|             return newFormat.format(data) | ||||
|         } catch (e : Exception) { | ||||
|         } catch (e: Exception) { | ||||
|             return null | ||||
|         } | ||||
|     } | ||||
|  | @ -207,15 +209,15 @@ class TenshiProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): ArrayList<SearchResponse> { | ||||
|         val url = "$mainUrl/anime" | ||||
|         var response = khttp.get(url, params = mapOf("q" to query), cookies = mapOf("loop-view" to "thumb")) | ||||
|         var document = Jsoup.parse(response.text) | ||||
|         var response = get(url, params = mapOf("q" to query), cookies = mapOf("loop-view" to "thumb")).text | ||||
|         var document = Jsoup.parse(response) | ||||
|         val returnValue = parseSearchPage(document) | ||||
| 
 | ||||
|         while (!document.select("""a.page-link[rel="next"]""").isEmpty()) { | ||||
|             val link = document.select("""a.page-link[rel="next"]""") | ||||
|             if (link != null && !link.isEmpty()) { | ||||
|                 response = khttp.get(link[0].attr("href"), cookies = mapOf("loop-view" to "thumb")) | ||||
|                 document = Jsoup.parse(response.text) | ||||
|                 response = get(link[0].attr("href"), cookies = mapOf("loop-view" to "thumb")).text | ||||
|                 document = Jsoup.parse(response) | ||||
|                 returnValue.addAll(parseSearchPage(document)) | ||||
|             } else { | ||||
|                 break | ||||
|  | @ -226,8 +228,8 @@ class TenshiProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val response = khttp.get(url, timeout = 120.0, cookies = mapOf("loop-view" to "thumb")) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url, cookies = mapOf("loop-view" to "thumb")).text | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
|         val englishTitle = document.selectFirst("span.value > span[title=\"English\"]")?.parent()?.text()?.trim() | ||||
|         val japaneseTitle = document.selectFirst("span.value > span[title=\"Japanese\"]")?.parent()?.text()?.trim() | ||||
|  | @ -291,8 +293,8 @@ class TenshiProvider : MainAPI() { | |||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ): Boolean { | ||||
|         val response = khttp.get(data) | ||||
|         val soup = Jsoup.parse(response.text) | ||||
|         val response = get(data).text | ||||
|         val soup = Jsoup.parse(response) | ||||
| 
 | ||||
|         data class Quality( | ||||
|             @JsonProperty("src") val src: String, | ||||
|  | @ -302,9 +304,9 @@ class TenshiProvider : MainAPI() { | |||
|         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 = khttp.get( | ||||
|             val sourceHTML = get( | ||||
|                 "https://tenshi.moe/embed?v=${source.attr("href").split("v=")[1].split("&")[0]}", | ||||
|                 headers=mapOf("Referer" to data) | ||||
|                 headers = mapOf("Referer" to data) | ||||
|             ).text | ||||
| 
 | ||||
|             val match = Regex("""sources: (\[(?:.|\s)+?type: ['\"]video\/.*?['\"](?:.|\s)+?\])""").find(sourceHTML) | ||||
|  |  | |||
|  | @ -3,6 +3,9 @@ package com.lagradost.cloudstream3.animeproviders | |||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.post | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
| import org.jsoup.Jsoup | ||||
|  | @ -27,13 +30,14 @@ class WatchCartoonOnlineProvider : MainAPI() { | |||
|         val url = "https://www.wcostream.com/search" | ||||
| 
 | ||||
|         var response = | ||||
|             khttp.post( | ||||
|             post( | ||||
|                 url, | ||||
|                 headers = mapOf("Referer" to url), | ||||
|                 data = mapOf("catara" to query, "konuara" to "series") | ||||
|             ) | ||||
|         var document = Jsoup.parse(response.text) | ||||
|             ).text | ||||
|         var document = Jsoup.parse(response) | ||||
|         var items = document.select("div#blog > div.cerceve").toList() | ||||
| 
 | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
| 
 | ||||
|         for (item in items) { | ||||
|  | @ -68,12 +72,12 @@ class WatchCartoonOnlineProvider : MainAPI() { | |||
| 
 | ||||
|         // "episodes-search", is used for finding movies, anime episodes should be filtered out | ||||
|         response = | ||||
|             khttp.post( | ||||
|             post( | ||||
|                 url, | ||||
|                 headers = mapOf("Referer" to url), | ||||
|                 data = mapOf("catara" to query, "konuara" to "episodes") | ||||
|             ) | ||||
|         document = Jsoup.parse(response.text) | ||||
|             ).text | ||||
|         document = Jsoup.parse(response) | ||||
|         items = document.select("#catlist-listview2 > ul > li").filter { it?.text() != null && !it?.text().toString().contains("Episode") } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -102,9 +106,8 @@ class WatchCartoonOnlineProvider : MainAPI() { | |||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val isMovie = !url.contains("/anime/") | ||||
| 
 | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
| 
 | ||||
|         return if (!isMovie) { | ||||
|  | @ -194,13 +197,12 @@ class WatchCartoonOnlineProvider : MainAPI() { | |||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ): Boolean { | ||||
|         val response = khttp.get(data) | ||||
|         val response = get(data).text | ||||
|         /*val embedUrl = fixUrl( | ||||
|             Regex("itemprop=\"embedURL\" content=\"(.*?)\"").find(response.text)?.groupValues?.get(1) ?: return false | ||||
|         )*/ | ||||
|         val text = response.text | ||||
|         val start = text.indexOf("itemprop=\"embedURL") | ||||
|         val foundJS = Regex("<script>(.*?)</script>").find(text, start)?.groupValues?.get(1) | ||||
|         val start = response.indexOf("itemprop=\"embedURL") | ||||
|         val foundJS = Regex("<script>(.*?)</script>").find(response, start)?.groupValues?.get(1) | ||||
|             ?.replace("document.write", "var returnValue = ") | ||||
| 
 | ||||
|         val rhino = Context.enter() | ||||
|  | @ -223,7 +225,7 @@ class WatchCartoonOnlineProvider : MainAPI() { | |||
|         val jsEval = scope.get("returnValue", scope) ?: return false | ||||
|         val src = fixUrl(Regex("src=\"(.*?)\"").find(jsEval as String)?.groupValues?.get(1) ?: return false) | ||||
| 
 | ||||
|         val embedResponse = khttp.get( | ||||
|         val embedResponse = get( | ||||
|             (src), | ||||
|             headers = mapOf("Referer" to data) | ||||
|         ) | ||||
|  | @ -231,7 +233,7 @@ class WatchCartoonOnlineProvider : MainAPI() { | |||
|         val getVidLink = fixUrl( | ||||
|             Regex("get\\(\"(.*?)\"").find(embedResponse.text)?.groupValues?.get(1) ?: return false | ||||
|         ) | ||||
|         val linkResponse = khttp.get( | ||||
|         val linkResponse = get( | ||||
|             getVidLink, headers = mapOf( | ||||
|                 "sec-ch-ua" to "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"", | ||||
|                 "sec-ch-ua-mobile" to "?0", | ||||
|  | @ -275,4 +277,4 @@ class WatchCartoonOnlineProvider : MainAPI() { | |||
| 
 | ||||
|         return true | ||||
|     } | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -3,6 +3,10 @@ package com.lagradost.cloudstream3.animeproviders | |||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.extractors.WcoStream | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.post | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import org.json.JSONObject | ||||
| import org.jsoup.Jsoup | ||||
| import org.jsoup.nodes.Document | ||||
| import java.util.* | ||||
|  | @ -45,9 +49,9 @@ class WcoProvider : MainAPI() { | |||
|         val items = ArrayList<HomePageList>() | ||||
|         for (i in urls) { | ||||
|             try { | ||||
|                 val response = khttp.get( | ||||
|                 val response = JSONObject(get( | ||||
|                     i.first, | ||||
|                 ).jsonObject.getString("html") // I won't make a dataclass for this shit | ||||
|                 ).text).getString("html") // I won't make a dataclass for this shit | ||||
|                 val document = Jsoup.parse(response) | ||||
|                 val results = document.select("div.flw-item").map { | ||||
|                     val filmPoster = it.selectFirst("> div.film-poster") | ||||
|  | @ -116,15 +120,16 @@ class WcoProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/search" | ||||
|         val response = khttp.get(url, params = mapOf("keyword" to query)) | ||||
|         val response = | ||||
|             get(url, params = mapOf("keyword" to query)) | ||||
|         var document = Jsoup.parse(response.text) | ||||
|         val returnValue = parseSearchPage(document) | ||||
| 
 | ||||
|         while (!document.select(".pagination").isEmpty()) { | ||||
|             val link = document.select("a.page-link[rel=\"next\"]") | ||||
|             if (!link.isEmpty()) { | ||||
|                 val extraResponse = khttp.get(fixUrl(link[0].attr("href"))) | ||||
|                 document = Jsoup.parse(extraResponse.text) | ||||
|                 val extraResponse = get(fixUrl(link[0].attr("href"))).text | ||||
|                 document = Jsoup.parse(extraResponse) | ||||
|                 returnValue.addAll(parseSearchPage(document)) | ||||
|             } else { | ||||
|                 break | ||||
|  | @ -136,10 +141,10 @@ class WcoProvider : MainAPI() { | |||
|     override fun quickSearch(query: String): List<SearchResponse> { | ||||
|         val returnValue: ArrayList<SearchResponse> = ArrayList() | ||||
| 
 | ||||
|         val response = khttp.post( | ||||
|         val response = JSONObject(post( | ||||
|             "https://wcostream.cc/ajax/search", | ||||
|             data = mapOf("keyword" to query) | ||||
|         ).jsonObject.getString("html") // I won't make a dataclass for this shit | ||||
|         ).text).getString("html") // I won't make a dataclass for this shit | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
|         document.select("a.nav-item").forEach { | ||||
|  | @ -177,8 +182,8 @@ class WcoProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val response = khttp.get(url, timeout = 120.0) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url, timeout = 120).text | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
|         val japaneseTitle = document.selectFirst("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(1)") | ||||
|             ?.text()?.trim()?.replace("Other names:", "")?.trim() | ||||
|  | @ -234,8 +239,8 @@ class WcoProvider : MainAPI() { | |||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ): Boolean { | ||||
|         val response = khttp.get(data) | ||||
|         val servers = Jsoup.parse(response.text).select("#servers-list > ul > li").map { | ||||
|         val response = get(data).text | ||||
|         val servers = Jsoup.parse(response).select("#servers-list > ul > li").map { | ||||
|             mapOf( | ||||
|                 "link" to it?.selectFirst("a")?.attr("data-embed"), | ||||
|                 "title" to it?.selectFirst("span")?.text()?.trim() | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
|  | @ -30,13 +32,13 @@ open class DoodLaExtractor : ExtractorApi() { | |||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||
|         val id = url.removePrefix("$mainUrl/e/").removePrefix("$mainUrl/d/") | ||||
|         val trueUrl = getExtractorUrl(id) | ||||
|         val response = khttp.get(trueUrl) | ||||
|         Regex("href=\".*/download/(.*?)\"").find(response.text)?.groupValues?.get(1)?.let { link -> | ||||
|         val response = get(trueUrl).text | ||||
|         Regex("href=\".*/download/(.*?)\"").find(response)?.groupValues?.get(1)?.let { link -> | ||||
|             if (link.isEmpty()) return null | ||||
|             sleep(5000) // might need this to not trigger anti bot | ||||
|             val downloadLink = "$mainUrl/download/$link" | ||||
|             val downloadResponse = khttp.get(downloadLink) | ||||
|             Regex("onclick=\"window\\.open\\((['\"])(.*?)(['\"])").find(downloadResponse.text)?.groupValues?.get(2) | ||||
|             val downloadResponse = get(downloadLink).text | ||||
|             Regex("onclick=\"window\\.open\\((['\"])(.*?)(['\"])").find(downloadResponse)?.groupValues?.get(2) | ||||
|                 ?.let { trueLink -> | ||||
|                     return listOf( | ||||
|                         ExtractorLink( | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
| 
 | ||||
| class MixDrop : ExtractorApi() { | ||||
|  | @ -13,7 +15,7 @@ class MixDrop : ExtractorApi() { | |||
|     } | ||||
| 
 | ||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||
|         with(khttp.get(url)) { | ||||
|         with(get(url)) { | ||||
|             getAndUnpack(this.text)?.let { unpackedText -> | ||||
|                 srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> | ||||
|                     return listOf( | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
| 
 | ||||
| class Mp4Upload : ExtractorApi() { | ||||
|  | @ -9,7 +11,7 @@ class Mp4Upload : ExtractorApi() { | |||
|     override val requiresReferer = true | ||||
| 
 | ||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||
|         with(khttp.get(url)) { | ||||
|         with(get(url)) { | ||||
|             getAndUnpack(this.text)?.let { unpackedText -> | ||||
|                 srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> | ||||
|                     return listOf( | ||||
|  |  | |||
|  | @ -1,5 +1,8 @@ | |||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.network.url | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
|  | @ -28,12 +31,12 @@ class MultiQuality : ExtractorApi() { | |||
| 
 | ||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||
|         val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() | ||||
|         with(khttp.get(url)) { | ||||
|         with(get(url)) { | ||||
|             sourceRegex.findAll(this.text).forEach { sourceMatch -> | ||||
|                 val extractedUrl = sourceMatch.groupValues[1] | ||||
|                 // Trusting this isn't mp4, may fuck up stuff | ||||
|                 if (extractedUrl.endsWith(".m3u8")) { | ||||
|                     with(khttp.get(extractedUrl)) { | ||||
|                     with(get(extractedUrl)) { | ||||
|                         m3u8Regex.findAll(this.text).forEach { match -> | ||||
|                             extractedLinksList.add( | ||||
|                                 ExtractorLink( | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getAndUnpack | ||||
|  | @ -21,12 +23,12 @@ class StreamSB : ExtractorApi() { | |||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||
|         val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() | ||||
|         val newUrl = url.replace("sbplay.org/embed-", "sbplay.org/play/").removeSuffix(".html") | ||||
|         with(khttp.get(newUrl, timeout = 10.0)) { | ||||
|         with(get(newUrl, timeout = 10)) { | ||||
|             getAndUnpack(this.text)?.let { | ||||
|                 sourceRegex.findAll(it).forEach { sourceMatch -> | ||||
|                     val extractedUrl = sourceMatch.groupValues[1] | ||||
|                     if (extractedUrl.contains(".m3u8")) { | ||||
|                         with(khttp.get(extractedUrl)) { | ||||
|                         with(get(extractedUrl)) { | ||||
|                             m3u8UrlRegex.findAll(this.text).forEach { match -> | ||||
|                                 val extractedUrlM3u8 = match.groupValues[2] | ||||
|                                 val extractedRes = match.groupValues[1] | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
|  | @ -14,7 +16,7 @@ class StreamTape : ExtractorApi() { | |||
|         Regex("""(i(|" \+ ')d(|" \+ ')=.*?&(|" \+ ')e(|" \+ ')x(|" \+ ')p(|" \+ ')i(|" \+ ')r(|" \+ ')e(|" \+ ')s(|" \+ ')=.*?&(|" \+ ')i(|" \+ ')p(|" \+ ')=.*?&(|" \+ ')t(|" \+ ')o(|" \+ ')k(|" \+ ')e(|" \+ ')n(|" \+ ')=.*)'""") | ||||
| 
 | ||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||
|         with(khttp.get(url)) { | ||||
|         with(get(url)) { | ||||
|             linkRegex.find(this.text)?.let { | ||||
|                 val extractedUrl = "https://streamtape.com/get_video?${it.groupValues[1]}".replace("""" + '""", "") | ||||
|                 return listOf( | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.JsUnpacker | ||||
|  | @ -18,8 +20,8 @@ class Streamhub : ExtractorApi() { | |||
|     } | ||||
| 
 | ||||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||
|         val response = khttp.get(url) | ||||
|         Regex("eval((.|\\n)*?)</script>").find(response.text)?.groupValues?.get(1)?.let { jsEval -> | ||||
|         val response = get(url).text | ||||
|         Regex("eval((.|\\n)*?)</script>").find(response)?.groupValues?.get(1)?.let { jsEval -> | ||||
|             JsUnpacker("eval$jsEval" ).unpack()?.let { unPacked -> | ||||
|                 Regex("sources:\\[\\{src:\"(.*?)\"").find(unPacked)?.groupValues?.get(1)?.let { link -> | ||||
|                     return listOf( | ||||
|  |  | |||
|  | @ -1,6 +1,9 @@ | |||
| package com.lagradost.cloudstream3.extractors | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.network.url | ||||
| import com.lagradost.cloudstream3.pmap | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.extractorApis | ||||
|  | @ -38,7 +41,7 @@ class Vidstream(overrideMainUrl: String? = null) { | |||
|             /** Stolen from GogoanimeProvider.kt extractor */ | ||||
|             normalSafeApiCall { | ||||
|                 val link = getDownloadUrl(id) | ||||
|                 val page = khttp.get(link, headers = mapOf("Referer" to extractorUrl)) | ||||
|                 val page = get(link, headers = mapOf("Referer" to extractorUrl)) | ||||
|                 val pageDoc = Jsoup.parse(page.text) | ||||
|                 val qualityRegex = Regex("(\\d+)P") | ||||
| 
 | ||||
|  | @ -60,7 +63,7 @@ class Vidstream(overrideMainUrl: String? = null) { | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             with(khttp.get(extractorUrl)) { | ||||
|             with(get(extractorUrl)) { | ||||
|                 val document = Jsoup.parse(this.text) | ||||
|                 val primaryLinks = document.select("ul.list-server-items > li.linkserver") | ||||
|                 //val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() | ||||
|  |  | |||
|  | @ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonProperty | |||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
| import com.lagradost.cloudstream3.mapper | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| 
 | ||||
| class WcoStream : ExtractorApi() { | ||||
|     override val name: String = "WcoStream" | ||||
|  | @ -14,14 +16,14 @@ class WcoStream : ExtractorApi() { | |||
|     override fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||
|         val baseUrl = url.split("/e/")[0] | ||||
| 
 | ||||
|         val html = khttp.get(url, headers = mapOf("Referer" to "https://wcostream.cc/")).text | ||||
|         val html = get(url, headers = mapOf("Referer" to "https://wcostream.cc/")).text | ||||
|         val (Id) = "/e/(.*?)?domain".toRegex().find(url)!!.destructured | ||||
|         val (skey) = """skey\s=\s['"](.*?)['"];""".toRegex().find(html)!!.destructured | ||||
| 
 | ||||
|         val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey" | ||||
|         val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" | ||||
| 
 | ||||
|         val response = khttp.get(apiLink, headers = mapOf("Referer" to referrer)).text | ||||
|         val response = get(apiLink, headers = mapOf("Referer" to referrer)).text | ||||
| 
 | ||||
|         data class Sources( | ||||
|             @JsonProperty("file") val file: String, | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ package com.lagradost.cloudstream3.extractors | |||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.mapper | ||||
| import com.lagradost.cloudstream3.network.post | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorApi | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
|  | @ -44,9 +46,10 @@ class XStreamCdn : ExtractorApi() { | |||
|         ) | ||||
|         val newUrl = url.replace("$mainUrl/v/", "$mainUrl/api/source/") | ||||
|         val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() | ||||
|         with(khttp.post(newUrl, headers = headers)) { | ||||
|             if (this.text == """{"success":false,"data":"Video not found or has been removed"}""") return listOf() | ||||
|             mapper.readValue<ResponseJson?>(this.text)?.let { | ||||
|         with(post(newUrl, headers = headers)) { | ||||
|             val text = this.text | ||||
|             if (text == """{"success":false,"data":"Video not found or has been removed"}""") return listOf() | ||||
|             mapper.readValue<ResponseJson?>(text)?.let { | ||||
|                 if (it.success && it.data != null) { | ||||
|                     it.data.forEach { data -> | ||||
|                         extractedLinksList.add( | ||||
|  |  | |||
|  | @ -2,9 +2,14 @@ package com.lagradost.cloudstream3.movieproviders | |||
| 
 | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.post | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.network.url | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
| import com.lagradost.cloudstream3.utils.loadExtractor | ||||
| import okio.Buffer | ||||
| import org.jsoup.Jsoup | ||||
| import org.jsoup.nodes.Document | ||||
| import java.lang.Thread.sleep | ||||
|  | @ -33,8 +38,8 @@ class AllMoviesForYouProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/?s=$query" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
|         val items = document.select("ul.MovieList > li > article > a") | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|  | @ -72,8 +77,8 @@ class AllMoviesForYouProvider : MainAPI() { | |||
|     override fun load(url: String): LoadResponse { | ||||
|         val type = getType(url) | ||||
| 
 | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
|         val title = document.selectFirst("h1.Title").text() | ||||
|         val descipt = document.selectFirst("div.Description > p").text() | ||||
|  | @ -98,8 +103,8 @@ class AllMoviesForYouProvider : MainAPI() { | |||
|             val episodeList = ArrayList<TvSeriesEpisode>() | ||||
| 
 | ||||
|             for (season in list) { | ||||
|                 val seasonResponse = khttp.get(season.second) | ||||
|                 val seasonDocument = Jsoup.parse(seasonResponse.text) | ||||
|                 val seasonResponse = get(season.second).text | ||||
|                 val seasonDocument = Jsoup.parse(seasonResponse) | ||||
|                 val episodes = seasonDocument.select("table > tbody > tr") | ||||
|                 if (episodes.isNotEmpty()) { | ||||
|                     episodes.forEach { episode -> | ||||
|  | @ -162,8 +167,8 @@ class AllMoviesForYouProvider : MainAPI() { | |||
|         callback: (ExtractorLink) -> Unit | ||||
|     ): Boolean { | ||||
|         if (data.startsWith("$mainUrl/episode/")) { | ||||
|             val response = khttp.get(data) | ||||
|             getLink(Jsoup.parse(response.text))?.let { links -> | ||||
|             val response = get(data).text | ||||
|             getLink(Jsoup.parse(response))?.let { links -> | ||||
|                 for (link in links) { | ||||
|                     if (link == data) continue | ||||
|                     loadLinks(link, isCasting, subtitleCallback, callback) | ||||
|  | @ -174,9 +179,21 @@ class AllMoviesForYouProvider : MainAPI() { | |||
|         } else if (data.startsWith(mainUrl) && data != mainUrl) { | ||||
|             val realDataUrl = URLDecoder.decode(data, "application/x-www-form-urlencoded") | ||||
|             if (data.contains("trdownload")) { | ||||
|                 val request = khttp.get(data, stream = true) | ||||
|                 val request = get(data) | ||||
|                 if (request.url.startsWith("https://streamhub.to/d/")) { | ||||
|                     val document = Jsoup.parse(request.text) | ||||
|                     val buffer = Buffer() | ||||
|                     val source = request.body?.source() | ||||
|                     var html = "" | ||||
|                     var tries = 0 // 20 tries = 163840 bytes = 0.16mb | ||||
| 
 | ||||
|                     while (source?.exhausted() == false && tries < 20) { | ||||
|                         // 8192 = max size | ||||
|                         source.read(buffer, 8192) | ||||
|                         tries += 1 | ||||
|                         html += buffer.readUtf8() | ||||
|                     } | ||||
| 
 | ||||
|                     val document = Jsoup.parse(html) | ||||
|                     val inputs = document.select("Form > input") | ||||
|                     if (inputs.size < 4) return false | ||||
|                     var op: String? = null | ||||
|  | @ -195,24 +212,33 @@ class AllMoviesForYouProvider : MainAPI() { | |||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     if(op == null || id == null || mode == null || hash == null) { | ||||
|                     if (op == null || id == null || mode == null || hash == null) { | ||||
|                         return false | ||||
|                     } | ||||
|                     sleep(5000) // ye this is needed, wont work with 0 delay | ||||
| 
 | ||||
|                     val postResponse = khttp.post(request.url, headers = mapOf("content-type" to "application/x-www-form-urlencoded", "referer" to request.url, "user-agent" to USER_AGENT, "accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"), data = mapOf("op" to op, "id" to id, "mode" to mode, "hash" to hash)) | ||||
|                     val postDocument = Jsoup.parse(postResponse.text) | ||||
|                     val postResponse = post( | ||||
|                         request.url, | ||||
|                         headers = mapOf( | ||||
|                             "content-type" to "application/x-www-form-urlencoded", | ||||
|                             "referer" to request.url, | ||||
|                             "user-agent" to USER_AGENT, | ||||
|                             "accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" | ||||
|                         ), | ||||
|                         data = mapOf("op" to op, "id" to id, "mode" to mode, "hash" to hash) | ||||
|                     ).text | ||||
|                     val postDocument = Jsoup.parse(postResponse) | ||||
| 
 | ||||
|                     val url = postDocument.selectFirst("a.downloadbtn").attr("href") | ||||
|                     if(url.isNullOrEmpty()) return false | ||||
|                     if (url.isNullOrEmpty()) return false | ||||
|                     callback(ExtractorLink(this.name, this.name, url, mainUrl, Qualities.Unknown.value)) | ||||
|                 } else { | ||||
|                     callback(ExtractorLink(this.name, this.name, realDataUrl, mainUrl, Qualities.Unknown.value)) | ||||
|                 } | ||||
|                 return true | ||||
|             } | ||||
|             val response = khttp.get(realDataUrl) | ||||
|             Regex("<iframe.*?src=\"(.*?)\"").find(response.text)?.groupValues?.get(1)?.let { url -> | ||||
|             val response = get(realDataUrl).text | ||||
|             Regex("<iframe.*?src=\"(.*?)\"").find(response)?.groupValues?.get(1)?.let { url -> | ||||
|                 loadExtractor(url.trimStart(), realDataUrl, callback) | ||||
|             } | ||||
|             return true | ||||
|  |  | |||
|  | @ -5,10 +5,11 @@ import com.fasterxml.jackson.core.JsonParser | |||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.getStatus | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.DataStore.toKotlinObject | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import khttp.get | ||||
| 
 | ||||
| class AsiaFlixProvider : MainAPI() { | ||||
|     override val mainUrl: String | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| package com.lagradost.cloudstream3.movieproviders | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
| import org.jsoup.Jsoup | ||||
|  | @ -18,8 +20,8 @@ class HDMProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/search/$query" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val items = document.select("div.col-md-2 > article > a") | ||||
|         if (items.isEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|  | @ -42,8 +44,8 @@ class HDMProvider : MainAPI() { | |||
|     ): Boolean { | ||||
|         if (data == "") return false | ||||
|         val slug = ".*/(.*?)\\.mp4".toRegex().find(data)?.groupValues?.get(1) ?: return false | ||||
|         val response = khttp.get(data) | ||||
|         val key = "playlist\\.m3u8(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return false | ||||
|         val response = get(data).text | ||||
|         val key = "playlist\\.m3u8(.*?)\"".toRegex().find(response)?.groupValues?.get(1) ?: return false | ||||
|         callback.invoke( | ||||
|             ExtractorLink( | ||||
|                 this.name, | ||||
|  | @ -58,14 +60,14 @@ class HDMProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse? { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = 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() | ||||
|             ?.toIntOrNull() | ||||
|         val data = "src/player/\\?v=(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return null | ||||
|         val data = "src/player/\\?v=(.*?)\"".toRegex().find(response)?.groupValues?.get(1) ?: return null | ||||
| 
 | ||||
|         return MovieLoadResponse( | ||||
|             title, url, this.name, TvType.Movie, | ||||
|  |  | |||
|  | @ -6,6 +6,8 @@ import com.lagradost.cloudstream3.* | |||
| import com.lagradost.cloudstream3.APIHolder.unixTime | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.extractors.M3u8Manifest | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import org.jsoup.Jsoup | ||||
| 
 | ||||
|  | @ -71,12 +73,12 @@ class LookMovieProvider : MainAPI() { | |||
| 
 | ||||
|     override fun quickSearch(query: String): List<SearchResponse> { | ||||
|         val movieUrl = "$mainUrl/api/v1/movies/search/?q=$query" | ||||
|         val movieResponse = khttp.get(movieUrl) | ||||
|         val movies = mapper.readValue<LookMovieSearchResultRoot>(movieResponse.text).result | ||||
|         val movieResponse = get(movieUrl).text | ||||
|         val movies = mapper.readValue<LookMovieSearchResultRoot>(movieResponse).result | ||||
| 
 | ||||
|         val showsUrl = "$mainUrl/api/v1/shows/search/?q=$query" | ||||
|         val showsResponse = khttp.get(showsUrl) | ||||
|         val shows = mapper.readValue<LookMovieSearchResultRoot>(showsResponse.text).result | ||||
|         val showsResponse = get(showsUrl).text | ||||
|         val shows = mapper.readValue<LookMovieSearchResultRoot>(showsResponse).result | ||||
| 
 | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|         if (!movies.isNullOrEmpty()) { | ||||
|  | @ -117,8 +119,8 @@ class LookMovieProvider : MainAPI() { | |||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         fun search(query: String, isMovie: Boolean): ArrayList<SearchResponse> { | ||||
|             val url = "$mainUrl/${if (isMovie) "movies" else "shows"}/search/?q=$query" | ||||
|             val response = khttp.get(url) | ||||
|             val document = Jsoup.parse(response.text) | ||||
|             val response = get(url).text | ||||
|             val document = Jsoup.parse(response) | ||||
| 
 | ||||
|             val items = document.select("div.flex-wrap-movielist > div.movie-item-style-1") | ||||
|             val returnValue = ArrayList<SearchResponse>() | ||||
|  | @ -161,8 +163,8 @@ class LookMovieProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     private fun loadCurrentLinks(url: String, callback: (ExtractorLink) -> Unit) { | ||||
|         val response = khttp.get(url.replace("\$unixtime", unixTime.toString())) | ||||
|         M3u8Manifest.extractLinks(response.text).forEach { | ||||
|         val response = get(url.replace("\$unixtime", unixTime.toString())).text | ||||
|         M3u8Manifest.extractLinks(response).forEach { | ||||
|             callback.invoke( | ||||
|                 ExtractorLink( | ||||
|                     this.name, | ||||
|  | @ -185,24 +187,24 @@ class LookMovieProvider : MainAPI() { | |||
|         val localData: LookMovieLinkLoad = mapper.readValue(data) | ||||
| 
 | ||||
|         if (localData.isMovie) { | ||||
|             val tokenResponse = khttp.get(localData.url) | ||||
|             val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse.text) | ||||
|             val tokenResponse = get(localData.url).text | ||||
|             val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse) | ||||
|             val accessToken = root.data?.accessToken ?: return false | ||||
|             addSubtitles(root.data.subtitles, subtitleCallback) | ||||
|             loadCurrentLinks(localData.extraUrl.replace("\$accessToken", accessToken), callback) | ||||
|             return true | ||||
|         } else { | ||||
|             loadCurrentLinks(localData.url, callback) | ||||
|             val subResponse = khttp.get(localData.extraUrl) | ||||
|             val subs = mapper.readValue<List<LookMovieTokenSubtitle>>(subResponse.text) | ||||
|             val subResponse = get(localData.extraUrl).text | ||||
|             val subs = mapper.readValue<List<LookMovieTokenSubtitle>>(subResponse) | ||||
|             addSubtitles(subs, subtitleCallback) | ||||
|         } | ||||
|         return true | ||||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse? { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val isMovie = url.contains("/movies/") | ||||
| 
 | ||||
|         val watchHeader = document.selectFirst("div.watch-heading") | ||||
|  | @ -215,7 +217,7 @@ class LookMovieProvider : MainAPI() { | |||
|         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 id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex().find(response.text)?.groupValues?.get(1) | ||||
|         val id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex().find(response)?.groupValues?.get(1) | ||||
|             ?.replace(" ", "") | ||||
|             ?: return null | ||||
|         val realSlug = url.replace("$mainUrl/${if (isMovie) "movies" else "shows"}/view/", "") | ||||
|  | @ -243,12 +245,12 @@ class LookMovieProvider : MainAPI() { | |||
|                 rating | ||||
|             ) | ||||
|         } else { | ||||
|             val tokenResponse = khttp.get(realUrl) | ||||
|             val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse.text) | ||||
|             val tokenResponse = get(realUrl).text | ||||
|             val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse) | ||||
|             val accessToken = root.data?.accessToken ?: return null | ||||
| 
 | ||||
|             val window = | ||||
|                 "window\\['show_storage'] =((.|\\n)*?<)".toRegex().find(response.text)?.groupValues?.get(1) | ||||
|                 "window\\['show_storage'] =((.|\\n)*?<)".toRegex().find(response)?.groupValues?.get(1) | ||||
|                     ?: return null | ||||
|             // val id = "id_show:(.*?),".toRegex().find(response.text)?.groupValues?.get(1) ?: return null | ||||
|             val season = "seasons:.*\\[((.|\\n)*?)]".toRegex().find(window)?.groupValues?.get(1) ?: return null | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ package com.lagradost.cloudstream3.movieproviders | |||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import org.jsoup.Jsoup | ||||
|  | @ -38,8 +40,8 @@ class MeloMovieProvider : MainAPI() { | |||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/movie/search/?name=$query" | ||||
|         val returnValue: ArrayList<SearchResponse> = ArrayList() | ||||
|         val response = khttp.get(url) | ||||
|         val mapped = response.let { mapper.readValue<List<MeloMovieSearchResult>>(it.text) } | ||||
|         val response = get(url).text | ||||
|         val mapped = response.let { mapper.readValue<List<MeloMovieSearchResult>>(it) } | ||||
|         if (mapped.isEmpty()) return returnValue | ||||
| 
 | ||||
|         for (i in mapped) { | ||||
|  | @ -115,7 +117,7 @@ class MeloMovieProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse? { | ||||
|         val response = khttp.get(url).text | ||||
|         val response = get(url).text | ||||
| 
 | ||||
|         //backdrop = imgurl | ||||
|         fun findUsingRegex(src: String): String? { | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ package com.lagradost.cloudstream3.movieproviders | |||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import java.util.concurrent.TimeUnit | ||||
|  | @ -41,8 +43,8 @@ class ThenosProvider : MainAPI() { | |||
|         val list = ArrayList<HomePageList>() | ||||
|         map.entries.forEach { | ||||
|             val url = "$apiUrl/library/${it.value}" | ||||
|             val response = khttp.get(url) | ||||
|             val mapped = mapper.readValue<ThenosLoadResponse>(response.text) | ||||
|             val response = get(url).text | ||||
|             val mapped = mapper.readValue<ThenosLoadResponse>(response) | ||||
| 
 | ||||
|             mapped.Metadata?.mapNotNull { meta -> | ||||
|                 meta?.toSearchResponse() | ||||
|  | @ -209,8 +211,8 @@ class ThenosProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     private fun searchFromUrl(url: String): List<SearchResponse> { | ||||
|         val response = khttp.get(url) | ||||
|         val test = mapper.readValue<ThenosSearchResponse>(response.text) | ||||
|         val response = get(url).text | ||||
|         val test = mapper.readValue<ThenosSearchResponse>(response) | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
| 
 | ||||
|         test.Hub?.forEach { | ||||
|  | @ -255,12 +257,12 @@ class ThenosProvider : MainAPI() { | |||
|         callback: (ExtractorLink) -> Unit | ||||
|     ): Boolean { | ||||
|         val url = "$apiUrl/library/watch/$data" | ||||
|         val response = khttp.get(url) | ||||
|         val mapped = mapper.readValue<ThenosSource>(response.text) | ||||
|         val response = get(url).text | ||||
|         val mapped = mapper.readValue<ThenosSource>(response) | ||||
| 
 | ||||
|         mapped.sources?.forEach { source -> | ||||
|             val isM3u8 = source.type != "video/mp4" | ||||
|             val token = khttp.get("https://token.noss.workers.dev/").text | ||||
|             val token = get("https://token.noss.workers.dev/").text | ||||
|             val authorization = | ||||
|                 String(android.util.Base64.decode(token, android.util.Base64.DEFAULT), Charsets.ISO_8859_1) | ||||
| 
 | ||||
|  | @ -423,12 +425,12 @@ class ThenosProvider : MainAPI() { | |||
|     private fun getAllEpisodes(id: String): List<TvSeriesEpisode> { | ||||
|         val episodes = ArrayList<TvSeriesEpisode>() | ||||
|         val url = "$apiUrl/library/metadata/$id/children" | ||||
|         val response = khttp.get(url) | ||||
|         val mapped = mapper.readValue<ThenosSeriesResponse>(response.text) | ||||
|         val response = get(url).text | ||||
|         val mapped = mapper.readValue<ThenosSeriesResponse>(response) | ||||
|         mapped.Metadata?.forEach { series_meta -> | ||||
|             val fixedUrl = apiUrl + series_meta.key | ||||
|             val child = khttp.get(fixedUrl) | ||||
|             val mappedSeason = mapper.readValue<SeasonResponse>(child.text) | ||||
|             val child = get(fixedUrl).text | ||||
|             val mappedSeason = mapper.readValue<SeasonResponse>(child) | ||||
|             mappedSeason.Metadata?.forEach mappedSeason@{ meta -> | ||||
|                 episodes.add( | ||||
|                     TvSeriesEpisode( | ||||
|  | @ -450,8 +452,8 @@ class ThenosProvider : MainAPI() { | |||
| 
 | ||||
|     override fun load(url: String): LoadResponse? { | ||||
|         val fixedUrl = "$apiUrl/library/metadata/${url.split("/").last()}" | ||||
|         val response = khttp.get(fixedUrl) | ||||
|         val mapped = mapper.readValue<ThenosLoadResponse>(response.text) | ||||
|         val response = get(fixedUrl).text | ||||
|         val mapped = mapper.readValue<ThenosLoadResponse>(response) | ||||
| 
 | ||||
|         val isShow = mapped.Metadata?.any { it?.type == "show" } == true | ||||
|         val metadata = mapped.Metadata?.getOrNull(0) ?: return null | ||||
|  |  | |||
|  | @ -2,6 +2,8 @@ package com.lagradost.cloudstream3.movieproviders | |||
| 
 | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
| import com.lagradost.cloudstream3.utils.SubtitleHelper | ||||
|  | @ -33,8 +35,8 @@ class TrailersToProvider : MainAPI() { | |||
|         get() = VPNStatus.MightBeNeeded | ||||
| 
 | ||||
|     override fun getMainPage(): HomePageResponse? { | ||||
|         val response = khttp.get(mainUrl) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(mainUrl).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val returnList = ArrayList<HomePageList>() | ||||
|         val docs = document.select("section.section > div.container") | ||||
|         for (doc in docs) { | ||||
|  | @ -76,8 +78,8 @@ class TrailersToProvider : MainAPI() { | |||
| 
 | ||||
|     override fun quickSearch(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/en/quick-search?q=$query" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val items = document.select("div.group-post-minimal > a.post-minimal") | ||||
|         if (items.isNullOrEmpty()) return ArrayList() | ||||
| 
 | ||||
|  | @ -104,8 +106,8 @@ class TrailersToProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/en/popular/movies-tvshows-collections?q=$query" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val items = document.select("div.col-lg-8 > article.list-item") | ||||
|         if (items.isNullOrEmpty()) return ArrayList() | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|  | @ -133,8 +135,8 @@ class TrailersToProvider : MainAPI() { | |||
|         data: String, | ||||
|         callback: (ExtractorLink) -> Unit, | ||||
|     ): Boolean { | ||||
|         val response = khttp.get(data) | ||||
|         val url = "<source src='(.*?)'".toRegex().find(response.text)?.groupValues?.get(1) | ||||
|         val response = get(data).text | ||||
|         val url = "<source src='(.*?)'".toRegex().find(response)?.groupValues?.get(1) | ||||
|         if (url != null) { | ||||
|             callback.invoke(ExtractorLink(this.name, this.name, url, mainUrl, Qualities.Unknown.value, false)) | ||||
|         } | ||||
|  | @ -144,8 +146,8 @@ class TrailersToProvider : MainAPI() { | |||
|     private fun loadSubs(url: String, subtitleCallback: (SubtitleFile) -> Unit) { | ||||
|         if (url.isEmpty()) return | ||||
| 
 | ||||
|         val response = khttp.get(fixUrl(url)) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(fixUrl(url)).text | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
|         val items = document.select("div.list-group > a.list-group-item") | ||||
|         for (item in items) { | ||||
|  | @ -181,8 +183,8 @@ class TrailersToProvider : MainAPI() { | |||
| 
 | ||||
|             return isSucc | ||||
|         } else if (url.contains("/episode/")) { | ||||
|             val response = khttp.get(url) | ||||
|             val document = Jsoup.parse(response.text) | ||||
|             val response = get(url).text | ||||
|             val document = Jsoup.parse(response) | ||||
|             // val qSub = document.select("subtitle-content") | ||||
|             val subUrl = document.select("subtitle-content")?.attr("data-url") ?: "" | ||||
| 
 | ||||
|  | @ -198,8 +200,8 @@ class TrailersToProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         var title = document?.selectFirst("h2.breadcrumbs-custom-title > a")?.text() ?: throw ErrorLoadingException("Service might be unavailable") | ||||
| 
 | ||||
|         val metaInfo = document.select("div.post-info-meta > ul.post-info-meta-list > li") | ||||
|  |  | |||
|  | @ -3,6 +3,10 @@ package com.lagradost.cloudstream3.movieproviders | |||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.fasterxml.jackson.module.kotlin.readValue | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.post | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.network.url | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import org.jsoup.Jsoup | ||||
|  | @ -21,8 +25,8 @@ class VMoveeProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/?s=$query" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val searchItems = document.select("div.search-page > div.result-item > article") | ||||
|         if (searchItems.size == 0) return ArrayList() | ||||
|         val returnValue = ArrayList<SearchResponse>() | ||||
|  | @ -75,24 +79,24 @@ class VMoveeProvider : MainAPI() { | |||
| 
 | ||||
|         val url = "$mainUrl/dashboard/admin-ajax.php" | ||||
|         val post = | ||||
|             khttp.post( | ||||
|             post( | ||||
|                 url, | ||||
|                 headers = mapOf("referer" to url), | ||||
|                 data = mapOf("action" to "doo_player_ajax", "post" to data, "nume" to "2", "type" to "movie") | ||||
|             ) | ||||
|             ).text | ||||
| 
 | ||||
|         val ajax = mapper.readValue<LoadLinksAjax>(post.text) | ||||
|         val ajax = mapper.readValue<LoadLinksAjax>(post) | ||||
|         var realUrl = ajax.embedUrl | ||||
|         if (realUrl.startsWith("//")) { | ||||
|             realUrl = "https:$realUrl" | ||||
|         } | ||||
| 
 | ||||
|         val request = khttp.get(realUrl) | ||||
|         val request = get(realUrl) | ||||
|         val prefix = "https://reeoov.tube/v/" | ||||
|         if (request.url.startsWith(prefix)) { | ||||
|             val apiUrl = "https://reeoov.tube/api/source/${request.url.removePrefix(prefix)}" | ||||
|             val apiResponse = khttp.post(apiUrl,headers = mapOf("Referer" to request.url),data = mapOf("r" to "https://www.vmovee.watch/", "d" to "reeoov.tube")) | ||||
|             val apiData = mapper.readValue<ReeoovAPI>(apiResponse.text) | ||||
|             val apiResponse = post(apiUrl,headers = mapOf("Referer" to request.url),data = mapOf("r" to "https://www.vmovee.watch/", "d" to "reeoov.tube")).text | ||||
|             val apiData = mapper.readValue<ReeoovAPI>(apiResponse) | ||||
|             for (d in apiData.data) { | ||||
|                 callback.invoke( | ||||
|                     ExtractorLink( | ||||
|  | @ -111,8 +115,8 @@ class VMoveeProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
|         val sheader = document.selectFirst("div.sheader") | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,22 +3,37 @@ package com.lagradost.cloudstream3.movieproviders | |||
| import org.jsoup.Jsoup | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.extractors.Vidstream | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.getQualityFromName | ||||
| import java.util.* | ||||
| import kotlin.collections.ArrayList | ||||
| 
 | ||||
| 
 | ||||
| /** Needs to inherit from MainAPI() to | ||||
|  * make the app know what functions to call | ||||
|  */ | ||||
| class VidEmbedProvider : MainAPI() { | ||||
|     // mainUrl is good to have as a holder for the url to make future changes easier. | ||||
|     override val mainUrl: String | ||||
|         get() = "https://vidembed.cc" | ||||
| 
 | ||||
|     // name is for how the provider will be named which is visible in the UI, no real rules for this. | ||||
|     override val name: String | ||||
|         get() = "VidEmbed" | ||||
| 
 | ||||
|     // hasQuickSearch defines if quickSearch() should be called, this is only when typing the searchbar | ||||
|     // gives results on the site instead of bringing you to another page. | ||||
|     // if hasQuickSearch is true and quickSearch() hasn't been overridden you will get errors. | ||||
|     // VidEmbed actually has quick search on their site, but the function wasn't implemented. | ||||
|     override val hasQuickSearch: Boolean | ||||
|         get() = false | ||||
| 
 | ||||
|     // If getMainPage() is functional, used to display the homepage in app, an optional, but highly encouraged endevour. | ||||
|     override val hasMainPage: Boolean | ||||
|         get() = true | ||||
| 
 | ||||
|     // Sometimes on sites the urls can be something like "/movie.html" which translates to "*full site url*/movie.html" in the browser | ||||
|     private fun fixUrl(url: String): String { | ||||
|         return if (url.startsWith("//")) { | ||||
|             "https:$url" | ||||
|  | @ -29,33 +44,49 @@ class VidEmbedProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // This is just extra metadata about what type of movies the provider has. | ||||
|     // Needed for search functionality. | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         get() = setOf(TvType.Anime, TvType.AnimeMovie, TvType.TvSeries, TvType.Movie) | ||||
| 
 | ||||
|     // Searching returns a SearchResponse, which can be one of the following: AnimeSearchResponse, MovieSearchResponse, TorrentSearchResponse, TvSeriesSearchResponse | ||||
|     // Each of the classes requires some different data, but always has some critical things like name, poster and url. | ||||
|     override fun search(query: String): ArrayList<SearchResponse> { | ||||
|         // Simply looking at devtools network is enough to spot a request like: | ||||
|         // https://vidembed.cc/search.html?keyword=neverland where neverland is the query, can be written as below. | ||||
|         val link = "$mainUrl/search.html?keyword=$query" | ||||
|         val html = khttp.get(link).text | ||||
|         val html = get(link).text | ||||
|         val soup = Jsoup.parse(html) | ||||
| 
 | ||||
|         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 = 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() | ||||
|             // 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() | ||||
| 
 | ||||
|             TvSeriesSearchResponse( | ||||
|                 // .trim() removes unwanted spaces in the start and end. | ||||
|                 if (!title.contains("Episode")) title else title.split("Episode")[0].trim(), | ||||
|                 href, | ||||
|                 this.name, | ||||
|                 TvType.TvSeries, | ||||
|                 poster, year, | ||||
|                 // You can't get the episodes from the search bar. | ||||
|                 null | ||||
|             ) | ||||
|         }) | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     // Load, like the name suggests loads the info page, where all the episodes and data usually is. | ||||
|     // Like search you should return either of: AnimeLoadResponse, MovieLoadResponse, TorrentLoadResponse, TvSeriesLoadResponse. | ||||
|     override fun load(url: String): LoadResponse? { | ||||
|         val html = khttp.get(url).text | ||||
|         // Gets the url returned from searching. | ||||
|         val html = get(url).text | ||||
|         val soup = Jsoup.parse(html) | ||||
| 
 | ||||
|         var title = soup.selectFirst("h1,h2,h3").text() | ||||
|  | @ -89,8 +120,10 @@ class VidEmbedProvider : MainAPI() { | |||
|                 epDate | ||||
|             ) | ||||
|         }.reversed() | ||||
|         val year = if (episodes.isNotEmpty()) episodes.first().date?.split("-")?.get(0)?.toIntOrNull() else null | ||||
| 
 | ||||
|         val year = episodes.first().date?.split("-")?.get(0)?.toIntOrNull() | ||||
| 
 | ||||
|         // Make sure to get the type right to display the correct UI. | ||||
|         val tvType = if (episodes.size == 1 && episodes[0].name == title) TvType.Movie else TvType.TvSeries | ||||
| 
 | ||||
|         return when (tvType) { | ||||
|  | @ -127,6 +160,8 @@ class VidEmbedProvider : MainAPI() { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // This loads the homepage, which is basically a collection of search results with labels. | ||||
|     // Optional function, but make sure to enable hasMainPage if you program this. | ||||
|     override fun getMainPage(): HomePageResponse? { | ||||
|         val urls = listOf( | ||||
|             mainUrl, | ||||
|  | @ -136,10 +171,12 @@ class VidEmbedProvider : MainAPI() { | |||
|             "$mainUrl/cinema-movies" | ||||
|         ) | ||||
|         val homePageList = ArrayList<HomePageList>() | ||||
|         // .pmap {} is used to fetch the different pages in parallel | ||||
|         urls.pmap { url -> | ||||
|             val response = khttp.get(url, timeout = 20.0) | ||||
|             val document = Jsoup.parse(response.text) | ||||
|             val response = get(url, timeout = 20).text | ||||
|             val document = Jsoup.parse(response) | ||||
|             document.select("div.main-inner")?.forEach { | ||||
|                 // Always trim your text unless you want the risk of spaces at the start or end. | ||||
|                 val title = it.select(".widget-title").text().trim() | ||||
|                 val elements = it.select(".video-block").map { | ||||
|                     val link = fixUrl(it.select("a").attr("href")) | ||||
|  | @ -182,13 +219,21 @@ class VidEmbedProvider : MainAPI() { | |||
|         return HomePageResponse(homePageList) | ||||
|     } | ||||
| 
 | ||||
|     // loadLinks gets the raw .mp4 or .m3u8 urls from the data parameter in the episodes class generated in load() | ||||
|     // See TvSeriesEpisode(...) in this provider. | ||||
|     // The data are usually links, but can be any other string to help aid loading the links. | ||||
|     override fun loadLinks( | ||||
|         data: String, | ||||
|         isCasting: Boolean, | ||||
|         // These callbacks are functions you should call when you get a link to a subtitle file or media file. | ||||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ): Boolean { | ||||
|         val iframeLink = Jsoup.parse(khttp.get(data).text).selectFirst("iframe")?.attr("src") ?: return false | ||||
|         // "?: return" is a very useful statement which returns if the iframe link isn't found. | ||||
|         val iframeLink = Jsoup.parse(get(data).text).selectFirst("iframe")?.attr("src") ?: return false | ||||
| 
 | ||||
|         // In this case the video player is a vidstream clone and can be handled by the vidstream extractor. | ||||
|         // This case is a both unorthodox and you normally do not call extractors as they detect the url returned and does the rest. | ||||
|         val vidstreamObject = Vidstream("https://vidembed.cc") | ||||
|         // https://vidembed.cc/streaming.php?id=MzUwNTY2&... -> MzUwNTY2 | ||||
|         val id = Regex("""id=([^&]*)""").find(iframeLink)?.groupValues?.get(1) | ||||
|  | @ -197,7 +242,7 @@ class VidEmbedProvider : MainAPI() { | |||
|             vidstreamObject.getUrl(id, isCasting, callback) | ||||
|         } | ||||
| 
 | ||||
|         val html = khttp.get(fixUrl(iframeLink)).text | ||||
|         val html = get(fixUrl(iframeLink)).text | ||||
|         val soup = Jsoup.parse(html) | ||||
| 
 | ||||
|         val servers = soup.select(".list-server-items > .linkserver").mapNotNull { li -> | ||||
|  | @ -208,12 +253,16 @@ class VidEmbedProvider : MainAPI() { | |||
|             } | ||||
|         } | ||||
|         servers.forEach { | ||||
|             // When checking strings make sure to make them lowercase and trimmed because edgecases like "beta server " wouldn't work otherwise. | ||||
|             if (it.first.toLowerCase(Locale.ROOT).trim() == "beta server") { | ||||
|                 // Group 1: link, Group 2: Label | ||||
|                 // Regex can be used to effectively parse small amounts of json without bothering with writing a json class. | ||||
|                 val sourceRegex = Regex("""sources:[\W\w]*?file:\s*["'](.*?)["'][\W\w]*?label:\s*["'](.*?)["']""") | ||||
|                 val trackRegex = Regex("""tracks:[\W\w]*?file:\s*["'](.*?)["'][\W\w]*?label:\s*["'](.*?)["']""") | ||||
| 
 | ||||
|                 val html = khttp.get(it.second, headers = mapOf("referer" to iframeLink)).text | ||||
|                 // Having a referer is often required. It's a basic security check most providers have. | ||||
|                 // Try to replicate what your browser does. | ||||
|                 val html = get(it.second, headers = mapOf("referer" to iframeLink)).text | ||||
|                 sourceRegex.findAll(html).forEach { match -> | ||||
|                     callback.invoke( | ||||
|                         ExtractorLink( | ||||
|  | @ -221,8 +270,11 @@ class VidEmbedProvider : MainAPI() { | |||
|                             match.groupValues.getOrNull(2)?.let { "${this.name} $it" } ?: this.name, | ||||
|                             match.groupValues[1], | ||||
|                             it.second, | ||||
|                             // Useful function to turn something like "1080p" to an app quality. | ||||
|                             getQualityFromName(match.groupValues.getOrNull(2) ?: ""), | ||||
|                             // Kinda risky | ||||
|                             // isM3u8 makes the player pick the correct extractor for the source. | ||||
|                             // If isM3u8 is wrong the player will error on that source. | ||||
|                             match.groupValues[1].endsWith(".m3u8"), | ||||
|                         ) | ||||
|                     ) | ||||
|  | @ -240,4 +292,4 @@ class VidEmbedProvider : MainAPI() { | |||
| 
 | ||||
|         return true | ||||
|     } | ||||
| } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										154
									
								
								app/src/main/java/com/lagradost/cloudstream3/network/Requests.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								app/src/main/java/com/lagradost/cloudstream3/network/Requests.kt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,154 @@ | |||
| package com.lagradost.cloudstream3.network | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.USER_AGENT | ||||
| import okhttp3.* | ||||
| import okhttp3.Headers.Companion.toHeaders | ||||
| import okio.Buffer | ||||
| import java.net.URI | ||||
| import java.util.* | ||||
| import java.util.concurrent.TimeUnit | ||||
| 
 | ||||
| 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() | ||||
|     } | ||||
| 
 | ||||
| val Response.cookies: Map<String, String> | ||||
|     get() { | ||||
|         val cookieList = | ||||
|             this.headers.filter { it.first.toLowerCase(Locale.ROOT) == "set-cookie" }.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() | ||||
|     } | ||||
| 
 | ||||
| fun getData(data: Map<String, String>): RequestBody { | ||||
|     val builder = FormBody.Builder() | ||||
|     data.forEach { | ||||
|         builder.add(it.key, it.value) | ||||
|     } | ||||
|     return builder.build() | ||||
| } | ||||
| 
 | ||||
| // https://github.com, id=test -> https://github.com?id=test | ||||
| 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 | ||||
| fun addParamsToUrl(url: String, params: Map<String, String>): String { | ||||
|     var appendedUrl = url | ||||
|     params.forEach { | ||||
|         appendedUrl = appendUri(appendedUrl, "${it.key}=${it.value}") | ||||
|     } | ||||
|     return appendedUrl | ||||
| } | ||||
| 
 | ||||
| fun getCache(cacheTime: Int, cacheUnit: TimeUnit): CacheControl { | ||||
|     return CacheControl.Builder().maxAge(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() | ||||
|     return (DEFAULT_COOKIES + DEFAULT_HEADERS + cookie + headers + refererMap).toHeaders() | ||||
| } | ||||
| 
 | ||||
| fun get( | ||||
|     url: String, | ||||
|     headers: Map<String, String> = mapOf(), | ||||
|     referer: String? = null, | ||||
|     params: Map<String, String> = mapOf(), | ||||
|     cookies: Map<String, String> = mapOf(), | ||||
|     allowRedirects: Boolean = true, | ||||
|     cacheTime: Int = DEFAULT_TIME, | ||||
|     cacheUnit: TimeUnit = DEFAULT_TIME_UNIT, | ||||
|     timeout: Long = 0L | ||||
| ): Response { | ||||
|     val client = OkHttpClient().newBuilder() | ||||
|         .followRedirects(allowRedirects) | ||||
|         .followSslRedirects(allowRedirects) | ||||
|         .callTimeout(timeout, TimeUnit.SECONDS) | ||||
|         .build() | ||||
|     val request = getRequestCreator(url, headers, referer, params, cookies, cacheTime, cacheUnit) | ||||
|     return client.newCall(request).execute() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| fun post( | ||||
|     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 | ||||
| ): Response { | ||||
|     val client = OkHttpClient().newBuilder() | ||||
|         .followRedirects(allowRedirects) | ||||
|         .followSslRedirects(allowRedirects) | ||||
|         .callTimeout(timeout, TimeUnit.SECONDS) | ||||
|         .build() | ||||
|     val request = postRequestCreator(url, headers, referer, params, cookies, data, cacheTime, cacheUnit) | ||||
|     return client.newCall(request).execute() | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| fun getRequestCreator( | ||||
|     url: String, | ||||
|     headers: Map<String, String>, | ||||
|     referer: String?, | ||||
|     params: Map<String, String>, | ||||
|     cookies: Map<String, String>, | ||||
|     cacheTime: Int, | ||||
|     cacheUnit: TimeUnit | ||||
| ): Request { | ||||
|     return Request.Builder() | ||||
|         .url(addParamsToUrl(url, params)) | ||||
|         .cacheControl(getCache(cacheTime, cacheUnit)) | ||||
|         .headers(getHeaders(headers, referer, cookies)) | ||||
|         .build() | ||||
| } | ||||
| 
 | ||||
| fun postRequestCreator( | ||||
|     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)) | ||||
|         .post(getData(data)) | ||||
|         .build() | ||||
| } | ||||
|  | @ -1,6 +1,8 @@ | |||
| package com.lagradost.cloudstream3.torrentproviders | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import com.lagradost.cloudstream3.utils.ExtractorLink | ||||
| import com.lagradost.cloudstream3.utils.Qualities | ||||
| import org.jsoup.Jsoup | ||||
|  | @ -23,8 +25,8 @@ class NyaaProvider : MainAPI() { | |||
| 
 | ||||
|     override fun search(query: String): List<SearchResponse> { | ||||
|         val url = "$mainUrl/?f=0&c=0_0&q=$query&s=seeders&o=desc" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
| 
 | ||||
|         val returnValues = ArrayList<SearchResponse>() | ||||
|                 val elements = document.select("table > tbody > tr") | ||||
|  | @ -43,8 +45,8 @@ class NyaaProvider : MainAPI() { | |||
|     } | ||||
| 
 | ||||
|     override fun load(url: String): LoadResponse { | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = 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 downloadLinks = document.select("div.panel-footer > a") | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| package com.lagradost.cloudstream3.utils | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import org.jsoup.Jsoup | ||||
| import java.util.* | ||||
| import kotlin.collections.HashMap | ||||
|  | @ -16,8 +18,8 @@ object FillerEpisodeCheck { | |||
|     private fun getFillerList(): Boolean { | ||||
|         if (list != null) return true | ||||
|         try { | ||||
|             val result = khttp.get("$MAIN_URL/shows") | ||||
|             val documented = Jsoup.parse(result.text) | ||||
|             val result = get("$MAIN_URL/shows").text | ||||
|             val documented = Jsoup.parse(result) | ||||
|             val localHTMLList = documented.select("div#ShowList > div.Group > ul > li > a") | ||||
|             val localList = HashMap<String, String>() | ||||
|             for (i in localHTMLList) { | ||||
|  | @ -71,8 +73,8 @@ object FillerEpisodeCheck { | |||
|             val realQuery = fixName(query.replace(blackListRegex, "")).replace("shippuuden", "shippuden") | ||||
|             if (!localList.containsKey(realQuery)) return null | ||||
|             val href = localList[realQuery]?.replace(MAIN_URL, "") ?: return null // JUST IN CASE | ||||
|             val result = khttp.get("$MAIN_URL$href") | ||||
|             val documented = Jsoup.parse(result.text) ?: return null | ||||
|             val result = get("$MAIN_URL$href").text | ||||
|             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" | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ class HttpSession { | |||
|         allowRedirects: Boolean? = null, | ||||
|         stream: Boolean = false, files: List<FileLike> = listOf(), | ||||
|     ): Response { | ||||
|         val res = khttp.get( | ||||
|         val res = get( | ||||
|             url, headers, params, | ||||
|             data, json, auth, | ||||
|             mergeCookies(sessionCookies, cookies), timeout, | ||||
|  | @ -62,7 +62,7 @@ class HttpSession { | |||
|         allowRedirects: Boolean? = null, | ||||
|         stream: Boolean = false, files: List<FileLike> = listOf() | ||||
|     ): Response { | ||||
|         val res = khttp.post( | ||||
|         val res = post( | ||||
|             url, headers, params, | ||||
|             data, json, auth, | ||||
|             mergeCookies(sessionCookies, cookies), timeout, | ||||
|  |  | |||
|  | @ -23,6 +23,8 @@ import com.lagradost.cloudstream3.MainActivity.Companion.showToast | |||
| import com.lagradost.cloudstream3.R | ||||
| import com.lagradost.cloudstream3.mvvm.logError | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import java.io.File | ||||
| import kotlin.concurrent.thread | ||||
| 
 | ||||
|  | @ -82,7 +84,7 @@ class InAppUpdater { | |||
|             val url = "https://api.github.com/repos/LagradOst/CloudStream-3/releases" | ||||
|             val headers = mapOf("Accept" to "application/vnd.github.v3+json") | ||||
|             val response = | ||||
|                 mapper.readValue<List<GithubRelease>>(khttp.get(url, headers = headers).text) | ||||
|                 mapper.readValue<List<GithubRelease>>(get(url, headers = headers).text) | ||||
| 
 | ||||
|             val versionRegex = Regex("""(.*?((\d+)\.(\d+)\.(\d+))\.apk)""") | ||||
|             val versionRegexLocal = Regex("""(.*?((\d+)\.(\d+)\.(\d+)).*)""") | ||||
|  | @ -138,7 +140,7 @@ class InAppUpdater { | |||
|             val releaseUrl = "https://api.github.com/repos/LagradOst/CloudStream-3/releases" | ||||
|             val headers = mapOf("Accept" to "application/vnd.github.v3+json") | ||||
|             val response = | ||||
|                 mapper.readValue<List<GithubRelease>>(khttp.get(releaseUrl, headers = headers).text) | ||||
|                 mapper.readValue<List<GithubRelease>>(get(releaseUrl, headers = headers).text) | ||||
| 
 | ||||
|             val found = | ||||
|                 response.lastOrNull { rel -> | ||||
|  | @ -147,7 +149,7 @@ class InAppUpdater { | |||
|             val foundAsset = found?.assets?.getOrNull(0) | ||||
| 
 | ||||
|             val tagResponse = | ||||
|                 mapper.readValue<GithubTag>(khttp.get(tagUrl, headers = headers).text) | ||||
|                 mapper.readValue<GithubTag>(get(tagUrl, headers = headers).text) | ||||
| 
 | ||||
|             val shouldUpdate = (getString(R.string.prerelease_commit_hash) != tagResponse.github_object.sha) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,8 @@ | |||
| package com.lagradost.cloudstream3.utils | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.mvvm.logError | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import javax.crypto.Cipher | ||||
| import javax.crypto.spec.IvParameterSpec | ||||
| import javax.crypto.spec.SecretKeySpec | ||||
|  | @ -79,9 +81,9 @@ class M3u8Helper { | |||
|     fun m3u8Generation(m3u8: M3u8Stream): List<M3u8Stream> { | ||||
|         val generate = sequence { | ||||
|             val m3u8Parent = getParentLink(m3u8.streamUrl) | ||||
|             val response = khttp.get(m3u8.streamUrl, headers = m3u8.headers) | ||||
|             val response = get(m3u8.streamUrl, headers = m3u8.headers).text | ||||
| 
 | ||||
|             for (match in QUALITY_REGEX.findAll(response.text)) { | ||||
|             for (match in QUALITY_REGEX.findAll(response)) { | ||||
|                 var (quality, m3u8Link, m3u8Link2) = match.destructured | ||||
|                 if (m3u8Link.isNullOrEmpty()) m3u8Link = m3u8Link2 | ||||
|                 if (absoluteExtensionDetermination(m3u8Link) == "m3u8") { | ||||
|  | @ -134,18 +136,17 @@ class M3u8Helper { | |||
| 
 | ||||
|         val secondSelection = selectBest(streams.ifEmpty { listOf(selected) }) | ||||
|         if (secondSelection != null) { | ||||
|             val m3u8Response = khttp.get(secondSelection.streamUrl, headers = headers) | ||||
|             val m3u8Data = m3u8Response.text | ||||
|             val m3u8Response = get(secondSelection.streamUrl, headers = headers).text | ||||
| 
 | ||||
|             var encryptionUri: String? = null | ||||
|             var encryptionIv = byteArrayOf() | ||||
|             var encryptionData = byteArrayOf() | ||||
| 
 | ||||
|             val encryptionState = isEncrypted(m3u8Data) | ||||
|             val encryptionState = isEncrypted(m3u8Response) | ||||
| 
 | ||||
|             if (encryptionState) { | ||||
|                 val match = | ||||
|                     ENCRYPTION_URL_IV_REGEX.find(m3u8Data)!!.destructured  // its safe to assume that its not going to be null | ||||
|                     ENCRYPTION_URL_IV_REGEX.find(m3u8Response)!!.destructured  // its safe to assume that its not going to be null | ||||
|                 encryptionUri = match.component2() | ||||
| 
 | ||||
|                 if (isNotCompleteUrl(encryptionUri)) { | ||||
|  | @ -153,11 +154,11 @@ class M3u8Helper { | |||
|                 } | ||||
| 
 | ||||
|                 encryptionIv = match.component3().toByteArray() | ||||
|                 val encryptionKeyResponse = khttp.get(encryptionUri, headers = headers) | ||||
|                 encryptionData = encryptionKeyResponse.content | ||||
|                 val encryptionKeyResponse = get(encryptionUri, headers = headers) | ||||
|                 encryptionData = encryptionKeyResponse.body?.bytes() ?: byteArrayOf() | ||||
|             } | ||||
| 
 | ||||
|             val allTs = TS_EXTENSION_REGEX.findAll(m3u8Data) | ||||
|             val allTs = TS_EXTENSION_REGEX.findAll(m3u8Response) | ||||
|             val allTsList = allTs.toList() | ||||
|             val totalTs = allTsList.size | ||||
|             if (totalTs == 0) { | ||||
|  | @ -176,8 +177,8 @@ class M3u8Helper { | |||
| 
 | ||||
|                     while (lastYield != c) { | ||||
|                         try { | ||||
|                             val tsResponse = khttp.get(url, headers = headers) | ||||
|                             var tsData = tsResponse.content | ||||
|                             val tsResponse = get(url, headers = headers) | ||||
|                             var tsData = tsResponse.body?.bytes() ?: byteArrayOf() | ||||
| 
 | ||||
|                             if (encryptionState) { | ||||
|                                 tsData = getDecrypter(encryptionData, tsData, encryptionIv) | ||||
|  |  | |||
|  | @ -1,5 +1,7 @@ | |||
| package com.lagradost.cloudstream3.utils | ||||
| 
 | ||||
| import com.lagradost.cloudstream3.network.get | ||||
| import com.lagradost.cloudstream3.network.text | ||||
| import org.jsoup.Jsoup | ||||
| import java.util.* | ||||
| 
 | ||||
|  | @ -16,8 +18,8 @@ object SubtitleHelper { | |||
| 
 | ||||
|     fun createISO() { | ||||
|         val url = "https://infogalactic.com/info/List_of_ISO_639-1_codes" | ||||
|         val response = khttp.get(url) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|         val response = get(url).text | ||||
|         val document = Jsoup.parse(response) | ||||
|         val headers = document.select("table.wikitable > tbody > tr") | ||||
| 
 | ||||
|         var text = "listOf(\n" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue