mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
[Sora] added flixon & animeKaizoku
This commit is contained in:
parent
7af99309a5
commit
5648710105
3 changed files with 214 additions and 20 deletions
|
@ -13,6 +13,7 @@ import com.lagradost.nicehttp.RequestBodyTypes
|
|||
import kotlinx.coroutines.delay
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.jsoup.Jsoup
|
||||
|
||||
val session = Session(Requests().baseClient)
|
||||
|
||||
|
@ -522,7 +523,8 @@ object SoraExtractor : SoraStream() {
|
|||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
|
||||
)
|
||||
).document
|
||||
val srcm3u8 = resDoc.selectFirst("script:containsData(let url =)")?.data()?.let {
|
||||
val srcm3u8 =
|
||||
resDoc.selectFirst("script:containsData(let url =)")?.data()?.let {
|
||||
Regex("['|\"](.*?.m3u8)['|\"]").find(it)?.groupValues?.getOrNull(1)
|
||||
}
|
||||
callback.invoke(
|
||||
|
@ -803,7 +805,8 @@ object SoraExtractor : SoraStream() {
|
|||
"versioncode" to "11",
|
||||
"clienttype" to "ios_jike_default"
|
||||
)
|
||||
val vipAPI = base64DecodeAPI("cA==YXA=cy8=Y20=di8=LnQ=b2s=a2w=bG8=aS4=YXA=ZS0=aWw=b2I=LW0=Z2E=Ly8=czo=dHA=aHQ=")
|
||||
val vipAPI =
|
||||
base64DecodeAPI("cA==YXA=cy8=Y20=di8=LnQ=b2s=a2w=bG8=aS4=YXA=ZS0=aWw=b2I=LW0=Z2E=Ly8=czo=dHA=aHQ=")
|
||||
val searchUrl = base64DecodeAPI("b20=LmM=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")
|
||||
val doc = app.get(
|
||||
"$searchUrl/search?keyword=$title",
|
||||
|
@ -1088,14 +1091,32 @@ object SoraExtractor : SoraStream() {
|
|||
|
||||
}
|
||||
|
||||
suspend fun invokeZoro(
|
||||
suspend fun invokeAnimes(
|
||||
id: Int? = null,
|
||||
title: String? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val malId = app.get("$tmdb2mal/?id=$id&s=$season").text.trim()
|
||||
val malId = if (season != null) app.get("$tmdb2mal/?id=$id&s=$season").text.trim() else null
|
||||
|
||||
argamap(
|
||||
{
|
||||
if (season != null) invokeZoro(malId, episode, subtitleCallback, callback)
|
||||
},
|
||||
{
|
||||
invokeAnimeKaizoku(title, malId, season, episode, callback)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun invokeZoro(
|
||||
malId: String? = null,
|
||||
episode: Int? = null,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val episodeId = app.get("$consumetMalAPI/info/$malId?provider=zoro")
|
||||
.parsedSafe<ConsumetDetails>()?.episodes?.find {
|
||||
it.number == episode
|
||||
|
@ -1131,7 +1152,74 @@ object SoraExtractor : SoraStream() {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private suspend fun invokeAnimeKaizoku(
|
||||
title: String? = null,
|
||||
malId: String? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val fixTitle = title.fixTitle()
|
||||
val search = app.get("$animeKaizokuAPI/?s=${fixTitle?.replace("-", " ")}").document
|
||||
val detailHref =
|
||||
search.select("ul#posts-container li").map { it.selectFirst("a")?.attr("href") }
|
||||
.find {
|
||||
if (season == null) it?.contains(
|
||||
fixTitle ?: return,
|
||||
true
|
||||
) == true else it?.contains(malId ?: return) == true
|
||||
}?.let { fixUrl(it, animeKaizokuAPI) }
|
||||
|
||||
val detail = app.get(detailHref ?: return).document
|
||||
val postId =
|
||||
detail.selectFirst("link[rel=shortlink]")?.attr("href")?.substringAfter("?p=") ?: return
|
||||
val script = detail.selectFirst("script:containsData(DDL)")?.data()?.splitData() ?: return
|
||||
|
||||
val media = fetchingKaizoku(animeKaizokuAPI, postId, script, detailHref).document
|
||||
val iframe = media.select("tbody td[colspan=2]").map { it.attr("onclick") to it.text() }
|
||||
.filter { it.second.contains("1080p", true) }
|
||||
|
||||
val eps = if (season == null) {
|
||||
null
|
||||
} else {
|
||||
if (episode!! < 10) "0$episode" else episode
|
||||
}
|
||||
|
||||
iframe.apmap { (data, name) ->
|
||||
val worker =
|
||||
fetchingKaizoku(animeKaizokuAPI, postId, data.splitData(), detailHref).document
|
||||
.select("tbody td")
|
||||
.map { Triple(it.attr("onclick"), it.text(), it.nextElementSibling()?.text()) }
|
||||
|
||||
val episodeData = worker.let { list ->
|
||||
if (season == null) list.firstOrNull() else list.find {
|
||||
it.second.contains(
|
||||
Regex("($eps\\.)|(-\\s$eps)")
|
||||
)
|
||||
}
|
||||
} ?: return@apmap null
|
||||
|
||||
val ouo = fetchingKaizoku(
|
||||
animeKaizokuAPI,
|
||||
postId,
|
||||
episodeData.first.splitData(),
|
||||
detailHref
|
||||
).text.substringAfter("openInNewTab(\"")
|
||||
.substringBefore("\")").let { base64Decode(it) }
|
||||
|
||||
if(!ouo.startsWith("https://ouo")) return@apmap null
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"AnimeKaizoku [${episodeData.third}]",
|
||||
"AnimeKaizoku [${episodeData.third}]",
|
||||
bypassOuo(ouo) ?: return@apmap null,
|
||||
"$animeKaizokuAPI/",
|
||||
Qualities.P1080.value,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun invokeLing(
|
||||
|
@ -1780,6 +1868,58 @@ object SoraExtractor : SoraStream() {
|
|||
)
|
||||
}
|
||||
|
||||
suspend fun invokeFlixon(
|
||||
tmdbId: Int? = null,
|
||||
imdbId: String? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val onionUrl = "https://onionplay.se/"
|
||||
val request = if (season == null) {
|
||||
val res = app.get("$flixonAPI/$imdbId", referer = onionUrl)
|
||||
if (res.text.contains("BEGIN PGP SIGNED MESSAGE")
|
||||
) app.get("$flixonAPI/$imdbId-1", referer = onionUrl) else res
|
||||
} else {
|
||||
app.get("$flixonAPI/$tmdbId-$season-$episode", referer = onionUrl)
|
||||
}
|
||||
|
||||
val script = request.document.selectFirst("script:containsData(= \"\";)")?.data()
|
||||
val collection = script?.substringAfter("= [")?.substringBefore("];")
|
||||
val num = script?.substringAfterLast("(value) -")?.substringBefore(");")?.trim()?.toInt()
|
||||
?: return
|
||||
|
||||
val iframe = collection?.split(",")?.map { it.trim().toInt() }?.map { nums ->
|
||||
nums.minus(num).toChar()
|
||||
}?.joinToString("")?.let { Jsoup.parse(it) }?.selectFirst("button.redirect")
|
||||
?.attr("onclick")
|
||||
?.substringAfter("('")?.substringBefore("')")
|
||||
|
||||
val unPacker =
|
||||
app.get(iframe ?: return).document.selectFirst("script:containsData(JuicyCodes.Run)")
|
||||
?.data()
|
||||
?.substringAfter("JuicyCodes.Run(")?.substringBefore(");")?.split("+")
|
||||
?.joinToString("") { it.replace("\"", "").trim() }
|
||||
?.let { getAndUnpack(base64Decode(it)) }
|
||||
|
||||
val ref = "https://onionflix.ru/"
|
||||
val link = Regex("[\"']file[\"']:[\"'](.+?)[\"'],").find(
|
||||
unPacker ?: return
|
||||
)?.groupValues?.getOrNull(1)?.let { app.get(it, referer = ref).url }
|
||||
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"Flixon",
|
||||
"Flixon",
|
||||
link ?: return,
|
||||
ref,
|
||||
Qualities.P720.value,
|
||||
link.contains(".m3u8")
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StreamM4u : XStreamCdn() {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.hexated
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.hexated.SoraExtractor.invoke123Movie
|
||||
import com.hexated.SoraExtractor.invokeAnimes
|
||||
import com.hexated.SoraExtractor.invokeBollyMaza
|
||||
import com.hexated.SoraExtractor.invokeDbgo
|
||||
import com.hexated.SoraExtractor.invokeFilmxy
|
||||
|
@ -21,6 +22,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
|||
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
|
||||
import com.hexated.SoraExtractor.invokeCrunchyroll
|
||||
import com.hexated.SoraExtractor.invokeFDMovies
|
||||
import com.hexated.SoraExtractor.invokeFlixon
|
||||
import com.hexated.SoraExtractor.invokeFwatayako
|
||||
import com.hexated.SoraExtractor.invokeGMovies
|
||||
import com.hexated.SoraExtractor.invokeKisskh
|
||||
|
@ -32,7 +34,6 @@ import com.hexated.SoraExtractor.invokeRStream
|
|||
import com.hexated.SoraExtractor.invokeSoraStream
|
||||
import com.hexated.SoraExtractor.invokeTvMovies
|
||||
import com.hexated.SoraExtractor.invokeUhdmovies
|
||||
import com.hexated.SoraExtractor.invokeZoro
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
|
@ -64,7 +65,8 @@ open class SoraStream : TmdbProvider() {
|
|||
base64DecodeAPI("cHA=LmE=ZWw=cmM=dmU=aC4=dGM=d2E=eHA=Ly8=czo=dHA=aHQ=")
|
||||
|
||||
// private var mainServerAPI = base64DecodeAPI("cA==YXA=bC4=Y2U=ZXI=LnY=aWU=b3Y=LW0=cmE=c28=Ly8=czo=dHA=aHQ=")
|
||||
var netMoviesAPI = base64DecodeAPI("aQ==YXA=cC8=YXA=bC4=Y2U=ZXI=LnY=bG0=Zmk=dC0=bmU=Ly8=czo=dHA=aHQ=")
|
||||
var netMoviesAPI =
|
||||
base64DecodeAPI("aQ==YXA=cC8=YXA=bC4=Y2U=ZXI=LnY=bG0=Zmk=dC0=bmU=Ly8=czo=dHA=aHQ=")
|
||||
const val twoEmbedAPI = "https://www.2embed.to"
|
||||
const val vidSrcAPI = "https://v2.vidsrc.me"
|
||||
const val dbgoAPI = "https://dbgo.fun"
|
||||
|
@ -95,6 +97,8 @@ open class SoraStream : TmdbProvider() {
|
|||
const val bollyMazaAPI = "https://b.bloginguru.info"
|
||||
const val moviesbayAPI = "https://moviesbay.live"
|
||||
const val rStreamAPI = "https://fsa.remotestre.am"
|
||||
const val flixonAPI = "https://flixon.ru"
|
||||
const val animeKaizokuAPI = "https://animekaizoku.com"
|
||||
|
||||
fun getType(t: String?): TvType {
|
||||
return when (t) {
|
||||
|
@ -350,13 +354,7 @@ open class SoraStream : TmdbProvider() {
|
|||
// )
|
||||
// },
|
||||
{
|
||||
if (res.season != null && res.isAnime) invokeZoro(
|
||||
res.id,
|
||||
res.season,
|
||||
res.episode,
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
if (res.isAnime) invokeAnimes(res.id, res.title, res.season, res.episode, subtitleCallback, callback)
|
||||
},
|
||||
{
|
||||
if (res.season != null && res.isAnime) invokeCrunchyroll(
|
||||
|
@ -516,7 +514,10 @@ open class SoraStream : TmdbProvider() {
|
|||
},
|
||||
{
|
||||
invokeRStream(res.id, res.season, res.episode, callback)
|
||||
}
|
||||
},
|
||||
{
|
||||
invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
|
||||
},
|
||||
)
|
||||
|
||||
return true
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.hexated
|
|||
import com.hexated.SoraStream.Companion.filmxyAPI
|
||||
import com.hexated.SoraStream.Companion.gdbot
|
||||
import com.hexated.SoraStream.Companion.tvMoviesAPI
|
||||
import com.lagradost.cloudstream3.APIHolder
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.base64Decode
|
||||
import com.lagradost.cloudstream3.base64Encode
|
||||
|
@ -12,6 +13,7 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import com.lagradost.cloudstream3.utils.SubtitleHelper
|
||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
import com.lagradost.nicehttp.NiceResponse
|
||||
import com.lagradost.nicehttp.RequestBodyTypes
|
||||
import com.lagradost.nicehttp.requestCreator
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -256,13 +258,64 @@ suspend fun extractCovyn(url: String?): Pair<String?, String?>? {
|
|||
}
|
||||
|
||||
fun getDirectGdrive(url: String): String {
|
||||
return if(url.endsWith("share_link")) {
|
||||
"https://drive.google.com/uc?id=${url.substringAfter("/d/").substringBefore("/")}&export=download"
|
||||
} else {
|
||||
return if (url.contains("&export=download")) {
|
||||
url
|
||||
} else {
|
||||
"https://drive.google.com/uc?id=${
|
||||
url.substringAfter("/d/").substringBefore("/")
|
||||
}&export=download"
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun bypassOuo(url: String?) : String? {
|
||||
var res = session.get(url ?: return null)
|
||||
(1..2).forEach { _ ->
|
||||
val document = res.document
|
||||
val nextUrl = document.select("form").attr("action")
|
||||
val data = document.select("form input").mapNotNull {
|
||||
it.attr("name") to it.attr("value")
|
||||
}.toMap().toMutableMap()
|
||||
val captchaKey = document.select("script[src*=https://www.google.com/recaptcha/api.js?render=]")
|
||||
.attr("src").substringAfter("render=")
|
||||
val token = APIHolder.getCaptchaToken(url, captchaKey)
|
||||
data["x-token"] = token ?: ""
|
||||
res = session.post(
|
||||
nextUrl,
|
||||
data = data,
|
||||
headers = mapOf("content-type" to "application/x-www-form-urlencoded"),
|
||||
allowRedirects = false
|
||||
)
|
||||
}
|
||||
|
||||
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? {
|
||||
val directUrl = app.get(url ?: return null, verify = false).document.select("a#link").attr("href")
|
||||
.substringAfter("/go/")
|
||||
|
@ -399,7 +452,7 @@ fun Document.findTvMoviesIframe(): String? {
|
|||
}
|
||||
|
||||
fun String?.fixTitle(): String? {
|
||||
return this?.replace(Regex("[!%:']|( &)"), "")?.replace(" ", "-")?.lowercase()
|
||||
return this?.replace(Regex("[!%:'?]|( &)"), "")?.replace(" ", "-")?.lowercase()
|
||||
?.replace("-–-", "-")
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue