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/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt
index 3adcdc02..5493c217 100644
--- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt
+++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt
@@ -8,6 +8,7 @@ import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.lagradost.cloudstream3.animeproviders.DubbedAnimeProvider
import com.lagradost.cloudstream3.animeproviders.ShiroProvider
import com.lagradost.cloudstream3.animeproviders.TenshiProvider
+import com.lagradost.cloudstream3.animeproviders.WcoProvider
import com.lagradost.cloudstream3.movieproviders.HDMProvider
import com.lagradost.cloudstream3.movieproviders.LookMovieProvider
import com.lagradost.cloudstream3.movieproviders.MeloMovieProvider
@@ -33,6 +34,7 @@ object APIHolder {
val apis = arrayListOf(
ShiroProvider(),
TenshiProvider(),
+ WcoProvider(),
MeloMovieProvider(),
DubbedAnimeProvider(),
HDMProvider(),
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 83c28eb3..23bb646e 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
new file mode 100644
index 00000000..5fd1022c
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt
@@ -0,0 +1,212 @@
+package com.lagradost.cloudstream3.animeproviders
+
+import com.lagradost.cloudstream3.*
+import com.lagradost.cloudstream3.utils.ExtractorLink
+import com.lagradost.cloudstream3.utils.extractors.WcoStream
+import org.jsoup.Jsoup
+import org.jsoup.nodes.Document
+import java.util.*
+import kotlin.collections.ArrayList
+
+
+class WcoProvider : MainAPI() {
+ companion object {
+ fun getType(t: String): TvType {
+ return if (t.contains("OVA") || t.contains("Special")) TvType.ONA
+ else if (t.contains("Movie")) TvType.Movie
+ else TvType.Anime
+ }
+ }
+
+ override val mainUrl: String
+ get() = "https://wcostream.cc"
+ override val name: String
+ get() = "WCO Stream"
+ override val hasQuickSearch: Boolean
+ get() = true
+
+
+ private fun getSlug(href: String): String {
+ return href.replace("$mainUrl/anime/", "").replace("/", "")
+ }
+
+ private fun fixAnimeLink(url: String): String {
+ val regex = "watch/([a-zA-Z\\-0-9]*)-episode".toRegex()
+ val (aniId) = regex.find(url)!!.destructured
+ return "$mainUrl/anime/$aniId"
+ }
+
+ private fun parseSearchPage(soup: Document): ArrayList {
+ val items = soup.select(".film_list-wrap > .flw-item")
+ if (items.isEmpty()) return ArrayList()
+ val returnValue = ArrayList()
+ for (i in items) {
+ val href = fixAnimeLink(i.selectFirst("a").attr("href"))
+ val img = fixUrl(i.selectFirst("img").attr("data-src"))
+ val title = i.selectFirst("img").attr("title")
+ val isDub = !i.select(".pick.film-poster-quality").isEmpty()
+ val year = i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(1)").text().toIntOrNull()
+ val type = i.selectFirst(".film-detail.film-detail-fix > div > span:nth-child(3)").text()
+
+ returnValue.add(
+ if (getType(type) == TvType.Movie) {
+ MovieSearchResponse(
+ title, href, getSlug(href), this.name, TvType.Movie, img, year
+ )
+ } else {
+ AnimeSearchResponse(
+ title,
+ href,
+ getSlug(href),
+ this.name,
+ TvType.Anime,
+ img,
+ year,
+ null,
+ EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed),
+ null,
+ null
+ )
+ }
+ )
+ }
+ return returnValue
+ }
+
+ override fun search(query: String): ArrayList {
+ val url = "$mainUrl/search"
+ val response = khttp.get(url, params=mapOf("keyword" to query))
+ var document = Jsoup.parse(response.text)
+ val returnValue = parseSearchPage(document)
+
+ while (!document.select(".pagination").isEmpty()) {
+ val link = document.select("a.page-link[rel=\"next\"]")
+ if (!link.isEmpty()) {
+ val extraResponse = khttp.get(fixUrl(link[0].attr("href")))
+ document = Jsoup.parse(extraResponse.text)
+ returnValue.addAll(parseSearchPage(document))
+ } else {
+ break
+ }
+ }
+ return returnValue
+ }
+
+ override fun quickSearch(query: String): ArrayList {
+ val returnValue: ArrayList = ArrayList()
+
+ val response = khttp.post(
+ "https://wcostream.cc/ajax/search",
+ data=mapOf("keyword" to query)
+ ).jsonObject.getString("html") // I won't make a dataclass for this shit
+ val document = Jsoup.parse(response)
+
+ document.select("a.nav-item").forEach {
+ val title = it.selectFirst("img")?.attr("title").toString()
+ val img = it?.selectFirst("img")?.attr("src")
+ val href = it?.attr("href").toString()
+ val isDub = title.contains("(Dub)")
+ val filmInfo = it?.selectFirst(".film-infor")
+ val year = filmInfo?.select("span")?.get(0)?.text()?.toIntOrNull()
+ val type = filmInfo?.select("span")?.get(1)?.text().toString()
+ if (title != "null") {
+ returnValue.add(
+ if (getType(type) == TvType.Movie) {
+ MovieSearchResponse(
+ title, href, getSlug(href), this.name, TvType.Movie, img, year
+ )
+ } else {
+ AnimeSearchResponse(
+ title,
+ href,
+ getSlug(href),
+ this.name,
+ TvType.Anime,
+ img,
+ year,
+ null,
+ EnumSet.of(if (isDub) DubStatus.Dubbed else DubStatus.Subbed),
+ null,
+ null
+ )
+ }
+ )
+ }
+ }
+ return returnValue
+ }
+
+ override fun load(slug: String): LoadResponse {
+ val url = "$mainUrl/anime/${slug}"
+
+ val response = khttp.get(url, timeout = 120.0)
+ val document = Jsoup.parse(response.text)
+
+ val japaneseTitle = document.selectFirst("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(1)")
+ ?.text()?.trim()?.replace("Other names:", "")?.trim()
+
+ val canonicalTitle = document.selectFirst("meta[name=\"title\"]")
+ ?.attr("content")?.split("| W")?.get(0).toString()
+
+ val isDubbed = canonicalTitle.contains("Dub")
+ val episodeNodes = document.select(".tab-content .nav-item > a")
+
+ val episodes = ArrayList(episodeNodes?.map {
+ AnimeEpisode(it.attr("href"))
+ }
+ ?: ArrayList())
+ val statusElem = document.selectFirst("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(2)")
+ val status = when (statusElem?.text()?.replace("Status:", "")?.trim()) {
+ "Ongoing" -> ShowStatus.Ongoing
+ "Completed" -> ShowStatus.Completed
+ else -> null
+ }
+ val yearText = document.selectFirst("div.elements div.row > div:nth-child(2) > div.row-line:nth-child(4)")?.text()
+ val year = yearText?.replace("Date release:", "")?.trim()?.split("-")?.get(0)?.toIntOrNull()
+
+ val poster = document.selectFirst(".film-poster-img")?.attr("src")
+ val type = document.selectFirst("span.item.mr-1 > a")?.text()?.trim()
+
+ val synopsis = document.selectFirst(".description > p")?.text()?.trim()
+ val genre = document.select("div.elements div.row > div:nth-child(1) > div.row-line:nth-child(5) > a").map { it?.text()?.trim().toString() }
+
+ return AnimeLoadResponse(
+ canonicalTitle,
+ japaneseTitle,
+ canonicalTitle,
+ "$mainUrl/anime/${slug}",
+ this.name,
+ getType(type ?: ""),
+ poster,
+ year,
+ if(isDubbed) episodes else null,
+ if(!isDubbed) episodes else null,
+ status,
+ synopsis,
+ ArrayList(genre),
+ ArrayList(),
+ )
+ }
+
+ override fun loadLinks(
+ data: String,
+ isCasting: Boolean,
+ subtitleCallback: (SubtitleFile) -> Unit,
+ callback: (ExtractorLink) -> Unit
+ ): Boolean {
+ val response = khttp.get(data)
+ val servers = Jsoup.parse(response.text).select("#servers-list > ul > li").map {
+ mapOf(
+ "link" to it?.selectFirst("a")?.attr("data-embed"),
+ "title" to it?.selectFirst("span")?.text()?.trim()
+ )
+ }
+
+ for (server in servers) {
+ WcoStream().getSafeUrl(server["link"].toString(), "")?.forEach {
+ callback.invoke(it)
+ }
+ }
+ return true
+ }
+}
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 e388c97e..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,10 +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.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,
@@ -54,10 +51,12 @@ fun getAndUnpack(string: String): String? {
val extractorApis: Array = arrayOf(
//AllProvider(),
Shiro(),
+ WcoStream(),
Mp4Upload(),
StreamTape(),
MixDrop(),
- XStreamCdn()
+ XStreamCdn(),
+ StreamSB(),
)
fun getExtractorApiFromName(name: String): ExtractorApi {
@@ -80,9 +79,16 @@ 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 {
return id
}
-}
\ No newline at end of file
+}
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
new file mode 100644
index 00000000..a124aede
--- /dev/null
+++ b/app/src/main/java/com/lagradost/cloudstream3/utils/extractors/WcoStream.kt
@@ -0,0 +1,58 @@
+package com.lagradost.cloudstream3.utils.extractors
+
+import com.fasterxml.jackson.annotation.JsonProperty
+import com.fasterxml.jackson.module.kotlin.readValue
+import com.lagradost.cloudstream3.utils.*
+import com.lagradost.cloudstream3.mapper
+
+class WcoStream : ExtractorApi() {
+ override val name: String = "WcoStream"
+ override val mainUrl: String = "https://vidstream.pro"
+ override val requiresReferer = false
+
+ override fun getUrl(url: String, referer: String?): List {
+ 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 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
+
+ data class Sources(
+ @JsonProperty("file") val file: String,
+ @JsonProperty("label") val label: String?
+ )
+
+ data class Media(
+ @JsonProperty("sources") val sources: List
+ )
+
+ data class WcoResponse(
+ @JsonProperty("success") val success: Boolean,
+ @JsonProperty("media") val media: Media
+ )
+
+ val mapped = response.let { mapper.readValue(it) }
+ val sources = mutableListOf()
+
+ 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
+ }
+}
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