[Sora-test] adding TVMovies

This commit is contained in:
hexated 2022-12-10 19:25:28 +07:00
parent 85d2e334f6
commit 62506de4da
3 changed files with 141 additions and 15 deletions

View file

@ -12,6 +12,7 @@ import com.lagradost.cloudstream3.extractors.XStreamCdn
import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.cloudstream3.network.CloudflareKiller
import com.lagradost.nicehttp.RequestBodyTypes import com.lagradost.nicehttp.RequestBodyTypes
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
@ -792,25 +793,34 @@ object SoraExtractor : SoraStream() {
} }
val script = if (scriptData.size == 1) { val script = if (scriptData.size == 1) {
scriptData.first() scriptData.firstOrNull()
} else { } else {
scriptData.first { scriptData.find {
if (season == null) { when (season) {
it.first.equals( null -> {
title, it.first.equals(
true title,
) && it.second == year true
} else { ) && it.second == year
it.first.contains( }
"$title", 1 -> {
true it.first.contains(
) && (it.second == year || it.first.contains("Season $season", true)) "$title",
true
) && (it.second == year || it.first.contains("Season $season", true))
}
else -> {
it.first.contains(
"$title",
true
) && it.second == year && it.first.contains("Season $season", true)
}
} }
} }
} }
val id = script.third?.last() val id = script?.third?.last() ?: return
val type = script.third?.get(2) val type = script.third?.get(2) ?: return
val jsonResponse = app.get( val jsonResponse = app.get(
"$vipAPI/movieDrama/get?id=${id}&category=${type}", "$vipAPI/movieDrama/get?id=${id}&category=${type}",
@ -1491,6 +1501,81 @@ object SoraExtractor : SoraStream() {
} }
suspend fun invokeTvMovies(
title: String? = null,
season: Int? = null,
episode: Int? = null,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
) {
val fixTitle = title.fixTitle()
val url = if (season == null) {
"$tvMoviesAPI/show/$fixTitle"
} else {
"$tvMoviesAPI/show/index-of-$fixTitle"
}
val server = getTvMoviesServer(url, season, episode) ?: return
val request = session.get(server.second ?: return, referer = "$tvMoviesAPI/")
var filehosting = session.baseClient.cookieJar.loadForRequest(url.toHttpUrl())
.find { it.name == "filehosting" }?.value
val iframe = request.document.findTvMoviesIframe()
delay(10000)
val request2 = session.get(
iframe ?: return, referer = url, headers = mapOf(
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Connection" to "keep-alive",
"Cookie" to "filehosting=$filehosting",
)
)
filehosting = session.baseClient.cookieJar.loadForRequest(url.toHttpUrl())
.find { it.name == "filehosting" }?.value
val iframe2 = request2.document.findTvMoviesIframe()
delay(11000)
val request3 = session.get(
iframe2 ?: return, referer = iframe, headers = mapOf(
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Connection" to "keep-alive",
"Cookie" to "filehosting=$filehosting",
)
)
filehosting = session.baseClient.cookieJar.loadForRequest(url.toHttpUrl())
.find { it.name == "filehosting" }?.value
val response = request3.document
val videoLink =
response.selectFirst("button.btn.btn--primary")?.attr("onclick")
?.substringAfter("location = '")?.substringBefore("';")?.let {
app.get(
it, referer = iframe2, headers = mapOf(
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Connection" to "keep-alive",
"Cookie" to "filehosting=$filehosting",
)
).url
}
val quality =
Regex("([0-9]{3,4})p").find(server.first)?.groupValues?.getOrNull(1)?.toIntOrNull()
val size =
response.selectFirst("ul.row--list li:contains(Filesize) span:last-child")
?.text()
callback.invoke(
ExtractorLink(
"TVMovies [$size]",
"TVMovies [$size]",
videoLink ?: return,
"",
quality ?: Qualities.Unknown.value
)
)
}
} }
class StreamM4u: XStreamCdn() { class StreamM4u: XStreamCdn() {

View file

@ -26,6 +26,7 @@ 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.invokeM4uhd
import com.hexated.SoraExtractor.invokeTvMovies
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
@ -78,6 +79,7 @@ open class SoraStream : TmdbProvider() {
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" const val m4uhdAPI = "https://m4uhd.tv"
const val tvMoviesAPI = "https://www.tvseriesnmovies.com"
fun getType(t: String?): TvType { fun getType(t: String?): TvType {
return when (t) { return when (t) {
@ -430,7 +432,10 @@ open class SoraStream : TmdbProvider() {
// }, // },
{ {
invokeM4uhd(res.title, res.year, res.season, res.episode, subtitleCallback, callback) invokeM4uhd(res.title, res.year, res.season, res.episode, subtitleCallback, callback)
} },
{
invokeTvMovies(res.title, res.season, res.episode, subtitleCallback, callback)
},
) )
return true return true

View file

@ -17,6 +17,7 @@ import okhttp3.FormBody
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.RequestBody.Companion.toRequestBody
import org.jsoup.nodes.Document
import java.net.URI import java.net.URI
data class FilmxyCookies( data class FilmxyCookies(
@ -222,6 +223,36 @@ suspend fun bypassFdAds(url: String): String? {
return app.get(finalLink ?: return null, verify = false).url return app.get(finalLink ?: return null, verify = false).url
} }
suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair<String, String?>? {
val req = app.get(url)
if(!req.isSuccessful) return null
val doc = req.document
return if (season == null) {
doc.select("table.wp-block-table tr:last-child td:first-child").text() to
doc.selectFirst("table.wp-block-table tr a")?.attr("href").let { link ->
app.get(link ?: return null).document.select("div#text-url a")
.mapIndexed { index, element ->
element.attr("href") to element.parent()?.textNodes()?.getOrNull(index)
?.text()
}.filter { it.second?.contains("Subtitles", true) == false }
.map { it.first }
}.lastOrNull()
} else {
doc.select("div.vc_tta-panels div#Season-$season table.wp-block-table tr:last-child td:first-child")
.text() to
doc.select("div.vc_tta-panels div#Season-$season table.wp-block-table tr a")
.mapNotNull { ele ->
app.get(ele.attr("href")).document.select("div#text-url a")
.mapIndexed { index, element ->
element.attr("href") to element.parent()?.textNodes()
?.getOrNull(index)?.text()
}.find { it.second?.contains("Episode $episode", true) == true }?.first
}.lastOrNull()
}
}
suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): FilmxyCookies? { suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): FilmxyCookies? {
val url = if (season == null) { val url = if (season == null) {
@ -269,6 +300,11 @@ suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): Filmx
return FilmxyCookies(phpsessid, wLog, wSec) return FilmxyCookies(phpsessid, wLog, wSec)
} }
fun Document.findTvMoviesIframe(): String? {
return this.selectFirst("script:containsData(var seconds)")?.data()?.substringAfter("href='")
?.substringBefore("'>")
}
fun String?.fixTitle(): String? { fun String?.fixTitle(): String? {
return this?.replace(Regex("[!%:]|( &)"), "")?.replace(" ", "-")?.lowercase() return this?.replace(Regex("[!%:]|( &)"), "")?.replace(" ", "-")?.lowercase()
?.replace("--", "-") ?.replace("--", "-")