Merge branch 'master' into adityajd-patch-1

This commit is contained in:
adityajd 2023-12-14 10:01:27 +07:00 committed by GitHub
commit 81e43f707f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 704 additions and 816 deletions

View File

@ -43,10 +43,6 @@ jobs:
- name: Access Secrets
env:
TMDB_API: ${{ secrets.TMDB_API }}
SORA_API: ${{ secrets.SORA_API }}
SORAHE: ${{ secrets.SORAHE }}
SORAXA: ${{ secrets.SORAXA }}
SORATED: ${{ secrets.SORATED }}
DUMP_API: ${{ secrets.DUMP_API }}
DUMP_KEY: ${{ secrets.DUMP_KEY }}
CRUNCHYROLL_BASIC_TOKEN: ${{ secrets.CRUNCHYROLL_BASIC_TOKEN }}
@ -55,16 +51,13 @@ jobs:
ANICHI_SERVER: ${{ secrets.ANICHI_SERVER }}
ANICHI_ENDPOINT: ${{ secrets.ANICHI_ENDPOINT }}
ANICHI_APP: ${{ secrets.ANICHI_APP }}
PRIMEWIRE_KEY: ${{ secrets.PRIMEWIRE_KEY }}
ZSHOW_API: ${{ secrets.ZSHOW_API }}
SFMOVIES_API: ${{ secrets.SFMOVIES_API }}
CINEMATV_API: ${{ secrets.CINEMATV_API }}
OMOVIES_API: ${{ secrets.OMOVIES_API }}
run: |
cd $GITHUB_WORKSPACE/src
echo SORA_API=$SORA_API >> local.properties
echo TMDB_API=$TMDB_API >> local.properties
echo SORAHE=$SORAHE >> local.properties
echo SORAXA=$SORAXA >> local.properties
echo SORATED=$SORATED >> local.properties
echo DUMP_API=$DUMP_API >> local.properties
echo DUMP_KEY=$DUMP_KEY >> local.properties
echo CRUNCHYROLL_BASIC_TOKEN=$CRUNCHYROLL_BASIC_TOKEN >> local.properties
@ -73,9 +66,10 @@ jobs:
echo ANICHI_SERVER=$ANICHI_SERVER >> local.properties
echo ANICHI_ENDPOINT=$ANICHI_ENDPOINT >> local.properties
echo ANICHI_APP=$ANICHI_APP >> local.properties
echo PRIMEWIRE_KEY=$PRIMEWIRE_KEY >> local.properties
echo ZSHOW_API=$ZSHOW_API >> local.properties
echo SFMOVIES_API=$SFMOVIES_API >> local.properties
echo CINEMATV_API=$CINEMATV_API >> local.properties
echo OMOVIES_API=$OMOVIES_API >> local.properties
- name: Build Plugins
run: |
@ -85,10 +79,10 @@ jobs:
cp **/build/*.cs3 $GITHUB_WORKSPACE/builds
cp build/plugins.json $GITHUB_WORKSPACE/builds
- name: Move Loklok
- name: Move Kuramanime
run: |
rm $GITHUB_WORKSPACE/builds/Loklok.cs3 || true
cp $GITHUB_WORKSPACE/builds/stored/Loklok.cs3 $GITHUB_WORKSPACE/builds
rm $GITHUB_WORKSPACE/builds/KuramanimeProvider.cs3 || true
cp $GITHUB_WORKSPACE/builds/stored/KuramanimeProvider.cs3 $GITHUB_WORKSPACE/builds
- name: Push builds
run: |

View File

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

View File

@ -138,7 +138,7 @@ class Animasu : MainAPI() {
document.select(".mobius > .mirror > option").mapNotNull {
fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("src")) to it.text()
}.apmap { (iframe, quality) ->
loadFixedExtractor(iframe, quality, "$mainUrl/", subtitleCallback, callback)
loadFixedExtractor(iframe.fixIframe(), quality, "$mainUrl/", subtitleCallback, callback)
}
return true
}
@ -157,7 +157,7 @@ class Animasu : MainAPI() {
link.name,
link.url,
link.referer,
if(link.type != ExtractorLinkType.M3U8) getIndexQuality(quality) else link.quality,
if(link.type == ExtractorLinkType.M3U8 || link.name == "Uservideo") link.quality else getIndexQuality(quality),
link.type,
link.headers,
link.extractorData
@ -166,6 +166,14 @@ class Animasu : MainAPI() {
}
}
private fun String.fixIframe() : String {
return if(this.startsWith("https://dl.berkasdrive.com")) {
base64Decode(this.substringAfter("id="))
} else {
this
}
}
private fun getIndexQuality(str: String?): Int {
return Regex("(\\d{3,4})[pP]").find(str ?: "")?.groupValues?.getOrNull(1)?.toIntOrNull()
?: Qualities.Unknown.value

View File

@ -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
}

View File

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

View File

@ -6,8 +6,12 @@ import com.lagradost.cloudstream3.utils.httpsify
import com.lagradost.cloudstream3.utils.loadExtractor
class DutaMovie : Gomov() {
override var mainUrl = "https://cinema.dutamovie21.vip"
override var name = "DutaMovie"
override var name = "DutaMovie"
override val mainPage = mainPageOf(
"category/box-office/page/%d/" to "Box Office",
"category/serial-tv/page/%d/" to "Serial TV",

View File

@ -1,21 +1,14 @@
package com.hexated
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.ErrorLoadingException
import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.base64Decode
import com.lagradost.cloudstream3.extractors.*
import com.lagradost.cloudstream3.extractors.helper.AesHelper
import com.lagradost.cloudstream3.utils.AppUtils
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper
import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.nodes.Document
import org.mozilla.javascript.Context
import org.mozilla.javascript.Scriptable
open class Uplayer : ExtractorApi() {
override val name = "Uplayer"
@ -94,81 +87,4 @@ class Likessb : StreamSB() {
class DbGdriveplayer : Gdriveplayer() {
override var mainUrl = "https://database.gdriveplayer.us"
}
object NineTv {
suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val mainUrl = getBaseUrl(url)
val res = app.get(url, headers = mapOf(
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language" to "en-US,en;q=0.5",
"Referer" to (referer ?: ""),
))
val master = Regex("\\s*=\\s*'([^']+)").find(res.text)?.groupValues?.get(1)
val key = "tSIsE8FgpRkv3QQQ"
val decrypt = AesHelper.cryptoAESHandler(master ?: return, key.toByteArray(), false)
?.replace("\\", "")
?: throw ErrorLoadingException("failed to decrypt")
val source = Regex(""""?file"?:\s*"([^"]+)""").find(decrypt)?.groupValues?.get(1)
val tracks = Regex("""tracks:\s*\[(.+)]""").find(decrypt)?.groupValues?.get(1)
val name = url.getHost()
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
)
)
}
}
private fun Document.getKeys(): String? {
val script = (this.selectFirst("script:containsData(eval\\()")?.data()
?.replace("eval(", "var result=")?.removeSuffix(");") + ";").trimIndent()
val run = script.runJS("result")
return """,\s*'([^']+)""".toRegex().find(run)?.groupValues?.getOrNull(1)
}
private fun String.runJS(variable: String): String {
val rhino = Context.enter()
rhino.optimizationLevel = -1
val scope: Scriptable = rhino.initSafeStandardObjects()
val result: String
try {
rhino.evaluateString(scope, this, "JavaScript", 1, null)
result = Context.toString(scope.get(variable, scope))
} finally {
Context.exit()
}
return result
}
data class Tracks(
@JsonProperty("file") val file: String? = null,
@JsonProperty("label") val label: String? = null,
@JsonProperty("kind") val kind: String? = null,
)
}

View File

@ -20,7 +20,6 @@ open class Gomov : MainAPI() {
TvType.TvSeries,
TvType.AsianDrama
)
private val sources = arrayOf("https://chillx.top", "https://watchx.top", "https://bestx.stream")
override val mainPage = mainPageOf(
"page/%d/?s&search=advanced&post_type=movie" to "Movies",
@ -46,7 +45,7 @@ open class Gomov : MainAPI() {
private fun Element.toSearchResult(): SearchResponse? {
val title = this.selectFirst("h2.entry-title > a")?.text()?.trim() ?: return null
val href = fixUrl(this.selectFirst("a")!!.attr("href"))
val posterUrl = fixUrlNull(this.selectFirst("a > img").getImgAttr()).fixImageQuality()
val posterUrl = fixUrlNull(this.selectFirst("a > img")?.getImageAttr()).fixImageQuality()
val quality = this.select("div.gmr-qual, div.gmr-quality-item > a").text().trim().replace("-", "")
return if (quality.isEmpty()) {
val episode =
@ -67,7 +66,7 @@ open class Gomov : MainAPI() {
private fun Element.toRecommendResult(): SearchResponse? {
val title = this.selectFirst("a > span.idmuvi-rp-title")?.text()?.trim() ?: return null
val href = this.selectFirst("a")!!.attr("href")
val posterUrl = fixUrlNull(this.selectFirst("a > img").getImgAttr().fixImageQuality())
val posterUrl = fixUrlNull(this.selectFirst("a > img")?.getImageAttr().fixImageQuality())
return newMovieSearchResponse(title, href, TvType.Movie) {
this.posterUrl = posterUrl
}
@ -89,7 +88,7 @@ open class Gomov : MainAPI() {
document.selectFirst("h1.entry-title")?.text()?.substringBefore("Season")?.substringBefore("Episode")?.trim()
.toString()
val poster =
fixUrlNull(document.selectFirst("figure.pull-left > img").getImgAttr())?.fixImageQuality()
fixUrlNull(document.selectFirst("figure.pull-left > img")?.getImageAttr())?.fixImageQuality()
val tags = document.select("span.gmr-movie-genre:contains(Genre:) > a").map { it.text() }
val year =
@ -159,12 +158,7 @@ open class Gomov : MainAPI() {
val iframe = app.get(fixUrl(ele.attr("href"))).document.selectFirst("div.gmr-embed-responsive iframe")
.getIframeAttr()?.let { httpsify(it) } ?: return@apmap
when {
sources.any { iframe.startsWith(it) } -> NineTv.getUrl(iframe, "$directUrl/", subtitleCallback, callback)
else -> {
loadExtractor(iframe, "$directUrl/", subtitleCallback, callback)
}
}
loadExtractor(iframe, "$directUrl/", subtitleCallback, callback)
}
} else {
document.select("div.tab-content-ajax").apmap { ele ->
@ -173,12 +167,7 @@ open class Gomov : MainAPI() {
data = mapOf("action" to "muvipro_player_content", "tab" to ele.attr("id"), "post_id" to "$id")
).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(server, "$directUrl/", subtitleCallback, callback)
}
}
@ -187,28 +176,29 @@ open class Gomov : MainAPI() {
}
private fun Element?.getImgAttr() : String? {
return this?.attr("data-src").takeIf { it?.isNotEmpty() == true } ?: this?.attr("src")
private fun Element.getImageAttr(): String? {
return when {
this.hasAttr("data-src") -> this.attr("abs:data-src")
this.hasAttr("data-lazy-src") -> this.attr("abs:data-lazy-src")
this.hasAttr("srcset") -> this.attr("abs:srcset").substringBefore(" ")
else -> this.attr("abs:src")
}
}
private fun Element?.getIframeAttr() : String? {
return this?.attr("data-litespeed-src").takeIf { it?.isNotEmpty() == true } ?: this?.attr("src")
}
}
fun String?.fixImageQuality(): String? {
if (this == null) return null
val regex = Regex("(-\\d*x\\d*)").find(this)?.groupValues?.get(0) ?: return this
return this.replace(regex, "")
}
fun getBaseUrl(url: String): String {
return URI(url).let {
"${it.scheme}://${it.host}"
private fun String?.fixImageQuality(): String? {
if (this == null) return null
val regex = Regex("(-\\d*x\\d*)").find(this)?.groupValues?.get(0) ?: return this
return this.replace(regex, "")
}
private fun getBaseUrl(url: String): String {
return URI(url).let {
"${it.scheme}://${it.host}"
}
}
}
fun String.getHost(): String {
return fixTitle(URI(this).host.substringBeforeLast(".").substringAfterLast("."))
}

View File

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

View File

@ -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(

View File

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

View File

@ -1,7 +1,14 @@
package com.hexated
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.extractors.Filesim
import com.lagradost.cloudstream3.extractors.StreamSB
import com.lagradost.cloudstream3.utils.ExtractorApi
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.getQualityFromName
class Nyomo : StreamSB() {
override var name: String = "Nyomo"
@ -11,4 +18,101 @@ class Nyomo : StreamSB() {
class Streamhide : Filesim() {
override var name: String = "Streamhide"
override var mainUrl: String = "https://streamhide.to"
}
open class Lbx : ExtractorApi() {
override val name = "Linkbox"
override val mainUrl = "https://lbx.to"
private val realUrl = "https://www.linkbox.to"
override val requiresReferer = true
override suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val token = Regex("""(?:/f/|/file/|\?id=)(\w+)""").find(url)?.groupValues?.get(1)
val id = app.get("$realUrl/api/file/share_out_list/?sortField=utime&sortAsc=0&pageNo=1&pageSize=50&shareToken=$token").parsedSafe<Responses>()?.data?.itemId
app.get("$realUrl/api/file/detail?itemId=$id", referer = url)
.parsedSafe<Responses>()?.data?.itemInfo?.resolutionList?.map { link ->
callback.invoke(
ExtractorLink(
name,
name,
link.url ?: return@map null,
"$realUrl/",
getQualityFromName(link.resolution)
)
)
}
}
data class Resolutions(
@JsonProperty("url") val url: String? = null,
@JsonProperty("resolution") val resolution: String? = null,
)
data class ItemInfo(
@JsonProperty("resolutionList") val resolutionList: ArrayList<Resolutions>? = arrayListOf(),
)
data class Data(
@JsonProperty("itemInfo") val itemInfo: ItemInfo? = null,
@JsonProperty("itemId") val itemId: String? = null,
)
data class Responses(
@JsonProperty("data") val data: Data? = null,
)
}
open class Kuramadrive : ExtractorApi() {
override val name = "DriveKurama"
override val mainUrl = "https://kuramadrive.com"
override val requiresReferer = true
override suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val req = app.get(url, referer = referer)
val doc = req.document
val title = doc.select("title").text()
val token = doc.select("meta[name=csrf-token]").attr("content")
val routeCheckAvl = doc.select("input#routeCheckAvl").attr("value")
val json = app.get(
routeCheckAvl, headers = mapOf(
"X-Requested-With" to "XMLHttpRequest",
"X-CSRF-TOKEN" to token
),
referer = url,
cookies = req.cookies
).parsedSafe<Source>()
callback.invoke(
ExtractorLink(
name,
name,
json?.url ?: return,
"$mainUrl/",
getIndexQuality(title),
)
)
}
private fun getIndexQuality(str: String?): Int {
return Regex("(\\d{3,4})[pP]").find(str ?: "")?.groupValues?.getOrNull(1)?.toIntOrNull()
?: Qualities.Unknown.value
}
private data class Source(
@JsonProperty("url") val url: String,
)
}

View File

@ -8,6 +8,8 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.loadExtractor
import com.lagradost.nicehttp.requestCreator
import okhttp3.Headers
import okhttp3.HttpUrl
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
@ -18,7 +20,7 @@ class KuramanimeProvider : MainAPI() {
override val hasMainPage = true
override var lang = "id"
override val hasDownloadSupport = true
private var auth: String? = null
private var params: AuthParams? = null
private var headers: Map<String,String> = mapOf()
private var cookies: Map<String,String> = mapOf()
override val supportedTypes = setOf(
@ -199,67 +201,70 @@ class KuramanimeProvider : MainAPI() {
val req = app.get(data)
val res = req.document
val token = res.select("meta[name=csrf-token]").attr("content")
headers = mapOf(
"Accept" to "application/json, text/javascript, */*; q=0.01",
"Authorization" to "${getAuth(data)}",
"X-Requested-With" to "XMLHttpRequest",
"X-CSRF-TOKEN" to token
)
cookies = req.cookies
res.select("select#changeServer option").apmap { source ->
val server = source.attr("value")
val link = "$data?dfgRr1OagZvvxbzHNpyCy0FqJQ18mCnb=${getMisc()}&twEvZlbZbYRWBdKKwxkOnwYF0VWoGGVg=$server"
if (server.contains(Regex("(?i)kuramadrive|archive"))) {
invokeLocalSource(link, server, data, callback)
} else {
app.get(
link,
referer = data,
headers = headers,
cookies = cookies
).document.select("div.iframe-container iframe").attr("src").let { videoUrl ->
loadExtractor(fixUrl(videoUrl), "$mainUrl/", subtitleCallback, callback)
argamap(
{
val auth = getAuth(data)
headers = auth.authHeader?.associate { it.first to it.second }?.filter { it.key != "Cookie" }!!
cookies = req.cookies
res.select("select#changeServer option").apmap { source ->
val server = source.attr("value")
val query = auth.serverUrl?.queryParameterNames?.map { it } ?: return@apmap
val link = "$data?${query[0]}=${getMisc(auth.authUrl)}&${query[1]}=$server"
if (server.contains(Regex("(?i)kuramadrive|archive"))) {
invokeLocalSource(link, server, data, callback)
} else {
app.get(
link,
referer = data,
headers = headers,
cookies = cookies
).document.select("div.iframe-container iframe").attr("src").let { videoUrl ->
loadExtractor(fixUrl(videoUrl), "$mainUrl/", subtitleCallback, callback)
}
}
}
},
{
res.select("div#animeDownloadLink a").apmap {
loadExtractor(it.attr("href"), "$mainUrl/", subtitleCallback, callback)
}
}
}
)
return true
}
private fun getAuth() : String {
val key = "kuramanime3:LEcXGYdOGcMCV8jM5fhRdM2mneSj6kaNts:${APIHolder.unixTimeMS};"
return base64Encode(base64Encode(key.toByteArray()).toByteArray())
}
private suspend fun fetchAuth(url: String) : String? {
private suspend fun fetchAuth(url: String) : AuthParams {
val regex = Regex("""$mainUrl/\S+""")
val found = WebViewResolver(
Regex("$mainUrl/misc/post/EVhcpMNbO77acNZcHr2XVjaG8WAdNC1u")
Regex("""$url(?!\?page=)\?"""),
additionalUrls = listOf(regex)
).resolveUsingWebView(
requestCreator(
"GET", url
)
).first
return found?.headers?.get("Authorization")
)
val addition = found.second.findLast { it.headers["X-Requested-With"] == "XMLHttpRequest" }
return AuthParams(found.first?.url, addition?.url.toString(), addition?.headers)
}
private suspend fun getAuth(url: String) = auth ?: fetchAuth(url)
private suspend fun getAuth(url: String) = params ?: fetchAuth(url).also { params = it }
private suspend fun getMisc(): String {
private suspend fun getMisc(url: String?): String {
val misc = app.get(
"$mainUrl/misc/post/EVhcpMNbO77acNZcHr2XVjaG8WAdNC1u",
headers = headers + mapOf("X-Request-ID" to getRequestId()),
"$url",
headers = headers,
cookies = cookies
)
cookies = misc.cookies
return misc.parsed()
}
private fun getRequestId(length: Int = 8): String {
val allowedChars = ('a'..'z') + ('0'..'9')
return (1..length)
.map { allowedChars.random() }
.joinToString("")
}
data class AuthParams (
val serverUrl: HttpUrl?,
val authUrl: String?,
val authHeader: Headers?,
)
}

View File

@ -12,5 +12,7 @@ class KuramanimeProviderPlugin: Plugin() {
registerMainAPI(KuramanimeProvider())
registerExtractorAPI(Nyomo())
registerExtractorAPI(Streamhide())
registerExtractorAPI(Kuramadrive())
registerExtractorAPI(Lbx())
}
}

View File

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

View File

@ -44,10 +44,12 @@ open class Streampai : ExtractorApi() {
this.name,
this.name,
fixUrl(it.file),
"$mainUrl/",
url,
getQualityFromName(it.label),
headers = mapOf(
"Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5",
"Accept-Language" to "en-US,en;q=0.5",
"DNT" to "1",
"Range" to "bytes=0-",
"Sec-Fetch-Dest" to "video",
"Sec-Fetch-Mode" to "no-cors",

View File

@ -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"))
@ -127,7 +107,7 @@ class Minioppai : MainAPI() {
val name = it.selectFirst("div.epl-num")?.text()
val link = fixUrlNull(it.selectFirst("a")?.attr("href")) ?: return@mapNotNull null
Episode(link, name = name)
}.reversed()
}
return newAnimeLoadResponse(title, url, TvType.NSFW) {
engName = title
@ -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 ->

View File

@ -1,5 +1,5 @@
// use an integer for version numbers
version = 2
version = 3
cloudstream {
@ -23,4 +23,4 @@ cloudstream {
)
iconUrl = "https://www.google.com/s2/favicons?domain=moviehab.com&sz=%size%"
}
}

View File

@ -12,7 +12,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor
import org.jsoup.nodes.Element
class Moviehab : MainAPI() {
override var mainUrl = "https://vivamax.asia"
override var mainUrl = "https://nowshowing.to"
override var name = "Moviehab"
override val hasMainPage = true
override var lang = "tl"
@ -23,16 +23,13 @@ class Moviehab : MainAPI() {
)
companion object {
private const val mainServer = "https://vivamax.asia"
private const val mainServer = "https://nowshowing.to"
}
override val mainPage = mainPageOf(
"$mainUrl/library/movies?sort_by=imdb_rate&page=" to "Movies by IMDB Rating",
"$mainUrl/library/shows?&sort_by=imdb_rate&page=" to "TV Shows by IMDB Rating",
"$mainUrl/library/movies?&sort_by=year&page=" to "New Movies",
"$mainUrl/library/shows?&sort_by=year&page=" to "New TV Shows",
"$mainUrl/library/movies?country=Philippines&sort_by=year&page=" to "New Philippines Movies",
"$mainUrl/library/shows?&country=Philippines&sort_by=year&page=" to "New Philippines TV Shows",
"$mainUrl/category/movies/" to "New Movies",
"$mainUrl/category/tv-series/" to "New TV Shows",
"$mainUrl/category/coming-soon/" to "Coming Soon",
)
override suspend fun getMainPage(

View File

@ -1,12 +1,12 @@
// use an integer for version numbers
version = 53
version = 55
cloudstream {
language = "hi"
// All of these properties are optional, you can safely remove them
description = "Include: Hdmovie2"
description = "Includes: Hdmovie2, Animesaga"
authors = listOf("Hexated")
/**

View File

@ -0,0 +1,23 @@
package com.hexated
import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.mainPageOf
class Animesaga : Movierulzhd() {
override var mainUrl = "https://www.animesaga.in"
override var name = "Animesaga"
override val supportedTypes = setOf(
TvType.Anime,
TvType.AnimeMovie,
TvType.OVA
)
override val mainPage = mainPageOf(
"movies" to "Movies",
"tvshows" to "TV-Shows",
"genre/hindi-dub" to "Hindi Dub",
)
}

View File

@ -2,10 +2,9 @@ package com.hexated
import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.extractors.Chillx
import com.lagradost.cloudstream3.utils.*
const val twoEmbedAPI = "https://www.2embed.to"
class Sbnmp : ExtractorApi() {
override val name = "Sbnmp"
override var mainUrl = "https://sbnmp.bar"
@ -66,3 +65,8 @@ open class Akamaicdn : ExtractorApi() {
)
}
}
class AnimesagaStream : Chillx() {
override val name = "AnimesagaStream"
override val mainUrl = "https://stream.animesaga.in"
}

View File

@ -12,7 +12,7 @@ import org.jsoup.Jsoup
class Hdmovie2 : Movierulzhd() {
override var mainUrl = "https://hdmovie2.boo"
override var mainUrl = "https://hdmovie2.li"
override var name = "Hdmovie2"
override val mainPage = mainPageOf(
"trending" to "Trending",
@ -44,7 +44,7 @@ class Hdmovie2 : Movierulzhd() {
} else {
var document = app.get(data).document
if (document.select("title").text() == "Just a moment...") {
document = app.get(data, interceptor = interceptor).document
document = app.get(data).document
}
val id = document.select("meta#dooplay-ajax-counter").attr("data-postid")
val type = if (data.contains("/movies/")) "movie" else "tv"

View File

@ -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,18 +33,13 @@ 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").mapNotNull {
document.select("div.items.normal article, div#archive-content article, div.items.full article").mapNotNull {
it.toSearchResult()
}
return newHomePageResponse(request.name, home)
@ -74,23 +68,17 @@ open class Movierulzhd : MainAPI() {
private fun Element.toSearchResult(): SearchResponse? {
val title = this.selectFirst("h3 > a")?.text() ?: return null
val href = getProperLink(fixUrl(this.selectFirst("h3 > a")!!.attr("href")))
val posterUrl = fixUrlNull(this.select("div.poster img").last()?.attr("src"))
val posterUrl = fixUrlNull(this.select("div.poster img").last()?.getImageAttr())
val quality = getQualityFromString(this.select("span.quality").text())
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,21 +86,17 @@ 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()
val poster = fixUrlNull(document.select("div.poster img:last-child").attr("src"))
val poster = fixUrlNull(document.selectFirst("div.poster img:last-child")?.getImageAttr())
val tags = document.select("div.sgeneros > a").map { it.text() }
val year = Regex(",\\s?(\\d+)").find(
@ -139,10 +123,9 @@ open class Movierulzhd : MainAPI() {
val recName =
it.selectFirst("a")!!.attr("href").toString().removeSuffix("/").split("/").last()
val recHref = it.selectFirst("a")!!.attr("href")
val recPosterUrl = it.selectFirst("img")?.attr("src").toString()
val recPosterUrl = it.selectFirst("img")?.getImageAttr()
newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) {
this.posterUrl = recPosterUrl
posterHeaders = interceptor.getCookieHeaders(url).toMap()
}
}
@ -151,7 +134,7 @@ open class Movierulzhd : MainAPI() {
document.select("ul.episodios > li").map {
val href = it.select("a").attr("href")
val name = fixTitle(it.select("div.episodiotitle > a").text().trim())
val image = it.select("div.imagen > img").attr("src")
val image = it.selectFirst("div.imagen > img")?.getImageAttr()
val episode =
it.select("div.numerando").text().replace(" ", "").split("-").last()
.toIntOrNull()
@ -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()
}
}
}
@ -230,18 +211,17 @@ open class Movierulzhd : MainAPI() {
referer = data,
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
).parsed<ResponseHash>().embed_url
if (!source.contains("youtube")) loadCustomExtractor(loadData?.tag, source, "$directUrl/", subtitleCallback, callback)
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 id = document.select("meta#dooplay-ajax-counter").attr("data-postid")
val type = if (data.contains("/movies/")) "movie" else "tv"
val document = app.get(data).document
document.select("ul#playeroptionsul > li").map {
it.attr("data-nume") to it.select("span.title").text()
}.apmap { (nume, tag) ->
Triple(
it.attr("data-post"),
it.attr("data-nume"),
it.attr("data-type")
)
}.apmap { (id, nume, type) ->
val source = app.post(
url = "$directUrl/wp-admin/admin-ajax.php",
data = mapOf(
@ -256,7 +236,6 @@ open class Movierulzhd : MainAPI() {
when {
!source.contains("youtube") -> loadCustomExtractor(
tag,
source,
"$directUrl/",
subtitleCallback,
@ -269,8 +248,16 @@ open class Movierulzhd : MainAPI() {
return true
}
private fun Element.getImageAttr(): String? {
return when {
this.hasAttr("data-src") -> this.attr("abs:data-src")
this.hasAttr("data-lazy-src") -> this.attr("abs:data-lazy-src")
this.hasAttr("srcset") -> this.attr("abs:srcset").substringBefore(" ")
else -> this.attr("abs:src")
}
}
private suspend fun loadCustomExtractor(
name: String? = null,
url: String,
referer: String? = null,
subtitleCallback: (SubtitleFile) -> Unit,
@ -278,21 +265,23 @@ open class Movierulzhd : MainAPI() {
quality: Int? = null,
) {
loadExtractor(url, referer, subtitleCallback) { link ->
callback.invoke(
ExtractorLink(
name ?: link.source,
name ?: link.name,
link.url,
link.referer,
when (link.type) {
ExtractorLinkType.M3U8 -> link.quality
else -> quality ?: link.quality
},
link.type,
link.headers,
link.extractorData
if(link.quality == Qualities.Unknown.value) {
callback.invoke(
ExtractorLink(
link.source,
link.name,
link.url,
link.referer,
when (link.type) {
ExtractorLinkType.M3U8 -> link.quality
else -> quality ?: link.quality
},
link.type,
link.headers,
link.extractorData
)
)
)
}
}
}

View File

@ -11,7 +11,9 @@ class MovierulzhdPlugin: Plugin() {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(Movierulzhd())
registerMainAPI(Hdmovie2())
registerMainAPI(Animesaga())
registerExtractorAPI(Sbnmp())
registerExtractorAPI(Akamaicdn())
registerExtractorAPI(AnimesagaStream())
}
}

View File

@ -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)

View File

@ -1,7 +1,7 @@
import org.jetbrains.kotlin.konan.properties.Properties
// use an integer for version numbers
version = 197
version = 204
android {
defaultConfig {
@ -9,15 +9,12 @@ android {
properties.load(project.rootProject.file("local.properties").inputStream())
buildConfigField("String", "TMDB_API", "\"${properties.getProperty("TMDB_API")}\"")
buildConfigField("String", "OMOVIES_API", "\"${properties.getProperty("OMOVIES_API")}\"")
buildConfigField("String", "CINEMATV_API", "\"${properties.getProperty("CINEMATV_API")}\"")
buildConfigField("String", "SFMOVIES_API", "\"${properties.getProperty("SFMOVIES_API")}\"")
buildConfigField("String", "ZSHOW_API", "\"${properties.getProperty("ZSHOW_API")}\"")
buildConfigField("String", "SORA_API", "\"${properties.getProperty("SORA_API")}\"")
buildConfigField("String", "SORAHE", "\"${properties.getProperty("SORAHE")}\"")
buildConfigField("String", "SORAXA", "\"${properties.getProperty("SORAXA")}\"")
buildConfigField("String", "SORATED", "\"${properties.getProperty("SORATED")}\"")
buildConfigField("String", "DUMP_API", "\"${properties.getProperty("DUMP_API")}\"")
buildConfigField("String", "DUMP_KEY", "\"${properties.getProperty("DUMP_KEY")}\"")
buildConfigField("String", "PRIMEWIRE_KEY", "\"${properties.getProperty("PRIMEWIRE_KEY")}\"")
buildConfigField("String", "CRUNCHYROLL_BASIC_TOKEN", "\"${properties.getProperty("CRUNCHYROLL_BASIC_TOKEN")}\"")
buildConfigField("String", "CRUNCHYROLL_REFRESH_TOKEN", "\"${properties.getProperty("CRUNCHYROLL_REFRESH_TOKEN")}\"")
}

View File

@ -6,17 +6,13 @@ import com.lagradost.cloudstream3.extractors.StreamSB
import com.lagradost.cloudstream3.extractors.Voe
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
import com.lagradost.cloudstream3.ErrorLoadingException
import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.base64Decode
import com.lagradost.cloudstream3.extractors.Pixeldrain
import com.lagradost.cloudstream3.extractors.helper.AesHelper
import com.lagradost.cloudstream3.extractors.Vidplay
import com.lagradost.cloudstream3.utils.*
import org.jsoup.nodes.Document
import org.mozilla.javascript.Context
import org.mozilla.javascript.Scriptable
import java.math.BigInteger
import java.security.MessageDigest
@ -202,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(
@ -212,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]") || link.contains("/dl.php?")) {
callback.invoke(
ExtractorLink(
this.name,
@ -238,83 +235,6 @@ open class VCloud : ExtractorApi() {
}
object NineTv {
suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val mainUrl = getBaseUrl(url)
val res = app.get(url, headers = mapOf(
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language" to "en-US,en;q=0.5",
"Referer" to (referer ?: ""),
))
val master = Regex("\\s*=\\s*'([^']+)").find(res.text)?.groupValues?.get(1)
val key = "tSIsE8FgpRkv3QQQ"
val decrypt = AesHelper.cryptoAESHandler(master ?: return, key.toByteArray(), false)
?.replace("\\", "")
?: throw ErrorLoadingException("failed to decrypt")
val source = Regex(""""?file"?:\s*"([^"]+)""").find(decrypt)?.groupValues?.get(1)
val tracks = Regex("""tracks:\s*\[(.+)]""").find(decrypt)?.groupValues?.get(1)
val name = url.getHost()
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
)
)
}
}
private fun Document.getKeys(): String? {
val script = (this.selectFirst("script:containsData(eval\\()")?.data()
?.replace("eval(", "var result=")?.removeSuffix(");") + ";").trimIndent()
val run = script.runJS("result")
return """,\s*'([^']+)""".toRegex().find(run)?.groupValues?.getOrNull(1)
}
private fun String.runJS(variable: String): String {
val rhino = Context.enter()
rhino.optimizationLevel = -1
val scope: Scriptable = rhino.initSafeStandardObjects()
val result: String
try {
rhino.evaluateString(scope, this, "JavaScript", 1, null)
result = Context.toString(scope.get(variable, scope))
} finally {
Context.exit()
}
return result
}
data class Tracks(
@JsonProperty("file") val file: String? = null,
@JsonProperty("label") val label: String? = null,
@JsonProperty("kind") val kind: String? = null,
)
}
open class Streamruby : ExtractorApi() {
override val name = "Streamruby"
override val mainUrl = "https://streamruby.com"
@ -390,6 +310,40 @@ open class Uploadever : ExtractorApi() {
}
open class Netembed : ExtractorApi() {
override var name: String = "Netembed"
override var mainUrl: String = "https://play.netembed.xyz"
override val requiresReferer = true
override suspend fun getUrl(
url: String,
referer: String?,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val response = app.get(url, referer = referer)
val script = getAndUnpack(response.text)
val m3u8 = Regex("((https:|http:)//.*\\.m3u8)").find(script)?.groupValues?.getOrNull(1)
callback.invoke(
ExtractorLink(
this.name,
this.name,
m3u8 ?: return,
"$mainUrl/",
getQuality(m3u8),
INFER_TYPE
)
)
}
private suspend fun getQuality(url: String) : Int {
val res = app.get(url, referer = "$mainUrl/").text
val regex = "#quality:\\s*(\\S+)".toRegex().find(res)?.groupValues?.get(1)
return getQualityFromName(regex)
}
}
class Streamwish : Filesim() {
override val name = "Streamwish"
override var mainUrl = "https://streamwish.to"
@ -405,11 +359,6 @@ class FilelionsTo : Filesim() {
override var mainUrl = "https://filelions.to"
}
class Hubcloud : VCloud() {
override val name = "Hubcloud"
override val mainUrl = "https://hubcloud.in"
}
class Pixeldra : Pixeldrain() {
override val mainUrl = "https://pixeldra.in"
}
@ -447,4 +396,8 @@ class Yipsu : Voe() {
class Embedwish : Filesim() {
override val name = "Embedwish"
override var mainUrl = "https://embedwish.com"
}
class Vidplay2 : Vidplay() {
override val mainUrl = "https://vidplay.online"
}

View File

@ -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
@ -110,7 +111,8 @@ object SoraExtractor : SoraStream() {
"$vidSrcAPI/embed/tv?tmdb=$id&season=$season&episode=$episode"
}
val iframedoc = app.get(url).document.select("iframe#player_iframe").attr("src").let { httpsify(it) }
val iframedoc =
app.get(url).document.select("iframe#player_iframe").attr("src").let { httpsify(it) }
val doc = app.get(iframedoc, referer = url).document
val index = doc.select("body").attr("data-i")
@ -246,6 +248,7 @@ object SoraExtractor : SoraStream() {
} else {
"$multimoviesAPI/episodes/$fixTitle-${season}x${episode}"
}
invokeWpmovies(null, url, subtitleCallback, callback)
}
suspend fun invokeNetmovies(
@ -273,12 +276,11 @@ object SoraExtractor : SoraStream() {
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val api = BuildConfig.ZSHOW_API
val fixTitle = title.createSlug()
val url = if (season == null) {
"$api/movie/$fixTitle-$year"
"$zshowAPI/movie/$fixTitle-$year"
} else {
"$api/episode/$fixTitle-season-$season-episode-$episode"
"$zshowAPI/episode/$fixTitle-season-$season-episode-$episode"
}
invokeWpmovies("ZShow", url, subtitleCallback, callback, encrypt = true)
}
@ -326,20 +328,7 @@ object SoraExtractor : SoraStream() {
else -> it.embed_url
}
} ?: return@apmap
val sources = arrayOf(
"https://chillx.top",
"https://watchx.top",
"https://bestx.stream",
"https://w1.moviesapi.club"
)
when {
sources.any { source.startsWith(it) } -> NineTv.getUrl(
source,
"$referer/",
subtitleCallback,
callback
)
!source.contains("youtube") -> {
loadCustomExtractor(name, source, "$referer/", subtitleCallback, callback)
}
@ -451,7 +440,7 @@ object SoraExtractor : SoraStream() {
sourcesData?.get("movie")?.get("movie")
} else {
sourcesData?.get("s$seasonSlug")?.get("e$episodeSlug")
}
} ?: return
val subSources = if (season == null) {
subSourcesData?.get("movie")?.get("movie")
} else {
@ -464,39 +453,45 @@ object SoraExtractor : SoraStream() {
Regex("var\\suserNonce.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1)
val userId =
Regex("var\\suser_id.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1)
val linkIDs = sources?.joinToString("") {
"&linkIDs%5B%5D=$it"
}?.replace("\"", "")
val json = app.post(
"$filmxyAPI/wp-admin/admin-ajax.php",
requestBody = "action=get_vid_links$linkIDs&user_id=$userId&nonce=$userNonce".toRequestBody(),
referer = url,
headers = mapOf(
"Accept" to "*/*",
"DNT" to "1",
"Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8",
"Origin" to filmxyAPI,
"X-Requested-With" to "XMLHttpRequest",
),
cookies = filmxyCookies
).text.let { tryParseJson<HashMap<String, String>>(it) }
val listSources = sources.withIndex()
.groupBy { it.index / 2 }
.map { entry -> entry.value.map { it.value } }
sources?.map { source ->
val link = json?.get(source)
val quality = sourcesDetail?.get(source)?.get("resolution")
val server = sourcesDetail?.get(source)?.get("server")
val size = sourcesDetail?.get(source)?.get("size")
listSources.apmap { src ->
val linkIDs = src.joinToString("") {
"&linkIDs%5B%5D=$it"
}.replace("\"", "")
val json = app.post(
"$filmxyAPI/wp-admin/admin-ajax.php",
requestBody = "action=get_vid_links$linkIDs&user_id=$userId&nonce=$userNonce".toRequestBody(),
referer = url,
headers = mapOf(
"Accept" to "*/*",
"DNT" to "1",
"Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8",
"Origin" to filmxyAPI,
"X-Requested-With" to "XMLHttpRequest",
),
cookies = filmxyCookies
).text.let { tryParseJson<HashMap<String, String>>(it) }
callback.invoke(
ExtractorLink(
"Filmxy",
"Filmxy $server [$size]",
link ?: return@map,
"$filmxyAPI/",
getQualityFromName(quality)
src.map { source ->
val link = json?.get(source)
val quality = sourcesDetail?.get(source)?.get("resolution")
val server = sourcesDetail?.get(source)?.get("server")
val size = sourcesDetail?.get(source)?.get("size")
callback.invoke(
ExtractorLink(
"Filmxy",
"Filmxy $server [$size]",
link ?: return@map,
"$filmxyAPI/",
getQualityFromName(quality)
)
)
)
}
}
subSources?.mapKeys { sub ->
@ -686,12 +681,20 @@ object SoraExtractor : SoraStream() {
"$vidsrctoAPI/embed/tv/$imdbId/$season/$episode"
}
val mediaId = app.get(url).document.selectFirst("ul.episodes li a")?.attr("data-id") ?: return
val mediaId =
app.get(url).document.selectFirst("ul.episodes li a")?.attr("data-id") ?: return
app.get("$vidsrctoAPI/ajax/embed/episode/$mediaId/sources").parsedSafe<VidsrctoSources>()?.result?.apmap {
val encUrl = app.get("$vidsrctoAPI/ajax/embed/source/${it.id}").parsedSafe<VidsrctoResponse>()?.result?.url
loadExtractor(vidsrctoDecrypt(encUrl ?: return@apmap), "$vidsrctoAPI/", subtitleCallback, callback)
}
app.get("$vidsrctoAPI/ajax/embed/episode/$mediaId/sources")
.parsedSafe<VidsrctoSources>()?.result?.apmap {
val encUrl = app.get("$vidsrctoAPI/ajax/embed/source/${it.id}")
.parsedSafe<VidsrctoResponse>()?.result?.url
loadExtractor(
vidsrctoDecrypt(encUrl ?: return@apmap),
"$vidsrctoAPI/",
subtitleCallback,
callback
)
}
val subtitles = app.get("$vidsrctoAPI/ajax/embed/episode/$mediaId/subtitles").text
tryParseJson<List<VidsrctoSubtitles>>(subtitles)?.map {
@ -965,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).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)
}
@ -1038,10 +1029,7 @@ object SoraExtractor : SoraStream() {
qualities
)
)
}
}
suspend fun invokeDotmovies(
@ -1103,40 +1091,34 @@ object SoraExtractor : SoraStream() {
1 -> "Season 1"
else -> "Season 1 $lastSeason"
}
val media =
res.selectFirst("div.blog-items article:has(h3.entry-title:matches((?i)$title.*$match)) a")
val media = res.selectFirst("div.blog-items article:has(h3.entry-title:matches((?i)$title.*$match)) a")
?.attr("href")
res = app.get(media ?: return).document
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 server = app.get(
href ?: return, interceptor = CloudflareKiller()
).document.selectFirst("div.entry-content > $selector")
?.attr("href") ?: return
loadCustomTagExtractor(
tags,
server,
"$api/",
subtitleCallback,
callback,
getIndexQuality(entry.text())
)
}
suspend fun invokeHdmovies4u(
@ -1213,7 +1195,14 @@ object SoraExtractor : SoraStream() {
iframe.apmap { (iframeLink, title) ->
val size = Regex("(?i)\\s(\\S+gb|mb)").find(title)?.groupValues?.getOrNull(1)
loadCustomTagExtractor("[$size]",iframeLink, "$gMoviesAPI/", subtitleCallback, callback, getIndexQuality(title))
loadCustomTagExtractor(
"[$size]",
iframeLink,
"$gMoviesAPI/",
subtitleCallback,
callback,
getIndexQuality(title)
)
}
}
@ -1304,7 +1293,9 @@ object SoraExtractor : SoraStream() {
scriptData.firstOrNull()
} else {
scriptData.find {
it.first.contains(Regex("(?i)$title \\($year\\s?\\)")) && if(season!=null) it.third?.contains("-tvshow-") == true else it.third?.contains("-movie-") == true
it.first.contains(Regex("(?i)$title \\($year\\s?\\)")) && if (season != null) it.third?.contains(
"-tvshow-"
) == true else it.third?.contains("-movie-") == true
}
}
@ -1527,10 +1518,16 @@ object SoraExtractor : SoraStream() {
iframe?.apmap {
val iframeDoc = app.get(it?.first ?: return@apmap).document
val formUrl = iframeDoc.select("form").attr("action")
val formData = iframeDoc.select("form button").associate { v -> v.attr("name") to v.attr("value") }
val formData =
iframeDoc.select("form button").associate { v -> v.attr("name") to v.attr("value") }
val videoUrl = app.post(formUrl, data = formData, referer = it.first).document.selectFirst("div.d-flex.justify-content-center.flex-wrap a")?.attr("href")
val quality = Regex("(\\d{3,4})p").find(it.second)?.groupValues?.getOrNull(1)?.toIntOrNull()
val videoUrl = app.post(
formUrl,
data = formData,
referer = it.first
).document.selectFirst("div.d-flex.justify-content-center.flex-wrap a")?.attr("href")
val quality =
Regex("(\\d{3,4})p").find(it.second)?.groupValues?.getOrNull(1)?.toIntOrNull()
val qualityName = it.second.replace("${quality}p", "").trim()
callback.invoke(
@ -1625,27 +1622,32 @@ object SoraExtractor : SoraStream() {
}
suspend fun invokeSmashyStream(
tmdbId: Int? = null,
imdbId: String? = null,
season: Int? = null,
episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit,
) {
val url = if (season == null) {
"$smashyStreamAPI/playere.php?tmdb=$tmdbId"
"$smashyStreamAPI/playere.php?imdb=$imdbId"
} else {
"$smashyStreamAPI/playere.php?tmdb=$tmdbId&season=$season&episode=$episode"
"$smashyStreamAPI/playere.php?imdb=$imdbId&season=$season&episode=$episode"
}
app.get(
url, referer = "https://smashystream.xyz/"
url, referer = "https://smashystream.com/"
).document.select("div#_default-servers a.server").map {
it.attr("data-url") to it.text()
}.apmap {
when {
it.second.contains(Regex("(Player F|Player FM)\$")) -> {
when (it.second) {
"Player F" -> {
invokeSmashyFfix(it.second, it.first, url, callback)
}
"Player D (Hindi)" -> {
invokeSmashyD(it.first, url, callback)
}
else -> return@apmap
}
}
@ -1920,14 +1922,15 @@ object SoraExtractor : SoraStream() {
"$twoEmbedAPI/embedtv/$imdbId&s=$season&e=$episode"
}
val framesrc = app.get(url).document.selectFirst("iframe#iframesrc")?.attr("data-src") ?: return
val framesrc =
app.get(url).document.selectFirst("iframe#iframesrc")?.attr("data-src") ?: return
val ref = getBaseUrl(framesrc)
val id = framesrc.substringAfter("id=").substringBefore("&")
loadExtractor("https://wishfast.top/e/$id", "$ref/", subtitleCallback, callback)
}
suspend fun invokeGomovies(
suspend fun invokeOmovies(
title: String? = null,
year: Int? = null,
season: Int? = null,
@ -1940,10 +1943,10 @@ object SoraExtractor : SoraStream() {
season,
episode,
callback,
"https://gomovies-online.cam",
"Gomovies",
"_smQamBQsETb",
"_sBWcqbTBMaT"
BuildConfig.OMOVIES_API,
"Omovies",
base64Decode("X3NtUWFtQlFzRVRi"),
base64Decode("X3NCV2NxYlRCTWFU")
)
}
@ -1968,14 +1971,11 @@ object SoraExtractor : SoraStream() {
} else {
"$title Season $season"
}
val idCookies =
mapOf(
"advanced-frontendgomovies7" to "bjd4n0nnv4hlt4fj5cdjgbrne2",
"_identitygomovies7" to "52fdc70b008c0b1d881dac0f01cca819edd512de01cc8bbc1224ed4aafb78b52a:2:{i:0;s:18:\"_identitygomovies7\";i:1;s:52:\"[2050366,\"HnVRRAObTASOJEr45YyCM8wiHol0V1ko\",2592000]\";}"
val savedCookies = mapOf(
"_identitygomovies7" to "52fdc70b008c0b1d881dac0f01cca819edd512de01cc8bbc1224ed4aafb78b52a%3A2%3A%7Bi%3A0%3Bs%3A18%3A%22_identitygomovies7%22%3Bi%3A1%3Bs%3A52%3A%22%5B2050366%2C%22HnVRRAObTASOJEr45YyCM8wiHol0V1ko%22%2C2592000%5D%22%3B%7D",
)
val req = app.get("$api/search/$query")
val doc = req.document
var cookies = req.cookies + idCookies
val media = doc.select("div.$mediaSelector").map {
Triple(
it.attr("data-filmName"), it.attr("data-year"), it.select("a").attr("href")
@ -2003,9 +2003,8 @@ object SoraExtractor : SoraStream() {
fixUrl(
media.third,
api
), cookies = cookies
)
)
cookies = cookies + res.cookies
res.document.selectFirst("div#$episodeSelector a:contains(Episode ${slug.second})")
?.attr("href")
} ?: return
@ -2016,11 +2015,11 @@ object SoraExtractor : SoraStream() {
media.third.substringAfterLast("/") to iframe.substringAfterLast("/")
.substringBefore("-")
}
val res = app.get(fixUrl(iframe ?: return, api), cookies = cookies, verify = false)
val res = app.get(fixUrl(iframe, api), verify = false)
val serverUrl = res.document.selectFirst("script:containsData(pushState)")?.data()?.let {
""",\s*'([^']+)""".toRegex().find(it)?.groupValues?.get(1)
} ?: return
cookies = cookies + res.cookies
val cookies = savedCookies + res.cookies
val url = res.document.select("meta[property=og:url]").attr("content")
val headers = mapOf("X-Requested-With" to "XMLHttpRequest")
val qualities = intArrayOf(2160, 1440, 1080, 720, 480, 360)
@ -2064,7 +2063,6 @@ object SoraExtractor : SoraStream() {
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit,
) {
val ref = "https://blackvid.space/"
val key = "b6055c533c19131a638c3d2299d525d5ec08a814"
val url = if (season == null) {
"$blackvidAPI/v3/movie/sources/$tmdbId?key=$key"
@ -2072,7 +2070,8 @@ object SoraExtractor : SoraStream() {
"$blackvidAPI/v3/tv/sources/$tmdbId/$season/$episode?key=$key"
}
val data = app.get(url, timeout = 120L, referer = ref).okhttpResponse.peekBody(1024 * 1024).bytes().decrypt("2378f8e4e844f2dc839ab48f66e00acc2305a401")
val data = request(url,).peekBody(1024 * 512).source().buffer.readByteArray()
.decrypt("2378f8e4e844f2dc839ab48f66e00acc2305a401")
val json = tryParseJson<BlackvidResponses>(data)
json?.sources?.map { source ->
@ -2082,7 +2081,7 @@ object SoraExtractor : SoraStream() {
"Blackvid",
"Blackvid${source.label}",
s.url ?: return@s,
ref,
"https://blackvid.space/",
if (s.quality.equals("4k")) Qualities.P2160.value else s.quality?.toIntOrNull()
?: Qualities.P1080.value,
INFER_TYPE
@ -2163,7 +2162,7 @@ object SoraExtractor : SoraStream() {
}
suspend fun invokeWatchOnline(
suspend fun invokeCinemaTv(
imdbId: String? = null,
title: String? = null,
year: Int? = null,
@ -2175,17 +2174,19 @@ object SoraExtractor : SoraStream() {
val id = imdbId?.removePrefix("tt")
val slug = title.createSlug()
val url = if (season == null) {
"$watchOnlineAPI/movies/play/$id-$slug-$year"
"$cinemaTvAPI/movies/play/$id-$slug-$year"
} else {
"$watchOnlineAPI/shows/play/$id-$slug-$year"
"$cinemaTvAPI/shows/play/$id-$slug-$year"
}
val doc = app.get(
url.replace(
watchOnlineAPI,
"https://ditairridgeleg.monster"
) + "?mid=1&sid=9k9iupt5sebbnfajrc6ti3ht7l&sec=1974bc4a902c4d69fcbab261dcec69094a9b8164&t=1694986826984"
).document
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"
val headers = mapOf(
"Cookie" to specialCookies,
"Connection" to "keep-alive",
"x-requested-with" to "XMLHttpRequest",
)
val doc = app.get(url, headers = headers).document
val script = doc.selectFirst("script:containsData(hash:)")?.data()
val hash = Regex("hash:\\s*['\"](\\S+)['\"]").find(script ?: return)?.groupValues?.get(1)
val expires = Regex("expires:\\s*(\\d+)").find(script)?.groupValues?.get(1)
@ -2196,24 +2197,24 @@ object SoraExtractor : SoraStream() {
}).let { it.toRegex().find(script)?.groupValues?.get(1) }
val videoUrl = if (season == null) {
"$watchOnlineAPI/api/v1/security/movie-access?id_movie=$episodeId&hash=$hash&expires=$expires"
"$cinemaTvAPI/api/v1/security/movie-access?id_movie=$episodeId&hash=$hash&expires=$expires"
} else {
"$watchOnlineAPI/api/v1/security/episode-access?id_episode=$episodeId&hash=$hash&expires=$expires"
"$cinemaTvAPI/api/v1/security/episode-access?id_episode=$episodeId&hash=$hash&expires=$expires"
}
val sources = app.get(
videoUrl,
referer = url,
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
).parsedSafe<WatchOnlineResponse>()
).parsedSafe<CinemaTvResponse>()
sources?.streams?.mapKeys { source ->
callback.invoke(
ExtractorLink(
"WatchOnline",
"WatchOnline",
"CinemaTv",
"CinemaTv",
source.value,
"$watchOnlineAPI/",
"$cinemaTvAPI/",
getQualityFromName(source.key),
true
)
@ -2225,7 +2226,7 @@ object SoraExtractor : SoraStream() {
subtitleCallback.invoke(
SubtitleFile(
sub.language ?: return@map,
if (file.startsWith("[")) return@map else fixUrl(file, watchOnlineAPI),
if (file.startsWith("[")) return@map else fixUrl(file, cinemaTvAPI),
)
)
}
@ -2248,7 +2249,7 @@ object SoraExtractor : SoraStream() {
val iframe = app.get(url, referer = "https://pressplay.top/").document.selectFirst("iframe")
?.attr("src")
NineTv.getUrl(iframe ?: return, "$nineTvAPI/", subtitleCallback, callback)
loadExtractor(iframe ?: return, "$nineTvAPI/", subtitleCallback, callback)
}
@ -2261,9 +2262,11 @@ object SoraExtractor : SoraStream() {
) {
val referer = "https://bflix.gs/"
val slug = getEpisodeSlug(season, episode)
var url = if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4"
var url =
if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4"
if (!app.get(url, referer = referer).isSuccessful) {
url = if (season == null) "$nowTvAPI/$imdbId.mp4" else "$nowTvAPI/tv/$imdbId/s${season}e${slug.second}.mp4"
url =
if (season == null) "$nowTvAPI/$imdbId.mp4" else "$nowTvAPI/tv/$imdbId/s${season}e${slug.second}.mp4"
if (!app.get(url, referer = referer).isSuccessful) return
}
callback.invoke(
@ -2463,7 +2466,7 @@ object SoraExtractor : SoraStream() {
ExtractorLink(
"SFMovies",
"SFMovies",
fixUrl(video, base64DecodeAPI("aQ==YXA=dGE=ZGE=c3Q=cmU=dC8=bmU=cy4=b3c=bmQ=d2k=ZS4=b3I=LmM=b2I=Ymw=aS4=YXA=dGE=ZGE=c3Q=cmU=Ly8=czo=dHA=aHQ=")),
fixUrl(video, getSfServer()),
"",
Qualities.P1080.value,
INFER_TYPE

View File

@ -152,14 +152,14 @@ data class JikanResponse(
@JsonProperty("data") val data: JikanData? = null,
)
data class WatchOnlineSubtitles(
data class CinemaTvSubtitles(
@JsonProperty("language") val language: String? = null,
@JsonProperty("file") val file: Any? = null,
)
data class WatchOnlineResponse(
data class CinemaTvResponse(
@JsonProperty("streams") val streams: HashMap<String, String>? = null,
@JsonProperty("subtitles") val subtitles: ArrayList<WatchOnlineSubtitles>? = arrayListOf(),
@JsonProperty("subtitles") val subtitles: ArrayList<CinemaTvSubtitles>? = arrayListOf(),
)
data class VidsrctoResult(
@ -424,4 +424,13 @@ data class RidoSearch(
data class SmashySources(
@JsonProperty("sourceUrls") var sourceUrls: ArrayList<String>? = arrayListOf(),
@JsonProperty("subtitleUrls") var subtitleUrls: String? = null,
)
data class SmashyDSources(
@JsonProperty("sourceUrls") var sourceUrls: ArrayList<SmashyDSourcesUrls>? = arrayListOf(),
)
data class SmashyDSourcesUrls(
@JsonProperty("file") var file: String? = null,
@JsonProperty("title") var title: String? = null,
)

View File

@ -43,7 +43,8 @@ import com.hexated.SoraExtractor.invokeTvMovies
import com.hexated.SoraExtractor.invokeUhdmovies
import com.hexated.SoraExtractor.invokeVegamovies
import com.hexated.SoraExtractor.invokeVidsrcto
import com.hexated.SoraExtractor.invokeWatchOnline
import com.hexated.SoraExtractor.invokeCinemaTv
import com.hexated.SoraExtractor.invokeOmovies
import com.hexated.SoraExtractor.invokeWatchsomuch
import com.hexated.SoraExtractor.invokeZshow
import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId
@ -93,10 +94,11 @@ open class SoraStream : TmdbProvider() {
const val flixonAPI = "https://flixon.lol"
const val smashyStreamAPI = "https://embed.smashystream.com"
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
const val watchOnlineAPI = "https://lookmovie.foundation"
var cinemaTvAPI = BuildConfig.CINEMATV_API
const val nineTvAPI = "https://moviesapi.club"
const val nowTvAPI = "https://myfilestorage.xyz"
const val gokuAPI = "https://goku.sx"
const val zshowAPI = BuildConfig.ZSHOW_API
const val ridomoviesAPI = "https://ridomovies.pw"
const val navyAPI = "https://navy-issue-i-239.site"
const val emoviesAPI = "https://emovies.si"
@ -115,8 +117,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.boo"
const val dotmoviesAPI = "https://dotmovies.im"
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"
@ -300,6 +302,7 @@ open class SoraStream : TmdbProvider() {
this.showStatus = getStatus(res.status)
this.recommendations = recommendations
this.actors = actors
this.contentRating = fetchContentRating(data.id, "US")
addTrailer(trailer)
addTMDbId(data.id.toString())
addImdbId(res.external_ids?.imdb_id)
@ -334,6 +337,7 @@ open class SoraStream : TmdbProvider() {
this.rating = rating
this.recommendations = recommendations
this.actors = actors
this.contentRating = fetchContentRating(data.id, "US")
addTrailer(trailer)
addTMDbId(data.id.toString())
addImdbId(res.external_ids?.imdb_id)
@ -351,6 +355,15 @@ open class SoraStream : TmdbProvider() {
val res = parseJson<LinkData>(data)
argamap(
{
if (!res.isAnime) invokeBlackvid(
res.id,
res.season,
res.episode,
subtitleCallback,
callback
)
},
{
invokeDumpStream(
res.title,
@ -430,7 +443,7 @@ open class SoraStream : TmdbProvider() {
)
},
{
invokeKisskh(
if (res.isAsian || res.isAnime) invokeKisskh(
res.title,
res.season,
res.episode,
@ -440,6 +453,15 @@ open class SoraStream : TmdbProvider() {
callback
)
},
{
if (!res.isAnime) invokeOmovies (
res.title,
res.year,
res.season,
res.episode,
callback
)
},
{
if (!res.isAnime) invokeLing(
res.title,
@ -455,7 +477,6 @@ open class SoraStream : TmdbProvider() {
res.title,
res.year,
res.season,
res.lastSeason,
res.episode,
callback
)
@ -527,7 +548,7 @@ open class SoraStream : TmdbProvider() {
},
{
if (!res.isAnime) invokeSmashyStream(
res.id,
res.imdbId,
res.season,
res.episode,
subtitleCallback,
@ -561,7 +582,7 @@ open class SoraStream : TmdbProvider() {
)
},
{
invokeWatchOnline(
invokeCinemaTv(
res.imdbId,
res.title,
res.airedYear ?: res.year,
@ -672,15 +693,6 @@ open class SoraStream : TmdbProvider() {
callback
)
},
{
if (!res.isAnime) invokeBlackvid(
res.id,
res.season,
res.episode,
subtitleCallback,
callback
)
},
{
if (!res.isAnime) invokeShowflix(
res.title,

View File

@ -29,7 +29,8 @@ import com.hexated.SoraExtractor.invokeSFMovies
import com.hexated.SoraExtractor.invokeShowflix
import com.hexated.SoraExtractor.invokeVidSrc
import com.hexated.SoraExtractor.invokeVidsrcto
import com.hexated.SoraExtractor.invokeWatchOnline
import com.hexated.SoraExtractor.invokeCinemaTv
import com.hexated.SoraExtractor.invokeOmovies
import com.hexated.SoraExtractor.invokeWatchsomuch
import com.hexated.SoraExtractor.invokeZshow
import com.lagradost.cloudstream3.SubtitleFile
@ -133,6 +134,15 @@ class SoraStreamLite : SoraStream() {
callback
)
},
{
if (!res.isAnime) invokeOmovies(
res.title,
res.year,
res.season,
res.episode,
callback
)
},
{
if (!res.isAnime) invokeKimcartoon(
res.title,
@ -144,7 +154,7 @@ class SoraStreamLite : SoraStream() {
},
{
if (!res.isAnime) invokeSmashyStream(
res.id,
res.imdbId,
res.season,
res.episode,
subtitleCallback,
@ -161,7 +171,7 @@ class SoraStreamLite : SoraStream() {
)
},
{
invokeKisskh(
if (res.isAsian || res.isAnime) invokeKisskh(
res.title,
res.season,
res.episode,
@ -198,7 +208,7 @@ class SoraStreamLite : SoraStream() {
if (!res.isAnime) invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
},
{
invokeWatchOnline(
invokeCinemaTv(
res.imdbId,
res.title,
res.airedYear ?: res.year,

View File

@ -20,7 +20,6 @@ class SoraStreamPlugin: Plugin() {
registerExtractorAPI(Playm4u())
registerExtractorAPI(VCloud())
registerExtractorAPI(Pixeldra())
registerExtractorAPI(Hubcloud())
registerExtractorAPI(M4ufree())
registerExtractorAPI(Streamruby())
registerExtractorAPI(Streamwish())
@ -28,5 +27,7 @@ class SoraStreamPlugin: Plugin() {
registerExtractorAPI(Embedwish())
registerExtractorAPI(Wishfast())
registerExtractorAPI(Uploadever())
registerExtractorAPI(Netembed())
registerExtractorAPI(Vidplay2())
}
}

View File

@ -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.*
@ -20,12 +19,16 @@ import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.nicehttp.NiceResponse
import com.lagradost.nicehttp.RequestBodyTypes
import com.lagradost.nicehttp.Requests.Companion.await
import com.lagradost.nicehttp.requestCreator
import kotlinx.coroutines.delay
import okhttp3.FormBody
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import org.jsoup.nodes.Document
import java.math.BigInteger
import java.net.*
@ -34,9 +37,8 @@ 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 java.util.concurrent.TimeUnit
import javax.crypto.Cipher
import javax.crypto.spec.GCMParameterSpec
import javax.crypto.spec.IvParameterSpec
@ -45,7 +47,9 @@ import kotlin.collections.ArrayList
import kotlin.math.min
var watchflxCookies: Map<String, String>? = null
var filmxyCookies: Map<String,String>? = null
var filmxyCookies: Map<String, String>? = null
var sfServer: String? = null
val encodedIndex = arrayOf(
"GamMovies",
"JSMovies",
@ -93,51 +97,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")
@ -450,16 +409,28 @@ suspend fun invokeSmashyFfix(
val json = app.get(url, referer = ref, headers = mapOf("X-Requested-With" to "XMLHttpRequest"))
.parsedSafe<SmashySources>()
json?.sourceUrls?.map {
callback.invoke(
ExtractorLink(
"Smashy [$name]",
"Smashy [$name]",
it,
if(name == "Player FM") "https://vidplay.site/" else "",
Qualities.P1080.value,
INFER_TYPE
)
)
M3u8Helper.generateM3u8(
"Smashy [$name]",
it,
""
).forEach(callback)
}
}
suspend fun invokeSmashyD(
url: String,
ref: String,
callback: (ExtractorLink) -> Unit,
) {
val json = app.get(url, referer = ref, headers = mapOf("X-Requested-With" to "XMLHttpRequest"))
.parsedSafe<SmashyDSources>()
json?.sourceUrls?.apmap {
M3u8Helper.generateM3u8(
"Smashy [Player D ${it.title}]",
it.file ?: return@apmap,
""
).forEach(callback)
}
}
@ -487,6 +458,7 @@ suspend fun getDumpIdAndType(title: String?, year: Int?, season: Int?): Pair<Str
true
) && it.releaseTime == "$year" && it.domainType == 0
}
1 -> {
it.name?.contains(
"$title",
@ -496,6 +468,7 @@ suspend fun getDumpIdAndType(title: String?, year: Int?, season: Int?): Pair<Str
true
)) && it.domainType == 1
}
else -> {
it.name?.contains(Regex("(?i)$title\\s?($season|${season.toRomanNumeral()}|Season\\s$season)")) == true && it.releaseTime == "$year" && it.domainType == 1
}
@ -531,25 +504,26 @@ suspend fun invokeDrivetot(
) {
val res = app.get(url)
val data = res.document.select("form input").associate { it.attr("name") to it.attr("value") }
app.post(res.url, data = data, cookies = res.cookies).document.select("div.card-body a").apmap { ele ->
val href = base64Decode(ele.attr("href").substringAfterLast("/")).let {
if(it.contains("hubcloud.lol")) it.replace("hubcloud.lol", "hubcloud.in") else it
}
loadExtractor(href, "$hdmovies4uAPI/", subtitleCallback) { link ->
callback.invoke(
ExtractorLink(
link.source,
"${link.name} $tags [$size]",
link.url,
link.referer,
link.quality,
link.type,
link.headers,
link.extractorData
app.post(res.url, data = data, cookies = res.cookies).document.select("div.card-body a")
.apmap { ele ->
val href = base64Decode(ele.attr("href").substringAfterLast("/")).let {
if (it.contains("hubcloud.lol")) it.replace("hubcloud.lol", "hubcloud.in") else it
}
loadExtractor(href, "$hdmovies4uAPI/", subtitleCallback) { link ->
callback.invoke(
ExtractorLink(
link.source,
"${link.name} $tags [$size]",
link.url,
link.referer,
link.quality,
link.type,
link.headers,
link.extractorData
)
)
)
}
}
}
}
suspend fun bypassBqrecipes(url: String): String? {
@ -614,28 +588,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(\"")
@ -644,94 +617,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)
@ -761,10 +646,20 @@ suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair<St
}.lastOrNull()
}
}
suspend fun getFilmxyCookies(url: String) = filmxyCookies ?: fetchFilmxyCookies(url).also { filmxyCookies = it }
suspend fun getSfServer() = sfServer ?: fetchSfServer().also { sfServer = it }
suspend fun fetchSfServer(): String {
return app.get("https://raw.githubusercontent.com/hexated/cloudstream-resources/main/sfmovies_server").text
}
suspend fun getFilmxyCookies(url: String) =
filmxyCookies ?: fetchFilmxyCookies(url).also { filmxyCookies = it }
suspend fun fetchFilmxyCookies(url: String): Map<String, String> {
val defaultCookies = mutableMapOf("G_ENABLED_IDPS" to "google", "true_checker" to "1", "XID" to "1")
val defaultCookies =
mutableMapOf("G_ENABLED_IDPS" to "google", "true_checker" to "1", "XID" to "1")
session.get(
url,
headers = mapOf(
@ -777,7 +672,10 @@ suspend fun fetchFilmxyCookies(url: String): Map<String, String> {
defaultCookies["PHPSESSID"] = phpsessid
val userNonce =
app.get("$filmxyAPI/login/?redirect_to=$filmxyAPI/", cookies = defaultCookies).document.select("script")
app.get(
"$filmxyAPI/login/?redirect_to=$filmxyAPI/",
cookies = defaultCookies
).document.select("script")
.find { it.data().contains("var userNonce") }?.data()?.let {
Regex("var\\suserNonce.*?\"(\\S+?)\";").find(it)?.groupValues?.get(1)
}
@ -801,7 +699,8 @@ suspend fun fetchFilmxyCookies(url: String): Map<String, String> {
return cookieJar.plus(defaultCookies)
}
suspend fun getWatchflxCookies() = watchflxCookies ?: fetchWatchflxCookies().also { watchflxCookies = it }
suspend fun getWatchflxCookies() =
watchflxCookies ?: fetchWatchflxCookies().also { watchflxCookies = it }
suspend fun fetchWatchflxCookies(): Map<String, String> {
session.get(watchflxAPI)
@ -813,7 +712,8 @@ suspend fun fetchWatchflxCookies(): Map<String, String> {
"continue_as_temp" to "true"
), cookies = cookies, headers = mapOf("X-Requested-With" to "XMLHttpRequest")
)
return session.baseClient.cookieJar.loadForRequest(loginUrl.toHttpUrl()).associate { it.name to it.value }
return session.baseClient.cookieJar.loadForRequest(loginUrl.toHttpUrl())
.associate { it.name to it.value }
}
fun Document.findTvMoviesIframe(): String? {
@ -1148,7 +1048,11 @@ fun String.decodePrimewireXor(key: String): String {
fun vidsrctoDecrypt(text: String): String {
val parse = Base64.decode(text.toByteArray(), Base64.URL_SAFE)
val cipher = Cipher.getInstance("RC4")
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec("8z5Ag5wgagfsOuhz".toByteArray(), "RC4"), cipher.parameters)
cipher.init(
Cipher.DECRYPT_MODE,
SecretKeySpec("8z5Ag5wgagfsOuhz".toByteArray(), "RC4"),
cipher.parameters
)
return decode(cipher.doFinal(parse).toString(Charsets.UTF_8))
}
@ -1288,7 +1192,7 @@ fun isUpcoming(dateString: String?): Boolean {
}
}
fun getDate() : TmdbDate {
fun getDate(): TmdbDate {
val formatter = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val calender = Calendar.getInstance()
val today = formatter.format(calender.time)
@ -1373,12 +1277,31 @@ private enum class Symbol(val decimalValue: Int) {
companion object {
fun closestBelow(value: Int) =
values()
entries.toTypedArray()
.sortedByDescending { it.decimalValue }
.firstOrNull { value >= it.decimalValue }
}
}
suspend fun request(
url: String,
allowRedirects: Boolean = true,
timeout: Long = 60L
): Response {
val client = OkHttpClient().newBuilder()
.connectTimeout(timeout, TimeUnit.SECONDS)
.readTimeout(timeout, TimeUnit.SECONDS)
.writeTimeout(timeout, TimeUnit.SECONDS)
.followRedirects(allowRedirects)
.followSslRedirects(allowRedirects)
.build()
val request: Request = Request.Builder()
.url(url)
.build()
return client.newCall(request).await()
}
object DumpUtils {
private val deviceId = getDeviceId()
@ -1644,4 +1567,4 @@ object AESGCM {
dateFormat.timeZone = TimeZone.getTimeZone("GMT")
return dateFormat.format(Date())
}
}
}

View File

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

View File

@ -13,8 +13,9 @@ import com.lagradost.cloudstream3.utils.AppUtils.toJson
import java.net.URI
import java.util.ArrayList
import kotlin.math.roundToInt
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
open class StremioX : MainAPI() {
open class StremioX : TmdbProvider() {
override var mainUrl = "https://torrentio.strem.fun"
override var name = "StremioX"
override val hasMainPage = true
@ -181,6 +182,7 @@ open class StremioX : MainAPI() {
this.showStatus = getStatus(res.status)
this.recommendations = recommendations
this.actors = actors
this.contentRating = fetchContentRating(data.id, "US")
addTrailer(trailer)
addTMDbId(data.id.toString())
addImdbId(res.external_ids?.imdb_id)
@ -202,6 +204,7 @@ open class StremioX : MainAPI() {
this.rating = rating
this.recommendations = recommendations
this.actors = actors
this.contentRating = fetchContentRating(data.id, "US")
addTrailer(trailer)
addTMDbId(data.id.toString())
addImdbId(res.external_ids?.imdb_id)

View File

@ -1,12 +1,12 @@
// use an integer for version numbers
version = 24
version = 25
cloudstream {
language = "hi"
// All of these properties are optional, you can safely remove them
description = "Include: Watchomovies"
description = "Includes: Watchomovies(NS*W), Max resolution is 720p in both extensions."
authors = listOf("Hexated")
/**

View File

@ -5,7 +5,7 @@ import com.lagradost.cloudstream3.TvType
import com.lagradost.cloudstream3.mainPageOf
class Watchomovies : YomoviesProvider() {
override var mainUrl = "https://watchomovies.beauty"
override var mainUrl = "https://watchomovies.lat"
override var name = "Watchomovies"
override var lang = "en"
override val supportedTypes = setOf(

View File

@ -10,7 +10,7 @@ import org.jsoup.nodes.Element
import java.net.URI
open class YomoviesProvider : MainAPI() {
override var mainUrl = "https://yomovies.show"
override var mainUrl = "https://yomovies.media"
private var directUrl = ""
override var name = "Yomovies"
override val hasMainPage = true

View File

@ -13,7 +13,7 @@ buildscript {
classpath("com.android.tools.build:gradle:7.0.4")
// Cloudstream gradle plugin which makes everything work and builds plugins
classpath("com.github.recloudstream:gradle:-SNAPSHOT")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21")
}
}