mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
small clean
This commit is contained in:
parent
09b46cbac1
commit
e8cd0a9af3
4 changed files with 3 additions and 277 deletions
|
@ -1,6 +1,7 @@
|
||||||
package com.hexated
|
package com.hexated
|
||||||
|
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
|
import com.lagradost.cloudstream3.APIHolder.unixTimeMS
|
||||||
import com.lagradost.cloudstream3.utils.*
|
import com.lagradost.cloudstream3.utils.*
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||||
import com.lagradost.nicehttp.Requests
|
import com.lagradost.nicehttp.Requests
|
||||||
|
@ -697,72 +698,6 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeFmovies(
|
|
||||||
title: String? = null,
|
|
||||||
year: Int? = null,
|
|
||||||
season: Int? = null,
|
|
||||||
episode: Int? = null,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
) {
|
|
||||||
val query = title?.replace(Regex("[^\\w-\\s]"), "")
|
|
||||||
val html =
|
|
||||||
app.get("$fmoviesAPI/ajax/film/search?keyword=$query")
|
|
||||||
.parsedSafe<FmoviesResponses>()?.result?.html
|
|
||||||
|
|
||||||
val mediaId = Jsoup.parse(html ?: return).select("a.item").map {
|
|
||||||
Triple(
|
|
||||||
it.attr("href"),
|
|
||||||
it.select("div.name").text(),
|
|
||||||
it.select("span.dot")[1].text(),
|
|
||||||
)
|
|
||||||
}.find {
|
|
||||||
if (season == null) {
|
|
||||||
it.first.contains("/movie/")
|
|
||||||
} else {
|
|
||||||
it.first.contains("/tv/")
|
|
||||||
} && (it.second.equals(title, true) || it.second.createSlug()
|
|
||||||
.equals(title.createSlug())) && it.third.toInt() == year
|
|
||||||
}?.first
|
|
||||||
|
|
||||||
val watchId =
|
|
||||||
app.get(fixUrl(mediaId ?: return, fmoviesAPI)).document.selectFirst("div.watch")
|
|
||||||
?.attr("data-id")
|
|
||||||
|
|
||||||
val episodeId = app.get(
|
|
||||||
"$fmoviesAPI/ajax/episode/list/${watchId ?: return}?vrf=${
|
|
||||||
comsumetEncodeVrf(watchId)
|
|
||||||
}"
|
|
||||||
).parsedSafe<FmoviesResult>()?.result?.let { Jsoup.parse(it) }
|
|
||||||
?.selectFirst("ul[data-season=${season ?: 1}] li a[data-num=${episode ?: 1}]")
|
|
||||||
?.attr("data-id")
|
|
||||||
|
|
||||||
val servers =
|
|
||||||
app.get(
|
|
||||||
"$fmoviesAPI/ajax/server/list/${episodeId ?: return}?vrf=${
|
|
||||||
comsumetEncodeVrf(
|
|
||||||
episodeId
|
|
||||||
)
|
|
||||||
}"
|
|
||||||
)
|
|
||||||
.parsedSafe<FmoviesResult>()?.result?.let { Jsoup.parse(it) }
|
|
||||||
?.select("ul li")?.map { it.attr("data-id") to it.attr("data-link-id") }
|
|
||||||
|
|
||||||
servers?.filter {
|
|
||||||
it.first == "41" || it.first == "45"
|
|
||||||
}?.apmap { (serverid, linkId) ->
|
|
||||||
delay(2000)
|
|
||||||
val decryptServer =
|
|
||||||
app.get("$fmoviesAPI/ajax/server/$linkId?vrf=${comsumetEncodeVrf(linkId)}")
|
|
||||||
.parsedSafe<FmoviesResponses>()?.result?.url?.let { comsumetDecodeVrf(it) }
|
|
||||||
if (serverid == "41") {
|
|
||||||
invokeVizcloud(serverid, decryptServer ?: return@apmap, subtitleCallback, callback)
|
|
||||||
} else {
|
|
||||||
loadExtractor(decryptServer ?: return@apmap, fmoviesAPI, subtitleCallback, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun invokeVidsrcto(
|
suspend fun invokeVidsrcto(
|
||||||
imdbId: String?,
|
imdbId: String?,
|
||||||
season: Int?,
|
season: Int?,
|
||||||
|
@ -2344,7 +2279,7 @@ object SoraExtractor : SoraStream() {
|
||||||
serverRes.document.select("ul li").amap { el ->
|
serverRes.document.select("ul li").amap { el ->
|
||||||
val server = el.attr("data-value")
|
val server = el.attr("data-value")
|
||||||
val encryptedData = app.get(
|
val encryptedData = app.get(
|
||||||
"$url?server=$server&_=${System.currentTimeMillis()}",
|
"$url?server=$server&_=${unixTimeMS}",
|
||||||
cookies = cookies,
|
cookies = cookies,
|
||||||
referer = url,
|
referer = url,
|
||||||
headers = headers
|
headers = headers
|
||||||
|
|
|
@ -36,7 +36,6 @@ data class PrimewireSources(
|
||||||
@JsonProperty("file") val file: String? = null,
|
@JsonProperty("file") val file: String? = null,
|
||||||
@JsonProperty("label") val label: Int? = null,
|
@JsonProperty("label") val label: Int? = null,
|
||||||
@JsonProperty("max") val max: String,
|
@JsonProperty("max") val max: String,
|
||||||
@JsonProperty("size") val size: String,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
data class UHDBackupUrl(
|
data class UHDBackupUrl(
|
||||||
|
@ -234,33 +233,11 @@ data class CryMoviesResponse(
|
||||||
@JsonProperty("streams") val streams: List<CryMoviesStream>? = null,
|
@JsonProperty("streams") val streams: List<CryMoviesStream>? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class FmoviesResponses(
|
|
||||||
@JsonProperty("result") val result: FmoviesResult? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class FmoviesResult(
|
|
||||||
@JsonProperty("html") val html: String? = null,
|
|
||||||
@JsonProperty("result") val result: String? = null,
|
|
||||||
@JsonProperty("url") val url: String? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class FmoviesSubtitles(
|
data class FmoviesSubtitles(
|
||||||
@JsonProperty("label") val label: String? = null,
|
@JsonProperty("label") val label: String? = null,
|
||||||
@JsonProperty("file") val file: String? = null,
|
@JsonProperty("file") val file: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class VizcloudSources(
|
|
||||||
@JsonProperty("file") val file: String? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class VizcloudResult(
|
|
||||||
@JsonProperty("sources") val sources: ArrayList<VizcloudSources>? = arrayListOf(),
|
|
||||||
)
|
|
||||||
|
|
||||||
data class VizcloudResponses(
|
|
||||||
@JsonProperty("result") val result: VizcloudResult? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class AnilistExternalLinks(
|
data class AnilistExternalLinks(
|
||||||
@JsonProperty("id") var id: Int? = null,
|
@JsonProperty("id") var id: Int? = null,
|
||||||
@JsonProperty("site") var site: String? = null,
|
@JsonProperty("site") var site: String? = null,
|
||||||
|
|
|
@ -80,7 +80,6 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val gdbot = "https://gdtot.pro"
|
const val gdbot = "https://gdtot.pro"
|
||||||
const val anilistAPI = "https://graphql.anilist.co"
|
const val anilistAPI = "https://graphql.anilist.co"
|
||||||
const val malsyncAPI = "https://api.malsync.moe"
|
const val malsyncAPI = "https://api.malsync.moe"
|
||||||
const val consumetHelper = "https://api.consumet.org/anime/9anime/helper"
|
|
||||||
const val jikanAPI = "https://api.jikan.moe/v4"
|
const val jikanAPI = "https://api.jikan.moe/v4"
|
||||||
const val watchhubApi = "https://watchhub.strem.io"
|
const val watchhubApi = "https://watchhub.strem.io"
|
||||||
|
|
||||||
|
@ -115,7 +114,6 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
|
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
|
||||||
const val watchOnlineAPI = "https://watchonline.ag"
|
const val watchOnlineAPI = "https://watchonline.ag"
|
||||||
const val nineTvAPI = "https://moviesapi.club"
|
const val nineTvAPI = "https://moviesapi.club"
|
||||||
const val fmoviesAPI = "https://fmovies.to"
|
|
||||||
const val nowTvAPI = "https://myfilestorage.xyz"
|
const val nowTvAPI = "https://myfilestorage.xyz"
|
||||||
const val gokuAPI = "https://goku.sx"
|
const val gokuAPI = "https://goku.sx"
|
||||||
const val ridomoviesAPI = "https://ridomovies.pw"
|
const val ridomoviesAPI = "https://ridomovies.pw"
|
||||||
|
|
|
@ -4,10 +4,8 @@ import android.util.Base64
|
||||||
import com.hexated.DumpUtils.queryApi
|
import com.hexated.DumpUtils.queryApi
|
||||||
import com.hexated.SoraStream.Companion.anilistAPI
|
import com.hexated.SoraStream.Companion.anilistAPI
|
||||||
import com.hexated.SoraStream.Companion.base64DecodeAPI
|
import com.hexated.SoraStream.Companion.base64DecodeAPI
|
||||||
import com.hexated.SoraStream.Companion.consumetHelper
|
|
||||||
import com.hexated.SoraStream.Companion.crunchyrollAPI
|
import com.hexated.SoraStream.Companion.crunchyrollAPI
|
||||||
import com.hexated.SoraStream.Companion.filmxyAPI
|
import com.hexated.SoraStream.Companion.filmxyAPI
|
||||||
import com.hexated.SoraStream.Companion.fmoviesAPI
|
|
||||||
import com.hexated.SoraStream.Companion.gdbot
|
import com.hexated.SoraStream.Companion.gdbot
|
||||||
import com.hexated.SoraStream.Companion.hdmovies4uAPI
|
import com.hexated.SoraStream.Companion.hdmovies4uAPI
|
||||||
import com.hexated.SoraStream.Companion.malsyncAPI
|
import com.hexated.SoraStream.Companion.malsyncAPI
|
||||||
|
@ -47,8 +45,6 @@ import kotlin.math.min
|
||||||
|
|
||||||
var watchflxCookies: Map<String, String>? = null
|
var watchflxCookies: Map<String, String>? = null
|
||||||
var filmxyCookies: Map<String,String>? = null
|
var filmxyCookies: Map<String,String>? = null
|
||||||
val bflixChipperKey = base64DecodeAPI("Yjc=ejM=TzA=YTk=WHE=WnU=bXU=RFo=")
|
|
||||||
const val bflixKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
|
||||||
val encodedIndex = arrayOf(
|
val encodedIndex = arrayOf(
|
||||||
"GamMovies",
|
"GamMovies",
|
||||||
"JSMovies",
|
"JSMovies",
|
||||||
|
@ -435,33 +431,6 @@ suspend fun getDirectGdrive(url: String): String {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeVizcloud(
|
|
||||||
serverid: String,
|
|
||||||
url: String,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit,
|
|
||||||
) {
|
|
||||||
val id = Regex("(?:/embed[-/]|/e/)([^?/]*)").find(url)?.groupValues?.getOrNull(1)
|
|
||||||
app.get("$consumetHelper?query=${id ?: return}&action=vizcloud")
|
|
||||||
.parsedSafe<VizcloudResponses>()?.result?.sources?.map {
|
|
||||||
M3u8Helper.generateM3u8(
|
|
||||||
"Vizcloud",
|
|
||||||
it.file ?: return@map,
|
|
||||||
"${getBaseUrl(url)}/"
|
|
||||||
).forEach(callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
val sub = app.get("${fmoviesAPI}/ajax/episode/subtitles/$serverid")
|
|
||||||
tryParseJson<List<FmoviesSubtitles>>(sub.text)?.map {
|
|
||||||
subtitleCallback.invoke(
|
|
||||||
SubtitleFile(
|
|
||||||
it.label ?: "",
|
|
||||||
it.file ?: return@map
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun invokeSmashyFfix(
|
suspend fun invokeSmashyFfix(
|
||||||
name: String,
|
name: String,
|
||||||
url: String,
|
url: String,
|
||||||
|
@ -644,32 +613,6 @@ suspend fun bypassOuo(url: String?): String? {
|
||||||
return res.headers["location"]
|
return res.headers["location"]
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchingKaizoku(
|
|
||||||
domain: String,
|
|
||||||
postId: String,
|
|
||||||
data: List<String>,
|
|
||||||
ref: String
|
|
||||||
): NiceResponse {
|
|
||||||
return app.post(
|
|
||||||
"$domain/wp-admin/admin-ajax.php",
|
|
||||||
data = mapOf(
|
|
||||||
"action" to "DDL",
|
|
||||||
"post_id" to postId,
|
|
||||||
"div_id" to data.first(),
|
|
||||||
"tab_id" to data[1],
|
|
||||||
"num" to data[2],
|
|
||||||
"folder" to data.last()
|
|
||||||
),
|
|
||||||
headers = mapOf("X-Requested-With" to "XMLHttpRequest"),
|
|
||||||
referer = ref
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.splitData(): List<String> {
|
|
||||||
return this.substringAfterLast("DDL(").substringBefore(")").split(",")
|
|
||||||
.map { it.replace("'", "").trim() }
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun bypassFdAds(url: String?): String? {
|
suspend fun bypassFdAds(url: String?): String? {
|
||||||
val directUrl =
|
val directUrl =
|
||||||
app.get(url ?: return null, verify = false).document.select("a#link").attr("href")
|
app.get(url ?: return null, verify = false).document.select("a#link").attr("href")
|
||||||
|
@ -1131,14 +1074,6 @@ fun getSeason(month: Int?): String? {
|
||||||
return seasons[month - 1]
|
return seasons[month - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPutlockerQuality(quality: String): Int {
|
|
||||||
return when {
|
|
||||||
quality.contains("NAME=\"1080p\"") || quality.contains("RESOLUTION=1920x1080") -> Qualities.P1080.value
|
|
||||||
quality.contains("NAME=\"720p\"") || quality.contains("RESOLUTION=1280x720") -> Qualities.P720.value
|
|
||||||
else -> Qualities.P480.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getEpisodeSlug(
|
fun getEpisodeSlug(
|
||||||
season: Int? = null,
|
season: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
|
@ -1225,7 +1160,7 @@ fun decodeIndexJson(json: String): String {
|
||||||
return base64Decode(slug.substring(0, slug.length - 20))
|
return base64Decode(slug.substring(0, slug.length - 20))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.decodePrimewireXor(key: String = BuildConfig.PRIMEWIRE_KEY): String {
|
fun String.decodePrimewireXor(key: String): String {
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
var i = 0
|
var i = 0
|
||||||
while (i < this.length) {
|
while (i < this.length) {
|
||||||
|
@ -1321,16 +1256,6 @@ fun getGMoviesQuality(str: String): Int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSoraQuality(quality: String): Int {
|
|
||||||
return when (quality) {
|
|
||||||
"GROOT_FD" -> Qualities.P360.value
|
|
||||||
"GROOT_LD" -> Qualities.P480.value
|
|
||||||
"GROOT_SD" -> Qualities.P720.value
|
|
||||||
"GROOT_HD" -> Qualities.P1080.value
|
|
||||||
else -> Qualities.Unknown.value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFDoviesQuality(str: String): String {
|
fun getFDoviesQuality(str: String): String {
|
||||||
return when {
|
return when {
|
||||||
str.contains("1080P", true) -> "1080P"
|
str.contains("1080P", true) -> "1080P"
|
||||||
|
@ -1369,115 +1294,6 @@ fun getDeviceId(length: Int = 16): String {
|
||||||
.joinToString("")
|
.joinToString("")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun comsumetEncodeVrf(query: String): String? {
|
|
||||||
return app.get("$consumetHelper?query=$query&action=fmovies-vrf", timeout = 30L)
|
|
||||||
.parsedSafe<Map<String, String>>()?.get("url")
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun comsumetDecodeVrf(query: String): String? {
|
|
||||||
val res = app.get("$consumetHelper?query=$query&action=fmovies-decrypt", timeout = 30L)
|
|
||||||
return tryParseJson<Map<String, String>>(res.text)?.get("url")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun encodeVrf(query: String): String {
|
|
||||||
return encode(
|
|
||||||
encryptVrf(
|
|
||||||
cipherVrf(bflixChipperKey, encode(query)),
|
|
||||||
bflixKey
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun decodeVrf(text: String): String {
|
|
||||||
return decode(cipherVrf(bflixChipperKey, decryptVrf(text, bflixKey)))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("SameParameterValue")
|
|
||||||
private fun encryptVrf(input: String, key: String): String {
|
|
||||||
if (input.any { it.code > 255 }) throw Exception("illegal characters!")
|
|
||||||
var output = ""
|
|
||||||
for (i in input.indices step 3) {
|
|
||||||
val a = intArrayOf(-1, -1, -1, -1)
|
|
||||||
a[0] = input[i].code shr 2
|
|
||||||
a[1] = (3 and input[i].code) shl 4
|
|
||||||
if (input.length > i + 1) {
|
|
||||||
a[1] = a[1] or (input[i + 1].code shr 4)
|
|
||||||
a[2] = (15 and input[i + 1].code) shl 2
|
|
||||||
}
|
|
||||||
if (input.length > i + 2) {
|
|
||||||
a[2] = a[2] or (input[i + 2].code shr 6)
|
|
||||||
a[3] = 63 and input[i + 2].code
|
|
||||||
}
|
|
||||||
for (n in a) {
|
|
||||||
if (n == -1) output += "="
|
|
||||||
else {
|
|
||||||
if (n in 0..63) output += key[n]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("SameParameterValue")
|
|
||||||
private fun decryptVrf(input: String, key: String): String {
|
|
||||||
val t = if (input.replace("""[\t\n\f\r]""".toRegex(), "").length % 4 == 0) {
|
|
||||||
input.replace("""==?$""".toRegex(), "")
|
|
||||||
} else input
|
|
||||||
if (t.length % 4 == 1 || t.contains("""[^+/\dA-Za-z]""".toRegex())) throw Exception("bad input")
|
|
||||||
var i: Int
|
|
||||||
var r = ""
|
|
||||||
var e = 0
|
|
||||||
var u = 0
|
|
||||||
for (o in t.indices) {
|
|
||||||
e = e shl 6
|
|
||||||
i = key.indexOf(t[o])
|
|
||||||
e = e or i
|
|
||||||
u += 6
|
|
||||||
if (24 == u) {
|
|
||||||
r += ((16711680 and e) shr 16).toChar()
|
|
||||||
r += ((65280 and e) shr 8).toChar()
|
|
||||||
r += (255 and e).toChar()
|
|
||||||
e = 0
|
|
||||||
u = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return if (12 == u) {
|
|
||||||
e = e shr 4
|
|
||||||
r + e.toChar()
|
|
||||||
} else {
|
|
||||||
if (18 == u) {
|
|
||||||
e = e shr 2
|
|
||||||
r += ((65280 and e) shr 8).toChar()
|
|
||||||
r += (255 and e).toChar()
|
|
||||||
}
|
|
||||||
r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun cipherVrf(key: String, text: String): String {
|
|
||||||
val arr = IntArray(256) { it }
|
|
||||||
|
|
||||||
var u = 0
|
|
||||||
var r: Int
|
|
||||||
arr.indices.forEach {
|
|
||||||
u = (u + arr[it] + key[it % key.length].code) % 256
|
|
||||||
r = arr[it]
|
|
||||||
arr[it] = arr[u]
|
|
||||||
arr[u] = r
|
|
||||||
}
|
|
||||||
u = 0
|
|
||||||
var c = 0
|
|
||||||
|
|
||||||
return text.indices.map { j ->
|
|
||||||
c = (c + 1) % 256
|
|
||||||
u = (u + arr[c]) % 256
|
|
||||||
r = arr[c]
|
|
||||||
arr[c] = arr[u]
|
|
||||||
arr[u] = r
|
|
||||||
(text[j].code xor arr[(arr[c] + arr[u]) % 256]).toChar()
|
|
||||||
}.joinToString("")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.encodeUrl(): String {
|
fun String.encodeUrl(): String {
|
||||||
val url = URL(this)
|
val url = URL(this)
|
||||||
val uri = URI(url.protocol, url.userInfo, url.host, url.port, url.path, url.query, url.ref)
|
val uri = URI(url.protocol, url.userInfo, url.host, url.port, url.path, url.query, url.ref)
|
||||||
|
|
Loading…
Reference in a new issue