2021-04-30 17:20:15 +00:00
|
|
|
package com.lagradost.cloudstream3
|
|
|
|
|
2021-05-15 23:37:42 +00:00
|
|
|
import android.app.Activity
|
|
|
|
import androidx.preference.PreferenceManager
|
2021-04-30 17:20:15 +00:00
|
|
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
|
|
|
import com.fasterxml.jackson.databind.json.JsonMapper
|
|
|
|
import com.fasterxml.jackson.module.kotlin.KotlinModule
|
2021-06-23 18:33:47 +00:00
|
|
|
import com.lagradost.cloudstream3.animeproviders.DubbedAnimeProvider
|
2021-07-21 23:49:56 +00:00
|
|
|
import com.lagradost.cloudstream3.animeproviders.TenshiProvider
|
2021-08-14 17:31:27 +00:00
|
|
|
import com.lagradost.cloudstream3.animeproviders.WatchCartoonOnlineProvider
|
2021-07-23 11:58:53 +00:00
|
|
|
import com.lagradost.cloudstream3.animeproviders.WcoProvider
|
2021-06-24 17:45:59 +00:00
|
|
|
import com.lagradost.cloudstream3.movieproviders.HDMProvider
|
2021-06-26 14:44:53 +00:00
|
|
|
import com.lagradost.cloudstream3.movieproviders.TrailersToProvider
|
2021-08-11 17:04:31 +00:00
|
|
|
import com.lagradost.cloudstream3.movieproviders.VMoveeProvider
|
2021-05-20 15:22:28 +00:00
|
|
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
2021-04-30 17:20:15 +00:00
|
|
|
import java.util.*
|
|
|
|
|
2021-08-14 17:31:27 +00:00
|
|
|
|
|
|
|
const val USER_AGENT =
|
|
|
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
2021-04-30 17:20:15 +00:00
|
|
|
val baseHeader = mapOf("User-Agent" to USER_AGENT)
|
|
|
|
val mapper = JsonMapper.builder().addModule(KotlinModule())
|
|
|
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build()!!
|
|
|
|
|
2021-05-12 21:51:02 +00:00
|
|
|
object APIHolder {
|
2021-06-17 16:20:05 +00:00
|
|
|
val unixTime: Long
|
|
|
|
get() = System.currentTimeMillis() / 1000L
|
|
|
|
|
2021-05-15 23:37:42 +00:00
|
|
|
private const val defProvider = 0
|
|
|
|
|
2021-06-16 22:31:41 +00:00
|
|
|
val apis = arrayListOf(
|
2021-07-29 15:44:16 +00:00
|
|
|
TrailersToProvider(),
|
2021-08-11 17:04:31 +00:00
|
|
|
//ShiroProvider(), // v2 fucked me
|
2021-07-21 23:49:56 +00:00
|
|
|
TenshiProvider(),
|
2021-07-23 11:58:53 +00:00
|
|
|
WcoProvider(),
|
2021-08-11 17:04:31 +00:00
|
|
|
// MeloMovieProvider(), // Captcha for links
|
2021-06-23 18:33:47 +00:00
|
|
|
DubbedAnimeProvider(),
|
2021-06-24 17:45:59 +00:00
|
|
|
HDMProvider(),
|
2021-07-23 23:44:54 +00:00
|
|
|
//LookMovieProvider(), // RECAPTCHA (Please allow up to 5 seconds...)
|
2021-08-11 17:04:31 +00:00
|
|
|
VMoveeProvider(),
|
2021-08-14 17:31:27 +00:00
|
|
|
WatchCartoonOnlineProvider(),
|
2021-05-12 21:51:02 +00:00
|
|
|
)
|
2021-05-15 23:37:42 +00:00
|
|
|
|
2021-05-22 22:25:56 +00:00
|
|
|
fun getApiFromName(apiName: String?): MainAPI {
|
2021-05-18 13:43:32 +00:00
|
|
|
for (api in apis) {
|
|
|
|
if (apiName == api.name)
|
|
|
|
return api
|
|
|
|
}
|
|
|
|
return apis[defProvider]
|
|
|
|
}
|
|
|
|
|
2021-07-29 00:19:42 +00:00
|
|
|
fun getApiFromNameNull(apiName: String?): MainAPI? {
|
|
|
|
for (api in apis) {
|
|
|
|
if (apiName == api.name)
|
|
|
|
return api
|
|
|
|
}
|
|
|
|
return null
|
|
|
|
}
|
2021-07-25 16:08:34 +00:00
|
|
|
|
|
|
|
fun LoadResponse.getId(): Int {
|
2021-07-30 23:41:54 +00:00
|
|
|
return url.replace(getApiFromName(apiName).mainUrl, "").replace("/", "").hashCode()
|
2021-07-25 16:08:34 +00:00
|
|
|
}
|
|
|
|
|
2021-05-15 23:37:42 +00:00
|
|
|
fun Activity.getApiSettings(): HashSet<String> {
|
|
|
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
|
|
|
|
2021-07-02 19:43:15 +00:00
|
|
|
return settingsManager.getStringSet(
|
|
|
|
this.getString(R.string.search_providers_list_key),
|
|
|
|
setOf(apis[defProvider].name)
|
|
|
|
)?.toHashSet() ?: hashSetOf(apis[defProvider].name)
|
2021-05-15 23:37:42 +00:00
|
|
|
}
|
2021-05-12 21:51:02 +00:00
|
|
|
}
|
|
|
|
|
2021-07-23 23:44:54 +00:00
|
|
|
/**Every provider will **not** have try catch built in, so handle exceptions when calling these functions*/
|
2021-05-12 21:51:02 +00:00
|
|
|
abstract class MainAPI {
|
2021-04-30 17:20:15 +00:00
|
|
|
open val name = "NONE"
|
|
|
|
open val mainUrl = "NONE"
|
2021-07-23 23:44:54 +00:00
|
|
|
|
|
|
|
/**If link is stored in the "data" string, so links can be instantly loaded*/
|
|
|
|
open val instantLinkLoading = false
|
|
|
|
|
|
|
|
/**Set false if links require referer or for some reason cant be played on a chromecast*/
|
|
|
|
open val hasChromecastSupport = true
|
|
|
|
|
|
|
|
/**If all links are m3u8 then set this to false*/
|
|
|
|
open val hasDownloadSupport = true
|
|
|
|
|
2021-07-29 00:19:42 +00:00
|
|
|
open val hasMainPage = false
|
|
|
|
open val hasQuickSearch = false
|
|
|
|
|
2021-08-14 17:31:27 +00:00
|
|
|
open val supportedTypes = setOf(
|
|
|
|
TvType.Movie,
|
|
|
|
TvType.TvSeries,
|
|
|
|
TvType.Cartoon,
|
|
|
|
TvType.Anime,
|
|
|
|
TvType.ONA
|
|
|
|
)
|
|
|
|
|
2021-07-30 23:41:54 +00:00
|
|
|
open fun getMainPage(): HomePageResponse? {
|
2021-07-29 00:19:42 +00:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2021-07-23 23:44:54 +00:00
|
|
|
open fun search(query: String): ArrayList<SearchResponse>? {
|
2021-04-30 17:20:15 +00:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2021-06-26 14:44:53 +00:00
|
|
|
open fun quickSearch(query: String): ArrayList<SearchResponse>? {
|
2021-06-17 16:20:05 +00:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2021-07-30 14:09:57 +00:00
|
|
|
open fun load(url: String): LoadResponse? {
|
2021-04-30 17:20:15 +00:00
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
2021-07-23 23:44:54 +00:00
|
|
|
/**Callback is fired once a link is found, will return true if method is executed successfully*/
|
2021-07-02 19:43:15 +00:00
|
|
|
open fun loadLinks(
|
|
|
|
data: String,
|
|
|
|
isCasting: Boolean,
|
|
|
|
subtitleCallback: (SubtitleFile) -> Unit,
|
|
|
|
callback: (ExtractorLink) -> Unit
|
|
|
|
): Boolean {
|
2021-04-30 17:20:15 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-04 01:50:24 +00:00
|
|
|
class ErrorLoadingException(message: String? = null) : Exception(message)
|
|
|
|
|
2021-06-26 14:44:53 +00:00
|
|
|
fun parseRating(ratingString: String?): Int? {
|
|
|
|
if (ratingString == null) return null
|
2021-06-24 17:45:59 +00:00
|
|
|
val floatRating = ratingString.toFloatOrNull() ?: return null
|
|
|
|
return (floatRating * 10).toInt()
|
|
|
|
}
|
|
|
|
|
2021-05-15 23:37:42 +00:00
|
|
|
fun MainAPI.fixUrl(url: String): String {
|
2021-06-26 14:44:53 +00:00
|
|
|
if (url.startsWith("http")) {
|
2021-06-23 18:33:47 +00:00
|
|
|
return url
|
|
|
|
}
|
|
|
|
|
|
|
|
val startsWithNoHttp = url.startsWith("//")
|
2021-06-26 14:44:53 +00:00
|
|
|
if (startsWithNoHttp) {
|
2021-06-23 18:33:47 +00:00
|
|
|
return "https:$url"
|
2021-06-26 14:44:53 +00:00
|
|
|
} else {
|
|
|
|
if (url.startsWith('/')) {
|
2021-06-23 18:33:47 +00:00
|
|
|
return mainUrl + url
|
|
|
|
}
|
2021-05-15 23:37:42 +00:00
|
|
|
return "$mainUrl/$url"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-10 19:43:05 +00:00
|
|
|
fun sortUrls(urls: List<ExtractorLink>): List<ExtractorLink> {
|
|
|
|
return urls.sortedBy { t -> -t.quality }
|
|
|
|
}
|
2021-05-15 23:37:42 +00:00
|
|
|
|
2021-07-02 19:43:15 +00:00
|
|
|
fun sortSubs(urls: List<SubtitleFile>): List<SubtitleFile> {
|
|
|
|
val encounteredTimes = HashMap<String, Int>()
|
|
|
|
return urls.sortedBy { t -> t.lang }.map {
|
|
|
|
val times = encounteredTimes[it.lang]?.plus(1) ?: 1
|
|
|
|
encounteredTimes[it.lang] = times
|
|
|
|
|
|
|
|
SubtitleFile("${it.lang} ${if (times > 1) "($times)" else ""}", it.url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-04 01:50:24 +00:00
|
|
|
/** https://www.imdb.com/title/tt2861424/ -> tt2861424 */
|
|
|
|
fun imdbUrlToId(url: String): String {
|
|
|
|
return url
|
|
|
|
.removePrefix("https://www.imdb.com/title/")
|
|
|
|
.removePrefix("https://imdb.com/title/tt2861424/")
|
|
|
|
.replace("/", "")
|
|
|
|
}
|
|
|
|
|
|
|
|
fun imdbUrlToIdNullable(url: String?): String? {
|
2021-08-11 17:04:31 +00:00
|
|
|
if (url == null) return null
|
2021-08-04 01:50:24 +00:00
|
|
|
return imdbUrlToId(url)
|
|
|
|
}
|
|
|
|
|
2021-04-30 17:20:15 +00:00
|
|
|
enum class ShowStatus {
|
|
|
|
Completed,
|
|
|
|
Ongoing,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum class DubStatus {
|
2021-05-22 22:25:56 +00:00
|
|
|
Dubbed,
|
|
|
|
Subbed,
|
2021-04-30 17:20:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
enum class TvType {
|
|
|
|
Movie,
|
|
|
|
TvSeries,
|
2021-08-14 17:31:27 +00:00
|
|
|
Cartoon,
|
2021-04-30 17:20:15 +00:00
|
|
|
Anime,
|
|
|
|
ONA,
|
|
|
|
}
|
|
|
|
|
2021-07-15 16:45:25 +00:00
|
|
|
// IN CASE OF FUTURE ANIME MOVIE OR SMTH
|
2021-07-25 16:08:34 +00:00
|
|
|
fun TvType.isMovieType(): Boolean {
|
2021-07-15 16:45:25 +00:00
|
|
|
return this == TvType.Movie
|
|
|
|
}
|
|
|
|
|
2021-07-02 19:43:15 +00:00
|
|
|
data class SubtitleFile(val lang: String, val url: String)
|
2021-07-01 20:11:33 +00:00
|
|
|
|
2021-07-29 00:19:42 +00:00
|
|
|
class HomePageResponse(
|
|
|
|
val items: List<HomePageList>
|
|
|
|
)
|
|
|
|
|
|
|
|
class HomePageList(
|
|
|
|
val name: String,
|
|
|
|
val list: List<SearchResponse>
|
|
|
|
)
|
|
|
|
|
2021-04-30 17:20:15 +00:00
|
|
|
interface SearchResponse {
|
|
|
|
val name: String
|
2021-05-18 13:43:32 +00:00
|
|
|
val url: String // PUBLIC URL FOR OPEN IN APP
|
2021-04-30 17:20:15 +00:00
|
|
|
val apiName: String
|
|
|
|
val type: TvType
|
|
|
|
val posterUrl: String?
|
|
|
|
val year: Int?
|
2021-07-30 23:41:54 +00:00
|
|
|
val id: Int?
|
2021-04-30 17:20:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
data class AnimeSearchResponse(
|
|
|
|
override val name: String,
|
|
|
|
override val url: String,
|
|
|
|
override val apiName: String,
|
|
|
|
override val type: TvType,
|
|
|
|
|
|
|
|
override val posterUrl: String?,
|
|
|
|
override val year: Int?,
|
|
|
|
|
|
|
|
val otherName: String?,
|
|
|
|
val dubStatus: EnumSet<DubStatus>?,
|
|
|
|
val dubEpisodes: Int?,
|
|
|
|
val subEpisodes: Int?,
|
2021-07-30 23:41:54 +00:00
|
|
|
override val id: Int? = null,
|
2021-04-30 17:20:15 +00:00
|
|
|
) : SearchResponse
|
|
|
|
|
|
|
|
data class MovieSearchResponse(
|
|
|
|
override val name: String,
|
|
|
|
override val url: String,
|
|
|
|
override val apiName: String,
|
|
|
|
override val type: TvType,
|
|
|
|
|
|
|
|
override val posterUrl: String?,
|
|
|
|
override val year: Int?,
|
2021-07-30 23:41:54 +00:00
|
|
|
override val id: Int? = null,
|
2021-04-30 17:20:15 +00:00
|
|
|
) : SearchResponse
|
|
|
|
|
|
|
|
data class TvSeriesSearchResponse(
|
|
|
|
override val name: String,
|
|
|
|
override val url: String,
|
|
|
|
override val apiName: String,
|
|
|
|
override val type: TvType,
|
|
|
|
|
|
|
|
override val posterUrl: String?,
|
|
|
|
override val year: Int?,
|
|
|
|
val episodes: Int?,
|
2021-07-30 23:41:54 +00:00
|
|
|
override val id: Int? = null,
|
2021-04-30 17:20:15 +00:00
|
|
|
) : SearchResponse
|
|
|
|
|
|
|
|
interface LoadResponse {
|
|
|
|
val name: String
|
|
|
|
val url: String
|
|
|
|
val apiName: String
|
|
|
|
val type: TvType
|
|
|
|
val posterUrl: String?
|
|
|
|
val year: Int?
|
2021-05-22 22:25:56 +00:00
|
|
|
val plot: String?
|
2021-06-26 14:44:53 +00:00
|
|
|
val rating: Int? // 0-100
|
2021-08-14 17:31:27 +00:00
|
|
|
val tags: List<String>?
|
2021-06-26 14:44:53 +00:00
|
|
|
val duration: String?
|
|
|
|
val trailerUrl: String?
|
2021-04-30 17:20:15 +00:00
|
|
|
}
|
|
|
|
|
2021-06-17 15:39:01 +00:00
|
|
|
fun LoadResponse?.isEpisodeBased(): Boolean {
|
|
|
|
if (this == null) return false
|
|
|
|
return (this is AnimeLoadResponse || this is TvSeriesLoadResponse) && (this.type == TvType.TvSeries || this.type == TvType.Anime)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun LoadResponse?.isAnimeBased(): Boolean {
|
|
|
|
if (this == null) return false
|
|
|
|
return (this.type == TvType.Anime || this.type == TvType.ONA) // && (this is AnimeLoadResponse)
|
2021-05-28 13:38:06 +00:00
|
|
|
}
|
|
|
|
|
2021-06-26 19:32:50 +00:00
|
|
|
data class AnimeEpisode(
|
|
|
|
val url: String,
|
|
|
|
val name: String? = null,
|
|
|
|
val posterUrl: String? = null,
|
|
|
|
val date: String? = null,
|
|
|
|
val rating: Int? = null,
|
|
|
|
val descript: String? = null,
|
|
|
|
)
|
2021-06-23 18:33:47 +00:00
|
|
|
|
2021-04-30 17:20:15 +00:00
|
|
|
data class AnimeLoadResponse(
|
2021-05-16 18:28:00 +00:00
|
|
|
val engName: String?,
|
|
|
|
val japName: String?,
|
2021-04-30 17:20:15 +00:00
|
|
|
override val name: String,
|
|
|
|
override val url: String,
|
|
|
|
override val apiName: String,
|
|
|
|
override val type: TvType,
|
|
|
|
|
|
|
|
override val posterUrl: String?,
|
|
|
|
override val year: Int?,
|
|
|
|
|
2021-08-14 17:31:27 +00:00
|
|
|
val dubEpisodes: List<AnimeEpisode>?,
|
|
|
|
val subEpisodes: List<AnimeEpisode>?,
|
2021-04-30 17:20:15 +00:00
|
|
|
val showStatus: ShowStatus?,
|
|
|
|
|
2021-05-22 22:25:56 +00:00
|
|
|
override val plot: String?,
|
2021-08-14 17:31:27 +00:00
|
|
|
override val tags: List<String>? = null,
|
|
|
|
val synonyms: List<String>? = null,
|
2021-04-30 17:20:15 +00:00
|
|
|
|
2021-06-23 18:33:47 +00:00
|
|
|
val malId: Int? = null,
|
|
|
|
val anilistId: Int? = null,
|
2021-06-24 17:45:59 +00:00
|
|
|
override val rating: Int? = null,
|
2021-06-26 14:44:53 +00:00
|
|
|
override val duration: String? = null,
|
|
|
|
override val trailerUrl: String? = null,
|
2021-04-30 17:20:15 +00:00
|
|
|
) : LoadResponse
|
|
|
|
|
|
|
|
data class MovieLoadResponse(
|
|
|
|
override val name: String,
|
|
|
|
override val url: String,
|
|
|
|
override val apiName: String,
|
|
|
|
override val type: TvType,
|
2021-06-23 18:33:47 +00:00
|
|
|
val dataUrl: String,
|
2021-04-30 17:20:15 +00:00
|
|
|
|
|
|
|
override val posterUrl: String?,
|
|
|
|
override val year: Int?,
|
2021-05-22 22:25:56 +00:00
|
|
|
override val plot: String?,
|
2021-04-30 17:20:15 +00:00
|
|
|
|
2021-08-04 01:50:24 +00:00
|
|
|
val imdbId: String?,
|
2021-06-24 17:45:59 +00:00
|
|
|
override val rating: Int? = null,
|
2021-08-14 17:31:27 +00:00
|
|
|
override val tags: List<String>? = null,
|
2021-06-26 14:44:53 +00:00
|
|
|
override val duration: String? = null,
|
|
|
|
override val trailerUrl: String? = null,
|
2021-04-30 17:20:15 +00:00
|
|
|
) : LoadResponse
|
|
|
|
|
2021-06-26 14:44:53 +00:00
|
|
|
data class TvSeriesEpisode(
|
|
|
|
val name: String?,
|
|
|
|
val season: Int?,
|
|
|
|
val episode: Int?,
|
|
|
|
val data: String,
|
|
|
|
val posterUrl: String? = null,
|
|
|
|
val date: String? = null,
|
|
|
|
val rating: Int? = null,
|
|
|
|
val descript: String? = null,
|
|
|
|
)
|
2021-06-16 22:31:41 +00:00
|
|
|
|
2021-04-30 17:20:15 +00:00
|
|
|
data class TvSeriesLoadResponse(
|
|
|
|
override val name: String,
|
|
|
|
override val url: String,
|
|
|
|
override val apiName: String,
|
|
|
|
override val type: TvType,
|
2021-08-14 17:31:27 +00:00
|
|
|
val episodes: List<TvSeriesEpisode>,
|
2021-04-30 17:20:15 +00:00
|
|
|
|
|
|
|
override val posterUrl: String?,
|
|
|
|
override val year: Int?,
|
2021-05-22 22:25:56 +00:00
|
|
|
override val plot: String?,
|
2021-04-30 17:20:15 +00:00
|
|
|
|
|
|
|
val showStatus: ShowStatus?,
|
2021-08-04 01:50:24 +00:00
|
|
|
val imdbId: String?,
|
2021-06-24 17:45:59 +00:00
|
|
|
override val rating: Int? = null,
|
2021-08-14 17:31:27 +00:00
|
|
|
override val tags: List<String>? = null,
|
2021-06-26 14:44:53 +00:00
|
|
|
override val duration: String? = null,
|
|
|
|
override val trailerUrl: String? = null,
|
2021-07-21 23:49:56 +00:00
|
|
|
) : LoadResponse
|