[Sora] fixed Gdbot - enabled GMovies & FDMovies - added M4uhd

This commit is contained in:
hexated 2022-12-09 15:44:01 +07:00
parent 937e3d720a
commit e9d716663c
5 changed files with 139 additions and 11 deletions

View file

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

View file

@ -8,9 +8,9 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.nicehttp.Requests
import com.lagradost.nicehttp.Session
import com.google.gson.JsonParser
import com.lagradost.cloudstream3.extractors.XStreamCdn
import com.lagradost.cloudstream3.network.CloudflareKiller
import kotlinx.coroutines.delay
import okhttp3.FormBody
import okhttp3.RequestBody.Companion.toRequestBody
val session = Session(Requests().baseClient)
@ -1343,7 +1343,7 @@ object SoraExtractor : SoraStream() {
iframe.apmap { (iframeLink, title) ->
val size = Regex("(?i)\\s(\\S+gb|mb)").find(title)?.groupValues?.getOrNull(1)
val gdBotLink = extractGdbot(iframeLink)
val videoLink = extractDrivebot(gdBotLink ?: return@apmap null)
val videoLink = extractDirectDl(gdBotLink ?: return@apmap null)
callback.invoke(
ExtractorLink(
@ -1386,7 +1386,7 @@ object SoraExtractor : SoraStream() {
iframe.apmap { (link, quality, size) ->
val fdLink = bypassFdAds(link)
val gdBotLink = extractGdbot(fdLink ?: return@apmap null)
val videoLink = extractDrivebot(gdBotLink ?: return@apmap null)
val videoLink = extractDirectDl(gdBotLink ?: return@apmap null)
callback.invoke(
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(
@ -1556,4 +1649,8 @@ data class SourcesFwatayako(
data class DriveBotLink(
@JsonProperty("url") val url: String? = null,
)
data class DirectDl(
@JsonProperty("download_url") val download_url: String? = null,
)

View file

@ -25,6 +25,7 @@ import com.hexated.SoraExtractor.invokeFDMovies
import com.hexated.SoraExtractor.invokeFwatayako
import com.hexated.SoraExtractor.invokeGMovies
import com.hexated.SoraExtractor.invokeLing
import com.hexated.SoraExtractor.invokeM4uhd
import com.hexated.SoraExtractor.invokeUhdmovies
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.toJson
@ -67,7 +68,7 @@ open class SoraStream : TmdbProvider() {
const val uniqueStreamAPI = "https://uniquestream.net"
const val filmxyAPI = "https://www.filmxy.vip"
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 consumetZoroAPI = "https://api.consumet.org/anime/zoro"
const val kissKhAPI = "https://kisskh.me"
@ -76,6 +77,7 @@ open class SoraStream : TmdbProvider() {
const val fwatayakoAPI = "https://5100.svetacdn.in"
const val gMoviesAPI = "https://gdrivemovies.xyz"
const val fdMoviesAPI = "https://freedrivemovie.com"
const val m4uhdAPI = "https://m4uhd.tv"
fun getType(t: String?): TvType {
return when (t) {
@ -420,12 +422,15 @@ open class SoraStream : TmdbProvider() {
{
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) invokeFDMovies(res.title, 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)
},
{
invokeM4uhd(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
}
)
return true

View file

@ -10,5 +10,6 @@ class SoraStreamPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(SoraStream())
registerExtractorAPI(StreamM4u())
}
}

View file

@ -11,9 +11,12 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.nicehttp.RequestBodyTypes
import com.lagradost.nicehttp.requestCreator
import okhttp3.FormBody
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import java.net.URI
data class FilmxyCookies(
@ -136,6 +139,28 @@ suspend fun extractGdbot(url: String): String? {
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? {
val iframeGdbot =
app.get(url).document.selectFirst("li.flex.flex-col.py-6 a:contains(Drivebot)")