mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
sora: fix upcloud,vidcloud, aniwatch
This commit is contained in:
parent
39d5247101
commit
f38a602b97
5 changed files with 38 additions and 27 deletions
|
@ -1,7 +1,7 @@
|
||||||
import org.jetbrains.kotlin.konan.properties.Properties
|
import org.jetbrains.kotlin.konan.properties.Properties
|
||||||
|
|
||||||
// use an integer for version numbers
|
// use an integer for version numbers
|
||||||
version = 145
|
version = 146
|
||||||
|
|
||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
|
|
@ -930,7 +930,7 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
argamap(
|
argamap(
|
||||||
{
|
{
|
||||||
invokeZoro(aniId, episode, subtitleCallback, callback)
|
invokeAniwatch(malId, episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeAnimeKaizoku(malId, epsTitle, season, episode, callback)
|
invokeAnimeKaizoku(malId, epsTitle, season, episode, callback)
|
||||||
|
@ -1004,28 +1004,26 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun invokeZoro(
|
private suspend fun invokeAniwatch(
|
||||||
aniId: Int? = null,
|
malId: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val animeId =
|
|
||||||
app.get("https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/anilist/anime/${aniId ?: return}.json")
|
|
||||||
.parsedSafe<MALSyncResponses>()?.pages?.zoro?.keys?.map { it }
|
|
||||||
val headers = mapOf(
|
val headers = mapOf(
|
||||||
"X-Requested-With" to "XMLHttpRequest",
|
"X-Requested-With" to "XMLHttpRequest",
|
||||||
)
|
)
|
||||||
|
val animeId = app.get("$malsyncAPI/mal/anime/${malId ?: return}").parsedSafe<MALSyncResponses>()?.sites?.zoro?.keys?.map { it }
|
||||||
animeId?.apmap { id ->
|
animeId?.apmap { id ->
|
||||||
val episodeId = app.get("$zoroAPI/ajax/episode/list/${id ?: return@apmap}", headers = headers)
|
val episodeId = app.get("$aniwatchAPI/ajax/v2/episode/list/${id ?: return@apmap}", headers = headers)
|
||||||
.parsedSafe<ZoroResponses>()?.html?.let {
|
.parsedSafe<AniwatchResponses>()?.html?.let {
|
||||||
Jsoup.parse(it)
|
Jsoup.parse(it)
|
||||||
}?.select("div.ss-list a")?.find { it.attr("data-number") == "${episode ?: 1}" }
|
}?.select("div.ss-list a")?.find { it.attr("data-number") == "${episode ?: 1}" }
|
||||||
?.attr("data-id")
|
?.attr("data-id")
|
||||||
|
|
||||||
val servers =
|
val servers =
|
||||||
app.get("$zoroAPI/ajax/episode/servers?episodeId=${episodeId ?: return@apmap}", headers = headers)
|
app.get("$aniwatchAPI/ajax/v2/episode/servers?episodeId=${episodeId ?: return@apmap}", headers = headers)
|
||||||
.parsedSafe<ZoroResponses>()?.html?.let { Jsoup.parse(it) }
|
.parsedSafe<AniwatchResponses>()?.html?.let { Jsoup.parse(it) }
|
||||||
?.select("div.item.server-item")?.map {
|
?.select("div.item.server-item")?.map {
|
||||||
Triple(
|
Triple(
|
||||||
it.text(),
|
it.text(),
|
||||||
|
@ -1035,22 +1033,21 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
servers?.apmap servers@{ server ->
|
servers?.apmap servers@{ server ->
|
||||||
val iframe =
|
val iframe = app.get("$aniwatchAPI/ajax/v2/episode/sources?id=${server.second ?: return@servers}", headers = headers)
|
||||||
app.get("$zoroAPI/ajax/episode/sources?id=${server.second ?: return@servers}", headers = headers)
|
.parsedSafe<AniwatchResponses>()?.link ?: return@servers
|
||||||
.parsedSafe<ZoroResponses>()?.link ?: return@servers
|
|
||||||
val audio = if (server.third == "sub") "Raw" else "English Dub"
|
val audio = if (server.third == "sub") "Raw" else "English Dub"
|
||||||
if (server.first.contains(Regex("Vidstreaming|MegaCloud|Vidcloud"))) {
|
if (server.first.contains(Regex("Vidstreaming|MegaCloud|Vidcloud"))) {
|
||||||
extractRabbitStream(
|
extractRabbitStream(
|
||||||
"${server.first} [$audio]",
|
"${server.first} [$audio]",
|
||||||
iframe,
|
iframe,
|
||||||
"$zoroAPI/",
|
"$aniwatchAPI/",
|
||||||
subtitleCallback,
|
subtitleCallback,
|
||||||
callback,
|
callback,
|
||||||
false,
|
false,
|
||||||
decryptKey = RabbitStream.getZoroKey()
|
decryptKey = RabbitStream.getZoroKey()
|
||||||
) { it }
|
) { it }
|
||||||
} else {
|
} else {
|
||||||
loadExtractor(iframe, "$zoroAPI/", subtitleCallback, callback)
|
loadExtractor(iframe, "$aniwatchAPI/", subtitleCallback, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -405,15 +405,15 @@ data class CrunchyrollSourcesResponses(
|
||||||
@JsonProperty("meta") val meta: CrunchyrollMeta? = null,
|
@JsonProperty("meta") val meta: CrunchyrollMeta? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class MALSyncPages(
|
data class MALSyncSites(
|
||||||
@JsonProperty("Zoro") val zoro: HashMap<String?, HashMap<String, String?>>? = hashMapOf(),
|
@JsonProperty("Zoro") val zoro: HashMap<String?, HashMap<String, String?>>? = hashMapOf(),
|
||||||
)
|
)
|
||||||
|
|
||||||
data class MALSyncResponses(
|
data class MALSyncResponses(
|
||||||
@JsonProperty("Pages") val pages: MALSyncPages? = null,
|
@JsonProperty("Sites") val sites: MALSyncSites? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class ZoroResponses(
|
data class AniwatchResponses(
|
||||||
@JsonProperty("html") val html: String? = null,
|
@JsonProperty("html") val html: String? = null,
|
||||||
@JsonProperty("link") val link: String? = null,
|
@JsonProperty("link") val link: String? = null,
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,7 +16,6 @@ import com.hexated.SoraExtractor.invokeMovieHab
|
||||||
import com.hexated.SoraExtractor.invokeNoverse
|
import com.hexated.SoraExtractor.invokeNoverse
|
||||||
import com.hexated.SoraExtractor.invokeSeries9
|
import com.hexated.SoraExtractor.invokeSeries9
|
||||||
import com.hexated.SoraExtractor.invokeVidSrc
|
import com.hexated.SoraExtractor.invokeVidSrc
|
||||||
import com.hexated.SoraExtractor.invokeXmovies
|
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||||
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
|
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
|
||||||
|
@ -100,7 +99,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val filmxyAPI = "https://www.filmxy.vip"
|
const val filmxyAPI = "https://www.filmxy.vip"
|
||||||
const val kimcartoonAPI = "https://kimcartoon.li"
|
const val kimcartoonAPI = "https://kimcartoon.li"
|
||||||
const val xMovieAPI = "https://xemovies.to"
|
const val xMovieAPI = "https://xemovies.to"
|
||||||
const val zoroAPI = "https://kaido.to"
|
const val aniwatchAPI = "https://aniwatch.to"
|
||||||
const val crunchyrollAPI = "https://beta-api.crunchyroll.com"
|
const val crunchyrollAPI = "https://beta-api.crunchyroll.com"
|
||||||
const val kissKhAPI = "https://kisskh.co"
|
const val kissKhAPI = "https://kisskh.co"
|
||||||
const val lingAPI = "https://ling-online.net"
|
const val lingAPI = "https://ling-online.net"
|
||||||
|
|
|
@ -21,6 +21,7 @@ import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
|
||||||
import com.lagradost.cloudstream3.APIHolder.unixTimeMS
|
import com.lagradost.cloudstream3.APIHolder.unixTimeMS
|
||||||
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
||||||
import com.lagradost.cloudstream3.utils.*
|
import com.lagradost.cloudstream3.utils.*
|
||||||
|
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.AppUtils.tryParseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||||
|
@ -578,7 +579,7 @@ suspend fun invokeSmashyIm(
|
||||||
Regex("['\"]?subtitle['\"]?:\\s*\"([^\"]+)").find(script)?.groupValues?.get(1) ?: return
|
Regex("['\"]?subtitle['\"]?:\\s*\"([^\"]+)").find(script)?.groupValues?.get(1) ?: return
|
||||||
|
|
||||||
M3u8Helper.generateM3u8(
|
M3u8Helper.generateM3u8(
|
||||||
name,
|
"Smashy [$name]",
|
||||||
sources,
|
sources,
|
||||||
""
|
""
|
||||||
).forEach(callback)
|
).forEach(callback)
|
||||||
|
@ -955,7 +956,7 @@ suspend fun searchWatchOnline(
|
||||||
}
|
}
|
||||||
|
|
||||||
//modified code from https://github.com/jmir1/aniyomi-extensions/blob/master/src/all/kamyroll/src/eu/kanade/tachiyomi/animeextension/all/kamyroll/AccessTokenInterceptor.kt
|
//modified code from https://github.com/jmir1/aniyomi-extensions/blob/master/src/all/kamyroll/src/eu/kanade/tachiyomi/animeextension/all/kamyroll/AccessTokenInterceptor.kt
|
||||||
fun getCrunchyrollToken(): Map<String, String> {
|
suspend fun getCrunchyrollToken(): Map<String, String> {
|
||||||
val client = app.baseClient.newBuilder()
|
val client = app.baseClient.newBuilder()
|
||||||
.proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress("cr-unblocker.us.to", 1080)))
|
.proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress("cr-unblocker.us.to", 1080)))
|
||||||
.build()
|
.build()
|
||||||
|
@ -975,7 +976,7 @@ fun getCrunchyrollToken(): Map<String, String> {
|
||||||
"Authorization" to "Basic ${BuildConfig.CRUNCHYROLL_BASIC_TOKEN}"
|
"Authorization" to "Basic ${BuildConfig.CRUNCHYROLL_BASIC_TOKEN}"
|
||||||
),
|
),
|
||||||
data = mapOf(
|
data = mapOf(
|
||||||
"refresh_token" to BuildConfig.CRUNCHYROLL_REFRESH_TOKEN,
|
"refresh_token" to app.get(BuildConfig.CRUNCHYROLL_REFRESH_TOKEN).text,
|
||||||
"grant_type" to "refresh_token",
|
"grant_type" to "refresh_token",
|
||||||
"scope" to "offline_access"
|
"scope" to "offline_access"
|
||||||
)
|
)
|
||||||
|
@ -1840,8 +1841,8 @@ object RabbitStream {
|
||||||
if (sources == null || encryptedMap.encrypted == false) {
|
if (sources == null || encryptedMap.encrypted == false) {
|
||||||
response.parsedSafe()
|
response.parsedSafe()
|
||||||
} else {
|
} else {
|
||||||
val decrypted =
|
val (realKey, encData) = extractRealKey(sources, decryptKey)
|
||||||
decryptMapped<List<Sources>>(sources, decryptKey)
|
val decrypted = decryptMapped<List<Sources>>(encData, realKey)
|
||||||
SourceObject(
|
SourceObject(
|
||||||
sources = decrypted,
|
sources = decrypted,
|
||||||
tracks = encryptedMap.tracks
|
tracks = encryptedMap.tracks
|
||||||
|
@ -1984,7 +1985,21 @@ object RabbitStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getZoroKey(): String {
|
suspend fun getZoroKey(): String {
|
||||||
return app.get("https://raw.githubusercontent.com/enimax-anime/key/e0/key.txt").text
|
return app.get("https://raw.githubusercontent.com/enimax-anime/key/e6/key.txt").text
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun extractRealKey(originalString: String?, stops: String) : Pair<String,String> {
|
||||||
|
val table = parseJson<List<List<Int>>>(stops)
|
||||||
|
val decryptedKey = StringBuilder()
|
||||||
|
var offset = 0
|
||||||
|
var encryptedString = originalString
|
||||||
|
|
||||||
|
table.forEach { (start, end) ->
|
||||||
|
decryptedKey.append(encryptedString?.substring(start - offset, end - offset))
|
||||||
|
encryptedString = encryptedString?.substring(0, start - offset) + encryptedString?.substring(end - offset)
|
||||||
|
offset += end - start
|
||||||
|
}
|
||||||
|
return decryptedKey.toString() to encryptedString.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T> decryptMapped(input: String, key: String): T? {
|
private inline fun <reified T> decryptMapped(input: String, key: String): T? {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue