cloudstream/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt

310 lines
7.2 KiB
Kotlin
Raw Normal View History

2021-05-19 18:44:02 +00:00
package com.lagradost.cloudstream3.utils
2022-01-07 19:27:25 +00:00
import android.net.Uri
import com.lagradost.cloudstream3.TvType
2021-09-30 15:51:34 +00:00
import com.lagradost.cloudstream3.USER_AGENT
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.extractors.*
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import kotlinx.coroutines.delay
2021-09-30 15:51:34 +00:00
import org.jsoup.Jsoup
2021-05-19 18:44:02 +00:00
data class ExtractorLink(
2021-05-20 15:22:28 +00:00
val source: String,
2021-05-19 18:44:02 +00:00
val name: String,
override val url: String,
override val referer: String,
2021-05-19 18:44:02 +00:00
val quality: Int,
val isM3u8: Boolean = false,
2022-02-11 09:17:04 +00:00
override val headers: Map<String, String> = mapOf(),
/** Used for getExtractorVerifierJob() */
val extractorData: String? = null
) : VideoDownloadManager.IDownloadableMinimum
2021-05-19 18:44:02 +00:00
2022-01-07 19:27:25 +00:00
data class ExtractorUri(
2022-04-18 18:49:17 +00:00
val uri: Uri,
val name: String,
2022-01-07 19:27:25 +00:00
val basePath: String? = null,
val relativePath: String? = null,
val displayName: String? = null,
2022-04-18 18:49:17 +00:00
val id: Int? = null,
val parentId: Int? = null,
val episode: Int? = null,
val season: Int? = null,
val headerName: String? = null,
2022-01-07 19:27:25 +00:00
val tvType: TvType? = null,
)
data class ExtractorSubtitleLink(
val name: String,
override val url: String,
override val referer: String,
override val headers: Map<String, String> = mapOf()
) : VideoDownloadManager.IDownloadableMinimum
2021-05-28 13:38:06 +00:00
2021-05-19 18:44:02 +00:00
enum class Qualities(var value: Int) {
2022-04-18 18:49:17 +00:00
Unknown(400),
P144(144), // 144p
P240(240), // 240p
P360(360), // 360p
P480(480), // 480p
P720(720), // 720p
P1080(1080), // 1080p
P1440(1440), // 1440p
P2160(2160); // 4k or 2160p
companion object {
2022-04-18 18:49:17 +00:00
fun getStringByInt(qual: Int?): String {
return when (qual) {
2022-04-18 22:00:49 +00:00
0 -> "Auto"
2022-04-18 18:49:17 +00:00
Unknown.value -> ""
P2160.value -> "4K"
null -> ""
2022-04-18 18:49:17 +00:00
else -> "${qual}p"
}
}
}
2021-05-19 18:44:02 +00:00
}
fun getQualityFromName(qualityName: String?): Int {
2022-04-18 18:49:17 +00:00
if (qualityName == null)
return Qualities.Unknown.value
2022-04-18 18:49:17 +00:00
val match = qualityName.lowercase().replace("p", "").trim()
return when (match) {
2021-08-24 21:06:40 +00:00
"4k" -> Qualities.P2160
2022-04-18 18:49:17 +00:00
else -> null
}?.value ?: match.toIntOrNull() ?: Qualities.Unknown.value
}
2021-05-19 18:44:02 +00:00
private val packedRegex = Regex("""eval\(function\(p,a,c,k,e,.*\)\)""")
fun getPacked(string: String): String? {
return packedRegex.find(string)?.value
}
fun getAndUnpack(string: String): String {
2021-05-19 18:44:02 +00:00
val packedText = getPacked(string)
return JsUnpacker(packedText).unpack() ?: string
2021-05-19 18:44:02 +00:00
}
2021-12-12 01:49:41 +00:00
/**
* Tries to load the appropriate extractor based on link, returns true if any extractor is loaded.
* */
2022-04-18 18:49:17 +00:00
suspend fun loadExtractor(
url: String,
referer: String? = null,
callback: (ExtractorLink) -> Unit
): Boolean {
for (extractor in extractorApis) {
if (url.startsWith(extractor.mainUrl)) {
extractor.getSafeUrl(url, referer)?.forEach(callback)
2021-12-12 01:49:41 +00:00
return true
}
}
2021-12-12 01:49:41 +00:00
return false
}
2022-06-17 17:25:41 +00:00
suspend fun loadExtractor(
url: String,
referer: String? = null,
): List<ExtractorLink> {
for (extractor in extractorApis) {
if (url.startsWith(extractor.mainUrl)) {
return extractor.getSafeUrl(url, referer) ?: emptyList()
}
}
return emptyList()
}
2021-05-20 15:22:28 +00:00
val extractorApis: Array<ExtractorApi> = arrayOf(
2021-05-19 18:44:02 +00:00
//AllProvider(),
2021-07-23 11:59:41 +00:00
WcoStream(),
Vidstreamz(),
Vizcloud(),
2022-03-05 12:19:50 +00:00
Vizcloud2(),
2022-03-21 18:19:29 +00:00
VizcloudOnline(),
VizcloudXyz(),
2022-04-07 15:54:20 +00:00
VizcloudLive(),
2022-04-10 23:06:17 +00:00
VizcloudInfo(),
MwvnVizcloudInfo(),
2022-04-18 17:52:40 +00:00
VizcloudDigital(),
VizcloudCloud(),
VideoVard(),
VideovardSX(),
2021-05-19 18:44:02 +00:00
Mp4Upload(),
StreamTape(),
//mixdrop extractors
MixDropBz(),
MixDropCh(),
MixDropTo(),
2021-05-19 18:44:02 +00:00
MixDrop(),
Mcloud(),
2021-07-23 16:41:37 +00:00
XStreamCdn(),
2021-07-23 16:41:37 +00:00
StreamSB(),
StreamSB1(),
StreamSB2(),
StreamSB3(),
StreamSB4(),
StreamSB5(),
StreamSB6(),
StreamSB7(),
StreamSB8(),
StreamSB9(),
2022-03-16 20:11:14 +00:00
StreamSB10(),
SBfull(),
2022-04-18 18:49:17 +00:00
// Streamhub(), cause Streamhub2() works
Streamhub2(),
2021-12-25 18:54:44 +00:00
FEmbed(),
FeHD(),
Fplayer(),
DBfilm(),
LayarKaca(),
2022-04-18 18:49:17 +00:00
// WatchSB(), 'cause StreamSB.kt works
Uqload(),
Uqload1(),
Evoload(),
Evoload1(),
VoeExtractor(),
2022-04-18 18:49:17 +00:00
// UpstreamExtractor(), GenericM3U8.kt works
Tomatomatela(),
Cinestart(),
OkRu(),
OkRuHttps(),
// dood extractors
DoodCxExtractor(),
DoodPmExtractor(),
DoodToExtractor(),
DoodSoExtractor(),
DoodLaExtractor(),
DoodWsExtractor(),
DoodShExtractor(),
DoodWatchExtractor(),
2021-12-25 18:54:44 +00:00
AsianLoad(),
2022-04-18 18:49:17 +00:00
// GenericM3U8(),
Jawcloud(),
Zplayer(),
ZplayerV2(),
Upstream(),
Maxstream(),
Tantifilm(),
Userload(),
Supervideo(),
GuardareStream(),
2022-04-18 18:49:17 +00:00
// StreamSB.kt works
// SBPlay(),
// SBPlay1(),
// SBPlay2(),
2022-03-13 06:44:02 +00:00
PlayerVoxzer(),
BullStream(),
GMPlayer(),
Blogger(),
Solidfiles(),
YourUpload(),
Hxfile(),
KotakAnimeid(),
Neonime8n(),
Neonime7n(),
Yufiles(),
Aico(),
JWPlayer(),
Meownime(),
DesuArcg(),
DesuOdchan(),
DesuOdvip(),
DesuDrive(),
Filesim(),
2022-06-17 17:25:41 +00:00
YoutubeExtractor(),
YoutubeShortLinkExtractor(),
2021-05-19 18:44:02 +00:00
)
2021-05-20 15:22:28 +00:00
fun getExtractorApiFromName(name: String): ExtractorApi {
for (api in extractorApis) {
if (api.name == name) return api
}
return extractorApis[0]
}
fun requireReferer(name: String): Boolean {
return getExtractorApiFromName(name).requiresReferer
}
2021-05-19 18:44:02 +00:00
fun httpsify(url: String): String {
return if (url.startsWith("//")) "https:$url" else url
}
2022-04-18 18:49:17 +00:00
suspend fun getPostForm(requestUrl: String, html: String): String? {
2021-09-30 15:51:34 +00:00
val document = Jsoup.parse(html)
val inputs = document.select("Form > input")
if (inputs.size < 4) return null
var op: String? = null
var id: String? = null
var mode: String? = null
var hash: String? = null
for (input in inputs) {
val value = input.attr("value") ?: continue
when (input.attr("name")) {
"op" -> op = value
"id" -> id = value
"mode" -> mode = value
"hash" -> hash = value
2022-01-07 19:27:25 +00:00
else -> Unit
2021-09-30 15:51:34 +00:00
}
}
if (op == null || id == null || mode == null || hash == null) {
return null
}
delay(5000) // ye this is needed, wont work with 0 delay
2021-09-30 15:51:34 +00:00
2022-04-18 18:49:17 +00:00
return app.post(
2021-09-30 15:51:34 +00:00
requestUrl,
headers = mapOf(
"content-type" to "application/x-www-form-urlencoded",
"referer" to requestUrl,
"user-agent" to USER_AGENT,
"accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
),
data = mapOf("op" to op, "id" to id, "mode" to mode, "hash" to hash)
).text
}
2021-05-19 18:44:02 +00:00
abstract class ExtractorApi {
abstract val name: String
abstract val mainUrl: String
abstract val requiresReferer: Boolean
suspend fun getSafeUrl(url: String, referer: String? = null): List<ExtractorLink>? {
return suspendSafeApiCall { getUrl(url, referer) }
2021-07-23 16:41:37 +00:00
}
/**
* Will throw errors, use getSafeUrl if you don't want to handle the exception yourself
*/
abstract suspend fun getUrl(url: String, referer: String? = null): List<ExtractorLink>?
2021-05-19 18:44:02 +00:00
2021-05-20 15:22:28 +00:00
open fun getExtractorUrl(id: String): String {
2021-05-19 18:44:02 +00:00
return id
}
2021-07-23 11:59:41 +00:00
}