diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 26d33521..00000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 33b144a8..1b86bb06 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -1,11 +1,11 @@ - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 6199cc2a..4bc4fc6e 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,9 +1,5 @@ - - - - - + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml deleted file mode 100644 index e96534fb..00000000 --- a/.idea/uiDesigner.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7f..35eb1ddf 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt index 6c5cfc6e..fac2ba92 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt @@ -1,31 +1,24 @@ package com.lagradost.cloudstream3.animeproviders import android.annotation.SuppressLint -import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.module.kotlin.readValue import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.extractors.Vidstream import com.lagradost.cloudstream3.utils.getQualityFromName +import khttp.structures.cookie.CookieJar import org.jsoup.Jsoup import org.jsoup.nodes.Document -import java.util.* -import kotlin.collections.ArrayList -import khttp.structures.cookie.CookieJar import java.text.SimpleDateFormat - - +import java.util.* class TenshiProvider : MainAPI() { - companion object { var token: String? = null var cookie: CookieJar? = null fun getType(t: String): TvType { - if (t.contains("OVA") || t.contains("Special")) return TvType.ONA - else if (t.contains("Movie")) return TvType.Movie - else return TvType.Anime + return if (t.contains("OVA") || t.contains("Special")) TvType.ONA + else if (t.contains("Movie")) TvType.Movie + else TvType.Anime } } @@ -43,9 +36,7 @@ class TenshiProvider : MainAPI() { private fun loadToken(): Boolean { return try { - val response = khttp.get( - "https://tenshi.moe/", - ) + val response = khttp.get(mainUrl) cookie = response.cookies val document = Jsoup.parse(response.text) token = document.selectFirst("""meta[name="csrf-token"]""").attr("content") @@ -179,7 +170,7 @@ class TenshiProvider : MainAPI() { return returnValue } - override fun load(slug: String): LoadResponse? { + override fun load(slug: String): LoadResponse { val url = "$mainUrl/anime/${slug}" val response = khttp.get(url, timeout = 120.0, cookies=mapOf("loop-view" to "thumb")) @@ -189,7 +180,6 @@ class TenshiProvider : MainAPI() { val japaneseTitle = document.selectFirst("span.value > span[title=\"Japanese\"]")?.parent()?.text()?.trim() val canonicalTitle = document.selectFirst("header.entry-header > h1.mb-3").text().trim() - val isDubbed = false val episodeNodes = document.select("li[class*=\"episode\"] > a") val episodes = ArrayList(episodeNodes?.map { @@ -212,7 +202,7 @@ class TenshiProvider : MainAPI() { val (year) = pattern.find(yearText)!!.destructured val poster = document.selectFirst("img.cover-image")?.attr("src") - val type = document.selectFirst("a[href*=\"https://tenshi.moe/type/\"]")?.text()?.trim() + val type = document.selectFirst("a[href*=\"$mainUrl/type/\"]")?.text()?.trim() val synopsis = document.selectFirst(".entry-description > .card-body")?.text()?.trim() val genre = document.select("li.genre.meta-data > span.value").map { it?.text()?.trim().toString() } @@ -232,7 +222,7 @@ class TenshiProvider : MainAPI() { episodes, status, synopsis, - ArrayList(genre) ?: ArrayList(), + ArrayList(genre), ArrayList(synonyms), null, null, diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt index f8b886af..5fd1022c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt @@ -10,7 +10,6 @@ import kotlin.collections.ArrayList class WcoProvider : MainAPI() { - companion object { fun getType(t: String): TvType { return if (t.contains("OVA") || t.contains("Special")) TvType.ONA @@ -137,7 +136,7 @@ class WcoProvider : MainAPI() { return returnValue } - override fun load(slug: String): LoadResponse? { + override fun load(slug: String): LoadResponse { val url = "$mainUrl/anime/${slug}" val response = khttp.get(url, timeout = 120.0) @@ -177,11 +176,11 @@ class WcoProvider : MainAPI() { canonicalTitle, "$mainUrl/anime/${slug}", this.name, - WcoProvider.getType(type ?: ""), + getType(type ?: ""), poster, year, - null, - episodes, + if(isDubbed) episodes else null, + if(!isDubbed) episodes else null, status, synopsis, ArrayList(genre), @@ -204,7 +203,7 @@ class WcoProvider : MainAPI() { } for (server in servers) { - WcoStream().getUrl(server["link"].toString(), "").forEach { + WcoStream().getSafeUrl(server["link"].toString(), "")?.forEach { callback.invoke(it) } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt index 7b83b964..f6a7955b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -1,11 +1,7 @@ package com.lagradost.cloudstream3.utils -import com.lagradost.cloudstream3.utils.extractors.MixDrop -import com.lagradost.cloudstream3.utils.extractors.Mp4Upload -import com.lagradost.cloudstream3.utils.extractors.Shiro -import com.lagradost.cloudstream3.utils.extractors.WcoStream -import com.lagradost.cloudstream3.utils.extractors.StreamTape -import com.lagradost.cloudstream3.utils.extractors.XStreamCdn +import com.lagradost.cloudstream3.mvvm.normalSafeApiCall +import com.lagradost.cloudstream3.utils.extractors.* data class ExtractorLink( val source: String, @@ -59,7 +55,8 @@ val extractorApis: Array = arrayOf( Mp4Upload(), StreamTape(), MixDrop(), - XStreamCdn() + XStreamCdn(), + StreamSB(), ) fun getExtractorApiFromName(name: String): ExtractorApi { @@ -82,6 +79,13 @@ abstract class ExtractorApi { abstract val mainUrl: String abstract val requiresReferer: Boolean + fun getSafeUrl(url: String, referer: String? = null): List? { + return normalSafeApiCall { getUrl(url, referer) } + } + + /** + * Will throw errors, use getSafeUrl if you don't want to handle the exception yourself + */ abstract fun getUrl(url: String, referer: String? = null): List? open fun getExtractorUrl(id: String): String { diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/MixDrop.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/MixDrop.kt index b3e2aa7d..f506645d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/MixDrop.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/MixDrop.kt @@ -13,25 +13,21 @@ class MixDrop : ExtractorApi() { } override fun getUrl(url: String, referer: String?): List? { - try { - with(khttp.get(url)) { - getAndUnpack(this.text)?.let { unpackedText -> - srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> - return listOf( - ExtractorLink( - name, - name, - httpsify(link), - url, - Qualities.Unknown.value, - ) + with(khttp.get(url)) { + getAndUnpack(this.text)?.let { unpackedText -> + srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> + return listOf( + ExtractorLink( + name, + name, + httpsify(link), + url, + Qualities.Unknown.value, ) - } + ) } } - return null - } catch (e: Exception) { - return null } + return null } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Mp4Upload.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Mp4Upload.kt index 188e9735..e8166583 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Mp4Upload.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Mp4Upload.kt @@ -9,25 +9,21 @@ class Mp4Upload : ExtractorApi() { override val requiresReferer = true override fun getUrl(url: String, referer: String?): List? { - try { - with(khttp.get(url)) { - getAndUnpack(this.text)?.let { unpackedText -> - srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> - return listOf( - ExtractorLink( - name, - name, - link, - url, - Qualities.Unknown.value, - ) + with(khttp.get(url)) { + getAndUnpack(this.text)?.let { unpackedText -> + srcRegex.find(unpackedText)?.groupValues?.get(1)?.let { link -> + return listOf( + ExtractorLink( + name, + name, + link, + url, + Qualities.Unknown.value, ) - } + ) } } - return null - } catch (e: Exception) { - return null } + return null } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/MultiQuality.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/MultiQuality.kt index df668356..2450c1e2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/MultiQuality.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/MultiQuality.kt @@ -27,44 +27,40 @@ class MultiQuality : ExtractorApi() { } override fun getUrl(url: String, referer: String?): List? { - try { - val extractedLinksList: MutableList = mutableListOf() - with(khttp.get(url)) { - sourceRegex.findAll(this.text).forEach { sourceMatch -> - val extractedUrl = sourceMatch.groupValues[1] - // Trusting this isn't mp4, may fuck up stuff - if (extractedUrl.endsWith(".m3u8")) { - with(khttp.get(extractedUrl)) { - m3u8Regex.findAll(this.text).forEach { match -> - extractedLinksList.add( - ExtractorLink( - name, - "$name ${match.groupValues[1]}p", - urlRegex.find(this.url)!!.groupValues[1] + match.groupValues[0], - url, - getQuality(match.groupValues[1]), - isM3u8 = true - ) + val extractedLinksList: MutableList = mutableListOf() + with(khttp.get(url)) { + sourceRegex.findAll(this.text).forEach { sourceMatch -> + val extractedUrl = sourceMatch.groupValues[1] + // Trusting this isn't mp4, may fuck up stuff + if (extractedUrl.endsWith(".m3u8")) { + with(khttp.get(extractedUrl)) { + m3u8Regex.findAll(this.text).forEach { match -> + extractedLinksList.add( + ExtractorLink( + name, + "$name ${match.groupValues[1]}p", + urlRegex.find(this.url)!!.groupValues[1] + match.groupValues[0], + url, + getQuality(match.groupValues[1]), + isM3u8 = true ) - } - - } - } else if (extractedUrl.endsWith(".mp4")) { - extractedLinksList.add( - ExtractorLink( - name, - "$name ${sourceMatch.groupValues[2]}", - extractedUrl, - url.replace(" ", "%20"), - Qualities.Unknown.value, ) - ) - } - } - return extractedLinksList - } - } catch (e: Exception) { + } + } + } else if (extractedUrl.endsWith(".mp4")) { + extractedLinksList.add( + ExtractorLink( + name, + "$name ${sourceMatch.groupValues[2]}", + extractedUrl, + url.replace(" ", "%20"), + Qualities.Unknown.value, + ) + ) + } + } + return extractedLinksList } return null } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/StreamSB.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/StreamSB.kt new file mode 100644 index 00000000..388c04c4 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/StreamSB.kt @@ -0,0 +1,51 @@ +package com.lagradost.cloudstream3.utils.extractors + +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.getAndUnpack +import com.lagradost.cloudstream3.utils.getQualityFromName + +class StreamSB : ExtractorApi() { + override val name: String = "StreamSB" + override val mainUrl: String = "https://sbplay.org" + private val sourceRegex = Regex("""sources:[\W\w]*?file:\s*"(.*?)"""") + + //private val m3u8Regex = Regex(""".*?(\d*).m3u8""") + //private val urlRegex = Regex("""(.*?)([^/]+$)""") + + // 1: Resolution 2: url + private val m3u8UrlRegex = Regex("""RESOLUTION=\d*x(\d*).*\n(http.*.m3u8)""") + override val requiresReferer = false + + // https://sbembed.com/embed-ns50b0cukf9j.html -> https://sbvideo.net/play/ns50b0cukf9j + override fun getUrl(url: String, referer: String?): List { + val extractedLinksList: MutableList = mutableListOf() + val newUrl = url.replace("sbplay.org/embed-", "sbplay.org/play/").removeSuffix(".html") + with(khttp.get(newUrl, timeout = 10.0)) { + getAndUnpack(this.text)?.let { + sourceRegex.findAll(it).forEach { sourceMatch -> + val extractedUrl = sourceMatch.groupValues[1] + if (extractedUrl.contains(".m3u8")) { + with(khttp.get(extractedUrl)) { + m3u8UrlRegex.findAll(this.text).forEach { match -> + val extractedUrlM3u8 = match.groupValues[2] + val extractedRes = match.groupValues[1] + extractedLinksList.add( + ExtractorLink( + name, + "$name ${extractedRes}p", + extractedUrlM3u8, + extractedUrl, + getQualityFromName(extractedRes), + true + ) + ) + } + } + } + } + } + } + return extractedLinksList + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/StreamTape.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/StreamTape.kt index b8661f03..aefc067d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/StreamTape.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/StreamTape.kt @@ -14,22 +14,19 @@ class StreamTape : ExtractorApi() { Regex("""(i(|" \+ ')d(|" \+ ')=.*?&(|" \+ ')e(|" \+ ')x(|" \+ ')p(|" \+ ')i(|" \+ ')r(|" \+ ')e(|" \+ ')s(|" \+ ')=.*?&(|" \+ ')i(|" \+ ')p(|" \+ ')=.*?&(|" \+ ')t(|" \+ ')o(|" \+ ')k(|" \+ ')e(|" \+ ')n(|" \+ ')=.*)'""") override fun getUrl(url: String, referer: String?): List? { - try { - with(khttp.get(url)) { - linkRegex.find(this.text)?.let { - val extractedUrl = "https://streamtape.com/get_video?${it.groupValues[1]}".replace("""" + '""", "") - return listOf( - ExtractorLink( - name, - name, - extractedUrl, - url, - Qualities.Unknown.value, - ) + with(khttp.get(url)) { + linkRegex.find(this.text)?.let { + val extractedUrl = "https://streamtape.com/get_video?${it.groupValues[1]}".replace("""" + '""", "") + return listOf( + ExtractorLink( + name, + name, + extractedUrl, + url, + Qualities.Unknown.value, ) - } + ) } - } catch (e: Exception) { } return null } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Vidstream.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Vidstream.kt index 72ae464b..e89a62fa 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Vidstream.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/Vidstream.kt @@ -20,7 +20,7 @@ class Vidstream { try { normalApis.pmap { api -> val url = api.getExtractorUrl(id) - val source = api.getUrl(url) + val source = api.getSafeUrl(url) source?.forEach { callback.invoke(it) } } @@ -38,7 +38,7 @@ class Vidstream { // Matches vidstream links with extractors extractorApis.filter { !it.requiresReferer || !isCasting }.pmap { api -> if (link.startsWith(api.mainUrl)) { - val extractedLinks = api.getUrl(link, url) + val extractedLinks = api.getSafeUrl(link, url) if (extractedLinks?.isNotEmpty() == true) { extractedLinks.forEach { callback.invoke(it) diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/WcoStream.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/WcoStream.kt index 85321793..a124aede 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/WcoStream.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/WcoStream.kt @@ -11,52 +11,48 @@ class WcoStream : ExtractorApi() { override val requiresReferer = false override fun getUrl(url: String, referer: String?): List { - try { - 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 (Id) = "/e/(.*?)?domain".toRegex().find(url)!!.destructured - val (skey) = """skey\s=\s['\"](.*?)['\"];""".toRegex().find(html)!!.destructured + val html = khttp.get(url, headers = mapOf("Referer" to "https://wcostream.cc/")).text + val (Id) = "/e/(.*?)?domain".toRegex().find(url)!!.destructured + val (skey) = """skey\s=\s['\"](.*?)['\"];""".toRegex().find(html)!!.destructured - val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey" - val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" + val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey" + val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" - val response = khttp.get(apiLink, headers=mapOf("Referer" to referrer)).text + val response = khttp.get(apiLink, headers = mapOf("Referer" to referrer)).text - data class Sources ( - @JsonProperty("file") val file : String, - @JsonProperty("label") val label : String - ) + data class Sources( + @JsonProperty("file") val file: String, + @JsonProperty("label") val label: String? + ) - data class Media ( - @JsonProperty("sources") val sources : List - ) + data class Media( + @JsonProperty("sources") val sources: List + ) - data class WcoResponse ( - @JsonProperty("success") val success : Boolean, - @JsonProperty("media") val media : Media - ) + data class WcoResponse( + @JsonProperty("success") val success: Boolean, + @JsonProperty("media") val media: Media + ) - val mapped = response.let { mapper.readValue(it) } - val sources = mutableListOf() + val mapped = response.let { mapper.readValue(it) } + val sources = mutableListOf() - if (mapped.success) { - mapped.media.sources.forEach { - sources.add( - ExtractorLink( - "WcoStream", - "WcoStream" + "- ${it.label}", - it.file, - "", - Qualities.HD.value, - it.file.contains(".m3u8") - ) + if (mapped.success) { + mapped.media.sources.forEach { + sources.add( + ExtractorLink( + name, + name + if (it.label != null) "- ${it.label}" else "", + it.file, + "", + Qualities.HD.value, + it.file.contains(".m3u8") ) - } + ) } - return sources - } catch (e: Exception) { - return listOf() } + return sources } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/XStreamCdn.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/XStreamCdn.kt index 6edf65dd..b30d9179 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/XStreamCdn.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/XStreamCdn.kt @@ -38,34 +38,29 @@ class XStreamCdn : ExtractorApi() { } override fun getUrl(url: String, referer: String?): List? { - try { - val headers = mapOf( - "Referer" to url, - "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0", - ) - val newUrl = url.replace("$mainUrl/v/", "$mainUrl/api/source/") - val extractedLinksList: MutableList = mutableListOf() - with(khttp.post(newUrl, headers = headers)) { - mapper.readValue(this.text)?.let { - if (it.success && it.data != null) { - it.data.forEach { data -> - extractedLinksList.add( - ExtractorLink( - name, - "$name ${data.label}", - data.file, - url, - getQuality(data.label), - ) + val headers = mapOf( + "Referer" to url, + "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0", + ) + val newUrl = url.replace("$mainUrl/v/", "$mainUrl/api/source/") + val extractedLinksList: MutableList = mutableListOf() + with(khttp.post(newUrl, headers = headers)) { + mapper.readValue(this.text)?.let { + if (it.success && it.data != null) { + it.data.forEach { data -> + extractedLinksList.add( + ExtractorLink( + name, + "$name ${data.label}", + data.file, + url, + getQuality(data.label), ) - } + ) } } } - return extractedLinksList - } catch (e: Exception) { } - return null + return extractedLinksList } - } \ No newline at end of file