mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Added Inf home to some providers and new providers (#1377)
* The Boys!! * Prikitieww...
This commit is contained in:
parent
c5406acc1e
commit
df509dfe1b
25 changed files with 938 additions and 477 deletions
|
@ -109,7 +109,8 @@ object APIHolder {
|
|||
PhimmoichillProvider(),
|
||||
HDrezkaProvider(),
|
||||
YomoviesProvider(),
|
||||
|
||||
DubokuProvider(),
|
||||
KisskhProvider(),
|
||||
|
||||
// Metadata providers
|
||||
//TmdbProvider(),
|
||||
|
@ -148,6 +149,7 @@ object APIHolder {
|
|||
AnimeIndoProvider(),
|
||||
AnimeSailProvider(),
|
||||
TocanimeProvider(),
|
||||
WcofunProvider(),
|
||||
//MultiAnimeProvider(),
|
||||
NginxProvider(),
|
||||
OlgplyProvider(),
|
||||
|
|
|
@ -62,20 +62,20 @@ class AnimeIndoProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = request(mainUrl).document
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/anime-terbaru/page/" to "Anime Terbaru",
|
||||
"$mainUrl/donghua-terbaru/page/" to "Donghua Terbaru"
|
||||
)
|
||||
|
||||
val homePageList = ArrayList<HomePageList>()
|
||||
|
||||
document.select("div.widget_senction").forEach { block ->
|
||||
val header = block.selectFirst("div.widget-title > h3")!!.text().trim()
|
||||
val items = block.select("div.post-show > article").map {
|
||||
it.toSearchResult()
|
||||
}
|
||||
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
|
||||
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 HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun getProperAnimeLink(uri: String): String {
|
||||
|
@ -96,8 +96,8 @@ class AnimeIndoProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): AnimeSearchResponse {
|
||||
val title = this.selectFirst("div.title")!!.text().trim()
|
||||
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())
|
||||
|
|
|
@ -47,20 +47,18 @@ class AnimeSailProvider : MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = request(mainUrl).document
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/page/" to "Episode Terbaru",
|
||||
"$mainUrl/movie-terbaru/page/" to "Movie Terbaru",
|
||||
"$mainUrl/genres/donghua/page/" to "Donghua"
|
||||
)
|
||||
|
||||
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()
|
||||
}
|
||||
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
|
||||
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 HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun getProperAnimeLink(uri: String): String {
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.lagradost.cloudstream3.animeproviders
|
|||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
|
@ -41,51 +40,41 @@ class GomunimeProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
private data class Response(
|
||||
@JsonProperty("status") val status: Boolean,
|
||||
@JsonProperty("html") val html: String
|
||||
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 urls = listOf(
|
||||
Pair("e", "Episode Baru"),
|
||||
Pair("c", "Completed"),
|
||||
Pair("la", "Live Action"),
|
||||
Pair("t", "Trending"),
|
||||
)
|
||||
|
||||
val items = ArrayList<HomePageList>()
|
||||
|
||||
for ((payload, name) in urls) {
|
||||
try {
|
||||
val home = Jsoup.parse(
|
||||
parseJson<Response>(
|
||||
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 payload, "pag" to "1")
|
||||
).text
|
||||
).html
|
||||
).select("li").map {
|
||||
val title = it.selectFirst("a.name")!!.text().trim()
|
||||
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)
|
||||
}
|
||||
}
|
||||
items.add(HomePageList(name, home))
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
if (items.size <= 0) throw ErrorLoadingException()
|
||||
return HomePageResponse(items)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
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 {
|
||||
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(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
|
@ -234,4 +209,24 @@ class GomunimeProvider : MainAPI() {
|
|||
|
||||
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?
|
||||
)
|
||||
|
||||
}
|
|
@ -2,11 +2,9 @@ package com.lagradost.cloudstream3.animeproviders
|
|||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
||||
import com.lagradost.cloudstream3.network.DdosGuardKiller
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.*
|
||||
|
||||
class KuramanimeProvider : MainAPI() {
|
||||
override var mainUrl = "https://kuramanime.com"
|
||||
|
@ -38,28 +36,24 @@ class KuramanimeProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
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",
|
||||
)
|
||||
|
||||
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 header = block.selectFirst("h4")?.text().toString()
|
||||
val animes = block.select("div.col-lg-4.col-md-6.col-sm-6").map {
|
||||
it.toSearchResult()
|
||||
}
|
||||
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
|
||||
val home = document.select("div.col-lg-4.col-md-6.col-sm-6").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
||||
document.select("div.product__sidebar__view").forEach { block ->
|
||||
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)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
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 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 episode = Regex("([0-9*])\\s?/").find(
|
||||
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> {
|
||||
val link = "$mainUrl/anime?search=$query&order_by=oldest"
|
||||
val document = app.get(link).document
|
||||
|
|
|
@ -39,20 +39,23 @@ class KuronimeProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
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",
|
||||
)
|
||||
|
||||
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()
|
||||
}
|
||||
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
|
||||
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 HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun getProperAnimeLink(uri: String): String {
|
||||
|
@ -77,7 +80,10 @@ class KuronimeProvider : MainAPI() {
|
|||
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 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) {
|
||||
|
@ -117,7 +123,8 @@ class KuronimeProvider : MainAPI() {
|
|||
|
||||
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 episode =
|
||||
it.selectFirst("a")?.text()?.trim()?.replace("Episode", "")?.trim()?.toIntOrNull()
|
||||
val link = it.selectFirst("a")!!.attr("href")
|
||||
Episode(link, name = name, episode = episode)
|
||||
}.reversed()
|
||||
|
|
|
@ -40,20 +40,18 @@ class NeonimeProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/episode/page/" to "Episode Terbaru",
|
||||
"$mainUrl/tvshows/page/" to "Anime Terbaru",
|
||||
"$mainUrl/movies/page/" to "Movie",
|
||||
)
|
||||
|
||||
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 {
|
||||
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()
|
||||
}
|
||||
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
|
||||
}
|
||||
|
||||
return HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
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 title = this.select("span.tt.title-episode,h2.title-episode-movie,span.ttps").text()
|
||||
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) {
|
||||
this.posterUrl = posterUrl
|
||||
|
|
|
@ -228,7 +228,7 @@ class NontonAnimeIDProvider : MainAPI() {
|
|||
val document = app.get(data).document
|
||||
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 dataNume = it.attr("data-nume")
|
||||
val dataType = it.attr("data-type")
|
||||
|
@ -240,7 +240,9 @@ class NontonAnimeIDProvider : MainAPI() {
|
|||
"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))
|
||||
|
|
|
@ -40,20 +40,21 @@ class OploverzProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
override val mainPage = mainPageOf(
|
||||
"&status=&type=&order=update" to "Episode Terbaru",
|
||||
"&status=&type=&order=latest" to "Anime Terbaru",
|
||||
"&sub=&order=popular" to "Popular Anime",
|
||||
)
|
||||
|
||||
val homePageList = ArrayList<HomePageList>()
|
||||
|
||||
document.select(".bixbox.bbnofrm").forEach { block ->
|
||||
val header = block.selectFirst("h3")!!.text().trim()
|
||||
val animes = block.select("article[itemscope=itemscope]").map {
|
||||
it.toSearchResult()
|
||||
}
|
||||
if (animes.isNotEmpty()) homePageList.add(HomePageList(header, animes))
|
||||
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 HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun getProperAnimeLink(uri: String): String {
|
||||
|
@ -68,7 +69,8 @@ class OploverzProvider : MainAPI() {
|
|||
)?.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()
|
||||
(title.contains("-movie")) -> Regex("(.+)-subtitle").find(title)?.groupValues?.get(1)
|
||||
.toString()
|
||||
else -> Regex("(.+)-subtitle").find(title)?.groupValues?.get(1).toString()
|
||||
.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 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 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) {
|
||||
this.posterUrl = posterUrl
|
||||
addSub(epNum)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,8 @@ class OploverzProvider : MainAPI() {
|
|||
|
||||
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 name =
|
||||
Regex("(Episode\\s?[0-9]+)").find(header)?.groupValues?.getOrNull(0) ?: header
|
||||
val link = fixUrl(it.select("a").attr("href"))
|
||||
Episode(link, name)
|
||||
}.reversed()
|
||||
|
|
|
@ -7,6 +7,7 @@ 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"
|
||||
|
@ -37,24 +38,24 @@ class OtakudesuProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/ongoing-anime/page/" to "Anime Ongoing",
|
||||
"$mainUrl/complete-anime/page/" to "Anime Completed"
|
||||
)
|
||||
|
||||
val homePageList = ArrayList<HomePageList>()
|
||||
|
||||
document.select("div.rseries").forEach { block ->
|
||||
val header = block.selectFirst("div.rvad > h1")!!.text().trim()
|
||||
val items = block.select("div.venz > ul > li").map {
|
||||
it.toSearchResult()
|
||||
}
|
||||
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
|
||||
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 HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): AnimeSearchResponse {
|
||||
val title = this.selectFirst("h2.jdlflm")!!.text().trim()
|
||||
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()
|
||||
|
@ -103,7 +104,9 @@ class OtakudesuProvider : MainAPI() {
|
|||
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 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()
|
||||
|
@ -180,7 +183,10 @@ class OtakudesuProvider : MainAPI() {
|
|||
).select("iframe").attr("src")
|
||||
|
||||
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")
|
||||
}
|
||||
if (sources.startsWith("https://yourupload.com")) {
|
||||
|
|
|
@ -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?,
|
||||
)
|
||||
|
||||
|
||||
}
|
|
@ -7,6 +7,10 @@ import com.lagradost.cloudstream3.utils.ExtractorApi
|
|||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.M3u8Helper
|
||||
|
||||
class Ssbstream : StreamSB() {
|
||||
override var mainUrl = "https://ssbstream.net"
|
||||
}
|
||||
|
||||
class SBfull : StreamSB() {
|
||||
override var mainUrl = "https://sbfull.com"
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import com.lagradost.cloudstream3.utils.getQualityFromName
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.ArrayList
|
||||
|
||||
class DramaidProvider : MainAPI() {
|
||||
override var mainUrl = "https://185.224.83.103"
|
||||
|
@ -30,20 +29,18 @@ class DramaidProvider : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
override val mainPage = mainPageOf(
|
||||
"&status=&type=&order=update" to "Drama Terbaru",
|
||||
"&order=latest" to "Baru Ditambahkan",
|
||||
"&status=&type=&order=popular" to "Drama Popular",
|
||||
)
|
||||
|
||||
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()
|
||||
}
|
||||
if (dramas.isNotEmpty()) homePageList.add(HomePageList(header, dramas))
|
||||
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 HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
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 title = this.selectFirst("h2[itemprop=headline]")!!.text().trim()
|
||||
val posterUrl = this.selectFirst(".limit > noscript > img")!!.attr("src")
|
||||
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
|
||||
|
|
|
@ -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?,
|
||||
)
|
||||
|
||||
|
||||
}
|
|
@ -6,6 +6,7 @@ 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"
|
||||
|
@ -19,29 +20,27 @@ class HDMovie5 : MainAPI() {
|
|||
TvType.TvSeries,
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val doc = app.get(mainUrl).document.select("div.content")
|
||||
val list = mapOf(
|
||||
"Featured Movies" to "featured",
|
||||
"Updated Movies" to "normal"
|
||||
)
|
||||
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"),
|
||||
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",
|
||||
)
|
||||
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
it.select("img").attr("src"),
|
||||
data.select("span").text().toIntOrNull()
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
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(
|
||||
|
|
|
@ -28,27 +28,25 @@ class HDrezkaProvider : MainAPI() {
|
|||
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>()
|
||||
|
||||
listOf(
|
||||
Pair("фильмы", "$mainUrl/films/?filter=watching"),
|
||||
Pair("сериалы", "$mainUrl/series/?filter=watching"),
|
||||
Pair("мультфильмы", "$mainUrl/cartoons/?filter=watching"),
|
||||
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"
|
||||
).map {
|
||||
it.toSearchResult()
|
||||
}
|
||||
items.add(HomePageList(fixTitle(header), home))
|
||||
}
|
||||
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()
|
||||
}
|
||||
if (items.size <= 0) throw ErrorLoadingException()
|
||||
return HomePageResponse(items)
|
||||
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse {
|
||||
|
|
|
@ -22,22 +22,25 @@ class IdlixProvider : MainAPI() {
|
|||
TvType.TvSeries,
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
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",
|
||||
)
|
||||
|
||||
val homePageList = ArrayList<HomePageList>()
|
||||
|
||||
document.select("div.items").forEach { block ->
|
||||
val header =
|
||||
fixTitle(block.previousElementSibling()?.previousElementSibling()?.select("header > h2")
|
||||
?.text()!!.trim())
|
||||
val items = block.select("article.item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
|
||||
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("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
||||
return HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun getProperLink(uri: String): String {
|
||||
|
@ -75,7 +78,8 @@ class IdlixProvider : MainAPI() {
|
|||
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 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) {
|
||||
|
@ -87,7 +91,9 @@ class IdlixProvider : MainAPI() {
|
|||
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 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() }
|
||||
|
||||
|
@ -157,7 +163,8 @@ class IdlixProvider : MainAPI() {
|
|||
|
||||
private fun getLanguage(str: String): String {
|
||||
return when {
|
||||
str.lowercase().contains("indonesia") || str.lowercase().contains("bahasa") -> "Indonesian"
|
||||
str.lowercase().contains("indonesia") || str.lowercase()
|
||||
.contains("bahasa") -> "Indonesian"
|
||||
else -> str
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +210,8 @@ class IdlixProvider : MainAPI() {
|
|||
|
||||
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("],")
|
||||
val subData =
|
||||
getAndUnpack(script.data()).substringAfter("\"tracks\":[").substringBefore("],")
|
||||
tryParseJson<List<Tracks>>("[$subData]")?.map { subtitle ->
|
||||
subCallback.invoke(
|
||||
SubtitleFile(
|
||||
|
|
|
@ -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?,
|
||||
)
|
||||
|
||||
}
|
|
@ -7,7 +7,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.*
|
||||
|
||||
class LayarKacaProvider : MainAPI() {
|
||||
override var mainUrl = "https://lk21.xn--6frz82g"
|
||||
|
@ -21,90 +20,33 @@ class LayarKacaProvider : MainAPI() {
|
|||
TvType.AsianDrama
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
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",
|
||||
)
|
||||
|
||||
val homePageList = ArrayList<HomePageList>()
|
||||
|
||||
document.select("section.hot-block,section#newseries").forEach { block ->
|
||||
val header = fixTitle(block.select("footer.load-more > a").text().trim())
|
||||
val items = block.select("div.slider-item").mapNotNull {
|
||||
it.toTopSearchResult()
|
||||
}
|
||||
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
|
||||
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()
|
||||
}
|
||||
|
||||
document.select("div#newest").forEach { block ->
|
||||
val header = fixTitle(block.select(".header > h2 > a").text())
|
||||
val items = block.select("div.item").mapNotNull {
|
||||
it.toMainSearchResult()
|
||||
}
|
||||
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)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
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())
|
||||
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
|
||||
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> {
|
||||
|
@ -138,12 +80,14 @@ class LayarKacaProvider : MainAPI() {
|
|||
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 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())
|
||||
val recPosterUrl =
|
||||
fixUrl(it.selectFirst(".poster-media > a > img")?.attr("src").toString())
|
||||
newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) {
|
||||
this.posterUrl = recPosterUrl
|
||||
}
|
||||
|
@ -172,8 +116,7 @@ class LayarKacaProvider : MainAPI() {
|
|||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
|
@ -196,10 +139,11 @@ class LayarKacaProvider : MainAPI() {
|
|||
|
||||
val document = app.get(data).document
|
||||
|
||||
val sources = if(data.contains("-episode-")) {
|
||||
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("';")
|
||||
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"))
|
||||
}
|
||||
|
@ -214,7 +158,7 @@ class LayarKacaProvider : MainAPI() {
|
|||
}
|
||||
|
||||
sources.apmap {
|
||||
val link = if(it.startsWith("https://layarkacaxxi.icu")) {
|
||||
val link = if (it.startsWith("https://layarkacaxxi.icu")) {
|
||||
it.substringBeforeLast("/")
|
||||
} else {
|
||||
it
|
||||
|
|
|
@ -8,7 +8,6 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
|||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.ArrayList
|
||||
|
||||
class MultiplexProvider : MainAPI() {
|
||||
override var mainUrl = "https://146.19.24.137"
|
||||
|
@ -22,45 +21,30 @@ class MultiplexProvider : MainAPI() {
|
|||
TvType.AsianDrama
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
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",
|
||||
)
|
||||
|
||||
val homePageList = ArrayList<HomePageList>()
|
||||
|
||||
document.select("div.col-md-12 > div.home-widget").forEach { block ->
|
||||
val header = fixTitle(block.select("h3.homemodule-title").text())
|
||||
val items = block.select("div.col-md-125").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
|
||||
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()
|
||||
}
|
||||
|
||||
document.select("div.container.gmr-maincontent")
|
||||
.forEach { block ->
|
||||
val header = fixTitle(block.select("h3.homemodule-title").text())
|
||||
val items = block.select("article.item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
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)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
|
@ -69,27 +53,24 @@ class MultiplexProvider : MainAPI() {
|
|||
} else {
|
||||
newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
this.quality = quality
|
||||
addQuality(quality)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun Element.toBottomSearchResult(): SearchResponse {
|
||||
val title = this.selectFirst("a > span.idmuvi-rp-title")!!.text().trim()
|
||||
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("div#gmr-main-load > article.item").map {
|
||||
return document.select("article.item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
@ -112,9 +93,10 @@ class MultiplexProvider : MainAPI() {
|
|||
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 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()
|
||||
}
|
||||
|
||||
|
|
|
@ -23,20 +23,25 @@ class PhimmoichillProvider : MainAPI() {
|
|||
TvType.AsianDrama
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
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",
|
||||
)
|
||||
|
||||
val homePageList = ArrayList<HomePageList>()
|
||||
|
||||
document.select("div.container div.block").forEach { block ->
|
||||
val header = fixTitle(block.selectFirst("h2")!!.text())
|
||||
val items = block.select("li.item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
|
||||
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 HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun decode(input: String): String? = URLDecoder.decode(input, "utf-8")
|
||||
|
@ -176,11 +181,11 @@ class PhimmoichillProvider : MainAPI() {
|
|||
} else {
|
||||
val playList = app.get(link, referer = "$mainUrl/")
|
||||
.parsedSafe<ResponseM3u>()?.main?.segments?.map { segment ->
|
||||
PlayListItem(
|
||||
segment.link,
|
||||
(segment.du.toFloat() * 1_000_000).toLong()
|
||||
)
|
||||
}
|
||||
PlayListItem(
|
||||
segment.link,
|
||||
(segment.du.toFloat() * 1_000_000).toLong()
|
||||
)
|
||||
}
|
||||
|
||||
callback.invoke(
|
||||
ExtractorLinkPlayList(
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.jsoup.nodes.Element
|
|||
import java.net.URI
|
||||
|
||||
class RebahinProvider : MainAPI() {
|
||||
override var mainUrl = "http://167.88.14.149"
|
||||
override var mainUrl = "http://104.237.198.194"
|
||||
override var name = "Rebahin"
|
||||
override val hasMainPage = true
|
||||
override var lang = "id"
|
||||
|
|
|
@ -23,20 +23,24 @@ class UakinoProvider : MainAPI() {
|
|||
TvType.Anime
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
override val mainPage = mainPageOf(
|
||||
"$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>()
|
||||
|
||||
document.select("div.main-section-inner").forEach { block ->
|
||||
val header = block.selectFirst("p.sidebar-title")?.text()?.trim().toString()
|
||||
val items = block.select("div.owl-item, div.movie-item").map {
|
||||
it.toSearchResponse()
|
||||
}
|
||||
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select("div.owl-item, div.movie-item").map {
|
||||
it.toSearchResponse()
|
||||
}
|
||||
|
||||
return HomePageResponse(homePageList)
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
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 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 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 trailer = document.selectFirst("iframe#pre")?.attr("data-src")
|
||||
val rating = document.selectFirst("div.film-info > div:nth-child(8) div.fi-desc")?.text()
|
||||
|
@ -83,21 +88,22 @@ class UakinoProvider : MainAPI() {
|
|||
|
||||
return if (tvType == TvType.TvSeries) {
|
||||
val id = url.split("/").last().split("-").first()
|
||||
val episodes = app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}")
|
||||
.parsedSafe<Responses>()?.response.let {
|
||||
Jsoup.parse(it.toString()).select("ul > li").mapNotNull { eps ->
|
||||
val href = fixUrl(eps.attr("data-file"))
|
||||
val name = eps.text().trim()
|
||||
if (href.isNotEmpty()) {
|
||||
Episode(
|
||||
href,
|
||||
name,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
val episodes =
|
||||
app.get("$mainUrl/engine/ajax/playlists.php?news_id=$id&xfield=playlist&time=${Date().time}")
|
||||
.parsedSafe<Responses>()?.response.let {
|
||||
Jsoup.parse(it.toString()).select("ul > li").mapNotNull { eps ->
|
||||
val href = fixUrl(eps.attr("data-file"))
|
||||
val name = eps.text().trim()
|
||||
if (href.isNotEmpty()) {
|
||||
Episode(
|
||||
href,
|
||||
name,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor
|
|||
import org.jsoup.nodes.Element
|
||||
|
||||
class YomoviesProvider : MainAPI() {
|
||||
override var mainUrl = "https://yomovies.vip"
|
||||
override var mainUrl = "https://yomovies.skin"
|
||||
override var name = "Yomovies"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
|
@ -19,21 +19,25 @@ class YomoviesProvider : MainAPI() {
|
|||
TvType.TvSeries,
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
override val mainPage = mainPageOf(
|
||||
"$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>()
|
||||
|
||||
document.select("div.movies-list-wrap.mlw-topview,div.movies-list-wrap.mlw-latestmovie")
|
||||
.forEach { block ->
|
||||
val header = fixTitle(block.selectFirst("div.ml-title span")?.text() ?: "")
|
||||
val items = block.select("div.ml-item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
if (items.isNotEmpty()) homePageList.add(HomePageList(header, items))
|
||||
}
|
||||
|
||||
return HomePageResponse(homePageList)
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select("div.ml-item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
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()
|
||||
.toIntOrNull()
|
||||
val tvType = if (document.selectFirst("div.les-content")
|
||||
?.select("a")?.size!! <= 1
|
||||
) TvType.Movie else TvType.TvSeries
|
||||
?.select("a")?.size!! > 1 || document.selectFirst("ul.idTabs li strong")?.text()
|
||||
?.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 trailer = fixUrlNull(document.select("iframe#iframe-trailer").attr("src"))
|
||||
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) {
|
||||
val episodes = document.select("div.les-content a").map {
|
||||
val href = it.attr("href")
|
||||
val name = it.text().trim()
|
||||
Episode(
|
||||
data = href,
|
||||
name = name,
|
||||
)
|
||||
val episodes = if (document.selectFirst("div.les-title strong")?.text().toString()
|
||||
.contains(Regex("(?i)EP\\s?[0-9]+|Episode\\s?[0-9]+"))
|
||||
) {
|
||||
document.select("ul.idTabs li").map {
|
||||
val id = it.select("a").attr("href")
|
||||
Episode(
|
||||
data = fixUrl(document.select("div$id iframe").attr("src")),
|
||||
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) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
|
@ -113,26 +129,30 @@ class YomoviesProvider : MainAPI() {
|
|||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
app.get(data).document.select("div.movieplay iframe").map { fixUrl(it.attr("src")) }
|
||||
.apmap { source ->
|
||||
safeApiCall {
|
||||
when {
|
||||
source.startsWith("https://membed.net") -> app.get(
|
||||
source,
|
||||
referer = "$mainUrl/"
|
||||
).document.select("ul.list-server-items li")
|
||||
.apmap {
|
||||
loadExtractor(
|
||||
it.attr("data-video").substringBefore("=https://msubload"),
|
||||
"$mainUrl/",
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
}
|
||||
else -> loadExtractor(source, "$mainUrl/", subtitleCallback, callback)
|
||||
if (data.startsWith(mainUrl)) {
|
||||
app.get(data).document.select("div.movieplay iframe").map { fixUrl(it.attr("src")) }
|
||||
.apmap { source ->
|
||||
safeApiCall {
|
||||
when {
|
||||
source.startsWith("https://membed.net") -> app.get(
|
||||
source,
|
||||
referer = "$mainUrl/"
|
||||
).document.select("ul.list-server-items li")
|
||||
.apmap {
|
||||
loadExtractor(
|
||||
it.attr("data-video").substringBefore("=https://msubload"),
|
||||
"$mainUrl/",
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
}
|
||||
else -> loadExtractor(source, "$mainUrl/", subtitleCallback, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loadExtractor(data, "$mainUrl/", subtitleCallback, callback)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -232,6 +232,7 @@ val extractorApis: Array<ExtractorApi> = arrayOf(
|
|||
SBfull(),
|
||||
// Streamhub(), cause Streamhub2() works
|
||||
Streamhub2(),
|
||||
Ssbstream(),
|
||||
|
||||
FEmbed(),
|
||||
FeHD(),
|
||||
|
|
Loading…
Reference in a new issue