mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
[test] Adding UHDMovies into SoraExtractor
This commit is contained in:
parent
de52441ad0
commit
6c10e59ee5
9 changed files with 135 additions and 17 deletions
|
@ -7,7 +7,7 @@ cloudstream {
|
||||||
// All of these properties are optional, you can safely remove them
|
// All of these properties are optional, you can safely remove them
|
||||||
|
|
||||||
description = "Premium porn with 4K support (use VPN if links not working)"
|
description = "Premium porn with 4K support (use VPN if links not working)"
|
||||||
authors = listOf("Hexated")
|
authors = listOf("Sora")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status int as the following:
|
* Status int as the following:
|
||||||
|
|
|
@ -7,7 +7,7 @@ cloudstream {
|
||||||
// All of these properties are optional, you can safely remove them
|
// All of these properties are optional, you can safely remove them
|
||||||
|
|
||||||
// description = "Lorem Ipsum"
|
// description = "Lorem Ipsum"
|
||||||
authors = listOf("Hexated")
|
authors = listOf("Sora")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status int as the following:
|
* Status int as the following:
|
||||||
|
|
|
@ -6,7 +6,7 @@ cloudstream {
|
||||||
language = "en"
|
language = "en"
|
||||||
// All of these properties are optional, you can safely remove them
|
// All of these properties are optional, you can safely remove them
|
||||||
|
|
||||||
description = "#1 best extension based on Loklok API"
|
description = "#2 best extension based on Loklok API"
|
||||||
authors = listOf("Hexated")
|
authors = listOf("Hexated")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,7 +7,7 @@ cloudstream {
|
||||||
// All of these properties are optional, you can safely remove them
|
// All of these properties are optional, you can safely remove them
|
||||||
|
|
||||||
description = "Series porn (use VPN if links not working)"
|
description = "Series porn (use VPN if links not working)"
|
||||||
authors = listOf("Hexated")
|
authors = listOf("Sora")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status int as the following:
|
* Status int as the following:
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
// use an integer for version numbers
|
// use an integer for version numbers
|
||||||
version = 32
|
version = 33
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
cloudstream {
|
||||||
language = "en"
|
language = "en"
|
||||||
// All of these properties are optional, you can safely remove them
|
// All of these properties are optional, you can safely remove them
|
||||||
|
|
||||||
description = "#2 best extention based on MultiAPI"
|
description = "#1 best extention based on MultiAPI"
|
||||||
authors = listOf("Hexated", "Sora")
|
authors = listOf("Hexated", "Sora")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1163,18 +1163,13 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
val source = app.get(iframe ?: return)
|
val source = app.get(iframe ?: return)
|
||||||
val link = Regex("((https:|http:)//.*\\.mp4)").find(source.text)?.value ?: return
|
val link = Regex("((https:|http:)//.*\\.mp4)").find(source.text)?.value ?: return
|
||||||
val quality = when {
|
|
||||||
link.contains("1080p") -> Qualities.P1080.value
|
|
||||||
link.contains("720p") -> Qualities.P720.value
|
|
||||||
else -> Qualities.Unknown.value
|
|
||||||
}
|
|
||||||
callback.invoke(
|
callback.invoke(
|
||||||
ExtractorLink(
|
ExtractorLink(
|
||||||
"Ling",
|
"Ling",
|
||||||
"Ling",
|
"Ling",
|
||||||
link,
|
link,
|
||||||
"$lingAPI/",
|
"$lingAPI/",
|
||||||
quality,
|
Qualities.Unknown.value,
|
||||||
headers = mapOf(
|
headers = mapOf(
|
||||||
"Range" to "bytes=0-"
|
"Range" to "bytes=0-"
|
||||||
)
|
)
|
||||||
|
@ -1192,6 +1187,81 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun invokeUhdmovies(
|
||||||
|
title: String? = null,
|
||||||
|
year: Int? = null,
|
||||||
|
season: Int? = null,
|
||||||
|
lastSeason: Int? = null,
|
||||||
|
episode: Int? = null,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
|
|
||||||
|
val doc = app.get("$uhdmoviesAPI/?s=$title").document
|
||||||
|
val scriptData = doc.select("div.row.gridlove-posts article").map {
|
||||||
|
it.selectFirst("a")?.attr("href") to it.selectFirst("h1")?.text()
|
||||||
|
}
|
||||||
|
val script = if (scriptData.size == 1) {
|
||||||
|
scriptData.first()
|
||||||
|
} else {
|
||||||
|
scriptData.find { it.second?.filterMedia(title, year, lastSeason) == true }
|
||||||
|
}
|
||||||
|
|
||||||
|
val detailDoc = app.get(script?.first ?: return).document
|
||||||
|
|
||||||
|
val iframe =
|
||||||
|
detailDoc.select("div.entry-content p").map { it }
|
||||||
|
.filter { it.text().filterIframe(season, year) }
|
||||||
|
.mapNotNull {
|
||||||
|
if (season == null) {
|
||||||
|
Triple(
|
||||||
|
it.ownText(),
|
||||||
|
it.selectFirst("span")?.text(),
|
||||||
|
it.nextElementSibling()?.select("a")?.attr("href")
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Triple(
|
||||||
|
it.ownText(),
|
||||||
|
it.selectFirst("span")?.text(),
|
||||||
|
it.nextElementSibling()?.select("a:contains(Episode $episode)")
|
||||||
|
?.attr("href")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe.apmap { (quality, size, link) ->
|
||||||
|
val res = app.get(link ?: return@apmap null).document
|
||||||
|
val base = getBaseUrl(link)
|
||||||
|
val bitLink =
|
||||||
|
res.selectFirst("a.btn.btn-outline-success")?.attr("href") ?: return@apmap null
|
||||||
|
val downLink =
|
||||||
|
app.get(fixUrl(bitLink, base)).document.selectFirst("div.mb-4 a")?.attr("href")
|
||||||
|
val mirrorLink = app.get(
|
||||||
|
downLink ?: return@apmap null
|
||||||
|
).document.selectFirst("form[method=post] a.btn.btn-primary")
|
||||||
|
?.attr("onclick")?.substringAfter("Openblank('")?.substringBefore("')")?.let {
|
||||||
|
app.get(it).document.selectFirst("script:containsData(input.value =)")
|
||||||
|
?.data()?.substringAfter("input.value = '")?.substringBefore("';")
|
||||||
|
}
|
||||||
|
|
||||||
|
val videoQuality = Regex("(\\d{3,4})p").find(quality)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
||||||
|
?: Qualities.Unknown.value
|
||||||
|
val videoSize = size?.substringBeforeLast("/")
|
||||||
|
callback.invoke(
|
||||||
|
ExtractorLink(
|
||||||
|
"UHDMovies [$videoSize]",
|
||||||
|
"UHDMovies [$videoSize]",
|
||||||
|
mirrorLink ?: return@apmap null,
|
||||||
|
"",
|
||||||
|
videoQuality
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class FilmxyCookies(
|
data class FilmxyCookies(
|
||||||
|
@ -1200,6 +1270,31 @@ data class FilmxyCookies(
|
||||||
val wSec: String? = null,
|
val wSec: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun String.filterIframe(seasonNum: Int?, year: Int?): Boolean {
|
||||||
|
return if (seasonNum != null) {
|
||||||
|
this.contains(Regex("(?i)(S0?$seasonNum)")) && !this.contains("Download", true)
|
||||||
|
} else {
|
||||||
|
this.contains("$year", true) && !this.contains("Download", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun String.filterMedia(title: String?, yearNum: Int?, seasonNum: Int?): Boolean {
|
||||||
|
return if (seasonNum != null) {
|
||||||
|
when {
|
||||||
|
seasonNum > 1 -> this.contains(Regex("(?i)(Season\\s0?1-0?$seasonNum)|(S0?1-S?0?$seasonNum)")) && this.contains(
|
||||||
|
"$title",
|
||||||
|
true
|
||||||
|
) && this.contains("$yearNum")
|
||||||
|
else -> this.contains(Regex("(?i)(Season\\s0?1)|(S0?1)")) && this.contains(
|
||||||
|
"$title",
|
||||||
|
true
|
||||||
|
) && this.contains("$yearNum")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.contains("$title", true) && this.contains("$yearNum")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): FilmxyCookies? {
|
suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): FilmxyCookies? {
|
||||||
|
|
||||||
val url = if (season == null) {
|
val url = if (season == null) {
|
||||||
|
|
|
@ -23,6 +23,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||||
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
|
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
|
||||||
import com.hexated.SoraExtractor.invoZoro
|
import com.hexated.SoraExtractor.invoZoro
|
||||||
import com.hexated.SoraExtractor.invokeLing
|
import com.hexated.SoraExtractor.invokeLing
|
||||||
|
import com.hexated.SoraExtractor.invokeUhdmovies
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
|
@ -69,6 +70,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val consumetZoroAPI = "https://api.consumet.org/anime/zoro"
|
const val consumetZoroAPI = "https://api.consumet.org/anime/zoro"
|
||||||
const val kissKhAPI = "https://kisskh.me"
|
const val kissKhAPI = "https://kisskh.me"
|
||||||
const val lingAPI = "https://ling-online.net"
|
const val lingAPI = "https://ling-online.net"
|
||||||
|
const val uhdmoviesAPI = "https://uhdmovies.site"
|
||||||
|
|
||||||
fun getType(t: String?): TvType {
|
fun getType(t: String?): TvType {
|
||||||
return when (t) {
|
return when (t) {
|
||||||
|
@ -209,6 +211,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
|
|
||||||
return if (type == TvType.TvSeries) {
|
return if (type == TvType.TvSeries) {
|
||||||
val episodes = mutableListOf<Episode>()
|
val episodes = mutableListOf<Episode>()
|
||||||
|
val lastSeason = res.seasons?.lastOrNull()?.seasonNumber
|
||||||
res.seasons?.apmap { season ->
|
res.seasons?.apmap { season ->
|
||||||
app.get("$tmdbAPI/${data.type}/${data.id}/season/${season.seasonNumber}?api_key=$apiKey")
|
app.get("$tmdbAPI/${data.type}/${data.id}/season/${season.seasonNumber}?api_key=$apiKey")
|
||||||
.parsedSafe<MediaDetailEpisodes>()?.episodes?.map { eps ->
|
.parsedSafe<MediaDetailEpisodes>()?.episodes?.map { eps ->
|
||||||
|
@ -223,7 +226,8 @@ open class SoraStream : TmdbProvider() {
|
||||||
year = season.airDate?.split("-")?.first()?.toIntOrNull(),
|
year = season.airDate?.split("-")?.first()?.toIntOrNull(),
|
||||||
orgTitle = orgTitle,
|
orgTitle = orgTitle,
|
||||||
show = show,
|
show = show,
|
||||||
airedYear = year
|
airedYear = year,
|
||||||
|
lastSeason = lastSeason
|
||||||
).toJson(),
|
).toJson(),
|
||||||
name = eps.name,
|
name = eps.name,
|
||||||
season = eps.seasonNumber,
|
season = eps.seasonNumber,
|
||||||
|
@ -342,9 +346,9 @@ open class SoraStream : TmdbProvider() {
|
||||||
{
|
{
|
||||||
invokeVidSrc(res.id, res.season, res.episode, subtitleCallback, callback)
|
invokeVidSrc(res.id, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
invokeOlgply(res.id, res.season, res.episode, callback)
|
// invokeOlgply(res.id, res.season, res.episode, callback)
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
|
@ -447,6 +451,17 @@ open class SoraStream : TmdbProvider() {
|
||||||
callback
|
callback
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
invokeUhdmovies(
|
||||||
|
res.title,
|
||||||
|
res.year,
|
||||||
|
res.season,
|
||||||
|
res.lastSeason,
|
||||||
|
res.episode,
|
||||||
|
subtitleCallback,
|
||||||
|
callback
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
@ -465,6 +480,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
val orgTitle: String? = null,
|
val orgTitle: String? = null,
|
||||||
val show: String? = null,
|
val show: String? = null,
|
||||||
val airedYear: Int? = null,
|
val airedYear: Int? = null,
|
||||||
|
val lastSeason: Int? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class Data(
|
data class Data(
|
||||||
|
|
|
@ -149,7 +149,7 @@ class WcofunProvider : MainAPI() {
|
||||||
"${this.name} ${source.second}",
|
"${this.name} ${source.second}",
|
||||||
"${this.name} ${source.second}",
|
"${this.name} ${source.second}",
|
||||||
"${it.server}/getvid?evid=${source.first}",
|
"${it.server}/getvid?evid=${source.first}",
|
||||||
mainUrl,
|
referer = mainUrl,
|
||||||
if (source.second == "HD") Qualities.P720.value else Qualities.P480.value
|
if (source.second == "HD") Qualities.P720.value else Qualities.P480.value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import com.lagradost.cloudstream3.gradle.CloudstreamExtension
|
import com.lagradost.cloudstream3.gradle.CloudstreamExtension
|
||||||
import com.android.build.gradle.BaseExtension
|
import com.android.build.gradle.BaseExtension
|
||||||
|
import java.util.Properties
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -47,6 +48,12 @@ subprojects {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 32
|
targetSdk = 32
|
||||||
|
|
||||||
|
// val properties = Properties()
|
||||||
|
// properties.load(project.rootProject.file("local.properties").inputStream())
|
||||||
|
//
|
||||||
|
// buildConfigField("String", "API_KEY", "\"${properties.getProperty("API_KEY")}\"")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
|
Loading…
Reference in a new issue