mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
[Sora] fixed Gdbot - enabled GMovies & FDMovies - added M4uhd
This commit is contained in:
parent
937e3d720a
commit
e9d716663c
5 changed files with 139 additions and 11 deletions
|
@ -1,5 +1,5 @@
|
||||||
// use an integer for version numbers
|
// use an integer for version numbers
|
||||||
version = 48
|
version = 49
|
||||||
|
|
||||||
|
|
||||||
cloudstream {
|
cloudstream {
|
||||||
|
|
|
@ -8,9 +8,9 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||||
import com.lagradost.nicehttp.Requests
|
import com.lagradost.nicehttp.Requests
|
||||||
import com.lagradost.nicehttp.Session
|
import com.lagradost.nicehttp.Session
|
||||||
import com.google.gson.JsonParser
|
import com.google.gson.JsonParser
|
||||||
|
import com.lagradost.cloudstream3.extractors.XStreamCdn
|
||||||
import com.lagradost.cloudstream3.network.CloudflareKiller
|
import com.lagradost.cloudstream3.network.CloudflareKiller
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import okhttp3.FormBody
|
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
|
||||||
val session = Session(Requests().baseClient)
|
val session = Session(Requests().baseClient)
|
||||||
|
@ -1343,7 +1343,7 @@ object SoraExtractor : SoraStream() {
|
||||||
iframe.apmap { (iframeLink, title) ->
|
iframe.apmap { (iframeLink, title) ->
|
||||||
val size = Regex("(?i)\\s(\\S+gb|mb)").find(title)?.groupValues?.getOrNull(1)
|
val size = Regex("(?i)\\s(\\S+gb|mb)").find(title)?.groupValues?.getOrNull(1)
|
||||||
val gdBotLink = extractGdbot(iframeLink)
|
val gdBotLink = extractGdbot(iframeLink)
|
||||||
val videoLink = extractDrivebot(gdBotLink ?: return@apmap null)
|
val videoLink = extractDirectDl(gdBotLink ?: return@apmap null)
|
||||||
|
|
||||||
callback.invoke(
|
callback.invoke(
|
||||||
ExtractorLink(
|
ExtractorLink(
|
||||||
|
@ -1386,7 +1386,7 @@ object SoraExtractor : SoraStream() {
|
||||||
iframe.apmap { (link, quality, size) ->
|
iframe.apmap { (link, quality, size) ->
|
||||||
val fdLink = bypassFdAds(link)
|
val fdLink = bypassFdAds(link)
|
||||||
val gdBotLink = extractGdbot(fdLink ?: return@apmap null)
|
val gdBotLink = extractGdbot(fdLink ?: return@apmap null)
|
||||||
val videoLink = extractDrivebot(gdBotLink ?: return@apmap null)
|
val videoLink = extractDirectDl(gdBotLink ?: return@apmap null)
|
||||||
|
|
||||||
callback.invoke(
|
callback.invoke(
|
||||||
ExtractorLink(
|
ExtractorLink(
|
||||||
|
@ -1401,7 +1401,100 @@ object SoraExtractor : SoraStream() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun invokeM4uhd(
|
||||||
|
title: String? = null,
|
||||||
|
year: Int? = null,
|
||||||
|
season: Int? = null,
|
||||||
|
episode: Int? = null,
|
||||||
|
subtitleCallback: (SubtitleFile) -> Unit,
|
||||||
|
callback: (ExtractorLink) -> Unit
|
||||||
|
) {
|
||||||
|
val res = app.get("$m4uhdAPI/search/${title.fixTitle()}.html").document
|
||||||
|
val scriptData = res.select("div.row div.item").map {
|
||||||
|
Triple(
|
||||||
|
it.selectFirst("img.imagecover")?.attr("title"),
|
||||||
|
it.selectFirst("div.jtip-top div:last-child")?.text(),
|
||||||
|
it.selectFirst("a")?.attr("href")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val script = if (scriptData.size == 1) {
|
||||||
|
scriptData.firstOrNull()
|
||||||
|
} else {
|
||||||
|
scriptData.find {
|
||||||
|
it.first?.contains(
|
||||||
|
"Watch Free ${title?.replace(":", "")}",
|
||||||
|
true
|
||||||
|
) == true && (it.first?.contains("$year") == true || it.second?.contains(
|
||||||
|
"$year"
|
||||||
|
) == true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val link = fixUrl(script?.third ?: return, m4uhdAPI)
|
||||||
|
val request = app.get(link)
|
||||||
|
var cookiesSet = request.headers.filter { it.first == "set-cookie" }
|
||||||
|
var xsrf = cookiesSet.find { it.second.contains("XSRF-TOKEN") }?.second?.substringAfter("XSRF-TOKEN=")
|
||||||
|
?.substringBefore(";")
|
||||||
|
var session = cookiesSet.find { it.second.contains("laravel_session") }?.second?.substringAfter("laravel_session=")
|
||||||
|
?.substringBefore(";")
|
||||||
|
|
||||||
|
val doc = request.document
|
||||||
|
val token = doc.selectFirst("meta[name=csrf-token]")?.attr("content")
|
||||||
|
val m4uData = if (season == null) {
|
||||||
|
doc.select("div.le-server span#fem").attr("data")
|
||||||
|
} else {
|
||||||
|
val episodeData = doc.selectFirst("div.col-lg-9.col-xl-9 p:matches((?i)S0?$season-E0?$episode$)") ?: return
|
||||||
|
val idepisode = episodeData.select("button").attr("idepisode") ?: return
|
||||||
|
val requestEmbed = app.post(
|
||||||
|
"$m4uhdAPI/ajaxtv",
|
||||||
|
data = mapOf(
|
||||||
|
"idepisode" to idepisode,
|
||||||
|
"_token" to "$token"
|
||||||
|
),
|
||||||
|
referer = link,
|
||||||
|
headers = mapOf(
|
||||||
|
"X-Requested-With" to "XMLHttpRequest",
|
||||||
|
),
|
||||||
|
cookies = mapOf(
|
||||||
|
"laravel_session" to "$session",
|
||||||
|
"XSRF-TOKEN" to "$xsrf",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
cookiesSet = requestEmbed.headers.filter { it.first == "set-cookie" }
|
||||||
|
xsrf = cookiesSet.find { it.second.contains("XSRF-TOKEN") }?.second?.substringAfter("XSRF-TOKEN=")
|
||||||
|
?.substringBefore(";")
|
||||||
|
session = cookiesSet.find { it.second.contains("laravel_session") }?.second?.substringAfter("laravel_session=")
|
||||||
|
?.substringBefore(";")
|
||||||
|
requestEmbed.document.select("span#fem").attr("data")
|
||||||
|
}
|
||||||
|
|
||||||
|
val iframe = app.post(
|
||||||
|
"$m4uhdAPI/ajax",
|
||||||
|
data = mapOf(
|
||||||
|
"m4u" to m4uData,
|
||||||
|
"_token" to "$token"
|
||||||
|
),
|
||||||
|
referer = link,
|
||||||
|
headers = mapOf(
|
||||||
|
"Accept" to "*/*",
|
||||||
|
"X-Requested-With" to "XMLHttpRequest",
|
||||||
|
),
|
||||||
|
cookies = mapOf(
|
||||||
|
"laravel_session" to "$session",
|
||||||
|
"XSRF-TOKEN" to "$xsrf",
|
||||||
|
),
|
||||||
|
).document.select("iframe").attr("src")
|
||||||
|
|
||||||
|
loadExtractor(iframe, m4uhdAPI, subtitleCallback, callback)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class StreamM4u: XStreamCdn() {
|
||||||
|
override val name: String = "StreamM4u"
|
||||||
|
override val mainUrl: String = "https://streamm4u.club"
|
||||||
}
|
}
|
||||||
|
|
||||||
data class UHDBackupUrl(
|
data class UHDBackupUrl(
|
||||||
|
@ -1557,3 +1650,7 @@ data class SourcesFwatayako(
|
||||||
data class DriveBotLink(
|
data class DriveBotLink(
|
||||||
@JsonProperty("url") val url: String? = null,
|
@JsonProperty("url") val url: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class DirectDl(
|
||||||
|
@JsonProperty("download_url") val download_url: String? = null,
|
||||||
|
)
|
|
@ -25,6 +25,7 @@ import com.hexated.SoraExtractor.invokeFDMovies
|
||||||
import com.hexated.SoraExtractor.invokeFwatayako
|
import com.hexated.SoraExtractor.invokeFwatayako
|
||||||
import com.hexated.SoraExtractor.invokeGMovies
|
import com.hexated.SoraExtractor.invokeGMovies
|
||||||
import com.hexated.SoraExtractor.invokeLing
|
import com.hexated.SoraExtractor.invokeLing
|
||||||
|
import com.hexated.SoraExtractor.invokeM4uhd
|
||||||
import com.hexated.SoraExtractor.invokeUhdmovies
|
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
|
||||||
|
@ -67,7 +68,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val uniqueStreamAPI = "https://uniquestream.net"
|
const val uniqueStreamAPI = "https://uniquestream.net"
|
||||||
const val filmxyAPI = "https://www.filmxy.vip"
|
const val filmxyAPI = "https://www.filmxy.vip"
|
||||||
const val kimcartoonAPI = "https://kimcartoon.li"
|
const val kimcartoonAPI = "https://kimcartoon.li"
|
||||||
const val xMovieAPI = "https://xemovies.net"
|
const val xMovieAPI = "https://xemovies.to"
|
||||||
const val consumetFlixhqAPI = "https://api.consumet.org/movies/flixhq"
|
const val consumetFlixhqAPI = "https://api.consumet.org/movies/flixhq"
|
||||||
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"
|
||||||
|
@ -76,6 +77,7 @@ open class SoraStream : TmdbProvider() {
|
||||||
const val fwatayakoAPI = "https://5100.svetacdn.in"
|
const val fwatayakoAPI = "https://5100.svetacdn.in"
|
||||||
const val gMoviesAPI = "https://gdrivemovies.xyz"
|
const val gMoviesAPI = "https://gdrivemovies.xyz"
|
||||||
const val fdMoviesAPI = "https://freedrivemovie.com"
|
const val fdMoviesAPI = "https://freedrivemovie.com"
|
||||||
|
const val m4uhdAPI = "https://m4uhd.tv"
|
||||||
|
|
||||||
fun getType(t: String?): TvType {
|
fun getType(t: String?): TvType {
|
||||||
return when (t) {
|
return when (t) {
|
||||||
|
@ -420,12 +422,15 @@ open class SoraStream : TmdbProvider() {
|
||||||
{
|
{
|
||||||
invokeFwatayako(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
invokeFwatayako(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// if(!res.isAnime) invokeGMovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
|
if(!res.isAnime) invokeGMovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
|
||||||
// },
|
},
|
||||||
// {
|
{
|
||||||
// if(!res.isAnime) invokeFDMovies(res.title, res.season, res.episode, subtitleCallback, callback)
|
if(!res.isAnime) invokeFDMovies(res.title, res.season, res.episode, subtitleCallback, callback)
|
||||||
// },
|
},
|
||||||
|
{
|
||||||
|
invokeM4uhd(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -10,5 +10,6 @@ class SoraStreamPlugin: Plugin() {
|
||||||
override fun load(context: Context) {
|
override fun load(context: Context) {
|
||||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||||
registerMainAPI(SoraStream())
|
registerMainAPI(SoraStream())
|
||||||
|
registerExtractorAPI(StreamM4u())
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,9 +11,12 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.Qualities
|
import com.lagradost.cloudstream3.utils.Qualities
|
||||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||||
|
import com.lagradost.nicehttp.RequestBodyTypes
|
||||||
import com.lagradost.nicehttp.requestCreator
|
import com.lagradost.nicehttp.requestCreator
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
data class FilmxyCookies(
|
data class FilmxyCookies(
|
||||||
|
@ -136,6 +139,28 @@ suspend fun extractGdbot(url: String): String? {
|
||||||
return requestFile.selectFirst("div.mt-8 a.float-right")?.attr("href")
|
return requestFile.selectFirst("div.mt-8 a.float-right")?.attr("href")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun extractDirectDl(url: String): String? {
|
||||||
|
val iframe = app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(Direct DL)")?.attr("href")
|
||||||
|
val request = app.get(iframe ?: return null)
|
||||||
|
val driveDoc = request.document
|
||||||
|
val token = driveDoc.select("section#generate_url").attr("data-token")
|
||||||
|
val uid = driveDoc.select("section#generate_url").attr("data-uid")
|
||||||
|
|
||||||
|
val ssid = request.cookies["PHPSESSID"]
|
||||||
|
val body = """{"type":"DOWNLOAD_GENERATE","payload":{"uid":"$uid","access_token":"$token"}}""".toRequestBody(
|
||||||
|
RequestBodyTypes.JSON.toMediaTypeOrNull()
|
||||||
|
)
|
||||||
|
|
||||||
|
val json = app.post(
|
||||||
|
"https://rajbetmovies.com/action", requestBody = body, headers = mapOf(
|
||||||
|
"Accept" to "application/json, text/plain, */*",
|
||||||
|
"Cookie" to "PHPSESSID=$ssid",
|
||||||
|
"X-Requested-With" to "xmlhttprequest"
|
||||||
|
), referer = request.url
|
||||||
|
).text
|
||||||
|
return tryParseJson<DirectDl>(json)?.download_url
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun extractDrivebot(url: String): String? {
|
suspend fun extractDrivebot(url: String): String? {
|
||||||
val iframeGdbot =
|
val iframeGdbot =
|
||||||
app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(Drivebot)")
|
app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(Drivebot)")
|
||||||
|
|
Loading…
Reference in a new issue