mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
sora: added Blackmovies & JSMovies
This commit is contained in:
parent
b99e6dad07
commit
b0847b21dd
5 changed files with 146 additions and 201 deletions
|
@ -1,5 +1,5 @@
|
||||||
// use an integer for version numbers
|
// use an integer for version numbers
|
||||||
version = 83
|
version = 84
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
cloudstream {
|
||||||
|
|
|
@ -22,46 +22,6 @@ val session = Session(Requests().baseClient)
|
||||||
|
|
||||||
object SoraExtractor : SoraStream() {
|
object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
/*
|
|
||||||
suspend fun invokeLocalSources(
|
|
||||||
url: String,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit
|
|
||||||
) {
|
|
||||||
val doc = app.get(
|
|
||||||
url,
|
|
||||||
headers = mapOf("User-Agent" to RandomUserAgent.getRandomUserAgent())
|
|
||||||
).document
|
|
||||||
val script = doc.select("script").find { it.data().contains("\"sources\":[") }?.data()
|
|
||||||
val sourcesData = script?.substringAfter("\"sources\":[")?.substringBefore("],")
|
|
||||||
val subData = script?.substringAfter("\"subtitles\":[")?.substringBefore("],")
|
|
||||||
|
|
||||||
tryParseJson<List<Sources>>("[$sourcesData]")?.map { source ->
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
this.name,
|
|
||||||
this.name,
|
|
||||||
source.url ?: return@map null,
|
|
||||||
"$mainServerAPI/",
|
|
||||||
source.quality?.toIntOrNull() ?: Qualities.Unknown.value,
|
|
||||||
isM3u8 = source.isM3U8,
|
|
||||||
headers = mapOf("Origin" to mainServerAPI)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
tryParseJson<List<Subtitles>>("[$subData]")?.map { sub ->
|
|
||||||
subtitleCallback.invoke(
|
|
||||||
SubtitleFile(
|
|
||||||
sub.lang.toString(),
|
|
||||||
sub.url ?: return@map null
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
suspend fun invokeTwoEmbed(
|
suspend fun invokeTwoEmbed(
|
||||||
id: Int? = null,
|
id: Int? = null,
|
||||||
season: Int? = null,
|
season: Int? = null,
|
||||||
|
@ -348,7 +308,7 @@ object SoraExtractor : SoraStream() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val request = app.get("$hdMovieBoxAPI/watch/$fixTitle")
|
val request = app.get("$hdMovieBoxAPI/watch/$fixTitle")
|
||||||
if (!request.isSuccessful) return
|
if (!request.isSuccessful) return
|
||||||
val doc = request.document
|
val doc = request.document
|
||||||
|
@ -416,7 +376,7 @@ object SoraExtractor : SoraStream() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val url = if (season == null) {
|
val url = if (season == null) {
|
||||||
"$series9API/film/$fixTitle/watching.html"
|
"$series9API/film/$fixTitle/watching.html"
|
||||||
} else {
|
} else {
|
||||||
|
@ -461,7 +421,7 @@ object SoraExtractor : SoraStream() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val url = if (season == null) {
|
val url = if (season == null) {
|
||||||
"$idlixAPI/movie/$fixTitle-$year"
|
"$idlixAPI/movie/$fixTitle-$year"
|
||||||
} else {
|
} else {
|
||||||
|
@ -498,7 +458,7 @@ object SoraExtractor : SoraStream() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val url = if (season == null) {
|
val url = if (season == null) {
|
||||||
"$uniqueStreamAPI/movies/$fixTitle-$year"
|
"$uniqueStreamAPI/movies/$fixTitle-$year"
|
||||||
} else {
|
} else {
|
||||||
|
@ -558,7 +518,7 @@ object SoraExtractor : SoraStream() {
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val url = if (season == null) {
|
val url = if (season == null) {
|
||||||
"$noverseAPI/movie/$fixTitle/download/"
|
"$noverseAPI/movie/$fixTitle/download/"
|
||||||
} else {
|
} else {
|
||||||
|
@ -721,7 +681,7 @@ object SoraExtractor : SoraStream() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val doc = if (season == null || season == 1) {
|
val doc = if (season == null || season == 1) {
|
||||||
app.get("$kimcartoonAPI/Cartoon/$fixTitle").document
|
app.get("$kimcartoonAPI/Cartoon/$fixTitle").document
|
||||||
} else {
|
} else {
|
||||||
|
@ -905,7 +865,7 @@ object SoraExtractor : SoraStream() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val doc = if (season == null) {
|
val doc = if (season == null) {
|
||||||
val res = app.get("$xMovieAPI/movies/$fixTitle/watch")
|
val res = app.get("$xMovieAPI/movies/$fixTitle/watch")
|
||||||
if (res.url == "$xMovieAPI/") app.get("$xMovieAPI/movies/$fixTitle-$year/watch").document else res.document
|
if (res.url == "$xMovieAPI/") app.get("$xMovieAPI/movies/$fixTitle-$year/watch").document else res.document
|
||||||
|
@ -1300,7 +1260,7 @@ object SoraExtractor : SoraStream() {
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val url = if (season == null) {
|
val url = if (season == null) {
|
||||||
"$uhdmoviesAPI/download-${title.fixTitle()}-$year"
|
"$uhdmoviesAPI/download-${title.createSlug()}-$year"
|
||||||
} else {
|
} else {
|
||||||
val url = "$uhdmoviesAPI/?s=$title"
|
val url = "$uhdmoviesAPI/?s=$title"
|
||||||
var doc = app.get(url).document
|
var doc = app.get(url).document
|
||||||
|
@ -1440,7 +1400,7 @@ object SoraExtractor : SoraStream() {
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val url = if (season == null || season == 1) {
|
val url = if (season == null || season == 1) {
|
||||||
"$gMoviesAPI/$fixTitle-$year"
|
"$gMoviesAPI/$fixTitle-$year"
|
||||||
} else {
|
} else {
|
||||||
|
@ -1489,7 +1449,7 @@ object SoraExtractor : SoraStream() {
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val url = if (season == null) {
|
val url = if (season == null) {
|
||||||
"$fdMoviesAPI/movies/$fixTitle"
|
"$fdMoviesAPI/movies/$fixTitle"
|
||||||
} else {
|
} else {
|
||||||
|
@ -1548,7 +1508,7 @@ object SoraExtractor : SoraStream() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val res = app.get("$m4uhdAPI/search/${title.fixTitle()}.html").document
|
val res = app.get("$m4uhdAPI/search/${title.createSlug()}.html").document
|
||||||
val scriptData = res.select("div.row div.item").map {
|
val scriptData = res.select("div.row div.item").map {
|
||||||
Triple(
|
Triple(
|
||||||
it.selectFirst("img.imagecover")?.attr("title"),
|
it.selectFirst("img.imagecover")?.attr("title"),
|
||||||
|
@ -1634,7 +1594,7 @@ object SoraExtractor : SoraStream() {
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val url = if (season == null) {
|
val url = if (season == null) {
|
||||||
"$tvMoviesAPI/show/$fixTitle"
|
"$tvMoviesAPI/show/$fixTitle"
|
||||||
} else {
|
} else {
|
||||||
|
@ -1667,7 +1627,7 @@ object SoraExtractor : SoraStream() {
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val id = searchCrunchyrollAnimeId(title ?: return) ?: searchKamyrollAnimeId(title) ?: return
|
val id = searchCrunchyrollAnimeId(title ?: return) ?: return
|
||||||
val detail = app.get("$consumetCrunchyrollAPI/info?id=$id&mediaType=series").text
|
val detail = app.get("$consumetCrunchyrollAPI/info?id=$id&mediaType=series").text
|
||||||
val epsId = tryParseJson<CrunchyrollDetails>(detail)?.findCrunchyrollId(
|
val epsId = tryParseJson<CrunchyrollDetails>(detail)?.findCrunchyrollId(
|
||||||
title,
|
title,
|
||||||
|
@ -1715,7 +1675,7 @@ object SoraExtractor : SoraStream() {
|
||||||
val json = app.get(url, referer = "$moviesbayAPI/")
|
val json = app.get(url, referer = "$moviesbayAPI/")
|
||||||
.parsedSafe<MoviesbayValues>()?.values
|
.parsedSafe<MoviesbayValues>()?.values
|
||||||
|
|
||||||
val media = json?.find { it.first() == "${title.fixTitle()}-$year" }
|
val media = json?.find { it.first() == "${title.createSlug()}-$year" }
|
||||||
|
|
||||||
media?.filter { it.startsWith("https://drive.google.com") }?.apmap {
|
media?.filter { it.startsWith("https://drive.google.com") }?.apmap {
|
||||||
val index = media.indexOf(it)
|
val index = media.indexOf(it)
|
||||||
|
@ -1779,7 +1739,7 @@ object SoraExtractor : SoraStream() {
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
) {
|
) {
|
||||||
val fixTitle = title?.fixTitle()?.replace("-", " ")
|
val fixTitle = title?.createSlug()?.replace("-", " ")
|
||||||
val doc = app.get("$apiUrl/?s=$fixTitle").document
|
val doc = app.get("$apiUrl/?s=$fixTitle").document
|
||||||
|
|
||||||
val matchMedia = doc.select("article.mh-loop-item").map {
|
val matchMedia = doc.select("article.mh-loop-item").map {
|
||||||
|
@ -1926,7 +1886,7 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeMovie123(
|
suspend fun invokeMovie123Net(
|
||||||
title: String? = null,
|
title: String? = null,
|
||||||
season: Int? = null,
|
season: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
|
@ -1934,11 +1894,11 @@ object SoraExtractor : SoraStream() {
|
||||||
callback: (ExtractorLink) -> Unit,
|
callback: (ExtractorLink) -> Unit,
|
||||||
) {
|
) {
|
||||||
val server = "https://vidcloud9.org"
|
val server = "https://vidcloud9.org"
|
||||||
val fixTitle = title.fixTitle()
|
val fixTitle = title.createSlug()
|
||||||
val m = app.get("$movie123NetAPI/searching?q=$title&limit=40")
|
val m = app.get("$movie123NetAPI/searching?q=$title&limit=40")
|
||||||
.parsedSafe<Movie123Search>()?.data?.find {
|
.parsedSafe<Movie123Search>()?.data?.find {
|
||||||
if (season == null) {
|
if (season == null) {
|
||||||
(it.t.equals(title, true) || it.t.fixTitle()
|
(it.t.equals(title, true) || it.t.createSlug()
|
||||||
.equals(fixTitle)) && it.t?.contains("season", true) == false
|
.equals(fixTitle)) && it.t?.contains("season", true) == false
|
||||||
} else {
|
} else {
|
||||||
it.t?.equals(
|
it.t?.equals(
|
||||||
|
@ -2002,26 +1962,43 @@ object SoraExtractor : SoraStream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeSmashyStream(
|
suspend fun invokeSmashyStream(
|
||||||
id: Int? = null,
|
imdbId: String? = null,
|
||||||
season: Int? = null,
|
season: Int? = null,
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit,
|
callback: (ExtractorLink) -> Unit,
|
||||||
) {
|
) {
|
||||||
val url = if (season == null) {
|
val url = if (season == null) {
|
||||||
"$smashyStreamAPI/playere.php?tmdb=$id"
|
"$smashyStreamAPI/gtop/tv.php?imdb=$imdbId"
|
||||||
} else {
|
} else {
|
||||||
"$smashyStreamAPI/playere.php?tmdb=$id&season=$season&episode=$episode"
|
"$smashyStreamAPI/gtop/tv.php?imdb=$imdbId&s=$season&e=$episode"
|
||||||
}
|
|
||||||
app.get(url).document.select("div.dropdown.servers a").map {
|
|
||||||
it.text() to it.attr("data-id")
|
|
||||||
}.apmap { (server, link) ->
|
|
||||||
when (val player = server.replace("Server", "Player").trim()) {
|
|
||||||
"Player 1" -> invokeSmashy1(player, link, subtitleCallback, callback)
|
|
||||||
"Player 2" -> invokeSmashy2(player, link, callback)
|
|
||||||
else -> return@apmap null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val doc = app.get(url).document
|
||||||
|
val script = doc.selectFirst("script:containsData(var secret)")?.data() ?: return
|
||||||
|
val secret =
|
||||||
|
script.substringAfter("secret = \"").substringBefore("\";").let { base64Decode(it) }
|
||||||
|
val key = script.substringAfter("token = \"").substringBefore("\";")
|
||||||
|
val source = app.get(
|
||||||
|
"$secret$key",
|
||||||
|
headers = mapOf(
|
||||||
|
"X-Requested-With" to "XMLHttpRequest"
|
||||||
|
)
|
||||||
|
).parsedSafe<Smashy1Source>() ?: return
|
||||||
|
|
||||||
|
val videoUrl = base64Decode(source.file ?: return)
|
||||||
|
val quality = Regex("(\\d{3,4})[Pp]").find(videoUrl)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
||||||
|
?: Qualities.P720.value
|
||||||
|
callback.invoke(
|
||||||
|
ExtractorLink(
|
||||||
|
"SmashyStream",
|
||||||
|
"SmashyStream",
|
||||||
|
videoUrl,
|
||||||
|
"",
|
||||||
|
quality,
|
||||||
|
videoUrl.contains(".m3u8")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO only subs
|
//TODO only subs
|
||||||
|
@ -2128,6 +2105,46 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun invokeJsmovies(
|
||||||
|
apiUrl: String,
|
||||||
|
api: String,
|
||||||
|
title: String? = null,
|
||||||
|
year: Int? = null,
|
||||||
|
season: Int? = null,
|
||||||
|
episode: Int? = null,
|
||||||
|
callback: (ExtractorLink) -> Unit,
|
||||||
|
) {
|
||||||
|
invokeChillmovies(
|
||||||
|
apiUrl,
|
||||||
|
api,
|
||||||
|
title,
|
||||||
|
year,
|
||||||
|
season,
|
||||||
|
episode,
|
||||||
|
callback,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun invokeBlackmovies(
|
||||||
|
apiUrl: String,
|
||||||
|
api: String,
|
||||||
|
title: String? = null,
|
||||||
|
year: Int? = null,
|
||||||
|
season: Int? = null,
|
||||||
|
episode: Int? = null,
|
||||||
|
callback: (ExtractorLink) -> Unit,
|
||||||
|
) {
|
||||||
|
invokeChillmovies(
|
||||||
|
apiUrl,
|
||||||
|
api,
|
||||||
|
title,
|
||||||
|
year,
|
||||||
|
season,
|
||||||
|
episode,
|
||||||
|
callback,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun invokeGammovies(
|
suspend fun invokeGammovies(
|
||||||
apiUrl: String,
|
apiUrl: String,
|
||||||
api: String,
|
api: String,
|
||||||
|
@ -2197,6 +2214,12 @@ object SoraExtractor : SoraStream() {
|
||||||
episode: Int? = null,
|
episode: Int? = null,
|
||||||
callback: (ExtractorLink) -> Unit,
|
callback: (ExtractorLink) -> Unit,
|
||||||
) {
|
) {
|
||||||
|
val encodedIndex = arrayOf(
|
||||||
|
"Gammovies",
|
||||||
|
"JSMovies",
|
||||||
|
"Blackmovies"
|
||||||
|
)
|
||||||
|
|
||||||
val query = getIndexQuery(title, year, season, episode)
|
val query = getIndexQuery(title, year, season, episode)
|
||||||
val body =
|
val body =
|
||||||
"""{"q":"$query","password":null,"page_token":null,"page_index":0}""".toRequestBody(
|
"""{"q":"$query","password":null,"page_token":null,"page_index":0}""".toRequestBody(
|
||||||
|
@ -2207,7 +2230,7 @@ object SoraExtractor : SoraStream() {
|
||||||
"page_token" to "",
|
"page_token" to "",
|
||||||
"page_index" to "0"
|
"page_index" to "0"
|
||||||
)
|
)
|
||||||
val search = if (api == "Gammovies") {
|
val search = if (api in encodedIndex) {
|
||||||
decodeIndexJson(app.post("${apiUrl}search", data = data).text)
|
decodeIndexJson(app.post("${apiUrl}search", data = data).text)
|
||||||
} else {
|
} else {
|
||||||
app.post("${apiUrl}search", requestBody = body).text
|
app.post("${apiUrl}search", requestBody = body).text
|
||||||
|
@ -2220,7 +2243,7 @@ object SoraExtractor : SoraStream() {
|
||||||
val pathData = mapOf(
|
val pathData = mapOf(
|
||||||
"id" to file.id,
|
"id" to file.id,
|
||||||
)
|
)
|
||||||
val path = (if (api == "Gammovies") {
|
val path = (if (api in encodedIndex) {
|
||||||
app.post(
|
app.post(
|
||||||
"${apiUrl}id2path", data = pathData
|
"${apiUrl}id2path", data = pathData
|
||||||
)
|
)
|
||||||
|
@ -2512,27 +2535,6 @@ data class DataAni(
|
||||||
@JsonProperty("data") val data: MediaAni? = null,
|
@JsonProperty("data") val data: MediaAni? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class KamyrollSearch(
|
|
||||||
@JsonProperty("items") var items: ArrayList<KamyrollItems> = arrayListOf()
|
|
||||||
)
|
|
||||||
|
|
||||||
data class KamyrollItems(
|
|
||||||
@JsonProperty("type") var type: String? = null,
|
|
||||||
@JsonProperty("items") var items: ArrayList<KamyrollAnimes> = arrayListOf()
|
|
||||||
)
|
|
||||||
|
|
||||||
data class KamyrollAnimes(
|
|
||||||
@JsonProperty("id") var id: String? = null,
|
|
||||||
@JsonProperty("slug_title") var slugTitle: String? = null,
|
|
||||||
@JsonProperty("title") var title: String? = null,
|
|
||||||
@JsonProperty("media_type") var mediaType: String? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
data class KamyrollToken(
|
|
||||||
@JsonProperty("access_token") val access_token: String? = null,
|
|
||||||
@JsonProperty("token_type") val token_type: String? = null,
|
|
||||||
)
|
|
||||||
|
|
||||||
data class Smashy1Tracks(
|
data class Smashy1Tracks(
|
||||||
@JsonProperty("file") val file: String? = null,
|
@JsonProperty("file") val file: String? = null,
|
||||||
@JsonProperty("label") val label: String? = null,
|
@JsonProperty("label") val label: String? = null,
|
||||||
|
|
|
@ -4,6 +4,7 @@ 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.invokeAnimes
|
||||||
import com.hexated.SoraExtractor.invokeBaymovies
|
import com.hexated.SoraExtractor.invokeBaymovies
|
||||||
|
import com.hexated.SoraExtractor.invokeBlackmovies
|
||||||
import com.hexated.SoraExtractor.invokeBollyMaza
|
import com.hexated.SoraExtractor.invokeBollyMaza
|
||||||
import com.hexated.SoraExtractor.invokeChillmovies0
|
import com.hexated.SoraExtractor.invokeChillmovies0
|
||||||
import com.hexated.SoraExtractor.invokeChillmovies1
|
import com.hexated.SoraExtractor.invokeChillmovies1
|
||||||
|
@ -29,10 +30,11 @@ 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.invokeGammovies
|
import com.hexated.SoraExtractor.invokeGammovies
|
||||||
|
import com.hexated.SoraExtractor.invokeJsmovies
|
||||||
import com.hexated.SoraExtractor.invokeKisskh
|
import com.hexated.SoraExtractor.invokeKisskh
|
||||||
import com.hexated.SoraExtractor.invokeLing
|
import com.hexated.SoraExtractor.invokeLing
|
||||||
import com.hexated.SoraExtractor.invokeM4uhd
|
import com.hexated.SoraExtractor.invokeM4uhd
|
||||||
import com.hexated.SoraExtractor.invokeMovie123
|
import com.hexated.SoraExtractor.invokeMovie123Net
|
||||||
import com.hexated.SoraExtractor.invokeMoviesbay
|
import com.hexated.SoraExtractor.invokeMoviesbay
|
||||||
import com.hexated.SoraExtractor.invokeMoviezAdd
|
import com.hexated.SoraExtractor.invokeMoviezAdd
|
||||||
import com.hexated.SoraExtractor.invokeRStream
|
import com.hexated.SoraExtractor.invokeRStream
|
||||||
|
@ -65,7 +67,6 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val jikanAPI = "https://api.jikan.moe/v4"
|
const val jikanAPI = "https://api.jikan.moe/v4"
|
||||||
const val gdbot = "https://gdbot.xyz"
|
const val gdbot = "https://gdbot.xyz"
|
||||||
const val consumetAnilistAPI = "https://api.consumet.org/meta/anilist"
|
const val consumetAnilistAPI = "https://api.consumet.org/meta/anilist"
|
||||||
const val kamyrollAPI = "https://api.kamyroll.tech"
|
|
||||||
const val baymovies = "https://opengatewayindex.pages.dev"
|
const val baymovies = "https://opengatewayindex.pages.dev"
|
||||||
|
|
||||||
private val apiKey =
|
private val apiKey =
|
||||||
|
@ -112,11 +113,13 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val animeKaizokuAPI = "https://animekaizoku.com"
|
const val animeKaizokuAPI = "https://animekaizoku.com"
|
||||||
const val movie123NetAPI = "https://ww7.0123movie.net"
|
const val movie123NetAPI = "https://ww7.0123movie.net"
|
||||||
const val smashyStreamAPI = "https://embed.smashystream.com"
|
const val smashyStreamAPI = "https://embed.smashystream.com"
|
||||||
|
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
|
||||||
const val baymoviesAPI = "https://thebayindexpublicgroupapi.zindex.eu.org"
|
const val baymoviesAPI = "https://thebayindexpublicgroupapi.zindex.eu.org"
|
||||||
const val chillmovies0API = "https://chill.aicirou.workers.dev/0:"
|
const val chillmovies0API = "https://chill.aicirou.workers.dev/0:"
|
||||||
const val chillmovies1API = "https://chill.aicirou.workers.dev/1:"
|
const val chillmovies1API = "https://chill.aicirou.workers.dev/1:"
|
||||||
const val gamMoviesAPI = "https://drive.gamick.workers.dev/0:"
|
const val gamMoviesAPI = "https://drive.gamick.workers.dev/0:"
|
||||||
const val watchSomuchAPI = "https://watchsomuch.tv" // sub only
|
const val jsMoviesAPI = "https://jsupload.jnsbot.workers.dev/0:"
|
||||||
|
const val blackMoviesAPI = "https://dl.blacklistedbois.workers.dev/0:"
|
||||||
|
|
||||||
fun getType(t: String?): TvType {
|
fun getType(t: String?): TvType {
|
||||||
return when (t) {
|
return when (t) {
|
||||||
|
@ -549,10 +552,10 @@ open class SoraStream : TmdbProvider() {
|
||||||
invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
|
invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeMovie123(res.title, res.season, res.episode, subtitleCallback, callback)
|
invokeMovie123Net(res.title, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeSmashyStream(res.id, res.season, res.episode, subtitleCallback, callback)
|
invokeSmashyStream(res.imdbId, res.season, res.episode, callback)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
if (!res.isAnime) invokeBaymovies(
|
if (!res.isAnime) invokeBaymovies(
|
||||||
|
@ -586,7 +589,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
invokeGammovies(
|
if (!res.isAnime) invokeGammovies(
|
||||||
gamMoviesAPI,
|
gamMoviesAPI,
|
||||||
"Gammovies",
|
"Gammovies",
|
||||||
res.title,
|
res.title,
|
||||||
|
@ -604,6 +607,28 @@ open class SoraStream : TmdbProvider() {
|
||||||
subtitleCallback
|
subtitleCallback
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
if (!res.isAnime) invokeBlackmovies(
|
||||||
|
blackMoviesAPI,
|
||||||
|
"Blackmovies",
|
||||||
|
res.title,
|
||||||
|
res.year,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
if (!res.isAnime) invokeJsmovies(
|
||||||
|
jsMoviesAPI,
|
||||||
|
"JSMovies",
|
||||||
|
res.title,
|
||||||
|
res.year,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -14,9 +14,11 @@ import com.hexated.SoraExtractor.invokeKimcartoon
|
||||||
import com.hexated.SoraExtractor.invokeKisskh
|
import com.hexated.SoraExtractor.invokeKisskh
|
||||||
import com.hexated.SoraExtractor.invokeLing
|
import com.hexated.SoraExtractor.invokeLing
|
||||||
import com.hexated.SoraExtractor.invokeM4uhd
|
import com.hexated.SoraExtractor.invokeM4uhd
|
||||||
|
import com.hexated.SoraExtractor.invokeMovie123Net
|
||||||
import com.hexated.SoraExtractor.invokeMovieHab
|
import com.hexated.SoraExtractor.invokeMovieHab
|
||||||
import com.hexated.SoraExtractor.invokeRStream
|
import com.hexated.SoraExtractor.invokeRStream
|
||||||
import com.hexated.SoraExtractor.invokeSeries9
|
import com.hexated.SoraExtractor.invokeSeries9
|
||||||
|
import com.hexated.SoraExtractor.invokeSmashyStream
|
||||||
import com.hexated.SoraExtractor.invokeSoraStream
|
import com.hexated.SoraExtractor.invokeSoraStream
|
||||||
import com.hexated.SoraExtractor.invokeTwoEmbed
|
import com.hexated.SoraExtractor.invokeTwoEmbed
|
||||||
import com.hexated.SoraExtractor.invokeUniqueStream
|
import com.hexated.SoraExtractor.invokeUniqueStream
|
||||||
|
@ -78,6 +80,15 @@ class SoraStreamLite : SoraStream() {
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
invokeMovie123Net(
|
||||||
|
res.title,
|
||||||
|
res.season,
|
||||||
|
res.episode,
|
||||||
|
subtitleCallback,
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
invokeMovieHab(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
invokeMovieHab(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
|
@ -141,6 +152,9 @@ class SoraStreamLite : SoraStream() {
|
||||||
{
|
{
|
||||||
invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback)
|
invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
invokeSmashyStream(res.imdbId, res.season, res.episode, callback)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
invokeXmovies(
|
invokeXmovies(
|
||||||
res.title,
|
res.title,
|
||||||
|
|
|
@ -5,7 +5,6 @@ import com.hexated.SoraStream.Companion.baymovies
|
||||||
import com.hexated.SoraStream.Companion.consumetCrunchyrollAPI
|
import com.hexated.SoraStream.Companion.consumetCrunchyrollAPI
|
||||||
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.kamyrollAPI
|
|
||||||
import com.hexated.SoraStream.Companion.tvMoviesAPI
|
import com.hexated.SoraStream.Companion.tvMoviesAPI
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
|
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
|
||||||
|
@ -285,68 +284,6 @@ suspend fun extractCovyn(url: String?): Pair<String?, String?>? {
|
||||||
return Pair(videoLink, size)
|
return Pair(videoLink, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun invokeSmashy1(
|
|
||||||
player: String,
|
|
||||||
url: String?,
|
|
||||||
subtitleCallback: (SubtitleFile) -> Unit,
|
|
||||||
callback: (ExtractorLink) -> Unit,
|
|
||||||
) {
|
|
||||||
val doc = app.get(url ?: return).document
|
|
||||||
val script = doc.selectFirst("script:containsData(secret)")?.data() ?: return
|
|
||||||
val secret = script.substringAfter("secret = \"").substringBefore("\";").let { base64Decode(it) }
|
|
||||||
val key = script.substringAfter("token = \"").substringBefore("\";")
|
|
||||||
val source = app.get(
|
|
||||||
"$secret$key",
|
|
||||||
headers = mapOf(
|
|
||||||
"Accept" to "application/json, text/javascript, */*; q=0.01",
|
|
||||||
"X-Requested-With" to "XMLHttpRequest"
|
|
||||||
)
|
|
||||||
).parsedSafe<Smashy1Source>() ?: return
|
|
||||||
|
|
||||||
val videoUrl = base64Decode(source.file ?: return)
|
|
||||||
if(videoUrl.contains(".m3u8")) {
|
|
||||||
M3u8Helper.generateM3u8(
|
|
||||||
"Smashy ($player)",
|
|
||||||
videoUrl,
|
|
||||||
""
|
|
||||||
).forEach(callback)
|
|
||||||
source.tracks?.map { sub ->
|
|
||||||
subtitleCallback.invoke(
|
|
||||||
SubtitleFile(
|
|
||||||
sub.label ?: return@map null,
|
|
||||||
sub.file ?: return@map null
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun invokeSmashy2(
|
|
||||||
player: String,
|
|
||||||
url: String?,
|
|
||||||
callback: (ExtractorLink) -> Unit,
|
|
||||||
) {
|
|
||||||
val base = getBaseUrl(url ?: return)
|
|
||||||
val doc = app.get(url).document
|
|
||||||
val script = doc.selectFirst("script:containsData(playlist:)")?.data() ?: return
|
|
||||||
Regex("""file:[\n\s]+?"(\S+?.m3u8)",[\n\s]+label:"(\S+)",""").findAll(script).map {
|
|
||||||
it.groupValues[1] to it.groupValues[2]
|
|
||||||
}.toList().map { (link, quality) ->
|
|
||||||
callback.invoke(
|
|
||||||
ExtractorLink(
|
|
||||||
"Smashy ($player)",
|
|
||||||
"Smashy ($player)",
|
|
||||||
link,
|
|
||||||
base,
|
|
||||||
quality.toIntOrNull() ?: Qualities.Unknown.value,
|
|
||||||
isM3u8 = link.contains(".m3u8"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDirectGdrive(url: String): String {
|
fun getDirectGdrive(url: String): String {
|
||||||
return if (url.contains("&export=download")) {
|
return if (url.contains("&export=download")) {
|
||||||
url
|
url
|
||||||
|
@ -538,25 +475,6 @@ fun Document.findTvMoviesIframe(): String? {
|
||||||
?.substringBefore("'>")
|
?.substringBefore("'>")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun searchKamyrollAnimeId(title: String): String? {
|
|
||||||
return app.get(
|
|
||||||
"$kamyrollAPI/content/v1/search",
|
|
||||||
headers = getCrunchyrollToken(),
|
|
||||||
params = mapOf(
|
|
||||||
"query" to title,
|
|
||||||
"channel_id" to "crunchyroll",
|
|
||||||
"limit" to "10",
|
|
||||||
)
|
|
||||||
).parsedSafe<KamyrollSearch>()?.items?.find { item ->
|
|
||||||
item.items.any {
|
|
||||||
(it.title?.contains(title, true) == true || it.slugTitle?.contains(
|
|
||||||
"${title.fixTitle()}",
|
|
||||||
true
|
|
||||||
) == true) && it.mediaType == "series"
|
|
||||||
}
|
|
||||||
}?.items?.firstOrNull()?.id
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun searchCrunchyrollAnimeId(title: String): String? {
|
suspend fun searchCrunchyrollAnimeId(title: String): String? {
|
||||||
val res = app.get("${consumetCrunchyrollAPI}/$title")
|
val res = app.get("${consumetCrunchyrollAPI}/$title")
|
||||||
.parsedSafe<ConsumetSearchResponse>()?.results
|
.parsedSafe<ConsumetSearchResponse>()?.results
|
||||||
|
@ -567,26 +485,12 @@ suspend fun searchCrunchyrollAnimeId(title: String): String? {
|
||||||
(it.title?.contains(
|
(it.title?.contains(
|
||||||
title,
|
title,
|
||||||
true
|
true
|
||||||
) == true || it.title.fixTitle()
|
) == true || it.title.createSlug()
|
||||||
?.contains("${title.fixTitle()}", true) == true) && it.type.equals("series")
|
?.contains("${title.createSlug()}", true) == true) && it.type.equals("series")
|
||||||
}
|
}
|
||||||
})?.id
|
})?.id
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getCrunchyrollToken(): Map<String, String> {
|
|
||||||
val res = app.get(
|
|
||||||
"$kamyrollAPI/auth/v1/token",
|
|
||||||
params = mapOf(
|
|
||||||
"device_id" to "com.service.data",
|
|
||||||
"device_type" to "sorastream",
|
|
||||||
"access_token" to "HMbQeThWmZq4t7w",
|
|
||||||
)
|
|
||||||
).parsedSafe<KamyrollToken>()
|
|
||||||
return mapOf(
|
|
||||||
"Authorization" to "${res?.token_type} ${res?.access_token}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun CrunchyrollDetails.findCrunchyrollId(
|
fun CrunchyrollDetails.findCrunchyrollId(
|
||||||
title: String?,
|
title: String?,
|
||||||
season: Int?,
|
season: Int?,
|
||||||
|
@ -621,7 +525,7 @@ fun getEpisodeSlug(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTitleSlug(title: String? = null): Pair<String?, String?> {
|
fun getTitleSlug(title: String? = null): Pair<String?, String?> {
|
||||||
return title.fixTitle()?.replace("-", ".") to title.fixTitle()?.replace("-", " ")
|
return title.createSlug()?.replace("-", ".") to title.createSlug()?.replace("-", " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getIndexQuery(
|
fun getIndexQuery(
|
||||||
|
@ -701,7 +605,7 @@ fun decodeIndexJson(json: String): String {
|
||||||
val slug = json.reversed().substring(24)
|
val slug = json.reversed().substring(24)
|
||||||
return base64Decode(slug.substring(0, slug.length - 20))
|
return base64Decode(slug.substring(0, slug.length - 20))
|
||||||
}
|
}
|
||||||
fun String?.fixTitle(): String? {
|
fun String?.createSlug(): String? {
|
||||||
return this?.replace(Regex("[!%:'?,]|( &)"), "")?.replace(" ", "-")?.lowercase()
|
return this?.replace(Regex("[!%:'?,]|( &)"), "")?.replace(" ", "-")?.lowercase()
|
||||||
?.replace("-–-", "-")
|
?.replace("-–-", "-")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue