mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
fix #425 ??
This commit is contained in:
parent
4cdfa5802d
commit
7f966fac10
13 changed files with 112 additions and 341 deletions
|
@ -4,12 +4,9 @@ import com.lagradost.cloudstream3.*
|
|||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.network.CloudflareKiller
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.httpsify
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
|
@ -18,26 +15,12 @@ class AnimeIndoProvider : MainAPI() {
|
|||
override var name = "AnimeIndo"
|
||||
override val hasMainPage = true
|
||||
override var lang = "id"
|
||||
private val cloudflareKiller by lazy { CloudflareKiller() }
|
||||
private val interceptor by lazy { CloudflareInterceptor(cloudflareKiller) }
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Anime,
|
||||
TvType.AnimeMovie,
|
||||
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 {
|
||||
fun getType(t: String): TvType {
|
||||
return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA
|
||||
|
@ -66,8 +49,7 @@ class AnimeIndoProvider : MainAPI() {
|
|||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val url = "$mainUrl/${request.data}/page/$page"
|
||||
val document = app.get(url, interceptor = interceptor).document
|
||||
val document = app.get("$mainUrl/${request.data}/page/$page").document
|
||||
val home = document.select("main#main div.animposx").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
@ -101,7 +83,6 @@ class AnimeIndoProvider : MainAPI() {
|
|||
return newAnimeSearchResponse(title, href, TvType.Anime) {
|
||||
this.posterUrl = posterUrl
|
||||
addSub(epNum)
|
||||
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -109,8 +90,7 @@ class AnimeIndoProvider : MainAPI() {
|
|||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val anime = mutableListOf<SearchResponse>()
|
||||
(1..2).forEach { page ->
|
||||
val link = "$mainUrl/page/$page/?s=$query"
|
||||
val document = app.get(link, interceptor = interceptor).document
|
||||
val document = app.get("$mainUrl/page/$page/?s=$query").document
|
||||
val media = document.select(".site-main.relat > article").mapNotNull {
|
||||
val title = it.selectFirst("div.title > h2")!!.ownText().trim()
|
||||
val href = it.selectFirst("a")!!.attr("href")
|
||||
|
@ -118,7 +98,6 @@ class AnimeIndoProvider : MainAPI() {
|
|||
val type = getType(it.select("div.type").text().trim())
|
||||
newAnimeSearchResponse(title, href, type) {
|
||||
this.posterUrl = posterUrl
|
||||
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
}
|
||||
if(media.isNotEmpty()) anime.addAll(media)
|
||||
|
@ -127,8 +106,7 @@ class AnimeIndoProvider : MainAPI() {
|
|||
}
|
||||
|
||||
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", "")
|
||||
?.trim() ?: return null
|
||||
val poster = document.selectFirst("div.thumb > img[itemprop=image]")?.attr("src")
|
||||
|
@ -168,7 +146,6 @@ class AnimeIndoProvider : MainAPI() {
|
|||
addTrailer(trailer)
|
||||
addMalId(tracker?.malId)
|
||||
addAniListId(tracker?.aniId?.toIntOrNull())
|
||||
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,12 +156,12 @@ class AnimeIndoProvider : MainAPI() {
|
|||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
val document = app.get(data, interceptor = interceptor).document
|
||||
val document = app.get(data).document
|
||||
document.select("div.itemleft > .mirror > option").mapNotNull {
|
||||
fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("src"))
|
||||
}.apmap {
|
||||
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 {
|
||||
it
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
// use an integer for version numbers
|
||||
version = 28
|
||||
version = 29
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
|
|
|
@ -6,7 +6,7 @@ import com.lagradost.cloudstream3.utils.httpsify
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
|
||||
class DutaMovie : Gomov() {
|
||||
override var mainUrl = "https://boxoffice.dutamovie21.club"
|
||||
override var mainUrl = "https://bioskop.dutamovie21.vip"
|
||||
override var name = "DutaMovie"
|
||||
override val mainPage = mainPageOf(
|
||||
"category/box-office/page/%d/" to "Box Office",
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.hexated
|
|||
import com.lagradost.cloudstream3.mainPageOf
|
||||
|
||||
class Ngefilm : Gomov() {
|
||||
override var mainUrl = "https://nge-film21.fun"
|
||||
override var mainUrl = "https://nge-film21.pics"
|
||||
override var name = "Ngefilm"
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
|
|
|
@ -9,7 +9,7 @@ import org.jsoup.nodes.Element
|
|||
import java.net.URI
|
||||
|
||||
class Nodrakorid : Gomov() {
|
||||
override var mainUrl = "https://no-drakor.xyz"
|
||||
override var mainUrl = "https://nodra-kor.xyz"
|
||||
override var name = "Nodrakorid"
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
|
|
|
@ -2,10 +2,7 @@ package com.hexated
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.network.CloudflareKiller
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
import java.net.URLDecoder
|
||||
|
@ -17,24 +14,10 @@ class Minioppai : MainAPI() {
|
|||
override var lang = "id"
|
||||
override val hasDownloadSupport = true
|
||||
override val hasQuickSearch = true
|
||||
private val cloudflareKiller by lazy { CloudflareKiller() }
|
||||
private val interceptor by lazy { CloudflareInterceptor(cloudflareKiller) }
|
||||
override val supportedTypes = setOf(
|
||||
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 {
|
||||
fun getStatus(t: String?): ShowStatus {
|
||||
return when (t) {
|
||||
|
@ -54,7 +37,7 @@ class Minioppai : MainAPI() {
|
|||
page: Int,
|
||||
request: MainPageRequest
|
||||
): 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 {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
@ -84,7 +67,6 @@ class Minioppai : MainAPI() {
|
|||
return newAnimeSearchResponse(title, href, TvType.NSFW) {
|
||||
this.posterUrl = posterUrl
|
||||
addSub(epNum)
|
||||
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -97,7 +79,6 @@ class Minioppai : MainAPI() {
|
|||
"action" to "ts_ac_do_search",
|
||||
"ts_ac_query" to query,
|
||||
), headers = mapOf("X-Requested-With" to "XMLHttpRequest"),
|
||||
interceptor = interceptor
|
||||
).parsedSafe<SearchResponses>()?.post?.firstOrNull()?.all?.mapNotNull { item ->
|
||||
newAnimeSearchResponse(
|
||||
item.postTitle ?: "",
|
||||
|
@ -105,13 +86,12 @@ class Minioppai : MainAPI() {
|
|||
TvType.NSFW
|
||||
) {
|
||||
this.posterUrl = item.postImage
|
||||
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 poster = fixUrlNull(document.selectFirst("div.limage img")?.attr("src"))
|
||||
|
@ -137,7 +117,6 @@ class Minioppai : MainAPI() {
|
|||
showStatus = status
|
||||
plot = description
|
||||
this.tags = tags
|
||||
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +126,7 @@ class Minioppai : MainAPI() {
|
|||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val document = app.get(data, interceptor = interceptor).document
|
||||
val document = app.get(data).document
|
||||
document.select("div.server ul.mirror li a").mapNotNull {
|
||||
Jsoup.parse(base64Decode(it.attr("data-em"))).select("iframe").attr("src")
|
||||
}.apmap { link ->
|
||||
|
|
|
@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty
|
|||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.network.CloudflareKiller
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import org.jsoup.nodes.Element
|
||||
|
@ -34,16 +33,11 @@ open class Movierulzhd : MainAPI() {
|
|||
"episodes" to "Episode",
|
||||
)
|
||||
|
||||
val interceptor = CloudflareKiller()
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
var 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 document = app.get("$mainUrl/${request.data}/page/$page").document
|
||||
val home =
|
||||
document.select("div.items.normal article, div#archive-content article, div.items.full article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
|
@ -79,18 +73,12 @@ open class Movierulzhd : MainAPI() {
|
|||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
this.quality = quality
|
||||
posterHeaders = interceptor.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val link = "$mainUrl/search/$query"
|
||||
var document = app.get(link).document
|
||||
if (document.select("title").text() == "Just a moment...") {
|
||||
document = app.get(link, interceptor = interceptor).document
|
||||
}
|
||||
|
||||
val document = app.get("$mainUrl/search/$query").document
|
||||
return document.select("div.result-item").map {
|
||||
val title =
|
||||
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()
|
||||
newMovieSearchResponse(title, href, TvType.TvSeries) {
|
||||
this.posterUrl = posterUrl
|
||||
posterHeaders = interceptor.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val request = app.get(url)
|
||||
var document = request.document
|
||||
if (document.select("title").text() == "Just a moment...") {
|
||||
document = app.get(url, interceptor = interceptor).document
|
||||
}
|
||||
val document = request.document
|
||||
directUrl = getBaseUrl(request.url)
|
||||
val title =
|
||||
document.selectFirst("div.data > h1")?.text()?.trim().toString()
|
||||
|
@ -142,7 +126,6 @@ open class Movierulzhd : MainAPI() {
|
|||
val recPosterUrl = it.selectFirst("img")?.imageFromElement()
|
||||
newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) {
|
||||
this.posterUrl = recPosterUrl
|
||||
posterHeaders = interceptor.getCookieHeaders(url).toMap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,7 +170,6 @@ open class Movierulzhd : MainAPI() {
|
|||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
posterHeaders = interceptor.getCookieHeaders(url).toMap()
|
||||
}
|
||||
} else {
|
||||
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
|
@ -199,7 +181,6 @@ open class Movierulzhd : MainAPI() {
|
|||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
posterHeaders = interceptor.getCookieHeaders(url).toMap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,10 +213,7 @@ open class Movierulzhd : MainAPI() {
|
|||
).parsed<ResponseHash>().embed_url
|
||||
if (!source.contains("youtube")) loadCustomExtractor(source, "$directUrl/", subtitleCallback, callback)
|
||||
} else {
|
||||
var document = app.get(data).document
|
||||
if (document.select("title").text() == "Just a moment...") {
|
||||
document = app.get(data, interceptor = interceptor).document
|
||||
}
|
||||
val document = app.get(data).document
|
||||
|
||||
document.select("ul#playeroptionsul > li").map {
|
||||
Triple(
|
||||
|
|
|
@ -4,13 +4,9 @@ import com.lagradost.cloudstream3.*
|
|||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.network.CloudflareKiller
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class Samehadaku : MainAPI() {
|
||||
|
@ -19,26 +15,12 @@ class Samehadaku : MainAPI() {
|
|||
override val hasMainPage = true
|
||||
override var lang = "id"
|
||||
override val hasDownloadSupport = true
|
||||
private val cloudflareKiller by lazy { CloudflareKiller() }
|
||||
private val interceptor by lazy { CloudflareInterceptor(cloudflareKiller) }
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Anime,
|
||||
TvType.AnimeMovie,
|
||||
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 {
|
||||
const val acefile = "https://acefile.co"
|
||||
|
||||
|
@ -69,7 +51,7 @@ class Samehadaku : MainAPI() {
|
|||
val items = mutableListOf<HomePageList>()
|
||||
|
||||
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 ->
|
||||
val header = block.selectFirst("div.widget-title h3")?.ownText() ?: return@forEach
|
||||
val home = block.select("div.animepost").mapNotNull {
|
||||
|
@ -80,8 +62,7 @@ class Samehadaku : MainAPI() {
|
|||
}
|
||||
|
||||
if (request.name == "Episode Terbaru") {
|
||||
val home =
|
||||
app.get(request.data + page, interceptor = interceptor).document.selectFirst("div.post-show")?.select("ul li")
|
||||
val home = app.get(request.data + page).document.selectFirst("div.post-show")?.select("ul li")
|
||||
?.mapNotNull {
|
||||
it.toSearchResult()
|
||||
} ?: throw ErrorLoadingException("No Media Found")
|
||||
|
@ -101,13 +82,12 @@ class Samehadaku : MainAPI() {
|
|||
return newAnimeSearchResponse(title, href ?: return null, TvType.Anime) {
|
||||
this.posterUrl = posterUrl
|
||||
addSub(epNum)
|
||||
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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 {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
@ -117,10 +97,10 @@ class Samehadaku : MainAPI() {
|
|||
val fixUrl = if (url.contains("/anime/")) {
|
||||
url
|
||||
} 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 poster = document.selectFirst("div.thumb > img")?.attr("src")
|
||||
val tags = document.select("div.genre-info > a").map { it.text() }
|
||||
|
@ -165,7 +145,6 @@ class Samehadaku : MainAPI() {
|
|||
this.recommendations = recommendations
|
||||
addMalId(tracker?.malId)
|
||||
addAniListId(tracker?.aniId?.toIntOrNull())
|
||||
posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -177,7 +156,7 @@ class Samehadaku : MainAPI() {
|
|||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
val document = app.get(data, interceptor = interceptor).document
|
||||
val document = app.get(data).document
|
||||
|
||||
argamap(
|
||||
{
|
||||
|
@ -196,7 +175,6 @@ class Samehadaku : MainAPI() {
|
|||
),
|
||||
referer = data,
|
||||
headers = mapOf("X-Requested-With" to "XMLHttpRequest"),
|
||||
interceptor = interceptor
|
||||
).document.select("iframe").attr("src")
|
||||
|
||||
loadFixedExtractor(fixedIframe(iframe), it.text(), "$mainUrl/", subtitleCallback, callback)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
// use an integer for version numbers
|
||||
version = 202
|
||||
version = 203
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
|
|
|
@ -198,9 +198,10 @@ open class VCloud : ExtractorApi() {
|
|||
val res = app.get(url)
|
||||
val doc = res.document
|
||||
val changedLink = doc.selectFirst("script:containsData(url =)")?.data()?.let {
|
||||
"""url\s*=\s*['"](.*)['"];""".toRegex().find(it)?.groupValues?.get(1)
|
||||
?.substringAfter("r=")
|
||||
} ?: doc.selectFirst("div.div.vd.d-none a")?.attr("href")
|
||||
val regex = """url\s*=\s*['"](.*)['"];""".toRegex()
|
||||
val doc2 = app.get(regex.find(it)?.groupValues?.get(1) ?: return).text
|
||||
regex.find(doc2)?.groupValues?.get(1)?.substringAfter("r=")
|
||||
}
|
||||
val header = doc.selectFirst("div.card-header")?.text()
|
||||
app.get(
|
||||
base64Decode(changedLink ?: return), cookies = res.cookies, headers = mapOf(
|
||||
|
@ -208,7 +209,7 @@ open class VCloud : ExtractorApi() {
|
|||
)
|
||||
).document.select("p.text-success ~ a").apmap {
|
||||
val link = it.attr("href")
|
||||
if (link.contains("workers.dev")) {
|
||||
if (link.contains("workers.dev") || it.text().contains("[Server : 1]")) {
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.hexated
|
|||
|
||||
import com.hexated.AESGCM.decrypt
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.unixTime
|
||||
import com.lagradost.cloudstream3.APIHolder.unixTimeMS
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||
|
@ -967,62 +968,50 @@ object SoraExtractor : SoraStream() {
|
|||
title: String? = null,
|
||||
year: Int? = null,
|
||||
season: Int? = null,
|
||||
lastSeason: Int? = null,
|
||||
episode: Int? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val slug = title.createSlug()?.replace("-", " ")
|
||||
val url = "$uhdmoviesAPI/?s=$slug"
|
||||
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 fixTitle = title.createSlug()
|
||||
val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode)
|
||||
|
||||
val detailUrl = (if (scriptData.size == 1) {
|
||||
scriptData.first()
|
||||
val url = if(season == null) {
|
||||
"$uhdmoviesAPI/download-$fixTitle-$year"
|
||||
} else {
|
||||
scriptData.find { it.second?.filterMedia(title, year, lastSeason) == true }
|
||||
})?.first
|
||||
"$uhdmoviesAPI/download-$fixTitle"
|
||||
}
|
||||
|
||||
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 }
|
||||
.filter { it.text().filterIframe(season, lastSeason, year, title) }.mapNotNull {
|
||||
if (season == null) {
|
||||
it.text() to it.nextElementSibling()?.select("a")?.attr("href")
|
||||
} else {
|
||||
it.text() to it.nextElementSibling()?.select("a")?.find { child ->
|
||||
child.select("span").text().equals("Episode $episode", true)
|
||||
}?.attr("href")
|
||||
}
|
||||
}.filter { it.second?.contains(Regex("(https:)|(http:)")) == true }
|
||||
val iSelector = if(season == null) {
|
||||
"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) {
|
||||
it.text() to it.nextElementSibling()?.select("a")?.attr("href")
|
||||
} else {
|
||||
it.text() to it.nextElementSibling()?.select("a")?.find { child ->
|
||||
child.select("span").text().equals("Episode $episode", true)
|
||||
}?.attr("href")
|
||||
}
|
||||
}.filter { it.first.contains(Regex("(2160p)|(1080p)")) }
|
||||
|
||||
iframeList.apmap { (quality, link) ->
|
||||
val driveLink =
|
||||
when {
|
||||
link?.contains("oddfirm") == true -> bypassHrefli(link)
|
||||
link?.contains("driveleech") == true -> bypassDriveleech(link)
|
||||
else -> bypassTechmny(link ?: return@apmap)
|
||||
}
|
||||
val driveLink = bypassHrefli(link ?: return@apmap)
|
||||
val base = getBaseUrl(driveLink ?: return@apmap)
|
||||
val driveReq = app.get(driveLink)
|
||||
val driveRes = driveReq.document
|
||||
val bitLink = driveRes.select("a.btn.btn-outline-success").attr("href")
|
||||
val insLink =
|
||||
driveRes.select("a.btn.btn-danger:contains(Instant Download)").attr("href")
|
||||
val insLink = driveRes.select("a.btn.btn-danger:contains(Instant Download)").attr("href")
|
||||
val downloadLink = when {
|
||||
insLink.isNotEmpty() -> extractInstantUHD(insLink)
|
||||
driveRes.select("button.btn.btn-success").text()
|
||||
.contains("Direct Download", true) -> extractDirectUHD(driveLink, driveReq)
|
||||
|
||||
bitLink.isNullOrEmpty() -> {
|
||||
val backupIframe = driveRes.select("a.btn.btn-outline-warning").attr("href")
|
||||
extractBackupUHD(backupIframe ?: return@apmap)
|
||||
}
|
||||
|
||||
else -> {
|
||||
extractMirrorUHD(bitLink, base)
|
||||
}
|
||||
|
@ -1040,10 +1029,7 @@ object SoraExtractor : SoraStream() {
|
|||
qualities
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
suspend fun invokeDotmovies(
|
||||
|
@ -1113,34 +1099,32 @@ object SoraExtractor : SoraStream() {
|
|||
val hTag = if (season == null) "h5" else "h3"
|
||||
val aTag = if (season == null) "Download Now" else "V-Cloud"
|
||||
val sTag = if (season == null) "" else "(Season $season|S$seasonSlug)"
|
||||
res.select("div.entry-content > $hTag:matches((?i)$sTag.*(1080p|2160p))")
|
||||
.filter { element -> !element.text().contains("Download", true) }.apmap {
|
||||
val tags =
|
||||
"""(?:1080p|2160p)(.*)""".toRegex().find(it.text())?.groupValues?.get(1)?.trim()
|
||||
val href =
|
||||
it.nextElementSibling()?.select("a:contains($aTag)")?.attr("href")?.let { url ->
|
||||
app.post(
|
||||
"${getBaseUrl(url)}/red.php",
|
||||
data = mapOf("link" to url),
|
||||
referer = "$api/"
|
||||
).text.substringAfter("location.href = \"").substringBefore("\"")
|
||||
}
|
||||
val selector =
|
||||
if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)"
|
||||
val server =
|
||||
app.get(
|
||||
href ?: return@apmap
|
||||
).document.selectFirst("div.entry-content > $selector")
|
||||
?.attr("href")
|
||||
loadCustomTagExtractor(
|
||||
tags,
|
||||
server ?: return@apmap,
|
||||
"$api/",
|
||||
subtitleCallback,
|
||||
callback,
|
||||
getIndexQuality(it.text())
|
||||
val entry = res.select("div.entry-content > $hTag:matches((?i)$sTag.*(1080p|2160p))")
|
||||
.findLast { element -> !element.text().contains("Download", true) } ?: return
|
||||
val tags =
|
||||
"""(?:1080p|2160p)(.*)""".toRegex().find(entry.text())?.groupValues?.get(1)?.trim()
|
||||
val href =
|
||||
entry.nextElementSibling()?.select("a:contains($aTag)")?.attr("href")
|
||||
val selector =
|
||||
if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)"
|
||||
val serverRes = app.get(
|
||||
href ?: return, interceptor = CloudflareKiller()
|
||||
).document
|
||||
val server = serverRes.selectFirst("div.entry-content > $selector")
|
||||
?.attr("href")
|
||||
loadExtractor(server ?: return, "$api/", subtitleCallback) { link ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
link.name,
|
||||
"${link.name} $tags",
|
||||
link.url,
|
||||
link.referer,
|
||||
getIndexQuality(entry.text()),
|
||||
link.type,
|
||||
link.headers,
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun invokeHdmovies4u(
|
||||
|
@ -2210,10 +2194,12 @@ object SoraExtractor : SoraStream() {
|
|||
"$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(
|
||||
"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",
|
||||
"x-requested-with" to "com.wwcinematv",
|
||||
"x-requested-with" to "XMLHttpRequest",
|
||||
)
|
||||
|
||||
val doc = app.get(url, headers = headers).document
|
||||
|
|
|
@ -116,8 +116,8 @@ open class SoraStream : TmdbProvider() {
|
|||
const val uhdmoviesAPI = "https://uhdmovies.zip"
|
||||
const val gMoviesAPI = "https://gdrivemovies.xyz"
|
||||
const val hdmovies4uAPI = "https://hdmovies4u.band"
|
||||
const val vegaMoviesAPI = "https://vegamovies.ec"
|
||||
const val dotmoviesAPI = "https://dotmovies.tokyo"
|
||||
const val vegaMoviesAPI = "https://vegamovies.dad"
|
||||
const val dotmoviesAPI = "https://dotmovies.bet"
|
||||
const val tvMoviesAPI = "https://www.tvseriesnmovies.com"
|
||||
const val moviezAddAPI = "https://ww3.moviezaddiction.click"
|
||||
const val bollyMazaAPI = "https://ww3.bollymaza.click"
|
||||
|
@ -467,7 +467,6 @@ open class SoraStream : TmdbProvider() {
|
|||
res.title,
|
||||
res.year,
|
||||
res.season,
|
||||
res.lastSeason,
|
||||
res.episode,
|
||||
callback
|
||||
)
|
||||
|
|
|
@ -8,7 +8,6 @@ import com.hexated.SoraStream.Companion.filmxyAPI
|
|||
import com.hexated.SoraStream.Companion.gdbot
|
||||
import com.hexated.SoraStream.Companion.hdmovies4uAPI
|
||||
import com.hexated.SoraStream.Companion.malsyncAPI
|
||||
import com.hexated.SoraStream.Companion.smashyStreamAPI
|
||||
import com.hexated.SoraStream.Companion.tvMoviesAPI
|
||||
import com.hexated.SoraStream.Companion.watchflxAPI
|
||||
import com.lagradost.cloudstream3.*
|
||||
|
@ -34,8 +33,6 @@ import java.security.*
|
|||
import java.security.spec.PKCS8EncodedKeySpec
|
||||
import java.security.spec.X509EncodedKeySpec
|
||||
import java.text.SimpleDateFormat
|
||||
import java.time.LocalDate
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.GCMParameterSpec
|
||||
|
@ -47,6 +44,7 @@ import kotlin.math.min
|
|||
var watchflxCookies: Map<String, String>? = null
|
||||
var filmxyCookies: Map<String, String>? = null
|
||||
var sfServer: String? = null
|
||||
var cinemaTvChecker: Boolean? = null
|
||||
|
||||
val encodedIndex = arrayOf(
|
||||
"GamMovies",
|
||||
|
@ -95,52 +93,6 @@ val mimeType = arrayOf(
|
|||
"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? {
|
||||
return this.select("div.mb-4 a").randomOrNull()
|
||||
?.attr("href")
|
||||
|
@ -632,28 +584,27 @@ suspend fun bypassFdAds(url: String?): String? {
|
|||
}
|
||||
|
||||
suspend fun bypassHrefli(url: String): String? {
|
||||
val postUrl = url.substringBefore("?id=").substringAfter("/?")
|
||||
val res = app.post(
|
||||
postUrl, data = mapOf(
|
||||
"_wp_http" to url.substringAfter("?id=")
|
||||
)
|
||||
).document
|
||||
fun Document.getFormUrl() : String {
|
||||
return this.select("form#landing").attr("action")
|
||||
}
|
||||
fun Document.getFormData() : Map<String,String> {
|
||||
return this.select("form#landing input").associate { it.attr("name") to it.attr("value") }
|
||||
}
|
||||
|
||||
val link = res.select("form#landing").attr("action")
|
||||
val wpHttp = res.select("input[name=_wp_http2]").attr("value")
|
||||
val token = res.select("input[name=token]").attr("value")
|
||||
val host = getBaseUrl(url)
|
||||
var res = app.get(url).document
|
||||
var formUrl = res.getFormUrl()
|
||||
var formData = res.getFormData()
|
||||
|
||||
val blogRes = app.post(
|
||||
link, data = mapOf(
|
||||
"_wp_http2" to wpHttp,
|
||||
"token" to token
|
||||
)
|
||||
).text
|
||||
res = app.post(formUrl, data = formData).document
|
||||
formUrl = res.getFormUrl()
|
||||
formData = res.getFormData()
|
||||
|
||||
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(
|
||||
"$postUrl?go=$skToken", cookies = mapOf(
|
||||
skToken to wpHttp
|
||||
"$host?go=$skToken", cookies = mapOf(
|
||||
skToken to "${formData["_wp_http2"]}"
|
||||
)
|
||||
).document.selectFirst("meta[http-equiv=refresh]")?.attr("content")?.substringAfter("url=")
|
||||
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))
|
||||
}
|
||||
|
||||
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?>? {
|
||||
|
||||
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 fetchSfServer(): String {
|
||||
|
@ -1410,7 +1283,7 @@ private enum class Symbol(val decimalValue: Int) {
|
|||
|
||||
companion object {
|
||||
fun closestBelow(value: Int) =
|
||||
values()
|
||||
entries.toTypedArray()
|
||||
.sortedByDescending { it.decimalValue }
|
||||
.firstOrNull { value >= it.decimalValue }
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue