diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 383b1239..cfbc4520 100644 --- a/SoraStream/build.gradle.kts +++ b/SoraStream/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 63 +version = 64 cloudstream { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 7ceaf6d0..c6e84e33 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1517,6 +1517,98 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeMoviesbay( + title: String? = null, + year: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val url = + "https://sheets.googleapis.com/v4/spreadsheets/12RD3HX3NkSiCyqQJxemyS8W0R9B7J4VBl35uLBa5W0E/values/main?alt=json&key=AIzaSyA_ZY8GYxyUZYlcKGkDIHuku_gmE4z-AHQ" + val json = app.get(url, referer = "$moviesbayAPI/") + .parsedSafe()?.values + + val media = json?.find { it.first() == "${title.fixTitle()}-$year" } + + media?.filter { it.startsWith("https://drive.google.com") }?.apmap { + val index = media.indexOf(it) + val size = media[index.minus(1)] + val quality = media[index.minus(2)] + val qualityName = media[index.minus(3)] + + val doc = app.get(it).document + val form = doc.select("form#download-form").attr("action") + val uc = doc.select("input#uc-download-link").attr("value") + val link = app.post( + form, data = mapOf( + "uc-download-link" to uc + ) + ).url + + callback.invoke( + ExtractorLink( + "Moviesbay $qualityName [$size]", + "Moviesbay $qualityName [$size]", + link, + "", + getQualityFromName(quality) + ) + ) + + } + } + + suspend fun invokeMoviezAdd( + title: String? = null, + year: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val doc = app.get("$moviezAddAPI/?s=$title").document + + val matchMedia = doc.select("article.mh-loop-item").map { + it.select("a").attr("href") to it.select("a").text() + }.find { it.second.contains("$title", true) && it.first.contains("$year") } + + val detailLink = + app.get(matchMedia?.first ?: return).document.selectFirst("a#jake1")?.attr("href") + + val iframeDoc = app.get(detailLink ?: return).document + + val media = iframeDoc.selectFirst("div.entry-content pre span")?.text()?.split("|") + ?.map { it.trim() } + + media?.apmapIndexed { index, name -> + delay(1000) + val link = iframeDoc.select("div.entry-content pre")[index.plus(1)].selectFirst("a") + ?.attr("href") ?: return@apmapIndexed null + val token = + app.get(link).document.select("input[name=_csrf_token_645a83a41868941e4692aa31e7235f2]") + .attr("value") + val shortLink = app.post( + link, + data = mapOf("_csrf_token_645a83a41868941e4692aa31e7235f2" to token) + ).document.selectFirst("a[rel=nofollow]")?.attr("href") + +// val videoUrl = extractRebrandly(shortLink ?: return@apmapIndexed null ) + val quality = Regex("([0-9]{3,4})p").find(name)?.groupValues?.getOrNull(1)?.toIntOrNull() + val qualityName = name.replace("${quality}p", "").trim() + + callback.invoke( + ExtractorLink( + "MoviezAdd $qualityName", + "MoviezAdd $qualityName", + shortLink ?: return@apmapIndexed null, + "", + quality ?: Qualities.Unknown.value + ) + ) + + } + + + } + } class StreamM4u : XStreamCdn() { @@ -1535,6 +1627,10 @@ data class UHDBackupUrl( @JsonProperty("url") val url: String? = null, ) +data class MoviesbayValues( + @JsonProperty("values") val values: List>? = arrayListOf(), +) + data class HdMovieBoxSource( @JsonProperty("videoUrl") val videoUrl: String? = null, @JsonProperty("videoServer") val videoServer: String? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index bd7ca745..873d34c3 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -26,6 +26,8 @@ import com.hexated.SoraExtractor.invokeGMovies import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeLing import com.hexated.SoraExtractor.invokeM4uhd +import com.hexated.SoraExtractor.invokeMoviesbay +import com.hexated.SoraExtractor.invokeMoviezAdd import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeZoro @@ -86,6 +88,8 @@ open class SoraStream : TmdbProvider() { const val fdMoviesAPI = "https://freedrivemovie.com" const val m4uhdAPI = "https://m4uhd.tv" const val tvMoviesAPI = "https://www.tvseriesnmovies.com" + const val moviezAddAPI = "https://moviezaddiction.bloginguru.info" + const val moviesbayAPI = "https://moviesbay.live" fun getType(t: String?): TvType { return when (t) { @@ -241,7 +245,7 @@ open class SoraStream : TmdbProvider() { newTvSeriesLoadResponse( title, url, - if(isAnime) TvType.Anime else TvType.TvSeries, + if (isAnime) TvType.Anime else TvType.TvSeries, episodes ) { this.posterUrl = poster @@ -470,6 +474,22 @@ open class SoraStream : TmdbProvider() { { invokeTvMovies(res.title, res.season, res.episode, subtitleCallback, callback) }, + { + if (res.season == null) invokeMoviesbay( + res.title, + res.year, + subtitleCallback, + callback + ) + }, + { + if (res.season == null) invokeMoviezAdd( + res.title, + res.year, + subtitleCallback, + callback + ) + }, ) return true