mirror of
https://github.com/recloudstream/cloudstream.git
synced 2025-05-17 19:25:55 +08:00
feat(Extensions): Extensions API documentation & deprecate old classes (#1475)
This commit is contained in:
@ -58,6 +58,7 @@ object APIHolder {
|
||||
apiMap = null
|
||||
}
|
||||
|
||||
/** String extension function to Capitalize first char of string.*/
|
||||
fun String.capitalize(): String {
|
||||
return this.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
|
||||
}
|
||||
@ -220,6 +221,10 @@ object APIHolder {
|
||||
}
|
||||
}
|
||||
|
||||
/** Searches Anilist using title.
|
||||
* @param title Title string of the show
|
||||
* @return [AniSearch] data class holds search info.
|
||||
* */
|
||||
private suspend fun searchAnilist(
|
||||
title: String?,
|
||||
): AniSearch? {
|
||||
@ -351,19 +356,28 @@ data class MainPageRequest(
|
||||
//TODO genre selection or smth
|
||||
)
|
||||
|
||||
/** Create [MainPageData] from url, name Strings & layout (Horizontal/Vertical) Boolean.
|
||||
* @param url page Url string.
|
||||
* @param name page Name string.
|
||||
* @param horizontalImages Boolean to control item card layout.
|
||||
* */
|
||||
fun mainPage(url: String, name: String, horizontalImages: Boolean = false): MainPageData {
|
||||
return MainPageData(name = name, data = url, horizontalImages = horizontalImages)
|
||||
}
|
||||
|
||||
/** return list of MainPageData with url to name, make for more readable code
|
||||
* @param elements parameter of [MainPageData] class of data*/
|
||||
fun mainPageOf(vararg elements: MainPageData): List<MainPageData> {
|
||||
return elements.toList()
|
||||
}
|
||||
|
||||
/** return list of MainPageData with url to name, make for more readable code */
|
||||
/** return list of MainPageData with url to name, make for more readable code
|
||||
* @param elements parameter of <String, String> map of url and name */
|
||||
fun mainPageOf(vararg elements: Pair<String, String>): List<MainPageData> {
|
||||
return elements.map { (url, name) -> MainPageData(name = name, data = url) }
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun newHomePageResponse(
|
||||
name: String,
|
||||
list: List<SearchResponse>,
|
||||
@ -375,6 +389,7 @@ fun newHomePageResponse(
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun newHomePageResponse(
|
||||
data: MainPageRequest,
|
||||
list: List<SearchResponse>,
|
||||
@ -386,10 +401,12 @@ fun newHomePageResponse(
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun newHomePageResponse(list: HomePageList, hasNext: Boolean? = null): HomePageResponse {
|
||||
return HomePageResponse(listOf(list), hasNext = hasNext ?: list.list.isNotEmpty())
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun newHomePageResponse(list: List<HomePageList>, hasNext: Boolean? = null): HomePageResponse {
|
||||
return HomePageResponse(list, hasNext = hasNext ?: list.any { it.list.isNotEmpty() })
|
||||
}
|
||||
@ -415,7 +432,10 @@ abstract class MainAPI {
|
||||
this.storedCredentials = data.credentials
|
||||
}
|
||||
|
||||
/** Name of the plugin that will used in UI */
|
||||
open var name = "NONE"
|
||||
|
||||
/** Main Url of the plugin that can be used directly in code or to be replaced using Clone site feature in settings */
|
||||
open var mainUrl = "NONE"
|
||||
open var storedCredentials: String? = null
|
||||
open var canBeOverridden: Boolean = true
|
||||
@ -483,6 +503,7 @@ abstract class MainAPI {
|
||||
open val mainPage = listOf(MainPageData("", "", false))
|
||||
|
||||
// @WorkerThread
|
||||
@Suppress("DEPRECATION")
|
||||
open suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest,
|
||||
@ -523,7 +544,14 @@ abstract class MainAPI {
|
||||
throw NotImplementedError()
|
||||
}
|
||||
|
||||
/**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
|
||||
* @param data dataUrl string returned from [load] function.
|
||||
* @see newMovieLoadResponse
|
||||
* @see newTvSeriesLoadResponse
|
||||
* @see newLiveStreamLoadResponse
|
||||
* @see newAnimeLoadResponse
|
||||
* @see newTorrentLoadResponse
|
||||
* */
|
||||
// @WorkerThread
|
||||
open suspend fun loadLinks(
|
||||
data: String,
|
||||
@ -552,10 +580,12 @@ abstract class MainAPI {
|
||||
fun base64Decode(string: String): String {
|
||||
return String(base64DecodeArray(string), Charsets.ISO_8859_1)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalEncodingApi::class)
|
||||
fun base64DecodeArray(string: String): ByteArray {
|
||||
return Base64.decode(string)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalEncodingApi::class)
|
||||
fun base64Encode(array: ByteArray): String {
|
||||
return Base64.encode(array)
|
||||
@ -590,14 +620,27 @@ fun MainAPI.fixUrl(url: String): String {
|
||||
}
|
||||
}
|
||||
|
||||
/** Sort the urls based on quality
|
||||
* @param urls Set of [ExtractorLink]
|
||||
* */
|
||||
fun sortUrls(urls: Set<ExtractorLink>): List<ExtractorLink> {
|
||||
return urls.sortedBy { t -> -t.quality }
|
||||
}
|
||||
|
||||
/** Capitalize the first letter of string.
|
||||
* @param str String to be capitalized
|
||||
* @return non-nullable String
|
||||
* @see capitalizeStringNullable
|
||||
* */
|
||||
fun capitalizeString(str: String): String {
|
||||
return capitalizeStringNullable(str) ?: str
|
||||
}
|
||||
|
||||
/** Capitalize the first letter of string.
|
||||
* @param str String to be capitalized
|
||||
* @return nullable String
|
||||
* @see capitalizeString
|
||||
* */
|
||||
fun capitalizeStringNullable(str: String?): String? {
|
||||
if (str == null)
|
||||
return null
|
||||
@ -617,7 +660,9 @@ fun fixTitle(str: String): String {
|
||||
|
||||
/**
|
||||
* Get rhino context in a safe way as it needs to be initialized on the main thread.
|
||||
*
|
||||
* Make sure you get the scope using: val scope: Scriptable = rhino.initSafeStandardObjects()
|
||||
*
|
||||
* Use like the following: rhino.evaluateString(scope, js, "JavaScript", 1, null)
|
||||
**/
|
||||
suspend fun getRhinoContext(): org.mozilla.javascript.Context {
|
||||
@ -629,31 +674,45 @@ suspend fun getRhinoContext(): org.mozilla.javascript.Context {
|
||||
}
|
||||
}
|
||||
|
||||
/** https://www.imdb.com/title/tt2861424/ -> tt2861424 */
|
||||
/** https://www.imdb.com/title/tt2861424/ -> tt2861424
|
||||
* @param url Imdb Url you need to get the Id from.
|
||||
* @return imdb id formatted string
|
||||
* @see imdbUrlToIdNullable
|
||||
* */
|
||||
fun imdbUrlToId(url: String): String? {
|
||||
return Regex("/title/(tt[0-9]*)").find(url)?.groupValues?.get(1)
|
||||
?: Regex("tt[0-9]{5,}").find(url)?.groupValues?.get(0)
|
||||
}
|
||||
|
||||
/** https://www.imdb.com/title/tt2861424/ -> tt2861424
|
||||
* @param url Imdb Url you need to get the Id from.
|
||||
* @return imdb id formatted nullable string
|
||||
* @see imdbUrlToId
|
||||
* */
|
||||
fun imdbUrlToIdNullable(url: String?): String? {
|
||||
if (url == null) return null
|
||||
return imdbUrlToId(url)
|
||||
}
|
||||
|
||||
/** enum class determines provider type:
|
||||
*
|
||||
* MetaProvider: When data is fetched from a 3rd party site like imdb
|
||||
*
|
||||
* DirectProvider: When all data is from the site
|
||||
* */
|
||||
enum class ProviderType {
|
||||
// When data is fetched from a 3rd party site like imdb
|
||||
MetaProvider,
|
||||
|
||||
// When all data is from the site
|
||||
DirectProvider,
|
||||
}
|
||||
|
||||
/** enum class determines VPN status (Non, MightBeNeeded or Torrent) */
|
||||
enum class VPNStatus {
|
||||
None,
|
||||
MightBeNeeded,
|
||||
Torrent,
|
||||
}
|
||||
|
||||
/** enum class determines Show status (Completed or Ongoing) */
|
||||
enum class ShowStatus {
|
||||
Completed,
|
||||
Ongoing,
|
||||
@ -701,50 +760,79 @@ public enum class AutoDownloadMode(val value: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Extension function of [TvType] to check if the type is Movie.
|
||||
* @return If the type is AnimeMovie, Live, Movie, Torrent returns true otherwise returns false.
|
||||
* */
|
||||
fun TvType.isMovieType(): Boolean {
|
||||
return when (this) {
|
||||
TvType.AnimeMovie,
|
||||
TvType.Live,
|
||||
TvType.Movie,
|
||||
TvType.Torrent -> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
/** Extension function of [TvType] to check if the type is Audio.
|
||||
* @return If the type is Audio, AudioBook, Music, PodCast returns true otherwise returns false.
|
||||
* */
|
||||
fun TvType.isAudioType(): Boolean {
|
||||
return when (this) {
|
||||
TvType.Audio,
|
||||
TvType.AudioBook,
|
||||
TvType.Music,
|
||||
TvType.Podcast -> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
/** Extension function of [TvType] to check if the type is Live stream.
|
||||
* @return If the type is Live returns true, otherwise returns false.
|
||||
* */
|
||||
fun TvType.isLiveStream(): Boolean {
|
||||
return this == TvType.Live
|
||||
}
|
||||
|
||||
// returns if the type has an anime opening
|
||||
/** Extension function of [TvType] to check if the type has an Anime opening.
|
||||
* @return If the type is Anime or OVA returns true otherwise returns false.
|
||||
* */
|
||||
fun TvType.isAnimeOp(): Boolean {
|
||||
return this == TvType.Anime || this == TvType.OVA
|
||||
}
|
||||
|
||||
/** Data class for the Subtitle file info.
|
||||
* @property lang Subtitle file language.
|
||||
* @property url Subtitle file url to download/load the file.
|
||||
* */
|
||||
data class SubtitleFile(val lang: String, val url: String)
|
||||
|
||||
/** Data class for the Homepage response info.
|
||||
* @property items List of [HomePageList] items.
|
||||
* @property hasNext if there is a next page or not.
|
||||
* */
|
||||
@Deprecated("Use newHomePageResponse method", level = DeprecationLevel.WARNING)
|
||||
data class HomePageResponse(
|
||||
val items: List<HomePageList>,
|
||||
val hasNext: Boolean = false
|
||||
)
|
||||
|
||||
/** Data class for the Homepage list info.
|
||||
* @property name name of the category shows on homepage UI.
|
||||
* @property list list of [SearchResponse] items that will be added to the category.
|
||||
* @property isHorizontalImages here you can control how the items' cards will be appeared on the UI (Horizontal or Vertical) cards.
|
||||
* */
|
||||
data class HomePageList(
|
||||
val name: String,
|
||||
var list: List<SearchResponse>,
|
||||
val isHorizontalImages: Boolean = false
|
||||
)
|
||||
|
||||
/** enum class holds search quality.
|
||||
*
|
||||
* [Movie release types](https://en.wikipedia.org/wiki/Pirated_movie_release_types)**/
|
||||
enum class SearchQuality(value: Int?) {
|
||||
// https://en.wikipedia.org/wiki/Pirated_movie_release_types
|
||||
Cam(1),
|
||||
CamRip(2),
|
||||
HdCam(3),
|
||||
@ -763,8 +851,11 @@ enum class SearchQuality(value: Int?) {
|
||||
WebRip(16)
|
||||
}
|
||||
|
||||
/**Add anything to here if you find a site that uses some specific naming convention*/
|
||||
/** Returns [SearchQuality] from String.
|
||||
* @param string String text that will be converted into [SearchQuality].
|
||||
* */
|
||||
fun getQualityFromString(string: String?): SearchQuality? {
|
||||
//Add anything to here if you find a site that uses some specific naming convention
|
||||
val check = (string ?: return null).trim().lowercase().replace(" ", "")
|
||||
|
||||
return when (check) {
|
||||
@ -808,6 +899,8 @@ fun getQualityFromString(string: String?): SearchQuality? {
|
||||
}
|
||||
}
|
||||
|
||||
/** Abstract interface of SearchResponse.
|
||||
* */
|
||||
interface SearchResponse {
|
||||
val name: String
|
||||
val url: String
|
||||
@ -819,6 +912,7 @@ interface SearchResponse {
|
||||
var quality: SearchQuality?
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun MainAPI.newTorrentSearchResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -838,6 +932,7 @@ fun MainAPI.newTorrentSearchResponse(
|
||||
return builder
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun MainAPI.newMovieSearchResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -851,6 +946,7 @@ fun MainAPI.newMovieSearchResponse(
|
||||
return builder
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun MainAPI.newLiveSearchResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -868,6 +964,7 @@ fun MainAPI.newLiveSearchResponse(
|
||||
return builder
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun MainAPI.newTvSeriesSearchResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -881,6 +978,7 @@ fun MainAPI.newTvSeriesSearchResponse(
|
||||
return builder
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun MainAPI.newAnimeSearchResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -894,31 +992,53 @@ fun MainAPI.newAnimeSearchResponse(
|
||||
return builder
|
||||
}
|
||||
|
||||
/** Extension function that adds quality to [SearchResponse]
|
||||
* @param quality as string
|
||||
* */
|
||||
fun SearchResponse.addQuality(quality: String) {
|
||||
this.quality = getQualityFromString(quality)
|
||||
}
|
||||
|
||||
/** Extension function that adds poster to [SearchResponse]
|
||||
* @param url nullable string for poster url
|
||||
* @param headers Optional <String, String> map of request headers
|
||||
* */
|
||||
fun SearchResponse.addPoster(url: String?, headers: Map<String, String>? = null) {
|
||||
this.posterUrl = url
|
||||
this.posterHeaders = headers
|
||||
}
|
||||
|
||||
/** Extension function that adds poster to [LoadResponse]
|
||||
* @param url nullable string for poster url
|
||||
* @param headers Optional <String, String> map of request headers
|
||||
* */
|
||||
fun LoadResponse.addPoster(url: String?, headers: Map<String, String>? = null) {
|
||||
this.posterUrl = url
|
||||
this.posterHeaders = headers
|
||||
}
|
||||
|
||||
/** enum class of Actor roles (Main, Supporting, Background).*/
|
||||
enum class ActorRole {
|
||||
Main,
|
||||
Supporting,
|
||||
Background,
|
||||
}
|
||||
|
||||
/** Data class hold Actor personal information
|
||||
* @property name Actor name.
|
||||
* @property image Url nullable String to Actor image (Optional).
|
||||
* */
|
||||
data class Actor(
|
||||
val name: String,
|
||||
val image: String? = null,
|
||||
)
|
||||
|
||||
/** Data class hold Actor information
|
||||
* @property actor [Actor] personal info, name & image.
|
||||
* @property role [ActorRole] (Optional).
|
||||
* @property roleString Actor role as a string (Optional).
|
||||
* @property voiceActor Voice [Actor] personal info, can be used in case of Animation for voice actors. (Optional).
|
||||
* */
|
||||
data class ActorData(
|
||||
val actor: Actor,
|
||||
val role: ActorRole? = null,
|
||||
@ -926,6 +1046,10 @@ data class ActorData(
|
||||
val voiceActor: Actor? = null,
|
||||
)
|
||||
|
||||
/** Data class of [SearchResponse] interface for Anime.
|
||||
* @see newAnimeSearchResponse
|
||||
* */
|
||||
@Deprecated("Use newAnimeSearchResponse", level = DeprecationLevel.WARNING)
|
||||
data class AnimeSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
@ -944,6 +1068,7 @@ data class AnimeSearchResponse(
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun AnimeSearchResponse.addDubStatus(status: DubStatus, episodes: Int? = null) {
|
||||
this.dubStatus = dubStatus?.also { it.add(status) } ?: EnumSet.of(status)
|
||||
if (this.type?.isMovieType() != true)
|
||||
@ -951,20 +1076,24 @@ fun AnimeSearchResponse.addDubStatus(status: DubStatus, episodes: Int? = null) {
|
||||
this.episodes[status] = episodes
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun AnimeSearchResponse.addDubStatus(isDub: Boolean, episodes: Int? = null) {
|
||||
addDubStatus(if (isDub) DubStatus.Dubbed else DubStatus.Subbed, episodes)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun AnimeSearchResponse.addDub(episodes: Int?) {
|
||||
if (episodes == null || episodes <= 0) return
|
||||
addDubStatus(DubStatus.Dubbed, episodes)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun AnimeSearchResponse.addSub(episodes: Int?) {
|
||||
if (episodes == null || episodes <= 0) return
|
||||
addDubStatus(DubStatus.Subbed, episodes)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun AnimeSearchResponse.addDubStatus(
|
||||
dubExist: Boolean,
|
||||
subExist: Boolean,
|
||||
@ -978,6 +1107,7 @@ fun AnimeSearchResponse.addDubStatus(
|
||||
addDubStatus(DubStatus.Subbed, subEpisodes)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun AnimeSearchResponse.addDubStatus(status: String, episodes: Int? = null) {
|
||||
if (status.contains("(dub)", ignoreCase = true)) {
|
||||
addDubStatus(DubStatus.Dubbed, episodes)
|
||||
@ -986,6 +1116,10 @@ fun AnimeSearchResponse.addDubStatus(status: String, episodes: Int? = null) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Data class of [SearchResponse] interface for Torrent.
|
||||
* @see newTorrentSearchResponse
|
||||
* */
|
||||
@Deprecated("Use newTorrentSearchResponse", level = DeprecationLevel.WARNING)
|
||||
data class TorrentSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
@ -998,6 +1132,10 @@ data class TorrentSearchResponse(
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
/** Data class of [SearchResponse] interface for Movies.
|
||||
* @see newMovieSearchResponse
|
||||
* */
|
||||
@Deprecated("Use newMovieSearchResponse", level = DeprecationLevel.WARNING)
|
||||
data class MovieSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
@ -1011,6 +1149,10 @@ data class MovieSearchResponse(
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
/** Data class of [SearchResponse] interface for Live streams.
|
||||
* @see newLiveSearchResponse
|
||||
* */
|
||||
@Deprecated("Use newLiveSearchResponse", level = DeprecationLevel.WARNING)
|
||||
data class LiveSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
@ -1024,6 +1166,10 @@ data class LiveSearchResponse(
|
||||
val lang: String? = null,
|
||||
) : SearchResponse
|
||||
|
||||
/** Data class of [SearchResponse] interface for Tv series.
|
||||
* @see newTvSeriesSearchResponse
|
||||
* */
|
||||
@Deprecated("Use newTvSeriesSearchResponse", level = DeprecationLevel.WARNING)
|
||||
data class TvSeriesSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
@ -1038,6 +1184,11 @@ data class TvSeriesSearchResponse(
|
||||
override var posterHeaders: Map<String, String>? = null,
|
||||
) : SearchResponse
|
||||
|
||||
/** Data class of Trailer data.
|
||||
* @property extractorUrl Url string of the Trailer video.
|
||||
* @property referer Nullable string of referer to be used in network request.
|
||||
* @property raw determines if [extractorUrl] should be used as direct Trailer video link instead of extracting it.
|
||||
* */
|
||||
data class TrailerData(
|
||||
val extractorUrl: String,
|
||||
val referer: String?,
|
||||
@ -1046,6 +1197,26 @@ data class TrailerData(
|
||||
// var subtitles: List<SubtitleFile> = emptyList(),
|
||||
)
|
||||
|
||||
/** Abstract interface of LoadResponse responses
|
||||
* @param name Title of the media, appears on result page.
|
||||
* @param url Url of the media.
|
||||
* @param apiName Plugin name, appears on result page.
|
||||
* @param type [TvType] of the media .
|
||||
* @param posterUrl Url of the media poster, appears on Top of result page.
|
||||
* @param year Year of the media, appears on result page.
|
||||
* @param plot Plot of the media, appears on result page.
|
||||
* @param rating Rating of the media, appears on result page (0-10000).
|
||||
* @param tags Tags of the media, appears on result page.
|
||||
* @param duration duration of the media, appears on result page.
|
||||
* @param trailers list of the media [TrailerData], used to load trailers.
|
||||
* @param recommendations list of the [SearchResponse] related to media, appears on result page.
|
||||
* @param actors list of the [ActorData] casted in the media, appears on result page.
|
||||
* @param comingSoon determines if the media is released or coming soon.
|
||||
* @param syncData Online sync services compatible with the media.
|
||||
* @param posterHeaders headers map used by network request to get the poster.
|
||||
* @param backgroundPosterUrl Url of the media background poster.
|
||||
* @param contentRating content rating of the media, appears on result page.
|
||||
* */
|
||||
interface LoadResponse {
|
||||
var name: String
|
||||
var url: String
|
||||
@ -1087,6 +1258,7 @@ interface LoadResponse {
|
||||
return tryParseJson(idString) ?: return emptyMap()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun LoadResponse.isMovie(): Boolean {
|
||||
return this.type.isMovieType() || this is MovieLoadResponse
|
||||
}
|
||||
@ -1163,7 +1335,7 @@ interface LoadResponse {
|
||||
addImdbId(imdbUrlToIdNullable(url))
|
||||
}
|
||||
|
||||
/**better to call addTrailer with mutible trailers directly instead of calling this multiple times*/
|
||||
/**better to call addTrailer with multiple trailers directly instead of calling this multiple times*/
|
||||
suspend fun LoadResponse.addTrailer(
|
||||
trailerUrl: String?,
|
||||
referer: String? = null,
|
||||
@ -1315,26 +1487,43 @@ fun getDurationFromString(input: String?): Int? {
|
||||
return null
|
||||
}
|
||||
|
||||
/** Extension function of [LoadResponse] to check if it's Episode based.
|
||||
* @return True if the response is [EpisodeResponse] and its type is Episode based.
|
||||
* */
|
||||
fun LoadResponse?.isEpisodeBased(): Boolean {
|
||||
if (this == null) return false
|
||||
return this is EpisodeResponse && this.type.isEpisodeBased()
|
||||
}
|
||||
|
||||
/** Extension function of [LoadResponse] to check if it's Anime based.
|
||||
* @return True if the response type is Anime or OVA.
|
||||
* @see TvType
|
||||
* */
|
||||
fun LoadResponse?.isAnimeBased(): Boolean {
|
||||
if (this == null) return false
|
||||
return (this.type == TvType.Anime || this.type == TvType.OVA) // && (this is AnimeLoadResponse)
|
||||
}
|
||||
|
||||
/** Extension function of [TvType] to check if it's Episode based.
|
||||
* @return True if the response type is Anime, AsianDrama, Cartoon or TvSeries.
|
||||
* @see TvType
|
||||
* */
|
||||
fun TvType?.isEpisodeBased(): Boolean {
|
||||
return when (this) {
|
||||
TvType.Anime,
|
||||
TvType.AsianDrama,
|
||||
TvType.Cartoon,
|
||||
TvType.TvSeries -> true
|
||||
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
/** Data class holds next airing Episode info.
|
||||
* @param episode Next airing Episode number.
|
||||
* @param unixTime Next airing Time in Unix time format.
|
||||
* @param season Season number of next airing episode (Optional).
|
||||
* */
|
||||
data class NextAiring(
|
||||
val episode: Int,
|
||||
val unixTime: Long,
|
||||
@ -1354,7 +1543,7 @@ data class NextAiring(
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
/** Data class holds season info.
|
||||
* @param season To be mapped with episode season, not shown in UI if displaySeason is defined
|
||||
* @param name To be shown next to the season like "Season $displaySeason $name" but if displaySeason is null then "$name"
|
||||
* @param displaySeason What to be displayed next to the season name, if null then the name is the only thing shown.
|
||||
@ -1365,6 +1554,7 @@ data class SeasonData(
|
||||
val displaySeason: Int? = null, // will use season if null
|
||||
)
|
||||
|
||||
/** Abstract interface of EpisodeResponse */
|
||||
interface EpisodeResponse {
|
||||
var showStatus: ShowStatus?
|
||||
var nextAiring: NextAiring?
|
||||
@ -1396,6 +1586,10 @@ fun EpisodeResponse.addSeasonNames(names: List<SeasonData>) {
|
||||
this.seasonNames = names.ifEmpty { null }
|
||||
}
|
||||
|
||||
/** Data class of [LoadResponse] interface for Torrent.
|
||||
* @see newTorrentLoadResponse
|
||||
*/
|
||||
@Deprecated("Use newTorrentLoadResponse method", level = DeprecationLevel.WARNING)
|
||||
data class TorrentLoadResponse(
|
||||
override var name: String,
|
||||
override var url: String,
|
||||
@ -1466,6 +1660,7 @@ data class TorrentLoadResponse(
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun MainAPI.newTorrentLoadResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -1487,6 +1682,11 @@ suspend fun MainAPI.newTorrentLoadResponse(
|
||||
return builder
|
||||
}
|
||||
|
||||
/** Data class of [LoadResponse] interface for Anime.
|
||||
* @see newAnimeLoadResponse
|
||||
* */
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("Use newAnimeLoadResponse method", level = DeprecationLevel.WARNING)
|
||||
data class AnimeLoadResponse(
|
||||
var engName: String? = null,
|
||||
var japName: String? = null,
|
||||
@ -1604,11 +1804,13 @@ data class AnimeLoadResponse(
|
||||
/**
|
||||
* If episodes already exist appends the list.
|
||||
* */
|
||||
@Suppress("DEPRECATION")
|
||||
fun AnimeLoadResponse.addEpisodes(status: DubStatus, episodes: List<Episode>?) {
|
||||
if (episodes.isNullOrEmpty()) return
|
||||
this.episodes[status] = (this.episodes[status] ?: emptyList()) + episodes
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun MainAPI.newAnimeLoadResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -1629,6 +1831,10 @@ suspend fun MainAPI.newAnimeLoadResponse(
|
||||
return builder
|
||||
}
|
||||
|
||||
/** Data class of [LoadResponse] interface for Live streams.
|
||||
* @see newLiveStreamLoadResponse
|
||||
* */
|
||||
@Deprecated("Use newLiveStreamLoadResponse method", level = DeprecationLevel.WARNING)
|
||||
data class LiveStreamLoadResponse(
|
||||
override var name: String,
|
||||
override var url: String,
|
||||
@ -1681,6 +1887,7 @@ data class LiveStreamLoadResponse(
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun MainAPI.newLiveStreamLoadResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -1698,6 +1905,10 @@ suspend fun MainAPI.newLiveStreamLoadResponse(
|
||||
return builder
|
||||
}
|
||||
|
||||
/** Data class of [LoadResponse] interface for Movies.
|
||||
* @see newMovieLoadResponse
|
||||
* */
|
||||
@Deprecated("Use newMovieLoadResponse method", level = DeprecationLevel.WARNING)
|
||||
data class MovieLoadResponse(
|
||||
override var name: String,
|
||||
override var url: String,
|
||||
@ -1750,6 +1961,7 @@ data class MovieLoadResponse(
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun <T> MainAPI.newMovieLoadResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -1778,6 +1990,7 @@ suspend fun <T> MainAPI.newMovieLoadResponse(
|
||||
return builder
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun MainAPI.newMovieLoadResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -1796,6 +2009,7 @@ suspend fun MainAPI.newMovieLoadResponse(
|
||||
builder.initializer()
|
||||
return builder
|
||||
}
|
||||
|
||||
/** Episode information that will be passed to LoadLinks function & showed on UI
|
||||
* @property data string used as main LoadLinks fun parameter.
|
||||
* @property name Name of the Episode.
|
||||
@ -1805,8 +2019,9 @@ suspend fun MainAPI.newMovieLoadResponse(
|
||||
* @property rating Episode rating.
|
||||
* @property date Episode air date, see addDate.
|
||||
* @property runTime Episode runtime in seconds.
|
||||
* @see[addDate]
|
||||
* @see newEpisode
|
||||
* */
|
||||
@Deprecated("Use newEpisode", level = DeprecationLevel.WARNING)
|
||||
data class Episode(
|
||||
var data: String,
|
||||
var name: String? = null,
|
||||
@ -1836,6 +2051,7 @@ data class Episode(
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun Episode.addDate(date: String?, format: String = "yyyy-MM-dd") {
|
||||
try {
|
||||
this.date = SimpleDateFormat(format)?.parse(date ?: return)?.time
|
||||
@ -1844,10 +2060,12 @@ fun Episode.addDate(date: String?, format: String = "yyyy-MM-dd") {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun Episode.addDate(date: Date?) {
|
||||
this.date = date?.time
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun MainAPI.newEpisode(
|
||||
url: String,
|
||||
initializer: Episode.() -> Unit = { },
|
||||
@ -1860,6 +2078,7 @@ fun MainAPI.newEpisode(
|
||||
return builder
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun <T> MainAPI.newEpisode(
|
||||
data: T,
|
||||
initializer: Episode.() -> Unit = { }
|
||||
@ -1898,6 +2117,11 @@ enum class SimklSyncServices(val originalName: String) {
|
||||
Mal("mal"),
|
||||
}
|
||||
|
||||
/** Data class of [LoadResponse] interface for Tv series.
|
||||
* @see newTvSeriesLoadResponse
|
||||
* */
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("Use newTvSeriesLoadResponse method", level = DeprecationLevel.WARNING)
|
||||
data class TvSeriesLoadResponse(
|
||||
override var name: String,
|
||||
override var url: String,
|
||||
@ -1998,6 +2222,7 @@ data class TvSeriesLoadResponse(
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
suspend fun MainAPI.newTvSeriesLoadResponse(
|
||||
name: String,
|
||||
url: String,
|
||||
@ -2098,4 +2323,4 @@ enum class TrackerType {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -431,6 +431,21 @@ val WIDEVINE_UUID = UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L)
|
||||
*/
|
||||
val PLAYREADY_UUID = UUID(-0x65fb0f8667bfbd7aL, -0x546d19a41f77a06bL)
|
||||
|
||||
/** Class holds extracted DRM media info to be passed to the player.
|
||||
* @property source Name of the media source, appears on player layout.
|
||||
* @property name Title of the media, appears on player layout.
|
||||
* @property url Url string of media file
|
||||
* @property referer Referer that will be used by network request.
|
||||
* @property quality Quality of the media file
|
||||
* @property headers Headers <String, String> map that will be used by network request.
|
||||
* @property extractorData Used for getExtractorVerifierJob()
|
||||
* @property type the type of the media, use [INFER_TYPE] if you want to auto infer the type from the url
|
||||
* @property kid Base64 value of The KID element (Key Id) contains the identifier of the key associated with a license.
|
||||
* @property key Base64 value of Key to be used to decrypt the media file.
|
||||
* @property uuid Drm UUID [WIDEVINE_UUID], [PLAYREADY_UUID], [CLEARKEY_UUID] (by default) .. etc
|
||||
* @property kty Key type "oct" (octet sequence) by default
|
||||
* @property keyRequestParameters Parameters that will used to request the key.
|
||||
* */
|
||||
open class DrmExtractorLink private constructor(
|
||||
override val source: String,
|
||||
override val name: String,
|
||||
@ -483,6 +498,16 @@ open class DrmExtractorLink private constructor(
|
||||
)
|
||||
}
|
||||
|
||||
/** Class holds extracted media info to be passed to the player.
|
||||
* @property source Name of the media source, appears on player layout.
|
||||
* @property name Title of the media, appears on player layout.
|
||||
* @property url Url string of media file
|
||||
* @property referer Referer that will be used by network request.
|
||||
* @property quality Quality of the media file
|
||||
* @property headers Headers <String, String> map that will be used by network request.
|
||||
* @property extractorData Used for getExtractorVerifierJob()
|
||||
* @property type Extracted link type (Video, M3u8, Dash, Torrent or Magnet)
|
||||
* */
|
||||
open class ExtractorLink constructor(
|
||||
open val source: String,
|
||||
open val name: String,
|
||||
|
Reference in New Issue
Block a user