diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index e39d81fb..4f42edbb 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 = 151 +version = 152 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index a419b1d1..8d7ce539 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -8,6 +8,7 @@ import com.lagradost.nicehttp.Session import com.hexated.RabbitStream.extractRabbitStream import com.lagradost.cloudstream3.extractors.Filesim import com.lagradost.cloudstream3.extractors.StreamSB +import com.lagradost.cloudstream3.extractors.Voe import com.lagradost.cloudstream3.extractors.helper.GogoHelper import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.nicehttp.RequestBodyTypes @@ -42,18 +43,18 @@ object SoraExtractor : SoraStream() { val media = app.get( "$gokuAPI/ajax/movie/search?keyword=$title", headers = headers ).document.select("div.item").find { ele -> - val url = ele.selectFirst("a")?.attr("href") + val url = ele.selectFirst("a.movie-link")?.attr("href") val titleMedia = ele.select("h3.movie-name").text() - val yearMedia = - ele.select("div.info-split > div:first-child").text().toIntOrNull() - val lastSeasonMedia = - ele.select("div.info-split > div:nth-child(2)").text().substringAfter("SS") - .substringBefore("/").trim().toIntOrNull() - (titleMedia.equals(title, true) || titleMedia.createSlug().equals(title.createSlug())) && + val titleSlug = title.createSlug() + val yearMedia = ele.select("div.info-split > div:first-child").text().toIntOrNull() + val lastSeasonMedia = ele.select("div.info-split > div:nth-child(2)").text().substringAfter("SS") + .substringBefore("/").trim().toIntOrNull() + (titleMedia.equals(title, true) || titleMedia.createSlug() + .equals(titleSlug) || url?.contains("$titleSlug-") == true) && (if (season == null) { - yearMedia == year && url?.contains("/watch-movie/") == true + yearMedia == year && url?.contains("/movie/") == true } else { - lastSeasonMedia == lastSeason && url?.contains("/watch-series/") == true + lastSeasonMedia == lastSeason && url?.contains("/series/") == true }) } ?: return @@ -479,6 +480,34 @@ object SoraExtractor : SoraStream() { } } + suspend fun invokeDoomovies( + title: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val res = app.get("$doomoviesAPI/movies/${title.createSlug()}/") + val host = getBaseUrl(res.url) + val document = res.document + document.select("ul#playeroptionsul > li") + .filter { element -> element.select("span.flag img").attr("src").contains("/en.") } + .map { + Triple( + it.attr("data-post"), + it.attr("data-nume"), + it.attr("data-type") + ) + }.apmap { (id, nume, type) -> + val source = app.get( + "$host/wp-json/dooplayer/v2/${id}/${type}/${nume}", + headers = mapOf("X-Requested-With" to "XMLHttpRequest"), + referer = "$host/" + ).parsed().embed_url + if (!source.contains("youtube")) { + loadExtractor(source, "$host/", subtitleCallback, callback) + } + } + } + suspend fun invokeUniqueStream( title: String? = null, year: Int? = null, @@ -1080,70 +1109,6 @@ object SoraExtractor : SoraStream() { } - private suspend fun invokeAnimeKaizoku( - malId: Int? = null, - epsTitle: String? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { - val search = app.get("$animeKaizokuAPI/?s=${malId ?: return}").document - val detailHref = - search.select("ul#posts-container li").map { it.selectFirst("a")?.attr("href") } - .find { - it?.contains("$malId") == true - }?.let { fixUrl(it, animeKaizokuAPI) } - - val detail = app.get(detailHref ?: return).document - val postId = - detail.selectFirst("link[rel=shortlink]")?.attr("href")?.substringAfter("?p=") ?: return - val script = detail.selectFirst("script:containsData(DDL)")?.data()?.splitData() ?: return - - val media = fetchingKaizoku(animeKaizokuAPI, postId, script, detailHref).document - val iframe = media.select("tbody td[colspan=2]").map { it.attr("onclick") to it.text() } - .filter { it.second.contains("1080p", true) } - - val eps = if (season == null) { - null - } else { - if (episode!! < 10) "0$episode" else episode - } - - iframe.apmap { (data, name) -> - val worker = - fetchingKaizoku(animeKaizokuAPI, postId, data.splitData(), detailHref).document - .select("tbody td") - .map { Triple(it.attr("onclick"), it.text(), it.nextElementSibling()?.text()) } - - val episodeData = worker.let { list -> - if (season == null) list.firstOrNull() else list.find { - it.second.contains( - Regex("($eps\\.)|(-\\s$eps)") - ) || it.second.contains("$epsTitle", true) - } - } ?: return@apmap null - - val ouo = fetchingKaizoku( - animeKaizokuAPI, - postId, - episodeData.first.splitData(), - detailHref - ).text.substringAfter("openInNewTab(\"") - .substringBefore("\")").let { base64Decode(it) } - - if (!ouo.startsWith("https://ouo")) return@apmap null - callback.invoke( - ExtractorLink( - "AnimeKaizoku", - "AnimeKaizoku [${episodeData.third}]", - bypassOuo(ouo) ?: return@apmap null, - "$animeKaizokuAPI/", - Qualities.P1080.value, - ) - ) - } - } - suspend fun invokeLing( title: String? = null, year: Int? = null, @@ -1960,81 +1925,6 @@ object SoraExtractor : SoraStream() { } - suspend fun invokeMovie123Net( - title: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, - ) { - val server = "https://vidcloud9.org" - val fixTitle = title.createSlug() - val m = app.get("$movie123NetAPI/searching?q=$title&limit=40") - .parsedSafe()?.data?.find { - if (season == null) { - (it.t.equals(title, true) || it.t.createSlug() - .equals(fixTitle)) && it.t?.contains("season", true) == false - } else { - it.t?.equals( - "$title - Season $season", - true - ) == true || it.s?.contains("$fixTitle-season-$season-", true) == true - } - }?.s?.substringAfterLast("-") ?: return - - listOf( - "1", - "2" - ).apmap { serverNum -> - val media = app.post( - "$movie123NetAPI/datas", - requestBody = """{"m":$m,"e":${episode ?: 1},"s":$serverNum}""".toRequestBody( - RequestBodyTypes.JSON.toMediaTypeOrNull() - ) - ).parsedSafe()?.url ?: return@apmap null - - val serverUrl = "$server/watch?v=$media" - val token = - app.get(serverUrl).document.selectFirst("script:containsData(setRequestHeader)") - ?.data()?.let { - Regex("\\('0x1f2'\\),'(\\S+?)'\\)").find(it)?.groupValues?.getOrNull(1) - } ?: return@apmap null - - val videoUrl = app.post( - "$server/data", - requestBody = """{"doc":"$media"}""".toRequestBody( - RequestBodyTypes.JSON.toMediaTypeOrNull() - ), - headers = mapOf( - "x-csrf-token" to token - ), - ).parsedSafe()?.url ?: return@apmap null - - if (videoUrl.startsWith("https")) { - loadExtractor(videoUrl, movie123NetAPI, subtitleCallback, callback) - } else { - callback.invoke( - ExtractorLink( - "123Movies", - "123Movies", - fixUrl(base64Decode(videoUrl), server), - serverUrl, - Qualities.P720.value, - true - ) - ) - - subtitleCallback.invoke( - SubtitleFile( - "English", - "https://sub.vxdn.net/sub/$m-${episode ?: 1}.vtt" - ) - ) - } - } - - } - suspend fun invokeSmashyStream( imdbId: String? = null, season: Int? = null, @@ -3291,3 +3181,8 @@ class MultimoviesSB : StreamSB() { override var mainUrl = "https://multimovies.website" } +class Yipsu : Voe() { + override val name = "Yipsu" + override var mainUrl = "https://yip.su" +} + diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index d54ef39a..b1859a67 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -20,6 +20,7 @@ import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.hexated.SoraExtractor.invokeDahmerMovies +import com.hexated.SoraExtractor.invokeDoomovies import com.hexated.SoraExtractor.invokeDreamfilm import com.hexated.SoraExtractor.invokeEdithxmovies import com.hexated.SoraExtractor.invokeFDMovies @@ -34,7 +35,6 @@ import com.hexated.SoraExtractor.invokeJmdkhMovies import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeLing import com.hexated.SoraExtractor.invokeM4uhd -import com.hexated.SoraExtractor.invokeMovie123Net import com.hexated.SoraExtractor.invokeMoviesbay import com.hexated.SoraExtractor.invokeMoviezAdd import com.hexated.SoraExtractor.invokeNavy @@ -116,7 +116,6 @@ open class SoraStream : TmdbProvider() { const val moviesbayAPI = "https://moviesbay.live" const val rStreamAPI = "https://remotestre.am" const val flixonAPI = "https://flixon.lol" - const val movie123NetAPI = "https://ww8.0123movie.net" const val smashyStreamAPI = "https://embed.smashystream.com" const val watchSomuchAPI = "https://watchsomuch.tv" // sub only val gomoviesAPI = @@ -137,6 +136,7 @@ open class SoraStream : TmdbProvider() { const val multimoviesAPI = "https://multimovies.xyz" const val netmoviesAPI = "https://netmovies.to" const val momentAPI = "https://moment-explanation-i-244.site" + const val doomoviesAPI = "https://doomovies.net" // INDEX SITE const val blackMoviesAPI = "https://dl.blacklistedbois.workers.dev/0:" @@ -162,7 +162,6 @@ open class SoraStream : TmdbProvider() { const val baymoviesAPI = "https://opengatewayindex.pages.dev" const val papaonMovies1API = "https://m.papaonwork.workers.dev/0:" const val papaonMovies2API = "https://m.papaonwork.workers.dev/1:" - const val animeKaizokuAPI = "https://animekaizoku.com" const val xMovieAPI = "https://xemovies.to" fun getType(t: String?): TvType { @@ -643,9 +642,6 @@ open class SoraStream : TmdbProvider() { { invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback) }, - { - invokeMovie123Net(res.title, res.season, res.episode, subtitleCallback, callback) - }, { invokeSmashyStream( res.imdbId, @@ -878,7 +874,14 @@ open class SoraStream : TmdbProvider() { subtitleCallback, callback ) - } + }, + { + if (!res.isAnime && res.season == null) invokeDoomovies( + res.title, + subtitleCallback, + callback + ) + }, ) return true @@ -1033,13 +1036,6 @@ open class SoraStream : TmdbProvider() { @JsonProperty("alternative_titles") val alternative_titles: ResultsAltTitles? = null, ) - data class EmbedJson( - @JsonProperty("type") val type: String? = null, - @JsonProperty("link") val link: String? = null, - @JsonProperty("sources") val sources: List = arrayListOf(), - @JsonProperty("tracks") val tracks: List? = null, - ) - data class MovieHabData( @JsonProperty("link") val link: String? = null, @JsonProperty("token") val token: String? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index e7771f1c..efd2a6d3 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -3,6 +3,7 @@ package com.hexated import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAsk4Movies import com.hexated.SoraExtractor.invokeDbgo +import com.hexated.SoraExtractor.invokeDoomovies import com.hexated.SoraExtractor.invokeDreamfilm import com.hexated.SoraExtractor.invokeFilmxy import com.hexated.SoraExtractor.invokeFlixon @@ -16,7 +17,6 @@ import com.hexated.SoraExtractor.invokeKimcartoon import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeLing import com.hexated.SoraExtractor.invokeM4uhd -import com.hexated.SoraExtractor.invokeMovie123Net import com.hexated.SoraExtractor.invokeMovieHab import com.hexated.SoraExtractor.invokeNavy import com.hexated.SoraExtractor.invokeNinetv @@ -35,7 +35,6 @@ import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeWatchOnline import com.hexated.SoraExtractor.invokeWatchsomuch -import com.hexated.SoraExtractor.invokeXmovies import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.argamap import com.lagradost.cloudstream3.utils.AppUtils @@ -107,15 +106,6 @@ class SoraStreamLite : SoraStream() { { invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) }, - { - invokeMovie123Net( - res.title, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, { invokeMovieHab(res.imdbId, res.season, res.episode, subtitleCallback, callback) }, @@ -350,6 +340,13 @@ class SoraStreamLite : SoraStream() { { invokeMoment(res.imdbId, res.season, res.episode, callback) }, + { + if (!res.isAnime && res.season == null) invokeDoomovies( + res.title, + subtitleCallback, + callback + ) + }, ) return true diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt index 69a6aec1..56f723f4 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt @@ -14,5 +14,6 @@ class SoraStreamPlugin: Plugin() { registerExtractorAPI(Animefever()) registerExtractorAPI(Multimovies()) registerExtractorAPI(MultimoviesSB()) + registerExtractorAPI(Yipsu()) } } \ No newline at end of file