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
|
||||
|
||||
description = "Premium porn with 4K support (use VPN if links not working)"
|
||||
authors = listOf("Hexated")
|
||||
authors = listOf("Sora")
|
||||
|
||||
/**
|
||||
* Status int as the following:
|
||||
|
|
|
@ -7,7 +7,7 @@ cloudstream {
|
|||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
// description = "Lorem Ipsum"
|
||||
authors = listOf("Hexated")
|
||||
authors = listOf("Sora")
|
||||
|
||||
/**
|
||||
* Status int as the following:
|
||||
|
|
|
@ -6,7 +6,7 @@ cloudstream {
|
|||
language = "en"
|
||||
// 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")
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,7 @@ cloudstream {
|
|||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
description = "Series porn (use VPN if links not working)"
|
||||
authors = listOf("Hexated")
|
||||
authors = listOf("Sora")
|
||||
|
||||
/**
|
||||
* Status int as the following:
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// use an integer for version numbers
|
||||
version = 32
|
||||
version = 33
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "en"
|
||||
// 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")
|
||||
|
||||
/**
|
||||
|
|
|
@ -1163,18 +1163,13 @@ object SoraExtractor : SoraStream() {
|
|||
|
||||
val source = app.get(iframe ?: 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(
|
||||
ExtractorLink(
|
||||
"Ling",
|
||||
"Ling",
|
||||
link,
|
||||
"$lingAPI/",
|
||||
quality,
|
||||
Qualities.Unknown.value,
|
||||
headers = mapOf(
|
||||
"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(
|
||||
|
@ -1200,6 +1270,31 @@ data class FilmxyCookies(
|
|||
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? {
|
||||
|
||||
val url = if (season == null) {
|
||||
|
|
|
@ -23,6 +23,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
|||
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
|
||||
import com.hexated.SoraExtractor.invoZoro
|
||||
import com.hexated.SoraExtractor.invokeLing
|
||||
import com.hexated.SoraExtractor.invokeUhdmovies
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
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 kissKhAPI = "https://kisskh.me"
|
||||
const val lingAPI = "https://ling-online.net"
|
||||
const val uhdmoviesAPI = "https://uhdmovies.site"
|
||||
|
||||
fun getType(t: String?): TvType {
|
||||
return when (t) {
|
||||
|
@ -209,6 +211,7 @@ open class SoraStream : TmdbProvider() {
|
|||
|
||||
return if (type == TvType.TvSeries) {
|
||||
val episodes = mutableListOf<Episode>()
|
||||
val lastSeason = res.seasons?.lastOrNull()?.seasonNumber
|
||||
res.seasons?.apmap { season ->
|
||||
app.get("$tmdbAPI/${data.type}/${data.id}/season/${season.seasonNumber}?api_key=$apiKey")
|
||||
.parsedSafe<MediaDetailEpisodes>()?.episodes?.map { eps ->
|
||||
|
@ -223,7 +226,8 @@ open class SoraStream : TmdbProvider() {
|
|||
year = season.airDate?.split("-")?.first()?.toIntOrNull(),
|
||||
orgTitle = orgTitle,
|
||||
show = show,
|
||||
airedYear = year
|
||||
airedYear = year,
|
||||
lastSeason = lastSeason
|
||||
).toJson(),
|
||||
name = eps.name,
|
||||
season = eps.seasonNumber,
|
||||
|
@ -342,9 +346,9 @@ open class SoraStream : TmdbProvider() {
|
|||
{
|
||||
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)
|
||||
},
|
||||
|
@ -447,6 +451,17 @@ open class SoraStream : TmdbProvider() {
|
|||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeUhdmovies(
|
||||
res.title,
|
||||
res.year,
|
||||
res.season,
|
||||
res.lastSeason,
|
||||
res.episode,
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
return true
|
||||
|
@ -465,6 +480,7 @@ open class SoraStream : TmdbProvider() {
|
|||
val orgTitle: String? = null,
|
||||
val show: String? = null,
|
||||
val airedYear: Int? = null,
|
||||
val lastSeason: Int? = null,
|
||||
)
|
||||
|
||||
data class Data(
|
||||
|
|
|
@ -149,7 +149,7 @@ class WcofunProvider : MainAPI() {
|
|||
"${this.name} ${source.second}",
|
||||
"${this.name} ${source.second}",
|
||||
"${it.server}/getvid?evid=${source.first}",
|
||||
mainUrl,
|
||||
referer = mainUrl,
|
||||
if (source.second == "HD") Qualities.P720.value else Qualities.P480.value
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import com.lagradost.cloudstream3.gradle.CloudstreamExtension
|
||||
import com.android.build.gradle.BaseExtension
|
||||
import java.util.Properties
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
|
@ -47,6 +48,12 @@ subprojects {
|
|||
defaultConfig {
|
||||
minSdk = 21
|
||||
targetSdk = 32
|
||||
|
||||
// val properties = Properties()
|
||||
// properties.load(project.rootProject.file("local.properties").inputStream())
|
||||
//
|
||||
// buildConfigField("String", "API_KEY", "\"${properties.getProperty("API_KEY")}\"")
|
||||
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
|
|
Loading…
Reference in a new issue