remove non english providers and add lang property

This commit is contained in:
C10udburst 2022-08-17 14:48:16 +02:00
parent a9190fa268
commit 9bd5bc00df
146 changed files with 31 additions and 7636 deletions

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -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("&amp")
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
}
}

View File

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

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=111.90.143.42&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,191 +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("$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
}
}

View File

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

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,25 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -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
}
}

View File

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

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -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?,
)
}

View File

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

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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",
"TvSeries",
"Movie",
)
iconUrl = "https://www.google.com/s2/favicons?domain=french-stream.re&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,273 +0,0 @@
package com.lagradost
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addRating
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.extractorApis
class FrenchStreamProvider : MainAPI() {
override var mainUrl = "https://french-stream.re"
override var name = "French Stream"
override val hasQuickSearch = false
override val hasMainPage = true
override var lang = "fr"
override val supportedTypes = setOf(TvType.AnimeMovie, TvType.TvSeries, TvType.Movie)
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/?do=search&subaction=search&story=$query"
val soup = app.post(link).document
return soup.select("div.short-in.nl").map { li ->
val href = fixUrl(li.selectFirst("a.short-poster")!!.attr("href"))
val poster = li.selectFirst("img")?.attr("src")
val title = li.selectFirst("> a.short-poster")!!.text().toString().replace(". ", "")
val year = li.selectFirst(".date")?.text()?.split("-")?.get(0)?.toIntOrNull()
if (title.contains(
"saison",
ignoreCase = true
)
) { // if saison in title ==> it's a TV serie
TvSeriesSearchResponse(
title,
href,
this.name,
TvType.TvSeries,
poster,
year,
(title.split("Eps ", " ")[1]).split(" ")[0].toIntOrNull()
)
} else { // it's a movie
MovieSearchResponse(
title,
href,
this.name,
TvType.Movie,
poster,
year,
)
}
}
}
override suspend fun load(url: String): LoadResponse {
val soup = app.get(url).document
val title = soup.selectFirst("h1#s-title")!!.text().toString()
val isMovie = !title.contains("saison", ignoreCase = true)
val description =
soup.selectFirst("div.fdesc")!!.text().toString()
.split("streaming", ignoreCase = true)[1].replace(" : ", "")
var poster = fixUrlNull(soup.selectFirst("div.fposter > img")?.attr("src"))
val listEpisode = soup.select("div.elink")
if (isMovie) {
val tags = soup.select("ul.flist-col > li").getOrNull(1)
val tagsList = tags?.select("a")
?.mapNotNull { // all the tags like action, thriller ...; unused variable
it?.text()
}
return newMovieLoadResponse(title, url, TvType.Movie, url) {
this.posterUrl = poster
addRating(soup.select("div.fr-count > div").text())
this.year = soup.select("ul.flist-col > li").getOrNull(2)?.text()?.toIntOrNull()
this.tags = tagsList
this.plot = description
addTrailer(soup.selectFirst("div.fleft > span > a")?.attr("href"))
}
} else // a tv serie
{
//println(listEpisode)
//println("listeEpisode:")
val episodeList = if ("<a" !in (listEpisode[0]).toString()) { // check if VF is empty
listEpisode[1] // no vf, return vostfr
} else {
listEpisode[0] // no vostfr, return vf
}
//println(url)
val episodes = episodeList.select("a").map { a ->
val epNum = a.text().split("Episode")[1].trim().toIntOrNull()
val epTitle = if (a.text().contains("Episode")) {
val type = if ("honey" in a.attr("id")) {
"VF"
} else {
"VOSTFR"
}
"Episode " + epNum?.toString() + " en " + type
} else {
a.text()
}
if (poster == null) {
poster = a.selectFirst("div.fposter > img")?.attr("src")
}
Episode(
fixUrl(url).plus("-episodenumber:$epNum"),
epTitle,
null,
epNum,
null, // episode Thumbnail
null // episode date
)
}
return TvSeriesLoadResponse(
title,
url,
this.name,
TvType.TvSeries,
episodes,
poster,
null,
description,
ShowStatus.Ongoing,
)
}
}
fun translate(
// the website has weird naming of series for episode 2 and 1 and original version content
episodeNumber: String,
is_vf_available: Boolean,
): String {
return if (episodeNumber == "1") {
if (is_vf_available) { // 1 translate differently if vf is available or not
"FGHIJK"
} else {
"episode033"
}
} else {
"episode" + (episodeNumber.toInt() + 32).toString()
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit,
): Boolean {
val servers =
if (data.contains("-episodenumber:"))// It's a serie:
{
val split =
data.split("-episodenumber:") // the data contains the url and the wanted episode number (a temporary dirty fix that will last forever)
val url = split[0]
val wantedEpisode =
if (split[1] == "2") { // the episode number 2 has id of ABCDE, don't ask any question
"ABCDE"
} else {
"episode" + split[1]
}
val soup = app.get(fixUrl(url)).document
val div =
if (wantedEpisode == "episode1") {
"> div.tabs-sel " // this element is added when the wanted episode is one (the place changes in the document)
} else {
""
}
val serversvf =// French version servers
soup.select("div#$wantedEpisode > div.selink > ul.btnss $div> li")
.mapNotNull { li -> // list of all french version servers
val serverUrl = fixUrl(li.selectFirst("a")!!.attr("href"))
// val litext = li.text()
if (serverUrl.isNotBlank()) {
if (li.text().replace("&nbsp;", "").replace(" ", "").isNotBlank()) {
Pair(li.text().replace(" ", ""), "vf" + fixUrl(serverUrl))
} else {
null
}
} else {
null
}
}
val translated = translate(split[1], serversvf.isNotEmpty())
val serversvo = // Original version servers
soup.select("div#$translated > div.selink > ul.btnss $div> li")
.mapNotNull { li ->
val serverUrl = fixUrlNull(li.selectFirst("a")?.attr("href"))
if (!serverUrl.isNullOrEmpty()) {
if (li.text().replace("&nbsp;", "").isNotBlank()) {
Pair(li.text().replace(" ", ""), "vo" + fixUrl(serverUrl))
} else {
null
}
} else {
null
}
}
serversvf + serversvo
} else { // it's a movie
val movieServers =
app.get(fixUrl(data)).document.select("nav#primary_nav_wrap > ul > li > ul > li > a")
.mapNotNull { a ->
val serverurl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null
val parent = a.parents()[2]
val element = parent.selectFirst("a")!!.text().plus(" ")
if (a.text().replace("&nbsp;", "").isNotBlank()) {
Pair(element.plus(a.text()), fixUrl(serverurl))
} else {
null
}
}
movieServers
}
servers.apmap {
for (extractor in extractorApis) {
if (it.first.contains(extractor.name, ignoreCase = true)) {
// val name = it.first
// print("true for $name")
extractor.getSafeUrl(it.second, it.second, subtitleCallback, callback)
break
}
}
}
return true
}
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse? {
val document = app.get(mainUrl).document
val docs = document.select("div.sect")
val returnList = docs.mapNotNull {
val epList = it.selectFirst("> div.sect-c.floats.clearfix") ?: return@mapNotNull null
val title =
it.selectFirst("> div.sect-t.fx-row.icon-r > div.st-left > a.st-capt")!!.text()
val list = epList.select("> div.short")
val isMovieType = title.contains("Films") // if truen type is Movie
val currentList = list.map { head ->
val hrefItem = head.selectFirst("> div.short-in.nl > a")
val href = fixUrl(hrefItem!!.attr("href"))
val img = hrefItem.selectFirst("> img")
val posterUrl = img!!.attr("src")
val name = img.attr("> div.short-title").toString()
return@map if (isMovieType) MovieSearchResponse(
name,
href,
this.name,
TvType.Movie,
posterUrl,
null
) else TvSeriesSearchResponse(
name,
href,
this.name,
TvType.TvSeries,
posterUrl,
null, null
)
}
if (currentList.isNotEmpty()) {
HomePageList(title, currentList)
} else null
}
if (returnList.isEmpty()) return null
return HomePageResponse(returnList)
}
}

View File

@ -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 FrenchStreamProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(FrenchStreamProvider())
}
}

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=185.231.223.76&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,232 +0,0 @@
package com.lagradost
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.mvvm.safeApiCall
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
import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup
class GomunimeProvider : MainAPI() {
override var mainUrl = "https://185.231.223.76"
override var name = "Gomunime"
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
}
}
}
override val mainPage = mainPageOf(
"e" to "Episode Baru",
"c" to "Completed",
"la" to "Live Action",
"t" to "Trending"
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val home = Jsoup.parse(
(app.post(
url = "$mainUrl/wp-admin/admin-ajax.php/wp-admin/admin-ajax.php",
headers = mapOf("Referer" to mainUrl),
data = mapOf(
"action" to "home_ajax",
"fungsi" to request.data,
"pag" to "$page"
)
).parsedSafe<Response>()?.html ?: throw ErrorLoadingException("Invalid Json reponse"))
).select("li").mapNotNull {
val title = it.selectFirst("a.name")?.text()?.trim() ?: return@mapNotNull null
val href = getProperAnimeLink(it.selectFirst("a")!!.attr("href"))
val posterUrl = it.selectFirst("img")?.attr("src")
val type = getType(it.selectFirst(".taglist > span")!!.text().trim())
val epNum = it.select(".tag.ep").text().replace(Regex("[^0-9]"), "").trim()
.toIntOrNull()
newAnimeSearchResponse(title, href, type) {
this.posterUrl = posterUrl
addSub(epNum)
}
}
return newHomePageResponse(request.name, home)
}
private fun getProperAnimeLink(uri: String): String {
return if (uri.contains("-episode")) {
val href =
"$mainUrl/anime/" + Regex("\\w\\d/(.*)-episode.*").find(uri)?.groupValues?.get(1)
.toString()
when {
href.contains("pokemon") -> href.replace(Regex("-[0-9]+"), "")
else -> href
}
} else {
uri
}
}
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/?s=$query"
val document = app.get(link).document
return document.select(".anime-list > li").map {
val title = it.selectFirst("a.name")!!.text()
val poster = it.selectFirst("img")!!.attr("src")
val tvType = getType(it.selectFirst(".taglist > span")?.text().toString())
val href = fixUrl(it.selectFirst("a.name")!!.attr("href"))
newAnimeSearchResponse(title, href, tvType) {
this.posterUrl = poster
addDubStatus(dubExist = false, subExist = true)
}
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val title = document.selectFirst(".entry-title")?.text().toString()
val poster = document.selectFirst(".thumbposter > img")?.attr("data-lazy-src")
val tags = document.select(".genxed > a").map { it.text() }
val year = Regex("\\d, ([0-9]*)").find(
document.select("time[itemprop = datePublished]").text()
)?.groupValues?.get(1)?.toIntOrNull()
val status = getStatus(document.selectFirst(".spe > span")!!.ownText())
val description = document.select("div[itemprop = description] > p").text()
val trailer = document.selectFirst("div.embed-responsive noscript iframe")?.attr("src")
val episodes = parseJson<List<EpisodeElement>>(
Regex("var episodelist = (\\[.*])").find(
document.select(".bixbox.bxcl.epcheck > script").toString().trim()
)?.groupValues?.get(1).toString().replace(Regex("""\\"""), "").trim()
).map {
val name =
Regex("(Episode\\s?[0-9]+)").find(it.epTitle.toString())?.groupValues?.getOrNull(0)
?: it.epTitle
val link = it.epLink
Episode(link, name)
}.reversed()
return newAnimeLoadResponse(title, url, TvType.Anime) {
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 = app.get(data).document
val scriptData = document.select("aside.sidebar > script").dataNodes().toString()
val key = scriptData.substringAfter("var a_ray = '").substringBefore("';")
val title = scriptData.substringAfter("var judul_postingan = \"").substringBefore("\";")
val sources: List<Pair<String, String>> = app.post(
url = "https://path.gomuni.me/app/vapi.php",
data = mapOf("data" to key, "judul" to title, "func" to "mirror")
).document.select("div.gomunime-server-mirror").map {
Pair(
it.attr("data-vhash"),
it.attr("data-type")
)
}
sources.apmap {
safeApiCall {
when {
it.second.contains("frame") -> {
loadExtractor(it.first, data, subtitleCallback, callback)
}
it.second.contains("hls") -> {
app.post(
url = "https://path.gomuni.me/app/vapi.php",
data = mapOf("fid" to it.first, "func" to "hls")
).text.let { link ->
M3u8Helper.generateM3u8(
this.name,
link,
"$mainUrl/",
headers = mapOf("Origin" to mainUrl)
).forEach(callback)
}
}
it.second.contains("mp4") -> {
app.post(
url = "https://path.gomuni.me/app/vapi.php",
data = mapOf("data" to it.first, "func" to "blogs")
).parsed<List<MobiSource>>().map {
callback.invoke(
ExtractorLink(
source = name,
name = "Mobi SD",
url = it.file,
referer = "$mainUrl/",
quality = Qualities.P360.value
)
)
}
}
else -> null
}
}
}
return true
}
private data class Response(
@JsonProperty("status") val status: Boolean,
@JsonProperty("html") val html: String
)
data class MobiSource(
@JsonProperty("file") val file: String,
@JsonProperty("label") val label: String,
@JsonProperty("type") val type: String
)
private data class EpisodeElement(
@JsonProperty("data-index") val dataIndex: Long?,
@JsonProperty("ep-num") val epNum: String?,
@JsonProperty("ep-title") val epTitle: String?,
@JsonProperty("ep-link") val epLink: String,
@JsonProperty("ep-date") val epDate: String?
)
}

View File

@ -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 GomunimeProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(GomunimeProvider())
}
}

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,24 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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",
)
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,154 +0,0 @@
package com.lagradost
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.httpsify
import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
class HDMovie5 : MainAPI() {
override var mainUrl = "https://hdmovie2.click"
override var name = "HDMovie"
override var lang = "hi"
override val hasQuickSearch = true
override val hasMainPage = true
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries,
)
override val mainPage = mainPageOf(
"$mainUrl/genre/tv-movie/page/" to "TV Movie",
"$mainUrl/genre/tv-show/page/" to "TV- Show",
"$mainUrl/genre/hindi-dubbed/page/" to "Hindi Dubbed",
"$mainUrl/genre/netflix/page/" to "NETFLIX",
)
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
val home = app.get(request.data + page).document.select("article.item").mapNotNull {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
}
private fun Element.toSearchResult(): SearchResponse? {
val title = this.selectFirst("h3 > a")?.text()?.trim() ?: return null
val href = fixUrl(this.selectFirst("a")!!.attr("href"))
val posterUrl = this.selectFirst("img")?.attr("src")
return newMovieSearchResponse(title, href, TvType.Movie) {
addPoster(posterUrl)
}
}
private data class QuickSearchResponse(
val title: String,
val url: String,
val img: String,
val extra: Extra
) {
data class Extra(
val date: String
)
}
override suspend fun quickSearch(query: String): List<SearchResponse> {
return app.get("$mainUrl/wp-json/dooplay/search/?keyword=$query&nonce=ddbde04d9c")
.parsed<Map<String, QuickSearchResponse>>().map {
val res = it.value
MovieSearchResponse(
res.title,
res.url,
this.name,
TvType.Movie,
res.img,
res.extra.date.toIntOrNull()
)
}
}
override suspend fun search(query: String): List<SearchResponse> {
return app.get("$mainUrl/?s=$query").document.select(".search-page>div.result-item").map {
val image = it.select(".image")
MovieSearchResponse(
image.select("img").attr("alt"),
image.select("a").attr("href"),
this.name,
TvType.Movie,
image.select("img").attr("src"),
it.select(".year").text().toIntOrNull()
)
}
}
override suspend fun load(url: String): LoadResponse {
val doc = app.get(url).document
val info = doc.select(".sheader")
val links = doc.select("#playeroptionsul>li")
val data = links.joinToString(",") { it.attr("data-post") }
return MovieLoadResponse(
info.select(".data>h1").text(),
url,
this.name,
TvType.Movie,
data,
info.select(".poster>img").attr("src"),
info.select(".date").text().substringAfter(", ").toIntOrNull(),
doc.select(".wp-content>p").let { it.getOrNull(it.size - 1)?.text() },
(doc.select("#repimdb>strong").text().toFloatOrNull()?.times(1000))?.toInt(),
info.select(".sgeneros>a").map { it.text() },
info.select(".runtime").text().substringBefore(" Min.").toIntOrNull(),
mutableListOf(),
doc.select("#single_relacionados>article>a").map {
val img = it.select("img")
MovieSearchResponse(
img.attr("alt"),
it.attr("href"),
this.name,
TvType.Movie,
img.attr("src")
)
},
doc.select("#cast>.persons>.person").mapNotNull {
if (it.attr("itemprop") != "director") {
ActorData(
Actor(
it.select("meta").attr("content"),
it.select("img").attr("src")
)
)
} else null
},
)
}
private data class PlayerAjaxResponse(
@JsonProperty("embed_url")
val embedURL: String? = null
)
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
return data.split(",").apmapIndexed { index, it ->
val p = app.post(
"$mainUrl/wp-admin/admin-ajax.php",
data = mapOf(
"action" to "doo_player_ajax",
"post" to it,
"nume" to "${index + 1}",
"type" to "movie"
)
)
val html = p.parsedSafe<PlayerAjaxResponse>()?.embedURL ?: return@apmapIndexed false
val doc = Jsoup.parse(html)
val link = doc.select("iframe").attr("src")
loadExtractor(httpsify(link), "$mainUrl/", subtitleCallback, callback)
}.contains(true)
}
}

View File

@ -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 HDMovie5Plugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(HDMovie5())
}
}

View File

@ -1,27 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=hdrezka19139.org&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,408 +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.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
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.Qualities
import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import java.util.*
class HDrezkaProvider : MainAPI() {
override var mainUrl = "https://hdrezka19139.org"
override var name = "HDrezka"
override val hasMainPage = true
override var lang = "ru"
override val hasDownloadSupport = true
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries,
TvType.Anime,
TvType.AsianDrama
)
override val mainPage = mainPageOf(
"$mainUrl/films/?filter=watching" to "фильмы",
"$mainUrl/series/?filter=watching" to "сериалы",
"$mainUrl/cartoons/?filter=watching" to "мультфильмы",
"$mainUrl/animation/?filter=watching" to "аниме",
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val url = request.data.split("?")
val home = app.get("${url.first()}page/$page/?${url.last()}").document.select(
"div.b-content__inline_items div.b-content__inline_item"
).map {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
}
private fun Element.toSearchResult(): SearchResponse {
val title =
this.selectFirst("div.b-content__inline_item-link > a")?.text()?.trim().toString()
val href = this.selectFirst("a")?.attr("href").toString()
val posterUrl = this.select("img").attr("src")
val type = if (this.select("span.info").isNotEmpty()) TvType.TvSeries else TvType.Movie
return if (type == TvType.Movie) {
newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl
}
} else {
val episode =
this.select("span.info").text().substringAfter(",").replace(Regex("[^0-9]"), "")
.toIntOrNull()
newAnimeSearchResponse(title, href, TvType.TvSeries) {
this.posterUrl = posterUrl
addDubStatus(
dubExist = true,
dubEpisodes = episode,
subExist = true,
subEpisodes = episode
)
}
}
}
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/search/?do=search&subaction=search&q=$query"
val document = app.get(link).document
return document.select("div.b-content__inline_items div.b-content__inline_item").map {
it.toSearchResult()
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val id = url.split("/").last().split("-").first()
val title = (document.selectFirst("div.b-post__origtitle")?.text()?.trim()
?: document.selectFirst("div.b-post__title h1")?.text()?.trim()).toString()
val poster = fixUrlNull(document.selectFirst("div.b-sidecover img")?.attr("src"))
val tags =
document.select("table.b-post__info > tbody > tr:nth-child(5) span[itemprop=genre]")
.map { it.text() }
val year = document.select("div.film-info > div:nth-child(2) a").text().toIntOrNull()
val tvType = if (document.select("div#simple-episodes-tabs")
.isNullOrEmpty()
) TvType.Movie else TvType.TvSeries
val description = document.selectFirst("div.b-post__description_text")?.text()?.trim()
val trailer = app.post(
"$mainUrl/engine/ajax/gettrailervideo.php",
data = mapOf("id" to id),
referer = url
).parsedSafe<Trailer>()?.code.let {
Jsoup.parse(it.toString()).select("iframe").attr("src")
}
val rating =
document.selectFirst("table.b-post__info > tbody > tr:nth-child(1) span.bold")?.text()
.toRatingInt()
val actors = document.select("table.b-post__info > tbody > tr:last-child span.item").map {
Actor(
it.selectFirst("span[itemprop=name]")?.text().toString(),
it.selectFirst("span[itemprop=actor]")?.attr("data-photo")
)
}
val recommendations = document.select("div.b-sidelist div.b-content__inline_item").map {
it.toSearchResult()
}
val data = HashMap<String, Any>()
val server = ArrayList<Map<String, String>>()
data["id"] = id
data["favs"] = document.selectFirst("input#ctrl_favs")?.attr("value").toString()
data["ref"] = url
return if (tvType == TvType.TvSeries) {
document.select("ul#translators-list li").map { res ->
server.add(
mapOf(
"translator_name" to res.text(),
"translator_id" to res.attr("data-translator_id"),
)
)
}
val episodes = document.select("div#simple-episodes-tabs ul li").map {
val season = it.attr("data-season_id").toIntOrNull()
val episode = it.attr("data-episode_id").toIntOrNull()
val name = "Episode $episode"
data["season"] = "$season"
data["episode"] = "$episode"
data["server"] = server
data["action"] = "get_stream"
Episode(
data.toJson(),
name,
season,
episode,
)
}
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
} else {
document.select("ul#translators-list li").map { res ->
server.add(
mapOf(
"translator_name" to res.text(),
"translator_id" to res.attr("data-translator_id"),
"camrip" to res.attr("data-camrip"),
"ads" to res.attr("data-ads"),
"director" to res.attr("data-director")
)
)
}
data["server"] = server
data["action"] = "get_movie"
newMovieLoadResponse(title, url, TvType.Movie, data.toJson()) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
}
}
private fun decryptStreamUrl(data: String): String {
fun getTrash(arr: List<String>, item: Int): List<String> {
val trash = ArrayList<List<String>>()
for (i in 1..item) {
trash.add(arr)
}
return trash.reduce { acc, list ->
val temp = ArrayList<String>()
acc.forEach { ac ->
list.forEach { li ->
temp.add(ac.plus(li))
}
}
return@reduce temp
}
}
val trashList = listOf("@", "#", "!", "^", "$")
val trashSet = getTrash(trashList, 2) + getTrash(trashList, 3)
var trashString = data.replace("#h", "").split("//_//").joinToString("")
trashSet.forEach {
val temp = base64Encode(it.toByteArray())
trashString = trashString.replace(temp, "")
}
return base64Decode(trashString)
}
private fun cleanCallback(
source: String,
url: String,
quality: String,
isM3u8: Boolean,
sourceCallback: (ExtractorLink) -> Unit
) {
sourceCallback.invoke(
ExtractorLink(
source,
source,
url,
"$mainUrl/",
getQuality(quality),
isM3u8,
headers = mapOf(
"Origin" to mainUrl
)
)
)
}
private fun getLanguage(str: String): String {
return when (str) {
"Русский" -> "Russian"
"Українська" -> "Ukrainian"
else -> str
}
}
private fun getQuality(str: String): Int {
return when (str) {
"360p" -> Qualities.P240.value
"480p" -> Qualities.P360.value
"720p" -> Qualities.P480.value
"1080p" -> Qualities.P720.value
"1080p Ultra" -> Qualities.P1080.value
else -> getQualityFromName(str)
}
}
private fun invokeSources(
source: String,
url: String,
subtitle: String,
subCallback: (SubtitleFile) -> Unit,
sourceCallback: (ExtractorLink) -> Unit
) {
decryptStreamUrl(url).split(",").map { links ->
val quality =
Regex("\\[([0-9]*p.*?)]").find(links)?.groupValues?.getOrNull(1)
.toString().trim()
links.replace("[$quality]", "").split("or").map { it.trim() }
.map { link ->
if (link.endsWith(".m3u8")) {
cleanCallback(
"$source (Main)",
link,
quality,
true,
sourceCallback,
)
} else {
cleanCallback(
"$source (Backup)",
link,
quality,
false,
sourceCallback,
)
}
}
}
subtitle.split(",").map { sub ->
val language =
Regex("\\[(.*)]").find(sub)?.groupValues?.getOrNull(1)
.toString()
val link = sub.replace("[$language]", "").trim()
subCallback.invoke(
SubtitleFile(
getLanguage(language),
link
)
)
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
tryParseJson<Data>(data)?.let { res ->
if (res.server?.isEmpty() == true) {
val document = app.get(res.ref ?: return@let).document
document.select("script").map { script ->
if (script.data().contains("sof.tv.initCDNMoviesEvents(")) {
val dataJson =
script.data().substringAfter("false, {").substringBefore("});")
tryParseJson<LocalSources>("{$dataJson}")?.let { source ->
invokeSources(
this.name,
source.streams,
source.subtitle.toString(),
subtitleCallback,
callback
)
}
}
}
} else {
res.server?.apmap { server ->
suspendSafeApiCall {
app.post(
url = "$mainUrl/ajax/get_cdn_series/?t=${Date().time}",
data = mapOf(
"id" to res.id,
"translator_id" to server.translator_id,
"favs" to res.favs,
"is_camrip" to server.camrip,
"is_ads" to server.ads,
"is_director" to server.director,
"season" to res.season,
"episode" to res.episode,
"action" to res.action,
).filterValues { it != null }.mapValues { it.value as String },
referer = res.ref
).parsedSafe<Sources>()?.let { source ->
invokeSources(
server.translator_name.toString(),
source.url,
source.subtitle.toString(),
subtitleCallback,
callback
)
}
}
}
}
}
return true
}
data class LocalSources(
@JsonProperty("streams") val streams: String,
@JsonProperty("subtitle") val subtitle: Any?,
)
data class Sources(
@JsonProperty("url") val url: String,
@JsonProperty("subtitle") val subtitle: Any?,
)
data class Server(
@JsonProperty("translator_name") val translator_name: String?,
@JsonProperty("translator_id") val translator_id: String?,
@JsonProperty("camrip") val camrip: String?,
@JsonProperty("ads") val ads: String?,
@JsonProperty("director") val director: String?,
)
data class Data(
@JsonProperty("id") val id: String?,
@JsonProperty("favs") val favs: String?,
@JsonProperty("server") val server: List<Server>?,
@JsonProperty("season") val season: String?,
@JsonProperty("episode") val episode: String?,
@JsonProperty("action") val action: String?,
@JsonProperty("ref") val ref: String?,
)
data class Trailer(
@JsonProperty("success") val success: Boolean?,
@JsonProperty("code") val code: String?,
)
}

View File

@ -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 HDrezkaProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(HDrezkaProvider())
}
}

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,25 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=94.103.82.88&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,385 +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.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import org.jsoup.nodes.Element
import java.net.URI
class IdlixProvider : MainAPI() {
override var mainUrl = "https://94.103.82.88"
override var name = "Idlix"
override val hasMainPage = true
override var lang = "id"
override val hasDownloadSupport = true
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries,
)
override val mainPage = mainPageOf(
"$mainUrl/trending/page/?get=movies" to "Trending Movies",
"$mainUrl/trending/page/?get=tv" to "Trending TV Series",
"$mainUrl/movie/page/" to "Movie Terbaru",
"$mainUrl/tvseries/page/" to "TV Series Terbaru",
"$mainUrl/season/page/" to "Season Terbaru",
"$mainUrl/episode/page/" to "Episode Terbaru",
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val url = request.data.split("?")
val document = app.get("${url.first()}$page/?${url.lastOrNull()}").document
val home = document.select("div.items.full article, div#archive-content article").mapNotNull {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
}
private fun getProperLink(uri: String): String {
return when {
uri.contains("/episode/") -> {
var title = uri.substringAfter("$mainUrl/episode/")
title = Regex("(.+?)-season").find(title)?.groupValues?.get(1).toString()
"$mainUrl/tvseries/$title"
}
uri.contains("/season/") -> {
var title = uri.substringAfter("$mainUrl/season/")
title = Regex("(.+?)-season").find(title)?.groupValues?.get(1).toString()
"$mainUrl/tvseries/$title"
}
else -> {
uri
}
}
}
private fun Element.toSearchResult(): SearchResponse {
val title = this.selectFirst("h3 > a")!!.text().replace(Regex("\\(\\d{4}\\)"), "").trim()
val href = getProperLink(this.selectFirst("h3 > a")!!.attr("href"))
val posterUrl = this.select("div.poster > img").attr("src").toString()
val quality = getQualityFromString(this.select("span.quality").text())
return newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl
this.quality = quality
}
}
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/search/$query"
val document = app.get(link).document
return document.select("div.result-item").map {
val title =
it.selectFirst("div.title > a")!!.text().replace(Regex("\\(\\d{4}\\)"), "").trim()
val href = getProperLink(it.selectFirst("div.title > a")!!.attr("href"))
val posterUrl = it.selectFirst("img")!!.attr("src").toString()
newMovieSearchResponse(title, href, TvType.TvSeries) {
this.posterUrl = posterUrl
}
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val title =
document.selectFirst("div.data > h1")?.text()?.replace(Regex("\\(\\d{4}\\)"), "")
?.trim().toString()
val poster = document.select("div.poster > img").attr("src").toString()
val tags = document.select("div.sgeneros > a").map { it.text() }
val year = Regex(",\\s?(\\d+)").find(
document.select("span.date").text().trim()
)?.groupValues?.get(1).toString().toIntOrNull()
val tvType = if (document.select("ul#section > li:nth-child(1)").text().contains("Episodes")
) TvType.TvSeries else TvType.Movie
val description = document.select("div.wp-content > p").text().trim()
val trailer = document.selectFirst("div.embed iframe")?.attr("src")
val rating =
document.selectFirst("span.dt_rating_vgs")?.text()?.toRatingInt()
val actors = document.select("div.persons > div[itemprop=actor]").map {
Actor(it.select("meta[itemprop=name]").attr("content"), it.select("img").attr("src"))
}
val recommendations = document.select("div.owl-item").map {
val recName =
it.selectFirst("a")!!.attr("href").toString().removeSuffix("/").split("/").last()
val recHref = it.selectFirst("a")!!.attr("href")
val recPosterUrl = it.selectFirst("img")?.attr("src").toString()
newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) {
this.posterUrl = recPosterUrl
}
}
return if (tvType == TvType.TvSeries) {
val episodes = document.select("ul.episodios > li").map {
val href = it.select("a").attr("href")
val name = fixTitle(it.select("div.episodiotitle > a").text().trim())
val image = it.select("div.imagen > img").attr("src")
val episode = it.select("div.numerando").text().replace(" ", "").split("-").last()
.toIntOrNull()
val season = it.select("div.numerando").text().replace(" ", "").split("-").first()
.toIntOrNull()
Episode(
href,
name,
season,
episode,
image
)
}
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
} else {
newMovieLoadResponse(title, url, TvType.Movie, url) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
}
}
private fun getLanguage(str: String): String {
return when {
str.lowercase().contains("indonesia") || str.lowercase()
.contains("bahasa") -> "Indonesian"
else -> str
}
}
data class ResponseHash(
@JsonProperty("embed_url") val embed_url: String,
@JsonProperty("type") val type: String?,
)
data class ResponseSource(
@JsonProperty("hls") val hls: Boolean,
@JsonProperty("videoSource") val videoSource: String,
@JsonProperty("securedLink") val securedLink: String?,
)
data class Tracks(
@JsonProperty("kind") val kind: String?,
@JsonProperty("file") val file: String,
@JsonProperty("label") val label: String?,
)
private suspend fun invokeLokalSource(
url: String,
subCallback: (SubtitleFile) -> Unit,
sourceCallback: (ExtractorLink) -> Unit
) {
val document = app.get(url, referer = "$mainUrl/").document
val hash = url.split("/").last().substringAfter("data=")
val m3uLink = app.post(
url = "https://jeniusplay.com/player/index.php?data=$hash&do=getVideo",
data = mapOf("hash" to hash, "r" to "$mainUrl/"),
referer = url,
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
).parsed<ResponseSource>().videoSource
M3u8Helper.generateM3u8(
this.name,
m3uLink,
url,
).forEach(sourceCallback)
document.select("script").map { script ->
if (script.data().contains("eval(function(p,a,c,k,e,d)")) {
val subData =
getAndUnpack(script.data()).substringAfter("\"tracks\":[").substringBefore("],")
tryParseJson<List<Tracks>>("[$subData]")?.map { subtitle ->
subCallback.invoke(
SubtitleFile(
getLanguage(subtitle.label!!),
subtitle.file
)
)
}
}
}
}
data class ResponseLaviolaSource(
@JsonProperty("file") val file: String,
@JsonProperty("label") val label: String?,
)
private suspend fun invokeLaviolaSource(
url: String,
subCallback: (SubtitleFile) -> Unit,
sourceCallback: (ExtractorLink) -> Unit
) {
val document = app.get(url, referer = "$mainUrl/").document
val baseName = "Laviola"
val baseUrl = "https://laviola.live/"
document.select("script").map { script ->
if (script.data().contains("var config = {")) {
val data = script.data().substringAfter("sources: [").substringBefore("],")
tryParseJson<List<ResponseLaviolaSource>>("[$data]")?.map { m3u ->
val m3uData = app.get(m3u.file, referer = baseUrl).text
val quality =
Regex("\\d{3,4}\\.m3u8").findAll(m3uData).map { it.value }.toList()
quality.forEach {
sourceCallback.invoke(
ExtractorLink(
source = baseName,
name = baseName,
url = m3u.file.replace("video.m3u8", it),
referer = baseUrl,
quality = getQualityFromName("${it.replace(".m3u8", "")}p"),
isM3u8 = true
)
)
}
}
val subData = script.data().substringAfter("tracks: [").substringBefore("],")
tryParseJson<List<Tracks>>("[$subData]")?.map { subtitle ->
subCallback.invoke(
SubtitleFile(
getLanguage(subtitle.label!!),
(if (subtitle.kind!!.contains("captions")) subtitle.file else null)!!
)
)
}
}
}
}
private data class Captions(
@JsonProperty("id") val id: String,
@JsonProperty("hash") val hash: String,
@JsonProperty("language") val language: String,
)
private data class Data(
@JsonProperty("file") val file: String,
@JsonProperty("label") val label: String,
)
private data class Player(
@JsonProperty("poster_file") val poster_file: String,
)
private data class ResponseCdn(
@JsonProperty("success") val success: Boolean,
@JsonProperty("player") val player: Player,
@JsonProperty("data") val data: List<Data>?,
@JsonProperty("captions") val captions: List<Captions>?
)
private suspend fun invokeCdnSource(
url: String,
subCallback: (SubtitleFile) -> Unit,
sourceCallback: (ExtractorLink) -> Unit
) {
val domainUrl = "https://cdnplayer.online"
val id = url.trimEnd('/').split("/").last()
val sources = app.post(
url = "$domainUrl/api/source/$id",
data = mapOf("r" to mainUrl, "d" to URI(url).host)
).parsed<ResponseCdn>()
sources.data?.map {
sourceCallback.invoke(
ExtractorLink(
name,
"Cdnplayer",
fixUrl(it.file),
referer = url,
quality = getQualityFromName(it.label)
)
)
}
val userData = sources.player.poster_file.split("/")[2]
sources.captions?.map { subtitle ->
subCallback.invoke(
SubtitleFile(
getLanguage(subtitle.language),
"$domainUrl/asset/userdata/$userData/caption/${subtitle.hash}/${subtitle.id}.srt"
)
)
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val document = app.get(data).document
val id = document.select("meta#dooplay-ajax-counter").attr("data-postid")
val type = if (data.contains("/movie/")) "movie" else "tv"
document.select("ul#playeroptionsul > li").map {
it.attr("data-nume")
}.apmap { nume ->
safeApiCall {
var source = app.post(
url = "$mainUrl/wp-admin/admin-ajax.php",
data = mapOf(
"action" to "doo_player_ajax",
"post" to id,
"nume" to nume,
"type" to type
)
).parsed<ResponseHash>().embed_url
when {
source.startsWith("https://jeniusplay.com") -> invokeLokalSource(
source,
subtitleCallback,
callback
)
source.startsWith("https://laviola.live") -> invokeLaviolaSource(
source,
subtitleCallback,
callback
)
source.startsWith("https://cdnplayer.online") -> invokeCdnSource(
source,
subtitleCallback,
callback
)
else -> {
if (source.startsWith("https://uservideo.xyz")) {
source = app.get(source).document.select("iframe").attr("src")
}
loadExtractor(source, data, subtitleCallback, callback)
}
}
}
}
return true
}
}

View File

@ -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 IdlixProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(IdlixProvider())
}
}

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=kuramanime.com&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,176 +0,0 @@
package com.lagradost
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import com.lagradost.cloudstream3.utils.ExtractorLink
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
class KuramanimeProvider : MainAPI() {
override var mainUrl = "https://kuramanime.com"
override var name = "Kuramanime"
override val hasQuickSearch = false
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) {
"Selesai Tayang" -> ShowStatus.Completed
"Sedang Tayang" -> ShowStatus.Ongoing
else -> ShowStatus.Completed
}
}
}
override val mainPage = mainPageOf(
"$mainUrl/anime/ongoing?order_by=updated&page=" to "Sedang Tayang",
"$mainUrl/anime/finished?order_by=updated&page=" to "Selesai Tayang",
"$mainUrl/properties/season/summer-2022?order_by=most_viewed&page=" to "Dilihat Terbanyak Musim Ini",
"$mainUrl/anime/movie?order_by=updated&page=" to "Film Layar Lebar",
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get(request.data + page).document
val home = document.select("div.col-lg-4.col-md-6.col-sm-6").mapNotNull {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
}
private fun getProperAnimeLink(uri: String): String {
return if (uri.contains("/episode")) {
Regex("(.*)/episode/.+").find(uri)?.groupValues?.get(1).toString() + "/"
} else {
uri
}
}
private fun Element.toSearchResult(): AnimeSearchResponse? {
val href = getProperAnimeLink(fixUrl(this.selectFirst("a")!!.attr("href")))
val title = this.selectFirst("h5 a")?.text() ?: return null
val posterUrl = fixUrl(this.select("div.product__item__pic.set-bg").attr("data-setbg"))
val episode = Regex("([0-9*])\\s?/").find(
this.select("div.ep span").text()
)?.groupValues?.getOrNull(1)?.toIntOrNull()
return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl
addSub(episode)
}
}
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/anime?search=$query&order_by=oldest"
val document = app.get(link).document
return document.select(".product__item").mapNotNull {
val title = it.selectFirst("div.product__item__text > h5")!!.text().trim()
val poster = it.selectFirst("a > div")!!.attr("data-setbg")
val tvType =
getType(it.selectFirst(".product__item__text > ul > li")!!.text().toString())
val href = fixUrl(it.selectFirst("a")!!.attr("href"))
newAnimeSearchResponse(title, href, tvType) {
this.posterUrl = poster
addDubStatus(dubExist = false, subExist = true)
}
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val title = document.selectFirst(".anime__details__title > h3")!!.text().trim()
val poster = document.selectFirst(".anime__details__pic")?.attr("data-setbg")
val tags =
document.select("div.anime__details__widget > div > div:nth-child(2) > ul > li:nth-child(1)")
.text().trim().replace("Genre: ", "").split(", ")
val year = Regex("[^0-9]").replace(
document.select("div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(5)")
.text().trim().replace("Musim: ", ""), ""
).toIntOrNull()
val status = getStatus(
document.select("div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(3)")
.text().trim().replace("Status: ", "")
)
val description = document.select(".anime__details__text > p").text().trim()
val episodes =
Jsoup.parse(document.select("#episodeLists").attr("data-content")).select("a").map {
val name = it.text().trim()
val link = it.attr("href")
Episode(link, name)
}
val recommendations = document.select("div#randomList > a").mapNotNull {
val epHref = it.attr("href")
val epTitle = it.select("h5.sidebar-title-h5.px-2.py-2").text()
val epPoster = it.select(".product__sidebar__view__item.set-bg").attr("data-setbg")
newAnimeSearchResponse(epTitle, epHref, TvType.Anime) {
this.posterUrl = epPoster
addDubStatus(dubExist = false, subExist = true)
}
}
return newAnimeLoadResponse(title, url, TvType.Anime) {
engName = title
posterUrl = poster
this.year = year
addEpisodes(DubStatus.Subbed, episodes)
showStatus = status
plot = description
this.tags = tags
this.recommendations = recommendations
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val servers = app.get(data).document
servers.select("video#player > source").map {
suspendSafeApiCall {
val url = it.attr("src")
val quality = it.attr("size").toInt()
callback.invoke(
ExtractorLink(
name,
name,
url,
referer = "$mainUrl/",
quality = quality
)
)
}
}
return true
}
}

View File

@ -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 KuramanimeProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(KuramanimeProvider())
}
}

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=45.12.2.2&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,197 +0,0 @@
package com.lagradost
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.mvvm.safeApiCall
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 KuronimeProvider : MainAPI() {
override var mainUrl = "https://45.12.2.2"
override var name = "Kuronime"
override val hasQuickSearch = false
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
}
}
}
override val mainPage = mainPageOf(
"$mainUrl/page/" to "New Episodes",
"$mainUrl/popular-anime/page/" to "Popular Anime",
"$mainUrl/movies/page/" to "Movies",
"$mainUrl/genres/donghua/page/" to "Donghua",
"$mainUrl/live-action/page/" to "Live Action",
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get(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")) -> Regex("nonton-(.+)-episode").find(
title
)?.groupValues?.get(1).toString()
(title.contains("-movie")) -> Regex("nonton-(.+)-movie").find(title)?.groupValues?.get(
1
).toString()
else -> title
}
"$mainUrl/anime/$title"
}
}
private fun Element.toSearchResult(): AnimeSearchResponse {
val href = getProperAnimeLink(fixUrlNull(this.selectFirst("a")?.attr("href")).toString())
val title = this.select(".bsuxtt, .tt > h4").text().trim()
val posterUrl = fixUrlNull(
this.selectFirst("div.view,div.bt")?.nextElementSibling()?.select("img")
?.attr("data-src")
)
val epNum = this.select(".ep").text().replace(Regex("[^0-9]"), "").trim().toIntOrNull()
val tvType = getType(this.selectFirst(".bt > span")?.text().toString())
return newAnimeSearchResponse(title, href, tvType) {
this.posterUrl = posterUrl
addSub(epNum)
}
}
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/?s=$query"
val document = app.get(link).document
return document.select("article.bs").map {
it.toSearchResult()
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val title = document.selectFirst(".entry-title")?.text().toString().trim()
val poster = document.selectFirst("div.l[itemprop=image] > img")?.attr("data-src")
val tags = document.select(".infodetail > ul > li:nth-child(2) > a").map { it.text() }
val type = getType(
document.selectFirst(".infodetail > ul > li:nth-child(7)")?.ownText()?.trim().toString()
)
val trailer = document.selectFirst("div.tply iframe")?.attr("data-lazy-src")
val year = Regex("\\d, ([0-9]*)").find(
document.select(".infodetail > ul > li:nth-child(5)").text()
)?.groupValues?.get(1)?.toIntOrNull()
val status = getStatus(
document.selectFirst(".infodetail > ul > li:nth-child(3)")!!.ownText()
.replace(Regex("\\W"), "")
)
val description = document.select("span.const > p").text()
val episodes = document.select("div.bixbox.bxcl > ul > li").map {
val name = it.selectFirst("a")?.text()?.trim()
val episode =
it.selectFirst("a")?.text()?.trim()?.replace("Episode", "")?.trim()?.toIntOrNull()
val link = it.selectFirst("a")!!.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
addTrailer(trailer)
this.tags = tags
}
}
private suspend fun invokeKuroSource(
url: String,
sourceCallback: (ExtractorLink) -> Unit
) {
val doc = app.get(url, referer = "${mainUrl}/").document
doc.select("script").map { script ->
if (script.data().contains("function jalankan_jwp() {")) {
val data = script.data()
val doma = data.substringAfter("var doma = \"").substringBefore("\";")
val token = data.substringAfter("var token = \"").substringBefore("\";")
val pat = data.substringAfter("var pat = \"").substringBefore("\";")
val link = "$doma$token$pat/index.m3u8"
val quality =
Regex("\\d{3,4}p").find(doc.select("title").text())?.groupValues?.get(0)
sourceCallback.invoke(
ExtractorLink(
this.name,
this.name,
link,
referer = "https://animeku.org/",
quality = getQualityFromName(quality),
headers = mapOf("Origin" to "https://animeku.org"),
isM3u8 = true
)
)
}
}
}
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("data-src"))
}
sources.apmap {
safeApiCall {
when {
it.startsWith("https://animeku.org") -> invokeKuroSource(it, callback)
else -> loadExtractor(it, mainUrl, subtitleCallback, callback)
}
}
}
return true
}
}

View File

@ -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 KuronimeProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(KuronimeProvider())
}
}

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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",
)
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,176 +0,0 @@
package com.lagradost
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
class LayarKacaProvider : MainAPI() {
override var mainUrl = "https://lk21.xn--6frz82g"
override var name = "LayarKaca"
override val hasMainPage = true
override var lang = "id"
override val hasDownloadSupport = true
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries,
TvType.AsianDrama
)
override val mainPage = mainPageOf(
"$mainUrl/populer/page/" to "Film Terplopuler",
"$mainUrl/latest-series/page/" to "Series Terbaru",
"$mainUrl/series/asian/page/" to "Film Asian Terbaru",
"$mainUrl/latest/page/" to "Film Upload Terbaru",
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get(request.data + page).document
val home = document.select("article.mega-item").mapNotNull {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
}
private fun Element.toSearchResult(): SearchResponse? {
val title = this.selectFirst("h1.grid-title > a")?.ownText()?.trim() ?: return null
val href = fixUrl(this.selectFirst("h1.grid-title > a")!!.attr("href"))
val posterUrl = fixUrlNull(this.selectFirst(".grid-poster > a > img")?.attr("src"))
val quality = this.select("div.quality").text().trim()
return newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl
addQuality(quality)
}
}
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/?s=$query"
val document = app.get(link).document
return document.select("div.search-item").map {
val title = it.selectFirst("h2 > a")!!.text().trim()
val href = it.selectFirst("h2 > a")!!.attr("href")
val posterUrl = fixUrl(it.selectFirst("img.img-thumbnail")?.attr("src").toString())
newTvSeriesSearchResponse(title, href, TvType.TvSeries) {
this.posterUrl = posterUrl
}
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val title = document.selectFirst("li.last > span[itemprop=name]")?.text()?.trim().toString()
val poster = fixUrl(document.select("img.img-thumbnail").attr("src").toString())
val tags = document.select("div.content > div:nth-child(5) > h3 > a").map { it.text() }
val year = Regex("\\d, (\\d+)").find(
document.select("div.content > div:nth-child(7) > h3").text().trim()
)?.groupValues?.get(1).toString().toIntOrNull()
val tvType = if (document.select("div.serial-wrapper")
.isNotEmpty()
) TvType.TvSeries else TvType.Movie
val description = document.select("div.content > blockquote").text().trim()
val trailer = document.selectFirst("div.action-player li > a.fancybox")?.attr("href")
val rating =
document.selectFirst("div.content > div:nth-child(6) > h3")?.text()?.toRatingInt()
val actors =
document.select("div.col-xs-9.content > div:nth-child(3) > h3 > a").map { it.text() }
val recommendations = document.select("div.row.item-media").map {
val recName = it.selectFirst("h3")?.text()?.trim().toString()
val recHref = it.selectFirst(".content-media > a")!!.attr("href")
val recPosterUrl =
fixUrl(it.selectFirst(".poster-media > a > img")?.attr("src").toString())
newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) {
this.posterUrl = recPosterUrl
}
}
return if (tvType == TvType.TvSeries) {
val episodes = document.select("div.episode-list > a:matches(\\d+)").map {
val href = fixUrl(it.attr("href"))
val episode = it.text().toIntOrNull()
val season =
it.attr("href").substringAfter("season-").substringBefore("-").toIntOrNull()
Episode(
href,
"Episode $episode",
season,
episode,
)
}.reversed()
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
} else {
newMovieLoadResponse(title, url, TvType.Movie, url) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val document = app.get(data).document
// maybe will need this in future
// val sources = if (data.contains("-episode-")) {
// document.select("script").mapNotNull { script ->
// if (script.data().contains("var data =")) {
// val scriptData =
// script.toString().substringAfter("var data = '").substringBefore("';")
// Jsoup.parse(scriptData).select("li").map {
// fixUrl(it.select("a").attr("href"))
// }
// } else {
// null
// }
// }[0]
// } else {
// document.select("ul#loadProviders > li").map {
// fixUrl(it.select("a").attr("href"))
// }
// }
document.select("ul#loadProviders > li").map {
fixUrl(it.select("a").attr("href"))
}.apmap {
val link = if (it.startsWith("https://layarkacaxxi.icu")) {
it.substringBeforeLast("/")
} else {
it
}
loadExtractor(link, data, subtitleCallback, callback)
}
return true
}
}

View File

@ -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 LayarKacaProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(LayarKacaProvider())
}
}

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=146.19.24.137&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,188 +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.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.nodes.Element
class MultiplexProvider : MainAPI() {
override var mainUrl = "https://146.19.24.137"
override var name = "Multiplex"
override val hasMainPage = true
override var lang = "id"
override val hasDownloadSupport = true
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries,
TvType.AsianDrama
)
override val mainPage = mainPageOf(
"$mainUrl/genre/top-popular-movies/page/" to "Top Popolar Movies",
"$mainUrl/genre/series-ongoing/page/" to "Series Ongoing",
"$mainUrl/genre/series-barat/page/" to "Series Barat",
"$mainUrl/genre/series-korea/page/" to "Series Korea",
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get(request.data + page).document
val home = document.select("article.item").mapNotNull {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
}
private fun Element.toSearchResult(): SearchResponse? {
val title = this.selectFirst("h2.entry-title > a")?.text()?.trim() ?: return null
val href = fixUrl(this.selectFirst("a")!!.attr("href"))
val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("data-src"))
val quality = this.select("div.gmr-quality-item > a").text().trim()
return if (quality.isEmpty()) {
val episode = this.select("div.gmr-numbeps > span").text().toIntOrNull()
newAnimeSearchResponse(title, href, TvType.TvSeries) {
this.posterUrl = posterUrl
addSub(episode)
}
} else {
newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl
addQuality(quality)
}
}
}
private fun Element.toBottomSearchResult(): SearchResponse? {
val title = this.selectFirst("a > span.idmuvi-rp-title")?.text()?.trim() ?: return null
val href = this.selectFirst("a")!!.attr("href")
val posterUrl = fixUrl(this.selectFirst("a > img")?.attr("data-src").toString())
return newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl
}
}
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/?s=$query&post_type[]=post&post_type[]=tv"
val document = app.get(link).document
return document.select("article.item").mapNotNull {
it.toSearchResult()
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val title =
document.selectFirst("h1.entry-title")?.text()?.substringBefore("Season")?.trim()
.toString()
val poster =
fixUrl(document.selectFirst("figure.pull-left > img")?.attr("data-src").toString())
val tags = document.select("span.gmr-movie-genre:contains(Genre:) > a").map { it.text() }
val year =
document.select("span.gmr-movie-genre:contains(Year:) > a").text().trim().toIntOrNull()
val tvType = if (url.contains("/tv/")) TvType.TvSeries else TvType.Movie
val description = document.selectFirst("div[itemprop=description] > p")?.text()?.trim()
val trailer = document.selectFirst("ul.gmr-player-nav li a.gmr-trailer-popup")?.attr("href")
val rating =
document.selectFirst("div.gmr-meta-rating > span[itemprop=ratingValue]")?.text()
?.toRatingInt()
val actors = document.select("div.gmr-moviedata").last()?.select("span[itemprop=actors]")
?.map { it.select("a").text() }
val recommendations = document.select("div.idmuvi-rp ul li").mapNotNull {
it.toBottomSearchResult()
}
return if (tvType == TvType.TvSeries) {
val episodes = document.select("div.gmr-listseries > a").map {
val href = fixUrl(it.attr("href"))
val episode = it.text().split(" ").last().toIntOrNull()
val season = it.text().split(" ").first().substringAfter("S").toIntOrNull()
Episode(
href,
"Episode $episode",
season,
episode,
)
}
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
} else {
newMovieLoadResponse(title, url, TvType.Movie, url) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
}
}
private data class ResponseSource(
@JsonProperty("file") val file: String,
@JsonProperty("type") val type: String?,
@JsonProperty("label") val label: String?
)
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val document = app.get(data).document
val id = document.selectFirst("div#muvipro_player_content_id")!!.attr("data-id")
val server = app.post(
"$mainUrl/wp-admin/admin-ajax.php",
data = mapOf("action" to "muvipro_player_content", "tab" to "player1", "post_id" to id)
).document.select("iframe").attr("src")
app.get(server, referer = "$mainUrl/").document.select("script").map { script ->
if (script.data().contains("var config = {")) {
val source = script.data().substringAfter("sources: [").substringBefore("],")
tryParseJson<List<ResponseSource>>("[$source]")?.map { m3u ->
val m3uData = app.get(m3u.file, referer = "https://gdriveplayer.link/").text
val quality =
Regex("\\d{3,4}\\.m3u8").findAll(m3uData).map { it.value }.toList()
quality.forEach {
callback.invoke(
ExtractorLink(
source = name,
name = name,
url = m3u.file.replace("video.m3u8", it),
referer = "https://gdriveplayer.link/",
quality = getQualityFromName("${it.replace(".m3u8", "")}p"),
isM3u8 = true
)
)
}
}
}
}
return true
}
}

View File

@ -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 MultiplexProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(MultiplexProvider())
}
}

View File

@ -1,27 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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",
"Movie",
"OVA",
)
iconUrl = "https://www.google.com/s2/favicons?domain=neonime.watch&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,178 +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 org.jsoup.nodes.Element
import java.util.*
class NeonimeProvider : MainAPI() {
override var mainUrl = "https://neonime.watch"
override var name = "Neonime"
override val hasQuickSearch = false
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) {
"Ended" -> ShowStatus.Completed
"OnGoing" -> ShowStatus.Ongoing
"Ongoing" -> ShowStatus.Ongoing
"In Production" -> ShowStatus.Ongoing
"Returning Series" -> ShowStatus.Ongoing
else -> ShowStatus.Completed
}
}
}
override val mainPage = mainPageOf(
"$mainUrl/episode/page/" to "Episode Terbaru",
"$mainUrl/tvshows/page/" to "Anime Terbaru",
"$mainUrl/movies/page/" to "Movie",
)
override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
val document = app.get(request.data + page).document
val home = document.select("tbody tr,div.item").mapNotNull {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
}
private fun getProperAnimeLink(uri: String): String {
return when {
uri.contains("/episode") -> {
val title = uri.substringAfter("$mainUrl/episode/").let { tt ->
val fixTitle = Regex("(.*)-\\d{1,2}x\\d+").find(tt)?.groupValues?.getOrNull(1).toString()
when {
!tt.contains("-season") && !tt.contains(Regex("-1x\\d+")) && !tt.contains("one-piece") -> "$fixTitle-season-${Regex("-(\\d{1,2})x\\d+").find(tt)?.groupValues?.getOrNull(1).toString()}"
tt.contains("-special") -> fixTitle.replace(Regex("-x\\d+"), "")
!fixTitle.contains("-subtitle-indonesia") -> "$fixTitle-subtitle-indonesia"
else -> fixTitle
}
}
// title = when {
// title.contains("youkoso-jitsuryoku") && !title.contains("-season") -> title.replace("-e-", "-e-tv-")
// else -> title
// }
"$mainUrl/tvshows/$title"
}
else -> uri
}
}
private fun Element.toSearchResult(): AnimeSearchResponse? {
val title = this.selectFirst("td.bb a")?.ownText() ?: this.selectFirst("h2")?.text() ?: return null
val href = getProperAnimeLink(fixUrl(this.select("a").attr("href")))
val posterUrl = fixUrl(this.select("img").attr("data-src"))
val epNum = this.selectFirst("td.bb span")?.text()?.let { eps ->
Regex("Episode\\s?([0-9]+)").find(eps)?.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 = app.get(link).document
return document.select("div.item.episode-home").mapNotNull {
val title = it.selectFirst("div.judul-anime > span")!!.text()
val poster = it.select("img").attr("data-src").toString().trim()
val episodes = it.selectFirst("div.fixyear > h2.text-center")!!
.text().replace(Regex("[^0-9]"), "").trim().toIntOrNull()
val tvType = getType(it.selectFirst("span.calidad2.episode")?.text().toString())
val href = getProperAnimeLink(fixUrl(it.selectFirst("a")!!.attr("href")))
newAnimeSearchResponse(title, href, tvType) {
this.posterUrl = poster
addSub(episodes)
}
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
if (url.contains("movie") || url.contains("live-action")) {
val mTitle = document.selectFirst(".sbox > .data > h1[itemprop = name]")?.text().toString().trim()
val mTrailer = document.selectFirst("div.youtube_id iframe")?.attr("data-wpfc-original-src")?.substringAfterLast("html#")?.let{ "https://www.youtube.com/embed/$it"}
return newMovieLoadResponse(name = mTitle, url = url, type = TvType.Movie, dataUrl = url) {
posterUrl = document.selectFirst(".sbox > .imagen > .fix > img[itemprop = image]")?.attr("data-src")
year = document.selectFirst("a[href*=release-year]")!!.text().toIntOrNull()
plot = document.select("div[itemprop = description]").text().trim()
rating = document.select("span[itemprop = ratingValue]").text().toIntOrNull()
tags = document.select("p.meta_dd > a").map { it.text() }
addTrailer(mTrailer)
}
}
else {
val title = document.select("h1[itemprop = name]").text().trim()
val trailer = document.selectFirst("div.youtube_id_tv iframe")?.attr("data-wpfc-original-src")?.substringAfterLast("html#")?.let{ "https://www.youtube.com/embed/$it"}
val episodes = document.select("ul.episodios > li").mapNotNull {
val header = it.selectFirst(".episodiotitle > a")?.ownText().toString()
val name = Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header
val link = fixUrl(it.selectFirst(".episodiotitle > a")!!.attr("href"))
Episode(link, name)
}.reversed()
return newAnimeLoadResponse(title, url, TvType.Anime) {
engName = title
posterUrl = document.selectFirst(".imagen > img")?.attr("data-src")
year = document.select("#info a[href*=\"-year/\"]").text().toIntOrNull()
addEpisodes(DubStatus.Subbed, episodes)
showStatus = getStatus(document.select("div.metadatac > span").last()!!.text().trim())
plot = document.select("div[itemprop = description] > p").text().trim()
tags = document.select("#info a[href*=\"-genre/\"]").map { it.text() }
addTrailer(trailer)
}
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val source = if(data.contains("movie") || data.contains("live-action")) {
app.get(data).document.select("#player2-1 > div[id*=div]").mapNotNull {
fixUrl(it.select("iframe").attr("data-src"))
}
} else {
app.get(data).document.select(".player2 > .embed2 > div[id*=player]").mapNotNull {
fixUrl(it.select("iframe").attr("data-src"))
}
}
source.apmap {
loadExtractor(it, data, subtitleCallback, callback)
}
return true
}
}

View File

@ -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 NeonimeProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(NeonimeProvider())
}
}

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -3,6 +3,7 @@ version = 1
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
// description = "Lorem Ipsum"

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=75.119.159.228&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,257 +0,0 @@
package com.lagradost
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
class NontonAnimeIDProvider : MainAPI() {
override var mainUrl = "https://75.119.159.228"
override var name = "NontonAnimeID"
override val hasQuickSearch = false
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 when {
t.contains("TV") -> TvType.Anime
t.contains("Movie") -> TvType.AnimeMovie
else -> TvType.OVA
}
}
fun getStatus(t: String): ShowStatus {
return when (t) {
"Finished Airing" -> ShowStatus.Completed
"Currently Airing" -> ShowStatus.Ongoing
else -> ShowStatus.Completed
}
}
}
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
val document = app.get(mainUrl).document
val homePageList = ArrayList<HomePageList>()
document.select("section#postbaru").forEach { block ->
val header = block.selectFirst("h2")!!.text().trim()
val animes = block.select("article.animeseries").map {
it.toSearchResult()
}
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
}
document.select("aside#sidebar_right > div:nth-child(4)").forEach { block ->
val header = block.selectFirst("h3")!!.ownText().trim()
val animes = block.select("li.fullwdth").map {
it.toSearchResultPopular()
}
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
}
return HomePageResponse(homePageList)
}
private fun getProperAnimeLink(uri: String): String {
return if (uri.contains("/anime/")) {
uri
} else {
var title = uri.substringAfter("$mainUrl/")
val fixTitle = Regex("(.*)-episode.*").find(title)?.groupValues?.getOrNull(1).toString()
title = when {
title.contains("utawarerumono-season-3") -> fixTitle.replace(
"season-3",
"futari-no-hakuoro"
)
title.contains("kingdom-season-4") -> fixTitle.replace("season-4", "4th-season")
title.contains("maou-sama-season-2") -> fixTitle.replace("season-2", "2")
title.contains("overlord-season-4") -> fixTitle.replace("season-4", "iv")
title.contains("kyoushitsu-e-season-2") -> fixTitle.replace(
"kyoushitsu-e-season-2",
"kyoushitsu-e-tv-2nd-season"
)
title.contains("season-2") -> fixTitle.replace("season-2", "2nd-season")
title.contains("season-3") -> fixTitle.replace("season-3", "3rd-season")
title.contains("movie") -> title.substringBefore("-movie")
else -> fixTitle
}
"$mainUrl/anime/$title"
}
}
private fun Element.toSearchResult(): AnimeSearchResponse {
val href = getProperAnimeLink(fixUrl(this.selectFirst("a")!!.attr("href")))
val title = this.selectFirst("h3.title")!!.text()
val posterUrl = fixUrl(this.select("img").attr("data-src"))
return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl
addDubStatus(dubExist = false, subExist = true)
}
}
private fun Element.toSearchResultPopular(): AnimeSearchResponse {
val href = getProperAnimeLink(fixUrl(this.selectFirst("a")!!.attr("href")))
val title = this.select("h4").text().trim()
val posterUrl = fixUrl(this.select("img").attr("data-src"))
return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl
addDubStatus(dubExist = false, subExist = true)
}
}
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/?s=$query"
val document = app.get(link).document
return document.select(".result > ul > li").mapNotNull {
val title = it.selectFirst("h2")!!.text().trim()
val poster = it.selectFirst("img")!!.attr("src")
val tvType = getType(
it.selectFirst(".boxinfores > span.typeseries")!!.text().toString()
)
val href = fixUrl(it.selectFirst("a")!!.attr("href"))
newAnimeSearchResponse(title, href, tvType) {
this.posterUrl = poster
addDubStatus(dubExist = false, subExist = true)
}
}
}
private data class EpResponse(
@JsonProperty("posts") val posts: String?,
@JsonProperty("max_page") val max_page: Int?,
@JsonProperty("found_posts") val found_posts: Int?,
@JsonProperty("content") val content: String
)
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val title = document.selectFirst("h1.entry-title.cs")!!.text().trim()
val poster = document.selectFirst(".poster > img")?.attr("data-src")
val tags = document.select(".tagline > a").map { it.text() }
val year = Regex("\\d, ([0-9]*)").find(
document.select(".bottomtitle > span:nth-child(5)").text()
)?.groupValues?.get(1)?.toIntOrNull()
val status = getStatus(
document.select("span.statusseries").text().trim()
)
val type = getType(document.select("span.typeseries").text().trim())
val rating = document.select("span.nilaiseries").text().trim().toIntOrNull()
val description = document.select(".entry-content.seriesdesc > p").text().trim()
val trailer = document.selectFirst("iframe#traileryt")?.attr("data-src")
val episodes = if (document.select("button.buttfilter").isNotEmpty()) {
val id = document.select("input[name=series_id]").attr("value")
val numEp =
document.selectFirst(".latestepisode > a")?.text()?.replace(Regex("[^0-9]"), "")
.toString()
Jsoup.parse(
app.post(
url = "$mainUrl/wp-admin/admin-ajax.php",
data = mapOf(
"misha_number_of_results" to numEp,
"misha_order_by" to "date-DESC",
"action" to "mishafilter",
"series_id" to id
)
).parsed<EpResponse>().content
).select("li").map {
val name = Regex("(Episode\\s?[0-9]+)").find(
it.selectFirst("a")?.text().toString()
)?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text()
val link = fixUrl(it.selectFirst("a")!!.attr("href"))
Episode(link, name)
}.reversed()
} else {
document.select("ul.misha_posts_wrap2 > li").map {
val name = Regex("(Episode\\s?[0-9]+)").find(
it.selectFirst("a")?.text().toString()
)?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text()
val link = it.select("a").attr("href")
Episode(link, name)
}.reversed()
}
val recommendations = document.select(".result > li").mapNotNull {
val epHref = it.selectFirst("a")!!.attr("href")
val epTitle = it.selectFirst("h3")!!.text()
val epPoster = it.select(".top > img").attr("data-src")
newAnimeSearchResponse(epTitle, epHref, TvType.Anime) {
this.posterUrl = epPoster
addDubStatus(dubExist = false, subExist = true)
}
}
return newAnimeLoadResponse(title, url, type) {
engName = title
posterUrl = poster
this.year = year
addEpisodes(DubStatus.Subbed, episodes)
showStatus = status
this.rating = rating
plot = description
addTrailer(trailer)
this.tags = tags
this.recommendations = recommendations
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val document = app.get(data).document
val sources = ArrayList<String>()
document.select(".container1 > ul > li:not(.boxtab)").apmap {
val dataPost = it.attr("data-post")
val dataNume = it.attr("data-nume")
val dataType = it.attr("data-type")
val iframe = app.post(
url = "$mainUrl/wp-admin/admin-ajax.php",
data = mapOf(
"action" to "player_ajax",
"post" to dataPost,
"nume" to dataNume,
"type" to dataType
),
referer = data,
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
).document.select("iframe").attr("src")
sources.add(fixUrl(iframe))
}
sources.apmap {
loadExtractor(it, "$mainUrl/", subtitleCallback, callback)
}
return true
}
}

View File

@ -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 NontonAnimeIDProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(NontonAnimeIDProvider())
}
}

View File

@ -3,6 +3,7 @@ version = 3
cloudstream {
language = "en"
// All of these properties are optional, you can safely remove them
description = "Uses TMDB"

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=65.108.132.145&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,203 +0,0 @@
package com.lagradost
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.utils.*
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import java.util.ArrayList
class OploverzProvider : MainAPI() {
override var mainUrl = "https://65.108.132.145"
override var name = "Oploverz"
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 when {
t.contains("TV") -> TvType.Anime
t.contains("Movie") -> TvType.AnimeMovie
else -> TvType.OVA
}
}
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 "Episode Terbaru",
"&status=&type=&order=latest" to "Anime Terbaru",
"&sub=&order=popular" to "Popular Anime",
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get("$mainUrl/anime/?page=$page${request.data}").document
val home = document.select("article[itemscope=itemscope]").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("-ova")) -> Regex("(.+)-episode").find(
title
)?.groupValues?.get(1).toString()
(title.contains("-ova")) -> Regex("(.+)-ova").find(title)?.groupValues?.get(1)
.toString()
(title.contains("-movie")) -> Regex("(.+)-subtitle").find(title)?.groupValues?.get(1)
.toString()
else -> Regex("(.+)-subtitle").find(title)?.groupValues?.get(1).toString()
.replace(Regex("-\\d+"), "")
}
when {
title.contains("overlord") -> {
title = title.replace("s", "season-")
}
title.contains("kaguya-sama") -> {
title = title.replace("s3", "ultra-romantic")
}
}
"$mainUrl/anime/$title"
}
}
private fun Element.toSearchResult(): AnimeSearchResponse? {
val href = getProperAnimeLink(this.selectFirst("a.tip")!!.attr("href"))
val title = this.selectFirst("h2[itemprop=headline]")?.text()?.trim() ?: return null
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
val type = getType(this.selectFirst(".eggtype, .typez")?.text()?.trim().toString())
return newAnimeSearchResponse(title, href, type) {
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(".tt")?.ownText()?.trim().toString()
val poster = fixUrlNull(it.selectFirst("img")?.attr("src"))
val tvType = getType(it.selectFirst(".typez")?.text().toString())
val href = fixUrl(it.selectFirst("a.tip")!!.attr("href"))
newAnimeSearchResponse(title, href, tvType) {
this.posterUrl = poster
addDubStatus(dubExist = false, subExist = true)
}
}
}
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 > 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 typeCheck =
when (document.select(".info-content > .spe > span:nth-child(5), .info-content > .spe > span")
.text().trim()) {
"OVA" -> "OVA"
"Movie" -> "Movie"
else -> "TV"
}
val type = getType(typeCheck)
val description = document.select(".entry-content > p").text().trim()
val trailer = document.selectFirst("a.trailerbutton")?.attr("href")
val episodes = document.select(".eplister > ul > li").map {
val header = it.select(".epl-title").text()
val name =
Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header
val link = fixUrl(it.select("a").attr("href"))
Episode(link, name)
}.reversed()
val recommendations =
document.select(".listupd > article[itemscope=itemscope]").mapNotNull { rec ->
val epTitle = rec.selectFirst(".tt")!!.ownText().trim()
val epPoster = rec.selectFirst("img")!!.attr("src")
val epType = getType(rec.selectFirst(".typez")?.text().toString())
val epHref = fixUrl(rec.selectFirst("a.tip")!!.attr("href"))
newAnimeSearchResponse(epTitle, epHref, epType) {
this.posterUrl = epPoster
addDubStatus(dubExist = false, subExist = true)
}
}
return newAnimeLoadResponse(title, url, type) {
engName = title
posterUrl = poster
this.year = year
addEpisodes(DubStatus.Subbed, episodes)
showStatus = status
plot = description
this.tags = tags
this.recommendations = recommendations
addTrailer(trailer)
}
}
data class Source(
@JsonProperty("play_url") val play_url: String,
@JsonProperty("format_id") val format_id: Int
)
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.apmap {
loadExtractor(it, data, subtitleCallback, callback)
}
return true
}
}

View File

@ -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 OploverzProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(OploverzProvider())
}
}

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=otakudesu.watch&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,204 +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.nodes.Element
import java.util.ArrayList
class OtakudesuProvider : MainAPI() {
override var mainUrl = "https://otakudesu.watch"
override var name = "Otakudesu"
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
}
}
}
override val mainPage = mainPageOf(
"$mainUrl/ongoing-anime/page/" to "Anime Ongoing",
"$mainUrl/complete-anime/page/" to "Anime Completed"
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get(request.data + page).document
val home = document.select("div.venz > ul > li").mapNotNull {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
}
private fun Element.toSearchResult(): AnimeSearchResponse? {
val title = this.selectFirst("h2.jdlflm")?.text()?.trim() ?: return null
val href = this.selectFirst("a")!!.attr("href")
val posterUrl = this.select("div.thumbz > img").attr("src").toString()
val epNum = this.selectFirst("div.epz")?.ownText()?.replace(Regex("[^0-9]"), "")?.trim()
?.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&post_type=anime"
val document = app.get(link).document
return document.select("ul.chivsrc > li").map {
val title = it.selectFirst("h2 > a")!!.ownText().trim()
val href = it.selectFirst("h2 > a")!!.attr("href")
val posterUrl = it.selectFirst("img")!!.attr("src").toString()
newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl
}
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val title = document.selectFirst("div.infozingle > p:nth-child(1) > span")?.ownText()
?.replace(":", "")?.trim().toString()
val poster = document.selectFirst("div.fotoanime > img")?.attr("src")
val tags = document.select("div.infozingle > p:nth-child(11) > span > a").map { it.text() }
val type = getType(
document.selectFirst("div.infozingle > p:nth-child(5) > span")?.ownText()
?.replace(":", "")?.trim().toString()
)
val year = Regex("\\d, ([0-9]*)").find(
document.select("div.infozingle > p:nth-child(9) > span").text()
)?.groupValues?.get(1)?.toIntOrNull()
val status = getStatus(
document.selectFirst("div.infozingle > p:nth-child(6) > span")!!.ownText()
.replace(":", "")
.trim()
)
val description = document.select("div.sinopc > p").text()
val episodes = document.select("div.episodelist")[1].select("ul > li").mapNotNull {
val name = Regex("(Episode\\s?[0-9]+)").find(
it.selectFirst("a")?.text().toString()
)?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text()
val link = fixUrl(it.selectFirst("a")!!.attr("href"))
Episode(link, name)
}.reversed()
val recommendations =
document.select("div.isi-recommend-anime-series > div.isi-konten").map {
val recName = it.selectFirst("span.judul-anime > a")!!.text()
val recHref = it.selectFirst("a")!!.attr("href")
val recPosterUrl = it.selectFirst("a > img")?.attr("src").toString()
newAnimeSearchResponse(recName, recHref, TvType.Anime) {
this.posterUrl = recPosterUrl
}
}
return newAnimeLoadResponse(title, url, type) {
engName = title
posterUrl = poster
this.year = year
addEpisodes(DubStatus.Subbed, episodes)
showStatus = status
plot = description
this.tags = tags
this.recommendations = recommendations
}
}
data class ResponseSources(
@JsonProperty("id") val id: String,
@JsonProperty("i") val i: String,
@JsonProperty("q") val q: String,
)
data class ResponseData(
@JsonProperty("data") val data: String
)
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val document = app.get(data).document
val scriptData = document.select("script").last()?.data()
val token = scriptData?.substringAfter("{action:\"")?.substringBefore("\"}").toString()
val nonce = app.post("$mainUrl/wp-admin/admin-ajax.php", data = mapOf("action" to token))
.parsed<ResponseData>().data
val action = scriptData?.substringAfter(",action:\"")?.substringBefore("\"}").toString()
val mirrorData = document.select("div.mirrorstream > ul > li").mapNotNull {
base64Decode(it.select("a").attr("data-content"))
}.toString()
tryParseJson<List<ResponseSources>>(mirrorData)?.apmap { res ->
val id = res.id
val i = res.i
val q = res.q
var sources = Jsoup.parse(
base64Decode(
app.post(
"${mainUrl}/wp-admin/admin-ajax.php", data = mapOf(
"id" to id,
"i" to i,
"q" to q,
"nonce" to nonce,
"action" to action
)
).parsed<ResponseData>().data
)
).select("iframe").attr("src")
if (sources.startsWith("https://desustream.me")) {
if (!sources.contains("/arcg/") && !sources.contains("/odchan/") && !sources.contains(
"/desudrive/"
)
) {
sources = app.get(sources).document.select("iframe").attr("src")
}
if (sources.startsWith("https://yourupload.com")) {
sources = sources.replace("//", "//www.")
}
}
loadExtractor(sources, data, subtitleCallback, callback)
}
return true
}
}

View File

@ -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 OtakudesuProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(OtakudesuProvider())
}
}

View File

@ -1,26 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=pelisflix.li&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,231 +0,0 @@
package com.lagradost
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor
class PelisflixProvider : MainAPI() {
override var mainUrl = "https://pelisflix.li"
override var name = "Pelisflix"
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/ver-peliculas-online-gratis-fullhdc3/", "Películas"),
Pair("$mainUrl/ver-series-online-gratis/", "Series"),
)
for (i in urls) {
try {
val soup = app.get(i.first).document
val home = soup.select("article.TPost.B").map {
val title = it.selectFirst("h2.title")!!.text()
val link = it.selectFirst("a")!!.attr("href")
TvSeriesSearchResponse(
title,
link,
this.name,
TvType.Movie,
it.selectFirst("figure img")!!.attr("data-src"),
null,
null,
)
}
items.add(HomePageList(i.second, 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 doc = app.get(url).document
return doc.select("article.TPost.B").map {
val href = it.selectFirst("a")!!.attr("href")
val poster = it.selectFirst("figure img")!!.attr("data-src")
val name = it.selectFirst("h2.title")!!.text()
val isMovie = href.contains("/pelicula/")
if (isMovie) {
MovieSearchResponse(
name,
href,
this.name,
TvType.Movie,
poster,
null
)
} else {
TvSeriesSearchResponse(
name,
href,
this.name,
TvType.TvSeries,
poster,
null,
null
)
}
}.toList()
}
override suspend fun load(url: String): LoadResponse? {
val type = if (url.contains("/pelicula/")) TvType.Movie else TvType.TvSeries
val document = app.get(url).document
val title = document.selectFirst("h1.Title")!!.text()
val descRegex = Regex("(.Recuerda.*Pelisflix.+)")
val descRegex2 = Regex("(Actualmente.*.)")
val descRegex3 = Regex("(.*Director:.*)")
val descRegex4 = Regex("(.*Actores:.*)")
val descRegex5 = Regex("(Ver.*(\\)|)((\\d+).))")
val descipt = document.selectFirst("div.Description")!!.text().replace(descRegex, "")
.replace(descRegex2, "").replace(descRegex3, "")
.replace(descRegex4, "").replace(descRegex5, "")
val desc2Regex = Regex("(G(e|é)nero:.*..)")
val descipt2 = document.selectFirst("div.Description")!!.text().replace(desc2Regex, "")
val rating =
document.selectFirst("div.rating-content button.like-mov span.vot_cl")?.text()
?.toFloatOrNull()
?.times(0)?.toInt()
val year = document.selectFirst("span.Date")?.text()
val duration =
if (type == TvType.Movie) document.selectFirst(".Container .Container span.Time")!!
.text() else null
val postercss = document.selectFirst("head").toString()
val posterRegex =
Regex("(\"og:image\" content=\"https:\\/\\/seriesflix.video\\/wp-content\\/uploads\\/(\\d+)\\/(\\d+)\\/?.*.jpg)")
val poster = try {
posterRegex.findAll(postercss).map {
it.value.replace("\"og:image\" content=\"", "")
}.toList().first()
} catch (e: Exception) {
document.select(".TPostBg").attr("src")
}
if (type == TvType.TvSeries) {
val list = ArrayList<Pair<Int, String>>()
document.select("main > section.SeasonBx > div > div.Title > a").forEach { element ->
val season = element.selectFirst("> span")?.text()?.toIntOrNull()
val href = element.attr("href")
if (season != null && season > 0 && !href.isNullOrBlank()) {
list.add(Pair(season, fixUrl(href)))
}
}
if (list.isEmpty()) throw ErrorLoadingException("No Seasons Found")
val episodeList = ArrayList<Episode>()
for ((seasonInt, seasonUrl) in list) {
val seasonDocument = app.get(seasonUrl).document
val episodes = seasonDocument.select("table > tbody > tr")
if (episodes.isNotEmpty()) {
episodes.forEach { episode ->
val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull()
val epthumb = episode.selectFirst("img")?.attr("src")
val aName = episode.selectFirst("> td.MvTbTtl > a")
val name = aName!!.text()
val href = aName.attr("href")
val date = episode.selectFirst("> td.MvTbTtl > span")?.text()
episodeList.add(
newEpisode(href) {
this.name = name
this.season = seasonInt
this.episode = epNum
this.posterUrl = fixUrlNull(epthumb)
addDate(date)
}
)
}
}
}
return TvSeriesLoadResponse(
title,
url,
this.name,
type,
episodeList,
fixUrlNull(poster),
year?.toIntOrNull(),
descipt2,
null,
rating
)
} else {
return newMovieLoadResponse(
title,
url,
type,
url
) {
posterUrl = fixUrlNull(poster)
this.year = year?.toIntOrNull()
this.plot = descipt
this.rating = rating
addDuration(duration)
}
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
app.get(data).document.select("li button.Button.sgty").forEach {
val movieID = it.attr("data-id")
val serverID = it.attr("data-key")
val type = if (data.contains("pelicula")) 1 else 2
val url =
"$mainUrl/?trembed=$serverID&trid=$movieID&trtype=$type" //This is to get the POST key value
val doc1 = app.get(url).document
doc1.select("div.Video iframe").apmap {
val iframe = it.attr("src")
val postkey = iframe.replace("/stream/index.php?h=", "") // this obtains
// djNIdHNCR2lKTGpnc3YwK3pyRCs3L2xkQmljSUZ4ai9ibTcza0JRODNMcmFIZ0hPejdlYW0yanJIL2prQ1JCZA POST KEY
app.post(
"https://pelisflix.li/stream/r.php",
headers = mapOf(
"Host" to "pelisflix.li",
"User-Agent" to USER_AGENT,
"Accept" to "ext/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",
"Sec-Fetch-User" to "?1",
"Pragma" to "no-cache",
"Cache-Control" to "no-cache",
"TE" to "trailers"
),
params = mapOf(Pair("h", postkey)),
data = mapOf(Pair("h", postkey)),
allowRedirects = false
).okhttpResponse.headers.values("location").apmap { link ->
val url1 = link.replace("#bu", "")
loadExtractor(url1, data, subtitleCallback, callback)
}
}
}
return true
}
}

View File

@ -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 PelisflixProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(PelisflixProvider())
}
}

View File

@ -1,27 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=phimmoichill.net&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,222 +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.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.*
import org.jsoup.nodes.Element
import java.net.URLDecoder
import java.util.ArrayList
class PhimmoichillProvider : MainAPI() {
override var mainUrl = "https://phimmoichill.net"
override var name = "Phimmoichill"
override val hasMainPage = true
override var lang = "vi"
override val hasDownloadSupport = true
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries,
TvType.Anime,
TvType.AsianDrama
)
override val mainPage = mainPageOf(
"$mainUrl/genre/phim-chieu-rap/page-" to "Phim Chiếu Rạp",
"$mainUrl/list/phim-le/page-" to "Phim Lẻ",
"$mainUrl/list/phim-bo/page-" to "Phim Bộ",
"$mainUrl/genre/phim-hoat-hinh/page-" to "Phim Hoạt Hình",
"$mainUrl/country/phim-han-quoc/page-" to "Phim Hàn Quốc",
"$mainUrl/country/phim-trung-quoc/page-" to "Phim Trung Quốc",
"$mainUrl/country/phim-thai-lan/page-" to "Phim Thái Lan",
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get(request.data + page).document
val home = document.select("li.item").mapNotNull {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
}
private fun decode(input: String): String? = URLDecoder.decode(input, "utf-8")
private fun Element.toSearchResult(): SearchResponse {
val title = this.selectFirst("p,h3")?.text()?.trim().toString()
val href = fixUrl(this.selectFirst("a")!!.attr("href"))
val posterUrl = decode(this.selectFirst("img")!!.attr("src").substringAfter("url="))
val temp = this.select("span.label").text()
return if (temp.contains(Regex("\\d"))) {
val episode = Regex("(\\((\\d+))|(\\s(\\d+))").find(temp)?.groupValues?.map { num ->
num.replace(Regex("\\(|\\s"), "")
}?.distinct()?.firstOrNull()?.toIntOrNull()
newAnimeSearchResponse(title, href, TvType.TvSeries) {
this.posterUrl = posterUrl
addSub(episode)
}
} else {
val quality =
temp.replace(Regex("(-.*)|(\\|.*)|(?i)(VietSub.*)|(?i)(Thuyết.*)"), "").trim()
newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl
addQuality(quality)
}
}
}
override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/tim-kiem/$query"
val document = app.get(link).document
return document.select("ul.list-film li").map {
it.toSearchResult()
}
}
override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document
val title = document.selectFirst("h1[itemprop=name]")?.text()?.trim().toString()
val link = document.select("ul.list-button li:last-child a").attr("href")
val poster = document.selectFirst("div.image img[itemprop=image]")?.attr("src")
val tags = document.select("ul.entry-meta.block-film li:nth-child(4) a").map { it.text() }
val year = document.select("ul.entry-meta.block-film li:nth-child(2) a").text().trim()
.toIntOrNull()
val tvType = if (document.select("div.latest-episode").isNotEmpty()
) TvType.TvSeries else TvType.Movie
val description = document.select("div#film-content-wrapper").text().trim()
val trailer =
document.select("div#trailer script").last()?.data()?.substringAfter("file: \"")
?.substringBefore("\",")
val rating =
document.select("ul.entry-meta.block-film li:nth-child(7) span").text().toRatingInt()
val actors = document.select("ul.entry-meta.block-film li:last-child a").map { it.text() }
val recommendations = document.select("ul#list-film-realted li.item").map {
it.toSearchResult()
}
return if (tvType == TvType.TvSeries) {
val docEpisodes = app.get(link).document
val episodes = docEpisodes.select("ul#list_episodes > li").map {
val href = it.select("a").attr("href")
val episode =
it.select("a").text().replace(Regex("[^0-9]"), "").trim().toIntOrNull()
val name = "Episode $episode"
Episode(
data = href,
name = name,
episode = episode,
)
}
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
} else {
newMovieLoadResponse(title, url, TvType.Movie, link) {
this.posterUrl = poster
this.year = year
this.plot = description
this.tags = tags
this.rating = rating
addActors(actors)
this.recommendations = recommendations
addTrailer(trailer)
}
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val document = app.get(data).document
val key = document.select("div#content script").mapNotNull { script ->
if (script.data().contains("filmInfo.episodeID =")) {
val id = script.data().substringAfter("filmInfo.episodeID = parseInt('")
.substringBefore("');")
app.post(
url = "$mainUrl/pmplayer.php",
data = mapOf("qcao" to id),
referer = data,
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
).text.substringAfterLast("iniPlayers(\"").substringBefore("\",")
} else {
null
}
}.first()
listOf(
Pair("https://so-trym.topphimmoi.org/hlspm/$key", "PMFAST"),
Pair("https://dash.megacdn.xyz/hlspm/$key", "PMHLS"),
Pair("https://dash.megacdn.xyz/dast/$key/index.m3u8", "PMBK")
).apmap { (link, source) ->
safeApiCall {
if (source == "PMBK") {
callback.invoke(
ExtractorLink(
source,
source,
link,
referer = "$mainUrl/",
quality = Qualities.P1080.value,
isM3u8 = true
)
)
} else {
val playList = app.get(link, referer = "$mainUrl/")
.parsedSafe<ResponseM3u>()?.main?.segments?.map { segment ->
PlayListItem(
segment.link,
(segment.du.toFloat() * 1_000_000).toLong()
)
}
callback.invoke(
ExtractorLinkPlayList(
source,
source,
playList ?: return@safeApiCall,
referer = "$mainUrl/",
quality = Qualities.P1080.value,
headers = mapOf(
// "If-None-Match" to "*",
"Origin" to mainUrl,
)
)
)
}
}
}
return true
}
data class Segment(
@JsonProperty("du") val du: String,
@JsonProperty("link") val link: String,
)
data class DataM3u(
@JsonProperty("segments") val segments: List<Segment>?,
)
data class ResponseM3u(
@JsonProperty("2048p") val main: DataM3u?,
)
}

View File

@ -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 PhimmoichillProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(PhimmoichillProvider())
}
}

View File

@ -1,25 +0,0 @@
// use an integer for version numbers
version = 1
cloudstream {
// 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=www.pinoy-hd.xyz&sz=24"
}

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -1,237 +0,0 @@
package com.lagradost
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor
class PinoyHDXyzProvider : MainAPI() {
override var name = "Pinoy-HD"
override var mainUrl = "https://www.pinoy-hd.xyz"
override var lang = "tl"
override val supportedTypes = setOf(TvType.AsianDrama)
override val hasDownloadSupport = true
override val hasMainPage = true
override val hasQuickSearch = false
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
val all = ArrayList<HomePageList>()
val document = app.get(mainUrl, referer = mainUrl).document
val mainbody = document.getElementsByTag("body")
mainbody.select("div.section-cotent.col-md-12.bordert").forEach { row ->
val title = row?.select("div.title-section.tt")?.text() ?: "<Row>"
val elements = row?.select("li.img_frame.preview-tumb7")?.mapNotNull {
// Get inner div from article
val innerBody = it?.selectFirst("a") ?: return@mapNotNull null
// Fetch details
val name = it.text().trim()
if (name.isBlank()) {
return@mapNotNull null
}
val link = innerBody.attr("href") ?: return@mapNotNull null
val image = fixUrlNull(innerBody.select("img").attr("src"))
//Log.i(this.name, "Result => (innerBody, image) ${innerBody} / ${image}")
// Get Year from Link
val rex = Regex("_(\\d+)_")
val year = rex.find(link)?.value?.replace("_", "")?.toIntOrNull()
//Log.i(this.name, "Result => (yearRes, year) ${yearRes} / ${year}")
MovieSearchResponse(
name = name,
url = link,
apiName = this.name,
type = TvType.Movie,
posterUrl = image,
year = year
)
}?.distinctBy { c -> c.url } ?: listOf()
// Add to Homepage
if (elements.isNotEmpty()) {
all.add(
HomePageList(
title, elements
)
)
}
}
return HomePageResponse(all)
}
override suspend fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/search/?q=${query.replace(" ", "+")}"
val document = app.get(url).document.select("div.portfolio-thumb")
return document.mapNotNull {
if (it == null) {
return@mapNotNull null
}
val link = it.selectFirst("a")?.attr("href") ?: return@mapNotNull null
val title = it.text() ?: ""
val year = null
val image = null // site provides no image on search page
MovieSearchResponse(
name = title,
url = link,
apiName = this.name,
type = TvType.Movie,
posterUrl = image,
year = year
)
}.distinctBy { c -> c.url }
}
override suspend fun load(url: String): LoadResponse {
val doc = app.get(url).document
val body = doc.getElementsByTag("body")
val inner = body.select("div.info")
// Video links
val listOfLinks: MutableList<String> = mutableListOf()
// Video details
var title = ""
var year: Int? = null
var tags: List<String>? = null
val poster = fixUrlNull(inner.select("div.portfolio-tumb.ph-link > img").attr("src"))
//Log.i(this.name, "Result => (imgLinkCode) ${imgLinkCode}")
inner.select("table").select("tr").forEach {
val td = it?.select("td") ?: return@forEach
val caption = td[0].text().lowercase()
//Log.i(this.name, "Result => (caption) $caption")
when (caption) {
"name" -> {
title = td[1].text()
}
"year" -> {
var yearRes = td[1].toString()
year = if (yearRes.isNotBlank()) {
if (yearRes.contains("var year =")) {
yearRes =
yearRes.substring(yearRes.indexOf("var year =") + "var year =".length)
//Log.i(this.name, "Result => (yearRes) $yearRes")
yearRes = yearRes.substring(0, yearRes.indexOf(';'))
.trim().removeSurrounding("'")
}
yearRes.toIntOrNull()
} else {
null
}
}
"genre" -> {
tags = td[1].select("a").mapNotNull { tag ->
tag?.text()?.trim() ?: return@mapNotNull null
}.filter { a -> a.isNotBlank() }
}
}
}
var descript = body.select("div.eText").text()
if (!descript.isNullOrEmpty()) {
try {
descript = "(undefined_x_Polus+[.\\d+])".toRegex().replace(descript, "")
descript = "(_x_Polus+[.\\d+])".toRegex().replace(descript, "")
descript = descript.trim().removeSuffix("undefined").trim()
} catch (e: java.lang.Exception) {
}
}
// Add links hidden in description
listOfLinks.addAll(fetchUrls(descript))
listOfLinks.forEach { link ->
//Log.i(this.name, "Result => (hidden link) $link")
descript = descript.replace(link, "")
}
// Try looking for episodes, for series
val episodeList = ArrayList<Episode>()
val bodyText = body.select("div.section-cotent1.col-md-12").select("section")
.select("script").toString()
//Log.i(this.name, "Result => (bodyText) ${bodyText}")
"(?<=ses=\\(')(.*)(?='\\).split)".toRegex().find(bodyText)?.groupValues?.get(0).let {
if (!it.isNullOrEmpty()) {
var count = 0
it.split(", ").forEach { ep ->
count++
val listEpStream = listOf(ep.trim()).toJson()
//Log.i(this.name, "Result => (ep $count) $listEpStream")
episodeList.add(
Episode(
name = null,
season = null,
episode = count,
data = listEpStream,
posterUrl = null,
date = null
)
)
}
}
}
if (episodeList.size > 0) {
return TvSeriesLoadResponse(
name = title,
url = url,
apiName = this.name,
type = TvType.AsianDrama,
episodes = episodeList,
posterUrl = poster,
year = year,
plot = descript,
tags = tags
)
}
// Video links for Movie
body.select("div.tabcontent > iframe").forEach {
val linkMain = it?.attr("src")
if (!linkMain.isNullOrEmpty()) {
listOfLinks.add(linkMain)
//Log.i(this.name, "Result => (linkMain) $linkMain")
}
}
body.select("div.tabcontent.hide > iframe").forEach {
val linkMain = it?.attr("src")
if (!linkMain.isNullOrEmpty()) {
listOfLinks.add(linkMain)
//Log.i(this.name, "Result => (linkMain hide) $linkMain")
}
}
val extraLinks = body.select("div.tabcontent.hide").text()
listOfLinks.addAll(fetchUrls(extraLinks))
val streamLinks = listOfLinks.distinct().toJson()
//Log.i(this.name, "Result => (streamLinks) streamLinks")
return MovieLoadResponse(
name = title,
url = url,
apiName = this.name,
type = TvType.Movie,
dataUrl = streamLinks,
posterUrl = poster,
year = year,
plot = descript,
tags = tags
)
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
var count = 0
parseJson<List<String>>(data).forEach { item ->
val url = item.trim()
if (url.isNotBlank()) {
if (loadExtractor(url, mainUrl, subtitleCallback, callback)) {
count++
}
}
}
return count > 0
}
}

View File

@ -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 PinoyHDXyzProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(PinoyHDXyzProvider())
}
}

Some files were not shown because too many files have changed in this diff Show More