Changed to okhttp from khttp (#113)

* added okhttp

fuck it merging it
This commit is contained in:
LagradOst 2021-09-29 22:03:58 +02:00 committed by GitHub
parent 1948a2c2d9
commit 3a78f41aad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 547 additions and 246 deletions

View file

@ -132,4 +132,7 @@ dependencies {
// Downloading // Downloading
implementation "androidx.work:work-runtime:2.7.0-beta01" implementation "androidx.work:work-runtime:2.7.0-beta01"
implementation "androidx.work:work-runtime-ktx:2.7.0-beta01" implementation "androidx.work:work-runtime-ktx:2.7.0-beta01"
// Networking
implementation "com.squareup.okhttp3:okhttp:4.9.0"
} }

View file

@ -5,6 +5,7 @@ import android.content.Context
import android.widget.Toast import android.widget.Toast
import com.google.auto.service.AutoService import com.google.auto.service.AutoService
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.network.post
import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread import com.lagradost.cloudstream3.utils.Coroutines.runOnMainThread
import org.acra.ReportField import org.acra.ReportField
import org.acra.config.CoreConfiguration import org.acra.config.CoreConfiguration
@ -27,7 +28,7 @@ class CustomReportSender : ReportSender {
thread { // to not run it on main thread thread { // to not run it on main thread
normalSafeApiCall { normalSafeApiCall {
val post = khttp.post(url, data = data) val post = post(url, data = data)
println("Report response: $post") println("Report response: $post")
} }
} }

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3.animeproviders package com.lagradost.cloudstream3.animeproviders
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.extractorApis import com.lagradost.cloudstream3.utils.extractorApis
@ -36,7 +38,7 @@ class AnimeFlickProvider : MainAPI() {
override fun search(query: String): ArrayList<SearchResponse> { override fun search(query: String): ArrayList<SearchResponse> {
val link = "https://animeflick.net/search.php?search=$query" 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) val doc = Jsoup.parse(html)
return ArrayList(doc.select(".row.mt-2").map { return ArrayList(doc.select(".row.mt-2").map {
@ -59,7 +61,7 @@ class AnimeFlickProvider : MainAPI() {
} }
override fun load(url: String): LoadResponse { override fun load(url: String): LoadResponse {
val html = khttp.get(url).text val html = get(url).text
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
val poster = mainUrl + doc.selectFirst("img.rounded").attr("src") val poster = mainUrl + doc.selectFirst("img.rounded").attr("src")
@ -101,7 +103,7 @@ class AnimeFlickProvider : MainAPI() {
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val html = khttp.get(data).text val html = get(data).text
val episodeRegex = Regex("""(https://.*?\.mp4)""") val episodeRegex = Regex("""(https://.*?\.mp4)""")
val links = episodeRegex.findAll(html).map { val links = episodeRegex.findAll(html).map {

View file

@ -1,12 +1,13 @@
package com.lagradost.cloudstream3.animeproviders package com.lagradost.cloudstream3.animeproviders
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import khttp.structures.cookie.CookieJar
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.network.*
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import okhttp3.Response
import org.jsoup.Jsoup import org.jsoup.Jsoup
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -15,7 +16,7 @@ class AnimePaheProvider : MainAPI() {
companion object { companion object {
const val MAIN_URL = "https://animepahe.com" const val MAIN_URL = "https://animepahe.com"
var cookies = CookieJar() var cookies: Map<String, String> = mapOf()
private fun getType(t: String): TvType { private fun getType(t: String): TvType {
return if (t.contains("OVA") || t.contains("Special")) TvType.ONA return if (t.contains("OVA") || t.contains("Special")) TvType.ONA
else if (t.contains("Movie")) TvType.AnimeMovie else if (t.contains("Movie")) TvType.AnimeMovie
@ -23,9 +24,9 @@ class AnimePaheProvider : MainAPI() {
} }
fun generateSession(): Boolean { fun generateSession(): Boolean {
if (cookies.entries.size != 0) return true if (cookies.isNotEmpty()) return true
return try { return try {
val response = khttp.get("$MAIN_URL/") val response = get("$MAIN_URL/")
cookies = response.cookies cookies = response.cookies
true true
} catch (e: Exception) { } catch (e: Exception) {
@ -82,8 +83,8 @@ class AnimePaheProvider : MainAPI() {
val items = ArrayList<HomePageList>() val items = ArrayList<HomePageList>()
for (i in urls) { for (i in urls) {
try { try {
val response = khttp.get(i.first) val response = get(i.first).text
val episodes = mapper.readValue<AnimePaheLatestReleases>(response.text).data.map { val episodes = mapper.readValue<AnimePaheLatestReleases>(response).data.map {
AnimeSearchResponse( AnimeSearchResponse(
it.animeTitle, it.animeTitle,
@ -132,8 +133,8 @@ class AnimePaheProvider : MainAPI() {
val url = "$mainUrl/api?m=search&l=8&q=$title" val url = "$mainUrl/api?m=search&l=8&q=$title"
val headers = mapOf("referer" to "$mainUrl/") val headers = mapOf("referer" to "$mainUrl/")
val req = khttp.get(url, headers = headers) val req = get(url, headers = headers).text
val data = req.let { mapper.readValue<AnimePaheSearch>(it.text) } val data = req.let { mapper.readValue<AnimePaheSearch>(it) }
for (anime in data.data) { for (anime in data.data) {
if (anime.id == animeId) { if (anime.id == animeId) {
return "https://animepahe.com/anime/${anime.session}" 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 url = "$mainUrl/api?m=search&l=8&q=$query"
val headers = mapOf("referer" to "$mainUrl/") val headers = mapOf("referer" to "$mainUrl/")
val req = khttp.get(url, headers = headers) val req = get(url, headers = headers).text
val data = req.let { mapper.readValue<AnimePaheSearch>(it.text) } val data = req.let { mapper.readValue<AnimePaheSearch>(it) }
return ArrayList(data.data.map { return ArrayList(data.data.map {
AnimeSearchResponse( AnimeSearchResponse(
@ -198,8 +199,8 @@ class AnimePaheProvider : MainAPI() {
val uri = "$mainUrl/api?m=release&id=$id&sort=episode_asc&page=1" val uri = "$mainUrl/api?m=release&id=$id&sort=episode_asc&page=1"
val headers = mapOf("referer" to "$mainUrl/") val headers = mapOf("referer" to "$mainUrl/")
val req = khttp.get(uri, headers = headers) val req = get(uri, headers = headers).text
val data = req.let { mapper.readValue<AnimePaheAnimeData>(it.text) } val data = req.let { mapper.readValue<AnimePaheAnimeData>(it) }
val lastPage = data.lastPage val lastPage = data.lastPage
val perPage = data.perPage val perPage = data.perPage
@ -257,7 +258,7 @@ class AnimePaheProvider : MainAPI() {
val (animeId, animeTitle) = regex.find(url)!!.destructured val (animeId, animeTitle) = regex.find(url)!!.destructured
val link = getAnimeByIdAndTitle(animeTitle, animeId.toInt())!! val link = getAnimeByIdAndTitle(animeTitle, animeId.toInt())!!
val html = khttp.get(link).text val html = get(link).text
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
val japTitle = doc.selectFirst("h2.japanese")?.text() val japTitle = doc.selectFirst("h2.japanese")?.text()
@ -454,17 +455,17 @@ class AnimePaheProvider : MainAPI() {
} }
var responseCode = 302 var responseCode = 302
var adflyContent: khttp.responses.Response? = null var adflyContent: Response? = null
var tries = 0 var tries = 0
while (responseCode != 200 && tries < 20) { while (responseCode != 200 && tries < 20) {
adflyContent = khttp.get( adflyContent = get(
khttp.get(adflyUri, cookies = cookies, allowRedirects = false).headers.getValue("location"), get(adflyUri, cookies = cookies, allowRedirects = false).url,
cookies = cookies, cookies = cookies,
allowRedirects = false allowRedirects = false
) )
cookies.putAll(adflyContent.cookies.toMap()) cookies = cookies + adflyContent.cookies
responseCode = adflyContent.statusCode responseCode = adflyContent.code
++tries ++tries
} }
if (tries > 19) { if (tries > 19) {
@ -475,33 +476,33 @@ class AnimePaheProvider : MainAPI() {
private fun getStreamUrlFromKwik(adflyUri: String): String { private fun getStreamUrlFromKwik(adflyUri: String): String {
val fContent = val fContent =
khttp.get(bypassAdfly(adflyUri), headers = mapOf("referer" to "https://kwik.cx/"), cookies = cookies) get(bypassAdfly(adflyUri), headers = mapOf("referer" to "https://kwik.cx/"), cookies = cookies)
cookies.putAll(fContent.cookies.toMap()) cookies = cookies + fContent.cookies
val (fullString, key, v1, v2) = KWIK_PARAMS_RE.find(fContent.text)!!.destructured val (fullString, key, v1, v2) = KWIK_PARAMS_RE.find(fContent.text)!!.destructured
val decrypted = decrypt(fullString, key, v1.toInt(), v2.toInt()) val decrypted = decrypt(fullString, key, v1.toInt(), v2.toInt())
val uri = KWIK_D_URL.find(decrypted)!!.destructured.component1() val uri = KWIK_D_URL.find(decrypted)!!.destructured.component1()
val tok = KWIK_D_TOKEN.find(decrypted)!!.destructured.component1() val tok = KWIK_D_TOKEN.find(decrypted)!!.destructured.component1()
var content: khttp.responses.Response? = null var content: Response? = null
var code = 419 var code = 419
var tries = 0 var tries = 0
while (code != 302 && tries < 20) { while (code != 302 && tries < 20) {
content = khttp.post( content = post(
uri, uri,
allowRedirects = false, allowRedirects = false,
data = mapOf("_token" to tok), data = mapOf("_token" to tok),
headers = mapOf("referer" to fContent.url), 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 ++tries
} }
if (tries > 19) { if (tries > 19) {
throw Exception("Failed to extract the stream uri from kwik.") 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> { private fun extractVideoLinks(episodeLink: String): List<ExtractorLink> {
@ -516,8 +517,8 @@ class AnimePaheProvider : MainAPI() {
link = link.replace(regex, "") link = link.replace(regex, "")
val req = khttp.get(link, headers = headers) val req = get(link, headers = headers).text
val jsonResponse = req.let { mapper.readValue<AnimePaheAnimeData>(it.text) } val jsonResponse = req.let { mapper.readValue<AnimePaheAnimeData>(it) }
val ep = ((jsonResponse.data.map { val ep = ((jsonResponse.data.map {
if (it.episode == episodeNum) { if (it.episode == episodeNum) {
it it
@ -527,8 +528,8 @@ class AnimePaheProvider : MainAPI() {
}).filterNotNull())[0] }).filterNotNull())[0]
link = "$mainUrl/api?m=links&id=${ep.animeId}&session=${ep.session}&p=kwik" link = "$mainUrl/api?m=links&id=${ep.animeId}&session=${ep.session}&p=kwik"
} }
val req = khttp.get(link, headers = headers) val req = get(link, headers = headers).text
val data = mapper.readValue<AnimePaheEpisodeLoadLinks>(req.text) val data = mapper.readValue<AnimePaheEpisodeLoadLinks>(req)
val qualities = ArrayList<ExtractorLink>() val qualities = ArrayList<ExtractorLink>()

View file

@ -5,6 +5,8 @@ import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.unixTime import com.lagradost.cloudstream3.APIHolder.unixTime
import com.lagradost.cloudstream3.APIHolder.unixTimeMS 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.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -61,8 +63,8 @@ class DubbedAnimeProvider : MainAPI() {
) )
private fun parseDocumentTrending(url: String): List<SearchResponse> { private fun parseDocumentTrending(url: String): List<SearchResponse> {
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
return document.select("li > a").map { return document.select("li > a").map {
val href = fixUrl(it.attr("href")) val href = fixUrl(it.attr("href"))
val title = it.selectFirst("> div > div.cittx").text() val title = it.selectFirst("> div > div.cittx").text()
@ -83,8 +85,8 @@ class DubbedAnimeProvider : MainAPI() {
} }
private fun parseDocument(url: String, trimEpisode: Boolean = false): List<SearchResponse> { private fun parseDocument(url: String, trimEpisode: Boolean = false): List<SearchResponse> {
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
return document.select("a.grid__link").map { return document.select("a.grid__link").map {
val href = fixUrl(it.attr("href")) val href = fixUrl(it.attr("href"))
val title = it.selectFirst("> div.gridtitlek").text() val title = it.selectFirst("> div.gridtitlek").text()
@ -124,10 +126,8 @@ class DubbedAnimeProvider : MainAPI() {
private fun getAnimeEpisode(slug: String, isMovie: Boolean): EpisodeInfo { private fun getAnimeEpisode(slug: String, isMovie: Boolean): EpisodeInfo {
val url = val url =
mainUrl + (if (isMovie) "/movies/jsonMovie" else "/xz/v3/jsonEpi") + ".php?slug=$slug&_=$unixTime" mainUrl + (if (isMovie) "/movies/jsonMovie" else "/xz/v3/jsonEpi") + ".php?slug=$slug&_=$unixTime"
val response = khttp.get(url) val response = get(url).text
println(response.text) val mapped = mapper.readValue<QueryEpisodeResultRoot>(response)
val mapped = mapper.readValue<QueryEpisodeResultRoot>(response.text)
return mapped.result.anime.first() return mapped.result.anime.first()
} }
@ -142,8 +142,8 @@ class DubbedAnimeProvider : MainAPI() {
override fun quickSearch(query: String): List<SearchResponse> { override fun quickSearch(query: String): List<SearchResponse> {
val url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=$unixTime" val url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=$unixTime"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val items = document.select("div.grid__item > a") val items = document.select("div.grid__item > a")
if (items.isEmpty()) return ArrayList() if (items.isEmpty()) return ArrayList()
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
@ -177,8 +177,8 @@ class DubbedAnimeProvider : MainAPI() {
override fun search(query: String): List<SearchResponse> { override fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/search/$query" val url = "$mainUrl/search/$query"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val items = document.select("div.resultinner > a.resulta") val items = document.select("div.resultinner > a.resulta")
if (items.isEmpty()) return ArrayList() if (items.isEmpty()) return ArrayList()
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
@ -229,9 +229,8 @@ class DubbedAnimeProvider : MainAPI() {
}.toList()) }.toList())
for (hl in hls) { for (hl in hls) {
try { try {
val sources = khttp.get("$mainUrl/xz/api/playeri.php?url=$hl&_=$unixTime") val sources = get("$mainUrl/xz/api/playeri.php?url=$hl&_=$unixTime").text
val txt = sources.text val find = "src=\"(.*?)\".*?label=\"(.*?)\"".toRegex().find(sources)
val find = "src=\"(.*?)\".*?label=\"(.*?)\"".toRegex().find(txt)
if (find != null) { if (find != null) {
val quality = find.groupValues[2] val quality = find.groupValues[2]
callback.invoke( callback.invoke(
@ -268,8 +267,8 @@ class DubbedAnimeProvider : MainAPI() {
null null
) )
} else { } else {
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val title = document.selectFirst("h4").text() val title = document.selectFirst("h4").text()
val descriptHeader = document.selectFirst("div.animeDescript") val descriptHeader = document.selectFirst("div.animeDescript")
val descript = descriptHeader.selectFirst("> p").text() val descript = descriptHeader.selectFirst("> p").text()

View file

@ -1,6 +1,9 @@
package com.lagradost.cloudstream3.animeproviders package com.lagradost.cloudstream3.animeproviders
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.extractorApis import com.lagradost.cloudstream3.utils.extractorApis
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
@ -67,7 +70,7 @@ class GogoanimeProvider : MainAPI() {
for (i in urls) { for (i in urls) {
try { try {
val params = mapOf("page" to "1", "type" to i.first) 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 { items.add(HomePageList(i.second, (parseRegex.findAll(html).map {
val (link, epNum, title, poster) = it.destructured val (link, epNum, title, poster) = it.destructured
AnimeSearchResponse( AnimeSearchResponse(
@ -93,7 +96,7 @@ class GogoanimeProvider : MainAPI() {
override fun search(query: String): ArrayList<SearchResponse> { override fun search(query: String): ArrayList<SearchResponse> {
val link = "$mainUrl/search.html?keyword=$query" val link = "$mainUrl/search.html?keyword=$query"
val html = khttp.get(link).text val html = get(link).text
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
val episodes = doc.select(""".last_episodes li""").map { val episodes = doc.select(""".last_episodes li""").map {
@ -126,7 +129,7 @@ class GogoanimeProvider : MainAPI() {
override fun load(url: String): LoadResponse { override fun load(url: String): LoadResponse {
val link = getProperAnimeLink(url) val link = getProperAnimeLink(url)
val episodeloadApi = "https://ajax.gogo-load.com/ajax/load-list-episode" 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 doc = Jsoup.parse(html)
val animeBody = doc.selectFirst(".anime_info_body_bg") val animeBody = doc.selectFirst(".anime_info_body_bg")
@ -166,7 +169,7 @@ class GogoanimeProvider : MainAPI() {
val animeId = doc.selectFirst("#movie_id").attr("value") val animeId = doc.selectFirst("#movie_id").attr("value")
val params = mapOf("ep_start" to "0", "ep_end" to "2000", "id" to animeId) val params = mapOf("ep_start" to "0", "ep_end" to "2000", "id" to animeId)
val responseHTML = khttp.get(episodeloadApi, params=params).text val responseHTML = get(episodeloadApi, params=params).text
val epiDoc = Jsoup.parse(responseHTML) val epiDoc = Jsoup.parse(responseHTML)
val episodes = epiDoc.select("a").map { val episodes = epiDoc.select("a").map {
AnimeEpisode( AnimeEpisode(
@ -195,13 +198,13 @@ class GogoanimeProvider : MainAPI() {
} }
private fun extractVideos(uri: String): List<ExtractorLink> { private fun extractVideos(uri: String): List<ExtractorLink> {
val html = khttp.get(uri).text val html = get(uri).text
val doc = Jsoup.parse(html) val doc = Jsoup.parse(html)
val iframe = "https:" + doc.selectFirst("div.play-video > iframe").attr("src") val iframe = "https:" + doc.selectFirst("div.play-video > iframe").attr("src")
val link = iframe.replace("streaming.php", "download") 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) val pageDoc = Jsoup.parse(page.text)
return pageDoc.select(".dowload > a").map { return pageDoc.select(".dowload > a").map {

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3.animeproviders package com.lagradost.cloudstream3.animeproviders
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -23,7 +25,9 @@ class KawaiifuProvider : MainAPI() {
override fun getMainPage(): HomePageResponse { override fun getMainPage(): HomePageResponse {
val items = ArrayList<HomePageList>() 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 { items.add(HomePageList("Latest Updates", soup.select(".today-update .item").map {
val title = it.selectFirst("img").attr("alt") val title = it.selectFirst("img").attr("alt")
@ -71,7 +75,7 @@ class KawaiifuProvider : MainAPI() {
override fun search(query: String): ArrayList<SearchResponse> { override fun search(query: String): ArrayList<SearchResponse> {
val link = "$mainUrl/search-movie?keyword=${query}" val link = "$mainUrl/search-movie?keyword=${query}"
val html = khttp.get(link).text val html = get(link).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
return ArrayList(soup.select(".item").map { return ArrayList(soup.select(".item").map {
@ -95,7 +99,7 @@ class KawaiifuProvider : MainAPI() {
} }
override fun load(url: String): LoadResponse { override fun load(url: String): LoadResponse {
val html = khttp.get(url).text val html = get(url).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
val title = soup.selectFirst(".title").text() val title = soup.selectFirst(".title").text()
@ -104,7 +108,7 @@ class KawaiifuProvider : MainAPI() {
.filter { it.select("strong").isEmpty() && it.select("iframe").isEmpty() }.joinToString("\n") { it.text() } .filter { it.select("strong").isEmpty() && it.select("iframe").isEmpty() }.joinToString("\n") { it.text() }
val year = url.split("/").filter { it.contains("-") }[0].split("-")[1].toIntOrNull() val year = url.split("/").filter { it.contains("-") }[0].split("-")[1].toIntOrNull()
val episodes = Jsoup.parse( val episodes = Jsoup.parse(
khttp.get( get(
soup.selectFirst("a[href*=\".html-episode\"]").attr("href") soup.selectFirst("a[href*=\".html-episode\"]").attr("href")
).text ).text
).selectFirst(".list-ep").select("li").map { ).selectFirst(".list-ep").select("li").map {
@ -140,7 +144,7 @@ class KawaiifuProvider : MainAPI() {
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val htmlSource = khttp.get(data).text val htmlSource = get(data).text
val soupa = Jsoup.parse(htmlSource) val soupa = Jsoup.parse(htmlSource)
val episodeNum = if (data.contains("ep=")) data.split("ep=")[1].split("&")[0].toIntOrNull() else null val episodeNum = if (data.contains("ep=")) data.split("ep=")[1].split("&")[0].toIntOrNull() else null
@ -159,7 +163,7 @@ class KawaiifuProvider : MainAPI() {
val sources = soupa.select("video > source").map { source -> Pair(source.attr("src"), source.attr("data-quality")) } val sources = soupa.select("video > source").map { source -> Pair(source.attr("src"), source.attr("data-quality")) }
Triple(it.first, sources, it.second.second) Triple(it.first, sources, it.second.second)
} else { } else {
val html = khttp.get(it.second.first).text val html = get(it.second.first).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
val sources = soup.select("video > source").map { source -> Pair(source.attr("src"), source.attr("data-quality")) } val sources = soup.select("video > source").map { source -> Pair(source.attr("src"), source.attr("data-quality")) }

View file

@ -4,9 +4,11 @@ import android.annotation.SuppressLint
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import khttp.structures.cookie.CookieJar
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -15,7 +17,7 @@ import java.util.*
class TenshiProvider : MainAPI() { class TenshiProvider : MainAPI() {
companion object { companion object {
var token: String? = null var token: String? = null
var cookie: CookieJar? = null var cookie: Map<String, String> = mapOf()
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA") || t.contains("Special")) TvType.ONA return if (t.contains("OVA") || t.contains("Special")) TvType.ONA
@ -39,7 +41,7 @@ class TenshiProvider : MainAPI() {
private fun loadToken(): Boolean { private fun loadToken(): Boolean {
return try { return try {
val response = khttp.get(mainUrl) val response = get(mainUrl)
cookie = response.cookies cookie = response.cookies
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response.text)
token = document.selectFirst("""meta[name="csrf-token"]""").attr("content") token = document.selectFirst("""meta[name="csrf-token"]""").attr("content")
@ -51,7 +53,7 @@ class TenshiProvider : MainAPI() {
override fun getMainPage(): HomePageResponse { override fun getMainPage(): HomePageResponse {
val items = ArrayList<HomePageList>() 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")) { for (section in soup.select("#content > section")) {
try { try {
if (section.attr("id") == "toplist-tabs") { if (section.attr("id") == "toplist-tabs") {
@ -207,15 +209,15 @@ class TenshiProvider : MainAPI() {
override fun search(query: String): ArrayList<SearchResponse> { override fun search(query: String): ArrayList<SearchResponse> {
val url = "$mainUrl/anime" val url = "$mainUrl/anime"
var response = khttp.get(url, params = mapOf("q" to query), cookies = mapOf("loop-view" to "thumb")) var response = get(url, params = mapOf("q" to query), cookies = mapOf("loop-view" to "thumb")).text
var document = Jsoup.parse(response.text) var document = Jsoup.parse(response)
val returnValue = parseSearchPage(document) val returnValue = parseSearchPage(document)
while (!document.select("""a.page-link[rel="next"]""").isEmpty()) { while (!document.select("""a.page-link[rel="next"]""").isEmpty()) {
val link = document.select("""a.page-link[rel="next"]""") val link = document.select("""a.page-link[rel="next"]""")
if (link != null && !link.isEmpty()) { if (link != null && !link.isEmpty()) {
response = khttp.get(link[0].attr("href"), cookies = mapOf("loop-view" to "thumb")) response = get(link[0].attr("href"), cookies = mapOf("loop-view" to "thumb")).text
document = Jsoup.parse(response.text) document = Jsoup.parse(response)
returnValue.addAll(parseSearchPage(document)) returnValue.addAll(parseSearchPage(document))
} else { } else {
break break
@ -226,8 +228,8 @@ class TenshiProvider : MainAPI() {
} }
override fun load(url: String): LoadResponse { override fun load(url: String): LoadResponse {
val response = khttp.get(url, timeout = 120.0, cookies = mapOf("loop-view" to "thumb")) val response = get(url, cookies = mapOf("loop-view" to "thumb")).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val englishTitle = document.selectFirst("span.value > span[title=\"English\"]")?.parent()?.text()?.trim() val englishTitle = document.selectFirst("span.value > span[title=\"English\"]")?.parent()?.text()?.trim()
val japaneseTitle = document.selectFirst("span.value > span[title=\"Japanese\"]")?.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, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val response = khttp.get(data) val response = get(data).text
val soup = Jsoup.parse(response.text) val soup = Jsoup.parse(response)
data class Quality( data class Quality(
@JsonProperty("src") val src: String, @JsonProperty("src") val src: String,
@ -302,7 +304,7 @@ class TenshiProvider : MainAPI() {
val sources = ArrayList<ExtractorLink>() val sources = ArrayList<ExtractorLink>()
for (source in soup.select("""[aria-labelledby="mirror-dropdown"] > li > a.dropdown-item""")) { for (source in soup.select("""[aria-labelledby="mirror-dropdown"] > li > a.dropdown-item""")) {
val release = source.text().replace("/", "").trim() val release = source.text().replace("/", "").trim()
val sourceHTML = khttp.get( val sourceHTML = get(
"https://tenshi.moe/embed?v=${source.attr("href").split("v=")[1].split("&")[0]}", "https://tenshi.moe/embed?v=${source.attr("href").split("v=")[1].split("&")[0]}",
headers = mapOf("Referer" to data) headers = mapOf("Referer" to data)
).text ).text

View file

@ -3,6 +3,9 @@ package com.lagradost.cloudstream3.animeproviders
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -27,13 +30,14 @@ class WatchCartoonOnlineProvider : MainAPI() {
val url = "https://www.wcostream.com/search" val url = "https://www.wcostream.com/search"
var response = var response =
khttp.post( post(
url, url,
headers = mapOf("Referer" to url), headers = mapOf("Referer" to url),
data = mapOf("catara" to query, "konuara" to "series") data = mapOf("catara" to query, "konuara" to "series")
) ).text
var document = Jsoup.parse(response.text) var document = Jsoup.parse(response)
var items = document.select("div#blog > div.cerceve").toList() var items = document.select("div#blog > div.cerceve").toList()
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
for (item in items) { for (item in items) {
@ -68,12 +72,12 @@ class WatchCartoonOnlineProvider : MainAPI() {
// "episodes-search", is used for finding movies, anime episodes should be filtered out // "episodes-search", is used for finding movies, anime episodes should be filtered out
response = response =
khttp.post( post(
url, url,
headers = mapOf("Referer" to url), headers = mapOf("Referer" to url),
data = mapOf("catara" to query, "konuara" to "episodes") data = mapOf("catara" to query, "konuara" to "episodes")
) ).text
document = Jsoup.parse(response.text) document = Jsoup.parse(response)
items = document.select("#catlist-listview2 > ul > li").filter { it?.text() != null && !it?.text().toString().contains("Episode") } 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 { override fun load(url: String): LoadResponse {
val isMovie = !url.contains("/anime/") val isMovie = !url.contains("/anime/")
val response = get(url).text
val response = khttp.get(url) val document = Jsoup.parse(response)
val document = Jsoup.parse(response.text)
return if (!isMovie) { return if (!isMovie) {
@ -194,13 +197,12 @@ class WatchCartoonOnlineProvider : MainAPI() {
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val response = khttp.get(data) val response = get(data).text
/*val embedUrl = fixUrl( /*val embedUrl = fixUrl(
Regex("itemprop=\"embedURL\" content=\"(.*?)\"").find(response.text)?.groupValues?.get(1) ?: return false Regex("itemprop=\"embedURL\" content=\"(.*?)\"").find(response.text)?.groupValues?.get(1) ?: return false
)*/ )*/
val text = response.text val start = response.indexOf("itemprop=\"embedURL")
val start = text.indexOf("itemprop=\"embedURL") val foundJS = Regex("<script>(.*?)</script>").find(response, start)?.groupValues?.get(1)
val foundJS = Regex("<script>(.*?)</script>").find(text, start)?.groupValues?.get(1)
?.replace("document.write", "var returnValue = ") ?.replace("document.write", "var returnValue = ")
val rhino = Context.enter() val rhino = Context.enter()
@ -223,7 +225,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
val jsEval = scope.get("returnValue", scope) ?: return false val jsEval = scope.get("returnValue", scope) ?: return false
val src = fixUrl(Regex("src=\"(.*?)\"").find(jsEval as String)?.groupValues?.get(1) ?: return false) val src = fixUrl(Regex("src=\"(.*?)\"").find(jsEval as String)?.groupValues?.get(1) ?: return false)
val embedResponse = khttp.get( val embedResponse = get(
(src), (src),
headers = mapOf("Referer" to data) headers = mapOf("Referer" to data)
) )
@ -231,7 +233,7 @@ class WatchCartoonOnlineProvider : MainAPI() {
val getVidLink = fixUrl( val getVidLink = fixUrl(
Regex("get\\(\"(.*?)\"").find(embedResponse.text)?.groupValues?.get(1) ?: return false Regex("get\\(\"(.*?)\"").find(embedResponse.text)?.groupValues?.get(1) ?: return false
) )
val linkResponse = khttp.get( val linkResponse = get(
getVidLink, headers = mapOf( getVidLink, headers = mapOf(
"sec-ch-ua" to "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"", "sec-ch-ua" to "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"",
"sec-ch-ua-mobile" to "?0", "sec-ch-ua-mobile" to "?0",

View file

@ -3,6 +3,10 @@ package com.lagradost.cloudstream3.animeproviders
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.extractors.WcoStream 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.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import java.util.* import java.util.*
@ -45,9 +49,9 @@ class WcoProvider : MainAPI() {
val items = ArrayList<HomePageList>() val items = ArrayList<HomePageList>()
for (i in urls) { for (i in urls) {
try { try {
val response = khttp.get( val response = JSONObject(get(
i.first, 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 document = Jsoup.parse(response)
val results = document.select("div.flw-item").map { val results = document.select("div.flw-item").map {
val filmPoster = it.selectFirst("> div.film-poster") val filmPoster = it.selectFirst("> div.film-poster")
@ -116,15 +120,16 @@ class WcoProvider : MainAPI() {
override fun search(query: String): List<SearchResponse> { override fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/search" 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) var document = Jsoup.parse(response.text)
val returnValue = parseSearchPage(document) val returnValue = parseSearchPage(document)
while (!document.select(".pagination").isEmpty()) { while (!document.select(".pagination").isEmpty()) {
val link = document.select("a.page-link[rel=\"next\"]") val link = document.select("a.page-link[rel=\"next\"]")
if (!link.isEmpty()) { if (!link.isEmpty()) {
val extraResponse = khttp.get(fixUrl(link[0].attr("href"))) val extraResponse = get(fixUrl(link[0].attr("href"))).text
document = Jsoup.parse(extraResponse.text) document = Jsoup.parse(extraResponse)
returnValue.addAll(parseSearchPage(document)) returnValue.addAll(parseSearchPage(document))
} else { } else {
break break
@ -136,10 +141,10 @@ class WcoProvider : MainAPI() {
override fun quickSearch(query: String): List<SearchResponse> { override fun quickSearch(query: String): List<SearchResponse> {
val returnValue: ArrayList<SearchResponse> = ArrayList() val returnValue: ArrayList<SearchResponse> = ArrayList()
val response = khttp.post( val response = JSONObject(post(
"https://wcostream.cc/ajax/search", "https://wcostream.cc/ajax/search",
data = mapOf("keyword" to query) 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) val document = Jsoup.parse(response)
document.select("a.nav-item").forEach { document.select("a.nav-item").forEach {
@ -177,8 +182,8 @@ class WcoProvider : MainAPI() {
} }
override fun load(url: String): LoadResponse { override fun load(url: String): LoadResponse {
val response = khttp.get(url, timeout = 120.0) val response = get(url, timeout = 120).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val japaneseTitle = document.selectFirst("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(1)") val japaneseTitle = document.selectFirst("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(1)")
?.text()?.trim()?.replace("Other names:", "")?.trim() ?.text()?.trim()?.replace("Other names:", "")?.trim()
@ -234,8 +239,8 @@ class WcoProvider : MainAPI() {
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val response = khttp.get(data) val response = get(data).text
val servers = Jsoup.parse(response.text).select("#servers-list > ul > li").map { val servers = Jsoup.parse(response).select("#servers-list > ul > li").map {
mapOf( mapOf(
"link" to it?.selectFirst("a")?.attr("data-embed"), "link" to it?.selectFirst("a")?.attr("data-embed"),
"title" to it?.selectFirst("span")?.text()?.trim() "title" to it?.selectFirst("span")?.text()?.trim()

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.extractors 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.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
@ -30,13 +32,13 @@ open class DoodLaExtractor : ExtractorApi() {
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
val id = url.removePrefix("$mainUrl/e/").removePrefix("$mainUrl/d/") val id = url.removePrefix("$mainUrl/e/").removePrefix("$mainUrl/d/")
val trueUrl = getExtractorUrl(id) val trueUrl = getExtractorUrl(id)
val response = khttp.get(trueUrl) val response = get(trueUrl).text
Regex("href=\".*/download/(.*?)\"").find(response.text)?.groupValues?.get(1)?.let { link -> Regex("href=\".*/download/(.*?)\"").find(response)?.groupValues?.get(1)?.let { link ->
if (link.isEmpty()) return null if (link.isEmpty()) return null
sleep(5000) // might need this to not trigger anti bot sleep(5000) // might need this to not trigger anti bot
val downloadLink = "$mainUrl/download/$link" val downloadLink = "$mainUrl/download/$link"
val downloadResponse = khttp.get(downloadLink) val downloadResponse = get(downloadLink).text
Regex("onclick=\"window\\.open\\((['\"])(.*?)(['\"])").find(downloadResponse.text)?.groupValues?.get(2) Regex("onclick=\"window\\.open\\((['\"])(.*?)(['\"])").find(downloadResponse)?.groupValues?.get(2)
?.let { trueLink -> ?.let { trueLink ->
return listOf( return listOf(
ExtractorLink( ExtractorLink(

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.extractors package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.network.get
import com.lagradost.cloudstream3.network.text
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
class MixDrop : ExtractorApi() { class MixDrop : ExtractorApi() {
@ -13,7 +15,7 @@ class MixDrop : ExtractorApi() {
} }
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
with(khttp.get(url)) { with(get(url)) {
getAndUnpack(this.text)?.let { unpackedText -> getAndUnpack(this.text)?.let { unpackedText ->
srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link ->
return listOf( return listOf(

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.extractors package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.network.get
import com.lagradost.cloudstream3.network.text
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
class Mp4Upload : ExtractorApi() { class Mp4Upload : ExtractorApi() {
@ -9,7 +11,7 @@ class Mp4Upload : ExtractorApi() {
override val requiresReferer = true override val requiresReferer = true
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
with(khttp.get(url)) { with(get(url)) {
getAndUnpack(this.text)?.let { unpackedText -> getAndUnpack(this.text)?.let { unpackedText ->
srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link ->
return listOf( return listOf(

View file

@ -1,5 +1,8 @@
package com.lagradost.cloudstream3.extractors 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.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
@ -28,12 +31,12 @@ class MultiQuality : ExtractorApi() {
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
with(khttp.get(url)) { with(get(url)) {
sourceRegex.findAll(this.text).forEach { sourceMatch -> sourceRegex.findAll(this.text).forEach { sourceMatch ->
val extractedUrl = sourceMatch.groupValues[1] val extractedUrl = sourceMatch.groupValues[1]
// Trusting this isn't mp4, may fuck up stuff // Trusting this isn't mp4, may fuck up stuff
if (extractedUrl.endsWith(".m3u8")) { if (extractedUrl.endsWith(".m3u8")) {
with(khttp.get(extractedUrl)) { with(get(extractedUrl)) {
m3u8Regex.findAll(this.text).forEach { match -> m3u8Regex.findAll(this.text).forEach { match ->
extractedLinksList.add( extractedLinksList.add(
ExtractorLink( ExtractorLink(

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.extractors 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.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.getAndUnpack import com.lagradost.cloudstream3.utils.getAndUnpack
@ -21,12 +23,12 @@ class StreamSB : ExtractorApi() {
override fun getUrl(url: String, referer: String?): List<ExtractorLink> { override fun getUrl(url: String, referer: String?): List<ExtractorLink> {
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
val newUrl = url.replace("sbplay.org/embed-", "sbplay.org/play/").removeSuffix(".html") 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 { getAndUnpack(this.text)?.let {
sourceRegex.findAll(it).forEach { sourceMatch -> sourceRegex.findAll(it).forEach { sourceMatch ->
val extractedUrl = sourceMatch.groupValues[1] val extractedUrl = sourceMatch.groupValues[1]
if (extractedUrl.contains(".m3u8")) { if (extractedUrl.contains(".m3u8")) {
with(khttp.get(extractedUrl)) { with(get(extractedUrl)) {
m3u8UrlRegex.findAll(this.text).forEach { match -> m3u8UrlRegex.findAll(this.text).forEach { match ->
val extractedUrlM3u8 = match.groupValues[2] val extractedUrlM3u8 = match.groupValues[2]
val extractedRes = match.groupValues[1] val extractedRes = match.groupValues[1]

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.extractors 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.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities 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(|" \+ ')=.*)'""") 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>? { override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
with(khttp.get(url)) { with(get(url)) {
linkRegex.find(this.text)?.let { linkRegex.find(this.text)?.let {
val extractedUrl = "https://streamtape.com/get_video?${it.groupValues[1]}".replace("""" + '""", "") val extractedUrl = "https://streamtape.com/get_video?${it.groupValues[1]}".replace("""" + '""", "")
return listOf( return listOf(

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.extractors 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.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.JsUnpacker import com.lagradost.cloudstream3.utils.JsUnpacker
@ -18,8 +20,8 @@ class Streamhub : ExtractorApi() {
} }
override fun getUrl(url: String, referer: String?): List<ExtractorLink>? { override fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
val response = khttp.get(url) val response = get(url).text
Regex("eval((.|\\n)*?)</script>").find(response.text)?.groupValues?.get(1)?.let { jsEval -> Regex("eval((.|\\n)*?)</script>").find(response)?.groupValues?.get(1)?.let { jsEval ->
JsUnpacker("eval$jsEval" ).unpack()?.let { unPacked -> JsUnpacker("eval$jsEval" ).unpack()?.let { unPacked ->
Regex("sources:\\[\\{src:\"(.*?)\"").find(unPacked)?.groupValues?.get(1)?.let { link -> Regex("sources:\\[\\{src:\"(.*?)\"").find(unPacked)?.groupValues?.get(1)?.let { link ->
return listOf( return listOf(

View file

@ -1,6 +1,9 @@
package com.lagradost.cloudstream3.extractors package com.lagradost.cloudstream3.extractors
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall 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.pmap
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.extractorApis import com.lagradost.cloudstream3.utils.extractorApis
@ -38,7 +41,7 @@ class Vidstream(overrideMainUrl: String? = null) {
/** Stolen from GogoanimeProvider.kt extractor */ /** Stolen from GogoanimeProvider.kt extractor */
normalSafeApiCall { normalSafeApiCall {
val link = getDownloadUrl(id) 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 pageDoc = Jsoup.parse(page.text)
val qualityRegex = Regex("(\\d+)P") 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 document = Jsoup.parse(this.text)
val primaryLinks = document.select("ul.list-server-items > li.linkserver") val primaryLinks = document.select("ul.list-server-items > li.linkserver")
//val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() //val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()

View file

@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.mapper import com.lagradost.cloudstream3.mapper
import com.lagradost.cloudstream3.network.get
import com.lagradost.cloudstream3.network.text
class WcoStream : ExtractorApi() { class WcoStream : ExtractorApi() {
override val name: String = "WcoStream" override val name: String = "WcoStream"
@ -14,14 +16,14 @@ class WcoStream : ExtractorApi() {
override fun getUrl(url: String, referer: String?): List<ExtractorLink> { override fun getUrl(url: String, referer: String?): List<ExtractorLink> {
val baseUrl = url.split("/e/")[0] 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 (Id) = "/e/(.*?)?domain".toRegex().find(url)!!.destructured
val (skey) = """skey\s=\s['"](.*?)['"];""".toRegex().find(html)!!.destructured val (skey) = """skey\s=\s['"](.*?)['"];""".toRegex().find(html)!!.destructured
val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey" val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey"
val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" 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( data class Sources(
@JsonProperty("file") val file: String, @JsonProperty("file") val file: String,

View file

@ -3,6 +3,8 @@ package com.lagradost.cloudstream3.extractors
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.mapper 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.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
@ -44,9 +46,10 @@ class XStreamCdn : ExtractorApi() {
) )
val newUrl = url.replace("$mainUrl/v/", "$mainUrl/api/source/") val newUrl = url.replace("$mainUrl/v/", "$mainUrl/api/source/")
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf() val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
with(khttp.post(newUrl, headers = headers)) { with(post(newUrl, headers = headers)) {
if (this.text == """{"success":false,"data":"Video not found or has been removed"}""") return listOf() val text = this.text
mapper.readValue<ResponseJson?>(this.text)?.let { 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) { if (it.success && it.data != null) {
it.data.forEach { data -> it.data.forEach { data ->
extractedLinksList.add( extractedLinksList.add(

View file

@ -2,9 +2,14 @@ package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import okio.Buffer
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import java.lang.Thread.sleep import java.lang.Thread.sleep
@ -33,8 +38,8 @@ class AllMoviesForYouProvider : MainAPI() {
override fun search(query: String): List<SearchResponse> { override fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/?s=$query" val url = "$mainUrl/?s=$query"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val items = document.select("ul.MovieList > li > article > a") val items = document.select("ul.MovieList > li > article > a")
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
@ -72,8 +77,8 @@ class AllMoviesForYouProvider : MainAPI() {
override fun load(url: String): LoadResponse { override fun load(url: String): LoadResponse {
val type = getType(url) val type = getType(url)
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val title = document.selectFirst("h1.Title").text() val title = document.selectFirst("h1.Title").text()
val descipt = document.selectFirst("div.Description > p").text() val descipt = document.selectFirst("div.Description > p").text()
@ -98,8 +103,8 @@ class AllMoviesForYouProvider : MainAPI() {
val episodeList = ArrayList<TvSeriesEpisode>() val episodeList = ArrayList<TvSeriesEpisode>()
for (season in list) { for (season in list) {
val seasonResponse = khttp.get(season.second) val seasonResponse = get(season.second).text
val seasonDocument = Jsoup.parse(seasonResponse.text) val seasonDocument = Jsoup.parse(seasonResponse)
val episodes = seasonDocument.select("table > tbody > tr") val episodes = seasonDocument.select("table > tbody > tr")
if (episodes.isNotEmpty()) { if (episodes.isNotEmpty()) {
episodes.forEach { episode -> episodes.forEach { episode ->
@ -162,8 +167,8 @@ class AllMoviesForYouProvider : MainAPI() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
if (data.startsWith("$mainUrl/episode/")) { if (data.startsWith("$mainUrl/episode/")) {
val response = khttp.get(data) val response = get(data).text
getLink(Jsoup.parse(response.text))?.let { links -> getLink(Jsoup.parse(response))?.let { links ->
for (link in links) { for (link in links) {
if (link == data) continue if (link == data) continue
loadLinks(link, isCasting, subtitleCallback, callback) loadLinks(link, isCasting, subtitleCallback, callback)
@ -174,9 +179,21 @@ class AllMoviesForYouProvider : MainAPI() {
} else if (data.startsWith(mainUrl) && data != mainUrl) { } else if (data.startsWith(mainUrl) && data != mainUrl) {
val realDataUrl = URLDecoder.decode(data, "application/x-www-form-urlencoded") val realDataUrl = URLDecoder.decode(data, "application/x-www-form-urlencoded")
if (data.contains("trdownload")) { if (data.contains("trdownload")) {
val request = khttp.get(data, stream = true) val request = get(data)
if (request.url.startsWith("https://streamhub.to/d/")) { 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") val inputs = document.select("Form > input")
if (inputs.size < 4) return false if (inputs.size < 4) return false
var op: String? = null var op: String? = null
@ -200,8 +217,17 @@ class AllMoviesForYouProvider : MainAPI() {
} }
sleep(5000) // ye this is needed, wont work with 0 delay 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 postResponse = post(
val postDocument = Jsoup.parse(postResponse.text) 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") val url = postDocument.selectFirst("a.downloadbtn").attr("href")
if (url.isNullOrEmpty()) return false if (url.isNullOrEmpty()) return false
@ -211,8 +237,8 @@ class AllMoviesForYouProvider : MainAPI() {
} }
return true return true
} }
val response = khttp.get(realDataUrl) val response = get(realDataUrl).text
Regex("<iframe.*?src=\"(.*?)\"").find(response.text)?.groupValues?.get(1)?.let { url -> Regex("<iframe.*?src=\"(.*?)\"").find(response)?.groupValues?.get(1)?.let { url ->
loadExtractor(url.trimStart(), realDataUrl, callback) loadExtractor(url.trimStart(), realDataUrl, callback)
} }
return true return true

View file

@ -5,10 +5,11 @@ import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.getStatus 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.DataStore.toKotlinObject
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import khttp.get
class AsiaFlixProvider : MainAPI() { class AsiaFlixProvider : MainAPI() {
override val mainUrl: String override val mainUrl: String

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3.movieproviders package com.lagradost.cloudstream3.movieproviders
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -18,8 +20,8 @@ class HDMProvider : MainAPI() {
override fun search(query: String): List<SearchResponse> { override fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/search/$query" val url = "$mainUrl/search/$query"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val items = document.select("div.col-md-2 > article > a") val items = document.select("div.col-md-2 > article > a")
if (items.isEmpty()) return ArrayList() if (items.isEmpty()) return ArrayList()
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
@ -42,8 +44,8 @@ class HDMProvider : MainAPI() {
): Boolean { ): Boolean {
if (data == "") return false if (data == "") return false
val slug = ".*/(.*?)\\.mp4".toRegex().find(data)?.groupValues?.get(1) ?: return false val slug = ".*/(.*?)\\.mp4".toRegex().find(data)?.groupValues?.get(1) ?: return false
val response = khttp.get(data) val response = get(data).text
val key = "playlist\\.m3u8(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return false val key = "playlist\\.m3u8(.*?)\"".toRegex().find(response)?.groupValues?.get(1) ?: return false
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
this.name, this.name,
@ -58,14 +60,14 @@ class HDMProvider : MainAPI() {
} }
override fun load(url: String): LoadResponse? { override fun load(url: String): LoadResponse? {
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val title = document.selectFirst("h2.movieTitle")?.text() ?: throw ErrorLoadingException("No Data Found") val title = document.selectFirst("h2.movieTitle")?.text() ?: throw ErrorLoadingException("No Data Found")
val poster = document.selectFirst("div.post-thumbnail > img").attr("src") val poster = document.selectFirst("div.post-thumbnail > img").attr("src")
val descript = document.selectFirst("div.synopsis > p").text() val descript = document.selectFirst("div.synopsis > p").text()
val year = document.select("div.movieInfoAll > div.row > div.col-md-6")?.get(1)?.selectFirst("> p > a")?.text() val year = document.select("div.movieInfoAll > div.row > div.col-md-6")?.get(1)?.selectFirst("> p > a")?.text()
?.toIntOrNull() ?.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( return MovieLoadResponse(
title, url, this.name, TvType.Movie, title, url, this.name, TvType.Movie,

View file

@ -6,6 +6,8 @@ import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.unixTime import com.lagradost.cloudstream3.APIHolder.unixTime
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.extractors.M3u8Manifest 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 com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -71,12 +73,12 @@ class LookMovieProvider : MainAPI() {
override fun quickSearch(query: String): List<SearchResponse> { override fun quickSearch(query: String): List<SearchResponse> {
val movieUrl = "$mainUrl/api/v1/movies/search/?q=$query" val movieUrl = "$mainUrl/api/v1/movies/search/?q=$query"
val movieResponse = khttp.get(movieUrl) val movieResponse = get(movieUrl).text
val movies = mapper.readValue<LookMovieSearchResultRoot>(movieResponse.text).result val movies = mapper.readValue<LookMovieSearchResultRoot>(movieResponse).result
val showsUrl = "$mainUrl/api/v1/shows/search/?q=$query" val showsUrl = "$mainUrl/api/v1/shows/search/?q=$query"
val showsResponse = khttp.get(showsUrl) val showsResponse = get(showsUrl).text
val shows = mapper.readValue<LookMovieSearchResultRoot>(showsResponse.text).result val shows = mapper.readValue<LookMovieSearchResultRoot>(showsResponse).result
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
if (!movies.isNullOrEmpty()) { if (!movies.isNullOrEmpty()) {
@ -117,8 +119,8 @@ class LookMovieProvider : MainAPI() {
override fun search(query: String): List<SearchResponse> { override fun search(query: String): List<SearchResponse> {
fun search(query: String, isMovie: Boolean): ArrayList<SearchResponse> { fun search(query: String, isMovie: Boolean): ArrayList<SearchResponse> {
val url = "$mainUrl/${if (isMovie) "movies" else "shows"}/search/?q=$query" val url = "$mainUrl/${if (isMovie) "movies" else "shows"}/search/?q=$query"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val items = document.select("div.flex-wrap-movielist > div.movie-item-style-1") val items = document.select("div.flex-wrap-movielist > div.movie-item-style-1")
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
@ -161,8 +163,8 @@ class LookMovieProvider : MainAPI() {
} }
private fun loadCurrentLinks(url: String, callback: (ExtractorLink) -> Unit) { private fun loadCurrentLinks(url: String, callback: (ExtractorLink) -> Unit) {
val response = khttp.get(url.replace("\$unixtime", unixTime.toString())) val response = get(url.replace("\$unixtime", unixTime.toString())).text
M3u8Manifest.extractLinks(response.text).forEach { M3u8Manifest.extractLinks(response).forEach {
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
this.name, this.name,
@ -185,24 +187,24 @@ class LookMovieProvider : MainAPI() {
val localData: LookMovieLinkLoad = mapper.readValue(data) val localData: LookMovieLinkLoad = mapper.readValue(data)
if (localData.isMovie) { if (localData.isMovie) {
val tokenResponse = khttp.get(localData.url) val tokenResponse = get(localData.url).text
val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse.text) val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse)
val accessToken = root.data?.accessToken ?: return false val accessToken = root.data?.accessToken ?: return false
addSubtitles(root.data.subtitles, subtitleCallback) addSubtitles(root.data.subtitles, subtitleCallback)
loadCurrentLinks(localData.extraUrl.replace("\$accessToken", accessToken), callback) loadCurrentLinks(localData.extraUrl.replace("\$accessToken", accessToken), callback)
return true return true
} else { } else {
loadCurrentLinks(localData.url, callback) loadCurrentLinks(localData.url, callback)
val subResponse = khttp.get(localData.extraUrl) val subResponse = get(localData.extraUrl).text
val subs = mapper.readValue<List<LookMovieTokenSubtitle>>(subResponse.text) val subs = mapper.readValue<List<LookMovieTokenSubtitle>>(subResponse)
addSubtitles(subs, subtitleCallback) addSubtitles(subs, subtitleCallback)
} }
return true return true
} }
override fun load(url: String): LoadResponse? { override fun load(url: String): LoadResponse? {
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val isMovie = url.contains("/movies/") val isMovie = url.contains("/movies/")
val watchHeader = document.selectFirst("div.watch-heading") 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) var poster = if (img.isNullOrEmpty()) null else "url\\((.*?)\\)".toRegex().find(img)?.groupValues?.get(1)
if (poster.isNullOrEmpty()) poster = imgElement?.attr("data-background-image") if (poster.isNullOrEmpty()) poster = imgElement?.attr("data-background-image")
val descript = document.selectFirst("p.description-short").text() val descript = document.selectFirst("p.description-short").text()
val id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex().find(response.text)?.groupValues?.get(1) val id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex().find(response)?.groupValues?.get(1)
?.replace(" ", "") ?.replace(" ", "")
?: return null ?: return null
val realSlug = url.replace("$mainUrl/${if (isMovie) "movies" else "shows"}/view/", "") val realSlug = url.replace("$mainUrl/${if (isMovie) "movies" else "shows"}/view/", "")
@ -243,12 +245,12 @@ class LookMovieProvider : MainAPI() {
rating rating
) )
} else { } else {
val tokenResponse = khttp.get(realUrl) val tokenResponse = get(realUrl).text
val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse.text) val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse)
val accessToken = root.data?.accessToken ?: return null val accessToken = root.data?.accessToken ?: return null
val window = 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 ?: return null
// val id = "id_show:(.*?),".toRegex().find(response.text)?.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 val season = "seasons:.*\\[((.|\\n)*?)]".toRegex().find(window)?.groupValues?.get(1) ?: return null

View file

@ -3,6 +3,8 @@ package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -38,8 +40,8 @@ class MeloMovieProvider : MainAPI() {
override fun search(query: String): List<SearchResponse> { override fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/movie/search/?name=$query" val url = "$mainUrl/movie/search/?name=$query"
val returnValue: ArrayList<SearchResponse> = ArrayList() val returnValue: ArrayList<SearchResponse> = ArrayList()
val response = khttp.get(url) val response = get(url).text
val mapped = response.let { mapper.readValue<List<MeloMovieSearchResult>>(it.text) } val mapped = response.let { mapper.readValue<List<MeloMovieSearchResult>>(it) }
if (mapped.isEmpty()) return returnValue if (mapped.isEmpty()) return returnValue
for (i in mapped) { for (i in mapped) {
@ -115,7 +117,7 @@ class MeloMovieProvider : MainAPI() {
} }
override fun load(url: String): LoadResponse? { override fun load(url: String): LoadResponse? {
val response = khttp.get(url).text val response = get(url).text
//backdrop = imgurl //backdrop = imgurl
fun findUsingRegex(src: String): String? { fun findUsingRegex(src: String): String? {

View file

@ -3,6 +3,8 @@ package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -41,8 +43,8 @@ class ThenosProvider : MainAPI() {
val list = ArrayList<HomePageList>() val list = ArrayList<HomePageList>()
map.entries.forEach { map.entries.forEach {
val url = "$apiUrl/library/${it.value}" val url = "$apiUrl/library/${it.value}"
val response = khttp.get(url) val response = get(url).text
val mapped = mapper.readValue<ThenosLoadResponse>(response.text) val mapped = mapper.readValue<ThenosLoadResponse>(response)
mapped.Metadata?.mapNotNull { meta -> mapped.Metadata?.mapNotNull { meta ->
meta?.toSearchResponse() meta?.toSearchResponse()
@ -209,8 +211,8 @@ class ThenosProvider : MainAPI() {
} }
private fun searchFromUrl(url: String): List<SearchResponse> { private fun searchFromUrl(url: String): List<SearchResponse> {
val response = khttp.get(url) val response = get(url).text
val test = mapper.readValue<ThenosSearchResponse>(response.text) val test = mapper.readValue<ThenosSearchResponse>(response)
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
test.Hub?.forEach { test.Hub?.forEach {
@ -255,12 +257,12 @@ class ThenosProvider : MainAPI() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val url = "$apiUrl/library/watch/$data" val url = "$apiUrl/library/watch/$data"
val response = khttp.get(url) val response = get(url).text
val mapped = mapper.readValue<ThenosSource>(response.text) val mapped = mapper.readValue<ThenosSource>(response)
mapped.sources?.forEach { source -> mapped.sources?.forEach { source ->
val isM3u8 = source.type != "video/mp4" 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 = val authorization =
String(android.util.Base64.decode(token, android.util.Base64.DEFAULT), Charsets.ISO_8859_1) 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> { private fun getAllEpisodes(id: String): List<TvSeriesEpisode> {
val episodes = ArrayList<TvSeriesEpisode>() val episodes = ArrayList<TvSeriesEpisode>()
val url = "$apiUrl/library/metadata/$id/children" val url = "$apiUrl/library/metadata/$id/children"
val response = khttp.get(url) val response = get(url).text
val mapped = mapper.readValue<ThenosSeriesResponse>(response.text) val mapped = mapper.readValue<ThenosSeriesResponse>(response)
mapped.Metadata?.forEach { series_meta -> mapped.Metadata?.forEach { series_meta ->
val fixedUrl = apiUrl + series_meta.key val fixedUrl = apiUrl + series_meta.key
val child = khttp.get(fixedUrl) val child = get(fixedUrl).text
val mappedSeason = mapper.readValue<SeasonResponse>(child.text) val mappedSeason = mapper.readValue<SeasonResponse>(child)
mappedSeason.Metadata?.forEach mappedSeason@{ meta -> mappedSeason.Metadata?.forEach mappedSeason@{ meta ->
episodes.add( episodes.add(
TvSeriesEpisode( TvSeriesEpisode(
@ -450,8 +452,8 @@ class ThenosProvider : MainAPI() {
override fun load(url: String): LoadResponse? { override fun load(url: String): LoadResponse? {
val fixedUrl = "$apiUrl/library/metadata/${url.split("/").last()}" val fixedUrl = "$apiUrl/library/metadata/${url.split("/").last()}"
val response = khttp.get(fixedUrl) val response = get(fixedUrl).text
val mapped = mapper.readValue<ThenosLoadResponse>(response.text) val mapped = mapper.readValue<ThenosLoadResponse>(response)
val isShow = mapped.Metadata?.any { it?.type == "show" } == true val isShow = mapped.Metadata?.any { it?.type == "show" } == true
val metadata = mapped.Metadata?.getOrNull(0) ?: return null val metadata = mapped.Metadata?.getOrNull(0) ?: return null

View file

@ -2,6 +2,8 @@ package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.SubtitleHelper import com.lagradost.cloudstream3.utils.SubtitleHelper
@ -33,8 +35,8 @@ class TrailersToProvider : MainAPI() {
get() = VPNStatus.MightBeNeeded get() = VPNStatus.MightBeNeeded
override fun getMainPage(): HomePageResponse? { override fun getMainPage(): HomePageResponse? {
val response = khttp.get(mainUrl) val response = get(mainUrl).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val returnList = ArrayList<HomePageList>() val returnList = ArrayList<HomePageList>()
val docs = document.select("section.section > div.container") val docs = document.select("section.section > div.container")
for (doc in docs) { for (doc in docs) {
@ -76,8 +78,8 @@ class TrailersToProvider : MainAPI() {
override fun quickSearch(query: String): List<SearchResponse> { override fun quickSearch(query: String): List<SearchResponse> {
val url = "$mainUrl/en/quick-search?q=$query" val url = "$mainUrl/en/quick-search?q=$query"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val items = document.select("div.group-post-minimal > a.post-minimal") val items = document.select("div.group-post-minimal > a.post-minimal")
if (items.isNullOrEmpty()) return ArrayList() if (items.isNullOrEmpty()) return ArrayList()
@ -104,8 +106,8 @@ class TrailersToProvider : MainAPI() {
override fun search(query: String): List<SearchResponse> { override fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/en/popular/movies-tvshows-collections?q=$query" val url = "$mainUrl/en/popular/movies-tvshows-collections?q=$query"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val items = document.select("div.col-lg-8 > article.list-item") val items = document.select("div.col-lg-8 > article.list-item")
if (items.isNullOrEmpty()) return ArrayList() if (items.isNullOrEmpty()) return ArrayList()
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
@ -133,8 +135,8 @@ class TrailersToProvider : MainAPI() {
data: String, data: String,
callback: (ExtractorLink) -> Unit, callback: (ExtractorLink) -> Unit,
): Boolean { ): Boolean {
val response = khttp.get(data) val response = get(data).text
val url = "<source src='(.*?)'".toRegex().find(response.text)?.groupValues?.get(1) val url = "<source src='(.*?)'".toRegex().find(response)?.groupValues?.get(1)
if (url != null) { if (url != null) {
callback.invoke(ExtractorLink(this.name, this.name, url, mainUrl, Qualities.Unknown.value, false)) 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) { private fun loadSubs(url: String, subtitleCallback: (SubtitleFile) -> Unit) {
if (url.isEmpty()) return if (url.isEmpty()) return
val response = khttp.get(fixUrl(url)) val response = get(fixUrl(url)).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val items = document.select("div.list-group > a.list-group-item") val items = document.select("div.list-group > a.list-group-item")
for (item in items) { for (item in items) {
@ -181,8 +183,8 @@ class TrailersToProvider : MainAPI() {
return isSucc return isSucc
} else if (url.contains("/episode/")) { } else if (url.contains("/episode/")) {
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
// val qSub = document.select("subtitle-content") // val qSub = document.select("subtitle-content")
val subUrl = document.select("subtitle-content")?.attr("data-url") ?: "" val subUrl = document.select("subtitle-content")?.attr("data-url") ?: ""
@ -198,8 +200,8 @@ class TrailersToProvider : MainAPI() {
} }
override fun load(url: String): LoadResponse { override fun load(url: String): LoadResponse {
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
var title = document?.selectFirst("h2.breadcrumbs-custom-title > a")?.text() ?: throw ErrorLoadingException("Service might be unavailable") 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") val metaInfo = document.select("div.post-info-meta > ul.post-info-meta-list > li")

View file

@ -3,6 +3,10 @@ package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -21,8 +25,8 @@ class VMoveeProvider : MainAPI() {
override fun search(query: String): List<SearchResponse> { override fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/?s=$query" val url = "$mainUrl/?s=$query"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val searchItems = document.select("div.search-page > div.result-item > article") val searchItems = document.select("div.search-page > div.result-item > article")
if (searchItems.size == 0) return ArrayList() if (searchItems.size == 0) return ArrayList()
val returnValue = ArrayList<SearchResponse>() val returnValue = ArrayList<SearchResponse>()
@ -75,24 +79,24 @@ class VMoveeProvider : MainAPI() {
val url = "$mainUrl/dashboard/admin-ajax.php" val url = "$mainUrl/dashboard/admin-ajax.php"
val post = val post =
khttp.post( post(
url, url,
headers = mapOf("referer" to url), headers = mapOf("referer" to url),
data = mapOf("action" to "doo_player_ajax", "post" to data, "nume" to "2", "type" to "movie") 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 var realUrl = ajax.embedUrl
if (realUrl.startsWith("//")) { if (realUrl.startsWith("//")) {
realUrl = "https:$realUrl" realUrl = "https:$realUrl"
} }
val request = khttp.get(realUrl) val request = get(realUrl)
val prefix = "https://reeoov.tube/v/" val prefix = "https://reeoov.tube/v/"
if (request.url.startsWith(prefix)) { if (request.url.startsWith(prefix)) {
val apiUrl = "https://reeoov.tube/api/source/${request.url.removePrefix(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 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.text) val apiData = mapper.readValue<ReeoovAPI>(apiResponse)
for (d in apiData.data) { for (d in apiData.data) {
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
@ -111,8 +115,8 @@ class VMoveeProvider : MainAPI() {
} }
override fun load(url: String): LoadResponse { override fun load(url: String): LoadResponse {
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val sheader = document.selectFirst("div.sheader") val sheader = document.selectFirst("div.sheader")

View file

@ -3,22 +3,37 @@ package com.lagradost.cloudstream3.movieproviders
import org.jsoup.Jsoup import org.jsoup.Jsoup
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.extractors.Vidstream 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.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
/** Needs to inherit from MainAPI() to
* make the app know what functions to call
*/
class VidEmbedProvider : MainAPI() { class VidEmbedProvider : MainAPI() {
// mainUrl is good to have as a holder for the url to make future changes easier.
override val mainUrl: String override val mainUrl: String
get() = "https://vidembed.cc" 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 override val name: String
get() = "VidEmbed" 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 override val hasQuickSearch: Boolean
get() = false get() = false
// If getMainPage() is functional, used to display the homepage in app, an optional, but highly encouraged endevour.
override val hasMainPage: Boolean override val hasMainPage: Boolean
get() = true 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 { private fun fixUrl(url: String): String {
return if (url.startsWith("//")) { return if (url.startsWith("//")) {
"https:$url" "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> override val supportedTypes: Set<TvType>
get() = setOf(TvType.Anime, TvType.AnimeMovie, TvType.TvSeries, TvType.Movie) 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> { 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 link = "$mainUrl/search.html?keyword=$query"
val html = khttp.get(link).text val html = get(link).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
return ArrayList(soup.select(".listing.items > .video-block").map { li -> return ArrayList(soup.select(".listing.items > .video-block").map { li ->
// Selects the href in <a href="...">
val href = fixUrl(li.selectFirst("a").attr("href")) val href = fixUrl(li.selectFirst("a").attr("href"))
val poster = li.selectFirst("img")?.attr("src") val poster = li.selectFirst("img")?.attr("src")
// .text() selects all the text in the element, be careful about doing this while too high up in the html hierarchy
val title = li.selectFirst(".name").text() val title = li.selectFirst(".name").text()
// Use get(0) and toIntOrNull() to prevent any possible crashes, [0] or toInt() will error the search on unexpected values.
val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull() val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull()
TvSeriesSearchResponse( TvSeriesSearchResponse(
// .trim() removes unwanted spaces in the start and end.
if (!title.contains("Episode")) title else title.split("Episode")[0].trim(), if (!title.contains("Episode")) title else title.split("Episode")[0].trim(),
href, href,
this.name, this.name,
TvType.TvSeries, TvType.TvSeries,
poster, year, poster, year,
// You can't get the episodes from the search bar.
null 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? { 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) val soup = Jsoup.parse(html)
var title = soup.selectFirst("h1,h2,h3").text() var title = soup.selectFirst("h1,h2,h3").text()
@ -89,8 +120,10 @@ class VidEmbedProvider : MainAPI() {
epDate epDate
) )
}.reversed() }.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 val tvType = if (episodes.size == 1 && episodes[0].name == title) TvType.Movie else TvType.TvSeries
return when (tvType) { 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? { override fun getMainPage(): HomePageResponse? {
val urls = listOf( val urls = listOf(
mainUrl, mainUrl,
@ -136,10 +171,12 @@ class VidEmbedProvider : MainAPI() {
"$mainUrl/cinema-movies" "$mainUrl/cinema-movies"
) )
val homePageList = ArrayList<HomePageList>() val homePageList = ArrayList<HomePageList>()
// .pmap {} is used to fetch the different pages in parallel
urls.pmap { url -> urls.pmap { url ->
val response = khttp.get(url, timeout = 20.0) val response = get(url, timeout = 20).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
document.select("div.main-inner")?.forEach { 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 title = it.select(".widget-title").text().trim()
val elements = it.select(".video-block").map { val elements = it.select(".video-block").map {
val link = fixUrl(it.select("a").attr("href")) val link = fixUrl(it.select("a").attr("href"))
@ -182,13 +219,21 @@ class VidEmbedProvider : MainAPI() {
return HomePageResponse(homePageList) 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( override fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
// These callbacks are functions you should call when you get a link to a subtitle file or media file.
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): 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") val vidstreamObject = Vidstream("https://vidembed.cc")
// https://vidembed.cc/streaming.php?id=MzUwNTY2&... -> MzUwNTY2 // https://vidembed.cc/streaming.php?id=MzUwNTY2&... -> MzUwNTY2
val id = Regex("""id=([^&]*)""").find(iframeLink)?.groupValues?.get(1) val id = Regex("""id=([^&]*)""").find(iframeLink)?.groupValues?.get(1)
@ -197,7 +242,7 @@ class VidEmbedProvider : MainAPI() {
vidstreamObject.getUrl(id, isCasting, callback) vidstreamObject.getUrl(id, isCasting, callback)
} }
val html = khttp.get(fixUrl(iframeLink)).text val html = get(fixUrl(iframeLink)).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
val servers = soup.select(".list-server-items > .linkserver").mapNotNull { li -> val servers = soup.select(".list-server-items > .linkserver").mapNotNull { li ->
@ -208,12 +253,16 @@ class VidEmbedProvider : MainAPI() {
} }
} }
servers.forEach { 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") { if (it.first.toLowerCase(Locale.ROOT).trim() == "beta server") {
// Group 1: link, Group 2: Label // 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 sourceRegex = Regex("""sources:[\W\w]*?file:\s*["'](.*?)["'][\W\w]*?label:\s*["'](.*?)["']""")
val trackRegex = Regex("""tracks:[\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 -> sourceRegex.findAll(html).forEach { match ->
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
@ -221,8 +270,11 @@ class VidEmbedProvider : MainAPI() {
match.groupValues.getOrNull(2)?.let { "${this.name} $it" } ?: this.name, match.groupValues.getOrNull(2)?.let { "${this.name} $it" } ?: this.name,
match.groupValues[1], match.groupValues[1],
it.second, it.second,
// Useful function to turn something like "1080p" to an app quality.
getQualityFromName(match.groupValues.getOrNull(2) ?: ""), getQualityFromName(match.groupValues.getOrNull(2) ?: ""),
// Kinda risky // 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"), match.groupValues[1].endsWith(".m3u8"),
) )
) )

View 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()
}

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3.torrentproviders package com.lagradost.cloudstream3.torrentproviders
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -23,8 +25,8 @@ class NyaaProvider : MainAPI() {
override fun search(query: String): List<SearchResponse> { override fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/?f=0&c=0_0&q=$query&s=seeders&o=desc" val url = "$mainUrl/?f=0&c=0_0&q=$query&s=seeders&o=desc"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val returnValues = ArrayList<SearchResponse>() val returnValues = ArrayList<SearchResponse>()
val elements = document.select("table > tbody > tr") val elements = document.select("table > tbody > tr")
@ -43,8 +45,8 @@ class NyaaProvider : MainAPI() {
} }
override fun load(url: String): LoadResponse { override fun load(url: String): LoadResponse {
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val title = document.selectFirst("h3.panel-title").text() val title = document.selectFirst("h3.panel-title").text()
val description = document.selectFirst("div#torrent-description").text() val description = document.selectFirst("div#torrent-description").text()
val downloadLinks = document.select("div.panel-footer > a") val downloadLinks = document.select("div.panel-footer > a")

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.utils package com.lagradost.cloudstream3.utils
import com.lagradost.cloudstream3.network.get
import com.lagradost.cloudstream3.network.text
import org.jsoup.Jsoup import org.jsoup.Jsoup
import java.util.* import java.util.*
import kotlin.collections.HashMap import kotlin.collections.HashMap
@ -16,8 +18,8 @@ object FillerEpisodeCheck {
private fun getFillerList(): Boolean { private fun getFillerList(): Boolean {
if (list != null) return true if (list != null) return true
try { try {
val result = khttp.get("$MAIN_URL/shows") val result = get("$MAIN_URL/shows").text
val documented = Jsoup.parse(result.text) val documented = Jsoup.parse(result)
val localHTMLList = documented.select("div#ShowList > div.Group > ul > li > a") val localHTMLList = documented.select("div#ShowList > div.Group > ul > li > a")
val localList = HashMap<String, String>() val localList = HashMap<String, String>()
for (i in localHTMLList) { for (i in localHTMLList) {
@ -71,8 +73,8 @@ object FillerEpisodeCheck {
val realQuery = fixName(query.replace(blackListRegex, "")).replace("shippuuden", "shippuden") val realQuery = fixName(query.replace(blackListRegex, "")).replace("shippuuden", "shippuden")
if (!localList.containsKey(realQuery)) return null if (!localList.containsKey(realQuery)) return null
val href = localList[realQuery]?.replace(MAIN_URL, "") ?: return null // JUST IN CASE val href = localList[realQuery]?.replace(MAIN_URL, "") ?: return null // JUST IN CASE
val result = khttp.get("$MAIN_URL$href") val result = get("$MAIN_URL$href").text
val documented = Jsoup.parse(result.text) ?: return null val documented = Jsoup.parse(result) ?: return null
val hashMap = HashMap<Int, Boolean>() val hashMap = HashMap<Int, Boolean>()
documented.select("table.EpisodeList > tbody > tr").forEach { documented.select("table.EpisodeList > tbody > tr").forEach {
val type = it.selectFirst("td.Type > span").text() == "Filler" val type = it.selectFirst("td.Type > span").text() == "Filler"

View file

@ -40,7 +40,7 @@ class HttpSession {
allowRedirects: Boolean? = null, allowRedirects: Boolean? = null,
stream: Boolean = false, files: List<FileLike> = listOf(), stream: Boolean = false, files: List<FileLike> = listOf(),
): Response { ): Response {
val res = khttp.get( val res = get(
url, headers, params, url, headers, params,
data, json, auth, data, json, auth,
mergeCookies(sessionCookies, cookies), timeout, mergeCookies(sessionCookies, cookies), timeout,
@ -62,7 +62,7 @@ class HttpSession {
allowRedirects: Boolean? = null, allowRedirects: Boolean? = null,
stream: Boolean = false, files: List<FileLike> = listOf() stream: Boolean = false, files: List<FileLike> = listOf()
): Response { ): Response {
val res = khttp.post( val res = post(
url, headers, params, url, headers, params,
data, json, auth, data, json, auth,
mergeCookies(sessionCookies, cookies), timeout, mergeCookies(sessionCookies, cookies), timeout,

View file

@ -23,6 +23,8 @@ import com.lagradost.cloudstream3.MainActivity.Companion.showToast
import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.R
import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.network.get
import com.lagradost.cloudstream3.network.text
import java.io.File import java.io.File
import kotlin.concurrent.thread import kotlin.concurrent.thread
@ -82,7 +84,7 @@ class InAppUpdater {
val url = "https://api.github.com/repos/LagradOst/CloudStream-3/releases" val url = "https://api.github.com/repos/LagradOst/CloudStream-3/releases"
val headers = mapOf("Accept" to "application/vnd.github.v3+json") val headers = mapOf("Accept" to "application/vnd.github.v3+json")
val response = 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 versionRegex = Regex("""(.*?((\d+)\.(\d+)\.(\d+))\.apk)""")
val versionRegexLocal = Regex("""(.*?((\d+)\.(\d+)\.(\d+)).*)""") val versionRegexLocal = Regex("""(.*?((\d+)\.(\d+)\.(\d+)).*)""")
@ -138,7 +140,7 @@ class InAppUpdater {
val releaseUrl = "https://api.github.com/repos/LagradOst/CloudStream-3/releases" val releaseUrl = "https://api.github.com/repos/LagradOst/CloudStream-3/releases"
val headers = mapOf("Accept" to "application/vnd.github.v3+json") val headers = mapOf("Accept" to "application/vnd.github.v3+json")
val response = val response =
mapper.readValue<List<GithubRelease>>(khttp.get(releaseUrl, headers = headers).text) mapper.readValue<List<GithubRelease>>(get(releaseUrl, headers = headers).text)
val found = val found =
response.lastOrNull { rel -> response.lastOrNull { rel ->
@ -147,7 +149,7 @@ class InAppUpdater {
val foundAsset = found?.assets?.getOrNull(0) val foundAsset = found?.assets?.getOrNull(0)
val tagResponse = 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) val shouldUpdate = (getString(R.string.prerelease_commit_hash) != tagResponse.github_object.sha)

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3.utils package com.lagradost.cloudstream3.utils
import com.lagradost.cloudstream3.mvvm.logError 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.Cipher
import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.IvParameterSpec
import javax.crypto.spec.SecretKeySpec import javax.crypto.spec.SecretKeySpec
@ -79,9 +81,9 @@ class M3u8Helper {
fun m3u8Generation(m3u8: M3u8Stream): List<M3u8Stream> { fun m3u8Generation(m3u8: M3u8Stream): List<M3u8Stream> {
val generate = sequence { val generate = sequence {
val m3u8Parent = getParentLink(m3u8.streamUrl) 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 var (quality, m3u8Link, m3u8Link2) = match.destructured
if (m3u8Link.isNullOrEmpty()) m3u8Link = m3u8Link2 if (m3u8Link.isNullOrEmpty()) m3u8Link = m3u8Link2
if (absoluteExtensionDetermination(m3u8Link) == "m3u8") { if (absoluteExtensionDetermination(m3u8Link) == "m3u8") {
@ -134,18 +136,17 @@ class M3u8Helper {
val secondSelection = selectBest(streams.ifEmpty { listOf(selected) }) val secondSelection = selectBest(streams.ifEmpty { listOf(selected) })
if (secondSelection != null) { if (secondSelection != null) {
val m3u8Response = khttp.get(secondSelection.streamUrl, headers = headers) val m3u8Response = get(secondSelection.streamUrl, headers = headers).text
val m3u8Data = m3u8Response.text
var encryptionUri: String? = null var encryptionUri: String? = null
var encryptionIv = byteArrayOf() var encryptionIv = byteArrayOf()
var encryptionData = byteArrayOf() var encryptionData = byteArrayOf()
val encryptionState = isEncrypted(m3u8Data) val encryptionState = isEncrypted(m3u8Response)
if (encryptionState) { if (encryptionState) {
val match = 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() encryptionUri = match.component2()
if (isNotCompleteUrl(encryptionUri)) { if (isNotCompleteUrl(encryptionUri)) {
@ -153,11 +154,11 @@ class M3u8Helper {
} }
encryptionIv = match.component3().toByteArray() encryptionIv = match.component3().toByteArray()
val encryptionKeyResponse = khttp.get(encryptionUri, headers = headers) val encryptionKeyResponse = get(encryptionUri, headers = headers)
encryptionData = encryptionKeyResponse.content encryptionData = encryptionKeyResponse.body?.bytes() ?: byteArrayOf()
} }
val allTs = TS_EXTENSION_REGEX.findAll(m3u8Data) val allTs = TS_EXTENSION_REGEX.findAll(m3u8Response)
val allTsList = allTs.toList() val allTsList = allTs.toList()
val totalTs = allTsList.size val totalTs = allTsList.size
if (totalTs == 0) { if (totalTs == 0) {
@ -176,8 +177,8 @@ class M3u8Helper {
while (lastYield != c) { while (lastYield != c) {
try { try {
val tsResponse = khttp.get(url, headers = headers) val tsResponse = get(url, headers = headers)
var tsData = tsResponse.content var tsData = tsResponse.body?.bytes() ?: byteArrayOf()
if (encryptionState) { if (encryptionState) {
tsData = getDecrypter(encryptionData, tsData, encryptionIv) tsData = getDecrypter(encryptionData, tsData, encryptionIv)

View file

@ -1,5 +1,7 @@
package com.lagradost.cloudstream3.utils package com.lagradost.cloudstream3.utils
import com.lagradost.cloudstream3.network.get
import com.lagradost.cloudstream3.network.text
import org.jsoup.Jsoup import org.jsoup.Jsoup
import java.util.* import java.util.*
@ -16,8 +18,8 @@ object SubtitleHelper {
fun createISO() { fun createISO() {
val url = "https://infogalactic.com/info/List_of_ISO_639-1_codes" val url = "https://infogalactic.com/info/List_of_ISO_639-1_codes"
val response = khttp.get(url) val response = get(url).text
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response)
val headers = document.select("table.wikitable > tbody > tr") val headers = document.select("table.wikitable > tbody > tr")
var text = "listOf(\n" var text = "listOf(\n"