Skip to content
18 changes: 14 additions & 4 deletions app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ object APIHolder {
PhimmoichillProvider(),
HDrezkaProvider(),
YomoviesProvider(),

DubokuProvider(),
KisskhProvider(),

// Metadata providers
//TmdbProvider(),
Expand Down Expand Up @@ -148,12 +149,14 @@ object APIHolder {
AnimeIndoProvider(),
AnimeSailProvider(),
TocanimeProvider(),
WcofunProvider(),
//MultiAnimeProvider(),
NginxProvider(),
OlgplyProvider(),
AniflixProvider(),
KimCartoonProvider(),
XcineProvider()
XcineProvider(),
SuperStream()
)


Expand All @@ -164,6 +167,10 @@ object APIHolder {
apiMap = null
}

fun String.capitalize(): String {
return this.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
}

var apis: List<MainAPI> = arrayListOf()
var apiMap: Map<String, Int>? = null

Expand Down Expand Up @@ -557,7 +564,10 @@ fun MainAPI.fixUrlNull(url: String?): String? {
}

fun MainAPI.fixUrl(url: String): String {
if (url.startsWith("http")) {
if (url.startsWith("http") ||
// Do not fix JSON objects when passed as urls.
url.startsWith("{\"")
) {
return url
}
if (url.isEmpty()) {
Expand Down Expand Up @@ -906,7 +916,7 @@ data class MovieSearchResponse(
override var type: TvType? = null,

override var posterUrl: String? = null,
val year: Int? = null,
var year: Int? = null,
override var id: Int? = null,
override var quality: SearchQuality? = null,
override var posterHeaders: Map<String, String>? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,20 @@ class AnimeIndoProvider : MainAPI() {
}
}

override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
val document = request(mainUrl).document

val homePageList = ArrayList<HomePageList>()
override val mainPage = mainPageOf(
"$mainUrl/anime-terbaru/page/" to "Anime Terbaru",
"$mainUrl/donghua-terbaru/page/" to "Donghua Terbaru"
)

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 {
Expand All @@ -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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,18 @@ class AnimeSailProvider : MainAPI() {
)
}

override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
val document = request(mainUrl).document

val homePageList = ArrayList<HomePageList>()
override val mainPage = mainPageOf(
"$mainUrl/page/" to "Episode Terbaru",
"$mainUrl/movie-terbaru/page/" to "Movie Terbaru",
"$mainUrl/genres/donghua/page/" to "Donghua"
)

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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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?
)

}
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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 {
Expand All @@ -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()
Expand All @@ -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
Expand Down
Loading