[Sora] added flixon & animeKaizoku

This commit is contained in:
hexated 2023-01-11 08:28:46 +07:00
parent 7af99309a5
commit 5648710105
3 changed files with 214 additions and 20 deletions

View file

@ -13,6 +13,7 @@ import com.lagradost.nicehttp.RequestBodyTypes
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import org.jsoup.Jsoup
val session = Session(Requests().baseClient) 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" "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"
) )
).document ).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) Regex("['|\"](.*?.m3u8)['|\"]").find(it)?.groupValues?.getOrNull(1)
} }
callback.invoke( callback.invoke(
@ -803,7 +805,8 @@ object SoraExtractor : SoraStream() {
"versioncode" to "11", "versioncode" to "11",
"clienttype" to "ios_jike_default" "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 searchUrl = base64DecodeAPI("b20=LmM=b2s=a2w=bG8=Ly8=czo=dHA=aHQ=")
val doc = app.get( val doc = app.get(
"$searchUrl/search?keyword=$title", "$searchUrl/search?keyword=$title",
@ -1088,14 +1091,32 @@ object SoraExtractor : SoraStream() {
} }
suspend fun invokeZoro( suspend fun invokeAnimes(
id: Int? = null, id: Int? = null,
title: String? = null,
season: Int? = null, season: Int? = null,
episode: Int? = null, episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit, subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> 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") val episodeId = app.get("$consumetMalAPI/info/$malId?provider=zoro")
.parsedSafe<ConsumetDetails>()?.episodes?.find { .parsedSafe<ConsumetDetails>()?.episodes?.find {
it.number == episode 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( suspend fun invokeLing(
@ -1760,13 +1848,13 @@ object SoraExtractor : SoraStream() {
episode: Int? = null, episode: Int? = null,
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
) { ) {
val url = if(season == null) { val url = if (season == null) {
"$rStreamAPI/Movies/$id/$id.mp4" "$rStreamAPI/Movies/$id/$id.mp4"
} else { } else {
"$rStreamAPI/Shows/$id/$season/$episode.mp4" "$rStreamAPI/Shows/$id/$season/$episode.mp4"
} }
if(!app.get(url).isSuccessful) return if (!app.get(url).isSuccessful) return
delay(4000) delay(4000)
callback.invoke( callback.invoke(
@ -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() { class StreamM4u : XStreamCdn() {

View file

@ -2,6 +2,7 @@ package com.hexated
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.hexated.SoraExtractor.invoke123Movie import com.hexated.SoraExtractor.invoke123Movie
import com.hexated.SoraExtractor.invokeAnimes
import com.hexated.SoraExtractor.invokeBollyMaza import com.hexated.SoraExtractor.invokeBollyMaza
import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeDbgo
import com.hexated.SoraExtractor.invokeFilmxy import com.hexated.SoraExtractor.invokeFilmxy
@ -21,6 +22,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.lagradost.cloudstream3.metaproviders.TmdbProvider
import com.hexated.SoraExtractor.invokeCrunchyroll import com.hexated.SoraExtractor.invokeCrunchyroll
import com.hexated.SoraExtractor.invokeFDMovies import com.hexated.SoraExtractor.invokeFDMovies
import com.hexated.SoraExtractor.invokeFlixon
import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeFwatayako
import com.hexated.SoraExtractor.invokeGMovies import com.hexated.SoraExtractor.invokeGMovies
import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeKisskh
@ -32,7 +34,6 @@ import com.hexated.SoraExtractor.invokeRStream
import com.hexated.SoraExtractor.invokeSoraStream import com.hexated.SoraExtractor.invokeSoraStream
import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeTvMovies
import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeUhdmovies
import com.hexated.SoraExtractor.invokeZoro
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.ExtractorLink 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=") 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=") // 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 twoEmbedAPI = "https://www.2embed.to"
const val vidSrcAPI = "https://v2.vidsrc.me" const val vidSrcAPI = "https://v2.vidsrc.me"
const val dbgoAPI = "https://dbgo.fun" const val dbgoAPI = "https://dbgo.fun"
@ -95,6 +97,8 @@ open class SoraStream : TmdbProvider() {
const val bollyMazaAPI = "https://b.bloginguru.info" const val bollyMazaAPI = "https://b.bloginguru.info"
const val moviesbayAPI = "https://moviesbay.live" const val moviesbayAPI = "https://moviesbay.live"
const val rStreamAPI = "https://fsa.remotestre.am" const val rStreamAPI = "https://fsa.remotestre.am"
const val flixonAPI = "https://flixon.ru"
const val animeKaizokuAPI = "https://animekaizoku.com"
fun getType(t: String?): TvType { fun getType(t: String?): TvType {
return when (t) { return when (t) {
@ -350,13 +354,7 @@ open class SoraStream : TmdbProvider() {
// ) // )
// }, // },
{ {
if (res.season != null && res.isAnime) invokeZoro( if (res.isAnime) invokeAnimes(res.id, res.title, res.season, res.episode, subtitleCallback, callback)
res.id,
res.season,
res.episode,
subtitleCallback,
callback
)
}, },
{ {
if (res.season != null && res.isAnime) invokeCrunchyroll( if (res.season != null && res.isAnime) invokeCrunchyroll(
@ -516,7 +514,10 @@ open class SoraStream : TmdbProvider() {
}, },
{ {
invokeRStream(res.id, res.season, res.episode, callback) invokeRStream(res.id, res.season, res.episode, callback)
} },
{
invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
},
) )
return true return true

View file

@ -3,6 +3,7 @@ package com.hexated
import com.hexated.SoraStream.Companion.filmxyAPI import com.hexated.SoraStream.Companion.filmxyAPI
import com.hexated.SoraStream.Companion.gdbot import com.hexated.SoraStream.Companion.gdbot
import com.hexated.SoraStream.Companion.tvMoviesAPI import com.hexated.SoraStream.Companion.tvMoviesAPI
import com.lagradost.cloudstream3.APIHolder
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.base64Decode import com.lagradost.cloudstream3.base64Decode
import com.lagradost.cloudstream3.base64Encode 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.Qualities
import com.lagradost.cloudstream3.utils.SubtitleHelper import com.lagradost.cloudstream3.utils.SubtitleHelper
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.nicehttp.NiceResponse
import com.lagradost.nicehttp.RequestBodyTypes import com.lagradost.nicehttp.RequestBodyTypes
import com.lagradost.nicehttp.requestCreator import com.lagradost.nicehttp.requestCreator
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -256,13 +258,64 @@ suspend fun extractCovyn(url: String?): Pair<String?, String?>? {
} }
fun getDirectGdrive(url: String): String { fun getDirectGdrive(url: String): String {
return if(url.endsWith("share_link")) { return if (url.contains("&export=download")) {
"https://drive.google.com/uc?id=${url.substringAfter("/d/").substringBefore("/")}&export=download"
} else {
url 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? { suspend fun bypassFdAds(url: String?): String? {
val directUrl = app.get(url ?: return null, verify = false).document.select("a#link").attr("href") val directUrl = app.get(url ?: return null, verify = false).document.select("a#link").attr("href")
.substringAfter("/go/") .substringAfter("/go/")
@ -399,7 +452,7 @@ fun Document.findTvMoviesIframe(): String? {
} }
fun String?.fixTitle(): String? { fun String?.fixTitle(): String? {
return this?.replace(Regex("[!%:']|( &)"), "")?.replace(" ", "-")?.lowercase() return this?.replace(Regex("[!%:'?]|( &)"), "")?.replace(" ", "-")?.lowercase()
?.replace("--", "-") ?.replace("--", "-")
} }