added new source into SoraExtractor

This commit is contained in:
hexated 2022-11-19 11:37:28 +07:00
parent f2b6850716
commit 1cbdfc282d
3 changed files with 115 additions and 22 deletions

View file

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

View file

@ -1046,20 +1046,8 @@ object SoraExtractor : SoraStream() {
link?.substringBefore("=http") ?: return@apmap null, link?.substringBefore("=http") ?: return@apmap null,
"$kissKhAPI/", "$kissKhAPI/",
subtitleCallback, subtitleCallback,
) { links -> callback
callback.invoke(
ExtractorLink(
"StreamSS",
"StreamSS",
links.url,
links.referer,
links.quality,
links.isM3u8,
links.headers,
links.extractorData
) )
)
}
} }
} }
} }
@ -1131,6 +1119,75 @@ object SoraExtractor : SoraStream() {
} }
suspend fun invokeLing(
title: String? = null,
year: Int? = null,
season: Int? = null,
episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val fixTitle = title?.replace("", "-")
val url = if(season == null) {
"$lingAPI/en/videos/films/?title=$fixTitle"
} else {
"$lingAPI/en/videos/serials/?title=$fixTitle"
}
val scriptData = app.get(url).document.select("div.blk.padding_b0 div.col-sm-30").map {
Triple(
it.selectFirst("div.video-body h5")?.text(),
it.selectFirst("div.video-body > p")?.text(),
it.selectFirst("div.video-body a")?.attr("href"),
)
}
val script = if (scriptData.size == 1) {
scriptData.first()
} else {
scriptData.find {
it.first?.contains("$fixTitle", true) == true && it.second?.contains("$year") == true
}
}
val doc = app.get(fixUrl(script?.third ?: return, lingAPI)).document
val iframe = (if(season == null) {
doc.selectFirst("a.video-js.vjs-default-skin")?.attr("data-href")
} else {
doc.select("div.blk div#tab_$season li")[episode!!.minus(1)].select("h5 a").attr("data-href")
})?.let { fixUrl(it, lingAPI) }
val source = app.get(iframe ?: return)
val link = Regex("((https:|http:)//.*\\.mp4)").find(source.text)?.value ?: return
val quality = when {
link.contains("1080p") -> Qualities.P1080.value
link.contains("720p") -> Qualities.P720.value
else -> Qualities.Unknown.value
}
callback.invoke(
ExtractorLink(
"Ling",
"Ling",
link,
"$lingAPI/",
quality,
headers = mapOf(
"Range" to "bytes=0-"
)
)
)
source.document.select("div#player-tracks track").map {
subtitleCallback.invoke(
SubtitleFile(
SubtitleHelper.fromTwoLettersToLanguage(it.attr("srclang")) ?: return@map null,
it.attr("src")
)
)
}
}
} }
data class FilmxyCookies( data class FilmxyCookies(

View file

@ -22,6 +22,7 @@ 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
import com.hexated.SoraExtractor.invoZoro import com.hexated.SoraExtractor.invoZoro
import com.hexated.SoraExtractor.invokeLing
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
@ -67,6 +68,7 @@ open class SoraStream : TmdbProvider() {
const val consumetFlixhqAPI = "https://api.consumet.org/movies/flixhq" const val consumetFlixhqAPI = "https://api.consumet.org/movies/flixhq"
const val consumetZoroAPI = "https://api.consumet.org/anime/zoro" const val consumetZoroAPI = "https://api.consumet.org/anime/zoro"
const val kissKhAPI = "https://kisskh.me" const val kissKhAPI = "https://kisskh.me"
const val lingAPI = "https://ling-online.net"
fun getType(t: String?): TvType { fun getType(t: String?): TvType {
return when (t) { return when (t) {
@ -181,9 +183,13 @@ open class SoraStream : TmdbProvider() {
?: throw ErrorLoadingException("Invalid Json Response") ?: throw ErrorLoadingException("Invalid Json Response")
val res = responses.result ?: return null val res = responses.result ?: return null
val title = res.title ?: res.name ?: return null val title = res.title ?: res.name ?: return null
val poster = getOriImageUrl(res.backdropPath)
val orgTitle = res.originalTitle ?: res.originalName ?: return null val orgTitle = res.originalTitle ?: res.originalName ?: return null
val type = getType(data.type) val type = getType(data.type)
val year = (res.releaseDate ?: res.firstAirDate)?.split("-")?.first()?.toIntOrNull() val year = (res.releaseDate ?: res.firstAirDate)?.split("-")?.first()?.toIntOrNull()
val genres = res.genres?.mapNotNull { it.name }
val show =
if (genres?.contains("Animation") == true && res.original_language == "ja") "Anime" else "Series/Movies"
val actors = responses.cast?.mapNotNull { cast -> val actors = responses.cast?.mapNotNull { cast ->
ActorData( ActorData(
@ -216,6 +222,8 @@ open class SoraStream : TmdbProvider() {
title = title, title = title,
year = season.airDate?.split("-")?.first()?.toIntOrNull(), year = season.airDate?.split("-")?.first()?.toIntOrNull(),
orgTitle = orgTitle, orgTitle = orgTitle,
show = show,
airedYear = year
).toJson(), ).toJson(),
name = eps.name, name = eps.name,
season = eps.seasonNumber, season = eps.seasonNumber,
@ -234,10 +242,10 @@ open class SoraStream : TmdbProvider() {
TvType.TvSeries, TvType.TvSeries,
episodes episodes
) { ) {
this.posterUrl = getOriImageUrl(res.backdropPath) this.posterUrl = poster
this.year = year this.year = year
this.plot = res.overview this.plot = res.overview
this.tags = res.genres?.mapNotNull { it.name } this.tags = genres
this.showStatus = getStatus(res.status) this.showStatus = getStatus(res.status)
this.recommendations = recommendations this.recommendations = recommendations
this.actors = actors this.actors = actors
@ -255,12 +263,13 @@ open class SoraStream : TmdbProvider() {
title = title, title = title,
year = year, year = year,
orgTitle = orgTitle, orgTitle = orgTitle,
show = show,
).toJson(), ).toJson(),
) { ) {
this.posterUrl = getOriImageUrl(res.backdropPath) this.posterUrl = poster
this.year = year this.year = year
this.plot = res.overview this.plot = res.overview
this.tags = res.genres?.mapNotNull { it.name } this.tags = genres
this.recommendations = recommendations this.recommendations = recommendations
this.actors = actors this.actors = actors
addTrailer(trailer) addTrailer(trailer)
@ -362,7 +371,7 @@ open class SoraStream : TmdbProvider() {
// ) // )
// }, // },
{ {
if (res.season != null) invoZoro( if (res.season != null && res.show == "Anime") invoZoro(
res.id, res.id,
res.season, res.season,
res.episode, res.episode,
@ -406,14 +415,38 @@ open class SoraStream : TmdbProvider() {
invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback) invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback)
}, },
{ {
invokeXmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) invokeXmovies(
res.title,
res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
}, },
{ {
invokeFlixhq(res.title, res.year, res.season, res.episode, subtitleCallback, callback) invokeFlixhq(
res.title,
res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
}, },
{ {
invoKisskh(res.title, res.season, res.episode, subtitleCallback, callback) invoKisskh(res.title, res.season, res.episode, subtitleCallback, callback)
}, },
{
invokeLing(
res.title,
res.airedYear ?: res.year,
res.season,
res.episode,
subtitleCallback,
callback
)
},
) )
return true return true
@ -430,6 +463,8 @@ open class SoraStream : TmdbProvider() {
val title: String? = null, val title: String? = null,
val year: Int? = null, val year: Int? = null,
val orgTitle: String? = null, val orgTitle: String? = null,
val show: String? = null,
val airedYear: Int? = null,
) )
data class Data( data class Data(
@ -525,6 +560,7 @@ open class SoraStream : TmdbProvider() {
@JsonProperty("release_date") val releaseDate: String? = null, @JsonProperty("release_date") val releaseDate: String? = null,
@JsonProperty("first_air_date") val firstAirDate: String? = null, @JsonProperty("first_air_date") val firstAirDate: String? = null,
@JsonProperty("overview") val overview: String? = null, @JsonProperty("overview") val overview: String? = null,
@JsonProperty("original_language") val original_language: String? = null,
@JsonProperty("status") val status: String? = null, @JsonProperty("status") val status: String? = null,
@JsonProperty("genres") val genres: ArrayList<Genres>? = arrayListOf(), @JsonProperty("genres") val genres: ArrayList<Genres>? = arrayListOf(),
@JsonProperty("seasons") val seasons: ArrayList<Seasons>? = arrayListOf(), @JsonProperty("seasons") val seasons: ArrayList<Seasons>? = arrayListOf(),