From 9b05f65f2ca8211b18df8b222a260af8f2231b29 Mon Sep 17 00:00:00 2001 From: jack Date: Sun, 10 Dec 2023 02:06:33 +0700 Subject: [PATCH] added Animesaga --- Movierulzhd/build.gradle.kts | 4 +- .../src/main/kotlin/com/hexated/Animesaga.kt | 17 +++ .../src/main/kotlin/com/hexated/Extractors.kt | 8 +- .../main/kotlin/com/hexated/Movierulzhd.kt | 55 +++----- .../kotlin/com/hexated/MovierulzhdPlugin.kt | 2 + .../main/kotlin/com/hexated/SoraExtractor.kt | 118 ++++++++++++------ 6 files changed, 123 insertions(+), 81 deletions(-) create mode 100644 Movierulzhd/src/main/kotlin/com/hexated/Animesaga.kt diff --git a/Movierulzhd/build.gradle.kts b/Movierulzhd/build.gradle.kts index 70a1d007..08c2a426 100644 --- a/Movierulzhd/build.gradle.kts +++ b/Movierulzhd/build.gradle.kts @@ -1,12 +1,12 @@ // use an integer for version numbers -version = 54 +version = 55 cloudstream { language = "hi" // All of these properties are optional, you can safely remove them - description = "Include: Hdmovie2" + description = "Includes: Hdmovie2, Animesaga" authors = listOf("Hexated") /** diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Animesaga.kt b/Movierulzhd/src/main/kotlin/com/hexated/Animesaga.kt new file mode 100644 index 00000000..e4bd115b --- /dev/null +++ b/Movierulzhd/src/main/kotlin/com/hexated/Animesaga.kt @@ -0,0 +1,17 @@ +package com.hexated + +import com.lagradost.cloudstream3.mainPageOf + +class Animesaga : Movierulzhd() { + + override var mainUrl = "https://www.animesaga.in" + override var name = "Animesaga" + + override val mainPage = mainPageOf( + "movies" to "Movies", + "tvshows" to "TV-Shows", + "genre/hindi-dub" to "Hindi Dub", + ) + + +} \ No newline at end of file diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Extractors.kt b/Movierulzhd/src/main/kotlin/com/hexated/Extractors.kt index 37772c96..c3a84b83 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Extractors.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Extractors.kt @@ -2,10 +2,9 @@ package com.hexated import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.Chillx import com.lagradost.cloudstream3.utils.* -const val twoEmbedAPI = "https://www.2embed.to" - class Sbnmp : ExtractorApi() { override val name = "Sbnmp" override var mainUrl = "https://sbnmp.bar" @@ -66,3 +65,8 @@ open class Akamaicdn : ExtractorApi() { ) } } + +class AnimesagaStream : Chillx() { + override val name = "AnimesagaStream" + override val mainUrl = "https://stream.animesaga.in" +} diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt index b66bf0a2..a7b03d3a 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt @@ -45,7 +45,7 @@ open class Movierulzhd : MainAPI() { document = app.get(request.data + page, interceptor = interceptor).document } val home = - document.select("div.items.normal article, div#archive-content article").mapNotNull { + document.select("div.items.normal article, div#archive-content article, div.items.full article").mapNotNull { it.toSearchResult() } return newHomePageResponse(request.name, home) @@ -74,7 +74,7 @@ open class Movierulzhd : MainAPI() { private fun Element.toSearchResult(): SearchResponse? { val title = this.selectFirst("h3 > a")?.text() ?: return null val href = getProperLink(fixUrl(this.selectFirst("h3 > a")!!.attr("href"))) - val posterUrl = fixUrlNull(this.select("div.poster img").last()?.attr("src")) + val posterUrl = fixUrlNull(this.select("div.poster img").last()?.imageFromElement()) val quality = getQualityFromString(this.select("span.quality").text()) return newMovieSearchResponse(title, href, TvType.Movie) { this.posterUrl = posterUrl @@ -112,7 +112,7 @@ open class Movierulzhd : MainAPI() { directUrl = getBaseUrl(request.url) val title = document.selectFirst("div.data > h1")?.text()?.trim().toString() - val poster = fixUrlNull(document.select("div.poster img:last-child").attr("src")) + val poster = fixUrlNull(document.selectFirst("div.poster img:last-child")?.imageFromElement()) val tags = document.select("div.sgeneros > a").map { it.text() } val year = Regex(",\\s?(\\d+)").find( @@ -139,7 +139,7 @@ open class Movierulzhd : MainAPI() { val recName = it.selectFirst("a")!!.attr("href").toString().removeSuffix("/").split("/").last() val recHref = it.selectFirst("a")!!.attr("href") - val recPosterUrl = it.selectFirst("img")?.attr("src").toString() + val recPosterUrl = it.selectFirst("img")?.imageFromElement() newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) { this.posterUrl = recPosterUrl posterHeaders = interceptor.getCookieHeaders(url).toMap() @@ -151,7 +151,7 @@ open class Movierulzhd : MainAPI() { document.select("ul.episodios > li").map { val href = it.select("a").attr("href") val name = fixTitle(it.select("div.episodiotitle > a").text().trim()) - val image = it.select("div.imagen > img").attr("src") + val image = it.selectFirst("div.imagen > img")?.imageFromElement() val episode = it.select("div.numerando").text().replace(" ", "").split("-").last() .toIntOrNull() @@ -230,18 +230,20 @@ open class Movierulzhd : MainAPI() { referer = data, headers = mapOf("X-Requested-With" to "XMLHttpRequest") ).parsed().embed_url - if (!source.contains("youtube")) loadCustomExtractor(loadData?.tag, source, "$directUrl/", subtitleCallback, callback) + if (!source.contains("youtube")) loadExtractor(source, "$directUrl/", subtitleCallback, callback) } else { var document = app.get(data).document if (document.select("title").text() == "Just a moment...") { document = app.get(data, interceptor = interceptor).document } - val id = document.select("meta#dooplay-ajax-counter").attr("data-postid") - val type = if (data.contains("/movies/")) "movie" else "tv" document.select("ul#playeroptionsul > li").map { - it.attr("data-nume") to it.select("span.title").text() - }.apmap { (nume, tag) -> + Triple( + it.attr("data-post"), + it.attr("data-nume"), + it.attr("data-type") + ) + }.apmap { (id, nume, type) -> val source = app.post( url = "$directUrl/wp-admin/admin-ajax.php", data = mapOf( @@ -255,8 +257,7 @@ open class Movierulzhd : MainAPI() { ).parsed().embed_url when { - !source.contains("youtube") -> loadCustomExtractor( - tag, + !source.contains("youtube") -> loadExtractor( source, "$directUrl/", subtitleCallback, @@ -269,30 +270,12 @@ open class Movierulzhd : MainAPI() { return true } - private suspend fun loadCustomExtractor( - name: String? = null, - url: String, - referer: String? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, - quality: Int? = null, - ) { - loadExtractor(url, referer, subtitleCallback) { link -> - callback.invoke( - ExtractorLink( - name ?: link.source, - name ?: link.name, - link.url, - link.referer, - when (link.type) { - ExtractorLinkType.M3U8 -> link.quality - else -> quality ?: link.quality - }, - link.type, - link.headers, - link.extractorData - ) - ) + private fun Element.imageFromElement(): String? { + return when { + this.hasAttr("data-src") -> this.attr("abs:data-src") + this.hasAttr("data-lazy-src") -> this.attr("abs:data-lazy-src") + this.hasAttr("srcset") -> this.attr("abs:srcset").substringBefore(" ") + else -> this.attr("abs:src") } } diff --git a/Movierulzhd/src/main/kotlin/com/hexated/MovierulzhdPlugin.kt b/Movierulzhd/src/main/kotlin/com/hexated/MovierulzhdPlugin.kt index 9ef951a8..680b49a0 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/MovierulzhdPlugin.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/MovierulzhdPlugin.kt @@ -11,7 +11,9 @@ class MovierulzhdPlugin: Plugin() { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(Movierulzhd()) registerMainAPI(Hdmovie2()) + registerMainAPI(Animesaga()) registerExtractorAPI(Sbnmp()) registerExtractorAPI(Akamaicdn()) + registerExtractorAPI(AnimesagaStream()) } } \ No newline at end of file diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 93386186..fd03beee 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -8,9 +8,11 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.Session import com.lagradost.cloudstream3.extractors.helper.AesHelper.cryptoAESHandler +import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.nicehttp.RequestBodyTypes import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody import org.jsoup.Jsoup @@ -110,7 +112,8 @@ object SoraExtractor : SoraStream() { "$vidSrcAPI/embed/tv?tmdb=$id&season=$season&episode=$episode" } - val iframedoc = app.get(url).document.select("iframe#player_iframe").attr("src").let { httpsify(it) } + val iframedoc = + app.get(url).document.select("iframe#player_iframe").attr("src").let { httpsify(it) } val doc = app.get(iframedoc, referer = url).document val index = doc.select("body").attr("data-i") @@ -680,12 +683,20 @@ object SoraExtractor : SoraStream() { "$vidsrctoAPI/embed/tv/$imdbId/$season/$episode" } - val mediaId = app.get(url).document.selectFirst("ul.episodes li a")?.attr("data-id") ?: return + val mediaId = + app.get(url).document.selectFirst("ul.episodes li a")?.attr("data-id") ?: return - app.get("$vidsrctoAPI/ajax/embed/episode/$mediaId/sources").parsedSafe()?.result?.apmap { - val encUrl = app.get("$vidsrctoAPI/ajax/embed/source/${it.id}").parsedSafe()?.result?.url - loadExtractor(vidsrctoDecrypt(encUrl ?: return@apmap), "$vidsrctoAPI/", subtitleCallback, callback) - } + app.get("$vidsrctoAPI/ajax/embed/episode/$mediaId/sources") + .parsedSafe()?.result?.apmap { + val encUrl = app.get("$vidsrctoAPI/ajax/embed/source/${it.id}") + .parsedSafe()?.result?.url + loadExtractor( + vidsrctoDecrypt(encUrl ?: return@apmap), + "$vidsrctoAPI/", + subtitleCallback, + callback + ) + } val subtitles = app.get("$vidsrctoAPI/ajax/embed/episode/$mediaId/subtitles").text tryParseJson>(subtitles)?.map { @@ -1107,30 +1118,32 @@ object SoraExtractor : SoraStream() { val sTag = if (season == null) "" else "(Season $season|S$seasonSlug)" res.select("div.entry-content > $hTag:matches((?i)$sTag.*(1080p|2160p))") .filter { element -> !element.text().contains("Download", true) }.apmap { - val tags = - """(?:1080p|2160p)(.*)""".toRegex().find(it.text())?.groupValues?.get(1)?.trim() - val href = - it.nextElementSibling()?.select("a:contains($aTag)")?.attr("href")?.let { url -> - app.post( - "${getBaseUrl(url)}/red.php", - data = mapOf("link" to url), - referer = "$api/" - ).text.substringAfter("location.href = \"").substringBefore("\"") - } - val selector = - if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)" - val server = - app.get(href ?: return@apmap).document.selectFirst("div.entry-content > $selector") - ?.attr("href") - loadCustomTagExtractor( - tags, - server ?: return@apmap, - "$api/", - subtitleCallback, - callback, - getIndexQuality(it.text()) - ) - } + val tags = + """(?:1080p|2160p)(.*)""".toRegex().find(it.text())?.groupValues?.get(1)?.trim() + val href = + it.nextElementSibling()?.select("a:contains($aTag)")?.attr("href")?.let { url -> + app.post( + "${getBaseUrl(url)}/red.php", + data = mapOf("link" to url), + referer = "$api/" + ).text.substringAfter("location.href = \"").substringBefore("\"") + } + val selector = + if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)" + val server = + app.get( + href ?: return@apmap + ).document.selectFirst("div.entry-content > $selector") + ?.attr("href") + loadCustomTagExtractor( + tags, + server ?: return@apmap, + "$api/", + subtitleCallback, + callback, + getIndexQuality(it.text()) + ) + } } suspend fun invokeHdmovies4u( @@ -1207,7 +1220,14 @@ object SoraExtractor : SoraStream() { 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)) + loadCustomTagExtractor( + "[$size]", + iframeLink, + "$gMoviesAPI/", + subtitleCallback, + callback, + getIndexQuality(title) + ) } } @@ -1298,7 +1318,9 @@ object SoraExtractor : SoraStream() { scriptData.firstOrNull() } else { scriptData.find { - it.first.contains(Regex("(?i)$title \\($year\\s?\\)")) && if(season!=null) it.third?.contains("-tvshow-") == true else it.third?.contains("-movie-") == true + it.first.contains(Regex("(?i)$title \\($year\\s?\\)")) && if (season != null) it.third?.contains( + "-tvshow-" + ) == true else it.third?.contains("-movie-") == true } } @@ -1521,10 +1543,16 @@ object SoraExtractor : SoraStream() { iframe?.apmap { val iframeDoc = app.get(it?.first ?: return@apmap).document val formUrl = iframeDoc.select("form").attr("action") - val formData = iframeDoc.select("form button").associate { v -> v.attr("name") to v.attr("value") } + val formData = + iframeDoc.select("form button").associate { v -> v.attr("name") to v.attr("value") } - val videoUrl = app.post(formUrl, data = formData, referer = it.first).document.selectFirst("div.d-flex.justify-content-center.flex-wrap a")?.attr("href") - val quality = Regex("(\\d{3,4})p").find(it.second)?.groupValues?.getOrNull(1)?.toIntOrNull() + val videoUrl = app.post( + formUrl, + data = formData, + referer = it.first + ).document.selectFirst("div.d-flex.justify-content-center.flex-wrap a")?.attr("href") + val quality = + Regex("(\\d{3,4})p").find(it.second)?.groupValues?.getOrNull(1)?.toIntOrNull() val qualityName = it.second.replace("${quality}p", "").trim() callback.invoke( @@ -1640,9 +1668,11 @@ object SoraExtractor : SoraStream() { "Player F" -> { invokeSmashyFfix(it.second, it.first, url, callback) } + "Player D (Hindi)" -> { invokeSmashyD(it.first, url, callback) } + else -> return@apmap } } @@ -1917,7 +1947,8 @@ object SoraExtractor : SoraStream() { "$twoEmbedAPI/embedtv/$imdbId&s=$season&e=$episode" } - val framesrc = app.get(url).document.selectFirst("iframe#iframesrc")?.attr("data-src") ?: return + val framesrc = + app.get(url).document.selectFirst("iframe#iframesrc")?.attr("data-src") ?: return val ref = getBaseUrl(framesrc) val id = framesrc.substringAfter("id=").substringBefore("&") loadExtractor("https://wishfast.top/e/$id", "$ref/", subtitleCallback, callback) @@ -2069,9 +2100,12 @@ object SoraExtractor : SoraStream() { "$blackvidAPI/v3/tv/sources/$tmdbId/$season/$episode?key=$key" } - val res = app.get(url, timeout = 120L, referer = ref).okhttpResponse.peekBody(1024 * 512) - delay(2000) - val data = res.bytes().decrypt("2378f8e4e844f2dc839ab48f66e00acc2305a401") + val data = app.get( + url, + timeout = 120L, + referer = ref + ).okhttpResponse.peekBody(1024 * 512).source().buffer.readByteArray() + .decrypt("2378f8e4e844f2dc839ab48f66e00acc2305a401") val json = tryParseJson(data) json?.sources?.map { source -> @@ -2260,9 +2294,11 @@ object SoraExtractor : SoraStream() { ) { val referer = "https://bflix.gs/" val slug = getEpisodeSlug(season, episode) - var url = if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" + var url = + if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" if (!app.get(url, referer = referer).isSuccessful) { - url = if (season == null) "$nowTvAPI/$imdbId.mp4" else "$nowTvAPI/tv/$imdbId/s${season}e${slug.second}.mp4" + url = + if (season == null) "$nowTvAPI/$imdbId.mp4" else "$nowTvAPI/tv/$imdbId/s${season}e${slug.second}.mp4" if (!app.get(url, referer = referer).isSuccessful) return } callback.invoke(