diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 74dbdf5e..7601086f 100644 --- a/SoraStream/build.gradle.kts +++ b/SoraStream/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.konan.properties.Properties // use an integer for version numbers -version = 223 +version = 224 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 24749e70..3a5873df 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1307,51 +1307,6 @@ object SoraExtractor : SoraStream() { } } - suspend fun invokeGMovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - val fixTitle = title.createSlug() - val url = if (season == null || season == 1) { - "$gMoviesAPI/$fixTitle-$year" - } else { - "$gMoviesAPI/$fixTitle-$year-season-$season" - } - - val doc = app.get(url).document - - val iframe = (if (season == null) { - doc.select("div.is-content-justification-center div.wp-block-button").map { - it.select("a").attr("href") to it.text() - } - } else { - doc.select("div.is-content-justification-center").find { - it.previousElementSibling()?.text() - ?.contains(Regex("(?i)episode\\s?$episode")) == true - }?.select("div.wp-block-button")?.map { - it.select("a").attr("href") to it.text() - } - })?.filter { - it.second.contains(Regex("(?i)(4k|1080p)")) - } ?: return - - iframe.apmap { (iframeLink, title) -> - val size = Regex("(?i)\\s(\\S+gb|mb)").find(title)?.groupValues?.getOrNull(1) - loadCustomTagExtractor( - "[$size]", - iframeLink, - "$gMoviesAPI/", - subtitleCallback, - callback, - getIndexQuality(title) - ) - } - } - suspend fun invokeFDMovies( title: String? = null, season: Int? = null, @@ -1694,6 +1649,58 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeNepu( + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit + ) { + val slug = title?.createSlug() + val headers = mapOf( + "X-Requested-With" to "XMLHttpRequest" + ) + val data = app.get("$nepuAPI/ajax/posts?q=$title", headers = headers, referer = "$nepuAPI/") + .parsedSafe()?.data + + val media = + data?.find { it.url?.startsWith(if (season == null) "/movie/$slug-$year-" else "/serie/$slug-$year-") == true } + ?: data?.find { + (it.name.equals( + title, + true + ) && it.type == if (season == null) "Movie" else "Serie") + } + + if (media?.url == null) return + val mediaUrl = if (season == null) { + media.url + } else { + "${media.url}/season/$season/episode/$episode" + } + + val dataId = app.get(fixUrl(mediaUrl, nepuAPI)).document.selectFirst("a[data-embed]")?.attr("data-embed") ?: return + val res = app.post( + "$nepuAPI/ajax/embed", data = mapOf( + "id" to dataId + ), referer = mediaUrl, headers = headers + ).text + + val m3u8 = "(http[^\"]+)".toRegex().find(res)?.groupValues?.get(1) + + callback.invoke( + ExtractorLink( + "Nepu", + "Nepu", + m3u8 ?: return, + "$nepuAPI/", + Qualities.P1080.value, + INFER_TYPE + ) + ) + + } + suspend fun invokeMoflix( tmdbId: Int? = null, season: Int? = null, @@ -2156,6 +2163,7 @@ object SoraExtractor : SoraStream() { episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, + api: String = "https://parse.showflix.online" ) { val where = if (season == null) "movieName" else "seriesName" val classes = if (season == null) "movies" else "series" @@ -2172,12 +2180,12 @@ object SoraExtractor : SoraStream() { "_ApplicationId": "SHOWFLIXAPPID", "_JavaScriptKey": "SHOWFLIXMASTERKEY", "_ClientVersion": "js3.4.1", - "_InstallationId": "d92d98d3-fa49-4103-8dcf-6347c86942a7" + "_InstallationId": "58f0e9ca-f164-42e0-a683-a1450ccf0221" } """.trimIndent().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) val data = - app.post("https://parse.showflix.tk/parse/classes/$classes", requestBody = body).text + app.post("$api/parse/classes/$classes", requestBody = body).text val iframes = if (season == null) { val result = tryParseJson(data)?.resultsMovies?.find { it.movieName.equals("$title ($year)", true) @@ -2204,6 +2212,46 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeZoechip( + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, + ) { + val slug = title?.createSlug() + val url = if (season == null) { + "$zoechipAPI/film/${title?.createSlug()}-$year" + } else { + "$zoechipAPI/episode/$slug-season-$season-episode-$episode" + } + + val id = app.get(url).document.selectFirst("div#show_player_ajax")?.attr("movie-id") ?: return + + val server = app.post( + "$zoechipAPI/wp-admin/admin-ajax.php", data = mapOf( + "action" to "lazy_player", + "movieID" to id, + ), referer = url, headers = mapOf( + "X-Requested-With" to "XMLHttpRequest" + ) + ).document.selectFirst("ul.nav a:contains(Filemoon)")?.attr("data-server") + + val res = app.get(server ?: return, referer = "$zoechipAPI/") + val host = getBaseUrl(res.url) + val script = res.document.select("script:containsData(function(p,a,c,k,e,d))").last()?.data() + val unpacked = getAndUnpack(script ?: return) + + val m3u8 = Regex("file:\\s*\"(.*?m3u8.*?)\"").find(unpacked)?.groupValues?.getOrNull(1) + + M3u8Helper.generateM3u8( + "Zoechip", + m3u8 ?: return, + "$host/", + ).forEach(callback) + + } + suspend fun invokeCinemaTv( imdbId: String? = null, title: String? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index c920555a..0fdb7778 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -470,4 +470,14 @@ data class CinemaTvResponse( @JsonProperty("language") val language: String? = null, @JsonProperty("file") val file: Any? = null, ) +} + +data class NepuSearch( + @JsonProperty("data") val data: ArrayList? = arrayListOf(), +) { + data class Data( + @JsonProperty("url") val url: String? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("type") val type: String? = null, + ) } \ No newline at end of file diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 2f12c19e..eeec600c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -18,7 +18,6 @@ import com.hexated.SoraExtractor.invokeDramaday import com.hexated.SoraExtractor.invokeDreamfilm import com.hexated.SoraExtractor.invokeFDMovies import com.hexated.SoraExtractor.invokeFlixon -import com.hexated.SoraExtractor.invokeGMovies import com.hexated.SoraExtractor.invokeGoku import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeLing @@ -41,9 +40,10 @@ import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeCinemaTv import com.hexated.SoraExtractor.invokeMoflix import com.hexated.SoraExtractor.invokeGhostx -import com.hexated.SoraExtractor.invokeMoviefiction +import com.hexated.SoraExtractor.invokeNepu import com.hexated.SoraExtractor.invokeWatchCartoon import com.hexated.SoraExtractor.invokeWatchsomuch +import com.hexated.SoraExtractor.invokeZoechip import com.hexated.SoraExtractor.invokeZshow import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId import com.lagradost.cloudstream3.LoadResponse.Companion.addTMDbId @@ -110,16 +110,17 @@ open class SoraStream : TmdbProvider() { const val vidsrctoAPI = "https://vidsrc.to" const val dramadayAPI = "https://dramaday.me" const val animetoshoAPI = "https://animetosho.org" - const val showflixAPI = "https://showflix.space" + const val showflixAPI = "https://showflix.lol" const val aoneroomAPI = "https://api3.aoneroom.com" const val mMoviesAPI = "https://multimovies.uno" const val watchCartoonAPI = "https://www1.watchcartoononline.bz" const val moflixAPI = "https://moflix-stream.xyz" const val moviefictionAPI = "https://moviefiction.com" + const val zoechipAPI = "https://zoechip.org" + const val nepuAPI = "https://nepu.to" const val fdMoviesAPI = "https://freedrivemovie.com" const val uhdmoviesAPI = "https://uhdmovies.us" - const val gMoviesAPI = "https://gdrivemovies.xyz" const val hdmovies4uAPI = "https://hdmovies4u.day" const val vegaMoviesAPI = "https://vegamovies.ngo" const val dotmoviesAPI = "https://dotmovies.dad" @@ -481,16 +482,6 @@ open class SoraStream : TmdbProvider() { 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, callback) }, @@ -688,8 +679,17 @@ open class SoraStream : TmdbProvider() { if (!res.isAnime) invokeMoflix(res.id, res.season, res.episode, callback) }, { - if (!res.isAnime) invokeMoviefiction(res.title, res.season, res.episode, subtitleCallback, callback) + if (!res.isAnime) invokeZoechip(res.title, res.year, res.season, res.episode, callback) }, + { + if (!res.isAnime) invokeNepu( + res.title, + res.airedYear ?: res.year, + res.season, + res.episode, + callback + ) + } ) return true diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 9da5d53b..122f4c45 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -30,8 +30,10 @@ import com.hexated.SoraExtractor.invokeCinemaTv import com.hexated.SoraExtractor.invokeMoflix import com.hexated.SoraExtractor.invokeGhostx import com.hexated.SoraExtractor.invokeMoviefiction +import com.hexated.SoraExtractor.invokeNepu import com.hexated.SoraExtractor.invokeWatchCartoon import com.hexated.SoraExtractor.invokeWatchsomuch +import com.hexated.SoraExtractor.invokeZoechip import com.hexated.SoraExtractor.invokeZshow import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.argamap @@ -321,14 +323,23 @@ class SoraStreamLite : SoraStream() { ) }, { - if (!res.isAnime) invokeMoviefiction( + if (!res.isAnime) invokeZoechip( res.title, + res.year, res.season, res.episode, - subtitleCallback, callback ) }, + { + if (!res.isAnime) invokeNepu( + res.title, + res.airedYear ?: res.year, + res.season, + res.episode, + callback + ) + } ) return true