sora: added Blackmovies & JSMovies

This commit is contained in:
hexated 2023-02-06 11:55:42 +07:00
parent b99e6dad07
commit b0847b21dd
5 changed files with 146 additions and 201 deletions

View file

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 83 version = 84
cloudstream { cloudstream {

View file

@ -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,

View file

@ -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

View file

@ -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,

View file

@ -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("--", "-")
} }