This commit is contained in:
helo 2023-10-21 16:18:16 +07:00
parent c954c59215
commit 249879f4d6
4 changed files with 65 additions and 34 deletions

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 14 version = 15
cloudstream { cloudstream {

View file

@ -4,9 +4,12 @@ import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.network.CloudflareKiller
import com.lagradost.cloudstream3.utils.ExtractorLink 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 okhttp3.Interceptor
import okhttp3.Response
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
@ -15,13 +18,26 @@ class AnimeIndoProvider : MainAPI() {
override var name = "AnimeIndo" override var name = "AnimeIndo"
override val hasMainPage = true override val hasMainPage = true
override var lang = "id" override var lang = "id"
private val cloudflareKiller by lazy { CloudflareKiller() }
private val interceptor by lazy { CloudflareInterceptor(cloudflareKiller) }
override val supportedTypes = setOf( override val supportedTypes = setOf(
TvType.Anime, TvType.Anime,
TvType.AnimeMovie, TvType.AnimeMovie,
TvType.OVA TvType.OVA
) )
class CloudflareInterceptor(private val cloudflareKiller: CloudflareKiller): Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val response = chain.proceed(request)
val doc = Jsoup.parse(response.peekBody(1024 * 1024).string())
if (doc.select("title").text() == "Just a moment...") {
return cloudflareKiller.intercept(chain)
}
return response
}
}
companion object { companion object {
fun getType(t: String): TvType { fun getType(t: String): TvType {
return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA
@ -51,7 +67,7 @@ class AnimeIndoProvider : MainAPI() {
request: MainPageRequest request: MainPageRequest
): HomePageResponse { ): HomePageResponse {
val url = "$mainUrl/${request.data}/page/$page" val url = "$mainUrl/${request.data}/page/$page"
val document = app.get(url).document val document = app.get(url, interceptor = interceptor).document
val home = document.select("main#main div.animposx").mapNotNull { val home = document.select("main#main div.animposx").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
@ -85,6 +101,7 @@ class AnimeIndoProvider : MainAPI() {
return newAnimeSearchResponse(title, href, TvType.Anime) { return newAnimeSearchResponse(title, href, TvType.Anime) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
addSub(epNum) addSub(epNum)
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
} }
} }
@ -93,7 +110,7 @@ class AnimeIndoProvider : MainAPI() {
val anime = mutableListOf<SearchResponse>() val anime = mutableListOf<SearchResponse>()
(1..2).forEach { page -> (1..2).forEach { page ->
val link = "$mainUrl/page/$page/?s=$query" val link = "$mainUrl/page/$page/?s=$query"
val document = app.get(link).document val document = app.get(link, interceptor = interceptor).document
val media = document.select(".site-main.relat > article").mapNotNull { val media = document.select(".site-main.relat > article").mapNotNull {
val title = it.selectFirst("div.title > h2")!!.ownText().trim() val title = it.selectFirst("div.title > h2")!!.ownText().trim()
val href = it.selectFirst("a")!!.attr("href") val href = it.selectFirst("a")!!.attr("href")
@ -101,6 +118,7 @@ class AnimeIndoProvider : MainAPI() {
val type = getType(it.select("div.type").text().trim()) val type = getType(it.select("div.type").text().trim())
newAnimeSearchResponse(title, href, type) { newAnimeSearchResponse(title, href, type) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
} }
} }
if(media.isNotEmpty()) anime.addAll(media) if(media.isNotEmpty()) anime.addAll(media)
@ -109,7 +127,7 @@ class AnimeIndoProvider : 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, interceptor = interceptor).document
val title = document.selectFirst("h1.entry-title")?.text()?.replace("Subtitle Indonesia", "") val title = document.selectFirst("h1.entry-title")?.text()?.replace("Subtitle Indonesia", "")
?.trim() ?: return null ?.trim() ?: return null
@ -150,6 +168,7 @@ class AnimeIndoProvider : MainAPI() {
addTrailer(trailer) addTrailer(trailer)
addMalId(tracker?.malId) addMalId(tracker?.malId)
addAniListId(tracker?.aniId?.toIntOrNull()) addAniListId(tracker?.aniId?.toIntOrNull())
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
} }
} }
@ -160,12 +179,12 @@ class AnimeIndoProvider : MainAPI() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val document = app.get(data).document val document = app.get(data, interceptor = interceptor).document
document.select("div.itemleft > .mirror > option").mapNotNull { document.select("div.itemleft > .mirror > option").mapNotNull {
fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("src")) fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("src"))
}.apmap { }.apmap {
if (it.startsWith(mainUrl)) { if (it.startsWith(mainUrl)) {
app.get(it, referer = "$mainUrl/").document.select("iframe").attr("src") app.get(it, referer = "$mainUrl/", interceptor = interceptor).document.select("iframe").attr("src")
} else { } else {
it it
} }

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 5 version = 6
cloudstream { cloudstream {

View file

@ -3,13 +3,14 @@ package com.hexated
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.net.URI
import java.net.URLDecoder import java.net.URLDecoder
class PhimmoichillProvider : MainAPI() { class PhimmoichillProvider : MainAPI() {
override var mainUrl = "https://phimmoichillg.net" override var mainUrl = "https://phimmoichillh.net"
private var directUrl = mainUrl
override var name = "Phimmoichill" override var name = "Phimmoichill"
override val hasMainPage = true override val hasMainPage = true
override var lang = "vi" override var lang = "vi"
@ -90,25 +91,32 @@ class PhimmoichillProvider : MainAPI() {
} }
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val document = app.get(url).document val request = app.get(url)
directUrl = getBaseUrl(request.url)
val document = request.document
val title = document.selectFirst("h1[itemprop=name]")?.text()?.trim().toString() val title = document.selectFirst("h1[itemprop=name]")?.text()?.trim().toString()
val link = document.select("ul.list-button li:last-child a").attr("href") val link = document.select("ul.list-button li:last-child a").attr("href")
val poster = document.selectFirst("div.image img[itemprop=image]")?.attr("src") val poster = document.selectFirst("div.image img[itemprop=image]")?.attr("src")
val tags = document.select("ul.entry-meta.block-film li:nth-child(4) a").map { it.text()!!.substringAfter("Phim") } val tags = document.select("ul.entry-meta.block-film li:nth-child(4) a")
.map { it.text().substringAfter("Phim") }
val year = document.select("ul.entry-meta.block-film li:nth-child(2) a").text().trim() val year = document.select("ul.entry-meta.block-film li:nth-child(2) a").text().trim()
.toIntOrNull() .toIntOrNull()
val tvType = if (document.select("div.latest-episode").isNotEmpty() val tvType = if (document.select("div.latest-episode").isNotEmpty()
) TvType.TvSeries else TvType.Movie ) TvType.TvSeries else TvType.Movie
val description = document.select("div#film-content").text().substringAfter("Full HD Vietsub Thuyết Minh").substringBefore("@phimmoi").trim() val description =
document.select("div#film-content").text().substringAfter("Full HD Vietsub Thuyết Minh")
.substringBefore("@phimmoi").trim()
val trailer = document.select("body script") val trailer = document.select("body script")
.find { it.data().contains("youtube.com") }?.data()?.substringAfterLast("file: \"")?.substringBefore("\",") .find { it.data().contains("youtube.com") }?.data()?.substringAfterLast("file: \"")
?.substringBefore("\",")
val rating = val rating =
document.select("ul.entry-meta.block-film li:nth-child(7) span").text().toRatingInt() document.select("ul.entry-meta.block-film li:nth-child(7) span").text().toRatingInt()
val actors = document.select("ul.entry-meta.block-film li:last-child a").map { it.text() } val actors = document.select("ul.entry-meta.block-film li:last-child a").map { it.text() }
val recommendations = document.select("ul#list-film-realted li.item").map { val recommendations = document.select("ul#list-film-realted li.item").map {
it.toSearchResult().apply { it.toSearchResult().apply {
this.posterUrl = decode(it.selectFirst("img")!!.attr("data-src").substringAfter("url=")) this.posterUrl =
decode(it.selectFirst("img")!!.attr("data-src").substringAfter("url="))
} }
} }
@ -159,39 +167,43 @@ class PhimmoichillProvider : MainAPI() {
val key = document.select("div#content script") val key = document.select("div#content script")
.find { it.data().contains("filmInfo.episodeID =") }?.data()?.let { script -> .find { it.data().contains("filmInfo.episodeID =") }?.data()?.let { script ->
val id = script.substringAfter("filmInfo.episodeID = parseInt('") val id = script.substringAfter("parseInt('").substringBefore("'")
app.post( app.post(
url = "${this.mainUrl}/chillsplayer.php", url = "$directUrl/chillsplayer.php",
data = mapOf("qcao" to id, "sv" to "0"), data = mapOf("qcao" to id),
referer = data, referer = data,
headers = mapOf( headers = mapOf(
"X-Requested-With" to "XMLHttpRequest", "X-Requested-With" to "XMLHttpRequest",
"Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8" "Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8"
) )
).text.substringAfterLast("iniPlayers(\"") ).text.substringAfterLast("iniPlayers(\"")
.substringBefore("\",") .substringBefore("\"")
} }
listOf( listOf(
Pair("https://so-trym.topphimmoi.org/raw/$key/index.m3u8", "PMFAST"), Pair("https://sotrim.topphimmoi.org/raw/$key/index.m3u8", "PMFAST"),
Pair("https://dash.megacdn.xyz/raw/$key/index.m3u8", "PMHLS"), Pair("https://dash.megacdn.xyz/raw/$key/index.m3u8", "PMHLS"),
Pair("https://so-trym.phimchill.net/dash/$key/index.m3u8", "PMPRO"), Pair("https://so-trym.phimchill.net/dash/$key/index.m3u8", "PMPRO"),
Pair("https://dash.megacdn.xyz/dast/$key/index.m3u8", "PMBK") Pair("https://dash.megacdn.xyz/dast/$key/index.m3u8", "PMBK")
).apmap { (link, source) -> ).map { (link, source) ->
safeApiCall {
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
source, source,
source, source,
link, link,
referer = "$mainUrl/", referer = "$directUrl/",
quality = Qualities.P1080.value, quality = Qualities.P1080.value,
isM3u8 = true, INFER_TYPE,
) )
) )
} }
}
return true return true
} }
private fun getBaseUrl(url: String): String {
return URI(url).let {
"${it.scheme}://${it.host}"
}
}
} }