mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
sora: added Putactor
This commit is contained in:
parent
d960e02d3a
commit
a4913d7ab7
6 changed files with 88 additions and 78 deletions
|
@ -1,7 +1,7 @@
|
|||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
// use an integer for version numbers
|
||||
version = 173
|
||||
version = 174
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
|
|
|
@ -1719,7 +1719,6 @@ object SoraExtractor : SoraStream() {
|
|||
imdbId: String? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
isAnime: Boolean = false,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
|
@ -1735,13 +1734,13 @@ object SoraExtractor : SoraStream() {
|
|||
it.attr("data-id") to it.text()
|
||||
}.apmap {
|
||||
when {
|
||||
(it.second.equals("Player F", true) || it.second.equals(
|
||||
it.second.equals("Player F", true) || it.second.equals(
|
||||
"Player N", true
|
||||
)) && !isAnime -> {
|
||||
) -> {
|
||||
invokeSmashyFfix(it.second, it.first, url, callback)
|
||||
}
|
||||
|
||||
it.second.equals("Player FM", true) && !isAnime -> invokeSmashyFm(
|
||||
it.second.equals("Player FM", true) -> invokeSmashyFm(
|
||||
it.second, it.first, url, callback
|
||||
)
|
||||
|
||||
|
@ -2034,6 +2033,26 @@ object SoraExtractor : SoraStream() {
|
|||
|
||||
}
|
||||
|
||||
suspend fun invokePutactor(
|
||||
title: String? = null,
|
||||
year: Int? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
invokeGpress(
|
||||
title,
|
||||
year,
|
||||
season,
|
||||
episode,
|
||||
callback,
|
||||
putactorAPI,
|
||||
"Putactor",
|
||||
"_VPzQdLFXWQppjNou",
|
||||
"_hfDAQaOJyNSkXHjy"
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun invokePrimewire(
|
||||
title: String? = null,
|
||||
year: Int? = null,
|
||||
|
@ -2041,8 +2060,32 @@ object SoraExtractor : SoraStream() {
|
|||
episode: Int? = null,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
fun String.decrypt(key: String): List<PrimewireSources>? {
|
||||
return tryParseJson<List<PrimewireSources>>(base64Decode(this).decodePrimewireXor(key))
|
||||
invokeGpress(
|
||||
title,
|
||||
year,
|
||||
season,
|
||||
episode,
|
||||
callback,
|
||||
primewireAPI,
|
||||
"Primewire",
|
||||
"RvnMfoxhgm",
|
||||
"vvqUtffkId"
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun invokeGpress(
|
||||
title: String? = null,
|
||||
year: Int? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
api: String,
|
||||
name: String,
|
||||
mediaSelector: String,
|
||||
episodeSelector: String,
|
||||
) {
|
||||
fun String.decrypt(key: String): List<GpressSources>? {
|
||||
return tryParseJson<List<GpressSources>>(base64Decode(this).decodePrimewireXor(key))
|
||||
}
|
||||
|
||||
val slug = getEpisodeSlug(season, episode)
|
||||
|
@ -2052,9 +2095,9 @@ object SoraExtractor : SoraStream() {
|
|||
"$title Season $season"
|
||||
}
|
||||
|
||||
val doc = app.get("$primewireAPI/search/$query").document
|
||||
val doc = app.get("$api/search/$query").document
|
||||
|
||||
val media = doc.select("div.RvnMfoxhgm").map {
|
||||
val media = doc.select("div.$mediaSelector").map {
|
||||
Triple(
|
||||
it.attr("data-filmName"), it.attr("data-year"), it.select("a").attr("href")
|
||||
)
|
||||
|
@ -2079,21 +2122,23 @@ object SoraExtractor : SoraStream() {
|
|||
} else {
|
||||
app.get(
|
||||
fixUrl(
|
||||
media.third, primewireAPI
|
||||
media.third,
|
||||
api
|
||||
)
|
||||
).document.selectFirst("div#vvqUtffkId a:contains(Episode ${slug.second})")
|
||||
).document.selectFirst("div#$episodeSelector a:contains(Episode ${slug.second})")
|
||||
?.attr("href")
|
||||
} ?: return
|
||||
|
||||
val res = app.get(fixUrl(iframe, primewireAPI), verify = false)
|
||||
val res = app.get(fixUrl(iframe, api), verify = false)
|
||||
val serverUrl = "var url = '(/user/servers/.*?\\?ep=.*?)';".toRegex()
|
||||
.find(res.text)?.groupValues?.get(1) ?: return
|
||||
val cookies = res.okhttpResponse.headers.getPrimewireCookies()
|
||||
val cookies = 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)
|
||||
val serverRes = app.get(
|
||||
"$primewireAPI$serverUrl", cookies = cookies, referer = url, headers = headers
|
||||
"$api$serverUrl",
|
||||
cookies = cookies, referer = url, headers = headers
|
||||
)
|
||||
val unpack = getAndUnpack(serverRes.text)
|
||||
val key = unpack.substringAfter("(key=").substringBefore(")")
|
||||
|
@ -2101,7 +2146,7 @@ object SoraExtractor : SoraStream() {
|
|||
serverRes.document.select("ul li").amap { el ->
|
||||
val server = el.attr("data-value")
|
||||
val encryptedData = app.get(
|
||||
"$url?server=$server&_=${unixTimeMS}",
|
||||
"$url?server=$server&_=$unixTimeMS",
|
||||
cookies = cookies,
|
||||
referer = url,
|
||||
headers = headers
|
||||
|
@ -2111,10 +2156,10 @@ object SoraExtractor : SoraStream() {
|
|||
qualities.filter { it <= video.max.toInt() }.forEach {
|
||||
callback(
|
||||
ExtractorLink(
|
||||
"Primewire",
|
||||
"Primewire",
|
||||
name,
|
||||
name,
|
||||
video.src.split("360", limit = 3).joinToString(it.toString()),
|
||||
"$primewireAPI/",
|
||||
"$api/",
|
||||
it,
|
||||
)
|
||||
)
|
||||
|
|
|
@ -31,7 +31,7 @@ data class AniSearch(
|
|||
@JsonProperty("data") var data: AniData? = AniData()
|
||||
)
|
||||
|
||||
data class PrimewireSources(
|
||||
data class GpressSources(
|
||||
@JsonProperty("src") val src: String,
|
||||
@JsonProperty("file") val file: String? = null,
|
||||
@JsonProperty("label") val label: Int? = null,
|
||||
|
|
|
@ -43,6 +43,7 @@ import com.hexated.SoraExtractor.invokeNetflix
|
|||
import com.hexated.SoraExtractor.invokeNetmovies
|
||||
import com.hexated.SoraExtractor.invokePobmovies
|
||||
import com.hexated.SoraExtractor.invokePrimewire
|
||||
import com.hexated.SoraExtractor.invokePutactor
|
||||
import com.hexated.SoraExtractor.invokeTvMovies
|
||||
import com.hexated.SoraExtractor.invokeUhdmovies
|
||||
import com.hexated.SoraExtractor.invokeVegamovies
|
||||
|
@ -124,6 +125,7 @@ open class SoraStream : TmdbProvider() {
|
|||
const val vidsrctoAPI = "https://vidsrc.to"
|
||||
const val dramadayAPI = "https://dramaday.me"
|
||||
const val animetoshoAPI = "https://animetosho.org"
|
||||
const val putactorAPI = "https://putlocker.actor"
|
||||
const val susflixAPI = "https://susflix.tv"
|
||||
const val jump1API = "https://ca.jump1.net"
|
||||
const val vegaMoviesAPI = "https://vegamovies.im"
|
||||
|
@ -152,7 +154,7 @@ open class SoraStream : TmdbProvider() {
|
|||
}
|
||||
}
|
||||
|
||||
fun base64DecodeAPI(api: String): String {
|
||||
private fun base64DecodeAPI(api: String): String {
|
||||
return api.chunked(4).map { base64Decode(it) }.reversed().joinToString("")
|
||||
}
|
||||
|
||||
|
@ -466,7 +468,7 @@ open class SoraStream : TmdbProvider() {
|
|||
)
|
||||
},
|
||||
{
|
||||
invokeLing(
|
||||
if (!res.isAnime) invokeLing(
|
||||
res.title,
|
||||
res.airedYear ?: res.year,
|
||||
res.season,
|
||||
|
@ -486,7 +488,7 @@ open class SoraStream : TmdbProvider() {
|
|||
)
|
||||
},
|
||||
{
|
||||
invokeFwatayako(res.imdbId, res.season, res.episode, callback)
|
||||
if (!res.isAnime) invokeFwatayako(res.imdbId, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokeGMovies(
|
||||
|
@ -516,7 +518,7 @@ open class SoraStream : TmdbProvider() {
|
|||
)
|
||||
},
|
||||
{
|
||||
invokeTvMovies(res.title, res.season, res.episode, callback)
|
||||
if (!res.isAnime) invokeTvMovies(res.title, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokeMoviezAdd(
|
||||
|
@ -541,23 +543,22 @@ open class SoraStream : TmdbProvider() {
|
|||
)
|
||||
},
|
||||
{
|
||||
invokeRStream(res.id, res.season, res.episode, callback)
|
||||
if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
|
||||
if (!res.isAnime) invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
invokeSmashyStream(
|
||||
if (!res.isAnime) invokeSmashyStream(
|
||||
res.imdbId,
|
||||
res.season,
|
||||
res.episode,
|
||||
res.isAnime,
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeWatchsomuch(
|
||||
if (!res.isAnime) invokeWatchsomuch(
|
||||
res.imdbId,
|
||||
res.season,
|
||||
res.episode,
|
||||
|
@ -583,17 +584,11 @@ open class SoraStream : TmdbProvider() {
|
|||
)
|
||||
},
|
||||
{
|
||||
invokePrimewire(res.title, res.year, res.season, res.episode, callback)
|
||||
if (!res.isAnime) invokePrimewire(res.title, res.year, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokePutactor(res.title, res.year, res.season, res.episode, callback)
|
||||
},
|
||||
// {
|
||||
// if (!res.isAnime) invokeGdbotMovies(
|
||||
// res.title,
|
||||
// res.year,
|
||||
// res.season,
|
||||
// res.episode,
|
||||
// callback
|
||||
// )
|
||||
// },
|
||||
{
|
||||
if (!res.isAnime) invokeShinobiMovies(
|
||||
shinobiMovieAPI,
|
||||
|
|
|
@ -28,6 +28,7 @@ import com.hexated.SoraExtractor.invokeMultimovies
|
|||
import com.hexated.SoraExtractor.invokeNetflix
|
||||
import com.hexated.SoraExtractor.invokeNetmovies
|
||||
import com.hexated.SoraExtractor.invokePrimewire
|
||||
import com.hexated.SoraExtractor.invokePutactor
|
||||
import com.hexated.SoraExtractor.invokeVidSrc
|
||||
import com.hexated.SoraExtractor.invokeVidsrcto
|
||||
import com.hexated.SoraExtractor.invokeWatchOnline
|
||||
|
@ -65,7 +66,7 @@ class SoraStreamLite : SoraStream() {
|
|||
// )
|
||||
// },
|
||||
{
|
||||
invokeWatchsomuch(
|
||||
if (!res.isAnime) invokeWatchsomuch(
|
||||
res.imdbId,
|
||||
res.season,
|
||||
res.episode,
|
||||
|
@ -129,16 +130,6 @@ class SoraStreamLite : SoraStream() {
|
|||
callback
|
||||
)
|
||||
},
|
||||
// {
|
||||
// invokeUniqueStream(
|
||||
// res.title,
|
||||
// res.year,
|
||||
// res.season,
|
||||
// res.episode,
|
||||
// subtitleCallback,
|
||||
// callback
|
||||
// )
|
||||
// },
|
||||
{
|
||||
if (!res.isAnime) invokeFilmxy(
|
||||
res.imdbId,
|
||||
|
@ -158,25 +149,14 @@ class SoraStreamLite : SoraStream() {
|
|||
)
|
||||
},
|
||||
{
|
||||
invokeSmashyStream(
|
||||
if (!res.isAnime) invokeSmashyStream(
|
||||
res.imdbId,
|
||||
res.season,
|
||||
res.episode,
|
||||
res.isAnime,
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
},
|
||||
// {
|
||||
// invokeXmovies(
|
||||
// res.title,
|
||||
// res.year,
|
||||
// res.season,
|
||||
// res.episode,
|
||||
// subtitleCallback,
|
||||
// callback
|
||||
// )
|
||||
// },
|
||||
{
|
||||
if (!res.isAnime) invokeVidsrcto(
|
||||
res.imdbId,
|
||||
|
@ -198,7 +178,7 @@ class SoraStreamLite : SoraStream() {
|
|||
)
|
||||
},
|
||||
{
|
||||
invokeLing(
|
||||
if (!res.isAnime) invokeLing(
|
||||
res.title,
|
||||
res.airedYear ?: res.year,
|
||||
res.season,
|
||||
|
@ -221,13 +201,16 @@ class SoraStreamLite : SoraStream() {
|
|||
)
|
||||
},
|
||||
{
|
||||
invokeRStream(res.id, res.season, res.episode, callback)
|
||||
if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
|
||||
if (!res.isAnime) invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
invokePrimewire(res.title, res.year, res.season, res.episode, callback)
|
||||
if (!res.isAnime) invokePrimewire(res.title, res.year, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokePutactor(res.title, res.year, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
invokeWatchOnline(
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.hexated
|
|||
import android.util.Base64
|
||||
import com.hexated.DumpUtils.queryApi
|
||||
import com.hexated.SoraStream.Companion.anilistAPI
|
||||
import com.hexated.SoraStream.Companion.base64DecodeAPI
|
||||
import com.hexated.SoraStream.Companion.crunchyrollAPI
|
||||
import com.hexated.SoraStream.Companion.filmxyAPI
|
||||
import com.hexated.SoraStream.Companion.gdbot
|
||||
|
@ -26,7 +25,6 @@ import com.lagradost.nicehttp.RequestBodyTypes
|
|||
import com.lagradost.nicehttp.requestCreator
|
||||
import kotlinx.coroutines.delay
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
|
@ -1202,17 +1200,6 @@ fun String.decodePrimewireXor(key: String): String {
|
|||
return sb.toString()
|
||||
}
|
||||
|
||||
fun Headers.getPrimewireCookies(cookieKey: String = "set-cookie"): Map<String, String> {
|
||||
val cookieList =
|
||||
this.filter { it.first.equals(cookieKey, ignoreCase = true) }.mapNotNull {
|
||||
it.second.split(";").firstOrNull()
|
||||
}
|
||||
return cookieList.associate {
|
||||
val split = it.split("=", limit = 2)
|
||||
(split.getOrNull(0)?.trim() ?: "") to (split.getOrNull(1)?.trim() ?: "")
|
||||
}.filter { it.key.isNotBlank() && it.value.isNotBlank() }
|
||||
}
|
||||
|
||||
fun String?.createSlug(): String? {
|
||||
return this?.replace(Regex("[^\\w\\s-]"), "")
|
||||
?.replace(" ", "-")
|
||||
|
|
Loading…
Reference in a new issue