sora: fix m4uhd

This commit is contained in:
lisa 2023-12-23 09:16:09 +07:00
parent 928db8c7ff
commit 211c58b0ef
9 changed files with 103 additions and 138 deletions

View file

@ -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: |

View file

@ -1,5 +1,5 @@
// use an integer for version numbers
version = 17
version = 18
cloudstream {

View file

@ -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")

View file

@ -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")}\"")

View file

@ -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() {

View file

@ -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
)
)
)
}
}

View file

@ -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,
)
}
}

View file

@ -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

View file

@ -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