year string: $it")
- Jsoup.parse(it).select("p")[1]
- }?.text()?.take(4)?.toIntOrNull()
- //Fetch genres
- val genre = otherInfoBody.substringAfter("
Genre :
")
- .substringBefore("
Release :
").let {
- //Log.i(this.name, "Result => genre string: $it")
- Jsoup.parse(it).select("a")
- }.mapNotNull { it?.text()?.trim() ?: return@mapNotNull null }
-
- return when (val tvType = if (episodes.isEmpty()) TvType.Movie else TvType.TvSeries) {
- TvType.TvSeries -> {
- TvSeriesLoadResponse(
- title,
- url,
- this.name,
- tvType,
- episodes.reversed(),
- fixUrlNull(poster),
- year = year,
- description,
- actors = casts,
- tags = genre
- )
- }
- TvType.Movie -> {
- MovieLoadResponse(
- title,
- url,
- this.name,
- tvType,
- url,
- fixUrlNull(poster),
- year = year,
- description,
- actors = casts,
- tags = genre
- )
- }
- else -> null
- }
- }
-
- data class ServerJson(
- @JsonProperty("0") val zero: String?,
- @JsonProperty("key") val key: Boolean?,
- @JsonProperty("val") val stream: String?,
- @JsonProperty("val_bak") val streambackup: String?,
- @JsonProperty("pos") val pos: Int?,
- @JsonProperty("type") val type: String?,
- @JsonProperty("subs") val subs: List
?,
- @JsonProperty("prev_epi_title") val prevEpiTitle: String?,
- @JsonProperty("prev_epi_url") val prevEpiUrl: String?,
- @JsonProperty("next_epi_title") val nextEpiTitle: String?,
- @JsonProperty("next_epi_url") val nextEpiUrl: String?
- )
-
- data class Subs(
- @JsonProperty("id") val id: Int?,
- @JsonProperty("movieId") val movieId: Int?,
- @JsonProperty("tvId") val tvId: Int?,
- @JsonProperty("episodeId") val episodeId: Int?,
- @JsonProperty("default") val default: Int?,
- @JsonProperty("IsShow") val IsShow: Int?,
- @JsonProperty("name") val name: String,
- @JsonProperty("path") val path: String?,
- @JsonProperty("downlink") val downlink: String?,
- @JsonProperty("source_file_name") val sourceFileName: String?,
- @JsonProperty("createtime") val createtime: Int?
- )
-
- override suspend fun loadLinks(
- data: String,
- isCasting: Boolean,
- subtitleCallback: (SubtitleFile) -> Unit,
- callback: (ExtractorLink) -> Unit
- ): Boolean {
- val doc = app.get(data).document
- val idplayer = doc.selectFirst("#divU")?.text()
- val idplayer2 = doc.selectFirst("#divP")?.text()
- val movieid = doc.selectFirst("div.row input#hId")!!.attr("value")
- val tvType = try {
- doc.selectFirst(".col-md-5 > div:nth-child(1) > div:nth-child(1) > img")!!.attr("src")
- ?: ""
- } catch (e: Exception) {
- ""
- }
- val ajaxlink =
- if (tvType.contains("movie")) "$mainUrl/home/index/GetMInfoAjax" else "$mainUrl/home/index/GetEInfoAjax"
- listOf(
- idplayer,
- idplayer2,
- ).mapNotNull { playerID ->
- val url = app.post(
- ajaxlink,
- headers = mapOf(
- "Host" to "secretlink.xyz",
- "User-Agent" to USER_AGENT,
- "Accept" to "application/json, text/javascript, */*; q=0.01",
- "Accept-Language" to "en-US,en;q=0.5",
- "Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8",
- "X-Requested-With" to "XMLHttpRequest",
- "Origin" to "https://secretlink.xyz",
- "DNT" to "1",
- "Connection" to "keep-alive",
- "Referer" to data,
- "Sec-Fetch-Dest" to "empty",
- "Sec-Fetch-Mode" to "cors",
- "Sec-Fetch-Site" to "same-origin",
- ),
- data = mapOf(
- Pair("pass", movieid),
- Pair("param", playerID ?: ""),
- )
- ).text.replace("\\\"", "\"").replace("\"{", "{").replace("}\"", "}")
- .replace("\\\\\\/", "\\/")
- val json = parseJson(url)
- listOfNotNull(
- json.stream,
- json.streambackup
- ).apmap { stream ->
- val cleanstreamurl = stream.replace("\\/", "/").replace("\\\\\\", "")
- if (cleanstreamurl.isNotBlank()) {
- callback(
- ExtractorLink(
- "Soap2Day",
- "Soap2Day",
- cleanstreamurl,
- "https://soap2day.ac",
- Qualities.Unknown.value,
- isM3u8 = false
- )
- )
- }
- }
- json.subs?.forEach { subtitle ->
- val sublink = mainUrl + subtitle.path
- listOf(
- sublink,
- subtitle.downlink
- ).mapNotNull { subs ->
- if (subs != null) {
- if (subs.isNotBlank()) {
- subtitleCallback(
- SubtitleFile(subtitle.name, subs)
- )
- }
- }
- }
- }
- }
- return true
- }
-}
diff --git a/SoaptwoDayProvider/src/main/kotlin/com/lagradost/SoaptwoDayProviderPlugin.kt b/SoaptwoDayProvider/src/main/kotlin/com/lagradost/SoaptwoDayProviderPlugin.kt
deleted file mode 100644
index e006f92..0000000
--- a/SoaptwoDayProvider/src/main/kotlin/com/lagradost/SoaptwoDayProviderPlugin.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package com.lagradost
-
-import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
-import com.lagradost.cloudstream3.plugins.Plugin
-import android.content.Context
-
-@CloudstreamPlugin
-class SoaptwoDayProviderPlugin: Plugin() {
- override fun load(context: Context) {
- // All providers should be added in this manner. Please don't edit the providers list directly.
- registerMainAPI(SoaptwoDayProvider())
- }
-}
\ No newline at end of file
diff --git a/SuperStream/build.gradle.kts b/SuperStream/build.gradle.kts
deleted file mode 100644
index 5593518..0000000
--- a/SuperStream/build.gradle.kts
+++ /dev/null
@@ -1,26 +0,0 @@
-// use an integer for version numbers
-version = 1
-
-
-cloudstream {
- // All of these properties are optional, you can safely remove them
-
- // description = "Lorem Ipsum"
- // authors = listOf("Cloudburst")
-
- /**
- * Status int as the following:
- * 0: Down
- * 1: Ok
- * 2: Slow
- * 3: Beta only
- * */
- status = 1 // will be 3 if unspecified
- tvTypes = listOf(
- "Anime",
- "Movie",
- "AnimeMovie",
- "TvSeries",
- )
- iconUrl = "https://raw.githubusercontent.com/recloudstream/cloudstream-extensions/master/SuperStream/icon.png"
-}
diff --git a/SuperStream/icon.png b/SuperStream/icon.png
deleted file mode 100644
index 2f0c206..0000000
Binary files a/SuperStream/icon.png and /dev/null differ
diff --git a/SuperStream/src/main/AndroidManifest.xml b/SuperStream/src/main/AndroidManifest.xml
deleted file mode 100644
index 29aec9d..0000000
--- a/SuperStream/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/SuperStream/src/main/kotlin/com/lagradost/SuperStream.kt b/SuperStream/src/main/kotlin/com/lagradost/SuperStream.kt
deleted file mode 100644
index 4fb0202..0000000
--- a/SuperStream/src/main/kotlin/com/lagradost/SuperStream.kt
+++ /dev/null
@@ -1,663 +0,0 @@
-package com.lagradost
-
-import android.util.Base64
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.lagradost.SuperStream.CipherUtils.getVerify
-import com.lagradost.cloudstream3.*
-import com.lagradost.cloudstream3.APIHolder.capitalize
-import com.lagradost.cloudstream3.APIHolder.unixTime
-import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId
-import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
-import com.lagradost.cloudstream3.utils.AppUtils.parseJson
-import com.lagradost.cloudstream3.utils.AppUtils.toJson
-import com.lagradost.cloudstream3.utils.ExtractorLink
-import com.lagradost.cloudstream3.utils.getQualityFromName
-import com.lagradost.nicehttp.NiceResponse
-import java.nio.charset.StandardCharsets
-import java.security.MessageDigest
-import java.security.NoSuchAlgorithmException
-import javax.crypto.Cipher
-import javax.crypto.spec.IvParameterSpec
-import javax.crypto.spec.SecretKeySpec
-import kotlin.math.roundToInt
-
-const val TYPE_SERIES = 2
-const val TYPE_MOVIES = 1
-
-class SuperStream : MainAPI() {
- override var name = "SuperStream"
- override val hasMainPage = true
- override val hasChromecastSupport = true
- override val supportedTypes = setOf(
- TvType.Movie,
- TvType.TvSeries,
- TvType.Anime,
- TvType.AnimeMovie,
- )
-
- // 0 to get nsfw
- private val hideNsfw = 1
-
- override val instantLinkLoading = true
-
- val headers = mapOf(
- "Platform" to "android",
- "Accept" to "charset=utf-8",
- )
-
- // Random 32 length string
- private fun randomToken(): String {
- return (0..31).joinToString("") {
- (('0'..'9') + ('a'..'f')).random().toString()
- }
- }
-
- private val token = randomToken()
-
- private object CipherUtils {
- private const val ALGORITHM = "DESede"
- private const val TRANSFORMATION = "DESede/CBC/PKCS5Padding"
- fun encrypt(str: String, key: String, iv: String): String? {
- return try {
- val cipher: Cipher = Cipher.getInstance(TRANSFORMATION)
- val bArr = ByteArray(24)
- val bytes: ByteArray = key.toByteArray()
- var length = if (bytes.size <= 24) bytes.size else 24
- System.arraycopy(bytes, 0, bArr, 0, length)
- while (length < 24) {
- bArr[length] = 0
- length++
- }
- cipher.init(
- 1,
- SecretKeySpec(bArr, ALGORITHM),
- IvParameterSpec(iv.toByteArray())
- )
-
- String(Base64.encode(cipher.doFinal(str.toByteArray()), 2), StandardCharsets.UTF_8)
- } catch (e: Exception) {
- e.printStackTrace()
- null
- }
- }
-
- fun md5(str: String): String? {
- return MD5Util.md5(str)?.let { HexDump.toHexString(it).lowercase() }
- }
-
- fun getVerify(str: String?, str2: String, str3: String): String? {
- if (str != null) {
- return md5(md5(str2) + str3 + str)
- }
- return null
- }
- }
-
- private object HexDump {
- private val HEX_DIGITS = charArrayOf(
- '0',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6',
- '7',
- '8',
- '9',
- 'A',
- 'B',
- 'C',
- 'D',
- 'E',
- 'F'
- )
-
- @JvmOverloads
- fun toHexString(bArr: ByteArray, i: Int = 0, i2: Int = bArr.size): String {
- val cArr = CharArray(i2 * 2)
- var i3 = 0
- for (i4 in i until i + i2) {
- val b = bArr[i4].toInt()
- val i5 = i3 + 1
- val cArr2 = HEX_DIGITS
- cArr[i3] = cArr2[b ushr 4 and 15]
- i3 = i5 + 1
- cArr[i5] = cArr2[b and 15]
- }
- return String(cArr)
- }
- }
-
- private object MD5Util {
- fun md5(str: String): ByteArray? {
- return this.md5(str.toByteArray())
- }
-
- fun md5(bArr: ByteArray?): ByteArray? {
- return try {
- val digest = MessageDigest.getInstance("MD5")
- digest.update(bArr ?: return null)
- digest.digest()
- } catch (e: NoSuchAlgorithmException) {
- e.printStackTrace()
- null
- }
- }
- }
-
- private suspend fun queryApi(query: String): NiceResponse {
- val encryptedQuery = CipherUtils.encrypt(query, key, iv)!!
- val appKeyHash = CipherUtils.md5(appKey)!!
- val newBody =
- """{"app_key":"$appKeyHash","verify":"${
- getVerify(
- encryptedQuery,
- appKey,
- key
- )
- }","encrypt_data":"$encryptedQuery"}"""
- val base64Body = String(Base64.encode(newBody.toByteArray(), Base64.DEFAULT))
-
- val data = mapOf(
- "data" to base64Body,
- "appid" to "27",
- "platform" to "android",
- "version" to "129",
- // Probably best to randomize this
- "medium" to "Website&token$token"
- )
-
- return app.post(apiUrl, headers = headers, data = data)
- }
-
- private suspend inline fun queryApiParsed(query: String): T {
- return queryApi(query).parsed()
- }
-
- private fun getExpiryDate(): Long {
- // Current time + 12 hours
- return unixTime + 60 * 60 * 12
- }
-
- private data class PostJSON(
- @JsonProperty("id") val id: Int? = null,
- @JsonProperty("title") val title: String? = null,
- @JsonProperty("poster") val poster: String? = null,
- @JsonProperty("poster_2") val poster2: String? = null,
- @JsonProperty("box_type") val boxType: Int? = null,
- @JsonProperty("imdb_rating") val imdbRating: String? = null,
- @JsonProperty("quality_tag") val quality_tag: String? = null,
- )
-
- private data class ListJSON(
- @JsonProperty("code") val code: Int? = null,
- @JsonProperty("type") val type: String? = null,
- @JsonProperty("name") val name: String? = null,
- @JsonProperty("box_type") val boxType: Int? = null,
- @JsonProperty("list") val list: ArrayList = arrayListOf(),
- )
-
- private data class DataJSON(
- @JsonProperty("data") val data: ArrayList = arrayListOf()
- )
-
- // We do not want content scanners to notice this scraping going on so we've hidden all constants
- // The source has its origins in China so I added some extra security with banned words
- // Mayhaps a tiny bit unethical, but this source is just too good :)
- // If you are copying this code please use precautions so they do not change their api.
-
- // Free Tibet, The Tienanmen Square protests of 1989
- private val iv = base64Decode("d0VpcGhUbiE=")
- private val key = base64Decode("MTIzZDZjZWRmNjI2ZHk1NDIzM2FhMXc2")
- private val ip = base64Decode("aHR0cHM6Ly8xNTIuMzIuMTQ5LjE2MA==")
- private val apiUrl =
- "$ip${base64Decode("L2FwaS9hcGlfY2xpZW50L2luZGV4Lw==")}"
- private val appKey = base64Decode("bW92aWVib3g=")
- private val appId = base64Decode("Y29tLnRkby5zaG93Ym94")
-
- override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
- val json = queryApi(
- """{"childmode":"$hideNsfw","app_version":"11.5","appid":"$appId","module":"Home_list_type_v2","channel":"Website","page":"$page","lang":"en","type":"all","pagelimit":"10","expired_date":"${getExpiryDate()}","platform":"android"}
- """.trimIndent()
- ).text
-
- // Cut off the first row (featured)
- val pages = parseJson(json).data.let { it.subList(minOf(it.size, 1), it.size) }
- .mapNotNull {
- var name = it.name
- if (name.isNullOrEmpty()) name = "Featured"
- val postList = it.list.mapNotNull second@{ post ->
- val type = if (post.boxType == 1) TvType.Movie else TvType.TvSeries
- newMovieSearchResponse(
- name = post.title ?: return@second null,
- url = LoadData(post.id ?: return@mapNotNull null, post.boxType).toJson(),
- type = type,
- fix = false
- ) {
- posterUrl = post.poster ?: post.poster2
- quality = getQualityFromString(post.quality_tag ?: "")
- }
- }
- if (postList.isEmpty()) return@mapNotNull null
- HomePageList(name, postList)
- }
- return HomePageResponse(pages, hasNext = !pages.any { it.list.isEmpty() })
- }
-
- private data class Data(
- @JsonProperty("id") val id: Int? = null,
- @JsonProperty("box_type") val boxType: Int? = null,
- @JsonProperty("title") val title: String? = null,
- @JsonProperty("poster_org") val posterOrg: String? = null,
- @JsonProperty("poster") val poster: String? = null,
- @JsonProperty("cats") val cats: String? = null,
- @JsonProperty("year") val year: Int? = null,
- @JsonProperty("imdb_rating") val imdbRating: String? = null,
- @JsonProperty("quality_tag") val qualityTag: String? = null,
- )
-
- private data class MainData(
- @JsonProperty("data") val data: ArrayList = arrayListOf()
- )
-
- override suspend fun search(query: String): List {
-
- val apiQuery =
- // Originally 8 pagelimit
- """{"childmode":"$hideNsfw","app_version":"11.5","appid":"$appId","module":"Search3","channel":"Website","page":"1","lang":"en","type":"all","keyword":"$query","pagelimit":"20","expired_date":"${getExpiryDate()}","platform":"android"}"""
- val searchResponse = parseJson(queryApi(apiQuery).text).data.mapNotNull {
- val type = if (it.boxType == 1) TvType.Movie else TvType.TvSeries
- newMovieSearchResponse(
- name = it.title ?: return@mapNotNull null,
- url = LoadData(it.id ?: return@mapNotNull null, it.boxType).toJson(),
- type = type,
- fix = false
- ) {
- posterUrl = it.posterOrg ?: it.poster
- year = it.year
- quality = getQualityFromString(it.qualityTag?.replace("-", "") ?: "")
- }
- }
- return searchResponse
- }
-
- private data class LoadData(
- val id: Int,
- val type: Int?
- )
-
- private data class MovieData(
- @JsonProperty("id") val id: Int? = null,
- @JsonProperty("title") val title: String? = null,
- @JsonProperty("director") val director: String? = null,
- @JsonProperty("writer") val writer: String? = null,
- @JsonProperty("actors") val actors: String? = null,
- @JsonProperty("runtime") val runtime: Int? = null,
- @JsonProperty("poster") val poster: String? = null,
- @JsonProperty("description") val description: String? = null,
- @JsonProperty("cats") val cats: String? = null,
- @JsonProperty("year") val year: Int? = null,
- @JsonProperty("imdb_id") val imdbId: String? = null,
- @JsonProperty("imdb_rating") val imdbRating: String? = null,
- @JsonProperty("trailer") val trailer: String? = null,
- @JsonProperty("released") val released: String? = null,
- @JsonProperty("content_rating") val contentRating: String? = null,
- @JsonProperty("tmdb_id") val tmdbId: Int? = null,
- @JsonProperty("tomato_meter") val tomatoMeter: Int? = null,
- @JsonProperty("poster_org") val posterOrg: String? = null,
- @JsonProperty("trailer_url") val trailerUrl: String? = null,
- @JsonProperty("imdb_link") val imdbLink: String? = null,
- @JsonProperty("box_type") val boxType: Int? = null,
- )
-
- private data class MovieDataProp(
- @JsonProperty("data") val data: MovieData? = MovieData()
- )
-
-
- private data class SeriesDataProp(
- @JsonProperty("code") val code: Int? = null,
- @JsonProperty("msg") val msg: String? = null,
- @JsonProperty("data") val data: SeriesData? = SeriesData()
- )
-
- private data class SeriesSeasonProp(
- @JsonProperty("code") val code: Int? = null,
- @JsonProperty("msg") val msg: String? = null,
- @JsonProperty("data") val data: ArrayList? = arrayListOf()
- )
-// data class PlayProgress (
-//
-// @JsonProperty("over" ) val over : Int? = null,
-// @JsonProperty("seconds" ) val seconds : Int? = null,
-// @JsonProperty("mp4_id" ) val mp4Id : Int? = null,
-// @JsonProperty("last_time" ) val lastTime : Int? = null
-//
-//)
-
- private data class SeriesEpisode(
- @JsonProperty("id") val id: Int? = null,
- @JsonProperty("tid") val tid: Int? = null,
- @JsonProperty("mb_id") val mbId: Int? = null,
- @JsonProperty("imdb_id") val imdbId: String? = null,
- @JsonProperty("imdb_id_status") val imdbIdStatus: Int? = null,
- @JsonProperty("srt_status") val srtStatus: Int? = null,
- @JsonProperty("season") val season: Int? = null,
- @JsonProperty("episode") val episode: Int? = null,
- @JsonProperty("state") val state: Int? = null,
- @JsonProperty("title") val title: String? = null,
- @JsonProperty("thumbs") val thumbs: String? = null,
- @JsonProperty("thumbs_bak") val thumbsBak: String? = null,
- @JsonProperty("thumbs_original") val thumbsOriginal: String? = null,
- @JsonProperty("poster_imdb") val posterImdb: Int? = null,
- @JsonProperty("synopsis") val synopsis: String? = null,
- @JsonProperty("runtime") val runtime: Int? = null,
- @JsonProperty("view") val view: Int? = null,
- @JsonProperty("download") val download: Int? = null,
- @JsonProperty("source_file") val sourceFile: Int? = null,
- @JsonProperty("code_file") val codeFile: Int? = null,
- @JsonProperty("add_time") val addTime: Int? = null,
- @JsonProperty("update_time") val updateTime: Int? = null,
- @JsonProperty("released") val released: String? = null,
- @JsonProperty("released_timestamp") val releasedTimestamp: Long? = null,
- @JsonProperty("audio_lang") val audioLang: String? = null,
- @JsonProperty("quality_tag") val qualityTag: String? = null,
- @JsonProperty("3d") val _3d: Int? = null,
- @JsonProperty("remark") val remark: String? = null,
- @JsonProperty("pending") val pending: String? = null,
- @JsonProperty("imdb_rating") val imdbRating: String? = null,
- @JsonProperty("display") val display: Int? = null,
- @JsonProperty("sync") val sync: Int? = null,
- @JsonProperty("tomato_meter") val tomatoMeter: Int? = null,
- @JsonProperty("tomato_meter_count") val tomatoMeterCount: Int? = null,
- @JsonProperty("tomato_audience") val tomatoAudience: Int? = null,
- @JsonProperty("tomato_audience_count") val tomatoAudienceCount: Int? = null,
- @JsonProperty("thumbs_min") val thumbsMin: String? = null,
- @JsonProperty("thumbs_org") val thumbsOrg: String? = null,
- @JsonProperty("imdb_link") val imdbLink: String? = null,
-// @JsonProperty("quality_tags") val qualityTags: ArrayList = arrayListOf(),
-// @JsonProperty("play_progress" ) val playProgress : PlayProgress? = PlayProgress()
-
- )
-
- private data class SeriesLanguage(
- @JsonProperty("title") val title: String? = null,
- @JsonProperty("lang") val lang: String? = null
- )
-
- private data class SeriesData(
- @JsonProperty("id") val id: Int? = null,
- @JsonProperty("mb_id") val mbId: Int? = null,
- @JsonProperty("title") val title: String? = null,
- @JsonProperty("display") val display: Int? = null,
- @JsonProperty("state") val state: Int? = null,
- @JsonProperty("vip_only") val vipOnly: Int? = null,
- @JsonProperty("code_file") val codeFile: Int? = null,
- @JsonProperty("director") val director: String? = null,
- @JsonProperty("writer") val writer: String? = null,
- @JsonProperty("actors") val actors: String? = null,
- @JsonProperty("add_time") val addTime: Int? = null,
- @JsonProperty("poster") val poster: String? = null,
- @JsonProperty("poster_imdb") val posterImdb: Int? = null,
- @JsonProperty("banner_mini") val bannerMini: String? = null,
- @JsonProperty("description") val description: String? = null,
- @JsonProperty("imdb_id") val imdbId: String? = null,
- @JsonProperty("cats") val cats: String? = null,
- @JsonProperty("year") val year: Int? = null,
- @JsonProperty("collect") val collect: Int? = null,
- @JsonProperty("view") val view: Int? = null,
- @JsonProperty("download") val download: Int? = null,
- @JsonProperty("update_time") val updateTime: String? = null,
- @JsonProperty("released") val released: String? = null,
- @JsonProperty("released_timestamp") val releasedTimestamp: Int? = null,
- @JsonProperty("episode_released") val episodeReleased: String? = null,
- @JsonProperty("episode_released_timestamp") val episodeReleasedTimestamp: Int? = null,
- @JsonProperty("max_season") val maxSeason: Int? = null,
- @JsonProperty("max_episode") val maxEpisode: Int? = null,
- @JsonProperty("remark") val remark: String? = null,
- @JsonProperty("imdb_rating") val imdbRating: String? = null,
- @JsonProperty("content_rating") val contentRating: String? = null,
- @JsonProperty("tmdb_id") val tmdbId: Int? = null,
- @JsonProperty("tomato_url") val tomatoUrl: String? = null,
- @JsonProperty("tomato_meter") val tomatoMeter: Int? = null,
- @JsonProperty("tomato_meter_count") val tomatoMeterCount: Int? = null,
- @JsonProperty("tomato_meter_state") val tomatoMeterState: String? = null,
- @JsonProperty("reelgood_url") val reelgoodUrl: String? = null,
- @JsonProperty("audience_score") val audienceScore: Int? = null,
- @JsonProperty("audience_score_count") val audienceScoreCount: Int? = null,
- @JsonProperty("no_tomato_url") val noTomatoUrl: Int? = null,
- @JsonProperty("order_year") val orderYear: Int? = null,
- @JsonProperty("episodate_id") val episodateId: String? = null,
- @JsonProperty("weights_day") val weightsDay: Double? = null,
- @JsonProperty("poster_min") val posterMin: String? = null,
- @JsonProperty("poster_org") val posterOrg: String? = null,
- @JsonProperty("banner_mini_min") val bannerMiniMin: String? = null,
- @JsonProperty("banner_mini_org") val bannerMiniOrg: String? = null,
- @JsonProperty("trailer_url") val trailerUrl: String? = null,
- @JsonProperty("years") val years: ArrayList = arrayListOf(),
- @JsonProperty("season") val season: ArrayList = arrayListOf(),
- @JsonProperty("history") val history: ArrayList = arrayListOf(),
- @JsonProperty("imdb_link") val imdbLink: String? = null,
- @JsonProperty("episode") val episode: ArrayList = arrayListOf(),
-// @JsonProperty("is_collect") val isCollect: Int? = null,
- @JsonProperty("language") val language: ArrayList = arrayListOf(),
- @JsonProperty("box_type") val boxType: Int? = null,
- @JsonProperty("year_year") val yearYear: String? = null,
- @JsonProperty("season_episode") val seasonEpisode: String? = null
- )
-
-
- override suspend fun load(url: String): LoadResponse {
- val loadData = parseJson(url)
- // val module = if(type === "TvType.Movie") "Movie_detail" else "*tv series module*"
-
- val isMovie = loadData.type == TYPE_MOVIES
-
- if (isMovie) { // 1 = Movie
- val apiQuery =
- """{"childmode":"$hideNsfw","uid":"","app_version":"11.5","appid":"$appId","module":"Movie_detail","channel":"Website","mid":"${loadData.id}","lang":"en","expired_date":"${getExpiryDate()}","platform":"android","oss":"","group":""}"""
- val data = (queryApiParsed(apiQuery)).data
- ?: throw RuntimeException("API error")
-
- return newMovieLoadResponse(
- data.title ?: "",
- url,
- TvType.Movie,
- LinkData(
- data.id ?: throw RuntimeException("No movie ID"),
- TYPE_MOVIES,
- null,
- null
- ),
- ) {
- this.posterUrl = data.posterOrg ?: data.poster
- this.year = data.year
- this.plot = data.description
- this.tags = data.cats?.split(",")?.map { it.capitalize() }
- this.rating = data.imdbRating?.split("/")?.get(0)?.toIntOrNull()
- addTrailer(data.trailerUrl)
- this.addImdbId(data.imdbId)
- }
- } else { // 2 Series
- val apiQuery =
- """{"childmode":"$hideNsfw","uid":"","app_version":"11.5","appid":"$appId","module":"TV_detail_1","display_all":"1","channel":"Website","lang":"en","expired_date":"${getExpiryDate()}","platform":"android","tid":"${loadData.id}"}"""
- val data = (queryApiParsed(apiQuery)).data
- ?: throw RuntimeException("API error")
-
- val episodes = data.season.mapNotNull {
- val seasonQuery =
- """{"childmode":"$hideNsfw","app_version":"11.5","year":"0","appid":"$appId","module":"TV_episode","display_all":"1","channel":"Website","season":"$it","lang":"en","expired_date":"${getExpiryDate()}","platform":"android","tid":"${loadData.id}"}"""
- (queryApiParsed(seasonQuery)).data
- }.flatten()
-
- return newTvSeriesLoadResponse(
- data.title ?: "",
- url,
- TvType.TvSeries,
- episodes.mapNotNull {
- Episode(
- LinkData(
- it.tid ?: it.id ?: return@mapNotNull null,
- TYPE_SERIES,
- it.season,
- it.episode
- ).toJson(),
- it.title,
- it.season,
- it.episode,
- it.thumbs ?: it.thumbsBak ?: it.thumbsMin ?: it.thumbsOriginal
- ?: it.thumbsOrg,
- it.imdbRating?.toDoubleOrNull()?.times(10)?.roundToInt(),
- it.synopsis,
- it.releasedTimestamp
- )
- }
- ) {
- this.year = data.year
- this.plot = data.description
- this.posterUrl = data.posterOrg ?: data.poster
- this.rating = data.imdbRating?.split("/")?.get(0)?.toIntOrNull()
- this.tags = data.cats?.split(",")?.map { it.capitalize() }
- this.addImdbId(data.imdbId)
- }
- }
- }
-
-
- private data class LinkData(
- val id: Int,
- val type: Int,
- val season: Int?,
- val episode: Int?
- )
-
-
- private data class LinkDataProp(
- @JsonProperty("code") val code: Int? = null,
- @JsonProperty("msg") val msg: String? = null,
- @JsonProperty("data") val data: ParsedLinkData? = ParsedLinkData()
- )
-
- private data class LinkList(
- @JsonProperty("path") val path: String? = null,
- @JsonProperty("quality") val quality: String? = null,
- @JsonProperty("real_quality") val realQuality: String? = null,
- @JsonProperty("format") val format: String? = null,
- @JsonProperty("size") val size: String? = null,
- @JsonProperty("size_bytes") val sizeBytes: Long? = null,
- @JsonProperty("count") val count: Int? = null,
- @JsonProperty("dateline") val dateline: Long? = null,
- @JsonProperty("fid") val fid: Int? = null,
- @JsonProperty("mmfid") val mmfid: Int? = null,
- @JsonProperty("h265") val h265: Int? = null,
- @JsonProperty("hdr") val hdr: Int? = null,
- @JsonProperty("filename") val filename: String? = null,
- @JsonProperty("original") val original: Int? = null,
- @JsonProperty("colorbit") val colorbit: Int? = null,
- @JsonProperty("success") val success: Int? = null,
- @JsonProperty("timeout") val timeout: Int? = null,
- @JsonProperty("vip_link") val vipLink: Int? = null,
- @JsonProperty("fps") val fps: Int? = null,
- @JsonProperty("bitstream") val bitstream: String? = null,
- @JsonProperty("width") val width: Int? = null,
- @JsonProperty("height") val height: Int? = null
- )
-
- private data class ParsedLinkData(
- @JsonProperty("seconds") val seconds: Int? = null,
- @JsonProperty("quality") val quality: ArrayList = arrayListOf(),
- @JsonProperty("list") val list: ArrayList = arrayListOf()
- )
-
- private data class SubtitleDataProp(
- @JsonProperty("code") val code: Int? = null,
- @JsonProperty("msg") val msg: String? = null,
- @JsonProperty("data") val data: PrivateSubtitleData? = PrivateSubtitleData()
- )
-
- private data class Subtitles(
- @JsonProperty("sid") val sid: Int? = null,
- @JsonProperty("mid") val mid: String? = null,
- @JsonProperty("file_path") val filePath: String? = null,
- @JsonProperty("lang") val lang: String? = null,
- @JsonProperty("language") val language: String? = null,
- @JsonProperty("delay") val delay: Int? = null,
- @JsonProperty("point") val point: String? = null,
- @JsonProperty("order") val order: Int? = null,
- @JsonProperty("admin_order") val adminOrder: Int? = null,
- @JsonProperty("myselect") val myselect: Int? = null,
- @JsonProperty("add_time") val addTime: Long? = null,
- @JsonProperty("count") val count: Int? = null
- )
-
- private data class SubtitleList(
-
- @JsonProperty("language") val language: String? = null,
- @JsonProperty("subtitles") val subtitles: ArrayList = arrayListOf()
-
- )
-
- private data class PrivateSubtitleData(
- @JsonProperty("select") val select: ArrayList = arrayListOf(),
- @JsonProperty("list") val list: ArrayList = arrayListOf()
- )
-
- override suspend fun loadLinks(
- data: String,
- isCasting: Boolean,
- subtitleCallback: (SubtitleFile) -> Unit,
- callback: (ExtractorLink) -> Unit
- ): Boolean {
- fun LinkList.toExtractorLink(): ExtractorLink? {
- return ExtractorLink(
- this@SuperStream.name,
- this.filename ?: "",
- this.path?.replace("\\/", "") ?: return null,
- "",
- getQualityFromName(this.quality),
- )
- }
-
- fun Subtitles.toSubtitleFile(): SubtitleFile? {
- return SubtitleFile(
- this.language ?: this.lang ?: "",
- this.filePath ?: return null
- )
- }
-
- val parsed = parseJson(data)
-
- // No childmode when getting links
- val query = if (parsed.type == TYPE_MOVIES) {
- """{"childmode":"0","uid":"","app_version":"11.5","appid":"$appId","module":"Movie_downloadurl_v3","channel":"Website","mid":"${parsed.id}","lang":"","expired_date":"${getExpiryDate()}","platform":"android","oss":"1","group":""}"""
- } else {
- val episode = parsed.episode ?: throw RuntimeException("No episode number!")
- val season = parsed.season ?: throw RuntimeException("No season number!")
- """{"childmode":"0","app_version":"11.5","module":"TV_downloadurl_v3","channel":"Website","episode":"$episode","expired_date":"${getExpiryDate()}","platform":"android","tid":"${parsed.id}","oss":"1","uid":"","appid":"$appId","season":"$season","lang":"en","group":""}"""
- }
-
- val linkData = queryApiParsed(query)
- linkData.data?.list?.forEach {
- callback.invoke(it.toExtractorLink() ?: return@forEach)
- }
-
- // Should really run this query for every link :(
- val fid = linkData.data?.list?.firstOrNull { it.fid != null }?.fid
-
- val subtitleQuery = if (parsed.type == TYPE_MOVIES) {
- """{"childmode":"0","fid":"$fid","uid":"","app_version":"11.5","appid":"$appId","module":"Movie_srt_list_v2","channel":"Website","mid":"${parsed.id}","lang":"en","expired_date":"${getExpiryDate()}","platform":"android"}"""
- } else {
- """{"childmode":"0","fid":"$fid","app_version":"11.5","module":"TV_srt_list_v2","channel":"Website","episode":"${parsed.episode}","expired_date":"${getExpiryDate()}","platform":"android","tid":"${parsed.id}","uid":"","appid":"$appId","season":"${parsed.season}","lang":"en"}"""
- }
-
- val subtitles = queryApiParsed(subtitleQuery).data
- subtitles?.list?.forEach {
- it.subtitles.forEach second@{ sub ->
- subtitleCallback.invoke(sub.toSubtitleFile() ?: return@second)
- }
- }
-
- return true
- }
-}
\ No newline at end of file
diff --git a/SuperStream/src/main/kotlin/com/lagradost/SuperStreamPlugin.kt b/SuperStream/src/main/kotlin/com/lagradost/SuperStreamPlugin.kt
deleted file mode 100644
index 7297a79..0000000
--- a/SuperStream/src/main/kotlin/com/lagradost/SuperStreamPlugin.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package com.lagradost
-
-import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
-import com.lagradost.cloudstream3.plugins.Plugin
-import android.content.Context
-
-@CloudstreamPlugin
-class SuperStreamPlugin: Plugin() {
- override fun load(context: Context) {
- // All providers should be added in this manner. Please don't edit the providers list directly.
- registerMainAPI(SuperStream())
- }
-}
\ No newline at end of file
diff --git a/TenshiProvider/build.gradle.kts b/TenshiProvider/build.gradle.kts
deleted file mode 100644
index d958ae3..0000000
--- a/TenshiProvider/build.gradle.kts
+++ /dev/null
@@ -1,27 +0,0 @@
-// use an integer for version numbers
-version = 1
-
-
-cloudstream {
- // All of these properties are optional, you can safely remove them
-
- // description = "Lorem Ipsum"
- // authors = listOf("Cloudburst")
-
- /**
- * Status int as the following:
- * 0: Down
- * 1: Ok
- * 2: Slow
- * 3: Beta only
- * */
- status = 1 // will be 3 if unspecified
- tvTypes = listOf(
- "AnimeMovie",
- "Anime",
- "Movie",
- "OVA",
- )
-
- iconUrl = "https://www.google.com/s2/favicons?domain=tenshi.moe&sz=24"
-}
\ No newline at end of file
diff --git a/TenshiProvider/src/main/AndroidManifest.xml b/TenshiProvider/src/main/AndroidManifest.xml
deleted file mode 100644
index 29aec9d..0000000
--- a/TenshiProvider/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TenshiProvider/src/main/kotlin/com/lagradost/TenshiProvider.kt b/TenshiProvider/src/main/kotlin/com/lagradost/TenshiProvider.kt
deleted file mode 100644
index 1fcf6a3..0000000
--- a/TenshiProvider/src/main/kotlin/com/lagradost/TenshiProvider.kt
+++ /dev/null
@@ -1,352 +0,0 @@
-package com.lagradost
-
-import android.annotation.SuppressLint
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.lagradost.cloudstream3.*
-import com.lagradost.cloudstream3.network.DdosGuardKiller
-import com.lagradost.cloudstream3.network.getHeaders
-import com.lagradost.cloudstream3.utils.AppUtils.parseJson
-import com.lagradost.cloudstream3.utils.ExtractorLink
-import com.lagradost.cloudstream3.utils.getQualityFromName
-import org.jsoup.nodes.Document
-import java.net.URI
-import java.text.SimpleDateFormat
-import java.util.*
-
-class TenshiProvider : MainAPI() {
- companion object {
- //var token: String? = null
- //var cookie: Map = mapOf()
-
- fun getType(t: String): TvType {
- return if (t.contains("OVA") || t.contains("Special")) TvType.OVA
- else if (t.contains("Movie")) TvType.AnimeMovie
- else TvType.Anime
- }
- }
-
- override var mainUrl = "https://tenshi.moe"
- override var name = "Tenshi.moe"
- override val hasQuickSearch = false
- override val hasMainPage = true
- override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie, TvType.OVA)
- private var ddosGuardKiller = DdosGuardKiller(true)
-
- /*private fun loadToken(): Boolean {
- return try {
- val response = get(mainUrl)
- cookie = response.cookies
- val document = Jsoup.parse(response.text)
- token = document.selectFirst("""meta[name="csrf-token"]""").attr("content")
- token != null
- } catch (e: Exception) {
- false
- }
- }*/
-
- override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
- val items = ArrayList()
- val soup = app.get(mainUrl, interceptor = ddosGuardKiller).document
- for (section in soup.select("#content > section")) {
- try {
- if (section.attr("id") == "toplist-tabs") {
- for (top in section.select(".tab-content > [role=\"tabpanel\"]")) {
- val title = "Top - " + top.attr("id").split("-")[1].replaceFirstChar {
- if (it.isLowerCase()) it.titlecase(
- Locale.UK
- ) else it.toString()
- }
- val anime = top.select("li > a").map {
- AnimeSearchResponse(
- it.selectFirst(".thumb-title")!!.text(),
- fixUrl(it.attr("href")),
- this.name,
- TvType.Anime,
- it.selectFirst("img")!!.attr("src"),
- null,
- EnumSet.of(DubStatus.Subbed),
- )
- }
- items.add(HomePageList(title, anime))
- }
- } else {
- val title = section.selectFirst("h2")!!.text()
- val anime = section.select("li > a").map {
- AnimeSearchResponse(
- it.selectFirst(".thumb-title")?.text() ?: "",
- fixUrl(it.attr("href")),
- this.name,
- TvType.Anime,
- it.selectFirst("img")!!.attr("src"),
- null,
- EnumSet.of(DubStatus.Subbed),
- )
- }
- items.add(HomePageList(title, anime))
- }
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- if (items.size <= 0) throw ErrorLoadingException()
- return HomePageResponse(items)
- }
-
- private fun getIsMovie(type: String, id: Boolean = false): Boolean {
- if (!id) return type == "Movie"
-
- val movies = listOf("rrso24fa", "e4hqvtym", "bl5jdbqn", "u4vtznut", "37t6h2r4", "cq4azcrj")
- val aniId = type.replace("$mainUrl/anime/", "")
- return movies.contains(aniId)
- }
-
- private fun parseSearchPage(soup: Document): List {
- val items = soup.select("ul.thumb > li > a")
- return items.map {
- val href = fixUrl(it.attr("href"))
- val img = fixUrl(it.selectFirst("img")!!.attr("src"))
- val title = it.attr("title")
- if (getIsMovie(href, true)) {
- MovieSearchResponse(
- title, href, this.name, TvType.Movie, img, null
- )
- } else {
- AnimeSearchResponse(
- title,
- href,
- this.name,
- TvType.Anime,
- img,
- null,
- EnumSet.of(DubStatus.Subbed),
- )
- }
- }
- }
-
- @SuppressLint("SimpleDateFormat")
- private fun dateParser(dateString: String?): Date? {
- if (dateString == null) return null
- try {
- val format = SimpleDateFormat("dd 'of' MMM',' yyyy")
- val data = format.parse(
- dateString.replace("th ", " ").replace("st ", " ").replace("nd ", " ")
- .replace("rd ", " ")
- ) ?: return null
- return data
- } catch (e: Exception) {
- return null
- }
- }
-
-// data class TenshiSearchResponse(
-// @JsonProperty("url") var url : String,
-// @JsonProperty("title") var title : String,
-// @JsonProperty("cover") var cover : String,
-// @JsonProperty("genre") var genre : String,
-// @JsonProperty("year") var year : Int,
-// @JsonProperty("type") var type : String,
-// @JsonProperty("eps") var eps : String,
-// @JsonProperty("cen") var cen : String
-// )
-
-// override suspend fun quickSearch(query: String): ArrayList? {
-// if (!autoLoadToken()) return quickSearch(query)
-// val url = "$mainUrl/anime/search"
-// val response = khttp.post(
-// url,
-// data=mapOf("q" to query),
-// headers=mapOf("x-csrf-token" to token, "x-requested-with" to "XMLHttpRequest"),
-// cookies = cookie
-//
-// )
-//
-// val items = mapper.readValue>(response.text)
-//
-// if (items.isEmpty()) return ArrayList()
-//
-// val returnValue = ArrayList()
-// for (i in items) {
-// val href = fixUrl(i.url)
-// val title = i.title
-// val img = fixUrl(i.cover)
-// val year = i.year
-//
-// returnValue.add(
-// if (getIsMovie(i.type)) {
-// MovieSearchResponse(
-// title, href, getSlug(href), this.name, TvType.Movie, img, year
-// )
-// } else {
-// AnimeSearchResponse(
-// title, href, getSlug(href), this.name,
-// TvType.Anime, img, year, null,
-// EnumSet.of(DubStatus.Subbed),
-// null, null
-// )
-// }
-// )
-// }
-// return returnValue
-// }
-
- override suspend fun search(query: String): List {
- val url = "$mainUrl/anime"
- var document = app.get(
- url,
- params = mapOf("q" to query),
- cookies = mapOf("loop-view" to "thumb"),
- interceptor = ddosGuardKiller
- ).document
-
- val returnValue = parseSearchPage(document).toMutableList()
-
- while (!document.select("""a.page-link[rel="next"]""").isEmpty()) {
- val link = document.selectFirst("""a.page-link[rel="next"]""")?.attr("href")
- if (!link.isNullOrBlank()) {
- document = app.get(
- link,
- cookies = mapOf("loop-view" to "thumb"),
- interceptor = ddosGuardKiller
- ).document
- returnValue.addAll(parseSearchPage(document))
- } else {
- break
- }
- }
-
- return returnValue
- }
-
- override suspend fun load(url: String): LoadResponse {
- var document = app.get(
- url,
- cookies = mapOf("loop-view" to "thumb"),
- interceptor = ddosGuardKiller
- ).document
-
- val canonicalTitle = document.selectFirst("header.entry-header > h1.mb-3")!!.text().trim()
- val episodeNodes = document.select("li[class*=\"episode\"] > a").toMutableList()
- val totalEpisodePages = if (document.select(".pagination").size > 0)
- document.select(".pagination .page-item a.page-link:not([rel])").last()!!.text()
- .toIntOrNull()
- else 1
-
- if (totalEpisodePages != null && totalEpisodePages > 1) {
- for (pageNum in 2..totalEpisodePages) {
- document = app.get(
- "$url?page=$pageNum",
- cookies = mapOf("loop-view" to "thumb"),
- interceptor = ddosGuardKiller
- ).document
- episodeNodes.addAll(document.select("li[class*=\"episode\"] > a"))
- }
- }
-
- val episodes = ArrayList(episodeNodes.map {
- val title = it.selectFirst(".episode-title")?.text()?.trim()
- newEpisode(it.attr("href")) {
- this.name = if (title == "No Title") null else title
- this.posterUrl = it.selectFirst("img")?.attr("src")
- addDate(dateParser(it?.selectFirst(".episode-date")?.text()?.trim()))
- this.description = it.attr("data-content").trim()
- }
- })
-
- val similarAnime = document.select("ul.anime-loop > li > a").mapNotNull { element ->
- val href = element.attr("href") ?: return@mapNotNull null
- val title =
- element.selectFirst("> .overlay > .thumb-title")?.text() ?: return@mapNotNull null
- val img = element.selectFirst("> img")?.attr("src")
- AnimeSearchResponse(title, href, this.name, TvType.Anime, img)
- }
-
- val type = document.selectFirst("a[href*=\"$mainUrl/type/\"]")?.text()?.trim()
-
- return newAnimeLoadResponse(canonicalTitle, url, getType(type ?: "")) {
- recommendations = similarAnime
- posterUrl = document.selectFirst("img.cover-image")?.attr("src")
- plot = document.selectFirst(".entry-description > .card-body")?.text()?.trim()
- tags =
- document.select("li.genre.meta-data > span.value")
- .map { it?.text()?.trim().toString() }
-
- synonyms =
- document.select("li.synonym.meta-data > div.info-box > span.value")
- .map { it?.text()?.trim().toString() }
-
- engName =
- document.selectFirst("span.value > span[title=\"English\"]")?.parent()?.text()
- ?.trim()
- japName =
- document.selectFirst("span.value > span[title=\"Japanese\"]")?.parent()?.text()
- ?.trim()
-
- val pattern = Regex("(\\d{4})")
- val yearText = document.selectFirst("li.release-date .value")!!.text()
- year = pattern.find(yearText)?.groupValues?.get(1)?.toIntOrNull()
-
- addEpisodes(DubStatus.Subbed, episodes)
-
- showStatus = when (document.selectFirst("li.status > .value")?.text()?.trim()) {
- "Ongoing" -> ShowStatus.Ongoing
- "Completed" -> ShowStatus.Completed
- else -> null
- }
- }
- }
-
-
- override suspend fun loadLinks(
- data: String,
- isCasting: Boolean,
- subtitleCallback: (SubtitleFile) -> Unit,
- callback: (ExtractorLink) -> Unit
- ): Boolean {
- val soup = app.get(data, interceptor = ddosGuardKiller).document
-
- data class Quality(
- @JsonProperty("src") val src: String,
- @JsonProperty("size") val size: Int
- )
-
- for (source in soup.select("""[aria-labelledby="mirror-dropdown"] > li > a.dropdown-item""")) {
- val release = source.text().replace("/", "").trim()
- val sourceHTML = app.get(
- "https://tenshi.moe/embed?v=${source.attr("href").split("v=")[1].split("&")[0]}",
- headers = mapOf("Referer" to data), interceptor = ddosGuardKiller
- ).text
-
- val match = Regex("""sources: (\[(?:.|\s)+?type: ['"]video/.*?['"](?:.|\s)+?])""").find(
- sourceHTML
- )
- if (match != null) {
- val qualities = parseJson>(
- match.destructured.component1()
- .replace("'", "\"")
- .replace(Regex("""(\w+): """), "\"\$1\": ")
- .replace(Regex("""\s+"""), "")
- .replace(",}", "}")
- .replace(",]", "]")
- )
- qualities.forEach {
- callback.invoke(
- ExtractorLink(
- this.name,
- "${this.name} $release",
- fixUrl(it.src),
- this.mainUrl,
- getQualityFromName("${it.size}"),
- headers = getHeaders(emptyMap(),
- ddosGuardKiller.savedCookiesMap[URI(this.mainUrl).host]
- ?: emptyMap()
- ).toMap()
- )
- )
- }
- }
- }
-
- return true
- }
-}
diff --git a/TenshiProvider/src/main/kotlin/com/lagradost/TenshiProviderPlugin.kt b/TenshiProvider/src/main/kotlin/com/lagradost/TenshiProviderPlugin.kt
deleted file mode 100644
index 5961ef9..0000000
--- a/TenshiProvider/src/main/kotlin/com/lagradost/TenshiProviderPlugin.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package com.lagradost
-
-import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
-import com.lagradost.cloudstream3.plugins.Plugin
-import android.content.Context
-
-@CloudstreamPlugin
-class TenshiProviderPlugin: Plugin() {
- override fun load(context: Context) {
- // All providers should be added in this manner. Please don't edit the providers list directly.
- registerMainAPI(TenshiProvider())
- }
-}
\ No newline at end of file
diff --git a/TheFlixToProvider/build.gradle.kts b/TheFlixToProvider/build.gradle.kts
deleted file mode 100644
index defd7e1..0000000
--- a/TheFlixToProvider/build.gradle.kts
+++ /dev/null
@@ -1,25 +0,0 @@
-// use an integer for version numbers
-version = 1
-
-
-cloudstream {
- // All of these properties are optional, you can safely remove them
-
- // description = "Lorem Ipsum"
- // authors = listOf("Cloudburst")
-
- /**
- * Status int as the following:
- * 0: Down
- * 1: Ok
- * 2: Slow
- * 3: Beta only
- * */
- status = 1 // will be 3 if unspecified
- tvTypes = listOf(
- "TvSeries",
- "Movie",
- )
-
- iconUrl = "https://www.google.com/s2/favicons?domain=theflix.to&sz=24"
-}
\ No newline at end of file
diff --git a/TheFlixToProvider/src/main/AndroidManifest.xml b/TheFlixToProvider/src/main/AndroidManifest.xml
deleted file mode 100644
index 29aec9d..0000000
--- a/TheFlixToProvider/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TheFlixToProvider/src/main/kotlin/com/lagradost/TheFlixToProvider.kt b/TheFlixToProvider/src/main/kotlin/com/lagradost/TheFlixToProvider.kt
deleted file mode 100644
index 84e0876..0000000
--- a/TheFlixToProvider/src/main/kotlin/com/lagradost/TheFlixToProvider.kt
+++ /dev/null
@@ -1,604 +0,0 @@
-package com.lagradost
-
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.lagradost.cloudstream3.*
-import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
-import com.lagradost.cloudstream3.network.cookies
-import com.lagradost.cloudstream3.utils.AppUtils.parseJson
-import com.lagradost.cloudstream3.utils.ExtractorLink
-import com.lagradost.cloudstream3.utils.getQualityFromName
-
-
-class TheFlixToProvider : MainAPI() {
- companion object {
- var latestCookies: Map = emptyMap()
- }
-
- override var name = "TheFlix.to"
- override var mainUrl = "https://theflix.to"
- override val instantLinkLoading = false
- override val hasMainPage = true
- override val supportedTypes = setOf(
- TvType.Movie,
- TvType.TvSeries,
- )
-
-
-
- data class HomeJson(
- @JsonProperty("props") val props: HomeProps = HomeProps(),
- )
-
- data class HomeProps(
- @JsonProperty("pageProps") val pageProps: PageProps = PageProps(),
- )
-
- data class PageProps(
- @JsonProperty("moviesListTrending") val moviesListTrending: MoviesListTrending = MoviesListTrending(),
- @JsonProperty("moviesListNewArrivals") val moviesListNewArrivals: MoviesListNewArrivals = MoviesListNewArrivals(),
- @JsonProperty("tvsListTrending") val tvsListTrending: TvsListTrending = TvsListTrending(),
- @JsonProperty("tvsListNewEpisodes") val tvsListNewEpisodes: TvsListNewEpisodes = TvsListNewEpisodes(),
- )
-
-
- data class MoviesListTrending(
- @JsonProperty("docs") val docs: ArrayList = arrayListOf(),
- @JsonProperty("total") val total: Int? = null,
- @JsonProperty("page") val page: Int? = null,
- @JsonProperty("limit") val limit: Int? = null,
- @JsonProperty("pages") val pages: Int? = null,
- @JsonProperty("type") val type: String? = null,
- )
-
- data class MoviesListNewArrivals(
- @JsonProperty("docs") val docs: ArrayList = arrayListOf(),
- @JsonProperty("total") val total: Int? = null,
- @JsonProperty("page") val page: Int? = null,
- @JsonProperty("limit") val limit: Int? = null,
- @JsonProperty("pages") val pages: Int? = null,
- @JsonProperty("type") val type: String? = null,
- )
-
- data class TvsListTrending(
- @JsonProperty("docs") val docs: ArrayList = arrayListOf(),
- @JsonProperty("total") val total: Int? = null,
- @JsonProperty("page") val page: Int? = null,
- @JsonProperty("limit") val limit: Int? = null,
- @JsonProperty("pages") val pages: Int? = null,
- @JsonProperty("type") val type: String? = null,
- )
-
- data class TvsListNewEpisodes(
- @JsonProperty("docs") val docs: ArrayList = arrayListOf(),
- @JsonProperty("total") val total: Int? = null,
- @JsonProperty("page") val page: Int? = null,
- @JsonProperty("limit") val limit: Int? = null,
- @JsonProperty("pages") val pages: Int? = null,
- @JsonProperty("type") val type: String? = null,
- )
-
- data class Docs(
- @JsonProperty("name") val name: String = String(),
- @JsonProperty("originalLanguage") val originalLanguage: String? = null,
- @JsonProperty("popularity") val popularity: Double? = null,
- @JsonProperty("runtime") val runtime: Int? = null,
- @JsonProperty("status") val status: String? = null,
- @JsonProperty("voteAverage") val voteAverage: Double? = null,
- @JsonProperty("voteCount") val voteCount: Int? = null,
- @JsonProperty("cast") val cast: String? = null,
- @JsonProperty("director") val director: String? = null,
- @JsonProperty("overview") val overview: String? = null,
- @JsonProperty("posterUrl") val posterUrl: String? = null,
- @JsonProperty("releaseDate") val releaseDate: String? = null,
- @JsonProperty("createdAt") val createdAt: String? = null,
- @JsonProperty("updatedAt") val updatedAt: String? = null,
- @JsonProperty("conversionDate") val conversionDate: String? = null,
- @JsonProperty("id") val id: Int? = null,
- @JsonProperty("available") val available: Boolean? = null,
- @JsonProperty("videos" ) val videos : ArrayList? = arrayListOf(),
- )
-
-
- private suspend fun getCookies(): Map {
- // val cookieResponse = app.post(
- // "https://theflix.to:5679/authorization/session/continue?contentUsageType=Viewing",
- // headers = mapOf(
- // "Host" to "theflix.to:5679",
- // "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0",
- // "Accept" to "application/json, text/plain,"
- // "Accept-Language" to "en-US,en;q=0.5",
- // "Content-Type" to "application/json;charset=utf-8",
- // "Content-Length" to "35",
- // "Origin" to "https://theflix.to",
- // "DNT" to "1",
- // "Connection" to "keep-alive",
- // "Referer" to "https://theflix.to/",
- // "Sec-Fetch-Dest" to "empty",
- // "Sec-Fetch-Mode" to "cors",
- // "Sec-Fetch-Site" to "same-site",)).okhttpResponse.headers.values("Set-Cookie")
-
- val cookies = app.post(
- "$mainUrl:5679/authorization/session/continue?contentUsageType=Viewing",
- headers = mapOf(
- "Host" to "theflix.to:5679",
- "User-Agent" to USER_AGENT,
- "Accept" to "application/json, text/plain, */*",
- "Accept-Language" to "en-US,en;q=0.5",
- "Content-Type" to "application/json;charset=utf-8",
- "Content-Length" to "35",
- "Origin" to mainUrl,
- "DNT" to "1",
- "Connection" to "keep-alive",
- "Referer" to mainUrl,
- "Sec-Fetch-Dest" to "empty",
- "Sec-Fetch-Mode" to "cors",
- "Sec-Fetch-Site" to "same-site",)
- ).cookies
- /* val cookieRegex = Regex("(theflix\\..*?id\\=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
- val findcookie = cookieRegex.findAll(cookieResponse.toString()).map { it.value }.toList()
- val cookiesstring = findcookie.toString().replace(", ","; ").replace("[","").replace("]","")
- val cookiesmap = mapOf("Cookie" to cookiesstring) */
- latestCookies = cookies
- return latestCookies
- }
-
-
- override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse {
- val items = ArrayList()
- val doc = app.get(mainUrl).document
- val scriptText = doc.selectFirst("script[type=application/json]")!!.data()
- if (scriptText.contains("moviesListTrending")) {
- val json = parseJson(scriptText)
- val homePageProps = json.props.pageProps
- listOf(
- Triple(
- homePageProps.moviesListNewArrivals.docs,
- homePageProps.moviesListNewArrivals.type,
- "New Movie arrivals"
- ),
- Triple(
- homePageProps.moviesListTrending.docs,
- homePageProps.moviesListTrending.type,
- "Trending Movies"
- ),
- Triple(
- homePageProps.tvsListTrending.docs,
- homePageProps.tvsListTrending.type,
- "Trending TV Series"
- ),
- Triple(
- homePageProps.tvsListNewEpisodes.docs,
- homePageProps.tvsListNewEpisodes.type,
- "New Episodes"
- )
- ).map { (docs, type, homename) ->
- val home = docs.map { info ->
- val title = info.name
- val poster = info.posterUrl
- val typeinfo =
- if (type?.contains("TV") == true) TvType.TvSeries else TvType.Movie
- val link =
- if (typeinfo == TvType.Movie) "$mainUrl/movie/${info.id}-${cleanTitle(title)}"
- else "$mainUrl/tv-show/${info.id}-${cleanTitle(title).replace("?","")}/season-1/episode-1"
- TvSeriesSearchResponse(
- title,
- link,
- this.name,
- typeinfo,
- poster,
- null,
- null,
- )
- }
- items.add(HomePageList(homename, home))
- }
-
- }
-
- if (items.size <= 0) throw ErrorLoadingException()
- return HomePageResponse(items)
- }
-
- data class SearchJson(
- @JsonProperty("props") val props: SearchProps = SearchProps(),
- )
-
- data class SearchProps(
- @JsonProperty("pageProps") val pageProps: SearchPageProps = SearchPageProps(),
- )
-
- data class SearchPageProps(
- @JsonProperty("mainList") val mainList: SearchMainList = SearchMainList(),
- )
-
- data class SearchMainList(
- @JsonProperty("docs") val docs: ArrayList = arrayListOf(),
- @JsonProperty("total") val total: Int? = null,
- @JsonProperty("page") val page: Int? = null,
- @JsonProperty("limit") val limit: Int? = null,
- @JsonProperty("pages") val pages: Int? = null,
- @JsonProperty("type") val type: String? = null,
- )
-
-
- override suspend fun search(query: String): List {
- val search = ArrayList()
- val urls = listOf(
- "$mainUrl/movies/trending?search=$query",
- "$mainUrl/tv-shows/trending?search=$query"
- )
- urls.apmap { url ->
- val doc = app.get(url).document
- val scriptText = doc.selectFirst("script[type=application/json]")!!.data()
- if (scriptText.contains("pageProps")) {
- val json = parseJson(scriptText)
- val searchPageProps = json.props.pageProps.mainList
- val pair = listOf(Pair(searchPageProps.docs, searchPageProps.type))
- pair.map { (docs, type) ->
- docs.map { info ->
- val title = info.name
- val poster = info.posterUrl
- val typeinfo =
- if (type?.contains("TV") == true) TvType.TvSeries else TvType.Movie
- val link = if (typeinfo == TvType.Movie) "$mainUrl/movie/${info.id}-${
- cleanTitle(title)
- }"
- else "$mainUrl/tv-show/${info.id}-${cleanTitle(title)}/season-1/episode-1"
- if (typeinfo == TvType.Movie) {
- search.add(
- MovieSearchResponse(
- title,
- link,
- this.name,
- TvType.Movie,
- poster,
- null
- )
- )
- } else {
- search.add(
- TvSeriesSearchResponse(
- title,
- link,
- this.name,
- TvType.TvSeries,
- poster,
- null,
- null
- )
- )
- }
- }
- }
- }
- }
- return search
- }
- data class LoadMain (
- @JsonProperty("props" ) val props : LoadProps? = LoadProps(),
- @JsonProperty("page" ) val page : String? = null,
- @JsonProperty("buildId" ) val buildId : String? = null,
- @JsonProperty("runtimeConfig" ) val runtimeConfig : RuntimeConfig? = RuntimeConfig(),
- @JsonProperty("isFallback" ) val isFallback : Boolean? = null,
- @JsonProperty("gssp" ) val gssp : Boolean? = null,
- @JsonProperty("customServer" ) val customServer : Boolean? = null,
- @JsonProperty("appGip" ) val appGip : Boolean? = null
- )
-
- data class LoadProps (
- @JsonProperty("pageProps" ) val pageProps : LoadPageProps? = LoadPageProps(),
- @JsonProperty("__N_SSP" ) val _NSSP : Boolean? = null
- )
-
- data class LoadPageProps (
- @JsonProperty("selectedTv" ) val selectedTv : TheFlixMetadata? = TheFlixMetadata(),
- @JsonProperty("movie") val movie: TheFlixMetadata? = TheFlixMetadata(),
- @JsonProperty("recommendationsList" ) val recommendationsList : RecommendationsList? = RecommendationsList(),
- @JsonProperty("basePageSegments" ) val basePageSegments : ArrayList? = arrayListOf()
- )
-
- data class TheFlixMetadata (
- @JsonProperty("episodeRuntime" ) val episodeRuntime : Int? = null,
- @JsonProperty("name" ) val name : String? = null,
- @JsonProperty("numberOfSeasons" ) val numberOfSeasons : Int? = null,
- @JsonProperty("numberOfEpisodes" ) val numberOfEpisodes : Int? = null,
- @JsonProperty("originalLanguage" ) val originalLanguage : String? = null,
- @JsonProperty("popularity" ) val popularity : Double? = null,
- @JsonProperty("status" ) val status : String? = null,
- @JsonProperty("voteAverage" ) val voteAverage : Double? = null,
- @JsonProperty("voteCount" ) val voteCount : Int? = null,
- @JsonProperty("cast" ) val cast : String? = null,
- @JsonProperty("director" ) val director : String? = null,
- @JsonProperty("overview" ) val overview : String? = null,
- @JsonProperty("posterUrl" ) val posterUrl : String? = null,
- @JsonProperty("releaseDate" ) val releaseDate : String? = null,
- @JsonProperty("createdAt" ) val createdAt : String? = null,
- @JsonProperty("updatedAt" ) val updatedAt : String? = null,
- @JsonProperty("id" ) val id : Int? = null,
- @JsonProperty("available" ) val available : Boolean? = null,
- @JsonProperty("genres" ) val genres : ArrayList? = arrayListOf(),
- @JsonProperty("seasons" ) val seasons : ArrayList? = arrayListOf(),
- @JsonProperty("videos" ) val videos : ArrayList? = arrayListOf(),
- @JsonProperty("runtime" ) val runtime : Int? = null,
- )
- data class Seasons(
- @JsonProperty("name") val name: String? = null,
- @JsonProperty("numberOfEpisodes") val numberOfEpisodes: Int? = null,
- @JsonProperty("seasonNumber") val seasonNumber: Int? = null,
- @JsonProperty("overview") val overview: String? = null,
- @JsonProperty("posterUrl") val posterUrl: String? = null,
- @JsonProperty("releaseDate") val releaseDate: String? = null,
- @JsonProperty("createdAt") val createdAt: String? = null,
- @JsonProperty("updatedAt") val updatedAt: String? = null,
- @JsonProperty("id") val id: Int? = null,
- @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf()
- )
-
- data class Episodes(
- @JsonProperty("episodeNumber") val episodeNumber: Int? = null,
- @JsonProperty("name") val name: String? = null,
- @JsonProperty("seasonNumber") val seasonNumber: Int? = null,
- @JsonProperty("voteAverage") val voteAverage: Double? = null,
- @JsonProperty("voteCount") val voteCount: Int? = null,
- @JsonProperty("overview") val overview: String? = null,
- @JsonProperty("releaseDate") val releaseDate: String? = null,
- @JsonProperty("createdAt") val createdAt: String? = null,
- @JsonProperty("updatedAt") val updatedAt: String? = null,
- @JsonProperty("id") val id: Int? = null,
- @JsonProperty("videos") val videos: ArrayList? = arrayListOf()
- )
-
-
- data class Genres (
- @JsonProperty("name" ) val name : String? = null,
- @JsonProperty("id" ) val id : Int? = null
- )
-
- data class RuntimeConfig (
- @JsonProperty("AddThisService" ) val AddThisService : RuntimeConfigData? = RuntimeConfigData(),
- @JsonProperty("Application" ) val Application : RuntimeConfigData? = RuntimeConfigData(),
- @JsonProperty("GtmService" ) val GtmService : RuntimeConfigData? = RuntimeConfigData(),
- @JsonProperty("Services" ) val Services : RuntimeConfigData? = RuntimeConfigData(),
- )
-
- data class RuntimeConfigData(
- @JsonProperty("PublicId" ) val PublicId : String? = null,
- @JsonProperty("ContentUsageType" ) val ContentUsageType : String? = null,
- @JsonProperty("IsDevelopmentMode" ) val IsDevelopmentMode : Boolean? = null,
- @JsonProperty("IsDevelopmentOrProductionMode" ) val IsDevelopmentOrProductionMode : Boolean? = null,
- @JsonProperty("IsProductionMode" ) val IsProductionMode : Boolean? = null,
- @JsonProperty("IsStagingMode" ) val IsStagingMode : Boolean? = null,
- @JsonProperty("IsTestMode" ) val IsTestMode : Boolean? = null,
- @JsonProperty("Mode" ) val Mode : String? = null,
- @JsonProperty("Name" ) val Name : String? = null,
- @JsonProperty("Url" ) val Url : String? = null,
- @JsonProperty("UseFilterInfoInUrl" ) val UseFilterInfoInUrl : Boolean? = null,
- @JsonProperty("TrackingId" ) val TrackingId : String? = null,
- @JsonProperty("Server" ) val Server : Server? = Server(),
- @JsonProperty("TmdbServer" ) val TmdbServer : TmdbServer? = TmdbServer(),
- )
-
- data class TmdbServer (
- @JsonProperty("Url" ) val Url : String? = null
- )
-
-
- data class Server (
- @JsonProperty("Url" ) val Url : String? = null
- )
-
- data class RecommendationsList (
- @JsonProperty("docs" ) val docs : ArrayList = arrayListOf(),
- @JsonProperty("total" ) val total : Int? = null,
- @JsonProperty("page" ) val page : Int? = null,
- @JsonProperty("limit" ) val limit : Int? = null,
- @JsonProperty("pages" ) val pages : Int? = null,
- @JsonProperty("type" ) val type : String? = null,
- )
-
- private fun cleanTitle(title: String): String {
- val dotTitle = title.substringBefore("/season")
- if (dotTitle.contains(Regex("\\..\\."))) { //For titles containing more than two dots (S.W.A.T.)
- return (dotTitle.removeSuffix(".")
- .replace(" - ", "-")
- .replace(".", "-").replace(" ", "-")
- .replace("-&", "")
- .replace(Regex("(:|-&)"), "")
- .replace("'", "-")).lowercase()
- }
- return (title
- .replace(" - ", "-")
- .replace(" ", "-")
- .replace("-&", "")
- .replace("/", "-")
- .replace(Regex("(:|-&|\\.)"), "")
- .replace("'", "-")).lowercase()
- }
-
- private suspend fun getLoadMan(url: String): LoadMain {
- getCookies()
- val og = app.get(url, headers = latestCookies)
- val soup = og.document
- val script = soup.selectFirst("script[type=application/json]")!!.data()
- return parseJson(script)
- }
-
- override suspend fun load(url: String): LoadResponse? {
- val tvtype = if (url.contains("movie")) TvType.Movie else TvType.TvSeries
- val json = getLoadMan(url)
- val episodes = ArrayList()
- val isMovie = tvtype == TvType.Movie
- val pageMain = json.props?.pageProps
-
- val metadata: TheFlixMetadata? = if (isMovie) pageMain?.movie else pageMain?.selectedTv
-
- val available = metadata?.available
-
- val comingsoon = !available!!
-
- val movieId = metadata.id
-
- val movietitle = metadata.name
-
- val poster = metadata.posterUrl
-
- val description = metadata.overview
-
- if (!isMovie) {
- metadata.seasons?.map { seasons ->
- val seasonPoster = seasons.posterUrl ?: metadata.posterUrl
- seasons.episodes?.forEach { epi ->
- val episodenu = epi.episodeNumber
- val seasonum = epi.seasonNumber
- val title = epi.name
- val epDesc = epi.overview
- val test = epi.videos
- val ratinginfo = (epi.voteAverage)?.times(10)?.toInt()
- val rating = if (ratinginfo?.equals(0) == true) null else ratinginfo
- val eps = Episode(
- "$mainUrl/tv-show/$movieId-${cleanTitle(movietitle!!)}/season-$seasonum/episode-$episodenu",
- title,
- seasonum,
- episodenu,
- description = epDesc!!,
- posterUrl = seasonPoster,
- rating = rating,
- )
- if (test!!.isNotEmpty()) {
- episodes.add(eps)
- } else {
- //Nothing, will prevent seasons/episodes with no videos to be added
- }
- }
- }
- }
- val rating = metadata.voteAverage?.toFloat()?.times(1000)?.toInt()
-
- val tags = metadata.genres?.mapNotNull { it.name }
-
- val recommendationsitem = pageMain?.recommendationsList?.docs?.map { loadDocs ->
- val title = loadDocs.name
- val posterrec = loadDocs.posterUrl
- val link = if (isMovie) "$mainUrl/movie/${loadDocs.id}-${cleanTitle(title)}"
- else "$mainUrl/tv-show/${loadDocs.id}-${cleanTitle(title)}/season-1/episode-1"
- MovieSearchResponse(
- title,
- link,
- this.name,
- tvtype,
- posterrec,
- year = null
- )
- }
-
- val year = metadata.releaseDate?.substringBefore("-")
-
- val runtime = metadata.runtime?.div(60) ?: metadata.episodeRuntime?.div(60)
- val cast = metadata.cast?.split(",")
-
- return when (tvtype) {
- TvType.TvSeries -> {
- return newTvSeriesLoadResponse(movietitle!!, url, TvType.TvSeries, episodes) {
- this.posterUrl = poster
- this.year = year?.toIntOrNull()
- this.plot = description
- this.duration = runtime
- addActors(cast)
- this.tags = tags
- this.recommendations = recommendationsitem
- this.comingSoon = comingsoon
- this.rating = rating
- }
- }
- TvType.Movie -> {
- newMovieLoadResponse(movietitle!!, url, TvType.Movie, url) {
- this.year = year?.toIntOrNull()
- this.posterUrl = poster
- this.plot = description
- this.duration = runtime
- addActors(cast)
- this.tags = tags
- this.recommendations = recommendationsitem
- this.comingSoon = comingsoon
- this.rating = rating
- }
- }
- else -> null
- }
- }
-
-
- data class VideoData (
- @JsonProperty("url" ) val url : String? = null,
- @JsonProperty("id" ) val id : String? = null,
- @JsonProperty("type" ) val type : String? = null,
- )
-
-
- override suspend fun loadLinks(
- data: String,
- isCasting: Boolean,
- subtitleCallback: (SubtitleFile) -> Unit,
- callback: (ExtractorLink) -> Unit
- ): Boolean {
- val json = getLoadMan(data)
- val authhost = json.runtimeConfig?.Services?.Server?.Url
- val isMovie = data.contains("/movie/")
- val qualityReg = Regex("(\\d+p)")
- if (isMovie){
- json.props?.pageProps?.movie?.videos?.apmap { id ->
- val jsonmovie = app.get("$authhost/movies/videos/$id/request-access?contentUsageType=Viewing",
- headers = latestCookies).parsedSafe() ?: return@apmap false
- val extractedlink = jsonmovie.url
- if (!extractedlink.isNullOrEmpty()) {
- val quality = qualityReg.find(extractedlink)?.value ?: ""
- callback(
- ExtractorLink(
- name,
- name,
- extractedlink,
- "",
- getQualityFromName(quality),
- false
- )
- )
- } else null
- }
- }
- else
- {
- val dataRegex = Regex("(season-(\\d+)\\/episode-(\\d+))")
- val cleandatainfo = dataRegex.find(data)?.value?.replace(Regex("(season-|episode-)"),"")?.replace("/","x")
- val tesatt = cleandatainfo.let { str ->
- str?.split("x")?.mapNotNull { subStr -> subStr.toIntOrNull() }
- }
- val epID = tesatt?.getOrNull(1)
- val seasonid = tesatt?.getOrNull(0)
- json.props?.pageProps?.selectedTv?.seasons?.map {
- it.episodes?.map {
- val epsInfo = Triple(it.seasonNumber, it.episodeNumber, it.videos)
- if (epsInfo.first == seasonid && epsInfo.second == epID) {
- epsInfo.third?.apmap { id ->
- val jsonserie = app.get("$authhost/tv/videos/$id/request-access?contentUsageType=Viewing", headers = latestCookies).parsedSafe() ?: return@apmap false
- val extractedlink = jsonserie.url
- if (!extractedlink.isNullOrEmpty()) {
- val quality = qualityReg.find(extractedlink)?.value ?: ""
- callback(
- ExtractorLink(
- name,
- name,
- extractedlink,
- "",
- getQualityFromName(quality),
- false
- )
- )
- } else null
- }
- }
- }
- }
- }
- return true
- }
-}
diff --git a/TheFlixToProvider/src/main/kotlin/com/lagradost/TheFlixToProviderPlugin.kt b/TheFlixToProvider/src/main/kotlin/com/lagradost/TheFlixToProviderPlugin.kt
deleted file mode 100644
index 6eb5cfa..0000000
--- a/TheFlixToProvider/src/main/kotlin/com/lagradost/TheFlixToProviderPlugin.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package com.lagradost
-
-import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
-import com.lagradost.cloudstream3.plugins.Plugin
-import android.content.Context
-
-@CloudstreamPlugin
-class TheFlixToProviderPlugin: Plugin() {
- override fun load(context: Context) {
- // All providers should be added in this manner. Please don't edit the providers list directly.
- registerMainAPI(TheFlixToProvider())
- }
-}
\ No newline at end of file
diff --git a/TrailersTwoProvider/build.gradle.kts b/TrailersTwoProvider/build.gradle.kts
deleted file mode 100644
index 8595414..0000000
--- a/TrailersTwoProvider/build.gradle.kts
+++ /dev/null
@@ -1,29 +0,0 @@
-// use an integer for version numbers
-version = 1
-
-
-cloudstream {
- // All of these properties are optional, you can safely remove them
-
- // description = "Lorem Ipsum"
- // authors = listOf("Cloudburst")
-
- /**
- * Status int as the following:
- * 0: Down
- * 1: Ok
- * 2: Slow
- * 3: Beta only
- * */
- status = 1 // will be 3 if unspecified
- tvTypes = listOf(
- "Cartoon",
- "Anime",
- "Movie",
- "AnimeMovie",
- "TvSeries",
- )
-
-
- iconUrl = "https://www.google.com/s2/favicons?domain=trailers.to&sz=24"
-}
\ No newline at end of file
diff --git a/TrailersTwoProvider/src/main/AndroidManifest.xml b/TrailersTwoProvider/src/main/AndroidManifest.xml
deleted file mode 100644
index 29aec9d..0000000
--- a/TrailersTwoProvider/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/TrailersTwoProvider/src/main/kotlin/com/lagradost/TrailersTwoProvider.kt b/TrailersTwoProvider/src/main/kotlin/com/lagradost/TrailersTwoProvider.kt
deleted file mode 100644
index d7d5212..0000000
--- a/TrailersTwoProvider/src/main/kotlin/com/lagradost/TrailersTwoProvider.kt
+++ /dev/null
@@ -1,319 +0,0 @@
-package com.lagradost
-
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.lagradost.cloudstream3.*
-import com.lagradost.cloudstream3.metaproviders.TmdbLink
-import com.lagradost.cloudstream3.metaproviders.TmdbProvider
-import com.lagradost.cloudstream3.utils.AppUtils.parseJson
-import com.lagradost.cloudstream3.utils.ExtractorLink
-import com.lagradost.cloudstream3.utils.Qualities
-import com.lagradost.cloudstream3.utils.SubtitleHelper
-
-class TrailersTwoProvider : TmdbProvider() {
- val user = "cloudstream"
- override val apiName = "Trailers.to"
- override var name = "Trailers.to"
- override var mainUrl = "https://trailers.to"
- override val useMetaLoadResponse = true
- override val instantLinkLoading = true
-
- data class TrailersEpisode(
- // val tvShowItemID: Long?,
- //val tvShow: String,
- //val tvShowIMDB: String?,
- //val tvShowTMDB: Long?,
- @JsonProperty("ItemID")
- val itemID: Int,
- //val title: String,
- //@JsonProperty("IMDb")
- @JsonProperty("IMDb")
- val imdb: String?,
- //@JsonProperty("TMDb")
- @JsonProperty("TMDb")
- val tmdb: Int?,
- //val releaseDate: String,
- //val entryDate: String
- )
-
- data class TrailersMovie(
- @JsonProperty("ItemID")
- val itemID: Int,
- @JsonProperty("IMDb")
- val imdb: String?,
- @JsonProperty("TMDb")
- val tmdb: Int?,
- //@JsonProperty("Title")
- //val title: String?,
- )
-
- /*companion object {
- private var tmdbToIdMovies: HashMap = hashMapOf()
- private var imdbToIdMovies: HashMap = hashMapOf()
- private var tmdbToIdTvSeries: HashMap = hashMapOf()
- private var imdbToIdTvSeries: HashMap = hashMapOf()
-
- private const val startDate = 1900
- private const val endDate = 9999
-
- fun getEpisode(tmdb: Int?, imdb: String?): Int? {
- var currentId: Int? = null
- if (tmdb != null) {
- currentId = tmdbToIdTvSeries[tmdb]
- }
- if (imdb != null && currentId == null) {
- currentId = imdbToIdTvSeries[imdb]
- }
- return currentId
- }
-
- fun getMovie(tmdb: Int?, imdb: String?): Int? {
- var currentId: Int? = null
- if (tmdb != null) {
- currentId = tmdbToIdMovies[tmdb]
- }
- if (imdb != null && currentId == null) {
- currentId = imdbToIdMovies[imdb]
- }
- return currentId
- }
-
- suspend fun fillData(isMovie: Boolean) {
- if (isMovie) {
- if (tmdbToIdMovies.isNotEmpty() || imdbToIdMovies.isNotEmpty()) {
- return
- }
- parseJson>(
- app.get(
- "https://trailers.to/movies?from=$startDate-01-01&to=$endDate",
- timeout = 30
- ).text
- ).forEach { movie ->
- movie.imdb?.let {
- imdbToIdTvSeries[it] = movie.itemID
- }
- movie.tmdb?.let {
- tmdbToIdTvSeries[it] = movie.itemID
- }
- }
- } else {
- if (tmdbToIdTvSeries.isNotEmpty() || imdbToIdTvSeries.isNotEmpty()) {
- return
- }
- parseJson>(
- app.get(
- "https://trailers.to/episodes?from=$startDate-01-01&to=$endDate",
- timeout = 30
- ).text
- ).forEach { episode ->
- episode.imdb?.let {
- imdbToIdTvSeries[it] = episode.itemID
- }
- episode.tmdb?.let {
- tmdbToIdTvSeries[it] = episode.itemID
- }
- }
- }
- }
- }*/
-
- override val supportedTypes = setOf(
- TvType.Movie,
- TvType.TvSeries,
- //TvType.AnimeMovie,
- //TvType.Anime,
- //TvType.Cartoon
- )
-
- override suspend fun loadLinks(
- data: String,
- isCasting: Boolean,
- subtitleCallback: (SubtitleFile) -> Unit,
- callback: (ExtractorLink) -> Unit
- ): Boolean {
- val mappedData = parseJson(data)
- val (id, site) = if (mappedData.imdbID != null) listOf(
- mappedData.imdbID,
- "imdb"
- ) else listOf(mappedData.tmdbID.toString(), "tmdb")
-
- val isMovie = mappedData.episode == null && mappedData.season == null
- val (videoUrl, subtitleUrl) = if (isMovie) {
- val suffix = "$user/$site/$id"
- Pair(
- "https://trailers.to/video/$suffix",
- "https://trailers.to/subtitles/$suffix"
- )
- } else {
- val suffix = "$user/$site/$id/S${mappedData.season ?: 1}E${mappedData.episode ?: 1}"
- Pair(
- "https://trailers.to/video/$suffix",
- "https://trailers.to/subtitles/$suffix"
- )
- }
-
- callback.invoke(
- ExtractorLink(
- this.name,
- this.name,
- videoUrl,
- "https://trailers.to",
- Qualities.Unknown.value,
- false,
- )
- )
-
- argamap(
- {
- val subtitles =
- app.get(subtitleUrl).text
- val subtitlesMapped = parseJson>(subtitles)
- subtitlesMapped.forEach {
- subtitleCallback.invoke(
- SubtitleFile(
- SubtitleHelper.fromTwoLettersToLanguage(it.LanguageCode ?: "en")
- ?: "English",
- "https://trailers.to/subtitles/${it.ContentHash ?: return@forEach}/${it.LanguageCode ?: return@forEach}.vtt" // ${it.MetaInfo?.SubFormat ?: "srt"}"
- )
- )
- }
- }, {
- //https://trailers.to/en/quick-search?q=iron man
- val name = mappedData.movieName
- if (name != null && isMovie) {
- app.get("https://trailers.to/en/quick-search?q=${name}").document.select("a.post-minimal")
- .mapNotNull {
- it?.attr("href")
- }.map { Regex("""/movie/(\d+)/""").find(it)?.groupValues?.getOrNull(1) }
- .firstOrNull()?.let { movieId ->
- val correctUrl = app.get(videoUrl).url
- callback.invoke(
- ExtractorLink(
- this.name,
- "${this.name} Backup",
- correctUrl.replace("/$user/0/", "/$user/$movieId/"),
- "https://trailers.to",
- Qualities.Unknown.value,
- false,
- )
- )
- }
- }
- }
- )
-
- /*
- // the problem with this code is that it tages ages and the json file is 50mb or so for movies
- fillData(isMovie)
- val movieId = if (isMovie) {
- getMovie(mappedData.tmdbID, mappedData.imdbID)
- } else {
- getEpisode(mappedData.tmdbID, mappedData.imdbID)
- } ?: return@argamap
- val request = app.get(data)
- val endUrl = request.url
- callback.invoke(
- ExtractorLink(
- this.name,
- "${this.name} Backup",
- endUrl.replace("/cloudstream/0/", "/cloudstream/$movieId/"),
- "https://trailers.to",
- Qualities.Unknown.value,
- false,
- )
- )
- */
-
- return true
- }
-}
-
-// Auto generated
-data class TrailersSubtitleFile(
- @JsonProperty("SubtitleID") val SubtitleID: Int?,
- @JsonProperty("ItemID") val ItemID: Int?,
- @JsonProperty("ContentText") val ContentText: String?,
- @JsonProperty("ContentHash") val ContentHash: String?,
- @JsonProperty("LanguageCode") val LanguageCode: String?,
- @JsonProperty("MetaInfo") val MetaInfo: MetaInfo?,
- @JsonProperty("EntryDate") val EntryDate: String?,
- @JsonProperty("ItemSubtitleAdaptations") val ItemSubtitleAdaptations: List?,
- @JsonProperty("ReleaseNames") val ReleaseNames: List?,
- @JsonProperty("SubFileNames") val SubFileNames: List?,
- @JsonProperty("Framerates") val Framerates: List?,
- @JsonProperty("IsRelevant") val IsRelevant: Boolean?
-)
-
-data class QueryParameters(
- @JsonProperty("imdbid") val imdbid: String?
-)
-
-data class MetaInfo(
- @JsonProperty("MatchedBy") val MatchedBy: String?,
- @JsonProperty("IDSubMovieFile") val IDSubMovieFile: String?,
- @JsonProperty("MovieHash") val MovieHash: String?,
- @JsonProperty("MovieByteSize") val MovieByteSize: String?,
- @JsonProperty("MovieTimeMS") val MovieTimeMS: String?,
- @JsonProperty("IDSubtitleFile") val IDSubtitleFile: String?,
- @JsonProperty("SubFileName") val SubFileName: String?,
- @JsonProperty("SubActualCD") val SubActualCD: String?,
- @JsonProperty("SubSize") val SubSize: String?,
- @JsonProperty("SubHash") val SubHash: String?,
- @JsonProperty("SubLastTS") val SubLastTS: String?,
- @JsonProperty("SubTSGroup") val SubTSGroup: String?,
- @JsonProperty("InfoReleaseGroup") val InfoReleaseGroup: String?,
- @JsonProperty("InfoFormat") val InfoFormat: String?,
- @JsonProperty("InfoOther") val InfoOther: String?,
- @JsonProperty("IDSubtitle") val IDSubtitle: String?,
- @JsonProperty("UserID") val UserID: String?,
- @JsonProperty("SubLanguageID") val SubLanguageID: String?,
- @JsonProperty("SubFormat") val SubFormat: String?,
- @JsonProperty("SubSumCD") val SubSumCD: String?,
- @JsonProperty("SubAuthorComment") val SubAuthorComment: String?,
- @JsonProperty("SubAddDate") val SubAddDate: String?,
- @JsonProperty("SubBad") val SubBad: String?,
- @JsonProperty("SubRating") val SubRating: String?,
- @JsonProperty("SubSumVotes") val SubSumVotes: String?,
- @JsonProperty("SubDownloadsCnt") val SubDownloadsCnt: String?,
- @JsonProperty("MovieReleaseName") val MovieReleaseName: String?,
- @JsonProperty("MovieFPS") val MovieFPS: String?,
- @JsonProperty("IDMovie") val IDMovie: String?,
- @JsonProperty("IDMovieImdb") val IDMovieImdb: String?,
- @JsonProperty("MovieName") val MovieName: String?,
- @JsonProperty("MovieNameEng") val MovieNameEng: String?,
- @JsonProperty("MovieYear") val MovieYear: String?,
- @JsonProperty("MovieImdbRating") val MovieImdbRating: String?,
- @JsonProperty("SubFeatured") val SubFeatured: String?,
- @JsonProperty("UserNickName") val UserNickName: String?,
- @JsonProperty("SubTranslator") val SubTranslator: String?,
- @JsonProperty("ISO639") val ISO639: String?,
- @JsonProperty("LanguageName") val LanguageName: String?,
- @JsonProperty("SubComments") val SubComments: String?,
- @JsonProperty("SubHearingImpaired") val SubHearingImpaired: String?,
- @JsonProperty("UserRank") val UserRank: String?,
- @JsonProperty("SeriesSeason") val SeriesSeason: String?,
- @JsonProperty("SeriesEpisode") val SeriesEpisode: String?,
- @JsonProperty("MovieKind") val MovieKind: String?,
- @JsonProperty("SubHD") val SubHD: String?,
- @JsonProperty("SeriesIMDBParent") val SeriesIMDBParent: String?,
- @JsonProperty("SubEncoding") val SubEncoding: String?,
- @JsonProperty("SubAutoTranslation") val SubAutoTranslation: String?,
- @JsonProperty("SubForeignPartsOnly") val SubForeignPartsOnly: String?,
- @JsonProperty("SubFromTrusted") val SubFromTrusted: String?,
- @JsonProperty("QueryCached") val QueryCached: Int?,
- @JsonProperty("SubTSGroupHash") val SubTSGroupHash: String?,
- @JsonProperty("SubDownloadLink") val SubDownloadLink: String?,
- @JsonProperty("ZipDownloadLink") val ZipDownloadLink: String?,
- @JsonProperty("SubtitlesLink") val SubtitlesLink: String?,
- @JsonProperty("QueryNumber") val QueryNumber: String?,
- @JsonProperty("QueryParameters") val QueryParameters: QueryParameters?,
- @JsonProperty("Score") val Score: Double?
-)
-
-data class ItemSubtitleAdaptations(
- @JsonProperty("ContentHash") val ContentHash: String?,
- @JsonProperty("OffsetMs") val OffsetMs: Int?,
- @JsonProperty("Framerate") val Framerate: Int?,
- @JsonProperty("Views") val Views: Int?,
- @JsonProperty("EntryDate") val EntryDate: String?,
- @JsonProperty("Subtitle") val Subtitle: String?
-)
\ No newline at end of file
diff --git a/TrailersTwoProvider/src/main/kotlin/com/lagradost/TrailersTwoProviderPlugin.kt b/TrailersTwoProvider/src/main/kotlin/com/lagradost/TrailersTwoProviderPlugin.kt
deleted file mode 100644
index 459713d..0000000
--- a/TrailersTwoProvider/src/main/kotlin/com/lagradost/TrailersTwoProviderPlugin.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package com.lagradost
-
-import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
-import com.lagradost.cloudstream3.plugins.Plugin
-import android.content.Context
-
-@CloudstreamPlugin
-class TrailersTwoProviderPlugin: Plugin() {
- override fun load(context: Context) {
- // All providers should be added in this manner. Please don't edit the providers list directly.
- registerMainAPI(TrailersTwoProvider())
- }
-}
\ No newline at end of file
diff --git a/VMoveeProvider/build.gradle.kts b/VMoveeProvider/build.gradle.kts
deleted file mode 100644
index b4e9d11..0000000
--- a/VMoveeProvider/build.gradle.kts
+++ /dev/null
@@ -1,26 +0,0 @@
-// use an integer for version numbers
-version = 1
-
-
-cloudstream {
- // All of these properties are optional, you can safely remove them
-
- // description = "Lorem Ipsum"
- // authors = listOf("Cloudburst")
-
- /**
- * Status int as the following:
- * 0: Down
- * 1: Ok
- * 2: Slow
- * 3: Beta only
- * */
- status = 1 // will be 3 if unspecified
- tvTypes = listOf(
- "TvSeries",
- "Movie",
- )
-
-
- iconUrl = "https://www.google.com/s2/favicons?domain=www.vmovee.watch&sz=24"
-}
\ No newline at end of file
diff --git a/VMoveeProvider/src/main/AndroidManifest.xml b/VMoveeProvider/src/main/AndroidManifest.xml
deleted file mode 100644
index 29aec9d..0000000
--- a/VMoveeProvider/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/VMoveeProvider/src/main/kotlin/com/lagradost/VMoveeProvider.kt b/VMoveeProvider/src/main/kotlin/com/lagradost/VMoveeProvider.kt
deleted file mode 100644
index 57f1e7a..0000000
--- a/VMoveeProvider/src/main/kotlin/com/lagradost/VMoveeProvider.kt
+++ /dev/null
@@ -1,125 +0,0 @@
-package com.lagradost
-
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.lagradost.cloudstream3.*
-import com.lagradost.cloudstream3.utils.AppUtils.parseJson
-import com.lagradost.cloudstream3.utils.ExtractorLink
-import com.lagradost.cloudstream3.utils.getQualityFromName
-import org.jsoup.Jsoup
-
-class VMoveeProvider : MainAPI() {
- override var name = "VMovee"
- override var mainUrl = "https://www.vmovee.watch"
-
- override val supportedTypes = setOf(TvType.Movie)
-
- override suspend fun search(query: String): List {
- val url = "$mainUrl/?s=$query"
- val response = app.get(url).text
- val document = Jsoup.parse(response)
- val searchItems = document.select("div.search-page > div.result-item > article")
- if (searchItems.size == 0) return ArrayList()
- val returnValue = ArrayList()
- for (item in searchItems) {
- val details = item.selectFirst("> div.details")
- val imgHolder = item.selectFirst("> div.image > div.thumbnail > a")
- // val href = imgHolder.attr("href")
- val poster = imgHolder!!.selectFirst("> img")!!.attr("data-lazy-src")
- val isTV = imgHolder.selectFirst("> span")!!.text() == "TV"
- if (isTV) continue // no TV support yet
-
- val titleHolder = details!!.selectFirst("> div.title > a")
- val title = titleHolder!!.text()
- val href = titleHolder.attr("href")
- val meta = details.selectFirst("> div.meta")
- val year = meta!!.selectFirst("> span.year")!!.text().toIntOrNull()
- // val rating = parseRating(meta.selectFirst("> span.rating").text().replace("IMDb ", ""))
- // val descript = details.selectFirst("> div.contenido").text()
- returnValue.add(
- if (isTV) TvSeriesSearchResponse(title, href, this.name, TvType.TvSeries, poster, year, null)
- else MovieSearchResponse(title, href, this.name, TvType.Movie, poster, year)
- )
- }
- return returnValue
- }
-
- data class LoadLinksAjax(
- @JsonProperty("embed_url")
- val embedUrl: String,
- )
-
- data class ReeoovAPIData(
- @JsonProperty("file")
- val file: String,
- @JsonProperty("label")
- val label: String,
- )
-
- data class ReeoovAPI(
- @JsonProperty("data")
- val data: List