This commit is contained in:
jack 2023-12-11 11:24:12 +07:00
parent 4cdfa5802d
commit 7f966fac10
13 changed files with 112 additions and 341 deletions

View file

@ -4,12 +4,9 @@ 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
@ -18,26 +15,12 @@ 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
@ -66,8 +49,7 @@ class AnimeIndoProvider : MainAPI() {
page: Int, page: Int,
request: MainPageRequest request: MainPageRequest
): HomePageResponse { ): HomePageResponse {
val url = "$mainUrl/${request.data}/page/$page" val document = app.get("$mainUrl/${request.data}/page/$page").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()
} }
@ -101,7 +83,6 @@ 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()
} }
} }
@ -109,8 +90,7 @@ class AnimeIndoProvider : MainAPI() {
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val anime = mutableListOf<SearchResponse>() val anime = mutableListOf<SearchResponse>()
(1..2).forEach { page -> (1..2).forEach { page ->
val link = "$mainUrl/page/$page/?s=$query" val document = app.get("$mainUrl/page/$page/?s=$query").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")
@ -118,7 +98,6 @@ 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)
@ -127,8 +106,7 @@ class AnimeIndoProvider : MainAPI() {
} }
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val document = app.get(url, interceptor = interceptor).document val document = app.get(url).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
val poster = document.selectFirst("div.thumb > img[itemprop=image]")?.attr("src") val poster = document.selectFirst("div.thumb > img[itemprop=image]")?.attr("src")
@ -168,7 +146,6 @@ 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()
} }
} }
@ -179,12 +156,12 @@ class AnimeIndoProvider : MainAPI() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val document = app.get(data, interceptor = interceptor).document val document = app.get(data).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/", interceptor = interceptor).document.select("iframe").attr("src") app.get(it, referer = "$mainUrl/").document.select("iframe").attr("src")
} else { } else {
it it
} }

View file

@ -1,7 +1,7 @@
import org.jetbrains.kotlin.konan.properties.Properties import org.jetbrains.kotlin.konan.properties.Properties
// use an integer for version numbers // use an integer for version numbers
version = 28 version = 29
android { android {
defaultConfig { defaultConfig {

View file

@ -6,7 +6,7 @@ import com.lagradost.cloudstream3.utils.httpsify
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
class DutaMovie : Gomov() { class DutaMovie : Gomov() {
override var mainUrl = "https://boxoffice.dutamovie21.club" override var mainUrl = "https://bioskop.dutamovie21.vip"
override var name = "DutaMovie" override var name = "DutaMovie"
override val mainPage = mainPageOf( override val mainPage = mainPageOf(
"category/box-office/page/%d/" to "Box Office", "category/box-office/page/%d/" to "Box Office",

View file

@ -3,7 +3,7 @@ package com.hexated
import com.lagradost.cloudstream3.mainPageOf import com.lagradost.cloudstream3.mainPageOf
class Ngefilm : Gomov() { class Ngefilm : Gomov() {
override var mainUrl = "https://nge-film21.fun" override var mainUrl = "https://nge-film21.pics"
override var name = "Ngefilm" override var name = "Ngefilm"
override val mainPage = mainPageOf( override val mainPage = mainPageOf(

View file

@ -9,7 +9,7 @@ import org.jsoup.nodes.Element
import java.net.URI import java.net.URI
class Nodrakorid : Gomov() { class Nodrakorid : Gomov() {
override var mainUrl = "https://no-drakor.xyz" override var mainUrl = "https://nodra-kor.xyz"
override var name = "Nodrakorid" override var name = "Nodrakorid"
override val mainPage = mainPageOf( override val mainPage = mainPageOf(

View file

@ -2,10 +2,7 @@ package com.hexated
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.network.CloudflareKiller
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import okhttp3.Interceptor
import okhttp3.Response
import org.jsoup.Jsoup import org.jsoup.Jsoup
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import java.net.URLDecoder import java.net.URLDecoder
@ -17,24 +14,10 @@ class Minioppai : MainAPI() {
override var lang = "id" override var lang = "id"
override val hasDownloadSupport = true override val hasDownloadSupport = true
override val hasQuickSearch = true override val hasQuickSearch = true
private val cloudflareKiller by lazy { CloudflareKiller() }
private val interceptor by lazy { CloudflareInterceptor(cloudflareKiller) }
override val supportedTypes = setOf( override val supportedTypes = setOf(
TvType.NSFW, TvType.NSFW,
) )
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 getStatus(t: String?): ShowStatus { fun getStatus(t: String?): ShowStatus {
return when (t) { return when (t) {
@ -54,7 +37,7 @@ class Minioppai : MainAPI() {
page: Int, page: Int,
request: MainPageRequest request: MainPageRequest
): HomePageResponse { ): HomePageResponse {
val document = app.get("${request.data}/page/$page", interceptor = interceptor).document val document = app.get("${request.data}/page/$page").document
val home = document.select("div.latest a").mapNotNull { val home = document.select("div.latest a").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
@ -84,7 +67,6 @@ class Minioppai : MainAPI() {
return newAnimeSearchResponse(title, href, TvType.NSFW) { return newAnimeSearchResponse(title, href, TvType.NSFW) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
addSub(epNum) addSub(epNum)
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
} }
} }
@ -97,7 +79,6 @@ class Minioppai : MainAPI() {
"action" to "ts_ac_do_search", "action" to "ts_ac_do_search",
"ts_ac_query" to query, "ts_ac_query" to query,
), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"),
interceptor = interceptor
).parsedSafe<SearchResponses>()?.post?.firstOrNull()?.all?.mapNotNull { item -> ).parsedSafe<SearchResponses>()?.post?.firstOrNull()?.all?.mapNotNull { item ->
newAnimeSearchResponse( newAnimeSearchResponse(
item.postTitle ?: "", item.postTitle ?: "",
@ -105,13 +86,12 @@ class Minioppai : MainAPI() {
TvType.NSFW TvType.NSFW
) { ) {
this.posterUrl = item.postImage this.posterUrl = item.postImage
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
} }
} }
} }
override suspend fun load(url: String): LoadResponse? { override suspend fun load(url: String): LoadResponse? {
val document = app.get(url, interceptor = interceptor).document val document = app.get(url).document
val title = document.selectFirst("h1.entry-title")?.text()?.trim() ?: return null val title = document.selectFirst("h1.entry-title")?.text()?.trim() ?: return null
val poster = fixUrlNull(document.selectFirst("div.limage img")?.attr("src")) val poster = fixUrlNull(document.selectFirst("div.limage img")?.attr("src"))
@ -137,7 +117,6 @@ class Minioppai : MainAPI() {
showStatus = status showStatus = status
plot = description plot = description
this.tags = tags this.tags = tags
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
} }
} }
@ -147,7 +126,7 @@ class Minioppai : MainAPI() {
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val document = app.get(data, interceptor = interceptor).document val document = app.get(data).document
document.select("div.server ul.mirror li a").mapNotNull { document.select("div.server ul.mirror li a").mapNotNull {
Jsoup.parse(base64Decode(it.attr("data-em"))).select("iframe").attr("src") Jsoup.parse(base64Decode(it.attr("data-em"))).select("iframe").attr("src")
}.apmap { link -> }.apmap { link ->

View file

@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty
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.network.CloudflareKiller
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.toJson
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
@ -34,16 +33,11 @@ open class Movierulzhd : MainAPI() {
"episodes" to "Episode", "episodes" to "Episode",
) )
val interceptor = CloudflareKiller()
override suspend fun getMainPage( override suspend fun getMainPage(
page: Int, page: Int,
request: MainPageRequest request: MainPageRequest
): HomePageResponse { ): HomePageResponse {
var document = app.get("$mainUrl/${request.data}/page/$page").document val document = app.get("$mainUrl/${request.data}/page/$page").document
if (document.select("title").text() == "Just a moment...") {
document = app.get(request.data + page, interceptor = interceptor).document
}
val home = val home =
document.select("div.items.normal article, div#archive-content article, div.items.full article").mapNotNull { document.select("div.items.normal article, div#archive-content article, div.items.full article").mapNotNull {
it.toSearchResult() it.toSearchResult()
@ -79,18 +73,12 @@ open class Movierulzhd : MainAPI() {
return newMovieSearchResponse(title, href, TvType.Movie) { return newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
this.quality = quality this.quality = quality
posterHeaders = interceptor.getCookieHeaders(mainUrl).toMap()
} }
} }
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val link = "$mainUrl/search/$query" val document = app.get("$mainUrl/search/$query").document
var document = app.get(link).document
if (document.select("title").text() == "Just a moment...") {
document = app.get(link, interceptor = interceptor).document
}
return document.select("div.result-item").map { return document.select("div.result-item").map {
val title = val title =
it.selectFirst("div.title > a")!!.text().replace(Regex("\\(\\d{4}\\)"), "").trim() it.selectFirst("div.title > a")!!.text().replace(Regex("\\(\\d{4}\\)"), "").trim()
@ -98,17 +86,13 @@ open class Movierulzhd : MainAPI() {
val posterUrl = it.selectFirst("img")!!.attr("src").toString() val posterUrl = it.selectFirst("img")!!.attr("src").toString()
newMovieSearchResponse(title, href, TvType.TvSeries) { newMovieSearchResponse(title, href, TvType.TvSeries) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
posterHeaders = interceptor.getCookieHeaders(mainUrl).toMap()
} }
} }
} }
override suspend fun load(url: String): LoadResponse { override suspend fun load(url: String): LoadResponse {
val request = app.get(url) val request = app.get(url)
var document = request.document val document = request.document
if (document.select("title").text() == "Just a moment...") {
document = app.get(url, interceptor = interceptor).document
}
directUrl = getBaseUrl(request.url) directUrl = getBaseUrl(request.url)
val title = val title =
document.selectFirst("div.data > h1")?.text()?.trim().toString() document.selectFirst("div.data > h1")?.text()?.trim().toString()
@ -142,7 +126,6 @@ open class Movierulzhd : MainAPI() {
val recPosterUrl = it.selectFirst("img")?.imageFromElement() val recPosterUrl = it.selectFirst("img")?.imageFromElement()
newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) { newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) {
this.posterUrl = recPosterUrl this.posterUrl = recPosterUrl
posterHeaders = interceptor.getCookieHeaders(url).toMap()
} }
} }
@ -187,7 +170,6 @@ open class Movierulzhd : MainAPI() {
addActors(actors) addActors(actors)
this.recommendations = recommendations this.recommendations = recommendations
addTrailer(trailer) addTrailer(trailer)
posterHeaders = interceptor.getCookieHeaders(url).toMap()
} }
} else { } else {
newMovieLoadResponse(title, url, TvType.Movie, url) { newMovieLoadResponse(title, url, TvType.Movie, url) {
@ -199,7 +181,6 @@ open class Movierulzhd : MainAPI() {
addActors(actors) addActors(actors)
this.recommendations = recommendations this.recommendations = recommendations
addTrailer(trailer) addTrailer(trailer)
posterHeaders = interceptor.getCookieHeaders(url).toMap()
} }
} }
} }
@ -232,10 +213,7 @@ open class Movierulzhd : MainAPI() {
).parsed<ResponseHash>().embed_url ).parsed<ResponseHash>().embed_url
if (!source.contains("youtube")) loadCustomExtractor(source, "$directUrl/", subtitleCallback, callback) if (!source.contains("youtube")) loadCustomExtractor(source, "$directUrl/", subtitleCallback, callback)
} else { } else {
var document = app.get(data).document val document = app.get(data).document
if (document.select("title").text() == "Just a moment...") {
document = app.get(data, interceptor = interceptor).document
}
document.select("ul#playeroptionsul > li").map { document.select("ul#playeroptionsul > li").map {
Triple( Triple(

View file

@ -4,13 +4,9 @@ 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.Qualities import com.lagradost.cloudstream3.utils.Qualities
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.nodes.Element import org.jsoup.nodes.Element
class Samehadaku : MainAPI() { class Samehadaku : MainAPI() {
@ -19,26 +15,12 @@ class Samehadaku : MainAPI() {
override val hasMainPage = true override val hasMainPage = true
override var lang = "id" override var lang = "id"
override val hasDownloadSupport = true override val hasDownloadSupport = true
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 {
const val acefile = "https://acefile.co" const val acefile = "https://acefile.co"
@ -69,7 +51,7 @@ class Samehadaku : MainAPI() {
val items = mutableListOf<HomePageList>() val items = mutableListOf<HomePageList>()
if (request.name != "Episode Terbaru" && page <= 1) { if (request.name != "Episode Terbaru" && page <= 1) {
val doc = app.get(request.data, interceptor = interceptor).document val doc = app.get(request.data).document
doc.select("div.widget_senction:not(:contains(Baca Komik))").forEach { block -> doc.select("div.widget_senction:not(:contains(Baca Komik))").forEach { block ->
val header = block.selectFirst("div.widget-title h3")?.ownText() ?: return@forEach val header = block.selectFirst("div.widget-title h3")?.ownText() ?: return@forEach
val home = block.select("div.animepost").mapNotNull { val home = block.select("div.animepost").mapNotNull {
@ -80,8 +62,7 @@ class Samehadaku : MainAPI() {
} }
if (request.name == "Episode Terbaru") { if (request.name == "Episode Terbaru") {
val home = val home = app.get(request.data + page).document.selectFirst("div.post-show")?.select("ul li")
app.get(request.data + page, interceptor = interceptor).document.selectFirst("div.post-show")?.select("ul li")
?.mapNotNull { ?.mapNotNull {
it.toSearchResult() it.toSearchResult()
} ?: throw ErrorLoadingException("No Media Found") } ?: throw ErrorLoadingException("No Media Found")
@ -101,13 +82,12 @@ class Samehadaku : MainAPI() {
return newAnimeSearchResponse(title, href ?: return null, TvType.Anime) { return newAnimeSearchResponse(title, href ?: return null, TvType.Anime) {
this.posterUrl = posterUrl this.posterUrl = posterUrl
addSub(epNum) addSub(epNum)
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
} }
} }
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val document = app.get("$mainUrl/?s=$query", interceptor = interceptor).document val document = app.get("$mainUrl/?s=$query").document
return document.select("main#main div.animepost").mapNotNull { return document.select("main#main div.animepost").mapNotNull {
it.toSearchResult() it.toSearchResult()
} }
@ -117,10 +97,10 @@ class Samehadaku : MainAPI() {
val fixUrl = if (url.contains("/anime/")) { val fixUrl = if (url.contains("/anime/")) {
url url
} else { } else {
app.get(url, interceptor = interceptor).document.selectFirst("div.nvs.nvsc a")?.attr("href") app.get(url).document.selectFirst("div.nvs.nvsc a")?.attr("href")
} }
val document = app.get(fixUrl ?: return null, interceptor = interceptor).document val document = app.get(fixUrl ?: return null).document
val title = document.selectFirst("h1.entry-title")?.text()?.removeBloat() ?: return null val title = document.selectFirst("h1.entry-title")?.text()?.removeBloat() ?: return null
val poster = document.selectFirst("div.thumb > img")?.attr("src") val poster = document.selectFirst("div.thumb > img")?.attr("src")
val tags = document.select("div.genre-info > a").map { it.text() } val tags = document.select("div.genre-info > a").map { it.text() }
@ -165,7 +145,6 @@ class Samehadaku : MainAPI() {
this.recommendations = recommendations this.recommendations = recommendations
addMalId(tracker?.malId) addMalId(tracker?.malId)
addAniListId(tracker?.aniId?.toIntOrNull()) addAniListId(tracker?.aniId?.toIntOrNull())
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
} }
} }
@ -177,7 +156,7 @@ class Samehadaku : MainAPI() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val document = app.get(data, interceptor = interceptor).document val document = app.get(data).document
argamap( argamap(
{ {
@ -196,7 +175,6 @@ class Samehadaku : MainAPI() {
), ),
referer = data, referer = data,
headers = mapOf("X-Requested-With" to "XMLHttpRequest"), headers = mapOf("X-Requested-With" to "XMLHttpRequest"),
interceptor = interceptor
).document.select("iframe").attr("src") ).document.select("iframe").attr("src")
loadFixedExtractor(fixedIframe(iframe), it.text(), "$mainUrl/", subtitleCallback, callback) loadFixedExtractor(fixedIframe(iframe), it.text(), "$mainUrl/", subtitleCallback, callback)

View file

@ -1,7 +1,7 @@
import org.jetbrains.kotlin.konan.properties.Properties import org.jetbrains.kotlin.konan.properties.Properties
// use an integer for version numbers // use an integer for version numbers
version = 202 version = 203
android { android {
defaultConfig { defaultConfig {

View file

@ -198,9 +198,10 @@ open class VCloud : ExtractorApi() {
val res = app.get(url) val res = app.get(url)
val doc = res.document val doc = res.document
val changedLink = doc.selectFirst("script:containsData(url =)")?.data()?.let { val changedLink = doc.selectFirst("script:containsData(url =)")?.data()?.let {
"""url\s*=\s*['"](.*)['"];""".toRegex().find(it)?.groupValues?.get(1) val regex = """url\s*=\s*['"](.*)['"];""".toRegex()
?.substringAfter("r=") val doc2 = app.get(regex.find(it)?.groupValues?.get(1) ?: return).text
} ?: doc.selectFirst("div.div.vd.d-none a")?.attr("href") regex.find(doc2)?.groupValues?.get(1)?.substringAfter("r=")
}
val header = doc.selectFirst("div.card-header")?.text() val header = doc.selectFirst("div.card-header")?.text()
app.get( app.get(
base64Decode(changedLink ?: return), cookies = res.cookies, headers = mapOf( base64Decode(changedLink ?: return), cookies = res.cookies, headers = mapOf(
@ -208,7 +209,7 @@ open class VCloud : ExtractorApi() {
) )
).document.select("p.text-success ~ a").apmap { ).document.select("p.text-success ~ a").apmap {
val link = it.attr("href") val link = it.attr("href")
if (link.contains("workers.dev")) { if (link.contains("workers.dev") || it.text().contains("[Server : 1]")) {
callback.invoke( callback.invoke(
ExtractorLink( ExtractorLink(
this.name, this.name,

View file

@ -2,6 +2,7 @@ package com.hexated
import com.hexated.AESGCM.decrypt import com.hexated.AESGCM.decrypt
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.unixTime
import com.lagradost.cloudstream3.APIHolder.unixTimeMS import com.lagradost.cloudstream3.APIHolder.unixTimeMS
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
@ -967,30 +968,26 @@ object SoraExtractor : SoraStream() {
title: String? = null, title: String? = null,
year: Int? = null, year: Int? = null,
season: Int? = null, season: Int? = null,
lastSeason: Int? = null,
episode: Int? = null, episode: Int? = null,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
) { ) {
val slug = title.createSlug()?.replace("-", " ") val fixTitle = title.createSlug()
val url = "$uhdmoviesAPI/?s=$slug" val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode)
var doc = app.get(url).document
if (doc.select("title").text() == "Just a moment...") {
doc = app.get(url, interceptor = CloudflareKiller()).document
}
val scriptData = doc.select("div.row.gridlove-posts article").map {
it.selectFirst("a")?.attr("href") to it.selectFirst("h1")?.text()
}
val detailUrl = (if (scriptData.size == 1) { val url = if(season == null) {
scriptData.first() "$uhdmoviesAPI/download-$fixTitle-$year"
} else { } else {
scriptData.find { it.second?.filterMedia(title, year, lastSeason) == true } "$uhdmoviesAPI/download-$fixTitle"
})?.first }
val detailDoc = app.get(detailUrl ?: return).document val detailDoc = app.get(url, interceptor = CloudflareKiller()).document
val iframeList = detailDoc.select("div.entry-content p").map { it } val iSelector = if(season == null) {
.filter { it.text().filterIframe(season, lastSeason, year, title) }.mapNotNull { "div.entry-content p:has(:matches($year))"
} else {
"div.entry-content p:has(:matches((?i)(?:S\\s*$seasonSlug|Season\\s*$seasonSlug)))"
}
val iframeList = detailDoc.select(iSelector).mapNotNull {
if (season == null) { if (season == null) {
it.text() to it.nextElementSibling()?.select("a")?.attr("href") it.text() to it.nextElementSibling()?.select("a")?.attr("href")
} else { } else {
@ -998,31 +995,23 @@ object SoraExtractor : SoraStream() {
child.select("span").text().equals("Episode $episode", true) child.select("span").text().equals("Episode $episode", true)
}?.attr("href") }?.attr("href")
} }
}.filter { it.second?.contains(Regex("(https:)|(http:)")) == true } }.filter { it.first.contains(Regex("(2160p)|(1080p)")) }
iframeList.apmap { (quality, link) -> iframeList.apmap { (quality, link) ->
val driveLink = val driveLink = bypassHrefli(link ?: return@apmap)
when {
link?.contains("oddfirm") == true -> bypassHrefli(link)
link?.contains("driveleech") == true -> bypassDriveleech(link)
else -> bypassTechmny(link ?: return@apmap)
}
val base = getBaseUrl(driveLink ?: return@apmap) val base = getBaseUrl(driveLink ?: return@apmap)
val driveReq = app.get(driveLink) val driveReq = app.get(driveLink)
val driveRes = driveReq.document val driveRes = driveReq.document
val bitLink = driveRes.select("a.btn.btn-outline-success").attr("href") val bitLink = driveRes.select("a.btn.btn-outline-success").attr("href")
val insLink = val insLink = driveRes.select("a.btn.btn-danger:contains(Instant Download)").attr("href")
driveRes.select("a.btn.btn-danger:contains(Instant Download)").attr("href")
val downloadLink = when { val downloadLink = when {
insLink.isNotEmpty() -> extractInstantUHD(insLink) insLink.isNotEmpty() -> extractInstantUHD(insLink)
driveRes.select("button.btn.btn-success").text() driveRes.select("button.btn.btn-success").text()
.contains("Direct Download", true) -> extractDirectUHD(driveLink, driveReq) .contains("Direct Download", true) -> extractDirectUHD(driveLink, driveReq)
bitLink.isNullOrEmpty() -> { bitLink.isNullOrEmpty() -> {
val backupIframe = driveRes.select("a.btn.btn-outline-warning").attr("href") val backupIframe = driveRes.select("a.btn.btn-outline-warning").attr("href")
extractBackupUHD(backupIframe ?: return@apmap) extractBackupUHD(backupIframe ?: return@apmap)
} }
else -> { else -> {
extractMirrorUHD(bitLink, base) extractMirrorUHD(bitLink, base)
} }
@ -1040,10 +1029,7 @@ object SoraExtractor : SoraStream() {
qualities qualities
) )
) )
} }
} }
suspend fun invokeDotmovies( suspend fun invokeDotmovies(
@ -1113,32 +1099,30 @@ object SoraExtractor : SoraStream() {
val hTag = if (season == null) "h5" else "h3" val hTag = if (season == null) "h5" else "h3"
val aTag = if (season == null) "Download Now" else "V-Cloud" val aTag = if (season == null) "Download Now" else "V-Cloud"
val sTag = if (season == null) "" else "(Season $season|S$seasonSlug)" val sTag = if (season == null) "" else "(Season $season|S$seasonSlug)"
res.select("div.entry-content > $hTag:matches((?i)$sTag.*(1080p|2160p))") val entry = res.select("div.entry-content > $hTag:matches((?i)$sTag.*(1080p|2160p))")
.filter { element -> !element.text().contains("Download", true) }.apmap { .findLast { element -> !element.text().contains("Download", true) } ?: return
val tags = val tags =
"""(?:1080p|2160p)(.*)""".toRegex().find(it.text())?.groupValues?.get(1)?.trim() """(?:1080p|2160p)(.*)""".toRegex().find(entry.text())?.groupValues?.get(1)?.trim()
val href = val href =
it.nextElementSibling()?.select("a:contains($aTag)")?.attr("href")?.let { url -> entry.nextElementSibling()?.select("a:contains($aTag)")?.attr("href")
app.post(
"${getBaseUrl(url)}/red.php",
data = mapOf("link" to url),
referer = "$api/"
).text.substringAfter("location.href = \"").substringBefore("\"")
}
val selector = val selector =
if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)" if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)"
val server = val serverRes = app.get(
app.get( href ?: return, interceptor = CloudflareKiller()
href ?: return@apmap ).document
).document.selectFirst("div.entry-content > $selector") val server = serverRes.selectFirst("div.entry-content > $selector")
?.attr("href") ?.attr("href")
loadCustomTagExtractor( loadExtractor(server ?: return, "$api/", subtitleCallback) { link ->
tags, callback.invoke(
server ?: return@apmap, ExtractorLink(
"$api/", link.name,
subtitleCallback, "${link.name} $tags",
callback, link.url,
getIndexQuality(it.text()) link.referer,
getIndexQuality(entry.text()),
link.type,
link.headers,
)
) )
} }
} }
@ -2210,10 +2194,12 @@ object SoraExtractor : SoraStream() {
"$cinemaTvAPI/shows/play/$id-$slug-$year" "$cinemaTvAPI/shows/play/$id-$slug-$year"
} }
val specialCookies = "PHPSESSID=e555h63ilisoj2l6j7b5d4jb6p; _csrf=9597150e45f485ad9c4f2e06a2572534d8415337eda9d48d0ecfa25b73b6a9e1a%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%222HcnegjGB0nX205FAUPb86fqMx9HWIF1%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0"
getCinemaChecker(specialCookies)
val headers = mapOf( val headers = mapOf(
"Cookie" to "PHPSESSID=e555h63ilisoj2l6j7b5d4jb6p; _csrf=9597150e45f485ad9c4f2e06a2572534d8415337eda9d48d0ecfa25b73b6a9e1a%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%222HcnegjGB0nX205FAUPb86fqMx9HWIF1%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTimeMS.4.0.1.$unixTimeMS.0.0.0", "Cookie" to specialCookies,
"Connection" to "keep-alive", "Connection" to "keep-alive",
"x-requested-with" to "com.wwcinematv", "x-requested-with" to "XMLHttpRequest",
) )
val doc = app.get(url, headers = headers).document val doc = app.get(url, headers = headers).document

View file

@ -116,8 +116,8 @@ open class SoraStream : TmdbProvider() {
const val uhdmoviesAPI = "https://uhdmovies.zip" const val uhdmoviesAPI = "https://uhdmovies.zip"
const val gMoviesAPI = "https://gdrivemovies.xyz" const val gMoviesAPI = "https://gdrivemovies.xyz"
const val hdmovies4uAPI = "https://hdmovies4u.band" const val hdmovies4uAPI = "https://hdmovies4u.band"
const val vegaMoviesAPI = "https://vegamovies.ec" const val vegaMoviesAPI = "https://vegamovies.dad"
const val dotmoviesAPI = "https://dotmovies.tokyo" const val dotmoviesAPI = "https://dotmovies.bet"
const val tvMoviesAPI = "https://www.tvseriesnmovies.com" const val tvMoviesAPI = "https://www.tvseriesnmovies.com"
const val moviezAddAPI = "https://ww3.moviezaddiction.click" const val moviezAddAPI = "https://ww3.moviezaddiction.click"
const val bollyMazaAPI = "https://ww3.bollymaza.click" const val bollyMazaAPI = "https://ww3.bollymaza.click"
@ -467,7 +467,6 @@ open class SoraStream : TmdbProvider() {
res.title, res.title,
res.year, res.year,
res.season, res.season,
res.lastSeason,
res.episode, res.episode,
callback callback
) )

View file

@ -8,7 +8,6 @@ import com.hexated.SoraStream.Companion.filmxyAPI
import com.hexated.SoraStream.Companion.gdbot import com.hexated.SoraStream.Companion.gdbot
import com.hexated.SoraStream.Companion.hdmovies4uAPI import com.hexated.SoraStream.Companion.hdmovies4uAPI
import com.hexated.SoraStream.Companion.malsyncAPI import com.hexated.SoraStream.Companion.malsyncAPI
import com.hexated.SoraStream.Companion.smashyStreamAPI
import com.hexated.SoraStream.Companion.tvMoviesAPI import com.hexated.SoraStream.Companion.tvMoviesAPI
import com.hexated.SoraStream.Companion.watchflxAPI import com.hexated.SoraStream.Companion.watchflxAPI
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
@ -34,8 +33,6 @@ import java.security.*
import java.security.spec.PKCS8EncodedKeySpec import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec import java.security.spec.X509EncodedKeySpec
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.* import java.util.*
import javax.crypto.Cipher import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec import javax.crypto.spec.GCMParameterSpec
@ -47,6 +44,7 @@ import kotlin.math.min
var watchflxCookies: Map<String, String>? = null var watchflxCookies: Map<String, String>? = null
var filmxyCookies: Map<String, String>? = null var filmxyCookies: Map<String, String>? = null
var sfServer: String? = null var sfServer: String? = null
var cinemaTvChecker: Boolean? = null
val encodedIndex = arrayOf( val encodedIndex = arrayOf(
"GamMovies", "GamMovies",
@ -95,52 +93,6 @@ val mimeType = arrayOf(
"video/x-msvideo" "video/x-msvideo"
) )
fun String.filterIframe(
seasonNum: Int? = null,
lastSeason: Int? = null,
year: Int?,
title: String?
): Boolean {
val slug = title.createSlug()
val dotSlug = slug?.replace("-", ".")
val spaceSlug = slug?.replace("-", " ")
return if (seasonNum != null) {
if (lastSeason == 1) {
this.contains(Regex("(?i)(S0?$seasonNum)|(Season\\s0?$seasonNum)|(\\d{3,4}p)")) && !this.contains(
"Download",
true
)
} else {
this.contains(Regex("(?i)(S0?$seasonNum)|(Season\\s0?$seasonNum)")) && !this.contains(
"Download",
true
)
}
} else {
this.contains(Regex("(?i)($year)|($dotSlug)|($spaceSlug)")) && !this.contains(
"Download",
true
)
}
}
fun String.filterMedia(title: String?, yearNum: Int?, seasonNum: Int?): Boolean {
val fixTitle = title.createSlug()?.replace("-", " ")
return if (seasonNum != null) {
when {
seasonNum > 1 -> this.contains(Regex("(?i)(Season\\s0?1-0?$seasonNum)|(S0?1-S?0?$seasonNum)")) && this.contains(
Regex("(?i)($fixTitle)|($title)")
)
else -> this.contains(Regex("(?i)(Season\\s0?1)|(S0?1)")) && this.contains(
Regex("(?i)($fixTitle)|($title)")
) && this.contains("$yearNum")
}
} else {
this.contains(Regex("(?i)($fixTitle)|($title)")) && this.contains("$yearNum")
}
}
fun Document.getMirrorLink(): String? { fun Document.getMirrorLink(): String? {
return this.select("div.mb-4 a").randomOrNull() return this.select("div.mb-4 a").randomOrNull()
?.attr("href") ?.attr("href")
@ -632,28 +584,27 @@ suspend fun bypassFdAds(url: String?): String? {
} }
suspend fun bypassHrefli(url: String): String? { suspend fun bypassHrefli(url: String): String? {
val postUrl = url.substringBefore("?id=").substringAfter("/?") fun Document.getFormUrl() : String {
val res = app.post( return this.select("form#landing").attr("action")
postUrl, data = mapOf( }
"_wp_http" to url.substringAfter("?id=") fun Document.getFormData() : Map<String,String> {
) return this.select("form#landing input").associate { it.attr("name") to it.attr("value") }
).document }
val link = res.select("form#landing").attr("action") val host = getBaseUrl(url)
val wpHttp = res.select("input[name=_wp_http2]").attr("value") var res = app.get(url).document
val token = res.select("input[name=token]").attr("value") var formUrl = res.getFormUrl()
var formData = res.getFormData()
val blogRes = app.post( res = app.post(formUrl, data = formData).document
link, data = mapOf( formUrl = res.getFormUrl()
"_wp_http2" to wpHttp, formData = res.getFormData()
"token" to token
)
).text
val skToken = blogRes.substringAfter("?go=").substringBefore("\"") res = app.post(formUrl, data = formData).document
val skToken = res.selectFirst("script:containsData(?go=)")?.data()?.substringAfter("?go=")?.substringBefore("\"") ?: return null
val driveUrl = app.get( val driveUrl = app.get(
"$postUrl?go=$skToken", cookies = mapOf( "$host?go=$skToken", cookies = mapOf(
skToken to wpHttp skToken to "${formData["_wp_http2"]}"
) )
).document.selectFirst("meta[http-equiv=refresh]")?.attr("content")?.substringAfter("url=") ).document.selectFirst("meta[http-equiv=refresh]")?.attr("content")?.substringAfter("url=")
val path = app.get(driveUrl ?: return null).text.substringAfter("replace(\"") val path = app.get(driveUrl ?: return null).text.substringAfter("replace(\"")
@ -662,94 +613,6 @@ suspend fun bypassHrefli(url: String): String? {
return fixUrl(path, getBaseUrl(driveUrl)) return fixUrl(path, getBaseUrl(driveUrl))
} }
suspend fun bypassTechmny(url: String): String? {
val techRes = app.get(url).document
val postUrl = url.substringBefore("?id=").substringAfter("/?")
val (goUrl, goHeader) = if (techRes.selectFirst("form#landing input[name=_wp_http_c]") != null) {
var res = app.post(
postUrl, data = mapOf(
"_wp_http_c" to url.substringAfter("?id=")
)
)
val (longC, catC, _) = getTechmnyCookies(res.text)
var headers = mapOf("Cookie" to "$longC; $catC")
var formLink = res.document.selectFirst("center a")?.attr("href")
res = app.get(formLink ?: return null, headers = headers)
val (longC2, _, postC) = getTechmnyCookies(res.text)
headers = mapOf("Cookie" to "$catC; $longC2; $postC")
formLink = res.document.selectFirst("center a")?.attr("href")
res = app.get(formLink ?: return null, headers = headers)
val goToken = res.text.substringAfter("?go=").substringBefore("\"")
val tokenUrl = "$postUrl?go=$goToken"
val newLongC = "$goToken=" + longC2.substringAfter("=")
headers = mapOf("Cookie" to "$catC; rdst_post=; $newLongC")
Pair(tokenUrl, headers)
} else {
val secondPage = techRes.getNextTechPage().document
val thirdPage = secondPage.getNextTechPage().text
val goToken = thirdPage.substringAfter("?go=").substringBefore("\"")
val tokenUrl = "$postUrl?go=$goToken"
val headers = mapOf(
"Cookie" to "$goToken=${
secondPage.select("form#landing input[name=_wp_http2]").attr("value")
}"
)
Pair(tokenUrl, headers)
}
val driveUrl =
app.get(goUrl, headers = goHeader).document.selectFirst("meta[http-equiv=refresh]")
?.attr("content")?.substringAfter("url=")
val path = app.get(driveUrl ?: return null).text.substringAfter("replace(\"")
.substringBefore("\")")
if (path == "/404") return null
return fixUrl(path, getBaseUrl(driveUrl))
}
private suspend fun Document.getNextTechPage(): NiceResponse {
return app.post(
this.select("form").attr("action"),
data = this.select("form input").mapNotNull {
it.attr("name") to it.attr("value")
}.toMap().toMutableMap()
)
}
suspend fun bypassDriveleech(url: String): String? {
val path = app.get(url).text.substringAfter("replace(\"")
.substringBefore("\")")
if (path == "/404") return null
return fixUrl(path, getBaseUrl(url))
}
private fun getTechmnyCookies(page: String): Triple<String, String, String> {
val cat = "rdst_cat"
val post = "rdst_post"
val longC = page.substringAfter(".setTime")
.substringAfter("document.cookie = \"")
.substringBefore("\"")
.substringBefore(";")
val catC = if (page.contains("$cat=")) {
page.substringAfterLast("$cat=")
.substringBefore(";").let {
"$cat=$it"
}
} else {
""
}
val postC = if (page.contains("$post=")) {
page.substringAfterLast("$post=")
.substringBefore(";").let {
"$post=$it"
}
} else {
""
}
return Triple(longC, catC, postC)
}
suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair<String, String?>? { suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair<String, String?>? {
val req = app.get(url) val req = app.get(url)
@ -780,6 +643,16 @@ suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair<St
} }
} }
suspend fun getCinemaChecker(cookie: String) = cinemaTvChecker ?: fetchCinemaChecker(cookie).also { cinemaTvChecker = it }
suspend fun fetchCinemaChecker(cookie: String): Boolean? {
return app.post(
base64Decode("aHR0cHM6Ly9jaW5lbWEud2l3aWNlbnRlci5jb20vYXBpL3YxL2Nvb2tpZQ=="),
data = mapOf("cookie" to cookie),
headers = mapOf("App-version" to "3.4", "Authorization" to "Basic d2l3aTpXaXdpQDIwMjA=")
).parsedSafe<Map<String,Boolean?>>()?.get("success")
}
suspend fun getSfServer() = sfServer ?: fetchSfServer().also { sfServer = it } suspend fun getSfServer() = sfServer ?: fetchSfServer().also { sfServer = it }
suspend fun fetchSfServer(): String { suspend fun fetchSfServer(): String {
@ -1410,7 +1283,7 @@ private enum class Symbol(val decimalValue: Int) {
companion object { companion object {
fun closestBelow(value: Int) = fun closestBelow(value: Int) =
values() entries.toTypedArray()
.sortedByDescending { it.decimalValue } .sortedByDescending { it.decimalValue }
.firstOrNull { value >= it.decimalValue } .firstOrNull { value >= it.decimalValue }
} }