mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
sora: fix m4uhd
This commit is contained in:
parent
928db8c7ff
commit
211c58b0ef
9 changed files with 103 additions and 138 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -55,7 +55,6 @@ jobs:
|
|||
SFMOVIES_API: ${{ secrets.SFMOVIES_API }}
|
||||
CINEMATV_API: ${{ secrets.CINEMATV_API }}
|
||||
OMOVIES_API: ${{ secrets.OMOVIES_API }}
|
||||
FEBBOX_API: ${{ secrets.FEBBOX_API }}
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE/src
|
||||
echo TMDB_API=$TMDB_API >> local.properties
|
||||
|
@ -71,7 +70,6 @@ jobs:
|
|||
echo SFMOVIES_API=$SFMOVIES_API >> local.properties
|
||||
echo CINEMATV_API=$CINEMATV_API >> local.properties
|
||||
echo OMOVIES_API=$OMOVIES_API >> local.properties
|
||||
echo FEBBOX_API=$FEBBOX_API >> local.properties
|
||||
|
||||
- name: Build Plugins
|
||||
run: |
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 17
|
||||
version = 18
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
|
@ -9,7 +9,7 @@ import org.jsoup.nodes.Element
|
|||
|
||||
class LayarKacaProvider : MainAPI() {
|
||||
override var mainUrl = "https://tv6.lk21official.wiki"
|
||||
private var seriesUrl = "https://tv8.nontondrama.click/"
|
||||
private var seriesUrl = "https://tv8.nontondrama.click"
|
||||
override var name = "LayarKaca"
|
||||
override val hasMainPage = true
|
||||
override var lang = "id"
|
||||
|
@ -40,6 +40,7 @@ class LayarKacaProvider : MainAPI() {
|
|||
}
|
||||
|
||||
private suspend fun getProperLink(url: String): String? {
|
||||
if(url.startsWith(seriesUrl)) return url
|
||||
val res = app.get(url).document
|
||||
return if (res.select("title").text().contains("- Nontondrama", true)) {
|
||||
res.selectFirst("div#content a")?.attr("href")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
// use an integer for version numbers
|
||||
version = 207
|
||||
version = 208
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
|
@ -9,7 +9,6 @@ android {
|
|||
properties.load(project.rootProject.file("local.properties").inputStream())
|
||||
|
||||
buildConfigField("String", "TMDB_API", "\"${properties.getProperty("TMDB_API")}\"")
|
||||
buildConfigField("String", "FEBBOX_API", "\"${properties.getProperty("FEBBOX_API")}\"")
|
||||
buildConfigField("String", "OMOVIES_API", "\"${properties.getProperty("OMOVIES_API")}\"")
|
||||
buildConfigField("String", "CINEMATV_API", "\"${properties.getProperty("CINEMATV_API")}\"")
|
||||
buildConfigField("String", "SFMOVIES_API", "\"${properties.getProperty("SFMOVIES_API")}\"")
|
||||
|
|
|
@ -124,8 +124,8 @@ open class Playm4u : ExtractorApi() {
|
|||
return "$this\\s*=\\s*[\"'](\\S+)[\"'];".toRegex().find(data)?.groupValues?.get(1) ?: ""
|
||||
}
|
||||
|
||||
private fun String.toLanguage() : String {
|
||||
return if(this == "EN") "English" else this
|
||||
private fun String.toLanguage(): String {
|
||||
return if (this == "EN") "English" else this
|
||||
}
|
||||
|
||||
data class Source(
|
||||
|
@ -209,7 +209,10 @@ open class VCloud : ExtractorApi() {
|
|||
)
|
||||
).document.select("p.text-success ~ a").apmap {
|
||||
val link = it.attr("href")
|
||||
if (link.contains("workers.dev") || it.text().contains("[Server : 1]") || link.contains("/dl.php?")) {
|
||||
if (link.contains("workers.dev") || it.text().contains("[Server : 1]") || link.contains(
|
||||
"/dl.php?"
|
||||
)
|
||||
) {
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
|
@ -221,7 +224,7 @@ open class VCloud : ExtractorApi() {
|
|||
)
|
||||
)
|
||||
} else {
|
||||
val direct = if(link.contains("gofile.io")) app.get(link).url else link
|
||||
val direct = if (link.contains("gofile.io")) app.get(link).url else link
|
||||
loadExtractor(direct, referer, subtitleCallback, callback)
|
||||
}
|
||||
}
|
||||
|
@ -247,12 +250,14 @@ open class Streamruby : ExtractorApi() {
|
|||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val id = "/e/(\\w+)".toRegex().find(url)?.groupValues?.get(1) ?: return
|
||||
val response = app.post("$mainUrl/dl", data = mapOf(
|
||||
"op" to "embed",
|
||||
"file_code" to id,
|
||||
"auto" to "1",
|
||||
"referer" to "",
|
||||
), referer = referer)
|
||||
val response = app.post(
|
||||
"$mainUrl/dl", data = mapOf(
|
||||
"op" to "embed",
|
||||
"file_code" to id,
|
||||
"auto" to "1",
|
||||
"referer" to "",
|
||||
), referer = referer
|
||||
)
|
||||
val script = if (!getPacked(response.text).isNullOrEmpty()) {
|
||||
getAndUnpack(response.text)
|
||||
} else {
|
||||
|
@ -282,17 +287,25 @@ open class Uploadever : ExtractorApi() {
|
|||
) {
|
||||
var res = app.get(url, referer = referer).document
|
||||
val formUrl = res.select("form").attr("action")
|
||||
var formData = res.select("form input").associate { it.attr("name") to it.attr("value") }.filterKeys { it != "go" }
|
||||
var formData = res.select("form input").associate { it.attr("name") to it.attr("value") }
|
||||
.filterKeys { it != "go" }
|
||||
.toMutableMap()
|
||||
val formReq = app.post(formUrl, data = formData)
|
||||
|
||||
res = formReq.document
|
||||
val captchaKey = res.select("script[src*=https://www.google.com/recaptcha/api.js?render=]").attr("src").substringAfter("render=")
|
||||
val captchaKey =
|
||||
res.select("script[src*=https://www.google.com/recaptcha/api.js?render=]").attr("src")
|
||||
.substringAfter("render=")
|
||||
val token = getCaptchaToken(url, captchaKey, referer = "$mainUrl/")
|
||||
formData = res.select("form#down input").associate { it.attr("name") to it.attr("value") }.toMutableMap()
|
||||
formData = res.select("form#down input").associate { it.attr("name") to it.attr("value") }
|
||||
.toMutableMap()
|
||||
formData["adblock_detected"] = "0"
|
||||
formData["referer"] = url
|
||||
res = app.post(formReq.url, data = formData + mapOf("g-recaptcha-response" to "$token"), cookies = formReq.cookies).document
|
||||
res = app.post(
|
||||
formReq.url,
|
||||
data = formData + mapOf("g-recaptcha-response" to "$token"),
|
||||
cookies = formReq.cookies
|
||||
).document
|
||||
val video = res.select("div.download-button a.btn.btn-dow.recaptchav2").attr("href")
|
||||
|
||||
callback.invoke(
|
||||
|
@ -325,18 +338,7 @@ open class Netembed : ExtractorApi() {
|
|||
val script = getAndUnpack(response.text)
|
||||
val m3u8 = Regex("((https:|http:)//.*\\.m3u8)").find(script)?.groupValues?.getOrNull(1) ?: return
|
||||
|
||||
if(m3u8.startsWith("https://www.febbox.com")) {
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
m3u8,
|
||||
"$mainUrl/",
|
||||
getQuality(m3u8),
|
||||
INFER_TYPE
|
||||
)
|
||||
)
|
||||
} else {
|
||||
if (!m3u8.startsWith("https://www.febbox.com")) {
|
||||
M3u8Helper.generateM3u8(
|
||||
this.name,
|
||||
m3u8,
|
||||
|
@ -344,12 +346,6 @@ open class Netembed : ExtractorApi() {
|
|||
).forEach(callback)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getQuality(url: String) : Int {
|
||||
val res = app.get(url, referer = "$mainUrl/").text
|
||||
val regex = "#quality:\\s*(\\S+)".toRegex().find(res)?.groupValues?.get(1)
|
||||
return getQualityFromName(regex)
|
||||
}
|
||||
}
|
||||
|
||||
class Streamwish : Filesim() {
|
||||
|
|
|
@ -1354,14 +1354,14 @@ object SoraExtractor : SoraStream() {
|
|||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val slugTitle = title.createSlug()
|
||||
val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode)
|
||||
val req = app.get("$m4uhdAPI/search/${title.createSlug()}.html")
|
||||
val req = app.get("$m4uhdAPI/search/$slugTitle.html")
|
||||
val referer = getBaseUrl(req.url)
|
||||
val scriptData = req.document.select("div.row div.item").map { ele ->
|
||||
Triple(
|
||||
ele.select("div.tiptitle p").text(),
|
||||
ele.select("div.jtip-top div:last-child").text().substringBefore("–")
|
||||
.filter { it.isDigit() },
|
||||
ele.select("div.tiptitle p").text().substringBefore("(").trim().createSlug(),
|
||||
ele.select("div.jtip-top div:last-child").text().filter { it.isDigit() },
|
||||
ele.selectFirst("a")?.attr("href")
|
||||
)
|
||||
}
|
||||
|
@ -1370,7 +1370,7 @@ object SoraExtractor : SoraStream() {
|
|||
scriptData.firstOrNull()
|
||||
} else {
|
||||
scriptData.find {
|
||||
it.first.contains(Regex("(?i)$title \\($year\\s?\\)")) && if (season != null) it.third?.contains(
|
||||
it.first.equals(slugTitle) && it.second == "$year" && if (season != null) it.third?.contains(
|
||||
"-tvshow-"
|
||||
) == true else it.third?.contains("-movie-") == true
|
||||
}
|
||||
|
@ -2133,52 +2133,6 @@ object SoraExtractor : SoraStream() {
|
|||
|
||||
}
|
||||
|
||||
suspend fun invokeBlackvid(
|
||||
tmdbId: Int? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
val key = "b6055c533c19131a638c3d2299d525d5ec08a814"
|
||||
val url = if (season == null) {
|
||||
"$blackvidAPI/v3/movie/sources/$tmdbId?key=$key"
|
||||
} else {
|
||||
"$blackvidAPI/v3/tv/sources/$tmdbId/$season/$episode?key=$key"
|
||||
}
|
||||
|
||||
val res = request(url).peekBody(1024 * 512)
|
||||
val bytes = res.bytes().also { res.closeQuietly() }
|
||||
val data = bytes.decrypt("2378f8e4e844f2dc839ab48f66e00acc2305a401")
|
||||
val json = tryParseJson<BlackvidResponses>(data)
|
||||
|
||||
json?.sources?.map { source ->
|
||||
source.sources.map s@{ s ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"Blackvid",
|
||||
"Blackvid${source.label}",
|
||||
s.url ?: return@s,
|
||||
"https://blackvid.space/",
|
||||
if (s.quality.equals("4k")) Qualities.P2160.value else s.quality?.toIntOrNull()
|
||||
?: Qualities.P1080.value,
|
||||
INFER_TYPE
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
json?.subtitles?.map { sub ->
|
||||
subtitleCallback.invoke(
|
||||
SubtitleFile(
|
||||
sub.language.takeIf { it?.isNotEmpty() == true } ?: return@map,
|
||||
sub.url ?: return@map,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
suspend fun invokeShowflix(
|
||||
title: String? = null,
|
||||
year: Int? = null,
|
||||
|
@ -2312,31 +2266,62 @@ object SoraExtractor : SoraStream() {
|
|||
}
|
||||
|
||||
suspend fun invokeFebbox(
|
||||
imdbId: String? = null,
|
||||
title: String? = null,
|
||||
year: Int? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
val url = if (season == null) {
|
||||
"$febboxAPI/stream/movie/$imdbId.json"
|
||||
val showboxApi = "https://www.showbox.media"
|
||||
val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode)
|
||||
|
||||
val res = app.post(
|
||||
"$showboxApi/search/autocomplate2", data = mapOf(
|
||||
"keyword" to "$title"
|
||||
), headers = mapOf("X-Requested-With" to "XMLHttpRequest")
|
||||
).parsed<String>().let { Jsoup.parse(it) }
|
||||
|
||||
val mediaId = res.select("a.nav-item").find {
|
||||
it.select("h3.film-name").text()
|
||||
.equals(title, true) && it.select("div.film-infor > span:first-child").text()
|
||||
.contains(if (season == null) "$year" else "SS") && it.select("div.film-infor > span:last-child")
|
||||
.text()
|
||||
.equals(if (season == null) "Movie" else "TV")
|
||||
}?.attr("href")?.substringAfterLast("/")
|
||||
|
||||
val shareKey =
|
||||
app.get("$showboxApi/index/share_link?id=${mediaId ?: return}&type=${if (season == null) "1" else "2"}")
|
||||
.parsedSafe<FebboxResponse>()?.data?.link?.substringAfterLast("/")
|
||||
|
||||
val headers = mapOf("Accept-Language" to "en")
|
||||
val shareRes = app.get("$febboxAPI/file/file_share_list?share_key=${shareKey ?: return}", headers = headers)
|
||||
.parsedSafe<FebboxResponse>()?.data
|
||||
|
||||
val fids = if (season == null) {
|
||||
shareRes?.file_list
|
||||
} else {
|
||||
"$febboxAPI/stream/series/$imdbId:$season:$episode.json"
|
||||
val parentId = shareRes?.file_list?.find { it.file_name.equals("season $season", true) }?.fid
|
||||
app.get("$febboxAPI/file/file_share_list?share_key=${shareKey}&parent_id=$parentId&page=1", headers = headers)
|
||||
.parsedSafe<FebboxResponse>()?.data?.file_list?.filter {
|
||||
it.file_name?.contains(
|
||||
"s${seasonSlug}e${episodeSlug}",
|
||||
true
|
||||
) == true
|
||||
}
|
||||
}
|
||||
|
||||
val res = request(url).body
|
||||
val data = res.string().also { res.closeQuietly() }
|
||||
val video = tryParseJson<FebboxResponse>(data)?.streams?.find { it.url?.startsWith("https://www.febbox.com") == true }?.url
|
||||
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"Febbox",
|
||||
"Febbox",
|
||||
video ?: return,
|
||||
"",
|
||||
Qualities.P1080.value,
|
||||
INFER_TYPE
|
||||
fids?.mapIndexed { index, fileList ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"Febbox",
|
||||
"Febbox [Server $index]",
|
||||
"$febboxAPI/hls/main/${fileList.oss_fid}.m3u8",
|
||||
"",
|
||||
getIndexQuality(fileList.file_name),
|
||||
isM3u8 = true
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -334,26 +334,6 @@ data class EMovieTraks(
|
|||
@JsonProperty("label") val label: String? = null,
|
||||
)
|
||||
|
||||
data class BlackvidSubtitles(
|
||||
@JsonProperty("language") val language: String? = null,
|
||||
@JsonProperty("url") val url: String? = null,
|
||||
)
|
||||
|
||||
data class BlackvidSource(
|
||||
@JsonProperty("quality") var quality: String? = null,
|
||||
@JsonProperty("url") var url: String? = null,
|
||||
)
|
||||
|
||||
data class BlackvidSources(
|
||||
@JsonProperty("label") var label: String? = null,
|
||||
@JsonProperty("sources") var sources: ArrayList<BlackvidSource> = arrayListOf()
|
||||
)
|
||||
|
||||
data class BlackvidResponses(
|
||||
@JsonProperty("sources") var sources: ArrayList<BlackvidSources> = arrayListOf(),
|
||||
@JsonProperty("subtitles") var subtitles: ArrayList<BlackvidSubtitles> = arrayListOf()
|
||||
)
|
||||
|
||||
data class ShowflixResultsMovies(
|
||||
@JsonProperty("movieName") val movieName: String? = null,
|
||||
@JsonProperty("streamwish") val streamwish: String? = null,
|
||||
|
@ -464,9 +444,16 @@ data class AoneroomResponse(
|
|||
}
|
||||
|
||||
data class FebboxResponse(
|
||||
@JsonProperty("streams") val streams: ArrayList<Streams>? = arrayListOf(),
|
||||
@JsonProperty("data") val data: Data? = null,
|
||||
) {
|
||||
data class Streams(
|
||||
@JsonProperty("url") val url: String? = null,
|
||||
)
|
||||
data class Data(
|
||||
@JsonProperty("link") val link: String? = null,
|
||||
@JsonProperty("file_list") val file_list: ArrayList<FileList>? = arrayListOf(),
|
||||
) {
|
||||
data class FileList(
|
||||
@JsonProperty("fid") val fid: Long? = null,
|
||||
@JsonProperty("file_name") val file_name: String? = null,
|
||||
@JsonProperty("oss_fid") val oss_fid: Long? = null,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty
|
|||
import com.hexated.SoraExtractor.invoke2embed
|
||||
import com.hexated.SoraExtractor.invokeAnimes
|
||||
import com.hexated.SoraExtractor.invokeAoneroom
|
||||
import com.hexated.SoraExtractor.invokeBlackvid
|
||||
import com.hexated.SoraExtractor.invokeBollyMaza
|
||||
import com.hexated.SoraExtractor.invokeDbgo
|
||||
import com.hexated.SoraExtractor.invokeFilmxy
|
||||
|
@ -113,10 +112,9 @@ open class SoraStream : TmdbProvider() {
|
|||
const val dramadayAPI = "https://dramaday.me"
|
||||
const val animetoshoAPI = "https://animetosho.org"
|
||||
const val watchflxAPI = "https://watchflx.tv"
|
||||
const val blackvidAPI = "https://prod.api.blackvid.space"
|
||||
const val showflixAPI = "https://showflix.space"
|
||||
const val aoneroomAPI = "https://api3.aoneroom.com"
|
||||
const val febboxAPI = BuildConfig.FEBBOX_API
|
||||
const val febboxAPI = "https://www.febbox.com"
|
||||
|
||||
const val fdMoviesAPI = "https://freedrivemovie.lol"
|
||||
const val uhdmoviesAPI = "https://uhdmovies.zip"
|
||||
|
@ -364,8 +362,9 @@ open class SoraStream : TmdbProvider() {
|
|||
|
||||
argamap(
|
||||
{
|
||||
if (!res.isAnime) invokeFebbox(
|
||||
res.imdbId,
|
||||
invokeFebbox(
|
||||
res.title,
|
||||
res.year,
|
||||
res.season,
|
||||
res.episode,
|
||||
callback
|
||||
|
|
|
@ -3,7 +3,6 @@ package com.hexated
|
|||
import com.hexated.SoraExtractor.invoke2embed
|
||||
import com.hexated.SoraExtractor.invokeAnimes
|
||||
import com.hexated.SoraExtractor.invokeAoneroom
|
||||
import com.hexated.SoraExtractor.invokeBlackvid
|
||||
import com.hexated.SoraExtractor.invokeDbgo
|
||||
import com.hexated.SoraExtractor.invokeDoomovies
|
||||
import com.hexated.SoraExtractor.invokeDramaday
|
||||
|
@ -54,8 +53,9 @@ class SoraStreamLite : SoraStream() {
|
|||
|
||||
argamap(
|
||||
{
|
||||
if (!res.isAnime) invokeFebbox(
|
||||
res.imdbId,
|
||||
invokeFebbox(
|
||||
res.title,
|
||||
res.year,
|
||||
res.season,
|
||||
res.episode,
|
||||
callback
|
||||
|
|
Loading…
Reference in a new issue