mirror of
https://github.com/recloudstream/cloudstream-extensions-multilingual.git
synced 2024-08-15 03:15:14 +00:00
Remove no french provider
This commit is contained in:
parent
7a45516ca5
commit
b177de518d
278 changed files with 0 additions and 18133 deletions
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "ar"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"Anime",
|
|
||||||
"Cartoon",
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=akwam.to&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,224 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.Qualities
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
|
|
||||||
class AkwamProvider : MainAPI() {
|
|
||||||
override var lang = "ar"
|
|
||||||
override var mainUrl = "https://akwam.to"
|
|
||||||
override var name = "Akwam"
|
|
||||||
override val usesWebView = false
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie, TvType.Anime, TvType.Cartoon)
|
|
||||||
|
|
||||||
private fun Element.toSearchResponse(): SearchResponse? {
|
|
||||||
val url = select("a.box").attr("href") ?: return null
|
|
||||||
if (url.contains("/games/") || url.contains("/programs/")) return null
|
|
||||||
val poster = select("picture > img")
|
|
||||||
val title = poster.attr("alt")
|
|
||||||
val posterUrl = poster.attr("data-src")
|
|
||||||
val year = select(".badge-secondary").text().toIntOrNull()
|
|
||||||
|
|
||||||
// If you need to differentiate use the url.
|
|
||||||
return MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this@AkwamProvider.name,
|
|
||||||
TvType.TvSeries,
|
|
||||||
posterUrl,
|
|
||||||
year,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
// Title, Url
|
|
||||||
val moviesUrl = listOf(
|
|
||||||
"Movies" to "$mainUrl/movies",
|
|
||||||
"Series" to "$mainUrl/series",
|
|
||||||
"Shows" to "$mainUrl/shows"
|
|
||||||
)
|
|
||||||
val pages = moviesUrl.apmap {
|
|
||||||
val doc = app.get(it.second).document
|
|
||||||
val list = doc.select("div.col-lg-auto.col-md-4.col-6.mb-12").mapNotNull { element ->
|
|
||||||
element.toSearchResponse()
|
|
||||||
}
|
|
||||||
HomePageList(it.first, list)
|
|
||||||
}.sortedBy { it.name }
|
|
||||||
return HomePageResponse(pages)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val url = "$mainUrl/search?q=$query"
|
|
||||||
val doc = app.get(url).document
|
|
||||||
return doc.select("div.col-lg-auto").mapNotNull {
|
|
||||||
it.toSearchResponse()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.getIntFromText(): Int? {
|
|
||||||
return Regex("""\d+""").find(this)?.groupValues?.firstOrNull()?.toIntOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Element.toEpisode(): Episode {
|
|
||||||
val a = select("a.text-white")
|
|
||||||
val url = a.attr("href")
|
|
||||||
val title = a.text()
|
|
||||||
val thumbUrl = select("picture > img").attr("src")
|
|
||||||
val date = select("p.entry-date").text()
|
|
||||||
return newEpisode(url) {
|
|
||||||
name = title
|
|
||||||
episode = title.getIntFromText()
|
|
||||||
posterUrl = thumbUrl
|
|
||||||
addDate(date)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val doc = app.get(url).document
|
|
||||||
val isMovie = url.contains("/movie/")
|
|
||||||
val title = doc.select("h1.entry-title").text()
|
|
||||||
val posterUrl = doc.select("picture > img").attr("src")
|
|
||||||
|
|
||||||
val year =
|
|
||||||
doc.select("div.font-size-16.text-white.mt-2").firstOrNull {
|
|
||||||
it.text().contains("السنة")
|
|
||||||
}?.text()?.getIntFromText()
|
|
||||||
|
|
||||||
// A bit iffy to parse twice like this, but it'll do.
|
|
||||||
val duration =
|
|
||||||
doc.select("div.font-size-16.text-white.mt-2").firstOrNull {
|
|
||||||
it.text().contains("مدة الفيلم")
|
|
||||||
}?.text()?.getIntFromText()
|
|
||||||
|
|
||||||
val synopsis = doc.select("div.widget-body p:first-child").text()
|
|
||||||
|
|
||||||
val rating = doc.select("span.mx-2").text().split("/").lastOrNull()?.toRatingInt()
|
|
||||||
|
|
||||||
val tags = doc.select("div.font-size-16.d-flex.align-items-center.mt-3 > a").map {
|
|
||||||
it.text()
|
|
||||||
}
|
|
||||||
|
|
||||||
val actors = doc.select("div.widget-body > div > div.entry-box > a").mapNotNull {
|
|
||||||
val name = it?.selectFirst("div > .entry-title")?.text() ?: return@mapNotNull null
|
|
||||||
val image = it.selectFirst("div > img")?.attr("src") ?: return@mapNotNull null
|
|
||||||
Actor(name, image)
|
|
||||||
}
|
|
||||||
|
|
||||||
val recommendations =
|
|
||||||
doc.select("div > div.widget-body > div.row > div > div.entry-box").mapNotNull {
|
|
||||||
val recTitle = it?.selectFirst("div.entry-body > .entry-title > .text-white")
|
|
||||||
?: return@mapNotNull null
|
|
||||||
val href = recTitle.attr("href") ?: return@mapNotNull null
|
|
||||||
val name = recTitle.text() ?: return@mapNotNull null
|
|
||||||
val poster = it.selectFirst(".entry-image > a > picture > img")?.attr("data-src")
|
|
||||||
?: return@mapNotNull null
|
|
||||||
MovieSearchResponse(name, href, this.name, TvType.Movie, fixUrl(poster))
|
|
||||||
}
|
|
||||||
|
|
||||||
return if (isMovie) {
|
|
||||||
newMovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
TvType.Movie,
|
|
||||||
url
|
|
||||||
) {
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
this.year = year
|
|
||||||
this.plot = synopsis
|
|
||||||
this.rating = rating
|
|
||||||
this.tags = tags
|
|
||||||
this.duration = duration
|
|
||||||
this.recommendations = recommendations
|
|
||||||
addActors(actors)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val episodes = doc.select("div.bg-primary2.p-4.col-lg-4.col-md-6.col-12").map {
|
|
||||||
it.toEpisode()
|
|
||||||
}.let {
|
|
||||||
val isReversed = (it.lastOrNull()?.episode ?: 1) < (it.firstOrNull()?.episode ?: 0)
|
|
||||||
if (isReversed)
|
|
||||||
it.reversed()
|
|
||||||
else it
|
|
||||||
}
|
|
||||||
|
|
||||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
|
||||||
this.duration = duration
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
this.tags = tags.filterNotNull()
|
|
||||||
this.rating = rating
|
|
||||||
this.year = year
|
|
||||||
this.plot = synopsis
|
|
||||||
this.recommendations = recommendations
|
|
||||||
addActors(actors)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// // Maybe possible to not use the url shortener but cba investigating that.
|
|
||||||
// private suspend fun skipUrlShortener(url: String): AppResponse {
|
|
||||||
// return app.get(app.get(url).document.select("a.download-link").attr("href"))
|
|
||||||
// }
|
|
||||||
|
|
||||||
private fun getQualityFromId(id: Int?): Qualities {
|
|
||||||
return when (id) {
|
|
||||||
2 -> Qualities.P360 // Extrapolated
|
|
||||||
3 -> Qualities.P480
|
|
||||||
4 -> Qualities.P720
|
|
||||||
5 -> Qualities.P1080
|
|
||||||
else -> Qualities.Unknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
val doc = app.get(data).document
|
|
||||||
|
|
||||||
val links = doc.select("div.tab-content.quality").map { element ->
|
|
||||||
val quality = getQualityFromId(element.attr("id").getIntFromText())
|
|
||||||
element.select(".col-lg-6 > a:contains(تحميل)").map { linkElement ->
|
|
||||||
if (linkElement.attr("href").contains("/download/")) {
|
|
||||||
Pair(
|
|
||||||
linkElement.attr("href"),
|
|
||||||
quality,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val url = "$mainUrl/download${
|
|
||||||
linkElement.attr("href").split("/link")[1]
|
|
||||||
}${data.split("/movie|/episode|/show/episode".toRegex())[1]}"
|
|
||||||
Pair(
|
|
||||||
url,
|
|
||||||
quality,
|
|
||||||
)
|
|
||||||
// just in case if they add the shorts urls again
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.flatten()
|
|
||||||
|
|
||||||
links.map {
|
|
||||||
val linkDoc = app.get(it.first).document
|
|
||||||
val button = linkDoc.select("div.btn-loader > a")
|
|
||||||
val url = button.attr("href")
|
|
||||||
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
this.name,
|
|
||||||
this.name,
|
|
||||||
url,
|
|
||||||
this.mainUrl,
|
|
||||||
it.second.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AkwamProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AkwamProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "it"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=altadefinizione.tienda&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,159 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
|
||||||
|
|
||||||
|
|
||||||
class AltadefinizioneProvider : MainAPI() {
|
|
||||||
override var lang = "it"
|
|
||||||
override var mainUrl = "https://altadefinizione.tienda"
|
|
||||||
override var name = "Altadefinizione"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Movie
|
|
||||||
)
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
Pair("$mainUrl/cerca/anno/2022/page/", "Ultimi Film"),
|
|
||||||
Pair("$mainUrl/cerca/openload-quality/HD/page/", "Film in HD"),
|
|
||||||
Pair("$mainUrl/cinema/page/", "Ora al cinema")
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
|
||||||
val url = request.data + page
|
|
||||||
|
|
||||||
val soup = app.get(url).document
|
|
||||||
val home = soup.select("div.box").map {
|
|
||||||
val title = it.selectFirst("img")!!.attr("alt")
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = mainUrl + it.selectFirst("img")!!.attr("src")
|
|
||||||
val quality = getQualityFromString(it.selectFirst("span")!!.text())
|
|
||||||
|
|
||||||
MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
image,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
quality,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val doc = app.post(
|
|
||||||
"$mainUrl/index.php", data = mapOf(
|
|
||||||
"do" to "search",
|
|
||||||
"subaction" to "search",
|
|
||||||
"story" to query,
|
|
||||||
"sortby" to "news_read"
|
|
||||||
)
|
|
||||||
).document
|
|
||||||
return doc.select("div.box").map {
|
|
||||||
val title = it.selectFirst("img")!!.attr("alt")
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = mainUrl + it.selectFirst("img")!!.attr("src")
|
|
||||||
val quality = getQualityFromString(it.selectFirst("span")!!.text())
|
|
||||||
|
|
||||||
MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
image,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
quality,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val page = app.get(url)
|
|
||||||
val document = page.document
|
|
||||||
val title = document.selectFirst(" h1 > a")!!.text().replace("streaming", "")
|
|
||||||
val description = document.select("#sfull").toString().substringAfter("altadefinizione")
|
|
||||||
.substringBeforeLast("fonte trama").html().toString()
|
|
||||||
val rating = null
|
|
||||||
|
|
||||||
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 recomm = document.select("ul.related-list > li").map {
|
|
||||||
val href = it.selectFirst("a")!!.attr("href")
|
|
||||||
val posterUrl = mainUrl + it.selectFirst("img")!!.attr("src")
|
|
||||||
val name = it.selectFirst("img")!!.attr("alt")
|
|
||||||
MovieSearchResponse(
|
|
||||||
name,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
posterUrl,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val actors: List<ActorData> =
|
|
||||||
document.select("#staring > a").map {
|
|
||||||
ActorData(actor = Actor(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")
|
|
||||||
|
|
||||||
return newMovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
TvType.Movie,
|
|
||||||
url
|
|
||||||
) {
|
|
||||||
posterUrl = fixUrlNull(poster)
|
|
||||||
this.year = year
|
|
||||||
this.plot = description
|
|
||||||
this.rating = rating
|
|
||||||
this.recommendations = recomm
|
|
||||||
this.duration = null
|
|
||||||
this.actors = actors
|
|
||||||
this.tags = tags
|
|
||||||
addTrailer(trailerurl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
val doc = app.get(data).document
|
|
||||||
if (doc.select("div.guardahd-player").isNullOrEmpty()) {
|
|
||||||
val videoUrl =
|
|
||||||
doc.select("input").last { it.hasAttr("data-mirror") }.attr("value")
|
|
||||||
loadExtractor(videoUrl, data, subtitleCallback, callback)
|
|
||||||
doc.select("#mirrors > li > a").forEach {
|
|
||||||
loadExtractor(fixUrl(it.attr("data-target")), data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val pagelinks = doc.select("div.guardahd-player").select("iframe").attr("src")
|
|
||||||
val docLinks = app.get(pagelinks).document
|
|
||||||
docLinks.select("body > div > ul > li").forEach {
|
|
||||||
loadExtractor(fixUrl(it.attr("data-link")), data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AltadefinizioneProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AltadefinizioneProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 2
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "it"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AnimeMovie",
|
|
||||||
"Anime",
|
|
||||||
"OVA"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=aniplay.it&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,216 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.M3u8Helper
|
|
||||||
import com.lagradost.cloudstream3.utils.Qualities
|
|
||||||
|
|
||||||
class AniPlayProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://aniplay.it"
|
|
||||||
override var name = "AniPlay"
|
|
||||||
override var lang = "it"
|
|
||||||
override val hasMainPage = true
|
|
||||||
private val dubIdentifier = " (ITA)"
|
|
||||||
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Anime,
|
|
||||||
TvType.AnimeMovie,
|
|
||||||
TvType.OVA
|
|
||||||
)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getStatus(t: String?): ShowStatus? {
|
|
||||||
return when (t?.lowercase()) {
|
|
||||||
"completato" -> ShowStatus.Completed
|
|
||||||
"in corso" -> ShowStatus.Ongoing
|
|
||||||
else -> null // "annunciato"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun getType(t: String?): TvType {
|
|
||||||
return when (t?.lowercase()) {
|
|
||||||
"ona" -> TvType.OVA
|
|
||||||
"movie" -> TvType.AnimeMovie
|
|
||||||
else -> TvType.Anime //"serie", "special"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isDub(title: String): Boolean{
|
|
||||||
return title.contains(dubIdentifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ApiPoster(
|
|
||||||
@JsonProperty("imageFull") val posterUrl: String
|
|
||||||
)
|
|
||||||
|
|
||||||
data class ApiMainPageAnime(
|
|
||||||
@JsonProperty("animeId") val id: Int,
|
|
||||||
@JsonProperty("episodeNumber") val episode: String?,
|
|
||||||
@JsonProperty("animeTitle") val title: String,
|
|
||||||
@JsonProperty("animeType") val type: String,
|
|
||||||
@JsonProperty("fullHd") val fullHD: Boolean,
|
|
||||||
@JsonProperty("animeVerticalImages") val posters: List<ApiPoster>
|
|
||||||
)
|
|
||||||
|
|
||||||
data class ApiSearchResult(
|
|
||||||
@JsonProperty("id") val id: Int,
|
|
||||||
@JsonProperty("title") val title: String,
|
|
||||||
@JsonProperty("status") val status: String,
|
|
||||||
@JsonProperty("type") val type: String,
|
|
||||||
@JsonProperty("verticalImages") val posters: List<ApiPoster>
|
|
||||||
)
|
|
||||||
|
|
||||||
data class ApiGenres(
|
|
||||||
@JsonProperty("description") val name: String
|
|
||||||
)
|
|
||||||
data class ApiWebsite(
|
|
||||||
@JsonProperty("listWebsiteId") val websiteId: Int,
|
|
||||||
@JsonProperty("url") val url: String
|
|
||||||
)
|
|
||||||
|
|
||||||
data class ApiEpisode(
|
|
||||||
@JsonProperty("id") val id: Int,
|
|
||||||
@JsonProperty("title") val title: String?,
|
|
||||||
@JsonProperty("episodeNumber") val number: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun ApiEpisode.toEpisode() : Episode? {
|
|
||||||
val number = this.number.toIntOrNull() ?: return null
|
|
||||||
return Episode(
|
|
||||||
data = "$mainUrl/api/episode/${this.id}",
|
|
||||||
episode = number,
|
|
||||||
name = this.title
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ApiSeason(
|
|
||||||
@JsonProperty("id") val id: Int,
|
|
||||||
@JsonProperty("name") val name: String
|
|
||||||
)
|
|
||||||
|
|
||||||
private suspend fun ApiSeason.toEpisodeList(url: String) : List<Episode> {
|
|
||||||
return parseJson<List<ApiEpisode>>(app.get("$url/season/${this.id}").text).mapNotNull { it.toEpisode() }
|
|
||||||
}
|
|
||||||
|
|
||||||
data class ApiAnime(
|
|
||||||
@JsonProperty("title") val title: String,
|
|
||||||
@JsonProperty("alternativeTitle") val japTitle: String?,
|
|
||||||
@JsonProperty("episodeDuration") val duration: Int,
|
|
||||||
@JsonProperty("storyline") val plot: String,
|
|
||||||
@JsonProperty("type") val type: String,
|
|
||||||
@JsonProperty("status") val status: String,
|
|
||||||
@JsonProperty("genres") val genres: List<ApiGenres>,
|
|
||||||
@JsonProperty("verticalImages") val posters: List<ApiPoster>,
|
|
||||||
@JsonProperty("listWebsites") val websites: List<ApiWebsite>,
|
|
||||||
@JsonProperty("episodes") val episodes: List<ApiEpisode>,
|
|
||||||
@JsonProperty("seasons") val seasons: List<ApiSeason>?
|
|
||||||
)
|
|
||||||
|
|
||||||
data class ApiEpisodeUrl(
|
|
||||||
@JsonProperty("videoUrl") val url: String
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
val response = parseJson<List<ApiMainPageAnime>>(app.get("$mainUrl/api/home/latest-episodes?page=0").text)
|
|
||||||
|
|
||||||
val results = response.map{
|
|
||||||
val isDub = isDub(it.title)
|
|
||||||
newAnimeSearchResponse(
|
|
||||||
name = if (isDub) it.title.replace(dubIdentifier, "") else it.title,
|
|
||||||
url = "$mainUrl/api/anime/${it.id}",
|
|
||||||
type = getType(it.type),
|
|
||||||
){
|
|
||||||
addDubStatus(isDub, it.episode?.toIntOrNull())
|
|
||||||
this.posterUrl = it.posters.first().posterUrl
|
|
||||||
this.quality = if (it.fullHD) SearchQuality.HD else null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return HomePageResponse(listOf(HomePageList("Ultime uscite",results)))
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val response = parseJson<List<ApiSearchResult>>(app.get("$mainUrl/api/anime/advanced-search?page=0&size=36&query=$query").text)
|
|
||||||
|
|
||||||
return response.map {
|
|
||||||
val isDub = isDub(it.title)
|
|
||||||
|
|
||||||
newAnimeSearchResponse(
|
|
||||||
name = if (isDub) it.title.replace(dubIdentifier, "") else it.title,
|
|
||||||
url = "$mainUrl/api/anime/${it.id}",
|
|
||||||
type = getType(it.type),
|
|
||||||
){
|
|
||||||
addDubStatus(isDub)
|
|
||||||
this.posterUrl = it.posters.first().posterUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
|
|
||||||
val response = parseJson<ApiAnime>(app.get(url).text)
|
|
||||||
|
|
||||||
val tags: List<String> = response.genres.map { it.name }
|
|
||||||
|
|
||||||
val malId: Int? = response.websites.find { it.websiteId == 1 }?.url?.removePrefix("https://myanimelist.net/anime/")?.split("/")?.first()?.toIntOrNull()
|
|
||||||
val aniListId: Int? = response.websites.find { it.websiteId == 4 }?.url?.removePrefix("https://anilist.co/anime/")?.split("/")?.first()?.toIntOrNull()
|
|
||||||
|
|
||||||
val episodes = if (response.seasons.isNullOrEmpty()) response.episodes.mapNotNull { it.toEpisode() } else response.seasons.map{ it.toEpisodeList(url) }.flatten()
|
|
||||||
val isDub = isDub(response.title)
|
|
||||||
|
|
||||||
return newAnimeLoadResponse(response.title, url, getType(response.type)) {
|
|
||||||
this.name = if (isDub) response.title.replace(dubIdentifier, "") else response.title
|
|
||||||
this.japName = response.japTitle
|
|
||||||
this.plot = response.plot
|
|
||||||
this.tags = tags
|
|
||||||
this.showStatus = getStatus(response.status)
|
|
||||||
addPoster(response.posters.first().posterUrl)
|
|
||||||
addEpisodes(if (isDub) DubStatus.Dubbed else DubStatus.Subbed, episodes)
|
|
||||||
addMalId(malId)
|
|
||||||
addAniListId(aniListId)
|
|
||||||
addDuration(response.duration.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
|
|
||||||
val episode = parseJson<ApiEpisodeUrl>(app.get(data).text)
|
|
||||||
|
|
||||||
if(episode.url.contains(".m3u8")){
|
|
||||||
val m3u8Helper = M3u8Helper()
|
|
||||||
val streams = m3u8Helper.m3u8Generation(M3u8Helper.M3u8Stream(episode.url,Qualities.Unknown.value), false)
|
|
||||||
|
|
||||||
streams.forEach {
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
name,
|
|
||||||
name,
|
|
||||||
it.streamUrl,
|
|
||||||
referer = mainUrl,
|
|
||||||
quality = it.quality ?: Qualities.Unknown.value,
|
|
||||||
isM3u8 = it.streamUrl.contains(".m3u8"))) }
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
name,
|
|
||||||
name,
|
|
||||||
episode.url,
|
|
||||||
referer = mainUrl,
|
|
||||||
quality = Qualities.Unknown.value,
|
|
||||||
isM3u8 = false,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AniPlayProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AniPlayProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "id"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AnimeMovie",
|
|
||||||
"OVA",
|
|
||||||
"Anime",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=animeindo.sbs&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,192 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
import com.lagradost.nicehttp.NiceResponse
|
|
||||||
import org.jsoup.Jsoup
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
|
|
||||||
class AnimeIndoProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://animeindo.sbs"
|
|
||||||
override var name = "AnimeIndo"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override var lang = "id"
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Anime,
|
|
||||||
TvType.AnimeMovie,
|
|
||||||
TvType.OVA
|
|
||||||
)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getType(t: String): TvType {
|
|
||||||
return if (t.contains("OVA") || t.contains("Special")) TvType.OVA
|
|
||||||
else if (t.contains("Movie")) TvType.AnimeMovie
|
|
||||||
else TvType.Anime
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getStatus(t: String): ShowStatus {
|
|
||||||
return when (t) {
|
|
||||||
"Finished Airing" -> ShowStatus.Completed
|
|
||||||
"Currently Airing" -> ShowStatus.Ongoing
|
|
||||||
else -> ShowStatus.Completed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun request(url: String): NiceResponse {
|
|
||||||
val req = app.get(
|
|
||||||
url,
|
|
||||||
cookies = mapOf("recaptcha_cookie" to "#Asia/Jakarta#-420#win32#Windows#0,false,false#Google Inc. (Intel)~ANGLE (Intel, Intel(R) HD Graphics 400 Direct3D11 vs_5_0 ps_5_0)")
|
|
||||||
)
|
|
||||||
if (req.isSuccessful) {
|
|
||||||
return req
|
|
||||||
} else {
|
|
||||||
val document = app.get(url).document
|
|
||||||
val captchaKey =
|
|
||||||
document.select("script[src*=https://www.google.com/recaptcha/api.js?render=]")
|
|
||||||
.attr("src").substringAfter("render=").substringBefore("&")
|
|
||||||
val token = getCaptchaToken(url, captchaKey)
|
|
||||||
return app.post(
|
|
||||||
url,
|
|
||||||
data = mapOf(
|
|
||||||
"action" to "recaptcha_for_all",
|
|
||||||
"token" to "$token",
|
|
||||||
"sitekey" to captchaKey
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
"$mainUrl/anime-terbaru/page/" to "Anime Terbaru",
|
|
||||||
"$mainUrl/donghua-terbaru/page/" to "Donghua Terbaru"
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(
|
|
||||||
page: Int,
|
|
||||||
request: MainPageRequest
|
|
||||||
): HomePageResponse {
|
|
||||||
val document = request(request.data + page).document
|
|
||||||
val home = document.select("div.post-show > article").mapNotNull {
|
|
||||||
it.toSearchResult()
|
|
||||||
}
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getProperAnimeLink(uri: String): String {
|
|
||||||
return if (uri.contains("/anime/")) {
|
|
||||||
uri
|
|
||||||
} else {
|
|
||||||
var title = uri.substringAfter("$mainUrl/")
|
|
||||||
title = when {
|
|
||||||
(title.contains("-episode")) && !(title.contains("-movie")) -> Regex("(.+)-episode").find(
|
|
||||||
title
|
|
||||||
)?.groupValues?.get(1).toString()
|
|
||||||
(title.contains("-movie")) -> Regex("(.+)-movie").find(title)?.groupValues?.get(
|
|
||||||
1
|
|
||||||
).toString()
|
|
||||||
else -> title
|
|
||||||
}
|
|
||||||
"$mainUrl/anime/$title"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Element.toSearchResult(): AnimeSearchResponse? {
|
|
||||||
val title = this.selectFirst("div.title")?.text()?.trim() ?: return null
|
|
||||||
val href = getProperAnimeLink(this.selectFirst("a")!!.attr("href"))
|
|
||||||
val posterUrl = this.select("img[itemprop=image]").attr("src").toString()
|
|
||||||
val type = getType(this.select("div.type").text().trim())
|
|
||||||
val epNum =
|
|
||||||
this.selectFirst("span.episode")?.ownText()?.replace(Regex("[^0-9]"), "")?.trim()
|
|
||||||
?.toIntOrNull()
|
|
||||||
return newAnimeSearchResponse(title, href, type) {
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
addSub(epNum)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val link = "$mainUrl/?s=$query"
|
|
||||||
val document = request(link).document
|
|
||||||
|
|
||||||
return document.select(".site-main.relat > article").map {
|
|
||||||
val title = it.selectFirst("div.title > h2")!!.ownText().trim()
|
|
||||||
val href = it.selectFirst("a")!!.attr("href")
|
|
||||||
val posterUrl = it.selectFirst("img")!!.attr("src").toString()
|
|
||||||
val type = getType(it.select("div.type").text().trim())
|
|
||||||
newAnimeSearchResponse(title, href, type) {
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val document = request(url).document
|
|
||||||
|
|
||||||
val title = document.selectFirst("h1.entry-title")?.text().toString().trim()
|
|
||||||
val poster = document.selectFirst("div.thumb > img[itemprop=image]")?.attr("src")
|
|
||||||
val tags = document.select("div.genxed > a").map { it.text() }
|
|
||||||
val type = getType(
|
|
||||||
document.selectFirst("div.info-content > div.spe > span:nth-child(6)")?.ownText()
|
|
||||||
.toString()
|
|
||||||
)
|
|
||||||
val year = Regex("\\d, ([0-9]*)").find(
|
|
||||||
document.select("div.info-content > div.spe > span:nth-child(9) > time").text()
|
|
||||||
)?.groupValues?.get(1)?.toIntOrNull()
|
|
||||||
val status = getStatus(
|
|
||||||
document.selectFirst("div.info-content > div.spe > span:nth-child(1)")!!.ownText()
|
|
||||||
.trim()
|
|
||||||
)
|
|
||||||
val description = document.select("div[itemprop=description] > p").text()
|
|
||||||
val trailer = document.selectFirst("div.player-embed iframe")?.attr("src")
|
|
||||||
val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull {
|
|
||||||
val header = it.selectFirst("span.lchx > a") ?: return@mapNotNull null
|
|
||||||
val name = header.text().trim()
|
|
||||||
val episode = header.text().trim().replace("Episode", "").trim().toIntOrNull()
|
|
||||||
val link = fixUrl(header.attr("href"))
|
|
||||||
Episode(link, name = name, episode = episode)
|
|
||||||
}.reversed()
|
|
||||||
|
|
||||||
return newAnimeLoadResponse(title, url, type) {
|
|
||||||
engName = title
|
|
||||||
posterUrl = poster
|
|
||||||
this.year = year
|
|
||||||
addEpisodes(DubStatus.Subbed, episodes)
|
|
||||||
showStatus = status
|
|
||||||
plot = description
|
|
||||||
this.tags = tags
|
|
||||||
addTrailer(trailer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
|
|
||||||
val document = request(data).document
|
|
||||||
document.select("div.itemleft > .mirror > option").mapNotNull {
|
|
||||||
fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("src"))
|
|
||||||
}.apmap {
|
|
||||||
if (it.startsWith("https://uservideo.xyz")) {
|
|
||||||
app.get(it, referer = "$mainUrl/").document.select("iframe").attr("src")
|
|
||||||
} else {
|
|
||||||
it
|
|
||||||
}
|
|
||||||
}.apmap {
|
|
||||||
loadExtractor(it, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AnimeIndoProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AnimeIndoProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 2
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "id"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
authors = listOf("Hexated")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AnimeMovie",
|
|
||||||
"Anime",
|
|
||||||
"OVA",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=111.90.143.42&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,195 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.Qualities
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
import com.lagradost.nicehttp.NiceResponse
|
|
||||||
import org.jsoup.Jsoup
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
|
|
||||||
class AnimeSailProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://111.90.143.42"
|
|
||||||
override var name = "AnimeSail"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override var lang = "id"
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Anime,
|
|
||||||
TvType.AnimeMovie,
|
|
||||||
TvType.OVA
|
|
||||||
)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getType(t: String): TvType {
|
|
||||||
return if (t.contains("OVA") || t.contains("Special")) TvType.OVA
|
|
||||||
else if (t.contains("Movie")) TvType.AnimeMovie
|
|
||||||
else TvType.Anime
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getStatus(t: String): ShowStatus {
|
|
||||||
return when (t) {
|
|
||||||
"Completed" -> ShowStatus.Completed
|
|
||||||
"Ongoing" -> ShowStatus.Ongoing
|
|
||||||
else -> ShowStatus.Completed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun request(url: String, ref: String? = null): NiceResponse {
|
|
||||||
return app.get(
|
|
||||||
url,
|
|
||||||
headers = mapOf("Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"),
|
|
||||||
cookies = mapOf("_as_ipin_ct" to "ID"),
|
|
||||||
referer = ref
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
"$mainUrl/page/" to "Episode Terbaru",
|
|
||||||
"$mainUrl/movie-terbaru/page/" to "Movie Terbaru",
|
|
||||||
"$mainUrl/genres/donghua/page/" to "Donghua"
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
|
||||||
val document = request(request.data + page).document
|
|
||||||
val home = document.select("article").map {
|
|
||||||
it.toSearchResult()
|
|
||||||
}
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getProperAnimeLink(uri: String): String {
|
|
||||||
return if (uri.contains("/anime/")) {
|
|
||||||
uri
|
|
||||||
} else {
|
|
||||||
var title = uri.substringAfter("$mainUrl/")
|
|
||||||
title = when {
|
|
||||||
(title.contains("-episode")) && !(title.contains("-movie")) -> title.substringBefore(
|
|
||||||
"-episode"
|
|
||||||
)
|
|
||||||
(title.contains("-movie")) -> title.substringBefore("-movie")
|
|
||||||
else -> title
|
|
||||||
}
|
|
||||||
|
|
||||||
"$mainUrl/anime/$title"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Element.toSearchResult(): AnimeSearchResponse {
|
|
||||||
val href = getProperAnimeLink(fixUrlNull(this.selectFirst("a")?.attr("href")).toString())
|
|
||||||
val title = this.select(".tt > h2").text().trim()
|
|
||||||
val posterUrl = fixUrlNull(this.selectFirst("div.limit img")?.attr("src"))
|
|
||||||
val epNum = this.selectFirst(".tt > h2")?.text()?.let {
|
|
||||||
Regex("Episode\\s?([0-9]+)").find(it)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
|
||||||
}
|
|
||||||
return newAnimeSearchResponse(title, href, TvType.Anime) {
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
addSub(epNum)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val link = "$mainUrl/?s=$query"
|
|
||||||
val document = request(link).document
|
|
||||||
|
|
||||||
return document.select("div.listupd article").map {
|
|
||||||
it.toSearchResult()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val document = request(url).document
|
|
||||||
|
|
||||||
val title = document.selectFirst("h1.entry-title")?.text().toString().trim()
|
|
||||||
val type = getType(
|
|
||||||
document.select("tbody th:contains(Tipe)").next().text()
|
|
||||||
)
|
|
||||||
val episodes = document.select("ul.daftar > li").map {
|
|
||||||
val header = it.select("a").text().trim()
|
|
||||||
val name =
|
|
||||||
Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header
|
|
||||||
val link = fixUrl(it.select("a").attr("href"))
|
|
||||||
Episode(link, name = name)
|
|
||||||
}.reversed()
|
|
||||||
|
|
||||||
return newAnimeLoadResponse(title, url, type) {
|
|
||||||
posterUrl = document.selectFirst("div.entry-content > img")?.attr("src")
|
|
||||||
this.year =
|
|
||||||
document.select("tbody th:contains(Dirilis)").next().text().trim().toIntOrNull()
|
|
||||||
addEpisodes(DubStatus.Subbed, episodes)
|
|
||||||
showStatus =
|
|
||||||
getStatus(document.select("tbody th:contains(Status)").next().text().trim())
|
|
||||||
plot = document.selectFirst("div.entry-content > p")?.text()
|
|
||||||
this.tags =
|
|
||||||
document.select("tbody th:contains(Genre)").next().select("a").map { it.text() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
|
|
||||||
val document = request(data).document
|
|
||||||
|
|
||||||
document.select(".mobius > .mirror > option").apmap {
|
|
||||||
safeApiCall {
|
|
||||||
val iframe = fixUrl(
|
|
||||||
Jsoup.parse(base64Decode(it.attr("data-em"))).select("iframe").attr("src")
|
|
||||||
?: throw ErrorLoadingException("No iframe found")
|
|
||||||
)
|
|
||||||
|
|
||||||
when {
|
|
||||||
iframe.startsWith("$mainUrl/utils/player/arch/") || iframe.startsWith(
|
|
||||||
"$mainUrl/utils/player/race/"
|
|
||||||
) -> request(iframe, ref = data).document.select("source").attr("src")
|
|
||||||
.let { link ->
|
|
||||||
val source =
|
|
||||||
when {
|
|
||||||
iframe.contains("/arch/") -> "Arch"
|
|
||||||
iframe.contains("/race/") -> "Race"
|
|
||||||
else -> this.name
|
|
||||||
}
|
|
||||||
val quality =
|
|
||||||
Regex("\\.([0-9]{3,4})\\.").find(link)?.groupValues?.get(1)
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
source = source,
|
|
||||||
name = source,
|
|
||||||
url = link,
|
|
||||||
referer = mainUrl,
|
|
||||||
quality = quality?.toIntOrNull() ?: Qualities.Unknown.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// skip for now
|
|
||||||
// iframe.startsWith("$mainUrl/utils/player/fichan/") -> ""
|
|
||||||
// iframe.startsWith("$mainUrl/utils/player/blogger/") -> ""
|
|
||||||
iframe.startsWith("https://aghanim.xyz/tools/redirect/") -> {
|
|
||||||
val link = "https://rasa-cintaku-semakin-berantai.xyz/v/${iframe.substringAfter("id=").substringBefore("&token")}"
|
|
||||||
loadExtractor(link, mainUrl, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
iframe.startsWith("$mainUrl/utils/player/framezilla/") || iframe.startsWith("https://uservideo.xyz") -> {
|
|
||||||
request(iframe, ref = data).document.select("iframe").attr("src")
|
|
||||||
.let { link ->
|
|
||||||
loadExtractor(fixUrl(link), mainUrl, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
loadExtractor(iframe, mainUrl, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AnimeSailProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AnimeSailProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "it"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"Anime",
|
|
||||||
"AnimeMovie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=www.animesaturn.cc&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,201 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addRating
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.Qualities
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
|
|
||||||
class AnimeSaturnProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://www.animesaturn.cc"
|
|
||||||
override var name = "AnimeSaturn"
|
|
||||||
override var lang = "it"
|
|
||||||
override val hasMainPage = true
|
|
||||||
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Anime,
|
|
||||||
TvType.AnimeMovie,
|
|
||||||
TvType.OVA
|
|
||||||
)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getStatus(t: String?): ShowStatus? {
|
|
||||||
return when (t?.lowercase()) {
|
|
||||||
"finito" -> ShowStatus.Completed
|
|
||||||
"in corso" -> ShowStatus.Ongoing
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Element.toSearchResult(): AnimeSearchResponse {
|
|
||||||
|
|
||||||
var title = this.select("a.badge-archivio").first()!!.text()
|
|
||||||
var isDubbed = false
|
|
||||||
|
|
||||||
if (title.contains(" (ITA)")){
|
|
||||||
title = title.replace(" (ITA)", "")
|
|
||||||
isDubbed = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val url = this.select("a.badge-archivio").first()!!.attr("href")
|
|
||||||
|
|
||||||
val posterUrl = this.select("img.locandina-archivio[src]").first()!!.attr("src")
|
|
||||||
|
|
||||||
return newAnimeSearchResponse(title, url, TvType.Anime) {
|
|
||||||
addDubStatus(isDubbed)
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Element.toEpisode(): Episode? {
|
|
||||||
var episode = this.text().split(" ")[1]
|
|
||||||
if(episode.contains(".")) return null
|
|
||||||
if(episode.contains("-"))
|
|
||||||
episode = episode.split("-")[0]
|
|
||||||
|
|
||||||
return Episode(
|
|
||||||
data = this.attr("href"),
|
|
||||||
episode = episode.toInt()
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
val document = app.get(mainUrl).document
|
|
||||||
val list = ArrayList<HomePageList>()
|
|
||||||
document.select("div.container:has(span.badge-saturn)").forEach {
|
|
||||||
val tabName = it.select("span.badge-saturn").first()!!.text()
|
|
||||||
if (tabName.equals("Ultimi episodi")) return@forEach
|
|
||||||
val results = ArrayList<AnimeSearchResponse>()
|
|
||||||
it.select(".main-anime-card").forEach { card ->
|
|
||||||
var title = card.select("a[title]").first()!!.attr("title")
|
|
||||||
var isDubbed = false
|
|
||||||
if(title.contains(" (ITA)")){
|
|
||||||
title = title.replace(" (ITA)", "")
|
|
||||||
isDubbed = true
|
|
||||||
}
|
|
||||||
val posterUrl = card.select("img.new-anime").first()!!.attr("src")
|
|
||||||
val url = card.select("a").first()!!.attr("href")
|
|
||||||
|
|
||||||
results.add(newAnimeSearchResponse(title, url, TvType.Anime){
|
|
||||||
addDubStatus(isDubbed)
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
})
|
|
||||||
}
|
|
||||||
list.add(HomePageList(tabName, results))
|
|
||||||
}
|
|
||||||
return HomePageResponse(list)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val document = app.get("$mainUrl/animelist?search=$query").document
|
|
||||||
return document.select("div.item-archivio").map {
|
|
||||||
it.toSearchResult()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
|
|
||||||
val document = app.get(url).document
|
|
||||||
|
|
||||||
val title = document.select("img.cover-anime").first()!!.attr("alt")
|
|
||||||
val japTitle = document.select("div.box-trasparente-alternativo").first()!!.text()
|
|
||||||
val posterUrl = document.select("img.cover-anime[src]").first()!!.attr("src")
|
|
||||||
var malId : Int? = null
|
|
||||||
var aniListId : Int? = null
|
|
||||||
|
|
||||||
document.select("[rel=\"noopener noreferrer\"]").forEach {
|
|
||||||
if(it.attr("href").contains("myanimelist"))
|
|
||||||
malId = it.attr("href").removeSuffix("/").split('/').last().toIntOrNull()
|
|
||||||
else
|
|
||||||
aniListId = it.attr("href").removeSuffix("/").split('/').last().toIntOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
val plot = document.select("div#shown-trama").first()?.text()
|
|
||||||
|
|
||||||
val tags = document.select("a.generi-as").map { it.text() }
|
|
||||||
|
|
||||||
val details : List<String>? = document.select("div.container:contains(Stato: )").first()?.text()?.split(" ")
|
|
||||||
var status : String? = null
|
|
||||||
var duration : String? = null
|
|
||||||
var year : String? = null
|
|
||||||
var score : String? = null
|
|
||||||
|
|
||||||
val isDubbed = document.select("div.anime-title-as").first()!!.text().contains("(ITA)")
|
|
||||||
|
|
||||||
if (!details.isNullOrEmpty()) {
|
|
||||||
details.forEach {
|
|
||||||
val index = details.indexOf(it) +1
|
|
||||||
when (it) {
|
|
||||||
"Stato:" -> status = details[index]
|
|
||||||
"episodi:" -> duration = details[index]
|
|
||||||
"uscita:" -> year = details[index + 2]
|
|
||||||
"Voto:" -> score = details[index].split("/")[0]
|
|
||||||
else -> return@forEach
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val episodes = document.select("a.bottone-ep").mapNotNull{ it.toEpisode() }
|
|
||||||
|
|
||||||
return newAnimeLoadResponse(title, url, TvType.Anime) {
|
|
||||||
this.engName = title
|
|
||||||
this.japName = japTitle
|
|
||||||
this.year = year?.toIntOrNull()
|
|
||||||
this.plot = plot
|
|
||||||
this.tags = tags
|
|
||||||
this.showStatus = getStatus(status)
|
|
||||||
addPoster(posterUrl)
|
|
||||||
addRating(score)
|
|
||||||
addEpisodes(if (isDubbed) DubStatus.Dubbed else DubStatus.Subbed, episodes)
|
|
||||||
addMalId(malId)
|
|
||||||
addAniListId(aniListId)
|
|
||||||
addDuration(duration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
|
|
||||||
val page = app.get(data).document
|
|
||||||
val episodeLink = page.select("div.card-body > a[href]").find {it1 ->
|
|
||||||
it1.attr("href").contains("watch?")
|
|
||||||
}?.attr("href")
|
|
||||||
|
|
||||||
val episodePage = app.get(episodeLink!!).document
|
|
||||||
val episodeUrl: String?
|
|
||||||
var isM3U8 = false
|
|
||||||
|
|
||||||
if(episodePage.select("video.afterglow > source").isNotEmpty()) //Old player
|
|
||||||
episodeUrl = episodePage.select("video.afterglow > source").first()!!.attr("src")
|
|
||||||
|
|
||||||
else{ //New player
|
|
||||||
val script = episodePage.select("script").find {
|
|
||||||
it.toString().contains("jwplayer('player_hls').setup({")
|
|
||||||
}!!.toString()
|
|
||||||
episodeUrl = script.split(" ").find { it.contains(".m3u8") and !it.contains(".replace") }!!.replace("\"","").replace(",", "")
|
|
||||||
isM3U8 = true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
name,
|
|
||||||
name,
|
|
||||||
episodeUrl!!,
|
|
||||||
isM3u8 = isM3U8,
|
|
||||||
referer = "https://www.animesaturn.io/", //Some servers need the old host as referer, and the new ones accept it too
|
|
||||||
quality = Qualities.Unknown.value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AnimeSaturnProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AnimeSaturnProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "it"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AnimeMovie",
|
|
||||||
"Anime",
|
|
||||||
"OVA",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=www.animeworld.tv&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
File diff suppressed because one or more lines are too long
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AnimeWorldProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AnimeWorldProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "es"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AnimeMovie",
|
|
||||||
"OVA",
|
|
||||||
"Anime",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=animefenix.com&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,249 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
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 java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
class AnimefenixProvider:MainAPI() {
|
|
||||||
|
|
||||||
override var mainUrl = "https://animefenix.com"
|
|
||||||
override var name = "Animefenix"
|
|
||||||
override var lang = "es"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.AnimeMovie,
|
|
||||||
TvType.OVA,
|
|
||||||
TvType.Anime,
|
|
||||||
)
|
|
||||||
|
|
||||||
fun getDubStatus(title: String): DubStatus {
|
|
||||||
return if (title.contains("Latino") || title.contains("Castellano"))
|
|
||||||
DubStatus.Dubbed
|
|
||||||
else DubStatus.Subbed
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
val urls = listOf(
|
|
||||||
Pair("$mainUrl/", "Animes"),
|
|
||||||
Pair("$mainUrl/animes?type[]=movie&order=default", "Peliculas", ),
|
|
||||||
Pair("$mainUrl/animes?type[]=ova&order=default", "OVA's", ),
|
|
||||||
)
|
|
||||||
|
|
||||||
val items = ArrayList<HomePageList>()
|
|
||||||
|
|
||||||
items.add(
|
|
||||||
HomePageList(
|
|
||||||
"Últimos episodios",
|
|
||||||
app.get(mainUrl).document.select(".capitulos-grid div.item").map {
|
|
||||||
val title = it.selectFirst("div.overtitle")?.text()
|
|
||||||
val poster = it.selectFirst("a img")?.attr("src")
|
|
||||||
val epRegex = Regex("(-(\\d+)\$|-(\\d+)\\.(\\d+))")
|
|
||||||
val url = it.selectFirst("a")?.attr("href")?.replace(epRegex,"")
|
|
||||||
?.replace("/ver/","/")
|
|
||||||
val epNum = it.selectFirst(".is-size-7")?.text()?.replace("Episodio ","")?.toIntOrNull()
|
|
||||||
newAnimeSearchResponse(title!!, url!!) {
|
|
||||||
this.posterUrl = poster
|
|
||||||
addDubStatus(getDubStatus(title), epNum)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
urls.apmap { (url, name) ->
|
|
||||||
val response = app.get(url)
|
|
||||||
val soup = Jsoup.parse(response.text)
|
|
||||||
val home = soup.select(".list-series article").map {
|
|
||||||
val title = it.selectFirst("h3 a")?.text()
|
|
||||||
val poster = it.selectFirst("figure img")?.attr("src")
|
|
||||||
AnimeSearchResponse(
|
|
||||||
title!!,
|
|
||||||
it.selectFirst("a")?.attr("href") ?: "",
|
|
||||||
this.name,
|
|
||||||
TvType.Anime,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
if (title.contains("Latino")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
items.add(HomePageList(name, home))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (items.size <= 0) throw ErrorLoadingException()
|
|
||||||
return HomePageResponse(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
return app.get("$mainUrl/animes?q=$query").document.select(".list-series article").map {
|
|
||||||
val title = it.selectFirst("h3 a")?.text()
|
|
||||||
val href = it.selectFirst("a")?.attr("href")
|
|
||||||
val image = it.selectFirst("figure img")?.attr("src")
|
|
||||||
AnimeSearchResponse(
|
|
||||||
title!!,
|
|
||||||
href!!,
|
|
||||||
this.name,
|
|
||||||
TvType.Anime,
|
|
||||||
fixUrl(image ?: ""),
|
|
||||||
null,
|
|
||||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
|
|
||||||
DubStatus.Subbed),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val doc = Jsoup.parse(app.get(url, timeout = 120).text)
|
|
||||||
val poster = doc.selectFirst(".image > img")?.attr("src")
|
|
||||||
val title = doc.selectFirst("h1.title.has-text-orange")?.text()
|
|
||||||
val description = doc.selectFirst("p.has-text-light")?.text()
|
|
||||||
val genres = doc.select(".genres a").map { it.text() }
|
|
||||||
val status = when (doc.selectFirst(".is-narrow-desktop a.button")?.text()) {
|
|
||||||
"Emisión" -> ShowStatus.Ongoing
|
|
||||||
"Finalizado" -> ShowStatus.Completed
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
val episodes = doc.select(".anime-page__episode-list li").map {
|
|
||||||
val name = it.selectFirst("span")?.text()
|
|
||||||
val link = it.selectFirst("a")?.attr("href")
|
|
||||||
Episode(link!!, name)
|
|
||||||
}.reversed()
|
|
||||||
val type = if (doc.selectFirst("ul.has-text-light")?.text()
|
|
||||||
!!.contains("Película") && episodes.size == 1
|
|
||||||
) TvType.AnimeMovie else TvType.Anime
|
|
||||||
return newAnimeLoadResponse(title!!, url, type) {
|
|
||||||
japName = null
|
|
||||||
engName = title
|
|
||||||
posterUrl = poster
|
|
||||||
addEpisodes(DubStatus.Subbed, episodes)
|
|
||||||
plot = description
|
|
||||||
tags = genres
|
|
||||||
showStatus = status
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cleanStreamID(input: String): String = input.replace(Regex("player=.*&code=|&"),"")
|
|
||||||
|
|
||||||
data class Amazon (
|
|
||||||
@JsonProperty("file") var file : String? = null,
|
|
||||||
@JsonProperty("type") var type : String? = null,
|
|
||||||
@JsonProperty("label") var label : String? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun cleanExtractor(
|
|
||||||
source: String,
|
|
||||||
name: String,
|
|
||||||
url: String,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
callback(
|
|
||||||
ExtractorLink(
|
|
||||||
source,
|
|
||||||
name,
|
|
||||||
url,
|
|
||||||
"",
|
|
||||||
Qualities.Unknown.value,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
val soup = app.get(data).document
|
|
||||||
val script = soup.selectFirst(".player-container script")?.data()
|
|
||||||
if (script!!.contains("var tabsArray =")) {
|
|
||||||
val sourcesRegex = Regex("player=.*&code(.*)&")
|
|
||||||
val test = sourcesRegex.findAll(script).toList()
|
|
||||||
test.apmap {
|
|
||||||
val codestream = it.value
|
|
||||||
val links = when {
|
|
||||||
codestream.contains("player=2&") -> "https://embedsito.com/v/"+cleanStreamID(codestream)
|
|
||||||
codestream.contains("player=3&") -> "https://www.mp4upload.com/embed-"+cleanStreamID(codestream)+".html"
|
|
||||||
codestream.contains("player=6&") -> "https://www.yourupload.com/embed/"+cleanStreamID(codestream)
|
|
||||||
codestream.contains("player=12&") -> "http://ok.ru/videoembed/"+cleanStreamID(codestream)
|
|
||||||
codestream.contains("player=4&") -> "https://sendvid.com/"+cleanStreamID(codestream)
|
|
||||||
codestream.contains("player=9&") -> "AmaNormal https://www.animefenix.com/stream/amz.php?v="+cleanStreamID(codestream)
|
|
||||||
codestream.contains("player=11&") -> "AmazonES https://www.animefenix.com/stream/amz.php?v="+cleanStreamID(codestream)
|
|
||||||
codestream.contains("player=22&") -> "Fireload https://www.animefenix.com/stream/fl.php?v="+cleanStreamID(codestream)
|
|
||||||
|
|
||||||
else -> ""
|
|
||||||
}
|
|
||||||
loadExtractor(links, data, subtitleCallback, callback)
|
|
||||||
|
|
||||||
argamap({
|
|
||||||
if (links.contains("AmaNormal")) {
|
|
||||||
val doc = app.get(links.replace("AmaNormal ","")).document
|
|
||||||
doc.select("script").map { script ->
|
|
||||||
if (script.data().contains("sources: [{\"file\"")) {
|
|
||||||
val text = script.data().substringAfter("sources:").substringBefore("]").replace("[","")
|
|
||||||
val json = parseJson<Amazon>(text)
|
|
||||||
if (json.file != null) {
|
|
||||||
cleanExtractor(
|
|
||||||
"Amazon",
|
|
||||||
"Amazon ${json.label}",
|
|
||||||
json.file!!,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (links.contains("AmazonES")) {
|
|
||||||
val amazonES = links.replace("AmazonES ", "")
|
|
||||||
val doc = app.get("$amazonES&ext=es").document
|
|
||||||
doc.select("script").map { script ->
|
|
||||||
if (script.data().contains("sources: [{\"file\"")) {
|
|
||||||
val text = script.data().substringAfter("sources:").substringBefore("]").replace("[","")
|
|
||||||
val json = parseJson<Amazon>(text)
|
|
||||||
if (json.file != null) {
|
|
||||||
cleanExtractor(
|
|
||||||
"AmazonES",
|
|
||||||
"AmazonES ${json.label}",
|
|
||||||
json.file!!,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (links.contains("Fireload")) {
|
|
||||||
val doc = app.get(links.replace("Fireload ", "")).document
|
|
||||||
doc.select("script").map { script ->
|
|
||||||
if (script.data().contains("sources: [{\"file\"")) {
|
|
||||||
val text = script.data().substringAfter("sources:").substringBefore("]").replace("[","")
|
|
||||||
val json = parseJson<Amazon>(text)
|
|
||||||
val testurl = if (json.file?.contains("fireload") == true) {
|
|
||||||
app.get("https://${json.file}").text
|
|
||||||
} else null
|
|
||||||
if (testurl?.contains("error") == true) {
|
|
||||||
//
|
|
||||||
} else if (json.file?.contains("fireload") == true) {
|
|
||||||
cleanExtractor(
|
|
||||||
"Fireload",
|
|
||||||
"Fireload ${json.label}",
|
|
||||||
"https://"+json.file!!,
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AnimefenixProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AnimefenixProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "es"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AnimeMovie",
|
|
||||||
"Anime",
|
|
||||||
"OVA",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=animeflv.io&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,239 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
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.Qualities
|
|
||||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class AnimeflvIOProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://animeflv.io" //Also scrapes from animeid.to
|
|
||||||
override var name = "Animeflv.io"
|
|
||||||
override var lang = "es"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.AnimeMovie,
|
|
||||||
TvType.OVA,
|
|
||||||
TvType.Anime,
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
|
||||||
val items = ArrayList<HomePageList>()
|
|
||||||
val urls = listOf(
|
|
||||||
Pair("$mainUrl/series", "Series actualizadas"),
|
|
||||||
Pair("$mainUrl/peliculas", "Peliculas actualizadas"),
|
|
||||||
)
|
|
||||||
items.add(
|
|
||||||
HomePageList(
|
|
||||||
"Estrenos",
|
|
||||||
app.get(mainUrl).document.select("div#owl-demo-premiere-movies .pull-left").map {
|
|
||||||
val title = it.selectFirst("p")?.text() ?: ""
|
|
||||||
AnimeSearchResponse(
|
|
||||||
title,
|
|
||||||
fixUrl(it.selectFirst("a")?.attr("href") ?: ""),
|
|
||||||
this.name,
|
|
||||||
TvType.Anime,
|
|
||||||
it.selectFirst("img")?.attr("src"),
|
|
||||||
it.selectFirst("span.year").toString().toIntOrNull(),
|
|
||||||
EnumSet.of(DubStatus.Subbed),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
urls.apmap { (url, name) ->
|
|
||||||
val soup = app.get(url).document
|
|
||||||
val home = soup.select("div.item-pelicula").map {
|
|
||||||
val title = it.selectFirst(".item-detail p")?.text() ?: ""
|
|
||||||
val poster = it.selectFirst("figure img")?.attr("src")
|
|
||||||
AnimeSearchResponse(
|
|
||||||
title,
|
|
||||||
fixUrl(it.selectFirst("a")?.attr("href") ?: ""),
|
|
||||||
this.name,
|
|
||||||
TvType.Anime,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
|
||||||
DubStatus.Dubbed
|
|
||||||
) else EnumSet.of(DubStatus.Subbed),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
items.add(HomePageList(name, home))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (items.size <= 0) throw ErrorLoadingException()
|
|
||||||
return HomePageResponse(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val headers = mapOf(
|
|
||||||
"Host" to "animeflv.io",
|
|
||||||
"User-Agent" to USER_AGENT,
|
|
||||||
"X-Requested-With" to "XMLHttpRequest",
|
|
||||||
"DNT" to "1",
|
|
||||||
"Alt-Used" to "animeflv.io",
|
|
||||||
"Connection" to "keep-alive",
|
|
||||||
"Referer" to "https://animeflv.io",
|
|
||||||
)
|
|
||||||
val url = "$mainUrl/search.html?keyword=$query"
|
|
||||||
val document = app.get(
|
|
||||||
url,
|
|
||||||
headers = headers
|
|
||||||
).document
|
|
||||||
return document.select(".item-pelicula.pull-left").map {
|
|
||||||
val title = it.selectFirst("div.item-detail p")?.text() ?: ""
|
|
||||||
val href = fixUrl(it.selectFirst("a")?.attr("href") ?: "")
|
|
||||||
var image = it.selectFirst("figure img")?.attr("src") ?: ""
|
|
||||||
val isMovie = href.contains("/pelicula/")
|
|
||||||
if (image.contains("/static/img/picture.png")) {
|
|
||||||
image = ""
|
|
||||||
}
|
|
||||||
if (isMovie) {
|
|
||||||
MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.AnimeMovie,
|
|
||||||
image,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
AnimeSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Anime,
|
|
||||||
image,
|
|
||||||
null,
|
|
||||||
EnumSet.of(DubStatus.Subbed),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
|
||||||
// Gets the url returned from searching.
|
|
||||||
val soup = app.get(url).document
|
|
||||||
val title = soup.selectFirst(".info-content h1")?.text()
|
|
||||||
val description = soup.selectFirst("span.sinopsis")?.text()?.trim()
|
|
||||||
val poster: String? = soup.selectFirst(".poster img")?.attr("src")
|
|
||||||
val episodes = soup.select(".item-season-episodes a").map { li ->
|
|
||||||
val href = fixUrl(li.selectFirst("a")?.attr("href") ?: "")
|
|
||||||
val name = li.selectFirst("a")?.text() ?: ""
|
|
||||||
Episode(
|
|
||||||
href, name,
|
|
||||||
)
|
|
||||||
}.reversed()
|
|
||||||
|
|
||||||
val year = Regex("(\\d*)").find(soup.select(".info-half").text())
|
|
||||||
|
|
||||||
val tvType = if (url.contains("/pelicula/")) TvType.AnimeMovie else TvType.Anime
|
|
||||||
val genre = soup.select(".content-type-a a")
|
|
||||||
.map { it?.text()?.trim().toString().replace(", ", "") }
|
|
||||||
val duration = Regex("""(\d*)""").find(
|
|
||||||
soup.select("p.info-half:nth-child(4)").text()
|
|
||||||
)
|
|
||||||
|
|
||||||
return when (tvType) {
|
|
||||||
TvType.Anime -> {
|
|
||||||
return newAnimeLoadResponse(title ?: "", url, tvType) {
|
|
||||||
japName = null
|
|
||||||
engName = title
|
|
||||||
posterUrl = poster
|
|
||||||
this.year = null
|
|
||||||
addEpisodes(DubStatus.Subbed, episodes)
|
|
||||||
plot = description
|
|
||||||
tags = genre
|
|
||||||
|
|
||||||
showStatus = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TvType.AnimeMovie -> {
|
|
||||||
MovieLoadResponse(
|
|
||||||
title ?: "",
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
tvType,
|
|
||||||
url,
|
|
||||||
poster,
|
|
||||||
year.toString().toIntOrNull(),
|
|
||||||
description,
|
|
||||||
null,
|
|
||||||
genre,
|
|
||||||
duration.toString().toIntOrNull(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class MainJson(
|
|
||||||
@JsonProperty("source") val source: List<Source>,
|
|
||||||
@JsonProperty("source_bk") val sourceBk: String?,
|
|
||||||
@JsonProperty("track") val track: List<String>?,
|
|
||||||
@JsonProperty("advertising") val advertising: List<String>?,
|
|
||||||
@JsonProperty("linkiframe") val linkiframe: String?
|
|
||||||
)
|
|
||||||
|
|
||||||
data class Source(
|
|
||||||
@JsonProperty("file") val file: String,
|
|
||||||
@JsonProperty("label") val label: String,
|
|
||||||
@JsonProperty("default") val default: String,
|
|
||||||
@JsonProperty("type") val type: String
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
app.get(data).document.select("li.tab-video").apmap {
|
|
||||||
val url = fixUrl(it.attr("data-video"))
|
|
||||||
if (url.contains("animeid")) {
|
|
||||||
val ajaxurl = url.replace("streaming.php", "ajax.php")
|
|
||||||
val ajaxurltext = app.get(ajaxurl).text
|
|
||||||
val json = parseJson<MainJson>(ajaxurltext)
|
|
||||||
json.source.forEach { source ->
|
|
||||||
if (source.file.contains("m3u8")) {
|
|
||||||
generateM3u8(
|
|
||||||
"Animeflv.io",
|
|
||||||
source.file,
|
|
||||||
"https://animeid.to",
|
|
||||||
headers = mapOf("Referer" to "https://animeid.to")
|
|
||||||
).apmap {
|
|
||||||
callback(
|
|
||||||
ExtractorLink(
|
|
||||||
"Animeflv.io",
|
|
||||||
"Animeflv.io",
|
|
||||||
it.url,
|
|
||||||
"https://animeid.to",
|
|
||||||
getQualityFromName(it.quality.toString()),
|
|
||||||
it.url.contains("m3u8")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback(
|
|
||||||
ExtractorLink(
|
|
||||||
name,
|
|
||||||
"$name ${source.label}",
|
|
||||||
source.file,
|
|
||||||
"https://animeid.to",
|
|
||||||
Qualities.Unknown.value,
|
|
||||||
isM3u8 = source.file.contains("m3u8")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loadExtractor(url, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AnimeflvIOProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AnimeflvIOProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "es"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AnimeMovie",
|
|
||||||
"Anime",
|
|
||||||
"OVA",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=www3.animeflv.net&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,182 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class AnimeflvnetProvider : MainAPI() {
|
|
||||||
companion object {
|
|
||||||
fun getType(t: String): TvType {
|
|
||||||
return if (t.contains("OVA") || t.contains("Especial")) TvType.OVA
|
|
||||||
else if (t.contains("Película")) TvType.AnimeMovie
|
|
||||||
else TvType.Anime
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDubStatus(title: String): DubStatus {
|
|
||||||
return if (title.contains("Latino") || title.contains("Castellano"))
|
|
||||||
DubStatus.Dubbed
|
|
||||||
else DubStatus.Subbed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override var mainUrl = "https://www3.animeflv.net"
|
|
||||||
override var name = "Animeflv.net"
|
|
||||||
override var lang = "es"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.AnimeMovie,
|
|
||||||
TvType.OVA,
|
|
||||||
TvType.Anime,
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
val urls = listOf(
|
|
||||||
Pair("$mainUrl/browse?type[]=movie&order=updated", "Películas"),
|
|
||||||
Pair("$mainUrl/browse?status[]=2&order=default", "Animes"),
|
|
||||||
Pair("$mainUrl/browse?status[]=1&order=rating", "En emision"),
|
|
||||||
)
|
|
||||||
val items = ArrayList<HomePageList>()
|
|
||||||
items.add(
|
|
||||||
HomePageList(
|
|
||||||
"Últimos episodios",
|
|
||||||
app.get(mainUrl).document.select("main.Main ul.ListEpisodios li").mapNotNull {
|
|
||||||
val title = it.selectFirst("strong.Title")?.text() ?: return@mapNotNull null
|
|
||||||
val poster = it.selectFirst("span img")?.attr("src") ?: return@mapNotNull null
|
|
||||||
val epRegex = Regex("(-(\\d+)\$)")
|
|
||||||
val url = it.selectFirst("a")?.attr("href")?.replace(epRegex, "")
|
|
||||||
?.replace("ver/", "anime/") ?: return@mapNotNull null
|
|
||||||
val epNum =
|
|
||||||
it.selectFirst("span.Capi")?.text()?.replace("Episodio ", "")?.toIntOrNull()
|
|
||||||
newAnimeSearchResponse(title, url) {
|
|
||||||
this.posterUrl = fixUrl(poster)
|
|
||||||
addDubStatus(getDubStatus(title), epNum)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
for ((url, name) in urls) {
|
|
||||||
try {
|
|
||||||
val doc = app.get(url).document
|
|
||||||
val home = doc.select("ul.ListAnimes li article").mapNotNull {
|
|
||||||
val title = it.selectFirst("h3.Title")?.text() ?: return@mapNotNull null
|
|
||||||
val poster = it.selectFirst("figure img")?.attr("src") ?: return@mapNotNull null
|
|
||||||
newAnimeSearchResponse(
|
|
||||||
title,
|
|
||||||
fixUrl(it.selectFirst("a")?.attr("href") ?: return@mapNotNull null)
|
|
||||||
) {
|
|
||||||
this.posterUrl = fixUrl(poster)
|
|
||||||
addDubStatus(getDubStatus(title))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
items.add(HomePageList(name, home))
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (items.size <= 0) throw ErrorLoadingException()
|
|
||||||
return HomePageResponse(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
data class SearchObject(
|
|
||||||
@JsonProperty("id") val id: String,
|
|
||||||
@JsonProperty("title") val title: String,
|
|
||||||
@JsonProperty("type") val type: String,
|
|
||||||
@JsonProperty("last_id") val lastId: String,
|
|
||||||
@JsonProperty("slug") val slug: String
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val response = app.post(
|
|
||||||
"https://www3.animeflv.net/api/animes/search",
|
|
||||||
data = mapOf(Pair("value", query))
|
|
||||||
).text
|
|
||||||
val json = parseJson<List<SearchObject>>(response)
|
|
||||||
return json.map { searchr ->
|
|
||||||
val title = searchr.title
|
|
||||||
val href = "$mainUrl/anime/${searchr.slug}"
|
|
||||||
val image = "$mainUrl/uploads/animes/covers/${searchr.id}.jpg"
|
|
||||||
AnimeSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Anime,
|
|
||||||
fixUrl(image),
|
|
||||||
null,
|
|
||||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
|
|
||||||
DubStatus.Subbed
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val doc = app.get(url).document
|
|
||||||
val episodes = ArrayList<Episode>()
|
|
||||||
val title = doc.selectFirst("h1.Title")!!.text()
|
|
||||||
val poster = doc.selectFirst("div.AnimeCover div.Image figure img")?.attr("src")!!
|
|
||||||
val description = doc.selectFirst("div.Description p")?.text()
|
|
||||||
val type = doc.selectFirst("span.Type")?.text() ?: ""
|
|
||||||
val status = when (doc.selectFirst("p.AnmStts span")?.text()) {
|
|
||||||
"En emision" -> ShowStatus.Ongoing
|
|
||||||
"Finalizado" -> ShowStatus.Completed
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
val genre = doc.select("nav.Nvgnrs a")
|
|
||||||
.map { it?.text()?.trim().toString() }
|
|
||||||
|
|
||||||
doc.select("script").map { script ->
|
|
||||||
if (script.data().contains("var episodes = [")) {
|
|
||||||
val data = script.data().substringAfter("var episodes = [").substringBefore("];")
|
|
||||||
data.split("],").forEach {
|
|
||||||
val epNum = it.removePrefix("[").substringBefore(",")
|
|
||||||
// val epthumbid = it.removePrefix("[").substringAfter(",").substringBefore("]")
|
|
||||||
val animeid = doc.selectFirst("div.Strs.RateIt")?.attr("data-id")
|
|
||||||
val epthumb = "https://cdn.animeflv.net/screenshots/$animeid/$epNum/th_3.jpg"
|
|
||||||
val link = url.replace("/anime/", "/ver/") + "-$epNum"
|
|
||||||
episodes.add(
|
|
||||||
Episode(
|
|
||||||
link,
|
|
||||||
null,
|
|
||||||
posterUrl = epthumb,
|
|
||||||
episode = epNum.toIntOrNull()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newAnimeLoadResponse(title, url, getType(type)) {
|
|
||||||
posterUrl = fixUrl(poster)
|
|
||||||
addEpisodes(DubStatus.Subbed, episodes.reversed())
|
|
||||||
showStatus = status
|
|
||||||
plot = description
|
|
||||||
tags = genre
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
app.get(data).document.select("script").apmap { script ->
|
|
||||||
if (script.data().contains("var videos = {") || script.data()
|
|
||||||
.contains("var anime_id =") || script.data().contains("server")
|
|
||||||
) {
|
|
||||||
val videos = script.data().replace("\\/", "/")
|
|
||||||
fetchUrls(videos).map {
|
|
||||||
it.replace("https://embedsb.com/e/", "https://watchsb.com/e/")
|
|
||||||
.replace("https://ok.ru", "http://ok.ru")
|
|
||||||
}.apmap {
|
|
||||||
loadExtractor(it, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class AnimeflvnetProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(AnimeflvnetProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "it"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"Live",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=calciostreaming.live&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,107 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.utils.*
|
|
||||||
|
|
||||||
|
|
||||||
class CalcioStreamingProvider : MainAPI() {
|
|
||||||
override var lang = "it"
|
|
||||||
override var mainUrl = "https://calciostreaming.live"
|
|
||||||
override var name = "CalcioStreaming"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Live,
|
|
||||||
|
|
||||||
)
|
|
||||||
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
|
||||||
val document = app.get(mainUrl+"/partite-streaming.html").document
|
|
||||||
val sections = document.select("div.slider-title").filter {it -> it.select("div.item").isNotEmpty()}
|
|
||||||
|
|
||||||
if (sections.isEmpty()) throw ErrorLoadingException()
|
|
||||||
|
|
||||||
return HomePageResponse(sections.map { it ->
|
|
||||||
val categoryname = it.selectFirst("h2 > strong")!!.text()
|
|
||||||
val shows = it.select("div.item").map {
|
|
||||||
val href = it.selectFirst("a")!!.attr("href")
|
|
||||||
val name = it.selectFirst("a > div > h1")!!.text()
|
|
||||||
val posterurl = fixUrl(it.selectFirst("a > img")!!.attr("src"))
|
|
||||||
LiveSearchResponse(
|
|
||||||
name,
|
|
||||||
href,
|
|
||||||
this@CalcioStreamingProvider.name,
|
|
||||||
TvType.Live,
|
|
||||||
posterurl,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
HomePageList(
|
|
||||||
categoryname,
|
|
||||||
shows,
|
|
||||||
isHorizontalImages = true
|
|
||||||
)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
|
|
||||||
val document = app.get(url).document
|
|
||||||
val poster = fixUrl(document.select("#title-single > div").attr("style").substringAfter("url(").substringBeforeLast(")"))
|
|
||||||
val Matchstart = document.select("div.info-wrap > div").textNodes().joinToString("").trim()
|
|
||||||
return LiveStreamLoadResponse(
|
|
||||||
document.selectFirst(" div.info-t > h1")!!.text(),
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
url,
|
|
||||||
poster,
|
|
||||||
plot = Matchstart
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private suspend fun extractVideoLinks(
|
|
||||||
url: String,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
) {
|
|
||||||
val document = app.get(url).document
|
|
||||||
document.select("button.btn").forEach { button ->
|
|
||||||
val link1 = button.attr("data-link")
|
|
||||||
val doc2 = app.get(link1).document
|
|
||||||
val truelink = doc2.selectFirst("iframe")!!.attr("src")
|
|
||||||
val newpage = app.get(truelink, referer = link1).document
|
|
||||||
val streamurl = Regex(""""((.|\n)*?).";""").find(
|
|
||||||
getAndUnpack(
|
|
||||||
newpage.select("script")[6].childNode(0).toString()
|
|
||||||
))!!.value.replace("""src="""", "").replace(""""""", "").replace(";", "")
|
|
||||||
|
|
||||||
callback(
|
|
||||||
ExtractorLink(
|
|
||||||
this.name,
|
|
||||||
button.text(),
|
|
||||||
streamurl,
|
|
||||||
truelink,
|
|
||||||
quality = 0,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
extractVideoLinks(data, callback)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class CalcioStreamingProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(CalcioStreamingProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "it"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=cb01.rip&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,187 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
|
|
||||||
|
|
||||||
class CineBlogProvider : MainAPI() {
|
|
||||||
override var lang = "it"
|
|
||||||
override var mainUrl = "https://cb01.rip"
|
|
||||||
override var name = "CineBlog"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Movie,
|
|
||||||
TvType.TvSeries,
|
|
||||||
)
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
Pair("$mainUrl/popolari/page/number/?get=movies", "Film Popolari"),
|
|
||||||
Pair("$mainUrl/popolari/page/number/?get=tv", "Serie Tv Popolari"),
|
|
||||||
Pair("$mainUrl/i-piu-votati/page/number/?get=movies", "Film più votati"),
|
|
||||||
Pair("$mainUrl/i-piu-votati/page/number/?get=tv", "Serie Tv più votate"),
|
|
||||||
Pair("$mainUrl/anno/2022/page/number", "Ultime uscite"),
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(
|
|
||||||
page: Int,
|
|
||||||
request : MainPageRequest
|
|
||||||
): HomePageResponse {
|
|
||||||
val url = request.data.replace("number", page.toString())
|
|
||||||
val soup = app.get(url, referer = url.substringBefore("page")).document
|
|
||||||
val home = soup.select("article.item").map {
|
|
||||||
val title = it.selectFirst("div.data > h3 > a")!!.text().substringBefore("(")
|
|
||||||
val link = it.selectFirst("div.poster > a")!!.attr("href")
|
|
||||||
val quality = getQualityFromString(it.selectFirst("span.quality")?.text())
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
it.selectFirst("img")!!.attr("src"),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
quality = quality
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val queryformatted = query.replace(" ", "+")
|
|
||||||
val url = "$mainUrl?s=$queryformatted"
|
|
||||||
val doc = app.get(url,referer= mainUrl ).document
|
|
||||||
return doc.select("div.result-item").map {
|
|
||||||
val href = it.selectFirst("div.image > div > a")!!.attr("href")
|
|
||||||
val poster = it.selectFirst("div.image > div > a > img")!!.attr("src")
|
|
||||||
val name = it.selectFirst("div.details > div.title > a")!!.text().substringBefore("(")
|
|
||||||
MovieSearchResponse(
|
|
||||||
name,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
poster
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val page = app.get(url)
|
|
||||||
val document = page.document
|
|
||||||
val type = if (url.contains("film")) TvType.Movie else TvType.TvSeries
|
|
||||||
val title = document.selectFirst("div.data > h1")!!.text().substringBefore("(")
|
|
||||||
val description = document.select("#info > div.wp-content > p").html().toString()
|
|
||||||
val rating = null
|
|
||||||
var year = document.selectFirst(" div.data > div.extra > span.date")!!.text().substringAfter(",")
|
|
||||||
.filter { it.isDigit() }
|
|
||||||
if (year.length > 4) {
|
|
||||||
year = year.dropLast(4)
|
|
||||||
}
|
|
||||||
|
|
||||||
val poster = document.selectFirst("div.poster > img")!!.attr("src")
|
|
||||||
|
|
||||||
val recomm = document.select("#single_relacionados >article").map {
|
|
||||||
val href = it.selectFirst("a")!!.attr("href")
|
|
||||||
val posterUrl = it.selectFirst("a > img")!!.attr("src")
|
|
||||||
val name = it.selectFirst("a > img")!!.attr("alt").substringBeforeLast("(")
|
|
||||||
MovieSearchResponse(
|
|
||||||
name,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
posterUrl
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (type == TvType.TvSeries) {
|
|
||||||
|
|
||||||
val episodeList = ArrayList<Episode>()
|
|
||||||
document.select("#seasons > div").reversed().map { element ->
|
|
||||||
val season = element.selectFirst("div.se-q > span.se-t")!!.text().toInt()
|
|
||||||
element.select("div.se-a > ul > li").filter { it -> it.text()!="There are still no episodes this season" }.map{ episode ->
|
|
||||||
val href = episode.selectFirst("div.episodiotitle > a")!!.attr("href")
|
|
||||||
val epNum =episode.selectFirst("div.numerando")!!.text().substringAfter("-").filter { it.isDigit() }.toIntOrNull()
|
|
||||||
val epTitle = episode.selectFirst("div.episodiotitle > a")!!.text()
|
|
||||||
val posterUrl = episode.selectFirst("div.imagen > img")!!.attr("src")
|
|
||||||
episodeList.add(
|
|
||||||
Episode(
|
|
||||||
href,
|
|
||||||
epTitle,
|
|
||||||
season,
|
|
||||||
epNum,
|
|
||||||
posterUrl,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TvSeriesLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
type,
|
|
||||||
episodeList,
|
|
||||||
fixUrlNull(poster),
|
|
||||||
year.toIntOrNull(),
|
|
||||||
description,
|
|
||||||
null,
|
|
||||||
rating,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
mutableListOf(),
|
|
||||||
recomm
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val actors: List<ActorData> =
|
|
||||||
document.select("div.person").filter{ it -> it.selectFirst("div.img > a > img")?.attr("src")!!.contains("/no/cast.png").not()}.map { actordata ->
|
|
||||||
val actorName = actordata.selectFirst("div.data > div.name > a")!!.text()
|
|
||||||
val actorImage : String? = actordata.selectFirst("div.img > a > img")?.attr("src")
|
|
||||||
val roleActor = actordata.selectFirst("div.data > div.caracter")!!.text()
|
|
||||||
ActorData(actor = Actor(actorName, image = actorImage), roleString = roleActor )
|
|
||||||
}
|
|
||||||
return newMovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
type,
|
|
||||||
url
|
|
||||||
) {
|
|
||||||
posterUrl = fixUrlNull(poster)
|
|
||||||
this.year = year.toIntOrNull()
|
|
||||||
this.plot = description
|
|
||||||
this.rating = rating
|
|
||||||
this.recommendations = recomm
|
|
||||||
this.duration = null
|
|
||||||
this.actors = actors
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
val doc = app.get(data).document
|
|
||||||
val type = if( data.contains("film") ){"movie"} else {"tv"}
|
|
||||||
val idpost=doc.select("#player-option-1").attr("data-post")
|
|
||||||
val test = app.post("$mainUrl/wp-admin/admin-ajax.php", headers = mapOf(
|
|
||||||
"content-type" to "application/x-www-form-urlencoded; charset=UTF-8",
|
|
||||||
"accept" to "*/*",
|
|
||||||
"X-Requested-With" to "XMLHttpRequest",
|
|
||||||
), data = mapOf(
|
|
||||||
"action" to "doo_player_ajax",
|
|
||||||
"post" to idpost,
|
|
||||||
"nume" to "1",
|
|
||||||
"type" to type,
|
|
||||||
))
|
|
||||||
|
|
||||||
val url2= Regex("""src='((.|\\n)*?)'""").find(test.text)?.groups?.get(1)?.value.toString()
|
|
||||||
val trueUrl = app.get(url2, headers = mapOf("referer" to mainUrl)).url
|
|
||||||
loadExtractor(trueUrl, data, subtitleCallback, callback)
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class CineBlogProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(CineBlogProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "es"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=cinecalidad.lol&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,258 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
// import com.lagradost.cloudstream3.extractors.Cinestart
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
|
|
||||||
class CinecalidadProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://cinecalidad.lol"
|
|
||||||
override var name = "Cinecalidad"
|
|
||||||
override var lang = "es"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Movie,
|
|
||||||
TvType.TvSeries,
|
|
||||||
)
|
|
||||||
override val vpnStatus = VPNStatus.MightBeNeeded //Due to evoload sometimes not loading
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
Pair("$mainUrl/ver-serie/page/", "Series"),
|
|
||||||
Pair("$mainUrl/page/", "Peliculas"),
|
|
||||||
Pair("$mainUrl/genero-de-la-pelicula/peliculas-en-calidad-4k/page/", "4K UHD"),
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(
|
|
||||||
page: Int,
|
|
||||||
request : MainPageRequest
|
|
||||||
): HomePageResponse {
|
|
||||||
val url = request.data + page
|
|
||||||
|
|
||||||
val soup = app.get(url).document
|
|
||||||
val home = soup.select(".item.movies").map {
|
|
||||||
val title = it.selectFirst("div.in_title")!!.text()
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
if (link.contains("/ver-pelicula/")) TvType.Movie else TvType.TvSeries,
|
|
||||||
it.selectFirst(".poster.custom img")!!.attr("data-src"),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val url = "$mainUrl/?s=${query}"
|
|
||||||
val document = app.get(url).document
|
|
||||||
|
|
||||||
return document.select("article").map {
|
|
||||||
val title = it.selectFirst("div.in_title")!!.text()
|
|
||||||
val href = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = it.selectFirst(".poster.custom img")!!.attr("data-src")
|
|
||||||
val isMovie = href.contains("/ver-pelicula/")
|
|
||||||
|
|
||||||
if (isMovie) {
|
|
||||||
MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
image,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.TvSeries,
|
|
||||||
image,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
|
||||||
val soup = app.get(url, timeout = 120).document
|
|
||||||
|
|
||||||
val title = soup.selectFirst(".single_left h1")!!.text()
|
|
||||||
val description = soup.selectFirst("div.single_left table tbody tr td p")?.text()?.trim()
|
|
||||||
val poster: String? = soup.selectFirst(".alignnone")!!.attr("data-src")
|
|
||||||
val episodes = soup.select("div.se-c div.se-a ul.episodios li").map { li ->
|
|
||||||
val href = li.selectFirst("a")!!.attr("href")
|
|
||||||
val epThumb = li.selectFirst("img.lazy")!!.attr("data-src")
|
|
||||||
val name = li.selectFirst(".episodiotitle a")!!.text()
|
|
||||||
val seasonid =
|
|
||||||
li.selectFirst(".numerando")!!.text().replace(Regex("(S|E)"), "").let { str ->
|
|
||||||
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
|
|
||||||
}
|
|
||||||
val isValid = seasonid.size == 2
|
|
||||||
val episode = if (isValid) seasonid.getOrNull(1) else null
|
|
||||||
val season = if (isValid) seasonid.getOrNull(0) else null
|
|
||||||
Episode(
|
|
||||||
href,
|
|
||||||
name,
|
|
||||||
season,
|
|
||||||
episode,
|
|
||||||
if (epThumb.contains("svg")) null else epThumb
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return when (val tvType =
|
|
||||||
if (url.contains("/ver-pelicula/")) TvType.Movie else TvType.TvSeries) {
|
|
||||||
TvType.TvSeries -> {
|
|
||||||
TvSeriesLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
tvType,
|
|
||||||
episodes,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
description,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
TvType.Movie -> {
|
|
||||||
MovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
tvType,
|
|
||||||
url,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
description,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
|
|
||||||
val datam = app.get(data)
|
|
||||||
val doc = datam.document
|
|
||||||
val datatext = datam.text
|
|
||||||
|
|
||||||
doc.select(".dooplay_player_option").apmap {
|
|
||||||
val url = it.attr("data-option")
|
|
||||||
// if (url.startsWith("https://cinestart.net")) {
|
|
||||||
// val extractor = Cinestart()
|
|
||||||
// extractor.getSafeUrl(url, null, subtitleCallback, callback)
|
|
||||||
// } else {
|
|
||||||
loadExtractor(url, mainUrl, subtitleCallback, callback)
|
|
||||||
// }
|
|
||||||
if (url.startsWith("https://cinecalidad.lol")) {
|
|
||||||
val cineurlregex =
|
|
||||||
Regex("(https:\\/\\/cinecalidad\\.lol\\/play\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
|
||||||
cineurlregex.findAll(url).map {
|
|
||||||
it.value.replace("/play/", "/play/r.php")
|
|
||||||
}.toList().apmap {
|
|
||||||
app.get(
|
|
||||||
it,
|
|
||||||
headers = mapOf(
|
|
||||||
"Host" to "cinecalidad.lol",
|
|
||||||
"User-Agent" to USER_AGENT,
|
|
||||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
|
||||||
"Accept-Language" to "en-US,en;q=0.5",
|
|
||||||
"DNT" to "1",
|
|
||||||
"Connection" to "keep-alive",
|
|
||||||
"Referer" to data,
|
|
||||||
"Upgrade-Insecure-Requests" to "1",
|
|
||||||
"Sec-Fetch-Dest" to "iframe",
|
|
||||||
"Sec-Fetch-Mode" to "navigate",
|
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
|
||||||
"Sec-Fetch-User" to "?1",
|
|
||||||
),
|
|
||||||
allowRedirects = false
|
|
||||||
).okhttpResponse.headers.values("location").apmap { extractedurl ->
|
|
||||||
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 {
|
|
||||||
val url = it.attr("data-option")
|
|
||||||
// if (url.startsWith("https://cinestart.net")) {
|
|
||||||
// val extractor = Cinestart()
|
|
||||||
// extractor.getSafeUrl(url, null, subtitleCallback, callback)
|
|
||||||
// } else {
|
|
||||||
loadExtractor(url, mainUrl, subtitleCallback, callback)
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (url.startsWith("https://cinecalidad.lol")) {
|
|
||||||
val cineurlregex =
|
|
||||||
Regex("(https:\\/\\/cinecalidad\\.lol\\/play\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
|
||||||
cineurlregex.findAll(url).map {
|
|
||||||
it.value.replace("/play/", "/play/r.php")
|
|
||||||
}.toList().apmap {
|
|
||||||
app.get(
|
|
||||||
it,
|
|
||||||
headers = mapOf(
|
|
||||||
"Host" to "cinecalidad.lol",
|
|
||||||
"User-Agent" to USER_AGENT,
|
|
||||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
|
||||||
"Accept-Language" to "en-US,en;q=0.5",
|
|
||||||
"DNT" to "1",
|
|
||||||
"Connection" to "keep-alive",
|
|
||||||
"Referer" to data,
|
|
||||||
"Upgrade-Insecure-Requests" to "1",
|
|
||||||
"Sec-Fetch-Dest" to "iframe",
|
|
||||||
"Sec-Fetch-Mode" to "navigate",
|
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
|
||||||
"Sec-Fetch-User" to "?1",
|
|
||||||
),
|
|
||||||
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")) {
|
|
||||||
doc.select("#panel_descarga.pane a").apmap {
|
|
||||||
val link =
|
|
||||||
if (data.contains("serie") || data.contains("episodio")) "${data}${it.attr("href")}"
|
|
||||||
else it.attr("href")
|
|
||||||
val docsub = app.get(link)
|
|
||||||
val linksub = docsub.document
|
|
||||||
val validsub = docsub.text
|
|
||||||
if (validsub.contains("Subtítulo") || validsub.contains("Forzados")) {
|
|
||||||
val langregex = Regex("(Subtítulo.*\$|Forzados.*\$)")
|
|
||||||
val langdoc = linksub.selectFirst("div.titulo h3")!!.text()
|
|
||||||
val reallang = langregex.find(langdoc)?.destructured?.component1()
|
|
||||||
linksub.select("a.link").apmap {
|
|
||||||
val sublink =
|
|
||||||
if (data.contains("serie") || data.contains("episodio")) "${data}${
|
|
||||||
it.attr("href")
|
|
||||||
}"
|
|
||||||
else it.attr("href")
|
|
||||||
subtitleCallback(
|
|
||||||
SubtitleFile(reallang!!, sublink)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class CinecalidadProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(CinecalidadProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "es"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"Anime",
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=cuevana3.me&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,324 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
|
|
||||||
class CuevanaProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://cuevana3.me"
|
|
||||||
override var name = "Cuevana"
|
|
||||||
override var lang = "es"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Movie,
|
|
||||||
TvType.TvSeries,
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
val items = ArrayList<HomePageList>()
|
|
||||||
val urls = listOf(
|
|
||||||
Pair(mainUrl, "Recientemente actualizadas"),
|
|
||||||
Pair("$mainUrl/estrenos/", "Estrenos"),
|
|
||||||
)
|
|
||||||
items.add(
|
|
||||||
HomePageList(
|
|
||||||
"Series",
|
|
||||||
app.get("$mainUrl/serie", timeout = 120).document.select("section.home-series li")
|
|
||||||
.map {
|
|
||||||
val title = it.selectFirst("h2.Title")!!.text()
|
|
||||||
val poster = it.selectFirst("img.lazy")!!.attr("data-src")
|
|
||||||
val url = it.selectFirst("a")!!.attr("href")
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
TvType.Anime,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
for ((url, name) in urls) {
|
|
||||||
try {
|
|
||||||
val soup = app.get(url).document
|
|
||||||
val home = soup.select("section li.xxx.TPostMv").map {
|
|
||||||
val title = it.selectFirst("h2.Title")!!.text()
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
if (link.contains("/pelicula/")) TvType.Movie else TvType.TvSeries,
|
|
||||||
it.selectFirst("img.lazy")!!.attr("data-src"),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
items.add(HomePageList(name, home))
|
|
||||||
} catch (e: Exception) {
|
|
||||||
logError(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (items.size <= 0) throw ErrorLoadingException()
|
|
||||||
return HomePageResponse(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val url = "$mainUrl/?s=${query}"
|
|
||||||
val document = app.get(url).document
|
|
||||||
|
|
||||||
return document.select("li.xxx.TPostMv").map {
|
|
||||||
val title = it.selectFirst("h2.Title")!!.text()
|
|
||||||
val href = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = it.selectFirst("img.lazy")!!.attr("data-src")
|
|
||||||
val isSerie = href.contains("/serie/")
|
|
||||||
|
|
||||||
if (isSerie) {
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.TvSeries,
|
|
||||||
image,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
image,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
|
||||||
val soup = app.get(url, timeout = 120).document
|
|
||||||
val title = soup.selectFirst("h1.Title")!!.text()
|
|
||||||
val description = soup.selectFirst(".Description p")?.text()?.trim()
|
|
||||||
val poster: String? = soup.selectFirst(".movtv-info div.Image img")!!.attr("data-src")
|
|
||||||
val year1 = soup.selectFirst("footer p.meta").toString()
|
|
||||||
val yearRegex = Regex("<span>(\\d+)</span>")
|
|
||||||
val yearf =
|
|
||||||
yearRegex.find(year1)?.destructured?.component1()?.replace(Regex("<span>|</span>"), "")
|
|
||||||
val year = if (yearf.isNullOrBlank()) null else yearf.toIntOrNull()
|
|
||||||
val episodes = soup.select(".all-episodes li.TPostMv article").map { li ->
|
|
||||||
val href = li.select("a").attr("href")
|
|
||||||
val epThumb =
|
|
||||||
li.selectFirst("div.Image img")?.attr("data-src") ?: li.selectFirst("img.lazy")!!
|
|
||||||
.attr("data-srcc")
|
|
||||||
val seasonid = li.selectFirst("span.Year")!!.text().let { str ->
|
|
||||||
str.split("x").mapNotNull { subStr -> subStr.toIntOrNull() }
|
|
||||||
}
|
|
||||||
val isValid = seasonid.size == 2
|
|
||||||
val episode = if (isValid) seasonid.getOrNull(1) else null
|
|
||||||
val season = if (isValid) seasonid.getOrNull(0) else null
|
|
||||||
Episode(
|
|
||||||
href,
|
|
||||||
null,
|
|
||||||
season,
|
|
||||||
episode,
|
|
||||||
fixUrl(epThumb)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
val tags = soup.select("ul.InfoList li.AAIco-adjust:contains(Genero) a").map { it.text() }
|
|
||||||
val tvType = if (episodes.isEmpty()) TvType.Movie else TvType.TvSeries
|
|
||||||
val recelement =
|
|
||||||
if (tvType == TvType.TvSeries) "main section div.series_listado.series div.xxx"
|
|
||||||
else "main section ul.MovieList li"
|
|
||||||
val recommendations =
|
|
||||||
soup.select(recelement).mapNotNull { element ->
|
|
||||||
val recTitle = element.select("h2.Title").text() ?: return@mapNotNull null
|
|
||||||
val image = element.select("figure img")?.attr("data-src")
|
|
||||||
val recUrl = fixUrl(element.select("a").attr("href"))
|
|
||||||
MovieSearchResponse(
|
|
||||||
recTitle,
|
|
||||||
recUrl,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
image,
|
|
||||||
year = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return when (tvType) {
|
|
||||||
TvType.TvSeries -> {
|
|
||||||
TvSeriesLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
tvType,
|
|
||||||
episodes,
|
|
||||||
poster,
|
|
||||||
year,
|
|
||||||
description,
|
|
||||||
tags = tags,
|
|
||||||
recommendations = recommendations
|
|
||||||
)
|
|
||||||
}
|
|
||||||
TvType.Movie -> {
|
|
||||||
MovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
tvType,
|
|
||||||
url,
|
|
||||||
poster,
|
|
||||||
year,
|
|
||||||
description,
|
|
||||||
tags = tags,
|
|
||||||
recommendations = recommendations
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Femcuevana(
|
|
||||||
@JsonProperty("url") val url: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
app.get(data).document.select("div.TPlayer.embed_div iframe").apmap {
|
|
||||||
val iframe = fixUrl(it.attr("data-src"))
|
|
||||||
if (iframe.contains("api.cuevana3.me/fembed/")) {
|
|
||||||
val femregex =
|
|
||||||
Regex("(https.\\/\\/api\\.cuevana3\\.me\\/fembed\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
|
||||||
femregex.findAll(iframe).map { femreg ->
|
|
||||||
femreg.value
|
|
||||||
}.toList().apmap { fem ->
|
|
||||||
val key = fem.replace("https://api.cuevana3.me/fembed/?h=", "")
|
|
||||||
val url = app.post(
|
|
||||||
"https://api.cuevana3.me/fembed/api.php",
|
|
||||||
allowRedirects = false,
|
|
||||||
headers = mapOf(
|
|
||||||
"Host" to "api.cuevana3.me",
|
|
||||||
"User-Agent" to USER_AGENT,
|
|
||||||
"Accept" to "application/json, text/javascript, */*; q=0.01",
|
|
||||||
"Accept-Language" to "en-US,en;q=0.5",
|
|
||||||
"Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8",
|
|
||||||
"X-Requested-With" to "XMLHttpRequest",
|
|
||||||
"Origin" to "https://api.cuevana3.me",
|
|
||||||
"DNT" to "1",
|
|
||||||
"Connection" to "keep-alive",
|
|
||||||
"Sec-Fetch-Dest" to "empty",
|
|
||||||
"Sec-Fetch-Mode" to "cors",
|
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
|
||||||
),
|
|
||||||
data = mapOf(Pair("h", key))
|
|
||||||
).text
|
|
||||||
val json = parseJson<Femcuevana>(url)
|
|
||||||
val link = json.url
|
|
||||||
if (link.contains("fembed")) {
|
|
||||||
loadExtractor(link, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (iframe.contains("tomatomatela")) {
|
|
||||||
val tomatoRegex =
|
|
||||||
Regex("(\\/\\/apialfa.tomatomatela.com\\/ir\\/player.php\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
|
||||||
tomatoRegex.findAll(iframe).map { tomreg ->
|
|
||||||
tomreg.value
|
|
||||||
}.toList().apmap { tom ->
|
|
||||||
val tomkey = tom.replace("//apialfa.tomatomatela.com/ir/player.php?h=", "")
|
|
||||||
app.post(
|
|
||||||
"https://apialfa.tomatomatela.com/ir/rd.php", allowRedirects = false,
|
|
||||||
headers = mapOf(
|
|
||||||
"Host" to "apialfa.tomatomatela.com",
|
|
||||||
"User-Agent" to USER_AGENT,
|
|
||||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
|
||||||
"Accept-Language" to "en-US,en;q=0.5",
|
|
||||||
"Content-Type" to "application/x-www-form-urlencoded",
|
|
||||||
"Origin" to "null",
|
|
||||||
"DNT" to "1",
|
|
||||||
"Connection" to "keep-alive",
|
|
||||||
"Upgrade-Insecure-Requests" to "1",
|
|
||||||
"Sec-Fetch-Dest" to "iframe",
|
|
||||||
"Sec-Fetch-Mode" to "navigate",
|
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
|
||||||
),
|
|
||||||
data = mapOf(Pair("url", tomkey))
|
|
||||||
).okhttpResponse.headers.values("location").apmap { loc ->
|
|
||||||
if (loc.contains("goto_ddh.php")) {
|
|
||||||
val gotoregex =
|
|
||||||
Regex("(\\/\\/api.cuevana3.me\\/ir\\/goto_ddh.php\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
|
||||||
gotoregex.findAll(loc).map { goreg ->
|
|
||||||
goreg.value.replace("//api.cuevana3.me/ir/goto_ddh.php?h=", "")
|
|
||||||
}.toList().apmap { gotolink ->
|
|
||||||
app.post(
|
|
||||||
"https://api.cuevana3.me/ir/redirect_ddh.php",
|
|
||||||
allowRedirects = false,
|
|
||||||
headers = mapOf(
|
|
||||||
"Host" to "api.cuevana3.me",
|
|
||||||
"User-Agent" to USER_AGENT,
|
|
||||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
|
||||||
"Accept-Language" to "en-US,en;q=0.5",
|
|
||||||
"Content-Type" to "application/x-www-form-urlencoded",
|
|
||||||
"Origin" to "null",
|
|
||||||
"DNT" to "1",
|
|
||||||
"Connection" to "keep-alive",
|
|
||||||
"Upgrade-Insecure-Requests" to "1",
|
|
||||||
"Sec-Fetch-Dest" to "iframe",
|
|
||||||
"Sec-Fetch-Mode" to "navigate",
|
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
|
||||||
),
|
|
||||||
data = mapOf(Pair("url", gotolink))
|
|
||||||
).okhttpResponse.headers.values("location").apmap { golink ->
|
|
||||||
loadExtractor(golink, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (loc.contains("index.php?h=")) {
|
|
||||||
val indexRegex =
|
|
||||||
Regex("(\\/\\/api.cuevana3.me\\/sc\\/index.php\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
|
||||||
indexRegex.findAll(loc).map { indreg ->
|
|
||||||
indreg.value.replace("//api.cuevana3.me/sc/index.php?h=", "")
|
|
||||||
}.toList().apmap { inlink ->
|
|
||||||
app.post(
|
|
||||||
"https://api.cuevana3.me/sc/r.php", allowRedirects = false,
|
|
||||||
headers = mapOf(
|
|
||||||
"Host" to "api.cuevana3.me",
|
|
||||||
"User-Agent" to USER_AGENT,
|
|
||||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
|
||||||
"Accept-Language" to "en-US,en;q=0.5",
|
|
||||||
"Accept-Encoding" to "gzip, deflate, br",
|
|
||||||
"Content-Type" to "application/x-www-form-urlencoded",
|
|
||||||
"Origin" to "null",
|
|
||||||
"DNT" to "1",
|
|
||||||
"Connection" to "keep-alive",
|
|
||||||
"Upgrade-Insecure-Requests" to "1",
|
|
||||||
"Sec-Fetch-Dest" to "iframe",
|
|
||||||
"Sec-Fetch-Mode" to "navigate",
|
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
|
||||||
"Sec-Fetch-User" to "?1",
|
|
||||||
),
|
|
||||||
data = mapOf(Pair("h", inlink))
|
|
||||||
).okhttpResponse.headers.values("location").apmap { link ->
|
|
||||||
loadExtractor(link, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class CuevanaProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(CuevanaProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "es"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"Anime",
|
|
||||||
"OVA",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=doramasyt.com&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,155 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
//import com.lagradost.cloudstream3.extractors.FEmbed
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
class DoramasYTProvider : MainAPI() {
|
|
||||||
companion object {
|
|
||||||
fun getType(t: String): TvType {
|
|
||||||
return if (t.contains("OVA") || t.contains("Especial")) TvType.OVA
|
|
||||||
else if (t.contains("Pelicula")) TvType.Movie
|
|
||||||
else TvType.TvSeries
|
|
||||||
}
|
|
||||||
fun getDubStatus(title: String): DubStatus {
|
|
||||||
return if (title.contains("Latino") || title.contains("Castellano"))
|
|
||||||
DubStatus.Dubbed
|
|
||||||
else DubStatus.Subbed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override var mainUrl = "https://doramasyt.com"
|
|
||||||
override var name = "DoramasYT"
|
|
||||||
override var lang = "es"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.AsianDrama,
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
val urls = listOf(
|
|
||||||
Pair("$mainUrl/emision", "En emisión"),
|
|
||||||
Pair(
|
|
||||||
"$mainUrl/doramas?categoria=pelicula&genero=false&fecha=false&letra=false",
|
|
||||||
"Peliculas"
|
|
||||||
),
|
|
||||||
Pair("$mainUrl/doramas", "Doramas"),
|
|
||||||
Pair(
|
|
||||||
"$mainUrl/doramas?categoria=live-action&genero=false&fecha=false&letra=false",
|
|
||||||
"Live Action"
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
val items = ArrayList<HomePageList>()
|
|
||||||
|
|
||||||
items.add(
|
|
||||||
HomePageList(
|
|
||||||
"Capítulos actualizados",
|
|
||||||
app.get(mainUrl, timeout = 120).document.select(".col-6").map {
|
|
||||||
val title = it.selectFirst("p")!!.text()
|
|
||||||
val poster = it.selectFirst(".chapter img")!!.attr("src")
|
|
||||||
val epRegex = Regex("episodio-(\\d+)")
|
|
||||||
val url = it.selectFirst("a")!!.attr("href").replace("ver/", "dorama/")
|
|
||||||
.replace(epRegex, "sub-espanol")
|
|
||||||
val epNum = it.selectFirst("h3")!!.text().toIntOrNull()
|
|
||||||
newAnimeSearchResponse(title,url) {
|
|
||||||
this.posterUrl = fixUrl(poster)
|
|
||||||
addDubStatus(getDubStatus(title), epNum)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
for (i in urls) {
|
|
||||||
try {
|
|
||||||
val home = app.get(i.first, timeout = 120).document.select(".col-6").map {
|
|
||||||
val title = it.selectFirst(".animedtls p")!!.text()
|
|
||||||
val poster = it.selectFirst(".anithumb img")!!.attr("src")
|
|
||||||
newAnimeSearchResponse(title, fixUrl(it.selectFirst("a")!!.attr("href"))) {
|
|
||||||
this.posterUrl = fixUrl(poster)
|
|
||||||
addDubStatus(getDubStatus(title))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
items.add(HomePageList(i.second, home))
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (items.size <= 0) throw ErrorLoadingException()
|
|
||||||
return HomePageResponse(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
return app.get("$mainUrl/buscar?q=$query", timeout = 120).document.select(".col-6").map {
|
|
||||||
val title = it.selectFirst(".animedtls p")!!.text()
|
|
||||||
val href = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = it.selectFirst(".animes img")!!.attr("src")
|
|
||||||
AnimeSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Anime,
|
|
||||||
image,
|
|
||||||
null,
|
|
||||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
|
||||||
DubStatus.Dubbed
|
|
||||||
) else EnumSet.of(DubStatus.Subbed),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val doc = app.get(url, timeout = 120).document
|
|
||||||
val poster = doc.selectFirst("div.flimimg img.img1")!!.attr("src")
|
|
||||||
val title = doc.selectFirst("h1")!!.text()
|
|
||||||
val type = doc.selectFirst("h4")!!.text()
|
|
||||||
val description = doc.selectFirst("p.textComplete")!!.text().replace("Ver menos", "")
|
|
||||||
val genres = doc.select(".nobel a").map { it.text() }
|
|
||||||
val status = when (doc.selectFirst(".state h6")?.text()) {
|
|
||||||
"Estreno" -> ShowStatus.Ongoing
|
|
||||||
"Finalizado" -> ShowStatus.Completed
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
val episodes = doc.select(".heromain .col-item").map {
|
|
||||||
val name = it.selectFirst(".dtlsflim p")!!.text()
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
val epThumb = it.selectFirst(".flimimg img.img1")!!.attr("src")
|
|
||||||
Episode(link, name, posterUrl = epThumb)
|
|
||||||
}
|
|
||||||
return newAnimeLoadResponse(title, url, getType(type)) {
|
|
||||||
posterUrl = poster
|
|
||||||
addEpisodes(DubStatus.Subbed, episodes)
|
|
||||||
showStatus = status
|
|
||||||
plot = description
|
|
||||||
tags = genres
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
app.get(data).document.select("div.playother p").apmap {
|
|
||||||
val encodedurl = it.select("p").attr("data-player")
|
|
||||||
val urlDecoded = base64Decode(encodedurl)
|
|
||||||
val url = (urlDecoded).replace("https://doramasyt.com/reproductor?url=", "")
|
|
||||||
if (url.startsWith("https://www.fembed.com")) {
|
|
||||||
val extractor = FEmbed()
|
|
||||||
extractor.getUrl(url).forEach { link ->
|
|
||||||
callback.invoke(link)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
loadExtractor(url, mainUrl, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class DoramasYTProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(DoramasYTProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.app
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorApi
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
|
||||||
|
|
||||||
class FEmbed: XStreamCdn() {
|
|
||||||
override val name: String = "FEmbed"
|
|
||||||
override val mainUrl: String = "https://www.fembed.com"
|
|
||||||
}
|
|
||||||
|
|
||||||
open class XStreamCdn : ExtractorApi() {
|
|
||||||
override val name: String = "XStreamCdn"
|
|
||||||
override val mainUrl: String = "https://embedsito.com"
|
|
||||||
override val requiresReferer = false
|
|
||||||
open var domainUrl: String = "embedsito.com"
|
|
||||||
|
|
||||||
private data class ResponseData(
|
|
||||||
@JsonProperty("file") val file: String,
|
|
||||||
@JsonProperty("label") val label: String,
|
|
||||||
//val type: String // Mp4
|
|
||||||
)
|
|
||||||
|
|
||||||
private data class ResponseJson(
|
|
||||||
@JsonProperty("success") val success: Boolean,
|
|
||||||
@JsonProperty("data") val data: List<ResponseData>?
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun getExtractorUrl(id: String): String {
|
|
||||||
return "$domainUrl/api/source/$id"
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
|
||||||
val headers = mapOf(
|
|
||||||
"Referer" to url,
|
|
||||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0",
|
|
||||||
)
|
|
||||||
val id = url.trimEnd('/').split("/").last()
|
|
||||||
val newUrl = "https://${domainUrl}/api/source/${id}"
|
|
||||||
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
|
|
||||||
with(app.post(newUrl, headers = headers)) {
|
|
||||||
if (this.code != 200) return listOf()
|
|
||||||
val text = this.text
|
|
||||||
if (text.isEmpty()) return listOf()
|
|
||||||
if (text == """{"success":false,"data":"Video not found or has been removed"}""") return listOf()
|
|
||||||
AppUtils.parseJson<ResponseJson?>(text)?.let {
|
|
||||||
if (it.success && it.data != null) {
|
|
||||||
it.data.forEach { data ->
|
|
||||||
extractedLinksList.add(
|
|
||||||
ExtractorLink(
|
|
||||||
name,
|
|
||||||
name = name,
|
|
||||||
data.file,
|
|
||||||
url,
|
|
||||||
getQualityFromName(data.label),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return extractedLinksList
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "id"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AsianDrama",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=185.224.83.103&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,213 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
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.Jsoup
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
|
|
||||||
class DramaidProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://185.224.83.103"
|
|
||||||
override var name = "DramaId"
|
|
||||||
override val hasQuickSearch = false
|
|
||||||
override val hasMainPage = true
|
|
||||||
override var lang = "id"
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val hasChromecastSupport = false
|
|
||||||
override val supportedTypes = setOf(TvType.AsianDrama)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun getStatus(t: String): ShowStatus {
|
|
||||||
return when (t) {
|
|
||||||
"Completed" -> ShowStatus.Completed
|
|
||||||
"Ongoing" -> ShowStatus.Ongoing
|
|
||||||
else -> ShowStatus.Completed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
"&status=&type=&order=update" to "Drama Terbaru",
|
|
||||||
"&order=latest" to "Baru Ditambahkan",
|
|
||||||
"&status=&type=&order=popular" to "Drama Popular",
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
|
||||||
val document = app.get("$mainUrl/series/?page=$page${request.data}").document
|
|
||||||
val home = document.select("article[itemscope=itemscope]").mapNotNull {
|
|
||||||
it.toSearchResult()
|
|
||||||
}
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getProperDramaLink(uri: String): String {
|
|
||||||
return if (uri.contains("/series/")) {
|
|
||||||
uri
|
|
||||||
} else {
|
|
||||||
"$mainUrl/series/" + Regex("$mainUrl/(.+)-ep.+").find(uri)?.groupValues?.get(1)
|
|
||||||
.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Element.toSearchResult(): SearchResponse? {
|
|
||||||
val href = getProperDramaLink(this.selectFirst("a.tip")!!.attr("href"))
|
|
||||||
val title = this.selectFirst("h2[itemprop=headline]")?.text()?.trim() ?: return null
|
|
||||||
val posterUrl = fixUrlNull(this.selectFirst(".limit > noscript > img")?.attr("src"))
|
|
||||||
|
|
||||||
return newTvSeriesSearchResponse(title, href, TvType.AsianDrama) {
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val link = "$mainUrl/?s=$query"
|
|
||||||
val document = app.get(link).document
|
|
||||||
|
|
||||||
return document.select("article[itemscope=itemscope]").map {
|
|
||||||
val title = it.selectFirst("h2[itemprop=headline]")!!.text().trim()
|
|
||||||
val poster = it.selectFirst(".limit > noscript > img")!!.attr("src")
|
|
||||||
val href = it.selectFirst("a.tip")!!.attr("href")
|
|
||||||
|
|
||||||
newTvSeriesSearchResponse(title, href, TvType.AsianDrama) {
|
|
||||||
this.posterUrl = poster
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val document = app.get(url).document
|
|
||||||
|
|
||||||
val title = document.selectFirst("h1.entry-title")!!.text().trim()
|
|
||||||
val poster = document.select(".thumb > noscript > img").attr("src")
|
|
||||||
val tags = document.select(".genxed > a").map { it.text() }
|
|
||||||
|
|
||||||
val year = Regex("\\d, ([0-9]*)").find(
|
|
||||||
document.selectFirst(".info-content > .spe > span > time")!!.text().trim()
|
|
||||||
)?.groupValues?.get(1).toString().toIntOrNull()
|
|
||||||
val status = getStatus(
|
|
||||||
document.select(".info-content > .spe > span:nth-child(1)")
|
|
||||||
.text().trim().replace("Status: ", "")
|
|
||||||
)
|
|
||||||
val description = document.select(".entry-content > p").text().trim()
|
|
||||||
|
|
||||||
val episodes = document.select(".eplister > ul > li").map {
|
|
||||||
val name = it.selectFirst("a > .epl-title")!!.text().trim()
|
|
||||||
val link = it.select("a").attr("href")
|
|
||||||
val epNum = it.selectFirst("a > .epl-num")!!.text().trim().toIntOrNull()
|
|
||||||
newEpisode(link) {
|
|
||||||
this.name = name
|
|
||||||
this.episode = epNum
|
|
||||||
}
|
|
||||||
}.reversed()
|
|
||||||
|
|
||||||
val recommendations =
|
|
||||||
document.select(".listupd > article[itemscope=itemscope]").map { rec ->
|
|
||||||
val epTitle = rec.selectFirst("h2[itemprop=headline]")!!.text().trim()
|
|
||||||
val epPoster = rec.selectFirst(".limit > noscript > img")!!.attr("src")
|
|
||||||
val epHref = fixUrl(rec.selectFirst("a.tip")!!.attr("href"))
|
|
||||||
|
|
||||||
newTvSeriesSearchResponse(epTitle, epHref, TvType.AsianDrama) {
|
|
||||||
this.posterUrl = epPoster
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (episodes.size == 1) {
|
|
||||||
return newMovieLoadResponse(title, url, TvType.Movie, episodes[0].data) {
|
|
||||||
posterUrl = poster
|
|
||||||
this.year = year
|
|
||||||
plot = description
|
|
||||||
this.tags = tags
|
|
||||||
this.recommendations = recommendations
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return newTvSeriesLoadResponse(title, url, TvType.AsianDrama, episodes = episodes) {
|
|
||||||
posterUrl = poster
|
|
||||||
this.year = year
|
|
||||||
showStatus = status
|
|
||||||
plot = description
|
|
||||||
this.tags = tags
|
|
||||||
this.recommendations = recommendations
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private data class Sources(
|
|
||||||
@JsonProperty("file") val file: String,
|
|
||||||
@JsonProperty("label") val label: String,
|
|
||||||
@JsonProperty("type") val type: String,
|
|
||||||
@JsonProperty("default") val default: Boolean?
|
|
||||||
)
|
|
||||||
|
|
||||||
private data class Tracks(
|
|
||||||
@JsonProperty("file") val file: String,
|
|
||||||
@JsonProperty("label") val label: String,
|
|
||||||
@JsonProperty("kind") val type: String,
|
|
||||||
@JsonProperty("default") val default: Boolean?
|
|
||||||
)
|
|
||||||
|
|
||||||
private suspend fun invokeDriveSource(
|
|
||||||
url: String,
|
|
||||||
name: String,
|
|
||||||
subCallback: (SubtitleFile) -> Unit,
|
|
||||||
sourceCallback: (ExtractorLink) -> Unit
|
|
||||||
) {
|
|
||||||
val server = app.get(url).document.selectFirst(".picasa")?.nextElementSibling()?.data()
|
|
||||||
|
|
||||||
val source = "[${server!!.substringAfter("sources: [").substringBefore("],")}]".trimIndent()
|
|
||||||
val trackers = server.substringAfter("tracks:[").substringBefore("],")
|
|
||||||
.replace("//language", "")
|
|
||||||
.replace("file", "\"file\"")
|
|
||||||
.replace("label", "\"label\"")
|
|
||||||
.replace("kind", "\"kind\"").trimIndent()
|
|
||||||
|
|
||||||
tryParseJson<List<Sources>>(source)?.map {
|
|
||||||
sourceCallback(
|
|
||||||
ExtractorLink(
|
|
||||||
name,
|
|
||||||
"Drive",
|
|
||||||
fixUrl(it.file),
|
|
||||||
referer = "https://motonews.club/",
|
|
||||||
quality = getQualityFromName(it.label)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
tryParseJson<Tracks>(trackers)?.let {
|
|
||||||
subCallback.invoke(
|
|
||||||
SubtitleFile(
|
|
||||||
if (it.label.contains("Indonesia")) "${it.label}n" else it.label,
|
|
||||||
it.file
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
val document = app.get(data).document
|
|
||||||
val sources = document.select(".mobius > .mirror > option").mapNotNull {
|
|
||||||
fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("src"))
|
|
||||||
}
|
|
||||||
|
|
||||||
sources.map {
|
|
||||||
it.replace("https://ndrama.xyz", "https://www.fembed.com")
|
|
||||||
}.apmap {
|
|
||||||
when {
|
|
||||||
it.contains("motonews.club") -> invokeDriveSource(it, this.name, subtitleCallback, callback)
|
|
||||||
else -> loadExtractor(it, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class DramaidProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(DramaidProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "zh"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AsianDrama",
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=www.duboku.tv&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,133 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.M3u8Helper
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
|
|
||||||
class DubokuProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://www.duboku.tv"
|
|
||||||
override var name = "Duboku"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override var lang = "zh"
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Movie,
|
|
||||||
TvType.TvSeries,
|
|
||||||
TvType.AsianDrama,
|
|
||||||
)
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
"$mainUrl/vodshow/2--time------" to "连续剧 时间",
|
|
||||||
"$mainUrl/vodshow/2--hits------" to "连续剧 人气",
|
|
||||||
"$mainUrl/vodshow/13--time------" to "陆剧 时间",
|
|
||||||
"$mainUrl/vodshow/13--hits------" to "陆剧 人气",
|
|
||||||
"$mainUrl/vodshow/15--time------" to "日韩剧 时间",
|
|
||||||
"$mainUrl/vodshow/15--hits------" to "日韩剧 人气",
|
|
||||||
"$mainUrl/vodshow/21--time------" to "短剧 时间",
|
|
||||||
"$mainUrl/vodshow/21--hits------" to "短剧 人气",
|
|
||||||
"$mainUrl/vodshow/16--time------" to "英美剧 时间",
|
|
||||||
"$mainUrl/vodshow/16--hits------" to "英美剧 人气",
|
|
||||||
"$mainUrl/vodshow/14--time------" to "台泰剧 时间",
|
|
||||||
"$mainUrl/vodshow/14--hits------" to "台泰剧 人气",
|
|
||||||
"$mainUrl/vodshow/20--time------" to "港剧 时间",
|
|
||||||
"$mainUrl/vodshow/20--hits------" to "港剧 人气",
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(
|
|
||||||
page: Int,
|
|
||||||
request: MainPageRequest
|
|
||||||
): HomePageResponse {
|
|
||||||
val document = app.get("${request.data}$page---.html").document
|
|
||||||
val home = document.select("ul.myui-vodlist.clearfix li").mapNotNull {
|
|
||||||
it.toSearchResult()
|
|
||||||
}
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Element.toSearchResult(): SearchResponse? {
|
|
||||||
val title = this.selectFirst("h4.title a")?.text()?.trim() ?: return null
|
|
||||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
|
||||||
val posterUrl = fixUrlNull(this.selectFirst("a")?.attr("data-original"))
|
|
||||||
val episode = this.selectFirst("span.pic-text.text-right")?.text()?.filter { it.isDigit() }
|
|
||||||
?.toIntOrNull()
|
|
||||||
|
|
||||||
return newAnimeSearchResponse(title, href, TvType.Movie) {
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
addSub(episode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val document = app.get("$mainUrl/vodsearch/-------------.html?wd=$query&submit=").document
|
|
||||||
|
|
||||||
return document.select("ul#searchList li").mapNotNull {
|
|
||||||
it.toSearchResult()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
|
||||||
val document = app.get(url).document
|
|
||||||
|
|
||||||
val title = document.selectFirst("h1.title")?.text()?.trim() ?: return null
|
|
||||||
val tvType = if (document.select("ul.myui-content__list li").size == 1
|
|
||||||
) TvType.Movie else TvType.TvSeries
|
|
||||||
val actors = document.select("p.data")[2].select("a").map { it.text() }
|
|
||||||
|
|
||||||
val episodes = document.select("ul.myui-content__list li").map {
|
|
||||||
val href = fixUrl(it.select("a").attr("href"))
|
|
||||||
val name = it.select("a").text().trim()
|
|
||||||
Episode(
|
|
||||||
data = href,
|
|
||||||
name = name,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return newTvSeriesLoadResponse(title, url, tvType, episodes) {
|
|
||||||
this.posterUrl = fixUrlNull(
|
|
||||||
document.selectFirst("a.myui-vodlist__thumb.picture img")?.attr("data-original")
|
|
||||||
)
|
|
||||||
this.year =
|
|
||||||
document.select("p.data")[0].select("a").last()?.text()?.trim()?.toIntOrNull()
|
|
||||||
this.plot = document.selectFirst("span.sketch.content")?.text()?.trim()
|
|
||||||
this.tags = document.select("p.data")[0].select("a").map { it.text() }
|
|
||||||
this.rating = document.select("div#rating span.branch").text().toRatingInt()
|
|
||||||
addActors(actors)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
|
|
||||||
app.get(data).document.select("script").map { script ->
|
|
||||||
if (script.data().contains("var player_data={")) {
|
|
||||||
val dataJson =
|
|
||||||
script.data().substringAfter("var player_data={").substringBefore("}")
|
|
||||||
tryParseJson<Sources>("{$dataJson}")?.let { source ->
|
|
||||||
M3u8Helper.generateM3u8(
|
|
||||||
this.name,
|
|
||||||
source.url ?: return@map,
|
|
||||||
referer = "https://w.duboku.io/",
|
|
||||||
headers = mapOf("Origin" to "https://w.duboku.io")
|
|
||||||
).forEach(callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
data class Sources(
|
|
||||||
@JsonProperty("url") val url: String?,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class DubokuProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(DubokuProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "ar"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"Anime",
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=www.egy.best&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,237 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
|
|
||||||
class EgyBestProvider : MainAPI() {
|
|
||||||
override var lang = "ar"
|
|
||||||
override var mainUrl = "https://www.egy.best"
|
|
||||||
override var name = "EgyBest"
|
|
||||||
override val usesWebView = false
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie, TvType.Anime)
|
|
||||||
|
|
||||||
private fun String.getIntFromText(): Int? {
|
|
||||||
return Regex("""\d+""").find(this)?.groupValues?.firstOrNull()?.toIntOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Element.toSearchResponse(): SearchResponse? {
|
|
||||||
val url = this.attr("href") ?: return null
|
|
||||||
val posterUrl = select("img")?.attr("src")
|
|
||||||
var title = select("span.title").text()
|
|
||||||
val year = title.getYearFromTitle()
|
|
||||||
val isMovie = Regex(".*/movie/.*|.*/masrahiya/.*").matches(url)
|
|
||||||
val tvType = if (isMovie) TvType.Movie else TvType.TvSeries
|
|
||||||
title = if (year !== null) title else title.split(" (")[0].trim()
|
|
||||||
val quality = select("span.ribbon span").text().replace("-", "")
|
|
||||||
// If you need to differentiate use the url.
|
|
||||||
return MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this@EgyBestProvider.name,
|
|
||||||
tvType,
|
|
||||||
posterUrl,
|
|
||||||
year,
|
|
||||||
null,
|
|
||||||
quality = getQualityFromString(quality)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
// url, title
|
|
||||||
val doc = app.get(mainUrl).document
|
|
||||||
val pages = arrayListOf<HomePageList>()
|
|
||||||
doc.select("#mainLoad div.mbox").apmap {
|
|
||||||
val name = it.select(".bdb.pda > strong").text()
|
|
||||||
if (it.select(".movie").first()?.attr("href")?.contains("season-(.....)|ep-(.....)".toRegex()) == true) return@apmap
|
|
||||||
val list = arrayListOf<SearchResponse>()
|
|
||||||
it.select(".movie").map { element ->
|
|
||||||
list.add(element.toSearchResponse()!!)
|
|
||||||
}
|
|
||||||
pages.add(HomePageList(name, list))
|
|
||||||
}
|
|
||||||
return HomePageResponse(pages)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val q = query.replace(" ","%20")
|
|
||||||
val result = arrayListOf<SearchResponse>()
|
|
||||||
listOf("$mainUrl/explore/?q=$q").apmap { url ->
|
|
||||||
val d = app.get(url).document
|
|
||||||
d.select("div.movies a").not("a.auto.load.btn.b").mapNotNull {
|
|
||||||
it.toSearchResponse()?.let { it1 -> result.add(it1) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.distinct().sortedBy { it.name }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun String.getYearFromTitle(): Int? {
|
|
||||||
return Regex("""\(\d{4}\)""").find(this)?.groupValues?.firstOrNull()?.toIntOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val doc = app.get(url).document
|
|
||||||
val isMovie = Regex(".*/movie/.*|.*/masrahiya/.*").matches(url)
|
|
||||||
val posterUrl = doc.select("div.movie_img a img")?.attr("src")
|
|
||||||
val year = doc.select("div.movie_title h1 a")?.text()?.toIntOrNull()
|
|
||||||
val title = doc.select("div.movie_title h1 span").text()
|
|
||||||
val youtubeTrailer = doc.select("div.play")?.attr("url")
|
|
||||||
|
|
||||||
val synopsis = doc.select("div.mbox").firstOrNull {
|
|
||||||
it.text().contains("القصة")
|
|
||||||
}?.text()?.replace("القصة ", "")
|
|
||||||
|
|
||||||
val tags = doc.select("table.movieTable tbody tr").firstOrNull {
|
|
||||||
it.text().contains("النوع")
|
|
||||||
}?.select("a")?.map { it.text() }
|
|
||||||
|
|
||||||
val actors = doc.select("div.cast_list .cast_item").mapNotNull {
|
|
||||||
val name = it.selectFirst("div > a > img")?.attr("alt") ?: return@mapNotNull null
|
|
||||||
val image = it.selectFirst("div > a > img")?.attr("src") ?: return@mapNotNull null
|
|
||||||
val roleString = it.selectFirst("div > span")!!.text()
|
|
||||||
val mainActor = Actor(name, image)
|
|
||||||
ActorData(actor = mainActor, roleString = roleString)
|
|
||||||
}
|
|
||||||
|
|
||||||
return if (isMovie) {
|
|
||||||
val recommendations = doc.select(".movies_small .movie").mapNotNull { element ->
|
|
||||||
element.toSearchResponse()
|
|
||||||
}
|
|
||||||
|
|
||||||
newMovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
TvType.Movie,
|
|
||||||
url
|
|
||||||
) {
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
this.year = year
|
|
||||||
this.recommendations = recommendations
|
|
||||||
this.plot = synopsis
|
|
||||||
this.tags = tags
|
|
||||||
this.actors = actors
|
|
||||||
addTrailer(youtubeTrailer)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val episodes = ArrayList<Episode>()
|
|
||||||
doc.select("#mainLoad > div:nth-child(2) > div.h_scroll > div a").map {
|
|
||||||
it.attr("href")
|
|
||||||
}.apmap {
|
|
||||||
val d = app.get(it).document
|
|
||||||
val season = Regex("season-(.....)").find(it)?.groupValues?.getOrNull(1)?.getIntFromText()
|
|
||||||
if(d.select("tr.published").isNotEmpty()) {
|
|
||||||
d.select("tr.published").map { element ->
|
|
||||||
val ep = Regex("ep-(.....)").find(element.select(".ep_title a").attr("href"))?.groupValues?.getOrNull(1)?.getIntFromText()
|
|
||||||
episodes.add(
|
|
||||||
Episode(
|
|
||||||
element.select(".ep_title a").attr("href"),
|
|
||||||
name = element.select("td.ep_title").html().replace(".*</span>|</a>".toRegex(), ""),
|
|
||||||
season,
|
|
||||||
ep,
|
|
||||||
rating = element.select("td.tam:not(.date, .ep_len)").text().getIntFromText()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
d.select("#mainLoad > div:nth-child(3) > div.movies_small a").map { eit ->
|
|
||||||
val ep = Regex("ep-(.....)").find(eit.attr("href"))?.groupValues?.getOrNull(1)?.getIntFromText()
|
|
||||||
episodes.add(
|
|
||||||
Episode(
|
|
||||||
eit.attr("href"),
|
|
||||||
eit.select("span.title").text(),
|
|
||||||
season,
|
|
||||||
ep,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes.distinct().sortedBy { it.episode }) {
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
this.tags = tags
|
|
||||||
this.year = year
|
|
||||||
this.plot = synopsis
|
|
||||||
this.actors = actors
|
|
||||||
addTrailer(youtubeTrailer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data class Sources (
|
|
||||||
@JsonProperty("quality") val quality: Int?,
|
|
||||||
@JsonProperty("link") val link: String
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
/*val baseURL = data.split("/")[0] + "//" + data.split("/")[2]
|
|
||||||
val episodeSoup = app.get(data).document
|
|
||||||
|
|
||||||
val vidstreamURL = fixUrlNull(episodeSoup.selectFirst("iframe.auto-size")?.attr("src") ) ?: throw ErrorLoadingException("No iframe")
|
|
||||||
val videoSoup = app.get(vidstreamURL).document
|
|
||||||
fixUrlNull( videoSoup.select("source").firstOrNull { it.hasAttr("src") }?.attr("src"))?.let {
|
|
||||||
callback.invoke(ExtractorLink(this.name,this.name,it,"",Qualities.Unknown.value,it.contains(".m3u8")))
|
|
||||||
} ?: run {
|
|
||||||
var jsCode = videoSoup.select("script")[1].data()
|
|
||||||
|
|
||||||
val verificationToken = Regex("{'[0-9a-zA-Z_]*':'ok'}").findAll(jsCode)[0][2:-7]
|
|
||||||
val encodedAdLinkVar = Regex("([0-9a-zA-Z_]{2,12}\[Math").findAll(jsCode)[0][1:-5]
|
|
||||||
val encodingArraysRegEx = Regex(",[0-9a-zA-Z_]{2,12}=\[\]").findAll(jsCode)
|
|
||||||
val firstEncodingArray = encodingArraysRegEx[1][1:-3]
|
|
||||||
val secondEncodingArray = encodingArraysRegEx[2][1:-3]
|
|
||||||
|
|
||||||
jsCode = Regex("^<script type=\"text/javascript\">", "", jsCode)
|
|
||||||
jsCode = Regex("[;,]\$\('\*'\)(.*)$", ";", jsCode)
|
|
||||||
jsCode = Regex(",ismob=(.*)\(navigator\[(.*)\]\)[,;]", ";", jsCode)
|
|
||||||
jsCode = Regex("var a0b=function\(\)(.*)a0a\(\);",).findAll( jsCode)
|
|
||||||
jsCode += "var link = ''; for (var i = 0; i <= $secondEncodingArray['length']; i++) { link += $firstEncodingArray[$secondEncodingArray[i]] || ''; } return [link, $encodedAdLinkVar[0]] }"
|
|
||||||
|
|
||||||
val jsCodeReturn = executeJS(jsCode)()
|
|
||||||
val verificationPath = jsCodeReturn[0]
|
|
||||||
val encodedAdPath = jsCodeReturn[1]
|
|
||||||
|
|
||||||
val adLink = baseURL + "/" + str(decode(encodedAdPath + "=" * (-len(encodedAdPath) % 4)), "utf-8")
|
|
||||||
val session.get(adLink)
|
|
||||||
|
|
||||||
val verificationLink = baseURL + "/tvc.php?verify=" + verificationPath
|
|
||||||
val session.post(verificationLink, data={verificationToken: "ok"})
|
|
||||||
|
|
||||||
val vidstreamResponseText = session.get(vidstreamURL).text
|
|
||||||
val videoSoup = BeautifulSoup(vidstreamResponseText, features="html.parser")
|
|
||||||
|
|
||||||
val qualityLinksFileURL = baseURL + videoSoup.body.find("source").get("src")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return true*/
|
|
||||||
|
|
||||||
val requestJSON = app.get("https://api.zr5.repl.co/egybest?url=$data").text
|
|
||||||
// To solve this you need to send a verify request which is pretty hidden, see
|
|
||||||
// https://vear.egybest.deals/tvc.php?verify=.......
|
|
||||||
val jsonArray = parseJson<List<Sources>>(requestJSON)
|
|
||||||
for (i in jsonArray) {
|
|
||||||
val quality = i.quality
|
|
||||||
val link = i.link
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
this.name,
|
|
||||||
this.name,
|
|
||||||
link,
|
|
||||||
this.mainUrl,
|
|
||||||
quality!!,
|
|
||||||
true,
|
|
||||||
// Does not work without these headers!
|
|
||||||
headers = mapOf("range" to "bytes=0-"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class EgyBestProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(EgyBestProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "es"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,94 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
|
|
||||||
class ElifilmsProvider : MainAPI() {
|
|
||||||
override var mainUrl: String = "https://elifilms.net"
|
|
||||||
override var name: String = "Elifilms"
|
|
||||||
override var lang = "es"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Movie,
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
val items = ArrayList<HomePageList>()
|
|
||||||
val newest = app.get(mainUrl).document.selectFirst("a.fav_link.premiera")?.attr("href")
|
|
||||||
val urls = listOf(
|
|
||||||
Pair(mainUrl, "Películas recientes"),
|
|
||||||
Pair("$mainUrl/4k-peliculas/", "Películas en 4k"),
|
|
||||||
Pair(newest, "Últimos estrenos"),
|
|
||||||
)
|
|
||||||
urls.apmap { (url, name) ->
|
|
||||||
val soup = app.get(url ?: "").document
|
|
||||||
val home = soup.select("article.shortstory.cf").map {
|
|
||||||
val title = it.selectFirst(".short_header")?.text() ?: ""
|
|
||||||
val link = it.selectFirst("div a")?.attr("href") ?: ""
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
it.selectFirst("a.ah-imagge img")?.attr("data-src"),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
items.add(HomePageList(name, home))
|
|
||||||
}
|
|
||||||
if (items.size <= 0) throw ErrorLoadingException()
|
|
||||||
return HomePageResponse(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val url = "$mainUrl/?s=$query"
|
|
||||||
val doc = app.get(url).document
|
|
||||||
return doc.select("article.cf").map {
|
|
||||||
val href = it.selectFirst("div.short_content a")?.attr("href") ?: ""
|
|
||||||
val poster = it.selectFirst("a.ah-imagge img")?.attr("data-src")
|
|
||||||
val name = it.selectFirst(".short_header")?.text() ?: ""
|
|
||||||
(MovieSearchResponse(name, href, this.name, TvType.Movie, poster, null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val document = app.get(url, timeout = 120).document
|
|
||||||
val title = document.selectFirst(".post_title h1")?.text() ?: ""
|
|
||||||
val rating = document.select("span.imdb.rki").toString().toIntOrNull()
|
|
||||||
val poster = document.selectFirst(".poster img")?.attr("src")
|
|
||||||
val desc = document.selectFirst("div.notext .actors p")?.text()
|
|
||||||
val tags = document.select("td.notext a")
|
|
||||||
.map { it?.text()?.trim().toString() }
|
|
||||||
return MovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
url,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
desc,
|
|
||||||
rating,
|
|
||||||
tags
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
app.get(data).document.select("li.change-server a").apmap {
|
|
||||||
val encodedurl = it.attr("data-id")
|
|
||||||
val urlDecoded = base64Decode(encodedurl)
|
|
||||||
val url = fixUrl(urlDecoded)
|
|
||||||
loadExtractor(url, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class ElifilmsProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(ElifilmsProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "es"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=entrepeliculasyseries.nu&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,177 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
|
|
||||||
class EntrepeliculasyseriesProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://entrepeliculasyseries.nu"
|
|
||||||
override var name = "EntrePeliculasySeries"
|
|
||||||
override var lang = "es"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Movie,
|
|
||||||
TvType.TvSeries,
|
|
||||||
)
|
|
||||||
override val vpnStatus = VPNStatus.MightBeNeeded //Due to evoload sometimes not loading
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
Pair("$mainUrl/series/page/", "Series"),
|
|
||||||
Pair("$mainUrl/peliculas/page/", "Peliculas"),
|
|
||||||
Pair("$mainUrl/anime/page/", "Animes"),
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(
|
|
||||||
page: Int,
|
|
||||||
request : MainPageRequest
|
|
||||||
): HomePageResponse {
|
|
||||||
val url = request.data + page
|
|
||||||
|
|
||||||
val soup = app.get(url).document
|
|
||||||
val home = soup.select("ul.list-movie li").map {
|
|
||||||
val title = it.selectFirst("a.link-title h2")!!.text()
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
if (link.contains("/pelicula/")) TvType.Movie else TvType.TvSeries,
|
|
||||||
it.selectFirst("a.poster img")!!.attr("src"),
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val url = "$mainUrl/?s=${query}"
|
|
||||||
val document = app.get(url).document
|
|
||||||
|
|
||||||
return document.select("li.xxx.TPostMv").map {
|
|
||||||
val title = it.selectFirst("h2.Title")!!.text()
|
|
||||||
val href = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = it.selectFirst("img.lazy")!!.attr("data-src")
|
|
||||||
val isMovie = href.contains("/pelicula/")
|
|
||||||
|
|
||||||
if (isMovie) {
|
|
||||||
MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
image,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.TvSeries,
|
|
||||||
image,
|
|
||||||
null,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
|
||||||
val soup = app.get(url, timeout = 120).document
|
|
||||||
|
|
||||||
val title = soup.selectFirst("h1.title-post")!!.text()
|
|
||||||
val description = soup.selectFirst("p.text-content:nth-child(3)")?.text()?.trim()
|
|
||||||
val poster: String? = soup.selectFirst("article.TPost img.lazy")!!.attr("data-src")
|
|
||||||
val episodes = soup.select(".TPostMv article").map { li ->
|
|
||||||
val href = (li.select("a") ?: li.select(".C a") ?: li.select("article a")).attr("href")
|
|
||||||
val epThumb = li.selectFirst("div.Image img")!!.attr("data-src")
|
|
||||||
val seasonid = li.selectFirst("span.Year")!!.text().let { str ->
|
|
||||||
str.split("x").mapNotNull { subStr -> subStr.toIntOrNull() }
|
|
||||||
}
|
|
||||||
val isValid = seasonid.size == 2
|
|
||||||
val episode = if (isValid) seasonid.getOrNull(1) else null
|
|
||||||
val season = if (isValid) seasonid.getOrNull(0) else null
|
|
||||||
Episode(
|
|
||||||
href,
|
|
||||||
null,
|
|
||||||
season,
|
|
||||||
episode,
|
|
||||||
fixUrl(epThumb)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return when (val tvType =
|
|
||||||
if (url.contains("/pelicula/")) TvType.Movie else TvType.TvSeries) {
|
|
||||||
TvType.TvSeries -> {
|
|
||||||
TvSeriesLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
tvType,
|
|
||||||
episodes,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
description,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
TvType.Movie -> {
|
|
||||||
MovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
tvType,
|
|
||||||
url,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
description,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
app.get(data).document.select(".video ul.dropdown-menu li").apmap {
|
|
||||||
val servers = it.attr("data-link")
|
|
||||||
val doc = app.get(servers).document
|
|
||||||
doc.select("input").apmap {
|
|
||||||
val postkey = it.attr("value")
|
|
||||||
app.post(
|
|
||||||
"https://entrepeliculasyseries.nu/r.php",
|
|
||||||
headers = mapOf(
|
|
||||||
"Host" to "entrepeliculasyseries.nu",
|
|
||||||
"User-Agent" to USER_AGENT,
|
|
||||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
|
||||||
"Accept-Language" to "en-US,en;q=0.5",
|
|
||||||
"Content-Type" to "application/x-www-form-urlencoded",
|
|
||||||
"Origin" to "https://entrepeliculasyseries.nu",
|
|
||||||
"DNT" to "1",
|
|
||||||
"Connection" to "keep-alive",
|
|
||||||
"Referer" to servers,
|
|
||||||
"Upgrade-Insecure-Requests" to "1",
|
|
||||||
"Sec-Fetch-Dest" to "document",
|
|
||||||
"Sec-Fetch-Mode" to "navigate",
|
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
|
||||||
"Sec-Fetch-User" to "?1",
|
|
||||||
),
|
|
||||||
//params = mapOf(Pair("h", postkey)),
|
|
||||||
data = mapOf(Pair("h", postkey)),
|
|
||||||
allowRedirects = false
|
|
||||||
).okhttpResponse.headers.values("location").apmap {
|
|
||||||
loadExtractor(it, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class EntrepeliculasyseriesProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(EntrepeliculasyseriesProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "es"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AsianDrama",
|
|
||||||
"Movie",
|
|
||||||
"OVA",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=www23.estrenosdoramas.net&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,286 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.network.WebViewResolver
|
|
||||||
import com.lagradost.cloudstream3.utils.*
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
|
|
||||||
class EstrenosDoramasProvider : MainAPI() {
|
|
||||||
companion object {
|
|
||||||
fun getType(t: String): TvType {
|
|
||||||
return if (t.contains("OVA") || t.contains("Especial")) TvType.OVA
|
|
||||||
else if (t.contains("Pelicula")) TvType.Movie
|
|
||||||
else TvType.TvSeries
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override var mainUrl = "https://www23.estrenosdoramas.net"
|
|
||||||
override var name = "EstrenosDoramas"
|
|
||||||
override var lang = "es"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val hasDownloadSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.AsianDrama,
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
val urls = listOf(
|
|
||||||
Pair(mainUrl, "Últimas series"),
|
|
||||||
Pair("$mainUrl/category/peliculas", "Películas"),
|
|
||||||
)
|
|
||||||
|
|
||||||
val items = ArrayList<HomePageList>()
|
|
||||||
|
|
||||||
urls.apmap { (url, name) ->
|
|
||||||
val home = app.get(url, timeout = 120).document.select("div.clearfix").map {
|
|
||||||
val title = cleanTitle(it.selectFirst("h3 a")?.text()!!)
|
|
||||||
val poster = it.selectFirst("img.cate_thumb")?.attr("src")
|
|
||||||
AnimeSearchResponse(
|
|
||||||
title,
|
|
||||||
it.selectFirst("a")?.attr("href")!!,
|
|
||||||
this.name,
|
|
||||||
TvType.AsianDrama,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
|
||||||
DubStatus.Dubbed
|
|
||||||
) else EnumSet.of(DubStatus.Subbed),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
items.add(HomePageList(name, home))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (items.size <= 0) throw ErrorLoadingException()
|
|
||||||
return HomePageResponse(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val searchob = ArrayList<AnimeSearchResponse>()
|
|
||||||
val search =
|
|
||||||
app.get("$mainUrl/?s=$query", timeout = 120).document.select("div.clearfix").map {
|
|
||||||
val title = cleanTitle(it.selectFirst("h3 a")?.text()!!)
|
|
||||||
val href = it.selectFirst("a")?.attr("href")
|
|
||||||
val image = it.selectFirst("img.cate_thumb")?.attr("src")
|
|
||||||
val lists =
|
|
||||||
AnimeSearchResponse(
|
|
||||||
title,
|
|
||||||
href!!,
|
|
||||||
this.name,
|
|
||||||
TvType.AsianDrama,
|
|
||||||
image,
|
|
||||||
null,
|
|
||||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
|
||||||
DubStatus.Dubbed
|
|
||||||
) else EnumSet.of(DubStatus.Subbed),
|
|
||||||
)
|
|
||||||
if (href.contains("capitulo")) {
|
|
||||||
//nothing
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
searchob.add(lists)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return searchob
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse? {
|
|
||||||
val doc = app.get(url, timeout = 120).document
|
|
||||||
val poster = doc.selectFirst("head meta[property]")?.attr("content")
|
|
||||||
val title = doc.selectFirst("h1.titulo")?.text()
|
|
||||||
val description = try {
|
|
||||||
doc.selectFirst("div.post div.highlight div.font")?.text()
|
|
||||||
} catch (e:Exception){
|
|
||||||
null
|
|
||||||
}
|
|
||||||
val finaldesc = description?.substringAfter("Sinopsis")?.replace(": ", "")?.trim()
|
|
||||||
val epi = ArrayList<Episode>()
|
|
||||||
val episodes = doc.select("div.post .lcp_catlist a").map {
|
|
||||||
val name = it.selectFirst("a")?.text()
|
|
||||||
val link = it.selectFirst("a")?.attr("href")
|
|
||||||
val test = Episode(link!!, name)
|
|
||||||
if (!link.equals(url)) {
|
|
||||||
epi.add(test)
|
|
||||||
}
|
|
||||||
}.reversed()
|
|
||||||
return when (val type = if (episodes.isEmpty()) TvType.Movie else TvType.AsianDrama) {
|
|
||||||
TvType.AsianDrama -> {
|
|
||||||
return newAnimeLoadResponse(title!!, url, type) {
|
|
||||||
japName = null
|
|
||||||
engName = title.replace(Regex("[Pp]elicula |[Pp]elicula"),"")
|
|
||||||
posterUrl = poster
|
|
||||||
addEpisodes(DubStatus.Subbed, epi.reversed())
|
|
||||||
plot = finaldesc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TvType.Movie -> {
|
|
||||||
MovieLoadResponse(
|
|
||||||
cleanTitle(title!!),
|
|
||||||
url,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
url,
|
|
||||||
poster,
|
|
||||||
null,
|
|
||||||
finaldesc,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data class ReproDoramas (
|
|
||||||
@JsonProperty("link") val link: String,
|
|
||||||
@JsonProperty("time") val time: Int
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun cleanTitle(title: String): String = title.replace(Regex("[Pp]elicula |[Pp]elicula"),"")
|
|
||||||
|
|
||||||
private fun cleanExtractor(
|
|
||||||
source: String,
|
|
||||||
name: String,
|
|
||||||
url: String,
|
|
||||||
referer: String,
|
|
||||||
m3u8: Boolean,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
callback(
|
|
||||||
ExtractorLink(
|
|
||||||
source,
|
|
||||||
name,
|
|
||||||
url,
|
|
||||||
referer,
|
|
||||||
Qualities.Unknown.value,
|
|
||||||
m3u8
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
val headers = mapOf("Host" to "repro3.estrenosdoramas.us",
|
|
||||||
"User-Agent" to USER_AGENT,
|
|
||||||
"Accept" to "*/*",
|
|
||||||
"Accept-Language" to "en-US,en;q=0.5",
|
|
||||||
"Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8",
|
|
||||||
"X-Requested-With" to "XMLHttpRequest",
|
|
||||||
"Origin" to "https://repro3.estrenosdoramas.us",
|
|
||||||
"DNT" to "1",
|
|
||||||
"Connection" to "keep-alive",
|
|
||||||
"Sec-Fetch-Dest" to "empty",
|
|
||||||
"Sec-Fetch-Mode" to "cors",
|
|
||||||
"Sec-Fetch-Site" to "same-origin",
|
|
||||||
"Cache-Control" to "max-age=0",)
|
|
||||||
|
|
||||||
val document = app.get(data).document
|
|
||||||
document.select("div.tab_container iframe").apmap { container ->
|
|
||||||
val directlink = fixUrl(container.attr("src"))
|
|
||||||
loadExtractor(directlink, data, subtitleCallback, callback)
|
|
||||||
|
|
||||||
if (directlink.contains("/repro/amz/")) {
|
|
||||||
val amzregex = Regex("https:\\/\\/repro3\\.estrenosdoramas\\.us\\/repro\\/amz\\/examples\\/.*\\.php\\?key=.*\$")
|
|
||||||
amzregex.findAll(directlink).map {
|
|
||||||
it.value.replace(Regex("https:\\/\\/repro3\\.estrenosdoramas\\.us\\/repro\\/amz\\/examples\\/.*\\.php\\?key="),"")
|
|
||||||
}.toList().apmap { key ->
|
|
||||||
val response = app.post("https://repro3.estrenosdoramas.us/repro/amz/examples/player/api/indexDCA.php",
|
|
||||||
headers = headers,
|
|
||||||
data = mapOf(
|
|
||||||
Pair("key",key),
|
|
||||||
Pair("token","MDAwMDAwMDAwMA=="),
|
|
||||||
),
|
|
||||||
allowRedirects = false
|
|
||||||
).text
|
|
||||||
val reprojson = parseJson<ReproDoramas>(response)
|
|
||||||
val decodeurl = base64Decode(reprojson.link)
|
|
||||||
if (decodeurl.contains("m3u8"))
|
|
||||||
|
|
||||||
cleanExtractor(
|
|
||||||
name,
|
|
||||||
name,
|
|
||||||
decodeurl,
|
|
||||||
"https://repro3.estrenosdoramas.us",
|
|
||||||
decodeurl.contains(".m3u8"),
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (directlink.contains("reproducir14")) {
|
|
||||||
val regex = Regex("(https:\\/\\/repro.\\.estrenosdoramas\\.us\\/repro\\/reproducir14\\.php\\?key=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
|
||||||
regex.findAll(directlink).map {
|
|
||||||
it.value
|
|
||||||
}.toList().apmap {
|
|
||||||
val doc = app.get(it).text
|
|
||||||
val videoid = doc.substringAfter("vid=\"").substringBefore("\" n")
|
|
||||||
val token = doc.substringAfter("name=\"").substringBefore("\" s")
|
|
||||||
val acctkn = doc.substringAfter("{ acc: \"").substringBefore("\", id:")
|
|
||||||
val link = app.post("https://repro3.estrenosdoramas.us/repro/proto4.php",
|
|
||||||
headers = headers,
|
|
||||||
data = mapOf(
|
|
||||||
Pair("acc",acctkn),
|
|
||||||
Pair("id",videoid),
|
|
||||||
Pair("tk",token)),
|
|
||||||
allowRedirects = false
|
|
||||||
).text
|
|
||||||
val extracteklink = link.substringAfter("\"urlremoto\":\"").substringBefore("\"}")
|
|
||||||
.replace("\\/", "/").replace("//ok.ru/","http://ok.ru/")
|
|
||||||
loadExtractor(extracteklink, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (directlink.contains("reproducir120")) {
|
|
||||||
val regex = Regex("(https:\\/\\/repro3.estrenosdoramas.us\\/repro\\/reproducir120\\.php\\?\\nkey=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
|
||||||
regex.findAll(directlink).map {
|
|
||||||
it.value
|
|
||||||
}.toList().apmap {
|
|
||||||
val doc = app.get(it).text
|
|
||||||
val videoid = doc.substringAfter("var videoid = '").substringBefore("';")
|
|
||||||
val token = doc.substringAfter("var tokens = '").substringBefore("';")
|
|
||||||
val acctkn = doc.substringAfter("{ acc: \"").substringBefore("\", id:")
|
|
||||||
val link = app.post("https://repro3.estrenosdoramas.us/repro/api3.php",
|
|
||||||
headers = headers,
|
|
||||||
data = mapOf(
|
|
||||||
Pair("acc",acctkn),
|
|
||||||
Pair("id",videoid),
|
|
||||||
Pair("tk",token)),
|
|
||||||
allowRedirects = false
|
|
||||||
).text
|
|
||||||
val extractedlink = link.substringAfter("\"{file:'").substringBefore("',label:")
|
|
||||||
.replace("\\/", "/")
|
|
||||||
val quality = link.substringAfter(",label:'").substringBefore("',type:")
|
|
||||||
val type = link.substringAfter("type: '").substringBefore("'}\"")
|
|
||||||
if (extractedlink.isNotBlank())
|
|
||||||
if (quality.contains("File not found", ignoreCase = true)) {
|
|
||||||
//Nothing
|
|
||||||
} else {
|
|
||||||
cleanExtractor(
|
|
||||||
"Movil",
|
|
||||||
"Movil $quality",
|
|
||||||
extractedlink,
|
|
||||||
"",
|
|
||||||
!type.contains("mp4"),
|
|
||||||
callback
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class EstrenosDoramasProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(EstrenosDoramasProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "it"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"TvSeries"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=eurostreaming.social&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,113 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
|
||||||
|
|
||||||
|
|
||||||
class EurostreamingProvider : MainAPI() {
|
|
||||||
override var lang = "it"
|
|
||||||
override var mainUrl = "https://eurostreaming.social"
|
|
||||||
override var name = "Eurostreaming"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.TvSeries
|
|
||||||
)
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
Pair("$mainUrl/serie-tv-archive/page/", "Ultime serie Tv"),
|
|
||||||
Pair("$mainUrl/animazione/page/", "Ultime serie Animazione"),
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
|
|
||||||
val url = request.data + page
|
|
||||||
|
|
||||||
val soup = app.get(url).document
|
|
||||||
val home = soup.select("div.post-thumb").map {
|
|
||||||
val title = it.selectFirst("img")!!.attr("alt")
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = fixUrl(it.selectFirst("img")!!.attr("src"))
|
|
||||||
|
|
||||||
MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
image
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val doc = app.post(
|
|
||||||
"$mainUrl/index.php", data = mapOf(
|
|
||||||
"do" to "search",
|
|
||||||
"subaction" to "search",
|
|
||||||
"story" to query,
|
|
||||||
"sortby" to "news_read"
|
|
||||||
)
|
|
||||||
).document
|
|
||||||
return doc.select("div.post-thumb").map {
|
|
||||||
val title = it.selectFirst("img")!!.attr("alt")
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = mainUrl + it.selectFirst("img")!!.attr("src")
|
|
||||||
|
|
||||||
MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
image
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val page = app.get(url)
|
|
||||||
val document = page.document
|
|
||||||
val title = document.selectFirst("h2")!!.text().replace("^([1-9+]]$","")
|
|
||||||
val style = document.selectFirst("div.entry-cover")!!.attr("style")
|
|
||||||
val poster = fixUrl(Regex("(/upload.+\\))").find(style)!!.value.dropLast(1))
|
|
||||||
val episodeList = ArrayList<Episode>()
|
|
||||||
document.select("div.tab-pane.fade").map { element ->
|
|
||||||
val season = element.attr("id").filter { it.isDigit() }.toInt()
|
|
||||||
element.select("li").filter { it-> it.selectFirst("a")?.hasAttr("data-title")?:false }.map{episode ->
|
|
||||||
val data = episode.select("div.mirrors > a").map { it.attr("data-link") }.toJson()
|
|
||||||
val epnameData = episode.selectFirst("a")
|
|
||||||
val epTitle = epnameData!!.attr("data-title")
|
|
||||||
val epNum = epnameData.text().toInt()
|
|
||||||
episodeList.add(
|
|
||||||
Episode(
|
|
||||||
data,
|
|
||||||
epTitle,
|
|
||||||
season,
|
|
||||||
epNum
|
|
||||||
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodeList) {
|
|
||||||
posterUrl = poster
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
parseJson<List<String>>(data).map { videoUrl ->
|
|
||||||
loadExtractor(videoUrl, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class EurostreamingProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(EurostreamingProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "ar"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"AsianDrama",
|
|
||||||
"Anime",
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=faselhd.io&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,163 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
|
|
||||||
class FaselHDProvider : MainAPI() {
|
|
||||||
override var lang = "ar"
|
|
||||||
override var mainUrl = "https://faselhd.io"
|
|
||||||
override var name = "FaselHD"
|
|
||||||
override val usesWebView = false
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie, TvType.AsianDrama, TvType.Anime)
|
|
||||||
|
|
||||||
private fun String.getIntFromText(): Int? {
|
|
||||||
return Regex("""\d+""").find(this)?.groupValues?.firstOrNull()?.toIntOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Element.toSearchResponse(): SearchResponse? {
|
|
||||||
val url = select("div.postDiv a").attr("href") ?: return null
|
|
||||||
val posterUrl = select("div.postDiv a div img").attr("data-src") ?:
|
|
||||||
select("div.postDiv a div img").attr("src")
|
|
||||||
val title = select("div.postDiv a div img").attr("alt")
|
|
||||||
val quality = select(".quality").first()?.text()?.replace("1080p |-".toRegex(), "")
|
|
||||||
val type = if(title.contains("فيلم")) TvType.Movie else TvType.TvSeries
|
|
||||||
return MovieSearchResponse(
|
|
||||||
title.replace("الموسم الأول|برنامج|فيلم|مترجم|اون لاين|مسلسل|مشاهدة|انمي|أنمي".toRegex(),""),
|
|
||||||
url,
|
|
||||||
this@FaselHDProvider.name,
|
|
||||||
type,
|
|
||||||
posterUrl,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
quality = getQualityFromString(quality)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
// Title, Url
|
|
||||||
val moviesUrl = listOf(
|
|
||||||
Pair("Movies", "$mainUrl/all-movies/page/"+(0..10).random()),
|
|
||||||
Pair("Series", "$mainUrl/series/page/"+(0..10).random()),
|
|
||||||
Pair("Top Movies IMDB", "$mainUrl/movies_top_imdb"),
|
|
||||||
)
|
|
||||||
val pages = moviesUrl.apmap { (title, url) ->
|
|
||||||
val doc = app.get(url).document
|
|
||||||
val list = doc.select("div[id=\"postList\"] div[class=\"col-xl-2 col-lg-2 col-md-3 col-sm-3\"]")
|
|
||||||
.mapNotNull { element ->
|
|
||||||
element.toSearchResponse()
|
|
||||||
}
|
|
||||||
HomePageList(title, list)
|
|
||||||
}
|
|
||||||
return HomePageResponse(pages)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val q = query.replace(" ","+")
|
|
||||||
val d = app.get("$mainUrl/?s=$q").document
|
|
||||||
return d.select("div[id=\"postList\"] div[class=\"col-xl-2 col-lg-2 col-md-3 col-sm-3\"]")
|
|
||||||
.mapNotNull {
|
|
||||||
it.toSearchResponse()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val doc = app.get(url).document
|
|
||||||
val isMovie = doc.select("div.epAll").isEmpty()
|
|
||||||
val posterUrl = doc.select("div.posterImg img").attr("src")
|
|
||||||
.ifEmpty { doc.select("div.seasonDiv.active img").attr("data-src") }
|
|
||||||
|
|
||||||
val year = doc.select("div[id=\"singleList\"] div[class=\"col-xl-6 col-lg-6 col-md-6 col-sm-6\"]").firstOrNull {
|
|
||||||
it.text().contains("سنة|موعد".toRegex())
|
|
||||||
}?.text()?.getIntFromText()
|
|
||||||
|
|
||||||
val title =
|
|
||||||
doc.select("title").text().replace(" - فاصل إعلاني", "")
|
|
||||||
.replace("الموسم الأول|برنامج|فيلم|مترجم|اون لاين|مسلسل|مشاهدة|انمي|أنمي|$year".toRegex(),"")
|
|
||||||
// A bit iffy to parse twice like this, but it'll do.
|
|
||||||
val duration = doc.select("div[id=\"singleList\"] div[class=\"col-xl-6 col-lg-6 col-md-6 col-sm-6\"]").firstOrNull {
|
|
||||||
it.text().contains("مدة|توقيت".toRegex())
|
|
||||||
}?.text()?.getIntFromText()
|
|
||||||
|
|
||||||
val tags = doc.select("div[id=\"singleList\"] div[class=\"col-xl-6 col-lg-6 col-md-6 col-sm-6\"]:contains(تصنيف الفيلم) a").map {
|
|
||||||
it.text()
|
|
||||||
}
|
|
||||||
val recommendations = doc.select("div#postList div.postDiv").mapNotNull {
|
|
||||||
it.toSearchResponse()
|
|
||||||
}
|
|
||||||
val synopsis = doc.select("div.singleDesc p").text()
|
|
||||||
return if (isMovie) {
|
|
||||||
newMovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
TvType.Movie,
|
|
||||||
url
|
|
||||||
) {
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
this.year = year
|
|
||||||
this.plot = synopsis
|
|
||||||
this.duration = duration
|
|
||||||
this.tags = tags
|
|
||||||
this.recommendations = recommendations
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val episodes = ArrayList<Episode>()
|
|
||||||
doc.select("div.epAll a").map {
|
|
||||||
episodes.add(
|
|
||||||
Episode(
|
|
||||||
it.attr("href"),
|
|
||||||
it.text(),
|
|
||||||
doc.select("div.seasonDiv.active div.title").text().getIntFromText() ?: 1,
|
|
||||||
it.text().getIntFromText(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
doc.select("div[id=\"seasonList\"] div[class=\"col-xl-2 col-lg-3 col-md-6\"] div.seasonDiv")
|
|
||||||
.not(".active").apmap { it ->
|
|
||||||
val s = app.get("$mainUrl/?p="+it.attr("data-href")).document
|
|
||||||
s.select("div.epAll a").map {
|
|
||||||
episodes.add(
|
|
||||||
Episode(
|
|
||||||
it.attr("href"),
|
|
||||||
it.text(),
|
|
||||||
s.select("div.seasonDiv.active div.title").text().getIntFromText(),
|
|
||||||
it.text().getIntFromText(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes.distinct().sortedBy { it.episode }) {
|
|
||||||
this.duration = duration
|
|
||||||
this.posterUrl = posterUrl
|
|
||||||
this.year = year
|
|
||||||
this.plot = synopsis
|
|
||||||
this.tags = tags
|
|
||||||
this.recommendations = recommendations
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
val player = app.get(app.get(data).document.select("iframe[name=\"player_iframe\"]").attr("src")).document
|
|
||||||
player.select("div.quality_change button.hd_btn").map {
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
this.name,
|
|
||||||
this.name,
|
|
||||||
it.attr("data-url"),
|
|
||||||
this.mainUrl,
|
|
||||||
quality = it.text().getIntFromText() ?: 0,
|
|
||||||
isM3u8 = true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class FaselHDProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(FaselHDProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "pl"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=filman.cc&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,149 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
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.select.Elements
|
|
||||||
|
|
||||||
class FilmanProvider : MainAPI() {
|
|
||||||
override var mainUrl = "https://filman.cc"
|
|
||||||
override var name = "Filman.cc"
|
|
||||||
override var lang = "pl"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Movie,
|
|
||||||
TvType.TvSeries
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
|
||||||
val document = app.get(mainUrl).document
|
|
||||||
val lists = document.select("#item-list,#series-list")
|
|
||||||
val categories = ArrayList<HomePageList>()
|
|
||||||
for (l in lists) {
|
|
||||||
val title = capitalizeString(l.parent()!!.select("h3").text().lowercase())
|
|
||||||
val items = l.select(".poster").map { i ->
|
|
||||||
val name = i.select("a[href]").attr("title")
|
|
||||||
val href = i.select("a[href]").attr("href")
|
|
||||||
val poster = i.select("img[src]").attr("src")
|
|
||||||
val year = l.select(".film_year").text().toIntOrNull()
|
|
||||||
if (l.hasClass("series-list")) TvSeriesSearchResponse(
|
|
||||||
name,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.TvSeries,
|
|
||||||
poster,
|
|
||||||
year,
|
|
||||||
null
|
|
||||||
) else MovieSearchResponse(
|
|
||||||
name,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
poster,
|
|
||||||
year
|
|
||||||
)
|
|
||||||
}
|
|
||||||
categories.add(HomePageList(title, items))
|
|
||||||
}
|
|
||||||
return HomePageResponse(categories)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val url = "$mainUrl/wyszukiwarka?phrase=$query"
|
|
||||||
val document = app.get(url).document
|
|
||||||
val lists = document.select("#advanced-search > div")
|
|
||||||
val movies = lists[1].select("#item-list > div:not(.clearfix)")
|
|
||||||
val series = lists[3].select("#item-list > div:not(.clearfix)")
|
|
||||||
if (movies.isEmpty() && series.isEmpty()) return ArrayList()
|
|
||||||
fun getVideos(type: TvType, items: Elements): List<SearchResponse> {
|
|
||||||
return items.mapNotNull { i ->
|
|
||||||
val href = i.selectFirst(".poster > a")?.attr("href") ?: return@mapNotNull null
|
|
||||||
val img =
|
|
||||||
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()
|
|
||||||
if (type === TvType.TvSeries) {
|
|
||||||
TvSeriesSearchResponse(
|
|
||||||
name,
|
|
||||||
href,
|
|
||||||
this.name,
|
|
||||||
type,
|
|
||||||
img,
|
|
||||||
year,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
MovieSearchResponse(name, href, this.name, type, img, year)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getVideos(TvType.Movie, movies) + getVideos(TvType.TvSeries, series)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val document = app.get(url).document
|
|
||||||
val documentTitle = document.select("title").text().trim()
|
|
||||||
|
|
||||||
if (documentTitle.startsWith("Logowanie")) {
|
|
||||||
throw RuntimeException("This page seems to be locked behind a login-wall on the website, unable to scrape it. If it is not please report it.")
|
|
||||||
}
|
|
||||||
|
|
||||||
var title = document.select("span[itemprop=title]").text()
|
|
||||||
val data = document.select("#links").outerHtml()
|
|
||||||
val posterUrl = document.select("#single-poster > img").attr("src")
|
|
||||||
val year = document.select(".info > ul > li").getOrNull(1)?.text()?.toIntOrNull()
|
|
||||||
val plot = document.select(".description").text()
|
|
||||||
val episodesElements = document.select("#episode-list a[href]")
|
|
||||||
if (episodesElements.isEmpty()) {
|
|
||||||
return MovieLoadResponse(title, url, name, TvType.Movie, data, posterUrl, year, plot)
|
|
||||||
}
|
|
||||||
title = document.selectFirst(".info")?.parent()?.select("h2")?.text() ?: ""
|
|
||||||
val episodes = episodesElements.mapNotNull { episode ->
|
|
||||||
val e = episode.text()
|
|
||||||
val regex = Regex("""\[s(\d{1,3})e(\d{1,3})]""").find(e) ?: return@mapNotNull null
|
|
||||||
val eid = regex.groups
|
|
||||||
Episode(
|
|
||||||
episode.attr("href"),
|
|
||||||
e.split("]")[1].trim(),
|
|
||||||
eid[1]?.value?.toInt(),
|
|
||||||
eid[2]?.value?.toInt(),
|
|
||||||
)
|
|
||||||
}.toMutableList()
|
|
||||||
|
|
||||||
return TvSeriesLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
name,
|
|
||||||
TvType.TvSeries,
|
|
||||||
episodes,
|
|
||||||
posterUrl,
|
|
||||||
year,
|
|
||||||
plot
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
val document = if (data.startsWith("http"))
|
|
||||||
app.get(data).document.select("#links").first()
|
|
||||||
else Jsoup.parse(data)
|
|
||||||
|
|
||||||
document?.select(".link-to-video")?.apmap { item ->
|
|
||||||
val decoded = base64Decode(item.select("a").attr("data-iframe"))
|
|
||||||
val link = tryParseJson<LinkElement>(decoded)?.src ?: return@apmap
|
|
||||||
loadExtractor(link, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data class LinkElement(
|
|
||||||
@JsonProperty("src") val src: String
|
|
||||||
)
|
|
|
@ -1,14 +0,0 @@
|
||||||
|
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
|
||||||
import com.lagradost.cloudstream3.plugins.Plugin
|
|
||||||
import android.content.Context
|
|
||||||
|
|
||||||
@CloudstreamPlugin
|
|
||||||
class FilmanProviderPlugin: Plugin() {
|
|
||||||
override fun load(context: Context) {
|
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
|
||||||
registerMainAPI(FilmanProvider())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
// use an integer for version numbers
|
|
||||||
version = 1
|
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
|
||||||
language = "it"
|
|
||||||
// All of these properties are optional, you can safely remove them
|
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
|
||||||
// authors = listOf("Cloudburst")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Status int as the following:
|
|
||||||
* 0: Down
|
|
||||||
* 1: Ok
|
|
||||||
* 2: Slow
|
|
||||||
* 3: Beta only
|
|
||||||
* */
|
|
||||||
status = 1 // will be 3 if unspecified
|
|
||||||
tvTypes = listOf(
|
|
||||||
"TvSeries",
|
|
||||||
"Movie",
|
|
||||||
)
|
|
||||||
|
|
||||||
iconUrl = "https://www.google.com/s2/favicons?domain=filmpertutti.photo&sz=%size%"
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest package="com.lagradost"/>
|
|
|
@ -1,193 +0,0 @@
|
||||||
package com.lagradost
|
|
||||||
|
|
||||||
//import androidx.core.text.parseAsHtml
|
|
||||||
import com.lagradost.cloudstream3.*
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addRating
|
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
|
||||||
import com.lagradost.cloudstream3.utils.ShortLink
|
|
||||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
|
||||||
import org.jsoup.nodes.Element
|
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.html
|
|
||||||
|
|
||||||
|
|
||||||
class FilmpertuttiProvider : MainAPI() {
|
|
||||||
override var lang = "it"
|
|
||||||
override var mainUrl = "https://filmpertutti.photo"
|
|
||||||
override var name = "Filmpertutti"
|
|
||||||
override val hasMainPage = true
|
|
||||||
override val hasChromecastSupport = true
|
|
||||||
override val supportedTypes = setOf(
|
|
||||||
TvType.Movie,
|
|
||||||
TvType.TvSeries
|
|
||||||
)
|
|
||||||
|
|
||||||
override val mainPage = mainPageOf(
|
|
||||||
Pair("$mainUrl/category/film/page/", "Film Popolari"),
|
|
||||||
Pair("$mainUrl/category/serie-tv/page/", "Serie Tv Popolari"),
|
|
||||||
Pair("$mainUrl/prime-visioni/", "Ultime uscite"),
|
|
||||||
)
|
|
||||||
|
|
||||||
override suspend fun getMainPage(
|
|
||||||
page: Int,
|
|
||||||
request: MainPageRequest
|
|
||||||
): HomePageResponse {
|
|
||||||
val url = request.data + page
|
|
||||||
|
|
||||||
val soup = app.get(url).document
|
|
||||||
val home = soup.select("ul.posts > li").map {
|
|
||||||
val title = it.selectFirst("div.title")!!.text().substringBeforeLast("(")
|
|
||||||
.substringBeforeLast("[")
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = it.selectFirst("a")!!.attr("data-thumbnail")
|
|
||||||
val qualitydata = it.selectFirst("div.hd")
|
|
||||||
val quality = if (qualitydata != null) {
|
|
||||||
getQualityFromString(qualitydata.text())
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
newTvSeriesSearchResponse(
|
|
||||||
title,
|
|
||||||
link
|
|
||||||
) {
|
|
||||||
this.posterUrl = image
|
|
||||||
this.quality = quality
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newHomePageResponse(request.name, home)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun search(query: String): List<SearchResponse> {
|
|
||||||
val queryformatted = query.replace(" ", "+")
|
|
||||||
val url = "$mainUrl/?s=$queryformatted"
|
|
||||||
val doc = app.get(url).document
|
|
||||||
return doc.select("ul.posts > li").map {
|
|
||||||
val title = it.selectFirst("div.title")!!.text().substringBeforeLast("(")
|
|
||||||
.substringBeforeLast("[")
|
|
||||||
val link = it.selectFirst("a")!!.attr("href")
|
|
||||||
val image = it.selectFirst("a")!!.attr("data-thumbnail")
|
|
||||||
val quality = getQualityFromString(it.selectFirst("div.hd")?.text())
|
|
||||||
|
|
||||||
MovieSearchResponse(
|
|
||||||
title,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
quality = quality,
|
|
||||||
posterUrl = image
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun load(url: String): LoadResponse {
|
|
||||||
val document = app.get(url).document
|
|
||||||
val type =
|
|
||||||
if (document.selectFirst("a.taxonomy.category")!!.attr("href").contains("serie-tv")
|
|
||||||
.not()
|
|
||||||
) TvType.Movie else TvType.TvSeries
|
|
||||||
val title = document.selectFirst("#content > h1")!!.text().substringBeforeLast("(")
|
|
||||||
.substringBeforeLast("[")
|
|
||||||
|
|
||||||
val description =
|
|
||||||
document.selectFirst("i.fa.fa-file-text-o.fa-fw")?.parent()?.nextSibling()?.toString()
|
|
||||||
?.html().toString()
|
|
||||||
|
|
||||||
|
|
||||||
val rating = document.selectFirst("div.rating > div.value")?.text()
|
|
||||||
|
|
||||||
val year =
|
|
||||||
document.selectFirst("#content > h1")?.text()?.substringAfterLast("(")
|
|
||||||
?.filter { it.isDigit() }?.toIntOrNull()
|
|
||||||
?: description.substringAfter("trasmessa nel").take(6).filter { it.isDigit() }
|
|
||||||
.toIntOrNull() ?: (document.selectFirst("i.fa.fa-calendar.fa-fw")?.parent()
|
|
||||||
?.nextSibling() as Element?)?.text()?.substringAfterLast(" ")
|
|
||||||
?.filter { it.isDigit() }?.toIntOrNull()
|
|
||||||
|
|
||||||
|
|
||||||
val poster = document.selectFirst("div.meta > div > img")?.attr("data-src")
|
|
||||||
|
|
||||||
|
|
||||||
val trailerurl =
|
|
||||||
document.selectFirst("div.youtube-player")?.attr("data-id")?.let { urldata ->
|
|
||||||
"https://www.youtube.com/watch?v=$urldata"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == TvType.TvSeries) {
|
|
||||||
|
|
||||||
val episodeList = ArrayList<Episode>()
|
|
||||||
document.select("div.accordion-item").filter { a ->
|
|
||||||
a.selectFirst("#season > ul > li.s_title > span")!!.text().isNotEmpty()
|
|
||||||
}.map { element ->
|
|
||||||
val season =
|
|
||||||
element.selectFirst("#season > ul > li.s_title > span")!!.text().toInt()
|
|
||||||
element.select("div.episode-wrap").map { episode ->
|
|
||||||
val href =
|
|
||||||
episode.select("#links > div > div > table > tbody:nth-child(2) > tr")
|
|
||||||
.map { it.selectFirst("a")!!.attr("href") }.toJson()
|
|
||||||
val epNum = episode.selectFirst("li.season-no")!!.text().substringAfter("x")
|
|
||||||
.filter { it.isDigit() }.toIntOrNull()
|
|
||||||
val epTitle = episode.selectFirst("li.other_link > a")?.text()
|
|
||||||
|
|
||||||
val posterUrl = episode.selectFirst("figure > img")?.attr("data-src")
|
|
||||||
episodeList.add(
|
|
||||||
Episode(
|
|
||||||
href,
|
|
||||||
epTitle,
|
|
||||||
season,
|
|
||||||
epNum,
|
|
||||||
posterUrl,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newTvSeriesLoadResponse(
|
|
||||||
title,
|
|
||||||
url, type, episodeList
|
|
||||||
) {
|
|
||||||
this.posterUrl = poster
|
|
||||||
this.year = year
|
|
||||||
this.plot = description
|
|
||||||
addRating(rating)
|
|
||||||
addTrailer(trailerurl)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
val urls0 = document.select("div.embed-player")
|
|
||||||
val urls = if (urls0.isNotEmpty()) {
|
|
||||||
urls0.map { it.attr("data-id") }.toJson()
|
|
||||||
} else {
|
|
||||||
document.select("#info > ul > li ").mapNotNull { it.selectFirst("a")?.attr("href") }
|
|
||||||
.toJson()
|
|
||||||
}
|
|
||||||
|
|
||||||
return newMovieLoadResponse(
|
|
||||||
title,
|
|
||||||
url,
|
|
||||||
type,
|
|
||||||
urls
|
|
||||||
) {
|
|
||||||
posterUrl = fixUrlNull(poster)
|
|
||||||
this.year = year
|
|
||||||
this.plot = description
|
|
||||||
addRating(rating)
|
|
||||||
addTrailer(trailerurl)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
|
||||||
data: String,
|
|
||||||
isCasting: Boolean,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
): Boolean {
|
|
||||||
tryParseJson<List<String>>(data)?.apmap { id ->
|
|
||||||
val link = ShortLink.unshorten(id).trim().replace("/v/", "/e/").replace("/f/", "/e/")
|
|
||||||
loadExtractor(link, data, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue