mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
added subtitles to ExtractorApi
This commit is contained in:
parent
a7e29dd8d5
commit
47f4e10078
69 changed files with 621 additions and 442 deletions
|
@ -899,6 +899,11 @@ data class TvSeriesSearchResponse(
|
||||||
override var posterHeaders: Map<String, String>? = null,
|
override var posterHeaders: Map<String, String>? = null,
|
||||||
) : SearchResponse
|
) : SearchResponse
|
||||||
|
|
||||||
|
data class TrailerData(
|
||||||
|
var mirros: List<ExtractorLink>,
|
||||||
|
var subtitles: List<SubtitleFile> = emptyList(),
|
||||||
|
)
|
||||||
|
|
||||||
interface LoadResponse {
|
interface LoadResponse {
|
||||||
var name: String
|
var name: String
|
||||||
var url: String
|
var url: String
|
||||||
|
@ -910,7 +915,8 @@ interface LoadResponse {
|
||||||
var rating: Int? // 0-10000
|
var rating: Int? // 0-10000
|
||||||
var tags: List<String>?
|
var tags: List<String>?
|
||||||
var duration: Int? // in minutes
|
var duration: Int? // in minutes
|
||||||
var trailers: List<ExtractorLink>?
|
var trailers: MutableList<TrailerData>
|
||||||
|
|
||||||
var recommendations: List<SearchResponse>?
|
var recommendations: List<SearchResponse>?
|
||||||
var actors: List<ActorData>?
|
var actors: List<ActorData>?
|
||||||
var comingSoon: Boolean
|
var comingSoon: Boolean
|
||||||
|
@ -965,35 +971,25 @@ interface LoadResponse {
|
||||||
/**better to call addTrailer with mutible trailers directly instead of calling this multiple times*/
|
/**better to call addTrailer with mutible trailers directly instead of calling this multiple times*/
|
||||||
suspend fun LoadResponse.addTrailer(trailerUrl: String?, referer: String? = null) {
|
suspend fun LoadResponse.addTrailer(trailerUrl: String?, referer: String? = null) {
|
||||||
if (!isTrailersEnabled || trailerUrl == null) return
|
if (!isTrailersEnabled || trailerUrl == null) return
|
||||||
try {
|
val links = arrayListOf<ExtractorLink>()
|
||||||
val newTrailers = loadExtractor(trailerUrl, referer)
|
val subs = arrayListOf<SubtitleFile>()
|
||||||
addTrailer(newTrailers)
|
loadExtractor(trailerUrl, referer, { subs.add(it) }, { links.add(it) })
|
||||||
} catch (e: Exception) {
|
this.trailers.add(TrailerData(links, subs))
|
||||||
logError(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LoadResponse.addTrailer(newTrailers: List<ExtractorLink>) {
|
fun LoadResponse.addTrailer(newTrailers: List<ExtractorLink>) {
|
||||||
if (this.trailers == null) {
|
trailers.addAll(newTrailers.map { TrailerData(listOf(it)) })
|
||||||
this.trailers = newTrailers
|
|
||||||
} else {
|
|
||||||
val update = this.trailers?.toMutableList() ?: mutableListOf()
|
|
||||||
update.addAll(newTrailers)
|
|
||||||
this.trailers = update
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun LoadResponse.addTrailer(trailerUrls: List<String>?, referer: String? = null) {
|
suspend fun LoadResponse.addTrailer(trailerUrls: List<String>?, referer: String? = null) {
|
||||||
if (!isTrailersEnabled || trailerUrls == null) return
|
if (!isTrailersEnabled || trailerUrls == null) return
|
||||||
val newTrailers = trailerUrls.apmap { trailerUrl ->
|
val trailers = trailerUrls.apmap { trailerUrl ->
|
||||||
try {
|
val links = arrayListOf<ExtractorLink>()
|
||||||
loadExtractor(trailerUrl, referer)
|
val subs = arrayListOf<SubtitleFile>()
|
||||||
} catch (e: Exception) {
|
loadExtractor(trailerUrl, referer, { subs.add(it) }, { links.add(it) })
|
||||||
logError(e)
|
links to subs
|
||||||
emptyList()
|
}.map { (links, subs) -> TrailerData(links, subs) }
|
||||||
}
|
this.trailers.addAll(trailers)
|
||||||
}.flatten().distinct()
|
|
||||||
addTrailer(newTrailers)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LoadResponse.addImdbId(id: String?) {
|
fun LoadResponse.addImdbId(id: String?) {
|
||||||
|
@ -1087,7 +1083,7 @@ data class TorrentLoadResponse(
|
||||||
override var rating: Int? = null,
|
override var rating: Int? = null,
|
||||||
override var tags: List<String>? = null,
|
override var tags: List<String>? = null,
|
||||||
override var duration: Int? = null,
|
override var duration: Int? = null,
|
||||||
override var trailers: List<ExtractorLink>? = null,
|
override var trailers: MutableList<TrailerData> = mutableListOf(),
|
||||||
override var recommendations: List<SearchResponse>? = null,
|
override var recommendations: List<SearchResponse>? = null,
|
||||||
override var actors: List<ActorData>? = null,
|
override var actors: List<ActorData>? = null,
|
||||||
override var comingSoon: Boolean = false,
|
override var comingSoon: Boolean = false,
|
||||||
|
@ -1115,7 +1111,7 @@ data class AnimeLoadResponse(
|
||||||
|
|
||||||
override var rating: Int? = null,
|
override var rating: Int? = null,
|
||||||
override var duration: Int? = null,
|
override var duration: Int? = null,
|
||||||
override var trailers: List<ExtractorLink>? = null,
|
override var trailers: MutableList<TrailerData> = mutableListOf(),
|
||||||
override var recommendations: List<SearchResponse>? = null,
|
override var recommendations: List<SearchResponse>? = null,
|
||||||
override var actors: List<ActorData>? = null,
|
override var actors: List<ActorData>? = null,
|
||||||
override var comingSoon: Boolean = false,
|
override var comingSoon: Boolean = false,
|
||||||
|
@ -1163,7 +1159,7 @@ data class LiveStreamLoadResponse(
|
||||||
override var rating: Int? = null,
|
override var rating: Int? = null,
|
||||||
override var tags: List<String>? = null,
|
override var tags: List<String>? = null,
|
||||||
override var duration: Int? = null,
|
override var duration: Int? = null,
|
||||||
override var trailers: List<ExtractorLink>? = null,
|
override var trailers: MutableList<TrailerData> = mutableListOf(),
|
||||||
override var recommendations: List<SearchResponse>? = null,
|
override var recommendations: List<SearchResponse>? = null,
|
||||||
override var actors: List<ActorData>? = null,
|
override var actors: List<ActorData>? = null,
|
||||||
override var comingSoon: Boolean = false,
|
override var comingSoon: Boolean = false,
|
||||||
|
@ -1185,7 +1181,7 @@ data class MovieLoadResponse(
|
||||||
override var rating: Int? = null,
|
override var rating: Int? = null,
|
||||||
override var tags: List<String>? = null,
|
override var tags: List<String>? = null,
|
||||||
override var duration: Int? = null,
|
override var duration: Int? = null,
|
||||||
override var trailers: List<ExtractorLink>? = null,
|
override var trailers: MutableList<TrailerData> = mutableListOf(),
|
||||||
override var recommendations: List<SearchResponse>? = null,
|
override var recommendations: List<SearchResponse>? = null,
|
||||||
override var actors: List<ActorData>? = null,
|
override var actors: List<ActorData>? = null,
|
||||||
override var comingSoon: Boolean = false,
|
override var comingSoon: Boolean = false,
|
||||||
|
@ -1306,7 +1302,7 @@ data class TvSeriesLoadResponse(
|
||||||
override var rating: Int? = null,
|
override var rating: Int? = null,
|
||||||
override var tags: List<String>? = null,
|
override var tags: List<String>? = null,
|
||||||
override var duration: Int? = null,
|
override var duration: Int? = null,
|
||||||
override var trailers: List<ExtractorLink>? = null,
|
override var trailers: MutableList<TrailerData> = mutableListOf(),
|
||||||
override var recommendations: List<SearchResponse>? = null,
|
override var recommendations: List<SearchResponse>? = null,
|
||||||
override var actors: List<ActorData>? = null,
|
override var actors: List<ActorData>? = null,
|
||||||
override var comingSoon: Boolean = false,
|
override var comingSoon: Boolean = false,
|
||||||
|
|
|
@ -56,8 +56,9 @@ class AnimeFlickProvider : MainAPI() {
|
||||||
val title = doc.selectFirst("h2.title")!!.text()
|
val title = doc.selectFirst("h2.title")!!.text()
|
||||||
|
|
||||||
val yearText = doc.selectFirst(".trending-year")?.text()
|
val yearText = doc.selectFirst(".trending-year")?.text()
|
||||||
val year = if (yearText != null) Regex("""(\d{4})""").find(yearText)?.destructured?.component1()
|
val year =
|
||||||
?.toIntOrNull() else null
|
if (yearText != null) Regex("""(\d{4})""").find(yearText)?.destructured?.component1()
|
||||||
|
?.toIntOrNull() else null
|
||||||
val description = doc.selectFirst("p")?.text()
|
val description = doc.selectFirst("p")?.text()
|
||||||
|
|
||||||
val genres = doc.select("a[href*=\"genre-\"]").map { it.text() }
|
val genres = doc.select("a[href*=\"genre-\"]").map { it.text() }
|
||||||
|
@ -95,7 +96,7 @@ class AnimeFlickProvider : MainAPI() {
|
||||||
var alreadyAdded = false
|
var alreadyAdded = false
|
||||||
for (extractor in extractorApis) {
|
for (extractor in extractorApis) {
|
||||||
if (link.startsWith(extractor.mainUrl)) {
|
if (link.startsWith(extractor.mainUrl)) {
|
||||||
extractor.getSafeUrl(link, data)?.forEach(callback)
|
extractor.getSafeUrl(link, data, subtitleCallback, callback)
|
||||||
alreadyAdded = true
|
alreadyAdded = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import com.lagradost.nicehttp.NiceResponse
|
import com.lagradost.nicehttp.NiceResponse
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
class AnimeIndoProvider : MainAPI() {
|
class AnimeIndoProvider : MainAPI() {
|
||||||
override var mainUrl = "https://animeindo.sbs"
|
override var mainUrl = "https://animeindo.sbs"
|
||||||
|
@ -183,7 +182,7 @@ class AnimeIndoProvider : MainAPI() {
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
}.apmap {
|
}.apmap {
|
||||||
loadExtractor(it, data, callback)
|
loadExtractor(it, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -112,7 +112,8 @@ class AnimeSailProvider : MainAPI() {
|
||||||
)
|
)
|
||||||
val episodes = document.select("ul.daftar > li").map {
|
val episodes = document.select("ul.daftar > li").map {
|
||||||
val header = it.select("a").text().trim()
|
val header = it.select("a").text().trim()
|
||||||
val name = Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header
|
val name =
|
||||||
|
Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header
|
||||||
val link = fixUrl(it.select("a").attr("href"))
|
val link = fixUrl(it.select("a").attr("href"))
|
||||||
Episode(link, name = name)
|
Episode(link, name = name)
|
||||||
}.reversed()
|
}.reversed()
|
||||||
|
@ -157,7 +158,8 @@ class AnimeSailProvider : MainAPI() {
|
||||||
iframe.contains("/race/") -> "Race"
|
iframe.contains("/race/") -> "Race"
|
||||||
else -> this.name
|
else -> this.name
|
||||||
}
|
}
|
||||||
val quality = Regex("\\.([0-9]{3,4})\\.").find(link)?.groupValues?.get(1)
|
val quality =
|
||||||
|
Regex("\\.([0-9]{3,4})\\.").find(link)?.groupValues?.get(1)
|
||||||
callback.invoke(
|
callback.invoke(
|
||||||
ExtractorLink(
|
ExtractorLink(
|
||||||
source = source,
|
source = source,
|
||||||
|
@ -174,11 +176,11 @@ class AnimeSailProvider : MainAPI() {
|
||||||
iframe.startsWith("$mainUrl/utils/player/framezilla/") || iframe.startsWith("https://uservideo.xyz") -> {
|
iframe.startsWith("$mainUrl/utils/player/framezilla/") || iframe.startsWith("https://uservideo.xyz") -> {
|
||||||
request(iframe, ref = data).document.select("iframe").attr("src")
|
request(iframe, ref = data).document.select("iframe").attr("src")
|
||||||
.let { link ->
|
.let { link ->
|
||||||
loadExtractor(fixUrl(link), mainUrl, callback)
|
loadExtractor(fixUrl(link), mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
loadExtractor(iframe, mainUrl, callback)
|
loadExtractor(iframe, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,12 @@ package com.lagradost.cloudstream3.animeproviders
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.utils.*
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.Qualities
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
|
|
||||||
class AnimefenixProvider:MainAPI() {
|
class AnimefenixProvider:MainAPI() {
|
||||||
|
@ -179,7 +180,7 @@ class AnimefenixProvider:MainAPI() {
|
||||||
|
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
loadExtractor(links, data, callback)
|
loadExtractor(links, data, subtitleCallback, callback)
|
||||||
|
|
||||||
argamap({
|
argamap({
|
||||||
if (links.contains("AmaNormal")) {
|
if (links.contains("AmaNormal")) {
|
||||||
|
|
|
@ -2,11 +2,13 @@ package com.lagradost.cloudstream3.movieproviders
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.utils.*
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
|
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
|
||||||
|
import com.lagradost.cloudstream3.utils.Qualities
|
||||||
|
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
class AnimeflvIOProvider:MainAPI() {
|
class AnimeflvIOProvider:MainAPI() {
|
||||||
override var mainUrl = "https://animeflv.io" //Also scrapes from animeid.to
|
override var mainUrl = "https://animeflv.io" //Also scrapes from animeid.to
|
||||||
|
@ -220,7 +222,7 @@ class AnimeflvIOProvider:MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadExtractor(url, data, callback)
|
loadExtractor(url, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,7 +173,7 @@ class AnimeflvnetProvider : MainAPI() {
|
||||||
it.replace("https://embedsb.com/e/", "https://watchsb.com/e/")
|
it.replace("https://embedsb.com/e/", "https://watchsb.com/e/")
|
||||||
.replace("https://ok.ru", "http://ok.ru")
|
.replace("https://ok.ru", "http://ok.ru")
|
||||||
}.apmap {
|
}.apmap {
|
||||||
loadExtractor(it, data, callback)
|
loadExtractor(it, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ package com.lagradost.cloudstream3.animeproviders
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
|
||||||
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
@ -126,7 +124,7 @@ class AnimekisaProvider : MainAPI() {
|
||||||
): Boolean {
|
): Boolean {
|
||||||
app.get(data).document.select("#servers-list ul.nav li a").apmap {
|
app.get(data).document.select("#servers-list ul.nav li a").apmap {
|
||||||
val server = it.attr("data-embed")
|
val server = it.attr("data-embed")
|
||||||
loadExtractor(server, data, callback)
|
loadExtractor(server, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -338,7 +338,11 @@ class GogoanimeProvider : MainAPI() {
|
||||||
@JsonProperty("default") val default: String? = null
|
@JsonProperty("default") val default: String? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
private suspend fun extractVideos(uri: String, callback: (ExtractorLink) -> Unit) {
|
private suspend fun extractVideos(
|
||||||
|
uri: String,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
val doc = app.get(uri).document
|
val doc = app.get(uri).document
|
||||||
|
|
||||||
val iframe = fixUrlNull(doc.selectFirst("div.play-video > iframe")?.attr("src")) ?: return
|
val iframe = fixUrlNull(doc.selectFirst("div.play-video > iframe")?.attr("src")) ?: return
|
||||||
|
@ -366,7 +370,7 @@ class GogoanimeProvider : MainAPI() {
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val url = it.attr("href")
|
val url = it.attr("href")
|
||||||
loadExtractor(url, null, callback)
|
loadExtractor(url, null, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
|
@ -378,7 +382,7 @@ class GogoanimeProvider : MainAPI() {
|
||||||
val status = element.attr("data-status") ?: return@forEach
|
val status = element.attr("data-status") ?: return@forEach
|
||||||
if (status != "1") return@forEach
|
if (status != "1") return@forEach
|
||||||
val data = element.attr("data-video") ?: return@forEach
|
val data = element.attr("data-video") ?: return@forEach
|
||||||
loadExtractor(data, streamingResponse.url, callback)
|
loadExtractor(data, streamingResponse.url, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
val iv = "3134003223491201"
|
val iv = "3134003223491201"
|
||||||
|
@ -405,7 +409,7 @@ class GogoanimeProvider : MainAPI() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
): Boolean {
|
): Boolean {
|
||||||
extractVideos(data, callback)
|
extractVideos(data, subtitleCallback, callback)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,9 @@ class GomunimeProvider : MainAPI() {
|
||||||
document.select(".bixbox.bxcl.epcheck > script").toString().trim()
|
document.select(".bixbox.bxcl.epcheck > script").toString().trim()
|
||||||
)?.groupValues?.get(1).toString().replace(Regex("""\\"""), "").trim()
|
)?.groupValues?.get(1).toString().replace(Regex("""\\"""), "").trim()
|
||||||
).map {
|
).map {
|
||||||
val name = Regex("(Episode\\s?[0-9]+)").find(it.epTitle.toString())?.groupValues?.getOrNull(0) ?: it.epTitle
|
val name =
|
||||||
|
Regex("(Episode\\s?[0-9]+)").find(it.epTitle.toString())?.groupValues?.getOrNull(0)
|
||||||
|
?: it.epTitle
|
||||||
val link = it.epLink
|
val link = it.epLink
|
||||||
Episode(link, name)
|
Episode(link, name)
|
||||||
}.reversed()
|
}.reversed()
|
||||||
|
@ -194,7 +196,7 @@ class GomunimeProvider : MainAPI() {
|
||||||
safeApiCall {
|
safeApiCall {
|
||||||
when {
|
when {
|
||||||
it.second.contains("frame") -> {
|
it.second.contains("frame") -> {
|
||||||
loadExtractor(it.first, data, callback)
|
loadExtractor(it.first, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
it.second.contains("hls") -> {
|
it.second.contains("hls") -> {
|
||||||
app.post(
|
app.post(
|
||||||
|
|
|
@ -3,12 +3,12 @@ package com.lagradost.cloudstream3.animeproviders
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.utils.*
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
|
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
|
||||||
|
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.collections.List
|
|
||||||
|
|
||||||
|
|
||||||
class JKAnimeProvider : MainAPI() {
|
class JKAnimeProvider : MainAPI() {
|
||||||
|
@ -34,9 +34,18 @@ class JKAnimeProvider : MainAPI() {
|
||||||
|
|
||||||
override suspend fun getMainPage(): HomePageResponse {
|
override suspend fun getMainPage(): HomePageResponse {
|
||||||
val urls = listOf(
|
val urls = listOf(
|
||||||
Pair("$mainUrl/directorio/?filtro=fecha&tipo=TV&estado=1&fecha=none&temporada=none&orden=desc", "En emisión"),
|
Pair(
|
||||||
Pair("$mainUrl/directorio/?filtro=fecha&tipo=none&estado=none&fecha=none&temporada=none&orden=none", "Animes"),
|
"$mainUrl/directorio/?filtro=fecha&tipo=TV&estado=1&fecha=none&temporada=none&orden=desc",
|
||||||
Pair("$mainUrl/directorio/?filtro=fecha&tipo=Movie&estado=none&fecha=none&temporada=none&orden=none", "Películas"),
|
"En emisión"
|
||||||
|
),
|
||||||
|
Pair(
|
||||||
|
"$mainUrl/directorio/?filtro=fecha&tipo=none&estado=none&fecha=none&temporada=none&orden=none",
|
||||||
|
"Animes"
|
||||||
|
),
|
||||||
|
Pair(
|
||||||
|
"$mainUrl/directorio/?filtro=fecha&tipo=Movie&estado=none&fecha=none&temporada=none&orden=none",
|
||||||
|
"Películas"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
val items = ArrayList<HomePageList>()
|
val items = ArrayList<HomePageList>()
|
||||||
|
@ -46,12 +55,14 @@ class JKAnimeProvider : MainAPI() {
|
||||||
"Últimos episodios",
|
"Últimos episodios",
|
||||||
app.get(mainUrl).document.select(".listadoanime-home a.bloqq").map {
|
app.get(mainUrl).document.select(".listadoanime-home a.bloqq").map {
|
||||||
val title = it.selectFirst("h5")?.text()
|
val title = it.selectFirst("h5")?.text()
|
||||||
val dubstat =if (title!!.contains("Latino") || title.contains("Castellano"))
|
val dubstat = if (title!!.contains("Latino") || title.contains("Castellano"))
|
||||||
DubStatus.Dubbed else DubStatus.Subbed
|
DubStatus.Dubbed else DubStatus.Subbed
|
||||||
val poster = it.selectFirst(".anime__sidebar__comment__item__pic img")?.attr("src") ?: ""
|
val poster =
|
||||||
|
it.selectFirst(".anime__sidebar__comment__item__pic img")?.attr("src") ?: ""
|
||||||
val epRegex = Regex("/(\\d+)/|/especial/|/ova/")
|
val epRegex = Regex("/(\\d+)/|/especial/|/ova/")
|
||||||
val url = it.attr("href").replace(epRegex, "")
|
val url = it.attr("href").replace(epRegex, "")
|
||||||
val epNum = it.selectFirst("h6")?.text()?.replace("Episodio ", "")?.toIntOrNull()
|
val epNum =
|
||||||
|
it.selectFirst("h6")?.text()?.replace("Episodio ", "")?.toIntOrNull()
|
||||||
newAnimeSearchResponse(title, url) {
|
newAnimeSearchResponse(title, url) {
|
||||||
this.posterUrl = poster
|
this.posterUrl = poster
|
||||||
addDubStatus(dubstat, epNum)
|
addDubStatus(dubstat, epNum)
|
||||||
|
@ -82,12 +93,12 @@ class JKAnimeProvider : MainAPI() {
|
||||||
return HomePageResponse(items)
|
return HomePageResponse(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class MainSearch (
|
data class MainSearch(
|
||||||
@JsonProperty("animes") val animes: List<Animes>,
|
@JsonProperty("animes") val animes: List<Animes>,
|
||||||
@JsonProperty("anime_types") val animeTypes: AnimeTypes
|
@JsonProperty("anime_types") val animeTypes: AnimeTypes
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Animes (
|
data class Animes(
|
||||||
@JsonProperty("id") val id: String,
|
@JsonProperty("id") val id: String,
|
||||||
@JsonProperty("slug") val slug: String,
|
@JsonProperty("slug") val slug: String,
|
||||||
@JsonProperty("title") val title: String,
|
@JsonProperty("title") val title: String,
|
||||||
|
@ -98,7 +109,7 @@ class JKAnimeProvider : MainAPI() {
|
||||||
@JsonProperty("thumbnail") val thumbnail: String
|
@JsonProperty("thumbnail") val thumbnail: String
|
||||||
)
|
)
|
||||||
|
|
||||||
data class AnimeTypes (
|
data class AnimeTypes(
|
||||||
@JsonProperty("TV") val TV: String,
|
@JsonProperty("TV") val TV: String,
|
||||||
@JsonProperty("OVA") val OVA: String,
|
@JsonProperty("OVA") val OVA: String,
|
||||||
@JsonProperty("Movie") val Movie: String,
|
@JsonProperty("Movie") val Movie: String,
|
||||||
|
@ -134,7 +145,8 @@ class JKAnimeProvider : MainAPI() {
|
||||||
val title = doc.selectFirst(".anime__details__title > h3")?.text()
|
val title = doc.selectFirst(".anime__details__title > h3")?.text()
|
||||||
val type = doc.selectFirst(".anime__details__text")?.text()
|
val type = doc.selectFirst(".anime__details__text")?.text()
|
||||||
val description = doc.selectFirst(".anime__details__text > p")?.text()
|
val description = doc.selectFirst(".anime__details__text > p")?.text()
|
||||||
val genres = doc.select("div.col-lg-6:nth-child(1) > ul:nth-child(1) > li:nth-child(2) > a").map { it.text() }
|
val genres = doc.select("div.col-lg-6:nth-child(1) > ul:nth-child(1) > li:nth-child(2) > a")
|
||||||
|
.map { it.text() }
|
||||||
val status = when (doc.selectFirst("span.enemision")?.text()) {
|
val status = when (doc.selectFirst("span.enemision")?.text()) {
|
||||||
"En emisión" -> ShowStatus.Ongoing
|
"En emisión" -> ShowStatus.Ongoing
|
||||||
"Concluido" -> ShowStatus.Completed
|
"Concluido" -> ShowStatus.Completed
|
||||||
|
@ -143,7 +155,8 @@ class JKAnimeProvider : MainAPI() {
|
||||||
val animeID = doc.selectFirst("div.ml-2")?.attr("data-anime")?.toInt()
|
val animeID = doc.selectFirst("div.ml-2")?.attr("data-anime")?.toInt()
|
||||||
val animeeps = "$mainUrl/ajax/last_episode/$animeID/"
|
val animeeps = "$mainUrl/ajax/last_episode/$animeID/"
|
||||||
val jsoneps = app.get(animeeps).text
|
val jsoneps = app.get(animeeps).text
|
||||||
val lastepnum = jsoneps.substringAfter("{\"number\":\"").substringBefore("\",\"title\"").toInt()
|
val lastepnum =
|
||||||
|
jsoneps.substringAfter("{\"number\":\"").substringBefore("\",\"title\"").toInt()
|
||||||
val episodes = (1..lastepnum).map {
|
val episodes = (1..lastepnum).map {
|
||||||
val link = "${url.removeSuffix("/")}/$it"
|
val link = "${url.removeSuffix("/")}/$it"
|
||||||
Episode(link)
|
Episode(link)
|
||||||
|
@ -158,7 +171,7 @@ class JKAnimeProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class Nozomi (
|
data class Nozomi(
|
||||||
@JsonProperty("file") val file: String?
|
@JsonProperty("file") val file: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -193,16 +206,17 @@ class JKAnimeProvider : MainAPI() {
|
||||||
if (script.data().contains("var video = []")) {
|
if (script.data().contains("var video = []")) {
|
||||||
val videos = script.data().replace("\\/", "/")
|
val videos = script.data().replace("\\/", "/")
|
||||||
fetchUrls(videos).map {
|
fetchUrls(videos).map {
|
||||||
it.replace("$mainUrl/jkfembed.php?u=","https://embedsito.com/v/")
|
it.replace("$mainUrl/jkfembed.php?u=", "https://embedsito.com/v/")
|
||||||
.replace("$mainUrl/jkokru.php?u=","http://ok.ru/videoembed/")
|
.replace("$mainUrl/jkokru.php?u=", "http://ok.ru/videoembed/")
|
||||||
.replace("$mainUrl/jkvmixdrop.php?u=","https://mixdrop.co/e/")
|
.replace("$mainUrl/jkvmixdrop.php?u=", "https://mixdrop.co/e/")
|
||||||
.replace("$mainUrl/jk.php?u=","$mainUrl/")
|
.replace("$mainUrl/jk.php?u=", "$mainUrl/")
|
||||||
}.apmap { link ->
|
}.apmap { link ->
|
||||||
loadExtractor(link, data, callback)
|
loadExtractor(link, data, subtitleCallback, callback)
|
||||||
if (link.contains("um2.php")) {
|
if (link.contains("um2.php")) {
|
||||||
val doc = app.get(link, referer = data).document
|
val doc = app.get(link, referer = data).document
|
||||||
val gsplaykey = doc.select("form input[value]").attr("value")
|
val gsplaykey = doc.select("form input[value]").attr("value")
|
||||||
val postgsplay = app.post("$mainUrl/gsplay/redirect_post.php",
|
app.post(
|
||||||
|
"$mainUrl/gsplay/redirect_post.php",
|
||||||
headers = mapOf(
|
headers = mapOf(
|
||||||
"Host" to "jkanime.net",
|
"Host" to "jkanime.net",
|
||||||
"User-Agent" to USER_AGENT,
|
"User-Agent" to USER_AGENT,
|
||||||
|
@ -219,11 +233,14 @@ class JKAnimeProvider : MainAPI() {
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
"Sec-Fetch-Site" to "same-origin",
|
||||||
"TE" to "trailers",
|
"TE" to "trailers",
|
||||||
"Pragma" to "no-cache",
|
"Pragma" to "no-cache",
|
||||||
"Cache-Control" to "no-cache",),
|
"Cache-Control" to "no-cache",
|
||||||
data = mapOf(Pair("data",gsplaykey)),
|
),
|
||||||
allowRedirects = false).okhttpResponse.headers.values("location").apmap { loc ->
|
data = mapOf(Pair("data", gsplaykey)),
|
||||||
val postkey = loc.replace("/gsplay/player.html#","")
|
allowRedirects = false
|
||||||
val nozomitext = app.post("$mainUrl/gsplay/api.php",
|
).okhttpResponse.headers.values("location").apmap { loc ->
|
||||||
|
val postkey = loc.replace("/gsplay/player.html#", "")
|
||||||
|
val nozomitext = app.post(
|
||||||
|
"$mainUrl/gsplay/api.php",
|
||||||
headers = mapOf(
|
headers = mapOf(
|
||||||
"Host" to "jkanime.net",
|
"Host" to "jkanime.net",
|
||||||
"User-Agent" to USER_AGENT,
|
"User-Agent" to USER_AGENT,
|
||||||
|
@ -236,8 +253,9 @@ class JKAnimeProvider : MainAPI() {
|
||||||
"Connection" to "keep-alive",
|
"Connection" to "keep-alive",
|
||||||
"Sec-Fetch-Dest" to "empty",
|
"Sec-Fetch-Dest" to "empty",
|
||||||
"Sec-Fetch-Mode" to "cors",
|
"Sec-Fetch-Mode" to "cors",
|
||||||
"Sec-Fetch-Site" to "same-origin",),
|
"Sec-Fetch-Site" to "same-origin",
|
||||||
data = mapOf(Pair("v",postkey)),
|
),
|
||||||
|
data = mapOf(Pair("v", postkey)),
|
||||||
allowRedirects = false
|
allowRedirects = false
|
||||||
).text
|
).text
|
||||||
val json = parseJson<Nozomi>(nozomitext)
|
val json = parseJson<Nozomi>(nozomitext)
|
||||||
|
@ -245,13 +263,20 @@ class JKAnimeProvider : MainAPI() {
|
||||||
if (nozomiurl.isEmpty()) null else
|
if (nozomiurl.isEmpty()) null else
|
||||||
nozomiurl.forEach { url ->
|
nozomiurl.forEach { url ->
|
||||||
val nozominame = "Nozomi"
|
val nozominame = "Nozomi"
|
||||||
streamClean(nozominame, url!!, "", null, callback, url.contains(".m3u8"))
|
streamClean(
|
||||||
|
nozominame,
|
||||||
|
url!!,
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
callback,
|
||||||
|
url.contains(".m3u8")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (link.contains("um.php")) {
|
if (link.contains("um.php")) {
|
||||||
val desutext = app.get(link, referer = data).text
|
val desutext = app.get(link, referer = data).text
|
||||||
val desuRegex = Regex("((https:|http:)\\/\\/.*\\.m3u8)")
|
val desuRegex = Regex("((https:|http:)//.*\\.m3u8)")
|
||||||
val file = desuRegex.find(desutext)?.value
|
val file = desuRegex.find(desutext)?.value
|
||||||
val namedesu = "Desu"
|
val namedesu = "Desu"
|
||||||
generateM3u8(
|
generateM3u8(
|
||||||
|
@ -259,13 +284,31 @@ class JKAnimeProvider : MainAPI() {
|
||||||
file!!,
|
file!!,
|
||||||
mainUrl,
|
mainUrl,
|
||||||
).forEach { desurl ->
|
).forEach { desurl ->
|
||||||
streamClean(namedesu, desurl.url, mainUrl, desurl.quality.toString(), callback, true)
|
streamClean(
|
||||||
|
namedesu,
|
||||||
|
desurl.url,
|
||||||
|
mainUrl,
|
||||||
|
desurl.quality.toString(),
|
||||||
|
callback,
|
||||||
|
true
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (link.contains("jkmedia")) {
|
if (link.contains("jkmedia")) {
|
||||||
app.get(link, referer = data, allowRedirects = false).okhttpResponse.headers.values("location").apmap { xtremeurl ->
|
app.get(
|
||||||
|
link,
|
||||||
|
referer = data,
|
||||||
|
allowRedirects = false
|
||||||
|
).okhttpResponse.headers.values("location").apmap { xtremeurl ->
|
||||||
val namex = "Xtreme S"
|
val namex = "Xtreme S"
|
||||||
streamClean(namex, xtremeurl, "", null, callback, xtremeurl.contains(".m3u8"))
|
streamClean(
|
||||||
|
namex,
|
||||||
|
xtremeurl,
|
||||||
|
"",
|
||||||
|
null,
|
||||||
|
callback,
|
||||||
|
xtremeurl.contains(".m3u8")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ 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.utils.loadExtractor
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.Jsoup
|
|
||||||
|
|
||||||
class KimCartoonProvider : MainAPI() {
|
class KimCartoonProvider : MainAPI() {
|
||||||
|
|
||||||
|
@ -83,9 +82,9 @@ class KimCartoonProvider : MainAPI() {
|
||||||
|
|
||||||
override suspend fun quickSearch(query: String): List<SearchResponse> {
|
override suspend fun quickSearch(query: String): List<SearchResponse> {
|
||||||
return app.post(
|
return app.post(
|
||||||
"$mainUrl/Ajax/SearchSuggest",
|
"$mainUrl/Ajax/SearchSuggest",
|
||||||
data = mapOf("keyword" to query)
|
data = mapOf("keyword" to query)
|
||||||
).document.select("a").map {
|
).document.select("a").map {
|
||||||
AnimeSearchResponse(
|
AnimeSearchResponse(
|
||||||
it.text(),
|
it.text(),
|
||||||
it.attr("href"),
|
it.attr("href"),
|
||||||
|
@ -143,7 +142,7 @@ class KimCartoonProvider : MainAPI() {
|
||||||
servers.apmap {
|
servers.apmap {
|
||||||
app.get(it).document.select("#my_video_1").attr("src").let { iframe ->
|
app.get(it).document.select("#my_video_1").attr("src").let { iframe ->
|
||||||
if (iframe.isNotEmpty()) {
|
if (iframe.isNotEmpty()) {
|
||||||
loadExtractor(iframe, "$mainUrl/", callback)
|
loadExtractor(iframe, "$mainUrl/", subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
//There are other servers, but they require some work to do
|
//There are other servers, but they require some work to do
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,7 +180,7 @@ class KuronimeProvider : MainAPI() {
|
||||||
safeApiCall {
|
safeApiCall {
|
||||||
when {
|
when {
|
||||||
it.startsWith("https://animeku.org") -> invokeKuroSource(it, callback)
|
it.startsWith("https://animeku.org") -> invokeKuroSource(it, callback)
|
||||||
else -> loadExtractor(it, mainUrl, callback)
|
else -> loadExtractor(it, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,7 +148,7 @@ class MonoschinosProvider : MainAPI() {
|
||||||
callback.invoke(link)
|
callback.invoke(link)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loadExtractor(url, mainUrl, callback)
|
loadExtractor(url, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -163,7 +163,7 @@ class MundoDonghuaProvider : MainAPI() {
|
||||||
}.toList().apmap {
|
}.toList().apmap {
|
||||||
val unpack = getAndUnpack(it).replace("diasfem","embedsito")
|
val unpack = getAndUnpack(it).replace("diasfem","embedsito")
|
||||||
fetchUrls(unpack).apmap { url ->
|
fetchUrls(unpack).apmap { url ->
|
||||||
loadExtractor(url, data, callback)
|
loadExtractor(url, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
if (unpack.contains("protea_tab")) {
|
if (unpack.contains("protea_tab")) {
|
||||||
val protearegex = Regex("(protea_tab.*slug.*,type)")
|
val protearegex = Regex("(protea_tab.*slug.*,type)")
|
||||||
|
|
|
@ -169,7 +169,7 @@ class NeonimeProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
source.apmap {
|
source.apmap {
|
||||||
loadExtractor(it, data, callback)
|
loadExtractor(it, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -339,7 +339,7 @@ class NineAnimeProvider : MainAPI() {
|
||||||
val encodedStreamUrl =
|
val encodedStreamUrl =
|
||||||
getEpisodeLinks(it.attr("data-link-id"))?.result?.url ?: return@apmap
|
getEpisodeLinks(it.attr("data-link-id"))?.result?.url ?: return@apmap
|
||||||
val url = decodeVrf(encodedStreamUrl)
|
val url = decodeVrf(encodedStreamUrl)
|
||||||
if (!loadExtractor(url, callback = callback, referer = mainUrl)) {
|
if (!loadExtractor(url, mainUrl, subtitleCallback, callback)) {
|
||||||
callback(
|
callback(
|
||||||
ExtractorLink(
|
ExtractorLink(
|
||||||
this.name,
|
this.name,
|
||||||
|
|
|
@ -3,10 +3,10 @@ package com.lagradost.cloudstream3.animeproviders
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||||
import com.lagradost.cloudstream3.utils.*
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
class NontonAnimeIDProvider : MainAPI() {
|
class NontonAnimeIDProvider : MainAPI() {
|
||||||
override var mainUrl = "https://75.119.159.228"
|
override var mainUrl = "https://75.119.159.228"
|
||||||
|
@ -175,13 +175,17 @@ class NontonAnimeIDProvider : MainAPI() {
|
||||||
)
|
)
|
||||||
).parsed<EpResponse>().content
|
).parsed<EpResponse>().content
|
||||||
).select("li").map {
|
).select("li").map {
|
||||||
val name = Regex("(Episode\\s?[0-9]+)").find(it.selectFirst("a")?.text().toString())?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text()
|
val name = Regex("(Episode\\s?[0-9]+)").find(
|
||||||
|
it.selectFirst("a")?.text().toString()
|
||||||
|
)?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text()
|
||||||
val link = fixUrl(it.selectFirst("a")!!.attr("href"))
|
val link = fixUrl(it.selectFirst("a")!!.attr("href"))
|
||||||
Episode(link, name)
|
Episode(link, name)
|
||||||
}.reversed()
|
}.reversed()
|
||||||
} else {
|
} else {
|
||||||
document.select("ul.misha_posts_wrap2 > li").map {
|
document.select("ul.misha_posts_wrap2 > li").map {
|
||||||
val name = Regex("(Episode\\s?[0-9]+)").find(it.selectFirst("a")?.text().toString())?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text()
|
val name = Regex("(Episode\\s?[0-9]+)").find(
|
||||||
|
it.selectFirst("a")?.text().toString()
|
||||||
|
)?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text()
|
||||||
val link = it.select("a").attr("href")
|
val link = it.select("a").attr("href")
|
||||||
Episode(link, name)
|
Episode(link, name)
|
||||||
}.reversed()
|
}.reversed()
|
||||||
|
@ -243,7 +247,7 @@ class NontonAnimeIDProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
sources.apmap {
|
sources.apmap {
|
||||||
loadExtractor(it, "$mainUrl/", callback)
|
loadExtractor(it, "$mainUrl/", subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -193,7 +193,7 @@ class OploverzProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
sources.apmap {
|
sources.apmap {
|
||||||
loadExtractor(it, data, callback)
|
loadExtractor(it, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -189,7 +189,7 @@ class OtakudesuProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadExtractor(sources, data, callback)
|
loadExtractor(sources, data, subtitleCallback, callback)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,8 @@ class WcoProvider : MainAPI() {
|
||||||
nameHeader.attr("href").replace("/watch/", "/anime/")
|
nameHeader.attr("href").replace("/watch/", "/anime/")
|
||||||
.replace(Regex("-episode-.*"), "/")
|
.replace(Regex("-episode-.*"), "/")
|
||||||
val isDub =
|
val isDub =
|
||||||
filmPoster!!.selectFirst("> div.film-poster-quality")?.text()?.contains("DUB")
|
filmPoster!!.selectFirst("> div.film-poster-quality")?.text()
|
||||||
|
?.contains("DUB")
|
||||||
?: false
|
?: false
|
||||||
val poster = filmPoster.selectFirst("> img")!!.attr("data-src")
|
val poster = filmPoster.selectFirst("> img")!!.attr("data-src")
|
||||||
val set: EnumSet<DubStatus> =
|
val set: EnumSet<DubStatus> =
|
||||||
|
@ -231,8 +232,8 @@ class WcoProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (server in servers) {
|
for (server in servers) {
|
||||||
WcoStream().getSafeUrl(server["link"].toString(), "")?.forEach(callback)
|
WcoStream().getSafeUrl(server["link"].toString(), null, subtitleCallback, callback)
|
||||||
Mcloud().getSafeUrl(server["link"].toString(), "")?.forEach(callback)
|
Mcloud().getSafeUrl(server["link"].toString(), null, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,17 +55,18 @@ class ZoroProvider : MainAPI() {
|
||||||
private fun Element.toSearchResult(): SearchResponse? {
|
private fun Element.toSearchResult(): SearchResponse? {
|
||||||
val href = fixUrl(this.select("a").attr("href"))
|
val href = fixUrl(this.select("a").attr("href"))
|
||||||
val title = this.select("h3.film-name").text()
|
val title = this.select("h3.film-name").text()
|
||||||
val dubSub = this.select(".film-poster > .tick.ltr").text()
|
val dubSub = this.select(".film-poster > .tick.ltr").text()
|
||||||
//val episodes = this.selectFirst(".film-poster > .tick-eps")?.text()?.toIntOrNull()
|
//val episodes = this.selectFirst(".film-poster > .tick-eps")?.text()?.toIntOrNull()
|
||||||
|
|
||||||
val dubExist = dubSub.contains("dub", ignoreCase = true)
|
val dubExist = dubSub.contains("dub", ignoreCase = true)
|
||||||
val subExist = dubSub.contains("sub", ignoreCase = true)
|
val subExist = dubSub.contains("sub", ignoreCase = true)
|
||||||
val episodes = this.selectFirst(".film-poster > .tick.rtl > .tick-eps")?.text()?.let { eps ->
|
val episodes =
|
||||||
//println("REGEX:::: $eps")
|
this.selectFirst(".film-poster > .tick.rtl > .tick-eps")?.text()?.let { eps ->
|
||||||
// current episode / max episode
|
//println("REGEX:::: $eps")
|
||||||
//Regex("Ep (\\d+)/(\\d+)")
|
// current episode / max episode
|
||||||
epRegex.find(eps)?.groupValues?.get(1)?.toIntOrNull()
|
//Regex("Ep (\\d+)/(\\d+)")
|
||||||
}
|
epRegex.find(eps)?.groupValues?.get(1)?.toIntOrNull()
|
||||||
|
}
|
||||||
if (href.contains("/news/") || title.trim().equals("News", ignoreCase = true)) return null
|
if (href.contains("/news/") || title.trim().equals("News", ignoreCase = true)) return null
|
||||||
val posterUrl = fixUrl(this.select("img").attr("data-src"))
|
val posterUrl = fixUrl(this.select("img").attr("data-src"))
|
||||||
val type = getType(this.select("div.fd-infor > span.fdi-item").text())
|
val type = getType(this.select("div.fd-infor > span.fdi-item").text())
|
||||||
|
@ -346,7 +347,7 @@ class ZoroProvider : MainAPI() {
|
||||||
link,
|
link,
|
||||||
).parsed<RapidCloudResponse>().link
|
).parsed<RapidCloudResponse>().link
|
||||||
val hasLoadedExtractorLink =
|
val hasLoadedExtractorLink =
|
||||||
loadExtractor(extractorLink, "https://rapid-cloud.ru/", callback)
|
loadExtractor(extractorLink, "https://rapid-cloud.ru/", subtitleCallback, callback)
|
||||||
|
|
||||||
if (!hasLoadedExtractorLink) {
|
if (!hasLoadedExtractorLink) {
|
||||||
extractRabbitStream(
|
extractRabbitStream(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.extractors
|
package com.lagradost.cloudstream3.extractors
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.SubtitleFile
|
||||||
import com.lagradost.cloudstream3.apmap
|
import com.lagradost.cloudstream3.apmap
|
||||||
import com.lagradost.cloudstream3.app
|
import com.lagradost.cloudstream3.app
|
||||||
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
||||||
|
@ -27,12 +28,16 @@ class Pelisplus(val mainUrl: String) {
|
||||||
private val normalApis = arrayListOf(MultiQuality())
|
private val normalApis = arrayListOf(MultiQuality())
|
||||||
|
|
||||||
// https://gogo-stream.com/streaming.php?id=MTE3NDg5
|
// https://gogo-stream.com/streaming.php?id=MTE3NDg5
|
||||||
suspend fun getUrl(id: String, isCasting: Boolean = false, callback: (ExtractorLink) -> Unit): Boolean {
|
suspend fun getUrl(
|
||||||
|
id: String,
|
||||||
|
isCasting: Boolean = false,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
): Boolean {
|
||||||
try {
|
try {
|
||||||
normalApis.apmap { api ->
|
normalApis.apmap { api ->
|
||||||
val url = api.getExtractorUrl(id)
|
val url = api.getExtractorUrl(id)
|
||||||
val source = api.getSafeUrl(url)
|
api.getSafeUrl(url, subtitleCallback = subtitleCallback, callback = callback)
|
||||||
source?.forEach { callback.invoke(it) }
|
|
||||||
}
|
}
|
||||||
val extractorUrl = getExtractorUrl(id)
|
val extractorUrl = getExtractorUrl(id)
|
||||||
|
|
||||||
|
@ -50,9 +55,10 @@ class Pelisplus(val mainUrl: String) {
|
||||||
val href = element.attr("href") ?: return@apmap
|
val href = element.attr("href") ?: return@apmap
|
||||||
val qual = if (element.text()
|
val qual = if (element.text()
|
||||||
.contains("HDP")
|
.contains("HDP")
|
||||||
) "1080" else qualityRegex.find(element.text())?.destructured?.component1().toString()
|
) "1080" else qualityRegex.find(element.text())?.destructured?.component1()
|
||||||
|
.toString()
|
||||||
|
|
||||||
if (!loadExtractor(href, link, callback)) {
|
if (!loadExtractor(href, link, subtitleCallback, callback)) {
|
||||||
callback.invoke(
|
callback.invoke(
|
||||||
ExtractorLink(
|
ExtractorLink(
|
||||||
this.name,
|
this.name,
|
||||||
|
@ -80,12 +86,7 @@ class Pelisplus(val mainUrl: String) {
|
||||||
// Matches vidstream links with extractors
|
// Matches vidstream links with extractors
|
||||||
extractorApis.filter { !it.requiresReferer || !isCasting }.apmap { api ->
|
extractorApis.filter { !it.requiresReferer || !isCasting }.apmap { api ->
|
||||||
if (link.startsWith(api.mainUrl)) {
|
if (link.startsWith(api.mainUrl)) {
|
||||||
val extractedLinks = api.getSafeUrl(link, extractorUrl)
|
api.getSafeUrl(link, extractorUrl, subtitleCallback, callback)
|
||||||
if (extractedLinks?.isNotEmpty() == true) {
|
|
||||||
extractedLinks.forEach {
|
|
||||||
callback.invoke(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.extractors
|
package com.lagradost.cloudstream3.extractors
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.SubtitleFile
|
||||||
import com.lagradost.cloudstream3.apmap
|
import com.lagradost.cloudstream3.apmap
|
||||||
import com.lagradost.cloudstream3.app
|
import com.lagradost.cloudstream3.app
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorApi
|
import com.lagradost.cloudstream3.utils.ExtractorApi
|
||||||
|
@ -12,35 +13,42 @@ class VidSrcExtractor : ExtractorApi() {
|
||||||
override val mainUrl = "https://v2.vidsrc.me"
|
override val mainUrl = "https://v2.vidsrc.me"
|
||||||
override val requiresReferer = false
|
override val requiresReferer = false
|
||||||
|
|
||||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
|
override suspend fun getUrl(
|
||||||
|
url: String,
|
||||||
|
referer: String?,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
val iframedoc = app.get(url).document
|
val iframedoc = app.get(url).document
|
||||||
|
|
||||||
val serverslist = iframedoc.select("div#sources.button_content div#content div#list div").map {
|
val serverslist =
|
||||||
val datahash = it.attr("data-hash")
|
iframedoc.select("div#sources.button_content div#content div#list div").map {
|
||||||
if (datahash.isNotBlank()) {
|
val datahash = it.attr("data-hash")
|
||||||
val links = try {
|
if (datahash.isNotBlank()) {
|
||||||
app.get("$mainUrl/src/$datahash", referer = "https://source.vidsrc.me/").url
|
val links = try {
|
||||||
} catch (e: Exception) {
|
app.get("$mainUrl/src/$datahash", referer = "https://source.vidsrc.me/").url
|
||||||
""
|
} catch (e: Exception) {
|
||||||
}
|
""
|
||||||
links
|
}
|
||||||
} else ""
|
links
|
||||||
}
|
} else ""
|
||||||
|
}
|
||||||
|
|
||||||
return serverslist.apmap { server ->
|
serverslist.apmap { server ->
|
||||||
val linkfixed = server.replace("https://vidsrc.xyz/","https://embedsito.com/")
|
val linkfixed = server.replace("https://vidsrc.xyz/", "https://embedsito.com/")
|
||||||
if (linkfixed.contains("/pro")) {
|
if (linkfixed.contains("/pro")) {
|
||||||
val srcresponse = app.get(server, referer = mainUrl).text
|
val srcresponse = app.get(server, referer = mainUrl).text
|
||||||
val m3u8Regex = Regex("((https:|http:)//.*\\.m3u8)")
|
val m3u8Regex = Regex("((https:|http:)//.*\\.m3u8)")
|
||||||
val srcm3u8 = m3u8Regex.find(srcresponse)?.value ?: return@apmap listOf()
|
val srcm3u8 = m3u8Regex.find(srcresponse)?.value ?: return@apmap
|
||||||
M3u8Helper.generateM3u8(
|
M3u8Helper.generateM3u8(
|
||||||
name,
|
name,
|
||||||
srcm3u8,
|
srcm3u8,
|
||||||
mainUrl
|
mainUrl
|
||||||
)
|
).forEach(callback)
|
||||||
} else {
|
} else {
|
||||||
loadExtractor(linkfixed, url)
|
loadExtractor(linkfixed, url, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}.flatten()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.extractors
|
package com.lagradost.cloudstream3.extractors
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.SubtitleFile
|
||||||
import com.lagradost.cloudstream3.apmap
|
import com.lagradost.cloudstream3.apmap
|
||||||
import com.lagradost.cloudstream3.app
|
import com.lagradost.cloudstream3.app
|
||||||
import com.lagradost.cloudstream3.argamap
|
import com.lagradost.cloudstream3.argamap
|
||||||
|
@ -30,15 +31,19 @@ class Vidstream(val mainUrl: String) {
|
||||||
suspend fun getUrl(
|
suspend fun getUrl(
|
||||||
id: String,
|
id: String,
|
||||||
isCasting: Boolean = false,
|
isCasting: Boolean = false,
|
||||||
callback: (ExtractorLink) -> Unit
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val extractorUrl = getExtractorUrl(id)
|
val extractorUrl = getExtractorUrl(id)
|
||||||
argamap(
|
argamap(
|
||||||
{
|
{
|
||||||
normalApis.apmap { api ->
|
normalApis.apmap { api ->
|
||||||
val url = api.getExtractorUrl(id)
|
val url = api.getExtractorUrl(id)
|
||||||
val source = api.getSafeUrl(url)
|
api.getSafeUrl(
|
||||||
source?.forEach { callback.invoke(it) }
|
url,
|
||||||
|
callback = callback,
|
||||||
|
subtitleCallback = subtitleCallback
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
/** Stolen from GogoanimeProvider.kt extractor */
|
/** Stolen from GogoanimeProvider.kt extractor */
|
||||||
|
@ -57,7 +62,7 @@ class Vidstream(val mainUrl: String) {
|
||||||
) "1080" else qualityRegex.find(element.text())?.destructured?.component1()
|
) "1080" else qualityRegex.find(element.text())?.destructured?.component1()
|
||||||
.toString()
|
.toString()
|
||||||
|
|
||||||
if (!loadExtractor(href, link, callback)) {
|
if (!loadExtractor(href, link, subtitleCallback, callback)) {
|
||||||
callback.invoke(
|
callback.invoke(
|
||||||
ExtractorLink(
|
ExtractorLink(
|
||||||
this.name,
|
this.name,
|
||||||
|
@ -84,12 +89,7 @@ class Vidstream(val mainUrl: String) {
|
||||||
// Matches vidstream links with extractors
|
// Matches vidstream links with extractors
|
||||||
extractorApis.filter { !it.requiresReferer || !isCasting }.apmap { api ->
|
extractorApis.filter { !it.requiresReferer || !isCasting }.apmap { api ->
|
||||||
if (link.startsWith(api.mainUrl)) {
|
if (link.startsWith(api.mainUrl)) {
|
||||||
val extractedLinks = api.getSafeUrl(link, extractorUrl)
|
api.getSafeUrl(link, extractorUrl, subtitleCallback, callback)
|
||||||
if (extractedLinks?.isNotEmpty() == true) {
|
|
||||||
extractedLinks.forEach {
|
|
||||||
callback.invoke(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package com.lagradost.cloudstream3.extractors
|
package com.lagradost.cloudstream3.extractors
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.ErrorLoadingException
|
import com.lagradost.cloudstream3.SubtitleFile
|
||||||
import com.lagradost.cloudstream3.mvvm.Resource
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
|
||||||
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.schemaStripRegex
|
import com.lagradost.cloudstream3.utils.schemaStripRegex
|
||||||
import org.schabi.newpipe.extractor.ServiceList
|
import org.schabi.newpipe.extractor.ServiceList
|
||||||
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor
|
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor
|
||||||
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory
|
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory
|
||||||
|
import org.schabi.newpipe.extractor.stream.SubtitlesStream
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream
|
import org.schabi.newpipe.extractor.stream.VideoStream
|
||||||
|
|
||||||
class YoutubeShortLinkExtractor : YoutubeExtractor() {
|
class YoutubeShortLinkExtractor : YoutubeExtractor() {
|
||||||
|
@ -26,56 +26,56 @@ open class YoutubeExtractor : ExtractorApi() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private var ytVideos: MutableMap<String, List<VideoStream>> = mutableMapOf()
|
private var ytVideos: MutableMap<String, List<VideoStream>> = mutableMapOf()
|
||||||
|
private var ytVideosSubtitles: MutableMap<String, List<SubtitlesStream>> = mutableMapOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getExtractorUrl(id: String): String {
|
override fun getExtractorUrl(id: String): String {
|
||||||
return "$mainUrl/watch?v=$id"
|
return "$mainUrl/watch?v=$id"
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
|
override suspend fun getUrl(
|
||||||
val streams = safeApiCall {
|
url: String,
|
||||||
val streams = ytVideos[url] ?: let {
|
referer: String?,
|
||||||
val link =
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
YoutubeStreamLinkHandlerFactory.getInstance().fromUrl(
|
callback: (ExtractorLink) -> Unit
|
||||||
url.replace(
|
) {
|
||||||
schemaStripRegex, ""
|
if (ytVideos[url].isNullOrEmpty()) {
|
||||||
)
|
val link =
|
||||||
|
YoutubeStreamLinkHandlerFactory.getInstance().fromUrl(
|
||||||
|
url.replace(
|
||||||
|
schemaStripRegex, ""
|
||||||
)
|
)
|
||||||
|
|
||||||
val s = object : YoutubeStreamExtractor(
|
|
||||||
ServiceList.YouTube,
|
|
||||||
link
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
s.fetchPage()
|
|
||||||
val streams = s.videoStreams ?: return@let emptyList()
|
|
||||||
ytVideos[url] = streams
|
|
||||||
streams
|
|
||||||
}
|
|
||||||
if (streams.isEmpty()) {
|
|
||||||
throw ErrorLoadingException("No Youtube streams")
|
|
||||||
}
|
|
||||||
|
|
||||||
streams
|
|
||||||
//streams.sortedBy { it.height }
|
|
||||||
// .firstOrNull { !it.isVideoOnly && it.height > 0 }
|
|
||||||
// ?: throw ErrorLoadingException("No valid Youtube stream")
|
|
||||||
}
|
|
||||||
if (streams is Resource.Success) {
|
|
||||||
return streams.value.mapNotNull {
|
|
||||||
if (it.isVideoOnly || it.height <= 0) return@mapNotNull null
|
|
||||||
|
|
||||||
ExtractorLink(
|
|
||||||
this.name,
|
|
||||||
this.name,
|
|
||||||
it.url ?: return@mapNotNull null,
|
|
||||||
"",
|
|
||||||
it.height
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val s = object : YoutubeStreamExtractor(
|
||||||
|
ServiceList.YouTube,
|
||||||
|
link
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
s.fetchPage()
|
||||||
|
ytVideos[url] = s.videoStreams
|
||||||
|
ytVideosSubtitles[url] = try {
|
||||||
|
s.subtitlesDefault.filterNotNull()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logError(e)
|
||||||
|
emptyList()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
ytVideos[url]?.mapNotNull {
|
||||||
|
if (it.isVideoOnly || it.height <= 0) return@mapNotNull null
|
||||||
|
|
||||||
|
ExtractorLink(
|
||||||
|
this.name,
|
||||||
|
this.name,
|
||||||
|
it.url ?: return@mapNotNull null,
|
||||||
|
"",
|
||||||
|
it.height
|
||||||
|
)
|
||||||
|
}?.forEach(callback)
|
||||||
|
ytVideosSubtitles[url]?.mapNotNull {
|
||||||
|
SubtitleFile(it.languageTag ?: return@mapNotNull null, it.url ?: return@mapNotNull null)
|
||||||
|
}?.forEach(subtitleCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package com.lagradost.cloudstream3.extractors.helper
|
package com.lagradost.cloudstream3.extractors.helper
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.lagradost.cloudstream3.SubtitleFile
|
||||||
import com.lagradost.cloudstream3.apmap
|
import com.lagradost.cloudstream3.apmap
|
||||||
import com.lagradost.cloudstream3.app
|
import com.lagradost.cloudstream3.app
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
@ -8,7 +9,11 @@ import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
|
|
||||||
class AsianEmbedHelper {
|
class AsianEmbedHelper {
|
||||||
companion object {
|
companion object {
|
||||||
suspend fun getUrls(url: String, callback: (ExtractorLink) -> Unit) {
|
suspend fun getUrls(
|
||||||
|
url: String,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
// Fetch links
|
// Fetch links
|
||||||
val doc = app.get(url).document
|
val doc = app.get(url).document
|
||||||
val links = doc.select("div#list-server-more > ul > li.linkserver")
|
val links = doc.select("div#list-server-more > ul > li.linkserver")
|
||||||
|
@ -17,7 +22,7 @@ class AsianEmbedHelper {
|
||||||
val datavid = it.attr("data-video") ?: ""
|
val datavid = it.attr("data-video") ?: ""
|
||||||
//Log.i("AsianEmbed", "Result => (datavid) ${datavid}")
|
//Log.i("AsianEmbed", "Result => (datavid) ${datavid}")
|
||||||
if (datavid.isNotBlank()) {
|
if (datavid.isNotBlank()) {
|
||||||
val res = loadExtractor(datavid, url, callback)
|
val res = loadExtractor(datavid, url, subtitleCallback, callback)
|
||||||
Log.i("AsianEmbed", "Result => ($res) (datavid) $datavid")
|
Log.i("AsianEmbed", "Result => ($res) (datavid) $datavid")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.extractors.helper
|
package com.lagradost.cloudstream3.extractors.helper
|
||||||
|
|
||||||
|
import com.lagradost.cloudstream3.SubtitleFile
|
||||||
import com.lagradost.cloudstream3.app
|
import com.lagradost.cloudstream3.app
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.Qualities
|
import com.lagradost.cloudstream3.utils.Qualities
|
||||||
|
@ -10,7 +11,11 @@ class VstreamhubHelper {
|
||||||
private val baseUrl: String = "https://vstreamhub.com"
|
private val baseUrl: String = "https://vstreamhub.com"
|
||||||
private val baseName: String = "Vstreamhub"
|
private val baseName: String = "Vstreamhub"
|
||||||
|
|
||||||
suspend fun getUrls(url: String, callback: (ExtractorLink) -> Unit) {
|
suspend fun getUrls(
|
||||||
|
url: String,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
if (url.startsWith(baseUrl)) {
|
if (url.startsWith(baseUrl)) {
|
||||||
// Fetch links
|
// Fetch links
|
||||||
val doc = app.get(url).document.select("script")
|
val doc = app.get(url).document.select("script")
|
||||||
|
@ -20,7 +25,8 @@ class VstreamhubHelper {
|
||||||
if (innerText.contains("file:")) {
|
if (innerText.contains("file:")) {
|
||||||
val startString = "file: "
|
val startString = "file: "
|
||||||
val aa = innerText.substring(innerText.indexOf(startString))
|
val aa = innerText.substring(innerText.indexOf(startString))
|
||||||
val linkUrl = aa.substring(startString.length + 1, aa.indexOf("\",")).trim()
|
val linkUrl =
|
||||||
|
aa.substring(startString.length + 1, aa.indexOf("\",")).trim()
|
||||||
//Log.i(baseName, "Result => (linkUrl) ${linkUrl}")
|
//Log.i(baseName, "Result => (linkUrl) ${linkUrl}")
|
||||||
val exlink = ExtractorLink(
|
val exlink = ExtractorLink(
|
||||||
name = "$baseName m3u8",
|
name = "$baseName m3u8",
|
||||||
|
@ -33,12 +39,14 @@ class VstreamhubHelper {
|
||||||
callback.invoke(exlink)
|
callback.invoke(exlink)
|
||||||
}
|
}
|
||||||
if (innerText.contains("playerInstance")) {
|
if (innerText.contains("playerInstance")) {
|
||||||
val aa = innerText.substring(innerText.indexOf("playerInstance.addButton"))
|
val aa =
|
||||||
|
innerText.substring(innerText.indexOf("playerInstance.addButton"))
|
||||||
val startString = "window.open(["
|
val startString = "window.open(["
|
||||||
val bb = aa.substring(aa.indexOf(startString))
|
val bb = aa.substring(aa.indexOf(startString))
|
||||||
val datavid = bb.substring(startString.length, bb.indexOf("]")).removeSurrounding("\"")
|
val datavid = bb.substring(startString.length, bb.indexOf("]"))
|
||||||
|
.removeSurrounding("\"")
|
||||||
if (datavid.isNotBlank()) {
|
if (datavid.isNotBlank()) {
|
||||||
loadExtractor(datavid, url, callback)
|
loadExtractor(datavid, url, subtitleCallback, callback)
|
||||||
//Log.i(baseName, "Result => (datavid) ${datavid}")
|
//Log.i(baseName, "Result => (datavid) ${datavid}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,9 +197,9 @@ class AllMoviesForYouProvider : MainAPI() {
|
||||||
val soup = app.get(id).document
|
val soup = app.get(id).document
|
||||||
soup.select("body iframe").map {
|
soup.select("body iframe").map {
|
||||||
val link = fixUrl(it.attr("src").replace("streamhub.to/d/", "streamhub.to/e/"))
|
val link = fixUrl(it.attr("src").replace("streamhub.to/d/", "streamhub.to/e/"))
|
||||||
loadExtractor(link, data, callback)
|
loadExtractor(link, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
} else loadExtractor(id, data, callback)
|
} else loadExtractor(id, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@ package com.lagradost.cloudstream3.movieproviders
|
||||||
|
|
||||||
import androidx.core.text.parseAsHtml
|
import androidx.core.text.parseAsHtml
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
|
||||||
import com.lagradost.cloudstream3.app
|
|
||||||
import com.lagradost.cloudstream3.utils.*
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||||
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
|
|
||||||
|
|
||||||
class AltadefinizioneProvider : MainAPI() {
|
class AltadefinizioneProvider : MainAPI() {
|
||||||
|
@ -55,16 +55,18 @@ class AltadefinizioneProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
override suspend fun search(query: String): List<SearchResponse> {
|
||||||
val doc = app.post("$mainUrl/index.php", data = mapOf(
|
val doc = app.post(
|
||||||
"do" to "search",
|
"$mainUrl/index.php", data = mapOf(
|
||||||
"subaction" to "search",
|
"do" to "search",
|
||||||
"story" to query,
|
"subaction" to "search",
|
||||||
"sortby" to "news_read"
|
"story" to query,
|
||||||
)).document
|
"sortby" to "news_read"
|
||||||
|
)
|
||||||
|
).document
|
||||||
return doc.select("div.box").map {
|
return doc.select("div.box").map {
|
||||||
val title = it.selectFirst("img")!!.attr("alt")
|
val title = it.selectFirst("img")!!.attr("alt")
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
val link = it.selectFirst("a")!!.attr("href")
|
||||||
val image = mainUrl+it.selectFirst("img")!!.attr("src")
|
val image = mainUrl + it.selectFirst("img")!!.attr("src")
|
||||||
val quality = getQualityFromString(it.selectFirst("span")!!.text())
|
val quality = getQualityFromString(it.selectFirst("span")!!.text())
|
||||||
|
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
|
@ -83,18 +85,20 @@ class AltadefinizioneProvider : MainAPI() {
|
||||||
override suspend fun load(url: String): LoadResponse {
|
override suspend fun load(url: String): LoadResponse {
|
||||||
val page = app.get(url)
|
val page = app.get(url)
|
||||||
val document = page.document
|
val document = page.document
|
||||||
val title = document.selectFirst(" h1 > a")!!.text().replace("streaming","")
|
val title = document.selectFirst(" h1 > a")!!.text().replace("streaming", "")
|
||||||
val description = document.select("#sfull").toString().substringAfter("altadefinizione").substringBeforeLast("fonte trama").parseAsHtml().toString()
|
val description = document.select("#sfull").toString().substringAfter("altadefinizione")
|
||||||
|
.substringBeforeLast("fonte trama").parseAsHtml().toString()
|
||||||
val rating = null
|
val rating = null
|
||||||
|
|
||||||
val year = document.selectFirst("#details > li:nth-child(2)")!!.childNode(2).toString().filter { it.isDigit() }.toInt()
|
val year = document.selectFirst("#details > li:nth-child(2)")!!.childNode(2).toString()
|
||||||
|
.filter { it.isDigit() }.toInt()
|
||||||
|
|
||||||
val poster = fixUrl(document.selectFirst("div.thumbphoto > img")!!.attr("src"))
|
val poster = fixUrl(document.selectFirst("div.thumbphoto > img")!!.attr("src"))
|
||||||
|
|
||||||
val recomm = document.select("ul.related-list > li").map {
|
val recomm = document.select("ul.related-list > li").map {
|
||||||
val href = it.selectFirst("a")!!.attr("href")
|
val href = it.selectFirst("a")!!.attr("href")
|
||||||
val posterUrl = mainUrl + it.selectFirst("img")!!.attr("src")
|
val posterUrl = mainUrl + it.selectFirst("img")!!.attr("src")
|
||||||
val name = it.selectFirst("img")!!.attr("alt")
|
val name = it.selectFirst("img")!!.attr("alt")
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
name,
|
name,
|
||||||
href,
|
href,
|
||||||
|
@ -110,29 +114,29 @@ class AltadefinizioneProvider : MainAPI() {
|
||||||
val actors: List<ActorData> =
|
val actors: List<ActorData> =
|
||||||
document.select("#staring > a").map {
|
document.select("#staring > a").map {
|
||||||
ActorData(actor = Actor(it.text()))
|
ActorData(actor = Actor(it.text()))
|
||||||
}
|
}
|
||||||
|
|
||||||
val tags: List<String> = document.select("#details > li:nth-child(1) > a").map { it.text() }
|
val tags: List<String> = document.select("#details > li:nth-child(1) > a").map { it.text() }
|
||||||
|
|
||||||
val trailerurl = document.selectFirst("#showtrailer > div > div > iframe")?.attr("src")
|
val trailerurl = document.selectFirst("#showtrailer > div > div > iframe")?.attr("src")
|
||||||
|
|
||||||
return newMovieLoadResponse(
|
return newMovieLoadResponse(
|
||||||
title,
|
title,
|
||||||
url,
|
url,
|
||||||
TvType.Movie,
|
TvType.Movie,
|
||||||
url
|
url
|
||||||
) {
|
) {
|
||||||
posterUrl = fixUrlNull(poster)
|
posterUrl = fixUrlNull(poster)
|
||||||
this.year = year
|
this.year = year
|
||||||
this.plot = description
|
this.plot = description
|
||||||
this.rating = rating
|
this.rating = rating
|
||||||
this.recommendations = recomm
|
this.recommendations = recomm
|
||||||
this.duration = null
|
this.duration = null
|
||||||
this.actors = actors
|
this.actors = actors
|
||||||
this.tags = tags
|
this.tags = tags
|
||||||
addTrailer(trailerurl)
|
addTrailer(trailerurl)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
override suspend fun loadLinks(
|
||||||
|
@ -142,23 +146,21 @@ class AltadefinizioneProvider : MainAPI() {
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val doc = app.get(data).document
|
val doc = app.get(data).document
|
||||||
if (doc.select("div.guardahd-player").isNullOrEmpty()){
|
if (doc.select("div.guardahd-player").isNullOrEmpty()) {
|
||||||
val videoUrl = doc.select("input").filter { it.hasAttr("data-mirror") }.last().attr("value")
|
val videoUrl =
|
||||||
loadExtractor(videoUrl, data, callback)
|
doc.select("input").filter { it.hasAttr("data-mirror") }.last().attr("value")
|
||||||
|
loadExtractor(videoUrl, data, subtitleCallback, callback)
|
||||||
doc.select("#mirrors > li > a").forEach {
|
doc.select("#mirrors > li > a").forEach {
|
||||||
loadExtractor(fixUrl(it.attr("data-target")), data, callback)
|
loadExtractor(fixUrl(it.attr("data-target")), data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
val pagelinks = doc.select("div.guardahd-player").select("iframe").attr("src")
|
val pagelinks = doc.select("div.guardahd-player").select("iframe").attr("src")
|
||||||
val docLinks = app.get(pagelinks).document
|
val docLinks = app.get(pagelinks).document
|
||||||
docLinks.select("body > div > ul > li").forEach {
|
docLinks.select("body > div > ul > li").forEach {
|
||||||
loadExtractor(fixUrl(it.attr("data-link")), data, callback)
|
loadExtractor(fixUrl(it.attr("data-link")), data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,8 +27,14 @@ open class BflixProvider : MainAPI() {
|
||||||
Pair("Movies", "div.tab-content[data-name=movies] div.filmlist div.item"),
|
Pair("Movies", "div.tab-content[data-name=movies] div.filmlist div.item"),
|
||||||
Pair("Shows", "div.tab-content[data-name=shows] div.filmlist div.item"),
|
Pair("Shows", "div.tab-content[data-name=shows] div.filmlist div.item"),
|
||||||
Pair("Trending", "div.tab-content[data-name=trending] div.filmlist div.item"),
|
Pair("Trending", "div.tab-content[data-name=trending] div.filmlist div.item"),
|
||||||
Pair("Latest Movies", "div.container section.bl:contains(Latest Movies) div.filmlist div.item"),
|
Pair(
|
||||||
Pair("Latest TV-Series", "div.container section.bl:contains(Latest TV-Series) div.filmlist div.item"),
|
"Latest Movies",
|
||||||
|
"div.container section.bl:contains(Latest Movies) div.filmlist div.item"
|
||||||
|
),
|
||||||
|
Pair(
|
||||||
|
"Latest TV-Series",
|
||||||
|
"div.container section.bl:contains(Latest TV-Series) div.filmlist div.item"
|
||||||
|
),
|
||||||
)
|
)
|
||||||
for ((name, element) in testa) try {
|
for ((name, element) in testa) try {
|
||||||
val test = soup.select(element).map {
|
val test = soup.select(element).map {
|
||||||
|
@ -57,7 +63,8 @@ open class BflixProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//Credits to https://github.com/jmir1
|
//Credits to https://github.com/jmir1
|
||||||
private val key = "5uLKesbh0nkrpPq9VwMC6+tQBdomjJ4HNl/fWOSiREvAYagT8yIG7zx2D13UZFXc" //key credits to @Modder4869
|
private val key =
|
||||||
|
"5uLKesbh0nkrpPq9VwMC6+tQBdomjJ4HNl/fWOSiREvAYagT8yIG7zx2D13UZFXc" //key credits to @Modder4869
|
||||||
|
|
||||||
private fun getVrf(id: String): String? {
|
private fun getVrf(id: String): String? {
|
||||||
val reversed = ue(encode(id) + "0000000").slice(0..5).reversed()
|
val reversed = ue(encode(id) + "0000000").slice(0..5).reversed()
|
||||||
|
@ -216,7 +223,7 @@ open class BflixProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
val tags = soup.select("div.info .meta div:contains(Genre) a").map { it.text() }
|
val tags = soup.select("div.info .meta div:contains(Genre) a").map { it.text() }
|
||||||
val episodes = Jsoup.parse(
|
val episodes = Jsoup.parse(
|
||||||
app.get(
|
app.get(
|
||||||
"$mainUrl/ajax/film/servers?id=$movieid&vrf=$movieidencoded"
|
"$mainUrl/ajax/film/servers?id=$movieid&vrf=$movieidencoded"
|
||||||
).parsed<Response>().html
|
).parsed<Response>().html
|
||||||
|
@ -232,15 +239,16 @@ open class BflixProvider : MainAPI() {
|
||||||
|
|
||||||
val eptitle = it.selectFirst(".episode a span.name")!!.text()
|
val eptitle = it.selectFirst(".episode a span.name")!!.text()
|
||||||
val secondtitle = it.selectFirst(".episode a span")!!.text()
|
val secondtitle = it.selectFirst(".episode a span")!!.text()
|
||||||
.replace(Regex("(Episode (\\d+):|Episode (\\d+)-|Episode (\\d+))"),"") ?: ""
|
.replace(Regex("(Episode (\\d+):|Episode (\\d+)-|Episode (\\d+))"), "") ?: ""
|
||||||
Episode(
|
Episode(
|
||||||
href,
|
href,
|
||||||
secondtitle+eptitle,
|
secondtitle + eptitle,
|
||||||
season,
|
season,
|
||||||
episode,
|
episode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val tvType = if (url.contains("/movie/") && episodes.size == 1) TvType.Movie else TvType.TvSeries
|
val tvType =
|
||||||
|
if (url.contains("/movie/") && episodes.size == 1) TvType.Movie else TvType.TvSeries
|
||||||
val recommendations =
|
val recommendations =
|
||||||
soup.select("div.bl-2 section.bl div.content div.filmlist div.item")
|
soup.select("div.bl-2 section.bl div.content div.filmlist div.item")
|
||||||
?.mapNotNull { element ->
|
?.mapNotNull { element ->
|
||||||
|
@ -261,9 +269,12 @@ open class BflixProvider : MainAPI() {
|
||||||
val durationregex = Regex("((\\d+) min)")
|
val durationregex = Regex("((\\d+) min)")
|
||||||
val yearegex = Regex("<span>(\\d+)<\\/span>")
|
val yearegex = Regex("<span>(\\d+)<\\/span>")
|
||||||
val duration = if (durationdoc.contains("na min")) null
|
val duration = if (durationdoc.contains("na min")) null
|
||||||
else durationregex.find(durationdoc)?.destructured?.component1()?.replace(" min","")?.toIntOrNull()
|
else durationregex.find(durationdoc)?.destructured?.component1()?.replace(" min", "")
|
||||||
val year = if (mainUrl == "https://bflix.ru") { yearegex.find(durationdoc)?.destructured?.component1()
|
?.toIntOrNull()
|
||||||
?.replace(Regex("<span>|<\\/span>"),"") } else null
|
val year = if (mainUrl == "https://bflix.ru") {
|
||||||
|
yearegex.find(durationdoc)?.destructured?.component1()
|
||||||
|
?.replace(Regex("<span>|<\\/span>"), "")
|
||||||
|
} else null
|
||||||
return when (tvType) {
|
return when (tvType) {
|
||||||
TvType.TvSeries -> {
|
TvType.TvSeries -> {
|
||||||
TvSeriesLoadResponse(
|
TvSeriesLoadResponse(
|
||||||
|
@ -343,7 +354,8 @@ open class BflixProvider : MainAPI() {
|
||||||
val a = it.select("a").map {
|
val a = it.select("a").map {
|
||||||
it.attr("data-kname")
|
it.attr("data-kname")
|
||||||
}
|
}
|
||||||
val tvType = if (data.contains("movie/") && a.size == 1) TvType.Movie else TvType.TvSeries
|
val tvType =
|
||||||
|
if (data.contains("movie/") && a.size == 1) TvType.Movie else TvType.TvSeries
|
||||||
val servers = if (tvType == TvType.Movie) it.select(".episode a").attr("data-ep")
|
val servers = if (tvType == TvType.Movie) it.select(".episode a").attr("data-ep")
|
||||||
else
|
else
|
||||||
it.select(".episode a[href=$cleandata]").attr("data-ep")
|
it.select(".episode a[href=$cleandata]").attr("data-ep")
|
||||||
|
@ -364,7 +376,7 @@ open class BflixProvider : MainAPI() {
|
||||||
?.replace("/embed/", "/e/")?.replace(Regex("(\\?sub.info.*)"), "")
|
?.replace("/embed/", "/e/")?.replace(Regex("(\\?sub.info.*)"), "")
|
||||||
}.apmap { url ->
|
}.apmap { url ->
|
||||||
loadExtractor(
|
loadExtractor(
|
||||||
url, data, callback
|
url, data, subtitleCallback, callback
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
//Apparently any server works, I haven't found any diference
|
//Apparently any server works, I haven't found any diference
|
||||||
|
|
|
@ -155,7 +155,7 @@ class CineblogProvider : MainAPI() {
|
||||||
rating,
|
rating,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
mutableListOf(),
|
||||||
recomm
|
recomm
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -205,7 +205,7 @@ class CineblogProvider : MainAPI() {
|
||||||
|
|
||||||
val url2= Regex("""src='((.|\\n)*?)'""").find(test.text)?.groups?.get(1)?.value.toString()
|
val url2= Regex("""src='((.|\\n)*?)'""").find(test.text)?.groups?.get(1)?.value.toString()
|
||||||
val trueUrl = app.get(url2, headers = mapOf("referer" to mainUrl)).url
|
val trueUrl = app.get(url2, headers = mapOf("referer" to mainUrl)).url
|
||||||
loadExtractor(trueUrl, data, callback)
|
loadExtractor(trueUrl, data, subtitleCallback, callback)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
|
|
||||||
class CinecalidadProvider:MainAPI() {
|
class CinecalidadProvider : MainAPI() {
|
||||||
override var mainUrl = "https://cinecalidad.lol"
|
override var mainUrl = "https://cinecalidad.lol"
|
||||||
override var name = "Cinecalidad"
|
override var name = "Cinecalidad"
|
||||||
override var lang = "es"
|
override var lang = "es"
|
||||||
|
@ -98,9 +98,10 @@ class CinecalidadProvider:MainAPI() {
|
||||||
val href = li.selectFirst("a")!!.attr("href")
|
val href = li.selectFirst("a")!!.attr("href")
|
||||||
val epThumb = li.selectFirst("img.lazy")!!.attr("data-src")
|
val epThumb = li.selectFirst("img.lazy")!!.attr("data-src")
|
||||||
val name = li.selectFirst(".episodiotitle a")!!.text()
|
val name = li.selectFirst(".episodiotitle a")!!.text()
|
||||||
val seasonid = li.selectFirst(".numerando")!!.text().replace(Regex("(S|E)"),"").let { str ->
|
val seasonid =
|
||||||
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
|
li.selectFirst(".numerando")!!.text().replace(Regex("(S|E)"), "").let { str ->
|
||||||
}
|
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||||
|
}
|
||||||
val isValid = seasonid.size == 2
|
val isValid = seasonid.size == 2
|
||||||
val episode = if (isValid) seasonid.getOrNull(1) else null
|
val episode = if (isValid) seasonid.getOrNull(1) else null
|
||||||
val season = if (isValid) seasonid.getOrNull(0) else null
|
val season = if (isValid) seasonid.getOrNull(0) else null
|
||||||
|
@ -112,7 +113,8 @@ class CinecalidadProvider:MainAPI() {
|
||||||
if (epThumb.contains("svg")) null else epThumb
|
if (epThumb.contains("svg")) null else epThumb
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return when (val tvType = if (url.contains("/ver-pelicula/")) TvType.Movie else TvType.TvSeries) {
|
return when (val tvType =
|
||||||
|
if (url.contains("/ver-pelicula/")) TvType.Movie else TvType.TvSeries) {
|
||||||
TvType.TvSeries -> {
|
TvType.TvSeries -> {
|
||||||
TvSeriesLoadResponse(
|
TvSeriesLoadResponse(
|
||||||
title,
|
title,
|
||||||
|
@ -156,18 +158,18 @@ class CinecalidadProvider:MainAPI() {
|
||||||
val url = it.attr("data-option")
|
val url = it.attr("data-option")
|
||||||
if (url.startsWith("https://cinestart.net")) {
|
if (url.startsWith("https://cinestart.net")) {
|
||||||
val extractor = Cinestart()
|
val extractor = Cinestart()
|
||||||
extractor.getSafeUrl(url)?.forEach { link ->
|
extractor.getSafeUrl(url, null, subtitleCallback, callback)
|
||||||
callback.invoke(link)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
loadExtractor(url, mainUrl, callback)
|
loadExtractor(url, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
if (url.startsWith("https://cinecalidad.lol")) {
|
if (url.startsWith("https://cinecalidad.lol")) {
|
||||||
val cineurlregex = Regex("(https:\\/\\/cinecalidad\\.lol\\/play\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
val cineurlregex =
|
||||||
|
Regex("(https:\\/\\/cinecalidad\\.lol\\/play\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||||
cineurlregex.findAll(url).map {
|
cineurlregex.findAll(url).map {
|
||||||
it.value.replace("/play/","/play/r.php")
|
it.value.replace("/play/", "/play/r.php")
|
||||||
}.toList().apmap {
|
}.toList().apmap {
|
||||||
app.get(it,
|
app.get(
|
||||||
|
it,
|
||||||
headers = mapOf(
|
headers = mapOf(
|
||||||
"Host" to "cinecalidad.lol",
|
"Host" to "cinecalidad.lol",
|
||||||
"User-Agent" to USER_AGENT,
|
"User-Agent" to USER_AGENT,
|
||||||
|
@ -182,57 +184,61 @@ class CinecalidadProvider:MainAPI() {
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
"Sec-Fetch-Site" to "same-origin",
|
||||||
"Sec-Fetch-User" to "?1",
|
"Sec-Fetch-User" to "?1",
|
||||||
),
|
),
|
||||||
allowRedirects = false).okhttpResponse.headers.values("location").apmap { extractedurl ->
|
allowRedirects = false
|
||||||
if (extractedurl.contains("cinestart")) {
|
).okhttpResponse.headers.values("location").apmap { extractedurl ->
|
||||||
loadExtractor(extractedurl, mainUrl, callback)
|
if (extractedurl.contains("cinestart")) {
|
||||||
|
loadExtractor(extractedurl, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (datatext.contains("en castellano")) app.get("$data?ref=es").document.select(".dooplay_player_option").apmap {
|
if (datatext.contains("en castellano")) app.get("$data?ref=es").document.select(".dooplay_player_option")
|
||||||
val url = it.attr("data-option")
|
.apmap {
|
||||||
if (url.startsWith("https://cinestart.net")) {
|
val url = it.attr("data-option")
|
||||||
val extractor = Cinestart()
|
if (url.startsWith("https://cinestart.net")) {
|
||||||
extractor.getSafeUrl(url)?.forEach { link ->
|
val extractor = Cinestart()
|
||||||
callback.invoke(link)
|
extractor.getSafeUrl(url, null, subtitleCallback, callback)
|
||||||
|
} else {
|
||||||
|
loadExtractor(url, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
loadExtractor(url, mainUrl, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url.startsWith("https://cinecalidad.lol")) {
|
if (url.startsWith("https://cinecalidad.lol")) {
|
||||||
val cineurlregex = Regex("(https:\\/\\/cinecalidad\\.lol\\/play\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
val cineurlregex =
|
||||||
cineurlregex.findAll(url).map {
|
Regex("(https:\\/\\/cinecalidad\\.lol\\/play\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||||
it.value.replace("/play/","/play/r.php")
|
cineurlregex.findAll(url).map {
|
||||||
}.toList().apmap {
|
it.value.replace("/play/", "/play/r.php")
|
||||||
app.get(it,
|
}.toList().apmap {
|
||||||
headers = mapOf(
|
app.get(
|
||||||
"Host" to "cinecalidad.lol",
|
it,
|
||||||
"User-Agent" to USER_AGENT,
|
headers = mapOf(
|
||||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
"Host" to "cinecalidad.lol",
|
||||||
"Accept-Language" to "en-US,en;q=0.5",
|
"User-Agent" to USER_AGENT,
|
||||||
"DNT" to "1",
|
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
||||||
"Connection" to "keep-alive",
|
"Accept-Language" to "en-US,en;q=0.5",
|
||||||
"Referer" to data,
|
"DNT" to "1",
|
||||||
"Upgrade-Insecure-Requests" to "1",
|
"Connection" to "keep-alive",
|
||||||
"Sec-Fetch-Dest" to "iframe",
|
"Referer" to data,
|
||||||
"Sec-Fetch-Mode" to "navigate",
|
"Upgrade-Insecure-Requests" to "1",
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
"Sec-Fetch-Dest" to "iframe",
|
||||||
"Sec-Fetch-User" to "?1",
|
"Sec-Fetch-Mode" to "navigate",
|
||||||
),
|
"Sec-Fetch-Site" to "same-origin",
|
||||||
allowRedirects = false).okhttpResponse.headers.values("location").apmap { extractedurl ->
|
"Sec-Fetch-User" to "?1",
|
||||||
if (extractedurl.contains("cinestart")) {
|
),
|
||||||
loadExtractor(extractedurl, mainUrl, callback)
|
allowRedirects = false
|
||||||
|
).okhttpResponse.headers.values("location").apmap { extractedurl ->
|
||||||
|
if (extractedurl.contains("cinestart")) {
|
||||||
|
loadExtractor(extractedurl, mainUrl, subtitleCallback, callback)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (datatext.contains("Subtítulo LAT") || datatext.contains("Forzados LAT")) {
|
||||||
if (datatext.contains("Subtítulo LAT") || datatext.contains("Forzados LAT")) {
|
|
||||||
doc.select("#panel_descarga.pane a").apmap {
|
doc.select("#panel_descarga.pane a").apmap {
|
||||||
val link = if (data.contains("serie") || data.contains("episodio")) "${data}${it.attr("href")}"
|
val link =
|
||||||
else it.attr("href")
|
if (data.contains("serie") || data.contains("episodio")) "${data}${it.attr("href")}"
|
||||||
|
else it.attr("href")
|
||||||
val docsub = app.get(link)
|
val docsub = app.get(link)
|
||||||
val linksub = docsub.document
|
val linksub = docsub.document
|
||||||
val validsub = docsub.text
|
val validsub = docsub.text
|
||||||
|
@ -241,8 +247,11 @@ class CinecalidadProvider:MainAPI() {
|
||||||
val langdoc = linksub.selectFirst("div.titulo h3")!!.text()
|
val langdoc = linksub.selectFirst("div.titulo h3")!!.text()
|
||||||
val reallang = langregex.find(langdoc)?.destructured?.component1()
|
val reallang = langregex.find(langdoc)?.destructured?.component1()
|
||||||
linksub.select("a.link").apmap {
|
linksub.select("a.link").apmap {
|
||||||
val sublink = if (data.contains("serie") || data.contains("episodio")) "${data}${it.attr("href")}"
|
val sublink =
|
||||||
else it.attr("href")
|
if (data.contains("serie") || data.contains("episodio")) "${data}${
|
||||||
|
it.attr("href")
|
||||||
|
}"
|
||||||
|
else it.attr("href")
|
||||||
subtitleCallback(
|
subtitleCallback(
|
||||||
SubtitleFile(reallang!!, sublink)
|
SubtitleFile(reallang!!, sublink)
|
||||||
)
|
)
|
||||||
|
|
|
@ -227,7 +227,7 @@ class CuevanaProvider : MainAPI() {
|
||||||
val json = parseJson<Femcuevana>(url)
|
val json = parseJson<Femcuevana>(url)
|
||||||
val link = json.url
|
val link = json.url
|
||||||
if (link.contains("fembed")) {
|
if (link.contains("fembed")) {
|
||||||
loadExtractor(link, data, callback)
|
loadExtractor(link, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,7 @@ class CuevanaProvider : MainAPI() {
|
||||||
),
|
),
|
||||||
data = mapOf(Pair("url", gotolink))
|
data = mapOf(Pair("url", gotolink))
|
||||||
).okhttpResponse.headers.values("location").apmap { golink ->
|
).okhttpResponse.headers.values("location").apmap { golink ->
|
||||||
loadExtractor(golink, data, callback)
|
loadExtractor(golink, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,7 +311,7 @@ class CuevanaProvider : MainAPI() {
|
||||||
),
|
),
|
||||||
data = mapOf(Pair("h", inlink))
|
data = mapOf(Pair("h", inlink))
|
||||||
).okhttpResponse.headers.values("location").apmap { link ->
|
).okhttpResponse.headers.values("location").apmap { link ->
|
||||||
loadExtractor(link, data, callback)
|
loadExtractor(link, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,7 +147,7 @@ class DoramasYTProvider : MainAPI() {
|
||||||
callback.invoke(link)
|
callback.invoke(link)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loadExtractor(url, mainUrl, callback)
|
loadExtractor(url, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -50,14 +50,15 @@ class DramaSeeProvider : MainAPI() {
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
override suspend fun search(query: String): List<SearchResponse> {
|
||||||
val url = "$mainUrl/search?q=$query"
|
val url = "$mainUrl/search?q=$query"
|
||||||
val document = app.get(url).document
|
val document = app.get(url).document
|
||||||
val posters = document.select ("div.film-poster")
|
val posters = document.select("div.film-poster")
|
||||||
|
|
||||||
|
|
||||||
return posters.mapNotNull {
|
return posters.mapNotNull {
|
||||||
val innerA = it.select("a") ?: return@mapNotNull null
|
val innerA = it.select("a") ?: return@mapNotNull null
|
||||||
val link = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
|
val link = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
|
||||||
val title = innerA.attr("title") ?: return@mapNotNull null
|
val title = innerA.attr("title") ?: return@mapNotNull null
|
||||||
val year = Regex(""".*\((\d{4})\)""").find(title)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
val year =
|
||||||
|
Regex(""".*\((\d{4})\)""").find(title)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
||||||
val imgSrc = it.select("img")?.attr("data-src") ?: return@mapNotNull null
|
val imgSrc = it.select("img")?.attr("data-src") ?: return@mapNotNull null
|
||||||
val image = fixUrlNull(imgSrc)
|
val image = fixUrlNull(imgSrc)
|
||||||
|
|
||||||
|
@ -193,7 +194,7 @@ class DramaSeeProvider : MainAPI() {
|
||||||
val status = element.attr("data-status") ?: return@forEach
|
val status = element.attr("data-status") ?: return@forEach
|
||||||
if (status != "1") return@forEach
|
if (status != "1") return@forEach
|
||||||
val extractorData = element.attr("data-video") ?: return@forEach
|
val extractorData = element.attr("data-video") ?: return@forEach
|
||||||
loadExtractor(extractorData, iframe.url, callback)
|
loadExtractor(extractorData, iframe.url, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
val iv = "9262859232435825"
|
val iv = "9262859232435825"
|
||||||
|
|
|
@ -206,7 +206,7 @@ class DramaidProvider : MainAPI() {
|
||||||
}.apmap {
|
}.apmap {
|
||||||
when {
|
when {
|
||||||
it.contains("motonews.club") -> invokeDriveSource(it, this.name, subtitleCallback, callback)
|
it.contains("motonews.club") -> invokeDriveSource(it, this.name, subtitleCallback, callback)
|
||||||
else -> loadExtractor(it, data, callback)
|
else -> loadExtractor(it, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ class ElifilmsProvider : MainAPI() {
|
||||||
val encodedurl = it.attr("data-id")
|
val encodedurl = it.attr("data-id")
|
||||||
val urlDecoded = base64Decode(encodedurl)
|
val urlDecoded = base64Decode(encodedurl)
|
||||||
val url = fixUrl(urlDecoded)
|
val url = fixUrl(urlDecoded)
|
||||||
loadExtractor(url, data, callback)
|
loadExtractor(url, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ class EntrepeliculasyseriesProvider:MainAPI() {
|
||||||
data = mapOf(Pair("h", postkey)),
|
data = mapOf(Pair("h", postkey)),
|
||||||
allowRedirects = false
|
allowRedirects = false
|
||||||
).okhttpResponse.headers.values("location").apmap {
|
).okhttpResponse.headers.values("location").apmap {
|
||||||
loadExtractor(it, data, callback)
|
loadExtractor(it, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,7 @@ class EstrenosDoramasProvider : MainAPI() {
|
||||||
val document = app.get(data).document
|
val document = app.get(data).document
|
||||||
document.select("div.tab_container iframe").apmap { container ->
|
document.select("div.tab_container iframe").apmap { container ->
|
||||||
val directlink = fixUrl(container.attr("src"))
|
val directlink = fixUrl(container.attr("src"))
|
||||||
loadExtractor(directlink, data, callback)
|
loadExtractor(directlink, data, subtitleCallback, callback)
|
||||||
|
|
||||||
if (directlink.contains("/repro/amz/")) {
|
if (directlink.contains("/repro/amz/")) {
|
||||||
val amzregex = Regex("https:\\/\\/repro3\\.estrenosdoramas\\.us\\/repro\\/amz\\/examples\\/.*\\.php\\?key=.*\$")
|
val amzregex = Regex("https:\\/\\/repro3\\.estrenosdoramas\\.us\\/repro\\/amz\\/examples\\/.*\\.php\\?key=.*\$")
|
||||||
|
@ -239,7 +239,7 @@ class EstrenosDoramasProvider : MainAPI() {
|
||||||
).text
|
).text
|
||||||
val extracteklink = link.substringAfter("\"urlremoto\":\"").substringBefore("\"}")
|
val extracteklink = link.substringAfter("\"urlremoto\":\"").substringBefore("\"}")
|
||||||
.replace("\\/", "/").replace("//ok.ru/","http://ok.ru/")
|
.replace("\\/", "/").replace("//ok.ru/","http://ok.ru/")
|
||||||
loadExtractor(extracteklink, data, callback)
|
loadExtractor(extracteklink, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,9 @@ package com.lagradost.cloudstream3.movieproviders
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.utils.*
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.select.Elements
|
import org.jsoup.select.Elements
|
||||||
|
|
||||||
|
@ -58,10 +59,11 @@ class FilmanProvider : MainAPI() {
|
||||||
val series = lists[3].select("#item-list > div:not(.clearfix)")
|
val series = lists[3].select("#item-list > div:not(.clearfix)")
|
||||||
if (movies.isEmpty() && series.isEmpty()) return ArrayList()
|
if (movies.isEmpty() && series.isEmpty()) return ArrayList()
|
||||||
fun getVideos(type: TvType, items: Elements): List<SearchResponse> {
|
fun getVideos(type: TvType, items: Elements): List<SearchResponse> {
|
||||||
return items.mapNotNull { i ->
|
return items.mapNotNull { i ->
|
||||||
val href = i.selectFirst(".poster > a")?.attr("href")?: return@mapNotNull null
|
val href = i.selectFirst(".poster > a")?.attr("href") ?: return@mapNotNull null
|
||||||
val img = i.selectFirst(".poster > a > img")?.attr("src")?.replace("/thumb/", "/big/")
|
val img =
|
||||||
val name = i.selectFirst(".film_title")?.text()?: return@mapNotNull null
|
i.selectFirst(".poster > a > img")?.attr("src")?.replace("/thumb/", "/big/")
|
||||||
|
val name = i.selectFirst(".film_title")?.text() ?: return@mapNotNull null
|
||||||
val year = i.selectFirst(".film_year")?.text()?.toIntOrNull()
|
val year = i.selectFirst(".film_year")?.text()?.toIntOrNull()
|
||||||
if (type === TvType.TvSeries) {
|
if (type === TvType.TvSeries) {
|
||||||
TvSeriesSearchResponse(
|
TvSeriesSearchResponse(
|
||||||
|
@ -136,7 +138,7 @@ class FilmanProvider : MainAPI() {
|
||||||
document?.select(".link-to-video")?.apmap { item ->
|
document?.select(".link-to-video")?.apmap { item ->
|
||||||
val decoded = base64Decode(item.select("a").attr("data-iframe"))
|
val decoded = base64Decode(item.select("a").attr("data-iframe"))
|
||||||
val link = tryParseJson<LinkElement>(decoded)?.src ?: return@apmap
|
val link = tryParseJson<LinkElement>(decoded)?.src ?: return@apmap
|
||||||
loadExtractor(link, null, callback)
|
loadExtractor(link, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,15 +224,15 @@ class FilmpertuttiProvider : MainAPI() {
|
||||||
tryParseJson<List<String>>(data)?.apmap { id ->
|
tryParseJson<List<String>>(data)?.apmap { id ->
|
||||||
if (id.contains("buckler")){
|
if (id.contains("buckler")){
|
||||||
val id2 = unshorten_linkup(id).trim().replace("/v/","/e/").replace("/f/","/e/")
|
val id2 = unshorten_linkup(id).trim().replace("/v/","/e/").replace("/f/","/e/")
|
||||||
loadExtractor(id2, data, callback)
|
loadExtractor(id2, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
else if (id.contains("isecure")){
|
else if (id.contains("isecure")){
|
||||||
val doc1 = app.get(id).document
|
val doc1 = app.get(id).document
|
||||||
val id2 = doc1.selectFirst("iframe")!!.attr("src")
|
val id2 = doc1.selectFirst("iframe")!!.attr("src")
|
||||||
loadExtractor(id2, data, callback)
|
loadExtractor(id2, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
loadExtractor(id, data, callback)
|
loadExtractor(id, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -68,7 +68,7 @@ class FrenchStreamProvider : MainAPI() {
|
||||||
?.mapNotNull { // all the tags like action, thriller ...; unused variable
|
?.mapNotNull { // all the tags like action, thriller ...; unused variable
|
||||||
it?.text()
|
it?.text()
|
||||||
}
|
}
|
||||||
return newMovieLoadResponse(title,url,TvType.Movie,url) {
|
return newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||||
this.posterUrl = poster
|
this.posterUrl = poster
|
||||||
addRating(soup.select("div.fr-count > div").text())
|
addRating(soup.select("div.fr-count > div").text())
|
||||||
this.year = soup.select("ul.flist-col > li").getOrNull(2)?.text()?.toIntOrNull()
|
this.year = soup.select("ul.flist-col > li").getOrNull(2)?.text()?.toIntOrNull()
|
||||||
|
@ -82,8 +82,7 @@ class FrenchStreamProvider : MainAPI() {
|
||||||
//println("listeEpisode:")
|
//println("listeEpisode:")
|
||||||
val episodeList = if ("<a" !in (listEpisode[0]).toString()) { // check if VF is empty
|
val episodeList = if ("<a" !in (listEpisode[0]).toString()) { // check if VF is empty
|
||||||
listEpisode[1] // no vf, return vostfr
|
listEpisode[1] // no vf, return vostfr
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
listEpisode[0] // no vostfr, return vf
|
listEpisode[0] // no vostfr, return vf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,9 +220,9 @@ class FrenchStreamProvider : MainAPI() {
|
||||||
servers.apmap {
|
servers.apmap {
|
||||||
for (extractor in extractorApis) {
|
for (extractor in extractorApis) {
|
||||||
if (it.first.contains(extractor.name, ignoreCase = true)) {
|
if (it.first.contains(extractor.name, ignoreCase = true)) {
|
||||||
// val name = it.first
|
// val name = it.first
|
||||||
// print("true for $name")
|
// print("true for $name")
|
||||||
extractor.getSafeUrl(it.second, it.second)?.forEach(callback)
|
extractor.getSafeUrl(it.second, it.second, subtitleCallback, callback)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ class HDMovie5 : MainAPI() {
|
||||||
(doc.select("#repimdb>strong").text().toFloatOrNull()?.times(1000))?.toInt(),
|
(doc.select("#repimdb>strong").text().toFloatOrNull()?.times(1000))?.toInt(),
|
||||||
info.select(".sgeneros>a").map { it.text() },
|
info.select(".sgeneros>a").map { it.text() },
|
||||||
info.select(".runtime").text().substringBefore(" Min.").toIntOrNull(),
|
info.select(".runtime").text().substringBefore(" Min.").toIntOrNull(),
|
||||||
null,
|
mutableListOf(),
|
||||||
doc.select("#single_relacionados>article>a").map {
|
doc.select("#single_relacionados>article>a").map {
|
||||||
val img = it.select("img")
|
val img = it.select("img")
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
|
@ -149,7 +149,7 @@ class HDMovie5 : MainAPI() {
|
||||||
val html = p.parsedSafe<PlayerAjaxResponse>()?.embedURL ?: return@apmapIndexed false
|
val html = p.parsedSafe<PlayerAjaxResponse>()?.embedURL ?: return@apmapIndexed false
|
||||||
val doc = Jsoup.parse(html)
|
val doc = Jsoup.parse(html)
|
||||||
val link = doc.select("iframe").attr("src")
|
val link = doc.select("iframe").attr("src")
|
||||||
loadExtractor(httpsify(link), "$mainUrl/", callback)
|
loadExtractor(httpsify(link), "$mainUrl/", subtitleCallback, callback)
|
||||||
}.contains(true)
|
}.contains(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -215,7 +215,7 @@ class IHaveNoTvProvider : MainAPI() {
|
||||||
|
|
||||||
val iframe = soup.selectFirst("#videoWrap iframe")
|
val iframe = soup.selectFirst("#videoWrap iframe")
|
||||||
if (iframe != null) {
|
if (iframe != null) {
|
||||||
loadExtractor(iframe.attr("src"), null, callback)
|
loadExtractor(iframe.attr("src"), null, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -365,7 +365,7 @@ class IdlixProvider : MainAPI() {
|
||||||
if (source.startsWith("https://uservideo.xyz")) {
|
if (source.startsWith("https://uservideo.xyz")) {
|
||||||
source = app.get(source).document.select("iframe").attr("src")
|
source = app.get(source).document.select("iframe").attr("src")
|
||||||
}
|
}
|
||||||
loadExtractor(source, data, callback)
|
loadExtractor(source, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,9 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
val rex = Regex("\\((\\d+)")
|
val rex = Regex("\\((\\d+)")
|
||||||
//Log.i(this.name, "Result => (rex value) ${rex.find(yearText)?.value}")
|
//Log.i(this.name, "Result => (rex value) ${rex.find(yearText)?.value}")
|
||||||
rex.find(yearText)?.value?.toIntOrNull()
|
rex.find(yearText)?.value?.toIntOrNull()
|
||||||
} catch (e: Exception) { null }
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
name = title,
|
name = title,
|
||||||
|
@ -67,7 +69,7 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
val url = "$mainUrl/?s=$query"
|
val url = "$mainUrl/?s=$query"
|
||||||
val html = app.get(url).document
|
val html = app.get(url).document
|
||||||
val document = html.getElementsByTag("body")
|
val document = html.getElementsByTag("body")
|
||||||
.select("div.item_1.items > div.item") ?: return listOf()
|
.select("div.item_1.items > div.item") ?: return listOf()
|
||||||
|
|
||||||
return document.mapNotNull {
|
return document.mapNotNull {
|
||||||
if (it == null) {
|
if (it == null) {
|
||||||
|
@ -105,15 +107,21 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
val startLink = "https://kdramahood.com/drama-release-year/"
|
val startLink = "https://kdramahood.com/drama-release-year/"
|
||||||
var res: Int? = null
|
var res: Int? = null
|
||||||
info?.select("div.metadatac")?.forEach {
|
info?.select("div.metadatac")?.forEach {
|
||||||
if (res != null) { return@forEach }
|
if (res != null) {
|
||||||
if (it == null) { return@forEach }
|
return@forEach
|
||||||
|
}
|
||||||
|
if (it == null) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
val yearLink = it.select("a").attr("href") ?: return@forEach
|
val yearLink = it.select("a").attr("href") ?: return@forEach
|
||||||
if (yearLink.startsWith(startLink)) {
|
if (yearLink.startsWith(startLink)) {
|
||||||
res = yearLink.substring(startLink.length).replace("/", "").toIntOrNull()
|
res = yearLink.substring(startLink.length).replace("/", "").toIntOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res
|
res
|
||||||
} catch (e: Exception) { null }
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
val recs = doc.select("div.sidebartv > div.tvitemrel").mapNotNull {
|
val recs = doc.select("div.sidebartv > div.tvitemrel").mapNotNull {
|
||||||
val a = it?.select("a") ?: return@mapNotNull null
|
val a = it?.select("a") ?: return@mapNotNull null
|
||||||
|
@ -161,10 +169,13 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
//Fetch default source and subtitles
|
//Fetch default source and subtitles
|
||||||
epVidLinkEl.select("div.embed2")?.forEach { defsrc ->
|
epVidLinkEl.select("div.embed2")?.forEach { defsrc ->
|
||||||
if (defsrc == null) { return@forEach }
|
if (defsrc == null) {
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
val scriptstring = defsrc.toString()
|
val scriptstring = defsrc.toString()
|
||||||
if (scriptstring.contains("sources: [{")) {
|
if (scriptstring.contains("sources: [{")) {
|
||||||
"(?<=playerInstance2.setup\\()([\\s\\S]*?)(?=\\);)".toRegex().find(scriptstring)?.value?.let { itemjs ->
|
"(?<=playerInstance2.setup\\()([\\s\\S]*?)(?=\\);)".toRegex()
|
||||||
|
.find(scriptstring)?.value?.let { itemjs ->
|
||||||
listOfLinks.add("$mainUrl$itemjs")
|
listOfLinks.add("$mainUrl$itemjs")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,7 +275,7 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
//Log.i(this.name, "Result => (url) $url")
|
//Log.i(this.name, "Result => (url) $url")
|
||||||
when {
|
when {
|
||||||
url.startsWith("https://asianembed.io") -> {
|
url.startsWith("https://asianembed.io") -> {
|
||||||
AsianEmbedHelper.getUrls(url, callback)
|
AsianEmbedHelper.getUrls(url, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
url.startsWith("https://embedsito.com") -> {
|
url.startsWith("https://embedsito.com") -> {
|
||||||
val extractor = XStreamCdn()
|
val extractor = XStreamCdn()
|
||||||
|
@ -274,7 +285,7 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
loadExtractor(url, mainUrl, callback)
|
loadExtractor(url, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,7 +219,7 @@ class LayarKacaProvider : MainAPI() {
|
||||||
} else {
|
} else {
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
loadExtractor(link, data, callback)
|
loadExtractor(link, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -126,7 +126,7 @@ class OpenVidsProvider:TmdbProvider() {
|
||||||
membed.isUsingAdaptiveKeys,
|
membed.isUsingAdaptiveKeys,
|
||||||
membed.isUsingAdaptiveData)
|
membed.isUsingAdaptiveData)
|
||||||
} else
|
} else
|
||||||
loadExtractor(links, data, callback)
|
loadExtractor(links, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,7 @@ class PeliSmartProvider: MainAPI() {
|
||||||
.replace("https://pelismarthd.com/p/1.php?v=","https://evoload.io/e/")
|
.replace("https://pelismarthd.com/p/1.php?v=","https://evoload.io/e/")
|
||||||
.replace("https://pelismarthd.com/p/2.php?v=","https://streamtape.com/e/")
|
.replace("https://pelismarthd.com/p/2.php?v=","https://streamtape.com/e/")
|
||||||
.replace("https://pelismarthd.com/p/4.php?v=","https://dood.to/e/")
|
.replace("https://pelismarthd.com/p/4.php?v=","https://dood.to/e/")
|
||||||
loadExtractor(urlc, data, callback)
|
loadExtractor(urlc, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,7 +222,7 @@ class PelisflixProvider : MainAPI() {
|
||||||
allowRedirects = false
|
allowRedirects = false
|
||||||
).okhttpResponse.headers.values("location").apmap { link ->
|
).okhttpResponse.headers.values("location").apmap { link ->
|
||||||
val url1 = link.replace("#bu", "")
|
val url1 = link.replace("#bu", "")
|
||||||
loadExtractor(url1, data, callback)
|
loadExtractor(url1, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,7 +165,7 @@ class PelisplusHDProvider:MainAPI() {
|
||||||
): Boolean {
|
): Boolean {
|
||||||
app.get(data).document.select("div.player > script").map { script ->
|
app.get(data).document.select("div.player > script").map { script ->
|
||||||
fetchUrls(script.data().replace("https://pelisplushd.net/fembed.php?url=","https://www.fembed.com/v/")).apmap {
|
fetchUrls(script.data().replace("https://pelisplushd.net/fembed.php?url=","https://www.fembed.com/v/")).apmap {
|
||||||
loadExtractor(it, data, callback)
|
loadExtractor(it, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -229,7 +229,7 @@ open class PelisplusProviderTemplate : MainAPI() {
|
||||||
if (info.contains("Latino")) {
|
if (info.contains("Latino")) {
|
||||||
doc.select(".server-item-1 li").apmap {
|
doc.select(".server-item-1 li").apmap {
|
||||||
val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play")
|
val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play")
|
||||||
loadExtractor(serverid, data, callback)
|
loadExtractor(serverid, data, subtitleCallback, callback)
|
||||||
if (serverid.contains("pelisplus.icu")) {
|
if (serverid.contains("pelisplus.icu")) {
|
||||||
getPelisStream(serverid, callback)
|
getPelisStream(serverid, callback)
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ open class PelisplusProviderTemplate : MainAPI() {
|
||||||
if (info.contains("Subtitulado")) {
|
if (info.contains("Subtitulado")) {
|
||||||
doc.select(".server-item-0 li").apmap {
|
doc.select(".server-item-0 li").apmap {
|
||||||
val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play")
|
val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play")
|
||||||
loadExtractor(serverid, data, callback)
|
loadExtractor(serverid, data, subtitleCallback, callback)
|
||||||
if (serverid.contains("pelisplus.icu")) {
|
if (serverid.contains("pelisplus.icu")) {
|
||||||
getPelisStream(serverid, callback)
|
getPelisStream(serverid, callback)
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ open class PelisplusProviderTemplate : MainAPI() {
|
||||||
if (info.contains("Castellano")) {
|
if (info.contains("Castellano")) {
|
||||||
doc.select(".server-item-2 li").apmap {
|
doc.select(".server-item-2 li").apmap {
|
||||||
val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play")
|
val serverid = fixUrl(it.attr("data-video")).replace("streaming.php","play")
|
||||||
loadExtractor(serverid, data, callback)
|
loadExtractor(serverid, data, subtitleCallback, callback)
|
||||||
if (serverid.contains("pelisplus.icu")) {
|
if (serverid.contains("pelisplus.icu")) {
|
||||||
getPelisStream(serverid, callback)
|
getPelisStream(serverid, callback)
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,7 +221,7 @@ class PinoyHDXyzProvider : MainAPI() {
|
||||||
mapper.readValue<List<String>>(data).forEach { item ->
|
mapper.readValue<List<String>>(data).forEach { item ->
|
||||||
val url = item.trim()
|
val url = item.trim()
|
||||||
if (url.isNotBlank()) {
|
if (url.isNotBlank()) {
|
||||||
if (loadExtractor(url, mainUrl, callback)) {
|
if (loadExtractor(url, mainUrl, subtitleCallback, callback)) {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,7 +231,7 @@ class PinoyMoviePediaProvider : MainAPI() {
|
||||||
callback.invoke(it)
|
callback.invoke(it)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loadExtractor(link, mainUrl, callback)
|
loadExtractor(link, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count > 0
|
return count > 0
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.lagradost.cloudstream3.movieproviders
|
package com.lagradost.cloudstream3.movieproviders
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.extractors.FEmbed
|
import com.lagradost.cloudstream3.extractors.FEmbed
|
||||||
|
@ -26,7 +25,11 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
@JsonProperty("type") val type: String
|
@JsonProperty("type") val type: String
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun getRowElements(mainbody: Elements, rows: List<Pair<String, String>>, sep: String): MutableList<HomePageList> {
|
private fun getRowElements(
|
||||||
|
mainbody: Elements,
|
||||||
|
rows: List<Pair<String, String>>,
|
||||||
|
sep: String
|
||||||
|
): MutableList<HomePageList> {
|
||||||
val all = mutableListOf<HomePageList>()
|
val all = mutableListOf<HomePageList>()
|
||||||
for (item in rows) {
|
for (item in rows) {
|
||||||
val title = item.first
|
val title = item.first
|
||||||
|
@ -36,10 +39,14 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
if (urlTitle.isNullOrEmpty()) {
|
if (urlTitle.isNullOrEmpty()) {
|
||||||
urlTitle = it?.select("div.data")
|
urlTitle = it?.select("div.data")
|
||||||
}
|
}
|
||||||
if (urlTitle.isNullOrEmpty()) { return@mapNotNull null }
|
if (urlTitle.isNullOrEmpty()) {
|
||||||
|
return@mapNotNull null
|
||||||
|
}
|
||||||
// Fetch details
|
// Fetch details
|
||||||
val link = fixUrlNull(urlTitle.select("a")?.attr("href"))
|
val link = fixUrlNull(urlTitle.select("a")?.attr("href"))
|
||||||
if (link.isNullOrBlank()) { return@mapNotNull null }
|
if (link.isNullOrBlank()) {
|
||||||
|
return@mapNotNull null
|
||||||
|
}
|
||||||
|
|
||||||
val image = it?.select("div.poster > img")?.attr("data-src")
|
val image = it?.select("div.poster > img")?.attr("data-src")
|
||||||
|
|
||||||
|
@ -47,7 +54,9 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
val name = urlTitle.select("h3")?.text()
|
val name = urlTitle.select("h3")?.text()
|
||||||
?: urlTitle.select("h2")?.text()
|
?: urlTitle.select("h2")?.text()
|
||||||
?: urlTitle.select("h1")?.text()
|
?: urlTitle.select("h1")?.text()
|
||||||
if (name.isNullOrBlank()) { return@mapNotNull null }
|
if (name.isNullOrBlank()) {
|
||||||
|
return@mapNotNull null
|
||||||
|
}
|
||||||
|
|
||||||
var year = urlTitle.select("span")?.text()?.toIntOrNull()
|
var year = urlTitle.select("span")?.text()?.toIntOrNull()
|
||||||
|
|
||||||
|
@ -80,27 +89,32 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
return all
|
return all
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getMainPage(): HomePageResponse {
|
override suspend fun getMainPage(): HomePageResponse {
|
||||||
val all = ArrayList<HomePageList>()
|
val all = ArrayList<HomePageList>()
|
||||||
val document = app.get(mainUrl).document
|
val document = app.get(mainUrl).document
|
||||||
val mainbody = document.getElementsByTag("body")
|
val mainbody = document.getElementsByTag("body")
|
||||||
if (mainbody != null) {
|
if (mainbody != null) {
|
||||||
// All rows will be hardcoded bc of the nature of the site
|
// All rows will be hardcoded bc of the nature of the site
|
||||||
val homepage1 = getRowElements(mainbody, listOf(
|
val homepage1 = getRowElements(
|
||||||
Pair("Suggestion", "items.featured"),
|
mainbody, listOf(
|
||||||
Pair("All Movies", "items.full")
|
Pair("Suggestion", "items.featured"),
|
||||||
), ".")
|
Pair("All Movies", "items.full")
|
||||||
|
), "."
|
||||||
|
)
|
||||||
if (homepage1.isNotEmpty()) {
|
if (homepage1.isNotEmpty()) {
|
||||||
all.addAll(homepage1)
|
all.addAll(homepage1)
|
||||||
}
|
}
|
||||||
//2nd rows
|
//2nd rows
|
||||||
val homepage2 = getRowElements(mainbody, listOf(
|
val homepage2 = getRowElements(
|
||||||
Pair("Action", "genre_action"),
|
mainbody, listOf(
|
||||||
Pair("Comedy", "genre_comedy"),
|
Pair("Action", "genre_action"),
|
||||||
Pair("Romance", "genre_romance"),
|
Pair("Comedy", "genre_comedy"),
|
||||||
Pair("Horror", "genre_horror")
|
Pair("Romance", "genre_romance"),
|
||||||
//Pair("Rated-R", "genre_rated-r")
|
Pair("Horror", "genre_horror")
|
||||||
), "#")
|
//Pair("Rated-R", "genre_rated-r")
|
||||||
|
), "#"
|
||||||
|
)
|
||||||
if (homepage2.isNotEmpty()) {
|
if (homepage2.isNotEmpty()) {
|
||||||
all.addAll(homepage2)
|
all.addAll(homepage2)
|
||||||
}
|
}
|
||||||
|
@ -156,7 +170,9 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
val aName = a.select("img")?.attr("alt") ?: return@mapNotNull null
|
val aName = a.select("img")?.attr("alt") ?: return@mapNotNull null
|
||||||
val aYear = try {
|
val aYear = try {
|
||||||
aName.trim().takeLast(5).removeSuffix(")").toIntOrNull()
|
aName.trim().takeLast(5).removeSuffix(")").toIntOrNull()
|
||||||
} catch (e: Exception) { null }
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
url = aUrl,
|
url = aUrl,
|
||||||
name = aName,
|
name = aName,
|
||||||
|
@ -181,8 +197,10 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
Pair("nume", "1"),
|
Pair("nume", "1"),
|
||||||
Pair("type", "movie")
|
Pair("type", "movie")
|
||||||
)
|
)
|
||||||
val innerPage = app.post("https://pinoymovies.es/wp-admin/admin-ajax.php ",
|
val innerPage = app.post(
|
||||||
referer = url, data = content).document.select("body")?.text()?.trim()
|
"https://pinoymovies.es/wp-admin/admin-ajax.php ",
|
||||||
|
referer = url, data = content
|
||||||
|
).document.select("body")?.text()?.trim()
|
||||||
if (!innerPage.isNullOrBlank()) {
|
if (!innerPage.isNullOrBlank()) {
|
||||||
tryParseJson<EmbedUrl>(innerPage)?.let {
|
tryParseJson<EmbedUrl>(innerPage)?.let {
|
||||||
listOfLinks.add(it.embed_url)
|
listOfLinks.add(it.embed_url)
|
||||||
|
@ -204,17 +222,17 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
override suspend fun loadLinks(
|
||||||
data: String,
|
data: String,
|
||||||
isCasting: Boolean,
|
isCasting: Boolean,
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
): Boolean {
|
): Boolean {
|
||||||
// parse movie servers
|
// parse movie servers
|
||||||
var count = 0
|
var count = 0
|
||||||
tryParseJson<List<String>>(data)?.forEach { link ->
|
tryParseJson<List<String>>(data)?.forEach { link ->
|
||||||
//Log.i(this.name, "Result => (link) $link")
|
//Log.i(this.name, "Result => (link) $link")
|
||||||
if (link.startsWith("https://vstreamhub.com")) {
|
if (link.startsWith("https://vstreamhub.com")) {
|
||||||
VstreamhubHelper.getUrls(link, callback)
|
VstreamhubHelper.getUrls(link, subtitleCallback, callback)
|
||||||
count++
|
count++
|
||||||
} else if (link.contains("fembed.com")) {
|
} else if (link.contains("fembed.com")) {
|
||||||
val extractor = FEmbed()
|
val extractor = FEmbed()
|
||||||
|
@ -224,7 +242,7 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (loadExtractor(link, mainUrl, callback)) {
|
if (loadExtractor(link, mainUrl, subtitleCallback, callback)) {
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,12 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||||
import com.lagradost.cloudstream3.network.WebViewResolver
|
import com.lagradost.cloudstream3.network.WebViewResolver
|
||||||
import com.lagradost.cloudstream3.utils.*
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||||
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||||
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
class RebahinProvider : MainAPI() {
|
class RebahinProvider : MainAPI() {
|
||||||
override var mainUrl = "http://167.88.14.149"
|
override var mainUrl = "http://167.88.14.149"
|
||||||
|
@ -263,7 +264,7 @@ class RebahinProvider : MainAPI() {
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
else -> {
|
else -> {
|
||||||
loadExtractor(link, "$mainUrl/", callback)
|
loadExtractor(link, "$mainUrl/", subtitleCallback, callback)
|
||||||
if (link.startsWith("https://sbfull.com")) {
|
if (link.startsWith("https://sbfull.com")) {
|
||||||
val response = app.get(
|
val response = app.get(
|
||||||
link, interceptor = WebViewResolver(
|
link, interceptor = WebViewResolver(
|
||||||
|
|
|
@ -217,7 +217,7 @@ class SeriesflixProvider : MainAPI() {
|
||||||
allowRedirects = false
|
allowRedirects = false
|
||||||
).okhttpResponse.headers.values("location").apmap { link ->
|
).okhttpResponse.headers.values("location").apmap { link ->
|
||||||
val url1 = link.replace("#bu", "")
|
val url1 = link.replace("#bu", "")
|
||||||
loadExtractor(url1, data, callback)
|
loadExtractor(url1, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
open class SflixProvider : MainAPI() {
|
open class SflixProvider : MainAPI() {
|
||||||
|
@ -346,7 +345,7 @@ open class SflixProvider : MainAPI() {
|
||||||
"https://ws11.rabbitstream.net/socket.io/?EIO=4&transport=polling"
|
"https://ws11.rabbitstream.net/socket.io/?EIO=4&transport=polling"
|
||||||
|
|
||||||
if (iframeLink.contains("streamlare", ignoreCase = true)) {
|
if (iframeLink.contains("streamlare", ignoreCase = true)) {
|
||||||
loadExtractor(iframeLink, null).forEach(callback)
|
loadExtractor(iframeLink, null,subtitleCallback,callback)
|
||||||
} else {
|
} else {
|
||||||
extractRabbitStream(iframeLink, subtitleCallback, callback, false) { it }
|
extractRabbitStream(iframeLink, subtitleCallback, callback, false) { it }
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,7 @@ class TantifilmProvider : MainAPI() {
|
||||||
iframe.forEach { id ->
|
iframe.forEach { id ->
|
||||||
val doc2 = app.get(id).document
|
val doc2 = app.get(id).document
|
||||||
val id2 = app.get(doc2.selectFirst("iframe")!!.attr("src")).url
|
val id2 = app.get(doc2.selectFirst("iframe")!!.attr("src")).url
|
||||||
loadExtractor(id2, data, callback)
|
loadExtractor(id2, data, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ class TwoEmbedProvider : TmdbProvider() {
|
||||||
if (iframeLink.contains("rabbitstream")) {
|
if (iframeLink.contains("rabbitstream")) {
|
||||||
extractRabbitStream(iframeLink, subtitleCallback, callback, false) { it }
|
extractRabbitStream(iframeLink, subtitleCallback, callback, false) { it }
|
||||||
} else {
|
} else {
|
||||||
loadExtractor(iframeLink, embedUrl, callback)
|
loadExtractor(iframeLink, embedUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -67,8 +67,10 @@ open class VidstreamProviderTemplate : MainAPI() {
|
||||||
open val iv: String? = null
|
open val iv: String? = null
|
||||||
open val secretKey: String? = null
|
open val secretKey: String? = null
|
||||||
open val secretDecryptKey: String? = null
|
open val secretDecryptKey: String? = null
|
||||||
|
|
||||||
/** Generated the key from IV and ID */
|
/** Generated the key from IV and ID */
|
||||||
open val isUsingAdaptiveKeys: Boolean = false
|
open val isUsingAdaptiveKeys: Boolean = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate data for the encrypt-ajax automatically (only on supported sites)
|
* Generate data for the encrypt-ajax automatically (only on supported sites)
|
||||||
* See $("script[data-name='episode']")[0].dataset.value
|
* See $("script[data-name='episode']")[0].dataset.value
|
||||||
|
@ -260,7 +262,16 @@ open class VidstreamProviderTemplate : MainAPI() {
|
||||||
val iframeLink =
|
val iframeLink =
|
||||||
Jsoup.parse(app.get(data).text).selectFirst("iframe")?.attr("src") ?: return false
|
Jsoup.parse(app.get(data).text).selectFirst("iframe")?.attr("src") ?: return false
|
||||||
|
|
||||||
extractVidstream(iframeLink, this.name, callback, iv, secretKey, secretDecryptKey, isUsingAdaptiveKeys, isUsingAdaptiveData)
|
extractVidstream(
|
||||||
|
iframeLink,
|
||||||
|
this.name,
|
||||||
|
callback,
|
||||||
|
iv,
|
||||||
|
secretKey,
|
||||||
|
secretDecryptKey,
|
||||||
|
isUsingAdaptiveKeys,
|
||||||
|
isUsingAdaptiveData
|
||||||
|
)
|
||||||
// In this case the video player is a vidstream clone and can be handled by the vidstream extractor.
|
// 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.
|
// 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(vidstreamExtractorUrl ?: mainUrl)
|
val vidstreamObject = Vidstream(vidstreamExtractorUrl ?: mainUrl)
|
||||||
|
@ -268,7 +279,7 @@ open class VidstreamProviderTemplate : MainAPI() {
|
||||||
val id = Regex("""id=([^&]*)""").find(iframeLink)?.groupValues?.get(1)
|
val id = Regex("""id=([^&]*)""").find(iframeLink)?.groupValues?.get(1)
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
vidstreamObject.getUrl(id, isCasting, callback)
|
vidstreamObject.getUrl(id, isCasting, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
val html = app.get(fixUrl(iframeLink)).text
|
val html = app.get(fixUrl(iframeLink)).text
|
||||||
|
|
|
@ -22,7 +22,7 @@ class WatchAsianProvider : MainAPI() {
|
||||||
val headers = mapOf("X-Requested-By" to mainUrl)
|
val headers = mapOf("X-Requested-By" to mainUrl)
|
||||||
val doc = app.get(mainUrl, headers = headers).document
|
val doc = app.get(mainUrl, headers = headers).document
|
||||||
val rowPair = mutableListOf<Pair<String, String>>()
|
val rowPair = mutableListOf<Pair<String, String>>()
|
||||||
doc.select("div.block-tab")?.forEach {
|
doc.select("div.block-tab").forEach {
|
||||||
it?.select("ul.tab > li")?.mapNotNull { row ->
|
it?.select("ul.tab > li")?.mapNotNull { row ->
|
||||||
val link = row?.attr("data-tab") ?: return@mapNotNull null
|
val link = row?.attr("data-tab") ?: return@mapNotNull null
|
||||||
val title = row.text() ?: return@mapNotNull null
|
val title = row.text() ?: return@mapNotNull null
|
||||||
|
@ -77,12 +77,12 @@ class WatchAsianProvider : MainAPI() {
|
||||||
return document.mapNotNull {
|
return document.mapNotNull {
|
||||||
val innerA = it?.selectFirst("a") ?: return@mapNotNull null
|
val innerA = it?.selectFirst("a") ?: return@mapNotNull null
|
||||||
val link = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
|
val link = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
|
||||||
val title = it.select("h3.title")?.text() ?: return@mapNotNull null
|
val title = it.select("h3.title").text() ?: return@mapNotNull null
|
||||||
if (title.isEmpty()) {
|
if (title.isEmpty()) {
|
||||||
return@mapNotNull null
|
return@mapNotNull null
|
||||||
}
|
}
|
||||||
val year = null
|
val year = null
|
||||||
val imgsrc = innerA.select("img")?.attr("data-original") ?: return@mapNotNull null
|
val imgsrc = innerA.select("img").attr("data-original") ?: return@mapNotNull null
|
||||||
val image = fixUrlNull(imgsrc)
|
val image = fixUrlNull(imgsrc)
|
||||||
//Log.i(this.name, "Result => (img movie) $title / $link")
|
//Log.i(this.name, "Result => (img movie) $title / $link")
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
|
@ -100,31 +100,31 @@ class WatchAsianProvider : MainAPI() {
|
||||||
val body = app.get(url).document
|
val body = app.get(url).document
|
||||||
// Declare vars
|
// Declare vars
|
||||||
val isDramaDetail = url.contains("/drama-detail/")
|
val isDramaDetail = url.contains("/drama-detail/")
|
||||||
var poster = ""
|
var poster: String? = null
|
||||||
var title = ""
|
var title = ""
|
||||||
var descript: String? = null
|
var descript: String? = null
|
||||||
var year: Int? = null
|
var year: Int? = null
|
||||||
var tags: List<String>? = null
|
var tags: List<String>? = null
|
||||||
if (isDramaDetail) {
|
if (isDramaDetail) {
|
||||||
val main = body.select("div.details")
|
val main = body.select("div.details")
|
||||||
val inner = main?.select("div.info")
|
val inner = main.select("div.info")
|
||||||
// Video details
|
// Video details
|
||||||
poster = fixUrlNull(main?.select("div.img > img")?.attr("src")) ?: ""
|
poster = fixUrlNull(main.select("div.img > img").attr("src"))
|
||||||
//Log.i(this.name, "Result => (imgLinkCode) ${imgLinkCode}")
|
//Log.i(this.name, "Result => (imgLinkCode) ${imgLinkCode}")
|
||||||
title = inner?.select("h1")?.firstOrNull()?.text() ?: ""
|
title = inner.select("h1").firstOrNull()?.text() ?: ""
|
||||||
//Log.i(this.name, "Result => (year) ${title.substring(title.length - 5)}")
|
//Log.i(this.name, "Result => (year) ${title.substring(title.length - 5)}")
|
||||||
descript = inner?.text()
|
descript = inner.text()
|
||||||
|
|
||||||
inner?.select("p")?.forEach { p ->
|
inner.select("p").forEach { p ->
|
||||||
val caption =
|
val caption =
|
||||||
p?.selectFirst("span")?.text()?.trim()?.lowercase()?.removeSuffix(":")?.trim()
|
p?.selectFirst("span")?.text()?.trim()?.lowercase()?.removeSuffix(":")?.trim()
|
||||||
?: return@forEach
|
?: return@forEach
|
||||||
when (caption) {
|
when (caption) {
|
||||||
"genre" -> {
|
"genre" -> {
|
||||||
tags = p.select("a")?.mapNotNull { it?.text()?.trim() }
|
tags = p.select("a").mapNotNull { it?.text()?.trim() }
|
||||||
}
|
}
|
||||||
"released" -> {
|
"released" -> {
|
||||||
year = p.select("a")?.text()?.trim()?.toIntOrNull()
|
year = p.select("a").text().trim()?.toIntOrNull()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ class WatchAsianProvider : MainAPI() {
|
||||||
|
|
||||||
// Episodes Links
|
// Episodes Links
|
||||||
//Log.i(this.name, "Result => (all eps) ${body.select("ul.list-episode-item-2.all-episode > li")}")
|
//Log.i(this.name, "Result => (all eps) ${body.select("ul.list-episode-item-2.all-episode > li")}")
|
||||||
val episodeList = body.select("ul.list-episode-item-2.all-episode > li")?.mapNotNull { ep ->
|
val episodeList = body.select("ul.list-episode-item-2.all-episode > li").mapNotNull { ep ->
|
||||||
//Log.i(this.name, "Result => (epA) ${ep.select("a")}")
|
//Log.i(this.name, "Result => (epA) ${ep.select("a")}")
|
||||||
val innerA = ep.select("a") ?: return@mapNotNull null
|
val innerA = ep.select("a") ?: return@mapNotNull null
|
||||||
//Log.i(this.name, "Result => (innerA) ${fixUrlNull(innerA.attr("href"))}")
|
//Log.i(this.name, "Result => (innerA) ${fixUrlNull(innerA.attr("href"))}")
|
||||||
|
@ -164,7 +164,7 @@ class WatchAsianProvider : MainAPI() {
|
||||||
posterUrl = poster,
|
posterUrl = poster,
|
||||||
date = null
|
date = null
|
||||||
)
|
)
|
||||||
} ?: listOf()
|
}
|
||||||
//If there's only 1 episode, consider it a movie.
|
//If there's only 1 episode, consider it a movie.
|
||||||
if (episodeList.size == 1) {
|
if (episodeList.size == 1) {
|
||||||
//Clean title
|
//Clean title
|
||||||
|
@ -216,21 +216,24 @@ class WatchAsianProvider : MainAPI() {
|
||||||
url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> {
|
url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> {
|
||||||
val iv = "9262859232435825"
|
val iv = "9262859232435825"
|
||||||
val secretKey = "93422192433952489752342908585752"
|
val secretKey = "93422192433952489752342908585752"
|
||||||
extractVidstream(url, this.name, callback, iv, secretKey, secretKey,
|
extractVidstream(
|
||||||
|
url, this.name, callback, iv, secretKey, secretKey,
|
||||||
isUsingAdaptiveKeys = false,
|
isUsingAdaptiveKeys = false,
|
||||||
isUsingAdaptiveData = false
|
isUsingAdaptiveData = false
|
||||||
)
|
)
|
||||||
AsianEmbedHelper.getUrls(url, callback)
|
AsianEmbedHelper.getUrls(url, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
url.startsWith("https://embedsito.com") -> {
|
url.startsWith("https://embedsito.com") -> {
|
||||||
val extractor = XStreamCdn()
|
val extractor = XStreamCdn()
|
||||||
extractor.domainUrl = "embedsito.com"
|
extractor.domainUrl = "embedsito.com"
|
||||||
extractor.getSafeUrl(url)?.apmap { link ->
|
extractor.getSafeUrl(
|
||||||
callback.invoke(link)
|
url,
|
||||||
}
|
subtitleCallback = subtitleCallback,
|
||||||
|
callback = callback,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
loadExtractor(url, mainUrl, callback)
|
loadExtractor(url, mainUrl, subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,8 +243,8 @@ class WatchAsianProvider : MainAPI() {
|
||||||
private suspend fun getServerLinks(url: String): String {
|
private suspend fun getServerLinks(url: String): String {
|
||||||
val moviedoc = app.get(url, referer = mainUrl).document
|
val moviedoc = app.get(url, referer = mainUrl).document
|
||||||
return moviedoc.select("div.anime_muti_link > ul > li")
|
return moviedoc.select("div.anime_muti_link > ul > li")
|
||||||
?.mapNotNull {
|
.mapNotNull {
|
||||||
fixUrlNull(it?.attr("data-video")) ?: return@mapNotNull null
|
fixUrlNull(it?.attr("data-video")) ?: return@mapNotNull null
|
||||||
}?.toJson() ?: ""
|
}.toJson()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
class YomoviesProvider : MainAPI() {
|
class YomoviesProvider : MainAPI() {
|
||||||
override var mainUrl = "https://yomovies.plus"
|
override var mainUrl = "https://yomovies.plus"
|
||||||
|
@ -122,8 +121,15 @@ class YomoviesProvider : MainAPI() {
|
||||||
source,
|
source,
|
||||||
referer = "$mainUrl/"
|
referer = "$mainUrl/"
|
||||||
).document.select("ul.list-server-items li")
|
).document.select("ul.list-server-items li")
|
||||||
.apmap { loadExtractor(it.attr("data-video").substringBefore("=https://msubload"), "$mainUrl/", callback) }
|
.apmap {
|
||||||
else -> loadExtractor(source, "$mainUrl/", callback)
|
loadExtractor(
|
||||||
|
it.attr("data-video").substringBefore("=https://msubload"),
|
||||||
|
"$mainUrl/",
|
||||||
|
subtitleCallback,
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> loadExtractor(source, "$mainUrl/", subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -375,6 +375,7 @@ abstract class AbstractPlayerFragment(
|
||||||
subView = player_view?.findViewById(R.id.exo_subtitles)
|
subView = player_view?.findViewById(R.id.exo_subtitles)
|
||||||
subStyle = SubtitlesFragment.getCurrentSavedStyle()
|
subStyle = SubtitlesFragment.getCurrentSavedStyle()
|
||||||
player.initSubtitles(subView, subtitle_holder, subStyle)
|
player.initSubtitles(subView, subtitle_holder, subStyle)
|
||||||
|
|
||||||
SubtitlesFragment.applyStyleEvent += ::onSubStyleChanged
|
SubtitlesFragment.applyStyleEvent += ::onSubStyleChanged
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -44,7 +44,9 @@ class LinkGenerator(
|
||||||
offset: Int
|
offset: Int
|
||||||
): Boolean {
|
): Boolean {
|
||||||
links.apmap { link ->
|
links.apmap { link ->
|
||||||
if (!extract || !loadExtractor(link, referer) {
|
if (!extract || !loadExtractor(link, referer, {
|
||||||
|
subtitleCallback(PlayerSubtitleHelper.getSubtitleData(it))
|
||||||
|
}) {
|
||||||
callback(it to null)
|
callback(it to null)
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.ui.player
|
package com.lagradost.cloudstream3.ui.player
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
|
@ -89,6 +90,7 @@ class PlayerSubtitleHelper {
|
||||||
regexSubtitlesToRemoveCaptions = style.removeCaptions
|
regexSubtitlesToRemoveCaptions = style.removeCaptions
|
||||||
subtitleView?.context?.let { ctx ->
|
subtitleView?.context?.let { ctx ->
|
||||||
subStyle = style
|
subStyle = style
|
||||||
|
Log.i(TAG,"SET STYLE = $style")
|
||||||
subtitleView?.setStyle(ctx.fromSaveToStyle(style))
|
subtitleView?.setStyle(ctx.fromSaveToStyle(style))
|
||||||
subtitleView?.translationY = -style.elevation.toPx.toFloat()
|
subtitleView?.translationY = -style.elevation.toPx.toFloat()
|
||||||
val size = style.fixedTextSize
|
val size = style.fixedTextSize
|
||||||
|
|
|
@ -1901,7 +1901,7 @@ class ResultFragment : ResultTrailerPlayer() {
|
||||||
setRecommendations(d.recommendations, null)
|
setRecommendations(d.recommendations, null)
|
||||||
setActors(d.actors)
|
setActors(d.actors)
|
||||||
setNextEpisode(if (d is EpisodeResponse) d.nextAiring else null)
|
setNextEpisode(if (d is EpisodeResponse) d.nextAiring else null)
|
||||||
setTrailers(d.trailers)
|
setTrailers(d.trailers.flatMap { it.mirros }) // I dont care about subtitles yet!
|
||||||
|
|
||||||
if (syncModel.addSyncs(d.syncData)) {
|
if (syncModel.addSyncs(d.syncData)) {
|
||||||
syncModel.updateMetaAndUser()
|
syncModel.updateMetaAndUser()
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package com.lagradost.cloudstream3.utils
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import com.lagradost.cloudstream3.SubtitleFile
|
||||||
import com.lagradost.cloudstream3.TvType
|
import com.lagradost.cloudstream3.TvType
|
||||||
import com.lagradost.cloudstream3.USER_AGENT
|
import com.lagradost.cloudstream3.USER_AGENT
|
||||||
import com.lagradost.cloudstream3.app
|
import com.lagradost.cloudstream3.app
|
||||||
import com.lagradost.cloudstream3.extractors.*
|
import com.lagradost.cloudstream3.extractors.*
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
|
||||||
|
@ -155,12 +155,26 @@ suspend fun unshortenLinkSafe(url: String): String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun loadExtractor(
|
||||||
|
url: String,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
): Boolean {
|
||||||
|
return loadExtractor(
|
||||||
|
url = url,
|
||||||
|
referer = null,
|
||||||
|
subtitleCallback = subtitleCallback,
|
||||||
|
callback = callback
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to load the appropriate extractor based on link, returns true if any extractor is loaded.
|
* Tries to load the appropriate extractor based on link, returns true if any extractor is loaded.
|
||||||
* */
|
* */
|
||||||
suspend fun loadExtractor(
|
suspend fun loadExtractor(
|
||||||
url: String,
|
url: String,
|
||||||
referer: String? = null,
|
referer: String? = null,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val currentUrl = unshortenLinkSafe(url)
|
val currentUrl = unshortenLinkSafe(url)
|
||||||
|
@ -169,7 +183,7 @@ suspend fun loadExtractor(
|
||||||
if (currentUrl.replace(schemaStripRegex, "")
|
if (currentUrl.replace(schemaStripRegex, "")
|
||||||
.startsWith(extractor.mainUrl.replace(schemaStripRegex, ""))
|
.startsWith(extractor.mainUrl.replace(schemaStripRegex, ""))
|
||||||
) {
|
) {
|
||||||
extractor.getSafeUrl(currentUrl, referer)?.forEach(callback)
|
extractor.getSafeUrl(currentUrl, referer, subtitleCallback, callback)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,20 +191,6 @@ suspend fun loadExtractor(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun loadExtractor(
|
|
||||||
url: String,
|
|
||||||
referer: String? = null,
|
|
||||||
): List<ExtractorLink> {
|
|
||||||
val currentUrl = unshortenLinkSafe(url)
|
|
||||||
|
|
||||||
for (extractor in extractorApis) {
|
|
||||||
if (currentUrl.startsWith(extractor.mainUrl)) {
|
|
||||||
return extractor.getSafeUrl(currentUrl, referer) ?: emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
|
|
||||||
val extractorApis: Array<ExtractorApi> = arrayOf(
|
val extractorApis: Array<ExtractorApi> = arrayOf(
|
||||||
//AllProvider(),
|
//AllProvider(),
|
||||||
WcoStream(),
|
WcoStream(),
|
||||||
|
@ -372,14 +372,39 @@ abstract class ExtractorApi {
|
||||||
abstract val mainUrl: String
|
abstract val mainUrl: String
|
||||||
abstract val requiresReferer: Boolean
|
abstract val requiresReferer: Boolean
|
||||||
|
|
||||||
suspend fun getSafeUrl(url: String, referer: String? = null): List<ExtractorLink>? {
|
//suspend fun getSafeUrl(url: String, referer: String? = null): List<ExtractorLink>? {
|
||||||
return suspendSafeApiCall { getUrl(url, referer) }
|
// return suspendSafeApiCall { getUrl(url, referer) }
|
||||||
|
//}
|
||||||
|
|
||||||
|
// this is the new extractorapi, override to add subtitles and stuff
|
||||||
|
open suspend fun getUrl(
|
||||||
|
url: String,
|
||||||
|
referer: String? = null,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
|
getUrl(url, referer)?.forEach(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSafeUrl(
|
||||||
|
url: String,
|
||||||
|
referer: String? = null,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
getUrl(url, referer, subtitleCallback, callback)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logError(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will throw errors, use getSafeUrl if you don't want to handle the exception yourself
|
* Will throw errors, use getSafeUrl if you don't want to handle the exception yourself
|
||||||
*/
|
*/
|
||||||
abstract suspend fun getUrl(url: String, referer: String? = null): List<ExtractorLink>?
|
open suspend fun getUrl(url: String, referer: String? = null): List<ExtractorLink>? {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
open fun getExtractorUrl(id: String): String {
|
open fun getExtractorUrl(id: String): String {
|
||||||
return id
|
return id
|
||||||
|
|
Loading…
Reference in a new issue