From ef69c854111ce602327a4bcbda9cb8cba48c6985 Mon Sep 17 00:00:00 2001 From: hexated Date: Wed, 19 Jul 2023 02:28:23 +0700 Subject: [PATCH 001/105] Ngefilm: update domain --- Ngefilm/build.gradle.kts | 2 +- Ngefilm/src/main/kotlin/com/hexated/Ngefilm.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Ngefilm/build.gradle.kts b/Ngefilm/build.gradle.kts index 3187c097..0903f827 100644 --- a/Ngefilm/build.gradle.kts +++ b/Ngefilm/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/Ngefilm/src/main/kotlin/com/hexated/Ngefilm.kt b/Ngefilm/src/main/kotlin/com/hexated/Ngefilm.kt index 7e330489..84a14d7d 100644 --- a/Ngefilm/src/main/kotlin/com/hexated/Ngefilm.kt +++ b/Ngefilm/src/main/kotlin/com/hexated/Ngefilm.kt @@ -8,7 +8,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element class Ngefilm : MainAPI() { - override var mainUrl = "https://ngefilm21.club" + override var mainUrl = "https://ngefilm21.cfd" override var name = "Ngefilm" override val hasMainPage = true override var lang = "id" From 4a1597dc2f558ff7b9c8665743e949de180d9bd3 Mon Sep 17 00:00:00 2001 From: sora Date: Wed, 19 Jul 2023 20:54:20 +0700 Subject: [PATCH 002/105] added Nekopoi and fix some providers --- DramaSerial/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/DramaSerial.kt | 8 +- .../kotlin/com/hexated/DramaSerialPlugin.kt | 2 +- .../src/main/kotlin/com/hexated/Lkctwoone.kt | 8 - Nekopoi/build.gradle.kts | 25 ++ Nekopoi/src/main/AndroidManifest.xml | 2 + .../src/main/kotlin/com/hexated/Nekopoi.kt | 276 ++++++++++++++++++ .../main/kotlin/com/hexated/NekopoiPlugin.kt | 13 + YomoviesProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/YomoviesProvider.kt | 7 +- 10 files changed, 331 insertions(+), 14 deletions(-) delete mode 100644 DramaSerial/src/main/kotlin/com/hexated/Lkctwoone.kt create mode 100644 Nekopoi/build.gradle.kts create mode 100644 Nekopoi/src/main/AndroidManifest.xml create mode 100644 Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt create mode 100644 Nekopoi/src/main/kotlin/com/hexated/NekopoiPlugin.kt diff --git a/DramaSerial/build.gradle.kts b/DramaSerial/build.gradle.kts index 37e56657..f198565b 100644 --- a/DramaSerial/build.gradle.kts +++ b/DramaSerial/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/DramaSerial/src/main/kotlin/com/hexated/DramaSerial.kt b/DramaSerial/src/main/kotlin/com/hexated/DramaSerial.kt index 881debc5..9a158a80 100644 --- a/DramaSerial/src/main/kotlin/com/hexated/DramaSerial.kt +++ b/DramaSerial/src/main/kotlin/com/hexated/DramaSerial.kt @@ -1,6 +1,7 @@ package com.hexated import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.extractors.Filesim import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element @@ -113,7 +114,7 @@ class DramaSerial : MainAPI() { mLink.attr("onclick").substringAfter("frame('").substringBefore("')").let { iLink -> val uLink = app.get(iLink, referer = iframe).document.select("script").find { it.data().contains("(document).ready") }?.data()?.substringAfter("replace(\"")?.substringBefore("\");") ?: return@apmap null val link = app.get(uLink, referer = iLink).document.selectFirst("iframe")?.attr("src") ?: return@apmap null - loadExtractor(fixUrl(link), "$mainUrl/", subtitleCallback, callback) + loadExtractor(fixUrl(link), "https://juraganfilm.info/", subtitleCallback, callback) } } @@ -122,3 +123,8 @@ class DramaSerial : MainAPI() { } } + +class Bk21 : Filesim() { + override val name = "Bk21" + override var mainUrl = "https://bk21.net" +} diff --git a/DramaSerial/src/main/kotlin/com/hexated/DramaSerialPlugin.kt b/DramaSerial/src/main/kotlin/com/hexated/DramaSerialPlugin.kt index 781dda9e..5d5de498 100644 --- a/DramaSerial/src/main/kotlin/com/hexated/DramaSerialPlugin.kt +++ b/DramaSerial/src/main/kotlin/com/hexated/DramaSerialPlugin.kt @@ -10,6 +10,6 @@ class DramaSerialPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(DramaSerial()) - registerExtractorAPI(Lkctwoone()) + registerExtractorAPI(Bk21()) } } \ No newline at end of file diff --git a/DramaSerial/src/main/kotlin/com/hexated/Lkctwoone.kt b/DramaSerial/src/main/kotlin/com/hexated/Lkctwoone.kt deleted file mode 100644 index 1957e026..00000000 --- a/DramaSerial/src/main/kotlin/com/hexated/Lkctwoone.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.hexated - -import com.lagradost.cloudstream3.extractors.XStreamCdn - -class Lkctwoone: XStreamCdn() { - override val name: String = "LKC21" - override val mainUrl: String = "https://lkc21.net" -} \ No newline at end of file diff --git a/Nekopoi/build.gradle.kts b/Nekopoi/build.gradle.kts new file mode 100644 index 00000000..2eb99748 --- /dev/null +++ b/Nekopoi/build.gradle.kts @@ -0,0 +1,25 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + language = "id" + // All of these properties are optional, you can safely remove them + + // description = "Lorem Ipsum" + authors = listOf("Sora") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "NSFW", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=nekopoi.care&sz=%size%" +} \ No newline at end of file diff --git a/Nekopoi/src/main/AndroidManifest.xml b/Nekopoi/src/main/AndroidManifest.xml new file mode 100644 index 00000000..c98063f8 --- /dev/null +++ b/Nekopoi/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt new file mode 100644 index 00000000..9c0a4cb7 --- /dev/null +++ b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt @@ -0,0 +1,276 @@ +package com.hexated + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.* +import com.lagradost.nicehttp.Requests +import com.lagradost.nicehttp.Session +import org.jsoup.nodes.Element +import java.net.URI + +class Nekopoi : MainAPI() { + override var mainUrl = "https://nekopoi.care" + override var name = "Nekopoi" + override val hasMainPage = true + override var lang = "id" + + override val supportedTypes = setOf( + TvType.NSFW, + ) + + companion object { + val session = Session(Requests().baseClient) + val mirrorBlackList = arrayOf( + "MegaupNet", + "DropApk", + "Racaty", + "ZippyShare", + "ZippySha", + "VideobinCo", + "DropApk", + "SendCm", + "GoogleDrive", + ) + + fun getStatus(t: String?): ShowStatus { + return when (t) { + "Completed" -> ShowStatus.Completed + "Ongoing" -> ShowStatus.Ongoing + else -> ShowStatus.Completed + } + } + + } + + override val mainPage = mainPageOf( + "$mainUrl/category/hentai/" to "Hentai", + "$mainUrl/category/jav/" to "Jav", + "$mainUrl/category/3d-hentai/" to "3D Hentai", + "$mainUrl/category/jav-cosplay/" to "Jav Cosplay", + ) + + override suspend fun getMainPage( + page: Int, + request: MainPageRequest + ): HomePageResponse { + val document = app.get("${request.data}/page/$page").document + val home = document.select("div.result ul li").mapNotNull { + it.toSearchResult() + } + return newHomePageResponse( + list = HomePageList( + name = request.name, + list = home, + isHorizontalImages = true + ), + hasNext = true + ) + } + + private fun getProperAnimeLink(uri: String): String { + return if (uri.contains("-episode-")) { + val title = uri.substringAfter("$mainUrl/").substringBefore("-episode-") + .removePrefix("new-release-").removePrefix("uncensored-") + "$mainUrl/hentai/$title" + } else { + uri + } + } + + private fun Element.toSearchResult(): AnimeSearchResponse? { + val title = this.selectFirst("h2 a")?.text()?.trim() ?: return null + val href = getProperAnimeLink(this.selectFirst("a")?.attr("href") ?: return null) + val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) + val epNum = this.selectFirst("i.dot")?.text()?.filter { it.isDigit() }?.toIntOrNull() + return newAnimeSearchResponse(title, href, TvType.NSFW) { + this.posterUrl = posterUrl + addSub(epNum) + } + + } + + override suspend fun search(query: String): List { + return app.get("$mainUrl/search/$query").document.select("div.result ul li") + .mapNotNull { + it.toSearchResult() + } + } + + override suspend fun load(url: String): LoadResponse { + val document = app.get(url).document + + val title = document.selectFirst("span.desc b, div.eroinfo h1")?.text()?.trim() ?: "" + val poster = fixUrlNull(document.selectFirst("div.imgdesc img, div.thm img")?.attr("src")) + val table = document.select("div.listinfo ul, div.konten") + val tags = + table.select("li:contains(Genres) a").map { it.text() }.takeIf { it.isNotEmpty() } + ?: table.select("p:contains(Genre)").text().substringAfter(":").split(",") + .map { it.trim() } + val year = + document.selectFirst("li:contains(Tayang)")?.text()?.substringAfterLast(",") + ?.filter { it.isDigit() }?.toIntOrNull() + val status = getStatus( + document.selectFirst("li:contains(Status)")?.text()?.substringAfter(":")?.trim() + ) + val duration = document.selectFirst("li:contains(Durasi)")?.text()?.substringAfterLast(":") + ?.filter { it.isDigit() }?.toIntOrNull() + val description = document.selectFirst("span.desc p")?.text() + + val episodes = document.select("div.episodelist ul li").mapNotNull { + val name = it.selectFirst("a")?.text() + val link = fixUrlNull(it.selectFirst("a")?.attr("href")) ?: return@mapNotNull null + Episode(link, name = name) + }.takeIf { it.isNotEmpty() } ?: listOf(Episode(url, title)) + + return newAnimeLoadResponse(title, url, TvType.NSFW) { + engName = title + posterUrl = poster + this.year = year + this.duration = duration + addEpisodes(DubStatus.Subbed, episodes) + showStatus = status + plot = description + this.tags = tags + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + val res = app.get(data).document + + argamap( + { + res.select("div#show-stream iframe").apmap { iframe -> + loadExtractor(iframe.attr("src"), "$mainUrl/", subtitleCallback, callback) + } + }, + { + res.select("div.boxdownload div.liner").map { ele -> + getIndexQuality( + ele.select("div.name").text() + ) to ele.selectFirst("a:contains(ouo)") + ?.attr("href") + }.filter { it.first != Qualities.P360.value }.map { + val bypassedAds = bypassMirrored(bypassOuo(it.second ?: return@map) ?: return@map) + bypassedAds.apmap ads@{ adsLink -> + loadExtractor( + fixEmbed(adsLink) ?: return@ads, + "$mainUrl/", + subtitleCallback, + ) { link -> + callback.invoke( + ExtractorLink( + link.name, + link.name, + link.url, + link.referer, + if(link.isM3u8) link.quality else it.first, + link.isM3u8, + link.headers, + link.extractorData + ) + ) + } + } + } + } + ) + + return true + } + + private fun fixEmbed(url: String?): String? { + if (url == null) return null + val host = getBaseUrl(url) + return when { + url.contains("streamsb", true) -> url.replace("$host/", "$host/e/") + else -> url + } + } + + private fun getBaseUrl(url: String): String { + return URI(url).let { + "${it.scheme}://${it.host}" + } + } + + private suspend fun bypassOuo(url: String?): String? { + var res = session.get(url ?: return null) + run lit@{ + (1..2).forEach { _ -> + if (res.headers["location"] != null) return@lit + val document = res.document + val nextUrl = document.select("form").attr("action") + val data = document.select("form input").mapNotNull { + it.attr("name") to it.attr("value") + }.toMap().toMutableMap() + val captchaKey = + document.select("script[src*=https://www.google.com/recaptcha/api.js?render=]") + .attr("src").substringAfter("render=") + val token = APIHolder.getCaptchaToken(url, captchaKey) + data["x-token"] = token ?: "" + res = session.post( + nextUrl, + data = data, + headers = mapOf("content-type" to "application/x-www-form-urlencoded"), + allowRedirects = false + ) + } + } + + return res.headers["location"] + } + + private suspend fun bypassMirrored(url: String): List { + val request = app.get(url) + val hostUrl = getBaseUrl(request.url) + var nextUrl = request.document.selectFirst("div.row div.centered a")?.attr("href") + nextUrl = app.get(nextUrl ?: return emptyList()).text.substringAfter("\"GET\", \"") + .substringBefore("\"") + return app.get(fixUrl(nextUrl, hostUrl)).document.select("table.hoverable tbody tr") + .filter { mirror -> + !mirrorIsBlackList(mirror.selectFirst("img")?.attr("alt")) + }.apmap { + val fileLink = it.selectFirst("a")?.attr("href") + app.get( + fixUrl( + fileLink.toString(), + hostUrl + ) + ).document.selectFirst("div.code_wrap code")?.text() + } + } + + private fun mirrorIsBlackList(host: String?) : Boolean { + return mirrorBlackList.any { it.equals(host, true) } + } + + private fun fixUrl(url: String, domain: String): String { + if (url.startsWith("http")) { + return url + } + if (url.isEmpty()) { + return "" + } + + val startsWithNoHttp = url.startsWith("//") + if (startsWithNoHttp) { + return "https:$url" + } else { + if (url.startsWith('/')) { + return domain + url + } + return "$domain/$url" + } + } + + private fun getIndexQuality(str: String?): Int { + return Regex("(\\d{3,4})[pP]").find(str ?: "")?.groupValues?.getOrNull(1)?.toIntOrNull() + ?: Qualities.Unknown.value + } + +} \ No newline at end of file diff --git a/Nekopoi/src/main/kotlin/com/hexated/NekopoiPlugin.kt b/Nekopoi/src/main/kotlin/com/hexated/NekopoiPlugin.kt new file mode 100644 index 00000000..a6fe53a3 --- /dev/null +++ b/Nekopoi/src/main/kotlin/com/hexated/NekopoiPlugin.kt @@ -0,0 +1,13 @@ +package com.hexated + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class NekopoiPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(Nekopoi()) + } +} \ No newline at end of file diff --git a/YomoviesProvider/build.gradle.kts b/YomoviesProvider/build.gradle.kts index 4def964d..8b53037f 100644 --- a/YomoviesProvider/build.gradle.kts +++ b/YomoviesProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 14 +version = 15 cloudstream { diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt index 6c46d869..ac5e991f 100644 --- a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt +++ b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt @@ -10,7 +10,7 @@ import org.jsoup.nodes.Element import java.net.URI class YomoviesProvider : MainAPI() { - override var mainUrl = "https://yomovies.team" + override var mainUrl = "https://yomovies.baby" private var directUrl = mainUrl override var name = "Yomovies" override val hasMainPage = true @@ -142,7 +142,7 @@ class YomoviesProvider : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { - if (data.contains("yomovies")) { + if (data.contains(directUrl.getHost(), true)) { val doc = app.get(data).document doc.select("div.movieplay iframe").map { fixUrl(it.attr("src")) } .apmap { source -> @@ -171,5 +171,8 @@ class YomoviesProvider : MainAPI() { return true } + private fun String.getHost(): String { + return fixTitle(URI(this).host.substringBeforeLast(".").substringAfterLast(".")) + } } From bf7340605cb5014f2c4bbf84fe74714111643abc Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Wed, 19 Jul 2023 21:07:50 +0700 Subject: [PATCH 003/105] Update DramaSerial.kt --- DramaSerial/src/main/kotlin/com/hexated/DramaSerial.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DramaSerial/src/main/kotlin/com/hexated/DramaSerial.kt b/DramaSerial/src/main/kotlin/com/hexated/DramaSerial.kt index 9a158a80..98047d9f 100644 --- a/DramaSerial/src/main/kotlin/com/hexated/DramaSerial.kt +++ b/DramaSerial/src/main/kotlin/com/hexated/DramaSerial.kt @@ -7,7 +7,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element class DramaSerial : MainAPI() { - override var mainUrl = "https://dramaserial.wiki" + override var mainUrl = "https://dramaserial.sbs" override var name = "DramaSerial" override val hasMainPage = true override var lang = "id" From 6fbdcf4edcb6f3baf99da80f80f181d0aa5fe44c Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 20 Jul 2023 01:41:51 +0700 Subject: [PATCH 004/105] update Kuramanime domain --- KuramanimeProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/KuramanimeProvider.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/KuramanimeProvider/build.gradle.kts b/KuramanimeProvider/build.gradle.kts index 31e82f6a..e9c83545 100644 --- a/KuramanimeProvider/build.gradle.kts +++ b/KuramanimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 12 +version = 13 cloudstream { diff --git a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt index 5d24fcad..989740bb 100644 --- a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt +++ b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt @@ -9,7 +9,7 @@ import org.jsoup.Jsoup import org.jsoup.nodes.Element class KuramanimeProvider : MainAPI() { - override var mainUrl = "https://kuramanime.net" + override var mainUrl = "https://kuramanime.xyz" override var name = "Kuramanime" override val hasQuickSearch = false override val hasMainPage = true From 785eda47c27a7b1971665bb9759ac5137c0b4493 Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 20 Jul 2023 11:56:56 +0700 Subject: [PATCH 005/105] Yomovies: added new source --- YomoviesProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 37 +++++++++++++++++++ .../main/kotlin/com/hexated/Watchomovies.kt | 23 ++++++++++++ .../kotlin/com/hexated/YomoviesProvider.kt | 37 ++++++++----------- .../com/hexated/YomoviesProviderPlugin.kt | 2 + 5 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 YomoviesProvider/src/main/kotlin/com/hexated/Extractors.kt create mode 100644 YomoviesProvider/src/main/kotlin/com/hexated/Watchomovies.kt diff --git a/YomoviesProvider/build.gradle.kts b/YomoviesProvider/build.gradle.kts index 8b53037f..42b439cd 100644 --- a/YomoviesProvider/build.gradle.kts +++ b/YomoviesProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 15 +version = 16 cloudstream { diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/Extractors.kt b/YomoviesProvider/src/main/kotlin/com/hexated/Extractors.kt new file mode 100644 index 00000000..08597bf1 --- /dev/null +++ b/YomoviesProvider/src/main/kotlin/com/hexated/Extractors.kt @@ -0,0 +1,37 @@ +package com.hexated + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.SpeedoStream +import com.lagradost.cloudstream3.utils.AppUtils +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.M3u8Helper +import com.lagradost.cloudstream3.utils.getAndUnpack + +class Streamoupload : SpeedoStream() { + override val mainUrl = "https://streamoupload.xyz" + override val name = "Streamoupload" + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val script = getAndUnpack(app.get(url, referer = referer).text) + val data = script.substringAfter("sources:[") + .substringBefore("],").replace("file", "\"file\"").trim() + AppUtils.tryParseJson(data)?.let { + M3u8Helper.generateM3u8( + name, + it.file, + "$mainUrl/", + ).forEach(callback) + } + } + + private data class File( + @JsonProperty("file") val file: String, + ) +} \ No newline at end of file diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/Watchomovies.kt b/YomoviesProvider/src/main/kotlin/com/hexated/Watchomovies.kt new file mode 100644 index 00000000..9ed5ad2d --- /dev/null +++ b/YomoviesProvider/src/main/kotlin/com/hexated/Watchomovies.kt @@ -0,0 +1,23 @@ +package com.hexated + +import com.lagradost.cloudstream3.TvType +import com.lagradost.cloudstream3.mainPageOf + +class Watchomovies : YomoviesProvider() { + override var mainUrl = "https://watchomovies.mom" + override var name = "Watchomovies" + override val hasMainPage = true + override var lang = "hi" + override val supportedTypes = setOf( + TvType.NSFW, + ) + + override val mainPage = mainPageOf( + "most-favorites" to "Most Viewed", + "genre/xxx-scenes" to "XXX Scenes", + "genre/18" to "18+ Movies", + "genre/erotic-movies" to "Erotic Movies Movies", + "genre/parody" to "Parody Movies", + "genre/tv-shows" to "TV Shows Movies", + ) +} \ No newline at end of file diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt index ac5e991f..1b2bd2a0 100644 --- a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt +++ b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt @@ -9,37 +9,32 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element import java.net.URI -class YomoviesProvider : MainAPI() { +open class YomoviesProvider : MainAPI() { override var mainUrl = "https://yomovies.baby" - private var directUrl = mainUrl + private var directUrl = "" override var name = "Yomovies" override val hasMainPage = true override var lang = "hi" - override val hasDownloadSupport = true override val supportedTypes = setOf( TvType.Movie, TvType.TvSeries, ) override val mainPage = mainPageOf( - "$mainUrl/most-favorites/page/" to "Most Viewed", - "$mainUrl/genre/web-series/page/" to "Web Series Movies", - "$mainUrl/genre/dual-audio/page/" to "Dual Audio Movies", - "$mainUrl/genre/bollywood/page/" to "Bollywood Movies", - "$mainUrl/genre/tv-shows/page/" to "TV Shows Movies", - "$mainUrl/genre/hollywood/page/" to "Hollywood Movies", - "$mainUrl/series/page/" to "All TV Series", + "most-favorites" to "Most Viewed", + "genre/web-series" to "Web Series Movies", + "genre/dual-audio" to "Dual Audio Movies", + "genre/bollywood" to "Bollywood Movies", + "genre/tv-shows" to "TV Shows Movies", + "genre/hollywood" to "Hollywood Movies", + "series" to "All TV Series", ) override suspend fun getMainPage( page: Int, request: MainPageRequest ): HomePageResponse { - val document = if (page == 1) { - app.get(request.data.removeSuffix("page/")).document - } else { - app.get(request.data + page).document - } + val document = app.get("$mainUrl/${request.data}/page/$page").document val home = document.select("div.ml-item").mapNotNull { it.toSearchResult() } @@ -129,12 +124,6 @@ class YomoviesProvider : MainAPI() { } } - private fun getBaseUrl(url: String): String { - return URI(url).let { - "${it.scheme}://${it.host}" - } - } - override suspend fun loadLinks( data: String, isCasting: Boolean, @@ -175,4 +164,10 @@ class YomoviesProvider : MainAPI() { return fixTitle(URI(this).host.substringBeforeLast(".").substringAfterLast(".")) } + private fun getBaseUrl(url: String): String { + return URI(url).let { + "${it.scheme}://${it.host}" + } + } + } diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProviderPlugin.kt b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProviderPlugin.kt index 72cbcd16..60bb8004 100644 --- a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProviderPlugin.kt +++ b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProviderPlugin.kt @@ -10,5 +10,7 @@ class YomoviesProviderPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(YomoviesProvider()) + registerMainAPI(Watchomovies()) + registerExtractorAPI(Streamoupload()) } } \ No newline at end of file From a55dc31798b066f2d02ddb2d8f17196f55b7c15f Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 20 Jul 2023 14:08:39 +0700 Subject: [PATCH 006/105] added Gomov --- Gomov/build.gradle.kts | 27 +++ Gomov/src/main/AndroidManifest.xml | 2 + Gomov/src/main/kotlin/com/hexated/Gomov.kt | 176 ++++++++++++++++++ .../main/kotlin/com/hexated/GomovPlugin.kt | 17 ++ 4 files changed, 222 insertions(+) create mode 100644 Gomov/build.gradle.kts create mode 100644 Gomov/src/main/AndroidManifest.xml create mode 100644 Gomov/src/main/kotlin/com/hexated/Gomov.kt create mode 100644 Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts new file mode 100644 index 00000000..5db843c0 --- /dev/null +++ b/Gomov/build.gradle.kts @@ -0,0 +1,27 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + language = "id" + // All of these properties are optional, you can safely remove them + + // description = "Lorem Ipsum" + authors = listOf("Hexated") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "AsianDrama", + "TvSeries", + "Movie", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=gomov.bio&sz=%size%" +} \ No newline at end of file diff --git a/Gomov/src/main/AndroidManifest.xml b/Gomov/src/main/AndroidManifest.xml new file mode 100644 index 00000000..c98063f8 --- /dev/null +++ b/Gomov/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Gomov/src/main/kotlin/com/hexated/Gomov.kt b/Gomov/src/main/kotlin/com/hexated/Gomov.kt new file mode 100644 index 00000000..3d92217d --- /dev/null +++ b/Gomov/src/main/kotlin/com/hexated/Gomov.kt @@ -0,0 +1,176 @@ +package com.hexated + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addActors +import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.extractors.* +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.httpsify +import com.lagradost.cloudstream3.utils.loadExtractor +import org.jsoup.nodes.Element + +class Gomov : MainAPI() { + override var mainUrl = "https://gomov.bio" + override var name = "Gomov" + override val hasMainPage = true + override var lang = "id" + override val supportedTypes = setOf( + TvType.Movie, + TvType.TvSeries, + TvType.AsianDrama + ) + + override val mainPage = mainPageOf( + "page/%d/?s&search=advanced&post_type=movie" to "Movies", + "category/western-series/page/%d/" to "Western Series", + "tv/page/%d/" to "Tv Shows", + "category/korean-series/page/%d/" to "Korean Series", + "category/chinese-series/page/%d/" to "Chinese Series", + "category/india-series/page/%d/" to "India Series", + ) + + override suspend fun getMainPage( + page: Int, + request: MainPageRequest + ): HomePageResponse { + val data = request.data.format(page) + val document = app.get("$mainUrl/$data").document + val home = document.select("article.item").mapNotNull { + it.toSearchResult() + } + return newHomePageResponse(request.name, home) + } + + private fun Element.toSearchResult(): SearchResponse? { + val title = this.selectFirst("h2.entry-title > a")?.text()?.trim() ?: return null + val href = fixUrl(this.selectFirst("a")!!.attr("href")) + val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("src")) + val quality = this.select("div.gmr-qual").text().trim() + return if (quality.isEmpty()) { + val episode = this.select("div.gmr-numbeps > span").text().toIntOrNull() + newAnimeSearchResponse(title, href, TvType.TvSeries) { + this.posterUrl = posterUrl + addSub(episode) + } + } else { + newMovieSearchResponse(title, href, TvType.Movie) { + this.posterUrl = posterUrl + addQuality(quality) + } + } + } + + private fun Element.toBottomSearchResult(): SearchResponse? { + val title = this.selectFirst("a > span.idmuvi-rp-title")?.text()?.trim() ?: return null + val href = this.selectFirst("a")!!.attr("href") + val posterUrl = fixUrl(this.selectFirst("a > img")?.attr("data-src").toString()) + return newMovieSearchResponse(title, href, TvType.Movie) { + this.posterUrl = posterUrl + } + } + + override suspend fun search(query: String): List { + return app.get("$mainUrl/?s=$query&post_type[]=post&post_type[]=tv").document.select("article.item") + .mapNotNull { + it.toSearchResult() + } + } + + override suspend fun load(url: String): LoadResponse { + val document = app.get(url).document + + val title = + document.selectFirst("h1.entry-title")?.text()?.substringBefore("Season")?.trim() + .toString() + val poster = + fixUrl(document.selectFirst("figure.pull-left > img")?.attr("src").toString()) + val tags = document.select("span.gmr-movie-genre:contains(Genre:) > a").map { it.text() } + + val year = + document.select("span.gmr-movie-genre:contains(Year:) > a").text().trim().toIntOrNull() + val tvType = if (url.contains("/tv/")) TvType.TvSeries else TvType.Movie + val description = document.selectFirst("div[itemprop=description] > p")?.text()?.trim() + val trailer = document.selectFirst("ul.gmr-player-nav li a.gmr-trailer-popup")?.attr("href") + val rating = + document.selectFirst("div.gmr-meta-rating > span[itemprop=ratingValue]")?.text() + ?.toRatingInt() + val actors = document.select("div.gmr-moviedata").last()?.select("span[itemprop=actors]") + ?.map { it.select("a").text() } + + val recommendations = document.select("div.idmuvi-rp ul li").mapNotNull { + it.toBottomSearchResult() + } + + return if (tvType == TvType.TvSeries) { + val episodes = document.select("div.vid-episodes div.episode").map { eps -> + val href = fixUrl(eps.select("a").attr("href")) + val episode = eps.attr("data-epi").toIntOrNull() + val season = eps.attr("data-sea").toIntOrNull() + Episode( + href, + season = season, + episode = episode, + ) + } + newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { + this.posterUrl = poster + this.year = year + this.plot = description + this.tags = tags + this.rating = rating + addActors(actors) + this.recommendations = recommendations + addTrailer(trailer) + } + } else { + newMovieLoadResponse(title, url, TvType.Movie, url) { + this.posterUrl = poster + this.year = year + this.plot = description + this.tags = tags + this.rating = rating + addActors(actors) + this.recommendations = recommendations + addTrailer(trailer) + } + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + val document = app.get(data).document + val id = document.selectFirst("div#muvipro_player_content_id")!!.attr("data-id") + + document.select("div.tab-content-ajax").apmap { + val server = app.post( + "$mainUrl/wp-admin/admin-ajax.php", + data = mapOf("action" to "muvipro_player_content", "tab" to it.attr("id"), "post_id" to id) + ).document.select("iframe").attr("src") + + loadExtractor(httpsify(server), "$mainUrl/", subtitleCallback, callback) + } + + return true + + } + +} + +class Filelions : Filesim() { + override val name = "Filelions" + override var mainUrl = "https://filelions.to" +} + +class Likessb : StreamSB() { + override var name = "Likessb" + override var mainUrl = "https://likessb.com" +} + +class DbGdriveplayer : Gdriveplayer() { + override var mainUrl = "https://database.gdriveplayer.us" +} \ No newline at end of file diff --git a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt new file mode 100644 index 00000000..05c8715b --- /dev/null +++ b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt @@ -0,0 +1,17 @@ + +package com.hexated + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class GomovPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(Gomov()) + registerExtractorAPI(Filelions()) + registerExtractorAPI(Likessb()) + registerExtractorAPI(DbGdriveplayer()) + } +} \ No newline at end of file From e1cbf5be2ef49580055b307c0a76445ff1f972a7 Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 20 Jul 2023 15:44:27 +0700 Subject: [PATCH 007/105] Gomov: added Dutamovie --- Gomov/build.gradle.kts | 4 +- .../src/main/kotlin/com/hexated/DutaMovie.kt | 44 +++++++++++++++++++ .../src/main/kotlin/com/hexated/Extractors.kt | 24 ++++++++++ Gomov/src/main/kotlin/com/hexated/Gomov.kt | 29 ++++-------- .../main/kotlin/com/hexated/GomovPlugin.kt | 2 + YomoviesProvider/build.gradle.kts | 2 +- 6 files changed, 81 insertions(+), 24 deletions(-) create mode 100644 Gomov/src/main/kotlin/com/hexated/DutaMovie.kt create mode 100644 Gomov/src/main/kotlin/com/hexated/Extractors.kt diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index 5db843c0..58ecbc21 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,12 +1,12 @@ // use an integer for version numbers -version = 1 +version = 2 cloudstream { language = "id" // All of these properties are optional, you can safely remove them - // description = "Lorem Ipsum" + description = "Include: DutaMovie" authors = listOf("Hexated") /** diff --git a/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt new file mode 100644 index 00000000..01a903bb --- /dev/null +++ b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt @@ -0,0 +1,44 @@ +package com.hexated + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.httpsify +import com.lagradost.cloudstream3.utils.loadExtractor + +class DutaMovie : Gomov() { + override var mainUrl = "https://dutamovie21.live" + override var name = "DutaMovie" + override val hasMainPage = true + override var lang = "id" + override val supportedTypes = setOf( + TvType.Movie, + TvType.TvSeries, + TvType.AsianDrama + ) + + override val mainPage = mainPageOf( + "category/box-office/page/%d/" to "Box Office", + "category/serial-tv/page/%d/" to "Serial TV", + "category/animation/page/%d/" to "Animasi", + "country/korea/page/%d/" to "Serial TV Korea", + "country/indonesia/page/%d/" to "Serial TV Indonesia", + ) + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + app.get(data).document.select("ul.muvipro-player-tabs li a").apmap { + val iframe = app.get(fixUrl(it.attr("href"))).document.selectFirst("div.gmr-embed-responsive iframe") + ?.attr("src") + loadExtractor(httpsify(iframe ?: return@apmap ), "$mainUrl/", subtitleCallback, callback) + } + + return true + } + + +} \ No newline at end of file diff --git a/Gomov/src/main/kotlin/com/hexated/Extractors.kt b/Gomov/src/main/kotlin/com/hexated/Extractors.kt new file mode 100644 index 00000000..25bd9f11 --- /dev/null +++ b/Gomov/src/main/kotlin/com/hexated/Extractors.kt @@ -0,0 +1,24 @@ +package com.hexated + +import com.lagradost.cloudstream3.extractors.Filesim +import com.lagradost.cloudstream3.extractors.Gdriveplayer +import com.lagradost.cloudstream3.extractors.StreamSB + +class Dutamovie21 : StreamSB() { + override var name = "Dutamovie21" + override var mainUrl = "https://dutamovie21.xyz" +} + +class Filelions : Filesim() { + override val name = "Filelions" + override var mainUrl = "https://filelions.to" +} + +class Likessb : StreamSB() { + override var name = "Likessb" + override var mainUrl = "https://likessb.com" +} + +class DbGdriveplayer : Gdriveplayer() { + override var mainUrl = "https://database.gdriveplayer.us" +} \ No newline at end of file diff --git a/Gomov/src/main/kotlin/com/hexated/Gomov.kt b/Gomov/src/main/kotlin/com/hexated/Gomov.kt index 3d92217d..2c2b1d36 100644 --- a/Gomov/src/main/kotlin/com/hexated/Gomov.kt +++ b/Gomov/src/main/kotlin/com/hexated/Gomov.kt @@ -3,13 +3,12 @@ package com.hexated import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer -import com.lagradost.cloudstream3.extractors.* import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.httpsify import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element -class Gomov : MainAPI() { +open class Gomov : MainAPI() { override var mainUrl = "https://gomov.bio" override var name = "Gomov" override val hasMainPage = true @@ -102,16 +101,18 @@ class Gomov : MainAPI() { } return if (tvType == TvType.TvSeries) { - val episodes = document.select("div.vid-episodes div.episode").map { eps -> - val href = fixUrl(eps.select("a").attr("href")) - val episode = eps.attr("data-epi").toIntOrNull() - val season = eps.attr("data-sea").toIntOrNull() + val episodes = document.select("div.vid-episodes a, div.gmr-listseries a").map { eps -> + val href = fixUrl(eps.attr("href")) + val name = eps.text() + val episode = name.split(" ").lastOrNull()?.filter { it.isDigit() }?.toIntOrNull() + val season = name.split(" ").firstOrNull()?.filter { it.isDigit() }?.toIntOrNull() Episode( href, + name, season = season, episode = episode, ) - } + }.filter { it.episode != null } newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { this.posterUrl = poster this.year = year @@ -159,18 +160,4 @@ class Gomov : MainAPI() { } -} - -class Filelions : Filesim() { - override val name = "Filelions" - override var mainUrl = "https://filelions.to" -} - -class Likessb : StreamSB() { - override var name = "Likessb" - override var mainUrl = "https://likessb.com" -} - -class DbGdriveplayer : Gdriveplayer() { - override var mainUrl = "https://database.gdriveplayer.us" } \ No newline at end of file diff --git a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt index 05c8715b..99c3213d 100644 --- a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt +++ b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt @@ -10,8 +10,10 @@ class GomovPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(Gomov()) + registerMainAPI(DutaMovie()) registerExtractorAPI(Filelions()) registerExtractorAPI(Likessb()) registerExtractorAPI(DbGdriveplayer()) + registerExtractorAPI(Dutamovie21()) } } \ No newline at end of file diff --git a/YomoviesProvider/build.gradle.kts b/YomoviesProvider/build.gradle.kts index 42b439cd..f00bbb7e 100644 --- a/YomoviesProvider/build.gradle.kts +++ b/YomoviesProvider/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "hi" // All of these properties are optional, you can safely remove them - // description = "Lorem Ipsum" + description = "Include: Watchomovies" authors = listOf("Hexated") /** From 0561fcf85751efaeb32db4d51025ac09d68929b9 Mon Sep 17 00:00:00 2001 From: tuan041 <30403510+tuan041@users.noreply.github.com> Date: Thu, 20 Jul 2023 15:50:17 +0700 Subject: [PATCH 008/105] Add Phim1080 Provider (#197) * bump * fix * new * new * new * new * change version --- Phim1080/build.gradle.kts | 28 ++ Phim1080/src/main/AndroidManifest.xml | 2 + .../src/main/com/hexated/Phim1080Provider.kt | 247 ++++++++++++++++++ .../com/hexated/Phim1080ProviderPlugin.kt | 14 + 4 files changed, 291 insertions(+) create mode 100644 Phim1080/build.gradle.kts create mode 100644 Phim1080/src/main/AndroidManifest.xml create mode 100644 Phim1080/src/main/com/hexated/Phim1080Provider.kt create mode 100644 Phim1080/src/main/com/hexated/Phim1080ProviderPlugin.kt diff --git a/Phim1080/build.gradle.kts b/Phim1080/build.gradle.kts new file mode 100644 index 00000000..bd0faf7c --- /dev/null +++ b/Phim1080/build.gradle.kts @@ -0,0 +1,28 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + language = "vi" + // All of these properties are optional, you can safely remove them + + description = "Xem Phim Online Chất Lượng Cao" + authors = listOf("TuaSan") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "AsianDrama", + "Anime", + "TvSeries", + "Movie", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=xem1080.com" +} diff --git a/Phim1080/src/main/AndroidManifest.xml b/Phim1080/src/main/AndroidManifest.xml new file mode 100644 index 00000000..a3f95b4f --- /dev/null +++ b/Phim1080/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/Phim1080/src/main/com/hexated/Phim1080Provider.kt b/Phim1080/src/main/com/hexated/Phim1080Provider.kt new file mode 100644 index 00000000..d4d35368 --- /dev/null +++ b/Phim1080/src/main/com/hexated/Phim1080Provider.kt @@ -0,0 +1,247 @@ +package com.hexated + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.ExtractorLink +import org.jsoup.nodes.Element + +class Phim1080Provider : MainAPI() { + override var mainUrl = "https://xem1080.com" + override var name = "Phim1080" + override val hasMainPage = true + override var lang = "vi" + override val hasDownloadSupport = true + override val supportedTypes = setOf( + TvType.Movie, + TvType.TvSeries, + TvType.Anime, + TvType.AsianDrama + ) + + private fun encodeString(e: String, t: Int): String { + var a = "" + for (i in 0 until e.length) { + val r = e[i].code + val o = r xor t + a += o.toChar() + } + return a + } + + override val mainPage = mainPageOf( + "$mainUrl/phim-de-cu?page=" to "Phim Đề Cử", + "$mainUrl/the-loai/hoat-hinh?page=" to "Phim Hoạt Hình", + "$mainUrl/phim-chieu-rap?page=" to "Phim Chiếu Rạp", + "$mainUrl/phim-bo?page=" to "Phim Bộ", + "$mainUrl/phim-le?page=" to "Phim Lẻ", + "$mainUrl/bang-xep-hang?page=" to "Bảng Xếp Hạng", + "$mainUrl/bo-suu-tap/disney-plus?page=" to "Disney+", + "$mainUrl/bo-suu-tap/netflix-original?page=" to "Netflix", + "$mainUrl/hom-nay-xem-gi?page=" to "Hôm Nay Xem Gì", + "$mainUrl/phim-sap-chieu?page=" to "Phim Sắp Chiếu", + ) + + override suspend fun getMainPage( + page: Int, + request: MainPageRequest + ): HomePageResponse { + val document = app.get(request.data + page).document + val home = document.select("div.tray-item").mapNotNull { + it.toSearchResult() + } + return newHomePageResponse( + list = HomePageList( + name = request.name, + list = home, + ), + hasNext = true + ) + } + + private fun Element.toSearchResult(): SearchResponse { + val title = this.selectFirst("div.tray-item-title")?.text()?.trim().toString() + val href = fixUrl(this.selectFirst("a")!!.attr("href")) + val posterUrl = this.selectFirst("img")!!.attr("data-src") + val temp = this.select("div.tray-film-likes").text() + return if (temp.contains("/")) { + val episode = Regex("((\\d+)\\s)").find(temp)?.groupValues?.map { num -> + num.replace(Regex("\\s"), "") + }?.distinct()?.firstOrNull()?.toIntOrNull() + newAnimeSearchResponse(title, href, TvType.TvSeries) { + this.posterUrl = posterUrl + addSub(episode) + } + } else { + val quality = this.select("span.tray-item-quality").text().replace("FHD", "HD").trim() + newMovieSearchResponse(title, href, TvType.Movie) { + this.posterUrl = posterUrl + addQuality(quality) + } + } + } + + override suspend fun search(query: String): List { + val link = "$mainUrl/tim-kiem/$query" + val document = app.get(link).document + + return document.select("div.tray-item").map { + it.toSearchResult() + } + } + + override suspend fun load( url: String ): LoadResponse { + val document = app.get( + url = url, + referer = "$mainUrl/", + headers = mapOf( + "Sec-Ch-Ua-Mobile" to "?1", + "Sec-Ch-Ua-Platform" to "\"Android\"", + "User-Agent" to "Mozilla/5.0 (Linux; Android 10; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.162 Mobile Safari/537.36 Edg/114.0.0.0", + ) + ).document + val fId = document.select("div.container").attr("data-id") + val filmInfo = app.get( + "$mainUrl/api/v2/films/$fId", + referer = url, + headers = mapOf( + "Content-Type" to "application/json", + "X-Requested-With" to "XMLHttpRequest" + ) + ).parsedSafe() + val title = filmInfo?.name?.trim().toString() + val poster = filmInfo?.thumbnail + val background = filmInfo?.poster + val slug = filmInfo?.slug + val link = "$mainUrl/$slug" + val tags = document.select("div.film-content div.film-info-genre:nth-child(7) a").map { it.text() } + val year = filmInfo?.year + val tvType = if (document.select("div.episode-group-tab").isNotEmpty()) TvType.TvSeries else TvType.Movie + val description = document.select("div.film-info-description").text().trim() + val comingSoon = document.select("button.direction-trailer").isNotEmpty() + val trailerCode = filmInfo?.trailer?.original?.id + val trailer = "https://www.youtube.com/embed/$trailerCode" + val recommendations = document.select("section.tray.index.related div.tray-content.carousel div.tray-item").map { + it.toSearchResult() + } + + return if (tvType == TvType.TvSeries) { + val epsInfo = app.get( + "$mainUrl/api/v2/films/$fId/episodes?sort=name", + referer = link, + headers = mapOf( + "Content-Type" to "application/json", + "X-Requested-With" to "XMLHttpRequest", + ) + ).parsedSafe()?.eps?.map { ep -> + Episode( + data = fixUrl(ep.link.toString()), + name = ep.detailname, + episode = ep.episodeNumber, + ) + } ?: listOf() + newTvSeriesLoadResponse(title, url, TvType.TvSeries, epsInfo) { + this.posterUrl = poster + this.backgroundPosterUrl = background + this.year = year + this.plot = description + this.tags = tags + this.comingSoon = comingSoon + addTrailer(trailer) + this.recommendations = recommendations + } + } else { + newMovieLoadResponse(title, url, TvType.Movie, link) { + this.posterUrl = poster + this.backgroundPosterUrl = background + this.year = year + this.plot = description + this.tags = tags + this.comingSoon = comingSoon + addTrailer(trailer) + this.recommendations = recommendations + } + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + val document = app.get(data).document + val fId = document.select("div.container").attr("data-id") + val epId = document.select("div.container").attr("data-episode-id") + val doc = app.get( + "$mainUrl/api/v2/films/$fId/episodes/$epId", + referer = data, + headers = mapOf( + "Content-Type" to "application/json", + "cookie" to "xem1080=%3D", + "X-Requested-With" to "XMLHttpRequest" + ) + ) + val source = doc.text.substringAfter(":{\"hls\":\"").substringBefore("\"},") + val link = encodeString(source, 69) + callback.invoke( + ExtractorLink( + "HS", + "HS", + link, + referer = data, + quality = Qualities.Unknown.value, + isM3u8 = true, + ) + ) + val subId = doc.parsedSafe()?.subtitle?.vi + val isSubIdEmpty = subId.isNullOrBlank() + if (!isSubIdEmpty) { + subtitleCallback.invoke( + SubtitleFile( + "Vietnamese", + "$mainUrl/subtitle/$subId.vtt" + ) + ) + } + return true + } + + data class filmInfo( + @JsonProperty("name") val name: String? = null, + @JsonProperty("poster") val poster: String? = null, + @JsonProperty("thumbnail") val thumbnail: String? = null, + @JsonProperty("slug") val slug: String? = null, + @JsonProperty("year") val year: Int? = null, + @JsonProperty("trailer") val trailer: TrailerInfo? = null, + ) + + data class TrailerInfo( + @JsonProperty("original") val original: TrailerKey? = null, + ) + + data class TrailerKey( + @JsonProperty("id") val id: String? = null, + ) + + data class MediaDetailEpisodes( + @JsonProperty("data") val eps: ArrayList? = arrayListOf(), + ) + + data class Episodes( + @JsonProperty("link") val link: String? = null, + @JsonProperty("detail_name") val detailname: String? = null, + @JsonProperty("name") val episodeNumber: Int? = null, + ) + + data class Media( + @JsonProperty("subtitle") val subtitle: SubInfo? = null, + ) + + data class SubInfo( + @JsonProperty("vi") val vi: String? = null, + ) + +} diff --git a/Phim1080/src/main/com/hexated/Phim1080ProviderPlugin.kt b/Phim1080/src/main/com/hexated/Phim1080ProviderPlugin.kt new file mode 100644 index 00000000..a521b6ac --- /dev/null +++ b/Phim1080/src/main/com/hexated/Phim1080ProviderPlugin.kt @@ -0,0 +1,14 @@ + +package com.hexated + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class Phim1080ProviderPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(Phim1080Provider()) + } +} From 46c67dbd35d444198492d9f03639fdb5855ab48a Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 20 Jul 2023 16:11:14 +0700 Subject: [PATCH 009/105] small fix --- Phim1080/src/main/{ => kotlin}/com/hexated/Phim1080Provider.kt | 0 .../src/main/{ => kotlin}/com/hexated/Phim1080ProviderPlugin.kt | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Phim1080/src/main/{ => kotlin}/com/hexated/Phim1080Provider.kt (100%) rename Phim1080/src/main/{ => kotlin}/com/hexated/Phim1080ProviderPlugin.kt (100%) diff --git a/Phim1080/src/main/com/hexated/Phim1080Provider.kt b/Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt similarity index 100% rename from Phim1080/src/main/com/hexated/Phim1080Provider.kt rename to Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt diff --git a/Phim1080/src/main/com/hexated/Phim1080ProviderPlugin.kt b/Phim1080/src/main/kotlin/com/hexated/Phim1080ProviderPlugin.kt similarity index 100% rename from Phim1080/src/main/com/hexated/Phim1080ProviderPlugin.kt rename to Phim1080/src/main/kotlin/com/hexated/Phim1080ProviderPlugin.kt From 864b266f9ef981260b9cdd85cd9ea348a7397486 Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 20 Jul 2023 19:35:26 +0700 Subject: [PATCH 010/105] fixed Rebahin and moved Ngefilm --- Gomov/build.gradle.kts | 4 +- .../src/main/kotlin/com/hexated/DutaMovie.kt | 7 - Gomov/src/main/kotlin/com/hexated/Gomov.kt | 21 ++- .../main/kotlin/com/hexated/GomovPlugin.kt | 1 + Gomov/src/main/kotlin/com/hexated/Ngefilm.kt | 40 +++++ Ngefilm/build.gradle.kts | 27 --- Ngefilm/src/main/AndroidManifest.xml | 2 - .../src/main/kotlin/com/hexated/Ngefilm.kt | 164 ------------------ .../main/kotlin/com/hexated/NgefilmPlugin.kt | 14 -- .../kotlin/com/hexated/Phim1080Provider.kt | 8 +- RebahinProvider/build.gradle.kts | 4 +- .../src/main/kotlin/com/hexated/Cgvindo.kt | 9 + .../kotlin/com/hexated/RebahinProvider.kt | 3 +- .../com/hexated/RebahinProviderPlugin.kt | 6 +- 14 files changed, 76 insertions(+), 234 deletions(-) create mode 100644 Gomov/src/main/kotlin/com/hexated/Ngefilm.kt delete mode 100644 Ngefilm/build.gradle.kts delete mode 100644 Ngefilm/src/main/AndroidManifest.xml delete mode 100644 Ngefilm/src/main/kotlin/com/hexated/Ngefilm.kt delete mode 100644 Ngefilm/src/main/kotlin/com/hexated/NgefilmPlugin.kt create mode 100644 RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index 58ecbc21..7f2b8216 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,12 +1,12 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Include: DutaMovie" + description = "Include: DutaMovie, Ngefilm" authors = listOf("Hexated") /** diff --git a/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt index 01a903bb..7912713c 100644 --- a/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt +++ b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt @@ -8,13 +8,6 @@ import com.lagradost.cloudstream3.utils.loadExtractor class DutaMovie : Gomov() { override var mainUrl = "https://dutamovie21.live" override var name = "DutaMovie" - override val hasMainPage = true - override var lang = "id" - override val supportedTypes = setOf( - TvType.Movie, - TvType.TvSeries, - TvType.AsianDrama - ) override val mainPage = mainPageOf( "category/box-office/page/%d/" to "Box Office", diff --git a/Gomov/src/main/kotlin/com/hexated/Gomov.kt b/Gomov/src/main/kotlin/com/hexated/Gomov.kt index 2c2b1d36..36128fb2 100644 --- a/Gomov/src/main/kotlin/com/hexated/Gomov.kt +++ b/Gomov/src/main/kotlin/com/hexated/Gomov.kt @@ -43,8 +43,8 @@ open class Gomov : MainAPI() { private fun Element.toSearchResult(): SearchResponse? { val title = this.selectFirst("h2.entry-title > a")?.text()?.trim() ?: return null val href = fixUrl(this.selectFirst("a")!!.attr("href")) - val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("src")) - val quality = this.select("div.gmr-qual").text().trim() + val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("src"))?.fixImageQuality() + val quality = this.select("div.gmr-qual, div.gmr-quality-item > a").text().trim().replace("-", "") return if (quality.isEmpty()) { val episode = this.select("div.gmr-numbeps > span").text().toIntOrNull() newAnimeSearchResponse(title, href, TvType.TvSeries) { @@ -59,10 +59,10 @@ open class Gomov : MainAPI() { } } - private fun Element.toBottomSearchResult(): SearchResponse? { + private fun Element.toRecommendResult(): SearchResponse? { val title = this.selectFirst("a > span.idmuvi-rp-title")?.text()?.trim() ?: return null val href = this.selectFirst("a")!!.attr("href") - val posterUrl = fixUrl(this.selectFirst("a > img")?.attr("data-src").toString()) + val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("src").fixImageQuality()) return newMovieSearchResponse(title, href, TvType.Movie) { this.posterUrl = posterUrl } @@ -82,7 +82,7 @@ open class Gomov : MainAPI() { document.selectFirst("h1.entry-title")?.text()?.substringBefore("Season")?.trim() .toString() val poster = - fixUrl(document.selectFirst("figure.pull-left > img")?.attr("src").toString()) + fixUrlNull(document.selectFirst("figure.pull-left > img")?.attr("src"))?.fixImageQuality() val tags = document.select("span.gmr-movie-genre:contains(Genre:) > a").map { it.text() } val year = @@ -97,7 +97,7 @@ open class Gomov : MainAPI() { ?.map { it.select("a").text() } val recommendations = document.select("div.idmuvi-rp ul li").mapNotNull { - it.toBottomSearchResult() + it.toRecommendResult() } return if (tvType == TvType.TvSeries) { @@ -109,7 +109,7 @@ open class Gomov : MainAPI() { Episode( href, name, - season = season, + season = if(name.contains(" ")) season else null, episode = episode, ) }.filter { it.episode != null } @@ -160,4 +160,11 @@ open class Gomov : MainAPI() { } + private fun String?.fixImageQuality(): String? { + if(this == null) return null + val regex = Regex("(-\\d*x\\d*)").find(this)?.groupValues + if(regex?.isEmpty() == true) return this + return this.replace(regex?.get(0) ?: return null, "") + } + } \ No newline at end of file diff --git a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt index 99c3213d..b3043cb7 100644 --- a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt +++ b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt @@ -11,6 +11,7 @@ class GomovPlugin: Plugin() { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(Gomov()) registerMainAPI(DutaMovie()) + registerMainAPI(Ngefilm()) registerExtractorAPI(Filelions()) registerExtractorAPI(Likessb()) registerExtractorAPI(DbGdriveplayer()) diff --git a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt new file mode 100644 index 00000000..7c4be51f --- /dev/null +++ b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt @@ -0,0 +1,40 @@ +package com.hexated + +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.fixUrl +import com.lagradost.cloudstream3.mainPageOf +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor + +class Ngefilm : Gomov() { + override var mainUrl = "https://ngefilm21.lol" + override var name = "Ngefilm" + + override val mainPage = mainPageOf( + "/page/%d/?s&search=advanced&post_type=movie&index&orderby&genre&movieyear&country&quality=" to "Movies Terbaru", + "/page/%d/?s=&search=advanced&post_type=tv&index=&orderby=&genre=&movieyear=&country=&quality=" to "Series Terbaru", + "/page/%d/?s=&search=advanced&post_type=tv&index=&orderby=&genre=drakor&movieyear=&country=&quality=" to "Series Korea", + "/page/%d/?s=&search=advanced&post_type=tv&index=&orderby=&genre=&movieyear=&country=indonesia&quality=" to "Series Indonesia", + ) + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + val document = app.get(data).document + document.select("ul.muvipro-player-tabs li a").apmap { server -> + val iframe = app.get(fixUrl(server.attr("href"))).document.selectFirst("div.gmr-embed-responsive iframe") + ?.attr("src")?.let { fixUrl(it) } ?: return@apmap + loadExtractor(iframe, "$mainUrl/", subtitleCallback, callback) + } + + return true + + } + +} \ No newline at end of file diff --git a/Ngefilm/build.gradle.kts b/Ngefilm/build.gradle.kts deleted file mode 100644 index 0903f827..00000000 --- a/Ngefilm/build.gradle.kts +++ /dev/null @@ -1,27 +0,0 @@ -// use an integer for version numbers -version = 4 - - -cloudstream { - language = "id" - // All of these properties are optional, you can safely remove them - - // description = "Lorem Ipsum" - authors = listOf("Hexated") - - /** - * Status int as the following: - * 0: Down - * 1: Ok - * 2: Slow - * 3: Beta only - * */ - status = 1 // will be 3 if unspecified - tvTypes = listOf( - "AsianDrama", - "TvSeries", - "Movie", - ) - - iconUrl = "https://www.google.com/s2/favicons?domain=ngefilm21.club&sz=%size%" -} \ No newline at end of file diff --git a/Ngefilm/src/main/AndroidManifest.xml b/Ngefilm/src/main/AndroidManifest.xml deleted file mode 100644 index c98063f8..00000000 --- a/Ngefilm/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/Ngefilm/src/main/kotlin/com/hexated/Ngefilm.kt b/Ngefilm/src/main/kotlin/com/hexated/Ngefilm.kt deleted file mode 100644 index 84a14d7d..00000000 --- a/Ngefilm/src/main/kotlin/com/hexated/Ngefilm.kt +++ /dev/null @@ -1,164 +0,0 @@ -package com.hexated - -import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.LoadResponse.Companion.addActors -import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.loadExtractor -import org.jsoup.nodes.Element - -class Ngefilm : MainAPI() { - override var mainUrl = "https://ngefilm21.cfd" - override var name = "Ngefilm" - override val hasMainPage = true - override var lang = "id" - override val hasDownloadSupport = true - override val supportedTypes = setOf( - TvType.Movie, - TvType.TvSeries, - TvType.AsianDrama - ) - - override val mainPage = mainPageOf( - "?s&search=advanced&post_type=movie&index&orderby&genre&movieyear&country&quality=" to "Movies Terbaru", - "?s=&search=advanced&post_type=tv&index=&orderby=&genre=&movieyear=&country=&quality=" to "Series Terbaru", - "?s=&search=advanced&post_type=tv&index=&orderby=&genre=drakor&movieyear=&country=&quality=" to "Series Korea", - "?s=&search=advanced&post_type=tv&index=&orderby=&genre=&movieyear=&country=indonesia&quality=" to "Series Indonesia", - ) - - override suspend fun getMainPage( - page: Int, - request: MainPageRequest - ): HomePageResponse { - val document = app.get("$mainUrl/page/$page/${request.data}").document - val home = document.select("main#main article").mapNotNull { - it.toSearchResult() - } - return newHomePageResponse(request.name, home) - } - - override suspend fun search(query: String): List { - val link = "$mainUrl/?s=$query&post_type[]=post&post_type[]=tv" - val document = app.get(link).document - return document.select("main#main article").mapNotNull { - it.toSearchResult() - } - } - - override suspend fun load(url: String): LoadResponse { - val document = app.get(url).document - - val title = - document.selectFirst("h1.entry-title")?.text()?.substringBefore("Season")?.trim() ?: "" - val poster = fixUrlNull( - document.selectFirst("figure.pull-left > img")?.attr("src")?.fixImageQuality() - ) - val tags = document.select("span.gmr-movie-genre:contains(Genre:) > a").map { it.text() } - - val year = - document.select("span.gmr-movie-genre:contains(Year:) > a").text().trim().toIntOrNull() - val tvType = if (url.contains("/tv/")) TvType.TvSeries else TvType.Movie - val description = document.selectFirst("div[itemprop=description] > p")?.text()?.trim() - val trailer = document.selectFirst("ul.gmr-player-nav li a.gmr-trailer-popup")?.attr("href") - val rating = - document.selectFirst("div.gmr-meta-rating > span[itemprop=ratingValue]")?.text() - ?.toRatingInt() - val actors = document.select("div.gmr-moviedata").last()?.select("span[itemprop=actors]") - ?.map { it.select("a").text() } - - val recommendations = document.select("div.idmuvi-rp ul li").mapNotNull { - it.toRecommendResult() - } - - return if (tvType == TvType.TvSeries) { - val episodes = document.select("div.gmr-listseries > a") - .filter { element -> !element.text().contains("Pilih Episode", true) } - .map { eps -> - val href = fixUrl(eps.attr("href")) - val episode = eps.text().substringAfter("Eps").toIntOrNull() - val season = - eps.text().split(" ").first().substringAfter("S").toIntOrNull() ?: 1 - Episode( - href, - season = season, - episode = episode, - ) - } - newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { - this.posterUrl = poster - this.year = year - this.plot = description - this.tags = tags - this.rating = rating - addActors(actors) - this.recommendations = recommendations - addTrailer(trailer) - } - } else { - newMovieLoadResponse(title, url, TvType.Movie, url) { - this.posterUrl = poster - this.year = year - this.plot = description - this.tags = tags - this.rating = rating - addActors(actors) - this.recommendations = recommendations - addTrailer(trailer) - } - } - } - - override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ): Boolean { - - val document = app.get(data).document - - document.select("ul.muvipro-player-tabs li a").apmap { server -> - val iframe = app.get(fixUrl(server.attr("href"))).document.selectFirst("div.gmr-embed-responsive iframe") - ?.attr("src")?.let { fixUrl(it) } ?: return@apmap - loadExtractor(iframe, "$mainUrl/", subtitleCallback, callback) - } - - return true - - } - - private fun Element.toSearchResult(): SearchResponse? { - val title = this.selectFirst("h2.entry-title > a")?.text()?.trim() ?: return null - val href = fixUrl(this.selectFirst("a")?.attr("href") ?: return null) - val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("src").fixImageQuality()) - val quality = this.select("div.gmr-quality-item > a").text().trim() - return if (quality.isEmpty()) { - val episode = - this.select("div.gmr-numbeps > span").text().filter { it.isDigit() }.toIntOrNull() - newAnimeSearchResponse(title, href, TvType.TvSeries) { - this.posterUrl = posterUrl - addSub(episode) - } - } else { - newMovieSearchResponse(title, href, TvType.Movie) { - this.posterUrl = posterUrl - addQuality(quality.replace("-", "")) - } - } - } - - private fun Element.toRecommendResult(): SearchResponse? { - val title = this.selectFirst("a > span.idmuvi-rp-title")?.text()?.trim() ?: return null - val href = this.selectFirst("a")!!.attr("href") - val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("src").fixImageQuality()) - return newMovieSearchResponse(title, href, TvType.Movie) { - this.posterUrl = posterUrl - } - } - - private fun String?.fixImageQuality(): String? { - val quality = Regex("(-\\d*x\\d*)").find(this ?: return null)?.groupValues?.get(0) - return this.replace(quality ?: return null, "") - } - -} \ No newline at end of file diff --git a/Ngefilm/src/main/kotlin/com/hexated/NgefilmPlugin.kt b/Ngefilm/src/main/kotlin/com/hexated/NgefilmPlugin.kt deleted file mode 100644 index 8fc845f8..00000000 --- a/Ngefilm/src/main/kotlin/com/hexated/NgefilmPlugin.kt +++ /dev/null @@ -1,14 +0,0 @@ - -package com.hexated - -import com.lagradost.cloudstream3.plugins.CloudstreamPlugin -import com.lagradost.cloudstream3.plugins.Plugin -import android.content.Context - -@CloudstreamPlugin -class NgefilmPlugin: Plugin() { - override fun load(context: Context) { - // All providers should be added in this manner. Please don't edit the providers list directly. - registerMainAPI(Ngefilm()) - } -} \ No newline at end of file diff --git a/Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt b/Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt index d4d35368..edadf591 100644 --- a/Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt +++ b/Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt @@ -22,8 +22,8 @@ class Phim1080Provider : MainAPI() { private fun encodeString(e: String, t: Int): String { var a = "" - for (i in 0 until e.length) { - val r = e[i].code + for (element in e) { + val r = element.code val o = r xor t a += o.toChar() } @@ -109,7 +109,7 @@ class Phim1080Provider : MainAPI() { "Content-Type" to "application/json", "X-Requested-With" to "XMLHttpRequest" ) - ).parsedSafe() + ).parsedSafe() val title = filmInfo?.name?.trim().toString() val poster = filmInfo?.thumbnail val background = filmInfo?.poster @@ -209,7 +209,7 @@ class Phim1080Provider : MainAPI() { return true } - data class filmInfo( + data class FilmInfo( @JsonProperty("name") val name: String? = null, @JsonProperty("poster") val poster: String? = null, @JsonProperty("thumbnail") val thumbnail: String? = null, diff --git a/RebahinProvider/build.gradle.kts b/RebahinProvider/build.gradle.kts index 32b9dd7e..0c5b2fdf 100644 --- a/RebahinProvider/build.gradle.kts +++ b/RebahinProvider/build.gradle.kts @@ -1,12 +1,12 @@ // use an integer for version numbers -version = 6 +version = 7 cloudstream { language = "id" // All of these properties are optional, you can safely remove them - // description = "Lorem Ipsum" + description = "Include: Cgvindo, Kitanonton" authors = listOf("Hexated") /** diff --git a/RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt b/RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt new file mode 100644 index 00000000..328f0a06 --- /dev/null +++ b/RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt @@ -0,0 +1,9 @@ +package com.hexated + +import com.lagradost.cloudstream3.TvType + +class Cgvindo : RebahinProvider() { + override var mainUrl = "http://cgvindo.click" + override var name = "Cgvindo" + +} \ No newline at end of file diff --git a/RebahinProvider/src/main/kotlin/com/hexated/RebahinProvider.kt b/RebahinProvider/src/main/kotlin/com/hexated/RebahinProvider.kt index e8e5ad1e..fcb63f6e 100644 --- a/RebahinProvider/src/main/kotlin/com/hexated/RebahinProvider.kt +++ b/RebahinProvider/src/main/kotlin/com/hexated/RebahinProvider.kt @@ -13,11 +13,10 @@ import org.jsoup.nodes.Element import java.net.URI open class RebahinProvider : MainAPI() { - override var mainUrl = "http://104.237.198.198" + override var mainUrl = "http://179.43.163.50" override var name = "Rebahin" override val hasMainPage = true override var lang = "id" - override val hasDownloadSupport = true open var mainServer = "http://172.96.161.72" override val supportedTypes = setOf( TvType.Movie, diff --git a/RebahinProvider/src/main/kotlin/com/hexated/RebahinProviderPlugin.kt b/RebahinProvider/src/main/kotlin/com/hexated/RebahinProviderPlugin.kt index ab58bb2d..e051cc41 100644 --- a/RebahinProvider/src/main/kotlin/com/hexated/RebahinProviderPlugin.kt +++ b/RebahinProvider/src/main/kotlin/com/hexated/RebahinProviderPlugin.kt @@ -1,4 +1,3 @@ - package com.hexated import com.lagradost.cloudstream3.plugins.CloudstreamPlugin @@ -6,10 +5,11 @@ import com.lagradost.cloudstream3.plugins.Plugin import android.content.Context @CloudstreamPlugin -class RebahinProviderPlugin: Plugin() { +class RebahinProviderPlugin : Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(RebahinProvider()) -registerMainAPI(Kitanonton()) + registerMainAPI(Kitanonton()) + registerMainAPI(Cgvindo()) } } \ No newline at end of file From ee302555a5d661effdc8dc559e85e742db5f5649 Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 20 Jul 2023 20:26:43 +0700 Subject: [PATCH 011/105] AnimeIndoProvider: fixed homepage --- AnimeIndoProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/AnimeIndoProvider.kt | 35 ++++++++++--------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/AnimeIndoProvider/build.gradle.kts b/AnimeIndoProvider/build.gradle.kts index 1b1a9869..297bbcc1 100644 --- a/AnimeIndoProvider/build.gradle.kts +++ b/AnimeIndoProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 10 +version = 11 cloudstream { diff --git a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt index 4c40ad78..b518016b 100644 --- a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt +++ b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt @@ -13,7 +13,6 @@ class AnimeIndoProvider : MainAPI() { override var name = "AnimeIndo" override val hasMainPage = true override var lang = "id" - override val hasDownloadSupport = true override val supportedTypes = setOf( TvType.Anime, @@ -39,18 +38,19 @@ class AnimeIndoProvider : MainAPI() { } override val mainPage = mainPageOf( - "$mainUrl/anime-terbaru/page/" to "Anime Terbaru", - "$mainUrl/ongoing/page/" to "Anime Ongoing", - "$mainUrl/populer/page/" to "Anime Populer", - "$mainUrl/donghua-terbaru/page/" to "Donghua Terbaru", + "episode-terbaru" to "Episode Terbaru", + "ongoing" to "Anime Ongoing", + "populer" to "Anime Populer", + "donghua-terbaru" to "Donghua Terbaru", ) override suspend fun getMainPage( page: Int, request: MainPageRequest ): HomePageResponse { - val document = app.get(request.data + page).document - val home = document.select("div.post-show > article, div.relat > article").mapNotNull { + val url = "$mainUrl/pages/${request.data}/page/$page" + val document = app.get(url).document + val home = document.select("main#main div.animposx").mapNotNull { it.toSearchResult() } return newHomePageResponse(request.name, home) @@ -60,7 +60,7 @@ class AnimeIndoProvider : MainAPI() { return if (uri.contains("/anime/")) { uri } else { - var title = uri.substringAfter("$mainUrl/") + var title = uri.substringAfter("nonton/") title = when { (title.contains("-episode")) && !(title.contains("-movie")) -> Regex("(.+)-episode").find( title @@ -74,15 +74,13 @@ class AnimeIndoProvider : MainAPI() { } } - private fun Element.toSearchResult(): AnimeSearchResponse? { - val title = this.selectFirst("div.title")?.text()?.trim() ?: return null + private fun Element.toSearchResult(): AnimeSearchResponse { + val title = this.selectFirst("div.titlex, h2.entry-title, h4")?.text()?.trim() ?: "" val href = getProperAnimeLink(this.selectFirst("a")!!.attr("href")) - val posterUrl = this.select("img[itemprop=image]").attr("src").toString() - val type = getType(this.select("div.type").text().trim()) - val epNum = - this.selectFirst("span.episode")?.ownText()?.replace(Regex("\\D"), "")?.trim() - ?.toIntOrNull() - return newAnimeSearchResponse(title, href, type) { + val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) + val epNum = this.selectFirst("span.episode")?.ownText()?.replace(Regex("\\D"), "")?.trim() + ?.toIntOrNull() + return newAnimeSearchResponse(title, href, TvType.Anime) { this.posterUrl = posterUrl addSub(epNum) } @@ -131,6 +129,10 @@ class AnimeIndoProvider : MainAPI() { Episode(link, header.text(), episode = episode) }.reversed() + val recommendations = document.select("div.relat div.animposx").mapNotNull { + it.toSearchResult() + } + return newAnimeLoadResponse(title, url, getType(type)) { engName = title posterUrl = poster @@ -139,6 +141,7 @@ class AnimeIndoProvider : MainAPI() { showStatus = status plot = description this.tags = tags + this.recommendations = recommendations addTrailer(trailer) } } From 8b9a58a5a0f77e58532817170a9f182147edd20e Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 20 Jul 2023 23:07:46 +0700 Subject: [PATCH 012/105] small fix --- Nekopoi/build.gradle.kts | 2 +- Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Nekopoi/build.gradle.kts b/Nekopoi/build.gradle.kts index 2eb99748..c3c51979 100644 --- a/Nekopoi/build.gradle.kts +++ b/Nekopoi/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 1 +version = 2 cloudstream { diff --git a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt index 9c0a4cb7..f94d78f8 100644 --- a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt +++ b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt @@ -155,8 +155,8 @@ class Nekopoi : MainAPI() { ) to ele.selectFirst("a:contains(ouo)") ?.attr("href") }.filter { it.first != Qualities.P360.value }.map { - val bypassedAds = bypassMirrored(bypassOuo(it.second ?: return@map) ?: return@map) - bypassedAds.apmap ads@{ adsLink -> + val bypassedAds = bypassMirrored(bypassOuo(it.second)) + bypassedAds.amap ads@{ adsLink -> loadExtractor( fixEmbed(adsLink) ?: return@ads, "$mainUrl/", @@ -225,8 +225,8 @@ class Nekopoi : MainAPI() { return res.headers["location"] } - private suspend fun bypassMirrored(url: String): List { - val request = app.get(url) + private suspend fun bypassMirrored(url: String?): List { + val request = app.get(url ?: return emptyList()) val hostUrl = getBaseUrl(request.url) var nextUrl = request.document.selectFirst("div.row div.centered a")?.attr("href") nextUrl = app.get(nextUrl ?: return emptyList()).text.substringAfter("\"GET\", \"") @@ -234,11 +234,11 @@ class Nekopoi : MainAPI() { return app.get(fixUrl(nextUrl, hostUrl)).document.select("table.hoverable tbody tr") .filter { mirror -> !mirrorIsBlackList(mirror.selectFirst("img")?.attr("alt")) - }.apmap { + }.amap { val fileLink = it.selectFirst("a")?.attr("href") app.get( fixUrl( - fileLink.toString(), + fileLink ?: return@amap null, hostUrl ) ).document.selectFirst("div.code_wrap code")?.text() From 65f5283ae60d69536b7f2b2a6dc502bdd4ddd9f3 Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 21 Jul 2023 00:49:46 +0700 Subject: [PATCH 013/105] TimefourTv: fix DaddyHD Channels --- TimefourTv/build.gradle.kts | 2 +- TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt | 7 +++++-- .../src/main/kotlin/com/hexated/TimefourTvExtractor.kt | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/TimefourTv/build.gradle.kts b/TimefourTv/build.gradle.kts index fa742b08..dbde5cf2 100644 --- a/TimefourTv/build.gradle.kts +++ b/TimefourTv/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 14 +version = 15 cloudstream { diff --git a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt index d1a32510..b5b0dbb0 100644 --- a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt +++ b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt @@ -19,8 +19,11 @@ open class TimefourTv : MainAPI() { ) companion object { - const val daddyUrl = "https://daddylive.watch" - val daddyHost: String = URI(daddyUrl).host.split(".").first() + const val daddyUrl = "https://d.daddylivehd.sx" + val daddyHost: String = daddyUrl.getHost() + private fun String.getHost(): String { + return URI(this).host.substringBeforeLast(".").substringAfterLast(".") + } } override val mainPage = mainPageOf( diff --git a/TimefourTv/src/main/kotlin/com/hexated/TimefourTvExtractor.kt b/TimefourTv/src/main/kotlin/com/hexated/TimefourTvExtractor.kt index c56fae01..57d484a2 100644 --- a/TimefourTv/src/main/kotlin/com/hexated/TimefourTvExtractor.kt +++ b/TimefourTv/src/main/kotlin/com/hexated/TimefourTvExtractor.kt @@ -72,7 +72,7 @@ object TimefourTvExtractor : TimefourTv() { return getSportLink(url) } - if(url.contains(daddyHost)) { + if(url.contains(daddyHost, true)) { mainServer = getBaseUrl(url) return getFinalLink(app.get(url, referer = daddyUrl)) } From 3b907e3d5a384ae3e7bbb12c47b7818b14e29c1f Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 21 Jul 2023 16:55:03 +0700 Subject: [PATCH 014/105] sora: fixed Smashy and Fdmovies --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 11 ++++++- .../src/main/kotlin/com/hexated/SoraUtils.kt | 33 +++++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index c770eba3..f035b3fd 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 = 144 +version = 145 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 933475ca..ad127d88 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1491,7 +1491,13 @@ object SoraExtractor : SoraStream() { extractGdflix(gdBotLink ?: return@apmap null) } type.contains("oiya") -> { - extractOiya(fdLink ?: return@apmap null, qualities) + val oiyaLink = extractOiya(fdLink ?: return@apmap null, qualities) + if(oiyaLink?.contains("gdtot") == true) { + val gdBotLink = extractGdbot(oiyaLink) + extractGdflix(gdBotLink ?: return@apmap null) + } else { + oiyaLink + } } else -> { return@apmap null @@ -2041,6 +2047,9 @@ object SoraExtractor : SoraStream() { it.first.contains("/rip") -> { invokeSmashyRip(it.second, it.first, subtitleCallback, callback) } + it.first.contains("/im.php") && !isAnime -> { + invokeSmashyIm(it.second, it.first, subtitleCallback, callback) + } else -> return@apmap } } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 524470c6..38416433 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -563,6 +563,39 @@ suspend fun invokeSmashyRip( } +suspend fun invokeSmashyIm( + name: String, + url: String, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, +) { + val script = + app.get(url).document.selectFirst("script:containsData(player =)")?.data() ?: return + + val sources = + Regex("['\"]?file['\"]?:\\s*\"([^\"]+)").find(script)?.groupValues?.get(1) ?: return + val subtitles = + Regex("['\"]?subtitle['\"]?:\\s*\"([^\"]+)").find(script)?.groupValues?.get(1) ?: return + + M3u8Helper.generateM3u8( + name, + sources, + "" + ).forEach(callback) + + subtitles.split(",").map { sub -> + val lang = Regex("\\[(.*?)]").find(sub)?.groupValues?.getOrNull(1)?.trim() + val trimmedSubLink = sub.removePrefix("[$lang]").trim().substringAfter("?url=") + subtitleCallback.invoke( + SubtitleFile( + lang.takeIf { !it.isNullOrEmpty() } ?: return@map, + trimmedSubLink + ) + ) + } + +} + suspend fun getDumpIdAndType(title: String?, year: Int?, season: Int?): Pair { val res = tryParseJson( queryApi( From 92bd21310a0e5019ae0fddaa64ac60cff2decadf Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 21 Jul 2023 20:47:12 +0700 Subject: [PATCH 015/105] fixed DramaidProvider --- DramaidProvider/build.gradle.kts | 2 +- DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt | 2 +- MultiplexProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/MultiplexProvider.kt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DramaidProvider/build.gradle.kts b/DramaidProvider/build.gradle.kts index 42fd4171..ac1628ab 100644 --- a/DramaidProvider/build.gradle.kts +++ b/DramaidProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 6 +version = 7 cloudstream { diff --git a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt index d1e90376..ad96071f 100644 --- a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt +++ b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt @@ -203,7 +203,7 @@ class DramaidProvider : MainAPI() { it.replace("https://ndrama.xyz", "https://www.fembed.com") }.apmap { when { - it.contains("motonews.club") -> invokeDriveSource( + it.contains("motonews") -> invokeDriveSource( it, this.name, subtitleCallback, diff --git a/MultiplexProvider/build.gradle.kts b/MultiplexProvider/build.gradle.kts index aaeb74f5..51ca5d94 100644 --- a/MultiplexProvider/build.gradle.kts +++ b/MultiplexProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 1 +version = 2 cloudstream { diff --git a/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProvider.kt b/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProvider.kt index 851c267e..7a76be91 100644 --- a/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProvider.kt +++ b/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProvider.kt @@ -10,7 +10,7 @@ import com.lagradost.cloudstream3.utils.getQualityFromName import org.jsoup.nodes.Element class MultiplexProvider : MainAPI() { - override var mainUrl = "https://146.19.24.137" + override var mainUrl = "http://5.104.81.46" override var name = "Multiplex" override val hasMainPage = true override var lang = "id" From b8b87dea74ca8f00d85c6a8c2e1f1ff396e428e6 Mon Sep 17 00:00:00 2001 From: sora Date: Fri, 21 Jul 2023 23:17:23 +0700 Subject: [PATCH 016/105] nekopoi: fix video loading --- Nekopoi/build.gradle.kts | 2 +- Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Nekopoi/build.gradle.kts b/Nekopoi/build.gradle.kts index c3c51979..a8c9601a 100644 --- a/Nekopoi/build.gradle.kts +++ b/Nekopoi/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { diff --git a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt index f94d78f8..27ecc2e8 100644 --- a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt +++ b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt @@ -30,6 +30,7 @@ class Nekopoi : MainAPI() { "SendCm", "GoogleDrive", ) + const val mirroredHost = "https://www.mirrored.to" fun getStatus(t: String?): ShowStatus { return when (t) { @@ -156,7 +157,7 @@ class Nekopoi : MainAPI() { ?.attr("href") }.filter { it.first != Qualities.P360.value }.map { val bypassedAds = bypassMirrored(bypassOuo(it.second)) - bypassedAds.amap ads@{ adsLink -> + bypassedAds.apmap ads@{ adsLink -> loadExtractor( fixEmbed(adsLink) ?: return@ads, "$mainUrl/", @@ -227,19 +228,18 @@ class Nekopoi : MainAPI() { private suspend fun bypassMirrored(url: String?): List { val request = app.get(url ?: return emptyList()) - val hostUrl = getBaseUrl(request.url) var nextUrl = request.document.selectFirst("div.row div.centered a")?.attr("href") nextUrl = app.get(nextUrl ?: return emptyList()).text.substringAfter("\"GET\", \"") .substringBefore("\"") - return app.get(fixUrl(nextUrl, hostUrl)).document.select("table.hoverable tbody tr") + return app.get(fixUrl(nextUrl, mirroredHost)).document.select("table.hoverable tbody tr") .filter { mirror -> !mirrorIsBlackList(mirror.selectFirst("img")?.attr("alt")) - }.amap { + }.apmap { val fileLink = it.selectFirst("a")?.attr("href") app.get( fixUrl( - fileLink ?: return@amap null, - hostUrl + fileLink ?: return@apmap null, + mirroredHost ) ).document.selectFirst("div.code_wrap code")?.text() } From 89a619929b25ff9321f71c9c62c5f7ab009c57c4 Mon Sep 17 00:00:00 2001 From: sora Date: Sat, 22 Jul 2023 12:45:24 +0700 Subject: [PATCH 017/105] changed daddyhd domain --- TimefourTv/build.gradle.kts | 2 +- TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt | 2 +- YomoviesProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Watchomovies.kt | 8 ++++++-- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/TimefourTv/build.gradle.kts b/TimefourTv/build.gradle.kts index dbde5cf2..3fb6e15e 100644 --- a/TimefourTv/build.gradle.kts +++ b/TimefourTv/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 15 +version = 16 cloudstream { diff --git a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt index b5b0dbb0..7b68e7a7 100644 --- a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt +++ b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt @@ -19,7 +19,7 @@ open class TimefourTv : MainAPI() { ) companion object { - const val daddyUrl = "https://d.daddylivehd.sx" + const val daddyUrl = "https://daddylivehd.com" val daddyHost: String = daddyUrl.getHost() private fun String.getHost(): String { return URI(this).host.substringBeforeLast(".").substringAfterLast(".") diff --git a/YomoviesProvider/build.gradle.kts b/YomoviesProvider/build.gradle.kts index f00bbb7e..f5249c1c 100644 --- a/YomoviesProvider/build.gradle.kts +++ b/YomoviesProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 16 +version = 17 cloudstream { diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/Watchomovies.kt b/YomoviesProvider/src/main/kotlin/com/hexated/Watchomovies.kt index 9ed5ad2d..cca19de1 100644 --- a/YomoviesProvider/src/main/kotlin/com/hexated/Watchomovies.kt +++ b/YomoviesProvider/src/main/kotlin/com/hexated/Watchomovies.kt @@ -1,13 +1,13 @@ package com.hexated +import com.lagradost.cloudstream3.LoadResponse import com.lagradost.cloudstream3.TvType import com.lagradost.cloudstream3.mainPageOf class Watchomovies : YomoviesProvider() { override var mainUrl = "https://watchomovies.mom" override var name = "Watchomovies" - override val hasMainPage = true - override var lang = "hi" + override var lang = "en" override val supportedTypes = setOf( TvType.NSFW, ) @@ -20,4 +20,8 @@ class Watchomovies : YomoviesProvider() { "genre/parody" to "Parody Movies", "genre/tv-shows" to "TV Shows Movies", ) + + override suspend fun load(url: String): LoadResponse? { + return super.load(url).apply { this?.type = TvType.NSFW } + } } \ No newline at end of file From 031aa780c95a6855e96b59440132570b18b81415 Mon Sep 17 00:00:00 2001 From: sora Date: Sat, 22 Jul 2023 14:59:26 +0700 Subject: [PATCH 018/105] added Oppadrama --- DramaidProvider/build.gradle.kts | 4 +- .../kotlin/com/hexated/DramaidProvider.kt | 101 ++++++++---------- .../com/hexated/DramaidProviderPlugin.kt | 1 + .../src/main/kotlin/com/hexated/Oppadrama.kt | 6 ++ Gomov/build.gradle.kts | 2 +- 5 files changed, 55 insertions(+), 59 deletions(-) create mode 100644 DramaidProvider/src/main/kotlin/com/hexated/Oppadrama.kt diff --git a/DramaidProvider/build.gradle.kts b/DramaidProvider/build.gradle.kts index ac1628ab..a1beeb4d 100644 --- a/DramaidProvider/build.gradle.kts +++ b/DramaidProvider/build.gradle.kts @@ -1,12 +1,12 @@ // use an integer for version numbers -version = 7 +version = 8 cloudstream { language = "id" // All of these properties are optional, you can safely remove them - // description = "Lorem Ipsum" + description = "Include: Oppadrama" authors = listOf("Hexated") /** diff --git a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt index ad96071f..a757305d 100644 --- a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt +++ b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt @@ -10,14 +10,11 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.Jsoup import org.jsoup.nodes.Element -class DramaidProvider : MainAPI() { +open class DramaidProvider : MainAPI() { override var mainUrl = "https://dramaid.best" override var name = "DramaId" - override val hasQuickSearch = false override val hasMainPage = true override var lang = "id" - override val hasDownloadSupport = true - override val hasChromecastSupport = false override val supportedTypes = setOf(TvType.AsianDrama) companion object { @@ -28,6 +25,14 @@ class DramaidProvider : MainAPI() { else -> ShowStatus.Completed } } + + fun getType(t: String?): TvType { + return when { + t?.contains("Movie", true) == true -> TvType.Movie + t?.contains("Anime", true) == true -> TvType.Anime + else -> TvType.AsianDrama + } + } } override val mainPage = mainPageOf( @@ -45,18 +50,19 @@ class DramaidProvider : MainAPI() { } private fun getProperDramaLink(uri: String): String { - return if (uri.contains("/series/")) { - uri - } else { + return if (uri.contains("-episode-")) { "$mainUrl/series/" + Regex("$mainUrl/(.+)-ep.+").find(uri)?.groupValues?.get(1) - .toString() + } else { + uri } } private fun Element.toSearchResult(): SearchResponse? { val href = getProperDramaLink(this.selectFirst("a.tip")!!.attr("href")) val title = this.selectFirst("h2[itemprop=headline]")?.text()?.trim() ?: return null - val posterUrl = fixUrlNull(this.selectFirst(".limit > noscript > img")?.attr("src")) + val posterUrl = fixUrlNull( + this.selectFirst("noscript img")?.attr("src") ?: this.selectFirst("img")?.attr("src") + ) return newTvSeriesSearchResponse(title, href, TvType.AsianDrama) { this.posterUrl = posterUrl @@ -64,27 +70,19 @@ class DramaidProvider : MainAPI() { } override suspend fun search(query: String): List { - val link = "$mainUrl/?s=$query" - val document = app.get(link).document - - return document.select("article[itemscope=itemscope]").map { - val title = it.selectFirst("h2[itemprop=headline]")!!.text().trim() - val poster = it.selectFirst(".limit > noscript > img")!!.attr("src") - val href = it.selectFirst("a.tip")!!.attr("href") - - newTvSeriesSearchResponse(title, href, TvType.AsianDrama) { - this.posterUrl = poster - } + val document = app.get("$mainUrl/?s=$query").document + return document.select("article[itemscope=itemscope]").mapNotNull { + it.toSearchResult() } } override suspend fun load(url: String): LoadResponse { val document = app.get(url).document - val title = document.selectFirst("h1.entry-title")!!.text().trim() - val poster = document.select(".thumb > noscript > img").attr("src") + val title = document.selectFirst("h1.entry-title")?.text()?.trim() ?: "" + val poster = fixUrlNull(document.selectFirst("div.thumb noscript img")?.attr("src") ?: document.selectFirst("div.thumb img")?.attr("src")) val tags = document.select(".genxed > a").map { it.text() } - + val type = document.selectFirst(".info-content .spe span:contains(Tipe:)")?.ownText() val year = Regex("\\d, ([0-9]*)").find( document.selectFirst(".info-content > .spe > span > time")!!.text().trim() )?.groupValues?.get(1).toString().toIntOrNull() @@ -94,44 +92,34 @@ class DramaidProvider : MainAPI() { ) val description = document.select(".entry-content > p").text().trim() - val episodes = document.select(".eplister > ul > li").map { - val name = it.selectFirst("a > .epl-title")!!.text().trim() - val link = it.select("a").attr("href") - val epNum = it.selectFirst("a > .epl-num")!!.text().trim().toIntOrNull() - newEpisode(link) { - this.name = name - this.episode = epNum - } + val episodes = document.select(".eplister > ul > li").mapNotNull { + val name = it.selectFirst("a > .epl-title")?.text() + val link = fixUrl(it.selectFirst("a")?.attr("href") ?: return@mapNotNull null) + val epNum = it.selectFirst(".epl-num")?.text()?.toIntOrNull() + Episode( + link, + name, + episode = epNum + ) }.reversed() val recommendations = - document.select(".listupd > article[itemscope=itemscope]").map { rec -> - val epTitle = rec.selectFirst("h2[itemprop=headline]")!!.text().trim() - val epPoster = rec.selectFirst(".limit > noscript > img")!!.attr("src") - val epHref = fixUrl(rec.selectFirst("a.tip")!!.attr("href")) - - newTvSeriesSearchResponse(epTitle, epHref, TvType.AsianDrama) { - this.posterUrl = epPoster - } + document.select(".listupd > article[itemscope=itemscope]").mapNotNull { rec -> + rec.toSearchResult() } - if (episodes.size == 1) { - return newMovieLoadResponse(title, url, TvType.Movie, episodes[0].data) { - posterUrl = poster - this.year = year - plot = description - this.tags = tags - this.recommendations = recommendations - } - } else { - return newTvSeriesLoadResponse(title, url, TvType.AsianDrama, episodes = episodes) { - posterUrl = poster - this.year = year - showStatus = status - plot = description - this.tags = tags - this.recommendations = recommendations - } + return newTvSeriesLoadResponse( + title, + url, + getType(type), + episodes = episodes + ) { + posterUrl = poster + this.year = year + showStatus = status + plot = description + this.tags = tags + this.recommendations = recommendations } } @@ -209,6 +197,7 @@ class DramaidProvider : MainAPI() { subtitleCallback, callback ) + else -> loadExtractor(it, data, subtitleCallback, callback) } } diff --git a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProviderPlugin.kt b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProviderPlugin.kt index 78c28ae2..bcf9ac4f 100644 --- a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProviderPlugin.kt +++ b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProviderPlugin.kt @@ -10,6 +10,7 @@ class DramaidProviderPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(DramaidProvider()) + registerMainAPI(Oppadrama()) registerExtractorAPI(Vanfem()) } } \ No newline at end of file diff --git a/DramaidProvider/src/main/kotlin/com/hexated/Oppadrama.kt b/DramaidProvider/src/main/kotlin/com/hexated/Oppadrama.kt new file mode 100644 index 00000000..44dcb365 --- /dev/null +++ b/DramaidProvider/src/main/kotlin/com/hexated/Oppadrama.kt @@ -0,0 +1,6 @@ +package com.hexated + +class Oppadrama : DramaidProvider() { + override var mainUrl = "http://185.217.95.34" + override var name = "Oppadrama" +} \ No newline at end of file diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index 7f2b8216..71e8c9c4 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Include: DutaMovie, Ngefilm" + description = "Include: DutaMovie, Ngefilm" authors = listOf("Hexated") /** From bf9d2d5c31e5ca2346afd508bf9c60498ae0c728 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 22 Jul 2023 21:48:46 +0700 Subject: [PATCH 019/105] fix marin in anichi and added Nodrakorid --- Anichi/build.gradle.kts | 2 +- .../kotlin/com/hexated/AnichiExtractors.kt | 21 ++++++++++--------- .../kotlin/com/hexated/DramaidProvider.kt | 7 +++---- .../src/main/kotlin/com/hexated/DutaMovie.kt | 2 +- .../main/kotlin/com/hexated/GomovPlugin.kt | 1 + Gomov/src/main/kotlin/com/hexated/Ngefilm.kt | 20 +----------------- .../src/main/kotlin/com/hexated/Nodrakorid.kt | 16 ++++++++++++++ 7 files changed, 34 insertions(+), 35 deletions(-) create mode 100644 Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt diff --git a/Anichi/build.gradle.kts b/Anichi/build.gradle.kts index 1a2f6d64..dcc2cb7b 100644 --- a/Anichi/build.gradle.kts +++ b/Anichi/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.konan.properties.Properties // use an integer for version numbers -version = 6 +version = 7 android { defaultConfig { diff --git a/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt b/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt index 5fe9ab9f..d5811278 100644 --- a/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt +++ b/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt @@ -6,6 +6,8 @@ import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.argamap import com.lagradost.cloudstream3.extractors.helper.GogoHelper import com.lagradost.cloudstream3.mvvm.safeApiCall +import com.lagradost.cloudstream3.utils.AppUtils +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.SubtitleHelper @@ -146,20 +148,19 @@ object AnichiExtractors : Anichi() { ), referer = "$marinHost/anime", ).cookies.let { - it["XSRF-TOKEN"] to it["marin_session"] + decode(it["XSRF-TOKEN"].toString()) to decode(it["marin_session"].toString()) } - app.get( + val json = app.get( url, headers = mapOf( - "Referer" to "$marinHost/", - "Cookie" to "__ddg1=;__ddg2_=; XSRF-TOKEN=${cookies.first}; marin_session=${cookies.second};", - "x-inertia" to "true", - "x-inertia-version" to "5ee7503af8c9844b1e8d34466b727694", - "X-Requested-With" to "XMLHttpRequest", - "X-XSRF-TOKEN" to decode(cookies.first.toString()) - ) - ).parsedSafe()?.props?.video?.data?.mirror?.map { video -> + "Accept" to "text/html, application/xhtml+xml", + "Cookie" to "__ddg1=;__ddg2_=;XSRF-TOKEN=${cookies.first};marin_session=${cookies.second};", + "X-XSRF-TOKEN" to cookies.first + ), + referer = "$marinHost/anime/$id" + ).document.selectFirst("div#app")?.attr("data-page") + tryParseJson(json)?.props?.video?.data?.mirror?.map { video -> callback.invoke( ExtractorLink( "Marin", diff --git a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt index a757305d..ab50f5b4 100644 --- a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt +++ b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt @@ -3,6 +3,7 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.extractors.XStreamCdn +import com.lagradost.cloudstream3.utils.AppUtils import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.getQualityFromName @@ -60,9 +61,7 @@ open class DramaidProvider : MainAPI() { private fun Element.toSearchResult(): SearchResponse? { val href = getProperDramaLink(this.selectFirst("a.tip")!!.attr("href")) val title = this.selectFirst("h2[itemprop=headline]")?.text()?.trim() ?: return null - val posterUrl = fixUrlNull( - this.selectFirst("noscript img")?.attr("src") ?: this.selectFirst("img")?.attr("src") - ) + val posterUrl = fixUrlNull(this.select("img:last-child").attr("src")) return newTvSeriesSearchResponse(title, href, TvType.AsianDrama) { this.posterUrl = posterUrl @@ -80,7 +79,7 @@ open class DramaidProvider : MainAPI() { val document = app.get(url).document val title = document.selectFirst("h1.entry-title")?.text()?.trim() ?: "" - val poster = fixUrlNull(document.selectFirst("div.thumb noscript img")?.attr("src") ?: document.selectFirst("div.thumb img")?.attr("src")) + val poster = fixUrlNull(document.select("div.thumb img:last-child").attr("src")) val tags = document.select(".genxed > a").map { it.text() } val type = document.selectFirst(".info-content .spe span:contains(Tipe:)")?.ownText() val year = Regex("\\d, ([0-9]*)").find( diff --git a/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt index 7912713c..08bf2b87 100644 --- a/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt +++ b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt @@ -5,7 +5,7 @@ import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.httpsify import com.lagradost.cloudstream3.utils.loadExtractor -class DutaMovie : Gomov() { +open class DutaMovie : Gomov() { override var mainUrl = "https://dutamovie21.live" override var name = "DutaMovie" diff --git a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt index b3043cb7..bd11fd67 100644 --- a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt +++ b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt @@ -12,6 +12,7 @@ class GomovPlugin: Plugin() { registerMainAPI(Gomov()) registerMainAPI(DutaMovie()) registerMainAPI(Ngefilm()) + registerMainAPI(Nodrakorid()) registerExtractorAPI(Filelions()) registerExtractorAPI(Likessb()) registerExtractorAPI(DbGdriveplayer()) diff --git a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt index 7c4be51f..00c20195 100644 --- a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt +++ b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt @@ -8,7 +8,7 @@ import com.lagradost.cloudstream3.mainPageOf import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor -class Ngefilm : Gomov() { +class Ngefilm : DutaMovie() { override var mainUrl = "https://ngefilm21.lol" override var name = "Ngefilm" @@ -19,22 +19,4 @@ class Ngefilm : Gomov() { "/page/%d/?s=&search=advanced&post_type=tv&index=&orderby=&genre=&movieyear=&country=indonesia&quality=" to "Series Indonesia", ) - override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ): Boolean { - - val document = app.get(data).document - document.select("ul.muvipro-player-tabs li a").apmap { server -> - val iframe = app.get(fixUrl(server.attr("href"))).document.selectFirst("div.gmr-embed-responsive iframe") - ?.attr("src")?.let { fixUrl(it) } ?: return@apmap - loadExtractor(iframe, "$mainUrl/", subtitleCallback, callback) - } - - return true - - } - } \ No newline at end of file diff --git a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt new file mode 100644 index 00000000..1e383927 --- /dev/null +++ b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt @@ -0,0 +1,16 @@ +package com.hexated + +import com.lagradost.cloudstream3.mainPageOf + +class Nodrakorid : DutaMovie() { + override var mainUrl = "https://no-drak-or.xyz" + override var name = "Nodrakorid" + + override val mainPage = mainPageOf( + "genre/movie/page/%d/" to "Film Terbaru", + "genre/korean-movie/page/%d/" to "Film Korea", + "genre/drama/page/%d/" to "Drama Korea", + "genre/c-drama/c-drama-c-drama/page/%d/" to "Drama China", + "genre/thai-drama/page/%d/" to "Drama Thailand", + ) +} \ No newline at end of file From 41d94d1810ea237976f6b765046b638f3e13a1a8 Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Sat, 22 Jul 2023 23:40:21 +0700 Subject: [PATCH 020/105] Update build.gradle.kts --- Gomov/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index 71e8c9c4..326a8138 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Include: DutaMovie, Ngefilm" + description = "Include: DutaMovie, Ngefilm, Nodrakorid" authors = listOf("Hexated") /** From e4597d95671566f8b2f1a4ddc9d24c91b9f6beb5 Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 23 Jul 2023 01:20:33 +0700 Subject: [PATCH 021/105] small fix --- Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt b/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt index 0656e2d2..2c34e9f7 100644 --- a/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt +++ b/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt @@ -87,6 +87,7 @@ private val embedBlackList = listOf( "https://videobin.co/", "https://ok.ru", "https://streamlare.com", + "https://filemoon", "streaming.php", ) From f38a602b972cb4a1ddeeb3453d55f7087ea15cd2 Mon Sep 17 00:00:00 2001 From: hexated Date: Mon, 24 Jul 2023 01:05:02 +0700 Subject: [PATCH 022/105] sora: fix upcloud,vidcloud, aniwatch --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 27 +++++++++---------- .../src/main/kotlin/com/hexated/SoraParser.kt | 6 ++--- .../src/main/kotlin/com/hexated/SoraStream.kt | 3 +-- .../src/main/kotlin/com/hexated/SoraUtils.kt | 27 ++++++++++++++----- 5 files changed, 38 insertions(+), 27 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index f035b3fd..0e7ce60e 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 = 145 +version = 146 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index ad127d88..63d46655 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -930,7 +930,7 @@ object SoraExtractor : SoraStream() { argamap( { - invokeZoro(aniId, episode, subtitleCallback, callback) + invokeAniwatch(malId, episode, subtitleCallback, callback) }, { invokeAnimeKaizoku(malId, epsTitle, season, episode, callback) @@ -1004,28 +1004,26 @@ object SoraExtractor : SoraStream() { } - private suspend fun invokeZoro( - aniId: Int? = null, + private suspend fun invokeAniwatch( + malId: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { - val animeId = - app.get("https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/anilist/anime/${aniId ?: return}.json") - .parsedSafe()?.pages?.zoro?.keys?.map { it } val headers = mapOf( "X-Requested-With" to "XMLHttpRequest", ) + val animeId = app.get("$malsyncAPI/mal/anime/${malId ?: return}").parsedSafe()?.sites?.zoro?.keys?.map { it } animeId?.apmap { id -> - val episodeId = app.get("$zoroAPI/ajax/episode/list/${id ?: return@apmap}", headers = headers) - .parsedSafe()?.html?.let { + val episodeId = app.get("$aniwatchAPI/ajax/v2/episode/list/${id ?: return@apmap}", headers = headers) + .parsedSafe()?.html?.let { Jsoup.parse(it) }?.select("div.ss-list a")?.find { it.attr("data-number") == "${episode ?: 1}" } ?.attr("data-id") val servers = - app.get("$zoroAPI/ajax/episode/servers?episodeId=${episodeId ?: return@apmap}", headers = headers) - .parsedSafe()?.html?.let { Jsoup.parse(it) } + app.get("$aniwatchAPI/ajax/v2/episode/servers?episodeId=${episodeId ?: return@apmap}", headers = headers) + .parsedSafe()?.html?.let { Jsoup.parse(it) } ?.select("div.item.server-item")?.map { Triple( it.text(), @@ -1035,22 +1033,21 @@ object SoraExtractor : SoraStream() { } servers?.apmap servers@{ server -> - val iframe = - app.get("$zoroAPI/ajax/episode/sources?id=${server.second ?: return@servers}", headers = headers) - .parsedSafe()?.link ?: return@servers + val iframe = app.get("$aniwatchAPI/ajax/v2/episode/sources?id=${server.second ?: return@servers}", headers = headers) + .parsedSafe()?.link ?: return@servers val audio = if (server.third == "sub") "Raw" else "English Dub" if (server.first.contains(Regex("Vidstreaming|MegaCloud|Vidcloud"))) { extractRabbitStream( "${server.first} [$audio]", iframe, - "$zoroAPI/", + "$aniwatchAPI/", subtitleCallback, callback, false, decryptKey = RabbitStream.getZoroKey() ) { it } } else { - loadExtractor(iframe, "$zoroAPI/", subtitleCallback, callback) + loadExtractor(iframe, "$aniwatchAPI/", subtitleCallback, callback) } } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 9646b846..ee85e838 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -405,15 +405,15 @@ data class CrunchyrollSourcesResponses( @JsonProperty("meta") val meta: CrunchyrollMeta? = null, ) -data class MALSyncPages( +data class MALSyncSites( @JsonProperty("Zoro") val zoro: HashMap>? = hashMapOf(), ) data class MALSyncResponses( - @JsonProperty("Pages") val pages: MALSyncPages? = null, + @JsonProperty("Sites") val sites: MALSyncSites? = null, ) -data class ZoroResponses( +data class AniwatchResponses( @JsonProperty("html") val html: String? = null, @JsonProperty("link") val link: String? = null, ) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index e0744b10..aab30a60 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -16,7 +16,6 @@ import com.hexated.SoraExtractor.invokeMovieHab import com.hexated.SoraExtractor.invokeNoverse import com.hexated.SoraExtractor.invokeSeries9 import com.hexated.SoraExtractor.invokeVidSrc -import com.hexated.SoraExtractor.invokeXmovies import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.metaproviders.TmdbProvider @@ -100,7 +99,7 @@ open class SoraStream : TmdbProvider() { const val filmxyAPI = "https://www.filmxy.vip" const val kimcartoonAPI = "https://kimcartoon.li" const val xMovieAPI = "https://xemovies.to" - const val zoroAPI = "https://kaido.to" + const val aniwatchAPI = "https://aniwatch.to" const val crunchyrollAPI = "https://beta-api.crunchyroll.com" const val kissKhAPI = "https://kisskh.co" const val lingAPI = "https://ling-online.net" diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 38416433..8db8f4f4 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -21,6 +21,7 @@ import com.lagradost.cloudstream3.APIHolder.getCaptchaToken import com.lagradost.cloudstream3.APIHolder.unixTimeMS import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.Coroutines.ioSafe @@ -578,7 +579,7 @@ suspend fun invokeSmashyIm( Regex("['\"]?subtitle['\"]?:\\s*\"([^\"]+)").find(script)?.groupValues?.get(1) ?: return M3u8Helper.generateM3u8( - name, + "Smashy [$name]", sources, "" ).forEach(callback) @@ -955,7 +956,7 @@ suspend fun searchWatchOnline( } //modified code from https://github.com/jmir1/aniyomi-extensions/blob/master/src/all/kamyroll/src/eu/kanade/tachiyomi/animeextension/all/kamyroll/AccessTokenInterceptor.kt -fun getCrunchyrollToken(): Map { +suspend fun getCrunchyrollToken(): Map { val client = app.baseClient.newBuilder() .proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress("cr-unblocker.us.to", 1080))) .build() @@ -975,7 +976,7 @@ fun getCrunchyrollToken(): Map { "Authorization" to "Basic ${BuildConfig.CRUNCHYROLL_BASIC_TOKEN}" ), data = mapOf( - "refresh_token" to BuildConfig.CRUNCHYROLL_REFRESH_TOKEN, + "refresh_token" to app.get(BuildConfig.CRUNCHYROLL_REFRESH_TOKEN).text, "grant_type" to "refresh_token", "scope" to "offline_access" ) @@ -1840,8 +1841,8 @@ object RabbitStream { if (sources == null || encryptedMap.encrypted == false) { response.parsedSafe() } else { - val decrypted = - decryptMapped>(sources, decryptKey) + val (realKey, encData) = extractRealKey(sources, decryptKey) + val decrypted = decryptMapped>(encData, realKey) SourceObject( sources = decrypted, tracks = encryptedMap.tracks @@ -1984,7 +1985,21 @@ object RabbitStream { } suspend fun getZoroKey(): String { - return app.get("https://raw.githubusercontent.com/enimax-anime/key/e0/key.txt").text + return app.get("https://raw.githubusercontent.com/enimax-anime/key/e6/key.txt").text + } + + private fun extractRealKey(originalString: String?, stops: String) : Pair { + val table = parseJson>>(stops) + val decryptedKey = StringBuilder() + var offset = 0 + var encryptedString = originalString + + table.forEach { (start, end) -> + decryptedKey.append(encryptedString?.substring(start - offset, end - offset)) + encryptedString = encryptedString?.substring(0, start - offset) + encryptedString?.substring(end - offset) + offset += end - start + } + return decryptedKey.toString() to encryptedString.toString() } private inline fun decryptMapped(input: String, key: String): T? { From 22b5f99e48a0bda4dbe7b644c214a7e6de186031 Mon Sep 17 00:00:00 2001 From: hexated Date: Mon, 24 Jul 2023 01:08:26 +0700 Subject: [PATCH 023/105] sora: disable animeKaizoku --- SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 63d46655..6d75648a 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -932,9 +932,6 @@ object SoraExtractor : SoraStream() { { invokeAniwatch(malId, episode, subtitleCallback, callback) }, - { - invokeAnimeKaizoku(malId, epsTitle, season, episode, callback) - }, { invokeBiliBili(aniId, episode, subtitleCallback, callback) }, From c1d59c7f8e727e40df7c61bc214051922e8079da Mon Sep 17 00:00:00 2001 From: hexated Date: Mon, 24 Jul 2023 21:25:57 +0700 Subject: [PATCH 024/105] sora: fixed ask4movies --- Nimegami/build.gradle.kts | 27 +++ Nimegami/src/main/AndroidManifest.xml | 2 + .../src/main/kotlin/com/hexated/Extractors.kt | 60 ++++++ .../src/main/kotlin/com/hexated/Nimegami.kt | 197 ++++++++++++++++++ .../main/kotlin/com/hexated/NimegamiPlugin.kt | 15 ++ NontonAnimeIDProvider/build.gradle.kts | 2 +- .../com/hexated/NontonAnimeIDProvider.kt | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 10 +- .../src/main/kotlin/com/hexated/SoraParser.kt | 8 +- .../src/main/kotlin/com/hexated/SoraStream.kt | 2 +- .../src/main/kotlin/com/hexated/SoraUtils.kt | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 37 ---- .../com/hexated/YomoviesProviderPlugin.kt | 1 - 13 files changed, 316 insertions(+), 49 deletions(-) create mode 100644 Nimegami/build.gradle.kts create mode 100644 Nimegami/src/main/AndroidManifest.xml create mode 100644 Nimegami/src/main/kotlin/com/hexated/Extractors.kt create mode 100644 Nimegami/src/main/kotlin/com/hexated/Nimegami.kt create mode 100644 Nimegami/src/main/kotlin/com/hexated/NimegamiPlugin.kt delete mode 100644 YomoviesProvider/src/main/kotlin/com/hexated/Extractors.kt diff --git a/Nimegami/build.gradle.kts b/Nimegami/build.gradle.kts new file mode 100644 index 00000000..82d96dc1 --- /dev/null +++ b/Nimegami/build.gradle.kts @@ -0,0 +1,27 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + language = "id" + // All of these properties are optional, you can safely remove them + + // description = "Lorem Ipsum" + authors = listOf("Hexated") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "AnimeMovie", + "Anime", + "OVA", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=nimegami.id&sz=%size%" +} \ No newline at end of file diff --git a/Nimegami/src/main/AndroidManifest.xml b/Nimegami/src/main/AndroidManifest.xml new file mode 100644 index 00000000..c98063f8 --- /dev/null +++ b/Nimegami/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Nimegami/src/main/kotlin/com/hexated/Extractors.kt b/Nimegami/src/main/kotlin/com/hexated/Extractors.kt new file mode 100644 index 00000000..aed3ac15 --- /dev/null +++ b/Nimegami/src/main/kotlin/com/hexated/Extractors.kt @@ -0,0 +1,60 @@ +package com.hexated + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities + +open class Mitedrive : ExtractorApi() { + override val name = "Mitedrive" + override val mainUrl = "https://mitedrive.com" + override val requiresReferer = false + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val id = url.substringAfterLast("/") + val video = app.post( + "$mainUrl/api/generate", + referer = "$mainUrl/", + data = mapOf( + "short_url" to id + ) + ).parsedSafe()?.data?.url + + val headers = mapOf( + "Accept" to "*/*", + "Connection" to "keep-alive", + "Sec-Fetch-Dest" to "empty", + "Sec-Fetch-Mode" to "cors", + "Sec-Fetch-Site" to "cross-site", + "Origin" to mainUrl, + ) + + callback.invoke( + ExtractorLink( + this.name, + this.name, + video ?: return, + "$mainUrl/", + Qualities.Unknown.value, + headers = headers + ) + ) + + } + + data class Data( + @JsonProperty("url") val url: String? = null, + ) + + data class Responses( + @JsonProperty("data") val data: Data? = null, + ) + +} \ No newline at end of file diff --git a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt new file mode 100644 index 00000000..69541e2e --- /dev/null +++ b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt @@ -0,0 +1,197 @@ +package com.hexated + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import org.jsoup.nodes.Element +import org.jsoup.select.Elements +import java.net.URI + +class Nimegami : MainAPI() { + override var mainUrl = "https://nimegami.id" + override var name = "Nimegami" + override val hasMainPage = true + override var lang = "id" + override val supportedTypes = setOf( + TvType.Anime, + TvType.AnimeMovie, + TvType.OVA + ) + + companion object { + fun getType(t: String): TvType { + return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA + else if (t.contains("Movie", true)) TvType.AnimeMovie + else TvType.Anime + } + + fun getStatus(t: String?): ShowStatus { + return when { + t?.contains("On-Going", true) == true -> ShowStatus.Ongoing + else -> ShowStatus.Completed + } + } + } + + override val mainPage = mainPageOf( + "" to "Updated Anime", + "/type/tv" to "Anime", + "/type/movie" to "Movie", + "/type/ona" to "ONA", + "/type/live-action" to "Live Action", + ) + + override suspend fun getMainPage( + page: Int, + request: MainPageRequest + ): HomePageResponse { + val document = app.get("$mainUrl${request.data}/page/$page").document + val home = document.select("div.post-article article, div.archive article").mapNotNull { + it.toSearchResult() + } + return newHomePageResponse( + list = HomePageList( + name = request.name, + list = home, + isHorizontalImages = request.name != "Updated Anime" + ), + hasNext = true + ) + } + + private fun Element.toSearchResult(): AnimeSearchResponse? { + val href = fixUrl(this.selectFirst("a")!!.attr("href")) + val title = this.selectFirst("h2 a")?.text() ?: return null + val posterUrl = (this.selectFirst("noscript img") ?: this.selectFirst("img"))?.attr("src") + val episode = this.selectFirst("ul li:contains(Episode), div.eps-archive")?.ownText() + ?.filter { it.isDigit() }?.toIntOrNull() + + return newAnimeSearchResponse(title, href, TvType.Anime) { + this.posterUrl = posterUrl + addSub(episode) + } + + } + + override suspend fun search(query: String): List { + return app.get("$mainUrl/?s=$query&post_type=post").document.select("div.archive article") + .mapNotNull { + it.toSearchResult() + } + } + + override suspend fun load(url: String): LoadResponse { + val document = app.get(url).document + + val table = document.select("div#Info table tbody") + val title = table.getContent("Judul :").text() + val poster = document.selectFirst("div.coverthumbnail img")?.attr("src") + val bgPoster = document.selectFirst("div.thumbnail-a img")?.attr("src") + val tags = table.getContent("Kategori").select("a").map { it.text() } + + val year = table.getContent("Musim / Rilis").text().filter { it.isDigit() }.toIntOrNull() + val status = getStatus(document.selectFirst("h1[itemprop=headline]")?.text()) + val type = table.getContent("Type").text() + val description = document.select("div#Sinopsis p").text().trim() + + + val episodes = document.select("div.list_eps_stream li") + .mapNotNull { + val name = it.text() + val link = it.attr("data") + Episode(link, name) + } + + val recommendations = document.select("div#randomList > a").mapNotNull { + val epHref = it.attr("href") + val epTitle = it.select("h5.sidebar-title-h5.px-2.py-2").text() + val epPoster = it.select(".product__sidebar__view__item.set-bg").attr("data-setbg") + + newAnimeSearchResponse(epTitle, epHref, TvType.Anime) { + this.posterUrl = epPoster + addDubStatus(dubExist = false, subExist = true) + } + } + + return newAnimeLoadResponse(title, url, getType(type)) { + engName = title + posterUrl = poster + backgroundPosterUrl = bgPoster + this.year = year + addEpisodes(DubStatus.Subbed, episodes) + showStatus = status + plot = description + this.tags = tags + this.recommendations = recommendations + } + + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + tryParseJson>(base64Decode(data))?.map { sources -> + sources.url?.apmap { url -> + loadFixedExtractor(url.fixIframe(), sources.format, "$mainUrl/", subtitleCallback, callback) + } + } + + return true + } + + private suspend fun loadFixedExtractor( + url: String, + quality: String?, + referer: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + loadExtractor(url, referer, subtitleCallback) { link -> + callback.invoke( + ExtractorLink( + link.name, + link.name, + link.url, + link.referer, + getQualityFromName(quality), + link.isM3u8, + link.headers, + link.extractorData + ) + ) + } + } + + private fun getBaseUrl(url: String): String { + return URI(url).let { + "${it.scheme}://${it.host}" + } + } + + private fun Elements.getContent(css: String) : Elements { + return this.select("tr:contains($css) td:last-child") + } + + private fun String.fixIframe() : String { + val url = base64Decode(this.substringAfter("url=").substringAfter("id=")) + val host = getBaseUrl(url) + return when { + url.contains("hxfile") -> { + val id = url.substringAfterLast("/") + "$host/embed-$id.html" + } + else -> fixUrl(url) + } + } + + data class Sources( + @JsonProperty("format") val format: String? = null, + @JsonProperty("url") val url: ArrayList? = arrayListOf(), + ) + +} diff --git a/Nimegami/src/main/kotlin/com/hexated/NimegamiPlugin.kt b/Nimegami/src/main/kotlin/com/hexated/NimegamiPlugin.kt new file mode 100644 index 00000000..8ab01378 --- /dev/null +++ b/Nimegami/src/main/kotlin/com/hexated/NimegamiPlugin.kt @@ -0,0 +1,15 @@ + +package com.hexated + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class NimegamiPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(Nimegami()) + registerExtractorAPI(Mitedrive()) + } +} \ No newline at end of file diff --git a/NontonAnimeIDProvider/build.gradle.kts b/NontonAnimeIDProvider/build.gradle.kts index 3da1506d..cff263d4 100644 --- a/NontonAnimeIDProvider/build.gradle.kts +++ b/NontonAnimeIDProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 15 +version = 16 cloudstream { diff --git a/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt b/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt index aa54f212..2912e7a2 100644 --- a/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt +++ b/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt @@ -11,7 +11,7 @@ import org.jsoup.nodes.Element import java.net.URI class NontonAnimeIDProvider : MainAPI() { - override var mainUrl = "https://nontonanimeid.bio" + override var mainUrl = "https://nontonanimeid.lol" override var name = "NontonAnimeID" override val hasQuickSearch = false override val hasMainPage = true diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 6d75648a..8b3819d5 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2695,7 +2695,15 @@ object SoraExtractor : SoraStream() { epsDoc.select("ul.group-links-list li:nth-child($episode) a").attr("data-embed-src") } - loadExtractor(iframe, ask4MoviesAPI, subtitleCallback, callback) + val iframeDoc = app.get(iframe, referer = "$ask4MoviesAPI/").text + val script = Regex("""eval\(function\(p,a,c,k,e,.*\)\)""").findAll(iframeDoc).lastOrNull()?.value + val unpacked = getAndUnpack(script ?: return) + val m3u8 = Regex("file:\\s*\"(.*?m3u8.*?)\"").find(unpacked)?.groupValues?.getOrNull(1) + M3u8Helper.generateM3u8( + "Ask4movie", + m3u8 ?: return, + mainUrl + ).forEach(callback) } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index ee85e838..a1e91094 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -336,16 +336,12 @@ data class VizcloudSources( @JsonProperty("file") val file: String? = null, ) -data class VizcloudMedia( +data class VizcloudResult( @JsonProperty("sources") val sources: ArrayList? = arrayListOf(), ) -data class VizcloudData( - @JsonProperty("media") val media: VizcloudMedia? = null, -) - data class VizcloudResponses( - @JsonProperty("data") val data: VizcloudData? = null, + @JsonProperty("result") val result: VizcloudResult? = null, ) data class AnilistExternalLinks( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index aab30a60..16d00b6b 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -119,7 +119,7 @@ open class SoraStream : TmdbProvider() { const val smashyStreamAPI = "https://embed.smashystream.com" const val watchSomuchAPI = "https://watchsomuch.tv" // sub only val gomoviesAPI = base64DecodeAPI("bQ==Y28=ZS4=aW4=bmw=LW8=ZXM=dmk=bW8=Z28=Ly8=czo=dHA=aHQ=") - const val ask4MoviesAPI = "https://ask4movie.net" + const val ask4MoviesAPI = "https://ask4movie.nl" const val biliBiliAPI = "https://api-vn.otakuz.live/server" const val watchOnlineAPI = "https://watchonline.ag" const val nineTvAPI = "https://api.9animetv.live" diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 8db8f4f4..5f2ae0fd 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -418,7 +418,7 @@ suspend fun invokeVizcloud( ) { val id = Regex("(?:/embed[-/]|/e/)([^?/]*)").find(url)?.groupValues?.getOrNull(1) app.get("$consumetHelper?query=${id ?: return}&action=vizcloud") - .parsedSafe()?.data?.media?.sources?.map { + .parsedSafe()?.result?.sources?.map { M3u8Helper.generateM3u8( "Vizcloud", it.file ?: return@map, diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/Extractors.kt b/YomoviesProvider/src/main/kotlin/com/hexated/Extractors.kt deleted file mode 100644 index 08597bf1..00000000 --- a/YomoviesProvider/src/main/kotlin/com/hexated/Extractors.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.hexated - -import com.fasterxml.jackson.annotation.JsonProperty -import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.extractors.SpeedoStream -import com.lagradost.cloudstream3.utils.AppUtils -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.M3u8Helper -import com.lagradost.cloudstream3.utils.getAndUnpack - -class Streamoupload : SpeedoStream() { - override val mainUrl = "https://streamoupload.xyz" - override val name = "Streamoupload" - - override suspend fun getUrl( - url: String, - referer: String?, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - val script = getAndUnpack(app.get(url, referer = referer).text) - val data = script.substringAfter("sources:[") - .substringBefore("],").replace("file", "\"file\"").trim() - AppUtils.tryParseJson(data)?.let { - M3u8Helper.generateM3u8( - name, - it.file, - "$mainUrl/", - ).forEach(callback) - } - } - - private data class File( - @JsonProperty("file") val file: String, - ) -} \ No newline at end of file diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProviderPlugin.kt b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProviderPlugin.kt index 60bb8004..45bf3e5a 100644 --- a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProviderPlugin.kt +++ b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProviderPlugin.kt @@ -11,6 +11,5 @@ class YomoviesProviderPlugin: Plugin() { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(YomoviesProvider()) registerMainAPI(Watchomovies()) - registerExtractorAPI(Streamoupload()) } } \ No newline at end of file From 839ec22f6768e24dbb058c66cef283e992a1d0dc Mon Sep 17 00:00:00 2001 From: hexated Date: Mon, 24 Jul 2023 21:26:12 +0700 Subject: [PATCH 025/105] sora: fixed ask4movies --- SoraStream/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 0e7ce60e..cc49bd00 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 = 146 +version = 147 android { defaultConfig { From 571f4551006489ad0a40812a9f538fab144292b9 Mon Sep 17 00:00:00 2001 From: sora Date: Tue, 25 Jul 2023 14:46:32 +0700 Subject: [PATCH 026/105] added Serienstream & Movie4k --- Aniworld/build.gradle.kts | 4 +- .../src/main/kotlin/com/hexated/Aniworld.kt | 3 +- .../main/kotlin/com/hexated/AniworldPlugin.kt | 1 + .../main/kotlin/com/hexated/Serienstream.kt | 12 ++++ Nimegami/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Nimegami.kt | 13 ++-- Xcineio/build.gradle.kts | 4 +- .../src/main/kotlin/com/hexated/Movie4k.kt | 16 +++++ Xcineio/src/main/kotlin/com/hexated/XCine.kt | 64 +++++++++---------- .../main/kotlin/com/hexated/XCinePlugin.kt | 1 + 10 files changed, 76 insertions(+), 44 deletions(-) create mode 100644 Aniworld/src/main/kotlin/com/hexated/Serienstream.kt create mode 100644 Xcineio/src/main/kotlin/com/hexated/Movie4k.kt diff --git a/Aniworld/build.gradle.kts b/Aniworld/build.gradle.kts index 004864a6..d303a028 100644 --- a/Aniworld/build.gradle.kts +++ b/Aniworld/build.gradle.kts @@ -1,12 +1,12 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { language = "de" // All of these properties are optional, you can safely remove them - // description = "Lorem Ipsum" + description = "Include: Serienstream" authors = listOf("Hexated") /** diff --git a/Aniworld/src/main/kotlin/com/hexated/Aniworld.kt b/Aniworld/src/main/kotlin/com/hexated/Aniworld.kt index f0765f52..a5c6b08f 100644 --- a/Aniworld/src/main/kotlin/com/hexated/Aniworld.kt +++ b/Aniworld/src/main/kotlin/com/hexated/Aniworld.kt @@ -13,12 +13,11 @@ import org.jsoup.nodes.Document import org.jsoup.nodes.Element import java.net.URI -class Aniworld : MainAPI() { +open class Aniworld : MainAPI() { override var mainUrl = "https://aniworld.to" override var name = "Aniworld" override val hasMainPage = true override var lang = "de" - override val hasDownloadSupport = true override val supportedTypes = setOf( TvType.Anime, diff --git a/Aniworld/src/main/kotlin/com/hexated/AniworldPlugin.kt b/Aniworld/src/main/kotlin/com/hexated/AniworldPlugin.kt index b70bad8f..7eee506e 100644 --- a/Aniworld/src/main/kotlin/com/hexated/AniworldPlugin.kt +++ b/Aniworld/src/main/kotlin/com/hexated/AniworldPlugin.kt @@ -10,6 +10,7 @@ class AniworldPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(Aniworld()) + registerMainAPI(Serienstream()) registerExtractorAPI(Urochsunloath()) registerExtractorAPI(Simpulumlamerop()) registerExtractorAPI(Dooood()) diff --git a/Aniworld/src/main/kotlin/com/hexated/Serienstream.kt b/Aniworld/src/main/kotlin/com/hexated/Serienstream.kt new file mode 100644 index 00000000..d7a88ed5 --- /dev/null +++ b/Aniworld/src/main/kotlin/com/hexated/Serienstream.kt @@ -0,0 +1,12 @@ +package com.hexated + +import com.lagradost.cloudstream3.TvType + +class Serienstream : Aniworld() { + override var mainUrl = "https://s.to" + override var name = "Serienstream" + override val supportedTypes = setOf( + TvType.Movie, + TvType.TvSeries, + ) +} \ No newline at end of file diff --git a/Nimegami/build.gradle.kts b/Nimegami/build.gradle.kts index 82d96dc1..e861ae1d 100644 --- a/Nimegami/build.gradle.kts +++ b/Nimegami/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 1 +version = 2 cloudstream { diff --git a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt index 69541e2e..7b2babd5 100644 --- a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt +++ b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt @@ -2,6 +2,7 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import org.jsoup.nodes.Element @@ -21,9 +22,12 @@ class Nimegami : MainAPI() { companion object { fun getType(t: String): TvType { - return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA - else if (t.contains("Movie", true)) TvType.AnimeMovie - else TvType.Anime + return when { + t.contains("Tv", true) -> TvType.AnimeMovie + t.contains("Movie", true) -> TvType.AnimeMovie + t.contains("OVA", true) || t.contains("Special", true) -> TvType.OVA + else -> TvType.Anime + } } fun getStatus(t: String?): ShowStatus { @@ -94,7 +98,7 @@ class Nimegami : MainAPI() { val status = getStatus(document.selectFirst("h1[itemprop=headline]")?.text()) val type = table.getContent("Type").text() val description = document.select("div#Sinopsis p").text().trim() - + val trailer = document.selectFirst("div#Trailer iframe")?.attr("src") val episodes = document.select("div.list_eps_stream li") .mapNotNull { @@ -124,6 +128,7 @@ class Nimegami : MainAPI() { plot = description this.tags = tags this.recommendations = recommendations + addTrailer(trailer) } } diff --git a/Xcineio/build.gradle.kts b/Xcineio/build.gradle.kts index 3261137f..2434acfa 100644 --- a/Xcineio/build.gradle.kts +++ b/Xcineio/build.gradle.kts @@ -1,12 +1,12 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { language = "de" // All of these properties are optional, you can safely remove them - // description = "Lorem Ipsum" + description = "Include: Movie4k" authors = listOf("Hexated") /** diff --git a/Xcineio/src/main/kotlin/com/hexated/Movie4k.kt b/Xcineio/src/main/kotlin/com/hexated/Movie4k.kt new file mode 100644 index 00000000..f5eca865 --- /dev/null +++ b/Xcineio/src/main/kotlin/com/hexated/Movie4k.kt @@ -0,0 +1,16 @@ +package com.hexated + +import com.lagradost.cloudstream3.mainPageOf + +class Movie4k : XCine() { + override var name = "Movie4k" + override var mainUrl = "https://movie4k.stream" + override var mainAPI = "https://api.movie4k.stream" + + override val mainPage = mainPageOf( + "data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=movies&order_by=trending" to "Derzeit Beliebt Filme", + "data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=movies&order_by=releases" to "Neu Filme", + "data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=tvseries&order_by=trending" to "Derzeit Beliebt Serien", + "data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=tvseries&order_by=releases" to "Neu Serien", + ) +} \ No newline at end of file diff --git a/Xcineio/src/main/kotlin/com/hexated/XCine.kt b/Xcineio/src/main/kotlin/com/hexated/XCine.kt index aaf68804..0431f393 100644 --- a/Xcineio/src/main/kotlin/com/hexated/XCine.kt +++ b/Xcineio/src/main/kotlin/com/hexated/XCine.kt @@ -9,22 +9,22 @@ import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.loadExtractor -class XCine : MainAPI() { +open class XCine : MainAPI() { override var name = "XCine" - override var mainUrl = "https://xcine.info" + override var mainUrl = "https://xcine.ru" override var lang = "de" override val hasQuickSearch = true override val usesWebView = false override val hasMainPage = true override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie) - private val mainAPI = "https://api.xcine.info" + open var mainAPI = "https://api.xcine.ru" override val mainPage = mainPageOf( - "$mainAPI/data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=movies&order_by=trending&page=" to "Trending", - "$mainAPI/data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=movies&order_by=Views&page=" to "Most View Filme", - "$mainAPI/data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=tvseries&order_by=Trending&page=" to "Trending Serien", - "$mainAPI/data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=movies&order_by=Updates&page=" to "Updated Filme", - "$mainAPI/data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=tvseries&order_by=Updates&page=" to "Updated Serien", + "data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=movies&order_by=trending" to "Trending", + "data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=movies&order_by=Views" to "Most View Filme", + "data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=tvseries&order_by=Trending" to "Trending Serien", + "data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=movies&order_by=Updates" to "Updated Filme", + "data/browse/?lang=2&keyword=&year=&rating=&votes=&genre=&country=&cast=&directors=&type=tvseries&order_by=Updates" to "Updated Serien", ) private fun getImageUrl(link: String?): String? { @@ -32,12 +32,17 @@ class XCine : MainAPI() { return if (link.startsWith("/")) "https://image.tmdb.org/t/p/w500/$link" else link } + private fun getBackupImageUrl(link: String?): String? { + if (link == null) return null + return "https://cdn.movie4k.stream/data${link.substringAfter("/data")}" + } + override suspend fun getMainPage( page: Int, request: MainPageRequest ): HomePageResponse { val home = - app.get(request.data + page, referer = "$mainUrl/") + app.get("$mainAPI/${request.data}&page=$page", referer = "$mainUrl/") .parsedSafe()?.movies?.mapNotNull { res -> res.toSearchResponse() } ?: throw ErrorLoadingException() @@ -48,11 +53,11 @@ class XCine : MainAPI() { return newAnimeSearchResponse( title ?: original_title ?: return null, // Data(_id).toJson(), - "$_id", + Link(id=_id).toJson(), TvType.TvSeries, false ) { - this.posterUrl = getImageUrl(poster_path ?: backdrop_path) + this.posterUrl = getImageUrl(poster_path ?: backdrop_path) ?: getBackupImageUrl(img) addDub(last_updated_epi?.toIntOrNull()) addSub(totalEpisodes?.toIntOrNull()) } @@ -61,16 +66,14 @@ class XCine : MainAPI() { override suspend fun quickSearch(query: String): List = search(query) override suspend fun search(query: String): List { - return app.get( - "$mainAPI/data/browse/?lang=2&keyword=$query&year=&rating=&votes=&genre=&country=&cast=&directors=&type=&order_by=&page=1", - referer = "$mainUrl/" - ).parsedSafe()?.movies?.mapNotNull { res -> - res.toSearchResponse() + val res = app.get("$mainAPI/data/search/?lang=2&keyword=$query", referer = "$mainUrl/").text + return tryParseJson>(res)?.mapNotNull { + it.toSearchResponse() } ?: throw ErrorLoadingException() } override suspend fun load(url: String): LoadResponse? { - val id = url.replace("$mainUrl/", "") + val id = parseJson(url).id val res = app.get("$mainAPI/data/watch/?_id=$id", referer = "$mainUrl/") .parsedSafe() ?: throw ErrorLoadingException() @@ -84,20 +87,13 @@ class XCine : MainAPI() { } return if (type == "tv") { - val episodes = mutableListOf() - val json = - app.get("$mainAPI/data/seasons/?lang=2&original_title=${res.original_title}").text.let { - tryParseJson>(it) - } - json?.map { season -> - season.streams?.distinctBy { it.e }?.map { eps -> - episodes.add(Episode(data = season.streams.filter { it.e == eps.e } - .map { Link(it.stream) } - .toJson(), episode = eps.e, season = season.s)) - } - } + val episodes = res.streams?.groupBy { it.e.toString().toIntOrNull() }?.mapNotNull { eps -> + val epsNum = eps.key + val epsLink = eps.value.map { it.stream }.toJson() + Episode(epsLink, episode = epsNum) + } ?: emptyList() newTvSeriesLoadResponse( - res.original_title ?: res.title ?: return null, + res.title ?: res.original_title ?: return null, url, TvType.TvSeries, episodes @@ -135,7 +131,7 @@ class XCine : MainAPI() { val loadData = parseJson>(data) loadData.apmap { val link = fixUrlNull(it.link) ?: return@apmap null - if(link.startsWith("https://dl.streamcloud")) { + if (link.startsWith("https://dl.streamcloud")) { callback.invoke( ExtractorLink( this.name, @@ -159,7 +155,8 @@ class XCine : MainAPI() { } data class Link( - val link: String?, + val link: String? = null, + val id: String? = null, ) data class Season( @@ -173,7 +170,7 @@ class XCine : MainAPI() { data class Streams( @JsonProperty("_id") val _id: String? = null, @JsonProperty("stream") val stream: String? = null, - @JsonProperty("e") val e: Int? = null, + @JsonProperty("e") val e: Any? = null, @JsonProperty("e_title") val e_title: String? = null, ) @@ -199,6 +196,7 @@ class XCine : MainAPI() { @JsonProperty("title") val title: String? = null, @JsonProperty("poster_path") val poster_path: String? = null, @JsonProperty("backdrop_path") val backdrop_path: String? = null, + @JsonProperty("img") val img: String? = null, @JsonProperty("imdb_id") val imdb_id: String? = null, @JsonProperty("totalEpisodes") val totalEpisodes: String? = null, @JsonProperty("last_updated_epi") val last_updated_epi: String? = null, diff --git a/Xcineio/src/main/kotlin/com/hexated/XCinePlugin.kt b/Xcineio/src/main/kotlin/com/hexated/XCinePlugin.kt index 625945aa..8989499f 100644 --- a/Xcineio/src/main/kotlin/com/hexated/XCinePlugin.kt +++ b/Xcineio/src/main/kotlin/com/hexated/XCinePlugin.kt @@ -10,6 +10,7 @@ class XCinePlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(XCine()) + registerMainAPI(Movie4k()) registerExtractorAPI(StreamTapeAdblockuser()) registerExtractorAPI(StreamTapeTo()) registerExtractorAPI(Mixdrp()) From e39b0b97c99f403008d583c8c0e15f01be62e502 Mon Sep 17 00:00:00 2001 From: sora Date: Tue, 25 Jul 2023 15:18:03 +0700 Subject: [PATCH 027/105] small fix --- Aniworld/src/main/kotlin/com/hexated/Serienstream.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Aniworld/src/main/kotlin/com/hexated/Serienstream.kt b/Aniworld/src/main/kotlin/com/hexated/Serienstream.kt index d7a88ed5..ff475aa6 100644 --- a/Aniworld/src/main/kotlin/com/hexated/Serienstream.kt +++ b/Aniworld/src/main/kotlin/com/hexated/Serienstream.kt @@ -1,5 +1,6 @@ package com.hexated +import com.lagradost.cloudstream3.LoadResponse import com.lagradost.cloudstream3.TvType class Serienstream : Aniworld() { @@ -9,4 +10,8 @@ class Serienstream : Aniworld() { TvType.Movie, TvType.TvSeries, ) + + override suspend fun load(url: String): LoadResponse? { + return super.load(url).apply { this?.type = TvType.TvSeries } + } } \ No newline at end of file From 75437d78a732292deb964a97e41a1c7161832788 Mon Sep 17 00:00:00 2001 From: sora Date: Tue, 25 Jul 2023 15:33:26 +0700 Subject: [PATCH 028/105] Nimegami: fix type --- Nimegami/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 15 +++++---------- Nimegami/src/main/kotlin/com/hexated/Nimegami.kt | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/Nimegami/build.gradle.kts b/Nimegami/build.gradle.kts index e861ae1d..f4617aee 100644 --- a/Nimegami/build.gradle.kts +++ b/Nimegami/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { diff --git a/Nimegami/src/main/kotlin/com/hexated/Extractors.kt b/Nimegami/src/main/kotlin/com/hexated/Extractors.kt index aed3ac15..a7f36f2e 100644 --- a/Nimegami/src/main/kotlin/com/hexated/Extractors.kt +++ b/Nimegami/src/main/kotlin/com/hexated/Extractors.kt @@ -27,15 +27,6 @@ open class Mitedrive : ExtractorApi() { ) ).parsedSafe()?.data?.url - val headers = mapOf( - "Accept" to "*/*", - "Connection" to "keep-alive", - "Sec-Fetch-Dest" to "empty", - "Sec-Fetch-Mode" to "cors", - "Sec-Fetch-Site" to "cross-site", - "Origin" to mainUrl, - ) - callback.invoke( ExtractorLink( this.name, @@ -43,7 +34,11 @@ open class Mitedrive : ExtractorApi() { video ?: return, "$mainUrl/", Qualities.Unknown.value, - headers = headers + headers = mapOf( + "Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5", + "Sec-Fetch-Dest" to "video", + "Sec-Fetch-Mode" to "no-cors", + ) ) ) diff --git a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt index 7b2babd5..a2ed9aaf 100644 --- a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt +++ b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt @@ -23,7 +23,7 @@ class Nimegami : MainAPI() { companion object { fun getType(t: String): TvType { return when { - t.contains("Tv", true) -> TvType.AnimeMovie + t.contains("Tv", true) -> TvType.Anime t.contains("Movie", true) -> TvType.AnimeMovie t.contains("OVA", true) || t.contains("Special", true) -> TvType.OVA else -> TvType.Anime From 9066c050e506ee723798760406dbffc597f6b58f Mon Sep 17 00:00:00 2001 From: tuan041 <30403510+tuan041@users.noreply.github.com> Date: Tue, 25 Jul 2023 15:44:45 +0700 Subject: [PATCH 029/105] fix phim1080 (#207) * bump * fix * new * new * new * new * change version * bump * Delete Phim1080/src/main/com/hexated directory * Add more servers * Update Phim1080Provider.kt --- Phim1080/build.gradle.kts | 2 +- .../kotlin/com/hexated/Phim1080Provider.kt | 88 ++++++++++++------- 2 files changed, 55 insertions(+), 35 deletions(-) diff --git a/Phim1080/build.gradle.kts b/Phim1080/build.gradle.kts index bd0faf7c..c0fd5859 100644 --- a/Phim1080/build.gradle.kts +++ b/Phim1080/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 1 +version = 2 cloudstream { diff --git a/Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt b/Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt index edadf591..4f25ba99 100644 --- a/Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt +++ b/Phim1080/src/main/kotlin/com/hexated/Phim1080Provider.kt @@ -3,12 +3,13 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.ExtractorLink import org.jsoup.nodes.Element class Phim1080Provider : MainAPI() { - override var mainUrl = "https://xem1080.com" + override var mainUrl = "https://phimnhanh2.com" override var name = "Phim1080" override val hasMainPage = true override var lang = "vi" @@ -20,10 +21,10 @@ class Phim1080Provider : MainAPI() { TvType.AsianDrama ) - private fun encodeString(e: String, t: Int): String { + private fun decodeString(e: String, t: Int): String { var a = "" - for (element in e) { - val r = element.code + for (i in 0 until e.length) { + val r = e[i].code val o = r xor t a += o.toChar() } @@ -109,7 +110,7 @@ class Phim1080Provider : MainAPI() { "Content-Type" to "application/json", "X-Requested-With" to "XMLHttpRequest" ) - ).parsedSafe() + ).parsedSafe() val title = filmInfo?.name?.trim().toString() val poster = filmInfo?.thumbnail val background = filmInfo?.poster @@ -176,26 +177,45 @@ class Phim1080Provider : MainAPI() { val fId = document.select("div.container").attr("data-id") val epId = document.select("div.container").attr("data-episode-id") val doc = app.get( - "$mainUrl/api/v2/films/$fId/episodes/$epId", - referer = data, - headers = mapOf( - "Content-Type" to "application/json", - "cookie" to "xem1080=%3D", - "X-Requested-With" to "XMLHttpRequest" - ) - ) - val source = doc.text.substringAfter(":{\"hls\":\"").substringBefore("\"},") - val link = encodeString(source, 69) - callback.invoke( - ExtractorLink( - "HS", - "HS", - link, - referer = data, - quality = Qualities.Unknown.value, - isM3u8 = true, - ) + "$mainUrl/api/v2/films/$fId/episodes/$epId", + referer = data, + headers = mapOf( + "Content-Type" to "application/json", + "cookie" to "phimnhanh=%3D", + "X-Requested-With" to "XMLHttpRequest" ) + ) + + val optEncode = if (doc.text.indexOf("\"opt\":\"") != -1) { + doc.text.substringAfter("\"opt\":\"").substringBefore("\"},") + } else { "" } + val opt = decodeString(optEncode as String, 69).replace("0uut$", "_").replace("index.m3u8", "3000k/hls/mixed.m3u8") + val hlsEncode = if (doc.text.indexOf(":{\"hls\":\"") != -1) { + doc.text.substringAfter(":{\"hls\":\"").substringBefore("\"},") + } else { "" } + val hls = decodeString(hlsEncode as String, 69) + val fb = if (doc.text.indexOf("\"fb\":[{\"src\":\"") != -1) { + doc.text.substringAfter("\"fb\":[{\"src\":\"").substringBefore("\",").replace("\\", "") + } else { "" } + + listOfNotNull( + if (hls.contains(".m3u8")) {Triple("$hls", "HS", true)} else null, + if (fb.contains(".mp4")) {Triple("$fb", "FB", false)} else null, + if (opt.contains(".m3u8")) {Triple("$opt", "OP", true)} else null, + ).apmap { (link, source, isM3u8) -> + safeApiCall { + callback.invoke( + ExtractorLink( + source, + source, + link, + referer = data, + quality = Qualities.Unknown.value, + isM3u8, + ) + ) + } + } val subId = doc.parsedSafe()?.subtitle?.vi val isSubIdEmpty = subId.isNullOrBlank() if (!isSubIdEmpty) { @@ -208,8 +228,8 @@ class Phim1080Provider : MainAPI() { } return true } - - data class FilmInfo( + + data class filmInfo( @JsonProperty("name") val name: String? = null, @JsonProperty("poster") val poster: String? = null, @JsonProperty("thumbnail") val thumbnail: String? = null, @@ -221,27 +241,27 @@ class Phim1080Provider : MainAPI() { data class TrailerInfo( @JsonProperty("original") val original: TrailerKey? = null, ) - + data class TrailerKey( @JsonProperty("id") val id: String? = null, ) - + data class MediaDetailEpisodes( @JsonProperty("data") val eps: ArrayList? = arrayListOf(), ) - + data class Episodes( @JsonProperty("link") val link: String? = null, @JsonProperty("detail_name") val detailname: String? = null, @JsonProperty("name") val episodeNumber: Int? = null, - ) - + ) + data class Media( @JsonProperty("subtitle") val subtitle: SubInfo? = null, ) - + data class SubInfo( @JsonProperty("vi") val vi: String? = null, - ) - + ) + } From 5fa20bfd64a2e2bbd33059723efb7ec5b703d72c Mon Sep 17 00:00:00 2001 From: hexated Date: Wed, 26 Jul 2023 14:31:20 +0700 Subject: [PATCH 030/105] sora: added Multimovies --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 57 ++++++++++++++++++- .../src/main/kotlin/com/hexated/SoraStream.kt | 9 ++- .../main/kotlin/com/hexated/SoraStreamLite.kt | 4 ++ .../kotlin/com/hexated/SoraStreamPlugin.kt | 3 + .../src/main/kotlin/com/hexated/SoraUtils.kt | 26 +++++++++ 6 files changed, 97 insertions(+), 4 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index cc49bd00..5dddfb7e 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 = 147 +version = 148 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 8b3819d5..829ca294 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -6,6 +6,8 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.nicehttp.Requests 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.helper.GogoHelper import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.nicehttp.RequestBodyTypes @@ -437,6 +439,41 @@ object SoraExtractor : SoraStream() { } } + suspend fun invokeMultimovies( + title: String? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val fixTitle = title.createSlug() + val url = if (season == null) { + "$multimoviesAPI/movies/$fixTitle" + } else { + "$multimoviesAPI/episodes/$fixTitle-${season}x${episode}" + } + + val res = app.get(url) + val referer = getBaseUrl(res.url) + val document = res.document + val id = document.select("meta#dooplay-ajax-counter").attr("data-postid") + val type = if (url.contains("/movies/")) "movie" else "tv" + + document.select("ul#playeroptionsul > li").map { + it.attr("data-nume") + }.apmap { nume -> + val source = app.post( + url = "$referer/wp-admin/admin-ajax.php", data = mapOf( + "action" to "doo_player_ajax", "post" to id, "nume" to nume, "type" to type + ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = url + ).parsed().embed_url.let { Jsoup.parse(it).select("IFRAME").attr("SRC") } + + if (!source.contains("youtube")) { + loadExtractor(source, "$referer/", subtitleCallback, callback) + } + } + } + suspend fun invokeUniqueStream( title: String? = null, year: Int? = null, @@ -2029,7 +2066,7 @@ object SoraExtractor : SoraStream() { it.attr("data-id") to it.text() }.apmap { when { - it.first.contains("/ffix") && !isAnime -> { + it.first.contains("/fix.php") && !isAnime -> { invokeSmashyFfix(it.second, it.first, url, callback) } it.first.contains("/gtop") -> { @@ -2044,6 +2081,9 @@ object SoraExtractor : SoraStream() { it.first.contains("/im.php") && !isAnime -> { invokeSmashyIm(it.second, it.first, subtitleCallback, callback) } + it.first.contains("/rw.php") && !isAnime -> { + invokeSmashyRw(it.second, it.first, subtitleCallback, callback) + } else -> return@apmap } } @@ -3225,3 +3265,18 @@ object SoraExtractor : SoraStream() { } +class Animefever : Filesim() { + override val name = "Animefever" + override var mainUrl = "https://animefever.fun" +} + +class Multimovies : Filesim() { + override val name = "Multimovies" + override var mainUrl = "https://multimovies.cloud" +} + +class MultimoviesSB : StreamSB() { + override var name = "Multimovies" + override var mainUrl = "https://multimovies.website" +} + diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 16d00b6b..090117d8 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -50,6 +50,7 @@ import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeFourCartoon +import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokePobmovies import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies @@ -98,7 +99,6 @@ open class SoraStream : TmdbProvider() { const val uniqueStreamAPI = "https://uniquestream.net" const val filmxyAPI = "https://www.filmxy.vip" const val kimcartoonAPI = "https://kimcartoon.li" - const val xMovieAPI = "https://xemovies.to" const val aniwatchAPI = "https://aniwatch.to" const val crunchyrollAPI = "https://beta-api.crunchyroll.com" const val kissKhAPI = "https://kisskh.co" @@ -114,7 +114,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 animeKaizokuAPI = "https://animekaizoku.com" const val movie123NetAPI = "https://ww8.0123movie.net" const val smashyStreamAPI = "https://embed.smashystream.com" const val watchSomuchAPI = "https://watchsomuch.tv" // sub only @@ -132,6 +131,7 @@ open class SoraStream : TmdbProvider() { const val emoviesAPI = "https://emovies.si" const val pobmoviesAPI = "https://pobmovies.cam" const val fourCartoonAPI = "https://4cartoon.net" + const val multimoviesAPI = "https://multimovies.xyz" // INDEX SITE const val blackMoviesAPI = "https://dl.blacklistedbois.workers.dev/0:" @@ -157,6 +157,8 @@ 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 { return when (t) { @@ -815,6 +817,9 @@ open class SoraStream : TmdbProvider() { }, { if(!res.isAnime) invokeFourCartoon(res.title, res.year, res.season, res.episode, callback) + }, + { + invokeMultimovies(res.title,res.season,res.episode,subtitleCallback,callback) } ) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index dec99931..285f002e 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -29,6 +29,7 @@ import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeFourCartoon +import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeWatchOnline import com.hexated.SoraExtractor.invokeWatchsomuch @@ -308,6 +309,9 @@ class SoraStreamLite : SoraStream() { res.episode, callback ) + }, + { + invokeMultimovies(res.title,res.season,res.episode,subtitleCallback,callback) } ) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt index 27f4b152..69a6aec1 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt @@ -11,5 +11,8 @@ class SoraStreamPlugin: Plugin() { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(SoraStream()) registerMainAPI(SoraStreamLite()) + registerExtractorAPI(Animefever()) + registerExtractorAPI(Multimovies()) + registerExtractorAPI(MultimoviesSB()) } } \ No newline at end of file diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 5f2ae0fd..a92603b6 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -597,6 +597,32 @@ suspend fun invokeSmashyIm( } +suspend fun invokeSmashyRw( + name: String, + url: String, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, +) { + val res = app.get(url).document + val video = res.selectFirst("media-player")?.attr("src") + + M3u8Helper.generateM3u8( + "Smashy [$name]", + video ?: return, + "" + ).forEach(callback) + + res.select("track").map { track -> + subtitleCallback.invoke( + SubtitleFile( + track.attr("label"), + track.attr("src"), + ) + ) + } + +} + suspend fun getDumpIdAndType(title: String?, year: Int?, season: Int?): Pair { val res = tryParseJson( queryApi( From eb1a1ff98e71ac32f6d3bba06b2f1a1bebd7793d Mon Sep 17 00:00:00 2001 From: sora Date: Wed, 26 Jul 2023 18:59:46 +0700 Subject: [PATCH 031/105] added Animasu --- Animasu/build.gradle.kts | 27 +++ Animasu/src/main/AndroidManifest.xml | 2 + .../src/main/kotlin/com/hexated/Animasu.kt | 167 ++++++++++++++++++ .../main/kotlin/com/hexated/AnimasuPlugin.kt | 14 ++ 4 files changed, 210 insertions(+) create mode 100644 Animasu/build.gradle.kts create mode 100644 Animasu/src/main/AndroidManifest.xml create mode 100644 Animasu/src/main/kotlin/com/hexated/Animasu.kt create mode 100644 Animasu/src/main/kotlin/com/hexated/AnimasuPlugin.kt diff --git a/Animasu/build.gradle.kts b/Animasu/build.gradle.kts new file mode 100644 index 00000000..4b81579b --- /dev/null +++ b/Animasu/build.gradle.kts @@ -0,0 +1,27 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + language = "id" + // All of these properties are optional, you can safely remove them + + // description = "Lorem Ipsum" + authors = listOf("Hexated") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "AnimeMovie", + "OVA", + "Anime", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=animasu.cc&sz=%size%" +} \ No newline at end of file diff --git a/Animasu/src/main/AndroidManifest.xml b/Animasu/src/main/AndroidManifest.xml new file mode 100644 index 00000000..874740e3 --- /dev/null +++ b/Animasu/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Animasu/src/main/kotlin/com/hexated/Animasu.kt b/Animasu/src/main/kotlin/com/hexated/Animasu.kt new file mode 100644 index 00000000..e693a672 --- /dev/null +++ b/Animasu/src/main/kotlin/com/hexated/Animasu.kt @@ -0,0 +1,167 @@ +package com.hexated + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.utils.* +import org.jsoup.Jsoup +import org.jsoup.nodes.Element + +class Animasu : MainAPI() { + override var mainUrl = "https://animasu.cc" + override var name = "Animasu" + override val hasMainPage = true + override var lang = "id" + override val hasDownloadSupport = true + + override val supportedTypes = setOf( + TvType.Anime, + TvType.AnimeMovie, + TvType.OVA + ) + + companion object { + fun getType(t: String?): TvType { + if(t == null) return TvType.Anime + return when { + t.contains("Tv", true) -> TvType.Anime + t.contains("Movie", true) -> TvType.AnimeMovie + t.contains("OVA", true) || t.contains("Special", true) -> TvType.OVA + else -> TvType.Anime + } + } + + fun getStatus(t: String?): ShowStatus { + if(t == null) return ShowStatus.Completed + return when { + t.contains("Sedang Tayang", true) -> ShowStatus.Ongoing + else -> ShowStatus.Completed + } + } + } + + override val mainPage = mainPageOf( + "urutan=update" to "Baru diupdate", + "status=&tipe=&urutan=publikasi" to "Baru ditambahkan", + "status=&tipe=&urutan=populer" to "Terpopuler", + "status=&tipe=&urutan=rating" to "Rating Tertinggi", + "status=&tipe=Movie&urutan=update" to "Movie Terbaru", + "status=&tipe=Movie&urutan=populer" to "Movie Terpopuler", + ) + + override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { + val document = app.get("$mainUrl/pencarian/?${request.data}&halaman=$page").document + val home = document.select("div.listupd div.bs").map { + it.toSearchResult() + } + return newHomePageResponse(request.name, home) + } + + private fun getProperAnimeLink(uri: String): String { + return if (uri.contains("/anime/")) { + uri + } else { + var title = uri.substringAfter("$mainUrl/") + title = when { + (title.contains("-episode")) && !(title.contains("-movie")) -> title.substringBefore( + "-episode" + ) + + (title.contains("-movie")) -> title.substringBefore("-movie") + else -> title + } + + "$mainUrl/anime/$title" + } + } + + private fun Element.toSearchResult(): AnimeSearchResponse { + val href = getProperAnimeLink(fixUrlNull(this.selectFirst("a")?.attr("href")).toString()) + val title = this.select("div.tt").text().trim() + val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) + val epNum = this.selectFirst("span.epx")?.text()?.filter { it.isDigit() }?.toIntOrNull() + return newAnimeSearchResponse(title, href, TvType.Anime) { + this.posterUrl = posterUrl + addSub(epNum) + } + + } + + override suspend fun search(query: String): List { + return app.get("$mainUrl/?s=$query").document.select("div.listupd div.bs").map { + it.toSearchResult() + } + } + + override suspend fun load(url: String): LoadResponse { + val document = app.get(url).document + + val title = document.selectFirst("div.infox h1")?.text().toString().replace("Sub Indo", "").trim() + val poster = document.selectFirst("div.bigcontent img")?.attr("src")?.replace("\n", "") + + val table = document.selectFirst("div.infox div.spe") + val type = table?.selectFirst("span:contains(Jenis:)")?.ownText() + val year = table?.selectFirst("span:contains(Rilis:)")?.ownText()?.substringAfterLast(",")?.trim()?.toIntOrNull() + val status = table?.selectFirst("span:contains(Status:) font")?.text() + val trailer = document.selectFirst("div.trailer iframe")?.attr("src") + val episodes = document.select("ul#daftarepisode > li").map { + val link = fixUrl(it.selectFirst("a")!!.attr("href")) + val name = it.selectFirst("a")?.text() ?: "" + val episode = Regex("Episode\\s?(\\d+)").find(name)?.groupValues?.getOrNull(0)?.toIntOrNull() + Episode(link, name, episode = episode) + }.reversed() + + return newAnimeLoadResponse(title, url, getType(type)) { + posterUrl = poster + this.year = year + addEpisodes(DubStatus.Subbed, episodes) + showStatus = getStatus(status) + plot = document.select("div.sinopsis p").text() + this.tags = table?.select("span:contains(Genre:) a")?.map { it.text() } + addTrailer(trailer) + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val document = app.get(data).document + document.select(".mobius > .mirror > option").mapNotNull { + fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("src")) to it.text() + }.apmap { (iframe, quality) -> + loadFixedExtractor(iframe, quality, "$mainUrl/", subtitleCallback, callback) + } + return true + } + + private suspend fun loadFixedExtractor( + url: String, + quality: String?, + referer: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + loadExtractor(url, referer, subtitleCallback) { link -> + callback.invoke( + ExtractorLink( + link.name, + link.name, + link.url, + link.referer, + if(!link.isM3u8) getIndexQuality(quality) else link.quality, + link.isM3u8, + link.headers, + link.extractorData + ) + ) + } + } + + private fun getIndexQuality(str: String?): Int { + return Regex("(\\d{3,4})[pP]").find(str ?: "")?.groupValues?.getOrNull(1)?.toIntOrNull() + ?: Qualities.Unknown.value + } + +} \ No newline at end of file diff --git a/Animasu/src/main/kotlin/com/hexated/AnimasuPlugin.kt b/Animasu/src/main/kotlin/com/hexated/AnimasuPlugin.kt new file mode 100644 index 00000000..845ac534 --- /dev/null +++ b/Animasu/src/main/kotlin/com/hexated/AnimasuPlugin.kt @@ -0,0 +1,14 @@ + +package com.hexated + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class AnimasuPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(Animasu()) + } +} \ No newline at end of file From 4f4d9f63de4ca96e8ef11ec871398a615e342b00 Mon Sep 17 00:00:00 2001 From: sora Date: Wed, 26 Jul 2023 21:16:46 +0700 Subject: [PATCH 032/105] Nodrakorid: fix missing episode --- Gomov/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Nodrakorid.kt | 122 +++++++++++++++++- 2 files changed, 122 insertions(+), 2 deletions(-) diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index 326a8138..a14f2a82 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt index 1e383927..c6c119d1 100644 --- a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt +++ b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt @@ -1,6 +1,12 @@ package com.hexated -import com.lagradost.cloudstream3.mainPageOf +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.AppUtils.toJson +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import org.jsoup.nodes.Element +import java.net.URI class Nodrakorid : DutaMovie() { override var mainUrl = "https://no-drak-or.xyz" @@ -13,4 +19,118 @@ class Nodrakorid : DutaMovie() { "genre/c-drama/c-drama-c-drama/page/%d/" to "Drama China", "genre/thai-drama/page/%d/" to "Drama Thailand", ) + + override suspend fun load(url: String): LoadResponse { + return super.load(url).apply { + when (this) { + is TvSeriesLoadResponse -> { + val doc = app.get(url).document + this.comingSoon = false + this.episodes = doc.select("div.entry-content p:contains(Episode)").distinctBy { + it.text() + }.map { eps -> + val num = eps.text() + val endSibling = eps.nextElementSiblings().select("p:contains(Episode)").firstOrNull() ?: eps.nextElementSiblings().select("div.content-moviedata").firstOrNull() + val siblings = eps.nextElementSiblingsUntil(endSibling).map { ele -> + ele.ownText().filter { it.isDigit() }.toIntOrNull() to ele.select("a") + .map { it.attr("href") to it.text() } + }.filter { it.first != null } + Episode(siblings.toJson(), episode = num.filter { it.isDigit() }.toIntOrNull()) + } + } + } + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + return if (data.startsWith("[")) { + tryParseJson>(data)?.filter { it.first != 360 }?.map { + it.second.apmap { link -> + loadFixedExtractor( + fixEmbed(link.first, link.second), + it.first, + "$mainUrl/", + subtitleCallback, + callback + ) + } + } + true + } else { + super.loadLinks(data, isCasting, subtitleCallback, callback) + } + } + + private fun fixEmbed(url: String, server: String): String { + return when { + server.contains("streamsb", true) -> { + val host = getBaseUrl(url) + url.replace("$host/", "$host/e/") + } + + server.contains("hxfile", true) -> { + val host = getBaseUrl(url) + val id = url.substringAfterLast("/") + "$host/embed-$id.html" + } + + else -> url + } + } + + private fun getBaseUrl(url: String): String { + return URI(url).let { + "${it.scheme}://${it.host}" + } + } + + private suspend fun loadFixedExtractor( + url: String, + quality: Int?, + referer: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + loadExtractor(url, referer, subtitleCallback) { link -> + callback.invoke( + ExtractorLink( + link.name, + link.name, + link.url, + link.referer, + if(link.isM3u8) link.quality else quality ?: Qualities.Unknown.value, + link.isM3u8, + link.headers, + link.extractorData + ) + ) + } + } + + private fun Element.nextElementSiblingsUntil(untilElement: Element?): List { + val siblings = mutableListOf() + var currentElement = this.nextElementSibling() + + while (currentElement != null && currentElement != untilElement) { + siblings.add(currentElement) + currentElement = currentElement.nextElementSibling() + } + + return siblings + } + + data class LinkData( + @JsonProperty("first") var first: Int? = null, + @JsonProperty("second") var second: ArrayList = arrayListOf() + ) + + data class Second( + @JsonProperty("first") var first: String, + @JsonProperty("second") var second: String + ) } \ No newline at end of file From a282acbb3654ee37c6f2a16fa9ff343e764f604a Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Wed, 26 Jul 2023 22:13:31 +0700 Subject: [PATCH 033/105] Update Gomov.kt --- Gomov/src/main/kotlin/com/hexated/Gomov.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gomov/src/main/kotlin/com/hexated/Gomov.kt b/Gomov/src/main/kotlin/com/hexated/Gomov.kt index 36128fb2..6282b98f 100644 --- a/Gomov/src/main/kotlin/com/hexated/Gomov.kt +++ b/Gomov/src/main/kotlin/com/hexated/Gomov.kt @@ -79,7 +79,7 @@ open class Gomov : MainAPI() { val document = app.get(url).document val title = - document.selectFirst("h1.entry-title")?.text()?.substringBefore("Season")?.trim() + document.selectFirst("h1.entry-title")?.text()?.substringBefore("Season")?.substringBefore("Episode")?.trim() .toString() val poster = fixUrlNull(document.selectFirst("figure.pull-left > img")?.attr("src"))?.fixImageQuality() From 332ccf5c6f208a37ed0b3a0b4d7645e38f2caea1 Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 27 Jul 2023 21:38:45 +0700 Subject: [PATCH 034/105] sora: added Netmovies --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 63 ++++++++-------- .../src/main/kotlin/com/hexated/SoraStream.kt | 73 ++++++++++++++++--- .../main/kotlin/com/hexated/SoraStreamLite.kt | 43 +++++++++-- 4 files changed, 136 insertions(+), 45 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 5dddfb7e..5420e8eb 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 = 148 +version = 149 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 829ca294..969ddf78 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -416,27 +416,7 @@ object SoraExtractor : SoraStream() { } else { "$idlixAPI/episode/$fixTitle-season-$season-episode-$episode" } - - val res = app.get(url) - if (!res.isSuccessful) return - val referer = getBaseUrl(res.url) - val document = res.document - val id = document.select("meta#dooplay-ajax-counter").attr("data-postid") - val type = if (url.contains("/movie/")) "movie" else "tv" - - document.select("ul#playeroptionsul > li").map { - it.attr("data-nume") - }.apmap { nume -> - val source = app.post( - url = "$referer/wp-admin/admin-ajax.php", data = mapOf( - "action" to "doo_player_ajax", "post" to id, "nume" to nume, "type" to type - ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = url - ).parsed().embed_url - - if (!source.contains("youtube")) { - loadExtractor(source, "$referer/", subtitleCallback, callback) - } - } + invokeWpmovies(url,subtitleCallback, callback) } suspend fun invokeMultimovies( @@ -452,22 +432,47 @@ object SoraExtractor : SoraStream() { } else { "$multimoviesAPI/episodes/$fixTitle-${season}x${episode}" } + invokeWpmovies(url,subtitleCallback, callback,true) + } - val res = app.get(url) + suspend fun invokeNetmovies( + 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) { + "$netmoviesAPI/movies/$fixTitle-$year" + } else { + "$netmoviesAPI/episodes/$fixTitle-${season}x${episode}" + } + invokeWpmovies(url,subtitleCallback, callback) + } + + private suspend fun invokeWpmovies( + url: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, + fixIframe: Boolean = false, + ) { + val res = app.get(url ?: return) val referer = getBaseUrl(res.url) val document = res.document - val id = document.select("meta#dooplay-ajax-counter").attr("data-postid") - val type = if (url.contains("/movies/")) "movie" else "tv" - document.select("ul#playeroptionsul > li").map { - it.attr("data-nume") - }.apmap { nume -> + Triple( + it.attr("data-post"), + it.attr("data-nume"), + it.attr("data-type") + ) + }.apmap { (id, nume, type) -> val source = app.post( url = "$referer/wp-admin/admin-ajax.php", data = mapOf( "action" to "doo_player_ajax", "post" to id, "nume" to nume, "type" to type ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = url - ).parsed().embed_url.let { Jsoup.parse(it).select("IFRAME").attr("SRC") } - + ).parsed().embed_url.let { if(fixIframe) Jsoup.parse(it).select("IFRAME").attr("SRC") else it } if (!source.contains("youtube")) { loadExtractor(source, "$referer/", subtitleCallback, callback) } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 090117d8..a9107b84 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -51,6 +51,7 @@ import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeFourCartoon import com.hexated.SoraExtractor.invokeMultimovies +import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokePobmovies import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies @@ -117,7 +118,8 @@ open class SoraStream : TmdbProvider() { const val movie123NetAPI = "https://ww8.0123movie.net" const val smashyStreamAPI = "https://embed.smashystream.com" const val watchSomuchAPI = "https://watchsomuch.tv" // sub only - val gomoviesAPI = base64DecodeAPI("bQ==Y28=ZS4=aW4=bmw=LW8=ZXM=dmk=bW8=Z28=Ly8=czo=dHA=aHQ=") + val gomoviesAPI = + base64DecodeAPI("bQ==Y28=ZS4=aW4=bmw=LW8=ZXM=dmk=bW8=Z28=Ly8=czo=dHA=aHQ=") const val ask4MoviesAPI = "https://ask4movie.nl" const val biliBiliAPI = "https://api-vn.otakuz.live/server" const val watchOnlineAPI = "https://watchonline.ag" @@ -132,6 +134,7 @@ open class SoraStream : TmdbProvider() { const val pobmoviesAPI = "https://pobmovies.cam" const val fourCartoonAPI = "https://4cartoon.net" const val multimoviesAPI = "https://multimovies.xyz" + const val netmoviesAPI = "https://netmovies.to" // INDEX SITE const val blackMoviesAPI = "https://dl.blacklistedbois.workers.dev/0:" @@ -268,7 +271,8 @@ open class SoraStream : TmdbProvider() { val year = releaseDate?.split("-")?.first()?.toIntOrNull() val rating = res.vote_average.toString().toRatingInt() val genres = res.genres?.mapNotNull { it.name } - val isAnime = genres?.contains("Animation") == true && (res.original_language == "zh" || res.original_language == "ja") + val isAnime = + genres?.contains("Animation") == true && (res.original_language == "zh" || res.original_language == "ja") val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty() .ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } } @@ -310,7 +314,7 @@ open class SoraStream : TmdbProvider() { date = season.airDate, airedDate = res.releaseDate ?: res.firstAirDate, ).toJson(), - name = eps.name + if(isUpcoming(eps.airDate)) " - [UPCOMING]" else "", + name = eps.name + if (isUpcoming(eps.airDate)) " - [UPCOMING]" else "", season = eps.seasonNumber, episode = eps.episodeNumber, posterUrl = getImageUrl(eps.stillPath), @@ -396,7 +400,15 @@ open class SoraStream : TmdbProvider() { ) }, { - invokeGoku(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) + invokeGoku( + res.title, + res.year, + res.season, + res.lastSeason, + res.episode, + subtitleCallback, + callback + ) }, { invokeVidSrc(res.id, res.season, res.episode, subtitleCallback, callback) @@ -499,7 +511,13 @@ open class SoraStream : TmdbProvider() { ) }, { - if(!res.isAnime) invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback) + if (!res.isAnime) invokeKimcartoon( + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) }, // { // invokeXmovies( @@ -522,7 +540,15 @@ open class SoraStream : TmdbProvider() { ) }, { - invokeKisskh(res.title, res.season, res.episode, res.isAnime, res.lastSeason, subtitleCallback, callback) + invokeKisskh( + res.title, + res.season, + res.episode, + res.isAnime, + res.lastSeason, + subtitleCallback, + callback + ) }, { invokeLing( @@ -810,16 +836,43 @@ open class SoraStream : TmdbProvider() { invokeNavy(res.imdbId, res.season, res.episode, callback) }, { - if (!res.isAnime) invokeEmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + if (!res.isAnime) invokeEmovies( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) }, { - if(!res.isAnime && res.season == null) invokePobmovies(res.title, res.year, callback) + if (!res.isAnime && res.season == null) invokePobmovies( + res.title, + res.year, + callback + ) }, { - if(!res.isAnime) invokeFourCartoon(res.title, res.year, res.season, res.episode, callback) + if (!res.isAnime) invokeFourCartoon( + res.title, + res.year, + res.season, + res.episode, + callback + ) }, { - invokeMultimovies(res.title,res.season,res.episode,subtitleCallback,callback) + invokeMultimovies(res.title, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeNetmovies( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) } ) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 285f002e..d40c12d5 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -30,6 +30,7 @@ import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeFourCartoon import com.hexated.SoraExtractor.invokeMultimovies +import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeWatchOnline import com.hexated.SoraExtractor.invokeWatchsomuch @@ -89,7 +90,15 @@ class SoraStreamLite : SoraStream() { ) }, { - invokeGoku(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) + invokeGoku( + res.title, + res.year, + res.season, + res.lastSeason, + res.episode, + subtitleCallback, + callback + ) }, { invokeVidSrc(res.id, res.season, res.episode, subtitleCallback, callback) @@ -189,7 +198,13 @@ class SoraStreamLite : SoraStream() { ) }, { - if(!res.isAnime) invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback) + if (!res.isAnime) invokeKimcartoon( + res.title, + res.season, + res.episode, + subtitleCallback, + callback + ) }, { invokeSmashyStream( @@ -222,7 +237,15 @@ class SoraStreamLite : SoraStream() { ) }, { - invokeKisskh(res.title, res.season, res.episode, res.isAnime, res.lastSeason, subtitleCallback, callback) + invokeKisskh( + res.title, + res.season, + res.episode, + res.isAnime, + res.lastSeason, + subtitleCallback, + callback + ) }, { invokeLing( @@ -302,7 +325,7 @@ class SoraStreamLite : SoraStream() { ) }, { - if(!res.isAnime) invokeFourCartoon( + if (!res.isAnime) invokeFourCartoon( res.title, res.year, res.season, @@ -311,7 +334,17 @@ class SoraStreamLite : SoraStream() { ) }, { - invokeMultimovies(res.title,res.season,res.episode,subtitleCallback,callback) + invokeMultimovies(res.title, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeNetmovies( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) } ) From ef851fea19fb383bf986f791a64bfbfbc13fb090 Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 27 Jul 2023 23:09:25 +0700 Subject: [PATCH 035/105] added Hdmovie2 --- Aniworld/build.gradle.kts | 2 +- DramaidProvider/build.gradle.kts | 2 +- Gomov/build.gradle.kts | 2 +- Movierulzhd/build.gradle.kts | 4 +- .../src/main/kotlin/com/hexated/Extractors.kt | 28 ++++++ .../src/main/kotlin/com/hexated/Hdmovie2.kt | 88 +++++++++++++++++ .../main/kotlin/com/hexated/Movierulzhd.kt | 98 ++++++++++--------- .../kotlin/com/hexated/MovierulzhdPlugin.kt | 2 + RebahinProvider/build.gradle.kts | 2 +- Xcineio/build.gradle.kts | 2 +- YomoviesProvider/build.gradle.kts | 2 +- 11 files changed, 179 insertions(+), 53 deletions(-) create mode 100644 Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt diff --git a/Aniworld/build.gradle.kts b/Aniworld/build.gradle.kts index d303a028..36d39d31 100644 --- a/Aniworld/build.gradle.kts +++ b/Aniworld/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "de" // All of these properties are optional, you can safely remove them - description = "Include: Serienstream" + description = "Included: Serienstream" authors = listOf("Hexated") /** diff --git a/DramaidProvider/build.gradle.kts b/DramaidProvider/build.gradle.kts index a1beeb4d..02f0a559 100644 --- a/DramaidProvider/build.gradle.kts +++ b/DramaidProvider/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Include: Oppadrama" + description = "Included: Oppadrama" authors = listOf("Hexated") /** diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index a14f2a82..65c73ec0 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Include: DutaMovie, Ngefilm, Nodrakorid" + description = "Included: DutaMovie, Ngefilm, Nodrakorid" authors = listOf("Hexated") /** diff --git a/Movierulzhd/build.gradle.kts b/Movierulzhd/build.gradle.kts index 1d596ef2..1da0d4c3 100644 --- a/Movierulzhd/build.gradle.kts +++ b/Movierulzhd/build.gradle.kts @@ -1,12 +1,12 @@ // use an integer for version numbers -version = 37 +version = 38 cloudstream { language = "hi" // All of these properties are optional, you can safely remove them -// description = "Movierulzhd recently have prank feature that the enable and disable cloudflare a " + description = "Included: Hdmovie2" authors = listOf("Hexated") /** diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Extractors.kt b/Movierulzhd/src/main/kotlin/com/hexated/Extractors.kt index 87ae7b6d..a96e9c7b 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Extractors.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Extractors.kt @@ -112,6 +112,34 @@ open class Sbflix : ExtractorApi() { } +open class Akamaicdn : ExtractorApi() { + override val name = "Akamaicdn" + override val mainUrl = "https://akamaicdn.life" + override val requiresReferer = true + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val res = app.get(url, referer = referer).document + val mapper = res.select("script:containsData(sniff)").last()?.data()?.substringAfter("sniff(") + ?.substringBefore(");")?.split(",")?.map { it.replace("\"", "").trim() } ?: return + callback.invoke( + ExtractorLink( + this.name, + this.name, + "$mainUrl/m3u8/${mapper[1]}/${mapper[2]}/master.txt?s=1&cache=1", + url, + Qualities.Unknown.value, + isM3u8 = true, + ) + ) + } + +} + suspend fun invokeTwoEmbed( url: String? = null, subtitleCallback: (SubtitleFile) -> Unit, diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt b/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt new file mode 100644 index 00000000..5fde2e77 --- /dev/null +++ b/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt @@ -0,0 +1,88 @@ +package com.hexated + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.mainPageOf +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor +import org.jsoup.Jsoup + +class Hdmovie2 : Movierulzhd() { + override var mainUrl = "https://hdmovie2.bar" + override var name = "Hdmovie2" + + override val mainPage = mainPageOf( + "trending" to "Trending", + "movies" to "Movies", + "genre/tv-series" to "TV-Series", + "genre/netflix" to "Netflix", + "genre/zee5-tv-series" to "Zee5 TV Series", + ) + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + if (data.startsWith("{")) { + val loadData = tryParseJson(data) + val source = app.get( + url = "$directUrl/wp-json/dooplayer/v2/${loadData?.post}/${loadData?.type}/${loadData?.nume}", + referer = data, + headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ).parsed().embed_url.getIframe() + 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") + }.apmap { nume -> + val source = app.get( + url = "$directUrl/wp-json/dooplayer/v2/${id}/${type}/${nume}", + referer = data, + headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ).parsed().embed_url.getIframe() + when { + !source.contains("youtube") -> loadExtractor( + source, + "$directUrl/", + subtitleCallback, + callback + ) + else -> return@apmap + } + } + } + return true + } + + private fun String.getIframe(): String { + return Jsoup.parse(this).select("iframe").attr("src") + } + + data class LinkData( + val type: String? = null, + val post: String? = null, + val nume: String? = null, + ) + + data class ResponseHash( + @JsonProperty("embed_url") val embed_url: String, + @JsonProperty("type") val type: String?, + ) +} \ No newline at end of file diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt index 263375b7..ba4452d9 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt @@ -4,16 +4,15 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer -import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.toJson import org.jsoup.nodes.Element import java.net.URI -class Movierulzhd : MainAPI() { - override var mainUrl = "https://movierulzhd.help" - private var directUrl = mainUrl +open class Movierulzhd : MainAPI() { + override var mainUrl = "https://movierulzhd.gold" + var directUrl = "" override var name = "Movierulzhd" override val hasMainPage = true override var lang = "hi" @@ -24,24 +23,24 @@ class Movierulzhd : MainAPI() { ) override val mainPage = mainPageOf( - "$mainUrl/trending/page/" to "Trending", - "$mainUrl/movies/page/" to "Movies", - "$mainUrl/tvshows/page/" to "TV Shows", - "$mainUrl/genre/netflix/page/" to "Netflix", - "$mainUrl/genre/amazon-prime/page/" to "Amazon Prime", - "$mainUrl/genre/Zee5/page/" to "Zee5", - "$mainUrl/seasons/page/" to "Season", - "$mainUrl/episodes/page/" to "Episode", + "trending" to "Trending", + "movies" to "Movies", + "tvshows" to "TV Shows", + "genre/netflix" to "Netflix", + "genre/amazon-prime" to "Amazon Prime", + "genre/Zee5" to "Zee5", + "seasons" to "Season", + "episodes" to "Episode", ) - private val interceptor = CloudflareKiller() + val interceptor = CloudflareKiller() override suspend fun getMainPage( page: Int, request: MainPageRequest ): HomePageResponse { - var document = app.get(request.data + page).document - if(document.select("title").text() == "Just a moment...") { + var document = app.get("$mainUrl/${request.data}/page/$page").document + if (document.select("title").text() == "Just a moment...") { document = app.get(request.data + page, interceptor = interceptor).document } val home = @@ -58,11 +57,13 @@ class Movierulzhd : MainAPI() { title = Regex("(.+?)-season").find(title)?.groupValues?.get(1).toString() "$mainUrl/tvshows/$title" } + uri.contains("/seasons/") -> { var title = uri.substringAfter("$mainUrl/seasons/") title = Regex("(.+?)-season").find(title)?.groupValues?.get(1).toString() "$mainUrl/tvshows/$title" } + else -> { uri } @@ -72,7 +73,7 @@ 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").attr("src")) + val posterUrl = fixUrlNull(this.select("div.poster img").last()?.attr("src")) val quality = getQualityFromString(this.select("span.quality").text()) return newMovieSearchResponse(title, href, TvType.Movie) { this.posterUrl = posterUrl @@ -85,7 +86,7 @@ class Movierulzhd : MainAPI() { override suspend fun search(query: String): List { val link = "$mainUrl/search/$query" var document = app.get(link).document - if(document.select("title").text() == "Just a moment...") { + if (document.select("title").text() == "Just a moment...") { document = app.get(link, interceptor = interceptor).document } @@ -104,13 +105,13 @@ class Movierulzhd : MainAPI() { override suspend fun load(url: String): LoadResponse { val request = app.get(url) var document = request.document - if(document.select("title").text() == "Just a moment...") { + if (document.select("title").text() == "Just a moment...") { document = app.get(url, interceptor = interceptor).document } directUrl = getBaseUrl(request.url) val title = document.selectFirst("div.data > h1")?.text()?.trim().toString() - val poster = document.select("div.poster > img").attr("src").toString() + val poster = fixUrlNull(document.select("div.poster img:last-child").attr("src")) val tags = document.select("div.sgeneros > a").map { it.text() } val year = Regex(",\\s?(\\d+)").find( @@ -119,7 +120,7 @@ class Movierulzhd : MainAPI() { val tvType = if (document.select("ul#section > li:nth-child(1)").text() .contains("Episodes") || document.selectFirst("ul#playeroptionsul li span.title") ?.text()?.contains( - Regex("Episode\\s\\d+") + Regex("Episode\\s+\\d+|EP\\d+|PE\\d+") ) == true ) TvType.TvSeries else TvType.Movie val description = document.select("div.wp-content > p").text().trim() @@ -127,7 +128,10 @@ class Movierulzhd : MainAPI() { val rating = document.selectFirst("span.dt_rating_vgs")?.text()?.toRatingInt() val actors = document.select("div.persons > div[itemprop=actor]").map { - Actor(it.select("meta[itemprop=name]").attr("content"), it.select("img").attr("src")) + Actor( + it.select("meta[itemprop=name]").attr("content"), + it.select("img:last-child").attr("src") + ) } val recommendations = document.select("div.owl-item").map { @@ -142,15 +146,17 @@ class Movierulzhd : MainAPI() { } return if (tvType == TvType.TvSeries) { - val episodes = if(document.select("ul.episodios > li").isNotEmpty()) { + val episodes = if (document.select("ul.episodios > li").isNotEmpty()) { 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 episode = it.select("div.numerando").text().replace(" ", "").split("-").last() - .toIntOrNull() - val season = it.select("div.numerando").text().replace(" ", "").split("-").first() - .toIntOrNull() + val episode = + it.select("div.numerando").text().replace(" ", "").split("-").last() + .toIntOrNull() + val season = + it.select("div.numerando").text().replace(" ", "").split("-").first() + .toIntOrNull() Episode( href, name, @@ -210,7 +216,7 @@ class Movierulzhd : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { - if(data.startsWith("{")) { + if (data.startsWith("{")) { val loadData = AppUtils.tryParseJson(data) val source = app.post( url = "$directUrl/wp-admin/admin-ajax.php", @@ -223,7 +229,7 @@ class Movierulzhd : MainAPI() { referer = data, headers = mapOf("X-Requested-With" to "XMLHttpRequest") ).parsed().embed_url - if(!source.contains("youtube")) loadExtractor(source, data, subtitleCallback, callback) + if (!source.contains("youtube")) loadExtractor(source, data, subtitleCallback, callback) } else { var document = app.get(data).document if (document.select("title").text() == "Just a moment...") { @@ -235,24 +241,26 @@ class Movierulzhd : MainAPI() { document.select("ul#playeroptionsul > li").map { it.attr("data-nume") }.apmap { nume -> - safeApiCall { - val source = app.post( - url = "$directUrl/wp-admin/admin-ajax.php", - data = mapOf( - "action" to "doo_player_ajax", - "post" to id, - "nume" to nume, - "type" to type - ), - referer = data, - headers = mapOf("X-Requested-With" to "XMLHttpRequest") - ).parsed().embed_url + val source = app.post( + url = "$directUrl/wp-admin/admin-ajax.php", + data = mapOf( + "action" to "doo_player_ajax", + "post" to id, + "nume" to nume, + "type" to type + ), + referer = data, + headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ).parsed().embed_url - when { - source.contains("2embed") -> invokeTwoEmbed(source,subtitleCallback, callback) - !source.contains("youtube") -> loadExtractor(source, data, subtitleCallback, callback) - else -> return@safeApiCall - } + when { + !source.contains("youtube") -> loadExtractor( + source, + data, + subtitleCallback, + callback + ) + else -> return@apmap } } } diff --git a/Movierulzhd/src/main/kotlin/com/hexated/MovierulzhdPlugin.kt b/Movierulzhd/src/main/kotlin/com/hexated/MovierulzhdPlugin.kt index 21710b9d..a97f4cc9 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/MovierulzhdPlugin.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/MovierulzhdPlugin.kt @@ -10,9 +10,11 @@ class MovierulzhdPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(Movierulzhd()) + registerMainAPI(Hdmovie2()) registerExtractorAPI(Sbflix()) registerExtractorAPI(Sbrulz()) registerExtractorAPI(Sbmiz()) registerExtractorAPI(Sbnmp()) + registerExtractorAPI(Akamaicdn()) } } \ No newline at end of file diff --git a/RebahinProvider/build.gradle.kts b/RebahinProvider/build.gradle.kts index 0c5b2fdf..b509bf93 100644 --- a/RebahinProvider/build.gradle.kts +++ b/RebahinProvider/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Include: Cgvindo, Kitanonton" + description = "Included: Cgvindo, Kitanonton" authors = listOf("Hexated") /** diff --git a/Xcineio/build.gradle.kts b/Xcineio/build.gradle.kts index 2434acfa..56bc2180 100644 --- a/Xcineio/build.gradle.kts +++ b/Xcineio/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "de" // All of these properties are optional, you can safely remove them - description = "Include: Movie4k" + description = "Included: Movie4k" authors = listOf("Hexated") /** diff --git a/YomoviesProvider/build.gradle.kts b/YomoviesProvider/build.gradle.kts index f5249c1c..ba22fc9a 100644 --- a/YomoviesProvider/build.gradle.kts +++ b/YomoviesProvider/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "hi" // All of these properties are optional, you can safely remove them - description = "Include: Watchomovies" + description = "Included: Watchomovies" authors = listOf("Hexated") /** From 22e734f17d006d8d36b78e3ee1a6f2aeaea06abd Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 27 Jul 2023 23:29:53 +0700 Subject: [PATCH 036/105] update desc --- Aniworld/build.gradle.kts | 2 +- DramaidProvider/build.gradle.kts | 2 +- Gomov/build.gradle.kts | 2 +- Movierulzhd/build.gradle.kts | 2 +- RebahinProvider/build.gradle.kts | 2 +- Xcineio/build.gradle.kts | 2 +- YomoviesProvider/build.gradle.kts | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Aniworld/build.gradle.kts b/Aniworld/build.gradle.kts index 36d39d31..d303a028 100644 --- a/Aniworld/build.gradle.kts +++ b/Aniworld/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "de" // All of these properties are optional, you can safely remove them - description = "Included: Serienstream" + description = "Include: Serienstream" authors = listOf("Hexated") /** diff --git a/DramaidProvider/build.gradle.kts b/DramaidProvider/build.gradle.kts index 02f0a559..a1beeb4d 100644 --- a/DramaidProvider/build.gradle.kts +++ b/DramaidProvider/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Included: Oppadrama" + description = "Include: Oppadrama" authors = listOf("Hexated") /** diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index 65c73ec0..a8b04bca 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Included: DutaMovie, Ngefilm, Nodrakorid" + description = "Includes: DutaMovie, Ngefilm, Nodrakorid" authors = listOf("Hexated") /** diff --git a/Movierulzhd/build.gradle.kts b/Movierulzhd/build.gradle.kts index 1da0d4c3..505d6303 100644 --- a/Movierulzhd/build.gradle.kts +++ b/Movierulzhd/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "hi" // All of these properties are optional, you can safely remove them - description = "Included: Hdmovie2" + description = "Include: Hdmovie2" authors = listOf("Hexated") /** diff --git a/RebahinProvider/build.gradle.kts b/RebahinProvider/build.gradle.kts index b509bf93..a1d65c12 100644 --- a/RebahinProvider/build.gradle.kts +++ b/RebahinProvider/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Included: Cgvindo, Kitanonton" + description = "Includes: Cgvindo, Kitanonton" authors = listOf("Hexated") /** diff --git a/Xcineio/build.gradle.kts b/Xcineio/build.gradle.kts index 56bc2180..2434acfa 100644 --- a/Xcineio/build.gradle.kts +++ b/Xcineio/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "de" // All of these properties are optional, you can safely remove them - description = "Included: Movie4k" + description = "Include: Movie4k" authors = listOf("Hexated") /** diff --git a/YomoviesProvider/build.gradle.kts b/YomoviesProvider/build.gradle.kts index ba22fc9a..f5249c1c 100644 --- a/YomoviesProvider/build.gradle.kts +++ b/YomoviesProvider/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "hi" // All of these properties are optional, you can safely remove them - description = "Included: Watchomovies" + description = "Include: Watchomovies" authors = listOf("Hexated") /** From 6fa564f9d3f3de72d3e6af742890b2812ce73497 Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 28 Jul 2023 19:36:39 +0700 Subject: [PATCH 037/105] sora: fix filmxy --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 23 +++++++------------ .../src/main/kotlin/com/hexated/SoraUtils.kt | 13 +++++------ 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 5420e8eb..1301ca94 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 = 149 +version = 150 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 969ddf78..2be73352 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -596,16 +596,16 @@ object SoraExtractor : SoraStream() { } else { "${filmxyAPI}/tv/$imdbId" } - val filmxyCookies = getFilmxyCookies(imdbId, season) + val filmxyCookies = getFilmxyCookies(imdbId, season) ?: return - val cookiesDoc = mapOf( + val cookies = mapOf( "G_ENABLED_IDPS" to "google", - "wordpress_logged_in_8bf9d5433ac88cc9a3a396d6b154cd01" to (filmxyCookies.wLog - ?: return), - "PHPSESSID" to (filmxyCookies.phpsessid ?: return) + "wp-secure-id" to "${filmxyCookies.wpSec}", + "wp-guest-token" to "${filmxyCookies.wpGuest}", + "PHPSESSID" to "${filmxyCookies.phpsessid}" ) - val doc = session.get(url, cookies = cookiesDoc).document + val doc = session.get(url, cookies = cookies).document val script = doc.selectFirst("script:containsData(var isSingle)")?.data() ?: return val sourcesData = @@ -644,16 +644,9 @@ object SoraExtractor : SoraStream() { "&linkIDs%5B%5D=$it" }?.replace("\"", "") - val body = "action=get_vid_links$linkIDs&user_id=$userId&nonce=$userNonce".toRequestBody() - val cookiesJson = mapOf( - "G_ENABLED_IDPS" to "google", - "PHPSESSID" to "${filmxyCookies.phpsessid}", - "wordpress_logged_in_8bf9d5433ac88cc9a3a396d6b154cd01" to "${filmxyCookies.wLog}", - "wordpress_sec_8bf9d5433ac88cc9a3a396d6b154cd01" to "${filmxyCookies.wSec}" - ) val json = app.post( "$filmxyAPI/wp-admin/admin-ajax.php", - requestBody = body, + requestBody = "action=get_vid_links$linkIDs&user_id=$userId&nonce=$userNonce".toRequestBody(), referer = url, headers = mapOf( "Accept" to "*/*", @@ -662,7 +655,7 @@ object SoraExtractor : SoraStream() { "Origin" to filmxyAPI, "X-Requested-With" to "XMLHttpRequest", ), - cookies = cookiesJson + cookies = cookies ).text.let { tryParseJson>(it) } sources?.map { source -> diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index a92603b6..20e9194c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -107,8 +107,8 @@ val mimeType = arrayOf( data class FilmxyCookies( val phpsessid: String? = null, - val wLog: String? = null, - val wSec: String? = null, + val wpSec: String? = null, + val wpGuest: String? = null, ) fun String.filterIframe( @@ -901,7 +901,7 @@ suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair Date: Sat, 29 Jul 2023 04:01:35 +0700 Subject: [PATCH 038/105] small fix --- SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 2be73352..e59030e8 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2064,7 +2064,7 @@ object SoraExtractor : SoraStream() { it.attr("data-id") to it.text() }.apmap { when { - it.first.contains("/fix.php") && !isAnime -> { + it.second.equals("Player F", true) || it.second.equals("Player N", true) && !isAnime -> { invokeSmashyFfix(it.second, it.first, url, callback) } it.first.contains("/gtop") -> { From b9bcf80c2af7faa77a67e1d3b93c53fc0045a012 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 29 Jul 2023 04:02:24 +0700 Subject: [PATCH 039/105] small fix --- SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index e59030e8..99143a88 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2064,7 +2064,7 @@ object SoraExtractor : SoraStream() { it.attr("data-id") to it.text() }.apmap { when { - it.second.equals("Player F", true) || it.second.equals("Player N", true) && !isAnime -> { + (it.second.equals("Player F", true) || it.second.equals("Player N", true)) && !isAnime -> { invokeSmashyFfix(it.second, it.first, url, callback) } it.first.contains("/gtop") -> { From 36c6022afae72ebbc218a838941f3197282536f1 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 29 Jul 2023 04:41:04 +0700 Subject: [PATCH 040/105] sora: added moment --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 49 ++++++++++++------- .../src/main/kotlin/com/hexated/SoraStream.kt | 5 ++ .../main/kotlin/com/hexated/SoraStreamLite.kt | 6 ++- .../src/main/kotlin/com/hexated/SoraUtils.kt | 19 ++----- 5 files changed, 46 insertions(+), 35 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 1301ca94..e39d81fb 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 = 150 +version = 151 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 99143a88..a419b1d1 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -596,16 +596,8 @@ object SoraExtractor : SoraStream() { } else { "${filmxyAPI}/tv/$imdbId" } - val filmxyCookies = getFilmxyCookies(imdbId, season) ?: return - - val cookies = mapOf( - "G_ENABLED_IDPS" to "google", - "wp-secure-id" to "${filmxyCookies.wpSec}", - "wp-guest-token" to "${filmxyCookies.wpGuest}", - "PHPSESSID" to "${filmxyCookies.phpsessid}" - ) - - val doc = session.get(url, cookies = cookies).document + val filmxyCookies = getFilmxyCookies(imdbId, season) + val doc = session.get(url, cookies = filmxyCookies).document val script = doc.selectFirst("script:containsData(var isSingle)")?.data() ?: return val sourcesData = @@ -655,7 +647,7 @@ object SoraExtractor : SoraStream() { "Origin" to filmxyAPI, "X-Requested-With" to "XMLHttpRequest", ), - cookies = cookies + cookies = filmxyCookies ).text.let { tryParseJson>(it) } sources?.map { source -> @@ -3109,18 +3101,39 @@ object SoraExtractor : SoraStream() { season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit, + ) { + invokeHindi(navyAPI, navyAPI, imdbId, season, episode, callback) + } + + suspend fun invokeMoment( + imdbId: String? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, + ) { + invokeHindi(momentAPI, "https://hdmovies4u.green", imdbId, season, episode, callback) + } + + private suspend fun invokeHindi( + host: String? = null, + referer: String? = null, + imdbId: String? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, ) { val res = app.get( - "$navyAPI/play/$imdbId", - referer = "$navyAPI/" + "$host/play/$imdbId", + referer = "$referer/" ).document.selectFirst("script:containsData(player =)")?.data()?.substringAfter("{") ?.substringBefore(";")?.substringBefore(")") val json = tryParseJson("{${res ?: return}") val headers = mapOf( "X-CSRF-TOKEN" to "${json?.key}" ) + val serverRes = app.get( - fixUrl(json?.file ?: return, navyAPI), headers = headers, referer = "$navyAPI/" + fixUrl(json?.file ?: return, navyAPI), headers = headers, referer = "$referer/" ).text.replace(Regex(""",\s*\[]"""), "") val server = tryParseJson>(serverRes).let { server -> if (season == null) { @@ -3135,15 +3148,15 @@ object SoraExtractor : SoraStream() { } val path = app.post( - "${navyAPI}/playlist/${server ?: return}.txt", + "${host}/playlist/${server ?: return}.txt", headers = headers, - referer = "$navyAPI/" + referer = "$referer/" ).text M3u8Helper.generateM3u8( - "Navy", + if(host == navyAPI) "Navy" else "Moment", path, - "${navyAPI}/" + "${referer}/" ).forEach(callback) } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index a9107b84..d54ef39a 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -50,6 +50,7 @@ import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeFourCartoon +import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokePobmovies @@ -135,6 +136,7 @@ open class SoraStream : TmdbProvider() { const val fourCartoonAPI = "https://4cartoon.net" const val multimoviesAPI = "https://multimovies.xyz" const val netmoviesAPI = "https://netmovies.to" + const val momentAPI = "https://moment-explanation-i-244.site" // INDEX SITE const val blackMoviesAPI = "https://dl.blacklistedbois.workers.dev/0:" @@ -835,6 +837,9 @@ open class SoraStream : TmdbProvider() { { invokeNavy(res.imdbId, res.season, res.episode, callback) }, + { + invokeMoment(res.imdbId, res.season, res.episode, callback) + }, { if (!res.isAnime) invokeEmovies( res.title, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index d40c12d5..e7771f1c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -29,6 +29,7 @@ import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeFourCartoon +import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokeVidSrc @@ -345,7 +346,10 @@ class SoraStreamLite : SoraStream() { subtitleCallback, callback ) - } + }, + { + invokeMoment(res.imdbId, res.season, res.episode, callback) + }, ) return true diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 20e9194c..2f912165 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -105,12 +105,6 @@ val mimeType = arrayOf( "video/x-msvideo" ) -data class FilmxyCookies( - val phpsessid: String? = null, - val wpSec: String? = null, - val wpGuest: String? = null, -) - fun String.filterIframe( seasonNum: Int? = null, lastSeason: Int? = null, @@ -901,7 +895,7 @@ suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair { val url = if (season == null) { "${filmxyAPI}/movie/$imdbId" @@ -917,7 +911,7 @@ suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): Filmx ), ) - if (!res.isSuccessful) return FilmxyCookies() + if (!res.isSuccessful) return emptyMap() val userNonce = res.document.select("script").find { it.data().contains("var userNonce") }?.data()?.let { @@ -938,13 +932,8 @@ suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): Filmx "X-Requested-With" to "XMLHttpRequest", ) ) - - val cookieJar = session.baseClient.cookieJar.loadForRequest(cookieUrl.toHttpUrl()) - phpsessid = cookieJar.first { it.name == "PHPSESSID" }.value - val wpSec = cookieJar.first { it.name == "wp-secure-id" }.value - val wpGuest = cookieJar.first { it.name == "wp-guest-token" }.value - - return FilmxyCookies(phpsessid, wpSec, wpGuest) + val cookieJar = session.baseClient.cookieJar.loadForRequest(cookieUrl.toHttpUrl()).associate { it.name to it.value }.toMutableMap() + return cookieJar.plus(mapOf("G_ENABLED_IDPS" to "google")) } fun Document.findTvMoviesIframe(): String? { From 05f2bce9a8d999bf8a33edc804cdcc448994f575 Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 30 Jul 2023 02:37:51 +0700 Subject: [PATCH 041/105] TimefourTv: fix daddy again --- .../src/main/kotlin/com/hexated/SoraUtils.kt | 2 +- TimefourTv/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/TimefourTv.kt | 20 ++++++++----------- .../kotlin/com/hexated/TimefourTvExtractor.kt | 9 +++++++-- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 2f912165..386dea91 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -918,7 +918,7 @@ suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): Map Date: Mon, 31 Jul 2023 11:30:48 +0700 Subject: [PATCH 042/105] sora/goku: fix missing shows --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 191 ++++-------------- .../src/main/kotlin/com/hexated/SoraStream.kt | 24 +-- .../main/kotlin/com/hexated/SoraStreamLite.kt | 19 +- .../kotlin/com/hexated/SoraStreamPlugin.kt | 1 + 5 files changed, 63 insertions(+), 174 deletions(-) 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 From 74e1b575599d3383351c8cc13d44ad60abd0a064 Mon Sep 17 00:00:00 2001 From: sora Date: Wed, 2 Aug 2023 06:30:41 +0700 Subject: [PATCH 043/105] fix provider --- Minioppai/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 65 +++++++++++++ .../src/main/kotlin/com/hexated/Minioppai.kt | 97 ++----------------- .../kotlin/com/hexated/MinioppaiPlugin.kt | 1 + 4 files changed, 75 insertions(+), 90 deletions(-) create mode 100644 Minioppai/src/main/kotlin/com/hexated/Extractors.kt diff --git a/Minioppai/build.gradle.kts b/Minioppai/build.gradle.kts index 3d8a6e96..42457c51 100644 --- a/Minioppai/build.gradle.kts +++ b/Minioppai/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/Minioppai/src/main/kotlin/com/hexated/Extractors.kt b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt new file mode 100644 index 00000000..c1bba19a --- /dev/null +++ b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt @@ -0,0 +1,65 @@ +package com.hexated + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.fixTitle +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.fixUrl +import com.lagradost.cloudstream3.utils.getAndUnpack +import com.lagradost.cloudstream3.utils.getQualityFromName + +open class Streampai : ExtractorApi() { + override val name = "Streampai" + override val mainUrl = "https://streampai.my.id" + override val requiresReferer = true + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val res = app.get(url, referer = referer).text + val data = getAndUnpack(res) + + val sources = data.substringAfter("sources:[").substringBefore("]").replace("\'", "\"") + val tracks = data.substringAfter("\"tracks\":[").substringBefore("]") + + tryParseJson>("[$sources]")?.forEach { + callback.invoke( + ExtractorLink( + this.name, + this.name, + fixUrl(it.file), + "$mainUrl/", + getQualityFromName(it.label), + headers = mapOf( + "Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5", + "Range" to "bytes=0-", + "Sec-Fetch-Dest" to "video", + "Sec-Fetch-Mode" to "no-cors", + ) + ) + ) + } + + tryParseJson>("[$tracks]")?.forEach { + subtitleCallback.invoke( + SubtitleFile( + fixTitle(it.label ?: ""), + fixUrl(it.file), + ) + ) + } + } + + data class Responses( + @JsonProperty("file") val file: String, + @JsonProperty("type") val type: String?, + @JsonProperty("label") val label: String? + ) + +} \ No newline at end of file diff --git a/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt b/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt index ece21181..04756c71 100644 --- a/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt +++ b/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt @@ -3,7 +3,6 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.utils.* -import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import org.jsoup.Jsoup import org.jsoup.nodes.Element import java.net.URLDecoder @@ -21,15 +20,6 @@ class Minioppai : MainAPI() { ) companion object { - const val libPaistream = "https://lb.paistream.my.id" - const val paistream = "https://paistream.my.id" - - fun getType(t: String): TvType { - return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA - else if (t.contains("Movie", true)) TvType.AnimeMovie - else TvType.Anime - } - fun getStatus(t: String?): ShowStatus { return when (t) { "Completed" -> ShowStatus.Completed @@ -37,7 +27,6 @@ class Minioppai : MainAPI() { else -> ShowStatus.Completed } } - } override val mainPage = mainPageOf( @@ -138,93 +127,23 @@ class Minioppai : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { - val document = app.get(data).document document.select("div.server ul.mirror li a").mapNotNull { - fixUrl( - Jsoup.parse(base64Decode(it.attr("data-em"))).select("iframe").attr("src") - ) to it.text() - }.apmap { (link, server) -> - if (link.startsWith(paistream)) { - invokeLocal(link, server, subtitleCallback, callback) - } else { - loadExtractor(fixUrl(decode(link.substringAfter("data="))), mainUrl, subtitleCallback, callback) - } + Jsoup.parse(base64Decode(it.attr("data-em"))).select("iframe").attr("src") + }.apmap { link -> + loadExtractor( + fixUrl(decode(link.substringAfter("data="))), + mainUrl, + subtitleCallback, + callback + ) } return true } - private suspend fun invokeLocal( - url: String, - server: String, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - val script = getAndUnpack(app.get(url, referer="$mainUrl/").text) - val sources = script.substringAfter("sources:[").substringBefore("]").replace("'", "\"") - val subtitles = script.substringAfter("\"tracks\":[").substringBefore("]") - - tryParseJson>("[$sources]")?.map { source -> - val pStream = fixLink(source.file ?: return@map, paistream).takeIf { - app.get( - it, - referer = "$paistream/" - ).isSuccessful - } - callback.invoke( - ExtractorLink( - server, - server, - pStream ?: fixLink(source.file ?: return@map, libPaistream), - "$paistream/", - getQualityFromName(source.label) - ) - ) - } - - tryParseJson>("[$subtitles]")?.map { - subtitleCallback.invoke( - SubtitleFile( - it.label ?: "", - fixLink(it.file ?: return@map, paistream) - ) - ) - } - - } - private fun decode(input: String): String = URLDecoder.decode(input, "utf-8") - private fun fixLink(url: String, domain: String): String { - if (url.startsWith("http")) { - return url - } - if (url.isEmpty()) { - return "" - } - - val startsWithNoHttp = url.startsWith("//") - if (startsWithNoHttp) { - return "https:$url" - } else { - if (url.startsWith('/')) { - return domain + url - } - return "$domain/$url" - } - } - - data class Subtitles( - @JsonProperty("file") var file: String? = null, - @JsonProperty("label") var label: String? = null, - ) - - data class Sources( - @JsonProperty("label") var label: String? = null, - @JsonProperty("file") var file: String? = null, - ) - data class SearchResponses( @JsonProperty("post") var post: ArrayList = arrayListOf() ) diff --git a/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt b/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt index 3e99c433..27afc040 100644 --- a/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt +++ b/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt @@ -9,5 +9,6 @@ class MinioppaiPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(Minioppai()) + registerExtractorAPI(Streampai()) } } \ No newline at end of file From ab639e3f483d722144c8689f2056fde11022070a Mon Sep 17 00:00:00 2001 From: hexated Date: Wed, 2 Aug 2023 22:57:51 +0700 Subject: [PATCH 044/105] fix idlix --- .github/workflows/build.yml | 2 ++ IdlixProvider/build.gradle.kts | 2 +- IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt | 2 +- SoraStream/build.gradle.kts | 3 ++- SoraStream/src/main/kotlin/com/hexated/SoraStream.kt | 6 +++--- SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt | 2 +- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a51d0526..3d905d0f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,6 +54,7 @@ jobs: ANICHI_SERVER: ${{ secrets.ANICHI_SERVER }} ANICHI_ENDPOINT: ${{ secrets.ANICHI_ENDPOINT }} ANICHI_APP: ${{ secrets.ANICHI_APP }} + GOMOVIES_KEY: ${{ secrets.GOMOVIES_KEY }} run: | cd $GITHUB_WORKSPACE/src echo SORA_API=$SORA_API >> local.properties @@ -68,6 +69,7 @@ jobs: echo ANICHI_SERVER=$ANICHI_SERVER >> local.properties echo ANICHI_ENDPOINT=$ANICHI_ENDPOINT >> local.properties echo ANICHI_APP=$ANICHI_APP >> local.properties + echo GOMOVIES_KEY=$GOMOVIES_KEY >> local.properties - name: Build Plugins run: | diff --git a/IdlixProvider/build.gradle.kts b/IdlixProvider/build.gradle.kts index cc7d7b0c..a2a176b5 100644 --- a/IdlixProvider/build.gradle.kts +++ b/IdlixProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 10 +version = 11 cloudstream { diff --git a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt index 56caefbc..0674303d 100644 --- a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt +++ b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt @@ -10,7 +10,7 @@ import org.jsoup.nodes.Element import java.net.URI class IdlixProvider : MainAPI() { - override var mainUrl = "https://idlixian.com" + override var mainUrl = "https://tv.idlixprime.com" private var directUrl = mainUrl override var name = "Idlix" override val hasMainPage = true diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 4f42edbb..1d33c459 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 = 152 +version = 153 android { defaultConfig { @@ -14,6 +14,7 @@ android { buildConfigField("String", "SORATED", "\"${properties.getProperty("SORATED")}\"") buildConfigField("String", "DUMP_API", "\"${properties.getProperty("DUMP_API")}\"") buildConfigField("String", "DUMP_KEY", "\"${properties.getProperty("DUMP_KEY")}\"") + buildConfigField("String", "GOMOVIES_KEY", "\"${properties.getProperty("GOMOVIES_KEY")}\"") buildConfigField("String", "CRUNCHYROLL_BASIC_TOKEN", "\"${properties.getProperty("CRUNCHYROLL_BASIC_TOKEN")}\"") buildConfigField("String", "CRUNCHYROLL_REFRESH_TOKEN", "\"${properties.getProperty("CRUNCHYROLL_REFRESH_TOKEN")}\"") diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index b1859a67..f46f41e2 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -95,8 +95,8 @@ open class SoraStream : TmdbProvider() { const val movieHabAPI = "https://moviehab.com" const val hdMovieBoxAPI = "https://hdmoviebox.net" const val dreamfilmAPI = "https://dreamfilmsw.net" - const val series9API = "https://series9.sh" - const val idlixAPI = "https://idlixian.com" + const val series9API = "https://series9.cx" + const val idlixAPI = "https://tv.idlixprime.com" const val noverseAPI = "https://www.nollyverse.com" const val uniqueStreamAPI = "https://uniquestream.net" const val filmxyAPI = "https://www.filmxy.vip" @@ -105,7 +105,7 @@ open class SoraStream : TmdbProvider() { const val crunchyrollAPI = "https://beta-api.crunchyroll.com" const val kissKhAPI = "https://kisskh.co" const val lingAPI = "https://ling-online.net" - const val uhdmoviesAPI = "https://uhdmovies.life" + const val uhdmoviesAPI = "https://uhdmovies.ink" const val fwatayakoAPI = "https://5100.svetacdn.in" const val gMoviesAPI = "https://gdrivemovies.xyz" const val fdMoviesAPI = "https://freedrivemovie.lol" diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 386dea91..40ed6859 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -1286,7 +1286,7 @@ fun decodeIndexJson(json: String): String { return base64Decode(slug.substring(0, slug.length - 20)) } -fun String.decryptGomoviesJson(key: String = "123"): String { +fun String.decryptGomoviesJson(key: String = BuildConfig.GOMOVIES_KEY): String { val sb = StringBuilder() var i = 0 while (i < this.length) { From 24f5f1a4dbf4576f16405a26f13ef2a3c74addce Mon Sep 17 00:00:00 2001 From: hexated Date: Thu, 3 Aug 2023 03:58:04 +0700 Subject: [PATCH 045/105] fix LayarKacaProvider --- LayarKacaProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/LayarKacaProvider.kt | 28 ++++++++----------- .../com/hexated/LayarKacaProviderPlugin.kt | 1 + 3 files changed, 14 insertions(+), 17 deletions(-) diff --git a/LayarKacaProvider/build.gradle.kts b/LayarKacaProvider/build.gradle.kts index b1cd5e23..7ec4087a 100644 --- a/LayarKacaProvider/build.gradle.kts +++ b/LayarKacaProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 14 +version = 15 cloudstream { diff --git a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt index 535214aa..a4055e54 100644 --- a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt +++ b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt @@ -3,27 +3,23 @@ package com.hexated import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.extractors.Filesim import com.lagradost.cloudstream3.utils.* import org.jsoup.nodes.Element import java.net.URLDecoder class LayarKacaProvider : MainAPI() { - override var mainUrl = "https://tv.lk21official.pro" + override var mainUrl = "https://tv1.lk21official.pro" private var seriesUrl = "https://tv1.nontondrama.click" override var name = "LayarKaca" override val hasMainPage = true override var lang = "id" - override val hasDownloadSupport = true override val supportedTypes = setOf( TvType.Movie, TvType.TvSeries, TvType.AsianDrama ) - companion object { - const val bananalicious = "https://bananalicious.xyz" - } - override val mainPage = mainPageOf( "$mainUrl/populer/page/" to "Film Terplopuler", "$mainUrl/rating/page/" to "Film Berdasarkan IMDb Rating", @@ -166,21 +162,16 @@ class LayarKacaProvider : MainAPI() { document.select("ul#loadProviders > li").map { fixUrl(it.select("a").attr("href")) }.apmap { - val link = when { - it.startsWith("https://layarkacaxxi.icu") -> { - it.substringBeforeLast("/") - } - it.startsWith(bananalicious) -> decode(it.substringAfter("url=")) - else -> { - it - } - } - loadExtractor(link, bananalicious, subtitleCallback, callback) + loadExtractor(it.getIframe(), "https://nganunganu.sbs", subtitleCallback, callback) } return true } + private suspend fun String.getIframe() : String { + return app.get(this, referer = "$seriesUrl/").document.select("div.embed iframe").attr("src") + } + private fun decode(input: String): String = URLDecoder.decode(input, "utf-8").replace(" ", "%20") } @@ -206,3 +197,8 @@ open class Emturbovid : ExtractorApi() { } } + +class Furher : Filesim() { + override val name = "Furher" + override var mainUrl = "https://furher.in" +} diff --git a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProviderPlugin.kt b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProviderPlugin.kt index bd3389cb..9a73cdc1 100644 --- a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProviderPlugin.kt +++ b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProviderPlugin.kt @@ -11,5 +11,6 @@ class LayarKacaProviderPlugin: Plugin() { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(LayarKacaProvider()) registerExtractorAPI(Emturbovid()) + registerExtractorAPI(Furher()) } } \ No newline at end of file From c510461e4717c5ac5bcfb85bf59eb8ebf04383cb Mon Sep 17 00:00:00 2001 From: hexated Date: Thu, 3 Aug 2023 08:07:43 +0700 Subject: [PATCH 046/105] small fix --- .../src/main/kotlin/com/hexated/SoraExtractor.kt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 8d7ce539..aeb8d026 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2455,13 +2455,8 @@ object SoraExtractor : SoraStream() { val request = app.get(url) if (!request.isSuccessful) return - - val paths = request.document.select("tr.file").map { - Triple( - it.select("a").text(), - it.select("a").attr("href"), - it.select("size").text(), - ) + val paths = request.document.select("a").map { + it.text() to it.attr("href") }.filter { if (season == null) { it.first.contains(Regex("(?i)(1080p|2160p)")) @@ -2474,11 +2469,10 @@ object SoraExtractor : SoraStream() { paths.map { val quality = getIndexQuality(it.first) val tags = getIndexQualityTags(it.first) - val size = "%.2f GB".format(bytesToGigaBytes(it.third.toDouble())) callback.invoke( ExtractorLink( "DahmerMovies", - "DahmerMovies $tags [$size]", + "DahmerMovies $tags", (url + it.second).encodeUrl(), "", quality, From b04f604e74b88b89df2bf333eec6b724fdc6eb25 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 5 Aug 2023 16:50:35 +0700 Subject: [PATCH 047/105] fix idlix --- IdlixProvider/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/IdlixProvider.kt | 18 +- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 207 ++++------ .../src/main/kotlin/com/hexated/SoraStream.kt | 3 - .../main/kotlin/com/hexated/SoraStreamLite.kt | 1 - .../src/main/kotlin/com/hexated/SoraUtils.kt | 363 ++---------------- 7 files changed, 119 insertions(+), 477 deletions(-) diff --git a/IdlixProvider/build.gradle.kts b/IdlixProvider/build.gradle.kts index a2a176b5..6533b773 100644 --- a/IdlixProvider/build.gradle.kts +++ b/IdlixProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 11 +version = 12 cloudstream { diff --git a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt index 0674303d..064c18dd 100644 --- a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt +++ b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt @@ -6,6 +6,9 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import com.lagradost.nicehttp.Requests +import com.lagradost.nicehttp.Session import org.jsoup.nodes.Element import java.net.URI @@ -16,6 +19,7 @@ class IdlixProvider : MainAPI() { override val hasMainPage = true override var lang = "id" override val hasDownloadSupport = true + private val session = Session(Requests().baseClient) override val supportedTypes = setOf( TvType.Movie, TvType.TvSeries, @@ -47,9 +51,9 @@ class IdlixProvider : MainAPI() { val url = request.data.split("?") val nonPaged = request.name == "Featured" && page <= 1 val req = if (nonPaged) { - app.get(request.data) + session.get(request.data) } else { - app.get("${url.first()}$page/?${url.lastOrNull()}") + session.get("${url.first()}$page/?${url.lastOrNull()}") } mainUrl = getBaseUrl(req.url) val document = req.document @@ -94,7 +98,7 @@ class IdlixProvider : MainAPI() { } override suspend fun search(query: String): List { - val req = app.get("$mainUrl/search/$query") + val req = session.get("$mainUrl/search/$query") mainUrl = getBaseUrl(req.url) val document = req.document return document.select("div.result-item").map { @@ -109,7 +113,7 @@ class IdlixProvider : MainAPI() { } override suspend fun load(url: String): LoadResponse { - val request = app.get(url) + val request = session.get(url) directUrl = getBaseUrl(request.url) val document = request.document val title = @@ -189,7 +193,7 @@ class IdlixProvider : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { - val document = app.get(data).document + val document = session.get(data).document val id = document.select("meta#dooplay-ajax-counter").attr("data-postid") val type = if (data.contains("/movie/")) "movie" else "tv" @@ -197,7 +201,7 @@ class IdlixProvider : MainAPI() { it.attr("data-nume") }.apmap { nume -> safeApiCall { - var source = app.post( + var source = session.post( url = "$directUrl/wp-admin/admin-ajax.php", data = mapOf( "action" to "doo_player_ajax", @@ -207,7 +211,7 @@ class IdlixProvider : MainAPI() { ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = data - ).parsed().embed_url + ).let { tryParseJson(it.text) }?.embed_url ?: return@safeApiCall if (source.startsWith("https://uservideo.xyz")) { source = app.get(source).document.select("iframe").attr("src") diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 1d33c459..4891d8da 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 = 153 +version = 154 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index aeb8d026..6041ab65 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -5,7 +5,6 @@ import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.nicehttp.Requests 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 @@ -15,7 +14,6 @@ import com.lagradost.nicehttp.RequestBodyTypes import kotlinx.coroutines.delay import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody -import okio.ByteString.Companion.encode import org.jsoup.Jsoup import org.jsoup.nodes.Document @@ -47,8 +45,9 @@ object SoraExtractor : SoraStream() { val titleMedia = ele.select("h3.movie-name").text() 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() + 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) { @@ -74,7 +73,8 @@ object SoraExtractor : SoraStream() { "$gokuAPI/ajax/movie/seasons/${ media.selectFirst("a.btn-wl")?.attr("data-id") ?: return }", headers = headers - ).document.select("a.ss-item").find { it.ownText().equals("Season $season", true) }?.attr("data-id") + ).document.select("a.ss-item").find { it.ownText().equals("Season $season", true) } + ?.attr("data-id") val episodeId = app.get( "$gokuAPI/ajax/movie/season/episodes/${seasonId ?: return}", @@ -93,15 +93,13 @@ object SoraExtractor : SoraStream() { val iframe = app.get("$gokuAPI/ajax/movie/episode/server/sources/$id", headers = headers) .parsedSafe()?.data?.link ?: return@apmap - extractRabbitStream( + loadCustomExtractor( if (iframe.contains("rabbitstream")) "Vidcloud" else "Upcloud", iframe, "$gokuAPI/", subtitleCallback, callback, - false, - decryptKey = RabbitStream.getKey() - ) { it } + ) } } @@ -417,7 +415,7 @@ object SoraExtractor : SoraStream() { } else { "$idlixAPI/episode/$fixTitle-season-$season-episode-$episode" } - invokeWpmovies(url,subtitleCallback, callback) + invokeWpmovies(url, subtitleCallback, callback) } suspend fun invokeMultimovies( @@ -433,7 +431,7 @@ object SoraExtractor : SoraStream() { } else { "$multimoviesAPI/episodes/$fixTitle-${season}x${episode}" } - invokeWpmovies(url,subtitleCallback, callback,true) + invokeWpmovies(url, subtitleCallback, callback, true) } suspend fun invokeNetmovies( @@ -450,7 +448,7 @@ object SoraExtractor : SoraStream() { } else { "$netmoviesAPI/episodes/$fixTitle-${season}x${episode}" } - invokeWpmovies(url,subtitleCallback, callback) + invokeWpmovies(url, subtitleCallback, callback) } private suspend fun invokeWpmovies( @@ -459,7 +457,7 @@ object SoraExtractor : SoraStream() { callback: (ExtractorLink) -> Unit, fixIframe: Boolean = false, ) { - val res = app.get(url ?: return) + val res = session.get(url ?: return) val referer = getBaseUrl(res.url) val document = res.document document.select("ul#playeroptionsul > li").map { @@ -469,11 +467,14 @@ object SoraExtractor : SoraStream() { it.attr("data-type") ) }.apmap { (id, nume, type) -> - val source = app.post( + val json = session.post( url = "$referer/wp-admin/admin-ajax.php", data = mapOf( "action" to "doo_player_ajax", "post" to id, "nume" to nume, "type" to type ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = url - ).parsed().embed_url.let { if(fixIframe) Jsoup.parse(it).select("IFRAME").attr("SRC") else it } + ) + val source = tryParseJson(json.text)?.embed_url?.let { + if (fixIframe) Jsoup.parse(it).select("IFRAME").attr("SRC") else it + } ?: return@apmap if (!source.contains("youtube")) { loadExtractor(source, "$referer/", subtitleCallback, callback) } @@ -560,9 +561,11 @@ object SoraExtractor : SoraStream() { ) ) } + !source.contains("youtube") -> loadExtractor( source, "$uniqueStreamAPI/", subtitleCallback, callback ) + else -> { // pass } @@ -912,7 +915,10 @@ object SoraExtractor : SoraStream() { when { season == null -> slugTitle?.equals(slug) == true lastSeason == 1 -> slugTitle?.contains(slug) == true - else -> slugTitle?.contains(slug) == true && it.title?.contains("Season $season", true) == true + else -> slugTitle?.contains(slug) == true && it.title?.contains( + "Season $season", + true + ) == true } } data?.id to data?.title @@ -1066,16 +1072,23 @@ object SoraExtractor : SoraStream() { val headers = mapOf( "X-Requested-With" to "XMLHttpRequest", ) - val animeId = app.get("$malsyncAPI/mal/anime/${malId ?: return}").parsedSafe()?.sites?.zoro?.keys?.map { it } + val animeId = app.get("$malsyncAPI/mal/anime/${malId ?: return}") + .parsedSafe()?.sites?.zoro?.keys?.map { it } animeId?.apmap { id -> - val episodeId = app.get("$aniwatchAPI/ajax/v2/episode/list/${id ?: return@apmap}", headers = headers) + val episodeId = app.get( + "$aniwatchAPI/ajax/v2/episode/list/${id ?: return@apmap}", + headers = headers + ) .parsedSafe()?.html?.let { Jsoup.parse(it) }?.select("div.ss-list a")?.find { it.attr("data-number") == "${episode ?: 1}" } ?.attr("data-id") val servers = - app.get("$aniwatchAPI/ajax/v2/episode/servers?episodeId=${episodeId ?: return@apmap}", headers = headers) + app.get( + "$aniwatchAPI/ajax/v2/episode/servers?episodeId=${episodeId ?: return@apmap}", + headers = headers + ) .parsedSafe()?.html?.let { Jsoup.parse(it) } ?.select("div.item.server-item")?.map { Triple( @@ -1086,27 +1099,21 @@ object SoraExtractor : SoraStream() { } servers?.apmap servers@{ server -> - val iframe = app.get("$aniwatchAPI/ajax/v2/episode/sources?id=${server.second ?: return@servers}", headers = headers) - .parsedSafe()?.link ?: return@servers + val iframe = app.get( + "$aniwatchAPI/ajax/v2/episode/sources?id=${server.second ?: return@servers}", + headers = headers + ) + .parsedSafe()?.link ?: return@servers val audio = if (server.third == "sub") "Raw" else "English Dub" - if (server.first.contains(Regex("Vidstreaming|MegaCloud|Vidcloud"))) { - extractRabbitStream( - "${server.first} [$audio]", - iframe, - "$aniwatchAPI/", - subtitleCallback, - callback, - false, - decryptKey = RabbitStream.getZoroKey() - ) { it } - } else { - loadExtractor(iframe, "$aniwatchAPI/", subtitleCallback, callback) - } - + loadCustomExtractor( + "${server.first} [$audio]", + iframe, + "$aniwatchAPI/", + subtitleCallback, + callback, + ) } } - - } suspend fun invokeLing( @@ -1307,9 +1314,11 @@ object SoraExtractor : SoraStream() { val gdBotLink = extractGdbot(link) extractGdflix(gdBotLink ?: return@apmap) } + link.contains("gdflix") -> { extractGdflix(link) } + else -> { return@apmap } @@ -1476,15 +1485,17 @@ object SoraExtractor : SoraStream() { val gdBotLink = extractGdbot(fdLink ?: return@apmap null) extractGdflix(gdBotLink ?: return@apmap null) } + type.contains("oiya") -> { val oiyaLink = extractOiya(fdLink ?: return@apmap null, qualities) - if(oiyaLink?.contains("gdtot") == true) { + if (oiyaLink?.contains("gdtot") == true) { val gdBotLink = extractGdbot(oiyaLink) extractGdflix(gdBotLink ?: return@apmap null) } else { oiyaLink } } + else -> { return@apmap null } @@ -1634,7 +1645,7 @@ object SoraExtractor : SoraStream() { callback: (ExtractorLink) -> Unit ) { val id = getCrunchyrollId("${aniId ?: return}") - ?: getCrunchyrollIdFromMalSync("${malId ?: return}") ?: return + ?: getCrunchyrollIdFromMalSync("${malId ?: return}") val audioLocal = listOf( "ja-JP", "en-US", @@ -1946,24 +1957,33 @@ object SoraExtractor : SoraStream() { it.attr("data-id") to it.text() }.apmap { when { - (it.second.equals("Player F", true) || it.second.equals("Player N", true)) && !isAnime -> { + (it.second.equals("Player F", true) || it.second.equals( + "Player N", + true + )) && !isAnime -> { invokeSmashyFfix(it.second, it.first, url, callback) } + it.first.contains("/gtop") -> { invokeSmashyGtop(it.second, it.first, callback) } + it.first.contains("/dude_tv") -> { invokeSmashyDude(it.second, it.first, callback) } + it.first.contains("/rip") -> { invokeSmashyRip(it.second, it.first, subtitleCallback, callback) } + it.first.contains("/im.php") && !isAnime -> { invokeSmashyIm(it.second, it.first, subtitleCallback, callback) } + it.first.contains("/rw.php") && !isAnime -> { invokeSmashyRw(it.second, it.first, subtitleCallback, callback) } + else -> return@apmap } } @@ -2015,63 +2035,6 @@ object SoraExtractor : SoraStream() { } - } - - suspend fun invokeBaymovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - ) { - val api = "https://thebayindexpublicgroupapi.zindex.eu.org" - val key = base64DecodeAPI("ZW0=c3Q=c3k=b28=YWQ=Ymg=") - val headers = mapOf( - "Referer" to "$baymoviesAPI/", - "Origin" to baymoviesAPI, - "cf_cache_token" to "UKsVpQqBMxB56gBfhYKbfCVkRIXMh42pk6G4DdkXXoVh7j4BjV" - ) - val query = getIndexQuery(title, year, season, episode) - val search = app.get( - "$api/0:search?q=$query&page_token=&page_index=0", - headers = headers - ).text - val media = searchIndex(title, season, episode, year, search) ?: return - - media.apmap { file -> - val expiry = (System.currentTimeMillis() + 345600000).toString() - val hmacSign = "${file.id}@$expiry".encode() - .hmacSha256(key.encode()).base64().replace("+", "-") - val encryptedId = - base64Encode(CryptoAES.encrypt(key, file.id ?: return@apmap null).toByteArray()) - val encryptedExpiry = base64Encode(CryptoAES.encrypt(key, expiry).toByteArray()) - val worker = getConfig().workers.randomOrNull() ?: return@apmap null - - val link = - "https://api.$worker.workers.dev/download.aspx?file=$encryptedId&expiry=$encryptedExpiry&mac=$hmacSign" - val size = file.size?.toDouble() ?: return@apmap null - val sizeFile = "%.2f GB".format(bytesToGigaBytes(size)) - val tags = Regex("\\d{3,4}[pP]\\.?(.*?)\\.(mkv|mp4)").find( - file.name ?: return@apmap null - )?.groupValues?.getOrNull(1)?.replace(".", " ")?.trim() - ?: "" - val quality = - Regex("(\\d{3,4})[pP]").find(file.name)?.groupValues?.getOrNull(1)?.toIntOrNull() - ?: Qualities.P1080.value - - callback.invoke( - ExtractorLink( - "Baymovies", - "Baymovies $tags [$sizeFile]", - link, - "$baymoviesAPI/", - quality, - ) - ) - - } - - } suspend fun invokeBlackmovies( @@ -2094,26 +2057,6 @@ object SoraExtractor : SoraStream() { ) } - suspend fun invokeRinzrymovies( - apiUrl: String, - api: String, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - ) { - invokeIndex( - apiUrl, - api, - title, - year, - season, - episode, - callback, - ) - } - suspend fun invokeCodexmovies( apiUrl: String, api: String, @@ -2490,7 +2433,7 @@ object SoraExtractor : SoraStream() { episode: Int? = null, callback: (ExtractorLink) -> Unit, ) { - val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) + val slug = getEpisodeSlug(season, episode) val query = if (season == null) { title } else { @@ -2530,7 +2473,7 @@ object SoraExtractor : SoraStream() { media.third, gomoviesAPI ) - ).document.selectFirst("div#g_MXOzFGouZrOAUioXjpddqkZK a:contains(Episode $episodeSlug)") + ).document.selectFirst("div#g_MXOzFGouZrOAUioXjpddqkZK a:contains(Episode ${slug.second})") ?.attr("href") } ?: return @@ -2576,7 +2519,6 @@ object SoraExtractor : SoraStream() { year: Int? = null, season: Int? = null, episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { val query = if (season == null) { @@ -2610,7 +2552,8 @@ object SoraExtractor : SoraStream() { } val iframeDoc = app.get(iframe, referer = "$ask4MoviesAPI/").text - val script = Regex("""eval\(function\(p,a,c,k,e,.*\)\)""").findAll(iframeDoc).lastOrNull()?.value + val script = + Regex("""eval\(function\(p,a,c,k,e,.*\)\)""").findAll(iframeDoc).lastOrNull()?.value val unpacked = getAndUnpack(script ?: return) val m3u8 = Regex("file:\\s*\"(.*?m3u8.*?)\"").find(unpacked)?.groupValues?.getOrNull(1) M3u8Helper.generateM3u8( @@ -2748,7 +2691,8 @@ object SoraExtractor : SoraStream() { "$nineTvAPI/tv/$tmdbId-$season-$episode" } - val iframe = app.get(url, referer = "https://pressplay.top/").document.selectFirst("iframe")?.attr("src") ?: return + val iframe = app.get(url, referer = "https://pressplay.top/").document.selectFirst("iframe") + ?.attr("src") ?: return loadExtractor(iframe, "$nineTvAPI/", subtitleCallback, callback) } @@ -2898,7 +2842,6 @@ object SoraExtractor : SoraStream() { imdbId: String? = null, title: String? = null, year: Int? = null, - season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit ) { @@ -2909,7 +2852,7 @@ object SoraExtractor : SoraStream() { null, title, year, - season, + null, episode, false ) @@ -2919,7 +2862,11 @@ object SoraExtractor : SoraStream() { val size = getIndexSize(stream.title) val headers = stream.behaviorHints?.proxyHeaders?.request ?: mapOf() - if(!app.get(stream.url ?: return@apmap, headers = headers).isSuccessful) return@apmap + if (!app.get( + stream.url ?: return@apmap, + headers = headers + ).isSuccessful + ) return@apmap callback.invoke( ExtractorLink( @@ -2943,7 +2890,8 @@ object SoraExtractor : SoraStream() { ) { val referer = "https://2now.tv/" val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) - val url = if(season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${episodeSlug}.mp4" + val url = + if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${episodeSlug}.mp4" if (!app.get(url, referer = referer).isSuccessful) return callback.invoke( ExtractorLink( @@ -3038,7 +2986,7 @@ object SoraExtractor : SoraStream() { ).text M3u8Helper.generateM3u8( - if(host == navyAPI) "Navy" else "Moment", + if (host == navyAPI) "Navy" else "Moment", path, "${referer}/" ).forEach(callback) @@ -3081,7 +3029,10 @@ object SoraExtractor : SoraStream() { ) ).parsedSafe()?.value - val script = app.get(server ?: return, referer = "$emoviesAPI/").document.selectFirst("script:containsData(sources:)")?.data() ?: return + val script = app.get( + server ?: return, + referer = "$emoviesAPI/" + ).document.selectFirst("script:containsData(sources:)")?.data() ?: return val sources = Regex("sources:\\s*\\[(.*)],").find(script)?.groupValues?.get(1)?.let { tryParseJson>("[$it]") } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index f46f41e2..14ee4366 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -159,7 +159,6 @@ open class SoraStream : TmdbProvider() { const val jsMoviesAPI = "https://jsupload.jnsbot.workers.dev/0:" const val xtremeMoviesAPI = "https://kartik19.xtrememirror0.workers.dev/0:" const val tgarMovieAPI = "https://tgarchive.eu.org" - 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 xMovieAPI = "https://xemovies.to" @@ -789,7 +788,6 @@ open class SoraStream : TmdbProvider() { res.year, res.season, res.episode, - subtitleCallback, callback ) }, @@ -819,7 +817,6 @@ open class SoraStream : TmdbProvider() { res.imdbId, res.title, res.year, - res.season, res.episode, callback ) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index efd2a6d3..1558a2f7 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -276,7 +276,6 @@ class SoraStreamLite : SoraStream() { res.year, res.season, res.episode, - subtitleCallback, callback ) }, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 40ed6859..35c490a5 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -1,11 +1,9 @@ package com.hexated import android.util.Base64 -import com.fasterxml.jackson.annotation.JsonProperty import com.hexated.DumpUtils.queryApi import com.hexated.SoraStream.Companion.anilistAPI import com.hexated.SoraStream.Companion.base64DecodeAPI -import com.hexated.SoraStream.Companion.baymoviesAPI import com.hexated.SoraStream.Companion.consumetHelper import com.hexated.SoraStream.Companion.crunchyrollAPI import com.hexated.SoraStream.Companion.filmxyAPI @@ -19,12 +17,9 @@ import com.hexated.SoraStream.Companion.watchOnlineAPI import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.APIHolder.getCaptchaToken import com.lagradost.cloudstream3.APIHolder.unixTimeMS -import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.utils.* -import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson -import com.lagradost.cloudstream3.utils.Coroutines.ioSafe import com.lagradost.nicehttp.NiceResponse import com.lagradost.nicehttp.RequestBodyTypes import com.lagradost.nicehttp.requestCreator @@ -37,7 +32,6 @@ import okhttp3.RequestBody.Companion.toRequestBody import org.jsoup.nodes.Document import java.math.BigInteger import java.net.* -import java.nio.charset.StandardCharsets import java.security.* import java.security.spec.PKCS8EncodedKeySpec import java.security.spec.X509EncodedKeySpec @@ -52,12 +46,6 @@ import kotlin.math.min val bflixChipperKey = base64DecodeAPI("Yjc=ejM=TzA=YTk=WHE=WnU=bXU=RFo=") const val bflixKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" const val otakuzBaseUrl = "https://otakuz.live/" -val soraHeaders = mapOf( - "lang" to "en", - "versioncode" to "33", - "clienttype" to "android_Official", - "deviceid" to getDeviceId(), -) val encodedIndex = arrayOf( "GamMovies", "JSMovies", @@ -1165,6 +1153,33 @@ suspend fun tmdbToAnimeId(title: String?, year: Int?, season: String?, type: TvT } +suspend fun loadCustomExtractor( + name: String, + url: String, + referer: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, + quality: Int? = null, +) { + loadExtractor(url, referer, subtitleCallback) { link -> + callback.invoke( + ExtractorLink( + name, + name, + link.url, + link.referer, + when { + link.isM3u8 -> link.quality + else -> quality ?: link.quality + }, + link.isM3u8, + link.headers, + link.extractorData + ) + ) + } +} + fun getSeason(month: Int?): String? { val seasons = arrayOf( "Winter", "Winter", "Spring", "Spring", "Spring", "Summer", @@ -1182,7 +1197,6 @@ fun getPutlockerQuality(quality: String): Int { } } - fun getEpisodeSlug( season: Int? = null, episode: Int? = null, @@ -1264,23 +1278,6 @@ fun matchingIndex( ) == true && ((mediaMimeType in mimeType) || mediaName.contains(Regex("\\.mkv|\\.mp4|\\.avi"))) } -suspend fun getConfig(): BaymoviesConfig { - val regex = """const country = "(.*?)"; -const downloadtime = "(.*?)"; -var arrayofworkers = (.*)""".toRegex() - val js = app.get( - "https://geolocation.zindex.eu.org/api.js", - referer = "$baymoviesAPI/", - ).text - val match = regex.find(js) ?: throw ErrorLoadingException() - val country = match.groupValues[1] - val downloadTime = match.groupValues[2] - val workers = tryParseJson>(match.groupValues[3]) - ?: throw ErrorLoadingException() - - return BaymoviesConfig(country, downloadTime, workers) -} - fun decodeIndexJson(json: String): String { val slug = json.reversed().substring(24) return base64Decode(slug.substring(0, slug.length - 20)) @@ -1791,312 +1788,6 @@ object CryptoAES { } -object RabbitStream { - - suspend fun MainAPI.extractRabbitStream( - server: String, - url: String, - ref: String, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, - useSidAuthentication: Boolean, - /** Used for extractorLink name, input: Source name */ - extractorData: String? = null, - decryptKey: String? = null, - nameTransformer: (String) -> String, - ) = suspendSafeApiCall { - // https://rapid-cloud.ru/embed-6/dcPOVRE57YOT?z= -> https://rapid-cloud.ru/embed-6 - val mainIframeUrl = - url.substringBeforeLast("/") - val mainIframeId = url.substringAfterLast("/") - .substringBefore("?") // https://rapid-cloud.ru/embed-6/dcPOVRE57YOT?z= -> dcPOVRE57YOT - var sid: String? = null - if (useSidAuthentication && extractorData != null) { - negotiateNewSid(extractorData)?.also { pollingData -> - app.post( - "$extractorData&t=${generateTimeStamp()}&sid=${pollingData.sid}", - requestBody = "40".toRequestBody(), - timeout = 60 - ) - val text = app.get( - "$extractorData&t=${generateTimeStamp()}&sid=${pollingData.sid}", - timeout = 60 - ).text.replaceBefore("{", "") - - sid = AppUtils.parseJson(text).sid - ioSafe { app.get("$extractorData&t=${generateTimeStamp()}&sid=${pollingData.sid}") } - } - } - val mainIframeAjax = mainIframeUrl.let { - if(it.contains("/embed-2/e-1")) it.replace( - "/embed-2/e-1", - "/embed-2/ajax/e-1" - ) else it.replace( - "/embed", - "/ajax/embed" - ) - } - val getSourcesUrl = "$mainIframeAjax/getSources?id=$mainIframeId${sid?.let { "$&sId=$it" } ?: ""}" - val response = app.get( - getSourcesUrl, - referer = mainUrl, - headers = mapOf( - "X-Requested-With" to "XMLHttpRequest", - "Accept" to "*/*", - "Accept-Language" to "en-US,en;q=0.5", - "Connection" to "keep-alive", - "TE" to "trailers" - ) - ) - - val sourceObject = if (decryptKey != null) { - val encryptedMap = response.parsedSafe() - val sources = encryptedMap?.sources - if (sources == null || encryptedMap.encrypted == false) { - response.parsedSafe() - } else { - val (realKey, encData) = extractRealKey(sources, decryptKey) - val decrypted = decryptMapped>(encData, realKey) - SourceObject( - sources = decrypted, - tracks = encryptedMap.tracks - ) - } - } else { - response.parsedSafe() - } ?: return@suspendSafeApiCall - - sourceObject.tracks?.forEach { track -> - track?.toSubtitleFile()?.let { subtitleFile -> - subtitleCallback.invoke(subtitleFile) - } - } - - val list = listOf( - sourceObject.sources to "source 1", - sourceObject.sources1 to "source 2", - sourceObject.sources2 to "source 3", - sourceObject.sourcesBackup to "source backup" - ) - - list.forEach { subList -> - subList.first?.forEach { source -> - source?.toExtractorLink( - server, - ref, - extractorData, - ) - ?.forEach { - // Sets Zoro SID used for video loading -// (this as? ZoroProvider)?.sid?.set(it.url.hashCode(), sid) - callback(it) - } - } - } - } - - private suspend fun Sources.toExtractorLink( - name: String, - referer: String, - extractorData: String? = null, - ): List? { - return this.file?.let { file -> - //println("FILE::: $file") - val isM3u8 = URI(this.file).path.endsWith(".m3u8") || this.type.equals( - "hls", - ignoreCase = true - ) - return if (isM3u8) { - suspendSafeApiCall { - M3u8Helper().m3u8Generation( - M3u8Helper.M3u8Stream( - this.file, - null, - mapOf("Referer" to "https://mzzcloud.life/") - ), false - ) - .map { stream -> - ExtractorLink( - name, - name, - stream.streamUrl, - referer, - getQualityFromName(stream.quality?.toString()), - true, - extractorData = extractorData - ) - } - }.takeIf { !it.isNullOrEmpty() } ?: listOf( - // Fallback if m3u8 extractor fails - ExtractorLink( - name, - name, - this.file, - referer, - getQualityFromName(this.label), - isM3u8, - extractorData = extractorData - ) - ) - } else { - listOf( - ExtractorLink( - name, - name, - file, - referer, - getQualityFromName(this.label), - false, - extractorData = extractorData - ) - ) - } - } - } - - private fun Tracks.toSubtitleFile(): SubtitleFile? { - return this.file?.let { - SubtitleFile( - this.label ?: "Unknown", - it - ) - } - } - - /** - * Generates a session - * 1 Get request. - * */ - private suspend fun negotiateNewSid(baseUrl: String): PollingData? { - // Tries multiple times - for (i in 1..5) { - val jsonText = - app.get("$baseUrl&t=${generateTimeStamp()}").text.replaceBefore( - "{", - "" - ) -// println("Negotiated sid $jsonText") - AppUtils.parseJson(jsonText)?.let { return it } - delay(1000L * i) - } - return null - } - - private fun generateTimeStamp(): String { - val chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_" - var code = "" - var time = APIHolder.unixTimeMS - while (time > 0) { - code += chars[(time % (chars.length)).toInt()] - time /= chars.length - } - return code.reversed() - } - - suspend fun getKey(): String { - return app.get("https://raw.githubusercontent.com/enimax-anime/key/e4/key.txt") - .text - } - - suspend fun getZoroKey(): String { - return app.get("https://raw.githubusercontent.com/enimax-anime/key/e6/key.txt").text - } - - private fun extractRealKey(originalString: String?, stops: String) : Pair { - val table = parseJson>>(stops) - val decryptedKey = StringBuilder() - var offset = 0 - var encryptedString = originalString - - table.forEach { (start, end) -> - decryptedKey.append(encryptedString?.substring(start - offset, end - offset)) - encryptedString = encryptedString?.substring(0, start - offset) + encryptedString?.substring(end - offset) - offset += end - start - } - return decryptedKey.toString() to encryptedString.toString() - } - - private inline fun decryptMapped(input: String, key: String): T? { - return tryParseJson(decrypt(input, key)) - } - - private fun decrypt(input: String, key: String): String { - return decryptSourceUrl( - generateKey( - base64DecodeArray(input).copyOfRange(8, 16), - key.toByteArray() - ), input - ) - } - - private fun generateKey(salt: ByteArray, secret: ByteArray): ByteArray { - var key = md5(secret + salt) - var currentKey = key - while (currentKey.size < 48) { - key = md5(key + secret + salt) - currentKey += key - } - return currentKey - } - - private fun md5(input: ByteArray): ByteArray { - return MessageDigest.getInstance("MD5").digest(input) - } - - private fun decryptSourceUrl(decryptionKey: ByteArray, sourceUrl: String): String { - val cipherData = base64DecodeArray(sourceUrl) - val encrypted = cipherData.copyOfRange(16, cipherData.size) - val aesCBC = Cipher.getInstance("AES/CBC/PKCS5Padding") - - Objects.requireNonNull(aesCBC).init( - Cipher.DECRYPT_MODE, SecretKeySpec( - decryptionKey.copyOfRange(0, 32), - "AES" - ), - IvParameterSpec(decryptionKey.copyOfRange(32, decryptionKey.size)) - ) - val decryptedData = aesCBC!!.doFinal(encrypted) - return String(decryptedData, StandardCharsets.UTF_8) - } - - data class PollingData( - @JsonProperty("sid") val sid: String? = null, - @JsonProperty("upgrades") val upgrades: ArrayList = arrayListOf(), - @JsonProperty("pingInterval") val pingInterval: Int? = null, - @JsonProperty("pingTimeout") val pingTimeout: Int? = null - ) - - data class Tracks( - @JsonProperty("file") val file: String?, - @JsonProperty("label") val label: String?, - @JsonProperty("kind") val kind: String? - ) - - data class Sources( - @JsonProperty("file") val file: String?, - @JsonProperty("type") val type: String?, - @JsonProperty("label") val label: String? - ) - - data class SourceObject( - @JsonProperty("sources") val sources: List? = null, - @JsonProperty("sources_1") val sources1: List? = null, - @JsonProperty("sources_2") val sources2: List? = null, - @JsonProperty("sourcesBackup") val sourcesBackup: List? = null, - @JsonProperty("tracks") val tracks: List? = null - ) - - data class SourceObjectEncrypted( - @JsonProperty("sources") val sources: String?, - @JsonProperty("encrypted") val encrypted: Boolean?, - @JsonProperty("sources_1") val sources1: String?, - @JsonProperty("sources_2") val sources2: String?, - @JsonProperty("sourcesBackup") val sourcesBackup: String?, - @JsonProperty("tracks") val tracks: List? - ) - -} - object DumpUtils { private val deviceId = getDeviceId() From 5341a03eb6aadd5ac5943f26ed3cd06ca8cb4c67 Mon Sep 17 00:00:00 2001 From: sora Date: Sun, 6 Aug 2023 01:59:19 +0700 Subject: [PATCH 048/105] Nodrakorid & Hdmovie2: fix episodes list --- Gomov/build.gradle.kts | 2 +- Gomov/src/main/kotlin/com/hexated/Gomov.kt | 4 +++- .../src/main/kotlin/com/hexated/Nodrakorid.kt | 2 +- Movierulzhd/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/Movierulzhd.kt | 6 ++--- .../main/kotlin/com/hexated/SoraExtractor.kt | 23 +++++++------------ .../src/main/kotlin/com/hexated/SoraUtils.kt | 6 ++--- 7 files changed, 20 insertions(+), 25 deletions(-) diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index a8b04bca..87aa82a7 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/Gomov/src/main/kotlin/com/hexated/Gomov.kt b/Gomov/src/main/kotlin/com/hexated/Gomov.kt index 6282b98f..ab1c5fcf 100644 --- a/Gomov/src/main/kotlin/com/hexated/Gomov.kt +++ b/Gomov/src/main/kotlin/com/hexated/Gomov.kt @@ -46,7 +46,9 @@ open class Gomov : MainAPI() { val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("src"))?.fixImageQuality() val quality = this.select("div.gmr-qual, div.gmr-quality-item > a").text().trim().replace("-", "") return if (quality.isEmpty()) { - val episode = this.select("div.gmr-numbeps > span").text().toIntOrNull() + val episode = + Regex("Episode\\s?([0-9]+)").find(title)?.groupValues?.getOrNull(1)?.toIntOrNull() + ?: this.select("div.gmr-numbeps > span").text().toIntOrNull() newAnimeSearchResponse(title, href, TvType.TvSeries) { this.posterUrl = posterUrl addSub(episode) diff --git a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt index c6c119d1..c65d6b2f 100644 --- a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt +++ b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt @@ -35,7 +35,7 @@ class Nodrakorid : DutaMovie() { ele.ownText().filter { it.isDigit() }.toIntOrNull() to ele.select("a") .map { it.attr("href") to it.text() } }.filter { it.first != null } - Episode(siblings.toJson(), episode = num.filter { it.isDigit() }.toIntOrNull()) + Episode(siblings.toJson(), episode = Regex("Episode\\s?([0-9]+)").find(num)?.groupValues?.getOrNull(1)?.toIntOrNull()) } } } diff --git a/Movierulzhd/build.gradle.kts b/Movierulzhd/build.gradle.kts index 505d6303..e3151139 100644 --- a/Movierulzhd/build.gradle.kts +++ b/Movierulzhd/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 38 +version = 39 cloudstream { diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt index ba4452d9..689a4f89 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt @@ -118,10 +118,10 @@ open class Movierulzhd : MainAPI() { document.select("span.date").text().trim() )?.groupValues?.get(1).toString().toIntOrNull() val tvType = if (document.select("ul#section > li:nth-child(1)").text() - .contains("Episodes") || document.selectFirst("ul#playeroptionsul li span.title") - ?.text()?.contains( + .contains("Episodes") || document.select("ul#playeroptionsul li span.title") + .text().contains( Regex("Episode\\s+\\d+|EP\\d+|PE\\d+") - ) == true + ) ) TvType.TvSeries else TvType.Movie val description = document.select("div.wp-content > p").text().trim() val trailer = document.selectFirst("div.embed iframe")?.attr("src") diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 6041ab65..0cd093b1 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -332,21 +332,14 @@ object SoraExtractor : SoraStream() { } val iframe = app.get(url).document.selectFirst("iframe.Moly")?.attr("data-src") - loadExtractor(iframe ?: return, "$dreamfilmAPI/", subtitleCallback) { link -> - callback.invoke( - ExtractorLink( - link.name, - link.name, - link.url, - link.referer, - Qualities.P1080.value, - link.isM3u8, - link.headers, - link.extractorData - ) - ) - } - + loadCustomExtractor( + null, + iframe ?: return, + "$dreamfilmAPI/", + subtitleCallback, + callback, + Qualities.P1080.value + ) } suspend fun invokeSeries9( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 35c490a5..bc76418a 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -1154,7 +1154,7 @@ suspend fun tmdbToAnimeId(title: String?, year: Int?, season: String?, type: TvT } suspend fun loadCustomExtractor( - name: String, + name: String? = null, url: String, referer: String? = null, subtitleCallback: (SubtitleFile) -> Unit, @@ -1164,8 +1164,8 @@ suspend fun loadCustomExtractor( loadExtractor(url, referer, subtitleCallback) { link -> callback.invoke( ExtractorLink( - name, - name, + name ?: link.source, + name ?: link.name, link.url, link.referer, when { From 72622e8d585b56bbd003785af692aa0719ce94f4 Mon Sep 17 00:00:00 2001 From: sora Date: Sun, 6 Aug 2023 08:10:12 +0700 Subject: [PATCH 049/105] sora: fix smashy N --- SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index bc76418a..23eea4c4 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -441,7 +441,7 @@ suspend fun invokeSmashyFfix( ExtractorLink( "Smashy [$name]", "Smashy [$name]", - link, + decode(link).replace("\\/", "/"), smashyStreamAPI, quality?.toIntOrNull() ?: return@map, isM3u8 = link.contains(".m3u8"), From 27d9b002df16cd1cf368ebddb7f0c207e7bfa718 Mon Sep 17 00:00:00 2001 From: sora Date: Mon, 7 Aug 2023 21:17:34 +0700 Subject: [PATCH 050/105] samehadaku:fix homepage --- Minioppai/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 5 +++ .../kotlin/com/hexated/MinioppaiPlugin.kt | 1 + Samehadaku/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Samehadaku.kt | 4 +-- .../main/kotlin/com/hexated/SoraExtractor.kt | 33 ++++++++++++++----- .../kotlin/com/hexated/SoraStreamPlugin.kt | 2 ++ 7 files changed, 36 insertions(+), 13 deletions(-) diff --git a/Minioppai/build.gradle.kts b/Minioppai/build.gradle.kts index 42457c51..c487633e 100644 --- a/Minioppai/build.gradle.kts +++ b/Minioppai/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/Minioppai/src/main/kotlin/com/hexated/Extractors.kt b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt index c1bba19a..95b96d9e 100644 --- a/Minioppai/src/main/kotlin/com/hexated/Extractors.kt +++ b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt @@ -11,6 +11,11 @@ import com.lagradost.cloudstream3.utils.fixUrl import com.lagradost.cloudstream3.utils.getAndUnpack import com.lagradost.cloudstream3.utils.getQualityFromName +class Paistream : Streampai() { + override val name = "Paistream" + override val mainUrl = "https://paistream.my.id" +} + open class Streampai : ExtractorApi() { override val name = "Streampai" override val mainUrl = "https://streampai.my.id" diff --git a/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt b/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt index 27afc040..83fbd781 100644 --- a/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt +++ b/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt @@ -10,5 +10,6 @@ class MinioppaiPlugin: Plugin() { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(Minioppai()) registerExtractorAPI(Streampai()) + registerExtractorAPI(Paistream()) } } \ No newline at end of file diff --git a/Samehadaku/build.gradle.kts b/Samehadaku/build.gradle.kts index a262ac5b..628eaa26 100644 --- a/Samehadaku/build.gradle.kts +++ b/Samehadaku/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 11 +version = 12 cloudstream { diff --git a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt index 773e2927..dfaee1b1 100644 --- a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt +++ b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt @@ -8,7 +8,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element class Samehadaku : MainAPI() { - override var mainUrl = "https://samehadaku.day" + override var mainUrl = "https://samehadaku.lat" override var name = "Samehadaku" override val hasMainPage = true override var lang = "id" @@ -51,7 +51,7 @@ class Samehadaku : MainAPI() { if (request.name != "Episode Terbaru" && page <= 1) { val doc = app.get(request.data).document - doc.select("div.widget_senction").forEach { block -> + doc.select("div.widget_senction:not(:contains(Baca Komik))").forEach { block -> val header = block.selectFirst("div.widget-title h3")?.ownText() ?: return@forEach val home = block.select("div.animepost").mapNotNull { it.toSearchResult() diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 0cd093b1..b9723fa2 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -6,6 +6,7 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.Session import com.lagradost.cloudstream3.extractors.Filesim +import com.lagradost.cloudstream3.extractors.GMPlayer import com.lagradost.cloudstream3.extractors.StreamSB import com.lagradost.cloudstream3.extractors.Voe import com.lagradost.cloudstream3.extractors.helper.GogoHelper @@ -331,15 +332,19 @@ object SoraExtractor : SoraStream() { "$dreamfilmAPI/series/$fixTitle/season-$season/episode-$episode" } - val iframe = app.get(url).document.selectFirst("iframe.Moly")?.attr("data-src") - loadCustomExtractor( - null, - iframe ?: return, - "$dreamfilmAPI/", - subtitleCallback, - callback, - Qualities.P1080.value - ) + val doc = app.get(url).document + doc.select("div#videosen a").apmap { + val iframe = app.get(it.attr("href")).document.selectFirst("div.card-video iframe") + ?.attr("data-src") + loadCustomExtractor( + null, + iframe ?: return@apmap, + "$dreamfilmAPI/", + subtitleCallback, + callback, + Qualities.P1080.value + ) + } } suspend fun invokeSeries9( @@ -3104,6 +3109,16 @@ object SoraExtractor : SoraStream() { } +class TravelR : GMPlayer() { + override val name = "TravelR" + override val mainUrl = "https://travel-russia.xyz" +} + +class Mwish : Filesim() { + override val name = "Mwish" + override var mainUrl = "https://mwish.pro" +} + class Animefever : Filesim() { override val name = "Animefever" override var mainUrl = "https://animefever.fun" diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt index 56f723f4..7bb7f262 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt @@ -15,5 +15,7 @@ class SoraStreamPlugin: Plugin() { registerExtractorAPI(Multimovies()) registerExtractorAPI(MultimoviesSB()) registerExtractorAPI(Yipsu()) + registerExtractorAPI(Mwish()) + registerExtractorAPI(TravelR()) } } \ No newline at end of file From 60ac662c207cf916847d56c7af4f352dca341bfc Mon Sep 17 00:00:00 2001 From: sora Date: Tue, 8 Aug 2023 14:57:19 +0700 Subject: [PATCH 051/105] fix Kuronime --- KuronimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/KuronimeProvider.kt | 235 ++++++++++++++---- 2 files changed, 189 insertions(+), 48 deletions(-) diff --git a/KuronimeProvider/build.gradle.kts b/KuronimeProvider/build.gradle.kts index c903bc0b..a4fc0461 100644 --- a/KuronimeProvider/build.gradle.kts +++ b/KuronimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 13 +version = 14 cloudstream { diff --git a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt index 2d050c26..14a24c6c 100644 --- a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt +++ b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt @@ -3,23 +3,27 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer -import com.lagradost.cloudstream3.mvvm.safeApiCall +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.loadExtractor -import org.jsoup.Jsoup import org.jsoup.nodes.Element import java.net.URI +import java.security.DigestException +import java.security.MessageDigest import java.util.ArrayList +import javax.crypto.Cipher +import javax.crypto.spec.IvParameterSpec +import javax.crypto.spec.SecretKeySpec class KuronimeProvider : MainAPI() { - override var mainUrl = "https://kuronime.top" + override var mainUrl = "https://45.12.2.26" + private var animekuUrl = "https://animeku.org" override var name = "Kuronime" override val hasQuickSearch = true override val hasMainPage = true override var lang = "id" - override val hasDownloadSupport = true - override val supportedTypes = setOf( TvType.Anime, TvType.AnimeMovie, @@ -27,6 +31,7 @@ class KuronimeProvider : MainAPI() { ) companion object { + const val KEY = "3&!Z0M,VIZ;dZW==" fun getType(t: String): TvType { return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA else if (t.contains("Movie", true)) TvType.AnimeMovie @@ -72,9 +77,11 @@ class KuronimeProvider : MainAPI() { (title.contains("-episode")) && !(title.contains("-movie")) -> Regex("nonton-(.+)-episode").find( title )?.groupValues?.get(1).toString() + (title.contains("-movie")) -> Regex("nonton-(.+)-movie").find(title)?.groupValues?.get( 1 ).toString() + else -> title } @@ -109,7 +116,11 @@ class KuronimeProvider : MainAPI() { "search" to "false" ), headers = mapOf("X-Requested-With" to "XMLHttpRequest") ).parsedSafe()?.anime?.firstOrNull()?.all?.mapNotNull { - newAnimeSearchResponse(it.postTitle ?: "", it.postLink ?: return@mapNotNull null, TvType.Anime) { + newAnimeSearchResponse( + it.postTitle ?: "", + it.postLink ?: return@mapNotNull null, + TvType.Anime + ) { this.posterUrl = it.postImage addSub(it.postLatest?.toIntOrNull()) } @@ -156,65 +167,195 @@ class KuronimeProvider : MainAPI() { } } - private suspend fun invokeKuroSource( - url: String, - sourceCallback: (ExtractorLink) -> Unit - ) { - val doc = app.get(url, referer = "${mainUrl}/").document - - doc.select("script").map { script -> - if (script.data().contains("function jalankan_jwp() {")) { - val data = script.data() - val doma = data.substringAfter("var doma = \"").substringBefore("\";") - val token = data.substringAfter("var token = \"").substringBefore("\";") - val pat = data.substringAfter("var pat = \"").substringBefore("\";") - val link = "$doma$token$pat/index.m3u8" - val quality = - Regex("\\d{3,4}p").find(doc.select("title").text())?.groupValues?.get(0) - - sourceCallback.invoke( - ExtractorLink( - this.name, - this.name, - link, - referer = "https://animeku.org/", - quality = getQualityFromName(quality), - headers = mapOf("Origin" to "https://animeku.org"), - isM3u8 = true - ) - ) - } - } - } - override suspend fun loadLinks( data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { - val document = app.get(data).document - val sources = document.select(".mobius > .mirror > option").mapNotNull { - fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("data-src")) - } - sources.apmap { - safeApiCall { - when { - it.startsWith("https://animeku.org") -> invokeKuroSource(it, callback) - else -> loadExtractor(it, mainUrl, subtitleCallback, callback) + val document = app.get(data).document + val id = document.selectFirst("div#content script:containsData(is_singular)")?.data() + ?.substringAfter("\"")?.substringBefore("\";") + ?: throw ErrorLoadingException("No id found") + val servers = app.post( + "$animekuUrl/afi.php", data = mapOf( + "id" to id + ), referer = "$mainUrl/" + ).parsedSafe() + + argamap( + { + val decrypt = cryptoAES( + servers?.src ?: return@argamap, + KEY.toByteArray(), + false + ) + val source = + tryParseJson(decrypt?.toJsonFormat())?.src?.replace("\\", "") + callback.invoke( + ExtractorLink( + this.name, + this.name, + source ?: return@argamap, + "$animekuUrl/", + Qualities.P1080.value, + true, + headers = mapOf("Origin" to animekuUrl) + ) + ) + }, + { + val decrypt = cryptoAES( + servers?.mirror ?: return@argamap, + KEY.toByteArray(), + false + ) + tryParseJson(decrypt)?.embed?.map { embed -> + embed.value.apmap { + loadFixedExtractor( + it.value, + embed.key.removePrefix("v"), + "$mainUrl/", + subtitleCallback, + callback + ) + } } + } - } + ) + return true } + private fun String.toJsonFormat(): String { + return if (this.startsWith("\"")) this.substringAfter("\"").substringBeforeLast("\"") + .replace("\\\"", "\"") else this + } + + private suspend fun loadFixedExtractor( + url: String? = null, + quality: String? = null, + referer: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + loadExtractor(url ?: return, referer, subtitleCallback) { link -> + callback.invoke( + ExtractorLink( + link.name, + link.name, + link.url, + link.referer, + getQualityFromName(quality), + link.isM3u8, + link.headers, + link.extractorData + ) + ) + } + } + private fun getBaseUrl(url: String): String { return URI(url).let { "${it.scheme}://${it.host}" } } + // https://stackoverflow.com/a/41434590/8166854 + private fun generateKeyAndIv( + password: ByteArray, + salt: ByteArray, + hashAlgorithm: String = "MD5", + keyLength: Int = 32, + ivLength: Int = 16, + iterations: Int = 1 + ): List? { + + val md = MessageDigest.getInstance(hashAlgorithm) + val digestLength = md.digestLength + val targetKeySize = keyLength + ivLength + val requiredLength = (targetKeySize + digestLength - 1) / digestLength * digestLength + val generatedData = ByteArray(requiredLength) + var generatedLength = 0 + + try { + md.reset() + + while (generatedLength < targetKeySize) { + if (generatedLength > 0) + md.update( + generatedData, + generatedLength - digestLength, + digestLength + ) + + md.update(password) + md.update(salt, 0, 8) + md.digest(generatedData, generatedLength, digestLength) + + for (i in 1 until iterations) { + md.update(generatedData, generatedLength, digestLength) + md.digest(generatedData, generatedLength, digestLength) + } + + generatedLength += digestLength + } + return listOf( + generatedData.copyOfRange(0, keyLength), + generatedData.copyOfRange(keyLength, targetKeySize) + ) + } catch (e: DigestException) { + return null + } + } + + private fun String.decodeHex(): ByteArray { + check(length % 2 == 0) { "Must have an even length" } + return chunked(2) + .map { it.toInt(16).toByte() } + .toByteArray() + } + + private fun cryptoAES( + data: String, + pass: ByteArray, + encrypt: Boolean = true + ): String? { + val json = tryParseJson(base64Decode(data)) + ?: throw ErrorLoadingException("No Data Found") + val (key, iv) = generateKeyAndIv(pass, json.s.decodeHex()) ?: return null + val cipher = Cipher.getInstance("AES/CBC/NoPadding") + return if (!encrypt) { + cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) + String(cipher.doFinal(base64DecodeArray(json.ct))) + } else { + cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) + base64Encode(cipher.doFinal(json.ct.toByteArray())) + + } + } + + data class AesData( + @JsonProperty("ct") val ct: String, + @JsonProperty("iv") val iv: String, + @JsonProperty("s") val s: String + ) + + data class Mirrors( + @JsonProperty("embed") val embed: Map> = emptyMap(), + ) + + data class Sources( + @JsonProperty("src") var src: String? = null, + ) + + data class Servers( + @JsonProperty("src") var src: String? = null, + @JsonProperty("mirror") var mirror: String? = null, + ) + data class All( @JsonProperty("post_image") var postImage: String? = null, @JsonProperty("post_image_html") var postImageHtml: String? = null, From eb19ad6cda003890c5229041f961353a893df0ea Mon Sep 17 00:00:00 2001 From: sora Date: Tue, 8 Aug 2023 15:55:55 +0700 Subject: [PATCH 052/105] Minioppai: added cloudflareKiller --- Minioppai/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Minioppai.kt | 27 +++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Minioppai/build.gradle.kts b/Minioppai/build.gradle.kts index c487633e..368ffe23 100644 --- a/Minioppai/build.gradle.kts +++ b/Minioppai/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 5 +version = 6 cloudstream { diff --git a/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt b/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt index 04756c71..f526c766 100644 --- a/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt +++ b/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt @@ -2,7 +2,10 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.cloudstream3.utils.* +import okhttp3.Interceptor +import okhttp3.Response import org.jsoup.Jsoup import org.jsoup.nodes.Element import java.net.URLDecoder @@ -14,11 +17,24 @@ class Minioppai : MainAPI() { override var lang = "id" override val hasDownloadSupport = true override val hasQuickSearch = true - + private val cloudflareKiller by lazy { CloudflareKiller() } + private val interceptor by lazy { CloudflareInterceptor(cloudflareKiller) } override val supportedTypes = setOf( TvType.NSFW, ) + class CloudflareInterceptor(private val cloudflareKiller: CloudflareKiller): Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + val response = chain.proceed(request) + val doc = Jsoup.parse(response.peekBody(1024 * 1024).string()) + if (doc.select("title").text() == "Just a moment...") { + return cloudflareKiller.intercept(chain) + } + return response + } + } + companion object { fun getStatus(t: String?): ShowStatus { return when (t) { @@ -38,7 +54,7 @@ class Minioppai : MainAPI() { page: Int, request: MainPageRequest ): HomePageResponse { - val document = app.get("${request.data}/page/$page").document + val document = app.get("${request.data}/page/$page", interceptor = interceptor).document val home = document.select("div.latest a").mapNotNull { it.toSearchResult() } @@ -79,7 +95,8 @@ class Minioppai : MainAPI() { "$mainUrl/wp-admin/admin-ajax.php", data = mapOf( "action" to "ts_ac_do_search", "ts_ac_query" to query, - ), headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), + interceptor = interceptor ).parsedSafe()?.post?.firstOrNull()?.all?.mapNotNull { item -> newAnimeSearchResponse( item.postTitle ?: "", @@ -92,7 +109,7 @@ class Minioppai : MainAPI() { } override suspend fun load(url: String): LoadResponse? { - val document = app.get(url).document + val document = app.get(url, interceptor = interceptor).document val title = document.selectFirst("h1.entry-title")?.text()?.trim() ?: return null val poster = fixUrlNull(document.selectFirst("div.limage img")?.attr("src")) @@ -127,7 +144,7 @@ class Minioppai : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { - val document = app.get(data).document + val document = app.get(data, interceptor = interceptor).document document.select("div.server ul.mirror li a").mapNotNull { Jsoup.parse(base64Decode(it.attr("data-em"))).select("iframe").attr("src") }.apmap { link -> From 5aa60512098b256483caf544185230ef1402390f Mon Sep 17 00:00:00 2001 From: sora Date: Tue, 8 Aug 2023 18:38:21 +0700 Subject: [PATCH 053/105] fix black poster --- Minioppai/src/main/kotlin/com/hexated/Minioppai.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt b/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt index f526c766..0a263379 100644 --- a/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt +++ b/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt @@ -84,6 +84,7 @@ class Minioppai : MainAPI() { return newAnimeSearchResponse(title, href, TvType.NSFW) { this.posterUrl = posterUrl addSub(epNum) + posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap() } } @@ -104,6 +105,7 @@ class Minioppai : MainAPI() { TvType.NSFW ) { this.posterUrl = item.postImage + posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap() } } } @@ -135,6 +137,7 @@ class Minioppai : MainAPI() { showStatus = status plot = description this.tags = tags + posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap() } } From a7b06dc3263dc68ccabef978e05b1a45a3677cd4 Mon Sep 17 00:00:00 2001 From: sora Date: Wed, 9 Aug 2023 04:11:50 +0700 Subject: [PATCH 054/105] sora: clean code & remove unworking sources --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 358 +----------------- .../src/main/kotlin/com/hexated/SoraParser.kt | 20 - .../src/main/kotlin/com/hexated/SoraStream.kt | 179 +-------- 4 files changed, 13 insertions(+), 546 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 4891d8da..a26c71b5 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 = 154 +version = 155 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index b9723fa2..8004b826 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -507,70 +507,6 @@ object SoraExtractor : SoraStream() { } } - suspend fun invokeUniqueStream( - 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) { - "$uniqueStreamAPI/movies/$fixTitle-$year" - } else { - "$uniqueStreamAPI/episodes/$fixTitle-season-$season-episode-$episode" - } - - val res = app.get(url) - if (!res.isSuccessful) return - val baseApi = getBaseUrl(res.url) - - val document = res.document - val type = if (url.contains("/movies/")) "movie" else "tv" - document.select("ul#playeroptionsul > li").apmap { el -> - val id = el.attr("data-post") - val nume = el.attr("data-nume") - val source = app.post( - url = "$baseApi/wp-admin/admin-ajax.php", data = mapOf( - "action" to "doo_player_ajax", "post" to id, "nume" to nume, "type" to type - ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = url - ).parsed().embed_url.let { fixUrl(it) } - - when { - source.contains("uniquestream") -> { - val resDoc = app.get( - source, referer = "$baseApi/", headers = mapOf( - "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8" - ) - ).document - val srcm3u8 = - resDoc.selectFirst("script:containsData(let url =)")?.data()?.let { - Regex("['|\"](.*?.m3u8)['|\"]").find(it)?.groupValues?.getOrNull(1) - } - callback.invoke( - ExtractorLink( - "UniqueStream", - "UniqueStream", - srcm3u8 ?: return@apmap null, - source, - Qualities.P1080.value, - true, - ) - ) - } - - !source.contains("youtube") -> loadExtractor( - source, "$uniqueStreamAPI/", subtitleCallback, callback - ) - - else -> { - // pass - } - } - } - } - suspend fun invokeNoverse( title: String? = null, season: Int? = null, @@ -765,59 +701,6 @@ object SoraExtractor : SoraStream() { } } - suspend fun invokeXmovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - val fixTitle = title.createSlug() - val doc = if (season == null) { - val res = app.get("$xMovieAPI/movies/$fixTitle/watch") - if (res.url == "$xMovieAPI/") app.get("$xMovieAPI/movies/$fixTitle-$year/watch").document else res.document - } else { - app.get("$xMovieAPI/series/$fixTitle-season-$season-episode-$episode/watch").document - } - - val script = doc.selectFirst("script:containsData(const player =)")?.data() ?: return - val link = - Regex("[\"|']file[\"|']:\\s?[\"|'](http.*?.(mp4|m3u8))[\"|'],").find(script)?.groupValues?.getOrNull( - 1 - ) ?: return - - if (link.contains(".m3u8")) { - M3u8Helper.generateM3u8( - "Xmovie", - link, - "", - ).forEach(callback) - } else { - callback.invoke( - ExtractorLink( - "Xmovie", - "Xmovie", - link, - "", - Qualities.P720.value, - ) - ) - } - - Regex(""""file":\s+?"(\S+\.(vtt|srt))""").find(script)?.groupValues?.getOrNull(1) - ?.let { sub -> - subtitleCallback.invoke( - SubtitleFile( - "English", - sub, - ) - ) - } - - - } - suspend fun invokeFmovies( title: String? = null, year: Int? = null, @@ -2035,110 +1918,6 @@ object SoraExtractor : SoraStream() { } - suspend fun invokeBlackmovies( - apiUrl: String, - api: String, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - ) { - invokeIndex( - apiUrl, - api, - title, - year, - season, - episode, - callback, - ) - } - - suspend fun invokeCodexmovies( - apiUrl: String, - api: String, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - password: String = "", - ) { - invokeIndex( - apiUrl, - api, - title, - year, - season, - episode, - callback, - password, - ) - } - - suspend fun invokeEdithxmovies( - apiUrl: String, - api: String, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - password: String = "", - ) { - invokeIndex( - apiUrl, - api, - title, - year, - season, - episode, - callback, - password, - ) - } - - suspend fun invokeJmdkhMovies( - apiUrl: String, - api: String, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - ) { - invokeIndex( - apiUrl, - api, - title, - year, - season, - episode, - callback, - ) - } - - suspend fun invokeRubyMovies( - apiUrl: String, - api: String, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - ) { - invokeIndex( - apiUrl, - api, - title, - year, - season, - episode, - callback, - ) - } - suspend fun invokeShinobiMovies( apiUrl: String, api: String, @@ -2159,26 +1938,6 @@ object SoraExtractor : SoraStream() { ) } - suspend fun invokeVitoenMovies( - apiUrl: String, - api: String, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - ) { - invokeIndex( - apiUrl, - api, - title, - year, - season, - episode, - callback, - ) - } - private suspend fun invokeIndex( apiUrl: String, api: String, @@ -2265,9 +2024,6 @@ object SoraExtractor : SoraStream() { } }.encodeUrl() -// removed due to rate limit -// if (!app.get(path).isSuccessful) return@apmap null - val size = "%.2f GB".format(bytesToGigaBytes(file.size?.toDouble() ?: return@apmap null)) val quality = getIndexQuality(file.name) @@ -2287,48 +2043,6 @@ object SoraExtractor : SoraStream() { } - suspend fun invokeTgarMovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - ) { - val query = getIndexQuery(title, year, season, episode) - - val files = app.get( - "https://api.tgarchive.superfastsearch.zindex.eu.org/search?name=${encode(query)}&page=1", - referer = tgarMovieAPI, - timeout = 600L - ).parsedSafe()?.documents?.filter { media -> - matchingIndex( - media.name, - media.mime_type, - title, - year, - season, - episode, - true - ) && media.name?.contains("XXX") == false - } - - files?.map { file -> - val size = "%.2f GB".format(bytesToGigaBytes(file.size ?: return@map null)) - val quality = getIndexQuality(file.name) - val tags = getIndexQualityTags(file.name) - callback.invoke( - ExtractorLink( - "TgarMovies", - "TgarMovies $tags [$size]", - "https://api.southkoreacdn.workers.dev/telegram/${file._id}", - "$tgarMovieAPI/", - quality, - ) - ) - } - - } - suspend fun invokeGdbotMovies( title: String? = null, year: Int? = null, @@ -2769,73 +2483,6 @@ object SoraExtractor : SoraStream() { } - suspend fun invokeShivamhw( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - ) { - val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) - val url = if (season == null) { - "$shivamhwAPI/search?search_box=$title&release_year=$year" - } else { - "$shivamhwAPI/api/series_search?search_box=$title&sess_nm=$seasonSlug&epi_nm=$episodeSlug" - } - - val res = app.get(url) - - val media = if (season == null) { - res.document.select("table.rwd-table tr").map { - Triple( - it.select("td[data-th=File Name]").text(), - it.select("td[data-th=Size]").text(), - it.selectFirst("div.download_button.pls_wait > a")?.attr("href") - ) - } - } else { - tryParseJson>(res.text)?.map { - Triple( - it.name, - it.size, - it.stream_link, - ) - } - } - - media?.filter { - matchingIndex( - it.first, - null, - title, - year, - season, - episode, - false - ) - }?.sortedByDescending { - it.second.getFileSize() - }?.apmap { source -> - val quality = getIndexQuality(source.first) - val tags = getIndexQualityTags(source.first) - val video = source.third - if (!app.get( - video ?: return@apmap, - referer = "$shivamhwAPI/" - ).isSuccessful - ) return@apmap - callback.invoke( - ExtractorLink( - "Shivamhw", - "Shivamhw $tags [${source.second}]", - video, - "$shivamhwAPI/", - quality, - ) - ) - } - } - suspend fun invokeCryMovies( imdbId: String? = null, title: String? = null, @@ -2887,9 +2534,8 @@ object SoraExtractor : SoraStream() { callback: (ExtractorLink) -> Unit ) { val referer = "https://2now.tv/" - val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) - val url = - if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${episodeSlug}.mp4" + val slug = getEpisodeSlug(season, episode) + val url = if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" if (!app.get(url, referer = referer).isSuccessful) return callback.invoke( ExtractorLink( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index a1e91094..382d507c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -202,18 +202,6 @@ data class IndexSearch( @JsonProperty("data") val data: IndexData? = null, ) -data class TgarMedia( - @JsonProperty("_id") val _id: Int? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("size") val size: Double? = null, - @JsonProperty("file_unique_id") val file_unique_id: String? = null, - @JsonProperty("mime_type") val mime_type: String? = null, -) - -data class TgarData( - @JsonProperty("documents") val documents: ArrayList? = arrayListOf(), -) - data class SorastreamResponse( @JsonProperty("data") val data: SorastreamVideos? = null, ) @@ -285,14 +273,6 @@ data class PutlockerResponses( @JsonProperty("backupLink") val backupLink: String? = null, ) -data class ShivamhwSources( - @JsonProperty("id") val id: String? = null, - @JsonProperty("stream_link") val stream_link: String? = null, - @JsonProperty("process_link") val process_link: String? = null, - @JsonProperty("name") val name: String, - @JsonProperty("size") val size: String, -) - data class CryMoviesProxyHeaders( @JsonProperty("request") val request: Map?, ) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 14ee4366..88efd8de 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -3,9 +3,7 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAsk4Movies -import com.hexated.SoraExtractor.invokeBlackmovies import com.hexated.SoraExtractor.invokeBollyMaza -import com.hexated.SoraExtractor.invokeCodexmovies import com.hexated.SoraExtractor.invokeCryMovies import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeFilmxy @@ -22,7 +20,6 @@ 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 import com.hexated.SoraExtractor.invokeFlixon import com.hexated.SoraExtractor.invokeFmovies @@ -31,7 +28,6 @@ import com.hexated.SoraExtractor.invokeGMovies import com.hexated.SoraExtractor.invokeGdbotMovies import com.hexated.SoraExtractor.invokeGoku import com.hexated.SoraExtractor.invokeGomovies -import com.hexated.SoraExtractor.invokeJmdkhMovies import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeLing import com.hexated.SoraExtractor.invokeM4uhd @@ -43,9 +39,7 @@ import com.hexated.SoraExtractor.invokeNowTv import com.hexated.SoraExtractor.invokePutlocker import com.hexated.SoraExtractor.invokeRStream import com.hexated.SoraExtractor.invokeRidomovies -import com.hexated.SoraExtractor.invokeRubyMovies import com.hexated.SoraExtractor.invokeShinobiMovies -import com.hexated.SoraExtractor.invokeShivamhw import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies @@ -56,7 +50,6 @@ import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokePobmovies import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies -import com.hexated.SoraExtractor.invokeVitoenMovies import com.hexated.SoraExtractor.invokeWatchOnline import com.hexated.SoraExtractor.invokeWatchsomuch import com.lagradost.cloudstream3.extractors.VidSrcExtractor @@ -98,7 +91,6 @@ open class SoraStream : TmdbProvider() { const val series9API = "https://series9.cx" const val idlixAPI = "https://tv.idlixprime.com" const val noverseAPI = "https://www.nollyverse.com" - const val uniqueStreamAPI = "https://uniquestream.net" const val filmxyAPI = "https://www.filmxy.vip" const val kimcartoonAPI = "https://kimcartoon.li" const val aniwatchAPI = "https://aniwatch.to" @@ -118,8 +110,7 @@ open class SoraStream : TmdbProvider() { const val flixonAPI = "https://flixon.lol" const val smashyStreamAPI = "https://embed.smashystream.com" const val watchSomuchAPI = "https://watchsomuch.tv" // sub only - val gomoviesAPI = - base64DecodeAPI("bQ==Y28=ZS4=aW4=bmw=LW8=ZXM=dmk=bW8=Z28=Ly8=czo=dHA=aHQ=") + val gomoviesAPI = base64DecodeAPI("bQ==Y28=ZS4=aW4=bmw=LW8=ZXM=dmk=bW8=Z28=Ly8=czo=dHA=aHQ=") const val ask4MoviesAPI = "https://ask4movie.nl" const val biliBiliAPI = "https://api-vn.otakuz.live/server" const val watchOnlineAPI = "https://watchonline.ag" @@ -139,29 +130,9 @@ open class SoraStream : TmdbProvider() { const val doomoviesAPI = "https://doomovies.net" // INDEX SITE - const val blackMoviesAPI = "https://dl.blacklistedbois.workers.dev/0:" - const val codexMoviesAPI = "https://packs.codexcloudx.tech/0:" - const val edithxMoviesAPI = "https://index.edithx.ga/0:" const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev" - const val jmdkhMovieAPI = "https://tg.jmdkh.eu.org/0:" - const val rubyMovieAPI = "https://upload.rubyshare111.workers.dev/0:" const val shinobiMovieAPI = "https://home.shinobicloud.cf/0:" - const val vitoenMovieAPI = "https://openmatte.vitoencodes.workers.dev/0:" - const val shivamhwAPI = "https://foogle.shivamhw.me" - val cryMoviesAPI = - base64DecodeAPI("ZXY=LmQ=cnM=a2U=b3I=Lnc=ZXI=ZGQ=bGE=cy0=b2I=YWM=Lmo=YWw=aW4=LWY=cm4=Ym8=cmU=Ly8=czo=dHA=aHQ=") - - // DEAD SITE - const val rinzryMoviesAPI = "https://rinzry.stream/0:" - const val chillmovies0API = "https://chill.aicirou.workers.dev/0:" - const val chillmovies1API = "https://chill.aicirou.workers.dev/1:" - const val gamMoviesAPI = "https://drive.gamick.workers.dev/0:" - const val jsMoviesAPI = "https://jsupload.jnsbot.workers.dev/0:" - const val xtremeMoviesAPI = "https://kartik19.xtrememirror0.workers.dev/0:" - const val tgarMovieAPI = "https://tgarchive.eu.org" - const val papaonMovies1API = "https://m.papaonwork.workers.dev/0:" - const val papaonMovies2API = "https://m.papaonwork.workers.dev/1:" - const val xMovieAPI = "https://xemovies.to" + val cryMoviesAPI = base64DecodeAPI("ZXY=LmQ=cnM=a2U=b3I=Lnc=ZXI=ZGQ=bGE=cy0=b2I=YWM=Lmo=YWw=aW4=LWY=cm4=Ym8=cmU=Ly8=czo=dHA=aHQ=") fun getType(t: String?): TvType { return when (t) { @@ -419,15 +390,6 @@ open class SoraStream : TmdbProvider() { { invokeMovieHab(res.imdbId, res.season, res.episode, subtitleCallback, callback) }, -// { -// invokeDatabaseGdrive( -// res.imdbId, -// res.season, -// res.episode, -// subtitleCallback, -// callback -// ) -// }, { if (res.isAnime) invokeAnimes( res.title, @@ -440,16 +402,6 @@ open class SoraStream : TmdbProvider() { callback ) }, -// { -// if (res.season != null && res.isAnime) invokeCrunchyroll( -// res.title, -// res.epsTitle, -// res.season, -// res.episode, -// subtitleCallback, -// callback -// ) -// }, { if (!res.isAnime) invokeHDMovieBox( res.title, @@ -488,18 +440,8 @@ open class SoraStream : TmdbProvider() { callback ) }, - { - invokeNoverse(res.title, res.season, res.episode, callback) - }, // { -// invokeUniqueStream( -// res.title, -// res.year, -// res.season, -// res.episode, -// subtitleCallback, -// callback -// ) +// invokeNoverse(res.title, res.season, res.episode, callback) // }, { if (!res.isAnime) invokeFilmxy( @@ -519,16 +461,6 @@ open class SoraStream : TmdbProvider() { callback ) }, -// { -// invokeXmovies( -// res.title, -// res.year, -// res.season, -// res.episode, -// subtitleCallback, -// callback -// ) -// }, { if (!res.isAnime) invokeFmovies( res.title, @@ -668,52 +600,6 @@ open class SoraStream : TmdbProvider() { callback ) }, - { - if (!res.isAnime) invokeBlackmovies( - blackMoviesAPI, - "BlackMovies", - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, -// { -// invokeRinzrymovies( -// rinzryMoviesAPI, -// "RinzryMovies", -// res.title, -// res.year, -// res.season, -// res.episode, -// callback, -// ) -// }, - { - if (!res.isAnime) invokeCodexmovies( - codexMoviesAPI, - "CodexMovies", - res.title, - res.year, - res.season, - res.episode, - callback, - "Basic Y29kZXg6Y29kZXhjbG91ZA==" - ) - }, - { - if (!res.isAnime) invokeEdithxmovies( - edithxMoviesAPI, - "EdithxMovies", - res.title, - res.year, - res.season, - res.episode, - callback, - "Basic ZWRpdGg6amFydmlz" - ) - }, { invokeDahmerMovies( res.title, @@ -727,28 +613,14 @@ open class SoraStream : TmdbProvider() { invokeGomovies(res.title, res.year, res.season, res.episode, callback) }, // { -// if (!res.isAnime) invokeTgarMovies(res.title, res.year, res.season, res.episode, callback) +// if (!res.isAnime) invokeGdbotMovies( +// res.title, +// res.year, +// res.season, +// res.episode, +// callback +// ) // }, - { - if (!res.isAnime) invokeGdbotMovies( - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, - { - if (!res.isAnime) invokeJmdkhMovies( - jmdkhMovieAPI, - "JmdkhMovies", - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, { if (!res.isAnime) invokeShinobiMovies( shinobiMovieAPI, @@ -760,28 +632,6 @@ open class SoraStream : TmdbProvider() { callback ) }, - { - if (!res.isAnime) invokeRubyMovies( - rubyMovieAPI, - "RubyMovies", - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, - { - if (!res.isAnime) invokeVitoenMovies( - vitoenMovieAPI, - "VitoenMovies", - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, { if (!res.isAnime) invokeAsk4Movies( res.title, @@ -803,15 +653,6 @@ open class SoraStream : TmdbProvider() { callback ) }, - { - if (!res.isAnime) invokeShivamhw( - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, { if (!res.isAnime && res.season == null) invokeCryMovies( res.imdbId, From 92475c077b91578d484a8c0b4b108ca7ea77b12d Mon Sep 17 00:00:00 2001 From: sora Date: Wed, 9 Aug 2023 23:30:29 +0700 Subject: [PATCH 055/105] added ZippyShare --- Nekopoi/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 32 +++++++++++++++++++ .../src/main/kotlin/com/hexated/Nekopoi.kt | 19 +++++------ .../main/kotlin/com/hexated/NekopoiPlugin.kt | 1 + .../src/main/kotlin/com/hexated/SoraStream.kt | 2 -- 5 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 Nekopoi/src/main/kotlin/com/hexated/Extractors.kt diff --git a/Nekopoi/build.gradle.kts b/Nekopoi/build.gradle.kts index a8c9601a..1d430492 100644 --- a/Nekopoi/build.gradle.kts +++ b/Nekopoi/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/Nekopoi/src/main/kotlin/com/hexated/Extractors.kt b/Nekopoi/src/main/kotlin/com/hexated/Extractors.kt new file mode 100644 index 00000000..47e90c61 --- /dev/null +++ b/Nekopoi/src/main/kotlin/com/hexated/Extractors.kt @@ -0,0 +1,32 @@ +package com.hexated + +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities + +open class ZippyShare : ExtractorApi() { + override val name = "ZippyShare" + override val mainUrl = "https://zippysha.re" + override val requiresReferer = true + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val res = app.get(url, referer = referer).document + val video = res.selectFirst("a#download-url")?.attr("href") + callback.invoke( + ExtractorLink( + this.name, + this.name, + video ?: return, + "$mainUrl/", + Qualities.Unknown.value + ) + ) + } +} \ No newline at end of file diff --git a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt index 27ecc2e8..f4721169 100644 --- a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt +++ b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt @@ -4,6 +4,7 @@ import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.utils.* import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.Session +import kotlinx.coroutines.delay import org.jsoup.nodes.Element import java.net.URI @@ -24,7 +25,6 @@ class Nekopoi : MainAPI() { "DropApk", "Racaty", "ZippyShare", - "ZippySha", "VideobinCo", "DropApk", "SendCm", @@ -227,16 +227,15 @@ class Nekopoi : MainAPI() { } private suspend fun bypassMirrored(url: String?): List { - val request = app.get(url ?: return emptyList()) - var nextUrl = request.document.selectFirst("div.row div.centered a")?.attr("href") - nextUrl = app.get(nextUrl ?: return emptyList()).text.substringAfter("\"GET\", \"") - .substringBefore("\"") - return app.get(fixUrl(nextUrl, mirroredHost)).document.select("table.hoverable tbody tr") + val request = session.get(url ?: return emptyList()) + delay(2000) + val nextUrl = request.text.substringAfter("\"GET\", \"").substringBefore("\"") + return session.get(fixUrl(nextUrl, mirroredHost)).document.select("table.hoverable tbody tr") .filter { mirror -> !mirrorIsBlackList(mirror.selectFirst("img")?.attr("alt")) }.apmap { val fileLink = it.selectFirst("a")?.attr("href") - app.get( + session.get( fixUrl( fileLink ?: return@apmap null, mirroredHost @@ -269,8 +268,10 @@ class Nekopoi : MainAPI() { } private fun getIndexQuality(str: String?): Int { - return Regex("(\\d{3,4})[pP]").find(str ?: "")?.groupValues?.getOrNull(1)?.toIntOrNull() - ?: Qualities.Unknown.value + return when (val quality = Regex("""(?i)\[(\d+[pk])]""").find(str ?: "")?.groupValues?.getOrNull(1)?.lowercase()) { + "2k" -> Qualities.P1440.value + else -> getQualityFromName(quality) + } } } \ No newline at end of file diff --git a/Nekopoi/src/main/kotlin/com/hexated/NekopoiPlugin.kt b/Nekopoi/src/main/kotlin/com/hexated/NekopoiPlugin.kt index a6fe53a3..62dea5a4 100644 --- a/Nekopoi/src/main/kotlin/com/hexated/NekopoiPlugin.kt +++ b/Nekopoi/src/main/kotlin/com/hexated/NekopoiPlugin.kt @@ -9,5 +9,6 @@ class NekopoiPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(Nekopoi()) + registerExtractorAPI(ZippyShare()) } } \ 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 88efd8de..e52f5b61 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -11,7 +11,6 @@ import com.hexated.SoraExtractor.invokeHDMovieBox import com.hexated.SoraExtractor.invokeIdlix import com.hexated.SoraExtractor.invokeKimcartoon import com.hexated.SoraExtractor.invokeMovieHab -import com.hexated.SoraExtractor.invokeNoverse import com.hexated.SoraExtractor.invokeSeries9 import com.hexated.SoraExtractor.invokeVidSrc import com.lagradost.cloudstream3.* @@ -25,7 +24,6 @@ import com.hexated.SoraExtractor.invokeFlixon import com.hexated.SoraExtractor.invokeFmovies import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeGMovies -import com.hexated.SoraExtractor.invokeGdbotMovies import com.hexated.SoraExtractor.invokeGoku import com.hexated.SoraExtractor.invokeGomovies import com.hexated.SoraExtractor.invokeKisskh From 0e3f20c251ddca0eab3147952657089bf710bc3e Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 11 Aug 2023 01:40:02 +0700 Subject: [PATCH 056/105] sora/sync:added tmdb/imdb id --- SoraStream/build.gradle.kts | 2 +- SoraStream/src/main/kotlin/com/hexated/SoraStream.kt | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index a26c71b5..b579a1b1 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 = 155 +version = 156 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index e52f5b61..3d27c454 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -50,7 +50,10 @@ import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeWatchOnline import com.hexated.SoraExtractor.invokeWatchsomuch +import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId +import com.lagradost.cloudstream3.LoadResponse.Companion.addTMDbId import com.lagradost.cloudstream3.extractors.VidSrcExtractor +import com.lagradost.cloudstream3.syncproviders.SyncIdName import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink @@ -112,7 +115,7 @@ open class SoraStream : TmdbProvider() { const val ask4MoviesAPI = "https://ask4movie.nl" const val biliBiliAPI = "https://api-vn.otakuz.live/server" const val watchOnlineAPI = "https://watchonline.ag" - const val nineTvAPI = "https://api.9animetv.live" + const val nineTvAPI = "https://moviesapi.club" const val putlockerAPI = "https://ww7.putlocker.vip" const val fmoviesAPI = "https://fmovies.to" const val nowTvAPI = "https://myfilestorage.xyz" @@ -310,6 +313,8 @@ open class SoraStream : TmdbProvider() { this.recommendations = recommendations this.actors = actors addTrailer(trailer) + addTMDbId(data.id.toString()) + addImdbId(res.external_ids?.imdb_id) } } else { newMovieLoadResponse( @@ -339,6 +344,8 @@ open class SoraStream : TmdbProvider() { this.recommendations = recommendations this.actors = actors addTrailer(trailer) + addTMDbId(data.id.toString()) + addImdbId(res.external_ids?.imdb_id) } } } From a0fa64bd7b97dde2cfd6b6c0a82902e7e6177baf Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 11 Aug 2023 04:04:54 +0700 Subject: [PATCH 057/105] small fix --- Nekopoi/build.gradle.kts | 2 +- Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Nekopoi/build.gradle.kts b/Nekopoi/build.gradle.kts index 1d430492..0d3c4901 100644 --- a/Nekopoi/build.gradle.kts +++ b/Nekopoi/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt index f4721169..f0b8d55f 100644 --- a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt +++ b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt @@ -13,7 +13,7 @@ class Nekopoi : MainAPI() { override var name = "Nekopoi" override val hasMainPage = true override var lang = "id" - + private val fetch by lazy { Session(app.baseClient) } override val supportedTypes = setOf( TvType.NSFW, ) @@ -53,7 +53,7 @@ class Nekopoi : MainAPI() { page: Int, request: MainPageRequest ): HomePageResponse { - val document = app.get("${request.data}/page/$page").document + val document = fetch.get("${request.data}/page/$page").document val home = document.select("div.result ul li").mapNotNull { it.toSearchResult() } @@ -90,14 +90,14 @@ class Nekopoi : MainAPI() { } override suspend fun search(query: String): List { - return app.get("$mainUrl/search/$query").document.select("div.result ul li") + return fetch.get("$mainUrl/search/$query").document.select("div.result ul li") .mapNotNull { it.toSearchResult() } } override suspend fun load(url: String): LoadResponse { - val document = app.get(url).document + val document = fetch.get(url).document val title = document.selectFirst("span.desc b, div.eroinfo h1")?.text()?.trim() ?: "" val poster = fixUrlNull(document.selectFirst("div.imgdesc img, div.thm img")?.attr("src")) @@ -141,7 +141,7 @@ class Nekopoi : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { - val res = app.get(data).document + val res = fetch.get(data).document argamap( { From a4bee8ffdf40bb294eb9f4094d5535a38c14d93f Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 11 Aug 2023 06:39:15 +0700 Subject: [PATCH 058/105] added KissasianMx & updated Oploverz domain --- Kissasian/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Kissasian.kt | 26 +++++---- .../main/kotlin/com/hexated/KissasianMx.kt | 58 +++++++++++++++++++ .../kotlin/com/hexated/KissasianPlugin.kt | 2 + .../src/main/kotlin/com/hexated/Nekopoi.kt | 25 ++++++-- OploverzProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/OploverzProvider.kt | 2 +- 7 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 Kissasian/src/main/kotlin/com/hexated/KissasianMx.kt diff --git a/Kissasian/build.gradle.kts b/Kissasian/build.gradle.kts index a81930da..8f461916 100644 --- a/Kissasian/build.gradle.kts +++ b/Kissasian/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { diff --git a/Kissasian/src/main/kotlin/com/hexated/Kissasian.kt b/Kissasian/src/main/kotlin/com/hexated/Kissasian.kt index eab56061..0d70fda2 100644 --- a/Kissasian/src/main/kotlin/com/hexated/Kissasian.kt +++ b/Kissasian/src/main/kotlin/com/hexated/Kissasian.kt @@ -1,13 +1,14 @@ package com.hexated import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.extractors.Filesim import com.lagradost.cloudstream3.extractors.helper.GogoHelper import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.httpsify import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element -class Kissasian : MainAPI() { +open class Kissasian : MainAPI() { override var mainUrl = "https://kissasian.pe" override var name = "Kissasian" override val hasMainPage = true @@ -44,8 +45,7 @@ class Kissasian : MainAPI() { private fun Element.toSearchResult(): SearchResponse? { val href = fixUrl(this.selectFirst("a")?.attr("href") ?: return null) val title = this.selectFirst("span.title")?.text()?.trim() ?: return null - val posterUrl = fixUrlNull(this.selectFirst("div.pic img")?.attr("src")) - + val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) return newTvSeriesSearchResponse(title, href, TvType.AsianDrama) { this.posterUrl = posterUrl } @@ -58,18 +58,19 @@ class Kissasian : MainAPI() { } } + open val contentInfoClass = "barContentInfo" override suspend fun load(url: String): LoadResponse? { val document = app.get(url).document - val title = document.selectFirst("div.barContentInfo a")?.text()?.trim() ?: return null - val poster = fixUrlNull(document.selectFirst("div.barContentInfo img")?.attr("src")) - val tags = document.select("div.barContentInfo p:contains(Genres:) a").map { it.text().removePrefix(",").trim() } + val title = document.selectFirst("div.$contentInfoClass a")?.text()?.trim() ?: return null + val poster = fixUrlNull(document.select("div.$contentInfoClass img").last()?.attr("src")) + val tags = document.select("div.$contentInfoClass p:contains(Genres:) a").map { it.text().removePrefix(",").trim() } - val year = document.selectFirst("div.barContentInfo p.type.Releasea")?.text()?.trim()?.toIntOrNull() - val status = getStatus(document.selectFirst("div.barContentInfo p:contains(Status:)")?.ownText()?.trim()) - val description = document.selectFirst("div.barContentInfo p.des")?.nextElementSiblings()?.select("p")?.text() + val year = document.selectFirst("div.$contentInfoClass p.type.Releasea")?.text()?.trim()?.toIntOrNull() + val status = getStatus(document.selectFirst("div.$contentInfoClass p:contains(Status:)")?.ownText()?.trim()) + val description = document.selectFirst("div.$contentInfoClass p.des, div.$contentInfoClass p:last-child")?.nextElementSiblings()?.select("p")?.text() - val episodes = document.select("ul.listing li").map { + val episodes = document.select("ul.listing li, table.listing td.episodeSub").map { val name = it.selectFirst("a")?.attr("title") val link = fixUrlNull(it.selectFirst("a")?.attr("href")) val epNum = Regex("Episode\\s(\\d+)").find("$name")?.groupValues?.getOrNull(1)?.toIntOrNull() @@ -138,3 +139,8 @@ class Kissasian : MainAPI() { } } + +class Kswplayer : Filesim() { + override val name = "Kswplayer" + override var mainUrl = "https://kswplayer.info" +} diff --git a/Kissasian/src/main/kotlin/com/hexated/KissasianMx.kt b/Kissasian/src/main/kotlin/com/hexated/KissasianMx.kt new file mode 100644 index 00000000..ede3dd86 --- /dev/null +++ b/Kissasian/src/main/kotlin/com/hexated/KissasianMx.kt @@ -0,0 +1,58 @@ +package com.hexated + +import com.lagradost.cloudstream3.SearchResponse +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.TvType +import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.fixUrl +import com.lagradost.cloudstream3.mainPageOf +import com.lagradost.cloudstream3.newTvSeriesSearchResponse +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor + +class KissasianMx : Kissasian() { + override var mainUrl = "https://kissasian.mx" + override var name = "KissasianMx" + override val contentInfoClass = "barContent" + override val mainPage = mainPageOf( + "Status/Ongoing?page=" to "Drama Ongoing", + "Status/Completed?page=" to "Drama Completed", + "Status/Completed?page=" to "Drama Completed", + "Genre/Romance?page=" to "Drama Romance", + "Genre/Reality-TV?page=" to "Reality-TV", + "Genre/Mystery?page=" to "Drama Mystery", + "Genre/Movie?page=" to "Movie", + ) + + override suspend fun search(query: String): List { + val document = app.post( + "$mainUrl/Search/SearchSuggest", data = mapOf( + "type" to "Drama", + "keyword" to query, + ), headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ).document + return document.select("a").mapNotNull { + val href = fixUrl(it.attr("href")) + val title = it.text() + newTvSeriesSearchResponse(title, href, TvType.AsianDrama) + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + val document = app.get(data).document + document.select("select#selectServer option").apmap { + val server = it.attr("value") + val iframe = app.get(fixUrl(server ?: return@apmap)).document.selectFirst("div#centerDivVideo iframe")?.attr("src") + loadExtractor(iframe ?: return@apmap, "$mainUrl/", subtitleCallback, callback) + } + + return true + } +} \ No newline at end of file diff --git a/Kissasian/src/main/kotlin/com/hexated/KissasianPlugin.kt b/Kissasian/src/main/kotlin/com/hexated/KissasianPlugin.kt index 932e9fc8..0fd3e446 100644 --- a/Kissasian/src/main/kotlin/com/hexated/KissasianPlugin.kt +++ b/Kissasian/src/main/kotlin/com/hexated/KissasianPlugin.kt @@ -10,5 +10,7 @@ class KissasianPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(Kissasian()) + registerMainAPI(KissasianMx()) + registerExtractorAPI(Kswplayer()) } } \ No newline at end of file diff --git a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt index f0b8d55f..c9a00826 100644 --- a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt +++ b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt @@ -2,6 +2,7 @@ package com.hexated import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.utils.* +import com.lagradost.nicehttp.NiceResponse import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.Session import kotlinx.coroutines.delay @@ -169,7 +170,7 @@ class Nekopoi : MainAPI() { link.name, link.url, link.referer, - if(link.isM3u8) link.quality else it.first, + if (link.isM3u8) link.quality else it.first, link.isM3u8, link.headers, link.extractorData @@ -226,11 +227,24 @@ class Nekopoi : MainAPI() { return res.headers["location"] } + private fun NiceResponse.selectMirror(): String? { + return this.document.selectFirst("script:containsData(#passcheck)")?.data() + ?.substringAfter("\"GET\", \"")?.substringBefore("\"") + } + private suspend fun bypassMirrored(url: String?): List { val request = session.get(url ?: return emptyList()) delay(2000) - val nextUrl = request.text.substringAfter("\"GET\", \"").substringBefore("\"") - return session.get(fixUrl(nextUrl, mirroredHost)).document.select("table.hoverable tbody tr") + val mirrorUrl = request.selectMirror() ?: run { + val nextUrl = request.document.select("div.col-sm.centered.extra-top a").attr("href") + app.get(nextUrl).selectMirror() + } + return session.get( + fixUrl( + mirrorUrl ?: return emptyList(), + mirroredHost + ) + ).document.select("table.hoverable tbody tr") .filter { mirror -> !mirrorIsBlackList(mirror.selectFirst("img")?.attr("alt")) }.apmap { @@ -244,7 +258,7 @@ class Nekopoi : MainAPI() { } } - private fun mirrorIsBlackList(host: String?) : Boolean { + private fun mirrorIsBlackList(host: String?): Boolean { return mirrorBlackList.any { it.equals(host, true) } } @@ -268,7 +282,8 @@ class Nekopoi : MainAPI() { } private fun getIndexQuality(str: String?): Int { - return when (val quality = Regex("""(?i)\[(\d+[pk])]""").find(str ?: "")?.groupValues?.getOrNull(1)?.lowercase()) { + return when (val quality = + Regex("""(?i)\[(\d+[pk])]""").find(str ?: "")?.groupValues?.getOrNull(1)?.lowercase()) { "2k" -> Qualities.P1440.value else -> getQualityFromName(quality) } diff --git a/OploverzProvider/build.gradle.kts b/OploverzProvider/build.gradle.kts index 49f2737c..036ff106 100644 --- a/OploverzProvider/build.gradle.kts +++ b/OploverzProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 20 +version = 21 cloudstream { diff --git a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt index 95d5bcab..26cac833 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt @@ -6,7 +6,7 @@ import com.lagradost.cloudstream3.utils.* import org.jsoup.nodes.Element class OploverzProvider : MainAPI() { - override var mainUrl = "https://oploverz.care" + override var mainUrl = "https://oploverz.team" override var name = "Oploverz" override val hasMainPage = true override var lang = "id" From ed82b78f9b099fd09753b11466cfa8f72da625a5 Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 11 Aug 2023 06:40:50 +0700 Subject: [PATCH 059/105] update desc --- Kissasian/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Kissasian/build.gradle.kts b/Kissasian/build.gradle.kts index 8f461916..03d38561 100644 --- a/Kissasian/build.gradle.kts +++ b/Kissasian/build.gradle.kts @@ -6,7 +6,7 @@ cloudstream { language = "en" // All of these properties are optional, you can safely remove them - // description = "Lorem Ipsum" + description = "Include: KissasianMx" authors = listOf("Hexated") /** From 5a35077a4f457426b18c071c429767e4d9f23dcb Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 11 Aug 2023 20:22:36 +0700 Subject: [PATCH 060/105] StremioX & StremioC: added imdb id --- StremioX/build.gradle.kts | 2 +- StremioX/src/main/kotlin/com/hexated/StremioC.kt | 13 ++++++++----- StremioX/src/main/kotlin/com/hexated/StremioX.kt | 12 ++++++++++-- StremioX/src/main/kotlin/com/hexated/Utils.kt | 10 ++++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/StremioX/build.gradle.kts b/StremioX/build.gradle.kts index 5e6b7146..3366ed71 100644 --- a/StremioX/build.gradle.kts +++ b/StremioX/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 9 +version = 10 cloudstream { diff --git a/StremioX/src/main/kotlin/com/hexated/StremioC.kt b/StremioX/src/main/kotlin/com/hexated/StremioC.kt index 9c766240..4d972d31 100644 --- a/StremioX/src/main/kotlin/com/hexated/StremioC.kt +++ b/StremioX/src/main/kotlin/com/hexated/StremioC.kt @@ -5,6 +5,7 @@ import com.hexated.SubsExtractors.invokeOpenSubs import com.hexated.SubsExtractors.invokeWatchsomuch import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addActors +import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.parseJson @@ -27,7 +28,7 @@ class StremioC : MainAPI() { val res = tryParseJson(request("${mainUrl}/manifest.json").body.string()) ?: return null val lists = mutableListOf() res.catalogs.apmap { catalog -> - catalog.toHomePageList(this)?.let { + catalog.toHomePageList(this).let { if (it.list.isNotEmpty()) lists.add(it) } } @@ -47,7 +48,7 @@ class StremioC : MainAPI() { return list.distinct() } - override suspend fun load(url: String): LoadResponse? { + override suspend fun load(url: String): LoadResponse { val res = parseJson(url) mainUrl = if ((res.type == "movie" || res.type == "series") && isImdborTmdb(res.id)) cinemataUrl else mainUrl @@ -161,7 +162,7 @@ class StremioC : MainAPI() { return entries } - suspend fun toHomePageList(provider: StremioC): HomePageList? { + suspend fun toHomePageList(provider: StremioC): HomePageList { val entries = mutableListOf() types.forEach { type -> val json = request("${provider.mainUrl}/catalog/${type}/${id}.json").body.string() @@ -211,7 +212,7 @@ class StremioC : MainAPI() { } suspend fun toLoadResponse(provider: StremioC, imdbId: String?): LoadResponse { - if (videos == null || videos.isEmpty()) { + if (videos.isNullOrEmpty()) { return provider.newMovieLoadResponse( name, "${provider.mainUrl}/meta/${type}/${id}.json", @@ -226,6 +227,7 @@ class StremioC : MainAPI() { tags = genre ?: genres addActors(cast) addTrailer(trailersSources?.map { "https://www.youtube.com/watch?v=${it.source}" }?.randomOrNull()) + addImdbId(imdbId) } } else { return provider.newTvSeriesLoadResponse( @@ -244,6 +246,7 @@ class StremioC : MainAPI() { tags = genre ?: genres addActors(cast) addTrailer(trailersSources?.map { "https://www.youtube.com/watch?v=${it.source}" }?.randomOrNull()) + addImdbId(imdbId) } } @@ -337,7 +340,7 @@ class StremioC : MainAPI() { val resp = app.get(TRACKER_LIST_URL).text val otherTrackers = resp .split("\n") - .filterIndexed { i, s -> i % 2 == 0 } + .filterIndexed { i, _ -> i % 2 == 0 } .filter { s -> s.isNotEmpty() }.joinToString("") { "&tr=$it" } val sourceTrackers = sources diff --git a/StremioX/src/main/kotlin/com/hexated/StremioX.kt b/StremioX/src/main/kotlin/com/hexated/StremioX.kt index 339c5277..7f2419fe 100644 --- a/StremioX/src/main/kotlin/com/hexated/StremioX.kt +++ b/StremioX/src/main/kotlin/com/hexated/StremioX.kt @@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.hexated.SubsExtractors.invokeOpenSubs import com.hexated.SubsExtractors.invokeWatchsomuch import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId +import com.lagradost.cloudstream3.LoadResponse.Companion.addTMDbId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.parseJson @@ -123,7 +125,8 @@ open class StremioX : MainAPI() { val title = res.title ?: res.name ?: return null val poster = getOriImageUrl(res.posterPath) val bgPoster = getOriImageUrl(res.backdropPath) - val year = (res.releaseDate ?: res.firstAirDate)?.split("-")?.first()?.toIntOrNull() + val releaseDate = res.releaseDate ?: res.firstAirDate + val year = releaseDate?.split("-")?.first()?.toIntOrNull() val rating = res.vote_average.toString().toRatingInt() val genres = res.genres?.mapNotNull { it.name } val isAnime = @@ -155,7 +158,7 @@ open class StremioX : MainAPI() { eps.seasonNumber, eps.episodeNumber ).toJson(), - name = eps.name, + name = eps.name + if (isUpcoming(eps.airDate)) " - [UPCOMING]" else "", season = eps.seasonNumber, episode = eps.episodeNumber, posterUrl = getImageUrl(eps.stillPath), @@ -179,6 +182,8 @@ open class StremioX : MainAPI() { this.recommendations = recommendations this.actors = actors addTrailer(trailer) + addTMDbId(data.id.toString()) + addImdbId(res.external_ids?.imdb_id) } } else { newMovieLoadResponse( @@ -188,6 +193,7 @@ open class StremioX : MainAPI() { LoadData(res.external_ids?.imdb_id).toJson() ) { this.posterUrl = poster + this.comingSoon = isUpcoming(releaseDate) this.backgroundPosterUrl = bgPoster this.year = year this.plot = res.overview @@ -197,6 +203,8 @@ open class StremioX : MainAPI() { this.recommendations = recommendations this.actors = actors addTrailer(trailer) + addTMDbId(data.id.toString()) + addImdbId(res.external_ids?.imdb_id) } } } diff --git a/StremioX/src/main/kotlin/com/hexated/Utils.kt b/StremioX/src/main/kotlin/com/hexated/Utils.kt index e75201fd..a75987a5 100644 --- a/StremioX/src/main/kotlin/com/hexated/Utils.kt +++ b/StremioX/src/main/kotlin/com/hexated/Utils.kt @@ -1,9 +1,12 @@ package com.hexated +import com.lagradost.cloudstream3.APIHolder import com.lagradost.nicehttp.Requests.Companion.await import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response +import java.text.SimpleDateFormat +import java.util.Locale import java.util.concurrent.TimeUnit const val defaultTimeOut = 30L @@ -54,6 +57,13 @@ fun getEpisodeSlug( } } +fun isUpcoming(dateString: String?): Boolean { + if (dateString == null) return false + val format = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) + val dateTime = format.parse(dateString)?.time ?: return false + return APIHolder.unixTimeMS < dateTime +} + fun fixUrl(url: String, domain: String): String { if (url.startsWith("http")) { return url From 017d861b00dd30453283f5e747bddcdf6248214f Mon Sep 17 00:00:00 2001 From: helo Date: Sat, 12 Aug 2023 08:02:14 +0700 Subject: [PATCH 061/105] Otakudesu: added more servers --- OtakudesuProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/OtakudesuProvider.kt | 181 ++++++++++++------ .../com/hexated/OtakudesuProviderPlugin.kt | 1 + 3 files changed, 120 insertions(+), 64 deletions(-) diff --git a/OtakudesuProvider/build.gradle.kts b/OtakudesuProvider/build.gradle.kts index 5e05690f..2f4a7f48 100644 --- a/OtakudesuProvider/build.gradle.kts +++ b/OtakudesuProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 12 +version = 13 cloudstream { diff --git a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt index 761b5d62..3bc73926 100644 --- a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt +++ b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt @@ -5,6 +5,7 @@ import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.extractors.JWPlayer import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.Jsoup import org.jsoup.nodes.Element @@ -23,7 +24,12 @@ class OtakudesuProvider : MainAPI() { ) companion object { - // private val interceptor = CloudflareKiller() + const val acefile = "https://acefile.co" + val mirrorBlackList = arrayOf( + "Mega", + "MegaUp", + "Otakufiles", + ) fun getType(t: String): TvType { return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA else if (t.contains("Movie", true)) TvType.AnimeMovie @@ -48,10 +54,7 @@ class OtakudesuProvider : MainAPI() { page: Int, request: MainPageRequest ): HomePageResponse { - val document = app.get( - request.data + page -// , interceptor = interceptor - ).document + val document = app.get(request.data + page).document val home = document.select("div.venz > ul > li").mapNotNull { it.toSearchResult() } @@ -67,35 +70,25 @@ class OtakudesuProvider : MainAPI() { return newAnimeSearchResponse(title, href, TvType.Anime) { this.posterUrl = posterUrl addSub(epNum) -// posterHeaders = interceptor.getCookieHeaders(url).toMap() } } override suspend fun search(query: String): List { - val link = "$mainUrl/?s=$query&post_type=anime" - val document = app.get( - link -// , interceptor = interceptor - ).document - - return document.select("ul.chivsrc > li").map { - val title = it.selectFirst("h2 > a")!!.ownText().trim() - val href = it.selectFirst("h2 > a")!!.attr("href") - val posterUrl = it.selectFirst("img")!!.attr("src").toString() - newAnimeSearchResponse(title, href, TvType.Anime) { - this.posterUrl = posterUrl -// posterHeaders = interceptor.getCookieHeaders(url).toMap() + return app.get("$mainUrl/?s=$query&post_type=anime").document.select("ul.chivsrc > li") + .map { + val title = it.selectFirst("h2 > a")!!.ownText().trim() + val href = it.selectFirst("h2 > a")!!.attr("href") + val posterUrl = it.selectFirst("img")!!.attr("src").toString() + newAnimeSearchResponse(title, href, TvType.Anime) { + this.posterUrl = posterUrl + } } - } } override suspend fun load(url: String): LoadResponse { - val document = app.get( - url -// , interceptor = interceptor - ).document + val document = app.get(url).document val title = document.selectFirst("div.infozingle > p:nth-child(1) > span")?.ownText() ?.replace(":", "")?.trim().toString() @@ -129,7 +122,6 @@ class OtakudesuProvider : MainAPI() { val recPosterUrl = it.selectFirst("a > img")?.attr("src").toString() newAnimeSearchResponse(recName, recHref, TvType.Anime) { this.posterUrl = recPosterUrl -// posterHeaders = interceptor.getCookieHeaders(url).toMap() } } @@ -142,7 +134,6 @@ class OtakudesuProvider : MainAPI() { plot = description this.tags = tags this.recommendations = recommendations -// posterHeaders = interceptor.getCookieHeaders(url).toMap() } } @@ -164,59 +155,123 @@ class OtakudesuProvider : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { - val document = app.get( - data -// , interceptor = interceptor - ).document - val scriptData = document.select("script:containsData(action:)").lastOrNull()?.data() - val token = scriptData?.substringAfter("{action:\"")?.substringBefore("\"}").toString() + val document = app.get(data).document - val nonce = app.post("$mainUrl/wp-admin/admin-ajax.php", data = mapOf("action" to token)) - .parsed().data - val action = scriptData?.substringAfter(",action:\"")?.substringBefore("\"}").toString() + argamap( + { + val scriptData = + document.select("script:containsData(action:)").lastOrNull()?.data() + val token = + scriptData?.substringAfter("{action:\"")?.substringBefore("\"}").toString() - val mirrorData = document.select("div.mirrorstream > ul > li").mapNotNull { - base64Decode(it.select("a").attr("data-content")) - }.toString() + val nonce = + app.post("$mainUrl/wp-admin/admin-ajax.php", data = mapOf("action" to token)) + .parsed().data + val action = + scriptData?.substringAfter(",action:\"")?.substringBefore("\"}").toString() - tryParseJson>(mirrorData)?.apmap { res -> - val id = res.id - val i = res.i - val q = res.q + val mirrorData = document.select("div.mirrorstream > ul > li").mapNotNull { + base64Decode(it.select("a").attr("data-content")) + }.toString() - var sources = Jsoup.parse( - base64Decode( - app.post( - "${mainUrl}/wp-admin/admin-ajax.php", data = mapOf( - "id" to id, - "i" to i, - "q" to q, - "nonce" to nonce, - "action" to action + tryParseJson>(mirrorData)?.apmap { res -> + val id = res.id + val i = res.i + val q = res.q + + val sources = Jsoup.parse( + base64Decode( + app.post( + "${mainUrl}/wp-admin/admin-ajax.php", data = mapOf( + "id" to id, + "i" to i, + "q" to q, + "nonce" to nonce, + "action" to action + ) + ).parsed().data ) - ).parsed().data - ) - ).select("iframe").attr("src") + ).select("iframe").attr("src") + + loadCustomExtractor(sources, data, subtitleCallback, callback, getQuality(q)) - if (sources.startsWith("https://desustream.me")) { - if (!sources.contains(Regex("/arcg/|/odchan/|/desudrive/|/moedesu/"))) { - sources = app.get(sources).document.select("iframe").attr("src") } - if (sources.startsWith("https://yourupload.com")) { - sources = sources.replace("//", "//www.") + }, + { + document.select("div.download li").map { ele -> + val quality = getQuality(ele.select("strong").text()) + ele.select("a").map { + it.attr("href") to it.text() + }.filter { + !inBlacklist(it.first) && quality != Qualities.P360.value + }.apmap { + val link = app.get(it.first, referer = "$mainUrl/").url + loadCustomExtractor( + fixedIframe(link), + data, + subtitleCallback, + callback, + quality + ) + } } } - - loadExtractor(sources, data, subtitleCallback, callback) - - } + ) return true } + private suspend fun loadCustomExtractor( + url: String, + referer: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, + quality: Int = Qualities.Unknown.value, + ) { + loadExtractor(url, referer, subtitleCallback) { link -> + callback.invoke( + ExtractorLink( + link.name, + link.name, + link.url, + link.referer, + quality, + link.isM3u8, + link.headers, + link.extractorData + ) + ) + } + } + + private fun fixedIframe(url: String): String { + return when { + url.startsWith(acefile) -> { + val id = Regex("""(?:/f/|/file/)(\w+)""").find(url)?.groupValues?.getOrNull(1) + "${acefile}/player/$id" + } + + else -> fixUrl(url) + } + } + + private fun inBlacklist(host: String?): Boolean { + return mirrorBlackList.any { it.equals(host, true) } + } + + private fun getQuality(str: String?): Int { + return Regex("(\\d{3,4})[pP]").find(str ?: "")?.groupValues?.getOrNull(1)?.toIntOrNull() + ?: Qualities.Unknown.value + } + } class Moedesu : JWPlayer() { override val name = "Moedesu" override val mainUrl = "https://desustream.me/moedesu/" +} + +class DesuBeta : JWPlayer() { + override val name = "DesuBeta" + override val mainUrl = "https://desustream.me/beta/" } \ No newline at end of file diff --git a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProviderPlugin.kt b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProviderPlugin.kt index ccac8600..462f0bee 100644 --- a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProviderPlugin.kt +++ b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProviderPlugin.kt @@ -11,5 +11,6 @@ class OtakudesuProviderPlugin: Plugin() { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(OtakudesuProvider()) registerExtractorAPI(Moedesu()) + registerExtractorAPI(DesuBeta()) } } \ No newline at end of file From 8a61d0891e9f0843b924765e83dc0503f3dfed77 Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 13 Aug 2023 00:42:08 +0700 Subject: [PATCH 062/105] Anichi: added lib/sync support --- Anichi/build.gradle.kts | 2 +- Anichi/src/main/kotlin/com/hexated/Anichi.kt | 27 +++++++++++++++++++ .../kotlin/com/hexated/AnichiExtractors.kt | 2 +- .../main/kotlin/com/hexated/AnichiParser.kt | 25 +++++++++++++++++ .../main/kotlin/com/hexated/AnichiUtils.kt | 11 +++++++- 5 files changed, 64 insertions(+), 3 deletions(-) diff --git a/Anichi/build.gradle.kts b/Anichi/build.gradle.kts index dcc2cb7b..c04dac6b 100644 --- a/Anichi/build.gradle.kts +++ b/Anichi/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.konan.properties.Properties // use an integer for version numbers -version = 7 +version = 8 android { defaultConfig { diff --git a/Anichi/src/main/kotlin/com/hexated/Anichi.kt b/Anichi/src/main/kotlin/com/hexated/Anichi.kt index 01c161d1..bbad3ae7 100644 --- a/Anichi/src/main/kotlin/com/hexated/Anichi.kt +++ b/Anichi/src/main/kotlin/com/hexated/Anichi.kt @@ -7,6 +7,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.syncproviders.SyncIdName import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.nicehttp.RequestBodyTypes @@ -27,6 +28,7 @@ open class Anichi : MainAPI() { } } + override val supportedSyncNames = setOf(SyncIdName.Anilist, SyncIdName.MyAnimeList) override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie) private val popularTitle = "Popular" @@ -110,6 +112,29 @@ open class Anichi : MainAPI() { } } + override suspend fun getLoadUrl(name: SyncIdName, id: String): String? { + val syncId = id.split("/").last() + val malId = if (name == SyncIdName.MyAnimeList) { + syncId + } else { + aniToMal(syncId) + } + + val media = app.get("$jikanApi/anime/$malId").parsedSafe()?.data + val link = + """$apiUrl?variables={"search":{"allowAdult":false,"allowUnknown":false,"query":"${media?.title}"},"limit":26,"page":1,"translationType":"sub","countryOrigin":"ALL"}&extensions={"persistedQuery":{"version":1,"sha256Hash":"$mainHash"}}""" + val res = app.get( + link, + headers = headers + ).parsedSafe()?.data?.shows?.edges + return res?.find { + (it.name.equals(media?.title, true) || it.englishName.equals( + media?.title_english, + true + ) || it.nativeName.equals(media?.title_japanese, true)) && it.airedStart?.year == media?.year + }?.Id + } + override suspend fun load(url: String): LoadResponse? { val id = url.substringAfterLast("/") @@ -218,6 +243,8 @@ open class Anichi : MainAPI() { const val serverUrl = BuildConfig.ANICHI_SERVER const val apiEndPoint = BuildConfig.ANICHI_ENDPOINT + const val anilistApi = "https://graphql.anilist.co" + const val jikanApi = "https://api.jikan.moe/v4" const val marinHost = "https://marin.moe" private const val mainHash = "e42a4466d984b2c0a2cecae5dd13aa68867f634b16ee0f17b380047d14482406" diff --git a/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt b/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt index d5811278..86d452ed 100644 --- a/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt +++ b/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt @@ -69,7 +69,7 @@ object AnichiExtractors : Anichi() { links.forEach { server -> val host = server.link.getHost() when { - source.sourceName == "Default" -> { + source.sourceName?.contains("Default") == true -> { if (server.resolutionStr == "SUB" || server.resolutionStr == "Alt vo_SUB") { getM3u8Qualities( server.link, diff --git a/Anichi/src/main/kotlin/com/hexated/AnichiParser.kt b/Anichi/src/main/kotlin/com/hexated/AnichiParser.kt index 0952180a..6cbe56ec 100644 --- a/Anichi/src/main/kotlin/com/hexated/AnichiParser.kt +++ b/Anichi/src/main/kotlin/com/hexated/AnichiParser.kt @@ -9,6 +9,31 @@ data class AnichiLoadData( val idMal: Int? = null, ) +data class JikanData( + @JsonProperty("title") val title: String? = null, + @JsonProperty("title_english") val title_english: String? = null, + @JsonProperty("title_japanese") val title_japanese: String? = null, + @JsonProperty("year") val year: Int? = null, + @JsonProperty("season") val season: String? = null, + @JsonProperty("type") val type: String? = null, +) + +data class JikanResponse( + @JsonProperty("data") val data: JikanData? = null, +) + +data class IdMal( + @JsonProperty("idMal") val idMal: String? = null, +) + +data class MediaAni( + @JsonProperty("Media") val media: IdMal? = null, +) + +data class DataAni( + @JsonProperty("data") val data: MediaAni? = null, +) + data class CoverImage( @JsonProperty("extraLarge") var extraLarge: String? = null, @JsonProperty("large") var large: String? = null, diff --git a/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt b/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt index 2c34e9f7..fb191bd1 100644 --- a/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt +++ b/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt @@ -1,5 +1,6 @@ package com.hexated +import com.hexated.Anichi.Companion.anilistApi import com.hexated.Anichi.Companion.apiEndPoint import com.lagradost.cloudstream3.Episode import com.lagradost.cloudstream3.app @@ -69,7 +70,7 @@ suspend fun fetchId(title: String?, year: Int?, season: String?, type: String?): ).toJson().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) return try { - app.post("https://graphql.anilist.co", requestBody = data) + app.post(anilistApi, requestBody = data) .parsedSafe()?.data?.Page?.media?.firstOrNull() } catch (t: Throwable) { logError(t) @@ -78,6 +79,14 @@ suspend fun fetchId(title: String?, year: Int?, season: String?, type: String?): } +suspend fun aniToMal(id: String): String? { + return app.post( + anilistApi, data = mapOf( + "query" to "{Media(id:$id,type:ANIME){idMal}}", + ) + ).parsedSafe()?.data?.media?.idMal +} + fun decode(input: String): String = URLDecoder.decode(input, "utf-8") private val embedBlackList = listOf( From 5654e312460f0ea13dbaf6d9e10401bce03440ca Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 19 Aug 2023 03:48:57 +0700 Subject: [PATCH 063/105] sora: fix UHD? --- .github/workflows/build.yml | 4 +- SoraStream/build.gradle.kts | 4 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 49 +++++++++++-------- .../src/main/kotlin/com/hexated/SoraParser.kt | 36 +------------- .../src/main/kotlin/com/hexated/SoraStream.kt | 6 +-- .../main/kotlin/com/hexated/SoraStreamLite.kt | 4 +- .../src/main/kotlin/com/hexated/SoraUtils.kt | 42 ++++++++++++---- .../kotlin/com/hexated/YomoviesProvider.kt | 2 +- 8 files changed, 71 insertions(+), 76 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3d905d0f..2ea8a425 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,7 +54,7 @@ jobs: ANICHI_SERVER: ${{ secrets.ANICHI_SERVER }} ANICHI_ENDPOINT: ${{ secrets.ANICHI_ENDPOINT }} ANICHI_APP: ${{ secrets.ANICHI_APP }} - GOMOVIES_KEY: ${{ secrets.GOMOVIES_KEY }} + PRIMEWIRE_KEY: ${{ secrets.PRIMEWIRE_KEY }} run: | cd $GITHUB_WORKSPACE/src echo SORA_API=$SORA_API >> local.properties @@ -69,7 +69,7 @@ jobs: echo ANICHI_SERVER=$ANICHI_SERVER >> local.properties echo ANICHI_ENDPOINT=$ANICHI_ENDPOINT >> local.properties echo ANICHI_APP=$ANICHI_APP >> local.properties - echo GOMOVIES_KEY=$GOMOVIES_KEY >> local.properties + echo PRIMEWIRE_KEY=$PRIMEWIRE_KEY >> local.properties - name: Build Plugins run: | diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index b579a1b1..b2614d35 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 = 156 +version = 157 android { defaultConfig { @@ -14,7 +14,7 @@ android { buildConfigField("String", "SORATED", "\"${properties.getProperty("SORATED")}\"") buildConfigField("String", "DUMP_API", "\"${properties.getProperty("DUMP_API")}\"") buildConfigField("String", "DUMP_KEY", "\"${properties.getProperty("DUMP_KEY")}\"") - buildConfigField("String", "GOMOVIES_KEY", "\"${properties.getProperty("GOMOVIES_KEY")}\"") + buildConfigField("String", "PRIMEWIRE_KEY", "\"${properties.getProperty("PRIMEWIRE_KEY")}\"") buildConfigField("String", "CRUNCHYROLL_BASIC_TOKEN", "\"${properties.getProperty("CRUNCHYROLL_BASIC_TOKEN")}\"") buildConfigField("String", "CRUNCHYROLL_REFRESH_TOKEN", "\"${properties.getProperty("CRUNCHYROLL_REFRESH_TOKEN")}\"") diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 8004b826..527338ac 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1127,13 +1127,19 @@ object SoraExtractor : SoraStream() { link ?: return@apmap ) val base = getBaseUrl(driveLink ?: return@apmap) - val resDoc = app.get(driveLink).document - val bitLink = resDoc.selectFirst("a.btn.btn-outline-success")?.attr("href") - val downloadLink = if (bitLink.isNullOrEmpty()) { - val backupIframe = resDoc.select("a.btn.btn-outline-warning").attr("href") - extractBackupUHD(backupIframe ?: return@apmap) - } else { - extractMirrorUHD(bitLink, base) + val driveReq = app.get(driveLink) + val driveRes = driveReq.document + val bitLink = driveRes.select("a.btn.btn-outline-success").attr("href") + val downloadLink = when { + driveRes.select("button.btn.btn-success").text() + .contains("Direct Download", true) -> extractDirectUHD(driveLink, driveReq) + bitLink.isNullOrEmpty() -> { + val backupIframe = driveRes.select("a.btn.btn-outline-warning").attr("href") + extractBackupUHD(backupIframe ?: return@apmap) + } + else -> { + extractMirrorUHD(bitLink, base) + } } val tags = getUhdTags(quality) @@ -2138,7 +2144,7 @@ object SoraExtractor : SoraStream() { } - suspend fun invokeGomovies( + suspend fun invokePrimewire( title: String? = null, year: Int? = null, season: Int? = null, @@ -2152,9 +2158,9 @@ object SoraExtractor : SoraStream() { "$title Season $season" } - val doc = app.get("$gomoviesAPI/search/$query").document + val doc = app.get("$primewireAPI/search/$query").document - val media = doc.select("div._gory div.g_yFsxmKnYLvpKDTrdbizeYMWy").map { + val media = doc.select("div.RvnMfoxhgm").map { Triple( it.attr("data-filmName"), it.attr("data-year"), @@ -2183,21 +2189,21 @@ object SoraExtractor : SoraStream() { app.get( fixUrl( media.third, - gomoviesAPI + primewireAPI ) - ).document.selectFirst("div#g_MXOzFGouZrOAUioXjpddqkZK a:contains(Episode ${slug.second})") + ).document.selectFirst("div#vvqUtffkId a:contains(Episode ${slug.second})") ?.attr("href") } ?: return - val res = app.get(fixUrl(iframe, gomoviesAPI), verify = false) + val res = app.get(fixUrl(iframe, primewireAPI), verify = false) val match = "var url = '(/user/servers/.*?\\?ep=.*?)';".toRegex().find(res.text) val serverUrl = match?.groupValues?.get(1) ?: return - val cookies = res.okhttpResponse.headers.getGomoviesCookies() + val cookies = res.okhttpResponse.headers.getPrimewireCookies() val url = res.document.select("meta[property=og:url]").attr("content") val headers = mapOf("X-Requested-With" to "XMLHttpRequest") val qualities = intArrayOf(2160, 1440, 1080, 720, 480, 360) app.get( - "$gomoviesAPI$serverUrl", + "$primewireAPI$serverUrl", cookies = cookies, referer = url, headers = headers ).document.select("ul li").amap { el -> val server = el.attr("data-value") @@ -2207,16 +2213,16 @@ object SoraExtractor : SoraStream() { referer = url, headers = headers ).text - val json = base64Decode(encryptedData).decryptGomoviesJson() - val links = tryParseJson>(json) ?: return@amap + val json = base64Decode(encryptedData).decodePrimewireXor() + val links = tryParseJson>(json) ?: return@amap links.forEach { video -> qualities.filter { it <= video.max.toInt() }.forEach { callback( ExtractorLink( - "Gomovies", - "Gomovies", + "Primewire", + "Primewire", video.src.split("360", limit = 3).joinToString(it.toString()), - "$gomoviesAPI/", + "$primewireAPI/", it, ) ) @@ -2535,7 +2541,8 @@ object SoraExtractor : SoraStream() { ) { val referer = "https://2now.tv/" val slug = getEpisodeSlug(season, episode) - val url = if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" + val url = + if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" if (!app.get(url, referer = referer).isSuccessful) return callback.invoke( ExtractorLink( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 382d507c..8387ccb9 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -9,12 +9,6 @@ data class FDMovieIFrame( val type: String, ) -data class BaymoviesConfig( - val country: String, - val downloadTime: String, - val workers: List -) - data class AniIds( var id: Int? = null, var idMal: Int? = null @@ -37,26 +31,7 @@ data class AniSearch( @JsonProperty("data") var data: AniData? = AniData() ) -data class Tmdb2Anilist( - @JsonProperty("tmdb_id") val tmdb_id: String? = null, - @JsonProperty("anilist_id") val anilist_id: String? = null, - @JsonProperty("mal_id") val mal_id: String? = null, -) - -data class Movie123Media( - @JsonProperty("url") val url: String? = null, -) - -data class Movie123Data( - @JsonProperty("t") val t: String? = null, - @JsonProperty("s") val s: String? = null, -) - -data class Movie123Search( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), -) - -data class GomoviesSources( +data class PrimewireSources( @JsonProperty("src") val src: String, @JsonProperty("file") val file: String? = null, @JsonProperty("label") val label: Int? = null, @@ -202,15 +177,6 @@ data class IndexSearch( @JsonProperty("data") val data: IndexData? = null, ) -data class SorastreamResponse( - @JsonProperty("data") val data: SorastreamVideos? = null, -) - -data class SorastreamVideos( - @JsonProperty("mediaUrl") val mediaUrl: String? = null, - @JsonProperty("currentDefinition") val currentDefinition: String? = null, -) - data class BiliBiliEpisodes( @JsonProperty("id") val id: Int? = null, @JsonProperty("sourceId") val sourceId: String? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 3d27c454..0b26e62c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -25,7 +25,6 @@ import com.hexated.SoraExtractor.invokeFmovies import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeGMovies import com.hexated.SoraExtractor.invokeGoku -import com.hexated.SoraExtractor.invokeGomovies import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeLing import com.hexated.SoraExtractor.invokeM4uhd @@ -46,6 +45,7 @@ import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokePobmovies +import com.hexated.SoraExtractor.invokePrimewire import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeWatchOnline @@ -111,7 +111,6 @@ open class SoraStream : TmdbProvider() { const val flixonAPI = "https://flixon.lol" const val smashyStreamAPI = "https://embed.smashystream.com" const val watchSomuchAPI = "https://watchsomuch.tv" // sub only - val gomoviesAPI = base64DecodeAPI("bQ==Y28=ZS4=aW4=bmw=LW8=ZXM=dmk=bW8=Z28=Ly8=czo=dHA=aHQ=") const val ask4MoviesAPI = "https://ask4movie.nl" const val biliBiliAPI = "https://api-vn.otakuz.live/server" const val watchOnlineAPI = "https://watchonline.ag" @@ -129,6 +128,7 @@ open class SoraStream : TmdbProvider() { const val netmoviesAPI = "https://netmovies.to" const val momentAPI = "https://moment-explanation-i-244.site" const val doomoviesAPI = "https://doomovies.net" + const val primewireAPI = "https://real-primewire.club" // INDEX SITE const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev" @@ -615,7 +615,7 @@ open class SoraStream : TmdbProvider() { ) }, { - invokeGomovies(res.title, res.year, res.season, res.episode, callback) + invokePrimewire(res.title, res.year, res.season, res.episode, callback) }, // { // if (!res.isAnime) invokeGdbotMovies( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 1558a2f7..63cc091b 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -10,7 +10,6 @@ import com.hexated.SoraExtractor.invokeFlixon import com.hexated.SoraExtractor.invokeFmovies import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeGoku -import com.hexated.SoraExtractor.invokeGomovies import com.hexated.SoraExtractor.invokeHDMovieBox import com.hexated.SoraExtractor.invokeIdlix import com.hexated.SoraExtractor.invokeKimcartoon @@ -32,6 +31,7 @@ import com.hexated.SoraExtractor.invokeFourCartoon import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies +import com.hexated.SoraExtractor.invokePrimewire import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeWatchOnline import com.hexated.SoraExtractor.invokeWatchsomuch @@ -268,7 +268,7 @@ class SoraStreamLite : SoraStream() { invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback) }, { - invokeGomovies(res.title, res.year, res.season, res.episode, callback) + invokePrimewire(res.title, res.year, res.season, res.episode, callback) }, { if (!res.isAnime) invokeAsk4Movies( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 23eea4c4..c918810b 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -165,6 +165,34 @@ suspend fun extractMirrorUHD(url: String, ref: String): String? { ) } +suspend fun extractDirectUHD(url: String, niceResponse: NiceResponse): String? { + val document = niceResponse.document + val script = document.selectFirst("script:containsData(cf_token)")?.data() ?: return null + val actionToken = script.substringAfter("\"key\", \"").substringBefore("\");") + val cfToken = script.substringAfter("cf_token = \"").substringBefore("\";") + val body = FormBody.Builder() + .addEncoded("action", "direct") + .addEncoded("key", actionToken) + .addEncoded("action_token", cfToken) + .build() + val cookies = mapOf("PHPSESSID" to "${niceResponse.cookies["PHPSESSID"]}") + val direct = app.post( + url, + requestBody = body, + cookies = cookies, + referer = url, + headers = mapOf( + "x-token" to "driveleech.org" + ) + ).parsedSafe>()?.get("url") + + return app.get( + direct ?: return null, cookies = cookies, + referer = url + ).text.substringAfter("worker_url = '").substringBefore("';") + +} + suspend fun extractBackupUHD(url: String): String? { val resumeDoc = app.get(url) @@ -425,14 +453,8 @@ suspend fun invokeSmashyFfix( ref: String, callback: (ExtractorLink) -> Unit, ) { - val script = - app.get(url, referer = ref).document.selectFirst("script:containsData(player =)")?.data() - ?: return - - val source = - Regex("['\"]?file['\"]?:\\s*\"([^\"]+)").find(script)?.groupValues?.get( - 1 - ) ?: return + val res = app.get(url, referer = ref).text + val source = Regex("['\"]?file['\"]?:\\s*\"([^\"]+)").find(res)?.groupValues?.get(1) ?: return source.split(",").map { links -> val quality = Regex("\\[(\\d+)]").find(links)?.groupValues?.getOrNull(1)?.trim() @@ -1283,7 +1305,7 @@ fun decodeIndexJson(json: String): String { return base64Decode(slug.substring(0, slug.length - 20)) } -fun String.decryptGomoviesJson(key: String = BuildConfig.GOMOVIES_KEY): String { +fun String.decodePrimewireXor(key: String = BuildConfig.PRIMEWIRE_KEY): String { val sb = StringBuilder() var i = 0 while (i < this.length) { @@ -1297,7 +1319,7 @@ fun String.decryptGomoviesJson(key: String = BuildConfig.GOMOVIES_KEY): String { return sb.toString() } -fun Headers.getGomoviesCookies(cookieKey: String = "set-cookie"): Map { +fun Headers.getPrimewireCookies(cookieKey: String = "set-cookie"): Map { val cookieList = this.filter { it.first.equals(cookieKey, ignoreCase = true) }.mapNotNull { it.second.split(";").firstOrNull() diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt index 1b2bd2a0..9f9fce7c 100644 --- a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt +++ b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt @@ -10,7 +10,7 @@ import org.jsoup.nodes.Element import java.net.URI open class YomoviesProvider : MainAPI() { - override var mainUrl = "https://yomovies.baby" + override var mainUrl = "https://yomovies.ltd" private var directUrl = "" override var name = "Yomovies" override val hasMainPage = true From ab8d75a4e5697c2608ab57acbfc7353a550aa46a Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 19 Aug 2023 04:35:24 +0700 Subject: [PATCH 064/105] update domain --- .../main/kotlin/com/hexated/SoraExtractor.kt | 27 +++++++++++++++++++ .../src/main/kotlin/com/hexated/SoraStream.kt | 10 +++---- .../main/kotlin/com/hexated/SoraStreamLite.kt | 7 +++-- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 527338ac..4f91fc46 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -767,6 +767,33 @@ object SoraExtractor : SoraStream() { } } + suspend fun invokeVidsrcto( + imdbId: String?, + season: Int?, + episode: Int?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val url = if(season == null) { + "$vidsrctoAPI/embed/movie/$imdbId" + } else { + "$vidsrctoAPI/embed/tv/$imdbId/$season/$episode" + } + + val id = app.get(url).document.selectFirst("ul.episodes li a")?.attr("data-id") ?: return + + val subtitles = app.get("$vidsrctoAPI/ajax/embed/episode/$id/subtitles").text + tryParseJson>(subtitles)?.map { + subtitleCallback.invoke( + SubtitleFile( + it.label ?: "", + it.file ?: return@map + ) + ) + } + + } + suspend fun invokeKisskh( title: String? = null, season: Int? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 0b26e62c..970288df 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -21,7 +21,6 @@ import com.hexated.SoraExtractor.invokeDoomovies import com.hexated.SoraExtractor.invokeDreamfilm import com.hexated.SoraExtractor.invokeFDMovies import com.hexated.SoraExtractor.invokeFlixon -import com.hexated.SoraExtractor.invokeFmovies import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeGMovies import com.hexated.SoraExtractor.invokeGoku @@ -48,6 +47,7 @@ import com.hexated.SoraExtractor.invokePobmovies import com.hexated.SoraExtractor.invokePrimewire import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies +import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeWatchOnline import com.hexated.SoraExtractor.invokeWatchsomuch import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId @@ -98,7 +98,7 @@ open class SoraStream : TmdbProvider() { const val crunchyrollAPI = "https://beta-api.crunchyroll.com" const val kissKhAPI = "https://kisskh.co" const val lingAPI = "https://ling-online.net" - const val uhdmoviesAPI = "https://uhdmovies.ink" + const val uhdmoviesAPI = "https://uhdmovies.actor" const val fwatayakoAPI = "https://5100.svetacdn.in" const val gMoviesAPI = "https://gdrivemovies.xyz" const val fdMoviesAPI = "https://freedrivemovie.lol" @@ -129,6 +129,7 @@ open class SoraStream : TmdbProvider() { const val momentAPI = "https://moment-explanation-i-244.site" const val doomoviesAPI = "https://doomovies.net" const val primewireAPI = "https://real-primewire.club" + const val vidsrctoAPI = "https://vidsrc.to" // INDEX SITE const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev" @@ -467,9 +468,8 @@ open class SoraStream : TmdbProvider() { ) }, { - if (!res.isAnime) invokeFmovies( - res.title, - res.airedYear ?: res.year, + if (!res.isAnime) invokeVidsrcto( + res.imdbId, res.season, res.episode, subtitleCallback, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 63cc091b..df1b3e27 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -7,7 +7,6 @@ import com.hexated.SoraExtractor.invokeDoomovies import com.hexated.SoraExtractor.invokeDreamfilm import com.hexated.SoraExtractor.invokeFilmxy import com.hexated.SoraExtractor.invokeFlixon -import com.hexated.SoraExtractor.invokeFmovies import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeGoku import com.hexated.SoraExtractor.invokeHDMovieBox @@ -33,6 +32,7 @@ import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokePrimewire import com.hexated.SoraExtractor.invokeVidSrc +import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeWatchOnline import com.hexated.SoraExtractor.invokeWatchsomuch import com.lagradost.cloudstream3.SubtitleFile @@ -218,9 +218,8 @@ class SoraStreamLite : SoraStream() { // ) // }, { - if (!res.isAnime) invokeFmovies( - res.title, - res.airedYear ?: res.year, + if (!res.isAnime) invokeVidsrcto( + res.imdbId, res.season, res.episode, subtitleCallback, From 0c99e2af7f81203c697bd8025720457e5a7f6900 Mon Sep 17 00:00:00 2001 From: helo Date: Sat, 19 Aug 2023 08:01:42 +0700 Subject: [PATCH 065/105] Oppadrama & Ngefilm: added new sources --- .../src/main/kotlin/com/hexated/DramaidProviderPlugin.kt | 1 + DramaidProvider/src/main/kotlin/com/hexated/Oppadrama.kt | 7 +++++++ Gomov/build.gradle.kts | 2 +- Gomov/src/main/kotlin/com/hexated/Extractors.kt | 5 +++++ Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt | 1 + 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProviderPlugin.kt b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProviderPlugin.kt index bcf9ac4f..536b3b2c 100644 --- a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProviderPlugin.kt +++ b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProviderPlugin.kt @@ -12,5 +12,6 @@ class DramaidProviderPlugin: Plugin() { registerMainAPI(DramaidProvider()) registerMainAPI(Oppadrama()) registerExtractorAPI(Vanfem()) + registerExtractorAPI(Filelions()) } } \ No newline at end of file diff --git a/DramaidProvider/src/main/kotlin/com/hexated/Oppadrama.kt b/DramaidProvider/src/main/kotlin/com/hexated/Oppadrama.kt index 44dcb365..21a0aeb7 100644 --- a/DramaidProvider/src/main/kotlin/com/hexated/Oppadrama.kt +++ b/DramaidProvider/src/main/kotlin/com/hexated/Oppadrama.kt @@ -1,6 +1,13 @@ package com.hexated +import com.lagradost.cloudstream3.extractors.Filesim + class Oppadrama : DramaidProvider() { override var mainUrl = "http://185.217.95.34" override var name = "Oppadrama" +} + +class Filelions : Filesim() { + override val name = "Filelions" + override var mainUrl = "https://filelions.live" } \ No newline at end of file diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index 87aa82a7..6620ccb2 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 5 +version = 6 cloudstream { diff --git a/Gomov/src/main/kotlin/com/hexated/Extractors.kt b/Gomov/src/main/kotlin/com/hexated/Extractors.kt index 25bd9f11..1dc4079a 100644 --- a/Gomov/src/main/kotlin/com/hexated/Extractors.kt +++ b/Gomov/src/main/kotlin/com/hexated/Extractors.kt @@ -14,6 +14,11 @@ class Filelions : Filesim() { override var mainUrl = "https://filelions.to" } +class Embedwish : Filesim() { + override val name = "Embedwish" + override var mainUrl = "https://embedwish.com" +} + class Likessb : StreamSB() { override var name = "Likessb" override var mainUrl = "https://likessb.com" diff --git a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt index bd11fd67..8bac805e 100644 --- a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt +++ b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt @@ -17,5 +17,6 @@ class GomovPlugin: Plugin() { registerExtractorAPI(Likessb()) registerExtractorAPI(DbGdriveplayer()) registerExtractorAPI(Dutamovie21()) + registerExtractorAPI(Embedwish()) } } \ No newline at end of file From 8c287e2cd13aa42a2dea9522b1286d0379949331 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 19 Aug 2023 09:38:32 +0700 Subject: [PATCH 066/105] sora: fix filmxy --- .../main/kotlin/com/hexated/SoraExtractor.kt | 2 +- .../src/main/kotlin/com/hexated/SoraUtils.kt | 42 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 4f91fc46..f2cc5694 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -562,7 +562,7 @@ object SoraExtractor : SoraStream() { } else { "${filmxyAPI}/tv/$imdbId" } - val filmxyCookies = getFilmxyCookies(imdbId, season) + val filmxyCookies = getFilmxyCookies(url) val doc = session.get(url, cookies = filmxyCookies).document val script = doc.selectFirst("script:containsData(var isSingle)")?.data() ?: return diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index c918810b..f256bf87 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -905,31 +905,29 @@ suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair { +var filmxyCookies: Map? = null +suspend fun getFilmxyCookies(url: String) = filmxyCookies ?: fetchFilmxyCookies(url).also { filmxyCookies = it } +suspend fun fetchFilmxyCookies(url: String): Map { - val url = if (season == null) { - "${filmxyAPI}/movie/$imdbId" - } else { - "${filmxyAPI}/tv/$imdbId" - } - val cookieUrl = "${filmxyAPI}/wp-admin/admin-ajax.php" - - val res = session.get( + val defaultCookies = mutableMapOf("G_ENABLED_IDPS" to "google", "true_checker" to "1", "XID" to "1") + session.get( url, headers = mapOf( "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8" ), + cookies = defaultCookies, ) - - if (!res.isSuccessful) return emptyMap() - - val userNonce = - res.document.select("script").find { it.data().contains("var userNonce") }?.data()?.let { - Regex("var\\suserNonce.*?\"(\\S+?)\";").find(it)?.groupValues?.get(1) - } - val phpsessid = session.baseClient.cookieJar.loadForRequest(url.toHttpUrl()) .first { it.name == "PHPSESSID" }.value + defaultCookies["PHPSESSID"] = phpsessid + + val userNonce = + app.get("$filmxyAPI/login/?redirect_to=$filmxyAPI/", cookies = defaultCookies).document.select("script") + .find { it.data().contains("var userNonce") }?.data()?.let { + Regex("var\\suserNonce.*?\"(\\S+?)\";").find(it)?.groupValues?.get(1) + } + + val cookieUrl = "${filmxyAPI}/wp-admin/admin-ajax.php" session.post( cookieUrl, @@ -938,12 +936,14 @@ suspend fun getFilmxyCookies(imdbId: String? = null, season: Int? = null): Map Date: Sat, 19 Aug 2023 13:26:08 +0700 Subject: [PATCH 067/105] small fix --- SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index f2cc5694..6cd9e89c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -563,7 +563,7 @@ object SoraExtractor : SoraStream() { "${filmxyAPI}/tv/$imdbId" } val filmxyCookies = getFilmxyCookies(url) - val doc = session.get(url, cookies = filmxyCookies).document + val doc = app.get(url, cookies = filmxyCookies).document val script = doc.selectFirst("script:containsData(var isSingle)")?.data() ?: return val sourcesData = From 3d60b9c792d02b11a4287fc121ddd69faa5af30b Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 20 Aug 2023 13:21:50 +0700 Subject: [PATCH 068/105] sora: added Dramaday --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 68 +++++++++++++++++++ .../src/main/kotlin/com/hexated/SoraStream.kt | 22 +++++- .../main/kotlin/com/hexated/SoraStreamLite.kt | 11 +++ 4 files changed, 99 insertions(+), 4 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index b2614d35..af164cb7 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 = 157 +version = 158 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 6cd9e89c..56aee7cd 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -644,6 +644,74 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeDramaday( + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + fun String.getQuality(): String? = + Regex("""\d{3,4}[pP]""").find(this)?.groupValues?.getOrNull(0) + + fun String.getTag(): String? = + Regex("""\d{3,4}[pP]\s*(.*)""").find(this)?.groupValues?.getOrNull(1) + + val slug = title.createSlug() + val epsSlug = getEpisodeSlug(season, episode) + val url = if (season == null) { + "$dramadayAPI/$slug-$year/" + } else { + "$dramadayAPI/$slug/" + } + val res = app.get(url).document + + val servers = if (season == null) { + val player = res.select("div.tabs__pane p a[href*=https://ouo]").attr("href") + val ouo = bypassOuo(player) + app.get(ouo ?: return).document.select("article p:matches(\\d{3,4}[pP]) + p:has(a)") + .flatMap { ele -> + val entry = ele.previousElementSibling()?.text() ?: "" + ele.select("a").map { + Triple(entry.getQuality(), entry.getTag(), it.attr("href")) + }.filter { + it.third.startsWith("https://pixeldrain.com") || it.third.startsWith("https://krakenfiles.com") + } + } + } else { + val data = res.select("tbody tr:has(td[data-order=${epsSlug.second}])") + val qualities = + data.select("td:nth-child(2)").attr("data-order").split("
").map { it } + val iframe = data.select("a[href*=https://ouo]").map { it.attr("href") } + qualities.zip(iframe).map { + Triple(it.first.getQuality(), it.first.getTag(), it.second) + } + } + + servers.filter { it.first == "720p" || it.first == "1080p" }.apmap { + val server = if (it.third.startsWith("https://ouo")) bypassOuo(it.third) else it.third + loadExtractor(server ?: return@apmap, "$dramadayAPI/", subtitleCallback) { link -> + callback.invoke( + ExtractorLink( + link.source, + "${link.name} ${it.second}", + link.url, + link.referer, + when { + link.isM3u8 -> link.quality + else -> getQualityFromName(it.first) + }, + link.isM3u8, + link.headers, + link.extractorData + ) + ) + } + } + + } + suspend fun invokeKimcartoon( title: String? = null, season: Int? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 970288df..36df7dc2 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -18,6 +18,7 @@ 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.invokeDramaday import com.hexated.SoraExtractor.invokeDreamfilm import com.hexated.SoraExtractor.invokeFDMovies import com.hexated.SoraExtractor.invokeFlixon @@ -130,11 +131,13 @@ open class SoraStream : TmdbProvider() { const val doomoviesAPI = "https://doomovies.net" const val primewireAPI = "https://real-primewire.club" const val vidsrctoAPI = "https://vidsrc.to" + const val dramadayAPI = "https://dramaday.me" // INDEX SITE const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev" const val shinobiMovieAPI = "https://home.shinobicloud.cf/0:" - val cryMoviesAPI = base64DecodeAPI("ZXY=LmQ=cnM=a2U=b3I=Lnc=ZXI=ZGQ=bGE=cy0=b2I=YWM=Lmo=YWw=aW4=LWY=cm4=Ym8=cmU=Ly8=czo=dHA=aHQ=") + val cryMoviesAPI = + base64DecodeAPI("ZXY=LmQ=cnM=a2U=b3I=Lnc=ZXI=ZGQ=bGE=cy0=b2I=YWM=Lmo=YWw=aW4=LWY=cm4=Ym8=cmU=Ly8=czo=dHA=aHQ=") fun getType(t: String?): TvType { return when (t) { @@ -244,8 +247,8 @@ open class SoraStream : TmdbProvider() { val year = releaseDate?.split("-")?.first()?.toIntOrNull() val rating = res.vote_average.toString().toRatingInt() val genres = res.genres?.mapNotNull { it.name } - val isAnime = - genres?.contains("Animation") == true && (res.original_language == "zh" || res.original_language == "ja") + val isAnime = genres?.contains("Animation") == true && (res.original_language == "zh" || res.original_language == "ja") + val isAsian = !isAnime && (res.original_language == "zh" || res.original_language == "ko") val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty() .ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } } @@ -286,6 +289,7 @@ open class SoraStream : TmdbProvider() { jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, date = season.airDate, airedDate = res.releaseDate ?: res.firstAirDate, + isAsian = isAsian, ).toJson(), name = eps.name + if (isUpcoming(eps.airDate)) " - [UPCOMING]" else "", season = eps.seasonNumber, @@ -332,6 +336,7 @@ open class SoraStream : TmdbProvider() { isAnime = isAnime, jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, airedDate = res.releaseDate ?: res.firstAirDate, + isAsian = isAsian, ).toJson(), ) { this.posterUrl = poster @@ -725,6 +730,16 @@ open class SoraStream : TmdbProvider() { callback ) }, + { + if(res.isAsian) invokeDramaday( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + } ) return true @@ -748,6 +763,7 @@ open class SoraStream : TmdbProvider() { val jpTitle: String? = null, val date: String? = null, val airedDate: String? = null, + val isAsian: Boolean = false, ) data class Data( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index df1b3e27..6b3a7818 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -4,6 +4,7 @@ import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAsk4Movies import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeDoomovies +import com.hexated.SoraExtractor.invokeDramaday import com.hexated.SoraExtractor.invokeDreamfilm import com.hexated.SoraExtractor.invokeFilmxy import com.hexated.SoraExtractor.invokeFlixon @@ -345,6 +346,16 @@ class SoraStreamLite : SoraStream() { callback ) }, + { + if(res.isAsian) invokeDramaday( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + } ) return true From 83e2c399f6d2f8aebe36afe2bf772d7595377170 Mon Sep 17 00:00:00 2001 From: hexated Date: Mon, 21 Aug 2023 07:55:21 +0700 Subject: [PATCH 069/105] sora: added Animetosho --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 117 +++++++++++------- .../src/main/kotlin/com/hexated/SoraParser.kt | 30 ++--- .../src/main/kotlin/com/hexated/SoraStream.kt | 10 +- .../main/kotlin/com/hexated/SoraStreamLite.kt | 11 +- 5 files changed, 100 insertions(+), 70 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index af164cb7..a9ef66fb 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 = 158 +version = 159 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 56aee7cd..18305310 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -17,6 +17,7 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody import org.jsoup.Jsoup import org.jsoup.nodes.Document +import org.jsoup.select.Elements val session = Session(Requests().baseClient) @@ -968,10 +969,10 @@ object SoraExtractor : SoraStream() { argamap( { - invokeAniwatch(malId, episode, subtitleCallback, callback) + invokeAnimetosho(malId, season, episode, subtitleCallback, callback) }, { - invokeBiliBili(aniId, episode, subtitleCallback, callback) + invokeAniwatch(malId, episode, subtitleCallback, callback) }, { if (season != null) invokeCrunchyroll( @@ -987,54 +988,55 @@ object SoraExtractor : SoraStream() { ) } - private suspend fun invokeBiliBili( - aniId: Int? = null, + private suspend fun invokeAnimetosho( + malId: Int? = null, + season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { - val res = app.get( - "$biliBiliAPI/anime/episodes?id=${aniId ?: return}&source_id=bilibili", - referer = otakuzBaseUrl - ) - .parsedSafe()?.episodes?.find { - it.episodeNumber == episode - } ?: return - - val sources = - app.get( - "$biliBiliAPI/source?episode_id=${res.sourceEpisodeId}&source_media_id=${res.sourceMediaId}&source_id=${res.sourceId}", - referer = otakuzBaseUrl - ) - .parsedSafe() - - sources?.sources?.apmap { source -> - val quality = - app.get( - source.file ?: return@apmap null, - referer = otakuzBaseUrl - ).document.selectFirst("Representation") - ?.attr("height") - callback.invoke( - ExtractorLink( - "BiliBili", - "BiliBili", - source.file, - "", - quality?.toIntOrNull() ?: Qualities.Unknown.value, - isDash = true - ) - ) + fun Elements.getLinks(): List> { + return this.flatMap { ele -> + ele.select("div.links a:matches(KrakenFiles|GoFile)").map { + Triple( + it.attr("href"), + ele.select("div.size").text(), + getIndexQuality(ele.select("div.link a").text()) + ) + } + } } - sources?.subtitles?.map { sub -> - subtitleCallback.invoke( - SubtitleFile( - SubtitleHelper.fromTwoLettersToLanguage(sub.lang ?: "") ?: sub.language - ?: return@map null, - sub.file ?: return@map null + val (seasonSLug, episodeSlug) = getEpisodeSlug(season, episode) + val jikan = app.get("$jikanAPI/anime/$malId/full").parsedSafe()?.data + val aniId = jikan?.external?.find { it.name == "AniDB" }?.url?.substringAfterLast("=") + val res = app.get("$animetoshoAPI/series/${jikan?.title?.createSlug()}.$aniId?filter[0][t]=nyaa_class&filter[0][v]=trusted").document + + val servers = if (season == null) { + res.select("div.home_list_entry:has(div.links)").getLinks() + } else { + res.select("div.home_list_entry:has(div.link a:matches([\\.\\s]$episodeSlug[\\.\\s]|S${seasonSLug}E$episodeSlug))") + .getLinks() + } + + servers.filter { it.third in arrayOf(Qualities.P1080.value,Qualities.P720.value) }.apmap { + loadExtractor(it.first, "$animetoshoAPI/", subtitleCallback) { link -> + callback.invoke( + ExtractorLink( + link.source, + "${link.name} [${it.second}]", + link.url, + link.referer, + when { + link.isM3u8 -> link.quality + else -> it.third + }, + link.isM3u8, + link.headers, + link.extractorData + ) ) - ) + } } } @@ -2209,7 +2211,7 @@ object SoraExtractor : SoraStream() { "$dahmerMoviesAPI/tvs/${title?.replace(":", " -")}/Season $season/" } - val request = app.get(url) + val request = app.get(url, timeout = 120L) if (!request.isSuccessful) return val paths = request.document.select("a").map { it.text() to it.attr("href") @@ -2239,6 +2241,33 @@ object SoraExtractor : SoraStream() { } + suspend fun invoke2embed( + imdbId: String?, + season: Int?, + episode: Int?, + callback: (ExtractorLink) -> Unit + ) { + val server = "https://stream.2embed.cc" + val url = if(season == null) { + "$twoEmbedAPI/embed/$imdbId" + } else { + "$twoEmbedAPI/embedtv/$imdbId&s=$season&e=$episode" + } + + val iframesrc = app.get(url).document.selectFirst("iframe#iframesrc")?.attr("src") + val framesrc = app.get(fixUrl(iframesrc ?: return, twoEmbedAPI)).document.selectFirst("iframe#framesrc")?.attr("src") + val video = app.get(fixUrl(framesrc ?: return, "$server/e/")).text.let { + Regex("file:\\s*\"(.*?m3u8.*?)\"").find(it)?.groupValues?.getOrNull(1) + } + + M3u8Helper.generateM3u8( + "2embed", + video ?: return, + "$server/", + ).forEach(callback) + + } + suspend fun invokePrimewire( title: String? = null, year: Int? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 8387ccb9..db94285e 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -177,32 +177,18 @@ data class IndexSearch( @JsonProperty("data") val data: IndexData? = null, ) -data class BiliBiliEpisodes( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("sourceId") val sourceId: String? = null, - @JsonProperty("sourceEpisodeId") val sourceEpisodeId: String? = null, - @JsonProperty("sourceMediaId") val sourceMediaId: String? = null, - @JsonProperty("episodeNumber") val episodeNumber: Int? = null, +data class JikanExternal( + @JsonProperty("name") val name: String? = null, + @JsonProperty("url") val url: String? = null, ) -data class BiliBiliDetails( - @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), +data class JikanData( + @JsonProperty("title") val title: String? = null, + @JsonProperty("external") val external: ArrayList? = arrayListOf(), ) -data class BiliBiliSubtitles( - @JsonProperty("file") val file: String? = null, - @JsonProperty("lang") val lang: String? = null, - @JsonProperty("language") val language: String? = null, -) - -data class BiliBiliSources( - @JsonProperty("file") val file: String? = null, - @JsonProperty("type") val type: String? = null, -) - -data class BiliBiliSourcesResponse( - @JsonProperty("sources") val sources: ArrayList? = arrayListOf(), - @JsonProperty("subtitles") val subtitles: ArrayList? = arrayListOf(), +data class JikanResponse( + @JsonProperty("data") val data: JikanData? = null, ) data class WatchOnlineItems( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 36df7dc2..16c74135 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -1,6 +1,7 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty +import com.hexated.SoraExtractor.invoke2embed import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAsk4Movies import com.hexated.SoraExtractor.invokeBollyMaza @@ -80,11 +81,13 @@ open class SoraStream : TmdbProvider() { const val anilistAPI = "https://graphql.anilist.co" const val malsyncAPI = "https://api.malsync.moe" const val consumetHelper = "https://api.consumet.org/anime/9anime/helper" + const val jikanAPI = "https://api.jikan.moe/v4" private val apiKey = base64DecodeAPI("ZTM=NTg=MjM=MjM=ODc=MzI=OGQ=MmE=Nzk=Nzk=ZjI=NTA=NDY=NDA=MzA=YjA=") // PLEASE DON'T STEAL /** ALL SOURCES */ + const val twoEmbedAPI = "https://www.2embed.cc" const val vidSrcAPI = "https://v2.vidsrc.me" const val dbgoAPI = "https://dbgo.fun" const val movieHabAPI = "https://moviehab.com" @@ -113,7 +116,6 @@ open class SoraStream : TmdbProvider() { const val smashyStreamAPI = "https://embed.smashystream.com" const val watchSomuchAPI = "https://watchsomuch.tv" // sub only const val ask4MoviesAPI = "https://ask4movie.nl" - const val biliBiliAPI = "https://api-vn.otakuz.live/server" const val watchOnlineAPI = "https://watchonline.ag" const val nineTvAPI = "https://moviesapi.club" const val putlockerAPI = "https://ww7.putlocker.vip" @@ -132,6 +134,7 @@ open class SoraStream : TmdbProvider() { const val primewireAPI = "https://real-primewire.club" const val vidsrctoAPI = "https://vidsrc.to" const val dramadayAPI = "https://dramaday.me" + const val animetoshoAPI = "https://animetosho.org" // INDEX SITE const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev" @@ -739,7 +742,10 @@ open class SoraStream : TmdbProvider() { subtitleCallback, callback ) - } + }, + { + if(!res.isAnime) invoke2embed(res.imdbId,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 6b3a7818..c5bf1a6d 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -1,5 +1,6 @@ package com.hexated +import com.hexated.SoraExtractor.invoke2embed import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAsk4Movies import com.hexated.SoraExtractor.invokeDbgo @@ -355,7 +356,15 @@ class SoraStreamLite : SoraStream() { subtitleCallback, callback ) - } + }, + { + if(!res.isAnime) invoke2embed( + res.imdbId, + res.season, + res.episode, + callback + ) + }, ) return true From 52f50292c900c9beb2f5f55200d7c5f8b8e533df Mon Sep 17 00:00:00 2001 From: hexated Date: Mon, 21 Aug 2023 17:13:07 +0700 Subject: [PATCH 070/105] sora: small fix --- .../src/main/kotlin/com/hexated/SoraExtractor.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 18305310..5e131676 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2320,16 +2320,17 @@ object SoraExtractor : SoraStream() { } ?: return val res = app.get(fixUrl(iframe, primewireAPI), verify = false) - val match = "var url = '(/user/servers/.*?\\?ep=.*?)';".toRegex().find(res.text) - val serverUrl = match?.groupValues?.get(1) ?: return + val serverUrl = "var url = '(/user/servers/.*?\\?ep=.*?)';".toRegex().find(res.text)?.groupValues?.get(1) ?: return val cookies = res.okhttpResponse.headers.getPrimewireCookies() val url = res.document.select("meta[property=og:url]").attr("content") val headers = mapOf("X-Requested-With" to "XMLHttpRequest") val qualities = intArrayOf(2160, 1440, 1080, 720, 480, 360) - app.get( + val serverRes = app.get( "$primewireAPI$serverUrl", cookies = cookies, referer = url, headers = headers - ).document.select("ul li").amap { el -> + ) + val key = getAndUnpack(serverRes.text).substringAfter("(key=").substringBefore(")") + serverRes.document.select("ul li").amap { el -> val server = el.attr("data-value") val encryptedData = app.get( "$url?server=$server&_=${System.currentTimeMillis()}", @@ -2337,7 +2338,7 @@ object SoraExtractor : SoraStream() { referer = url, headers = headers ).text - val json = base64Decode(encryptedData).decodePrimewireXor() + val json = base64Decode(encryptedData).decodePrimewireXor(key) val links = tryParseJson>(json) ?: return@amap links.forEach { video -> qualities.filter { it <= video.max.toInt() }.forEach { From b2227f51feb387a3e66fcdac08ec30926aa85e31 Mon Sep 17 00:00:00 2001 From: sora Date: Tue, 22 Aug 2023 00:23:43 +0700 Subject: [PATCH 071/105] Ngefilm, Samehadaku: updated domain --- Gomov/build.gradle.kts | 2 +- Gomov/src/main/kotlin/com/hexated/Gomov.kt | 16 +++++++++++++--- Gomov/src/main/kotlin/com/hexated/Ngefilm.kt | 2 +- Samehadaku/build.gradle.kts | 4 ++-- .../src/main/kotlin/com/hexated/Samehadaku.kt | 2 +- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index 6620ccb2..b2bef495 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 6 +version = 7 cloudstream { diff --git a/Gomov/src/main/kotlin/com/hexated/Gomov.kt b/Gomov/src/main/kotlin/com/hexated/Gomov.kt index ab1c5fcf..6fc1892e 100644 --- a/Gomov/src/main/kotlin/com/hexated/Gomov.kt +++ b/Gomov/src/main/kotlin/com/hexated/Gomov.kt @@ -7,9 +7,11 @@ import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.httpsify import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element +import java.net.URI open class Gomov : MainAPI() { override var mainUrl = "https://gomov.bio" + private var directUrl: String? = null override var name = "Gomov" override val hasMainPage = true override var lang = "id" @@ -78,7 +80,9 @@ open class Gomov : MainAPI() { } override suspend fun load(url: String): LoadResponse { - val document = app.get(url).document + val fetch = app.get(url) + directUrl = getBaseUrl(fetch.url) + val document = fetch.document val title = document.selectFirst("h1.entry-title")?.text()?.substringBefore("Season")?.substringBefore("Episode")?.trim() @@ -151,11 +155,11 @@ open class Gomov : MainAPI() { document.select("div.tab-content-ajax").apmap { val server = app.post( - "$mainUrl/wp-admin/admin-ajax.php", + "$directUrl/wp-admin/admin-ajax.php", data = mapOf("action" to "muvipro_player_content", "tab" to it.attr("id"), "post_id" to id) ).document.select("iframe").attr("src") - loadExtractor(httpsify(server), "$mainUrl/", subtitleCallback, callback) + loadExtractor(httpsify(server), "$directUrl/", subtitleCallback, callback) } return true @@ -169,4 +173,10 @@ open class Gomov : MainAPI() { return this.replace(regex?.get(0) ?: return null, "") } + private fun getBaseUrl(url: String): String { + return URI(url).let { + "${it.scheme}://${it.host}" + } + } + } \ No newline at end of file diff --git a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt index 00c20195..51b17cf2 100644 --- a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt +++ b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt @@ -9,7 +9,7 @@ import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor class Ngefilm : DutaMovie() { - override var mainUrl = "https://ngefilm21.lol" + override var mainUrl = "https://ngefilm21.lat" override var name = "Ngefilm" override val mainPage = mainPageOf( diff --git a/Samehadaku/build.gradle.kts b/Samehadaku/build.gradle.kts index 628eaa26..0749d906 100644 --- a/Samehadaku/build.gradle.kts +++ b/Samehadaku/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 12 +version = 13 cloudstream { @@ -23,5 +23,5 @@ cloudstream { "Anime", ) - iconUrl = "https://www.google.com/s2/favicons?domain=194.163.183.129&sz=%size%" + iconUrl = "https://www.google.com/s2/favicons?domain=samehadaku.world&sz=%size%" } \ No newline at end of file diff --git a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt index dfaee1b1..78264113 100644 --- a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt +++ b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt @@ -8,7 +8,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element class Samehadaku : MainAPI() { - override var mainUrl = "https://samehadaku.lat" + override var mainUrl = "https://samehadaku.world" override var name = "Samehadaku" override val hasMainPage = true override var lang = "id" From 3b1d78858789c2036e9f088ee7b94e4cd58ccf24 Mon Sep 17 00:00:00 2001 From: sora Date: Thu, 24 Aug 2023 05:12:42 +0700 Subject: [PATCH 072/105] fix AnimeIndo,Gomov,Oppadrama --- AnimeIndoProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/AnimeIndoProvider.kt | 2 +- DramaidProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/DramaidProvider.kt | 3 +-- Gomov/build.gradle.kts | 2 +- Gomov/src/main/kotlin/com/hexated/Extractors.kt | 7 ++++++- Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt | 3 ++- Samehadaku/build.gradle.kts | 2 +- 8 files changed, 14 insertions(+), 9 deletions(-) diff --git a/AnimeIndoProvider/build.gradle.kts b/AnimeIndoProvider/build.gradle.kts index 297bbcc1..e2cc3499 100644 --- a/AnimeIndoProvider/build.gradle.kts +++ b/AnimeIndoProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 11 +version = 12 cloudstream { diff --git a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt index b518016b..91f8de5e 100644 --- a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt +++ b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt @@ -48,7 +48,7 @@ class AnimeIndoProvider : MainAPI() { page: Int, request: MainPageRequest ): HomePageResponse { - val url = "$mainUrl/pages/${request.data}/page/$page" + val url = "$mainUrl/${request.data}/page/$page" val document = app.get(url).document val home = document.select("main#main div.animposx").mapNotNull { it.toSearchResult() diff --git a/DramaidProvider/build.gradle.kts b/DramaidProvider/build.gradle.kts index a1beeb4d..476c5d00 100644 --- a/DramaidProvider/build.gradle.kts +++ b/DramaidProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 8 +version = 9 cloudstream { diff --git a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt index ab50f5b4..17f9b7e1 100644 --- a/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt +++ b/DramaidProvider/src/main/kotlin/com/hexated/DramaidProvider.kt @@ -3,7 +3,6 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.extractors.XStreamCdn -import com.lagradost.cloudstream3.utils.AppUtils import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.getQualityFromName @@ -197,7 +196,7 @@ open class DramaidProvider : MainAPI() { callback ) - else -> loadExtractor(it, data, subtitleCallback, callback) + else -> loadExtractor(it, "$mainUrl/", subtitleCallback, callback) } } diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index b2bef495..b66e81e1 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 7 +version = 8 cloudstream { diff --git a/Gomov/src/main/kotlin/com/hexated/Extractors.kt b/Gomov/src/main/kotlin/com/hexated/Extractors.kt index 1dc4079a..7017d7fa 100644 --- a/Gomov/src/main/kotlin/com/hexated/Extractors.kt +++ b/Gomov/src/main/kotlin/com/hexated/Extractors.kt @@ -9,11 +9,16 @@ class Dutamovie21 : StreamSB() { override var mainUrl = "https://dutamovie21.xyz" } -class Filelions : Filesim() { +class FilelionsTo : Filesim() { override val name = "Filelions" override var mainUrl = "https://filelions.to" } +class Lylxan : Filesim() { + override val name = "Lylxan" + override var mainUrl = "https://lylxan.com" +} + class Embedwish : Filesim() { override val name = "Embedwish" override var mainUrl = "https://embedwish.com" diff --git a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt index 8bac805e..975337d4 100644 --- a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt +++ b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt @@ -13,10 +13,11 @@ class GomovPlugin: Plugin() { registerMainAPI(DutaMovie()) registerMainAPI(Ngefilm()) registerMainAPI(Nodrakorid()) - registerExtractorAPI(Filelions()) + registerExtractorAPI(FilelionsTo()) registerExtractorAPI(Likessb()) registerExtractorAPI(DbGdriveplayer()) registerExtractorAPI(Dutamovie21()) registerExtractorAPI(Embedwish()) + registerExtractorAPI(Lylxan()) } } \ No newline at end of file diff --git a/Samehadaku/build.gradle.kts b/Samehadaku/build.gradle.kts index 0749d906..c7f120a3 100644 --- a/Samehadaku/build.gradle.kts +++ b/Samehadaku/build.gradle.kts @@ -23,5 +23,5 @@ cloudstream { "Anime", ) - iconUrl = "https://www.google.com/s2/favicons?domain=samehadaku.world&sz=%size%" + iconUrl = "https://www.google.com/s2/favicons?domain=https://samehadaku.world&sz=%size%" } \ No newline at end of file From 4c28c0567c6de6e8d1e8093df25277737674e1ff Mon Sep 17 00:00:00 2001 From: Bnyro <82752168+Bnyro@users.noreply.github.com> Date: Sun, 27 Aug 2023 01:12:26 +0200 Subject: [PATCH 073/105] add German FilmPalast provider (#241) --- FilmPalast/build.gradle.kts | 24 ++++++ FilmPalast/src/main/AndroidManifest.xml | 2 + .../com/example/FilmpalastExtractors.kt | 30 +++++++ .../kotlin/com/example/FilmpalastPlugin.kt | 18 ++++ .../kotlin/com/example/FilmpalastProvider.kt | 82 +++++++++++++++++++ 5 files changed, 156 insertions(+) create mode 100644 FilmPalast/build.gradle.kts create mode 100644 FilmPalast/src/main/AndroidManifest.xml create mode 100644 FilmPalast/src/main/kotlin/com/example/FilmpalastExtractors.kt create mode 100644 FilmPalast/src/main/kotlin/com/example/FilmpalastPlugin.kt create mode 100644 FilmPalast/src/main/kotlin/com/example/FilmpalastProvider.kt diff --git a/FilmPalast/build.gradle.kts b/FilmPalast/build.gradle.kts new file mode 100644 index 00000000..6f3a4bdc --- /dev/null +++ b/FilmPalast/build.gradle.kts @@ -0,0 +1,24 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + // All of these properties are optional, you can safely remove them + + description = "German Filmpalast provider" + authors = listOf("Bnyro") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + + // List of video source types. Users are able to filter for extensions in a given category. + // You can find a list of avaliable types here: + // https://recloudstream.github.io/cloudstream/html/app/com.lagradost.cloudstream3/-tv-type/index.html + tvTypes = listOf("TvSeries", "Movie") +} diff --git a/FilmPalast/src/main/AndroidManifest.xml b/FilmPalast/src/main/AndroidManifest.xml new file mode 100644 index 00000000..1863f02a --- /dev/null +++ b/FilmPalast/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/FilmPalast/src/main/kotlin/com/example/FilmpalastExtractors.kt b/FilmPalast/src/main/kotlin/com/example/FilmpalastExtractors.kt new file mode 100644 index 00000000..11611566 --- /dev/null +++ b/FilmPalast/src/main/kotlin/com/example/FilmpalastExtractors.kt @@ -0,0 +1,30 @@ +package com.example + +import com.lagradost.cloudstream3.extractors.Filesim +import com.lagradost.cloudstream3.extractors.StreamTape +import com.lagradost.cloudstream3.extractors.Streamhub +import com.lagradost.cloudstream3.extractors.Voe + +class StreamTapeTo : StreamTape() { + override var mainUrl = "https://streamtape.com" +} + +class StreamHubGg : Streamhub() { + override var name = "Streamhub Gg" + override var mainUrl = "https://streamhub.gg" +} + +class VoeSx: Voe() { + override val name = "Voe Sx" + override val mainUrl = "https://voe.sx" +} + +class MetaGnathTuggers : Voe() { + override val name = "Metagnathtuggers" + override val mainUrl = "https://metagnathtuggers.com" +} + +class FileLions : Filesim() { + override val name = "Filelions" + override var mainUrl = "https://filelions.to" +} diff --git a/FilmPalast/src/main/kotlin/com/example/FilmpalastPlugin.kt b/FilmPalast/src/main/kotlin/com/example/FilmpalastPlugin.kt new file mode 100644 index 00000000..023c0f59 --- /dev/null +++ b/FilmPalast/src/main/kotlin/com/example/FilmpalastPlugin.kt @@ -0,0 +1,18 @@ +package com.example + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class FilmpalastPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(FilmpalastProvider()) + registerExtractorAPI(StreamTapeTo()) + registerExtractorAPI(StreamHubGg()) + registerExtractorAPI(VoeSx()) + registerExtractorAPI(MetaGnathTuggers()) + registerExtractorAPI(FileLions()) + } +} \ No newline at end of file diff --git a/FilmPalast/src/main/kotlin/com/example/FilmpalastProvider.kt b/FilmPalast/src/main/kotlin/com/example/FilmpalastProvider.kt new file mode 100644 index 00000000..7c606967 --- /dev/null +++ b/FilmPalast/src/main/kotlin/com/example/FilmpalastProvider.kt @@ -0,0 +1,82 @@ +package com.example + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.AppUtils.parseJson +import com.lagradost.cloudstream3.utils.AppUtils.toJson +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor +import org.jsoup.nodes.Element +import org.jsoup.select.Elements + +class FilmpalastProvider : MainAPI() { + override var mainUrl = "https://filmpalast.to" + override var name = "Filmpalast" + override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries) + + override var lang = "de" + override val hasMainPage = true + + private fun Element.toSearchResponse(): SearchResponse { + val title = select("cite a.rb").text() + val url = select("a.rb").attr("href") + val posterPath = select("img.cover-opacity").attr("src") + return newMovieSearchResponse(title, type = TvType.Movie, url = url).apply { + this.posterUrl = "$mainUrl$posterPath" + } + } + + override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { + val movies = app.get("$mainUrl/movies/top").document + val movieResults = movies.select("#content .liste.rb").mapNotNull { + it.toSearchResponse() + } + val series = app.get("$mainUrl/serien/view").document + val seriesResults = series.select("#content .liste.rb").mapNotNull { + it.toSearchResponse() + } + val homePageLists = listOf(HomePageList("Movies", movieResults), HomePageList("Series", seriesResults)) + return newHomePageResponse(homePageLists, hasNext = false) + } + + override suspend fun search(query: String): List { + val document = app.get("$mainUrl/search/title/$query").document + return document.select("#content .glowliste").mapNotNull { + it.toSearchResponse() + } + } + + override suspend fun load(url: String): LoadResponse { + val document = app.get(url).document.select("#content") + + val title = document.select("h2.rb.bgDark").text() + val imagePath = document.select(".detail.rb img.cover2").attr("src") + val description = document.select("span[itemprop=description]").text() + val details = document.select("detail-content-list li") + val year = details.first()?.html()?.split("
")?.getOrNull(1)?.filter { it.isDigit() }?.toIntOrNull() + val duration = details.select("em").first()?.ownText()?.filter { it.isDigit() }?.toIntOrNull() + + val links = document.select(".currentStreamLinks a.iconPlay").mapNotNull { + it.attr("href") ?: it.attr("data-player-url") + } + return newMovieLoadResponse(title, url, TvType.Movie, links.toJson()).apply { + this.posterUrl = "$mainUrl$imagePath" + this.plot = description + this.duration = duration + this.year = year + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val links = parseJson>(data) + links.apmap { + val link = fixUrlNull(it) ?: return@apmap null + loadExtractor(link, "$mainUrl/", subtitleCallback, callback) + } + return links.isNotEmpty() + } +} From e4736f1e942bb95d2db10aa2d1bd6ce9469c77f2 Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Sun, 27 Aug 2023 06:13:47 +0700 Subject: [PATCH 074/105] Update KuramanimeProvider.kt --- .../src/main/kotlin/com/hexated/KuramanimeProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt index 989740bb..b8751442 100644 --- a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt +++ b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt @@ -9,7 +9,7 @@ import org.jsoup.Jsoup import org.jsoup.nodes.Element class KuramanimeProvider : MainAPI() { - override var mainUrl = "https://kuramanime.xyz" + override var mainUrl = "https://kuramanime.pro" override var name = "Kuramanime" override val hasQuickSearch = false override val hasMainPage = true From 4bb810839857e4cc5b0896fb556edbd62ab54b69 Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Sun, 27 Aug 2023 06:14:10 +0700 Subject: [PATCH 075/105] Update build.gradle.kts --- KuramanimeProvider/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KuramanimeProvider/build.gradle.kts b/KuramanimeProvider/build.gradle.kts index e9c83545..400d87fb 100644 --- a/KuramanimeProvider/build.gradle.kts +++ b/KuramanimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 13 +version = 14 cloudstream { From bd99f996433947da9927bd0d0411e77b6e57c45e Mon Sep 17 00:00:00 2001 From: IndusAryan <125901294+IndusAryan@users.noreply.github.com> Date: Mon, 28 Aug 2023 01:46:15 +0530 Subject: [PATCH 076/105] Update YomoviesProvider.kt (#246) --- .../src/main/kotlin/com/hexated/YomoviesProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt index 9f9fce7c..f75772cc 100644 --- a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt +++ b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt @@ -10,7 +10,7 @@ import org.jsoup.nodes.Element import java.net.URI open class YomoviesProvider : MainAPI() { - override var mainUrl = "https://yomovies.ltd" + override var mainUrl = "https://yomovies.fan" private var directUrl = "" override var name = "Yomovies" override val hasMainPage = true From 029046bcc6099b88e4aa447cdd518df4de38975f Mon Sep 17 00:00:00 2001 From: movieforme <142312645+movieforme@users.noreply.github.com> Date: Mon, 28 Aug 2023 03:16:24 +0700 Subject: [PATCH 077/105] Update domain Phimmoichill (#242) * update domain * fix domain * update domain --- .../src/main/kotlin/com/hexated/PhimmoichillProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PhimmoichillProvider/src/main/kotlin/com/hexated/PhimmoichillProvider.kt b/PhimmoichillProvider/src/main/kotlin/com/hexated/PhimmoichillProvider.kt index 79823186..aa7c4f5d 100644 --- a/PhimmoichillProvider/src/main/kotlin/com/hexated/PhimmoichillProvider.kt +++ b/PhimmoichillProvider/src/main/kotlin/com/hexated/PhimmoichillProvider.kt @@ -9,7 +9,7 @@ import org.jsoup.nodes.Element import java.net.URLDecoder class PhimmoichillProvider : MainAPI() { - override var mainUrl = "https://phimmoichilld.net" + override var mainUrl = "https://phimmoichillg.net" override var name = "Phimmoichill" override val hasMainPage = true override var lang = "vi" From e8661648da64a643ea2b06978e65f518d3d646b1 Mon Sep 17 00:00:00 2001 From: hexated Date: Tue, 29 Aug 2023 20:28:15 +0700 Subject: [PATCH 078/105] sora: fix Jeniusplay --- IdlixProvider/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/IdlixProvider.kt | 39 +-- .../src/main/kotlin/com/hexated/Utils.kt | 95 ++++++ SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 100 ++---- .../src/main/kotlin/com/hexated/SoraParser.kt | 20 +- .../src/main/kotlin/com/hexated/SoraStream.kt | 10 +- .../main/kotlin/com/hexated/SoraStreamLite.kt | 10 - .../src/main/kotlin/com/hexated/SoraUtils.kt | 288 +++++------------- 9 files changed, 224 insertions(+), 342 deletions(-) create mode 100644 IdlixProvider/src/main/kotlin/com/hexated/Utils.kt diff --git a/IdlixProvider/build.gradle.kts b/IdlixProvider/build.gradle.kts index 6533b773..44b7432e 100644 --- a/IdlixProvider/build.gradle.kts +++ b/IdlixProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 12 +version = 13 cloudstream { diff --git a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt index 064c18dd..9d4afcaf 100644 --- a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt +++ b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt @@ -13,13 +13,12 @@ import org.jsoup.nodes.Element import java.net.URI class IdlixProvider : MainAPI() { - override var mainUrl = "https://tv.idlixprime.com" + override var mainUrl = "https://tv.idlixplus.net" private var directUrl = mainUrl override var name = "Idlix" override val hasMainPage = true override var lang = "id" override val hasDownloadSupport = true - private val session = Session(Requests().baseClient) override val supportedTypes = setOf( TvType.Movie, TvType.TvSeries, @@ -51,9 +50,9 @@ class IdlixProvider : MainAPI() { val url = request.data.split("?") val nonPaged = request.name == "Featured" && page <= 1 val req = if (nonPaged) { - session.get(request.data) + app.get(request.data) } else { - session.get("${url.first()}$page/?${url.lastOrNull()}") + app.get("${url.first()}$page/?${url.lastOrNull()}") } mainUrl = getBaseUrl(req.url) val document = req.document @@ -98,7 +97,7 @@ class IdlixProvider : MainAPI() { } override suspend fun search(query: String): List { - val req = session.get("$mainUrl/search/$query") + val req = app.get("$mainUrl/search/$query") mainUrl = getBaseUrl(req.url) val document = req.document return document.select("div.result-item").map { @@ -113,7 +112,7 @@ class IdlixProvider : MainAPI() { } override suspend fun load(url: String): LoadResponse { - val request = session.get(url) + val request = app.get(url) directUrl = getBaseUrl(request.url) val document = request.document val title = @@ -193,7 +192,7 @@ class IdlixProvider : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { - val document = session.get(data).document + val document = app.get(data).document val id = document.select("meta#dooplay-ajax-counter").attr("data-postid") val type = if (data.contains("/movie/")) "movie" else "tv" @@ -201,22 +200,18 @@ class IdlixProvider : MainAPI() { it.attr("data-nume") }.apmap { nume -> safeApiCall { - var source = session.post( - url = "$directUrl/wp-admin/admin-ajax.php", - data = mapOf( - "action" to "doo_player_ajax", - "post" to id, - "nume" to nume, - "type" to type - ), + val source = app.get( + url = "$directUrl/wp-json/dooplayer/v2/$id/$type/$nume", headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = data - ).let { tryParseJson(it.text) }?.embed_url ?: return@safeApiCall + ).let { tryParseJson(it.text) } ?: return@safeApiCall - if (source.startsWith("https://uservideo.xyz")) { - source = app.get(source).document.select("iframe").attr("src") + var decrypted = AesHelper.cryptoAESHandler(source.embed_url,source.key.toByteArray(), false)?.fixBloat() ?: return@safeApiCall + + if (decrypted.startsWith("https://uservideo.xyz")) { + decrypted = app.get(decrypted).document.select("iframe").attr("src") } - loadExtractor(source, directUrl, subtitleCallback, callback) + loadExtractor(decrypted, "$directUrl/", subtitleCallback, callback) } } @@ -224,9 +219,15 @@ class IdlixProvider : MainAPI() { return true } + private fun String.fixBloat() : String { + return this.replace("\"", "").replace("\\", "") + } + data class ResponseHash( @JsonProperty("embed_url") val embed_url: String, + @JsonProperty("key") val key: String, @JsonProperty("type") val type: String?, ) + } \ No newline at end of file diff --git a/IdlixProvider/src/main/kotlin/com/hexated/Utils.kt b/IdlixProvider/src/main/kotlin/com/hexated/Utils.kt new file mode 100644 index 00000000..96bb5a14 --- /dev/null +++ b/IdlixProvider/src/main/kotlin/com/hexated/Utils.kt @@ -0,0 +1,95 @@ +package com.hexated + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.ErrorLoadingException +import com.lagradost.cloudstream3.base64DecodeArray +import com.lagradost.cloudstream3.base64Encode +import com.lagradost.cloudstream3.utils.AppUtils +import java.security.DigestException +import java.security.MessageDigest +import javax.crypto.Cipher +import javax.crypto.spec.IvParameterSpec +import javax.crypto.spec.SecretKeySpec + +object AesHelper { + + fun cryptoAESHandler( + data: String, + pass: ByteArray, + encrypt: Boolean = true, + padding: String = "AES/CBC/PKCS5PADDING", + ): String? { + val parse = AppUtils.tryParseJson(data) ?: return null + val (key, iv) = generateKeyAndIv(pass, parse.s.hexToByteArray()) ?: throw ErrorLoadingException("failed to generate key") + val cipher = Cipher.getInstance(padding) + return if (!encrypt) { + cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) + String(cipher.doFinal(base64DecodeArray(parse.ct))) + } else { + cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) + base64Encode(cipher.doFinal(parse.ct.toByteArray())) + } + } + + // https://stackoverflow.com/a/41434590/8166854 + private fun generateKeyAndIv( + password: ByteArray, + salt: ByteArray, + hashAlgorithm: String = "MD5", + keyLength: Int = 32, + ivLength: Int = 16, + iterations: Int = 1 + ): List? { + + val md = MessageDigest.getInstance(hashAlgorithm) + val digestLength = md.digestLength + val targetKeySize = keyLength + ivLength + val requiredLength = (targetKeySize + digestLength - 1) / digestLength * digestLength + val generatedData = ByteArray(requiredLength) + var generatedLength = 0 + + try { + md.reset() + + while (generatedLength < targetKeySize) { + if (generatedLength > 0) + md.update( + generatedData, + generatedLength - digestLength, + digestLength + ) + + md.update(password) + md.update(salt, 0, 8) + md.digest(generatedData, generatedLength, digestLength) + + for (i in 1 until iterations) { + md.update(generatedData, generatedLength, digestLength) + md.digest(generatedData, generatedLength, digestLength) + } + + generatedLength += digestLength + } + return listOf( + generatedData.copyOfRange(0, keyLength), + generatedData.copyOfRange(keyLength, targetKeySize) + ) + } catch (e: DigestException) { + return null + } + } + + private fun String.hexToByteArray(): ByteArray { + check(length % 2 == 0) { "Must have an even length" } + return chunked(2) + .map { it.toInt(16).toByte() } + .toByteArray() + } + + private data class AesData( + @JsonProperty("ct") val ct: String, + @JsonProperty("iv") val iv: String, + @JsonProperty("s") val s: String + ) + +} \ No newline at end of file diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index a9ef66fb..71a6eef1 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 = 159 +version = 160 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 5e131676..b73e815f 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1,5 +1,6 @@ package com.hexated +import com.hexated.AesHelper.cryptoAESHandler import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson @@ -414,7 +415,7 @@ object SoraExtractor : SoraStream() { } else { "$idlixAPI/episode/$fixTitle-season-$season-episode-$episode" } - invokeWpmovies(url, subtitleCallback, callback) + invokeWpmovies(url, subtitleCallback, callback, encrypt = true) } suspend fun invokeMultimovies( @@ -455,8 +456,13 @@ object SoraExtractor : SoraStream() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, fixIframe: Boolean = false, + encrypt: Boolean = false, ) { - val res = session.get(url ?: return) + fun String.fixBloat() : String { + return this.replace("\"", "").replace("\\", "") + } + val res = app.get(url ?: return) + val headers = mapOf("X-Requested-With" to "XMLHttpRequest") val referer = getBaseUrl(res.url) val document = res.document document.select("ul#playeroptionsul > li").map { @@ -466,13 +472,21 @@ object SoraExtractor : SoraStream() { it.attr("data-type") ) }.apmap { (id, nume, type) -> - val json = session.post( + val json = if(encrypt) app.get( + url = "$referer/wp-json/dooplayer/v2/$id/$type/$nume", + headers = headers, + referer = url + ) else app.post( url = "$referer/wp-admin/admin-ajax.php", data = mapOf( "action" to "doo_player_ajax", "post" to id, "nume" to nume, "type" to type - ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = url + ), headers = headers, referer = url ) - val source = tryParseJson(json.text)?.embed_url?.let { - if (fixIframe) Jsoup.parse(it).select("IFRAME").attr("SRC") else it + val source = tryParseJson(json.text)?.let { + when { + encrypt -> cryptoAESHandler(it.embed_url,it.key.toByteArray(), false)?.fixBloat() + fixIframe -> Jsoup.parse(it.embed_url).select("IFRAME").attr("SRC") + else -> it.embed_url + } } ?: return@apmap if (!source.contains("youtube")) { loadExtractor(source, "$referer/", subtitleCallback, callback) @@ -2540,80 +2554,6 @@ object SoraExtractor : SoraStream() { } - suspend fun invokePutlocker( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - ) { - val query = if (season == null) { - title - } else { - "$title - season $season" - } - - val res = app.get("$putlockerAPI/movie/search/$query").document - val scripData = res.select("div.movies-list div.ml-item").map { - it.selectFirst("h2")?.text() to it.selectFirst("a")?.attr("href") - } - val script = if (scripData.size == 1) { - scripData.first() - } else { - scripData.find { - if (season == null) { - it.first.equals(title, true) || (it.first?.contains( - "$title", true - ) == true && it.first?.contains("$year") == true) - } else { - it.first?.contains("$title", true) == true && it.first?.contains( - "Season $season", true - ) == true - } - } - } - - val id = fixUrl(script?.second ?: return).split("-").lastOrNull()?.removeSuffix("/") - val iframe = app.get("$putlockerAPI/ajax/movie_episodes/$id") - .parsedSafe()?.html?.let { Jsoup.parse(it) }?.let { server -> - if (season == null) { - server.select("div.les-content a").map { - it.attr("data-id") to it.attr("data-server") - } - } else { - server.select("div.les-content a").map { it } - .filter { it.text().contains("Episode $episode", true) }.map { - it.attr("data-id") to it.attr("data-server") - } - } - } - - iframe?.apmap { - delay(3000) - val embedUrl = app.get("$putlockerAPI/ajax/movie_embed/${it.first}") - .parsedSafe()?.src ?: return@apmap null - val sources = extractPutlockerSources(embedUrl)?.parsedSafe() - - argamap( - { - sources?.callback(embedUrl, "Server ${it.second}", callback) - }, - { - if (!sources?.backupLink.isNullOrBlank()) { - extractPutlockerSources(sources?.backupLink)?.parsedSafe() - ?.callback( - embedUrl, "Backup ${it.second}", callback - ) - } else { - return@argamap - } - }, - ) - - } - - } - suspend fun invokeCryMovies( 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 db94285e..f01fd804 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -65,6 +65,7 @@ data class HdMovieBoxIframe( data class ResponseHash( @JsonProperty("embed_url") val embed_url: String, + @JsonProperty("key") val key: String, @JsonProperty("type") val type: String?, ) @@ -206,25 +207,6 @@ data class WatchOnlineResponse( @JsonProperty("subtitles") val subtitles: Any? = null, ) -data class PutlockerEpisodes( - @JsonProperty("html") val html: String? = null, -) - -data class PutlockerEmbed( - @JsonProperty("src") val src: String? = null, -) - -data class PutlockerSources( - @JsonProperty("file") val file: String, - @JsonProperty("label") val label: String? = null, - @JsonProperty("type") val type: String? = null, -) - -data class PutlockerResponses( - @JsonProperty("sources") val sources: ArrayList? = arrayListOf(), - @JsonProperty("backupLink") val backupLink: String? = null, -) - data class CryMoviesProxyHeaders( @JsonProperty("request") val request: Map?, ) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 16c74135..4f163d30 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -34,7 +34,6 @@ import com.hexated.SoraExtractor.invokeMoviezAdd import com.hexated.SoraExtractor.invokeNavy import com.hexated.SoraExtractor.invokeNinetv import com.hexated.SoraExtractor.invokeNowTv -import com.hexated.SoraExtractor.invokePutlocker import com.hexated.SoraExtractor.invokeRStream import com.hexated.SoraExtractor.invokeRidomovies import com.hexated.SoraExtractor.invokeShinobiMovies @@ -55,7 +54,6 @@ import com.hexated.SoraExtractor.invokeWatchsomuch import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId import com.lagradost.cloudstream3.LoadResponse.Companion.addTMDbId import com.lagradost.cloudstream3.extractors.VidSrcExtractor -import com.lagradost.cloudstream3.syncproviders.SyncIdName import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink @@ -94,7 +92,7 @@ open class SoraStream : TmdbProvider() { const val hdMovieBoxAPI = "https://hdmoviebox.net" const val dreamfilmAPI = "https://dreamfilmsw.net" const val series9API = "https://series9.cx" - const val idlixAPI = "https://tv.idlixprime.com" + const val idlixAPI = "https://tv.idlixplus.net" const val noverseAPI = "https://www.nollyverse.com" const val filmxyAPI = "https://www.filmxy.vip" const val kimcartoonAPI = "https://kimcartoon.li" @@ -102,7 +100,7 @@ open class SoraStream : TmdbProvider() { const val crunchyrollAPI = "https://beta-api.crunchyroll.com" const val kissKhAPI = "https://kisskh.co" const val lingAPI = "https://ling-online.net" - const val uhdmoviesAPI = "https://uhdmovies.actor" + const val uhdmoviesAPI = "https://uhdmovies.wiki" const val fwatayakoAPI = "https://5100.svetacdn.in" const val gMoviesAPI = "https://gdrivemovies.xyz" const val fdMoviesAPI = "https://freedrivemovie.lol" @@ -118,7 +116,6 @@ open class SoraStream : TmdbProvider() { const val ask4MoviesAPI = "https://ask4movie.nl" const val watchOnlineAPI = "https://watchonline.ag" const val nineTvAPI = "https://moviesapi.club" - const val putlockerAPI = "https://ww7.putlocker.vip" const val fmoviesAPI = "https://fmovies.to" const val nowTvAPI = "https://myfilestorage.xyz" const val gokuAPI = "https://goku.sx" @@ -545,9 +542,6 @@ open class SoraStream : TmdbProvider() { callback ) }, - { - invokePutlocker(res.title, res.year, res.season, res.episode, callback) - }, { invokeTvMovies(res.title, res.season, res.episode, callback) }, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index c5bf1a6d..ebe91e71 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -21,7 +21,6 @@ import com.hexated.SoraExtractor.invokeMovieHab import com.hexated.SoraExtractor.invokeNavy import com.hexated.SoraExtractor.invokeNinetv import com.hexated.SoraExtractor.invokeNowTv -import com.hexated.SoraExtractor.invokePutlocker import com.hexated.SoraExtractor.invokeRStream import com.hexated.SoraExtractor.invokeRidomovies import com.hexated.SoraExtractor.invokeSeries9 @@ -55,15 +54,6 @@ class SoraStreamLite : SoraStream() { val res = AppUtils.parseJson(data) argamap( - { - invokePutlocker( - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, { invokeWatchsomuch( res.imdbId, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index f256bf87..3f640572 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -1,6 +1,7 @@ package com.hexated import android.util.Base64 +import com.fasterxml.jackson.annotation.JsonProperty import com.hexated.DumpUtils.queryApi import com.hexated.SoraStream.Companion.anilistAPI import com.hexated.SoraStream.Companion.base64DecodeAPI @@ -10,7 +11,6 @@ import com.hexated.SoraStream.Companion.filmxyAPI import com.hexated.SoraStream.Companion.fmoviesAPI import com.hexated.SoraStream.Companion.gdbot import com.hexated.SoraStream.Companion.malsyncAPI -import com.hexated.SoraStream.Companion.putlockerAPI import com.hexated.SoraStream.Companion.smashyStreamAPI import com.hexated.SoraStream.Companion.tvMoviesAPI import com.hexated.SoraStream.Companion.watchOnlineAPI @@ -41,11 +41,9 @@ import javax.crypto.Cipher import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec import kotlin.collections.ArrayList -import kotlin.math.min val bflixChipperKey = base64DecodeAPI("Yjc=ejM=TzA=YTk=WHE=WnU=bXU=RFo=") const val bflixKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" -const val otakuzBaseUrl = "https://otakuz.live/" val encodedIndex = arrayOf( "GamMovies", "JSMovies", @@ -1055,52 +1053,6 @@ suspend fun getCrunchyrollIdFromMalSync(aniId: String?): String? { ?: regex.find("$crunchyroll")?.groupValues?.getOrNull(1) } -suspend fun extractPutlockerSources(url: String?): NiceResponse? { - val embedHost = url?.substringBefore("/embed-player") - val player = app.get( - url ?: return null, - referer = "${putlockerAPI}/" - ).document.select("div#player") - - val text = "\"${player.attr("data-id")}\"" - val password = player.attr("data-hash") - val cipher = CryptoAES.plEncrypt(password, text) - - return app.get( - "$embedHost/ajax/getSources/", params = mapOf( - "id" to cipher.cipherText, - "h" to cipher.password, - "a" to cipher.iv, - "t" to cipher.salt, - ), referer = url - ) -} - -suspend fun PutlockerResponses?.callback( - referer: String, - server: String, - callback: (ExtractorLink) -> Unit -) { - val ref = getBaseUrl(referer) - this?.sources?.map { source -> - val request = app.get(source.file, referer = ref) - callback.invoke( - ExtractorLink( - "Putlocker [$server]", - "Putlocker [$server]", - if (!request.isSuccessful) return@map null else source.file, - ref, - if (source.file.contains("m3u8")) getPutlockerQuality(request.text) else source.label?.replace( - Regex("[Pp]"), - "" - )?.trim()?.toIntOrNull() - ?: Qualities.P720.value, - source.file.contains("m3u8") - ) - ) - } -} - suspend fun convertTmdbToAnimeId( title: String?, date: String?, @@ -1655,161 +1607,6 @@ private enum class Symbol(val decimalValue: Int) { } } -// code found on https://stackoverflow.com/a/63701411 - -/** - * Conforming with CryptoJS AES method - */ -// see https://gist.github.com/thackerronak/554c985c3001b16810af5fc0eb5c358f -@Suppress("unused", "FunctionName", "SameParameterValue") -object CryptoAES { - - private const val KEY_SIZE = 256 - private const val IV_SIZE = 128 - private const val HASH_CIPHER = "AES/CBC/PKCS5Padding" - private const val AES = "AES" - private const val KDF_DIGEST = "MD5" - - // Seriously crypto-js, what's wrong with you? - private const val APPEND = "Salted__" - - /** - * Encrypt - * @param password passphrase - * @param plainText plain string - */ - fun encrypt(password: String, plainText: String): String { - val saltBytes = generateSalt(8) - val key = ByteArray(KEY_SIZE / 8) - val iv = ByteArray(IV_SIZE / 8) - EvpKDF(password.toByteArray(), KEY_SIZE, IV_SIZE, saltBytes, key, iv) - val keyS = SecretKeySpec(key, AES) - val cipher = Cipher.getInstance(HASH_CIPHER) - val ivSpec = IvParameterSpec(iv) - cipher.init(Cipher.ENCRYPT_MODE, keyS, ivSpec) - val cipherText = cipher.doFinal(plainText.toByteArray()) - // Thanks kientux for this: https://gist.github.com/kientux/bb48259c6f2133e628ad - // Create CryptoJS-like encrypted! - val sBytes = APPEND.toByteArray() - val b = ByteArray(sBytes.size + saltBytes.size + cipherText.size) - System.arraycopy(sBytes, 0, b, 0, sBytes.size) - System.arraycopy(saltBytes, 0, b, sBytes.size, saltBytes.size) - System.arraycopy(cipherText, 0, b, sBytes.size + saltBytes.size, cipherText.size) - val bEncode = Base64.encode(b, Base64.NO_WRAP) - return String(bEncode) - } - - fun plEncrypt(password: String, plainText: String): EncryptResult { - val saltBytes = generateSalt(8) - val key = ByteArray(KEY_SIZE / 8) - val iv = ByteArray(IV_SIZE / 8) - EvpKDF(password.toByteArray(), KEY_SIZE, IV_SIZE, saltBytes, key, iv) - val keyS = SecretKeySpec(key, AES) - val cipher = Cipher.getInstance(HASH_CIPHER) - val ivSpec = IvParameterSpec(iv) - cipher.init(Cipher.ENCRYPT_MODE, keyS, ivSpec) - val cipherText = cipher.doFinal(plainText.toByteArray()) - val bEncode = Base64.encode(cipherText, Base64.NO_WRAP) - return EncryptResult( - String(bEncode).toHex(), - password.toHex(), - saltBytes.toHex(), - iv.toHex() - ) - } - - /** - * Decrypt - * Thanks Artjom B. for this: http://stackoverflow.com/a/29152379/4405051 - * @param password passphrase - * @param cipherText encrypted string - */ - fun decrypt(password: String, cipherText: String): String { - val ctBytes = Base64.decode(cipherText.toByteArray(), Base64.NO_WRAP) - val saltBytes = Arrays.copyOfRange(ctBytes, 8, 16) - val cipherTextBytes = Arrays.copyOfRange(ctBytes, 16, ctBytes.size) - val key = ByteArray(KEY_SIZE / 8) - val iv = ByteArray(IV_SIZE / 8) - EvpKDF(password.toByteArray(), KEY_SIZE, IV_SIZE, saltBytes, key, iv) - val cipher = Cipher.getInstance(HASH_CIPHER) - val keyS = SecretKeySpec(key, AES) - cipher.init(Cipher.DECRYPT_MODE, keyS, IvParameterSpec(iv)) - val plainText = cipher.doFinal(cipherTextBytes) - return String(plainText) - } - - private fun EvpKDF( - password: ByteArray, - keySize: Int, - ivSize: Int, - salt: ByteArray, - resultKey: ByteArray, - resultIv: ByteArray - ): ByteArray { - return EvpKDF(password, keySize, ivSize, salt, 1, KDF_DIGEST, resultKey, resultIv) - } - - @Suppress("NAME_SHADOWING") - private fun EvpKDF( - password: ByteArray, - keySize: Int, - ivSize: Int, - salt: ByteArray, - iterations: Int, - hashAlgorithm: String, - resultKey: ByteArray, - resultIv: ByteArray - ): ByteArray { - val keySize = keySize / 32 - val ivSize = ivSize / 32 - val targetKeySize = keySize + ivSize - val derivedBytes = ByteArray(targetKeySize * 4) - var numberOfDerivedWords = 0 - var block: ByteArray? = null - val hash = MessageDigest.getInstance(hashAlgorithm) - while (numberOfDerivedWords < targetKeySize) { - if (block != null) { - hash.update(block) - } - hash.update(password) - block = hash.digest(salt) - hash.reset() - // Iterations - for (i in 1 until iterations) { - block = hash.digest(block!!) - hash.reset() - } - System.arraycopy( - block!!, 0, derivedBytes, numberOfDerivedWords * 4, - min(block.size, (targetKeySize - numberOfDerivedWords) * 4) - ) - numberOfDerivedWords += block.size / 4 - } - System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4) - System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4) - return derivedBytes // key + iv - } - - private fun generateSalt(length: Int): ByteArray { - return ByteArray(length).apply { - SecureRandom().nextBytes(this) - } - } - - private fun ByteArray.toHex(): String = - joinToString(separator = "") { eachByte -> "%02x".format(eachByte) } - - private fun String.toHex(): String = toByteArray().toHex() - - data class EncryptResult( - val cipherText: String, - val password: String, - val salt: String, - val iv: String - ) - -} - object DumpUtils { private val deviceId = getDeviceId() @@ -1926,4 +1723,87 @@ object RSAEncryptionHelper { exception.printStackTrace() null } +} + +object AesHelper { + + fun cryptoAESHandler( + data: String, + pass: ByteArray, + encrypt: Boolean = true, + padding: String = "AES/CBC/PKCS5PADDING", + ): String? { + val parse = AppUtils.tryParseJson(data) ?: return null + val (key, iv) = generateKeyAndIv(pass, parse.s.hexToByteArray()) ?: throw ErrorLoadingException("failed to generate key") + val cipher = Cipher.getInstance(padding) + return if (!encrypt) { + cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) + String(cipher.doFinal(base64DecodeArray(parse.ct))) + } else { + cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) + base64Encode(cipher.doFinal(parse.ct.toByteArray())) + } + } + + // https://stackoverflow.com/a/41434590/8166854 + private fun generateKeyAndIv( + password: ByteArray, + salt: ByteArray, + hashAlgorithm: String = "MD5", + keyLength: Int = 32, + ivLength: Int = 16, + iterations: Int = 1 + ): List? { + + val md = MessageDigest.getInstance(hashAlgorithm) + val digestLength = md.digestLength + val targetKeySize = keyLength + ivLength + val requiredLength = (targetKeySize + digestLength - 1) / digestLength * digestLength + val generatedData = ByteArray(requiredLength) + var generatedLength = 0 + + try { + md.reset() + + while (generatedLength < targetKeySize) { + if (generatedLength > 0) + md.update( + generatedData, + generatedLength - digestLength, + digestLength + ) + + md.update(password) + md.update(salt, 0, 8) + md.digest(generatedData, generatedLength, digestLength) + + for (i in 1 until iterations) { + md.update(generatedData, generatedLength, digestLength) + md.digest(generatedData, generatedLength, digestLength) + } + + generatedLength += digestLength + } + return listOf( + generatedData.copyOfRange(0, keyLength), + generatedData.copyOfRange(keyLength, targetKeySize) + ) + } catch (e: DigestException) { + return null + } + } + + private fun String.hexToByteArray(): ByteArray { + check(length % 2 == 0) { "Must have an even length" } + return chunked(2) + .map { it.toInt(16).toByte() } + .toByteArray() + } + + private data class AesData( + @JsonProperty("ct") val ct: String, + @JsonProperty("iv") val iv: String, + @JsonProperty("s") val s: String + ) + } \ No newline at end of file From 54dc8ce2c915b6e0ee990edddf3e709045001df2 Mon Sep 17 00:00:00 2001 From: IndusAryan <125901294+IndusAryan@users.noreply.github.com> Date: Tue, 29 Aug 2023 19:02:42 +0530 Subject: [PATCH 079/105] update: hdmovie2 and movierulz domain (#250) * Update Movierulzhd.kt * Update Hdmovie2.kt --- Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt | 4 ++-- Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt b/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt index 5fde2e77..a77991f5 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt @@ -11,7 +11,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.Jsoup class Hdmovie2 : Movierulzhd() { - override var mainUrl = "https://hdmovie2.bar" + override var mainUrl = "https://hdmovie2.media" override var name = "Hdmovie2" override val mainPage = mainPageOf( @@ -85,4 +85,4 @@ class Hdmovie2 : Movierulzhd() { @JsonProperty("embed_url") val embed_url: String, @JsonProperty("type") val type: String?, ) -} \ No newline at end of file +} diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt index 689a4f89..45529bc2 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt @@ -11,7 +11,7 @@ import org.jsoup.nodes.Element import java.net.URI open class Movierulzhd : MainAPI() { - override var mainUrl = "https://movierulzhd.gold" + override var mainUrl = "https://movierulzhd.tools" var directUrl = "" override var name = "Movierulzhd" override val hasMainPage = true From 9b2205ba89aa1f6bd3a9796450fe347d4ebb4f14 Mon Sep 17 00:00:00 2001 From: hexated Date: Wed, 30 Aug 2023 03:38:46 +0700 Subject: [PATCH 080/105] small fix --- .../src/main/kotlin/com/hexated/IdlixProvider.kt | 8 ++++---- SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt | 6 +----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt index 9d4afcaf..7c8e37de 100644 --- a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt +++ b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt @@ -200,10 +200,10 @@ class IdlixProvider : MainAPI() { it.attr("data-nume") }.apmap { nume -> safeApiCall { - val source = app.get( - url = "$directUrl/wp-json/dooplayer/v2/$id/$type/$nume", - headers = mapOf("X-Requested-With" to "XMLHttpRequest"), - referer = data + val source = app.post( + url = "$directUrl/wp-admin/admin-ajax.php", data = mapOf( + "action" to "doo_player_ajax", "post" to id, "nume" to nume, "type" to type + ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = data ).let { tryParseJson(it.text) } ?: return@safeApiCall var decrypted = AesHelper.cryptoAESHandler(source.embed_url,source.key.toByteArray(), false)?.fixBloat() ?: return@safeApiCall diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index b73e815f..56063048 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -472,11 +472,7 @@ object SoraExtractor : SoraStream() { it.attr("data-type") ) }.apmap { (id, nume, type) -> - val json = if(encrypt) app.get( - url = "$referer/wp-json/dooplayer/v2/$id/$type/$nume", - headers = headers, - referer = url - ) else app.post( + val json = app.post( url = "$referer/wp-admin/admin-ajax.php", data = mapOf( "action" to "doo_player_ajax", "post" to id, "nume" to nume, "type" to type ), headers = headers, referer = url From c40b6b272bf0c210393fd93e3a952bb834b4ce49 Mon Sep 17 00:00:00 2001 From: hexated Date: Wed, 30 Aug 2023 09:17:46 +0700 Subject: [PATCH 081/105] sora: added Jump1 & Susflix --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 74 +++++++++++++++++++ .../src/main/kotlin/com/hexated/SoraParser.kt | 30 ++++++++ .../src/main/kotlin/com/hexated/SoraStream.kt | 23 +++++- .../main/kotlin/com/hexated/SoraStreamLite.kt | 14 ++++ settings.gradle.kts | 2 +- 6 files changed, 142 insertions(+), 3 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 71a6eef1..334a826b 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 = 160 +version = 161 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 56063048..e0cf44db 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2820,6 +2820,80 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeSusflix( + tmdbId: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, + ) { + val url = if(season == null) { + "$susflixAPI/view/movie/$tmdbId" + } else { + "$susflixAPI/view/tv/$tmdbId/$season/$episode" + } + + val res = app.get(url,cookies = mapOf( + "session" to "eyJfZnJlc2giOmZhbHNlLCJwaG9uZV9udW1iZXIiOiJzdXNoZXg5OCJ9.ZO6CsA.XUs6Y5gna8ExAUX55-myMi1QpYU" + )).text.substringAfter("response = {").substringBefore("};").replace("\'", "\"") + + val sources = tryParseJson("{$res}") + sources?.qualities?.map { source -> + callback.invoke( + ExtractorLink( + "Susflix", + "Susflix", + source.path ?: return@map, + "$susflixAPI/", + getQualityFromName(source.quality) + ) + ) + } + + sources?.srtfiles?.map { sub -> + subtitleCallback.invoke( + SubtitleFile( + sub.caption ?: return@map, + sub.url ?: return@map, + ) + ) + } + + } + + suspend fun invokeJump1( + tmdbId: Int? = null, + tvdbId: Int? = null, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, + ) { + val referer = "https://jump1.net/" + val res = if(season == null) { + val body = """{"filters":[{"type":"slug","args":{"slugs":["${title.createSlug()}-$year"]}}],"sort":"addedRecent","skip":0,"limit":100}""".toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) + app.post("$jump1API/api/movies", requestBody = body, referer = referer) + } else { + app.get("$jump1API/api/shows/$tvdbId/seasons", referer = referer) + }.text + + val source = if(season == null) { + tryParseJson(res)?.movies?.find { it.id == tmdbId }?.videoId + } else { + val jumpSeason = tryParseJson>(res)?.find { it.seasonNumber == season }?.id + val seasonRes = app.get("$jump1API/api/shows/seasons/${jumpSeason ?: return}/episodes", referer = referer) + tryParseJson>(seasonRes.text)?.find { it.episodeNumber == episode }?.videoId + } + + M3u8Helper.generateM3u8( + "Jump1", + "$jump1API/hls/${source ?: return}/master.m3u8?ts=${APIHolder.unixTimeMS}", + referer + ).forEach(callback) + + } + } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index f01fd804..adb05049 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -88,11 +88,41 @@ data class KisskhDetail( @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), ) +data class SusflixSrtfiles( + @JsonProperty("caption") val caption: String? = null, + @JsonProperty("url") val url: String? = null, +) + +data class SusflixQualities( + @JsonProperty("path") val path: String? = null, + @JsonProperty("quality") val quality: String? = null, +) + +data class SusflixSources( + @JsonProperty("Qualities") val qualities: ArrayList? = arrayListOf(), + @JsonProperty("Srtfiles") val srtfiles: ArrayList? = arrayListOf(), +) + data class KisskhResults( @JsonProperty("id") val id: Int?, @JsonProperty("title") val title: String?, ) +data class Jump1Episodes( + @JsonProperty("id") val id: Any? = null, + @JsonProperty("episodeNumber") val episodeNumber: Int? = null, + @JsonProperty("videoId") val videoId: String? = null, +) + +data class Jump1Season( + @JsonProperty("seasonNumber") val seasonNumber: Int? = null, + @JsonProperty("id") val id: String? = null, +) + +data class Jump1Movies( + @JsonProperty("movies") val movies: ArrayList? = arrayListOf(), +) + data class EpisodesFwatayako( @JsonProperty("id") val id: String? = null, @JsonProperty("file") val file: String? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 4f163d30..5377dd49 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -41,11 +41,13 @@ import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeFourCartoon +import com.hexated.SoraExtractor.invokeJump1 import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokePobmovies import com.hexated.SoraExtractor.invokePrimewire +import com.hexated.SoraExtractor.invokeSusflix import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeVidsrcto @@ -132,6 +134,8 @@ open class SoraStream : TmdbProvider() { const val vidsrctoAPI = "https://vidsrc.to" const val dramadayAPI = "https://dramaday.me" const val animetoshoAPI = "https://animetosho.org" + const val susflixAPI = "https://susflix.tv" + const val jump1API = "https://ca.jump1.net" // INDEX SITE const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev" @@ -276,6 +280,7 @@ open class SoraStream : TmdbProvider() { LinkData( data.id, res.external_ids?.imdb_id, + res.external_ids?.tvdb_id, data.type, eps.seasonNumber, eps.episodeNumber, @@ -329,6 +334,7 @@ open class SoraStream : TmdbProvider() { LinkData( data.id, res.external_ids?.imdb_id, + res.external_ids?.tvdb_id, data.type, title = title, year = year, @@ -740,6 +746,20 @@ open class SoraStream : TmdbProvider() { { if(!res.isAnime) invoke2embed(res.imdbId,res.season,res.episode,callback) }, + { + invokeSusflix(res.id,res.season,res.episode,subtitleCallback,callback) + }, + { + if(!res.isAnime) invokeJump1( + res.id, + res.tvdbId, + res.title, + res.year, + res.season, + res.episode, + callback + ) + }, ) return true @@ -748,6 +768,7 @@ open class SoraStream : TmdbProvider() { data class LinkData( val id: Int? = null, val imdbId: String? = null, + val tvdbId: Int? = null, val type: String? = null, val season: Int? = null, val episode: Int? = null, @@ -852,7 +873,7 @@ open class SoraStream : TmdbProvider() { data class ExternalIds( @JsonProperty("imdb_id") val imdb_id: String? = null, - @JsonProperty("tvdb_id") val tvdb_id: String? = null, + @JsonProperty("tvdb_id") val tvdb_id: Int? = null, ) data class Credits( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index ebe91e71..239dc682 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -28,10 +28,12 @@ import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeFourCartoon +import com.hexated.SoraExtractor.invokeJump1 import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokePrimewire +import com.hexated.SoraExtractor.invokeSusflix import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeWatchOnline @@ -54,6 +56,18 @@ class SoraStreamLite : SoraStream() { val res = AppUtils.parseJson(data) argamap( + { + if(!res.isAnime) invokeJump1(res.id,res.tvdbId,res.title,res.year,res.season,res.episode,callback) + }, + { + invokeSusflix( + res.id, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, { invokeWatchsomuch( res.imdbId, diff --git a/settings.gradle.kts b/settings.gradle.kts index f2497ec2..5df21340 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,7 +2,7 @@ rootProject.name = "CloudstreamPlugins" // This file sets what projects are included. All new projects should get automatically included unless specified in "disabled" variable. -val disabled = listOf("Animixplay") +val disabled = listOf("Animixplay","Kickassanime") File(rootDir, ".").eachDir { dir -> if (!disabled.contains(dir.name) && File(dir, "build.gradle.kts").exists()) { From 54a72689026f5904995cd165cafcb79a040b5c65 Mon Sep 17 00:00:00 2001 From: hexated Date: Wed, 30 Aug 2023 14:55:22 +0700 Subject: [PATCH 082/105] small fix --- .../src/main/kotlin/com/hexated/SoraExtractor.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index e0cf44db..a99f48b3 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2886,12 +2886,16 @@ object SoraExtractor : SoraStream() { tryParseJson>(seasonRes.text)?.find { it.episodeNumber == episode }?.videoId } - M3u8Helper.generateM3u8( - "Jump1", - "$jump1API/hls/${source ?: return}/master.m3u8?ts=${APIHolder.unixTimeMS}", - referer - ).forEach(callback) - + callback.invoke( + ExtractorLink( + "Jump1", + "Jump1", + "$jump1API/hls/${source ?: return}/master.m3u8?ts=${APIHolder.unixTimeMS}", + referer, + Qualities.P1080.value, + true + ) + ) } From 610bb856c5503d9ec4a4f20ee1a985fae55a97d2 Mon Sep 17 00:00:00 2001 From: hexated Date: Wed, 30 Aug 2023 15:03:08 +0700 Subject: [PATCH 083/105] AnimeIndo: fix homepage --- AnimeIndoProvider/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/AnimeIndoProvider.kt | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/AnimeIndoProvider/build.gradle.kts b/AnimeIndoProvider/build.gradle.kts index e2cc3499..d52cf888 100644 --- a/AnimeIndoProvider/build.gradle.kts +++ b/AnimeIndoProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 12 +version = 13 cloudstream { diff --git a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt index 91f8de5e..aee7726e 100644 --- a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt +++ b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt @@ -60,22 +60,22 @@ class AnimeIndoProvider : MainAPI() { return if (uri.contains("/anime/")) { uri } else { - var title = uri.substringAfter("nonton/") + var title = uri.substringAfter("$mainUrl/") title = when { - (title.contains("-episode")) && !(title.contains("-movie")) -> Regex("(.+)-episode").find( - title - )?.groupValues?.get(1).toString() - (title.contains("-movie")) -> Regex("(.+)-movie").find(title)?.groupValues?.get( - 1 - ).toString() + (title.contains("-episode")) && !(title.contains("-movie")) -> title.substringBefore( + "-episode" + ) + + (title.contains("-movie")) -> title.substringBefore("-movie") else -> title } + "$mainUrl/anime/$title" } } private fun Element.toSearchResult(): AnimeSearchResponse { - val title = this.selectFirst("div.titlex, h2.entry-title, h4")?.text()?.trim() ?: "" + val title = this.selectFirst("div.title, h2.entry-title, h4")?.text()?.trim() ?: "" val href = getProperAnimeLink(this.selectFirst("a")!!.attr("href")) val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) val epNum = this.selectFirst("span.episode")?.ownText()?.replace(Regex("\\D"), "")?.trim() From 261e5ccaf8d4cfe33b67d499f205437e06ce9205 Mon Sep 17 00:00:00 2001 From: hexated Date: Wed, 30 Aug 2023 15:10:07 +0700 Subject: [PATCH 084/105] remove Susflix --- SoraStream/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/SoraStream.kt | 6 +++--- .../main/kotlin/com/hexated/SoraStreamLite.kt | 18 +++++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 334a826b..2e8ec58f 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 = 161 +version = 162 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 5377dd49..46add238 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -746,9 +746,9 @@ open class SoraStream : TmdbProvider() { { if(!res.isAnime) invoke2embed(res.imdbId,res.season,res.episode,callback) }, - { - invokeSusflix(res.id,res.season,res.episode,subtitleCallback,callback) - }, +// { +// invokeSusflix(res.id,res.season,res.episode,subtitleCallback,callback) +// }, { if(!res.isAnime) invokeJump1( res.id, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 239dc682..2e7d99ab 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -59,15 +59,15 @@ class SoraStreamLite : SoraStream() { { if(!res.isAnime) invokeJump1(res.id,res.tvdbId,res.title,res.year,res.season,res.episode,callback) }, - { - invokeSusflix( - res.id, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, +// { +// invokeSusflix( +// res.id, +// res.season, +// res.episode, +// subtitleCallback, +// callback +// ) +// }, { invokeWatchsomuch( res.imdbId, From 414d672109122ba34353872969593d06a58346b0 Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 1 Sep 2023 15:45:31 +0700 Subject: [PATCH 085/105] sora: fix Jeniusplay --- IdlixProvider/build.gradle.kts | 2 +- IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt | 6 +++--- SoraStream/build.gradle.kts | 2 +- SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt | 5 +++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/IdlixProvider/build.gradle.kts b/IdlixProvider/build.gradle.kts index 44b7432e..13421dec 100644 --- a/IdlixProvider/build.gradle.kts +++ b/IdlixProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 13 +version = 14 cloudstream { diff --git a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt index 7c8e37de..2763d98b 100644 --- a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt +++ b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt @@ -7,8 +7,6 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson -import com.lagradost.nicehttp.Requests -import com.lagradost.nicehttp.Session import org.jsoup.nodes.Element import java.net.URI @@ -26,6 +24,8 @@ class IdlixProvider : MainAPI() { TvType.AsianDrama ) + private val key = "\\x5a\\x6d\\x5a\\x6c\\x4e\\x7a\\x55\\x79\\x4d\\x54\\x56\\x6a\\x5a\\x47\\x52\\x69\\x5a\\x44\\x55\\x30\\x5a\\x6d\\x59\\x35\\x4f\\x57\\x45\\x33\\x4d\\x44\\x4a\\x69\\x4e\\x32\\x4a\\x6c\\x4f\\x54\\x42\\x6c\\x4e\\x7a\\x49\\x3d" + override val mainPage = mainPageOf( "$mainUrl/" to "Featured", "$mainUrl/trending/page/?get=movies" to "Trending Movies", @@ -206,7 +206,7 @@ class IdlixProvider : MainAPI() { ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = data ).let { tryParseJson(it.text) } ?: return@safeApiCall - var decrypted = AesHelper.cryptoAESHandler(source.embed_url,source.key.toByteArray(), false)?.fixBloat() ?: return@safeApiCall + var decrypted = AesHelper.cryptoAESHandler(source.embed_url,key.toByteArray(), false)?.fixBloat() ?: return@safeApiCall if (decrypted.startsWith("https://uservideo.xyz")) { decrypted = app.get(decrypted).document.select("iframe").attr("src") diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 2e8ec58f..a6a8ce22 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 = 162 +version = 163 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index a99f48b3..5efdec40 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -415,7 +415,7 @@ object SoraExtractor : SoraStream() { } else { "$idlixAPI/episode/$fixTitle-season-$season-episode-$episode" } - invokeWpmovies(url, subtitleCallback, callback, encrypt = true) + invokeWpmovies(url, subtitleCallback, callback, encrypt = true, key = "\\x5a\\x6d\\x5a\\x6c\\x4e\\x7a\\x55\\x79\\x4d\\x54\\x56\\x6a\\x5a\\x47\\x52\\x69\\x5a\\x44\\x55\\x30\\x5a\\x6d\\x59\\x35\\x4f\\x57\\x45\\x33\\x4d\\x44\\x4a\\x69\\x4e\\x32\\x4a\\x6c\\x4f\\x54\\x42\\x6c\\x4e\\x7a\\x49\\x3d") } suspend fun invokeMultimovies( @@ -457,6 +457,7 @@ object SoraExtractor : SoraStream() { callback: (ExtractorLink) -> Unit, fixIframe: Boolean = false, encrypt: Boolean = false, + key: String? = null, ) { fun String.fixBloat() : String { return this.replace("\"", "").replace("\\", "") @@ -479,7 +480,7 @@ object SoraExtractor : SoraStream() { ) val source = tryParseJson(json.text)?.let { when { - encrypt -> cryptoAESHandler(it.embed_url,it.key.toByteArray(), false)?.fixBloat() + encrypt -> cryptoAESHandler(it.embed_url,(key ?: return@apmap).toByteArray(), false)?.fixBloat() fixIframe -> Jsoup.parse(it.embed_url).select("IFRAME").attr("SRC") else -> it.embed_url } From 62d97837059205de467298b781b3a31e10f0e6bc Mon Sep 17 00:00:00 2001 From: hexated Date: Fri, 1 Sep 2023 18:15:36 +0700 Subject: [PATCH 086/105] small fix --- SoraStream/src/main/kotlin/com/hexated/SoraParser.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index adb05049..0897e838 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -65,8 +65,8 @@ data class HdMovieBoxIframe( data class ResponseHash( @JsonProperty("embed_url") val embed_url: String, - @JsonProperty("key") val key: String, - @JsonProperty("type") val type: String?, + @JsonProperty("key") val key: String? = null, + @JsonProperty("type") val type: String? = null, ) data class KisskhSources( From f511569c342031822b0597c696af9d69a2742919 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 2 Sep 2023 05:48:35 +0700 Subject: [PATCH 087/105] fix #254 --- Gomov/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 9 +- .../main/kotlin/com/hexated/GomovPlugin.kt | 1 + .../src/main/kotlin/com/hexated/Nodrakorid.kt | 38 +++++-- IdlixProvider/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/IdlixProvider.kt | 102 ++++++++++++++++-- LayarKacaProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/LayarKacaProvider.kt | 14 ++- 8 files changed, 137 insertions(+), 33 deletions(-) diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index b66e81e1..000dde9a 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 8 +version = 9 cloudstream { diff --git a/Gomov/src/main/kotlin/com/hexated/Extractors.kt b/Gomov/src/main/kotlin/com/hexated/Extractors.kt index 7017d7fa..aa629966 100644 --- a/Gomov/src/main/kotlin/com/hexated/Extractors.kt +++ b/Gomov/src/main/kotlin/com/hexated/Extractors.kt @@ -1,8 +1,11 @@ package com.hexated -import com.lagradost.cloudstream3.extractors.Filesim -import com.lagradost.cloudstream3.extractors.Gdriveplayer -import com.lagradost.cloudstream3.extractors.StreamSB +import com.lagradost.cloudstream3.extractors.* + +class Doods : DoodLaExtractor() { + override var name = "Doods" + override var mainUrl = "https://doods.pro" +} class Dutamovie21 : StreamSB() { override var name = "Dutamovie21" diff --git a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt index 975337d4..be1f392c 100644 --- a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt +++ b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt @@ -18,6 +18,7 @@ class GomovPlugin: Plugin() { registerExtractorAPI(DbGdriveplayer()) registerExtractorAPI(Dutamovie21()) registerExtractorAPI(Embedwish()) + registerExtractorAPI(Doods()) registerExtractorAPI(Lylxan()) } } \ No newline at end of file diff --git a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt index c65d6b2f..846c6ee0 100644 --- a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt +++ b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt @@ -26,16 +26,30 @@ class Nodrakorid : DutaMovie() { is TvSeriesLoadResponse -> { val doc = app.get(url).document this.comingSoon = false - this.episodes = doc.select("div.entry-content p:contains(Episode)").distinctBy { - it.text() - }.map { eps -> - val num = eps.text() - val endSibling = eps.nextElementSiblings().select("p:contains(Episode)").firstOrNull() ?: eps.nextElementSiblings().select("div.content-moviedata").firstOrNull() - val siblings = eps.nextElementSiblingsUntil(endSibling).map { ele -> - ele.ownText().filter { it.isDigit() }.toIntOrNull() to ele.select("a") - .map { it.attr("href") to it.text() } - }.filter { it.first != null } - Episode(siblings.toJson(), episode = Regex("Episode\\s?([0-9]+)").find(num)?.groupValues?.getOrNull(1)?.toIntOrNull()) + this.episodes = when { + doc.select("div.vid-episodes a, div.gmr-listseries a").isNotEmpty() -> this.episodes + doc.select("div#download").isEmpty() -> { + doc.select("div.entry-content p:contains(Episode)").distinctBy { + it.text() + }.mapNotNull { eps -> + val endSibling = eps.nextElementSiblings().select("p:contains(Episode)").firstOrNull() ?: eps.nextElementSiblings().select("div.content-moviedata").firstOrNull() + val siblings = eps.nextElementSiblingsUntil(endSibling).map { ele -> + ele.ownText().filter { it.isDigit() }.toIntOrNull() to ele.select("a") + .map { it.attr("href") to it.text() } + }.filter { it.first != null } + Episode(siblings.toJson(), episode = eps.text().toEpisode()) + } + } + else -> { + doc.select("div#download h3.title-download").mapNotNull { eps -> + val siblings = eps.nextElementSibling()?.select("li")?.map { ele -> + ele.text().filter { it.isDigit() }.toIntOrNull() to ele.select("a").map { + it.attr("href") to it.text().split(" ").first() + } + }?.filter { it.first != null } + Episode(siblings?.toJson() ?: return@mapNotNull null, episode = eps.text().toEpisode()) + } + } } } } @@ -83,6 +97,10 @@ class Nodrakorid : DutaMovie() { } } + private fun String.toEpisode() : Int? { + return Regex("(?i)Episode\\s?([0-9]+)").find(this)?.groupValues?.getOrNull(1)?.toIntOrNull() + } + private fun getBaseUrl(url: String): String { return URI(url).let { "${it.scheme}://${it.host}" diff --git a/IdlixProvider/build.gradle.kts b/IdlixProvider/build.gradle.kts index 13421dec..63fef982 100644 --- a/IdlixProvider/build.gradle.kts +++ b/IdlixProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 14 +version = 15 cloudstream { diff --git a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt index 2763d98b..cacd8e54 100644 --- a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt +++ b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt @@ -5,8 +5,12 @@ import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.mvvm.safeApiCall +import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import okhttp3.Interceptor +import okhttp3.Response +import org.jsoup.Jsoup import org.jsoup.nodes.Element import java.net.URI @@ -17,6 +21,8 @@ class IdlixProvider : MainAPI() { override val hasMainPage = true override var lang = "id" override val hasDownloadSupport = true + private val cloudflareKiller by lazy { CloudflareKiller() } + private val interceptor by lazy { CloudflareInterceptor(cloudflareKiller) } override val supportedTypes = setOf( TvType.Movie, TvType.TvSeries, @@ -50,9 +56,9 @@ class IdlixProvider : MainAPI() { val url = request.data.split("?") val nonPaged = request.name == "Featured" && page <= 1 val req = if (nonPaged) { - app.get(request.data) + app.get(request.data, interceptor = interceptor) } else { - app.get("${url.first()}$page/?${url.lastOrNull()}") + app.get("${url.first()}$page/?${url.lastOrNull()}", interceptor = interceptor) } mainUrl = getBaseUrl(req.url) val document = req.document @@ -92,12 +98,13 @@ class IdlixProvider : MainAPI() { return newMovieSearchResponse(title, href, TvType.Movie) { this.posterUrl = posterUrl this.quality = quality + posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap() } } override suspend fun search(query: String): List { - val req = app.get("$mainUrl/search/$query") + val req = app.get("$mainUrl/search/$query", interceptor = interceptor) mainUrl = getBaseUrl(req.url) val document = req.document return document.select("div.result-item").map { @@ -107,12 +114,13 @@ class IdlixProvider : MainAPI() { val posterUrl = it.selectFirst("img")!!.attr("src").toString() newMovieSearchResponse(title, href, TvType.TvSeries) { this.posterUrl = posterUrl + posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap() } } } override suspend fun load(url: String): LoadResponse { - val request = app.get(url) + val request = app.get(url, interceptor = interceptor, referer = "$directUrl/") directUrl = getBaseUrl(request.url) val document = request.document val title = @@ -141,6 +149,7 @@ class IdlixProvider : MainAPI() { val recPosterUrl = it.selectFirst("img")?.attr("src").toString() newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) { this.posterUrl = recPosterUrl + posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap() } } @@ -170,6 +179,7 @@ class IdlixProvider : MainAPI() { addActors(actors) this.recommendations = recommendations addTrailer(trailer) + posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap() } } else { newMovieLoadResponse(title, url, TvType.Movie, url) { @@ -181,6 +191,7 @@ class IdlixProvider : MainAPI() { addActors(actors) this.recommendations = recommendations addTrailer(trailer) + posterHeaders = cloudflareKiller.getCookieHeaders(mainUrl).toMap() } } } @@ -192,7 +203,7 @@ class IdlixProvider : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { - val document = app.get(data).document + val document = app.get(data, interceptor = interceptor, referer = "$directUrl/").document val id = document.select("meta#dooplay-ajax-counter").attr("data-postid") val type = if (data.contains("/movie/")) "movie" else "tv" @@ -203,15 +214,17 @@ class IdlixProvider : MainAPI() { val source = app.post( url = "$directUrl/wp-admin/admin-ajax.php", data = mapOf( "action" to "doo_player_ajax", "post" to id, "nume" to nume, "type" to type - ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = data + ), headers = mapOf("X-Requested-With" to "XMLHttpRequest"), referer = data, interceptor = interceptor ).let { tryParseJson(it.text) } ?: return@safeApiCall - var decrypted = AesHelper.cryptoAESHandler(source.embed_url,key.toByteArray(), false)?.fixBloat() ?: return@safeApiCall + val password = if(source.key?.startsWith("\\x") == true) source.key else key + var decrypted = AesHelper.cryptoAESHandler(source.embed_url, password.toByteArray(), false)?.fixBloat() ?: return@safeApiCall if (decrypted.startsWith("https://uservideo.xyz")) { decrypted = app.get(decrypted).document.select("iframe").attr("src") } - loadExtractor(decrypted, "$directUrl/", subtitleCallback, callback) + + getUrl(decrypted, "$directUrl/", subtitleCallback, callback) } } @@ -219,13 +232,84 @@ class IdlixProvider : MainAPI() { return true } + class CloudflareInterceptor(private val cloudflareKiller: CloudflareKiller): Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val request = chain.request() + val response = chain.proceed(request) + val doc = Jsoup.parse(response.peekBody(1024 * 1024).string()) + if (doc.select("title").text() == "Just a moment...") { + return cloudflareKiller.intercept(chain) + } + return response + } + } + private fun String.fixBloat() : String { return this.replace("\"", "").replace("\\", "") } + private suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val document = app.get(url, referer = "$mainUrl/").document + val hash = url.split("/").last().substringAfter("data=") + + val m3uLink = app.post( + url = "$mainUrl/player/index.php?data=$hash&do=getVideo", + data = mapOf("hash" to hash, "r" to "$referer"), + referer = referer, + headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ).parsed().videoSource + + M3u8Helper.generateM3u8( + this.name, + m3uLink, + "$referer", + ).forEach(callback) + + + document.select("script").map { script -> + if (script.data().contains("eval(function(p,a,c,k,e,d)")) { + val subData = + getAndUnpack(script.data()).substringAfter("\"tracks\":[").substringBefore("],") + tryParseJson>("[$subData]")?.map { subtitle -> + subtitleCallback.invoke( + SubtitleFile( + getLanguage(subtitle.label ?: ""), + subtitle.file + ) + ) + } + } + } + } + + private fun getLanguage(str: String): String { + return when { + str.contains("indonesia", true) || str + .contains("bahasa", true) -> "Indonesian" + else -> str + } + } + + data class ResponseSource( + @JsonProperty("hls") val hls: Boolean, + @JsonProperty("videoSource") val videoSource: String, + @JsonProperty("securedLink") val securedLink: String?, + ) + + data class Tracks( + @JsonProperty("kind") val kind: String?, + @JsonProperty("file") val file: String, + @JsonProperty("label") val label: String?, + ) + data class ResponseHash( @JsonProperty("embed_url") val embed_url: String, - @JsonProperty("key") val key: String, + @JsonProperty("key") val key: String?, @JsonProperty("type") val type: String?, ) diff --git a/LayarKacaProvider/build.gradle.kts b/LayarKacaProvider/build.gradle.kts index 7ec4087a..0be264f6 100644 --- a/LayarKacaProvider/build.gradle.kts +++ b/LayarKacaProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 15 +version = 16 cloudstream { diff --git a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt index a4055e54..cbccb55d 100644 --- a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt +++ b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt @@ -9,7 +9,7 @@ import org.jsoup.nodes.Element import java.net.URLDecoder class LayarKacaProvider : MainAPI() { - override var mainUrl = "https://tv1.lk21official.pro" + override var mainUrl = "https://tv3.lk21official.pro" private var seriesUrl = "https://tv1.nontondrama.click" override var name = "LayarKaca" override val hasMainPage = true @@ -72,11 +72,11 @@ class LayarKacaProvider : MainAPI() { } override suspend fun search(query: String): List { - val document = app.get("$mainUrl/?s=$query").document - return document.select("div.search-item").map { - val title = it.selectFirst("h2 > a")!!.text().trim() - val href = fixUrl(it.selectFirst("a")!!.attr("href")) - val posterUrl = fixUrl(it.selectFirst("img.img-thumbnail")?.attr("src").toString()) + val document = app.get("$mainUrl/search.php?s=$query").document + return document.select("div.search-item").mapNotNull { + val title = it.selectFirst("a")?.attr("title") ?: "" + val href = fixUrl(it.selectFirst("a")?.attr("href") ?: return@mapNotNull null) + val posterUrl = fixUrlNull(it.selectFirst("img.img-thumbnail")?.attr("src")) newTvSeriesSearchResponse(title, href, TvType.TvSeries) { this.posterUrl = posterUrl } @@ -172,8 +172,6 @@ class LayarKacaProvider : MainAPI() { return app.get(this, referer = "$seriesUrl/").document.select("div.embed iframe").attr("src") } - private fun decode(input: String): String = URLDecoder.decode(input, "utf-8").replace(" ", "%20") - } open class Emturbovid : ExtractorApi() { From 1affe156b1d0fb086b727733ef04b10f388a7e29 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 2 Sep 2023 06:42:34 +0700 Subject: [PATCH 088/105] . --- IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt index cacd8e54..d103bad9 100644 --- a/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt +++ b/IdlixProvider/src/main/kotlin/com/hexated/IdlixProvider.kt @@ -254,7 +254,7 @@ class IdlixProvider : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { - val document = app.get(url, referer = "$mainUrl/").document + val document = app.get(url, referer = referer).document val hash = url.split("/").last().substringAfter("data=") val m3uLink = app.post( From 471a1703a335e7bf6061dc71f4887a0fdded2bda Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 3 Sep 2023 09:12:38 +0700 Subject: [PATCH 089/105] fix #245 --- Gomov/build.gradle.kts | 4 +- .../main/kotlin/com/hexated/GomovPlugin.kt | 1 + .../src/main/kotlin/com/hexated/Multiplex.kt | 15 ++ Minioppai/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 5 + .../kotlin/com/hexated/MinioppaiPlugin.kt | 1 + MultiplexProvider/build.gradle.kts | 27 --- .../src/main/AndroidManifest.xml | 2 - .../kotlin/com/hexated/MultiplexProvider.kt | 188 ------------------ .../com/hexated/MultiplexProviderPlugin.kt | 14 -- OploverzProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 45 +++++ .../kotlin/com/hexated/OploverzProvider.kt | 2 +- .../com/hexated/OploverzProviderPlugin.kt | 1 + 14 files changed, 73 insertions(+), 236 deletions(-) create mode 100644 Gomov/src/main/kotlin/com/hexated/Multiplex.kt delete mode 100644 MultiplexProvider/build.gradle.kts delete mode 100644 MultiplexProvider/src/main/AndroidManifest.xml delete mode 100644 MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProvider.kt delete mode 100644 MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProviderPlugin.kt create mode 100644 OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index 000dde9a..a811b0e8 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,12 +1,12 @@ // use an integer for version numbers -version = 9 +version = 10 cloudstream { language = "id" // All of these properties are optional, you can safely remove them - description = "Includes: DutaMovie, Ngefilm, Nodrakorid" + description = "Includes: DutaMovie, Ngefilm, Nodrakorid, Multiplex" authors = listOf("Hexated") /** diff --git a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt index be1f392c..8ee692f2 100644 --- a/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt +++ b/Gomov/src/main/kotlin/com/hexated/GomovPlugin.kt @@ -13,6 +13,7 @@ class GomovPlugin: Plugin() { registerMainAPI(DutaMovie()) registerMainAPI(Ngefilm()) registerMainAPI(Nodrakorid()) + registerMainAPI(Multiplex()) registerExtractorAPI(FilelionsTo()) registerExtractorAPI(Likessb()) registerExtractorAPI(DbGdriveplayer()) diff --git a/Gomov/src/main/kotlin/com/hexated/Multiplex.kt b/Gomov/src/main/kotlin/com/hexated/Multiplex.kt new file mode 100644 index 00000000..e45af7d2 --- /dev/null +++ b/Gomov/src/main/kotlin/com/hexated/Multiplex.kt @@ -0,0 +1,15 @@ +package com.hexated + +import com.lagradost.cloudstream3.mainPageOf + +class Multiplex : DutaMovie() { + override var mainUrl = "http://5.104.81.46" + override var name = "Multiplex" + + override val mainPage = mainPageOf( + "country/usa/page/%d/" to "Movie", + "west-series/page/%d/" to "West Series", + "nonton-drama-korea/page/%d/" to "Drama Korea", + ) + +} \ No newline at end of file diff --git a/Minioppai/build.gradle.kts b/Minioppai/build.gradle.kts index 368ffe23..efcdc659 100644 --- a/Minioppai/build.gradle.kts +++ b/Minioppai/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 6 +version = 7 cloudstream { diff --git a/Minioppai/src/main/kotlin/com/hexated/Extractors.kt b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt index 95b96d9e..de2f8520 100644 --- a/Minioppai/src/main/kotlin/com/hexated/Extractors.kt +++ b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt @@ -16,6 +16,11 @@ class Paistream : Streampai() { override val mainUrl = "https://paistream.my.id" } +class TvMinioppai : Streampai() { + override val name = "Tv.Minioppai" + override val mainUrl = "https://tv.minioppai.org" +} + open class Streampai : ExtractorApi() { override val name = "Streampai" override val mainUrl = "https://streampai.my.id" diff --git a/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt b/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt index 83fbd781..5832d055 100644 --- a/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt +++ b/Minioppai/src/main/kotlin/com/hexated/MinioppaiPlugin.kt @@ -11,5 +11,6 @@ class MinioppaiPlugin: Plugin() { registerMainAPI(Minioppai()) registerExtractorAPI(Streampai()) registerExtractorAPI(Paistream()) + registerExtractorAPI(TvMinioppai()) } } \ No newline at end of file diff --git a/MultiplexProvider/build.gradle.kts b/MultiplexProvider/build.gradle.kts deleted file mode 100644 index 51ca5d94..00000000 --- a/MultiplexProvider/build.gradle.kts +++ /dev/null @@ -1,27 +0,0 @@ -// use an integer for version numbers -version = 2 - - -cloudstream { - language = "id" - // All of these properties are optional, you can safely remove them - - // description = "Lorem Ipsum" - authors = listOf("Hexated") - - /** - * Status int as the following: - * 0: Down - * 1: Ok - * 2: Slow - * 3: Beta only - * */ - status = 1 // will be 3 if unspecified - tvTypes = listOf( - "AsianDrama", - "TvSeries", - "Movie", - ) - - iconUrl = "https://www.google.com/s2/favicons?domain=146.19.24.137&sz=%size%" -} \ No newline at end of file diff --git a/MultiplexProvider/src/main/AndroidManifest.xml b/MultiplexProvider/src/main/AndroidManifest.xml deleted file mode 100644 index c98063f8..00000000 --- a/MultiplexProvider/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProvider.kt b/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProvider.kt deleted file mode 100644 index 7a76be91..00000000 --- a/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProvider.kt +++ /dev/null @@ -1,188 +0,0 @@ -package com.hexated - -import com.fasterxml.jackson.annotation.JsonProperty -import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.LoadResponse.Companion.addActors -import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer -import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.getQualityFromName -import org.jsoup.nodes.Element - -class MultiplexProvider : MainAPI() { - override var mainUrl = "http://5.104.81.46" - override var name = "Multiplex" - override val hasMainPage = true - override var lang = "id" - override val hasDownloadSupport = true - override val supportedTypes = setOf( - TvType.Movie, - TvType.TvSeries, - TvType.AsianDrama - ) - - override val mainPage = mainPageOf( - "$mainUrl/genre/top-popular-movies/page/" to "Top Popolar Movies", - "$mainUrl/genre/series-ongoing/page/" to "Series Ongoing", - "$mainUrl/genre/series-barat/page/" to "Series Barat", - "$mainUrl/genre/series-korea/page/" to "Series Korea", - ) - - override suspend fun getMainPage( - page: Int, - request: MainPageRequest - ): HomePageResponse { - val document = app.get(request.data + page).document - val home = document.select("article.item").mapNotNull { - it.toSearchResult() - } - return newHomePageResponse(request.name, home) - } - - private fun Element.toSearchResult(): SearchResponse? { - val title = this.selectFirst("h2.entry-title > a")?.text()?.trim() ?: return null - val href = fixUrl(this.selectFirst("a")!!.attr("href")) - val posterUrl = fixUrlNull(this.selectFirst("a > img")?.attr("data-src")) - val quality = this.select("div.gmr-quality-item > a").text().trim() - return if (quality.isEmpty()) { - val episode = this.select("div.gmr-numbeps > span").text().toIntOrNull() - newAnimeSearchResponse(title, href, TvType.TvSeries) { - this.posterUrl = posterUrl - addSub(episode) - } - } else { - newMovieSearchResponse(title, href, TvType.Movie) { - this.posterUrl = posterUrl - addQuality(quality) - } - } - } - - private fun Element.toBottomSearchResult(): SearchResponse? { - val title = this.selectFirst("a > span.idmuvi-rp-title")?.text()?.trim() ?: return null - val href = this.selectFirst("a")!!.attr("href") - val posterUrl = fixUrl(this.selectFirst("a > img")?.attr("data-src").toString()) - return newMovieSearchResponse(title, href, TvType.Movie) { - this.posterUrl = posterUrl - } - } - - override suspend fun search(query: String): List { - val link = "$mainUrl/?s=$query&post_type[]=post&post_type[]=tv" - val document = app.get(link).document - return document.select("article.item").mapNotNull { - it.toSearchResult() - } - } - - override suspend fun load(url: String): LoadResponse { - val document = app.get(url).document - - val title = - document.selectFirst("h1.entry-title")?.text()?.substringBefore("Season")?.trim() - .toString() - val poster = - fixUrl(document.selectFirst("figure.pull-left > img")?.attr("data-src").toString()) - val tags = document.select("span.gmr-movie-genre:contains(Genre:) > a").map { it.text() } - - val year = - document.select("span.gmr-movie-genre:contains(Year:) > a").text().trim().toIntOrNull() - val tvType = if (url.contains("/tv/")) TvType.TvSeries else TvType.Movie - val description = document.selectFirst("div[itemprop=description] > p")?.text()?.trim() - val trailer = document.selectFirst("ul.gmr-player-nav li a.gmr-trailer-popup")?.attr("href") - val rating = - document.selectFirst("div.gmr-meta-rating > span[itemprop=ratingValue]")?.text() - ?.toRatingInt() - val actors = document.select("div.gmr-moviedata").last()?.select("span[itemprop=actors]") - ?.map { it.select("a").text() } - - val recommendations = document.select("div.idmuvi-rp ul li").mapNotNull { - it.toBottomSearchResult() - } - - return if (tvType == TvType.TvSeries) { - val episodes = document.select("div.gmr-listseries > a").map { - val href = fixUrl(it.attr("href")) - val episode = it.text().split(" ").last().toIntOrNull() - val season = it.text().split(" ").first().substringAfter("S").toIntOrNull() - Episode( - href, - "Episode $episode", - season, - episode, - ) - } - newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { - this.posterUrl = poster - this.year = year - this.plot = description - this.tags = tags - this.rating = rating - addActors(actors) - this.recommendations = recommendations - addTrailer(trailer) - } - } else { - newMovieLoadResponse(title, url, TvType.Movie, url) { - this.posterUrl = poster - this.year = year - this.plot = description - this.tags = tags - this.rating = rating - addActors(actors) - this.recommendations = recommendations - addTrailer(trailer) - } - } - } - - private data class ResponseSource( - @JsonProperty("file") val file: String, - @JsonProperty("type") val type: String?, - @JsonProperty("label") val label: String? - ) - - override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ): Boolean { - - val document = app.get(data).document - - val id = document.selectFirst("div#muvipro_player_content_id")!!.attr("data-id") - val server = app.post( - "$mainUrl/wp-admin/admin-ajax.php", - data = mapOf("action" to "muvipro_player_content", "tab" to "player1", "post_id" to id) - ).document.select("iframe").attr("src") - - app.get(server, referer = "$mainUrl/").document.select("script").map { script -> - if (script.data().contains("var config = {")) { - val source = script.data().substringAfter("sources: [").substringBefore("],") - tryParseJson>("[$source]")?.map { m3u -> - val m3uData = app.get(m3u.file, referer = "https://gdriveplayer.link/").text - val quality = - Regex("\\d{3,4}\\.m3u8").findAll(m3uData).map { it.value }.toList() - quality.forEach { - callback.invoke( - ExtractorLink( - source = name, - name = name, - url = m3u.file.replace("video.m3u8", it), - referer = "https://gdriveplayer.link/", - quality = getQualityFromName("${it.replace(".m3u8", "")}p"), - isM3u8 = true - ) - ) - } - } - } - } - - return true - - } - - -} \ No newline at end of file diff --git a/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProviderPlugin.kt b/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProviderPlugin.kt deleted file mode 100644 index f689b83f..00000000 --- a/MultiplexProvider/src/main/kotlin/com/hexated/MultiplexProviderPlugin.kt +++ /dev/null @@ -1,14 +0,0 @@ - -package com.hexated - -import com.lagradost.cloudstream3.plugins.CloudstreamPlugin -import com.lagradost.cloudstream3.plugins.Plugin -import android.content.Context - -@CloudstreamPlugin -class MultiplexProviderPlugin: Plugin() { - override fun load(context: Context) { - // All providers should be added in this manner. Please don't edit the providers list directly. - registerMainAPI(MultiplexProvider()) - } -} \ No newline at end of file diff --git a/OploverzProvider/build.gradle.kts b/OploverzProvider/build.gradle.kts index 036ff106..1f615de5 100644 --- a/OploverzProvider/build.gradle.kts +++ b/OploverzProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 21 +version = 22 cloudstream { diff --git a/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt b/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt new file mode 100644 index 00000000..c38c13b8 --- /dev/null +++ b/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt @@ -0,0 +1,45 @@ +package com.hexated + +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.* + +open class Qiwi : ExtractorApi() { + override val name = "Qiwi" + override val mainUrl = "https://qiwi.gg" + override val requiresReferer = true + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val document = app.get(url, referer = referer).document + val title = document.select("title").text() + val source = document.select("video source").attr("src") + + callback.invoke( + ExtractorLink( + this.name, + this.name, + source, + "$mainUrl/", + getIndexQuality(title), + headers = mapOf( + "Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5", + "Range" to "bytes=0-", + "Sec-Fetch-Dest" to "video", + "Sec-Fetch-Mode" to "no-cors", + ) + ) + ) + + } + + private fun getIndexQuality(str: String): Int { + return Regex("(\\d{3,4})[pP]").find(str)?.groupValues?.getOrNull(1)?.toIntOrNull() + ?: Qualities.Unknown.value + } + +} \ No newline at end of file diff --git a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt index 26cac833..042e62f8 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt @@ -6,7 +6,7 @@ import com.lagradost.cloudstream3.utils.* import org.jsoup.nodes.Element class OploverzProvider : MainAPI() { - override var mainUrl = "https://oploverz.team" + override var mainUrl = "https://oploverz.red" override var name = "Oploverz" override val hasMainPage = true override var lang = "id" diff --git a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProviderPlugin.kt b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProviderPlugin.kt index 157869bd..ba7c0b85 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProviderPlugin.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProviderPlugin.kt @@ -10,5 +10,6 @@ class OploverzProviderPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(OploverzProvider()) + registerExtractorAPI(Qiwi()) } } \ No newline at end of file From dd612e12bcebe2c13cf242bdaabaa8b3a75fcae1 Mon Sep 17 00:00:00 2001 From: hexated Date: Sat, 9 Sep 2023 19:16:04 +0700 Subject: [PATCH 090/105] update few providers --- Animasu/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Animasu.kt | 4 +- AnimeSailProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/AnimeSailProvider.kt | 41 +++- Aniworld/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Aniworld.kt | 2 +- Gomov/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Nodrakorid.kt | 4 +- Hdfilmcehennemi/build.gradle.kts | 2 +- .../kotlin/com/hexated/Hdfilmcehennemi.kt | 2 +- KuronimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/KuronimeProvider.kt | 102 +--------- Minioppai/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 2 +- .../src/main/kotlin/com/hexated/Minioppai.kt | 2 +- Nekopoi/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Nekopoi.kt | 4 +- Nimegami/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Nimegami.kt | 2 +- OploverzProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/OploverzProvider.kt | 2 +- OtakudesuProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/OtakudesuProvider.kt | 2 +- Samehadaku/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Samehadaku.kt | 2 +- SoraStream/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 162 +++++++++++++++ .../main/kotlin/com/hexated/SoraExtractor.kt | 64 ++---- .../src/main/kotlin/com/hexated/SoraStream.kt | 4 +- .../main/kotlin/com/hexated/SoraStreamLite.kt | 2 +- .../kotlin/com/hexated/SoraStreamPlugin.kt | 1 + .../src/main/kotlin/com/hexated/SoraUtils.kt | 188 +++++++++++------- 32 files changed, 370 insertions(+), 248 deletions(-) create mode 100644 SoraStream/src/main/kotlin/com/hexated/Extractors.kt diff --git a/Animasu/build.gradle.kts b/Animasu/build.gradle.kts index 4b81579b..4c3d51d1 100644 --- a/Animasu/build.gradle.kts +++ b/Animasu/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 1 +version = 2 cloudstream { diff --git a/Animasu/src/main/kotlin/com/hexated/Animasu.kt b/Animasu/src/main/kotlin/com/hexated/Animasu.kt index e693a672..e6e38833 100644 --- a/Animasu/src/main/kotlin/com/hexated/Animasu.kt +++ b/Animasu/src/main/kotlin/com/hexated/Animasu.kt @@ -150,8 +150,8 @@ class Animasu : MainAPI() { link.name, link.url, link.referer, - if(!link.isM3u8) getIndexQuality(quality) else link.quality, - link.isM3u8, + if(link.type != ExtractorLinkType.M3U8) getIndexQuality(quality) else link.quality, + link.type, link.headers, link.extractorData ) diff --git a/AnimeSailProvider/build.gradle.kts b/AnimeSailProvider/build.gradle.kts index d0914891..73173634 100644 --- a/AnimeSailProvider/build.gradle.kts +++ b/AnimeSailProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 8 +version = 9 cloudstream { diff --git a/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt b/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt index 45094af4..da62e664 100644 --- a/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt +++ b/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt @@ -3,6 +3,7 @@ package com.hexated import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.ExtractorLinkType import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.nicehttp.NiceResponse @@ -144,7 +145,7 @@ class AnimeSailProvider : MainAPI() { Jsoup.parse(base64Decode(it.attr("data-em"))).select("iframe").attr("src") ?: throw ErrorLoadingException("No iframe found") ) - + val quality = getIndexQuality(it.text()) when { iframe.startsWith("$mainUrl/utils/player/arch/") || iframe.startsWith( "$mainUrl/utils/player/race/" @@ -156,15 +157,13 @@ class AnimeSailProvider : MainAPI() { iframe.contains("/race/") -> "Race" else -> this.name } - val quality = - Regex("\\.(\\d{3,4})\\.").find(link)?.groupValues?.get(1) callback.invoke( ExtractorLink( source = source, name = source, url = link, referer = mainUrl, - quality = quality?.toIntOrNull() ?: Qualities.Unknown.value + quality = quality ) ) } @@ -175,16 +174,16 @@ class AnimeSailProvider : MainAPI() { val link = "https://rasa-cintaku-semakin-berantai.xyz/v/${ iframe.substringAfter("id=").substringBefore("&token") }" - loadExtractor(link, mainUrl, subtitleCallback, callback) + loadFixedExtractor(link, quality, mainUrl, subtitleCallback, callback) } iframe.startsWith("$mainUrl/utils/player/framezilla/") || iframe.startsWith("https://uservideo.xyz") -> { request(iframe, ref = data).document.select("iframe").attr("src") .let { link -> - loadExtractor(fixUrl(link), mainUrl, subtitleCallback, callback) + loadFixedExtractor(fixUrl(link), quality, mainUrl, subtitleCallback, callback) } } else -> { - loadExtractor(iframe, mainUrl, subtitleCallback, callback) + loadFixedExtractor(iframe, quality, mainUrl, subtitleCallback, callback) } } } @@ -193,4 +192,32 @@ class AnimeSailProvider : MainAPI() { return true } + private suspend fun loadFixedExtractor( + url: String, + quality: Int?, + referer: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + loadExtractor(url, referer, subtitleCallback) { link -> + callback.invoke( + ExtractorLink( + link.name, + link.name, + link.url, + link.referer, + if(link.type == ExtractorLinkType.M3U8) link.quality else quality ?: Qualities.Unknown.value, + link.type, + link.headers, + link.extractorData + ) + ) + } + } + + private fun getIndexQuality(str: String): Int { + return Regex("(\\d{3,4})[pP]").find(str)?.groupValues?.getOrNull(1)?.toIntOrNull() + ?: Qualities.Unknown.value + } + } \ No newline at end of file diff --git a/Aniworld/build.gradle.kts b/Aniworld/build.gradle.kts index d303a028..86c61272 100644 --- a/Aniworld/build.gradle.kts +++ b/Aniworld/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 5 +version = 6 cloudstream { diff --git a/Aniworld/src/main/kotlin/com/hexated/Aniworld.kt b/Aniworld/src/main/kotlin/com/hexated/Aniworld.kt index a5c6b08f..f55ac59e 100644 --- a/Aniworld/src/main/kotlin/com/hexated/Aniworld.kt +++ b/Aniworld/src/main/kotlin/com/hexated/Aniworld.kt @@ -158,7 +158,7 @@ open class Aniworld : MainAPI() { link.url, link.referer, link.quality, - link.isM3u8, + link.type, link.headers, link.extractorData ) diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index a811b0e8..cae88ee2 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 10 +version = 11 cloudstream { diff --git a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt index 846c6ee0..afc8e4da 100644 --- a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt +++ b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt @@ -121,8 +121,8 @@ class Nodrakorid : DutaMovie() { link.name, link.url, link.referer, - if(link.isM3u8) link.quality else quality ?: Qualities.Unknown.value, - link.isM3u8, + if(link.type == ExtractorLinkType.M3U8) link.quality else quality ?: Qualities.Unknown.value, + link.type, link.headers, link.extractorData ) diff --git a/Hdfilmcehennemi/build.gradle.kts b/Hdfilmcehennemi/build.gradle.kts index 991be08d..3b75abc6 100644 --- a/Hdfilmcehennemi/build.gradle.kts +++ b/Hdfilmcehennemi/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 10 +version = 11 cloudstream { diff --git a/Hdfilmcehennemi/src/main/kotlin/com/hexated/Hdfilmcehennemi.kt b/Hdfilmcehennemi/src/main/kotlin/com/hexated/Hdfilmcehennemi.kt index 9e80daaa..cce3f58e 100644 --- a/Hdfilmcehennemi/src/main/kotlin/com/hexated/Hdfilmcehennemi.kt +++ b/Hdfilmcehennemi/src/main/kotlin/com/hexated/Hdfilmcehennemi.kt @@ -213,7 +213,7 @@ class Hdfilmcehennemi : MainAPI() { link.url, link.referer, link.quality, - link.isM3u8, + link.type, link.headers, link.extractorData ) diff --git a/KuronimeProvider/build.gradle.kts b/KuronimeProvider/build.gradle.kts index a4fc0461..74ca1975 100644 --- a/KuronimeProvider/build.gradle.kts +++ b/KuronimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 14 +version = 15 cloudstream { diff --git a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt index 14a24c6c..9160beb0 100644 --- a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt +++ b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt @@ -3,6 +3,7 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer +import com.lagradost.cloudstream3.extractors.helper.AesHelper import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.Qualities @@ -10,12 +11,7 @@ import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element import java.net.URI -import java.security.DigestException -import java.security.MessageDigest import java.util.ArrayList -import javax.crypto.Cipher -import javax.crypto.spec.IvParameterSpec -import javax.crypto.spec.SecretKeySpec class KuronimeProvider : MainAPI() { override var mainUrl = "https://45.12.2.26" @@ -186,10 +182,11 @@ class KuronimeProvider : MainAPI() { argamap( { - val decrypt = cryptoAES( - servers?.src ?: return@argamap, + val decrypt = AesHelper.cryptoAESHandler( + base64Decode(servers?.src ?: return@argamap), KEY.toByteArray(), - false + false, + "AES/CBC/NoPadding" ) val source = tryParseJson(decrypt?.toJsonFormat())?.src?.replace("\\", "") @@ -206,10 +203,11 @@ class KuronimeProvider : MainAPI() { ) }, { - val decrypt = cryptoAES( - servers?.mirror ?: return@argamap, + val decrypt = AesHelper.cryptoAESHandler( + base64Decode(servers?.mirror ?: return@argamap), KEY.toByteArray(), - false + false, + "AES/CBC/NoPadding" ) tryParseJson(decrypt)?.embed?.map { embed -> embed.value.apmap { @@ -249,7 +247,7 @@ class KuronimeProvider : MainAPI() { link.url, link.referer, getQualityFromName(quality), - link.isM3u8, + link.type, link.headers, link.extractorData ) @@ -263,86 +261,6 @@ class KuronimeProvider : MainAPI() { } } - // https://stackoverflow.com/a/41434590/8166854 - private fun generateKeyAndIv( - password: ByteArray, - salt: ByteArray, - hashAlgorithm: String = "MD5", - keyLength: Int = 32, - ivLength: Int = 16, - iterations: Int = 1 - ): List? { - - val md = MessageDigest.getInstance(hashAlgorithm) - val digestLength = md.digestLength - val targetKeySize = keyLength + ivLength - val requiredLength = (targetKeySize + digestLength - 1) / digestLength * digestLength - val generatedData = ByteArray(requiredLength) - var generatedLength = 0 - - try { - md.reset() - - while (generatedLength < targetKeySize) { - if (generatedLength > 0) - md.update( - generatedData, - generatedLength - digestLength, - digestLength - ) - - md.update(password) - md.update(salt, 0, 8) - md.digest(generatedData, generatedLength, digestLength) - - for (i in 1 until iterations) { - md.update(generatedData, generatedLength, digestLength) - md.digest(generatedData, generatedLength, digestLength) - } - - generatedLength += digestLength - } - return listOf( - generatedData.copyOfRange(0, keyLength), - generatedData.copyOfRange(keyLength, targetKeySize) - ) - } catch (e: DigestException) { - return null - } - } - - private fun String.decodeHex(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - return chunked(2) - .map { it.toInt(16).toByte() } - .toByteArray() - } - - private fun cryptoAES( - data: String, - pass: ByteArray, - encrypt: Boolean = true - ): String? { - val json = tryParseJson(base64Decode(data)) - ?: throw ErrorLoadingException("No Data Found") - val (key, iv) = generateKeyAndIv(pass, json.s.decodeHex()) ?: return null - val cipher = Cipher.getInstance("AES/CBC/NoPadding") - return if (!encrypt) { - cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) - String(cipher.doFinal(base64DecodeArray(json.ct))) - } else { - cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) - base64Encode(cipher.doFinal(json.ct.toByteArray())) - - } - } - - data class AesData( - @JsonProperty("ct") val ct: String, - @JsonProperty("iv") val iv: String, - @JsonProperty("s") val s: String - ) - data class Mirrors( @JsonProperty("embed") val embed: Map> = emptyMap(), ) diff --git a/Minioppai/build.gradle.kts b/Minioppai/build.gradle.kts index efcdc659..ee49ee06 100644 --- a/Minioppai/build.gradle.kts +++ b/Minioppai/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 7 +version = 8 cloudstream { diff --git a/Minioppai/src/main/kotlin/com/hexated/Extractors.kt b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt index de2f8520..6a82e5d3 100644 --- a/Minioppai/src/main/kotlin/com/hexated/Extractors.kt +++ b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt @@ -17,7 +17,7 @@ class Paistream : Streampai() { } class TvMinioppai : Streampai() { - override val name = "Tv.Minioppai" + override val name = "Minioppai" override val mainUrl = "https://tv.minioppai.org" } diff --git a/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt b/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt index 0a263379..2dc220a1 100644 --- a/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt +++ b/Minioppai/src/main/kotlin/com/hexated/Minioppai.kt @@ -47,7 +47,7 @@ class Minioppai : MainAPI() { override val mainPage = mainPageOf( "$mainUrl/watch" to "New Episode", - "$mainUrl/popular" to "Popular Hentai", + "$mainUrl/populars" to "Popular Hentai", ) override suspend fun getMainPage( diff --git a/Nekopoi/build.gradle.kts b/Nekopoi/build.gradle.kts index 0d3c4901..809c2b60 100644 --- a/Nekopoi/build.gradle.kts +++ b/Nekopoi/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 5 +version = 6 cloudstream { diff --git a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt index c9a00826..124595b6 100644 --- a/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt +++ b/Nekopoi/src/main/kotlin/com/hexated/Nekopoi.kt @@ -170,8 +170,8 @@ class Nekopoi : MainAPI() { link.name, link.url, link.referer, - if (link.isM3u8) link.quality else it.first, - link.isM3u8, + if (link.type == ExtractorLinkType.M3U8) link.quality else it.first, + link.type, link.headers, link.extractorData ) diff --git a/Nimegami/build.gradle.kts b/Nimegami/build.gradle.kts index f4617aee..afc730a5 100644 --- a/Nimegami/build.gradle.kts +++ b/Nimegami/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt index a2ed9aaf..3143bc15 100644 --- a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt +++ b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt @@ -164,7 +164,7 @@ class Nimegami : MainAPI() { link.url, link.referer, getQualityFromName(quality), - link.isM3u8, + link.type, link.headers, link.extractorData ) diff --git a/OploverzProvider/build.gradle.kts b/OploverzProvider/build.gradle.kts index 1f615de5..3b5d9597 100644 --- a/OploverzProvider/build.gradle.kts +++ b/OploverzProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 22 +version = 23 cloudstream { diff --git a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt index 042e62f8..92547017 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt @@ -195,7 +195,7 @@ class OploverzProvider : MainAPI() { link.url, link.referer, name.fixQuality(), - link.isM3u8, + link.type, link.headers, link.extractorData ) diff --git a/OtakudesuProvider/build.gradle.kts b/OtakudesuProvider/build.gradle.kts index 2f4a7f48..39e00b68 100644 --- a/OtakudesuProvider/build.gradle.kts +++ b/OtakudesuProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 13 +version = 14 cloudstream { diff --git a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt index 3bc73926..0a4b0dd3 100644 --- a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt +++ b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt @@ -236,7 +236,7 @@ class OtakudesuProvider : MainAPI() { link.url, link.referer, quality, - link.isM3u8, + link.type, link.headers, link.extractorData ) diff --git a/Samehadaku/build.gradle.kts b/Samehadaku/build.gradle.kts index c7f120a3..1c566566 100644 --- a/Samehadaku/build.gradle.kts +++ b/Samehadaku/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 13 +version = 14 cloudstream { diff --git a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt index 78264113..a903d225 100644 --- a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt +++ b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt @@ -203,7 +203,7 @@ class Samehadaku : MainAPI() { link.url, link.referer, name.fixQuality(), - link.isM3u8, + link.type, link.headers, link.extractorData ) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index a6a8ce22..10dc59bc 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 = 163 +version = 164 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt new file mode 100644 index 00000000..6def3d06 --- /dev/null +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -0,0 +1,162 @@ +package com.hexated + +import com.lagradost.cloudstream3.extractors.Filesim +import com.lagradost.cloudstream3.extractors.GMPlayer +import com.lagradost.cloudstream3.extractors.StreamSB +import com.lagradost.cloudstream3.extractors.Voe +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.APIHolder.getCaptchaToken +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.* +import java.math.BigInteger +import java.security.MessageDigest + +open class Playm4u : ExtractorApi() { + override val name = "Playm4u" + override val mainUrl = "https://play9str.playm4u.xyz" + override val requiresReferer = true + private val password = "plhq@@@22" + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val document = app.get(url, referer = referer).document + val script = document.selectFirst("script:containsData(idfile =)")?.data() ?: return + val passScript = document.selectFirst("script:containsData(domain_ref =)")?.data() ?: return + + val pass = passScript.substringAfter("CryptoJS.MD5('").substringBefore("')") + val amount = passScript.substringAfter(".toString()), ").substringBefore("));").toInt() + + val idFile = "idfile\\s*=\\s*[\"'](\\S+)[\"'];".findIn(script) + val idUser = "idUser\\s*=\\s*[\"'](\\S+)[\"'];".findIn(script) + val domainApi = "DOMAIN_API\\s*=\\s*[\"'](\\S+)[\"'];".findIn(script) + val nameKeyV3 = "NameKeyV3\\s*=\\s*[\"'](\\S+)[\"'];".findIn(script) + val dataEnc = caesarShift( + mahoa( + "Win32|$idUser|$idFile|$referer", + md5(pass) + ), amount + ).toHex() + + val captchaKey = + document.select("script[src*=https://www.google.com/recaptcha/api.js?render=]") + .attr("src").substringAfter("render=") + val token = getCaptchaToken( + url, + captchaKey, + referer = referer + ) + + val source = app.post( + domainApi, data = mapOf( + "namekey" to nameKeyV3, + "token" to "$token", + "referrer" to "$referer", + "data" to "$dataEnc|${md5(dataEnc + password)}", + ), referer = "$mainUrl/" + ).parsedSafe() + + callback.invoke( + ExtractorLink( + this.name, + this.name, + source?.data ?: return, + "$mainUrl/", + Qualities.P1080.value, + INFER_TYPE + ) + ) + + subtitleCallback.invoke( + SubtitleFile( + source.sub?.substringBefore("|")?.toLanguage() ?: return, + source.sub.substringAfter("|"), + ) + ) + + } + + private fun caesarShift(str: String, amount: Int): String { + var output = "" + val adjustedAmount = if (amount < 0) amount + 26 else amount + for (element in str) { + var c = element + if (c.isLetter()) { + val code = c.code + c = when (code) { + in 65..90 -> ((code - 65 + adjustedAmount) % 26 + 65).toChar() + in 97..122 -> ((code - 97 + adjustedAmount) % 26 + 97).toChar() + else -> c + } + } + output += c + } + return output + } + + private fun mahoa(input: String, key: String): String { + val a = CryptoJS.encrypt(key, input) + return a.replace("U2FsdGVkX1", "") + .replace("/", "|a") + .replace("+", "|b") + .replace("=", "|c") + .replace("|", "-z") + } + + private fun md5(input: String): String { + val md = MessageDigest.getInstance("MD5") + return BigInteger(1, md.digest(input.toByteArray())).toString(16).padStart(32, '0') + } + + private fun String.toHex(): String { + return this.toByteArray().joinToString("") { "%02x".format(it) } + } + + private fun String.findIn(data: String): String { + return this.toRegex().find(data)?.groupValues?.get(1) ?: "" + } + + private fun String.toLanguage() : String { + return if(this == "EN") "English" else this + } + + data class Source( + @JsonProperty("data") val data: String? = null, + @JsonProperty("sub") val sub: String? = null, + ) + +} + +class TravelR : GMPlayer() { + override val name = "TravelR" + override val mainUrl = "https://travel-russia.xyz" +} + +class Mwish : Filesim() { + override val name = "Mwish" + override var mainUrl = "https://mwish.pro" +} + +class Animefever : Filesim() { + override val name = "Animefever" + override var mainUrl = "https://animefever.fun" +} + +class Multimovies : Filesim() { + override val name = "Multimovies" + override var mainUrl = "https://multimovies.cloud" +} + +class MultimoviesSB : StreamSB() { + override var name = "Multimovies" + override var mainUrl = "https://multimovies.website" +} + +class Yipsu : Voe() { + override val name = "Yipsu" + override var mainUrl = "https://yip.su" +} \ 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 5efdec40..3f53a400 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1,6 +1,5 @@ package com.hexated -import com.hexated.AesHelper.cryptoAESHandler import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson @@ -10,6 +9,7 @@ import com.lagradost.cloudstream3.extractors.Filesim import com.lagradost.cloudstream3.extractors.GMPlayer import com.lagradost.cloudstream3.extractors.StreamSB import com.lagradost.cloudstream3.extractors.Voe +import com.lagradost.cloudstream3.extractors.helper.AesHelper.cryptoAESHandler import com.lagradost.cloudstream3.extractors.helper.GogoHelper import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.nicehttp.RequestBodyTypes @@ -127,7 +127,7 @@ object SoraExtractor : SoraStream() { link.url, link.referer, if (link.name == "VidSrc") Qualities.P1080.value else link.quality, - link.isM3u8, + link.type, link.headers, link.extractorData ) @@ -273,7 +273,7 @@ object SoraExtractor : SoraStream() { video.url, video.referer, Qualities.P1080.value, - video.isM3u8, + video.type, video.headers, video.extractorData ) @@ -415,7 +415,7 @@ object SoraExtractor : SoraStream() { } else { "$idlixAPI/episode/$fixTitle-season-$season-episode-$episode" } - invokeWpmovies(url, subtitleCallback, callback, encrypt = true, key = "\\x5a\\x6d\\x5a\\x6c\\x4e\\x7a\\x55\\x79\\x4d\\x54\\x56\\x6a\\x5a\\x47\\x52\\x69\\x5a\\x44\\x55\\x30\\x5a\\x6d\\x59\\x35\\x4f\\x57\\x45\\x33\\x4d\\x44\\x4a\\x69\\x4e\\x32\\x4a\\x6c\\x4f\\x54\\x42\\x6c\\x4e\\x7a\\x49\\x3d") + invokeWpmovies(url, subtitleCallback, callback, encrypt = true) } suspend fun invokeMultimovies( @@ -480,7 +480,7 @@ object SoraExtractor : SoraStream() { ) val source = tryParseJson(json.text)?.let { when { - encrypt -> cryptoAESHandler(it.embed_url,(key ?: return@apmap).toByteArray(), false)?.fixBloat() + encrypt -> cryptoAESHandler(it.embed_url,(it.key ?: return@apmap).toByteArray(), false)?.fixBloat() fixIframe -> Jsoup.parse(it.embed_url).select("IFRAME").attr("SRC") else -> it.embed_url } @@ -711,10 +711,10 @@ object SoraExtractor : SoraStream() { link.url, link.referer, when { - link.isM3u8 -> link.quality + link.type == ExtractorLinkType.M3U8 -> link.quality else -> getQualityFromName(it.first) }, - link.isM3u8, + link.type, link.headers, link.extractorData ) @@ -1039,10 +1039,10 @@ object SoraExtractor : SoraStream() { link.url, link.referer, when { - link.isM3u8 -> link.quality + link.type == ExtractorLinkType.M3U8 -> link.quality else -> it.third }, - link.isM3u8, + link.type, link.headers, link.extractorData ) @@ -1517,7 +1517,9 @@ object SoraExtractor : SoraStream() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { - val res = app.get("$m4uhdAPI/search/${title.createSlug()}.html").document + val req = app.get("$m4uhdAPI/search/${title.createSlug()}.html") + val referer = getBaseUrl(req.url) + val res = req.document val scriptData = res.select("div.row div.item").map { Triple( it.selectFirst("img.imagecover")?.attr("title"), @@ -1538,7 +1540,7 @@ object SoraExtractor : SoraStream() { } } - val link = fixUrl(script?.third ?: return, m4uhdAPI) + val link = fixUrl(script?.third ?: return, referer) val request = app.get(link) var cookiesSet = request.headers.filter { it.first == "set-cookie" } var xsrf = @@ -1558,7 +1560,7 @@ object SoraExtractor : SoraStream() { ?: return val idepisode = episodeData.select("button").attr("idepisode") ?: return val requestEmbed = app.post( - "$m4uhdAPI/ajaxtv", data = mapOf( + "$referer/ajaxtv", data = mapOf( "idepisode" to idepisode, "_token" to "$token" ), referer = link, headers = mapOf( "X-Requested-With" to "XMLHttpRequest", @@ -1572,14 +1574,16 @@ object SoraExtractor : SoraStream() { cookiesSet.find { it.second.contains("XSRF-TOKEN") }?.second?.substringAfter("XSRF-TOKEN=") ?.substringBefore(";") session = - cookiesSet.find { it.second.contains("laravel_session") }?.second?.substringAfter("laravel_session=") + cookiesSet.find { it.second.contains("laravel_session") }?.second?.substringAfter( + "laravel_session=" + ) ?.substringBefore(";") requestEmbed.document.select("div.le-server span").map { it.attr("data") } } m4uData.apmap { data -> val iframe = app.post( - "$m4uhdAPI/ajax", + "$referer/ajax", data = mapOf( "m4u" to data, "_token" to "$token" ), @@ -1594,7 +1598,7 @@ object SoraExtractor : SoraStream() { ), ).document.select("iframe").attr("src") - loadExtractor(iframe, m4uhdAPI, subtitleCallback, callback) + loadExtractor(iframe, referer, subtitleCallback, callback) } } @@ -2902,33 +2906,3 @@ object SoraExtractor : SoraStream() { } -class TravelR : GMPlayer() { - override val name = "TravelR" - override val mainUrl = "https://travel-russia.xyz" -} - -class Mwish : Filesim() { - override val name = "Mwish" - override var mainUrl = "https://mwish.pro" -} - -class Animefever : Filesim() { - override val name = "Animefever" - override var mainUrl = "https://animefever.fun" -} - -class Multimovies : Filesim() { - override val name = "Multimovies" - override var mainUrl = "https://multimovies.cloud" -} - -class MultimoviesSB : StreamSB() { - override var name = "Multimovies" - 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 46add238..ea77a419 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -126,7 +126,7 @@ open class SoraStream : TmdbProvider() { const val emoviesAPI = "https://emovies.si" const val pobmoviesAPI = "https://pobmovies.cam" const val fourCartoonAPI = "https://4cartoon.net" - const val multimoviesAPI = "https://multimovies.xyz" + const val multimoviesAPI = "https://multi-movies.xyz" const val netmoviesAPI = "https://netmovies.to" const val momentAPI = "https://moment-explanation-i-244.site" const val doomoviesAPI = "https://doomovies.net" @@ -539,7 +539,7 @@ open class SoraStream : TmdbProvider() { ) }, { - invokeM4uhd( + if(!res.isAnime) invokeM4uhd( res.title, res.year, res.season, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 2e7d99ab..2703133e 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -257,7 +257,7 @@ class SoraStreamLite : SoraStream() { invokeFwatayako(res.imdbId, res.season, res.episode, callback) }, { - invokeM4uhd( + if(!res.isAnime) invokeM4uhd( res.title, res.year, res.season, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt index 7bb7f262..3e0cda41 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt @@ -17,5 +17,6 @@ class SoraStreamPlugin: Plugin() { registerExtractorAPI(Yipsu()) registerExtractorAPI(Mwish()) registerExtractorAPI(TravelR()) + registerExtractorAPI(Playm4u()) } } \ No newline at end of file diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 3f640572..09f6f822 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -1,7 +1,6 @@ package com.hexated import android.util.Base64 -import com.fasterxml.jackson.annotation.JsonProperty import com.hexated.DumpUtils.queryApi import com.hexated.SoraStream.Companion.anilistAPI import com.hexated.SoraStream.Companion.base64DecodeAPI @@ -41,6 +40,7 @@ import javax.crypto.Cipher import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec import kotlin.collections.ArrayList +import kotlin.math.min val bflixChipperKey = base64DecodeAPI("Yjc=ejM=TzA=YTk=WHE=WnU=bXU=RFo=") const val bflixKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" @@ -1143,10 +1143,10 @@ suspend fun loadCustomExtractor( link.url, link.referer, when { - link.isM3u8 -> link.quality + link.type == ExtractorLinkType.M3U8 -> link.quality else -> quality ?: link.quality }, - link.isM3u8, + link.type, link.headers, link.extractorData ) @@ -1725,85 +1725,125 @@ object RSAEncryptionHelper { } } -object AesHelper { +// code found on https://stackoverflow.com/a/63701411 - fun cryptoAESHandler( - data: String, - pass: ByteArray, - encrypt: Boolean = true, - padding: String = "AES/CBC/PKCS5PADDING", - ): String? { - val parse = AppUtils.tryParseJson(data) ?: return null - val (key, iv) = generateKeyAndIv(pass, parse.s.hexToByteArray()) ?: throw ErrorLoadingException("failed to generate key") - val cipher = Cipher.getInstance(padding) - return if (!encrypt) { - cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) - String(cipher.doFinal(base64DecodeArray(parse.ct))) - } else { - cipher.init(Cipher.ENCRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv)) - base64Encode(cipher.doFinal(parse.ct.toByteArray())) - } +/** + * Conforming with CryptoJS AES method + */ +// see https://gist.github.com/thackerronak/554c985c3001b16810af5fc0eb5c358f +@Suppress("unused", "FunctionName", "SameParameterValue") +object CryptoJS { + + private const val KEY_SIZE = 256 + private const val IV_SIZE = 128 + private const val HASH_CIPHER = "AES/CBC/PKCS7Padding" + private const val AES = "AES" + private const val KDF_DIGEST = "MD5" + + // Seriously crypto-js, what's wrong with you? + private const val APPEND = "Salted__" + + /** + * Encrypt + * @param password passphrase + * @param plainText plain string + */ + fun encrypt(password: String, plainText: String): String { + val saltBytes = generateSalt(8) + val key = ByteArray(KEY_SIZE / 8) + val iv = ByteArray(IV_SIZE / 8) + EvpKDF(password.toByteArray(), KEY_SIZE, IV_SIZE, saltBytes, key, iv) + val keyS = SecretKeySpec(key, AES) + val cipher = Cipher.getInstance(HASH_CIPHER) + val ivSpec = IvParameterSpec(iv) + cipher.init(Cipher.ENCRYPT_MODE, keyS, ivSpec) + val cipherText = cipher.doFinal(plainText.toByteArray()) + // Thanks kientux for this: https://gist.github.com/kientux/bb48259c6f2133e628ad + // Create CryptoJS-like encrypted! + val sBytes = APPEND.toByteArray() + val b = ByteArray(sBytes.size + saltBytes.size + cipherText.size) + System.arraycopy(sBytes, 0, b, 0, sBytes.size) + System.arraycopy(saltBytes, 0, b, sBytes.size, saltBytes.size) + System.arraycopy(cipherText, 0, b, sBytes.size + saltBytes.size, cipherText.size) + val bEncode = Base64.encode(b, Base64.NO_WRAP) + return String(bEncode) } - // https://stackoverflow.com/a/41434590/8166854 - private fun generateKeyAndIv( + /** + * Decrypt + * Thanks Artjom B. for this: http://stackoverflow.com/a/29152379/4405051 + * @param password passphrase + * @param cipherText encrypted string + */ + fun decrypt(password: String, cipherText: String): String { + val ctBytes = Base64.decode(cipherText.toByteArray(), Base64.NO_WRAP) + val saltBytes = Arrays.copyOfRange(ctBytes, 8, 16) + val cipherTextBytes = Arrays.copyOfRange(ctBytes, 16, ctBytes.size) + val key = ByteArray(KEY_SIZE / 8) + val iv = ByteArray(IV_SIZE / 8) + EvpKDF(password.toByteArray(), KEY_SIZE, IV_SIZE, saltBytes, key, iv) + val cipher = Cipher.getInstance(HASH_CIPHER) + val keyS = SecretKeySpec(key, AES) + cipher.init(Cipher.DECRYPT_MODE, keyS, IvParameterSpec(iv)) + val plainText = cipher.doFinal(cipherTextBytes) + return String(plainText) + } + + private fun EvpKDF( password: ByteArray, + keySize: Int, + ivSize: Int, salt: ByteArray, - hashAlgorithm: String = "MD5", - keyLength: Int = 32, - ivLength: Int = 16, - iterations: Int = 1 - ): List? { + resultKey: ByteArray, + resultIv: ByteArray + ): ByteArray { + return EvpKDF(password, keySize, ivSize, salt, 1, KDF_DIGEST, resultKey, resultIv) + } - val md = MessageDigest.getInstance(hashAlgorithm) - val digestLength = md.digestLength - val targetKeySize = keyLength + ivLength - val requiredLength = (targetKeySize + digestLength - 1) / digestLength * digestLength - val generatedData = ByteArray(requiredLength) - var generatedLength = 0 - - try { - md.reset() - - while (generatedLength < targetKeySize) { - if (generatedLength > 0) - md.update( - generatedData, - generatedLength - digestLength, - digestLength - ) - - md.update(password) - md.update(salt, 0, 8) - md.digest(generatedData, generatedLength, digestLength) - - for (i in 1 until iterations) { - md.update(generatedData, generatedLength, digestLength) - md.digest(generatedData, generatedLength, digestLength) - } - - generatedLength += digestLength + @Suppress("NAME_SHADOWING") + private fun EvpKDF( + password: ByteArray, + keySize: Int, + ivSize: Int, + salt: ByteArray, + iterations: Int, + hashAlgorithm: String, + resultKey: ByteArray, + resultIv: ByteArray + ): ByteArray { + val keySize = keySize / 32 + val ivSize = ivSize / 32 + val targetKeySize = keySize + ivSize + val derivedBytes = ByteArray(targetKeySize * 4) + var numberOfDerivedWords = 0 + var block: ByteArray? = null + val hash = MessageDigest.getInstance(hashAlgorithm) + while (numberOfDerivedWords < targetKeySize) { + if (block != null) { + hash.update(block) } - return listOf( - generatedData.copyOfRange(0, keyLength), - generatedData.copyOfRange(keyLength, targetKeySize) + hash.update(password) + block = hash.digest(salt) + hash.reset() + // Iterations + for (i in 1 until iterations) { + block = hash.digest(block!!) + hash.reset() + } + System.arraycopy( + block!!, 0, derivedBytes, numberOfDerivedWords * 4, + min(block.size, (targetKeySize - numberOfDerivedWords) * 4) ) - } catch (e: DigestException) { - return null + numberOfDerivedWords += block.size / 4 + } + System.arraycopy(derivedBytes, 0, resultKey, 0, keySize * 4) + System.arraycopy(derivedBytes, keySize * 4, resultIv, 0, ivSize * 4) + return derivedBytes // key + iv + } + + private fun generateSalt(length: Int): ByteArray { + return ByteArray(length).apply { + SecureRandom().nextBytes(this) } } - - private fun String.hexToByteArray(): ByteArray { - check(length % 2 == 0) { "Must have an even length" } - return chunked(2) - .map { it.toInt(16).toByte() } - .toByteArray() - } - - private data class AesData( - @JsonProperty("ct") val ct: String, - @JsonProperty("iv") val iv: String, - @JsonProperty("s") val s: String - ) - } \ No newline at end of file From 23683ba979e04c6b7c8df97dda8f0f328f8453f1 Mon Sep 17 00:00:00 2001 From: IndusAryan <125901294+IndusAryan@users.noreply.github.com> Date: Sun, 10 Sep 2023 01:24:42 +0530 Subject: [PATCH 091/105] update: movierulzhd and hdmovie2 (#260) * Update Movierulzhd.kt * Update Hdmovie2.kt * Update Movierulzhd.kt * Update Hdmovie2.kt * Update build.gradle.kts --- Movierulzhd/build.gradle.kts | 2 +- Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt | 4 +++- Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Movierulzhd/build.gradle.kts b/Movierulzhd/build.gradle.kts index e3151139..2f1b59d2 100644 --- a/Movierulzhd/build.gradle.kts +++ b/Movierulzhd/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 39 +version = 40 cloudstream { diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt b/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt index a77991f5..63831c0e 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt @@ -11,7 +11,9 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.Jsoup class Hdmovie2 : Movierulzhd() { - override var mainUrl = "https://hdmovie2.media" + + override var mainUrl = "https://hdmovie2.codes" + override var name = "Hdmovie2" override val mainPage = mainPageOf( diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt index 45529bc2..9c5c93af 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt @@ -11,7 +11,9 @@ import org.jsoup.nodes.Element import java.net.URI open class Movierulzhd : MainAPI() { - override var mainUrl = "https://movierulzhd.tools" + + override var mainUrl = "https://movierulzvid.gold" + var directUrl = "" override var name = "Movierulzhd" override val hasMainPage = true From 972277a109e89dba2ef63056841d7e9fdd1ea3a3 Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 10 Sep 2023 13:12:57 +0700 Subject: [PATCH 092/105] sora: fix WatchOnline --- .../src/main/kotlin/com/hexated/Extractors.kt | 10 +-- .../main/kotlin/com/hexated/SoraExtractor.kt | 72 +++++++++---------- 2 files changed, 38 insertions(+), 44 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt index 6def3d06..b91348b1 100644 --- a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -31,10 +31,10 @@ open class Playm4u : ExtractorApi() { val pass = passScript.substringAfter("CryptoJS.MD5('").substringBefore("')") val amount = passScript.substringAfter(".toString()), ").substringBefore("));").toInt() - val idFile = "idfile\\s*=\\s*[\"'](\\S+)[\"'];".findIn(script) - val idUser = "idUser\\s*=\\s*[\"'](\\S+)[\"'];".findIn(script) - val domainApi = "DOMAIN_API\\s*=\\s*[\"'](\\S+)[\"'];".findIn(script) - val nameKeyV3 = "NameKeyV3\\s*=\\s*[\"'](\\S+)[\"'];".findIn(script) + val idFile = "idfile".findIn(script) + val idUser = "idUser".findIn(script) + val domainApi = "DOMAIN_API".findIn(script) + val nameKeyV3 = "NameKeyV3".findIn(script) val dataEnc = caesarShift( mahoa( "Win32|$idUser|$idFile|$referer", @@ -117,7 +117,7 @@ open class Playm4u : ExtractorApi() { } private fun String.findIn(data: String): String { - return this.toRegex().find(data)?.groupValues?.get(1) ?: "" + return "$this\\s*=\\s*[\"'](\\S+)[\"'];".toRegex().find(data)?.groupValues?.get(1) ?: "" } private fun String.toLanguage() : String { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 3f53a400..0f2d1d83 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2443,7 +2443,6 @@ object SoraExtractor : SoraStream() { var res = app.get(url) if (res.code == 403) return if (!res.isSuccessful) res = searchWatchOnline(title, season, imdbId, tmdbId) ?: return - val doc = res.document val episodeId = if (season == null) { doc.selectFirst("div.movie__buttons-items a")?.attr("data-watch-list-media-id") @@ -2452,35 +2451,31 @@ object SoraExtractor : SoraStream() { it.select("div.episodes__number").text().equals("Episode $episode", true) }?.attr("data-id-episode") } ?: return - - val videoUrl = if (season == null) { - "$watchOnlineAPI/api/v1/security/movie-access?id_movie=$episodeId" - } else { - "$watchOnlineAPI/api/v1/security/episode-access?id=$episodeId" - } - - val json = app.get(videoUrl, referer = url).parsedSafe() - - json?.streams?.mapKeys { source -> - callback.invoke( - ExtractorLink( - "WatchOnline", - "WatchOnline", - source.value, - "$watchOnlineAPI/", - getQualityFromName(source.key), - true - ) - ) - } - argamap( { - invokeMonster( - res.url.substringAfterLast("/"), episodeId, season, callback - ) + invokeMonster(res.url.substringAfterLast("/"), episodeId, season, callback) }, { + val videoUrl = if (season == null) { + "$watchOnlineAPI/api/v1/security/movie-access?id_movie=$episodeId" + } else { + "$watchOnlineAPI/api/v1/security/episode-access?id=$episodeId" + } + + val json = app.get(videoUrl, referer = url).parsedSafe() + + json?.streams?.mapKeys { source -> + callback.invoke( + ExtractorLink( + "WatchOnline", + "WatchOnline", + source.value, + "$watchOnlineAPI/", + getQualityFromName(source.key), + true + ) + ) + } val subtitles = json?.subtitles as ArrayList> subtitles.map { sub -> subtitleCallback.invoke( @@ -2490,7 +2485,8 @@ object SoraExtractor : SoraStream() { ) ) } - }) + } + ) } @@ -2500,19 +2496,17 @@ object SoraExtractor : SoraStream() { season: Int? = null, callback: (ExtractorLink) -> Unit, ) { - val monsterMainUrl = "https://mobirs.monster" - val playSlug = if (season == null) { - "movies/play/$urlSlug" + val monsterMainUrl = "https://lookmovie.foundation" + val viewSlug = if (season == null) { + "movies/view/$urlSlug" } else { - "shows/play/$urlSlug" + "shows/view/$urlSlug" } - val sid = "9k9iupt5sebbnfajrc6ti3ht7l" - val sec = "1974bc4a902c4d69fcbab261dcec69094a9b8164" - val url = - "$monsterMainUrl/$playSlug?mid=1&sid=$sid&sec=$sec&t=${System.currentTimeMillis()}" - val res = app.get(url).document - val script = res.selectFirst("script:containsData(window['show_storage'])")?.data() - val hash = Regex("hash:\\s*['\"](\\S+)['\"],").find(script ?: return)?.groupValues?.get(1) + val streamUrl = app.get("$monsterMainUrl/$viewSlug").document.select("a.round-button:first-child").attr("href") + val res = app.get(streamUrl).document + val script = res.selectFirst("script:containsData(hash:)")?.data() + val hash = + Regex("hash:\\s*['\"](\\S+)['\"],").find(script ?: return)?.groupValues?.get(1) val expires = Regex("expires:\\s*(\\d+),").find(script)?.groupValues?.get(1) val videoUrl = if (season == null) { @@ -2521,7 +2515,7 @@ object SoraExtractor : SoraStream() { "$monsterMainUrl/api/v1/security/episode-access?id_episode=$episodeId&hash=$hash&expires=$expires" } - app.get(videoUrl, referer = url) + app.get(videoUrl, referer = streamUrl) .parsedSafe()?.streams?.mapKeys { source -> callback.invoke( ExtractorLink( From 2f2358d6c1cfb785dd48097508ab7cc42123bc1f Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 10 Sep 2023 16:34:33 +0700 Subject: [PATCH 093/105] sora: bump --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 105 ++---------------- .../src/main/kotlin/com/hexated/SoraParser.kt | 16 --- .../src/main/kotlin/com/hexated/SoraStream.kt | 17 +-- .../main/kotlin/com/hexated/SoraStreamLite.kt | 23 +--- 5 files changed, 14 insertions(+), 149 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 10dc59bc..ee899967 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 = 164 +version = 165 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 0f2d1d83..bf84c606 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -234,92 +234,6 @@ object SoraExtractor : SoraStream() { } } - suspend fun invokeHDMovieBox( - title: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - val fixTitle = title.createSlug() - val url = "$hdMovieBoxAPI/watch/$fixTitle" - val doc = app.get(url).document - val id = if (season == null) { - doc.selectFirst("div.player div#not-loaded")?.attr("data-whatwehave") - } else { - doc.select("div.season-list-column div[data-season=$season] div.list div.item")[episode?.minus( - 1 - ) ?: 0].selectFirst("div.ui.checkbox")?.attr("data-episode") - } ?: return - - val iframeUrl = app.post( - "$hdMovieBoxAPI/ajax/service", data = mapOf( - "e_id" to id, - "v_lang" to "en", - "type" to "get_whatwehave", - ), headers = mapOf("X-Requested-With" to "XMLHttpRequest") - ).parsedSafe()?.apiIframe ?: return - - delay(1000) - val iframe = app.get(iframeUrl, referer = url).document.selectFirst("iframe") - ?.attr("src").let { httpsify(it ?: return) } - - if (iframe.startsWith("https://vidmoly.to")) { - loadExtractor(iframe, "$hdMovieBoxAPI/", subtitleCallback) { video -> - callback.invoke( - ExtractorLink( - video.name, - video.name, - video.url, - video.referer, - Qualities.P1080.value, - video.type, - video.headers, - video.extractorData - ) - ) - } - } else { - val base = getBaseUrl(iframe) - val script = app.get( - httpsify(iframe), referer = "$hdMovieBoxAPI/" - ).document.selectFirst("script:containsData(var vhash =)")?.data() - ?.substringAfter("vhash, {")?.substringBefore("}, false") - - tryParseJson("{$script}").let { source -> - val disk = if (source?.videoDisk == null) { - "" - } else { - base64Encode(source.videoDisk.toString().toByteArray()) - } - val link = getBaseUrl(iframe) + source?.videoUrl?.replace( - "\\", "" - ) + "?s=${source?.videoServer}&d=$disk" - callback.invoke( - ExtractorLink( - "HDMovieBox", - "HDMovieBox", - link, - iframe, - Qualities.P1080.value, - isM3u8 = true, - ) - ) - - source?.tracks?.map { sub -> - subtitleCallback.invoke( - SubtitleFile( - sub.label ?: "", - fixUrl(sub.file ?: return@map null, base), - ) - ) - } - } - } - - - } - suspend fun invokeDreamfilm( title: String? = null, season: Int? = null, @@ -1517,14 +1431,15 @@ object SoraExtractor : SoraStream() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { + val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) val req = app.get("$m4uhdAPI/search/${title.createSlug()}.html") val referer = getBaseUrl(req.url) val res = req.document - val scriptData = res.select("div.row div.item").map { + val scriptData = res.select("div.row div.item").map { ele -> Triple( - it.selectFirst("img.imagecover")?.attr("title"), - it.selectFirst("div.jtip-top div:last-child")?.text(), - it.selectFirst("a")?.attr("href") + ele.select("div.tiptitle p").text(), + ele.select("div.jtip-top div:last-child").text().filter { it.isDigit() }, + ele.selectFirst("a")?.attr("href") ) } @@ -1532,11 +1447,9 @@ object SoraExtractor : SoraStream() { scriptData.firstOrNull() } else { scriptData.find { - it.first?.contains( - "Watch Free ${title?.replace(":", "")}", true - ) == true && (it.first?.contains("$year") == true || it.second?.contains( - "$year" - ) == true) + it.first.contains( + "$title", true + ) && it.second == "$year" } } @@ -1556,7 +1469,7 @@ object SoraExtractor : SoraStream() { doc.select("div.le-server span").map { it.attr("data") } } else { val episodeData = - doc.selectFirst("div.col-lg-9.col-xl-9 p:matches((?i)S0?$season-E0?$episode$)") + doc.selectFirst("div.col-lg-9.col-xl-9 p:matches((?i)S$seasonSlug-E$episodeSlug)") ?: return val idepisode = episodeData.select("button").attr("idepisode") ?: return val requestEmbed = app.post( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 0897e838..483be230 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -47,22 +47,6 @@ data class MoviesbayValues( @JsonProperty("values") val values: List>? = arrayListOf(), ) -data class HdMovieBoxTracks( - @JsonProperty("label") val label: String? = null, - @JsonProperty("file") val file: String? = null, -) - -data class HdMovieBoxSource( - @JsonProperty("videoUrl") val videoUrl: String? = null, - @JsonProperty("videoServer") val videoServer: String? = null, - @JsonProperty("videoDisk") val videoDisk: Any? = null, - @JsonProperty("tracks") val tracks: ArrayList? = arrayListOf(), -) - -data class HdMovieBoxIframe( - @JsonProperty("api_iframe") val apiIframe: String? = null, -) - data class ResponseHash( @JsonProperty("embed_url") val embed_url: String, @JsonProperty("key") val key: String? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index ea77a419..c58f07ec 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -8,7 +8,6 @@ import com.hexated.SoraExtractor.invokeBollyMaza import com.hexated.SoraExtractor.invokeCryMovies import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeFilmxy -import com.hexated.SoraExtractor.invokeHDMovieBox import com.hexated.SoraExtractor.invokeIdlix import com.hexated.SoraExtractor.invokeKimcartoon import com.hexated.SoraExtractor.invokeMovieHab @@ -91,7 +90,6 @@ open class SoraStream : TmdbProvider() { const val vidSrcAPI = "https://v2.vidsrc.me" const val dbgoAPI = "https://dbgo.fun" const val movieHabAPI = "https://moviehab.com" - const val hdMovieBoxAPI = "https://hdmoviebox.net" const val dreamfilmAPI = "https://dreamfilmsw.net" const val series9API = "https://series9.cx" const val idlixAPI = "https://tv.idlixplus.net" @@ -106,7 +104,7 @@ open class SoraStream : TmdbProvider() { const val fwatayakoAPI = "https://5100.svetacdn.in" const val gMoviesAPI = "https://gdrivemovies.xyz" const val fdMoviesAPI = "https://freedrivemovie.lol" - const val m4uhdAPI = "https://m4uhd.tv" + const val m4uhdAPI = "https://ww2.m4ufree.com" const val tvMoviesAPI = "https://www.tvseriesnmovies.com" const val moviezAddAPI = "https://ww2.moviezaddiction.click" const val bollyMazaAPI = "https://m.bollymaza.click" @@ -127,7 +125,7 @@ open class SoraStream : TmdbProvider() { const val pobmoviesAPI = "https://pobmovies.cam" const val fourCartoonAPI = "https://4cartoon.net" const val multimoviesAPI = "https://multi-movies.xyz" - const val netmoviesAPI = "https://netmovies.to" + const val netmoviesAPI = "https://web.netmovies.to" const val momentAPI = "https://moment-explanation-i-244.site" const val doomoviesAPI = "https://doomovies.net" const val primewireAPI = "https://real-primewire.club" @@ -419,15 +417,6 @@ open class SoraStream : TmdbProvider() { callback ) }, - { - if (!res.isAnime) invokeHDMovieBox( - res.title, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, { if (!res.isAnime) invokeDreamfilm( res.title, @@ -541,7 +530,7 @@ open class SoraStream : TmdbProvider() { { if(!res.isAnime) invokeM4uhd( res.title, - res.year, + res.airedYear ?: res.year, res.season, res.episode, subtitleCallback, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 2703133e..abe0c861 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -11,7 +11,6 @@ import com.hexated.SoraExtractor.invokeFilmxy import com.hexated.SoraExtractor.invokeFlixon import com.hexated.SoraExtractor.invokeFwatayako import com.hexated.SoraExtractor.invokeGoku -import com.hexated.SoraExtractor.invokeHDMovieBox import com.hexated.SoraExtractor.invokeIdlix import com.hexated.SoraExtractor.invokeKimcartoon import com.hexated.SoraExtractor.invokeKisskh @@ -33,7 +32,6 @@ import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokePrimewire -import com.hexated.SoraExtractor.invokeSusflix import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeWatchOnline @@ -127,25 +125,6 @@ class SoraStreamLite : SoraStream() { callback ) }, -// { -// if (res.season != null && res.isAnime) invokeCrunchyroll( -// res.title, -// res.epsTitle, -// res.season, -// res.episode, -// subtitleCallback, -// callback -// ) -// }, - { - if (!res.isAnime) invokeHDMovieBox( - res.title, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, { if (!res.isAnime) invokeDreamfilm( res.title, @@ -259,7 +238,7 @@ class SoraStreamLite : SoraStream() { { if(!res.isAnime) invokeM4uhd( res.title, - res.year, + res.airedYear ?: res.year, res.season, res.episode, subtitleCallback, From f29605ec952458c3c0ab9a1617da2a643b61021f Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 10 Sep 2023 17:01:03 +0700 Subject: [PATCH 094/105] sora: added timeout in index --- .../src/main/kotlin/com/hexated/SoraExtractor.kt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index bf84c606..90269e66 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2000,7 +2000,8 @@ object SoraExtractor : SoraStream() { "${apiUrl}search", data = data, headers = passHeaders, - referer = apiUrl + referer = apiUrl, + timeout = 120L ).text else app.post( "${apiUrl}search", data = data, @@ -2008,7 +2009,7 @@ object SoraExtractor : SoraStream() { ).text ) } else { - app.post("${apiUrl}search", requestBody = body, referer = apiUrl).text + app.post("${apiUrl}search", requestBody = body, referer = apiUrl, timeout = 120L).text } val media = if (api in untrimmedIndex) searchIndex( title, @@ -2031,20 +2032,22 @@ object SoraExtractor : SoraStream() { "${apiUrl}id2path", data = pathData, headers = passHeaders, - referer = apiUrl + referer = apiUrl, + timeout = 120L ) } else { app.post( - "${apiUrl}id2path", data = pathData, referer = apiUrl + "${apiUrl}id2path", data = pathData, referer = apiUrl, timeout = 120L ) } } else { - app.post("${apiUrl}id2path", requestBody = pathBody, referer = apiUrl) + app.post("${apiUrl}id2path", requestBody = pathBody, referer = apiUrl, timeout = 120L) }).text.let { path -> if (api in ddomainIndex) { val worker = app.get( "${fixUrl(path, apiUrl).encodeUrl()}?a=view", - referer = if (api in needRefererIndex) apiUrl else "" + referer = if (api in needRefererIndex) apiUrl else "", + timeout = 120L ).document.selectFirst("script:containsData(downloaddomain)")?.data() ?.substringAfter("\"downloaddomain\":\"")?.substringBefore("\",")?.let { "$it/0:" From 62cab062e385bb20beb0660f62cc05a2262115aa Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 10 Sep 2023 17:03:04 +0700 Subject: [PATCH 095/105] sora: added timeout in index --- .../main/kotlin/com/hexated/SoraExtractor.kt | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 90269e66..3f7e6719 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1120,30 +1120,30 @@ object SoraExtractor : SoraStream() { } }.filter { it.second?.contains(Regex("(https:)|(http:)")) == true } - val sources = mutableListOf>() - if (iframeList.any { - it.first.contains( - "2160p", - true - ) - }) { - sources.addAll(iframeList.filter { - it.first.contains( - "2160p", - true - ) - }) - sources.add(iframeList.first { - it.first.contains( - "1080p", - true - ) - }) - } else { - sources.addAll(iframeList.filter { it.first.contains("1080p", true) }) - } +// val sources = mutableListOf>() +// if (iframeList.any { +// it.first.contains( +// "2160p", +// true +// ) +// }) { +// sources.addAll(iframeList.filter { +// it.first.contains( +// "2160p", +// true +// ) +// }) +// sources.add(iframeList.first { +// it.first.contains( +// "1080p", +// true +// ) +// }) +// } else { +// sources.addAll(iframeList.filter { it.first.contains("1080p", true) }) +// } - sources.apmap { (quality, link) -> + iframeList.apmap { (quality, link) -> val driveLink = if (link?.contains("driveleech") == true) bypassDriveleech(link) else bypassTechmny( link ?: return@apmap From 18c07cc0693550fb3e7f0936aa4095a210e3c0c8 Mon Sep 17 00:00:00 2001 From: sora Date: Sun, 10 Sep 2023 19:56:48 +0700 Subject: [PATCH 096/105] TimefourTv: added search page --- TimefourTv/build.gradle.kts | 2 +- TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/TimefourTv/build.gradle.kts b/TimefourTv/build.gradle.kts index 8194a3f8..41074ab6 100644 --- a/TimefourTv/build.gradle.kts +++ b/TimefourTv/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 17 +version = 18 cloudstream { diff --git a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt index 2ecb947b..690a5b8d 100644 --- a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt +++ b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt @@ -110,6 +110,13 @@ open class TimefourTv : MainAPI() { } + override suspend fun search(query: String): List { + val document = app.get("$daddyUrl/24-7-channels.php").document + return document.select("div.grid-container div.grid-item:contains($query)").mapNotNull { + it.toSearchDaddy() + } + } + private suspend fun loadSchedule(url: String): LoadResponse { val name = url.removePrefix("$mainUrl/") val doc = app.get("$mainUrl/schedule.php").document From 67896f1d693e1902f867fd644bd4ac2a7e6da3d8 Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 10 Sep 2023 21:21:50 +0700 Subject: [PATCH 097/105] fix #258 --- .../src/main/kotlin/com/hexated/SoraExtractor.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 3f7e6719..a7b59f8a 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2206,6 +2206,9 @@ object SoraExtractor : SoraStream() { episode: Int? = null, callback: (ExtractorLink) -> Unit, ) { + fun String.decrypt(key: String) : List? { + return tryParseJson>(base64Decode(this).decodePrimewireXor(key)) + } val slug = getEpisodeSlug(season, episode) val query = if (season == null) { title @@ -2260,7 +2263,9 @@ object SoraExtractor : SoraStream() { "$primewireAPI$serverUrl", cookies = cookies, referer = url, headers = headers ) - val key = getAndUnpack(serverRes.text).substringAfter("(key=").substringBefore(")") + val unpack = getAndUnpack(serverRes.text) + val key = unpack.substringAfter("(key=").substringBefore(")") + val key2 = unpack.substringAfter("<\"").substringBefore("\".") serverRes.document.select("ul li").amap { el -> val server = el.attr("data-value") val encryptedData = app.get( @@ -2269,8 +2274,7 @@ object SoraExtractor : SoraStream() { referer = url, headers = headers ).text - val json = base64Decode(encryptedData).decodePrimewireXor(key) - val links = tryParseJson>(json) ?: return@amap + val links = encryptedData.decrypt(key) ?: encryptedData.decrypt(key2) ?: return@amap links.forEach { video -> qualities.filter { it <= video.max.toInt() }.forEach { callback( From fe95a53ba9d2c02fdf3faf432a8106c73dd6a8c8 Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 10 Sep 2023 22:59:48 +0700 Subject: [PATCH 098/105] Anichi: fix episode title --- Anichi/build.gradle.kts | 2 +- Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Anichi/build.gradle.kts b/Anichi/build.gradle.kts index c04dac6b..643809b0 100644 --- a/Anichi/build.gradle.kts +++ b/Anichi/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.konan.properties.Properties // use an integer for version numbers -version = 8 +version = 9 android { defaultConfig { diff --git a/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt b/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt index fb191bd1..42d3242f 100644 --- a/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt +++ b/Anichi/src/main/kotlin/com/hexated/AnichiUtils.kt @@ -113,7 +113,6 @@ fun AvailableEpisodesDetail.getEpisode( return meta.map { eps -> Episode( AnichiLoadData(id, lang, eps, malId).toJson(), - "Ep $eps", episode = eps.toIntOrNull() ) }.reversed() From 6cdeb659222cee55e38bd25dee7c93227f158217 Mon Sep 17 00:00:00 2001 From: hexated Date: Mon, 11 Sep 2023 11:55:09 +0700 Subject: [PATCH 099/105] sora: added omega --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 73 ++++++------------- .../src/main/kotlin/com/hexated/SoraParser.kt | 14 ++++ .../src/main/kotlin/com/hexated/SoraStream.kt | 32 ++++---- .../main/kotlin/com/hexated/SoraStreamLite.kt | 18 ++--- 5 files changed, 57 insertions(+), 82 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index ee899967..129c982d 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 = 165 +version = 166 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index a7b59f8a..5b80bdfd 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -263,58 +263,6 @@ object SoraExtractor : SoraStream() { } } - suspend fun invokeSeries9( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - val fixTitle = title.createSlug() - val doc = if (season == null) { - val res = app.get("$series9API/film/$fixTitle/watching.html") - if (!res.isSuccessful) app.get("$series9API/film/$fixTitle-$year/watching.html").document else res.document - } else { - app.get("$series9API/film/$fixTitle-season-$season/watching.html").document - } - - val server = doc.select("div#list-eps div.le-server").map { ele -> - if (season == null) { - ele.select("a").attr("player-data") - } else { - ele.select("a[episode-data=$episode]").attr("player-data") - } - }.find { it.contains(Regex("movembed|membed")) } - - val iframe = app.get(httpsify(server ?: return)) - val iframeDoc = iframe.document - - argamap({ - iframeDoc.select(".list-server-items > .linkserver") - .forEach { element -> - val status = element.attr("data-status") ?: return@forEach - if (status != "1") return@forEach - val extractorData = element.attr("data-video") ?: return@forEach - loadExtractor(extractorData, iframe.url, subtitleCallback, callback) - } - }, { - val iv = "9225679083961858" - val secretKey = "25742532592138496744665879883281" - GogoHelper.extractVidstream( - iframe.url, - "Vidstream", - callback, - iv, - secretKey, - secretKey, - isUsingAdaptiveKeys = false, - isUsingAdaptiveData = true, - iframeDocument = iframeDoc - ) - }) - } - suspend fun invokeIdlix( title: String? = null, year: Int? = null, @@ -2292,6 +2240,27 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeOmega( + tmdbId: Int? = null, + callback: (ExtractorLink) -> Unit, + ) { + app.get("$omegaAPI/v3/movie/sources/$tmdbId") + .parsedSafe()?.sources?.filter { it.label != "2" }?.map { sources -> + sources.sources?.map source@{ source -> + callback.invoke( + ExtractorLink( + "Omega ${sources.label}", + "Omega ${sources.label}", + source.url ?: return@source, + "", + getQualityFromName(source.quality), + INFER_TYPE + ) + ) + } + } + } + suspend fun invokeAsk4Movies( title: String? = null, year: Int? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 483be230..fe32debf 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -58,6 +58,20 @@ data class KisskhSources( @JsonProperty("ThirdParty") val thirdParty: String?, ) +data class OmegaSource( + @JsonProperty("quality") val quality: String? = null, + @JsonProperty("url") val url: String? = null, +) + +data class OmegaSources( + @JsonProperty("label") val label: String? = null, + @JsonProperty("sources") val sources: ArrayList? = arrayListOf(), +) + +data class OmegaResponse( + @JsonProperty("sources") val sources: ArrayList? = arrayListOf(), +) + data class KisskhSubtitle( @JsonProperty("src") val src: String?, @JsonProperty("label") val label: String?, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index c58f07ec..617ecb57 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -11,7 +11,6 @@ import com.hexated.SoraExtractor.invokeFilmxy import com.hexated.SoraExtractor.invokeIdlix import com.hexated.SoraExtractor.invokeKimcartoon import com.hexated.SoraExtractor.invokeMovieHab -import com.hexated.SoraExtractor.invokeSeries9 import com.hexated.SoraExtractor.invokeVidSrc import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer @@ -44,9 +43,9 @@ import com.hexated.SoraExtractor.invokeJump1 import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies +import com.hexated.SoraExtractor.invokeOmega import com.hexated.SoraExtractor.invokePobmovies import com.hexated.SoraExtractor.invokePrimewire -import com.hexated.SoraExtractor.invokeSusflix import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeVidsrcto @@ -91,7 +90,6 @@ open class SoraStream : TmdbProvider() { const val dbgoAPI = "https://dbgo.fun" const val movieHabAPI = "https://moviehab.com" const val dreamfilmAPI = "https://dreamfilmsw.net" - const val series9API = "https://series9.cx" const val idlixAPI = "https://tv.idlixplus.net" const val noverseAPI = "https://www.nollyverse.com" const val filmxyAPI = "https://www.filmxy.vip" @@ -134,6 +132,7 @@ open class SoraStream : TmdbProvider() { const val animetoshoAPI = "https://animetosho.org" const val susflixAPI = "https://susflix.tv" const val jump1API = "https://ca.jump1.net" + const val omegaAPI = "https://prod.omega.themoviearchive.site" // INDEX SITE const val dahmerMoviesAPI = "https://edytjedhgmdhm.abfhaqrhbnf.workers.dev" @@ -249,7 +248,8 @@ open class SoraStream : TmdbProvider() { val year = releaseDate?.split("-")?.first()?.toIntOrNull() val rating = res.vote_average.toString().toRatingInt() val genres = res.genres?.mapNotNull { it.name } - val isAnime = genres?.contains("Animation") == true && (res.original_language == "zh" || res.original_language == "ja") + val isAnime = + genres?.contains("Animation") == true && (res.original_language == "zh" || res.original_language == "ja") val isAsian = !isAnime && (res.original_language == "zh" || res.original_language == "ko") val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty() .ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } } @@ -426,16 +426,6 @@ open class SoraStream : TmdbProvider() { callback ) }, - { - invokeSeries9( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, { invokeIdlix( res.title, @@ -528,7 +518,7 @@ open class SoraStream : TmdbProvider() { ) }, { - if(!res.isAnime) invokeM4uhd( + if (!res.isAnime) invokeM4uhd( res.title, res.airedYear ?: res.year, res.season, @@ -723,7 +713,7 @@ open class SoraStream : TmdbProvider() { ) }, { - if(res.isAsian) invokeDramaday( + if (res.isAsian) invokeDramaday( res.title, res.year, res.season, @@ -733,13 +723,13 @@ open class SoraStream : TmdbProvider() { ) }, { - if(!res.isAnime) invoke2embed(res.imdbId,res.season,res.episode,callback) + if (!res.isAnime) invoke2embed(res.imdbId, res.season, res.episode, callback) }, // { // invokeSusflix(res.id,res.season,res.episode,subtitleCallback,callback) // }, { - if(!res.isAnime) invokeJump1( + if (!res.isAnime) invokeJump1( res.id, res.tvdbId, res.title, @@ -749,6 +739,12 @@ open class SoraStream : TmdbProvider() { callback ) }, + { + if (!res.isAnime && res.season == null) invokeOmega( + res.id, + callback + ) + }, ) return true diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index abe0c861..d0f9146e 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -22,7 +22,6 @@ import com.hexated.SoraExtractor.invokeNinetv import com.hexated.SoraExtractor.invokeNowTv import com.hexated.SoraExtractor.invokeRStream import com.hexated.SoraExtractor.invokeRidomovies -import com.hexated.SoraExtractor.invokeSeries9 import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies @@ -31,6 +30,7 @@ import com.hexated.SoraExtractor.invokeJump1 import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies +import com.hexated.SoraExtractor.invokeOmega import com.hexated.SoraExtractor.invokePrimewire import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeVidsrcto @@ -134,16 +134,6 @@ class SoraStreamLite : SoraStream() { callback ) }, - { - invokeSeries9( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, { invokeIdlix( res.title, @@ -245,6 +235,12 @@ class SoraStreamLite : SoraStream() { callback ) }, + { + if (!res.isAnime && res.season == null) invokeOmega( + res.id, + callback + ) + }, { invokeRStream(res.id, res.season, res.episode, callback) }, From c6f89db48a9d8e509dba8b9449a5a39b146a4d4b Mon Sep 17 00:00:00 2001 From: hexated Date: Mon, 11 Sep 2023 18:34:11 +0700 Subject: [PATCH 100/105] fix #263 --- SoraStream/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/SoraExtractor.kt | 2 ++ SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt | 12 ++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 129c982d..82fa01b5 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 = 166 +version = 167 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 5b80bdfd..5f6e72f0 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1100,7 +1100,9 @@ object SoraExtractor : SoraStream() { val driveReq = app.get(driveLink) val driveRes = driveReq.document val bitLink = driveRes.select("a.btn.btn-outline-success").attr("href") + val insLink = driveRes.select("a.btn.btn-danger:contains(Instant Download)").attr("href") val downloadLink = when { + insLink.isNotEmpty() -> extractInstantUHD(insLink) driveRes.select("button.btn.btn-success").text() .contains("Direct Download", true) -> extractDirectUHD(driveLink, driveReq) bitLink.isNullOrEmpty() -> { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 09f6f822..5895b637 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -163,6 +163,18 @@ suspend fun extractMirrorUHD(url: String, ref: String): String? { ) } +suspend fun extractInstantUHD(url: String): String? { + val host = getBaseUrl(url) + val body = FormBody.Builder() + .addEncoded("keys", url.substringAfter("url=")) + .build() + return app.post( + "$host/api", requestBody = body, headers = mapOf( + "x-token" to "${url.toUri().host}" + ), referer = "$host/" + ).parsedSafe>()?.get("url") +} + suspend fun extractDirectUHD(url: String, niceResponse: NiceResponse): String? { val document = niceResponse.document val script = document.selectFirst("script:containsData(cf_token)")?.data() ?: return null From 7dabff1da9cde26a83c84a58d32b67971976d656 Mon Sep 17 00:00:00 2001 From: helo Date: Mon, 11 Sep 2023 22:25:05 +0700 Subject: [PATCH 101/105] anime/indo: optimize detail page and domain --- Animasu/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Animasu.kt | 17 +++++++++++----- AnimeIndoProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/AnimeIndoProvider.kt | 17 +++++++++++----- AnimeSailProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/AnimeSailProvider.kt | 15 ++++++++++---- KuramanimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/KuramanimeProvider.kt | 16 ++++++++++----- KuronimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/KuronimeProvider.kt | 17 +++++++++++----- NeonimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/NeonimeProvider.kt | 19 +++++++++++++----- Nimegami/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Nimegami.kt | 18 +++++++++++------ NontonAnimeIDProvider/build.gradle.kts | 2 +- .../com/hexated/NontonAnimeIDProvider.kt | 17 ++++++++++------ OploverzProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/OploverzProvider.kt | 20 ++++++++++++------- OtakudesuProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/OtakudesuProvider.kt | 17 +++++++++++----- Samehadaku/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Samehadaku.kt | 17 +++++++++++----- 22 files changed, 143 insertions(+), 69 deletions(-) diff --git a/Animasu/build.gradle.kts b/Animasu/build.gradle.kts index 4c3d51d1..ce71e900 100644 --- a/Animasu/build.gradle.kts +++ b/Animasu/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { diff --git a/Animasu/src/main/kotlin/com/hexated/Animasu.kt b/Animasu/src/main/kotlin/com/hexated/Animasu.kt index e6e38833..04efbd3a 100644 --- a/Animasu/src/main/kotlin/com/hexated/Animasu.kt +++ b/Animasu/src/main/kotlin/com/hexated/Animasu.kt @@ -1,13 +1,15 @@ package com.hexated import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.* import org.jsoup.Jsoup import org.jsoup.nodes.Element class Animasu : MainAPI() { - override var mainUrl = "https://animasu.cc" + override var mainUrl = "https://animasu.uno" override var name = "Animasu" override val hasMainPage = true override var lang = "id" @@ -99,7 +101,7 @@ class Animasu : MainAPI() { val poster = document.selectFirst("div.bigcontent img")?.attr("src")?.replace("\n", "") val table = document.selectFirst("div.infox div.spe") - val type = table?.selectFirst("span:contains(Jenis:)")?.ownText() + val type = getType(table?.selectFirst("span:contains(Jenis:)")?.ownText()) val year = table?.selectFirst("span:contains(Rilis:)")?.ownText()?.substringAfterLast(",")?.trim()?.toIntOrNull() val status = table?.selectFirst("span:contains(Status:) font")?.text() val trailer = document.selectFirst("div.trailer iframe")?.attr("src") @@ -107,17 +109,22 @@ class Animasu : MainAPI() { val link = fixUrl(it.selectFirst("a")!!.attr("href")) val name = it.selectFirst("a")?.text() ?: "" val episode = Regex("Episode\\s?(\\d+)").find(name)?.groupValues?.getOrNull(0)?.toIntOrNull() - Episode(link, name, episode = episode) + Episode(link, episode = episode) }.reversed() - return newAnimeLoadResponse(title, url, getType(type)) { - posterUrl = poster + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = getStatus(status) plot = document.select("div.sinopsis p").text() this.tags = table?.select("span:contains(Genre:) a")?.map { it.text() } addTrailer(trailer) + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } diff --git a/AnimeIndoProvider/build.gradle.kts b/AnimeIndoProvider/build.gradle.kts index d52cf888..f6e8b592 100644 --- a/AnimeIndoProvider/build.gradle.kts +++ b/AnimeIndoProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 13 +version = 14 cloudstream { diff --git a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt index aee7726e..5f3d09bd 100644 --- a/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt +++ b/AnimeIndoProvider/src/main/kotlin/com/hexated/AnimeIndoProvider.kt @@ -1,6 +1,8 @@ package com.hexated import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.httpsify @@ -113,8 +115,8 @@ class AnimeIndoProvider : MainAPI() { ?.trim() ?: return null val poster = document.selectFirst("div.thumb > img[itemprop=image]")?.attr("src") val tags = document.select("div.genxed > a").map { it.text() } - val type = document.selectFirst("div.info-content > div.spe > span:contains(Type:)")?.ownText() - ?.trim()?.lowercase() ?: "tv" + val type = getType(document.selectFirst("div.info-content > div.spe > span:contains(Type:)")?.ownText() + ?.trim()?.lowercase() ?: "tv") val year = document.selectFirst("div.info-content > div.spe > span:contains(Released:)")?.ownText()?.let { Regex("\\d,\\s(\\d*)").find(it)?.groupValues?.get(1)?.toIntOrNull() } @@ -126,16 +128,19 @@ class AnimeIndoProvider : MainAPI() { val header = it.selectFirst("span.lchx > a") ?: return@mapNotNull null val episode = header.text().trim().replace("Episode", "").trim().toIntOrNull() val link = fixUrl(header.attr("href")) - Episode(link, header.text(), episode = episode) + Episode(link, episode = episode) }.reversed() val recommendations = document.select("div.relat div.animposx").mapNotNull { it.toSearchResult() } - return newAnimeLoadResponse(title, url, getType(type)) { + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { engName = title - posterUrl = poster + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status @@ -143,6 +148,8 @@ class AnimeIndoProvider : MainAPI() { this.tags = tags this.recommendations = recommendations addTrailer(trailer) + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } diff --git a/AnimeSailProvider/build.gradle.kts b/AnimeSailProvider/build.gradle.kts index 73173634..cea32bdc 100644 --- a/AnimeSailProvider/build.gradle.kts +++ b/AnimeSailProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 9 +version = 10 cloudstream { diff --git a/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt b/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt index da62e664..721121a2 100644 --- a/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt +++ b/AnimeSailProvider/src/main/kotlin/com/hexated/AnimeSailProvider.kt @@ -1,6 +1,8 @@ package com.hexated import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLinkType @@ -108,18 +110,21 @@ class AnimeSailProvider : MainAPI() { val title = document.selectFirst("h1.entry-title")?.text().toString() .replace("Subtitle Indonesia", "").trim() val poster = document.selectFirst("div.entry-content > img")?.attr("src") - val type = document.select("tbody th:contains(Tipe)").next().text().lowercase() + val type = getType(document.select("tbody th:contains(Tipe)").next().text().lowercase()) val year = document.select("tbody th:contains(Dirilis)").next().text().trim().toIntOrNull() val episodes = document.select("ul.daftar > li").map { val link = fixUrl(it.select("a").attr("href")) val name = it.select("a").text() val episode = Regex("Episode\\s?(\\d+)").find(name)?.groupValues?.getOrNull(0)?.toIntOrNull() - Episode(link, name, episode = episode) + Episode(link, episode = episode) }.reversed() - return newAnimeLoadResponse(title, url, getType(type)) { - posterUrl = poster + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = @@ -127,6 +132,8 @@ class AnimeSailProvider : MainAPI() { plot = document.selectFirst("div.entry-content > p")?.text() this.tags = document.select("tbody th:contains(Genre)").next().select("a").map { it.text() } + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } diff --git a/KuramanimeProvider/build.gradle.kts b/KuramanimeProvider/build.gradle.kts index 400d87fb..34c7e57e 100644 --- a/KuramanimeProvider/build.gradle.kts +++ b/KuramanimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 14 +version = 15 cloudstream { diff --git a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt index b8751442..63a94194 100644 --- a/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt +++ b/KuramanimeProvider/src/main/kotlin/com/hexated/KuramanimeProvider.kt @@ -1,6 +1,8 @@ package com.hexated import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.Qualities @@ -106,7 +108,6 @@ class KuramanimeProvider : MainAPI() { document.select("div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(3)") .text().trim().replace("Status: ", "") ) - val type = document.selectFirst("div.col-lg-6.col-md-6 ul li:contains(Tipe:) a")?.text()?.lowercase() ?: "tv" val description = document.select(".anime__details__text > p").text().trim() val episodes = mutableListOf() @@ -119,31 +120,36 @@ class KuramanimeProvider : MainAPI() { val episode = Regex("(\\d+[.,]?\\d*)").find(name)?.groupValues?.getOrNull(0) ?.toIntOrNull() val link = it.attr("href") - Episode(link, name, episode = episode) + Episode(link, episode = episode) } if(eps.isEmpty()) break else episodes.addAll(eps) } + val type = getType(document.selectFirst("div.col-lg-6.col-md-6 ul li:contains(Tipe:) a")?.text()?.lowercase() ?: "tv", episodes.size) val recommendations = document.select("div#randomList > a").mapNotNull { val epHref = it.attr("href") val epTitle = it.select("h5.sidebar-title-h5.px-2.py-2").text() val epPoster = it.select(".product__sidebar__view__item.set-bg").attr("data-setbg") - newAnimeSearchResponse(epTitle, epHref, TvType.Anime) { this.posterUrl = epPoster addDubStatus(dubExist = false, subExist = true) } } - return newAnimeLoadResponse(title, url, getType(type, episodes.size)) { + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { engName = title - posterUrl = poster + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status plot = description this.tags = tags this.recommendations = recommendations + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } diff --git a/KuronimeProvider/build.gradle.kts b/KuronimeProvider/build.gradle.kts index 74ca1975..5b95951e 100644 --- a/KuronimeProvider/build.gradle.kts +++ b/KuronimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 15 +version = 16 cloudstream { diff --git a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt index 9160beb0..1a49aaee 100644 --- a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt +++ b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt @@ -2,6 +2,8 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.extractors.helper.AesHelper import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson @@ -130,8 +132,8 @@ class KuronimeProvider : MainAPI() { val poster = document.selectFirst("div.l[itemprop=image] > img")?.attr("data-src") val tags = document.select(".infodetail > ul > li:nth-child(2) > a").map { it.text() } val type = - document.selectFirst(".infodetail > ul > li:nth-child(7)")?.ownText()?.removePrefix(":") - ?.lowercase()?.trim() ?: "tv" + getType(document.selectFirst(".infodetail > ul > li:nth-child(7)")?.ownText()?.removePrefix(":") + ?.lowercase()?.trim() ?: "tv") val trailer = document.selectFirst("div.tply iframe")?.attr("data-src") val year = Regex("\\d, (\\d*)").find( @@ -148,18 +150,23 @@ class KuronimeProvider : MainAPI() { val name = it.selectFirst("a")?.text() ?: return@mapNotNull null val episode = Regex("(\\d+[.,]?\\d*)").find(name)?.groupValues?.getOrNull(0)?.toIntOrNull() - Episode(link, name, episode = episode) + Episode(link, episode = episode) }.reversed() - return newAnimeLoadResponse(title, url, getType(type)) { + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { engName = title - posterUrl = poster + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status plot = description addTrailer(trailer) this.tags = tags + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } diff --git a/NeonimeProvider/build.gradle.kts b/NeonimeProvider/build.gradle.kts index 657d7382..bfa7a96c 100644 --- a/NeonimeProvider/build.gradle.kts +++ b/NeonimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 7 +version = 8 cloudstream { diff --git a/NeonimeProvider/src/main/kotlin/com/hexated/NeonimeProvider.kt b/NeonimeProvider/src/main/kotlin/com/hexated/NeonimeProvider.kt index bd7059d5..f6e2d83c 100644 --- a/NeonimeProvider/src/main/kotlin/com/hexated/NeonimeProvider.kt +++ b/NeonimeProvider/src/main/kotlin/com/hexated/NeonimeProvider.kt @@ -1,6 +1,8 @@ package com.hexated import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor @@ -8,7 +10,7 @@ import org.jsoup.nodes.Element import java.net.URI class NeonimeProvider : MainAPI() { - override var mainUrl = "https://neonime.fun" + override var mainUrl = "https://neonime.ink" private var baseUrl = mainUrl override var name = "Neonime" override val hasQuickSearch = false @@ -120,13 +122,17 @@ class NeonimeProvider : MainAPI() { val mPoster = document.selectFirst(".sbox > .imagen > .fix > img[itemprop = image]")?.attr("data-src") val mTrailer = document.selectFirst("div.youtube_id iframe")?.attr("data-wpfc-original-src")?.substringAfterLast("html#")?.let{ "https://www.youtube.com/embed/$it"} val year = document.selectFirst("a[href*=release-year]")!!.text().toIntOrNull() + val tracker = APIHolder.getTracker(listOf(mTitle),TrackerType.getTypes(TvType.Movie),year,true) return newMovieLoadResponse(name = mTitle, url = url, type = TvType.Movie, dataUrl = url) { - posterUrl = mPoster + posterUrl = tracker?.image ?: mPoster + backgroundPosterUrl = tracker?.cover this.year = year plot = document.select("div[itemprop = description]").text().trim() rating = document.select("span[itemprop = ratingValue]").text().toIntOrNull() tags = document.select("p.meta_dd > a").map { it.text() } addTrailer(mTrailer) + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } else { @@ -138,18 +144,21 @@ class NeonimeProvider : MainAPI() { val link = fixUrl(it.selectFirst(".episodiotitle > a")!!.attr("href")) val name = it.selectFirst(".episodiotitle > a")?.ownText().toString() val episode = Regex("(\\d+[.,]?\\d*)").find(name)?.groupValues?.getOrNull(0)?.toIntOrNull() - Episode(link, name, episode = episode) + Episode(link, episode = episode) }.reversed() - + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(TvType.Anime),year,true) return newAnimeLoadResponse(title, url, TvType.Anime) { engName = title - posterUrl = poster + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = getStatus(document.select("div.metadatac > span").last()!!.text().trim()) plot = document.select("div[itemprop = description] > p").text().trim() tags = document.select("#info a[href*=\"-genre/\"]").map { it.text() } addTrailer(trailer) + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } } diff --git a/Nimegami/build.gradle.kts b/Nimegami/build.gradle.kts index afc730a5..a1e4ca98 100644 --- a/Nimegami/build.gradle.kts +++ b/Nimegami/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt index 3143bc15..5fffdd9d 100644 --- a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt +++ b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt @@ -2,6 +2,8 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson @@ -96,15 +98,15 @@ class Nimegami : MainAPI() { val year = table.getContent("Musim / Rilis").text().filter { it.isDigit() }.toIntOrNull() val status = getStatus(document.selectFirst("h1[itemprop=headline]")?.text()) - val type = table.getContent("Type").text() + val type = getType(table.getContent("Type").text()) val description = document.select("div#Sinopsis p").text().trim() val trailer = document.selectFirst("div#Trailer iframe")?.attr("src") val episodes = document.select("div.list_eps_stream li") .mapNotNull { - val name = it.text() + val episode = Regex("Episode\\s?(\\d+)").find(it.text())?.groupValues?.getOrNull(0)?.toIntOrNull() val link = it.attr("data") - Episode(link, name) + Episode(link, episode = episode) } val recommendations = document.select("div#randomList > a").mapNotNull { @@ -118,10 +120,12 @@ class Nimegami : MainAPI() { } } - return newAnimeLoadResponse(title, url, getType(type)) { + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { engName = title - posterUrl = poster - backgroundPosterUrl = bgPoster + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover ?: bgPoster this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status @@ -129,6 +133,8 @@ class Nimegami : MainAPI() { this.tags = tags this.recommendations = recommendations addTrailer(trailer) + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } diff --git a/NontonAnimeIDProvider/build.gradle.kts b/NontonAnimeIDProvider/build.gradle.kts index cff263d4..14a56948 100644 --- a/NontonAnimeIDProvider/build.gradle.kts +++ b/NontonAnimeIDProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 16 +version = 17 cloudstream { diff --git a/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt b/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt index 2912e7a2..6f068fba 100644 --- a/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt +++ b/NontonAnimeIDProvider/src/main/kotlin/com/hexated/NontonAnimeIDProvider.kt @@ -2,6 +2,8 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.extractors.Hxfile import com.lagradost.cloudstream3.utils.ExtractorLink @@ -11,7 +13,7 @@ import org.jsoup.nodes.Element import java.net.URI class NontonAnimeIDProvider : MainAPI() { - override var mainUrl = "https://nontonanimeid.lol" + override var mainUrl = "https://nontonanimeid.top" override var name = "NontonAnimeID" override val hasQuickSearch = false override val hasMainPage = true @@ -130,7 +132,7 @@ class NontonAnimeIDProvider : MainAPI() { val status = getStatus( document.select("span.statusseries").text().trim() ) - val type = document.select("span.typeseries").text().trim().lowercase() + val type = getType(document.select("span.typeseries").text().trim().lowercase()) val rating = document.select("span.nilaiseries").text().trim().toIntOrNull() val description = document.select(".entry-content.seriesdesc > p").text().trim() val trailer = document.selectFirst("a.trailerbutton")?.attr("href") @@ -167,21 +169,22 @@ class NontonAnimeIDProvider : MainAPI() { }.reversed() } - val recommendations = document.select(".result > li").mapNotNull { val epHref = it.selectFirst("a")!!.attr("href") val epTitle = it.selectFirst("h3")!!.text() val epPoster = it.select(".top > img").attr("data-src") - newAnimeSearchResponse(epTitle, epHref, TvType.Anime) { this.posterUrl = epPoster addDubStatus(dubExist = false, subExist = true) } } - return newAnimeLoadResponse(title, url, getType(type)) { + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { engName = title - posterUrl = poster + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status @@ -190,6 +193,8 @@ class NontonAnimeIDProvider : MainAPI() { addTrailer(trailer) this.tags = tags this.recommendations = recommendations + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } diff --git a/OploverzProvider/build.gradle.kts b/OploverzProvider/build.gradle.kts index 3b5d9597..e2ebbfc0 100644 --- a/OploverzProvider/build.gradle.kts +++ b/OploverzProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 23 +version = 24 cloudstream { diff --git a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt index 92547017..8ed03196 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt @@ -1,7 +1,8 @@ package com.hexated import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.extractors.Filesim +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.utils.* import org.jsoup.nodes.Element @@ -113,18 +114,21 @@ class OploverzProvider : MainAPI() { val title = document.selectFirst("h1.entry-title")?.text() ?.replace("Subtitle Indonesia", "")?.trim() ?: "" - val type = document.selectFirst("div.alternati span.type")?.text() ?: "" - + val type = getType(document.selectFirst("div.alternati span.type")?.text() ?: "") + val year = document.selectFirst("div.alternati a")?.text()?.filter { it.isDigit() }?.toIntOrNull() val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull { val header = it.selectFirst("a") ?: return@mapNotNull null val episode = header.text().trim().toIntOrNull() val link = fixUrl(header.attr("href")) - Episode(link, header.text(), episode = episode) + Episode(link, episode = episode) }.reversed() - return newAnimeLoadResponse(title, url, getType(type)) { - posterUrl = document.selectFirst("div.thumb > img")?.attr("src") - this.year = document.selectFirst("div.alternati a")?.text()?.filter { it.isDigit() }?.toIntOrNull() + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { + posterUrl = tracker?.image ?: document.selectFirst("div.thumb > img")?.attr("src") + backgroundPosterUrl = tracker?.cover + this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = getStatus( @@ -133,6 +137,8 @@ class OploverzProvider : MainAPI() { plot = document.selectFirst("div.entry-content > p")?.text()?.trim() this.tags = document.select("div.genre-info a").map { it.text() } + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } diff --git a/OtakudesuProvider/build.gradle.kts b/OtakudesuProvider/build.gradle.kts index 39e00b68..fd37451e 100644 --- a/OtakudesuProvider/build.gradle.kts +++ b/OtakudesuProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 14 +version = 15 cloudstream { diff --git a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt index 0a4b0dd3..9632d72e 100644 --- a/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt +++ b/OtakudesuProvider/src/main/kotlin/com/hexated/OtakudesuProvider.kt @@ -2,6 +2,8 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.extractors.JWPlayer import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink @@ -94,8 +96,8 @@ class OtakudesuProvider : MainAPI() { ?.replace(":", "")?.trim().toString() val poster = document.selectFirst("div.fotoanime > img")?.attr("src") val tags = document.select("div.infozingle > p:nth-child(11) > span > a").map { it.text() } - val type = document.selectFirst("div.infozingle > p:nth-child(5) > span")?.ownText() - ?.replace(":", "")?.trim() ?: "tv" + val type = getType(document.selectFirst("div.infozingle > p:nth-child(5) > span")?.ownText() + ?.replace(":", "")?.trim() ?: "tv") val year = Regex("\\d, (\\d*)").find( document.select("div.infozingle > p:nth-child(9) > span").text() @@ -112,7 +114,7 @@ class OtakudesuProvider : MainAPI() { val episode = Regex("Episode\\s?(\\d+)").find(name)?.groupValues?.getOrNull(0) ?: it.selectFirst("a")?.text() val link = fixUrl(it.selectFirst("a")!!.attr("href")) - Episode(link, name, episode = episode?.toIntOrNull()) + Episode(link, episode = episode?.toIntOrNull()) }.reversed() val recommendations = @@ -125,15 +127,20 @@ class OtakudesuProvider : MainAPI() { } } - return newAnimeLoadResponse(title, url, getType(type)) { + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { engName = title - posterUrl = poster + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status plot = description this.tags = tags this.recommendations = recommendations + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } diff --git a/Samehadaku/build.gradle.kts b/Samehadaku/build.gradle.kts index 1c566566..f3101866 100644 --- a/Samehadaku/build.gradle.kts +++ b/Samehadaku/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 14 +version = 15 cloudstream { diff --git a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt index a903d225..d97e5426 100644 --- a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt +++ b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt @@ -1,6 +1,8 @@ package com.hexated import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId +import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.Qualities @@ -8,7 +10,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element class Samehadaku : MainAPI() { - override var mainUrl = "https://samehadaku.world" + override var mainUrl = "https://samehadaku.bond" override var name = "Samehadaku" override val hasMainPage = true override var lang = "id" @@ -111,8 +113,8 @@ class Samehadaku : MainAPI() { document.selectFirst("div.spe > span:contains(Status)")?.ownText() ?: return null ) val type = - document.selectFirst("div.spe > span:contains(Type)")?.ownText()?.trim()?.lowercase() - ?: "tv" + getType(document.selectFirst("div.spe > span:contains(Type)")?.ownText()?.trim()?.lowercase() + ?: "tv") val rating = document.selectFirst("span.ratingValue")?.text()?.trim()?.toRatingInt() val description = document.select("div.desc p").text().trim() val trailer = document.selectFirst("div.trailer-anime iframe")?.attr("src") @@ -129,9 +131,12 @@ class Samehadaku : MainAPI() { it.toSearchResult() } - return newAnimeLoadResponse(title, url, getType(type)) { + val tracker = APIHolder.getTracker(listOf(title),TrackerType.getTypes(type),year,true) + + return newAnimeLoadResponse(title, url, type) { engName = title - posterUrl = poster + posterUrl = tracker?.image ?: poster + backgroundPosterUrl = tracker?.cover this.year = year addEpisodes(DubStatus.Subbed, episodes) showStatus = status @@ -140,6 +145,8 @@ class Samehadaku : MainAPI() { addTrailer(trailer) this.tags = tags this.recommendations = recommendations + addMalId(tracker?.malId) + addAniListId(tracker?.aniId?.toIntOrNull()) } } From 2dd73dd012b1157c56bc0e0a04e816a5204c5db0 Mon Sep 17 00:00:00 2001 From: helo Date: Mon, 11 Sep 2023 22:56:36 +0700 Subject: [PATCH 102/105] fix build --- SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 5895b637..f9d02a50 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -170,7 +170,7 @@ suspend fun extractInstantUHD(url: String): String? { .build() return app.post( "$host/api", requestBody = body, headers = mapOf( - "x-token" to "${url.toUri().host}" + "x-token" to URI(url).host ), referer = "$host/" ).parsedSafe>()?.get("url") } From d3aed5ccc10660931b8cbe7dcd36d335c20ded11 Mon Sep 17 00:00:00 2001 From: IndusAryan <125901294+IndusAryan@users.noreply.github.com> Date: Tue, 12 Sep 2023 05:24:24 +0530 Subject: [PATCH 103/105] update: Yomovies domain (#266) * Update YomoviesProvider.kt * Update build.gradle.kts --- YomoviesProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/YomoviesProvider.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/YomoviesProvider/build.gradle.kts b/YomoviesProvider/build.gradle.kts index f5249c1c..7ea9709a 100644 --- a/YomoviesProvider/build.gradle.kts +++ b/YomoviesProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 17 +version = 18 cloudstream { diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt index f75772cc..9919400c 100644 --- a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt +++ b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt @@ -10,7 +10,7 @@ import org.jsoup.nodes.Element import java.net.URI open class YomoviesProvider : MainAPI() { - override var mainUrl = "https://yomovies.fan" + override var mainUrl = "https://yomovies.cheap" private var directUrl = "" override var name = "Yomovies" override val hasMainPage = true From 02c7a9b51197379711401c2c274b2b1a1c4cf8cc Mon Sep 17 00:00:00 2001 From: Serene Mathew <46328829+hatt3r@users.noreply.github.com> Date: Tue, 12 Sep 2023 05:24:37 +0530 Subject: [PATCH 104/105] changing domain name (#265) had different domain name, so updating it --- WcofunProvider/src/main/kotlin/com/hexated/WcofunProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WcofunProvider/src/main/kotlin/com/hexated/WcofunProvider.kt b/WcofunProvider/src/main/kotlin/com/hexated/WcofunProvider.kt index 0fd06390..b6c5193e 100644 --- a/WcofunProvider/src/main/kotlin/com/hexated/WcofunProvider.kt +++ b/WcofunProvider/src/main/kotlin/com/hexated/WcofunProvider.kt @@ -9,7 +9,7 @@ import org.jsoup.Jsoup import org.jsoup.nodes.Element class WcofunProvider : MainAPI() { - override var mainUrl = "https://www.wcofun.net" + override var mainUrl = "https://www.wcofun.org" override var name = "WCO Fun" override val hasMainPage = true override val hasDownloadSupport = true From 2c3bab56c514204b2e725fa0f477632becbbc7e8 Mon Sep 17 00:00:00 2001 From: helo Date: Tue, 12 Sep 2023 11:58:10 +0700 Subject: [PATCH 105/105] Kuronime: fix video source --- KuronimeProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/KuronimeProvider.kt | 19 +++++++------------ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/KuronimeProvider/build.gradle.kts b/KuronimeProvider/build.gradle.kts index 5b95951e..84d6863e 100644 --- a/KuronimeProvider/build.gradle.kts +++ b/KuronimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 16 +version = 17 cloudstream { diff --git a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt index 1a49aaee..70e75127 100644 --- a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt +++ b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt @@ -8,7 +8,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.extractors.helper.AesHelper import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.Qualities +import com.lagradost.cloudstream3.utils.M3u8Helper import com.lagradost.cloudstream3.utils.getQualityFromName import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element @@ -197,17 +197,12 @@ class KuronimeProvider : MainAPI() { ) val source = tryParseJson(decrypt?.toJsonFormat())?.src?.replace("\\", "") - callback.invoke( - ExtractorLink( - this.name, - this.name, - source ?: return@argamap, - "$animekuUrl/", - Qualities.P1080.value, - true, - headers = mapOf("Origin" to animekuUrl) - ) - ) + M3u8Helper.generateM3u8( + this.name, + source ?: return@argamap, + "$animekuUrl/", + headers = mapOf("Origin" to animekuUrl) + ).forEach(callback) }, { val decrypt = AesHelper.cryptoAESHandler(