Added Inf home to some providers and new providers (#1377)

* The Boys!!

* Prikitieww...
This commit is contained in:
Hexated 2022-08-02 20:17:43 +07:00 committed by GitHub
parent c5406acc1e
commit df509dfe1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 938 additions and 477 deletions

View file

@ -109,7 +109,8 @@ object APIHolder {
PhimmoichillProvider(), PhimmoichillProvider(),
HDrezkaProvider(), HDrezkaProvider(),
YomoviesProvider(), YomoviesProvider(),
DubokuProvider(),
KisskhProvider(),
// Metadata providers // Metadata providers
//TmdbProvider(), //TmdbProvider(),
@ -148,6 +149,7 @@ object APIHolder {
AnimeIndoProvider(), AnimeIndoProvider(),
AnimeSailProvider(), AnimeSailProvider(),
TocanimeProvider(), TocanimeProvider(),
WcofunProvider(),
//MultiAnimeProvider(), //MultiAnimeProvider(),
NginxProvider(), NginxProvider(),
OlgplyProvider(), OlgplyProvider(),

View file

@ -62,20 +62,20 @@ class AnimeIndoProvider : MainAPI() {
} }
} }
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = request(mainUrl).document "$mainUrl/anime-terbaru/page/" to "Anime Terbaru",
"$mainUrl/donghua-terbaru/page/" to "Donghua Terbaru"
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select("div.widget_senction").forEach { block -> request: MainPageRequest
val header = block.selectFirst("div.widget-title > h3")!!.text().trim() ): HomePageResponse {
val items = block.select("div.post-show > article").map { val document = request(request.data + page).document
val home = document.select("div.post-show > article").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun getProperAnimeLink(uri: String): String { private fun getProperAnimeLink(uri: String): String {
@ -96,8 +96,8 @@ class AnimeIndoProvider : MainAPI() {
} }
} }
private fun Element.toSearchResult(): AnimeSearchResponse { private fun Element.toSearchResult(): AnimeSearchResponse? {
val title = this.selectFirst("div.title")!!.text().trim() val title = this.selectFirst("div.title")?.text()?.trim() ?: return null
val href = getProperAnimeLink(this.selectFirst("a")!!.attr("href")) val href = getProperAnimeLink(this.selectFirst("a")!!.attr("href"))
val posterUrl = this.select("img[itemprop=image]").attr("src").toString() val posterUrl = this.select("img[itemprop=image]").attr("src").toString()
val type = getType(this.select("div.type").text().trim()) val type = getType(this.select("div.type").text().trim())

View file

@ -47,20 +47,18 @@ class AnimeSailProvider : MainAPI() {
) )
} }
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 { override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
val document = request(mainUrl).document val document = request(request.data + page).document
val home = document.select("article").map {
val homePageList = ArrayList<HomePageList>()
document.select(".bixbox").forEach { block ->
val header = block.select(".releases > h3").text().trim()
val animes = block.select("article").map {
it.toSearchResult() it.toSearchResult()
} }
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun getProperAnimeLink(uri: String): String { private fun getProperAnimeLink(uri: String): String {

View file

@ -3,7 +3,6 @@ package com.lagradost.cloudstream3.animeproviders
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
@ -41,35 +40,31 @@ class GomunimeProvider : MainAPI() {
} }
} }
private data class Response( override val mainPage = mainPageOf(
@JsonProperty("status") val status: Boolean, "e" to "Episode Baru",
@JsonProperty("html") val html: String "c" to "Completed",
"la" to "Live Action",
"t" to "Trending"
) )
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override suspend fun getMainPage(
val urls = listOf( page: Int,
Pair("e", "Episode Baru"), request: MainPageRequest
Pair("c", "Completed"), ): HomePageResponse {
Pair("la", "Live Action"),
Pair("t", "Trending"),
)
val items = ArrayList<HomePageList>()
for ((payload, name) in urls) {
try {
val home = Jsoup.parse( val home = Jsoup.parse(
parseJson<Response>( (app.post(
app.post(
url = "$mainUrl/wp-admin/admin-ajax.php/wp-admin/admin-ajax.php", url = "$mainUrl/wp-admin/admin-ajax.php/wp-admin/admin-ajax.php",
headers = mapOf("Referer" to mainUrl), headers = mapOf("Referer" to mainUrl),
data = mapOf("action" to "home_ajax", "fungsi" to payload, "pag" to "1") data = mapOf(
).text "action" to "home_ajax",
).html "fungsi" to request.data,
).select("li").map { "pag" to "$page"
val title = it.selectFirst("a.name")!!.text().trim() )
).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 href = getProperAnimeLink(it.selectFirst("a")!!.attr("href"))
val posterUrl = it.selectFirst("img")!!.attr("src") val posterUrl = it.selectFirst("img")?.attr("src")
val type = getType(it.selectFirst(".taglist > span")!!.text().trim()) val type = getType(it.selectFirst(".taglist > span")!!.text().trim())
val epNum = it.select(".tag.ep").text().replace(Regex("[^0-9]"), "").trim() val epNum = it.select(".tag.ep").text().replace(Regex("[^0-9]"), "").trim()
.toIntOrNull() .toIntOrNull()
@ -78,14 +73,8 @@ class GomunimeProvider : MainAPI() {
addSub(epNum) addSub(epNum)
} }
} }
items.add(HomePageList(name, home))
} catch (e: Exception) {
logError(e)
}
}
if (items.size <= 0) throw ErrorLoadingException() return newHomePageResponse(request.name, home)
return HomePageResponse(items)
} }
private fun getProperAnimeLink(uri: String): String { private fun getProperAnimeLink(uri: String): String {
@ -119,14 +108,6 @@ class GomunimeProvider : MainAPI() {
} }
} }
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?
)
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document val document = app.get(url).document
@ -164,12 +145,6 @@ class GomunimeProvider : MainAPI() {
} }
} }
data class MobiSource(
@JsonProperty("file") val file: String,
@JsonProperty("label") val label: String,
@JsonProperty("type") val type: String
)
override suspend fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
isCasting: Boolean, isCasting: Boolean,
@ -234,4 +209,24 @@ class GomunimeProvider : MainAPI() {
return true 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

@ -2,11 +2,9 @@ package com.lagradost.cloudstream3.animeproviders
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import com.lagradost.cloudstream3.network.DdosGuardKiller
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.*
class KuramanimeProvider : MainAPI() { class KuramanimeProvider : MainAPI() {
override var mainUrl = "https://kuramanime.com" override var mainUrl = "https://kuramanime.com"
@ -38,28 +36,24 @@ class KuramanimeProvider : MainAPI() {
} }
} }
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "$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",
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get(request.data + page).document
document.select("div.trending__product").forEach { block -> val home = document.select("div.col-lg-4.col-md-6.col-sm-6").mapNotNull {
val header = block.selectFirst("h4")?.text().toString()
val animes = block.select("div.col-lg-4.col-md-6.col-sm-6").map {
it.toSearchResult() it.toSearchResult()
} }
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
}
document.select("div.product__sidebar__view").forEach { block -> return newHomePageResponse(request.name, home)
val header = block.selectFirst("h5")?.text().toString()
val animes = block.select("div.product__sidebar__comment__item").map {
it.toSearchResultView()
}
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
}
return HomePageResponse(homePageList)
} }
private fun getProperAnimeLink(uri: String): String { private fun getProperAnimeLink(uri: String): String {
@ -70,9 +64,9 @@ class KuramanimeProvider : MainAPI() {
} }
} }
private fun Element.toSearchResult(): AnimeSearchResponse { private fun Element.toSearchResult(): AnimeSearchResponse? {
val href = getProperAnimeLink(fixUrl(this.selectFirst("a")!!.attr("href"))) val href = getProperAnimeLink(fixUrl(this.selectFirst("a")!!.attr("href")))
val title = this.selectFirst("h5 a")?.text().toString() val title = this.selectFirst("h5 a")?.text() ?: return null
val posterUrl = fixUrl(this.select("div.product__item__pic.set-bg").attr("data-setbg")) val posterUrl = fixUrl(this.select("div.product__item__pic.set-bg").attr("data-setbg"))
val episode = Regex("([0-9*])\\s?/").find( val episode = Regex("([0-9*])\\s?/").find(
this.select("div.ep span").text() this.select("div.ep span").text()
@ -85,23 +79,6 @@ class KuramanimeProvider : MainAPI() {
} }
private fun Element.toSearchResultView(): AnimeSearchResponse {
val href = getProperAnimeLink(fixUrl(this.selectFirst("a")?.attr("href").toString()))
val title = this.selectFirst("h5")?.text()?.trim().toString()
val posterUrl = fixUrlNull(
this.selectFirst("div.product__sidebar__comment__item__pic.set-bg")?.attr("data-setbg")
)
val episode =
this.selectFirst("h5")?.nextElementSibling()?.text()?.replace(Regex("[^0-9]"), "")
?.toIntOrNull()
return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl
addSub(episode)
}
}
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/anime?search=$query&order_by=oldest" val link = "$mainUrl/anime?search=$query&order_by=oldest"
val document = app.get(link).document val document = app.get(link).document

View file

@ -39,20 +39,23 @@ class KuronimeProvider : MainAPI() {
} }
} }
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "$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",
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select(".bixbox").forEach { block -> request: MainPageRequest
val header = block.select(".releases > h3").text().trim() ): HomePageResponse {
val animes = block.select("article").map { val document = app.get(request.data + page).document
val home = document.select("article").map {
it.toSearchResult() it.toSearchResult()
} }
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun getProperAnimeLink(uri: String): String { private fun getProperAnimeLink(uri: String): String {
@ -77,7 +80,10 @@ class KuronimeProvider : MainAPI() {
private fun Element.toSearchResult(): AnimeSearchResponse { private fun Element.toSearchResult(): AnimeSearchResponse {
val href = getProperAnimeLink(fixUrlNull(this.selectFirst("a")?.attr("href")).toString()) val href = getProperAnimeLink(fixUrlNull(this.selectFirst("a")?.attr("href")).toString())
val title = this.select(".bsuxtt, .tt > h4").text().trim() 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 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 epNum = this.select(".ep").text().replace(Regex("[^0-9]"), "").trim().toIntOrNull()
val tvType = getType(this.selectFirst(".bt > span")?.text().toString()) val tvType = getType(this.selectFirst(".bt > span")?.text().toString())
return newAnimeSearchResponse(title, href, tvType) { return newAnimeSearchResponse(title, href, tvType) {
@ -117,7 +123,8 @@ class KuronimeProvider : MainAPI() {
val episodes = document.select("div.bixbox.bxcl > ul > li").map { val episodes = document.select("div.bixbox.bxcl > ul > li").map {
val name = it.selectFirst("a")?.text()?.trim() val name = it.selectFirst("a")?.text()?.trim()
val episode = it.selectFirst("a")?.text()?.trim()?.replace("Episode", "")?.trim()?.toIntOrNull() val episode =
it.selectFirst("a")?.text()?.trim()?.replace("Episode", "")?.trim()?.toIntOrNull()
val link = it.selectFirst("a")!!.attr("href") val link = it.selectFirst("a")!!.attr("href")
Episode(link, name = name, episode = episode) Episode(link, name = name, episode = episode)
}.reversed() }.reversed()

View file

@ -40,20 +40,18 @@ class NeonimeProvider : MainAPI() {
} }
} }
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 { override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
val document = app.get(mainUrl).document val document = app.get(request.data + page).document
val home = document.select("tbody tr,div.item").mapNotNull {
val homePageList = ArrayList<HomePageList>()
document.select("div.item_1.items,div#slid01").forEach { block ->
val header = block.previousElementSibling()?.select("h1")?.text() ?: block.selectFirst("h3")?.text().toString()
val animes = block.select("div.item").map {
it.toSearchResult() it.toSearchResult()
} }
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun getProperAnimeLink(uri: String): String { private fun getProperAnimeLink(uri: String): String {
@ -80,11 +78,13 @@ class NeonimeProvider : MainAPI() {
} }
} }
private fun Element.toSearchResult(): AnimeSearchResponse { 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 href = getProperAnimeLink(fixUrl(this.select("a").attr("href")))
val title = this.select("span.tt.title-episode,h2.title-episode-movie,span.ttps").text()
val posterUrl = fixUrl(this.select("img").attr("data-src")) val posterUrl = fixUrl(this.select("img").attr("data-src"))
val epNum = this.select(".fixyear > h2.text-center").text().replace(Regex("[^0-9]"), "").trim().toIntOrNull() 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) { return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl this.posterUrl = posterUrl

View file

@ -228,7 +228,7 @@ class NontonAnimeIDProvider : MainAPI() {
val document = app.get(data).document val document = app.get(data).document
val sources = ArrayList<String>() val sources = ArrayList<String>()
document.select(".container1 > ul > li").apmap { document.select(".container1 > ul > li:not(.boxtab)").apmap {
val dataPost = it.attr("data-post") val dataPost = it.attr("data-post")
val dataNume = it.attr("data-nume") val dataNume = it.attr("data-nume")
val dataType = it.attr("data-type") val dataType = it.attr("data-type")
@ -240,7 +240,9 @@ class NontonAnimeIDProvider : MainAPI() {
"post" to dataPost, "post" to dataPost,
"nume" to dataNume, "nume" to dataNume,
"type" to dataType "type" to dataType
) ),
referer = data,
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
).document.select("iframe").attr("src") ).document.select("iframe").attr("src")
sources.add(fixUrl(iframe)) sources.add(fixUrl(iframe))

View file

@ -40,20 +40,21 @@ class OploverzProvider : MainAPI() {
} }
} }
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "&status=&type=&order=update" to "Episode Terbaru",
"&status=&type=&order=latest" to "Anime Terbaru",
"&sub=&order=popular" to "Popular Anime",
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select(".bixbox.bbnofrm").forEach { block -> request: MainPageRequest
val header = block.selectFirst("h3")!!.text().trim() ): HomePageResponse {
val animes = block.select("article[itemscope=itemscope]").map { val document = app.get("$mainUrl/anime/?page=$page${request.data}").document
val home = document.select("article[itemscope=itemscope]").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun getProperAnimeLink(uri: String): String { private fun getProperAnimeLink(uri: String): String {
@ -68,7 +69,8 @@ class OploverzProvider : MainAPI() {
)?.groupValues?.get(1).toString() )?.groupValues?.get(1).toString()
(title.contains("-ova")) -> Regex("(.+)-ova").find(title)?.groupValues?.get(1) (title.contains("-ova")) -> Regex("(.+)-ova").find(title)?.groupValues?.get(1)
.toString() .toString()
(title.contains("-movie")) -> Regex("(.+)-subtitle").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() else -> Regex("(.+)-subtitle").find(title)?.groupValues?.get(1).toString()
.replace(Regex("-\\d+"), "") .replace(Regex("-\\d+"), "")
} }
@ -87,16 +89,14 @@ class OploverzProvider : MainAPI() {
} }
private fun Element.toSearchResult(): AnimeSearchResponse { private fun Element.toSearchResult(): AnimeSearchResponse? {
val href = getProperAnimeLink(this.selectFirst("a.tip")!!.attr("href")) val href = getProperAnimeLink(this.selectFirst("a.tip")!!.attr("href"))
val title = this.selectFirst("h2[itemprop=headline]")?.text()?.trim() ?: "" val title = this.selectFirst("h2[itemprop=headline]")?.text()?.trim() ?: return null
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
val type = getType(this.selectFirst(".eggtype, .typez")?.text()?.trim().toString()) val type = getType(this.selectFirst(".eggtype, .typez")?.text()?.trim().toString())
val epNum = this.selectFirst(".eggepisode, span.epx")?.text()?.replace(Regex("[^0-9]"), "")?.trim()?.toIntOrNull()
return newAnimeSearchResponse(title, href, type) { return newAnimeSearchResponse(title, href, type) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
addSub(epNum)
} }
} }
@ -144,7 +144,8 @@ class OploverzProvider : MainAPI() {
val episodes = document.select(".eplister > ul > li").map { val episodes = document.select(".eplister > ul > li").map {
val header = it.select(".epl-title").text() val header = it.select(".epl-title").text()
val name = Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header val name =
Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header
val link = fixUrl(it.select("a").attr("href")) val link = fixUrl(it.select("a").attr("href"))
Episode(link, name) Episode(link, name)
}.reversed() }.reversed()

View file

@ -7,6 +7,7 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.ArrayList
class OtakudesuProvider : MainAPI() { class OtakudesuProvider : MainAPI() {
override var mainUrl = "https://otakudesu.watch" override var mainUrl = "https://otakudesu.watch"
@ -37,24 +38,24 @@ class OtakudesuProvider : MainAPI() {
} }
} }
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "$mainUrl/ongoing-anime/page/" to "Anime Ongoing",
"$mainUrl/complete-anime/page/" to "Anime Completed"
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select("div.rseries").forEach { block -> request: MainPageRequest
val header = block.selectFirst("div.rvad > h1")!!.text().trim() ): HomePageResponse {
val items = block.select("div.venz > ul > li").map { val document = app.get(request.data + page).document
val home = document.select("div.venz > ul > li").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items)) return newHomePageResponse(request.name, home)
} }
return HomePageResponse(homePageList) private fun Element.toSearchResult(): AnimeSearchResponse? {
} val title = this.selectFirst("h2.jdlflm")?.text()?.trim() ?: return null
private fun Element.toSearchResult(): AnimeSearchResponse {
val title = this.selectFirst("h2.jdlflm")!!.text().trim()
val href = this.selectFirst("a")!!.attr("href") val href = this.selectFirst("a")!!.attr("href")
val posterUrl = this.select("div.thumbz > img").attr("src").toString() val posterUrl = this.select("div.thumbz > img").attr("src").toString()
val epNum = this.selectFirst("div.epz")?.ownText()?.replace(Regex("[^0-9]"), "")?.trim() val epNum = this.selectFirst("div.epz")?.ownText()?.replace(Regex("[^0-9]"), "")?.trim()
@ -103,7 +104,9 @@ class OtakudesuProvider : MainAPI() {
val description = document.select("div.sinopc > p").text() val description = document.select("div.sinopc > p").text()
val episodes = document.select("div.episodelist")[1].select("ul > li").mapNotNull { 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 name = Regex("(Episode\\s?[0-9]+)").find(
it.selectFirst("a")?.text().toString()
)?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text()
val link = fixUrl(it.selectFirst("a")!!.attr("href")) val link = fixUrl(it.selectFirst("a")!!.attr("href"))
Episode(link, name) Episode(link, name)
}.reversed() }.reversed()
@ -180,7 +183,10 @@ class OtakudesuProvider : MainAPI() {
).select("iframe").attr("src") ).select("iframe").attr("src")
if (sources.startsWith("https://desustream.me")) { if (sources.startsWith("https://desustream.me")) {
if (!sources.contains("/arcg/") && !sources.contains("/odchan/") && !sources.contains("/desudrive/")) { if (!sources.contains("/arcg/") && !sources.contains("/odchan/") && !sources.contains(
"/desudrive/"
)
) {
sources = app.get(sources).document.select("iframe").attr("src") sources = app.get(sources).document.select("iframe").attr("src")
} }
if (sources.startsWith("https://yourupload.com")) { if (sources.startsWith("https://yourupload.com")) {

View file

@ -0,0 +1,172 @@
package com.lagradost.cloudstream3.animeproviders
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
class WcofunProvider : MainAPI() {
override var mainUrl = "https://www.wcofun.com"
override var name = "WCO Fun"
override val hasMainPage = true
override val hasDownloadSupport = true
override val supportedTypes = setOf(
TvType.Anime,
TvType.AnimeMovie,
TvType.OVA
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val document = app.get(mainUrl).document
val homePageList = ArrayList<HomePageList>()
document.select("div#sidebar_right,div#sidebar_right2").forEach { block ->
val header = block.previousElementSibling()?.ownText() ?: return@forEach
val animes = block.select("ul.items li").mapNotNull {
it.toSearchResult()
}
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/")
title = when {
(title.contains(Regex("-season-[0-9]+-episode"))) && title.contains("-dubbed") -> title.substringBefore("-season")
(title.contains(Regex("-season-[0-9]+-episode"))) && title.contains("-subbed") -> title.replace(Regex("-season-[0-9]+-episode-[0-9]+"), "")
title.contains("-subbed") -> title.replace(Regex("-episode-[0-9]+"), "")
title.contains("-dubbed") -> title.substringBefore("-episode")
else -> title
}
"$mainUrl/anime/$title"
}
}
private fun Element.toSearchResult(): AnimeSearchResponse? {
val header = this.selectFirst("div.recent-release-episodes a")?.text()
val title = header?.trim() ?: return null
val href = getProperAnimeLink(this.selectFirst("a")!!.attr("href"))
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
val epNum = header.let { eps ->
Regex("Episode\\s?([0-9]+)").find(eps)?.groupValues?.getOrNull(1)?.toIntOrNull()
}
val isDub = header.contains("Dubbed")
val isSub = header.contains("Subbed")
return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl
addDubStatus(isDub, isSub, epNum, epNum)
}
}
override suspend fun search(query: String): List<SearchResponse> {
val document = app.post(
"$mainUrl/search",
referer = mainUrl,
data = mapOf("catara" to query, "konuara" to "series")
).document
return document.select("div#sidebar_right2 li").mapNotNull {
it.toSearchResult()
}
}
override suspend fun load(url: String): LoadResponse? {
val document = app.get(url).document
val title = document.selectFirst("div.h1-tag a")?.text() ?: return null
val eps = document.select("div#sidebar_right3 div.cat-eps")
val type = if (eps.size == 1 || eps.first()?.text()
?.contains(Regex("Episode\\s?[0-9]+")) != true
) TvType.AnimeMovie else TvType.Anime
val episodes = eps.map {
val name = it.select("a").text()
val link = it.selectFirst("a")!!.attr("href")
Episode(link, name = name)
}.reversed()
return newAnimeLoadResponse(title, url, type) {
posterUrl = fixUrlNull(document.selectFirst("img.img5")?.attr("src"))
addEpisodes(DubStatus.Subbed, episodes)
plot = document.select("div#sidebar_cat > p").text()
this.tags = document.select("div#sidebar_cat a").map { it.text() }
}
}
private suspend fun getIframe(url: String): String? {
val document = app.get(url).document
val scriptData =
document.select("script").find { it.data().contains("= \"\";") }?.data() ?: return null
val subtractionNumber =
Regex("""(?<=\.replace\(/\\D/g,''\)\) - )\d+""").find(scriptData)?.value?.toInt()
?: return null
val html = Regex("""(?<=\["|, ").+?(?=")""").findAll(scriptData).map {
val number = base64Decode(it.value).replace(Regex("\\D"), "").toInt()
(number - subtractionNumber).toChar()
}.joinToString("")
return Jsoup.parse(html).select("iframe").attr("src").let { fixUrl(it) }
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
getIframe(data)?.let { iframe ->
val link = app.get(iframe, referer = data).text.let {
fixUrlNull(
Regex("\"(/inc/embed/getvidlink.php.*)\"").find(it)?.groupValues?.getOrNull(
1
)
)
}
app.get(
link ?: return@let,
referer = iframe,
headers = mapOf("x-requested-with" to "XMLHttpRequest")
).parsedSafe<Sources>()?.let {
listOf(
Pair(it.hd, "HD"),
Pair(it.enc, "SD")
).map { source ->
suspendSafeApiCall {
callback.invoke(
ExtractorLink(
"${this.name} ${source.second}",
"${this.name} ${source.second}",
"${it.server}/getvid?evid=${source.first}",
mainUrl,
if (source.second == "HD") Qualities.P720.value else Qualities.P480.value
)
)
}
}
}
}
return true
}
data class Sources(
@JsonProperty("enc") val enc: String?,
@JsonProperty("server") val server: String?,
@JsonProperty("cdn") val cdn: String?,
@JsonProperty("hd") val hd: String?,
)
}

View file

@ -7,6 +7,10 @@ import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper import com.lagradost.cloudstream3.utils.M3u8Helper
class Ssbstream : StreamSB() {
override var mainUrl = "https://ssbstream.net"
}
class SBfull : StreamSB() { class SBfull : StreamSB() {
override var mainUrl = "https://sbfull.com" override var mainUrl = "https://sbfull.com"
} }

View file

@ -8,7 +8,6 @@ import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.ArrayList
class DramaidProvider : MainAPI() { class DramaidProvider : MainAPI() {
override var mainUrl = "https://185.224.83.103" override var mainUrl = "https://185.224.83.103"
@ -30,20 +29,18 @@ class DramaidProvider : MainAPI() {
} }
} }
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 { override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
val document = app.get(mainUrl).document val document = app.get("$mainUrl/series/?page=$page${request.data}").document
val home = document.select("article[itemscope=itemscope]").mapNotNull {
val homePageList = ArrayList<HomePageList>()
document.select(".bixbox").forEach { block ->
val header = block.selectFirst(".releases > h3")!!.text().trim()
val dramas = block.select("article[itemscope=itemscope]").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
if (dramas.isNotEmpty()) homePageList.add(HomePageList(header, dramas)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun getProperDramaLink(uri: String): String { private fun getProperDramaLink(uri: String): String {
@ -55,10 +52,10 @@ class DramaidProvider : MainAPI() {
} }
} }
private fun Element.toSearchResult(): SearchResponse { private fun Element.toSearchResult(): SearchResponse? {
val href = getProperDramaLink(this.selectFirst("a.tip")!!.attr("href")) val href = getProperDramaLink(this.selectFirst("a.tip")!!.attr("href"))
val title = this.selectFirst("h2[itemprop=headline]")!!.text().trim() val title = this.selectFirst("h2[itemprop=headline]")?.text()?.trim() ?: return null
val posterUrl = this.selectFirst(".limit > noscript > img")!!.attr("src") val posterUrl = fixUrlNull(this.selectFirst(".limit > noscript > img")?.attr("src"))
return newTvSeriesSearchResponse(title, href, TvType.AsianDrama) { return newTvSeriesSearchResponse(title, href, TvType.AsianDrama) {
this.posterUrl = posterUrl this.posterUrl = posterUrl

View file

@ -0,0 +1,133 @@
package com.lagradost.cloudstream3.movieproviders
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

@ -6,6 +6,7 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.httpsify import com.lagradost.cloudstream3.utils.httpsify
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element
class HDMovie5 : MainAPI() { class HDMovie5 : MainAPI() {
override var mainUrl = "https://hdmovie2.click" override var mainUrl = "https://hdmovie2.click"
@ -19,29 +20,27 @@ class HDMovie5 : MainAPI() {
TvType.TvSeries, TvType.TvSeries,
) )
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val doc = app.get(mainUrl).document.select("div.content") "$mainUrl/genre/tv-movie/page/" to "TV Movie",
val list = mapOf( "$mainUrl/genre/tv-show/page/" to "TV- Show",
"Featured Movies" to "featured", "$mainUrl/genre/hindi-dubbed/page/" to "Hindi Dubbed",
"Updated Movies" to "normal" "$mainUrl/genre/netflix/page/" to "NETFLIX",
) )
return HomePageResponse(list.map { item ->
HomePageList(item.key,
doc.select("div.${item.value}>.item").map {
val data = it.select(".data")
val a = data.select("a")
MovieSearchResponse(
a.text(),
a.attr("href"),
this.name, override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
TvType.Movie, val home = app.get(request.data + page).document.select("article.item").mapNotNull {
it.select("img").attr("src"), it.toSearchResult()
data.select("span").text().toIntOrNull() }
) 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( private data class QuickSearchResponse(

View file

@ -28,27 +28,25 @@ class HDrezkaProvider : MainAPI() {
TvType.AsianDrama TvType.AsianDrama
) )
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
"$mainUrl/films/?filter=watching" to "фильмы",
"$mainUrl/series/?filter=watching" to "сериалы",
"$mainUrl/cartoons/?filter=watching" to "мультфильмы",
"$mainUrl/animation/?filter=watching" to "аниме",
)
val items = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
listOf( request: MainPageRequest
Pair("фильмы", "$mainUrl/films/?filter=watching"), ): HomePageResponse {
Pair("сериалы", "$mainUrl/series/?filter=watching"), val url = request.data.split("?")
Pair("мультфильмы", "$mainUrl/cartoons/?filter=watching"), val home = app.get("${url.first()}page/$page/?${url.last()}").document.select(
Pair("аниме", "$mainUrl/animation/?filter=watching"),
).apmap { (header, url) ->
safeApiCall {
val home = app.get(url).document.select(
"div.b-content__inline_items div.b-content__inline_item" "div.b-content__inline_items div.b-content__inline_item"
).map { ).map {
it.toSearchResult() it.toSearchResult()
} }
items.add(HomePageList(fixTitle(header), home))
} return newHomePageResponse(request.name, home)
}
if (items.size <= 0) throw ErrorLoadingException()
return HomePageResponse(items)
} }
private fun Element.toSearchResult(): SearchResponse { private fun Element.toSearchResult(): SearchResponse {

View file

@ -22,22 +22,25 @@ class IdlixProvider : MainAPI() {
TvType.TvSeries, TvType.TvSeries,
) )
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "$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",
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select("div.items").forEach { block -> request: MainPageRequest
val header = ): HomePageResponse {
fixTitle(block.previousElementSibling()?.previousElementSibling()?.select("header > h2") val url = request.data.split("?")
?.text()!!.trim()) val document = app.get("${url.first()}$page/?${url.lastOrNull()}").document
val items = block.select("article.item").mapNotNull { val home = document.select("article").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun getProperLink(uri: String): String { private fun getProperLink(uri: String): String {
@ -75,7 +78,8 @@ class IdlixProvider : MainAPI() {
val document = app.get(link).document val document = app.get(link).document
return document.select("div.result-item").map { return document.select("div.result-item").map {
val title = it.selectFirst("div.title > a")!!.text().replace(Regex("\\(\\d{4}\\)"), "").trim() val title =
it.selectFirst("div.title > a")!!.text().replace(Regex("\\(\\d{4}\\)"), "").trim()
val href = getProperLink(it.selectFirst("div.title > a")!!.attr("href")) val href = getProperLink(it.selectFirst("div.title > a")!!.attr("href"))
val posterUrl = it.selectFirst("img")!!.attr("src").toString() val posterUrl = it.selectFirst("img")!!.attr("src").toString()
newMovieSearchResponse(title, href, TvType.TvSeries) { newMovieSearchResponse(title, href, TvType.TvSeries) {
@ -87,7 +91,9 @@ class IdlixProvider : MainAPI() {
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document val document = app.get(url).document
val title = document.selectFirst("div.data > h1")?.text()?.replace(Regex("\\(\\d{4}\\)"), "")?.trim().toString() 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 poster = document.select("div.poster > img").attr("src").toString()
val tags = document.select("div.sgeneros > a").map { it.text() } val tags = document.select("div.sgeneros > a").map { it.text() }
@ -157,7 +163,8 @@ class IdlixProvider : MainAPI() {
private fun getLanguage(str: String): String { private fun getLanguage(str: String): String {
return when { return when {
str.lowercase().contains("indonesia") || str.lowercase().contains("bahasa") -> "Indonesian" str.lowercase().contains("indonesia") || str.lowercase()
.contains("bahasa") -> "Indonesian"
else -> str else -> str
} }
} }
@ -203,7 +210,8 @@ class IdlixProvider : MainAPI() {
document.select("script").map { script -> document.select("script").map { script ->
if (script.data().contains("eval(function(p,a,c,k,e,d)")) { if (script.data().contains("eval(function(p,a,c,k,e,d)")) {
val subData = getAndUnpack(script.data()).substringAfter("\"tracks\":[").substringBefore("],") val subData =
getAndUnpack(script.data()).substringAfter("\"tracks\":[").substringBefore("],")
tryParseJson<List<Tracks>>("[$subData]")?.map { subtitle -> tryParseJson<List<Tracks>>("[$subData]")?.map { subtitle ->
subCallback.invoke( subCallback.invoke(
SubtitleFile( SubtitleFile(

View file

@ -0,0 +1,204 @@
package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
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.M3u8Helper
import com.lagradost.cloudstream3.utils.loadExtractor
import java.util.ArrayList
class KisskhProvider : MainAPI() {
override var mainUrl = "https://kisskh.me"
override var name = "Kisskh"
override val hasMainPage = true
override val hasDownloadSupport = true
override val supportedTypes = setOf(
TvType.AsianDrama,
TvType.Anime
)
override val mainPage = mainPageOf(
"&type=2&sub=0&country=2&status=0&order=1" to "Movie Pupular",
"&type=2&sub=0&country=2&status=0&order=2" to "Movie Last Update",
"&type=1&sub=0&country=2&status=0&order=1" to "TVSeries Popular",
"&type=1&sub=0&country=2&status=0&order=2" to "TVSeries Last Update",
"&type=3&sub=0&country=0&status=0&order=1" to "Anime Popular",
"&type=3&sub=0&country=0&status=0&order=2" to "Anime Last Update",
)
override suspend fun getMainPage(
page: Int,
request: MainPageRequest
): HomePageResponse {
val home = app.get("$mainUrl/api/DramaList/List?page=$page${request.data}")
.parsedSafe<Responses>()?.data
?.mapNotNull { media ->
media.toSearchResponse()
} ?: throw ErrorLoadingException("Invalid Json reponse")
return newHomePageResponse(request.name, home)
}
private fun Media.toSearchResponse(): SearchResponse? {
return newAnimeSearchResponse(
title ?: return null,
"$title/$id",
TvType.TvSeries,
) {
this.posterUrl = thumbnail
addSub(episodesCount)
}
}
override suspend fun search(query: String): List<SearchResponse> {
val searchResponse = app.get("$mainUrl/api/DramaList/Search?q=$query&type=0", referer = "$mainUrl/").text
return tryParseJson<ArrayList<Media>>(searchResponse)?.mapNotNull { media ->
media.toSearchResponse()
} ?: throw ErrorLoadingException("Invalid Json reponse")
}
private fun getTitle(str: String): String {
return str.replace(Regex("[^a-zA-Z0-9]"), "-")
}
override suspend fun load(url: String): LoadResponse? {
val id = url.split("/")
val res = app.get(
"$mainUrl/api/DramaList/Drama/${id.last()}?isq=false",
referer = "$mainUrl/Drama/${
getTitle(id.first())
}?id=${id.last()}"
).parsedSafe<MediaDetail>()
?: throw ErrorLoadingException("Invalid Json reponse")
val episodes = res.episodes?.map { eps ->
Episode(
data = Data(res.title, eps.number, res.id, eps.id).toJson(),
episode = eps.number
)
} ?: throw ErrorLoadingException("No Episode")
return newTvSeriesLoadResponse(
res.title ?: return null,
url,
if (res.type == "Movie" || episodes.size == 1) TvType.Movie else TvType.TvSeries,
episodes
) {
this.posterUrl = res.thumbnail
this.year = res.releaseDate?.split("-")?.first()?.toIntOrNull()
this.plot = res.description
this.tags = listOf("${res.country}", "${res.status}", "${res.type}")
this.showStatus = when (res.status) {
"Completed" -> ShowStatus.Completed
"Ongoing" -> ShowStatus.Ongoing
else -> null
}
}
}
private fun getLanguage(str: String): String {
return when (str) {
"Indonesia" -> "Indonesian"
else -> str
}
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val loadData = parseJson<Data>(data)
app.get(
"$mainUrl/api/DramaList/Episode/${loadData.epsId}.png?err=false&ts=&time=",
referer = "$mainUrl/Drama/${getTitle("${loadData.title}")}/Episode-${loadData.eps}?id=${loadData.id}&ep=${loadData.epsId}&page=0&pageSize=100"
).parsedSafe<Sources>()?.let { source ->
listOf(source.video, source.thirdParty).apmap { link ->
safeApiCall {
if (link?.contains(".m3u8") == true) {
M3u8Helper.generateM3u8(
this.name,
link,
referer = "$mainUrl/",
headers = mapOf("Origin" to mainUrl)
).forEach(callback)
} else {
loadExtractor(
link?.substringBefore("=http") ?: return@safeApiCall,
"$mainUrl/",
subtitleCallback,
callback
)
}
}
}
}
app.get("$mainUrl/api/Sub/${loadData.epsId}").parsedSafe<List<Subtitle>>()?.map { sub ->
subtitleCallback.invoke(
SubtitleFile(
getLanguage(sub.label ?: return@map),
sub.src ?: return@map
)
)
}
return true
}
data class Data(
val title: String?,
val eps: Int?,
val id: Int?,
val epsId: Int?,
)
data class Sources(
@JsonProperty("Video") val video: String?,
@JsonProperty("ThirdParty") val thirdParty: String?,
)
data class Subtitle(
@JsonProperty("src") val src: String?,
@JsonProperty("label") val label: String?,
)
data class Responses(
@JsonProperty("data") val data: ArrayList<Media>? = arrayListOf(),
)
data class Media(
@JsonProperty("episodesCount") val episodesCount: Int?,
@JsonProperty("thumbnail") val thumbnail: String?,
@JsonProperty("id") val id: Int?,
@JsonProperty("title") val title: String?,
)
data class Episodes(
@JsonProperty("id") val id: Int?,
@JsonProperty("number") val number: Int?,
@JsonProperty("sub") val sub: Int?,
)
data class MediaDetail(
@JsonProperty("description") val description: String?,
@JsonProperty("releaseDate") val releaseDate: String?,
@JsonProperty("status") val status: String?,
@JsonProperty("type") val type: String?,
@JsonProperty("country") val country: String?,
@JsonProperty("episodes") val episodes: ArrayList<Episodes>? = arrayListOf(),
@JsonProperty("thumbnail") val thumbnail: String?,
@JsonProperty("id") val id: Int?,
@JsonProperty("title") val title: String?,
)
}

View file

@ -7,7 +7,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.*
class LayarKacaProvider : MainAPI() { class LayarKacaProvider : MainAPI() {
override var mainUrl = "https://lk21.xn--6frz82g" override var mainUrl = "https://lk21.xn--6frz82g"
@ -21,90 +20,33 @@ class LayarKacaProvider : MainAPI() {
TvType.AsianDrama TvType.AsianDrama
) )
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "$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",
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select("section.hot-block,section#newseries").forEach { block -> request: MainPageRequest
val header = fixTitle(block.select("footer.load-more > a").text().trim()) ): HomePageResponse {
val items = block.select("div.slider-item").mapNotNull { val document = app.get(request.data + page).document
it.toTopSearchResult() val home = document.select("article.mega-item").mapNotNull {
it.toSearchResult()
} }
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items)) return newHomePageResponse(request.name, home)
} }
document.select("div#newest").forEach { block -> private fun Element.toSearchResult(): SearchResponse? {
val header = fixTitle(block.select(".header > h2 > a").text()) val title = this.selectFirst("h1.grid-title > a")?.ownText()?.trim() ?: return null
val items = block.select("div.item").mapNotNull { val href = fixUrl(this.selectFirst("h1.grid-title > a")!!.attr("href"))
it.toMainSearchResult() val posterUrl = fixUrlNull(this.selectFirst(".grid-poster > a > img")?.attr("src"))
} val quality = this.select("div.quality").text().trim()
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
}
document.select("section#recomendation,section#populer,section#seriespopuler")
.forEach { block ->
val header = fixTitle(block.select(".header > h2 > a").text())
val items = block.select("div.item").mapNotNull {
it.toBottomSearchResult()
}
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
}
return HomePageResponse(homePageList)
}
private fun Element.toTopSearchResult(): SearchResponse {
val title = this.selectFirst("h3.caption")!!.text().trim()
val href = this.selectFirst("a")!!.attr("href")
val posterUrl = fixUrl(this.selectFirst("a > img")?.attr("src").toString())
val type =
if (this.select("div.quality-top").isNotEmpty()) TvType.Movie else TvType.TvSeries
return if (type == TvType.Movie) {
val quality = getQualityFromString(this.select("div.quality-top").text().trim())
newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl
this.quality = quality
}
} else {
val episode = this.select("div.last-episode > span").text().toIntOrNull()
newAnimeSearchResponse(title, href, TvType.TvSeries) {
this.posterUrl = posterUrl
addSub(episode)
}
}
}
private fun Element.toMainSearchResult(): SearchResponse {
val title = this.selectFirst("h3.caption")!!.text().trim()
val href = this.selectFirst("a")!!.attr("href")
val posterUrl = fixUrl(this.select("a > img").attr("src").toString())
val quality = getQualityFromString(this.select("div.quality-top").text().trim())
return newMovieSearchResponse(title, href, TvType.Movie) { return newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
this.quality = quality addQuality(quality)
} }
}
private fun Element.toBottomSearchResult(): SearchResponse {
val title = this.selectFirst("h1.grid-title > a")!!.ownText().trim()
val href = this.selectFirst("h1.grid-title > a")!!.attr("href")
val posterUrl = fixUrl(this.selectFirst(".grid-poster > a > img")?.attr("src").toString())
val type = if (this.select("div.quality").isNotEmpty()) TvType.Movie else TvType.TvSeries
return if (type == TvType.Movie) {
val quality = getQualityFromString(this.select("div.quality").text().trim())
return newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl
this.quality = quality
}
} else {
newTvSeriesSearchResponse(title, href, TvType.TvSeries) {
this.posterUrl = posterUrl
}
}
} }
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
@ -138,12 +80,14 @@ class LayarKacaProvider : MainAPI() {
val trailer = document.selectFirst("div.action-player li > a.fancybox")?.attr("href") val trailer = document.selectFirst("div.action-player li > a.fancybox")?.attr("href")
val rating = val rating =
document.selectFirst("div.content > div:nth-child(6) > h3")?.text()?.toRatingInt() 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 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 recommendations = document.select("div.row.item-media").map {
val recName = it.selectFirst("h3")?.text()?.trim().toString() val recName = it.selectFirst("h3")?.text()?.trim().toString()
val recHref = it.selectFirst(".content-media > a")!!.attr("href") val recHref = it.selectFirst(".content-media > a")!!.attr("href")
val recPosterUrl = fixUrl(it.selectFirst(".poster-media > a > img")?.attr("src").toString()) val recPosterUrl =
fixUrl(it.selectFirst(".poster-media > a > img")?.attr("src").toString())
newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) { newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) {
this.posterUrl = recPosterUrl this.posterUrl = recPosterUrl
} }
@ -172,8 +116,7 @@ class LayarKacaProvider : MainAPI() {
this.recommendations = recommendations this.recommendations = recommendations
addTrailer(trailer) addTrailer(trailer)
} }
} } else {
else {
newMovieLoadResponse(title, url, TvType.Movie, url) { newMovieLoadResponse(title, url, TvType.Movie, url) {
this.posterUrl = poster this.posterUrl = poster
this.year = year this.year = year
@ -199,7 +142,8 @@ class LayarKacaProvider : MainAPI() {
val sources = if (data.contains("-episode-")) { val sources = if (data.contains("-episode-")) {
document.select("script").mapNotNull { script -> document.select("script").mapNotNull { script ->
if (script.data().contains("var data =")) { if (script.data().contains("var data =")) {
val scriptData = script.toString().substringAfter("var data = '").substringBefore("';") val scriptData =
script.toString().substringAfter("var data = '").substringBefore("';")
Jsoup.parse(scriptData).select("li").map { Jsoup.parse(scriptData).select("li").map {
fixUrl(it.select("a").attr("href")) fixUrl(it.select("a").attr("href"))
} }

View file

@ -8,7 +8,6 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.util.ArrayList
class MultiplexProvider : MainAPI() { class MultiplexProvider : MainAPI() {
override var mainUrl = "https://146.19.24.137" override var mainUrl = "https://146.19.24.137"
@ -22,45 +21,30 @@ class MultiplexProvider : MainAPI() {
TvType.AsianDrama TvType.AsianDrama
) )
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "$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",
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select("div.col-md-12 > div.home-widget").forEach { block -> request: MainPageRequest
val header = fixTitle(block.select("h3.homemodule-title").text()) ): HomePageResponse {
val items = block.select("div.col-md-125").mapNotNull { val document = app.get(request.data + page).document
val home = document.select("article.item").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items)) return newHomePageResponse(request.name, home)
} }
document.select("div.container.gmr-maincontent") private fun Element.toSearchResult(): SearchResponse? {
.forEach { block -> val title = this.selectFirst("h2.entry-title > a")?.text()?.trim() ?: return null
val header = fixTitle(block.select("h3.homemodule-title").text()) val href = fixUrl(this.selectFirst("a")!!.attr("href"))
val items = block.select("article.item").mapNotNull { val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("data-src"))
it.toSearchResult() val quality = this.select("div.gmr-quality-item > a").text().trim()
} return if (quality.isEmpty()) {
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
}
document.select("div#idmuvi-rp-2").forEach { block ->
val header = fixTitle(block.selectFirst("h3.widget-title")?.ownText()!!.trim())
val items = block.select("div.idmuvi-rp ul li").mapNotNull {
it.toBottomSearchResult()
}
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
}
return HomePageResponse(homePageList)
}
private fun Element.toSearchResult(): SearchResponse {
val title = this.selectFirst("h2.entry-title > a")!!.text().trim()
val href = this.selectFirst("a")!!.attr("href")
val posterUrl = fixUrl(this.selectFirst("a > img")?.attr("data-src").toString())
val quality = getQualityFromString(this.select("div.gmr-quality-item > a").text().trim())
return if (quality == null) {
val episode = this.select("div.gmr-numbeps > span").text().toIntOrNull() val episode = this.select("div.gmr-numbeps > span").text().toIntOrNull()
newAnimeSearchResponse(title, href, TvType.TvSeries) { newAnimeSearchResponse(title, href, TvType.TvSeries) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
@ -69,27 +53,24 @@ class MultiplexProvider : MainAPI() {
} else { } else {
newMovieSearchResponse(title, href, TvType.Movie) { newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
this.quality = quality addQuality(quality)
}
} }
} }
} private fun Element.toBottomSearchResult(): SearchResponse? {
val title = this.selectFirst("a > span.idmuvi-rp-title")?.text()?.trim() ?: return null
private fun Element.toBottomSearchResult(): SearchResponse {
val title = this.selectFirst("a > span.idmuvi-rp-title")!!.text().trim()
val href = this.selectFirst("a")!!.attr("href") val href = this.selectFirst("a")!!.attr("href")
val posterUrl = fixUrl(this.selectFirst("a > img")?.attr("data-src").toString()) val posterUrl = fixUrl(this.selectFirst("a > img")?.attr("data-src").toString())
return newMovieSearchResponse(title, href, TvType.Movie) { return newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
} }
} }
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/?s=$query&post_type[]=post&post_type[]=tv" val link = "$mainUrl/?s=$query&post_type[]=post&post_type[]=tv"
val document = app.get(link).document val document = app.get(link).document
return document.select("article.item").mapNotNull {
return document.select("div#gmr-main-load > article.item").map {
it.toSearchResult() it.toSearchResult()
} }
} }
@ -112,9 +93,10 @@ class MultiplexProvider : MainAPI() {
val rating = val rating =
document.selectFirst("div.gmr-meta-rating > span[itemprop=ratingValue]")?.text() document.selectFirst("div.gmr-meta-rating > span[itemprop=ratingValue]")?.text()
?.toRatingInt() ?.toRatingInt()
val actors = document.select("div.gmr-moviedata").last()?.select("span[itemprop=actors]")?.map { it.select("a").text() } 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").map { val recommendations = document.select("div.idmuvi-rp ul li").mapNotNull {
it.toBottomSearchResult() it.toBottomSearchResult()
} }

View file

@ -23,20 +23,25 @@ class PhimmoichillProvider : MainAPI() {
TvType.AsianDrama TvType.AsianDrama
) )
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "$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",
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select("div.container div.block").forEach { block -> request: MainPageRequest
val header = fixTitle(block.selectFirst("h2")!!.text()) ): HomePageResponse {
val items = block.select("li.item").mapNotNull { val document = app.get(request.data + page).document
val home = document.select("li.item").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun decode(input: String): String? = URLDecoder.decode(input, "utf-8") private fun decode(input: String): String? = URLDecoder.decode(input, "utf-8")

View file

@ -15,7 +15,7 @@ import org.jsoup.nodes.Element
import java.net.URI import java.net.URI
class RebahinProvider : MainAPI() { class RebahinProvider : MainAPI() {
override var mainUrl = "http://167.88.14.149" override var mainUrl = "http://104.237.198.194"
override var name = "Rebahin" override var name = "Rebahin"
override val hasMainPage = true override val hasMainPage = true
override var lang = "id" override var lang = "id"

View file

@ -23,20 +23,24 @@ class UakinoProvider : MainAPI() {
TvType.Anime TvType.Anime
) )
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "$mainUrl/filmy/page/" to "Фільми",
"$mainUrl/seriesss/page/" to "Серіали",
"$mainUrl/seriesss/doramy/page/" to "Дорами",
"$mainUrl/animeukr/page/" to "Аніме",
"$mainUrl/cartoon/page/" to "Мультфільми",
"$mainUrl/cartoon/cartoonseries/page/" to "Мультсеріали",
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select("div.main-section-inner").forEach { block -> request: MainPageRequest
val header = block.selectFirst("p.sidebar-title")?.text()?.trim().toString() ): HomePageResponse {
val items = block.select("div.owl-item, div.movie-item").map { val document = app.get(request.data + page).document
val home = document.select("div.owl-item, div.movie-item").map {
it.toSearchResponse() it.toSearchResponse()
} }
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun Element.toSearchResponse(): SearchResponse { private fun Element.toSearchResponse(): SearchResponse {
@ -70,7 +74,8 @@ class UakinoProvider : MainAPI() {
val poster = fixUrl(document.selectFirst("div.film-poster img")?.attr("src").toString()) val poster = fixUrl(document.selectFirst("div.film-poster img")?.attr("src").toString())
val tags = document.select("div.film-info > div:nth-child(4) a").map { it.text() } val tags = document.select("div.film-info > div:nth-child(4) a").map { it.text() }
val year = document.select("div.film-info > div:nth-child(2) a").text().toIntOrNull() val year = document.select("div.film-info > div:nth-child(2) a").text().toIntOrNull()
val tvType = if (url.contains(Regex("(/anime-series)|(/seriesss)|(/cartoonseries)"))) TvType.TvSeries else TvType.Movie val tvType =
if (url.contains(Regex("(/anime-series)|(/seriesss)|(/cartoonseries)"))) TvType.TvSeries else TvType.Movie
val description = document.selectFirst("div[itemprop=description]")?.text()?.trim() val description = document.selectFirst("div[itemprop=description]")?.text()?.trim()
val trailer = document.selectFirst("iframe#pre")?.attr("data-src") val trailer = document.selectFirst("iframe#pre")?.attr("data-src")
val rating = document.selectFirst("div.film-info > div:nth-child(8) div.fi-desc")?.text() val rating = document.selectFirst("div.film-info > div:nth-child(8) div.fi-desc")?.text()
@ -83,7 +88,8 @@ class UakinoProvider : MainAPI() {
return if (tvType == TvType.TvSeries) { return if (tvType == TvType.TvSeries) {
val id = url.split("/").last().split("-").first() val id = url.split("/").last().split("-").first()
val episodes = app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}") val episodes =
app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}")
.parsedSafe<Responses>()?.response.let { .parsedSafe<Responses>()?.response.let {
Jsoup.parse(it.toString()).select("ul > li").mapNotNull { eps -> Jsoup.parse(it.toString()).select("ul > li").mapNotNull { eps ->
val href = fixUrl(eps.attr("data-file")) val href = fixUrl(eps.attr("data-file"))

View file

@ -9,7 +9,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
class YomoviesProvider : MainAPI() { class YomoviesProvider : MainAPI() {
override var mainUrl = "https://yomovies.vip" override var mainUrl = "https://yomovies.skin"
override var name = "Yomovies" override var name = "Yomovies"
override val hasMainPage = true override val hasMainPage = true
override var lang = "hi" override var lang = "hi"
@ -19,21 +19,25 @@ class YomoviesProvider : MainAPI() {
TvType.TvSeries, TvType.TvSeries,
) )
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { override val mainPage = mainPageOf(
val document = app.get(mainUrl).document "$mainUrl/most-favorites/page/" to "Most Viewed",
"$mainUrl/genre/web-series/page/" to "Web Series Movies",
"$mainUrl/genre/dual-audio/page/" to "Dual Audio Movies",
"$mainUrl/genre/bollywood/page/" to "Bollywood Movies",
"$mainUrl/genre/tv-shows/page/" to "TV Shows Movies",
"$mainUrl/genre/hollywood/page/" to "Hollywood Movies",
"$mainUrl/series/page/" to "All TV Series",
)
val homePageList = ArrayList<HomePageList>() override suspend fun getMainPage(
page: Int,
document.select("div.movies-list-wrap.mlw-topview,div.movies-list-wrap.mlw-latestmovie") request: MainPageRequest
.forEach { block -> ): HomePageResponse {
val header = fixTitle(block.selectFirst("div.ml-title span")?.text() ?: "") val document = app.get(request.data + page).document
val items = block.select("div.ml-item").mapNotNull { val home = document.select("div.ml-item").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items)) return newHomePageResponse(request.name, home)
}
return HomePageResponse(homePageList)
} }
private fun Element.toSearchResult(): SearchResponse? { private fun Element.toSearchResult(): SearchResponse? {
@ -63,8 +67,9 @@ class YomoviesProvider : MainAPI() {
val year = document.select("div.mvici-right p:nth-child(3) a").text().trim() val year = document.select("div.mvici-right p:nth-child(3) a").text().trim()
.toIntOrNull() .toIntOrNull()
val tvType = if (document.selectFirst("div.les-content") val tvType = if (document.selectFirst("div.les-content")
?.select("a")?.size!! <= 1 ?.select("a")?.size!! > 1 || document.selectFirst("ul.idTabs li strong")?.text()
) TvType.Movie else TvType.TvSeries ?.contains(Regex("(?i)(EP\\s?[0-9]+)|(episode\\s?[0-9]+)")) == true
) TvType.TvSeries else TvType.Movie
val description = document.selectFirst("p.f-desc")?.text()?.trim() val description = document.selectFirst("p.f-desc")?.text()?.trim()
val trailer = fixUrlNull(document.select("iframe#iframe-trailer").attr("src")) val trailer = fixUrlNull(document.select("iframe#iframe-trailer").attr("src"))
val rating = document.select("div.mvici-right > div.imdb_r span").text().toRatingInt() val rating = document.select("div.mvici-right > div.imdb_r span").text().toRatingInt()
@ -74,14 +79,25 @@ class YomoviesProvider : MainAPI() {
} }
return if (tvType == TvType.TvSeries) { return if (tvType == TvType.TvSeries) {
val episodes = document.select("div.les-content a").map { val episodes = if (document.selectFirst("div.les-title strong")?.text().toString()
val href = it.attr("href") .contains(Regex("(?i)EP\\s?[0-9]+|Episode\\s?[0-9]+"))
val name = it.text().trim() ) {
document.select("ul.idTabs li").map {
val id = it.select("a").attr("href")
Episode( Episode(
data = href, data = fixUrl(document.select("div$id iframe").attr("src")),
name = name, name = it.select("strong").text(),
) )
} }
} else {
document.select("div.les-content a").map {
Episode(
data = it.attr("href"),
name = it.text().trim(),
)
}
}
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
this.posterUrl = poster this.posterUrl = poster
this.year = year this.year = year
@ -113,6 +129,7 @@ class YomoviesProvider : MainAPI() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
if (data.startsWith(mainUrl)) {
app.get(data).document.select("div.movieplay iframe").map { fixUrl(it.attr("src")) } app.get(data).document.select("div.movieplay iframe").map { fixUrl(it.attr("src")) }
.apmap { source -> .apmap { source ->
safeApiCall { safeApiCall {
@ -133,6 +150,9 @@ class YomoviesProvider : MainAPI() {
} }
} }
} }
} else {
loadExtractor(data, "$mainUrl/", subtitleCallback, callback)
}
return true return true
} }

View file

@ -232,6 +232,7 @@ val extractorApis: Array<ExtractorApi> = arrayOf(
SBfull(), SBfull(),
// Streamhub(), cause Streamhub2() works // Streamhub(), cause Streamhub2() works
Streamhub2(), Streamhub2(),
Ssbstream(),
FEmbed(), FEmbed(),
FeHD(), FeHD(),