This commit is contained in:
hexated 2023-09-26 12:45:33 +07:00
parent 207f8359c2
commit f4f5ee5f5b
9 changed files with 184 additions and 33 deletions

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 = 15 version = 16
android { android {
defaultConfig { defaultConfig {

View file

@ -1,6 +1,14 @@
package com.hexated package com.hexated
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.ErrorLoadingException
import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.extractors.* import com.lagradost.cloudstream3.extractors.*
import com.lagradost.cloudstream3.extractors.helper.AesHelper
import com.lagradost.cloudstream3.utils.AppUtils
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
class Doods : DoodLaExtractor() { class Doods : DoodLaExtractor() {
override var name = "Doods" override var name = "Doods"
@ -35,3 +43,60 @@ class Likessb : StreamSB() {
class DbGdriveplayer : Gdriveplayer() { class DbGdriveplayer : Gdriveplayer() {
override var mainUrl = "https://database.gdriveplayer.us" override var mainUrl = "https://database.gdriveplayer.us"
} }
class NineTv {
companion object {
private const val key = "B#8G4o2\$WWFz"
suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val mainUrl = getBaseUrl(url)
val master = Regex("MasterJS\\s*=\\s*'([^']+)").find(
app.get(
url,
referer = referer
).text
)?.groupValues?.get(1)
val decrypt = AesHelper.cryptoAESHandler(master ?: return, key.toByteArray(), false)
?.replace("\\", "") ?: throw ErrorLoadingException("failed to decrypt")
val name = url.getHost()
val source = Regex(""""?file"?:\s*"([^"]+)""").find(decrypt)?.groupValues?.get(1)
val tracks = Regex("""tracks:\s*\[(.+)]""").find(decrypt)?.groupValues?.get(1)
M3u8Helper.generateM3u8(
name,
source ?: return,
"$mainUrl/",
headers = mapOf(
"Accept" to "*/*",
"Connection" to "keep-alive",
"Sec-Fetch-Dest" to "empty",
"Sec-Fetch-Mode" to "cors",
"Sec-Fetch-Site" to "cross-site",
"Origin" to mainUrl,
)
).forEach(callback)
AppUtils.tryParseJson<List<Tracks>>("[$tracks]")
?.filter { it.kind == "captions" }?.map { track ->
subtitleCallback.invoke(
SubtitleFile(
track.label ?: "",
track.file ?: return@map null
)
)
}
}
}
data class Tracks(
@JsonProperty("file") val file: String? = null,
@JsonProperty("label") val label: String? = null,
@JsonProperty("kind") val kind: String? = null,
)
}

View file

@ -21,6 +21,8 @@ open class Gomov : MainAPI() {
TvType.AsianDrama TvType.AsianDrama
) )
val sources = arrayOf("https://chillx.top", "https://watchx.top", "https://bestx.stream")
override val mainPage = mainPageOf( override val mainPage = mainPageOf(
"page/%d/?s&search=advanced&post_type=movie" to "Movies", "page/%d/?s&search=advanced&post_type=movie" to "Movies",
"category/western-series/page/%d/" to "Western Series", "category/western-series/page/%d/" to "Western Series",
@ -154,19 +156,31 @@ open class Gomov : MainAPI() {
val id = document.selectFirst("div#muvipro_player_content_id")?.attr("data-id") val id = document.selectFirst("div#muvipro_player_content_id")?.attr("data-id")
if(id.isNullOrEmpty()) { if(id.isNullOrEmpty()) {
document.select("ul.muvipro-player-tabs li a").apmap { document.select("ul.muvipro-player-tabs li a").apmap { ele ->
val iframe = app.get(fixUrl(it.attr("href"))).document.selectFirst("div.gmr-embed-responsive iframe") val iframe = app.get(fixUrl(ele.attr("href"))).document.selectFirst("div.gmr-embed-responsive iframe")
?.attr("src") ?.attr("src")?.let { httpsify(it) } ?: return@apmap
loadExtractor(httpsify(iframe ?: return@apmap ), "$directUrl/", subtitleCallback, callback)
when {
sources.any { iframe.startsWith(it) } -> NineTv.getUrl(iframe, "$directUrl/", subtitleCallback, callback)
else -> {
loadExtractor(iframe, "$directUrl/", subtitleCallback, callback)
}
}
} }
} else { } else {
document.select("div.tab-content-ajax").apmap { document.select("div.tab-content-ajax").apmap { ele ->
val server = app.post( val server = app.post(
"$directUrl/wp-admin/admin-ajax.php", "$directUrl/wp-admin/admin-ajax.php",
data = mapOf("action" to "muvipro_player_content", "tab" to it.attr("id"), "post_id" to "$id") data = mapOf("action" to "muvipro_player_content", "tab" to ele.attr("id"), "post_id" to "$id")
).document.select("iframe").attr("src") ).document.select("iframe").attr("src").let { httpsify(it) }
when {
sources.any { server.startsWith(it) } -> NineTv.getUrl(server, "$directUrl/", subtitleCallback, callback)
else -> {
loadExtractor(server, "$directUrl/", subtitleCallback, callback)
}
}
loadExtractor(httpsify(server), "$directUrl/", subtitleCallback, callback)
} }
} }
@ -174,17 +188,21 @@ open class Gomov : MainAPI() {
} }
private fun String?.fixImageQuality(): String? { }
fun String?.fixImageQuality(): String? {
if(this == null) return null if(this == null) return null
val regex = Regex("(-\\d*x\\d*)").find(this)?.groupValues val regex = Regex("(-\\d*x\\d*)").find(this)?.groupValues
if(regex?.isEmpty() == true) return this if(regex?.isEmpty() == true) return this
return this.replace(regex?.get(0) ?: return null, "") return this.replace(regex?.get(0) ?: return null, "")
} }
private fun getBaseUrl(url: String): String { fun getBaseUrl(url: String): String {
return URI(url).let { return URI(url).let {
"${it.scheme}://${it.host}" "${it.scheme}://${it.host}"
} }
} }
fun String.getHost(): String {
return fixTitle(URI(this).host.substringBeforeLast(".").substringAfterLast("."))
} }

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 = 174 version = 175
android { android {
defaultConfig { defaultConfig {

View file

@ -6,14 +6,15 @@ import com.lagradost.cloudstream3.extractors.StreamSB
import com.lagradost.cloudstream3.extractors.Voe import com.lagradost.cloudstream3.extractors.Voe
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
import com.lagradost.cloudstream3.ErrorLoadingException
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.base64Decode import com.lagradost.cloudstream3.base64Decode
import com.lagradost.cloudstream3.extractors.Pixeldrain import com.lagradost.cloudstream3.extractors.Pixeldrain
import com.lagradost.cloudstream3.extractors.helper.AesHelper
import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.*
import java.math.BigInteger import java.math.BigInteger
import java.net.URI
import java.security.MessageDigest import java.security.MessageDigest
open class Playm4u : ExtractorApi() { open class Playm4u : ExtractorApi() {
@ -234,6 +235,63 @@ open class VCloud : ExtractorApi() {
} }
class NineTv {
companion object {
private const val key = "B#8G4o2\$WWFz"
suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val mainUrl = getBaseUrl(url)
val master = Regex("MasterJS\\s*=\\s*'([^']+)").find(
app.get(
url,
referer = referer
).text
)?.groupValues?.get(1)
val decrypt = AesHelper.cryptoAESHandler(master ?: return, key.toByteArray(), false)
?.replace("\\", "") ?: throw ErrorLoadingException("failed to decrypt")
val name = url.getHost()
val source = Regex(""""?file"?:\s*"([^"]+)""").find(decrypt)?.groupValues?.get(1)
val tracks = Regex("""tracks:\s*\[(.+)]""").find(decrypt)?.groupValues?.get(1)
M3u8Helper.generateM3u8(
name,
source ?: return,
"$mainUrl/",
headers = mapOf(
"Accept" to "*/*",
"Connection" to "keep-alive",
"Sec-Fetch-Dest" to "empty",
"Sec-Fetch-Mode" to "cors",
"Sec-Fetch-Site" to "cross-site",
"Origin" to mainUrl,
)
).forEach(callback)
AppUtils.tryParseJson<List<Tracks>>("[$tracks]")
?.filter { it.kind == "captions" }?.map { track ->
subtitleCallback.invoke(
SubtitleFile(
track.label ?: "",
track.file ?: return@map null
)
)
}
}
}
data class Tracks(
@JsonProperty("file") val file: String? = null,
@JsonProperty("label") val label: String? = null,
@JsonProperty("kind") val kind: String? = null,
)
}
class Hubcloud : VCloud() { class Hubcloud : VCloud() {
override val name = "Hubcloud" override val name = "Hubcloud"
override val mainUrl = "https://hubcloud.in" override val mainUrl = "https://hubcloud.in"
@ -272,3 +330,4 @@ class Yipsu : Voe() {
override val name = "Yipsu" override val name = "Yipsu"
override var mainUrl = "https://yip.su" override var mainUrl = "https://yip.su"
} }

View file

@ -304,11 +304,15 @@ object SoraExtractor : SoraStream() {
else -> it.embed_url else -> it.embed_url
} }
} ?: return@apmap } ?: return@apmap
if (!source.contains("youtube")) { val sources = arrayOf("https://chillx.top", "https://watchx.top", "https://bestx.stream")
when {
sources.any { source.startsWith(it) } -> NineTv.getUrl(source, "$referer/", subtitleCallback, callback)
!source.contains("youtube") -> {
loadCustomExtractor(name, source, "$referer/", subtitleCallback, callback) loadCustomExtractor(name, source, "$referer/", subtitleCallback, callback)
} }
} }
} }
}
suspend fun invokeDoomovies( suspend fun invokeDoomovies(
title: String? = null, title: String? = null,
@ -2289,9 +2293,9 @@ object SoraExtractor : SoraStream() {
"$nineTvAPI/tv/$tmdbId-$season-$episode" "$nineTvAPI/tv/$tmdbId-$season-$episode"
} }
val iframe = app.get(url, referer = "https://pressplay.top/").document.selectFirst("iframe") val iframe = app.get(url, referer = "https://pressplay.top/").document.selectFirst("iframe")?.attr("src")
?.attr("src") ?: return
loadExtractor(iframe, "$nineTvAPI/", subtitleCallback, callback) NineTv.getUrl(iframe ?: return, "$nineTvAPI/", subtitleCallback, callback)
} }

View file

@ -118,7 +118,7 @@ open class SoraStream : TmdbProvider() {
const val emoviesAPI = "https://emovies.si" const val emoviesAPI = "https://emovies.si"
const val pobmoviesAPI = "https://pobmovies.cam" const val pobmoviesAPI = "https://pobmovies.cam"
const val multimoviesAPI = "https://multi-movies.xyz" const val multimoviesAPI = "https://multi-movies.xyz"
const val netmoviesAPI = "https://web.netmovies.to" const val netmoviesAPI = "https://netmovies.to"
const val momentAPI = "https://moment-explanation-i-244.site" const val momentAPI = "https://moment-explanation-i-244.site"
const val doomoviesAPI = "https://doomovies.net" const val doomoviesAPI = "https://doomovies.net"
const val primewireAPI = "https://real-primewire.club" const val primewireAPI = "https://real-primewire.club"
@ -626,7 +626,7 @@ open class SoraStream : TmdbProvider() {
if (!res.isAnime) invokeNowTv(res.id, res.season, res.episode, callback) if (!res.isAnime) invokeNowTv(res.id, res.season, res.episode, callback)
}, },
{ {
if (res.season == null) invokeRidomovies(res.title, res.year, callback) if (!res.isAnime && res.season == null) invokeRidomovies(res.title, res.year, callback)
}, },
{ {
invokeNavy(res.imdbId, res.season, res.episode, callback) invokeNavy(res.imdbId, res.season, res.episode, callback)

View file

@ -231,7 +231,7 @@ class SoraStreamLite : SoraStream() {
invokeNavy(res.imdbId, res.season, res.episode, callback) invokeNavy(res.imdbId, res.season, res.episode, callback)
}, },
{ {
if (res.season == null) invokeRidomovies( if (!res.isAnime && res.season == null) invokeRidomovies(
res.title, res.title,
res.year, res.year,
callback callback

View file

@ -1079,8 +1079,9 @@ suspend fun loadCustomExtractor(
name ?: link.name, name ?: link.name,
link.url, link.url,
link.referer, link.referer,
when (link.type) { when {
ExtractorLinkType.M3U8 -> link.quality link.type == ExtractorLinkType.M3U8 -> link.quality
link.name == "VidSrc" -> Qualities.P1080.value
else -> quality ?: link.quality else -> quality ?: link.quality
}, },
link.type, link.type,
@ -1321,6 +1322,10 @@ fun getBaseUrl(url: String): String {
} }
} }
fun String.getHost(): String {
return fixTitle(URI(this).host.substringBeforeLast(".").substringAfterLast("."))
}
fun isUpcoming(dateString: String?): Boolean { fun isUpcoming(dateString: String?): Boolean {
return try { return try {
val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())