small subtitle support

This commit is contained in:
LagradOst 2021-07-01 22:11:33 +02:00
parent 672dc8c8d1
commit 9fc732c68c
12 changed files with 266 additions and 124 deletions

View file

@ -72,7 +72,7 @@ abstract class MainAPI {
} }
// callback is fired once a link is found, will return true if method is executed successfully // callback is fired once a link is found, will return true if method is executed successfully
open fun loadLinks(data: String, isCasting: Boolean, callback: (ExtractorLink) -> Unit): Boolean { open fun loadLinks(data: String, isCasting: Boolean, subtitleCallback : (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit): Boolean {
return false return false
} }
} }
@ -120,6 +120,8 @@ enum class TvType {
ONA, ONA,
} }
data class SubtitleFile(val lang : String, val url : String)
interface SearchResponse { interface SearchResponse {
val name: String val name: String
val url: String // PUBLIC URL FOR OPEN IN APP val url: String // PUBLIC URL FOR OPEN IN APP

View file

@ -86,7 +86,8 @@ class DubbedAnimeProvider : MainAPI() {
title, href, getSlug(href), this.name, TvType.Movie, img, null title, href, getSlug(href), this.name, TvType.Movie, img, null
) )
} else { } else {
AnimeSearchResponse(title, AnimeSearchResponse(
title,
href, href,
getSlug(href), getSlug(href),
this.name, this.name,
@ -96,8 +97,10 @@ class DubbedAnimeProvider : MainAPI() {
null, null,
EnumSet.of(DubStatus.Dubbed), EnumSet.of(DubStatus.Dubbed),
null, null,
null) null
}) )
}
)
} }
return returnValue return returnValue
} }
@ -121,7 +124,8 @@ class DubbedAnimeProvider : MainAPI() {
title, href, getSlug(href), this.name, TvType.Movie, img, null title, href, getSlug(href), this.name, TvType.Movie, img, null
) )
} else { } else {
AnimeSearchResponse(title, AnimeSearchResponse(
title,
href, href,
getSlug(href), getSlug(href),
this.name, this.name,
@ -131,14 +135,21 @@ class DubbedAnimeProvider : MainAPI() {
null, null,
EnumSet.of(DubStatus.Dubbed), EnumSet.of(DubStatus.Dubbed),
null, null,
null) null
}) )
}
)
} }
return returnValue return returnValue
} }
override fun loadLinks(data: String, isCasting: Boolean, callback: (ExtractorLink) -> Unit): Boolean { override fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val serversHTML = (if (data.startsWith(mainUrl)) { // CLASSIC EPISODE val serversHTML = (if (data.startsWith(mainUrl)) { // CLASSIC EPISODE
val slug = getSlug(data) val slug = getSlug(data)
getAnimeEpisode(slug, false).serversHTML getAnimeEpisode(slug, false).serversHTML
@ -154,11 +165,15 @@ class DubbedAnimeProvider : MainAPI() {
val find = "src=\"(.*?)\".*?label=\"(.*?)\"".toRegex().find(txt) val find = "src=\"(.*?)\".*?label=\"(.*?)\"".toRegex().find(txt)
if (find != null) { if (find != null) {
val quality = find.groupValues[2] val quality = find.groupValues[2]
callback.invoke(ExtractorLink(this.name, callback.invoke(
ExtractorLink(
this.name,
this.name + " " + quality + if (quality.endsWith('p')) "" else 'p', this.name + " " + quality + if (quality.endsWith('p')) "" else 'p',
fixUrl(find.groupValues[1]), fixUrl(find.groupValues[1]),
this.mainUrl, this.mainUrl,
getQualityFromName(quality))) getQualityFromName(quality)
)
)
} }
} catch (e: Exception) { } catch (e: Exception) {
//IDK //IDK
@ -172,7 +187,8 @@ class DubbedAnimeProvider : MainAPI() {
val realSlug = slug.replace("movies/", "") val realSlug = slug.replace("movies/", "")
val episode = getAnimeEpisode(realSlug, true) val episode = getAnimeEpisode(realSlug, true)
val poster = episode.previewImg ?: episode.wideImg val poster = episode.previewImg ?: episode.wideImg
return MovieLoadResponse(episode.title, return MovieLoadResponse(
episode.title,
realSlug, realSlug,
this.name, this.name,
TvType.Movie, TvType.Movie,
@ -180,7 +196,8 @@ class DubbedAnimeProvider : MainAPI() {
if (poster == null) null else fixUrl(poster), if (poster == null) null else fixUrl(poster),
episode.year?.toIntOrNull(), episode.year?.toIntOrNull(),
episode.desc, episode.desc,
null) null
)
} else { } else {
val response = khttp.get("$mainUrl/$slug") val response = khttp.get("$mainUrl/$slug")
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response.text)

View file

@ -167,12 +167,14 @@ class ShiroProvider : MainAPI() {
override fun quickSearch(query: String): ArrayList<SearchResponse> { override fun quickSearch(query: String): ArrayList<SearchResponse> {
val returnValue: ArrayList<SearchResponse> = ArrayList() val returnValue: ArrayList<SearchResponse> = ArrayList()
val response = khttp.get("https://tapi.shiro.is/anime/auto-complete/${ val response = khttp.get(
"https://tapi.shiro.is/anime/auto-complete/${
URLEncoder.encode( URLEncoder.encode(
query, query,
"UTF-8" "UTF-8"
) )
}?token=$token".replace("+", "%20")) }?token=$token".replace("+", "%20")
)
if (response.text == "{\"status\":\"Found\",\"data\":[]}") return returnValue // OR ELSE WILL CAUSE WEIRD ERROR if (response.text == "{\"status\":\"Found\",\"data\":[]}") return returnValue // OR ELSE WILL CAUSE WEIRD ERROR
val mapped = response.let { mapper.readValue<ShiroSearchResponse>(it.text) } val mapped = response.let { mapper.readValue<ShiroSearchResponse>(it.text) }
@ -185,12 +187,14 @@ class ShiroProvider : MainAPI() {
override fun search(query: String): ArrayList<SearchResponse>? { override fun search(query: String): ArrayList<SearchResponse>? {
if (!autoLoadToken()) return null if (!autoLoadToken()) return null
val returnValue: ArrayList<SearchResponse> = ArrayList() val returnValue: ArrayList<SearchResponse> = ArrayList()
val response = khttp.get("https://tapi.shiro.is/advanced?search=${ val response = khttp.get(
"https://tapi.shiro.is/advanced?search=${
URLEncoder.encode( URLEncoder.encode(
query, query,
"UTF-8" "UTF-8"
) )
}&token=$token".replace("+", "%20")) }&token=$token".replace("+", "%20")
)
if (response.text == "{\"status\":\"Found\",\"data\":[]}") return returnValue // OR ELSE WILL CAUSE WEIRD ERROR if (response.text == "{\"status\":\"Found\",\"data\":[]}") return returnValue // OR ELSE WILL CAUSE WEIRD ERROR
val mapped = response.let { mapper.readValue<ShiroFullSearchResponse>(it.text) } val mapped = response.let { mapper.readValue<ShiroFullSearchResponse>(it.text) }
@ -235,7 +239,12 @@ class ShiroProvider : MainAPI() {
) )
} }
override fun loadLinks(data: String, isCasting: Boolean, callback: (ExtractorLink) -> Unit): Boolean { override fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
return Vidstream().getUrl(data, isCasting) { return Vidstream().getUrl(data, isCasting) {
callback.invoke(it) callback.invoke(it)
} }

View file

@ -29,17 +29,26 @@ class HDMProvider : MainAPI() {
return returnValue return returnValue
} }
override fun loadLinks(data: String, isCasting: Boolean, callback: (ExtractorLink) -> Unit): Boolean { override fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
if (data == "") return false if (data == "") return false
val slug = ".*/(.*?)\\.mp4".toRegex().find(data)?.groupValues?.get(1) ?: return false val slug = ".*/(.*?)\\.mp4".toRegex().find(data)?.groupValues?.get(1) ?: return false
val response = khttp.get(data) val response = khttp.get(data)
val key = "playlist\\.m3u8(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return false val key = "playlist\\.m3u8(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return false
callback.invoke(ExtractorLink(this.name, callback.invoke(
ExtractorLink(
this.name,
this.name, this.name,
"https://hls.1o.to/vod/$slug/playlist.m3u8$key", "https://hls.1o.to/vod/$slug/playlist.m3u8$key",
"", "",
Qualities.HD.value, Qualities.HD.value,
true)) true
)
)
return true return true
} }
@ -53,7 +62,9 @@ class HDMProvider : MainAPI() {
?.toIntOrNull() ?.toIntOrNull()
val data = "src/player/\\?v=(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return null val data = "src/player/\\?v=(.*?)\"".toRegex().find(response.text)?.groupValues?.get(1) ?: return null
return MovieLoadResponse(title, slug, this.name, TvType.Movie, return MovieLoadResponse(
"$mainUrl/src/player/?v=$data", poster, year, descript, null) title, slug, this.name, TvType.Movie,
"$mainUrl/src/player/?v=$data", poster, year, descript, null
)
} }
} }

View file

@ -5,7 +5,6 @@ import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.unixTime import com.lagradost.cloudstream3.APIHolder.unixTime
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.extractors.M3u8Manifest import com.lagradost.cloudstream3.utils.extractors.M3u8Manifest
import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.getQualityFromName
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -43,7 +42,7 @@ class LookMovieProvider : MainAPI() {
data class LookMovieTokenSubtitle( data class LookMovieTokenSubtitle(
@JsonProperty("language") val language: String, @JsonProperty("language") val language: String,
//@JsonProperty("source") val source: String, @JsonProperty("source") val source: String?,
//@JsonProperty("source_id") val source_id: String, //@JsonProperty("source_id") val source_id: String,
//@JsonProperty("kind") val kind: String, //@JsonProperty("kind") val kind: String,
//@JsonProperty("id") val id: String, //@JsonProperty("id") val id: String,
@ -77,26 +76,34 @@ class LookMovieProvider : MainAPI() {
if (!movies.isNullOrEmpty()) { if (!movies.isNullOrEmpty()) {
for (m in movies) { for (m in movies) {
val url = "$mainUrl/movies/view/${m.slug}" val url = "$mainUrl/movies/view/${m.slug}"
returnValue.add(MovieSearchResponse(m.title, returnValue.add(
MovieSearchResponse(
m.title,
url, url,
url,//m.slug, url,//m.slug,
this.name, this.name,
TvType.Movie, TvType.Movie,
m.poster ?: m.backdrop, m.poster ?: m.backdrop,
m.year?.toIntOrNull())) m.year?.toIntOrNull()
)
)
} }
} }
if (!shows.isNullOrEmpty()) { if (!shows.isNullOrEmpty()) {
for (s in shows) { for (s in shows) {
val url = "$mainUrl/shows/view/${s.slug}" val url = "$mainUrl/shows/view/${s.slug}"
returnValue.add(MovieSearchResponse(s.title, returnValue.add(
MovieSearchResponse(
s.title,
url, url,
url,//s.slug, url,//s.slug,
this.name, this.name,
TvType.TvSeries, TvType.TvSeries,
s.poster ?: s.backdrop, s.poster ?: s.backdrop,
s.year?.toIntOrNull())) s.year?.toIntOrNull()
)
)
} }
} }
@ -119,7 +126,8 @@ class LookMovieProvider : MainAPI() {
val poster = posterHolder.selectFirst("> img")?.attr("data-src") val poster = posterHolder.selectFirst("> img")?.attr("data-src")
val year = posterHolder.selectFirst("> p.year")?.text()?.toIntOrNull() val year = posterHolder.selectFirst("> p.year")?.text()?.toIntOrNull()
returnValue.add(if (isMovie) { returnValue.add(
if (isMovie) {
MovieSearchResponse( MovieSearchResponse(
name, href, href, this.name, TvType.Movie, poster, year name, href, href, this.name, TvType.Movie, poster, year
) )
@ -138,15 +146,52 @@ class LookMovieProvider : MainAPI() {
return movieList return movieList
} }
override fun loadLinks(data: String, isCasting: Boolean, callback: (ExtractorLink) -> Unit): Boolean { data class LookMovieLinkLoad(val url: String, val extraUrl: String, val isMovie: Boolean)
val response = khttp.get(data.replace("\$unixtime", unixTime.toString()))
private fun addSubtitles(subs: List<LookMovieTokenSubtitle>?, subtitleCallback: (SubtitleFile) -> Unit) {
if (subs == null) return
subs.forEach {
if (it.source != "opensubtitle")
subtitleCallback.invoke(SubtitleFile(it.language, fixUrl(it.file)))
}
}
private fun loadCurrentLinks(url: String, callback: (ExtractorLink) -> Unit) {
val response = khttp.get(url.replace("\$unixtime", unixTime.toString()))
M3u8Manifest.extractLinks(response.text).forEach { M3u8Manifest.extractLinks(response.text).forEach {
callback.invoke(ExtractorLink(this.name, callback.invoke(
ExtractorLink(
this.name,
"${this.name} - ${it.second}", "${this.name} - ${it.second}",
fixUrl(it.first), fixUrl(it.first),
"", "",
getQualityFromName(it.second), getQualityFromName(it.second),
true)) true
)
)
}
}
override fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val localData: LookMovieLinkLoad = mapper.readValue(data)
if (localData.isMovie) {
val tokenResponse = khttp.get(localData.url)
val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse.text)
val accessToken = root.data?.accessToken ?: return false
addSubtitles(root.data.subtitles, subtitleCallback)
loadCurrentLinks(localData.extraUrl.replace("\$accessToken", accessToken), callback)
return true
} else {
loadCurrentLinks(localData.url, callback)
val subResponse = khttp.get(localData.extraUrl)
val subs = mapper.readValue<List<LookMovieTokenSubtitle>>(subResponse.text)
addSubtitles(subs, subtitleCallback)
} }
return true return true
} }
@ -159,7 +204,7 @@ class LookMovieProvider : MainAPI() {
val watchHeader = document.selectFirst("div.watch-heading") val watchHeader = document.selectFirst("div.watch-heading")
val nameHeader = watchHeader.selectFirst("> h1.bd-hd") val nameHeader = watchHeader.selectFirst("> h1.bd-hd")
val year = nameHeader.selectFirst("> span")?.text()?.toIntOrNull() val year = nameHeader.selectFirst("> span")?.text()?.toIntOrNull()
val name = nameHeader.ownText() val title = nameHeader.ownText()
val rating = parseRating(watchHeader.selectFirst("> div.movie-rate > div.rate > p > span").text()) val rating = parseRating(watchHeader.selectFirst("> div.movie-rate > div.rate > p > span").text())
val imgElement = document.selectFirst("div.movie-img > p.movie__poster") val imgElement = document.selectFirst("div.movie-img > p.movie__poster")
val img = imgElement?.attr("style") val img = imgElement?.attr("style")
@ -173,22 +218,31 @@ class LookMovieProvider : MainAPI() {
val realUrl = val realUrl =
"$mainUrl/api/v1/security/${if (isMovie) "movie" else "show"}-access?${if (isMovie) "id_movie=$id" else "slug=$realSlug"}&token=1&sk=&step=1" "$mainUrl/api/v1/security/${if (isMovie) "movie" else "show"}-access?${if (isMovie) "id_movie=$id" else "slug=$realSlug"}&token=1&sk=&step=1"
val tokenResponse = khttp.get(realUrl)
val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse.text)
val accessToken = root.data?.accessToken ?: return null
if (isMovie) { if (isMovie) {
return MovieLoadResponse(name, val localData = mapper.writeValueAsString(
LookMovieLinkLoad(
realUrl,
"$mainUrl/manifests/movies/json/$id/\$unixtime/\$accessToken/master.m3u8",
true
)
)
return MovieLoadResponse(
title,
slug, slug,
this.name, this.name,
TvType.Movie, TvType.Movie,
"$mainUrl/manifests/movies/json/$id/\$unixtime/$accessToken/master.m3u8", localData,
poster, poster,
year, year,
descript, descript,
null, null,
rating) rating
)
} else { } else {
val tokenResponse = khttp.get(realUrl)
val root = mapper.readValue<LookMovieTokenRoot>(tokenResponse.text)
val accessToken = root.data?.accessToken ?: return null
val window = val window =
"window\\[\\'show_storage\\'\\] =((.|\\n)*?\\<)".toRegex().find(response.text)?.groupValues?.get(1) "window\\[\\'show_storage\\'\\] =((.|\\n)*?\\<)".toRegex().find(response.text)?.groupValues?.get(1)
?: return null ?: return null
@ -208,13 +262,24 @@ class LookMovieProvider : MainAPI() {
val realJson = "[" + json.substring(0, json.lastIndexOf(',')) + "]" val realJson = "[" + json.substring(0, json.lastIndexOf(',')) + "]"
val episodes = mapper.readValue<List<LookMovieEpisode>>(realJson).map { val episodes = mapper.readValue<List<LookMovieEpisode>>(realJson).map {
TvSeriesEpisode(it.title, val localData = mapper.writeValueAsString(
LookMovieLinkLoad(
"$mainUrl/manifests/shows/json/$accessToken/\$unixtime/${it.idEpisode}/master.m3u8",
"https://lookmovie.io/api/v1/shows/episode-subtitles/?id_episode=${it.idEpisode}",
false
)
)
TvSeriesEpisode(
it.title,
it.season.toIntOrNull(), it.season.toIntOrNull(),
it.episode.toIntOrNull(), it.episode.toIntOrNull(),
"$mainUrl/manifests/shows/json/$accessToken/\$unixtime/${it.idEpisode}/master.m3u8") localData
)
}.toList() }.toList()
return TvSeriesLoadResponse(name, return TvSeriesLoadResponse(
title,
slug, slug,
this.name, this.name,
TvType.TvSeries, TvType.TvSeries,
@ -224,7 +289,8 @@ class LookMovieProvider : MainAPI() {
descript, descript,
null, null,
null, null,
rating) rating
)
} }
} }
} }

View file

@ -44,22 +44,30 @@ class MeloMovieProvider : MainAPI() {
val currentUrl = "$mainUrl/movie/${i.id}" val currentUrl = "$mainUrl/movie/${i.id}"
val currentPoster = "$mainUrl/assets/images/poster/${i.imdbId}.jpg" val currentPoster = "$mainUrl/assets/images/poster/${i.imdbId}.jpg"
if (i.type == 2) { // TV-SERIES if (i.type == 2) { // TV-SERIES
returnValue.add(TvSeriesSearchResponse(i.title, returnValue.add(
TvSeriesSearchResponse(
i.title,
currentUrl, currentUrl,
currentUrl, currentUrl,
this.name, this.name,
TvType.TvSeries, TvType.TvSeries,
currentPoster, currentPoster,
i.year, i.year,
null)) null
)
)
} else if (i.type == 1) { // MOVIE } else if (i.type == 1) { // MOVIE
returnValue.add(MovieSearchResponse(i.title, returnValue.add(
MovieSearchResponse(
i.title,
currentUrl, currentUrl,
currentUrl, currentUrl,
this.name, this.name,
TvType.Movie, TvType.Movie,
currentUrl, currentUrl,
i.year)) i.year
)
)
} }
} }
return returnValue return returnValue
@ -67,7 +75,7 @@ class MeloMovieProvider : MainAPI() {
// http not https, the links are not https! // http not https, the links are not https!
private fun fixUrl(url: String): String { private fun fixUrl(url: String): String {
if(url.isEmpty()) return "" if (url.isEmpty()) return ""
if (url.startsWith("//")) { if (url.startsWith("//")) {
return "http:$url" return "http:$url"
@ -93,7 +101,12 @@ class MeloMovieProvider : MainAPI() {
return mapper.writeValueAsString(parsed) return mapper.writeValueAsString(parsed)
} }
override fun loadLinks(data: String, isCasting: Boolean, callback: (ExtractorLink) -> Unit): Boolean { override fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val links = mapper.readValue<List<MeloMovieLink>>(data) val links = mapper.readValue<List<MeloMovieLink>>(data)
for (link in links) { for (link in links) {
callback.invoke(ExtractorLink(this.name, link.name, link.link, "", getQualityFromName(link.name), false)) callback.invoke(ExtractorLink(this.name, link.name, link.link, "", getQualityFromName(link.name), false))
@ -120,7 +133,8 @@ class MeloMovieProvider : MainAPI() {
if (type == 1) { // MOVIE if (type == 1) { // MOVIE
val serialize = document.selectFirst("table.accordion__list") val serialize = document.selectFirst("table.accordion__list")
return MovieLoadResponse(title, return MovieLoadResponse(
title,
slug, slug,
this.name, this.name,
TvType.Movie, TvType.Movie,
@ -128,7 +142,8 @@ class MeloMovieProvider : MainAPI() {
poster, poster,
year, year,
plot, plot,
imdbUrl) imdbUrl
)
} else if (type == 2) { } else if (type == 2) {
val episodes = ArrayList<TvSeriesEpisode>() val episodes = ArrayList<TvSeriesEpisode>()
val seasons = document.select("div.accordion__card") val seasons = document.select("div.accordion__card")
@ -145,7 +160,8 @@ class MeloMovieProvider : MainAPI() {
} }
} }
episodes.reverse() episodes.reverse()
return TvSeriesLoadResponse(title, return TvSeriesLoadResponse(
title,
slug, slug,
this.name, this.name,
TvType.TvSeries, TvType.TvSeries,
@ -154,7 +170,8 @@ class MeloMovieProvider : MainAPI() {
year, year,
plot, plot,
null, null,
imdbUrl) imdbUrl
)
} }
return null return null
} }

View file

@ -80,7 +80,12 @@ class TrailersToProvider : MainAPI() {
return false return false
} }
override fun loadLinks(data: String, isCasting: Boolean, callback: (ExtractorLink) -> Unit): Boolean { override fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
if (isCasting) return false if (isCasting) return false
val isMovie = data.contains("/web-sources/") val isMovie = data.contains("/web-sources/")
if (isMovie) { if (isMovie) {
@ -142,7 +147,8 @@ class TrailersToProvider : MainAPI() {
val epDescript = main.selectFirst("> p")?.text() val epDescript = main.selectFirst("> p")?.text()
TvSeriesEpisode(epName, season, episode, href, epPoster, date, epRating, epDescript) TvSeriesEpisode(epName, season, episode, href, epPoster, date, epRating, epDescript)
} }
return TvSeriesLoadResponse(title, return TvSeriesLoadResponse(
title,
slug, slug,
this.name, this.name,
TvType.TvSeries, TvType.TvSeries,
@ -155,10 +161,12 @@ class TrailersToProvider : MainAPI() {
rating, rating,
tags, tags,
duration, duration,
trailer) trailer
)
} else { } else {
val data = fixUrl(document.selectFirst("content").attr("data-url") ?: return null) val data = fixUrl(document.selectFirst("content").attr("data-url") ?: return null)
return MovieLoadResponse(title, return MovieLoadResponse(
title,
slug, slug,
this.name, this.name,
TvType.Movie, TvType.Movie,
@ -170,7 +178,8 @@ class TrailersToProvider : MainAPI() {
rating, rating,
tags, tags,
duration, duration,
trailer) trailer
)
} }
} }
} }

View file

@ -128,7 +128,8 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
epData, epData,
holder, holder,
index, index,
remoteMediaClient?.mediaInfo?.customData) remoteMediaClient?.mediaInfo?.customData
)
val startAt = remoteMediaClient?.approximateStreamPosition ?: 0 val startAt = remoteMediaClient?.approximateStreamPosition ?: 0
@ -139,12 +140,17 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
val nextId = remoteMediaClient.mediaQueue.itemIds?.get(currentIdIndex?.plus(1) ?: 0) val nextId = remoteMediaClient.mediaQueue.itemIds?.get(currentIdIndex?.plus(1) ?: 0)
if (currentIdIndex == null && nextId != null) { if (currentIdIndex == null && nextId != null) {
awaitLinks(remoteMediaClient?.queueInsertAndPlayItem(MediaQueueItem.Builder( awaitLinks(
mediaItem) remoteMediaClient?.queueInsertAndPlayItem(
MediaQueueItem.Builder(
mediaItem
)
.build(), .build(),
nextId, nextId,
startAt, startAt,
JSONObject())) { JSONObject()
)
) {
loadMirror(index + 1) loadMirror(index + 1)
} }
} else { } else {
@ -204,7 +210,7 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
val links = ArrayList<ExtractorLink>() val links = ArrayList<ExtractorLink>()
val res = safeApiCall { val res = safeApiCall {
getApiFromName(meta.apiName).loadLinks(epData.data, true) { getApiFromName(meta.apiName).loadLinks(epData.data, true, { subtitleFile -> }) {
for (i in links) { for (i in links) {
if (i.url == it.url) return@loadLinks if (i.url == it.url) return@loadLinks
} }
@ -225,7 +231,8 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
epData, epData,
jsonCopy, jsonCopy,
0, 0,
done) done
)
/*fun loadIndex(index: Int) { /*fun loadIndex(index: Int) {
println("LOAD INDEX::::: $index") println("LOAD INDEX::::: $index")
@ -240,8 +247,12 @@ class SelectSourceController(val view: ImageView, val activity: ControllerActivi
} }
}*/ }*/
awaitLinks(remoteMediaClient?.queueAppendItem(MediaQueueItem.Builder(mediaInfo).build(), awaitLinks(
JSONObject())) { remoteMediaClient?.queueAppendItem(
MediaQueueItem.Builder(mediaInfo).build(),
JSONObject()
)
) {
println("FAILED TO LOAD NEXT ITEM") println("FAILED TO LOAD NEXT ITEM")
// loadIndex(1) // loadIndex(1)
} }

View file

@ -147,11 +147,11 @@ class EpisodeAdapter(
clickCallback.invoke(EpisodeClickEvent(ACTION_CHROME_CAST_EPISODE, card)) clickCallback.invoke(EpisodeClickEvent(ACTION_CHROME_CAST_EPISODE, card))
} else { } else {
// clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card)) // clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card)) clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
} }
} else { } else {
// clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card)) // clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
clickCallback.invoke(EpisodeClickEvent(ACTION_DOWNLOAD_EPISODE, card)) clickCallback.invoke(EpisodeClickEvent(ACTION_PLAY_EPISODE_IN_PLAYER, card))
} }
} }
} }

View file

@ -206,7 +206,7 @@ class ResultViewModel : ViewModel() {
} }
val links = ArrayList<ExtractorLink>() val links = ArrayList<ExtractorLink>()
val localData = safeApiCall { val localData = safeApiCall {
getApiFromName(_apiName.value).loadLinks(data, isCasting) { getApiFromName(_apiName.value).loadLinks(data, isCasting, { subtitleFile -> }) {
for (i in links) { for (i in links) {
if (i.url == it.url) return@loadLinks if (i.url == it.url) return@loadLinks
} }

View file

@ -148,7 +148,7 @@ class SearchFragment : Fragment() {
allApi.providersActive = requireActivity().getApiSettings() allApi.providersActive = requireActivity().getApiSettings()
//searchViewModel.search("iron man") //searchViewModel.search("iron man")
(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro") //(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro")
/* /*
(requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction() (requireActivity() as AppCompatActivity).supportFragmentManager.beginTransaction()
.setCustomAnimations(R.anim.enter_anim, .setCustomAnimations(R.anim.enter_anim,

View file

@ -7,7 +7,7 @@ object M3u8Manifest {
val data: ArrayList<Pair<String, String>> = ArrayList() val data: ArrayList<Pair<String, String>> = ArrayList()
"\"(.*?)\":\"(.*?)\"".toRegex().findAll(m3u8Data).forEach { "\"(.*?)\":\"(.*?)\"".toRegex().findAll(m3u8Data).forEach {
var quality = it.groupValues[1].replace("auto", "Auto") var quality = it.groupValues[1].replace("auto", "Auto")
if (quality != "Auto") quality += "p" if (quality != "Auto" && !quality.endsWith('p')) quality += "p"
val url = it.groupValues[2] val url = it.groupValues[2]
data.add(Pair(url, quality)) data.add(Pair(url, quality))
} }