From 2ec22f868535258bc3e1067999f6da879ae1539e Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Wed, 20 Dec 2023 15:33:26 +0700 Subject: [PATCH 001/125] Update SoraExtractor.kt --- 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 ef4bc6d9..6833110d 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2094,7 +2094,7 @@ object SoraExtractor : SoraStream() { .substringBefore("-") } val res = app.get(fixUrl(iframe, api), verify = false) - delay(1000) + delay(2000) val serverUrl = res.document.selectFirst("script:containsData(pushState)")?.data()?.let { """,\s*'([^']+)""".toRegex().find(it)?.groupValues?.get(1) } ?: return From 3db0da8dd1682834bd9b76cafd5640bba30df372 Mon Sep 17 00:00:00 2001 From: lisa Date: Wed, 20 Dec 2023 21:54:14 +0700 Subject: [PATCH 002/125] update --- SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index ef4bc6d9..0c6d6112 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2149,8 +2149,8 @@ object SoraExtractor : SoraStream() { "$blackvidAPI/v3/tv/sources/$tmdbId/$season/$episode?key=$key" } - val res = request(url).body - val bytes = res.bytes().also { res.closeQuietly() } + val res = request(url) + val bytes = res.peekBody(1024 * 512).bytes().also { res.closeQuietly() } val data = bytes.decrypt("2378f8e4e844f2dc839ab48f66e00acc2305a401") val json = tryParseJson(data) From d94f79e9a712fe83ddf33732318260ad7c981c8f Mon Sep 17 00:00:00 2001 From: lisa Date: Wed, 20 Dec 2023 22:52:04 +0700 Subject: [PATCH 003/125] update --- .../main/kotlin/com/hexated/SoraExtractor.kt | 5 ++- .../src/main/kotlin/com/hexated/SoraUtils.kt | 44 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index f44058d0..59757a47 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2260,10 +2260,11 @@ object SoraExtractor : SoraStream() { } val session = "PHPSESSID=ngr4cudjrimdnhkth30ssohs0n; _csrf=a6ffd7bb7654083fce6df528225a238d0e85aa1fb885dc7638c1259ec1ba0d5ca%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22mTTLiDLjxohs-CpKk0bjRH3HdYMB9uBV%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0" + cinemaCookiesChecker(session) + val headers = mapOf( "Cookie" to session, - "Connection" to "keep-alive", - "x-requested-with" to "XMLHttpRequest", + "x-requested-with" to "com.wwcinematv", ) val doc = app.get(url, headers = headers).document diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index f5895a6e..3ca40d2d 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -49,6 +49,7 @@ import kotlin.math.min var watchflxCookies: Map? = null var filmxyCookies: Map? = null var sfServer: String? = null +var cinemaCookiesChecker: Boolean? = null val encodedIndex = arrayOf( "GamMovies", @@ -647,6 +648,49 @@ suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair) { + app.get( + "$wiwiApi/api/v1/app-config", + headers = headers + ).text + } + suspend fun checkCookies(session: String, headers: Map) { + app.post( + "$wiwiApi/api/v1/cookie", + data = mapOf("cookie" to session), + headers = headers + ).text + } + val configHeaders = mapOf( + "App-version" to "3.4", + "Authorization" to "Basic d2l3aTpXaXdpQDIwMjA=", + "Country" to "Indonesia", + "Device-id" to getDeviceId(), + "User-id" to "user-6694327", + ) + listOf(1..2).apmap { createConfig(configHeaders) } + val unityData = """ + { + "platform": "android", + "idfi": "d1ec7051-f58f-4ddb-9da8-8debb82cfbea", + "sdkVersionName": "4.3.0", + "gdpr.consent": true, + "user.nonbehavioral": false, + "unity.privacy.permissions.all": false, + "unity.privacy.permissions.gameExp": false, + "unity.privacy.permissions.ads": false, + "unity.privacy.permissions.external": false + } + """.trimIndent().toJson().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) + app.post("https://configv2.unityads.unity3d.com/privacy/4519473/state", requestBody = unityData).text + listOf(1..4).map {checkCookies(session, configHeaders)} + return true +} + suspend fun getSfServer() = sfServer ?: fetchSfServer().also { sfServer = it } suspend fun fetchSfServer(): String { From f05a3cfc15f2a38f832b9532c7b79a4e2549a8ee Mon Sep 17 00:00:00 2001 From: lisa Date: Thu, 21 Dec 2023 01:34:21 +0700 Subject: [PATCH 004/125] update --- 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 59757a47..204667a0 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2093,7 +2093,7 @@ object SoraExtractor : SoraStream() { media.third.substringAfterLast("/") to iframe.substringAfterLast("/") .substringBefore("-") } - val res = app.get(fixUrl(iframe, api), verify = false) + val res = app.get(fixUrl(iframe, api)) delay(2000) val serverUrl = res.document.selectFirst("script:containsData(pushState)")?.data()?.let { """,\s*'([^']+)""".toRegex().find(it)?.groupValues?.get(1) From 0695426de9792ee866a0ff1a046e736a87530f0e Mon Sep 17 00:00:00 2001 From: lisa Date: Thu, 21 Dec 2023 10:39:54 +0700 Subject: [PATCH 005/125] sora: fix soraextrators --- .github/workflows/build.yml | 2 ++ SoraStream/build.gradle.kts | 3 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 36 ++++++++++++++++--- .../src/main/kotlin/com/hexated/SoraParser.kt | 8 +++++ .../src/main/kotlin/com/hexated/SoraStream.kt | 10 +++--- .../main/kotlin/com/hexated/SoraStreamLite.kt | 9 +++-- .../src/main/kotlin/com/hexated/SoraUtils.kt | 2 +- 7 files changed, 53 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5e17d0d..c88973ef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,6 +55,7 @@ jobs: SFMOVIES_API: ${{ secrets.SFMOVIES_API }} CINEMATV_API: ${{ secrets.CINEMATV_API }} OMOVIES_API: ${{ secrets.OMOVIES_API }} + FEBBOX_API: ${{ secrets.FEBBOX_API }} run: | cd $GITHUB_WORKSPACE/src echo TMDB_API=$TMDB_API >> local.properties @@ -70,6 +71,7 @@ jobs: echo SFMOVIES_API=$SFMOVIES_API >> local.properties echo CINEMATV_API=$CINEMATV_API >> local.properties echo OMOVIES_API=$OMOVIES_API >> local.properties + echo FEBBOX_API=$FEBBOX_API >> local.properties - name: Build Plugins run: | diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 4896f243..cd61e696 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 = 206 +version = 207 android { defaultConfig { @@ -9,6 +9,7 @@ android { properties.load(project.rootProject.file("local.properties").inputStream()) buildConfigField("String", "TMDB_API", "\"${properties.getProperty("TMDB_API")}\"") + buildConfigField("String", "FEBBOX_API", "\"${properties.getProperty("FEBBOX_API")}\"") buildConfigField("String", "OMOVIES_API", "\"${properties.getProperty("OMOVIES_API")}\"") buildConfigField("String", "CINEMATV_API", "\"${properties.getProperty("CINEMATV_API")}\"") buildConfigField("String", "SFMOVIES_API", "\"${properties.getProperty("SFMOVIES_API")}\"") diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 204667a0..7fe1c9bc 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -103,7 +103,6 @@ object SoraExtractor : SoraStream() { id: Int? = null, season: Int? = null, episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { val url = if (season == null) { @@ -1703,7 +1702,6 @@ object SoraExtractor : SoraStream() { imdbId: String? = null, season: Int? = null, episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { val url = if (season == null) { @@ -2149,8 +2147,8 @@ object SoraExtractor : SoraStream() { "$blackvidAPI/v3/tv/sources/$tmdbId/$season/$episode?key=$key" } - val res = request(url) - val bytes = res.peekBody(1024 * 512).bytes().also { res.closeQuietly() } + val res = request(url).peekBody(1024 * 512) + val bytes = res.bytes().also { res.closeQuietly() } val data = bytes.decrypt("2378f8e4e844f2dc839ab48f66e00acc2305a401") val json = tryParseJson(data) @@ -2260,7 +2258,6 @@ object SoraExtractor : SoraStream() { } val session = "PHPSESSID=ngr4cudjrimdnhkth30ssohs0n; _csrf=a6ffd7bb7654083fce6df528225a238d0e85aa1fb885dc7638c1259ec1ba0d5ca%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22mTTLiDLjxohs-CpKk0bjRH3HdYMB9uBV%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0" - cinemaCookiesChecker(session) val headers = mapOf( "Cookie" to session, @@ -2314,6 +2311,35 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeFebbox( + imdbId: String? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, + ) { + val url = if (season == null) { + "$febboxAPI/stream/movie/$imdbId.json" + } else { + "$febboxAPI/stream/series/$imdbId:$season:$episode.json" + } + + val res = request(url).body + val data = res.string().also { res.closeQuietly() } + val video = tryParseJson(data)?.streams?.find { it.url?.startsWith("https://www.febbox.com") == true }?.url + + callback.invoke( + ExtractorLink( + "Febbox", + "Febbox", + video ?: return, + "", + Qualities.P1080.value, + INFER_TYPE + ) + ) + + } + suspend fun invokeNinetv( tmdbId: Int? = null, season: Int? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index fb2b3ef5..40a19102 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -461,4 +461,12 @@ data class AoneroomResponse( ) } } +} + +data class FebboxResponse( + @JsonProperty("streams") val streams: ArrayList? = arrayListOf(), +) { + data class Streams( + @JsonProperty("url") val url: String? = null, + ) } \ No newline at end of file diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 859c9037..76acfb44 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -45,6 +45,7 @@ import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeVegamovies import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeCinemaTv +import com.hexated.SoraExtractor.invokeFebbox import com.hexated.SoraExtractor.invokeOmovies import com.hexated.SoraExtractor.invokeWatchsomuch import com.hexated.SoraExtractor.invokeZshow @@ -115,6 +116,7 @@ open class SoraStream : TmdbProvider() { const val blackvidAPI = "https://prod.api.blackvid.space" const val showflixAPI = "https://showflix.space" const val aoneroomAPI = "https://api3.aoneroom.com" + const val febboxAPI = BuildConfig.FEBBOX_API const val fdMoviesAPI = "https://freedrivemovie.lol" const val uhdmoviesAPI = "https://uhdmovies.zip" @@ -362,11 +364,10 @@ open class SoraStream : TmdbProvider() { argamap( { - if (!res.isAnime) invokeBlackvid( - res.id, + if (!res.isAnime) invokeFebbox( + res.imdbId, res.season, res.episode, - subtitleCallback, callback ) }, @@ -392,7 +393,7 @@ open class SoraStream : TmdbProvider() { ) }, { - invokeVidSrc(res.id, res.season, res.episode, subtitleCallback, callback) + invokeVidSrc(res.id, res.season, res.episode, callback) }, { invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) @@ -567,7 +568,6 @@ open class SoraStream : TmdbProvider() { res.imdbId, 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 d4b25315..ce8701cf 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -31,6 +31,7 @@ import com.hexated.SoraExtractor.invokeShowflix import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeCinemaTv +import com.hexated.SoraExtractor.invokeFebbox import com.hexated.SoraExtractor.invokeOmovies import com.hexated.SoraExtractor.invokeWatchsomuch import com.hexated.SoraExtractor.invokeZshow @@ -53,11 +54,10 @@ class SoraStreamLite : SoraStream() { argamap( { - if (!res.isAnime) invokeBlackvid( - res.id, + if (!res.isAnime) invokeFebbox( + res.imdbId, res.season, res.episode, - subtitleCallback, callback ) }, @@ -100,7 +100,7 @@ class SoraStreamLite : SoraStream() { ) }, { - invokeVidSrc(res.id, res.season, res.episode, subtitleCallback, callback) + invokeVidSrc(res.id, res.season, res.episode, callback) }, { invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) @@ -158,7 +158,6 @@ class SoraStreamLite : SoraStream() { res.imdbId, 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 3ca40d2d..5b98eeeb 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -648,7 +648,7 @@ suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair Date: Thu, 21 Dec 2023 10:42:57 +0700 Subject: [PATCH 006/125] Update mainurl (#458) * Update RebahinProvider.kt * Update LayarKacaProvider.kt update main url ="https://tv3.lk21official.wiki" change to "https://tv4.lk21official.wiki" * Update LayarKacaProvider.kt * Update Dubbindo.kt update domain * Update Cgvindo.kt * Update DramaidProvider.kt * Update DutaMovie.kt * Update Ngefilm.kt * Update Pusatfilm.kt * Update LayarKacaProvider.kt * Update build.gradle.kts * Update RebahinProvider.kt * Update DutaMovie.kt Update mainurl * Update build.gradle.kts * Update Ngefilm.kt * Update DramaSerial.kt * Update Nodrakorid.kt update mainurl * Update Pusatfilm.kt update mainurl * Update DramaSerial.kt update serverurl http://31.220.73.179/ * Update build.gradle.kts * Update LayarKacaProvider.kt update mainurl * Update DutaMovie.kt update mainurl * Update Pusatfilm.kt update mainurl * Update Multiplex.kt update mainurl * Update Ngefilm.kt update mainurl * Update Ngefilm.kt update mainurl * Update DutaMovie.kt update mainurl * Update Multiplex.kt update mainurl * Update Ngefilm.kt update mainurl * Update Pusatfilm.kt update mainurl * Update build.gradle.kts * Update LayarKacaProvider.kt update mainUrl update seriesUrl --- Gomov/src/main/kotlin/com/hexated/DutaMovie.kt | 8 ++------ Gomov/src/main/kotlin/com/hexated/Multiplex.kt | 5 ++--- Gomov/src/main/kotlin/com/hexated/Ngefilm.kt | 2 +- Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt | 3 +-- LayarKacaProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/LayarKacaProvider.kt | 4 ++-- 6 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt index 270bf211..0643ffe2 100644 --- a/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt +++ b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt @@ -6,12 +6,8 @@ import com.lagradost.cloudstream3.utils.httpsify import com.lagradost.cloudstream3.utils.loadExtractor class DutaMovie : Gomov() { - - override var mainUrl = "https://cinema.dutamovie21.vip" - - - -override var name = "DutaMovie" + override var mainUrl = "https://drama.dutamovie21.tech/" + override var name = "DutaMovie" override val mainPage = mainPageOf( "category/box-office/page/%d/" to "Box Office", "category/serial-tv/page/%d/" to "Serial TV", diff --git a/Gomov/src/main/kotlin/com/hexated/Multiplex.kt b/Gomov/src/main/kotlin/com/hexated/Multiplex.kt index 18b8db3b..1ea025f1 100644 --- a/Gomov/src/main/kotlin/com/hexated/Multiplex.kt +++ b/Gomov/src/main/kotlin/com/hexated/Multiplex.kt @@ -3,13 +3,12 @@ package com.hexated import com.lagradost.cloudstream3.mainPageOf class Multiplex : Gomov() { - override var mainUrl = "http://5.104.81.46" + override var mainUrl = "http://5.189.181.147" 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/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt index 48acf2cb..c70bebc8 100644 --- a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt +++ b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt @@ -3,7 +3,7 @@ package com.hexated import com.lagradost.cloudstream3.mainPageOf class Ngefilm : Gomov() { - override var mainUrl = "https://nge-film21.pics/" + override var mainUrl = "https://tv.ngefilm21.homes" 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", diff --git a/Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt b/Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt index 3a18e469..aabb0ecd 100644 --- a/Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt +++ b/Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt @@ -6,9 +6,8 @@ import com.lagradost.cloudstream3.TvSeriesLoadResponse import com.lagradost.cloudstream3.* class Pusatfilm : Gomov() { - override var mainUrl = "http://31.220.90.203/" + override var mainUrl = "https://tv2.pusatfilm21.art" override var name = "Pusatfilm" - override val mainPage = mainPageOf( "film-terbaru/page/%d/" to "Film Terbaru", "series-terbaru/page/%d/" to "Series Terbaru", diff --git a/LayarKacaProvider/build.gradle.kts b/LayarKacaProvider/build.gradle.kts index 5c2f043d..5f978538 100644 --- a/LayarKacaProvider/build.gradle.kts +++ b/LayarKacaProvider/build.gradle.kts @@ -23,5 +23,5 @@ cloudstream { "Movie", ) - iconUrl = "https://www.google.com/s2/favicons?domain=tv5.lk21official.wiki&sz=%size%" + iconUrl = "https://www.google.com/s2/favicons?domain=tv6.lk21official.wiki&sz=%size%" } diff --git a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt index 328257e9..34ebfdc7 100644 --- a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt +++ b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt @@ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.* import org.jsoup.nodes.Element class LayarKacaProvider : MainAPI() { - override var mainUrl = "https://tv5.lk21official.wiki" - private var seriesUrl = "https://tv7.nontondrama.click" + override var mainUrl = "https://tv6.lk21official.wiki" + private var seriesUrl = "https://tv8.nontondrama.click/" override var name = "LayarKaca" override val hasMainPage = true override var lang = "id" From a8f16991279f734bf025f456f16885b6881ea070 Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Thu, 21 Dec 2023 17:00:14 +0700 Subject: [PATCH 007/125] Update KuronimeProvider.kt --- .../src/main/kotlin/com/hexated/KuronimeProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt index 0ebfafbf..57eccd6e 100644 --- a/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt +++ b/KuronimeProvider/src/main/kotlin/com/hexated/KuronimeProvider.kt @@ -16,7 +16,7 @@ import java.net.URI import java.util.ArrayList class KuronimeProvider : MainAPI() { - override var mainUrl = "https://tv.kuronime.vip" + override var mainUrl = "https://tv1.kuronime.vip" private var animekuUrl = "https://animeku.org" override var name = "Kuronime" override val hasQuickSearch = true From f83c9273fdf0fa06a4c91f53703ed4033e68a780 Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Thu, 21 Dec 2023 17:00:40 +0700 Subject: [PATCH 008/125] Update build.gradle.kts --- KuronimeProvider/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KuronimeProvider/build.gradle.kts b/KuronimeProvider/build.gradle.kts index 863fbfc2..d68a2267 100644 --- a/KuronimeProvider/build.gradle.kts +++ b/KuronimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 19 +version = 20 cloudstream { From 1398f9bc0003c98705cd2d4b7a2b5dd9867f53cd Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Fri, 22 Dec 2023 01:33:41 +0700 Subject: [PATCH 009/125] Update Samehadaku.kt --- Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt index 51404e62..69bdf841 100644 --- a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt +++ b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt @@ -10,7 +10,7 @@ import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.nodes.Element class Samehadaku : MainAPI() { - override var mainUrl = "https://samehadaku.digital/" + override var mainUrl = "https://samehadaku.guru" override var name = "Samehadaku" override val hasMainPage = true override var lang = "id" From 928db8c7ff467c72d4b348ade1d20438f6aa5cf8 Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Fri, 22 Dec 2023 01:34:06 +0700 Subject: [PATCH 010/125] Update build.gradle.kts --- Samehadaku/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Samehadaku/build.gradle.kts b/Samehadaku/build.gradle.kts index ad80241e..25a86ea3 100644 --- a/Samehadaku/build.gradle.kts +++ b/Samehadaku/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 17 +version = 18 cloudstream { From 211c58b0ef493167d0bc34f7faf6e3ea68bf3197 Mon Sep 17 00:00:00 2001 From: lisa Date: Sat, 23 Dec 2023 09:16:09 +0700 Subject: [PATCH 011/125] sora: fix m4uhd --- .github/workflows/build.yml | 2 - LayarKacaProvider/build.gradle.kts | 2 +- .../kotlin/com/hexated/LayarKacaProvider.kt | 3 +- SoraStream/build.gradle.kts | 3 +- .../src/main/kotlin/com/hexated/Extractors.kt | 60 ++++----- .../main/kotlin/com/hexated/SoraExtractor.kt | 121 ++++++++---------- .../src/main/kotlin/com/hexated/SoraParser.kt | 35 ++--- .../src/main/kotlin/com/hexated/SoraStream.kt | 9 +- .../main/kotlin/com/hexated/SoraStreamLite.kt | 6 +- 9 files changed, 103 insertions(+), 138 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c88973ef..b5e17d0d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,7 +55,6 @@ jobs: SFMOVIES_API: ${{ secrets.SFMOVIES_API }} CINEMATV_API: ${{ secrets.CINEMATV_API }} OMOVIES_API: ${{ secrets.OMOVIES_API }} - FEBBOX_API: ${{ secrets.FEBBOX_API }} run: | cd $GITHUB_WORKSPACE/src echo TMDB_API=$TMDB_API >> local.properties @@ -71,7 +70,6 @@ jobs: echo SFMOVIES_API=$SFMOVIES_API >> local.properties echo CINEMATV_API=$CINEMATV_API >> local.properties echo OMOVIES_API=$OMOVIES_API >> local.properties - echo FEBBOX_API=$FEBBOX_API >> local.properties - name: Build Plugins run: | diff --git a/LayarKacaProvider/build.gradle.kts b/LayarKacaProvider/build.gradle.kts index 5f978538..85bf1cb9 100644 --- a/LayarKacaProvider/build.gradle.kts +++ b/LayarKacaProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 17 +version = 18 cloudstream { diff --git a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt index 34ebfdc7..552e412e 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 class LayarKacaProvider : MainAPI() { override var mainUrl = "https://tv6.lk21official.wiki" - private var seriesUrl = "https://tv8.nontondrama.click/" + private var seriesUrl = "https://tv8.nontondrama.click" override var name = "LayarKaca" override val hasMainPage = true override var lang = "id" @@ -40,6 +40,7 @@ class LayarKacaProvider : MainAPI() { } private suspend fun getProperLink(url: String): String? { + if(url.startsWith(seriesUrl)) return url val res = app.get(url).document return if (res.select("title").text().contains("- Nontondrama", true)) { res.selectFirst("div#content a")?.attr("href") diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index cd61e696..327754b2 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 = 207 +version = 208 android { defaultConfig { @@ -9,7 +9,6 @@ android { properties.load(project.rootProject.file("local.properties").inputStream()) buildConfigField("String", "TMDB_API", "\"${properties.getProperty("TMDB_API")}\"") - buildConfigField("String", "FEBBOX_API", "\"${properties.getProperty("FEBBOX_API")}\"") buildConfigField("String", "OMOVIES_API", "\"${properties.getProperty("OMOVIES_API")}\"") buildConfigField("String", "CINEMATV_API", "\"${properties.getProperty("CINEMATV_API")}\"") buildConfigField("String", "SFMOVIES_API", "\"${properties.getProperty("SFMOVIES_API")}\"") diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt index 0d72837f..0e5ae558 100644 --- a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -124,8 +124,8 @@ open class Playm4u : ExtractorApi() { return "$this\\s*=\\s*[\"'](\\S+)[\"'];".toRegex().find(data)?.groupValues?.get(1) ?: "" } - private fun String.toLanguage() : String { - return if(this == "EN") "English" else this + private fun String.toLanguage(): String { + return if (this == "EN") "English" else this } data class Source( @@ -209,7 +209,10 @@ open class VCloud : ExtractorApi() { ) ).document.select("p.text-success ~ a").apmap { val link = it.attr("href") - if (link.contains("workers.dev") || it.text().contains("[Server : 1]") || link.contains("/dl.php?")) { + if (link.contains("workers.dev") || it.text().contains("[Server : 1]") || link.contains( + "/dl.php?" + ) + ) { callback.invoke( ExtractorLink( this.name, @@ -221,7 +224,7 @@ open class VCloud : ExtractorApi() { ) ) } else { - val direct = if(link.contains("gofile.io")) app.get(link).url else link + val direct = if (link.contains("gofile.io")) app.get(link).url else link loadExtractor(direct, referer, subtitleCallback, callback) } } @@ -247,12 +250,14 @@ open class Streamruby : ExtractorApi() { callback: (ExtractorLink) -> Unit ) { val id = "/e/(\\w+)".toRegex().find(url)?.groupValues?.get(1) ?: return - val response = app.post("$mainUrl/dl", data = mapOf( - "op" to "embed", - "file_code" to id, - "auto" to "1", - "referer" to "", - ), referer = referer) + val response = app.post( + "$mainUrl/dl", data = mapOf( + "op" to "embed", + "file_code" to id, + "auto" to "1", + "referer" to "", + ), referer = referer + ) val script = if (!getPacked(response.text).isNullOrEmpty()) { getAndUnpack(response.text) } else { @@ -282,17 +287,25 @@ open class Uploadever : ExtractorApi() { ) { var res = app.get(url, referer = referer).document val formUrl = res.select("form").attr("action") - var formData = res.select("form input").associate { it.attr("name") to it.attr("value") }.filterKeys { it != "go" } + var formData = res.select("form input").associate { it.attr("name") to it.attr("value") } + .filterKeys { it != "go" } .toMutableMap() val formReq = app.post(formUrl, data = formData) res = formReq.document - val captchaKey = res.select("script[src*=https://www.google.com/recaptcha/api.js?render=]").attr("src").substringAfter("render=") + val captchaKey = + res.select("script[src*=https://www.google.com/recaptcha/api.js?render=]").attr("src") + .substringAfter("render=") val token = getCaptchaToken(url, captchaKey, referer = "$mainUrl/") - formData = res.select("form#down input").associate { it.attr("name") to it.attr("value") }.toMutableMap() + formData = res.select("form#down input").associate { it.attr("name") to it.attr("value") } + .toMutableMap() formData["adblock_detected"] = "0" formData["referer"] = url - res = app.post(formReq.url, data = formData + mapOf("g-recaptcha-response" to "$token"), cookies = formReq.cookies).document + res = app.post( + formReq.url, + data = formData + mapOf("g-recaptcha-response" to "$token"), + cookies = formReq.cookies + ).document val video = res.select("div.download-button a.btn.btn-dow.recaptchav2").attr("href") callback.invoke( @@ -325,18 +338,7 @@ open class Netembed : ExtractorApi() { val script = getAndUnpack(response.text) val m3u8 = Regex("((https:|http:)//.*\\.m3u8)").find(script)?.groupValues?.getOrNull(1) ?: return - if(m3u8.startsWith("https://www.febbox.com")) { - callback.invoke( - ExtractorLink( - this.name, - this.name, - m3u8, - "$mainUrl/", - getQuality(m3u8), - INFER_TYPE - ) - ) - } else { + if (!m3u8.startsWith("https://www.febbox.com")) { M3u8Helper.generateM3u8( this.name, m3u8, @@ -344,12 +346,6 @@ open class Netembed : ExtractorApi() { ).forEach(callback) } } - - private suspend fun getQuality(url: String) : Int { - val res = app.get(url, referer = "$mainUrl/").text - val regex = "#quality:\\s*(\\S+)".toRegex().find(res)?.groupValues?.get(1) - return getQualityFromName(regex) - } } class Streamwish : Filesim() { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 7fe1c9bc..8c4853af 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1354,14 +1354,14 @@ object SoraExtractor : SoraStream() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { + val slugTitle = title.createSlug() val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) - val req = app.get("$m4uhdAPI/search/${title.createSlug()}.html") + val req = app.get("$m4uhdAPI/search/$slugTitle.html") val referer = getBaseUrl(req.url) val scriptData = req.document.select("div.row div.item").map { ele -> Triple( - ele.select("div.tiptitle p").text(), - ele.select("div.jtip-top div:last-child").text().substringBefore("–") - .filter { it.isDigit() }, + ele.select("div.tiptitle p").text().substringBefore("(").trim().createSlug(), + ele.select("div.jtip-top div:last-child").text().filter { it.isDigit() }, ele.selectFirst("a")?.attr("href") ) } @@ -1370,7 +1370,7 @@ object SoraExtractor : SoraStream() { scriptData.firstOrNull() } else { scriptData.find { - it.first.contains(Regex("(?i)$title \\($year\\s?\\)")) && if (season != null) it.third?.contains( + it.first.equals(slugTitle) && it.second == "$year" && if (season != null) it.third?.contains( "-tvshow-" ) == true else it.third?.contains("-movie-") == true } @@ -2133,52 +2133,6 @@ object SoraExtractor : SoraStream() { } - suspend fun invokeBlackvid( - tmdbId: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, - ) { - val key = "b6055c533c19131a638c3d2299d525d5ec08a814" - val url = if (season == null) { - "$blackvidAPI/v3/movie/sources/$tmdbId?key=$key" - } else { - "$blackvidAPI/v3/tv/sources/$tmdbId/$season/$episode?key=$key" - } - - val res = request(url).peekBody(1024 * 512) - val bytes = res.bytes().also { res.closeQuietly() } - val data = bytes.decrypt("2378f8e4e844f2dc839ab48f66e00acc2305a401") - val json = tryParseJson(data) - - json?.sources?.map { source -> - source.sources.map s@{ s -> - callback.invoke( - ExtractorLink( - "Blackvid", - "Blackvid${source.label}", - s.url ?: return@s, - "https://blackvid.space/", - if (s.quality.equals("4k")) Qualities.P2160.value else s.quality?.toIntOrNull() - ?: Qualities.P1080.value, - INFER_TYPE - ) - ) - } - } - - json?.subtitles?.map { sub -> - subtitleCallback.invoke( - SubtitleFile( - sub.language.takeIf { it?.isNotEmpty() == true } ?: return@map, - sub.url ?: return@map, - ) - ) - } - - } - suspend fun invokeShowflix( title: String? = null, year: Int? = null, @@ -2312,31 +2266,62 @@ object SoraExtractor : SoraStream() { } suspend fun invokeFebbox( - imdbId: String? = null, + title: String? = null, + year: Int? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit, ) { - val url = if (season == null) { - "$febboxAPI/stream/movie/$imdbId.json" + val showboxApi = "https://www.showbox.media" + val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) + + val res = app.post( + "$showboxApi/search/autocomplate2", data = mapOf( + "keyword" to "$title" + ), headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ).parsed().let { Jsoup.parse(it) } + + val mediaId = res.select("a.nav-item").find { + it.select("h3.film-name").text() + .equals(title, true) && it.select("div.film-infor > span:first-child").text() + .contains(if (season == null) "$year" else "SS") && it.select("div.film-infor > span:last-child") + .text() + .equals(if (season == null) "Movie" else "TV") + }?.attr("href")?.substringAfterLast("/") + + val shareKey = + app.get("$showboxApi/index/share_link?id=${mediaId ?: return}&type=${if (season == null) "1" else "2"}") + .parsedSafe()?.data?.link?.substringAfterLast("/") + + val headers = mapOf("Accept-Language" to "en") + val shareRes = app.get("$febboxAPI/file/file_share_list?share_key=${shareKey ?: return}", headers = headers) + .parsedSafe()?.data + + val fids = if (season == null) { + shareRes?.file_list } else { - "$febboxAPI/stream/series/$imdbId:$season:$episode.json" + val parentId = shareRes?.file_list?.find { it.file_name.equals("season $season", true) }?.fid + app.get("$febboxAPI/file/file_share_list?share_key=${shareKey}&parent_id=$parentId&page=1", headers = headers) + .parsedSafe()?.data?.file_list?.filter { + it.file_name?.contains( + "s${seasonSlug}e${episodeSlug}", + true + ) == true + } } - val res = request(url).body - val data = res.string().also { res.closeQuietly() } - val video = tryParseJson(data)?.streams?.find { it.url?.startsWith("https://www.febbox.com") == true }?.url - - callback.invoke( - ExtractorLink( - "Febbox", - "Febbox", - video ?: return, - "", - Qualities.P1080.value, - INFER_TYPE + fids?.mapIndexed { index, fileList -> + callback.invoke( + ExtractorLink( + "Febbox", + "Febbox [Server $index]", + "$febboxAPI/hls/main/${fileList.oss_fid}.m3u8", + "", + getIndexQuality(fileList.file_name), + isM3u8 = true + ) ) - ) + } } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 40a19102..01ebad4a 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -334,26 +334,6 @@ data class EMovieTraks( @JsonProperty("label") val label: String? = null, ) -data class BlackvidSubtitles( - @JsonProperty("language") val language: String? = null, - @JsonProperty("url") val url: String? = null, -) - -data class BlackvidSource( - @JsonProperty("quality") var quality: String? = null, - @JsonProperty("url") var url: String? = null, -) - -data class BlackvidSources( - @JsonProperty("label") var label: String? = null, - @JsonProperty("sources") var sources: ArrayList = arrayListOf() -) - -data class BlackvidResponses( - @JsonProperty("sources") var sources: ArrayList = arrayListOf(), - @JsonProperty("subtitles") var subtitles: ArrayList = arrayListOf() -) - data class ShowflixResultsMovies( @JsonProperty("movieName") val movieName: String? = null, @JsonProperty("streamwish") val streamwish: String? = null, @@ -464,9 +444,16 @@ data class AoneroomResponse( } data class FebboxResponse( - @JsonProperty("streams") val streams: ArrayList? = arrayListOf(), + @JsonProperty("data") val data: Data? = null, ) { - data class Streams( - @JsonProperty("url") val url: String? = null, - ) + data class Data( + @JsonProperty("link") val link: String? = null, + @JsonProperty("file_list") val file_list: ArrayList? = arrayListOf(), + ) { + data class FileList( + @JsonProperty("fid") val fid: Long? = null, + @JsonProperty("file_name") val file_name: String? = null, + @JsonProperty("oss_fid") val oss_fid: Long? = null, + ) + } } \ No newline at end of file diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 76acfb44..0477026d 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.hexated.SoraExtractor.invoke2embed import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAoneroom -import com.hexated.SoraExtractor.invokeBlackvid import com.hexated.SoraExtractor.invokeBollyMaza import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeFilmxy @@ -113,10 +112,9 @@ open class SoraStream : TmdbProvider() { const val dramadayAPI = "https://dramaday.me" const val animetoshoAPI = "https://animetosho.org" const val watchflxAPI = "https://watchflx.tv" - const val blackvidAPI = "https://prod.api.blackvid.space" const val showflixAPI = "https://showflix.space" const val aoneroomAPI = "https://api3.aoneroom.com" - const val febboxAPI = BuildConfig.FEBBOX_API + const val febboxAPI = "https://www.febbox.com" const val fdMoviesAPI = "https://freedrivemovie.lol" const val uhdmoviesAPI = "https://uhdmovies.zip" @@ -364,8 +362,9 @@ open class SoraStream : TmdbProvider() { argamap( { - if (!res.isAnime) invokeFebbox( - res.imdbId, + invokeFebbox( + 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 ce8701cf..5e5afe20 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -3,7 +3,6 @@ package com.hexated import com.hexated.SoraExtractor.invoke2embed import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAoneroom -import com.hexated.SoraExtractor.invokeBlackvid import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeDoomovies import com.hexated.SoraExtractor.invokeDramaday @@ -54,8 +53,9 @@ class SoraStreamLite : SoraStream() { argamap( { - if (!res.isAnime) invokeFebbox( - res.imdbId, + invokeFebbox( + res.title, + res.year, res.season, res.episode, callback From 51d8c748807c9e780c03837947a9ed7755bc8fe7 Mon Sep 17 00:00:00 2001 From: lisa Date: Sat, 23 Dec 2023 09:41:12 +0700 Subject: [PATCH 012/125] small fix --- .../main/kotlin/com/hexated/SoraExtractor.kt | 33 ++++++++++++++----- .../src/main/kotlin/com/hexated/SoraParser.kt | 6 ++++ .../src/main/kotlin/com/hexated/SoraStream.kt | 1 + .../main/kotlin/com/hexated/SoraStreamLite.kt | 1 + 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 8c4853af..2af0cbe1 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2269,9 +2269,11 @@ object SoraExtractor : SoraStream() { title: String? = null, year: Int? = null, season: Int? = null, + lastSeason: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit, ) { + val showboxApi = "https://www.showbox.media" val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) @@ -2281,16 +2283,31 @@ object SoraExtractor : SoraStream() { ), headers = mapOf("X-Requested-With" to "XMLHttpRequest") ).parsed().let { Jsoup.parse(it) } - val mediaId = res.select("a.nav-item").find { - it.select("h3.film-name").text() - .equals(title, true) && it.select("div.film-infor > span:first-child").text() - .contains(if (season == null) "$year" else "SS") && it.select("div.film-infor > span:last-child") - .text() - .equals(if (season == null) "Movie" else "TV") - }?.attr("href")?.substringAfterLast("/") + val mediaRes = res.select("a.nav-item").map { + ShowboxMedia( + it.attr("href"), + it.select("h3.film-name").text(), + it.select("div.film-infor > span:first-child").text(), + it.select("div.film-infor > span:last-child").text(), + ) + } + + val media = mediaRes.find { + it.title.equals( + title, + true + ) && it.infor == if (season == null) "$year" else "SS $lastSeason" && it.type == if (season == null) "Movie" else "TV" + } ?: mediaRes.find { + it.title.equals( + title, + true + ) && it.infor.contains(if (season == null) "$year" else "SS") && it.type == if (season == null) "Movie" else "TV" + } + + val shareId = media?.url?.substringAfterLast("/") ?: return val shareKey = - app.get("$showboxApi/index/share_link?id=${mediaId ?: return}&type=${if (season == null) "1" else "2"}") + app.get("$showboxApi/index/share_link?id=${shareId}&type=${if (season == null) "1" else "2"}") .parsedSafe()?.data?.link?.substringAfterLast("/") val headers = mapOf("Accept-Language" to "en") diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 01ebad4a..938462bc 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -2,6 +2,12 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty +data class ShowboxMedia( + val url: String, + val title: String, + val infor: String, + val type: String, +) data class FDMovieIFrame( val link: String, val quality: String, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 0477026d..379a47e0 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -366,6 +366,7 @@ open class SoraStream : TmdbProvider() { res.title, res.year, res.season, + res.lastSeason, res.episode, callback ) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 5e5afe20..22f27b3a 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -57,6 +57,7 @@ class SoraStreamLite : SoraStream() { res.title, res.year, res.season, + res.lastSeason, res.episode, callback ) From 0d09638a9c659f4a5066d756a6c40f7b54244413 Mon Sep 17 00:00:00 2001 From: lisa Date: Sat, 23 Dec 2023 09:48:18 +0700 Subject: [PATCH 013/125] 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 2af0cbe1..1a349288 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2296,7 +2296,7 @@ object SoraExtractor : SoraStream() { it.title.equals( title, true - ) && it.infor == if (season == null) "$year" else "SS $lastSeason" && it.type == if (season == null) "Movie" else "TV" + ) && it.infor.equals(if (season == null) "$year" else "SS $lastSeason") && it.type == if (season == null) "Movie" else "TV" } ?: mediaRes.find { it.title.equals( title, From f1e35269424324a8a0813627e12987d529468378 Mon Sep 17 00:00:00 2001 From: lisa Date: Sat, 23 Dec 2023 10:16:48 +0700 Subject: [PATCH 014/125] small fix --- .../main/kotlin/com/hexated/SoraExtractor.kt | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 1a349288..1bde5716 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2277,18 +2277,14 @@ object SoraExtractor : SoraStream() { val showboxApi = "https://www.showbox.media" val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) - val res = app.post( - "$showboxApi/search/autocomplate2", data = mapOf( - "keyword" to "$title" - ), headers = mapOf("X-Requested-With" to "XMLHttpRequest") - ).parsed().let { Jsoup.parse(it) } + val res = app.get("$showboxApi/search?keyword=$title").document - val mediaRes = res.select("a.nav-item").map { + val mediaRes = res.select("div.film_list-wrap div.flw-item").map { ShowboxMedia( - it.attr("href"), - it.select("h3.film-name").text(), - it.select("div.film-infor > span:first-child").text(), - it.select("div.film-infor > span:last-child").text(), + it.select("h2.film-name a").attr("href"), + it.select("h2.film-name a").text(), + it.select("div.fd-infor > span:first-child").text(), + it.select("div.fd-infor > span:last-child").text(), ) } @@ -2331,7 +2327,7 @@ object SoraExtractor : SoraStream() { callback.invoke( ExtractorLink( "Febbox", - "Febbox [Server $index]", + "Febbox [Server ${index + 1}]", "$febboxAPI/hls/main/${fileList.oss_fid}.m3u8", "", getIndexQuality(fileList.file_name), From 8ab71d47e5cc804afeb593180a2b4b8762065643 Mon Sep 17 00:00:00 2001 From: lisa Date: Sat, 23 Dec 2023 10:29:36 +0700 Subject: [PATCH 015/125] 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 1bde5716..9e56345f 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2297,7 +2297,7 @@ object SoraExtractor : SoraStream() { it.title.equals( title, true - ) && it.infor.contains(if (season == null) "$year" else "SS") && it.type == if (season == null) "Movie" else "TV" + ) && it.infor.equals(if (season == null) "$year" else "SS ${lastSeason?.minus(1)}") && it.type == if (season == null) "Movie" else "TV" } val shareId = media?.url?.substringAfterLast("/") ?: return From 9954986e478d22447a0f76393905c01f4246717b Mon Sep 17 00:00:00 2001 From: lisa Date: Sat, 23 Dec 2023 17:54:55 +0700 Subject: [PATCH 016/125] update --- 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 9e56345f..1bde5716 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2297,7 +2297,7 @@ object SoraExtractor : SoraStream() { it.title.equals( title, true - ) && it.infor.equals(if (season == null) "$year" else "SS ${lastSeason?.minus(1)}") && it.type == if (season == null) "Movie" else "TV" + ) && it.infor.contains(if (season == null) "$year" else "SS") && it.type == if (season == null) "Movie" else "TV" } val shareId = media?.url?.substringAfterLast("/") ?: return From f08894d2aa328236d0ec4192a77bb1f15cb41e86 Mon Sep 17 00:00:00 2001 From: irfannajmudinsidik <50092754+irfannajmudinsidik@users.noreply.github.com> Date: Sun, 24 Dec 2023 00:27:54 +0700 Subject: [PATCH 017/125] Update Cgvindo.kt (#466) * Update Cgvindo.kt * Update Ngefilm.kt * Update Ngefilm.kt --- RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt b/RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt index 370dda11..da0cb643 100644 --- a/RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt +++ b/RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt @@ -3,7 +3,7 @@ package com.hexated import com.lagradost.cloudstream3.TvType class Cgvindo : RebahinProvider() { - override var mainUrl = "http://167.86.79.231" + override var mainUrl = "http://198.54.124.245" override var name = "Cgvindo" } From ae93b677e18a49d8670e4951253a677b0074ed8a Mon Sep 17 00:00:00 2001 From: monica Date: Sun, 24 Dec 2023 07:57:10 +0700 Subject: [PATCH 018/125] update --- .../main/kotlin/com/hexated/SoraExtractor.kt | 42 ++++++++------ .../src/main/kotlin/com/hexated/SoraStream.kt | 2 +- .../src/main/kotlin/com/hexated/SoraUtils.kt | 58 +++---------------- 3 files changed, 33 insertions(+), 69 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 1bde5716..387e19ea 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -252,9 +252,9 @@ object SoraExtractor : SoraStream() { val req = app.get(url) val directUrl = getBaseUrl(req.url) val iframe = req.document.selectFirst("div.pframe iframe")?.attr("src") ?: return - if(!iframe.contains("youtube")) { + if (!iframe.contains("youtube")) { loadExtractor(iframe, "$directUrl/", subtitleCallback) { link -> - if(link.quality == Qualities.Unknown.value) { + if (link.quality == Qualities.Unknown.value) { callback.invoke( ExtractorLink( link.source, @@ -1319,7 +1319,7 @@ object SoraExtractor : SoraStream() { } type.contains("oiya") || type.contains("rarbgx") -> { - val oiyaLink = extractOiya(fdLink ?: return@apmap null, qualities) + val oiyaLink = extractOiya(fdLink ?: return@apmap null) if (oiyaLink?.contains("gdtot") == true) { val gdBotLink = extractGdbot(oiyaLink) extractGdflix(gdBotLink ?: return@apmap null) @@ -2211,7 +2211,8 @@ object SoraExtractor : SoraStream() { "$cinemaTvAPI/shows/play/$id-$slug-$year" } - val session = "PHPSESSID=ngr4cudjrimdnhkth30ssohs0n; _csrf=a6ffd7bb7654083fce6df528225a238d0e85aa1fb885dc7638c1259ec1ba0d5ca%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22mTTLiDLjxohs-CpKk0bjRH3HdYMB9uBV%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0" + val session = + "PHPSESSID=ngr4cudjrimdnhkth30ssohs0n; _csrf=a6ffd7bb7654083fce6df528225a238d0e85aa1fb885dc7638c1259ec1ba0d5ca%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22mTTLiDLjxohs-CpKk0bjRH3HdYMB9uBV%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0" val headers = mapOf( "Cookie" to session, @@ -2288,16 +2289,16 @@ object SoraExtractor : SoraStream() { ) } - val media = mediaRes.find { - it.title.equals( - title, - true - ) && it.infor.equals(if (season == null) "$year" else "SS $lastSeason") && it.type == if (season == null) "Movie" else "TV" - } ?: mediaRes.find { - it.title.equals( - title, - true - ) && it.infor.contains(if (season == null) "$year" else "SS") && it.type == if (season == null) "Movie" else "TV" + val filter = mediaRes.filter { + it.title.equals(title, true) && it.type == if (season == null) "Movie" else "TV" + } + + val media = if (season == null) { + filter.find { it.infor == "$year" } + } else { + filter.find { it.infor == "SS $lastSeason" } + ?: filter.find { it.infor == "SS ${lastSeason?.minus(1)}" } + ?: filter.find { it.infor == "SS 1" } } val shareId = media?.url?.substringAfterLast("/") ?: return @@ -2307,14 +2308,21 @@ object SoraExtractor : SoraStream() { .parsedSafe()?.data?.link?.substringAfterLast("/") val headers = mapOf("Accept-Language" to "en") - val shareRes = app.get("$febboxAPI/file/file_share_list?share_key=${shareKey ?: return}", headers = headers) + val shareRes = app.get( + "$febboxAPI/file/file_share_list?share_key=${shareKey ?: return}", + headers = headers + ) .parsedSafe()?.data val fids = if (season == null) { shareRes?.file_list } else { - val parentId = shareRes?.file_list?.find { it.file_name.equals("season $season", true) }?.fid - app.get("$febboxAPI/file/file_share_list?share_key=${shareKey}&parent_id=$parentId&page=1", headers = headers) + val parentId = + shareRes?.file_list?.find { it.file_name.equals("season $season", true) }?.fid + app.get( + "$febboxAPI/file/file_share_list?share_key=${shareKey}&parent_id=$parentId&page=1", + headers = headers + ) .parsedSafe()?.data?.file_list?.filter { it.file_name?.contains( "s${seasonSlug}e${episodeSlug}", diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 379a47e0..ca283c99 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -116,7 +116,7 @@ open class SoraStream : TmdbProvider() { const val aoneroomAPI = "https://api3.aoneroom.com" const val febboxAPI = "https://www.febbox.com" - const val fdMoviesAPI = "https://freedrivemovie.lol" + const val fdMoviesAPI = "https://freedrivemovie.com" const val uhdmoviesAPI = "https://uhdmovies.zip" const val gMoviesAPI = "https://gdrivemovies.xyz" const val hdmovies4uAPI = "https://hdmovies4u.band" diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 5b98eeeb..0d349112 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -49,7 +49,6 @@ import kotlin.math.min var watchflxCookies: Map? = null var filmxyCookies: Map? = null var sfServer: String? = null -var cinemaCookiesChecker: Boolean? = null val encodedIndex = arrayOf( "GamMovies", @@ -331,10 +330,8 @@ suspend fun getDrivebotLink(url: String?): String? { ?.data()?.substringAfter("window.open('")?.substringBefore("')") } -suspend fun extractOiya(url: String, quality: String): String? { - val doc = app.get(url).document - return doc.selectFirst("div.wp-block-button a:matches((?i)$quality)")?.attr("href") - ?: doc.selectFirst("div.wp-block-button a")?.attr("href") +suspend fun extractOiya(url: String): String? { + return app.get(url).document.selectFirst("div.wp-block-button a")?.attr("href") } fun deobfstr(hash: String, index: String): String { @@ -589,10 +586,11 @@ suspend fun bypassFdAds(url: String?): String? { } suspend fun bypassHrefli(url: String): String? { - fun Document.getFormUrl() : String { + fun Document.getFormUrl(): String { return this.select("form#landing").attr("action") } - fun Document.getFormData() : Map { + + fun Document.getFormData(): Map { return this.select("form#landing input").associate { it.attr("name") to it.attr("value") } } @@ -606,7 +604,8 @@ suspend fun bypassHrefli(url: String): String? { formData = res.getFormData() res = app.post(formUrl, data = formData).document - val skToken = res.selectFirst("script:containsData(?go=)")?.data()?.substringAfter("?go=")?.substringBefore("\"") ?: return null + val skToken = res.selectFirst("script:containsData(?go=)")?.data()?.substringAfter("?go=") + ?.substringBefore("\"") ?: return null val driveUrl = app.get( "$host?go=$skToken", cookies = mapOf( skToken to "${formData["_wp_http2"]}" @@ -648,49 +647,6 @@ suspend fun getTvMoviesServer(url: String, season: Int?, episode: Int?): Pair) { - app.get( - "$wiwiApi/api/v1/app-config", - headers = headers - ).text - } - suspend fun checkCookies(session: String, headers: Map) { - app.post( - "$wiwiApi/api/v1/cookie", - data = mapOf("cookie" to session), - headers = headers - ).text - } - val configHeaders = mapOf( - "App-version" to "3.4", - "Authorization" to "Basic d2l3aTpXaXdpQDIwMjA=", - "Country" to "Indonesia", - "Device-id" to getDeviceId(), - "User-id" to "user-6694327", - ) - listOf(1..2).apmap { createConfig(configHeaders) } - val unityData = """ - { - "platform": "android", - "idfi": "d1ec7051-f58f-4ddb-9da8-8debb82cfbea", - "sdkVersionName": "4.3.0", - "gdpr.consent": true, - "user.nonbehavioral": false, - "unity.privacy.permissions.all": false, - "unity.privacy.permissions.gameExp": false, - "unity.privacy.permissions.ads": false, - "unity.privacy.permissions.external": false - } - """.trimIndent().toJson().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) - app.post("https://configv2.unityads.unity3d.com/privacy/4519473/state", requestBody = unityData).text - listOf(1..4).map {checkCookies(session, configHeaders)} - return true -} - suspend fun getSfServer() = sfServer ?: fetchSfServer().also { sfServer = it } suspend fun fetchSfServer(): String { From d3bd6f16098cb5c9cae41488cde8f5fe8d9b6815 Mon Sep 17 00:00:00 2001 From: Saksham Kushwaha <92094239+LiReNa00@users.noreply.github.com> Date: Sun, 24 Dec 2023 06:28:43 +0530 Subject: [PATCH 019/125] Update YugenAnime.kt (#462) * Update YugenAnime.kt Updated the mainurl (it's .sx now) and search function (/discover instead of /search) * Update YugenAnime.kt --- YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt b/YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt index d8c6c982..af605a82 100644 --- a/YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt +++ b/YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt @@ -13,7 +13,7 @@ import org.jsoup.nodes.Element import java.net.URI class YugenAnime : MainAPI() { - override var mainUrl = "https://yugenanime.tv" + override var mainUrl = "https://yugenanime.sx" override var name = "YugenAnime" override val hasMainPage = true override var lang = "en" @@ -84,7 +84,7 @@ class YugenAnime : MainAPI() { } override suspend fun search(query: String): List { - val document = app.get("$mainUrl/search/?q=$query").document + val document = app.get("$mainUrl/discover/?q=$query").document return document.select("div.cards-grid a.anime-meta").mapNotNull { it.toSearchResult() } @@ -231,4 +231,4 @@ class YugenAnime : MainAPI() { @JsonProperty("season") val season: String? = null, ) -} \ No newline at end of file +} From eb128bf97a272be3d6c731f667ea322d22da33fc Mon Sep 17 00:00:00 2001 From: monica Date: Sun, 24 Dec 2023 16:09:45 +0700 Subject: [PATCH 020/125] sora: added WatchCartoon --- SoraStream/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 6 +++ .../main/kotlin/com/hexated/SoraExtractor.kt | 50 ++++++++++++++++++- .../src/main/kotlin/com/hexated/SoraStream.kt | 13 +++++ .../main/kotlin/com/hexated/SoraStreamLite.kt | 12 +++++ .../kotlin/com/hexated/SoraStreamPlugin.kt | 1 + .../src/main/kotlin/com/hexated/SoraUtils.kt | 12 +++++ 7 files changed, 93 insertions(+), 3 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 327754b2..8ce610c3 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 = 208 +version = 209 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt index 0e5ae558..a2e33744 100644 --- a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -10,6 +10,7 @@ import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.base64Decode +import com.lagradost.cloudstream3.extractors.Jeniusplay import com.lagradost.cloudstream3.extractors.Pixeldrain import com.lagradost.cloudstream3.extractors.Vidplay import com.lagradost.cloudstream3.utils.* @@ -409,4 +410,9 @@ class Vidplay2 : Vidplay() { class Flaswish : Filesim() { override val name = "Flaswish" override var mainUrl = "https://flaswish.com" +} + +class Comedyshow : Jeniusplay() { + override val mainUrl = "https://comedyshow.to" + override val name = "Comedyshow" } \ 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 387e19ea..ab1e1441 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -14,7 +14,6 @@ import com.lagradost.nicehttp.RequestBodyTypes import kotlinx.coroutines.delay import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody -import okhttp3.internal.closeQuietly import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.select.Elements @@ -323,6 +322,52 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeWatchCartoon( + 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) { + "$watchCartoonAPI/movies/$fixTitle-$year" + } else { + "$watchCartoonAPI/episode/$fixTitle-season-$season-episode-$episode" + } + + val req = app.get(url) + val host = getBaseUrl(req.url) + val doc = req.document + + val id = doc.select("link[rel=shortlink]").attr("href").substringAfterLast("=") + doc.select("div.form-group.list-server option").apmap { + val server = app.get( + "$host/ajax-get-link-stream/?server=${it.attr("value")}&filmId=$id", + headers = mapOf( + "X-Requested-With" to "XMLHttpRequest" + ) + ).text + loadExtractor(server, "$host/", subtitleCallback) { link -> + if (link.quality == Qualities.Unknown.value) { + callback.invoke( + ExtractorLink( + "WatchCartoon", + "WatchCartoon", + link.url, + link.referer, + Qualities.P720.value, + link.type, + link.headers, + link.extractorData + ) + ) + } + } + } + } + suspend fun invokeNetmovies( title: String? = null, year: Int? = null, @@ -1702,6 +1747,7 @@ object SoraExtractor : SoraStream() { imdbId: String? = null, season: Int? = null, episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { val url = if (season == null) { @@ -1717,7 +1763,7 @@ object SoraExtractor : SoraStream() { }.apmap { when (it.second) { "Player F" -> { - invokeSmashyFfix(it.second, it.first, url, callback) + invokeSmashyFfix(it.second, it.first, url, subtitleCallback, callback) } "Player D (Hindi)" -> { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index ca283c99..0ce3233c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -46,6 +46,7 @@ import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeCinemaTv import com.hexated.SoraExtractor.invokeFebbox import com.hexated.SoraExtractor.invokeOmovies +import com.hexated.SoraExtractor.invokeWatchCartoon import com.hexated.SoraExtractor.invokeWatchsomuch import com.hexated.SoraExtractor.invokeZshow import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId @@ -115,6 +116,7 @@ open class SoraStream : TmdbProvider() { const val showflixAPI = "https://showflix.space" const val aoneroomAPI = "https://api3.aoneroom.com" const val febboxAPI = "https://www.febbox.com" + const val watchCartoonAPI = "https://www1.watchcartoononline.bz" const val fdMoviesAPI = "https://freedrivemovie.com" const val uhdmoviesAPI = "https://uhdmovies.zip" @@ -450,6 +452,16 @@ open class SoraStream : TmdbProvider() { callback ) }, + { + if (!res.isAnime && res.isCartoon) invokeWatchCartoon( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, { if (!res.isAnime) invokeVidsrcto( res.imdbId, @@ -568,6 +580,7 @@ open class SoraStream : TmdbProvider() { res.imdbId, 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 22f27b3a..90ad38d5 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -32,6 +32,7 @@ import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeCinemaTv import com.hexated.SoraExtractor.invokeFebbox import com.hexated.SoraExtractor.invokeOmovies +import com.hexated.SoraExtractor.invokeWatchCartoon import com.hexated.SoraExtractor.invokeWatchsomuch import com.hexated.SoraExtractor.invokeZshow import com.lagradost.cloudstream3.SubtitleFile @@ -106,6 +107,16 @@ class SoraStreamLite : SoraStream() { { invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) }, + { + if (!res.isAnime && res.isCartoon) invokeWatchCartoon( + res.title, + res.year, + res.season, + res.episode, + subtitleCallback, + callback + ) + }, { if (res.isAnime) invokeAnimes( res.title, @@ -159,6 +170,7 @@ class SoraStreamLite : SoraStream() { res.imdbId, 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 23cc44f2..c6cd296e 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt @@ -30,5 +30,6 @@ class SoraStreamPlugin: Plugin() { registerExtractorAPI(Netembed()) registerExtractorAPI(Vidplay2()) registerExtractorAPI(Flaswish()) + registerExtractorAPI(Comedyshow()) } } \ 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 0d349112..89593955 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -402,6 +402,7 @@ suspend fun invokeSmashyFfix( name: String, url: String, ref: String, + subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { val json = app.get(url, referer = ref, headers = mapOf("X-Requested-With" to "XMLHttpRequest")) @@ -414,6 +415,17 @@ suspend fun invokeSmashyFfix( ).forEach(callback) } + json?.subtitleUrls?.split(",")?.map { sub -> + val lang = "\\[(.*)]".toRegex().find(sub)?.groupValues?.get(1) + val subUrl = sub.replace("[$lang]", "").trim() + subtitleCallback.invoke( + SubtitleFile( + lang ?: return@map, + subUrl + ) + ) + } + } suspend fun invokeSmashyD( From 8178fc171e6a00e024a390dbcc12c60f84df34bf Mon Sep 17 00:00:00 2001 From: IndusAryan <125901294+IndusAryan@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:28:10 +0530 Subject: [PATCH 021/125] update: some domains and kgp (#477) * Update kgp * Update YomoviesProvider.kt * Update build.gradle.kts * Update Movierulzhd.kt * Update Hdmovie2.kt * Update build.gradle.kts --- Movierulzhd/build.gradle.kts | 2 +- Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt | 2 +- Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt | 2 +- YomoviesProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/YomoviesProvider.kt | 2 +- build.gradle.kts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Movierulzhd/build.gradle.kts b/Movierulzhd/build.gradle.kts index 08c2a426..f12a9845 100644 --- a/Movierulzhd/build.gradle.kts +++ b/Movierulzhd/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 55 +version = 56 cloudstream { diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt b/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt index 4e0f12b7..5ed281c4 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Hdmovie2.kt @@ -12,7 +12,7 @@ import org.jsoup.Jsoup class Hdmovie2 : Movierulzhd() { - override var mainUrl = "https://hdmovie2.li" + override var mainUrl = "https://hdmovie2.foo" override var name = "Hdmovie2" override val mainPage = mainPageOf( "trending" to "Trending", diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt index 77260037..85624375 100644 --- a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt +++ b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt @@ -11,7 +11,7 @@ import java.net.URI open class Movierulzhd : MainAPI() { - override var mainUrl = "https://movierulzhd.bet" + override var mainUrl = "https://movierulzhd.host" var directUrl = "" override var name = "Movierulzhd" override val hasMainPage = true diff --git a/YomoviesProvider/build.gradle.kts b/YomoviesProvider/build.gradle.kts index 7934b290..31a810db 100644 --- a/YomoviesProvider/build.gradle.kts +++ b/YomoviesProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 25 +version = 26 cloudstream { diff --git a/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt b/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt index d84867d4..324130e4 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.media" + override var mainUrl = "https://yomovies.boo" private var directUrl = "" override var name = "Yomovies" override val hasMainPage = true diff --git a/build.gradle.kts b/build.gradle.kts index c59fbf5d..15b04626 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,7 +13,7 @@ buildscript { classpath("com.android.tools.build:gradle:7.0.4") // Cloudstream gradle plugin which makes everything work and builds plugins classpath("com.github.recloudstream:gradle:-SNAPSHOT") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22") } } From 248803c497645920ee3432741c270b256d87d3cc Mon Sep 17 00:00:00 2001 From: irfannajmudinsidik <50092754+irfannajmudinsidik@users.noreply.github.com> Date: Fri, 29 Dec 2023 15:58:19 +0700 Subject: [PATCH 022/125] Update Link Ngefilm (#480) Update link Ngefilm --- Gomov/src/main/kotlin/com/hexated/Ngefilm.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt index c70bebc8..6836fc3f 100644 --- a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt +++ b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt @@ -3,7 +3,7 @@ package com.hexated import com.lagradost.cloudstream3.mainPageOf class Ngefilm : Gomov() { - override var mainUrl = "https://tv.ngefilm21.homes" + override var mainUrl = "https://tv1.ngefilm21.homes" 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", From 638b60dd5d96886ed5102a087067acf86f04fa54 Mon Sep 17 00:00:00 2001 From: monica Date: Sat, 30 Dec 2023 16:09:19 +0700 Subject: [PATCH 023/125] fix #472 fix #473 --- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 81 +++++++------------ .../src/main/kotlin/com/hexated/SoraParser.kt | 22 ++--- .../src/main/kotlin/com/hexated/SoraStream.kt | 17 ++-- .../main/kotlin/com/hexated/SoraStreamLite.kt | 8 +- 5 files changed, 51 insertions(+), 79 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 8ce610c3..f8d93318 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 = 209 +version = 210 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index ab1e1441..3ee5c51a 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.AESGCM.decrypt import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.APIHolder.unixTime import com.lagradost.cloudstream3.APIHolder.unixTimeMS @@ -9,7 +8,6 @@ import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.nicehttp.Requests import com.lagradost.nicehttp.Session import com.lagradost.cloudstream3.extractors.helper.AesHelper.cryptoAESHandler -import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.nicehttp.RequestBodyTypes import kotlinx.coroutines.delay import okhttp3.MediaType.Companion.toMediaTypeOrNull @@ -294,7 +292,7 @@ object SoraExtractor : SoraStream() { }?.subjectId val data = app.get( - "$aoneroomAPI/wefeed-mobile-bff/subject-api/resource?subjectId=${subjectId ?: return}&page=1&perPage=10000&all=0&startPosition=1&endPosition=1&pagerMode=0&resolution=480", + "$aoneroomAPI/wefeed-mobile-bff/subject-api/resource?subjectId=${subjectId ?: return}&page=1&perPage=20&all=0&startPosition=1&endPosition=1&pagerMode=0&resolution=480", headers = headers ).parsedSafe()?.data?.list?.findLast { it.se == (season ?: 0) && it.ep == (episode ?: 0) @@ -1229,7 +1227,7 @@ object SoraExtractor : SoraStream() { val selector = if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)" val server = app.get( - href ?: return, interceptor = CloudflareKiller() + href ?: return, interceptor = wpredisInterceptor ).document.selectFirst("div.entry-content > $selector") ?.attr("href") ?: return @@ -1695,9 +1693,9 @@ object SoraExtractor : SoraStream() { imdbId: String? = null, season: Int? = null, episode: Int? = null, - callback: (ExtractorLink) -> Unit + callback: (ExtractorLink) -> Unit, + onionUrl: String = "https://onionplay.se/" ) { - val onionUrl = "https://onionplay.se/" val request = if (season == null) { val res = app.get("$flixonAPI/$imdbId", referer = onionUrl) if (res.text.contains("BEGIN PGP SIGNED MESSAGE")) app.get( @@ -2319,13 +2317,10 @@ object SoraExtractor : SoraStream() { lastSeason: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit, + showboxApi: String = "https://www.showbox.media" ) { - - val showboxApi = "https://www.showbox.media" val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) - - val res = app.get("$showboxApi/search?keyword=$title").document - + val res = app.get("$showboxApi/search?keyword=$title", interceptor = showboxInterceptor).document val mediaRes = res.select("div.film_list-wrap div.flw-item").map { ShowboxMedia( it.select("h2.film-name a").attr("href"), @@ -2350,7 +2345,7 @@ object SoraExtractor : SoraStream() { val shareId = media?.url?.substringAfterLast("/") ?: return val shareKey = - app.get("$showboxApi/index/share_link?id=${shareId}&type=${if (season == null) "1" else "2"}") + app.get("$showboxApi/index/share_link?id=${shareId}&type=${if (season == null) "1" else "2"}", interceptor = showboxInterceptor) .parsedSafe()?.data?.link?.substringAfterLast("/") val headers = mapOf("Accept-Language" to "en") @@ -2417,9 +2412,9 @@ object SoraExtractor : SoraStream() { imdbId: String? = null, season: Int? = null, episode: Int? = null, - callback: (ExtractorLink) -> Unit + callback: (ExtractorLink) -> Unit, + referer: String = "https://bflix.gs/" ) { - val referer = "https://bflix.gs/" val slug = getEpisodeSlug(season, episode) var url = if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" @@ -2472,63 +2467,45 @@ object SoraExtractor : SoraStream() { } } - suspend fun invokeNavy( - imdbId: String? = null, - 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.band", imdbId, season, episode, callback) - } - - private suspend fun invokeHindi( - host: String? = null, - referer: String? = null, + suspend fun invokeAllMovieland( imdbId: String? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit, + host: String = "https://esh-bostewsom-i-273.site", ) { val res = app.get( - "$host/play/$imdbId", referer = "$referer/" + "$host/play/$imdbId", referer = "$allmovielandAPI/" ).document.selectFirst("script:containsData(player =)")?.data()?.substringAfter("{") ?.substringBefore(";")?.substringBefore(")") - val json = tryParseJson("{${res ?: return}") + 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 = "$referer/" + fixUrl(json?.file ?: return, host), headers = headers, referer = "$allmovielandAPI/" ).text.replace(Regex(""",\s*\[]"""), "") - val server = tryParseJson>(serverRes).let { server -> + val servers = tryParseJson>(serverRes).let { server -> if (season == null) { - server?.find { it.title == "English" }?.file + server?.map { it.file to it.title } } else { - server?.find { it.id.equals("$season") }?.folder?.find { it.episode.equals("$episode") }?.folder?.find { - it.title.equals( - "English" - ) - }?.file + server?.find { it.id.equals("$season") }?.folder?.find { it.episode.equals("$episode") }?.folder?.map { + it.file to it.title + } } } - val path = app.post( - "${host}/playlist/${server ?: return}.txt", headers = headers, referer = "$referer/" - ).text - - M3u8Helper.generateM3u8( - if (host == navyAPI) "Navy" else "Moment", path, "${referer}/" - ).forEach(callback) + servers?.apmap { (server, lang) -> + val path = app.post( + "${host}/playlist/${server ?: return@apmap}.txt", headers = headers, referer = "$allmovielandAPI/" + ).text + M3u8Helper.generateM3u8( + "Allmovieland [$lang]", + path, + "$allmovielandAPI/" + ).forEach(callback) + } } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 938462bc..21eb55a6 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -269,26 +269,26 @@ data class GokuServer( @JsonProperty("data") val data: GokuData? = GokuData(), ) -data class NavyEpisodeFolder( +data class AllMovielandEpisodeFolder( @JsonProperty("title") val title: String? = null, @JsonProperty("id") val id: String? = null, @JsonProperty("file") val file: String? = null, ) -data class NavySeasonFolder( - @JsonProperty("episode") val episode: String? = null, - @JsonProperty("id") val id: String? = null, - @JsonProperty("folder") val folder: ArrayList? = arrayListOf(), +data class AllMovielandSeasonFolder( + @JsonProperty("episode") val episode: String? = null, + @JsonProperty("id") val id: String? = null, + @JsonProperty("folder") val folder: ArrayList? = arrayListOf(), ) -data class NavyServer( - @JsonProperty("title") val title: String? = null, - @JsonProperty("id") val id: String? = null, - @JsonProperty("file") val file: String? = null, - @JsonProperty("folder") val folder: ArrayList? = arrayListOf(), +data class AllMovielandServer( + @JsonProperty("title") val title: String? = null, + @JsonProperty("id") val id: String? = null, + @JsonProperty("file") val file: String? = null, + @JsonProperty("folder") val folder: ArrayList? = arrayListOf(), ) -data class NavyPlaylist( +data class AllMovielandPlaylist( @JsonProperty("file") val file: String? = null, @JsonProperty("key") val key: String? = null, @JsonProperty("href") val href: String? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 0ce3233c..7021b572 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -2,6 +2,7 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.hexated.SoraExtractor.invoke2embed +import com.hexated.SoraExtractor.invokeAllMovieland import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAoneroom import com.hexated.SoraExtractor.invokeBollyMaza @@ -25,7 +26,6 @@ import com.hexated.SoraExtractor.invokeKisskh import com.hexated.SoraExtractor.invokeLing import com.hexated.SoraExtractor.invokeM4uhd import com.hexated.SoraExtractor.invokeMoviezAdd -import com.hexated.SoraExtractor.invokeNavy import com.hexated.SoraExtractor.invokeNinetv import com.hexated.SoraExtractor.invokeNowTv import com.hexated.SoraExtractor.invokeRStream @@ -34,7 +34,6 @@ import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeHdmovies4u -import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokeSFMovies @@ -51,6 +50,7 @@ import com.hexated.SoraExtractor.invokeWatchsomuch import com.hexated.SoraExtractor.invokeZshow import com.lagradost.cloudstream3.LoadResponse.Companion.addImdbId import com.lagradost.cloudstream3.LoadResponse.Companion.addTMDbId +import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink @@ -68,6 +68,9 @@ open class SoraStream : TmdbProvider() { TvType.Anime, ) + val showboxInterceptor by lazy { CloudflareKiller() } + val wpredisInterceptor by lazy { CloudflareKiller() } + /** AUTHOR : Hexated & Sora */ companion object { /** TOOLS */ @@ -102,12 +105,11 @@ open class SoraStream : TmdbProvider() { const val gokuAPI = "https://goku.sx" const val zshowAPI = BuildConfig.ZSHOW_API const val ridomoviesAPI = "https://ridomovies.pw" - const val navyAPI = "https://navy-issue-i-239.site" const val emoviesAPI = "https://emovies.si" const val multimoviesAPI = "https://multimovies.top" const val multimovies2API = "https://multimovies.click" const val netmoviesAPI = "https://netmovies.to" - const val momentAPI = "https://izzillent-dickstonyx-i-262.site" + const val allmovielandAPI = "https://allmovieland.fun" const val doomoviesAPI = "https://doomovies.net" const val vidsrctoAPI = "https://vidsrc.to" const val dramadayAPI = "https://dramaday.me" @@ -121,7 +123,7 @@ open class SoraStream : TmdbProvider() { const val fdMoviesAPI = "https://freedrivemovie.com" const val uhdmoviesAPI = "https://uhdmovies.zip" const val gMoviesAPI = "https://gdrivemovies.xyz" - const val hdmovies4uAPI = "https://hdmovies4u.band" + const val hdmovies4uAPI = "https://hdmovies4u.dad" const val vegaMoviesAPI = "https://vegamovies.dad" const val dotmoviesAPI = "https://dotmovies.bet" const val tvMoviesAPI = "https://www.tvseriesnmovies.com" @@ -632,10 +634,7 @@ open class SoraStream : TmdbProvider() { ) }, { - invokeNavy(res.imdbId, res.season, res.episode, callback) - }, - { - invokeMoment(res.imdbId, res.season, res.episode, callback) + if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) }, { if (!res.isAnime) invokeEmovies( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 90ad38d5..fb015f5d 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -1,6 +1,7 @@ package com.hexated import com.hexated.SoraExtractor.invoke2embed +import com.hexated.SoraExtractor.invokeAllMovieland import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAoneroom import com.hexated.SoraExtractor.invokeDbgo @@ -14,7 +15,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.invokeNavy import com.hexated.SoraExtractor.invokeNinetv import com.hexated.SoraExtractor.invokeNowTv import com.hexated.SoraExtractor.invokeRStream @@ -22,7 +22,6 @@ import com.hexated.SoraExtractor.invokeRidomovies import com.hexated.SoraExtractor.invokeSmashyStream import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies -import com.hexated.SoraExtractor.invokeMoment import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies import com.hexated.SoraExtractor.invokeSFMovies @@ -244,9 +243,6 @@ class SoraStreamLite : SoraStream() { callback ) }, - { - invokeNavy(res.imdbId, res.season, res.episode, callback) - }, { if (!res.isAnime && res.season == null) invokeRidomovies( res.id, @@ -281,7 +277,7 @@ class SoraStreamLite : SoraStream() { ) }, { - invokeMoment(res.imdbId, res.season, res.episode, callback) + if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) }, { if (!res.isAnime && res.season == null) invokeDoomovies( From 1e2f7466768d5f21fec91441efebb11b7b16a514 Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 31 Dec 2023 12:07:11 +0700 Subject: [PATCH 024/125] fix layarkaca --- LayarKacaProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 86 +++++++++++++++++++ .../kotlin/com/hexated/LayarKacaProvider.kt | 85 +++++++----------- .../com/hexated/LayarKacaProviderPlugin.kt | 1 + 4 files changed, 117 insertions(+), 57 deletions(-) create mode 100644 LayarKacaProvider/src/main/kotlin/com/hexated/Extractors.kt diff --git a/LayarKacaProvider/build.gradle.kts b/LayarKacaProvider/build.gradle.kts index 85bf1cb9..7003fef2 100644 --- a/LayarKacaProvider/build.gradle.kts +++ b/LayarKacaProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 18 +version = 19 cloudstream { diff --git a/LayarKacaProvider/src/main/kotlin/com/hexated/Extractors.kt b/LayarKacaProvider/src/main/kotlin/com/hexated/Extractors.kt new file mode 100644 index 00000000..8aa99fd9 --- /dev/null +++ b/LayarKacaProvider/src/main/kotlin/com/hexated/Extractors.kt @@ -0,0 +1,86 @@ +package com.hexated + +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.Filesim +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.INFER_TYPE +import com.lagradost.cloudstream3.utils.M3u8Helper +import com.lagradost.cloudstream3.utils.getQualityFromName + +open class Emturbovid : ExtractorApi() { + override val name = "Emturbovid" + override val mainUrl = "https://emturbovid.com" + override val requiresReferer = true + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val response = app.get(url, referer = referer) + val m3u8 = Regex("[\"'](.*?master\\.m3u8.*?)[\"']").find(response.text)?.groupValues?.getOrNull(1) + M3u8Helper.generateM3u8( + name, + m3u8 ?: return, + mainUrl + ).forEach(callback) + } + +} + +open class Hownetwork : ExtractorApi() { + override val name = "Hownetwork" + override val mainUrl = "https://stream.hownetwork.xyz" + override val requiresReferer = true + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val id = url.substringAfter("id=") + val res = app.post( + "$mainUrl/api.php?id=$id", + data = mapOf( + "r" to "https://playeriframe.shop/", + "d" to "stream.hownetwork.xyz", + ), + referer = url, + headers = mapOf( + "X-Requested-With" to "XMLHttpRequest" + ) + ).parsedSafe() + + res?.data?.map { + callback.invoke( + ExtractorLink( + this.name, + this.name, + it.file, + url, + getQualityFromName(it.label), + INFER_TYPE + ) + ) + } + + } + + data class Sources( + val data: ArrayList + ) { + data class Data( + val file: String, + val label: String?, + ) + } +} + +class Furher : Filesim() { + override val name = "Furher" + override var mainUrl = "https://furher.in" +} \ No newline at end of file diff --git a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt index 552e412e..05b9dcd0 100644 --- a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt +++ b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt @@ -8,29 +8,29 @@ import com.lagradost.cloudstream3.utils.* import org.jsoup.nodes.Element class LayarKacaProvider : MainAPI() { - override var mainUrl = "https://tv6.lk21official.wiki" - private var seriesUrl = "https://tv8.nontondrama.click" + override var mainUrl = "https://tv7.lk21official.wiki" + private var seriesUrl = "https://tv9.nontondrama.click" override var name = "LayarKaca" override val hasMainPage = true override var lang = "id" override val supportedTypes = setOf( - TvType.Movie, - TvType.TvSeries, - TvType.AsianDrama + TvType.Movie, + TvType.TvSeries, + TvType.AsianDrama ) override val mainPage = mainPageOf( - "$mainUrl/populer/page/" to "Film Terplopuler", - "$mainUrl/rating/page/" to "Film Berdasarkan IMDb Rating", - "$mainUrl/most-commented/page/" to "Film Dengan Komentar Terbanyak", - "$seriesUrl/latest/page/" to "Series Terbaru", - "$seriesUrl/series/asian/page/" to "Film Asian Terbaru", - "$mainUrl/latest/page/" to "Film Upload Terbaru", + "$mainUrl/populer/page/" to "Film Terplopuler", + "$mainUrl/rating/page/" to "Film Berdasarkan IMDb Rating", + "$mainUrl/most-commented/page/" to "Film Dengan Komentar Terbanyak", + "$seriesUrl/latest-series/page/" to "Series Terbaru", + "$seriesUrl/series/asian/page/" to "Film Asian Terbaru", + "$mainUrl/latest/page/" to "Film Upload Terbaru", ) override suspend fun getMainPage( - page: Int, - request: MainPageRequest + page: Int, + request: MainPageRequest ): HomePageResponse { val document = app.get(request.data + page).document val home = document.select("article.mega-item").mapNotNull { @@ -54,10 +54,10 @@ class LayarKacaProvider : MainAPI() { val href = fixUrl(this.selectFirst("a")!!.attr("href")) val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) val type = - if (this.selectFirst("div.last-episode") == null) TvType.Movie else TvType.TvSeries + if (this.selectFirst("div.last-episode") == null) TvType.Movie else TvType.TvSeries return if (type == TvType.TvSeries) { val episode = this.selectFirst("div.last-episode span")?.text()?.filter { it.isDigit() } - ?.toIntOrNull() + ?.toIntOrNull() newAnimeSearchResponse(title, href, TvType.TvSeries) { this.posterUrl = posterUrl addSub(episode) @@ -92,23 +92,23 @@ class LayarKacaProvider : MainAPI() { val tags = document.select("div.content > div:nth-child(5) > h3 > a").map { it.text() } val year = Regex("\\d, (\\d+)").find( - document.select("div.content > div:nth-child(7) > h3").text().trim() + document.select("div.content > div:nth-child(7) > h3").text().trim() )?.groupValues?.get(1).toString().toIntOrNull() val tvType = if (document.select("div.serial-wrapper") - .isNotEmpty() + .isNotEmpty() ) TvType.TvSeries else TvType.Movie val description = document.select("div.content > blockquote").text().trim() val trailer = document.selectFirst("div.action-player li > a.fancybox")?.attr("href") val rating = - document.selectFirst("div.content > div:nth-child(6) > h3")?.text()?.toRatingInt() + document.selectFirst("div.content > div:nth-child(6) > h3")?.text()?.toRatingInt() val actors = - document.select("div.col-xs-9.content > div:nth-child(3) > h3 > a").map { it.text() } + document.select("div.col-xs-9.content > div:nth-child(3) > h3 > a").map { it.text() } val recommendations = document.select("div.row.item-media").map { val recName = it.selectFirst("h3")?.text()?.trim().toString() val recHref = it.selectFirst(".content-media > a")!!.attr("href") val recPosterUrl = - fixUrl(it.selectFirst(".poster-media > a > img")?.attr("src").toString()) + fixUrl(it.selectFirst(".poster-media > a > img")?.attr("src").toString()) newTvSeriesSearchResponse(recName, recHref, TvType.TvSeries) { this.posterUrl = recPosterUrl } @@ -119,12 +119,12 @@ class LayarKacaProvider : MainAPI() { val href = fixUrl(it.attr("href")) val episode = it.text().toIntOrNull() val season = - it.attr("href").substringAfter("season-").substringBefore("-").toIntOrNull() + it.attr("href").substringAfter("season-").substringBefore("-").toIntOrNull() Episode( - href, - "Episode $episode", - season, - episode, + href, + "Episode $episode", + season, + episode, ) }.reversed() newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { @@ -152,10 +152,10 @@ class LayarKacaProvider : MainAPI() { } override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit ): Boolean { val document = app.get(data).document @@ -173,30 +173,3 @@ class LayarKacaProvider : MainAPI() { } } - -open class Emturbovid : ExtractorApi() { - override val name = "Emturbovid" - override val mainUrl = "https://emturbovid.com" - override val requiresReferer = true - - override suspend fun getUrl( - url: String, - referer: String?, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - val response = app.get(url, referer = referer) - val m3u8 = Regex("[\"'](.*?master\\.m3u8.*?)[\"']").find(response.text)?.groupValues?.getOrNull(1) - M3u8Helper.generateM3u8( - name, - m3u8 ?: return, - mainUrl - ).forEach(callback) - } - -} - -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 9a73cdc1..d3a57242 100644 --- a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProviderPlugin.kt +++ b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProviderPlugin.kt @@ -12,5 +12,6 @@ class LayarKacaProviderPlugin: Plugin() { registerMainAPI(LayarKacaProvider()) registerExtractorAPI(Emturbovid()) registerExtractorAPI(Furher()) + registerExtractorAPI(Hownetwork()) } } \ No newline at end of file From aada4b49fe1f458b7f89440dc4e919ae76ab406c Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 1 Jan 2024 18:42:32 +0700 Subject: [PATCH 025/125] sora: fix crunchy --- Samehadaku/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Samehadaku.kt | 5 ++- SoraStream/build.gradle.kts | 2 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 20 ++++----- .../src/main/kotlin/com/hexated/SoraParser.kt | 43 ++++++++++++------- .../src/main/kotlin/com/hexated/SoraUtils.kt | 18 +++++--- 6 files changed, 56 insertions(+), 34 deletions(-) diff --git a/Samehadaku/build.gradle.kts b/Samehadaku/build.gradle.kts index 25a86ea3..0ef8f5ed 100644 --- a/Samehadaku/build.gradle.kts +++ b/Samehadaku/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 18 +version = 19 cloudstream { diff --git a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt index 69bdf841..b31f4c7e 100644 --- a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt +++ b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt @@ -217,9 +217,10 @@ class Samehadaku : MainAPI() { } private fun String.fixQuality() : Int { - return when(this) { - "MP4HD" -> Qualities.P720.value + return when(this.uppercase()) { + "4K" -> Qualities.P2160.value "FULLHD" -> Qualities.P1080.value + "MP4HD" -> Qualities.P720.value else -> this.filter { it.isDigit() }.toIntOrNull() ?: Qualities.Unknown.value } } diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index f8d93318..8c2f717a 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 = 210 +version = 211 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 3ee5c51a..677c7bc2 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1505,7 +1505,8 @@ object SoraExtractor : SoraStream() { "en-US", "zh-CN", ) - val headers = getCrunchyrollToken() + val token = getCrunchyrollToken() + val headers = mapOf("Authorization" to "${token.tokenType} ${token.accessToken}") val seasonIdData = app.get( "$crunchyrollAPI/content/v2/cms/series/${id ?: return}/seasons", headers = headers ).parsedSafe()?.data?.let { s -> @@ -1532,17 +1533,18 @@ object SoraExtractor : SoraStream() { it.title.equals(epsTitle, true) || it.slug_title.equals( epsTitle.createSlug(), true ) || it.episode_number == episode - }?.streams_link - val sources = - app.get(fixUrl(streamsLink ?: return@apmap, crunchyrollAPI), headers = headers) - .parsedSafe() + }?.streams_link?.substringAfter("/videos/")?.substringBefore("/streams") ?: return@apmap + val sources = app.get( + "$crunchyrollAPI/cms/v2${token.bucket}/videos/$streamsLink/streams?Policy=${token.policy}&Signature=${token.signature}&Key-Pair-Id=${token.key_pair_id}", + headers = headers + ).parsedSafe() listOf( "adaptive_hls", "vo_adaptive_hls" ).map { hls -> val name = if (hls == "adaptive_hls") "Crunchyroll" else "Vrv" val audio = if (audioL == "en-US") "English Dub" else "Raw" - val source = sources?.data?.firstOrNull()?.let { + val source = sources?.streams?.let { if (hls == "adaptive_hls") it.adaptive_hls else it.vo_adaptive_hls } M3u8Helper.generateM3u8( @@ -1552,7 +1554,7 @@ object SoraExtractor : SoraStream() { ).forEach(callback) } - sources?.meta?.subtitles?.map { sub -> + sources?.subtitles?.map { sub -> subtitleCallback.invoke( SubtitleFile( "${fixCrunchyrollLang(sub.key) ?: sub.key} [ass]", @@ -1560,8 +1562,6 @@ object SoraExtractor : SoraStream() { ) ) } - - } } @@ -2135,7 +2135,7 @@ object SoraExtractor : SoraStream() { media.third.substringAfterLast("/") to iframe.substringAfterLast("/") .substringBefore("-") } - val res = app.get(fixUrl(iframe, api)) + val res = app.get(fixUrl(iframe, api), verify = false) delay(2000) val serverUrl = res.document.selectFirst("script:containsData(pushState)")?.data()?.let { """,\s*'([^']+)""".toRegex().find(it)?.groupValues?.get(1) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 21eb55a6..03eafa4c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -2,6 +2,15 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty +data class CrunchyrollAccessToken( + val accessToken: String? = null, + val tokenType: String? = null, + val bucket: String? = null, + val policy: String? = null, + val signature: String? = null, + val key_pair_id: String? = null, +) + data class ShowboxMedia( val url: String, val title: String, @@ -207,12 +216,17 @@ data class AnilistResponses( ) data class CrunchyrollToken( - @JsonProperty("access_token") val accessToken: String? = null, - @JsonProperty("expires_in") val expiresIn: Int? = null, - @JsonProperty("token_type") val tokenType: String? = null, - @JsonProperty("scope") val scope: String? = null, - @JsonProperty("country") val country: String? = null -) + @JsonProperty("access_token") val accessToken: String? = null, + @JsonProperty("token_type") val tokenType: String? = null, + @JsonProperty("cms") val cms: Cms? = null, +) { + data class Cms( + @JsonProperty("bucket") var bucket: String? = null, + @JsonProperty("policy") var policy: String? = null, + @JsonProperty("signature") var signature: String? = null, + @JsonProperty("key_pair_id") var key_pair_id: String? = null, + ) +} data class CrunchyrollVersions( @JsonProperty("audio_locale") val audio_locale: String? = null, @@ -227,22 +241,21 @@ data class CrunchyrollData( @JsonProperty("episode_number") val episode_number: Int? = null, @JsonProperty("versions") val versions: ArrayList? = null, @JsonProperty("streams_link") val streams_link: String? = null, - @JsonProperty("adaptive_hls") val adaptive_hls: HashMap>? = hashMapOf(), - @JsonProperty("vo_adaptive_hls") val vo_adaptive_hls: HashMap>? = hashMapOf(), ) data class CrunchyrollResponses( @JsonProperty("data") val data: ArrayList? = arrayListOf(), ) -data class CrunchyrollMeta( - @JsonProperty("subtitles") val subtitles: HashMap>? = hashMapOf(), -) - data class CrunchyrollSourcesResponses( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), - @JsonProperty("meta") val meta: CrunchyrollMeta? = null, -) + @JsonProperty("streams") val streams: Streams? = Streams(), + @JsonProperty("subtitles") val subtitles: HashMap>? = hashMapOf(), +) { + data class Streams( + @JsonProperty("adaptive_hls") val adaptive_hls: HashMap>? = hashMapOf(), + @JsonProperty("vo_adaptive_hls") val vo_adaptive_hls: HashMap>? = hashMapOf(), + ) +} data class MALSyncSites( @JsonProperty("Zoro") val zoro: HashMap>? = hashMapOf(), diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 89593955..22c68cac 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -734,7 +734,7 @@ fun Document.findTvMoviesIframe(): String? { } //modified code from https://github.com/jmir1/aniyomi-extensions/blob/master/src/all/kamyroll/src/eu/kanade/tachiyomi/animeextension/all/kamyroll/AccessTokenInterceptor.kt -suspend fun getCrunchyrollToken(): Map { +suspend fun getCrunchyrollToken(): CrunchyrollAccessToken { val client = app.baseClient.newBuilder() .proxy(Proxy(Proxy.Type.SOCKS, InetSocketAddress("cr-unblocker.us.to", 1080))) .build() @@ -760,9 +760,17 @@ suspend fun getCrunchyrollToken(): Map { ) ) - val response = tryParseJson(client.newCall(request).execute().body.string()) - return mapOf("Authorization" to "${response?.tokenType} ${response?.accessToken}") - + val token = tryParseJson(client.newCall(request).execute().body.string()) + val headers = mapOf("Authorization" to "${token?.tokenType} ${token?.accessToken}") + val cms = app.get("$crunchyrollAPI/index/v2", headers = headers).parsedSafe()?.cms + return CrunchyrollAccessToken( + token?.accessToken, + token?.tokenType, + cms?.bucket, + cms?.policy, + cms?.signature, + cms?.key_pair_id, + ) } suspend fun getCrunchyrollId(aniId: String?): String? { @@ -796,7 +804,7 @@ suspend fun getCrunchyrollId(aniId: String?): String? { return (externalLinks?.find { it.site == "VRV" } ?: externalLinks?.find { it.site == "Crunchyroll" })?.url?.let { - Regex("series/(\\w+)/?").find(it)?.groupValues?.get(1) + app.get(it).url.substringAfter("/series/").substringBefore("/") } } From bbe17aabed4f7d8753549ba2886ec5a624435fe3 Mon Sep 17 00:00:00 2001 From: alex Date: Mon, 1 Jan 2024 19:05:41 +0700 Subject: [PATCH 026/125] fix --- SoraStream/src/main/kotlin/com/hexated/Extractors.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt index a2e33744..9f50b592 100644 --- a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -11,7 +11,7 @@ import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.base64Decode import com.lagradost.cloudstream3.extractors.Jeniusplay -import com.lagradost.cloudstream3.extractors.Pixeldrain +import com.lagradost.cloudstream3.extractors.PixelDrain import com.lagradost.cloudstream3.extractors.Vidplay import com.lagradost.cloudstream3.utils.* import java.math.BigInteger @@ -364,7 +364,7 @@ class FilelionsTo : Filesim() { override var mainUrl = "https://filelions.to" } -class Pixeldra : Pixeldrain() { +class Pixeldra : PixelDrain() { override val mainUrl = "https://pixeldra.in" } From 03c2641c86eda9d801f46812e808fada4da0f662 Mon Sep 17 00:00:00 2001 From: irfannajmudinsidik <50092754+irfannajmudinsidik@users.noreply.github.com> Date: Mon, 1 Jan 2024 19:06:40 +0700 Subject: [PATCH 027/125] Update Ngefilm.kt (#486) Update --- Gomov/src/main/kotlin/com/hexated/Ngefilm.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt index 6836fc3f..5061d790 100644 --- a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt +++ b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt @@ -3,7 +3,7 @@ package com.hexated import com.lagradost.cloudstream3.mainPageOf class Ngefilm : Gomov() { - override var mainUrl = "https://tv1.ngefilm21.homes" + override var mainUrl = "https://tv2.ngefilm21.homes" 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", From 4643275ab45042f95ac02e517f2397ac27acd19e Mon Sep 17 00:00:00 2001 From: Saksham Kushwaha <92094239+LiReNa00@users.noreply.github.com> Date: Mon, 1 Jan 2024 17:39:03 +0530 Subject: [PATCH 028/125] Updated Consumet Instance (#484) * Update YugenAnime.kt consumet has closed it's public api instance for months now and to use it consumet a person has to host his/her own instance so just updated the instance * Update Anilibria.kt * Update Kickassanime.kt * Update Loklok.kt --- Anilibria/src/main/kotlin/com/hexated/Anilibria.kt | 4 ++-- Kickassanime/src/main/kotlin/com/hexated/Kickassanime.kt | 6 +++--- Loklok/src/main/kotlin/com/hexated/Loklok.kt | 2 +- YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Anilibria/src/main/kotlin/com/hexated/Anilibria.kt b/Anilibria/src/main/kotlin/com/hexated/Anilibria.kt index c51afb3c..d4975a0b 100644 --- a/Anilibria/src/main/kotlin/com/hexated/Anilibria.kt +++ b/Anilibria/src/main/kotlin/com/hexated/Anilibria.kt @@ -144,7 +144,7 @@ class Anilibria : MainAPI() { } private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { - val res = app.get("https://api.consumet.org/meta/anilist/$title") + val res = app.get("https://consumet-instance.vercel.app/meta/anilist/$title") .parsedSafe()?.results?.find { media -> (media.title?.english.equals(title, true) || media.title?.romaji.equals( title, @@ -194,4 +194,4 @@ class Anilibria : MainAPI() { @JsonProperty("mes") val mes: String? = null, ) -} \ No newline at end of file +} diff --git a/Kickassanime/src/main/kotlin/com/hexated/Kickassanime.kt b/Kickassanime/src/main/kotlin/com/hexated/Kickassanime.kt index 75184a6e..2ca2465e 100644 --- a/Kickassanime/src/main/kotlin/com/hexated/Kickassanime.kt +++ b/Kickassanime/src/main/kotlin/com/hexated/Kickassanime.kt @@ -35,8 +35,8 @@ open class Kickassanime : MainAPI() { companion object { const val kaast = "https://kaast1.com" - private const val consumetAnilist = "https://api.consumet.org/meta/anilist" - private const val consumetMal = "https://api.consumet.org/meta/mal" + private const val consumetAnilist = "https://consumet-instance.vercel.app/meta/anilist" + private const val consumetMal = "https://consumet-instance.vercel.app/meta/mal" fun getType(t: String): TvType { return when { t.contains("Ova", true) -> TvType.OVA @@ -379,4 +379,4 @@ open class Kickassanime : MainAPI() { @JsonProperty("title") val title: SyncTitle? = null, ) -} \ No newline at end of file +} diff --git a/Loklok/src/main/kotlin/com/hexated/Loklok.kt b/Loklok/src/main/kotlin/com/hexated/Loklok.kt index 5e8c8ca5..143d5c01 100644 --- a/Loklok/src/main/kotlin/com/hexated/Loklok.kt +++ b/Loklok/src/main/kotlin/com/hexated/Loklok.kt @@ -268,7 +268,7 @@ class Loklok : MainAPI() { } private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { - val res = app.get("https://api.consumet.org/meta/anilist/$title") + val res = app.get("https://consumet-instance.vercel.app/meta/anilist/$title") .parsedSafe()?.results?.find { media -> (media.title?.english.equals(title, true) || media.title?.romaji.equals( title, diff --git a/YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt b/YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt index af605a82..5a99253f 100644 --- a/YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt +++ b/YugenAnime/src/main/kotlin/com/hexated/YugenAnime.kt @@ -31,8 +31,8 @@ class YugenAnime : MainAPI() { ) companion object { - private const val consumetAnilist = "https://api.consumet.org/meta/anilist" - private const val consumetMal = "https://api.consumet.org/meta/mal" + private const val consumetAnilist = "https://consumet-instance.vercel.app/meta/anilist" + private const val consumetMal = "https://consumet-instance.vercel.app/meta/mal" fun getType(t: String): TvType { return if (t.contains("OVA", true) || t.contains("Special", true)) TvType.OVA From 4c14b600e53e9f37587fd765fe83a719148b3d4e Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 2 Jan 2024 01:07:49 +0700 Subject: [PATCH 029/125] update --- Anilibria/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Anilibria.kt | 52 ++----------------- .../src/main/kotlin/com/hexated/SoraStream.kt | 20 +++---- .../main/kotlin/com/hexated/SoraStreamLite.kt | 20 +++---- 4 files changed, 26 insertions(+), 68 deletions(-) diff --git a/Anilibria/build.gradle.kts b/Anilibria/build.gradle.kts index 061d5f39..f29ed62f 100644 --- a/Anilibria/build.gradle.kts +++ b/Anilibria/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { diff --git a/Anilibria/src/main/kotlin/com/hexated/Anilibria.kt b/Anilibria/src/main/kotlin/com/hexated/Anilibria.kt index d4975a0b..254fdade 100644 --- a/Anilibria/src/main/kotlin/com/hexated/Anilibria.kt +++ b/Anilibria/src/main/kotlin/com/hexated/Anilibria.kt @@ -84,17 +84,13 @@ class Anilibria : MainAPI() { val document = app.get(url).document val title = document.selectFirst("h1.release-title")?.text() ?: return null - val poster = fixUrlNull(document.selectFirst("img#adminPoster")?.attr("src")) - val trackTitle = (document.selectFirst("h1.release-title br")?.nextSibling() + val enTitle = (document.selectFirst("h1.release-title br")?.nextSibling() ?: document.selectFirst("h1.release-title")?.text()?.substringAfter("/")?.trim()).toString() + val poster = fixUrlNull(document.selectFirst("img#adminPoster")?.attr("src")) val type = document.selectFirst("div#xreleaseInfo b:contains(Тип:)")?.nextSibling() .toString().substringBefore(",").trim() - val trackType = type.let { - if(it.contains("Фильм", true)) "movie" else "tv" - } val year = document.selectFirst("div#xreleaseInfo b:contains(Сезон:)")?.nextElementSibling() ?.text()?.filter { it.isDigit() }?.toIntOrNull() - val (malId, anilistId, image, cover) = getTracker(trackTitle, trackType, year) val episodes = document.select("script").find { it.data().contains("var player =") }?.data() ?.substringAfter("file:[")?.substringBefore("],")?.let { data -> tryParseJson>("[$data]")?.mapNotNull { eps -> @@ -106,15 +102,14 @@ class Anilibria : MainAPI() { } } return newAnimeLoadResponse(title, url, getType(type)) { - posterUrl = image ?: poster - backgroundPosterUrl = cover ?: image ?: poster + japName = enTitle + posterUrl = poster + backgroundPosterUrl = poster this.year = year addEpisodes(DubStatus.Subbed, episodes) plot = document.select("p.detail-description").text().trim() this.tags = document.selectFirst("div#xreleaseInfo b:contains(Жанры:)")?.nextSibling() .toString().split(",").map { it.trim() } - addMalId(malId) - addAniListId(anilistId?.toIntOrNull()) } } @@ -143,43 +138,6 @@ class Anilibria : MainAPI() { return true } - private suspend fun getTracker(title: String?, type: String?, year: Int?): Tracker { - val res = app.get("https://consumet-instance.vercel.app/meta/anilist/$title") - .parsedSafe()?.results?.find { media -> - (media.title?.english.equals(title, true) || media.title?.romaji.equals( - title, - true - )) || (media.type.equals(type, true) && media.releaseDate == year) - } - return Tracker(res?.malId, res?.aniId, res?.image, res?.cover) - } - - data class Tracker( - val malId: Int? = null, - val aniId: String? = null, - val image: String? = null, - val cover: String? = null, - ) - - data class Title( - @JsonProperty("romaji") val romaji: String? = null, - @JsonProperty("english") val english: String? = null, - ) - - data class Results( - @JsonProperty("id") val aniId: String? = null, - @JsonProperty("malId") val malId: Int? = null, - @JsonProperty("title") val title: Title? = null, - @JsonProperty("releaseDate") val releaseDate: Int? = null, - @JsonProperty("type") val type: String? = null, - @JsonProperty("image") val image: String? = null, - @JsonProperty("cover") val cover: String? = null, - ) - - data class AniSearch( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), - ) - private data class Episodes( @JsonProperty("file") val file: String? = null, @JsonProperty("title") val title: String? = null, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 7021b572..141c5839 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -365,16 +365,16 @@ open class SoraStream : TmdbProvider() { val res = parseJson(data) argamap( - { - invokeFebbox( - res.title, - res.year, - res.season, - res.lastSeason, - res.episode, - callback - ) - }, +// { +// invokeFebbox( +// res.title, +// res.year, +// res.season, +// res.lastSeason, +// res.episode, +// callback +// ) +// }, { invokeDumpStream( res.title, diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index fb015f5d..3b9e975f 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -52,16 +52,16 @@ class SoraStreamLite : SoraStream() { val res = AppUtils.parseJson(data) argamap( - { - invokeFebbox( - res.title, - res.year, - res.season, - res.lastSeason, - res.episode, - callback - ) - }, +// { +// invokeFebbox( +// res.title, +// res.year, +// res.season, +// res.lastSeason, +// res.episode, +// callback +// ) +// }, { if (!res.isAnime) invokeWatchsomuch( res.imdbId, From 2d23f05fa0a070a426b4d7751eff3f0d46ca82dd Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 2 Jan 2024 02:00:28 +0700 Subject: [PATCH 030/125] update --- 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 677c7bc2..1a9392d6 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -2092,7 +2092,7 @@ object SoraExtractor : SoraStream() { "$title Season $season" } val savedCookies = mapOf( - "_identitygomovies7" to "52fdc70b008c0b1d881dac0f01cca819edd512de01cc8bbc1224ed4aafb78b52a%3A2%3A%7Bi%3A0%3Bs%3A18%3A%22_identitygomovies7%22%3Bi%3A1%3Bs%3A52%3A%22%5B2050366%2C%22HnVRRAObTASOJEr45YyCM8wiHol0V1ko%22%2C2592000%5D%22%3B%7D", + base64Decode("X2lkZW50aXR5Z29tb3ZpZXM3") to base64Decode("NTJmZGM3MGIwMDhjMGIxZDg4MWRhYzBmMDFjY2E4MTllZGQ1MTJkZTAxY2M4YmJjMTIyNGVkNGFhZmI3OGI1MmElM0EyJTNBJTdCaSUzQTAlM0JzJTNBMTglM0ElMjJfaWRlbnRpdHlnb21vdmllczclMjIlM0JpJTNBMSUzQnMlM0E1MiUzQSUyMiU1QjIwNTAzNjYlMkMlMjJIblZSUkFPYlRBU09KRXI0NVl5Q004d2lIb2wwVjFrbyUyMiUyQzI1OTIwMDAlNUQlMjIlM0IlN0Q="), ) val req = app.get("$api/search/$query") val doc = req.document From 29c78d2468f2f2ce7ceb28cd6d7f1875df30ba44 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 3 Jan 2024 06:57:41 +0700 Subject: [PATCH 031/125] sora: added mMovies & fix oploverz --- OploverzProvider/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 35 + .../kotlin/com/hexated/OploverzProvider.kt | 2 +- .../com/hexated/OploverzProviderPlugin.kt | 1 + SoraStream/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 8 +- .../main/kotlin/com/hexated/SoraExtractor.kt | 1872 +++++------------ .../src/main/kotlin/com/hexated/SoraParser.kt | 362 ++-- .../src/main/kotlin/com/hexated/SoraStream.kt | 879 +++----- .../main/kotlin/com/hexated/SoraStreamLite.kt | 402 +--- 10 files changed, 1079 insertions(+), 2486 deletions(-) diff --git a/OploverzProvider/build.gradle.kts b/OploverzProvider/build.gradle.kts index e2ebbfc0..a8b4e717 100644 --- a/OploverzProvider/build.gradle.kts +++ b/OploverzProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 24 +version = 25 cloudstream { diff --git a/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt b/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt index c38c13b8..02a8f86d 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt @@ -42,4 +42,39 @@ open class Qiwi : ExtractorApi() { ?: Qualities.Unknown.value } +} + +open class Mediafire : ExtractorApi() { + override val name = "Mediafire" + override val mainUrl = "https://www.mediafire.com" + 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 title = res.select("div.dl-btn-label").text() + val video = res.selectFirst("a#downloadButton")?.attr("href") + + callback.invoke( + ExtractorLink( + this.name, + this.name, + video ?: return, + "", + getQuality(title), + INFER_TYPE + ) + ) + + } + + private fun getQuality(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 8ed03196..4d5dc26d 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProvider.kt @@ -7,7 +7,7 @@ import com.lagradost.cloudstream3.utils.* import org.jsoup.nodes.Element class OploverzProvider : MainAPI() { - override var mainUrl = "https://oploverz.red" + override var mainUrl = "https://oploverz.life" 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 ba7c0b85..a635a694 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProviderPlugin.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProviderPlugin.kt @@ -11,5 +11,6 @@ class OploverzProviderPlugin: Plugin() { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(OploverzProvider()) registerExtractorAPI(Qiwi()) + registerExtractorAPI(Mediafire()) } } \ No newline at end of file diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 8c2f717a..f157e229 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 = 211 +version = 212 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt index 9f50b592..1674ebc2 100644 --- a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -339,13 +339,7 @@ open class Netembed : ExtractorApi() { val script = getAndUnpack(response.text) val m3u8 = Regex("((https:|http:)//.*\\.m3u8)").find(script)?.groupValues?.getOrNull(1) ?: return - if (!m3u8.startsWith("https://www.febbox.com")) { - M3u8Helper.generateM3u8( - this.name, - m3u8, - "$mainUrl/", - ).forEach(callback) - } + M3u8Helper.generateM3u8(this.name, m3u8, "$mainUrl/", ).forEach(callback) } } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 1a9392d6..5e556735 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -10,6 +10,7 @@ import com.lagradost.nicehttp.Session import com.lagradost.cloudstream3.extractors.helper.AesHelper.cryptoAESHandler import com.lagradost.nicehttp.RequestBodyTypes import kotlinx.coroutines.delay +import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.RequestBody.Companion.toRequestBody import org.jsoup.Jsoup @@ -20,35 +21,20 @@ val session = Session(Requests().baseClient) object SoraExtractor : SoraStream() { - suspend fun invokeGoku( - title: String? = null, - year: Int? = null, - season: Int? = null, - lastSeason: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - val headers = mapOf( - "X-Requested-With" to "XMLHttpRequest" - ) + suspend fun invokeGoku(title: String? = null, year: Int? = null, season: Int? = null, lastSeason: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { + val headers = mapOf("X-Requested-With" to "XMLHttpRequest") fun Document.getServers(): List> { return this.select("a").map { it.attr("data-id") to it.text() } } - val media = app.get( - "$gokuAPI/ajax/movie/search?keyword=$title", headers = headers - ).document.select("div.item").find { ele -> + val media = app.get("$gokuAPI/ajax/movie/search?keyword=$title", headers = headers).document.select("div.item").find { ele -> val url = ele.selectFirst("a.movie-link")?.attr("href") 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() - (titleMedia.equals(title, true) || titleMedia.createSlug() - .equals(titleSlug) || url?.contains("$titleSlug-") == true) && (if (season == null) { + 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("/movie/") == true } else { lastSeasonMedia == lastSeason && url?.contains("/series/") == true @@ -56,160 +42,91 @@ object SoraExtractor : SoraStream() { } ?: return val serversId = if (season == null) { - val movieId = app.get( - fixUrl( - media.selectFirst("a")?.attr("href") ?: return, gokuAPI - ) - ).url.substringAfterLast("/") - app.get( - "$gokuAPI/ajax/movie/episode/servers/$movieId", headers = headers - ).document.getServers() + val movieId = app.get(fixUrl(media.selectFirst("a")?.attr("href") + ?: return, gokuAPI)).url.substringAfterLast("/") + app.get("$gokuAPI/ajax/movie/episode/servers/$movieId", headers = headers).document.getServers() } else { - val seasonId = app.get( - "$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") - val episodeId = app.get( - "$gokuAPI/ajax/movie/season/episodes/${seasonId ?: return}", headers = headers - ).document.select("div.item").find { + val seasonId = app.get("$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") + val episodeId = app.get("$gokuAPI/ajax/movie/season/episodes/${seasonId ?: return}", headers = headers).document.select("div.item").find { it.selectFirst("strong")?.text().equals("Eps $episode:", true) }?.selectFirst("a")?.attr("data-id") - app.get( - "$gokuAPI/ajax/movie/episode/servers/${episodeId ?: return}", headers = headers - ).document.getServers() + app.get("$gokuAPI/ajax/movie/episode/servers/${episodeId ?: return}", headers = headers).document.getServers() } serversId.apmap { (id, name) -> - val iframe = - app.get("$gokuAPI/ajax/movie/episode/server/sources/$id", headers = headers) - .parsedSafe()?.data?.link ?: return@apmap + val iframe = app.get("$gokuAPI/ajax/movie/episode/server/sources/$id", headers = headers).parsedSafe()?.data?.link + ?: return@apmap loadCustomExtractor( - name, - iframe, - "$gokuAPI/", - subtitleCallback, - callback, + name, + iframe, + "$gokuAPI/", + subtitleCallback, + callback, ) } } - suspend fun invokeVidSrc( - id: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeVidSrc(id: Int? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit) { val url = if (season == null) { "$vidSrcAPI/embed/movie?tmdb=$id" } else { "$vidSrcAPI/embed/tv?tmdb=$id&season=$season&episode=$episode" } - val iframedoc = - app.get(url).document.select("iframe#player_iframe").attr("src").let { httpsify(it) } + val iframedoc = app.get(url).document.select("iframe#player_iframe").attr("src").let { httpsify(it) } val doc = app.get(iframedoc, referer = url).document val index = doc.select("body").attr("data-i") val hash = doc.select("div#hidden").attr("data-h") val srcrcp = deobfstr(hash, index) - val script = app.get( - httpsify(srcrcp), - referer = iframedoc - ).document.selectFirst("script:containsData(Playerjs)")?.data() - val video = script?.substringAfter("file:\"#2")?.substringBefore("\"") - ?.replace(Regex("(//\\S+?=)"), "")?.let { base64Decode(it) } + val script = app.get(httpsify(srcrcp), referer = iframedoc).document.selectFirst("script:containsData(Playerjs)")?.data() + val video = script?.substringAfter("file:\"#2")?.substringBefore("\"")?.replace(Regex("(//\\S+?=)"), "")?.let { base64Decode(it) } - callback.invoke( - ExtractorLink( - "Vidsrc", - "Vidsrc", - video ?: return, - "https://vidsrc.stream/", - Qualities.P1080.value, - INFER_TYPE - ) - ) + callback.invoke(ExtractorLink("Vidsrc", "Vidsrc", video + ?: return, "https://vidsrc.stream/", Qualities.P1080.value, INFER_TYPE)) } - suspend fun invokeDbgo( - id: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeDbgo(id: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val iframeDbgo: String? val script = if (season == null) { val doc = app.get("$dbgoAPI/imdb.php?id=$id").document iframeDbgo = doc.select("div.myvideo iframe").attr("src") - app.get(iframeDbgo, referer = "$dbgoAPI/").document.select("script") - .find { it.data().contains("CDNplayerConfig =") }?.data() + app.get(iframeDbgo, referer = "$dbgoAPI/").document.select("script").find { it.data().contains("CDNplayerConfig =") }?.data() } else { val doc = app.get("$dbgoAPI/tv-imdb.php?id=$id&s=$season").document iframeDbgo = doc.select("div.myvideo iframe").attr("src") - val token = app.get( - iframeDbgo, referer = "$dbgoAPI/" - ).document.selectFirst("select#translator-name option")?.attr("data-token") - app.get("https://voidboost.net/serial/$token/iframe?s=$season&e=$episode&h=dbgo.fun").document.select( - "script" - ).find { it.data().contains("CDNplayerConfig =") }?.data() + val token = app.get(iframeDbgo, referer = "$dbgoAPI/").document.selectFirst("select#translator-name option")?.attr("data-token") + app.get("https://voidboost.net/serial/$token/iframe?s=$season&e=$episode&h=dbgo.fun").document.select("script").find { it.data().contains("CDNplayerConfig =") }?.data() } ?: return - val source = - Regex("['|\"]file['|\"]:\\s['|\"](#\\S+?)['|\"]").find(script)?.groupValues?.get( - 1 - ) ?: return - val subtitle = - Regex("['|\"]subtitle['|\"]:\\s['|\"](\\S+?)['|\"]").find(script)?.groupValues?.get( - 1 - ) + val source = Regex("['|\"]file['|\"]:\\s['|\"](#\\S+?)['|\"]").find(script)?.groupValues?.get(1) + ?: return + val subtitle = Regex("['|\"]subtitle['|\"]:\\s['|\"](\\S+?)['|\"]").find(script)?.groupValues?.get(1) val ref = getBaseUrl(iframeDbgo) decryptStreamUrl(source).split(",").map { links -> val quality = Regex("\\[(\\d*p.*?)]").find(links)?.groupValues?.getOrNull(1)?.trim() - ?: return@map null + ?: return@map null links.replace("[$quality]", "").split(" or ").map { it.trim() }.map { link -> val name = if (link.contains(".m3u8")) "Dbgo (Main)" else "Dbgo (Backup)" - callback.invoke( - ExtractorLink( - name, - name, - link, - "$ref/", - getQuality(quality), - isM3u8 = link.contains(".m3u8"), - headers = mapOf( - "Origin" to ref - ) - ) - ) + callback.invoke(ExtractorLink(name, name, link, "$ref/", getQuality(quality), isM3u8 = link.contains(".m3u8"), headers = mapOf("Origin" to ref))) } } subtitle?.split(",")?.map { sub -> val language = Regex("\\[(.*)]").find(sub)?.groupValues?.getOrNull(1) ?: return@map null val link = sub.replace("[$language]", "").trim() - subtitleCallback.invoke( - SubtitleFile( - getDbgoLanguage(language), link - ) - ) + subtitleCallback.invoke(SubtitleFile(getDbgoLanguage(language), link)) } } - suspend fun invokeDreamfilm( - title: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeDreamfilm(title: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val fixTitle = title.createSlug() val url = if (season == null) { "$dreamfilmAPI/$fixTitle" @@ -219,27 +136,13 @@ object SoraExtractor : SoraStream() { 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 - ) + 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 invokeMultimovies( - apiUrl: String, - title: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeMultimovies(apiUrl: String, title: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val fixTitle = title.createSlug() val url = if (season == null) { "$apiUrl/movies/$fixTitle" @@ -252,82 +155,47 @@ object SoraExtractor : SoraStream() { if (!iframe.contains("youtube")) { loadExtractor(iframe, "$directUrl/", subtitleCallback) { link -> if (link.quality == Qualities.Unknown.value) { - callback.invoke( - ExtractorLink( - link.source, - link.name, - link.url, - link.referer, - Qualities.P1080.value, - link.type, - link.headers, - link.extractorData - ) - ) + callback.invoke(ExtractorLink(link.source, link.name, link.url, link.referer, Qualities.P1080.value, link.type, link.headers, link.extractorData)) } } } } suspend fun invokeAoneroom( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, ) { - val headers = mapOf( - "Authorization" to "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjcyODc3MjQ5OTg4MzA0NzM5NzYsInV0cCI6MSwiZXhwIjoxNzEwMzg4NzczLCJpYXQiOjE3MDI2MTI3NzN9.Myt-gVHfPfQFbFyRX3WXtiiwvRzDwBrXTEKy1l-GDRU" - ) - val subjectId = app.post( - "$aoneroomAPI/wefeed-mobile-bff/subject-api/search", data = mapOf( + val headers = mapOf("Authorization" to "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjcyODc3MjQ5OTg4MzA0NzM5NzYsInV0cCI6MSwiZXhwIjoxNzEwMzg4NzczLCJpYXQiOjE3MDI2MTI3NzN9.Myt-gVHfPfQFbFyRX3WXtiiwvRzDwBrXTEKy1l-GDRU") + val subjectId = app.post("$aoneroomAPI/wefeed-mobile-bff/subject-api/search", data = mapOf( "page" to "1", "perPage" to "10", "keyword" to "$title", "subjectType" to if (season == null) "1" else "2", - ), headers = headers - ).parsedSafe()?.data?.items?.find { + ), headers = headers).parsedSafe()?.data?.items?.find { it.title.equals(title, true) && it.releaseDate?.substringBefore("-") == "$year" }?.subjectId - val data = app.get( - "$aoneroomAPI/wefeed-mobile-bff/subject-api/resource?subjectId=${subjectId ?: return}&page=1&perPage=20&all=0&startPosition=1&endPosition=1&pagerMode=0&resolution=480", - headers = headers - ).parsedSafe()?.data?.list?.findLast { + val data = app.get("$aoneroomAPI/wefeed-mobile-bff/subject-api/resource?subjectId=${subjectId ?: return}&page=1&perPage=20&all=0&startPosition=1&endPosition=1&pagerMode=0&resolution=480", headers = headers).parsedSafe()?.data?.list?.findLast { it.se == (season ?: 0) && it.ep == (episode ?: 0) } - callback.invoke( - ExtractorLink( - "Aoneroom", - "Aoneroom", - data?.resourceLink ?: return, - "", - data.resolution ?: Qualities.Unknown.value, - INFER_TYPE - ) - ) + callback.invoke(ExtractorLink("Aoneroom", "Aoneroom", data?.resourceLink + ?: return, "", data.resolution ?: Qualities.Unknown.value, INFER_TYPE)) data.extCaptions?.map { sub -> - subtitleCallback.invoke( - SubtitleFile( + subtitleCallback.invoke(SubtitleFile( sub.lanName ?: return@map, sub.url ?: return@map, - ) - ) + )) } } - suspend fun invokeWatchCartoon( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeWatchCartoon(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) { "$watchCartoonAPI/movies/$fixTitle-$year" @@ -341,39 +209,16 @@ object SoraExtractor : SoraStream() { val id = doc.select("link[rel=shortlink]").attr("href").substringAfterLast("=") doc.select("div.form-group.list-server option").apmap { - val server = app.get( - "$host/ajax-get-link-stream/?server=${it.attr("value")}&filmId=$id", - headers = mapOf( - "X-Requested-With" to "XMLHttpRequest" - ) - ).text + val server = app.get("$host/ajax-get-link-stream/?server=${it.attr("value")}&filmId=$id", headers = mapOf("X-Requested-With" to "XMLHttpRequest")).text loadExtractor(server, "$host/", subtitleCallback) { link -> if (link.quality == Qualities.Unknown.value) { - callback.invoke( - ExtractorLink( - "WatchCartoon", - "WatchCartoon", - link.url, - link.referer, - Qualities.P720.value, - link.type, - link.headers, - link.extractorData - ) - ) + callback.invoke(ExtractorLink("WatchCartoon", "WatchCartoon", link.url, link.referer, Qualities.P720.value, link.type, link.headers, link.extractorData)) } } } } - suspend fun invokeNetmovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + 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" @@ -383,14 +228,7 @@ object SoraExtractor : SoraStream() { invokeWpmovies(null, url, subtitleCallback, callback) } - suspend fun invokeZshow( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeZshow(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) { "$zshowAPI/movie/$fixTitle-$year" @@ -400,43 +238,45 @@ object SoraExtractor : SoraStream() { invokeWpmovies("ZShow", url, subtitleCallback, callback, encrypt = true) } + suspend fun invokeMMovies(title: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { + val fixTitle = title.createSlug() + val url = if (season == null) { + "$mMoviesAPI/movies/$fixTitle" + } else { + "$mMoviesAPI/episodes/$fixTitle-${season}x${episode}" + } + + invokeWpmovies(null, url, subtitleCallback, callback, true, hasCloudflare = true, interceptor = multiInterceptor) + } + private suspend fun invokeWpmovies( - name: String? = null, - url: String? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, - fixIframe: Boolean = false, - encrypt: Boolean = false, + name: String? = null, + url: String? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, + fixIframe: Boolean = false, + encrypt: Boolean = false, + hasCloudflare: Boolean = false, + interceptor: Interceptor? = null, ) { fun String.fixBloat(): String { return this.replace("\"", "").replace("\\", "") } - val res = app.get(url ?: return) + val res = app.get(url ?: return, interceptor = if (hasCloudflare) interceptor else null) val referer = getBaseUrl(res.url) val document = res.document document.select("ul#playeroptionsul > li").map { - Triple( - it.attr("data-post"), it.attr("data-nume"), it.attr("data-type") - ) + Triple(it.attr("data-post"), it.attr("data-nume"), it.attr("data-type")) }.apmap { (id, nume, type) -> delay(1000) - 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 = mapOf("Accept" to "*/*", "X-Requested-With" to "XMLHttpRequest"), - referer = url - ) + 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 = mapOf("Accept" to "*/*", "X-Requested-With" to "XMLHttpRequest"), referer = url, interceptor = if (hasCloudflare) interceptor else null) val source = tryParseJson(json.text)?.let { when { encrypt -> { val meta = tryParseJson(it.embed_url)?.meta ?: return@apmap val key = generateWpKey(it.key ?: return@apmap, meta) - cryptoAESHandler( - it.embed_url, key.toByteArray(), false - )?.fixBloat() + cryptoAESHandler(it.embed_url, key.toByteArray(), false)?.fixBloat() } fixIframe -> Jsoup.parse(it.embed_url).select("IFRAME").attr("SRC") @@ -451,38 +291,21 @@ object SoraExtractor : SoraStream() { } } - suspend fun invokeDoomovies( - title: String? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + 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) - } + 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 invokeNoverse( - title: String? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeNoverse(title: String? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit) { val fixTitle = title.createSlug() val url = if (season == null) { "$noverseAPI/movie/$fixTitle/download/" @@ -497,36 +320,27 @@ object SoraExtractor : SoraStream() { it.select("a").attr("href") to it.selectFirst("td")?.text() } } else { - doc.select("table.table-striped tbody tr") - .find { it.text().contains("Episode $episode") }?.select("td")?.map { - it.select("a").attr("href") to it.select("a").text() - } + doc.select("table.table-striped tbody tr").find { it.text().contains("Episode $episode") }?.select("td")?.map { + it.select("a").attr("href") to it.select("a").text() + } } ?: return delay(4000) links.map { (link, quality) -> - val name = - quality?.replace(Regex("\\d{3,4}p"), "Noverse")?.replace(".", " ") ?: "Noverse" - callback.invoke( - ExtractorLink( + val name = quality?.replace(Regex("\\d{3,4}p"), "Noverse")?.replace(".", " ") + ?: "Noverse" + callback.invoke(ExtractorLink( "Noverse", name, link, "", getQualityFromName("${quality?.substringBefore("p")?.trim()}p"), - ) - ) + )) } } - suspend fun invokeFilmxy( - imdbId: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeFilmxy(imdbId: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val url = if (season == null) { "${filmxyAPI}/movie/$imdbId" } else { @@ -536,18 +350,15 @@ object SoraExtractor : SoraStream() { val doc = app.get(url, cookies = filmxyCookies).document val script = doc.selectFirst("script:containsData(var isSingle)")?.data() ?: return - val sourcesData = - Regex("listSE\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1).let { - tryParseJson>>>(it) - } - val sourcesDetail = - Regex("linkDetails\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1).let { - tryParseJson>>(it) - } - val subSourcesData = - Regex("dSubtitles\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1).let { - tryParseJson>>>(it) - } + val sourcesData = Regex("listSE\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1).let { + tryParseJson>>>(it) + } + val sourcesDetail = Regex("linkDetails\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1).let { + tryParseJson>>(it) + } + val subSourcesData = Regex("dSubtitles\\s*=\\s?(.*?),[\\n|\\s]").find(script)?.groupValues?.get(1).let { + tryParseJson>>>(it) + } val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) @@ -562,34 +373,24 @@ object SoraExtractor : SoraStream() { subSourcesData?.get("s$seasonSlug")?.get("e$episodeSlug") } - val scriptUser = - doc.select("script").find { it.data().contains("var userNonce") }?.data() ?: return - val userNonce = - Regex("var\\suserNonce.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1) - val userId = - Regex("var\\suser_id.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1) + val scriptUser = doc.select("script").find { it.data().contains("var userNonce") }?.data() + ?: return + val userNonce = Regex("var\\suserNonce.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1) + val userId = Regex("var\\suser_id.*?[\"|'](\\S+?)[\"|'];").find(scriptUser)?.groupValues?.get(1) - val listSources = sources.withIndex() - .groupBy { it.index / 2 } - .map { entry -> entry.value.map { it.value } } + val listSources = sources.withIndex().groupBy { it.index / 2 }.map { entry -> entry.value.map { it.value } } listSources.apmap { src -> val linkIDs = src.joinToString("") { "&linkIDs%5B%5D=$it" }.replace("\"", "") - val json = app.post( - "$filmxyAPI/wp-admin/admin-ajax.php", - requestBody = "action=get_vid_links$linkIDs&user_id=$userId&nonce=$userNonce".toRequestBody(), - referer = url, - headers = mapOf( + val json = app.post("$filmxyAPI/wp-admin/admin-ajax.php", requestBody = "action=get_vid_links$linkIDs&user_id=$userId&nonce=$userNonce".toRequestBody(), referer = url, headers = mapOf( "Accept" to "*/*", "DNT" to "1", "Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8", "Origin" to filmxyAPI, "X-Requested-With" to "XMLHttpRequest", - ), - cookies = filmxyCookies - ).text.let { tryParseJson>(it) } + ), cookies = filmxyCookies).text.let { tryParseJson>(it) } src.map { source -> val link = json?.get(source) @@ -597,42 +398,22 @@ object SoraExtractor : SoraStream() { val server = sourcesDetail?.get(source)?.get("server") val size = sourcesDetail?.get(source)?.get("size") - callback.invoke( - ExtractorLink( - "Filmxy", - "Filmxy $server [$size]", - link ?: return@map, - "$filmxyAPI/", - getQualityFromName(quality) - ) - ) + callback.invoke(ExtractorLink("Filmxy", "Filmxy $server [$size]", link + ?: return@map, "$filmxyAPI/", getQualityFromName(quality))) } } subSources?.mapKeys { sub -> - subtitleCallback.invoke( - SubtitleFile( - SubtitleHelper.fromTwoLettersToLanguage(sub.key) ?: return@mapKeys, - "https://www.mysubs.org/get-subtitle/${sub.value}" - ) - ) + subtitleCallback.invoke(SubtitleFile(SubtitleHelper.fromTwoLettersToLanguage(sub.key) + ?: return@mapKeys, "https://www.mysubs.org/get-subtitle/${sub.value}")) } } - 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) + 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) + fun String.getTag(): String? = Regex("""\d{3,4}[pP]\s*(.*)""").find(this)?.groupValues?.getOrNull(1) val slug = title.createSlug() val epsSlug = getEpisodeSlug(season, episode) @@ -646,19 +427,18 @@ object SoraExtractor : SoraStream() { 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") - } + 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 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) @@ -667,74 +447,13 @@ object SoraExtractor : SoraStream() { servers.filter { it.first == "720p" || it.first == "1080p" }.apmap { val server = if (it.third.startsWith("https://ouo")) bypassOuo(it.third) else it.third - loadCustomTagExtractor( - it.second, - server ?: return@apmap, - "$dramadayAPI/", - subtitleCallback, - callback, - getQualityFromName(it.first) - ) + loadCustomTagExtractor(it.second, server + ?: return@apmap, "$dramadayAPI/", subtitleCallback, callback, getQualityFromName(it.first)) } } - suspend fun invokeWatchflx( - tmdbId: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { - val epsSlug = getEpisodeSlug(season, episode) - val cookies = getWatchflxCookies() - val url = if (season == null) { - "$watchflxAPI/browse/playmovie/$tmdbId/directplay" - } else { - "$watchflxAPI/Playseries/series/$tmdbId/directplay" - } - val res = app.get(url, cookies = cookies).document - - val showUrl = if (season == null) { - res.selectFirst("iframe.movie_player")?.attr("src") - } else { - val seasonUrl = - res.select("ul.nav.nav-tabs.tabs-left li:matches(Season $season\$) a").attr("href") - val episodeUrl = app.get( - seasonUrl, cookies = cookies - ).document.select("div.thumb-nail-list a:contains(${epsSlug.second}:)").attr("href") - app.get(episodeUrl, cookies = cookies).document.selectFirst("iframe.movie_player") - ?.attr("src") - } - val iframe = app.get( - showUrl ?: return, referer = "$watchflxAPI/" - ).document.selectFirst("div#the_frame iframe")?.attr("src") - ?.let { fixUrl(it, getBaseUrl(showUrl)) } ?: return - - val video = app.get(iframe.replace("/loc/", "/pro/"), referer = iframe).text.let { - """mp4_url\s*=\s*["'](.*)["'];""".toRegex().find(it)?.groupValues?.getOrNull(1) - } - - callback.invoke( - ExtractorLink( - "Watchflx", - "Watchflx", - video ?: return, - "$watchflxAPI/", - Qualities.P1080.value, - INFER_TYPE - ) - ) - - - } - - suspend fun invokeKimcartoon( - title: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeKimcartoon(title: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val fixTitle = title.createSlug() val doc = if (season == null || season == 1) { app.get("$kimcartoonAPI/Cartoon/$fixTitle").document @@ -750,9 +469,7 @@ object SoraExtractor : SoraStream() { it.attr("href").contains(Regex("(?i)Episode-0*$episode")) }?.attr("href") } ?: return - val servers = - app.get(fixUrl(iframe, kimcartoonAPI)).document.select("#selectServer > option") - .map { fixUrl(it.attr("value"), kimcartoonAPI) } + val servers = app.get(fixUrl(iframe, kimcartoonAPI)).document.select("#selectServer > option").map { fixUrl(it.attr("value"), kimcartoonAPI) } servers.apmap { app.get(it).document.select("#my_video_1").attr("src").let { iframe -> @@ -764,83 +481,53 @@ object SoraExtractor : SoraStream() { } suspend fun invokeDumpStream( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, ) { val (id, type) = getDumpIdAndType(title, year, season) val json = fetchDumpEpisodes("$id", "$type", episode) ?: return json.subtitlingList?.map { sub -> - subtitleCallback.invoke( - SubtitleFile( - getVipLanguage(sub.languageAbbr ?: return@map), sub.subtitlingUrl ?: return@map - ) - ) + subtitleCallback.invoke(SubtitleFile(getVipLanguage(sub.languageAbbr + ?: return@map), sub.subtitlingUrl ?: return@map)) } } - suspend fun invokeVidsrcto( - imdbId: String?, - season: Int?, - episode: Int?, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + 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 mediaId = - app.get(url).document.selectFirst("ul.episodes li a")?.attr("data-id") ?: return + val mediaId = app.get(url).document.selectFirst("ul.episodes li a")?.attr("data-id") + ?: return - app.get("$vidsrctoAPI/ajax/embed/episode/$mediaId/sources") - .parsedSafe()?.result?.apmap { - val encUrl = app.get("$vidsrctoAPI/ajax/embed/source/${it.id}") - .parsedSafe()?.result?.url - loadExtractor( - vidsrctoDecrypt(encUrl ?: return@apmap), - "$vidsrctoAPI/", - subtitleCallback, - callback - ) - } + app.get("$vidsrctoAPI/ajax/embed/episode/$mediaId/sources").parsedSafe()?.result?.apmap { + val encUrl = app.get("$vidsrctoAPI/ajax/embed/source/${it.id}").parsedSafe()?.result?.url + loadExtractor(vidsrctoDecrypt(encUrl + ?: return@apmap), "$vidsrctoAPI/", subtitleCallback, callback) + } val subtitles = app.get("$vidsrctoAPI/ajax/embed/episode/$mediaId/subtitles").text tryParseJson>(subtitles)?.map { - subtitleCallback.invoke( - SubtitleFile( - it.label ?: "", - it.file ?: return@map - ) - ) + subtitleCallback.invoke(SubtitleFile(it.label ?: "", it.file ?: return@map)) } } - suspend fun invokeKisskh( - title: String? = null, - season: Int? = null, - episode: Int? = null, - isAnime: Boolean = false, - lastSeason: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeKisskh(title: String? = null, season: Int? = null, episode: Int? = null, isAnime: Boolean = false, lastSeason: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val slug = title.createSlug() ?: return val type = when { isAnime -> "3" season == null -> "2" else -> "1" } - val res = app.get( - "$kissKhAPI/api/DramaList/Search?q=$title&type=$type", referer = "$kissKhAPI/" - ).text.let { + val res = app.get("$kissKhAPI/api/DramaList/Search?q=$title&type=$type", referer = "$kissKhAPI/").text.let { tryParseJson>(it) } ?: return @@ -852,20 +539,15 @@ object SoraExtractor : SoraStream() { when { season == null -> slugTitle == slug lastSeason == 1 -> slugTitle.contains(slug) - else -> (slugTitle.contains(slug) && it.title?.contains( - "Season $season", - true - ) == true) + else -> (slugTitle.contains(slug) && it.title?.contains("Season $season", true) == true) } } ?: res.find { it.title.equals(title) } data?.id to data?.title } - val resDetail = app.get( - "$kissKhAPI/api/DramaList/Drama/$id?isq=false", referer = "$kissKhAPI/Drama/${ - getKisskhTitle(contentTitle) - }?id=$id" - ).parsedSafe() ?: return + val resDetail = app.get("$kissKhAPI/api/DramaList/Drama/$id?isq=false", referer = "$kissKhAPI/Drama/${ + getKisskhTitle(contentTitle) + }?id=$id").parsedSafe() ?: return val epsId = if (season == null) { resDetail.episodes?.first()?.id @@ -873,80 +555,45 @@ object SoraExtractor : SoraStream() { resDetail.episodes?.find { it.number == episode }?.id } - app.get( - "$kissKhAPI/api/DramaList/Episode/$epsId.png?err=false&ts=&time=", - referer = "$kissKhAPI/Drama/${getKisskhTitle(contentTitle)}/Episode-${episode ?: 0}?id=$id&ep=$epsId&page=0&pageSize=100" - ).parsedSafe()?.let { source -> + app.get("$kissKhAPI/api/DramaList/Episode/$epsId.png?err=false&ts=&time=", referer = "$kissKhAPI/Drama/${getKisskhTitle(contentTitle)}/Episode-${episode ?: 0}?id=$id&ep=$epsId&page=0&pageSize=100").parsedSafe()?.let { source -> listOf(source.video, source.thirdParty).apmap { link -> if (link?.contains(".m3u8") == true) { - M3u8Helper.generateM3u8( - "Kisskh", link, "$kissKhAPI/", headers = mapOf("Origin" to kissKhAPI) - ).forEach(callback) + M3u8Helper.generateM3u8("Kisskh", link, "$kissKhAPI/", headers = mapOf("Origin" to kissKhAPI)).forEach(callback) } else { - loadExtractor( - link?.substringBefore("=http") ?: return@apmap null, - "$kissKhAPI/", - subtitleCallback, - callback - ) + loadExtractor(link?.substringBefore("=http") + ?: return@apmap null, "$kissKhAPI/", subtitleCallback, callback) } } } app.get("$kissKhAPI/api/Sub/$epsId").text.let { resSub -> tryParseJson>(resSub)?.map { sub -> - subtitleCallback.invoke( - SubtitleFile( - getLanguage(sub.label ?: return@map), sub.src ?: return@map - ) - ) + subtitleCallback.invoke(SubtitleFile(getLanguage(sub.label ?: return@map), sub.src + ?: return@map)) } } } - suspend fun invokeAnimes( - title: String? = null, - epsTitle: String? = null, - date: String?, - airedDate: String?, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeAnimes(title: String? = null, epsTitle: String? = null, date: String?, airedDate: String?, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { - val (aniId, malId) = convertTmdbToAnimeId( - title, date, airedDate, if (season == null) TvType.AnimeMovie else TvType.Anime - ) + val (aniId, malId) = convertTmdbToAnimeId(title, date, airedDate, if (season == null) TvType.AnimeMovie else TvType.Anime) argamap({ invokeAnimetosho(malId, season, episode, subtitleCallback, callback) }, { invokeAniwatch(malId, episode, subtitleCallback, callback) }, { - if (season != null) invokeCrunchyroll( - aniId, malId, epsTitle, season, episode, subtitleCallback, callback - ) + if (season != null) invokeCrunchyroll(aniId, malId, epsTitle, season, episode, subtitleCallback, callback) }) } - private suspend fun invokeAnimetosho( - malId: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + private suspend fun invokeAnimetosho(malId: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { 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()) - ) + Triple(it.attr("href"), ele.select("div.size").text(), getIndexQuality(ele.select("div.link a").text())) } } } @@ -954,80 +601,54 @@ object SoraExtractor : SoraStream() { 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 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() + 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 { - loadCustomTagExtractor( - it.second, it.first, "$animetoshoAPI/", subtitleCallback, callback, it.third - ) + loadCustomTagExtractor(it.second, it.first, "$animetoshoAPI/", subtitleCallback, callback, it.third) } } - private suspend fun invokeAniwatch( - malId: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + private suspend fun invokeAniwatch(malId: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val headers = mapOf( - "X-Requested-With" to "XMLHttpRequest", + "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 - ).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") + }?.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 - ).parsedSafe()?.html?.let { Jsoup.parse(it) } - ?.select("div.item.server-item")?.map { - Triple( + val servers = 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(), it.attr("data-id"), it.attr("data-type"), - ) - } + ) + } 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" loadCustomExtractor( - "${server.first} [$audio]", - iframe, - "$aniwatchAPI/", - subtitleCallback, - callback, + "${server.first} [$audio]", + iframe, + "$aniwatchAPI/", + subtitleCallback, + callback, ) } } } - suspend fun invokeLing( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeLing(title: String? = null, year: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val fixTitle = title?.replace("–", "-") val url = if (season == null) { "$lingAPI/en/videos/films/?title=$fixTitle" @@ -1037,9 +658,9 @@ object SoraExtractor : SoraStream() { val scriptData = app.get(url).document.select("div.blk.padding_b0 div.col-sm-30").map { Triple( - it.selectFirst("div.video-body h5")?.text(), - it.selectFirst("div.video-body > p")?.text(), - it.selectFirst("div.video-body a")?.attr("href"), + it.selectFirst("div.video-body h5")?.text(), + it.selectFirst("div.video-body > p")?.text(), + it.selectFirst("div.video-body a")?.attr("href"), ) } @@ -1047,9 +668,7 @@ object SoraExtractor : SoraStream() { scriptData.first() } else { scriptData.find { - it.first?.contains( - "$fixTitle", true - ) == true && it.second?.contains("$year") == true + it.first?.contains("$fixTitle", true) == true && it.second?.contains("$year") == true } } @@ -1057,36 +676,21 @@ object SoraExtractor : SoraStream() { val iframe = (if (season == null) { doc.selectFirst("a.video-js.vjs-default-skin")?.attr("data-href") } else { - doc.select("div.blk div#tab_$season li")[episode!!.minus(1)].select("h5 a") - .attr("data-href") + doc.select("div.blk div#tab_$season li")[episode!!.minus(1)].select("h5 a").attr("data-href") })?.let { fixUrl(it, lingAPI) } val source = app.get(iframe ?: return) val link = Regex("((https:|http:)//.*\\.mp4)").find(source.text)?.value ?: return - callback.invoke( - ExtractorLink( - "Ling", "Ling", "$link/index.m3u8", "$lingAPI/", Qualities.P720.value, INFER_TYPE - ) - ) + callback.invoke(ExtractorLink("Ling", "Ling", "$link/index.m3u8", "$lingAPI/", Qualities.P720.value, INFER_TYPE)) source.document.select("div#player-tracks track").map { - subtitleCallback.invoke( - SubtitleFile( - SubtitleHelper.fromTwoLettersToLanguage(it.attr("srclang")) ?: return@map null, - it.attr("src") - ) - ) + subtitleCallback.invoke(SubtitleFile(SubtitleHelper.fromTwoLettersToLanguage(it.attr("srclang")) + ?: return@map null, it.attr("src"))) } } - suspend fun invokeUhdmovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeUhdmovies(title: String? = null, year: Int? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit) { val fixTitle = title.createSlug() val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) @@ -1119,12 +723,10 @@ 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 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) + 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") @@ -1139,70 +741,20 @@ object SoraExtractor : SoraStream() { val tags = getUhdTags(quality) val qualities = getIndexQuality(quality) val size = getIndexSize(quality) - callback.invoke( - ExtractorLink( - "UHDMovies", - "UHDMovies $tags [$size]", - downloadLink ?: return@apmap, - "", - qualities - ) - ) + callback.invoke(ExtractorLink("UHDMovies", "UHDMovies $tags [$size]", downloadLink + ?: return@apmap, "", qualities)) } } - suspend fun invokeDotmovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - lastSeason: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - invokeWpredis( - title, - year, - season, - lastSeason, - episode, - subtitleCallback, - callback, - dotmoviesAPI - ) + suspend fun invokeDotmovies(title: String? = null, year: Int? = null, season: Int? = null, lastSeason: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { + invokeWpredis(title, year, season, lastSeason, episode, subtitleCallback, callback, dotmoviesAPI) } - suspend fun invokeVegamovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - lastSeason: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - invokeWpredis( - title, - year, - season, - lastSeason, - episode, - subtitleCallback, - callback, - vegaMoviesAPI - ) + suspend fun invokeVegamovies(title: String? = null, year: Int? = null, season: Int? = null, lastSeason: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { + invokeWpredis(title, year, season, lastSeason, episode, subtitleCallback, callback, vegaMoviesAPI) } - private suspend fun invokeWpredis( - title: String? = null, - year: Int? = null, - season: Int? = null, - lastSeason: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, - api: String - ) { + private suspend fun invokeWpredis(title: String? = null, year: Int? = null, season: Int? = null, lastSeason: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, api: String) { val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) var res = app.get("$api/search/$title").document val match = when (season) { @@ -1210,68 +762,42 @@ object SoraExtractor : SoraStream() { 1 -> "Season 1" else -> "Season 1 – $lastSeason" } - val media = - res.selectFirst("div.blog-items article:has(h3.entry-title:matches((?i)$title.*$match)) a") - ?.attr("href") + val media = res.selectFirst("div.blog-items article:has(h3.entry-title:matches((?i)$title.*$match)) a")?.attr("href") res = app.get(media ?: return).document val hTag = if (season == null) "h5" else "h3" val aTag = if (season == null) "Download Now" else "V-Cloud" val sTag = if (season == null) "" else "(Season $season|S$seasonSlug)" - val entry = res.select("div.entry-content > $hTag:matches((?i)$sTag.*(1080p|2160p))") - .findLast { element -> !element.text().contains("Download", true) } ?: return - val tags = - """(?:1080p|2160p)(.*)""".toRegex().find(entry.text())?.groupValues?.get(1)?.trim() - val href = - entry.nextElementSibling()?.select("a:contains($aTag)")?.attr("href") - val selector = - if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)" - val server = app.get( - href ?: return, interceptor = wpredisInterceptor - ).document.selectFirst("div.entry-content > $selector") - ?.attr("href") ?: return + val entry = res.select("div.entry-content > $hTag:matches((?i)$sTag.*(1080p|2160p))").findLast { element -> !element.text().contains("Download", true) } + ?: return + val tags = """(?:1080p|2160p)(.*)""".toRegex().find(entry.text())?.groupValues?.get(1)?.trim() + val href = entry.nextElementSibling()?.select("a:contains($aTag)")?.attr("href") + val selector = if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)" + val server = app.get(href + ?: return, interceptor = wpredisInterceptor).document.selectFirst("div.entry-content > $selector")?.attr("href") + ?: return - loadCustomTagExtractor( - tags, - server, - "$api/", - subtitleCallback, - callback, - getIndexQuality(entry.text()) - ) + loadCustomTagExtractor(tags, server, "$api/", subtitleCallback, callback, getIndexQuality(entry.text())) } - suspend fun invokeHdmovies4u( - title: String? = null, - imdbId: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeHdmovies4u(title: String? = null, imdbId: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { fun String.decodeLink(): String { return base64Decode(this.substringAfterLast("/")) } val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) - val media = - app.get("$hdmovies4uAPI/?s=${if (season == null) imdbId else title}").document.let { - val selector = - if (season == null) "a" else "a:matches((?i)$title.*Season $season)" - it.selectFirst("div.gridxw.gridxe $selector")?.attr("href") - } + val media = app.get("$hdmovies4uAPI/?s=${if (season == null) imdbId else title}").document.let { + val selector = if (season == null) "a" else "a:matches((?i)$title.*Season $season)" + it.selectFirst("div.gridxw.gridxe $selector")?.attr("href") + } val selector = if (season == null) "1080p|2160p" else "(?i)Episode.*(?:1080p|2160p)" - app.get( - media ?: return - ).document.select("section h4:matches($selector)").apmap { ele -> + app.get(media ?: return).document.select("section h4:matches($selector)").apmap { ele -> val (tags, size) = ele.select("span").map { it.text() }.let { it[it.lastIndex - 1] to it.last().substringAfter("-").trim() } val link = ele.nextElementSibling()?.select("a:contains(DriveTOT)")?.attr("href") val iframe = bypassBqrecipes(link?.decodeLink() ?: return@apmap).let { if (it?.contains("/pack/") == true) { - val href = - app.get(it).document.select("table tbody tr:contains(S${seasonSlug}E${episodeSlug}) a") - .attr("href") + val href = app.get(it).document.select("table tbody tr:contains(S${seasonSlug}E${episodeSlug}) a").attr("href") bypassBqrecipes(href.decodeLink()) } else { it @@ -1281,14 +807,7 @@ object SoraExtractor : SoraStream() { } } - suspend fun invokeGMovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeGMovies(title: String? = null, year: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val fixTitle = title.createSlug() val url = if (season == null || season == 1) { "$gMoviesAPI/$fixTitle-$year" @@ -1304,8 +823,7 @@ object SoraExtractor : SoraStream() { } } else { doc.select("div.is-content-justification-center").find { - it.previousElementSibling()?.text() - ?.contains(Regex("(?i)episode\\s?$episode")) == true + it.previousElementSibling()?.text()?.contains(Regex("(?i)episode\\s?$episode")) == true }?.select("div.wp-block-button")?.map { it.select("a").attr("href") to it.text() } @@ -1315,23 +833,11 @@ object SoraExtractor : SoraStream() { iframe.apmap { (iframeLink, title) -> val size = Regex("(?i)\\s(\\S+gb|mb)").find(title)?.groupValues?.getOrNull(1) - loadCustomTagExtractor( - "[$size]", - iframeLink, - "$gMoviesAPI/", - subtitleCallback, - callback, - getIndexQuality(title) - ) + loadCustomTagExtractor("[$size]", iframeLink, "$gMoviesAPI/", subtitleCallback, callback, getIndexQuality(title)) } } - suspend fun invokeFDMovies( - title: String? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeFDMovies(title: String? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit) { val fixTitle = title.createSlug() val url = if (season == null) { "$fdMoviesAPI/movies/$fixTitle" @@ -1343,12 +849,7 @@ object SoraExtractor : SoraStream() { if (!request.isSuccessful) return val iframe = request.document.select("div#download tbody tr").map { - FDMovieIFrame( - it.select("a").attr("href"), - it.select("strong.quality").text(), - it.select("td:nth-child(4)").text(), - it.select("img").attr("src") - ) + FDMovieIFrame(it.select("a").attr("href"), it.select("strong.quality").text(), it.select("td:nth-child(4)").text(), it.select("img").attr("src")) }.filter { it.quality.contains(Regex("(?i)(1080p|4k)")) && it.type.contains(Regex("(gdtot|oiya|rarbgx)")) } @@ -1376,46 +877,26 @@ object SoraExtractor : SoraStream() { } } - callback.invoke( - ExtractorLink( - "FDMovies", - "FDMovies [$size]", - videoLink ?: return@apmap null, - "", - getQualityFromName(qualities) - ) - ) + callback.invoke(ExtractorLink("FDMovies", "FDMovies [$size]", videoLink + ?: return@apmap null, "", getQualityFromName(qualities))) } } - suspend fun invokeM4uhd( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeM4uhd(title: String? = null, year: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val slugTitle = title.createSlug() val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) val req = app.get("$m4uhdAPI/search/$slugTitle.html") val referer = getBaseUrl(req.url) val scriptData = req.document.select("div.row div.item").map { ele -> - Triple( - ele.select("div.tiptitle p").text().substringBefore("(").trim().createSlug(), - ele.select("div.jtip-top div:last-child").text().filter { it.isDigit() }, - ele.selectFirst("a")?.attr("href") - ) + Triple(ele.select("div.tiptitle p").text().substringBefore("(").trim().createSlug(), ele.select("div.jtip-top div:last-child").text().filter { it.isDigit() }, ele.selectFirst("a")?.attr("href")) } val script = if (scriptData.size == 1) { scriptData.firstOrNull() } else { scriptData.find { - it.first.equals(slugTitle) && it.second == "$year" && if (season != null) it.third?.contains( - "-tvshow-" - ) == true else it.third?.contains("-movie-") == true + it.first.equals(slugTitle) && it.second == "$year" && if (season != null) it.third?.contains("-tvshow-") == true else it.third?.contains("-movie-") == true } } @@ -1429,28 +910,20 @@ object SoraExtractor : SoraStream() { val m4uData = if (season == null) { doc.select("div.le-server span").map { it.attr("data") } } else { - val idepisode = - doc.selectFirst("div.detail > p:matches((?i)S$seasonSlug-E$episodeSlug) button") - ?.attr("idepisode") + val idepisode = doc.selectFirst("div.detail > p:matches((?i)S$seasonSlug-E$episodeSlug) button")?.attr("idepisode") ?: return - val requestEmbed = app.post( - "$referer/ajaxtv", data = mapOf( - "idepisode" to idepisode, "_token" to "$token" - ), referer = link, headers = headers, cookies = cookies - ) + val requestEmbed = app.post("$referer/ajaxtv", data = mapOf("idepisode" to idepisode, "_token" to "$token"), referer = link, headers = headers, cookies = cookies) cookies = requestEmbed.cookies requestEmbed.document.select("div.le-server span").map { it.attr("data") } } m4uData.apmap { data -> val iframe = app.post( - "$referer/ajax", - data = mapOf( - "m4u" to data, "_token" to "$token" - ), - referer = link, - headers = headers, - cookies = cookies, + "$referer/ajax", + data = mapOf("m4u" to data, "_token" to "$token"), + referer = link, + headers = headers, + cookies = cookies, ).document.select("iframe").attr("src") loadExtractor(iframe, referer, subtitleCallback, callback) @@ -1458,12 +931,7 @@ object SoraExtractor : SoraStream() { } - suspend fun invokeTvMovies( - title: String? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeTvMovies(title: String? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit) { val fixTitle = title.createSlug() val url = if (season == null) { "$tvMoviesAPI/show/$fixTitle" @@ -1473,43 +941,25 @@ object SoraExtractor : SoraStream() { val server = getTvMoviesServer(url, season, episode) ?: return val videoData = extractCovyn(server.second ?: return) - val quality = - Regex("(\\d{3,4})p").find(server.first)?.groupValues?.getOrNull(1)?.toIntOrNull() + val quality = Regex("(\\d{3,4})p").find(server.first)?.groupValues?.getOrNull(1)?.toIntOrNull() - callback.invoke( - ExtractorLink( - "TVMovies", - "TVMovies [${videoData?.second}]", - videoData?.first ?: return, - "", - quality ?: Qualities.Unknown.value - ) - ) + callback.invoke(ExtractorLink("TVMovies", "TVMovies [${videoData?.second}]", videoData?.first + ?: return, "", quality ?: Qualities.Unknown.value)) } - private suspend fun invokeCrunchyroll( - aniId: Int? = null, - malId: Int? = null, - epsTitle: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + private suspend fun invokeCrunchyroll(aniId: Int? = null, malId: Int? = null, epsTitle: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val id = getCrunchyrollId("${aniId ?: return}") - ?: getCrunchyrollIdFromMalSync("${malId ?: return}") + ?: getCrunchyrollIdFromMalSync("${malId ?: return}") val audioLocal = listOf( - "ja-JP", - "en-US", - "zh-CN", + "ja-JP", + "en-US", + "zh-CN", ) val token = getCrunchyrollToken() val headers = mapOf("Authorization" to "${token.tokenType} ${token.accessToken}") - val seasonIdData = app.get( - "$crunchyrollAPI/content/v2/cms/series/${id ?: return}/seasons", headers = headers - ).parsedSafe()?.data?.let { s -> + val seasonIdData = app.get("$crunchyrollAPI/content/v2/cms/series/${id ?: return}/seasons", headers = headers).parsedSafe()?.data?.let { s -> if (s.size == 1) { s.firstOrNull() } else { @@ -1522,82 +972,41 @@ object SoraExtractor : SoraStream() { } ?: s.find { it.season_number?.plus(1) == season } } } - val seasonId = seasonIdData?.versions?.filter { it.audio_locale in audioLocal } - ?.map { it.guid to it.audio_locale } ?: listOf(seasonIdData?.id to "ja-JP") + val seasonId = seasonIdData?.versions?.filter { it.audio_locale in audioLocal }?.map { it.guid to it.audio_locale } + ?: listOf(seasonIdData?.id to "ja-JP") seasonId.apmap { (sId, audioL) -> - val streamsLink = app.get( - "$crunchyrollAPI/content/v2/cms/seasons/${sId ?: return@apmap}/episodes", - headers = headers - ).parsedSafe()?.data?.find { - it.title.equals(epsTitle, true) || it.slug_title.equals( - epsTitle.createSlug(), true - ) || it.episode_number == episode + val streamsLink = app.get("$crunchyrollAPI/content/v2/cms/seasons/${sId ?: return@apmap}/episodes", headers = headers).parsedSafe()?.data?.find { + it.title.equals(epsTitle, true) || it.slug_title.equals(epsTitle.createSlug(), true) || it.episode_number == episode }?.streams_link?.substringAfter("/videos/")?.substringBefore("/streams") ?: return@apmap - val sources = app.get( - "$crunchyrollAPI/cms/v2${token.bucket}/videos/$streamsLink/streams?Policy=${token.policy}&Signature=${token.signature}&Key-Pair-Id=${token.key_pair_id}", - headers = headers - ).parsedSafe() + val sources = app.get("$crunchyrollAPI/cms/v2${token.bucket}/videos/$streamsLink/streams?Policy=${token.policy}&Signature=${token.signature}&Key-Pair-Id=${token.key_pair_id}", headers = headers).parsedSafe() - listOf( - "adaptive_hls", "vo_adaptive_hls" - ).map { hls -> + listOf("adaptive_hls", "vo_adaptive_hls").map { hls -> val name = if (hls == "adaptive_hls") "Crunchyroll" else "Vrv" val audio = if (audioL == "en-US") "English Dub" else "Raw" val source = sources?.streams?.let { if (hls == "adaptive_hls") it.adaptive_hls else it.vo_adaptive_hls } - M3u8Helper.generateM3u8( - "$name [$audio]", - source?.get("")?.get("url") ?: return@map, - "https://static.crunchyroll.com/" - ).forEach(callback) + M3u8Helper.generateM3u8("$name [$audio]", source?.get("")?.get("url") + ?: return@map, "https://static.crunchyroll.com/").forEach(callback) } sources?.subtitles?.map { sub -> - subtitleCallback.invoke( - SubtitleFile( - "${fixCrunchyrollLang(sub.key) ?: sub.key} [ass]", - sub.value["url"] ?: return@map null - ) - ) + subtitleCallback.invoke(SubtitleFile("${fixCrunchyrollLang(sub.key) ?: sub.key} [ass]", sub.value["url"] + ?: return@map null)) } } } - suspend fun invokeMoviezAdd( - apiUrl: String? = null, - api: String? = null, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeMoviezAdd(apiUrl: String? = null, api: String? = null, title: String? = null, year: Int? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit) { invokeBloginguru(apiUrl, api, title, year, season, episode, callback) } - suspend fun invokeBollyMaza( - apiUrl: String? = null, - api: String? = null, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeBollyMaza(apiUrl: String? = null, api: String? = null, title: String? = null, year: Int? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit) { invokeBloginguru(apiUrl, api, title, year, season, episode, callback) } - private suspend fun invokeBloginguru( - apiUrl: String? = null, - api: String? = null, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { + private suspend fun invokeBloginguru(apiUrl: String? = null, api: String? = null, title: String? = null, year: Int? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit) { val fixTitle = title?.createSlug()?.replace("-", " ") val doc = app.get("$apiUrl/?s=$fixTitle").document @@ -1611,97 +1020,55 @@ object SoraExtractor : SoraStream() { } } - val mediaLink = - app.get(matchMedia?.first ?: return).document.selectFirst("a#jake1")?.attr("href") + val mediaLink = app.get(matchMedia?.first + ?: return).document.selectFirst("a#jake1")?.attr("href") val detailDoc = app.get(mediaLink ?: return).document - val media = detailDoc.selectFirst("div.entry-content pre span")?.text() - ?.split("|") - ?.map { it.trim() } + val media = detailDoc.selectFirst("div.entry-content pre span")?.text()?.split("|")?.map { it.trim() } val iframe = (if (season == null) { media?.mapIndexed { index, name -> - detailDoc.select("div.entry-content > h2")[index].selectFirst("a") - ?.attr("href") to name + detailDoc.select("div.entry-content > h2")[index].selectFirst("a")?.attr("href") to name } } else { media?.mapIndexed { index, name -> - val linkMedia = - detailDoc.select("div.entry-content > h2")[index].selectFirst("a") - ?.attr("href") - app.get( - linkMedia ?: return@mapIndexed null - ).document.selectFirst("div.entry-content strong:matches((?i)S0?${season}E0?${episode}) a") - ?.attr("href") to name + val linkMedia = detailDoc.select("div.entry-content > h2")[index].selectFirst("a")?.attr("href") + app.get(linkMedia + ?: return@mapIndexed null).document.selectFirst("div.entry-content strong:matches((?i)S0?${season}E0?${episode}) a")?.attr("href") to name } })?.filter { it?.first?.startsWith("http") == true } iframe?.apmap { val iframeDoc = app.get(it?.first ?: return@apmap).document val formUrl = iframeDoc.select("form").attr("action") - val formData = - iframeDoc.select("form button").associate { v -> v.attr("name") to v.attr("value") } + val formData = iframeDoc.select("form button").associate { v -> v.attr("name") to v.attr("value") } - val videoUrl = app.post( - formUrl, - data = formData, - referer = it.first - ).document.selectFirst("div.d-flex.justify-content-center.flex-wrap a")?.attr("href") - val quality = - Regex("(\\d{3,4})p").find(it.second)?.groupValues?.getOrNull(1)?.toIntOrNull() + val videoUrl = app.post(formUrl, data = formData, referer = it.first).document.selectFirst("div.d-flex.justify-content-center.flex-wrap a")?.attr("href") + val quality = Regex("(\\d{3,4})p").find(it.second)?.groupValues?.getOrNull(1)?.toIntOrNull() val qualityName = it.second.replace("${quality}p", "").trim() - callback.invoke( - ExtractorLink( - "$api", - "$api $qualityName", - videoUrl ?: return@apmap, - "", - quality ?: Qualities.Unknown.value - ) - ) + callback.invoke(ExtractorLink("$api", "$api $qualityName", videoUrl + ?: return@apmap, "", quality ?: Qualities.Unknown.value)) } } - suspend fun invokeRStream( - id: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeRStream(id: Int? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit) { val url = if (season == null) { "$rStreamAPI/e/?tmdb=$id" } else { "$rStreamAPI/e/?tmdb=$id&s=$season&e=$episode" } - val res = app.get( - "$url&apikey=whXgvN4kVyoubGwqXpw26Oy3PVryl8dm", - referer = "https://watcha.movie/" - ).text + val res = app.get("$url&apikey=whXgvN4kVyoubGwqXpw26Oy3PVryl8dm", referer = "https://watcha.movie/").text val link = Regex("\"file\":\"(http.*?)\"").find(res)?.groupValues?.getOrNull(1) ?: return - callback.invoke( - ExtractorLink( - "RStream", "RStream", link, "$rStreamAPI/", Qualities.P1080.value, INFER_TYPE - ) - ) + callback.invoke(ExtractorLink("RStream", "RStream", link, "$rStreamAPI/", Qualities.P1080.value, INFER_TYPE)) } - suspend fun invokeFlixon( - tmdbId: Int? = null, - imdbId: String? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - onionUrl: String = "https://onionplay.se/" - ) { + suspend fun invokeFlixon(tmdbId: Int? = null, imdbId: String? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit, onionUrl: String = "https://onionplay.se/") { val request = if (season == null) { val res = app.get("$flixonAPI/$imdbId", referer = onionUrl) - if (res.text.contains("BEGIN PGP SIGNED MESSAGE")) app.get( - "$flixonAPI/$imdbId-1", - referer = onionUrl - ) else res + if (res.text.contains("BEGIN PGP SIGNED MESSAGE")) app.get("$flixonAPI/$imdbId-1", referer = onionUrl) else res } else { app.get("$flixonAPI/$tmdbId-$season-$episode", referer = onionUrl) } @@ -1709,44 +1076,30 @@ object SoraExtractor : SoraStream() { val script = request.document.selectFirst("script:containsData(= \"\";)")?.data() val collection = script?.substringAfter("= [")?.substringBefore("];") val num = script?.substringAfterLast("(value) -")?.substringBefore(");")?.trim()?.toInt() - ?: return + ?: return val iframe = collection?.split(",")?.map { it.trim().toInt() }?.map { nums -> nums.minus(num).toChar() - }?.joinToString("")?.let { Jsoup.parse(it) }?.selectFirst("button.redirect") - ?.attr("onclick")?.substringAfter("('")?.substringBefore("')") + }?.joinToString("")?.let { Jsoup.parse(it) }?.selectFirst("button.redirect")?.attr("onclick")?.substringAfter("('")?.substringBefore("')") delay(1000) - val unPacker = app.get( - iframe ?: return, referer = "$flixonAPI/" - ).document.selectFirst("script:containsData(JuicyCodes.Run)")?.data() - ?.substringAfter("JuicyCodes.Run(")?.substringBefore(");")?.split("+") - ?.joinToString("") { it.replace("\"", "").trim() } - ?.let { getAndUnpack(base64Decode(it)) } + val unPacker = app.get(iframe + ?: return, referer = "$flixonAPI/").document.selectFirst("script:containsData(JuicyCodes.Run)")?.data()?.substringAfter("JuicyCodes.Run(")?.substringBefore(");")?.split("+")?.joinToString("") { it.replace("\"", "").trim() }?.let { getAndUnpack(base64Decode(it)) } - val link = Regex("[\"']file[\"']:[\"'](.+?)[\"'],").find( - unPacker ?: return - )?.groupValues?.getOrNull(1) + val link = Regex("[\"']file[\"']:[\"'](.+?)[\"'],").find(unPacker + ?: return)?.groupValues?.getOrNull(1) - callback.invoke( - ExtractorLink( - "Flixon", - "Flixon", - link ?: return, - "https://onionplay.stream/", - Qualities.P720.value, - link.contains(".m3u8") - ) - ) + callback.invoke(ExtractorLink("Flixon", "Flixon", link + ?: return, "https://onionplay.stream/", Qualities.P720.value, link.contains(".m3u8"))) } suspend fun invokeSmashyStream( - imdbId: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, + imdbId: String? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, ) { val url = if (season == null) { "$smashyStreamAPI/playere.php?imdb=$imdbId" @@ -1754,9 +1107,7 @@ object SoraExtractor : SoraStream() { "$smashyStreamAPI/playere.php?imdb=$imdbId&season=$season&episode=$episode" } - app.get( - url, referer = "https://smashystream.com/" - ).document.select("div#_default-servers a.server").map { + app.get(url, referer = "https://smashystream.com/").document.select("div#_default-servers a.server").map { it.attr("data-url") to it.text() }.apmap { when (it.second) { @@ -1776,21 +1127,13 @@ object SoraExtractor : SoraStream() { //TODO only subs suspend fun invokeWatchsomuch( - imdbId: String? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, + imdbId: String? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, ) { val id = imdbId?.removePrefix("tt") - val epsId = app.post( - "$watchSomuchAPI/Watch/ajMovieTorrents.aspx", data = mapOf( - "index" to "0", - "mid" to "$id", - "wsk" to "f6ea6cde-e42b-4c26-98d3-b4fe48cdd4fb", - "lid" to "", - "liu" to "" - ), headers = mapOf("X-Requested-With" to "XMLHttpRequest") - ).parsedSafe()?.movie?.torrents?.let { eps -> + val epsId = app.post("$watchSomuchAPI/Watch/ajMovieTorrents.aspx", data = mapOf("index" to "0", "mid" to "$id", "wsk" to "f6ea6cde-e42b-4c26-98d3-b4fe48cdd4fb", "lid" to "", "liu" to ""), headers = mapOf("X-Requested-With" to "XMLHttpRequest")).parsedSafe()?.movie?.torrents?.let { eps -> if (season == null) { eps.firstOrNull()?.id } else { @@ -1807,191 +1150,145 @@ object SoraExtractor : SoraStream() { } app.get(subUrl).parsedSafe()?.subtitles?.map { sub -> - subtitleCallback.invoke( - SubtitleFile( - sub.label ?: "", fixUrl(sub.url ?: return@map null, watchSomuchAPI) - ) - ) + subtitleCallback.invoke(SubtitleFile(sub.label ?: "", fixUrl(sub.url + ?: return@map null, watchSomuchAPI))) } } suspend fun invokeShinobiMovies( - apiUrl: String, - api: String, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, + 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, + apiUrl, + api, + title, + year, + season, + episode, + callback, ) } private suspend fun invokeIndex( - apiUrl: String, - api: String, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - password: String = "", + apiUrl: String, + api: String, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, + password: String = "", ) { - val passHeaders = mapOf( - "Authorization" to password - ) + val passHeaders = mapOf("Authorization" to password) val query = getIndexQuery(title, year, season, episode).let { if (api in mkvIndex) "$it mkv" else it } - val body = - """{"q":"$query","password":null,"page_token":null,"page_index":0}""".toRequestBody( - RequestBodyTypes.JSON.toMediaTypeOrNull() - ) - val data = mapOf( - "q" to query, "page_token" to "", "page_index" to "0" - ) + val body = """{"q":"$query","password":null,"page_token":null,"page_index":0}""".toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) + val data = mapOf("q" to query, "page_token" to "", "page_index" to "0") val search = if (api in encodedIndex) { - decodeIndexJson( - if (api in lockedIndex) app.post( - "${apiUrl}search", - data = data, - headers = passHeaders, - referer = apiUrl, - timeout = 120L - ).text else app.post( - "${apiUrl}search", data = data, referer = apiUrl - ).text - ) + decodeIndexJson(if (api in lockedIndex) app.post("${apiUrl}search", data = data, headers = passHeaders, referer = apiUrl, timeout = 120L).text else app.post("${apiUrl}search", data = data, referer = apiUrl).text) } else { app.post("${apiUrl}search", requestBody = body, referer = apiUrl, timeout = 120L).text } - val media = if (api in untrimmedIndex) searchIndex( - title, season, episode, year, search, false - ) else searchIndex(title, season, episode, year, search) + val media = if (api in untrimmedIndex) searchIndex(title, season, episode, year, search, false) else searchIndex(title, season, episode, year, search) media?.apmap { file -> - val pathBody = """{"id":"${file.id ?: return@apmap null}"}""".toRequestBody( - RequestBodyTypes.JSON.toMediaTypeOrNull() - ) + val pathBody = """{"id":"${file.id ?: return@apmap null}"}""".toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) val pathData = mapOf( - "id" to file.id, + "id" to file.id, ) val path = (if (api in encodedIndex) { if (api in lockedIndex) { - app.post( - "${apiUrl}id2path", - data = pathData, - headers = passHeaders, - referer = apiUrl, - timeout = 120L - ) + app.post("${apiUrl}id2path", data = pathData, headers = passHeaders, referer = apiUrl, timeout = 120L) } else { - app.post( - "${apiUrl}id2path", data = pathData, referer = apiUrl, timeout = 120L - ) + app.post("${apiUrl}id2path", data = pathData, referer = apiUrl, timeout = 120L) } } else { - app.post( - "${apiUrl}id2path", requestBody = pathBody, referer = apiUrl, timeout = 120L - ) + 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 "", - timeout = 120L - ).document.selectFirst("script:containsData(downloaddomain)")?.data() - ?.substringAfter("\"downloaddomain\":\"")?.substringBefore("\",")?.let { - "$it/0:" - } + val worker = app.get("${fixUrl(path, apiUrl).encodeUrl()}?a=view", referer = if (api in needRefererIndex) apiUrl else "", timeout = 120L).document.selectFirst("script:containsData(downloaddomain)")?.data()?.substringAfter("\"downloaddomain\":\"")?.substringBefore("\",")?.let { + "$it/0:" + } fixUrl(path, worker ?: return@apmap null) } else { fixUrl(path, apiUrl) } }.encodeUrl() - val size = - "%.2f GB".format(bytesToGigaBytes(file.size?.toDouble() ?: return@apmap null)) + val size = "%.2f GB".format(bytesToGigaBytes(file.size?.toDouble() + ?: return@apmap null)) val quality = getIndexQuality(file.name) val tags = getIndexQualityTags(file.name) - callback.invoke( - ExtractorLink( + callback.invoke(ExtractorLink( api, "$api $tags [$size]", path, if (api in needRefererIndex) apiUrl else "", quality, - ) - ) + )) } } suspend fun invokeGdbotMovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, ) { val query = getIndexQuery(title, null, season, episode) val files = app.get("$gdbot/search?q=$query").document.select("ul.divide-y li").map { - Triple( - it.select("a").attr("href"), it.select("a").text(), it.select("span").text() - ) + Triple(it.select("a").attr("href"), it.select("a").text(), it.select("span").text()) }.filter { matchingIndex( - it.second, - null, - title, - year, - season, - episode, + it.second, + null, + title, + year, + season, + episode, ) }.sortedByDescending { it.third.getFileSize() } files.let { file -> - listOfNotNull(file.find { it.second.contains("2160p", true) }, - file.find { it.second.contains("1080p", true) }) + listOfNotNull(file.find { it.second.contains("2160p", true) }, file.find { it.second.contains("1080p", true) }) }.apmap { file -> val videoUrl = extractGdflix(file.first) val quality = getIndexQuality(file.second) val tags = getIndexQualityTags(file.second) val size = Regex("(\\d+\\.?\\d+\\sGB|MB)").find(file.third)?.groupValues?.get(0)?.trim() - callback.invoke( - ExtractorLink( + callback.invoke(ExtractorLink( "GdbotMovies", "GdbotMovies $tags [$size]", videoUrl ?: return@apmap null, "", quality, - ) - ) + )) } } suspend fun invokeDahmerMovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, ) { val url = if (season == null) { "$dahmerMoviesAPI/movies/${title?.replace(":", "")} ($year)/" @@ -2015,35 +1312,27 @@ object SoraExtractor : SoraStream() { paths.map { val quality = getIndexQuality(it.first) val tags = getIndexQualityTags(it.first) - callback.invoke( - ExtractorLink( + callback.invoke(ExtractorLink( "DahmerMovies", "DahmerMovies $tags", (url + it.second).encodeUrl(), "", quality, - ) - ) + )) } } - suspend fun invoke2embed( - imdbId: String?, - season: Int?, - episode: Int?, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invoke2embed(imdbId: String?, season: Int?, episode: Int?, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val url = if (season == null) { "$twoEmbedAPI/embed/$imdbId" } else { "$twoEmbedAPI/embedtv/$imdbId&s=$season&e=$episode" } - val framesrc = - app.get(url).document.selectFirst("iframe#iframesrc")?.attr("data-src") ?: return + val framesrc = app.get(url).document.selectFirst("iframe#iframesrc")?.attr("data-src") + ?: return val ref = getBaseUrl(framesrc) val id = framesrc.substringAfter("id=").substringBefore("&") loadExtractor("https://wishfast.top/e/$id", "$ref/", subtitleCallback, callback) @@ -2051,35 +1340,25 @@ object SoraExtractor : SoraStream() { } suspend fun invokeOmovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, ) { - invokeGpress( - title, - year, - season, - episode, - callback, - BuildConfig.OMOVIES_API, - "Omovies", - base64Decode("X3NtUWFtQlFzRVRi"), - base64Decode("X3NCV2NxYlRCTWFU") - ) + invokeGpress(title, year, season, episode, callback, BuildConfig.OMOVIES_API, "Omovies", base64Decode("X3NtUWFtQlFzRVRi"), base64Decode("X3NCV2NxYlRCTWFU")) } private suspend fun invokeGpress( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - api: String, - name: String, - mediaSelector: String, - episodeSelector: String, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, + api: String, + name: String, + mediaSelector: String, + episodeSelector: String, ) { fun String.decrypt(key: String): List? { return tryParseJson>(base64Decode(this).decodePrimewireXor(key)) @@ -2092,23 +1371,19 @@ object SoraExtractor : SoraStream() { "$title Season $season" } val savedCookies = mapOf( - base64Decode("X2lkZW50aXR5Z29tb3ZpZXM3") to base64Decode("NTJmZGM3MGIwMDhjMGIxZDg4MWRhYzBmMDFjY2E4MTllZGQ1MTJkZTAxY2M4YmJjMTIyNGVkNGFhZmI3OGI1MmElM0EyJTNBJTdCaSUzQTAlM0JzJTNBMTglM0ElMjJfaWRlbnRpdHlnb21vdmllczclMjIlM0JpJTNBMSUzQnMlM0E1MiUzQSUyMiU1QjIwNTAzNjYlMkMlMjJIblZSUkFPYlRBU09KRXI0NVl5Q004d2lIb2wwVjFrbyUyMiUyQzI1OTIwMDAlNUQlMjIlM0IlN0Q="), + base64Decode("X2lkZW50aXR5Z29tb3ZpZXM3") to base64Decode("NTJmZGM3MGIwMDhjMGIxZDg4MWRhYzBmMDFjY2E4MTllZGQ1MTJkZTAxY2M4YmJjMTIyNGVkNGFhZmI3OGI1MmElM0EyJTNBJTdCaSUzQTAlM0JzJTNBMTglM0ElMjJfaWRlbnRpdHlnb21vdmllczclMjIlM0JpJTNBMSUzQnMlM0E1MiUzQSUyMiU1QjIwNTAzNjYlMkMlMjJIblZSUkFPYlRBU09KRXI0NVl5Q004d2lIb2wwVjFrbyUyMiUyQzI1OTIwMDAlNUQlMjIlM0IlN0Q="), ) val req = app.get("$api/search/$query") val doc = req.document val media = doc.select("div.$mediaSelector").map { - Triple( - it.attr("data-filmName"), it.attr("data-year"), it.select("a").attr("href") - ) + Triple(it.attr("data-filmName"), it.attr("data-year"), it.select("a").attr("href")) }.let { el -> if (el.size == 1) { el.firstOrNull() } else { el.find { if (season == null) { - (it.first.equals(title, true) || it.first.equals( - "$title ($year)", true - )) && it.second.equals("$year") + (it.first.equals(title, true) || it.first.equals("$title ($year)", true)) && it.second.equals("$year") } else { it.first.equals("$title - Season $season", true) } @@ -2119,21 +1394,14 @@ object SoraExtractor : SoraStream() { val iframe = if (season == null) { media.third } else { - val res = app.get( - fixUrl( - media.third, - api - ) - ) - res.document.selectFirst("div#$episodeSelector a:contains(Episode ${slug.second})") - ?.attr("href") + val res = app.get(fixUrl(media.third, api)) + res.document.selectFirst("div#$episodeSelector a:contains(Episode ${slug.second})")?.attr("href") } ?: return val users = if (season == null) { media.third.substringAfterLast("/") to "0" } else { - media.third.substringAfterLast("/") to iframe.substringAfterLast("/") - .substringBefore("-") + media.third.substringAfterLast("/") to iframe.substringAfterLast("/").substringBefore("-") } val res = app.get(fixUrl(iframe, api), verify = false) delay(2000) @@ -2144,33 +1412,23 @@ object SoraExtractor : SoraStream() { 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) - val serverRes = app.get( - "$api/user/servers/${users.first}?ep=${users.second}", - cookies = cookies, referer = url, headers = headers - ) + val serverRes = app.get("$api/user/servers/${users.first}?ep=${users.second}", cookies = cookies, referer = url, headers = headers) 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( - "${fixUrl(serverUrl, api)}?server=$server&_=$unixTimeMS", - cookies = cookies, - referer = url, - headers = headers - ).text + val encryptedData = app.get("${fixUrl(serverUrl, api)}?server=$server&_=$unixTimeMS", cookies = cookies, referer = url, headers = headers).text val links = encryptedData.decrypt(key) ?: encryptedData.decrypt(key2) ?: return@amap links.forEach { video -> qualities.filter { it <= video.max.toInt() }.forEach { - callback( - ExtractorLink( + callback(ExtractorLink( name, name, video.src.split("360", limit = 3).joinToString(it.toString()), "$api/", it, - ) - ) + )) } } } @@ -2178,12 +1436,12 @@ object SoraExtractor : SoraStream() { } suspend fun invokeShowflix( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, ) { val where = if (season == null) "movieName" else "seriesName" val classes = if (season == null) "movies" else "series" @@ -2204,31 +1462,24 @@ object SoraExtractor : SoraStream() { } """.trimIndent().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) - val data = - app.post("https://parse.showflix.tk/parse/classes/$classes", requestBody = body).text + val data = app.post("https://parse.showflix.tk/parse/classes/$classes", requestBody = body).text val iframes = if (season == null) { val result = tryParseJson(data)?.resultsMovies?.find { - it.movieName.equals( - "$title ($year)", - true - ) + it.movieName.equals("$title ($year)", true) } listOf( - "https://streamwish.to/e/${result?.streamwish}", - "https://filelions.to/v/${result?.filelions}.html", - "https://streamruby.com/e/${result?.streamruby}.html", + "https://streamwish.to/e/${result?.streamwish}", + "https://filelions.to/v/${result?.filelions}.html", + "https://streamruby.com/e/${result?.streamruby}.html", ) } else { val result = tryParseJson(data)?.resultsSeries?.find { - it.seriesName.equals( - title, - true - ) + it.seriesName.equals(title, true) } listOf( - result?.streamwish?.get("Season $season")?.get(episode!!), - result?.filelions?.get("Season $season")?.get(episode!!), - result?.streamruby?.get("Season $season")?.get(episode!!), + result?.streamwish?.get("Season $season")?.get(episode!!), + result?.filelions?.get("Season $season")?.get(episode!!), + result?.streamruby?.get("Season $season")?.get(episode!!), ) } @@ -2239,13 +1490,13 @@ object SoraExtractor : SoraStream() { } suspend fun invokeCinemaTv( - imdbId: String? = null, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, + imdbId: String? = null, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, ) { val id = imdbId?.removePrefix("tt") val slug = title.createSlug() @@ -2255,12 +1506,11 @@ object SoraExtractor : SoraStream() { "$cinemaTvAPI/shows/play/$id-$slug-$year" } - val session = - "PHPSESSID=ngr4cudjrimdnhkth30ssohs0n; _csrf=a6ffd7bb7654083fce6df528225a238d0e85aa1fb885dc7638c1259ec1ba0d5ca%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22mTTLiDLjxohs-CpKk0bjRH3HdYMB9uBV%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0" + val session = "PHPSESSID=ngr4cudjrimdnhkth30ssohs0n; _csrf=a6ffd7bb7654083fce6df528225a238d0e85aa1fb885dc7638c1259ec1ba0d5ca%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22mTTLiDLjxohs-CpKk0bjRH3HdYMB9uBV%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0" val headers = mapOf( - "Cookie" to session, - "x-requested-with" to "com.wwcinematv", + "Cookie" to session, + "x-requested-with" to "com.wwcinematv", ) val doc = app.get(url, headers = headers).document @@ -2279,213 +1529,81 @@ object SoraExtractor : SoraStream() { "$cinemaTvAPI/api/v1/security/episode-access?id_episode=$episodeId&hash=$hash&expires=$expires" } - val sources = app.get( - videoUrl, - referer = url, - headers = mapOf("X-Requested-With" to "XMLHttpRequest") - ).parsedSafe() + val sources = app.get(videoUrl, referer = url, headers = mapOf("X-Requested-With" to "XMLHttpRequest")).parsedSafe() sources?.streams?.mapKeys { source -> - callback.invoke( - ExtractorLink( - "CinemaTv", - "CinemaTv", - source.value, - "$cinemaTvAPI/", - getQualityFromName(source.key), - true - ) - ) + callback.invoke(ExtractorLink("CinemaTv", "CinemaTv", source.value, "$cinemaTvAPI/", getQualityFromName(source.key), true)) } sources?.subtitles?.map { sub -> val file = sub.file.toString() - subtitleCallback.invoke( - SubtitleFile( + subtitleCallback.invoke(SubtitleFile( sub.language ?: return@map, if (file.startsWith("[")) return@map else fixUrl(file, cinemaTvAPI), - ) - ) + )) } } - suspend fun invokeFebbox( - title: String? = null, - year: Int? = null, - season: Int? = null, - lastSeason: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - showboxApi: String = "https://www.showbox.media" - ) { - val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) - val res = app.get("$showboxApi/search?keyword=$title", interceptor = showboxInterceptor).document - val mediaRes = res.select("div.film_list-wrap div.flw-item").map { - ShowboxMedia( - it.select("h2.film-name a").attr("href"), - it.select("h2.film-name a").text(), - it.select("div.fd-infor > span:first-child").text(), - it.select("div.fd-infor > span:last-child").text(), - ) - } - - val filter = mediaRes.filter { - it.title.equals(title, true) && it.type == if (season == null) "Movie" else "TV" - } - - val media = if (season == null) { - filter.find { it.infor == "$year" } - } else { - filter.find { it.infor == "SS $lastSeason" } - ?: filter.find { it.infor == "SS ${lastSeason?.minus(1)}" } - ?: filter.find { it.infor == "SS 1" } - } - - val shareId = media?.url?.substringAfterLast("/") ?: return - - val shareKey = - app.get("$showboxApi/index/share_link?id=${shareId}&type=${if (season == null) "1" else "2"}", interceptor = showboxInterceptor) - .parsedSafe()?.data?.link?.substringAfterLast("/") - - val headers = mapOf("Accept-Language" to "en") - val shareRes = app.get( - "$febboxAPI/file/file_share_list?share_key=${shareKey ?: return}", - headers = headers - ) - .parsedSafe()?.data - - val fids = if (season == null) { - shareRes?.file_list - } else { - val parentId = - shareRes?.file_list?.find { it.file_name.equals("season $season", true) }?.fid - app.get( - "$febboxAPI/file/file_share_list?share_key=${shareKey}&parent_id=$parentId&page=1", - headers = headers - ) - .parsedSafe()?.data?.file_list?.filter { - it.file_name?.contains( - "s${seasonSlug}e${episodeSlug}", - true - ) == true - } - } - - fids?.mapIndexed { index, fileList -> - callback.invoke( - ExtractorLink( - "Febbox", - "Febbox [Server ${index + 1}]", - "$febboxAPI/hls/main/${fileList.oss_fid}.m3u8", - "", - getIndexQuality(fileList.file_name), - isM3u8 = true - ) - ) - } - - } - - suspend fun invokeNinetv( - tmdbId: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { + suspend fun invokeNinetv(tmdbId: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { val url = if (season == null) { "$nineTvAPI/movie/$tmdbId" } else { "$nineTvAPI/tv/$tmdbId-$season-$episode" } - val iframe = app.get(url, referer = "https://pressplay.top/").document.selectFirst("iframe") - ?.attr("src") + val iframe = app.get(url, referer = "https://pressplay.top/").document.selectFirst("iframe")?.attr("src") loadExtractor(iframe ?: return, "$nineTvAPI/", subtitleCallback, callback) } - suspend fun invokeNowTv( - tmdbId: Int? = null, - imdbId: String? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - referer: String = "https://bflix.gs/" - ) { + suspend fun invokeNowTv(tmdbId: Int? = null, imdbId: String? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit, referer: String = "https://bflix.gs/") { val slug = getEpisodeSlug(season, episode) - var url = - if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" + var url = if (season == null) "$nowTvAPI/$tmdbId.mp4" else "$nowTvAPI/tv/$tmdbId/s${season}e${slug.second}.mp4" if (!app.get(url, referer = referer).isSuccessful) { - url = - if (season == null) "$nowTvAPI/$imdbId.mp4" else "$nowTvAPI/tv/$imdbId/s${season}e${slug.second}.mp4" + url = if (season == null) "$nowTvAPI/$imdbId.mp4" else "$nowTvAPI/tv/$imdbId/s${season}e${slug.second}.mp4" if (!app.get(url, referer = referer).isSuccessful) return } - callback.invoke( - ExtractorLink( + callback.invoke(ExtractorLink( "NowTv", "NowTv", url, referer, Qualities.P1080.value, - ) - ) + )) } suspend fun invokeRidomovies( - tmdbId: Int? = null, - imdbId: String? = null, - callback: (ExtractorLink) -> Unit, + tmdbId: Int? = null, + imdbId: String? = null, + callback: (ExtractorLink) -> Unit, ) { - val slug = app.get("$ridomoviesAPI/core/api/search?q=$imdbId") - .parsedSafe()?.data?.items?.find { - it.contentable?.tmdbId == tmdbId || it.contentable?.imdbId == imdbId - }?.slug ?: return - app.get("$ridomoviesAPI/core/api/movies/$slug/videos") - .parsedSafe()?.data?.apmap { link -> - val iframe = Jsoup.parse(link.url ?: return@apmap).select("iframe").attr("data-src") - val unpacked = - getAndUnpack( - app.get( - iframe, - referer = "$ridomoviesAPI/" - ).text - ) - val video = Regex("=\"(aHR.*?)\";").find(unpacked)?.groupValues?.get(1) - callback.invoke( - ExtractorLink( - "Ridomovies", - "Ridomovies", - base64Decode(video ?: return@apmap), - "${getBaseUrl(iframe)}/", - Qualities.P1080.value, - isM3u8 = true - ) - ) - } + val slug = app.get("$ridomoviesAPI/core/api/search?q=$imdbId").parsedSafe()?.data?.items?.find { + it.contentable?.tmdbId == tmdbId || it.contentable?.imdbId == imdbId + }?.slug ?: return + app.get("$ridomoviesAPI/core/api/movies/$slug/videos").parsedSafe()?.data?.apmap { link -> + val iframe = Jsoup.parse(link.url ?: return@apmap).select("iframe").attr("data-src") + val unpacked = getAndUnpack(app.get(iframe, referer = "$ridomoviesAPI/").text) + val video = Regex("=\"(aHR.*?)\";").find(unpacked)?.groupValues?.get(1) + callback.invoke(ExtractorLink("Ridomovies", "Ridomovies", base64Decode(video + ?: return@apmap), "${getBaseUrl(iframe)}/", Qualities.P1080.value, isM3u8 = true)) + } } suspend fun invokeAllMovieland( - imdbId: String? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, - host: String = "https://esh-bostewsom-i-273.site", + imdbId: String? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, + host: String = "https://esh-bostewsom-i-273.site", ) { - val res = app.get( - "$host/play/$imdbId", referer = "$allmovielandAPI/" - ).document.selectFirst("script:containsData(player =)")?.data()?.substringAfter("{") - ?.substringBefore(";")?.substringBefore(")") + val res = app.get("$host/play/$imdbId", referer = "$allmovielandAPI/").document.selectFirst("script:containsData(player =)")?.data()?.substringAfter("{")?.substringBefore(";")?.substringBefore(")") val json = tryParseJson("{${res ?: return}") - val headers = mapOf( - "X-CSRF-TOKEN" to "${json?.key}" - ) + val headers = mapOf("X-CSRF-TOKEN" to "${json?.key}") - val serverRes = app.get( - fixUrl(json?.file ?: return, host), headers = headers, referer = "$allmovielandAPI/" - ).text.replace(Regex(""",\s*\[]"""), "") + val serverRes = app.get(fixUrl(json?.file + ?: return, host), headers = headers, referer = "$allmovielandAPI/").text.replace(Regex(""",\s*\[]"""), "") val servers = tryParseJson>(serverRes).let { server -> if (season == null) { server?.map { it.file to it.title } @@ -2497,25 +1615,19 @@ object SoraExtractor : SoraStream() { } servers?.apmap { (server, lang) -> - val path = app.post( - "${host}/playlist/${server ?: return@apmap}.txt", headers = headers, referer = "$allmovielandAPI/" - ).text - M3u8Helper.generateM3u8( - "Allmovieland [$lang]", - path, - "$allmovielandAPI/" - ).forEach(callback) + val path = app.post("${host}/playlist/${server ?: return@apmap}.txt", headers = headers, referer = "$allmovielandAPI/").text + M3u8Helper.generateM3u8("Allmovieland [$lang]", path, "$allmovielandAPI/").forEach(callback) } } suspend fun invokeEmovies( - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit, ) { val slug = title.createSlug() val url = if (season == null) { @@ -2531,22 +1643,16 @@ object SoraExtractor : SoraStream() { res.selectFirst("select#selectServer option[sv=oserver]")?.attr("value") } else { res.select("div.le-server a").find { - val num = - Regex("Episode (\\d+)").find(it.text())?.groupValues?.get(1)?.toIntOrNull() + val num = Regex("Episode (\\d+)").find(it.text())?.groupValues?.get(1)?.toIntOrNull() num == episode }?.attr("href") })?.substringAfter("id=")?.substringBefore("&") - val server = app.get( - "$emoviesAPI/ajax/v4_get_sources?s=oserver&id=${id ?: return}&_=${unixTimeMS}", - headers = mapOf( - "X-Requested-With" to "XMLHttpRequest" - ) - ).parsedSafe()?.value + val server = app.get("$emoviesAPI/ajax/v4_get_sources?s=oserver&id=${id ?: return}&_=${unixTimeMS}", headers = mapOf("X-Requested-With" to "XMLHttpRequest")).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]") } @@ -2555,59 +1661,39 @@ object SoraExtractor : SoraStream() { } sources?.map { source -> - M3u8Helper.generateM3u8( - "Emovies", source.file ?: return@map, "https://embed.vodstream.xyz/" - ).forEach(callback) + M3u8Helper.generateM3u8("Emovies", source.file + ?: return@map, "https://embed.vodstream.xyz/").forEach(callback) } tracks?.map { track -> - subtitleCallback.invoke( - SubtitleFile( + subtitleCallback.invoke(SubtitleFile( track.label ?: "", track.file ?: return@map, - ) - ) + )) } } suspend fun invokeSFMovies( - tmdbId: Int? = null, - title: String? = null, - year: Int? = null, - season: Int? = null, - episode: Int? = null, - callback: (ExtractorLink) -> Unit, + tmdbId: Int? = null, + title: String? = null, + year: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit, ) { - val headers = - mapOf("Authorization" to "Bearer 44d784c55e9a1e3dbb586f24b18b1cbcd1521673bd6178ef385890d2f989681fe22d05e291e2e0f03fce99cbc50cd520219e52cc6e30c944a559daf53a129af18349ec98f6a0e4e66b8d370a354f4f7fbd49df0ab806d533a3db71eecc7f75131a59ce8cffc5e0cc38e8af5919c23c0d904fbe31995308f065f0ff9cd1eda488") - val data = app.get( - "${BuildConfig.SFMOVIES_API}/api/mains?filters[title][\$contains]=$title", - headers = headers - ) - .parsedSafe()?.data + val headers = mapOf("Authorization" to "Bearer 44d784c55e9a1e3dbb586f24b18b1cbcd1521673bd6178ef385890d2f989681fe22d05e291e2e0f03fce99cbc50cd520219e52cc6e30c944a559daf53a129af18349ec98f6a0e4e66b8d370a354f4f7fbd49df0ab806d533a3db71eecc7f75131a59ce8cffc5e0cc38e8af5919c23c0d904fbe31995308f065f0ff9cd1eda488") + val data = app.get("${BuildConfig.SFMOVIES_API}/api/mains?filters[title][\$contains]=$title", headers = headers).parsedSafe()?.data val media = data?.find { - it.attributes?.contentId.equals("$tmdbId") || (it.attributes?.title.equals( - title, - true - ) || it.attributes?.releaseDate?.substringBefore("-").equals("$year")) + it.attributes?.contentId.equals("$tmdbId") || (it.attributes?.title.equals(title, true) || it.attributes?.releaseDate?.substringBefore("-").equals("$year")) } val video = if (season == null || episode == null) { media?.attributes?.video } else { media?.attributes?.seriess?.get(season - 1)?.get(episode - 1)?.svideos } ?: return - callback.invoke( - ExtractorLink( - "SFMovies", - "SFMovies", - fixUrl(video, getSfServer()), - "", - Qualities.P1080.value, - INFER_TYPE - ) - ) + callback.invoke(ExtractorLink("SFMovies", "SFMovies", fixUrl(video, getSfServer()), "", Qualities.P1080.value, INFER_TYPE)) } } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index 03eafa4c..c4378663 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -11,209 +11,185 @@ data class CrunchyrollAccessToken( val key_pair_id: String? = null, ) -data class ShowboxMedia( - val url: String, - val title: String, - val infor: String, - val type: String, -) data class FDMovieIFrame( - val link: String, - val quality: String, - val size: String, - val type: String, + val link: String, + val quality: String, + val size: String, + val type: String, ) -data class AniIds( - var id: Int? = null, - var idMal: Int? = null -) +data class AniIds(var id: Int? = null, var idMal: Int? = null) data class TmdbDate( - val today: String, - val nextWeek: String, + val today: String, + val nextWeek: String, ) -data class AniMedia( - @JsonProperty("id") var id: Int? = null, - @JsonProperty("idMal") var idMal: Int? = null -) +data class AniMedia(@JsonProperty("id") var id: Int? = null, @JsonProperty("idMal") var idMal: Int? = null) -data class AniPage( - @JsonProperty("media") var media: java.util.ArrayList = arrayListOf() -) +data class AniPage(@JsonProperty("media") var media: java.util.ArrayList = arrayListOf()) -data class AniData( - @JsonProperty("Page") var Page: AniPage? = AniPage() -) +data class AniData(@JsonProperty("Page") var Page: AniPage? = AniPage()) -data class AniSearch( - @JsonProperty("data") var data: AniData? = AniData() -) +data class AniSearch(@JsonProperty("data") var data: AniData? = AniData()) data class GpressSources( - @JsonProperty("src") val src: String, - @JsonProperty("file") val file: String? = null, - @JsonProperty("label") val label: Int? = null, - @JsonProperty("max") val max: String, + @JsonProperty("src") val src: String, + @JsonProperty("file") val file: String? = null, + @JsonProperty("label") val label: Int? = null, + @JsonProperty("max") val max: String, ) data class UHDBackupUrl( - @JsonProperty("url") val url: String? = null, + @JsonProperty("url") val url: String? = null, ) data class ResponseHash( - @JsonProperty("embed_url") val embed_url: String, - @JsonProperty("key") val key: String? = null, - @JsonProperty("type") val type: String? = null, + @JsonProperty("embed_url") val embed_url: String, + @JsonProperty("key") val key: String? = null, + @JsonProperty("type") val type: String? = null, ) data class KisskhSources( - @JsonProperty("Video") val video: String?, - @JsonProperty("ThirdParty") val thirdParty: String?, + @JsonProperty("Video") val video: String?, + @JsonProperty("ThirdParty") val thirdParty: String?, ) data class KisskhSubtitle( - @JsonProperty("src") val src: String?, - @JsonProperty("label") val label: String?, + @JsonProperty("src") val src: String?, + @JsonProperty("label") val label: String?, ) data class KisskhEpisodes( - @JsonProperty("id") val id: Int?, - @JsonProperty("number") val number: Int?, + @JsonProperty("id") val id: Int?, + @JsonProperty("number") val number: Int?, ) data class KisskhDetail( - @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), + @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), ) data class KisskhResults( - @JsonProperty("id") val id: Int?, - @JsonProperty("title") val title: String?, + @JsonProperty("id") val id: Int?, + @JsonProperty("title") val title: String?, ) data class DriveBotLink( - @JsonProperty("url") val url: String? = null, + @JsonProperty("url") val url: String? = null, ) data class DirectDl( - @JsonProperty("download_url") val download_url: String? = null, + @JsonProperty("download_url") val download_url: String? = null, ) data class Safelink( - @JsonProperty("safelink") val safelink: String? = null, + @JsonProperty("safelink") val safelink: String? = null, ) data class FDAds( - @JsonProperty("linkr") val linkr: String? = null, + @JsonProperty("linkr") val linkr: String? = null, ) data class ZShowEmbed( - @JsonProperty("m") val meta: String? = null, + @JsonProperty("m") val meta: String? = null, ) data class WatchsomuchTorrents( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("movieId") val movieId: Int? = null, - @JsonProperty("season") val season: Int? = null, - @JsonProperty("episode") val episode: Int? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("movieId") val movieId: Int? = null, + @JsonProperty("season") val season: Int? = null, + @JsonProperty("episode") val episode: Int? = null, ) data class WatchsomuchMovies( - @JsonProperty("torrents") val torrents: ArrayList? = arrayListOf(), + @JsonProperty("torrents") val torrents: ArrayList? = arrayListOf(), ) data class WatchsomuchResponses( - @JsonProperty("movie") val movie: WatchsomuchMovies? = null, + @JsonProperty("movie") val movie: WatchsomuchMovies? = null, ) data class WatchsomuchSubtitles( - @JsonProperty("url") val url: String? = null, - @JsonProperty("label") val label: String? = null, + @JsonProperty("url") val url: String? = null, + @JsonProperty("label") val label: String? = null, ) data class WatchsomuchSubResponses( - @JsonProperty("subtitles") val subtitles: ArrayList? = arrayListOf(), + @JsonProperty("subtitles") val subtitles: ArrayList? = arrayListOf(), ) data class IndexMedia( - @JsonProperty("id") val id: String? = null, - @JsonProperty("driveId") val driveId: String? = null, - @JsonProperty("mimeType") val mimeType: String? = null, - @JsonProperty("size") val size: String? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("modifiedTime") val modifiedTime: String? = null, + @JsonProperty("id") val id: String? = null, + @JsonProperty("driveId") val driveId: String? = null, + @JsonProperty("mimeType") val mimeType: String? = null, + @JsonProperty("size") val size: String? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("modifiedTime") val modifiedTime: String? = null, ) data class IndexData( - @JsonProperty("files") val files: ArrayList? = arrayListOf(), + @JsonProperty("files") val files: ArrayList? = arrayListOf(), ) data class IndexSearch( - @JsonProperty("data") val data: IndexData? = null, + @JsonProperty("data") val data: IndexData? = null, ) data class JikanExternal( - @JsonProperty("name") val name: String? = null, - @JsonProperty("url") val url: String? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("url") val url: String? = null, ) data class JikanData( - @JsonProperty("title") val title: String? = null, - @JsonProperty("external") val external: ArrayList? = arrayListOf(), + @JsonProperty("title") val title: String? = null, + @JsonProperty("external") val external: ArrayList? = arrayListOf(), ) data class JikanResponse( - @JsonProperty("data") val data: JikanData? = null, + @JsonProperty("data") val data: JikanData? = null, ) data class CinemaTvSubtitles( - @JsonProperty("language") val language: String? = null, - @JsonProperty("file") val file: Any? = null, + @JsonProperty("language") val language: String? = null, + @JsonProperty("file") val file: Any? = null, ) data class CinemaTvResponse( - @JsonProperty("streams") val streams: HashMap? = null, - @JsonProperty("subtitles") val subtitles: ArrayList? = arrayListOf(), + @JsonProperty("streams") val streams: HashMap? = null, + @JsonProperty("subtitles") val subtitles: ArrayList? = arrayListOf(), ) data class VidsrctoResult( - @JsonProperty("id") val id: String? = null, - @JsonProperty("title") val title: String? = null, - @JsonProperty("url") val url: String? = null, + @JsonProperty("id") val id: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("url") val url: String? = null, ) data class VidsrctoResponse( - @JsonProperty("result") val result: VidsrctoResult? = null, + @JsonProperty("result") val result: VidsrctoResult? = null, ) data class VidsrctoSources( - @JsonProperty("result") val result: ArrayList? = arrayListOf(), + @JsonProperty("result") val result: ArrayList? = arrayListOf(), ) data class VidsrctoSubtitles( - @JsonProperty("label") val label: String? = null, - @JsonProperty("file") val file: String? = null, + @JsonProperty("label") val label: String? = null, + @JsonProperty("file") val file: String? = null, ) data class AnilistExternalLinks( - @JsonProperty("id") var id: Int? = null, - @JsonProperty("site") var site: String? = null, - @JsonProperty("url") var url: String? = null, - @JsonProperty("type") var type: String? = null, + @JsonProperty("id") var id: Int? = null, + @JsonProperty("site") var site: String? = null, + @JsonProperty("url") var url: String? = null, + @JsonProperty("type") var type: String? = null, ) -data class AnilistMedia( - @JsonProperty("externalLinks") var externalLinks: ArrayList = arrayListOf() -) +data class AnilistMedia(@JsonProperty("externalLinks") var externalLinks: ArrayList = arrayListOf()) -data class AnilistData( - @JsonProperty("Media") var Media: AnilistMedia? = AnilistMedia() -) +data class AnilistData(@JsonProperty("Media") var Media: AnilistMedia? = AnilistMedia()) -data class AnilistResponses( - @JsonProperty("data") var data: AnilistData? = AnilistData() -) +data class AnilistResponses(@JsonProperty("data") var data: AnilistData? = AnilistData()) data class CrunchyrollToken( @JsonProperty("access_token") val accessToken: String? = null, @@ -229,22 +205,22 @@ data class CrunchyrollToken( } data class CrunchyrollVersions( - @JsonProperty("audio_locale") val audio_locale: String? = null, - @JsonProperty("guid") val guid: String? = null, + @JsonProperty("audio_locale") val audio_locale: String? = null, + @JsonProperty("guid") val guid: String? = null, ) data class CrunchyrollData( - @JsonProperty("id") val id: String? = null, - @JsonProperty("title") val title: String? = null, - @JsonProperty("slug_title") val slug_title: String? = null, - @JsonProperty("season_number") val season_number: Int? = null, - @JsonProperty("episode_number") val episode_number: Int? = null, - @JsonProperty("versions") val versions: ArrayList? = null, - @JsonProperty("streams_link") val streams_link: String? = null, + @JsonProperty("id") val id: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("slug_title") val slug_title: String? = null, + @JsonProperty("season_number") val season_number: Int? = null, + @JsonProperty("episode_number") val episode_number: Int? = null, + @JsonProperty("versions") val versions: ArrayList? = null, + @JsonProperty("streams_link") val streams_link: String? = null, ) data class CrunchyrollResponses( - @JsonProperty("data") val data: ArrayList? = arrayListOf(), + @JsonProperty("data") val data: ArrayList? = arrayListOf(), ) data class CrunchyrollSourcesResponses( @@ -258,34 +234,34 @@ data class CrunchyrollSourcesResponses( } data class MALSyncSites( - @JsonProperty("Zoro") val zoro: HashMap>? = hashMapOf(), + @JsonProperty("Zoro") val zoro: HashMap>? = hashMapOf(), ) data class MALSyncResponses( - @JsonProperty("Sites") val sites: MALSyncSites? = null, + @JsonProperty("Sites") val sites: MALSyncSites? = null, ) data class AniwatchResponses( - @JsonProperty("html") val html: String? = null, - @JsonProperty("link") val link: String? = null, + @JsonProperty("html") val html: String? = null, + @JsonProperty("link") val link: String? = null, ) data class MalSyncRes( - @JsonProperty("Sites") val Sites: Map>>? = null, + @JsonProperty("Sites") val Sites: Map>>? = null, ) data class GokuData( - @JsonProperty("link") val link: String? = null, + @JsonProperty("link") val link: String? = null, ) data class GokuServer( - @JsonProperty("data") val data: GokuData? = GokuData(), + @JsonProperty("data") val data: GokuData? = GokuData(), ) data class AllMovielandEpisodeFolder( - @JsonProperty("title") val title: String? = null, - @JsonProperty("id") val id: String? = null, - @JsonProperty("file") val file: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("id") val id: String? = null, + @JsonProperty("file") val file: String? = null, ) data class AllMovielandSeasonFolder( @@ -302,177 +278,159 @@ data class AllMovielandServer( ) data class AllMovielandPlaylist( - @JsonProperty("file") val file: String? = null, - @JsonProperty("key") val key: String? = null, - @JsonProperty("href") val href: String? = null, + @JsonProperty("file") val file: String? = null, + @JsonProperty("key") val key: String? = null, + @JsonProperty("href") val href: String? = null, ) data class DumpMedia( - @JsonProperty("id") val id: String? = null, - @JsonProperty("domainType") val domainType: Int? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("releaseTime") val releaseTime: String? = null, + @JsonProperty("id") val id: String? = null, + @JsonProperty("domainType") val domainType: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("releaseTime") val releaseTime: String? = null, ) data class DumpQuickSearchData( - @JsonProperty("searchResults") val searchResults: ArrayList? = arrayListOf(), + @JsonProperty("searchResults") val searchResults: ArrayList? = arrayListOf(), ) data class SubtitlingList( - @JsonProperty("languageAbbr") val languageAbbr: String? = null, - @JsonProperty("language") val language: String? = null, - @JsonProperty("subtitlingUrl") val subtitlingUrl: String? = null, + @JsonProperty("languageAbbr") val languageAbbr: String? = null, + @JsonProperty("language") val language: String? = null, + @JsonProperty("subtitlingUrl") val subtitlingUrl: String? = null, ) data class DefinitionList( - @JsonProperty("code") val code: String? = null, - @JsonProperty("description") val description: String? = null, + @JsonProperty("code") val code: String? = null, + @JsonProperty("description") val description: String? = null, ) data class EpisodeVo( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("seriesNo") val seriesNo: Int? = null, - @JsonProperty("definitionList") val definitionList: ArrayList? = arrayListOf(), - @JsonProperty("subtitlingList") val subtitlingList: ArrayList? = arrayListOf(), + @JsonProperty("id") val id: Int? = null, + @JsonProperty("seriesNo") val seriesNo: Int? = null, + @JsonProperty("definitionList") val definitionList: ArrayList? = arrayListOf(), + @JsonProperty("subtitlingList") val subtitlingList: ArrayList? = arrayListOf(), ) data class DumpMediaDetail( - @JsonProperty("episodeVo") val episodeVo: ArrayList? = arrayListOf(), + @JsonProperty("episodeVo") val episodeVo: ArrayList? = arrayListOf(), ) data class EMovieServer( - @JsonProperty("value") val value: String? = null, + @JsonProperty("value") val value: String? = null, ) data class EMovieSources( - @JsonProperty("file") val file: String? = null, + @JsonProperty("file") val file: String? = null, ) data class EMovieTraks( - @JsonProperty("file") val file: String? = null, - @JsonProperty("label") val label: String? = null, + @JsonProperty("file") val file: String? = null, + @JsonProperty("label") val label: String? = null, ) data class ShowflixResultsMovies( - @JsonProperty("movieName") val movieName: String? = null, - @JsonProperty("streamwish") val streamwish: String? = null, - @JsonProperty("filelions") val filelions: String? = null, - @JsonProperty("streamruby") val streamruby: String? = null, + @JsonProperty("movieName") val movieName: String? = null, + @JsonProperty("streamwish") val streamwish: String? = null, + @JsonProperty("filelions") val filelions: String? = null, + @JsonProperty("streamruby") val streamruby: String? = null, ) data class ShowflixResultsSeries( - @JsonProperty("seriesName") val seriesName: String? = null, - @JsonProperty("streamwish") val streamwish: HashMap>? = hashMapOf(), - @JsonProperty("filelions") val filelions: HashMap>? = hashMapOf(), - @JsonProperty("streamruby") val streamruby: HashMap>? = hashMapOf(), + @JsonProperty("seriesName") val seriesName: String? = null, + @JsonProperty("streamwish") val streamwish: HashMap>? = hashMapOf(), + @JsonProperty("filelions") val filelions: HashMap>? = hashMapOf(), + @JsonProperty("streamruby") val streamruby: HashMap>? = hashMapOf(), ) data class ShowflixSearchMovies( - @JsonProperty("results") val resultsMovies: ArrayList? = arrayListOf(), + @JsonProperty("results") val resultsMovies: ArrayList? = arrayListOf(), ) data class ShowflixSearchSeries( - @JsonProperty("results") val resultsSeries: ArrayList? = arrayListOf(), + @JsonProperty("results") val resultsSeries: ArrayList? = arrayListOf(), ) data class SFMoviesSeriess( - @JsonProperty("title") var title: String? = null, - @JsonProperty("svideos") var svideos: String? = null, + @JsonProperty("title") var title: String? = null, + @JsonProperty("svideos") var svideos: String? = null, ) data class SFMoviesAttributes( - @JsonProperty("title") var title: String? = null, - @JsonProperty("video") var video: String? = null, - @JsonProperty("releaseDate") var releaseDate: String? = null, - @JsonProperty("seriess") var seriess: ArrayList>? = arrayListOf(), - @JsonProperty("contentId") var contentId: String? = null, + @JsonProperty("title") var title: String? = null, + @JsonProperty("video") var video: String? = null, + @JsonProperty("releaseDate") var releaseDate: String? = null, + @JsonProperty("seriess") var seriess: ArrayList>? = arrayListOf(), + @JsonProperty("contentId") var contentId: String? = null, ) -data class SFMoviesData( - @JsonProperty("id") var id: Int? = null, - @JsonProperty("attributes") var attributes: SFMoviesAttributes? = SFMoviesAttributes() -) +data class SFMoviesData(@JsonProperty("id") var id: Int? = null, @JsonProperty("attributes") var attributes: SFMoviesAttributes? = SFMoviesAttributes()) data class SFMoviesSearch( - @JsonProperty("data") var data: ArrayList? = arrayListOf(), + @JsonProperty("data") var data: ArrayList? = arrayListOf(), ) data class RidoContentable( - @JsonProperty("imdbId") var imdbId: String? = null, - @JsonProperty("tmdbId") var tmdbId: Int? = null, + @JsonProperty("imdbId") var imdbId: String? = null, + @JsonProperty("tmdbId") var tmdbId: Int? = null, ) data class RidoItems( - @JsonProperty("slug") var slug: String? = null, - @JsonProperty("contentable") var contentable: RidoContentable? = null, + @JsonProperty("slug") var slug: String? = null, + @JsonProperty("contentable") var contentable: RidoContentable? = null, ) data class RidoData( - @JsonProperty("url") var url: String? = null, - @JsonProperty("items") var items: ArrayList? = arrayListOf(), + @JsonProperty("url") var url: String? = null, + @JsonProperty("items") var items: ArrayList? = arrayListOf(), ) data class RidoResponses( - @JsonProperty("data") var data: ArrayList? = arrayListOf(), + @JsonProperty("data") var data: ArrayList? = arrayListOf(), ) data class RidoSearch( - @JsonProperty("data") var data: RidoData? = null, + @JsonProperty("data") var data: RidoData? = null, ) data class SmashySources( - @JsonProperty("sourceUrls") var sourceUrls: ArrayList? = arrayListOf(), - @JsonProperty("subtitleUrls") var subtitleUrls: String? = null, + @JsonProperty("sourceUrls") var sourceUrls: ArrayList? = arrayListOf(), + @JsonProperty("subtitleUrls") var subtitleUrls: String? = null, ) data class SmashyDSources( - @JsonProperty("sourceUrls") var sourceUrls: ArrayList? = arrayListOf(), + @JsonProperty("sourceUrls") var sourceUrls: ArrayList? = arrayListOf(), ) data class SmashyDSourcesUrls( - @JsonProperty("file") var file: String? = null, - @JsonProperty("title") var title: String? = null, + @JsonProperty("file") var file: String? = null, + @JsonProperty("title") var title: String? = null, ) data class AoneroomResponse( - @JsonProperty("data") val data: Data? = null, + @JsonProperty("data") val data: Data? = null, ) { data class Data( - @JsonProperty("items") val items: ArrayList? = arrayListOf(), - @JsonProperty("list") val list: ArrayList? = arrayListOf(), + @JsonProperty("items") val items: ArrayList? = arrayListOf(), + @JsonProperty("list") val list: ArrayList? = arrayListOf(), ) { data class Items( - @JsonProperty("subjectId") val subjectId: String? = null, - @JsonProperty("title") val title: String? = null, - @JsonProperty("releaseDate") val releaseDate: String? = null, + @JsonProperty("subjectId") val subjectId: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("releaseDate") val releaseDate: String? = null, ) data class List( - @JsonProperty("resourceLink") val resourceLink: String? = null, - @JsonProperty("extCaptions") val extCaptions: ArrayList? = arrayListOf(), - @JsonProperty("se") val se: Int? = null, - @JsonProperty("ep") val ep: Int? = null, - @JsonProperty("resolution") val resolution: Int? = null, + @JsonProperty("resourceLink") val resourceLink: String? = null, + @JsonProperty("extCaptions") val extCaptions: ArrayList? = arrayListOf(), + @JsonProperty("se") val se: Int? = null, + @JsonProperty("ep") val ep: Int? = null, + @JsonProperty("resolution") val resolution: Int? = null, ) { data class ExtCaptions( - @JsonProperty("lanName") val lanName: String? = null, - @JsonProperty("url") val url: String? = null, + @JsonProperty("lanName") val lanName: String? = null, + @JsonProperty("url") val url: String? = null, ) } } -} - -data class FebboxResponse( - @JsonProperty("data") val data: Data? = null, -) { - data class Data( - @JsonProperty("link") val link: String? = null, - @JsonProperty("file_list") val file_list: ArrayList? = arrayListOf(), - ) { - data class FileList( - @JsonProperty("fid") val fid: Long? = null, - @JsonProperty("file_name") val file_name: String? = null, - @JsonProperty("oss_fid") val oss_fid: Long? = null, - ) - } } \ No newline at end of file diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 141c5839..8c6aa0ea 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -43,7 +43,7 @@ import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeVegamovies import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeCinemaTv -import com.hexated.SoraExtractor.invokeFebbox +import com.hexated.SoraExtractor.invokeMMovies import com.hexated.SoraExtractor.invokeOmovies import com.hexated.SoraExtractor.invokeWatchCartoon import com.hexated.SoraExtractor.invokeWatchsomuch @@ -63,13 +63,13 @@ open class SoraStream : TmdbProvider() { override val useMetaLoadResponse = true override val hasQuickSearch = true override val supportedTypes = setOf( - TvType.Movie, - TvType.TvSeries, - TvType.Anime, + TvType.Movie, + TvType.TvSeries, + TvType.Anime, ) - val showboxInterceptor by lazy { CloudflareKiller() } val wpredisInterceptor by lazy { CloudflareKiller() } + val multiInterceptor by lazy { CloudflareKiller() } /** AUTHOR : Hexated & Sora */ companion object { @@ -114,10 +114,9 @@ open class SoraStream : TmdbProvider() { const val vidsrctoAPI = "https://vidsrc.to" const val dramadayAPI = "https://dramaday.me" const val animetoshoAPI = "https://animetosho.org" - const val watchflxAPI = "https://watchflx.tv" const val showflixAPI = "https://showflix.space" const val aoneroomAPI = "https://api3.aoneroom.com" - const val febboxAPI = "https://www.febbox.com" + const val mMoviesAPI = "https://multimovies.uno" const val watchCartoonAPI = "https://www1.watchcartoononline.bz" const val fdMoviesAPI = "https://freedrivemovie.com" @@ -148,26 +147,26 @@ open class SoraStream : TmdbProvider() { } override val mainPage = mainPageOf( - "$tmdbAPI/trending/all/day?api_key=$apiKey®ion=US" to "Trending", - "$tmdbAPI/movie/popular?api_key=$apiKey®ion=US" to "Popular Movies", - "$tmdbAPI/tv/popular?api_key=$apiKey®ion=US&with_original_language=en" to "Popular TV Shows", - "$tmdbAPI/tv/airing_today?api_key=$apiKey®ion=US&with_original_language=en" to "Airing Today TV Shows", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=213" to "Netflix", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=1024" to "Amazon", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=2739" to "Disney+", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=453" to "Hulu", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=2552" to "Apple TV+", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=49" to "HBO", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=4330" to "Paramount+", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=3353" to "Peacock", - "$tmdbAPI/movie/top_rated?api_key=$apiKey®ion=US" to "Top Rated Movies", - "$tmdbAPI/tv/top_rated?api_key=$apiKey®ion=US" to "Top Rated TV Shows", - "$tmdbAPI/movie/upcoming?api_key=$apiKey®ion=US" to "Upcoming Movies", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_original_language=ko" to "Korean Shows", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243&sort_by=popularity.desc&air_date.lte=${getDate().today}&air_date.gte=${getDate().today}" to "Airing Today Anime", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243&sort_by=popularity.desc&air_date.lte=${getDate().nextWeek}&air_date.gte=${getDate().today}" to "On The Air Anime", - "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243" to "Anime", - "$tmdbAPI/discover/movie?api_key=$apiKey&with_keywords=210024|222243" to "Anime Movies", + "$tmdbAPI/trending/all/day?api_key=$apiKey®ion=US" to "Trending", + "$tmdbAPI/movie/popular?api_key=$apiKey®ion=US" to "Popular Movies", + "$tmdbAPI/tv/popular?api_key=$apiKey®ion=US&with_original_language=en" to "Popular TV Shows", + "$tmdbAPI/tv/airing_today?api_key=$apiKey®ion=US&with_original_language=en" to "Airing Today TV Shows", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=213" to "Netflix", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=1024" to "Amazon", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=2739" to "Disney+", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=453" to "Hulu", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=2552" to "Apple TV+", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=49" to "HBO", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=4330" to "Paramount+", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_networks=3353" to "Peacock", + "$tmdbAPI/movie/top_rated?api_key=$apiKey®ion=US" to "Top Rated Movies", + "$tmdbAPI/tv/top_rated?api_key=$apiKey®ion=US" to "Top Rated TV Shows", + "$tmdbAPI/movie/upcoming?api_key=$apiKey®ion=US" to "Upcoming Movies", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_original_language=ko" to "Korean Shows", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243&sort_by=popularity.desc&air_date.lte=${getDate().today}&air_date.gte=${getDate().today}" to "Airing Today Anime", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243&sort_by=popularity.desc&air_date.lte=${getDate().nextWeek}&air_date.gte=${getDate().today}" to "On The Air Anime", + "$tmdbAPI/discover/tv?api_key=$apiKey&with_keywords=210024|222243" to "Anime", + "$tmdbAPI/discover/movie?api_key=$apiKey&with_keywords=210024|222243" to "Anime Movies", ) private fun getImageUrl(link: String?): String? { @@ -180,26 +179,20 @@ open class SoraStream : TmdbProvider() { return if (link.startsWith("/")) "https://image.tmdb.org/t/p/original/$link" else link } - override suspend fun getMainPage( - page: Int, - request: MainPageRequest - ): HomePageResponse { - val adultQuery = - if (settingsForProvider.enableAdult) "" else "&without_keywords=190370|13059|226161|195669" + override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { + val adultQuery = if (settingsForProvider.enableAdult) "" else "&without_keywords=190370|13059|226161|195669" val type = if (request.data.contains("/movie")) "movie" else "tv" - val home = app.get("${request.data}$adultQuery&page=$page") - .parsedSafe()?.results - ?.mapNotNull { media -> - media.toSearchResponse(type) - } ?: throw ErrorLoadingException("Invalid Json reponse") + val home = app.get("${request.data}$adultQuery&page=$page").parsedSafe()?.results?.mapNotNull { media -> + media.toSearchResponse(type) + } ?: throw ErrorLoadingException("Invalid Json reponse") return newHomePageResponse(request.name, home) } private fun Media.toSearchResponse(type: String? = null): SearchResponse? { return newMovieSearchResponse( - title ?: name ?: originalTitle ?: return null, - Data(id = id, type = mediaType ?: type).toJson(), - TvType.Movie, + title ?: name ?: originalTitle ?: return null, + Data(id = id, type = mediaType ?: type).toJson(), + TvType.Movie, ) { this.posterUrl = getImageUrl(posterPath) } @@ -208,9 +201,7 @@ open class SoraStream : TmdbProvider() { override suspend fun quickSearch(query: String): List? = search(query) override suspend fun search(query: String): List? { - return app.get( - "$tmdbAPI/search/multi?api_key=$apiKey&language=en-US&query=$query&page=1&include_adult=${settingsForProvider.enableAdult}" - ).parsedSafe()?.results?.mapNotNull { media -> + return app.get("$tmdbAPI/search/multi?api_key=$apiKey&language=en-US&query=$query&page=1&include_adult=${settingsForProvider.enableAdult}").parsedSafe()?.results?.mapNotNull { media -> media.toSearchResponse() } } @@ -225,7 +216,7 @@ open class SoraStream : TmdbProvider() { "$tmdbAPI/tv/${data.id}?api_key=$apiKey&append_to_response=$append" } val res = app.get(resUrl).parsedSafe() - ?: throw ErrorLoadingException("Invalid Json Response") + ?: throw ErrorLoadingException("Invalid Json Response") val title = res.title ?: res.name ?: return null val poster = getOriImageUrl(res.posterPath) @@ -241,68 +232,27 @@ open class SoraStream : TmdbProvider() { val isAsian = !isAnime && (res.original_language == "zh" || res.original_language == "ko") val isBollywood = res.production_countries?.any { it.name == "India" } ?: false - val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty() - .ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } } + val keywords = res.keywords?.results?.mapNotNull { it.name }.orEmpty().ifEmpty { res.keywords?.keywords?.mapNotNull { it.name } } val actors = res.credits?.cast?.mapNotNull { cast -> - ActorData( - Actor( - cast.name ?: cast.originalName ?: return@mapNotNull null, - getImageUrl(cast.profilePath) - ), - roleString = cast.character - ) + ActorData(Actor(cast.name ?: cast.originalName + ?: return@mapNotNull null, getImageUrl(cast.profilePath)), roleString = cast.character) } ?: return null - val recommendations = - res.recommendations?.results?.mapNotNull { media -> media.toSearchResponse() } + val recommendations = res.recommendations?.results?.mapNotNull { media -> media.toSearchResponse() } - val trailer = res.videos?.results?.map { "https://www.youtube.com/watch?v=${it.key}" } - ?.randomOrNull() + val trailer = res.videos?.results?.map { "https://www.youtube.com/watch?v=${it.key}" }?.randomOrNull() return if (type == TvType.TvSeries) { val lastSeason = res.last_episode_to_air?.season_number val episodes = res.seasons?.mapNotNull { season -> - app.get("$tmdbAPI/${data.type}/${data.id}/season/${season.seasonNumber}?api_key=$apiKey") - .parsedSafe()?.episodes?.map { eps -> - Episode( - LinkData( - data.id, - res.external_ids?.imdb_id, - res.external_ids?.tvdb_id, - data.type, - eps.seasonNumber, - eps.episodeNumber, - title = title, - year = season.airDate?.split("-")?.first()?.toIntOrNull(), - orgTitle = orgTitle, - isAnime = isAnime, - airedYear = year, - lastSeason = lastSeason, - epsTitle = eps.name, - jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, - date = season.airDate, - airedDate = res.releaseDate ?: res.firstAirDate, - isAsian = isAsian, - isBollywood = isBollywood, - isCartoon = isCartoon - ).toJson(), - name = eps.name + if (isUpcoming(eps.airDate)) " - [UPCOMING]" else "", - season = eps.seasonNumber, - episode = eps.episodeNumber, - posterUrl = getImageUrl(eps.stillPath), - rating = eps.voteAverage?.times(10)?.roundToInt(), - description = eps.overview - ).apply { - this.addDate(eps.airDate) - } + app.get("$tmdbAPI/${data.type}/${data.id}/season/${season.seasonNumber}?api_key=$apiKey").parsedSafe()?.episodes?.map { eps -> + Episode(LinkData(data.id, res.external_ids?.imdb_id, res.external_ids?.tvdb_id, data.type, eps.seasonNumber, eps.episodeNumber, title = title, year = season.airDate?.split("-")?.first()?.toIntOrNull(), orgTitle = orgTitle, isAnime = isAnime, airedYear = year, lastSeason = lastSeason, epsTitle = eps.name, jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, date = season.airDate, airedDate = res.releaseDate + ?: res.firstAirDate, isAsian = isAsian, isBollywood = isBollywood, isCartoon = isCartoon).toJson(), name = eps.name + if (isUpcoming(eps.airDate)) " - [UPCOMING]" else "", season = eps.seasonNumber, episode = eps.episodeNumber, posterUrl = getImageUrl(eps.stillPath), rating = eps.voteAverage?.times(10)?.roundToInt(), description = eps.overview).apply { + this.addDate(eps.airDate) } + } }?.flatten() ?: listOf() - newTvSeriesLoadResponse( - title, - url, - if (isAnime) TvType.Anime else TvType.TvSeries, - episodes - ) { + newTvSeriesLoadResponse(title, url, if (isAnime) TvType.Anime else TvType.TvSeries, episodes) { this.posterUrl = poster this.backgroundPosterUrl = bgPoster this.year = year @@ -319,23 +269,11 @@ open class SoraStream : TmdbProvider() { } } else { newMovieLoadResponse( - title, - url, - TvType.Movie, - LinkData( - data.id, - res.external_ids?.imdb_id, - res.external_ids?.tvdb_id, - data.type, - title = title, - year = year, - orgTitle = orgTitle, - isAnime = isAnime, - jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, - airedDate = res.releaseDate ?: res.firstAirDate, - isAsian = isAsian, - isBollywood = isBollywood - ).toJson(), + title, + url, + TvType.Movie, + LinkData(data.id, res.external_ids?.imdb_id, res.external_ids?.tvdb_id, data.type, title = title, year = year, orgTitle = orgTitle, isAnime = isAnime, jpTitle = res.alternative_titles?.results?.find { it.iso_3166_1 == "JP" }?.title, airedDate = res.releaseDate + ?: res.firstAirDate, isAsian = isAsian, isBollywood = isBollywood).toJson(), ) { this.posterUrl = poster this.backgroundPosterUrl = bgPoster @@ -355,556 +293,315 @@ open class SoraStream : TmdbProvider() { } } - override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ): Boolean { + override suspend fun loadLinks(data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit): Boolean { val res = parseJson(data) argamap( -// { -// invokeFebbox( -// res.title, -// res.year, -// res.season, -// res.lastSeason, -// res.episode, -// callback -// ) -// }, - { - invokeDumpStream( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - invokeGoku( - res.title, - res.year, - res.season, - res.lastSeason, - res.episode, - subtitleCallback, - callback - ) - }, - { - invokeVidSrc(res.id, res.season, res.episode, callback) - }, - { - invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeAoneroom( - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (res.isAnime) invokeAnimes( - res.title, - res.epsTitle, - res.date, - res.airedDate, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeDreamfilm( - res.title, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, + { + invokeDumpStream(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeGoku(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) + }, + { + invokeVidSrc(res.id, res.season, res.episode, callback) + }, + { + invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeAoneroom(res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (res.isAnime) invokeAnimes(res.title, res.epsTitle, res.date, res.airedDate, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeDreamfilm(res.title, res.season, res.episode, subtitleCallback, callback) + }, // { // invokeNoverse(res.title, res.season, res.episode, callback) // }, - { - if (!res.isAnime) invokeFilmxy( - res.imdbId, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime && res.isCartoon) invokeKimcartoon( - res.title, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime && res.isCartoon) invokeWatchCartoon( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeVidsrcto( - res.imdbId, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (res.isAsian || res.isAnime) invokeKisskh( - res.title, - res.season, - res.episode, - res.isAnime, - res.lastSeason, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeOmovies ( - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, - { - if (!res.isAnime) invokeLing( - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeUhdmovies( - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, - { - if (!res.isAnime) invokeGMovies( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeFDMovies( - res.title, - res.season, - res.episode, - callback - ) - }, - { - if (!res.isAnime) invokeM4uhd( - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeTvMovies(res.title, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeMoviezAdd( - moviezAddAPI, - "MoviezAdd", - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, - { - if (!res.isAnime && res.isBollywood) invokeBollyMaza( - bollyMazaAPI, - "BollyMaza", - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, - { - if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeFlixon( - res.id, - res.imdbId, - res.season, - res.episode, - callback - ) - }, - { - if (!res.isAnime) invokeSmashyStream( - res.imdbId, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeWatchsomuch( - res.imdbId, - res.season, - res.episode, - subtitleCallback - ) - }, - { - if (!res.isAnime) invokeNinetv( - res.id, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - invokeDahmerMovies( - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, - { - invokeCinemaTv( - res.imdbId, - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeNowTv(res.id, res.imdbId, res.season, res.episode, callback) - }, - { - if (!res.isAnime && res.season == null) invokeRidomovies( - res.id, - res.imdbId, - callback - ) - }, - { - if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeEmovies( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeVegamovies( - res.title, - res.year, - res.season, - res.lastSeason, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime && res.isBollywood) invokeDotmovies( - res.title, - res.year, - res.season, - res.lastSeason, - res.episode, - subtitleCallback, - callback - ) - }, - { - if(res.isBollywood) invokeMultimovies(multimoviesAPI, res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - if(res.isBollywood) invokeMultimovies(multimovies2API, res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - invokeNetmovies( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime && res.season == null) invokeDoomovies( - res.title, - subtitleCallback, - callback - ) - }, - { - if (res.isAsian) invokeDramaday( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invoke2embed(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime) invokeHdmovies4u( - res.title, - res.imdbId, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - invokeZshow( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeShowflix( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeSFMovies( - res.id, - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - callback - ) - } + { + if (!res.isAnime) invokeFilmxy(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime && res.isCartoon) invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime && res.isCartoon) invokeWatchCartoon(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeVidsrcto(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (res.isAsian || res.isAnime) invokeKisskh(res.title, res.season, res.episode, res.isAnime, res.lastSeason, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeOmovies(res.title, res.year, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeLing(res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeUhdmovies(res.title, res.year, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeGMovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeFDMovies(res.title, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeM4uhd(res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeTvMovies(res.title, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeMoviezAdd(moviezAddAPI, "MoviezAdd", res.title, res.year, res.season, res.episode, callback) + }, + { + if (!res.isAnime && res.isBollywood) invokeBollyMaza(bollyMazaAPI, "BollyMaza", res.title, res.year, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeSmashyStream(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeWatchsomuch(res.imdbId, res.season, res.episode, subtitleCallback) + }, + { + if (!res.isAnime) invokeNinetv(res.id, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeDahmerMovies(res.title, res.year, res.season, res.episode, callback) + }, + { + invokeCinemaTv(res.imdbId, res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeNowTv(res.id, res.imdbId, res.season, res.episode, callback) + }, + { + if (!res.isAnime && res.season == null) invokeRidomovies(res.id, res.imdbId, callback) + }, + { + if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeEmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeVegamovies(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime && res.isBollywood) invokeDotmovies(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) + }, + { + if (res.isBollywood) invokeMultimovies(multimoviesAPI, res.title, res.season, res.episode, subtitleCallback, callback) + }, + { + if (res.isBollywood) invokeMultimovies(multimovies2API, res.title, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeNetmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime && res.season == null) invokeDoomovies(res.title, subtitleCallback, callback) + }, + { + if (res.isAsian) invokeDramaday(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invoke2embed(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeHdmovies4u(res.title, res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeZshow(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeShowflix(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeSFMovies(res.id, res.title, res.airedYear + ?: res.year, res.season, res.episode, callback) + }, + { + invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback) + }, ) return true } 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, - val aniId: String? = null, - val animeId: String? = null, - val title: String? = null, - val year: Int? = null, - val orgTitle: String? = null, - val isAnime: Boolean = false, - val airedYear: Int? = null, - val lastSeason: Int? = null, - val epsTitle: String? = null, - val jpTitle: String? = null, - val date: String? = null, - val airedDate: String? = null, - val isAsian: Boolean = false, - val isBollywood: Boolean = false, - val isCartoon: Boolean = false, + val id: Int? = null, + val imdbId: String? = null, + val tvdbId: Int? = null, + val type: String? = null, + val season: Int? = null, + val episode: Int? = null, + val aniId: String? = null, + val animeId: String? = null, + val title: String? = null, + val year: Int? = null, + val orgTitle: String? = null, + val isAnime: Boolean = false, + val airedYear: Int? = null, + val lastSeason: Int? = null, + val epsTitle: String? = null, + val jpTitle: String? = null, + val date: String? = null, + val airedDate: String? = null, + val isAsian: Boolean = false, + val isBollywood: Boolean = false, + val isCartoon: Boolean = false, ) data class Data( - val id: Int? = null, - val type: String? = null, - val aniId: String? = null, - val malId: Int? = null, + val id: Int? = null, + val type: String? = null, + val aniId: String? = null, + val malId: Int? = null, ) data class Results( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) data class Media( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("title") val title: String? = null, - @JsonProperty("original_title") val originalTitle: String? = null, - @JsonProperty("media_type") val mediaType: String? = null, - @JsonProperty("poster_path") val posterPath: String? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("original_title") val originalTitle: String? = null, + @JsonProperty("media_type") val mediaType: String? = null, + @JsonProperty("poster_path") val posterPath: String? = null, ) data class Genres( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, ) data class Keywords( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, ) data class KeywordResults( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), - @JsonProperty("keywords") val keywords: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("keywords") val keywords: ArrayList? = arrayListOf(), ) data class Seasons( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("season_number") val seasonNumber: Int? = null, - @JsonProperty("air_date") val airDate: String? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("season_number") val seasonNumber: Int? = null, + @JsonProperty("air_date") val airDate: String? = null, ) data class Cast( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("original_name") val originalName: String? = null, - @JsonProperty("character") val character: String? = null, - @JsonProperty("known_for_department") val knownForDepartment: String? = null, - @JsonProperty("profile_path") val profilePath: String? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("original_name") val originalName: String? = null, + @JsonProperty("character") val character: String? = null, + @JsonProperty("known_for_department") val knownForDepartment: String? = null, + @JsonProperty("profile_path") val profilePath: String? = null, ) data class Episodes( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("overview") val overview: String? = null, - @JsonProperty("air_date") val airDate: String? = null, - @JsonProperty("still_path") val stillPath: String? = null, - @JsonProperty("vote_average") val voteAverage: Double? = null, - @JsonProperty("episode_number") val episodeNumber: Int? = null, - @JsonProperty("season_number") val seasonNumber: Int? = null, + @JsonProperty("id") val id: Int? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("overview") val overview: String? = null, + @JsonProperty("air_date") val airDate: String? = null, + @JsonProperty("still_path") val stillPath: String? = null, + @JsonProperty("vote_average") val voteAverage: Double? = null, + @JsonProperty("episode_number") val episodeNumber: Int? = null, + @JsonProperty("season_number") val seasonNumber: Int? = null, ) data class MediaDetailEpisodes( - @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), + @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), ) data class Trailers( - @JsonProperty("key") val key: String? = null, + @JsonProperty("key") val key: String? = null, ) data class ResultsTrailer( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) data class AltTitles( - @JsonProperty("iso_3166_1") val iso_3166_1: String? = null, - @JsonProperty("title") val title: String? = null, - @JsonProperty("type") val type: String? = null, + @JsonProperty("iso_3166_1") val iso_3166_1: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("type") val type: String? = null, ) data class ResultsAltTitles( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) data class ExternalIds( - @JsonProperty("imdb_id") val imdb_id: String? = null, - @JsonProperty("tvdb_id") val tvdb_id: Int? = null, + @JsonProperty("imdb_id") val imdb_id: String? = null, + @JsonProperty("tvdb_id") val tvdb_id: Int? = null, ) data class Credits( - @JsonProperty("cast") val cast: ArrayList? = arrayListOf(), + @JsonProperty("cast") val cast: ArrayList? = arrayListOf(), ) data class ResultsRecommendations( - @JsonProperty("results") val results: ArrayList? = arrayListOf(), + @JsonProperty("results") val results: ArrayList? = arrayListOf(), ) data class LastEpisodeToAir( - @JsonProperty("episode_number") val episode_number: Int? = null, - @JsonProperty("season_number") val season_number: Int? = null, + @JsonProperty("episode_number") val episode_number: Int? = null, + @JsonProperty("season_number") val season_number: Int? = null, ) data class ProductionCountries( - @JsonProperty("name") val name: String? = null, + @JsonProperty("name") val name: String? = null, ) data class MediaDetail( - @JsonProperty("id") val id: Int? = null, - @JsonProperty("imdb_id") val imdbId: String? = null, - @JsonProperty("title") val title: String? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("original_title") val originalTitle: String? = null, - @JsonProperty("original_name") val originalName: String? = null, - @JsonProperty("poster_path") val posterPath: String? = null, - @JsonProperty("backdrop_path") val backdropPath: String? = null, - @JsonProperty("release_date") val releaseDate: String? = null, - @JsonProperty("first_air_date") val firstAirDate: String? = null, - @JsonProperty("overview") val overview: String? = null, - @JsonProperty("runtime") val runtime: Int? = null, - @JsonProperty("vote_average") val vote_average: Any? = null, - @JsonProperty("original_language") val original_language: String? = null, - @JsonProperty("status") val status: String? = null, - @JsonProperty("genres") val genres: ArrayList? = arrayListOf(), - @JsonProperty("keywords") val keywords: KeywordResults? = null, - @JsonProperty("last_episode_to_air") val last_episode_to_air: LastEpisodeToAir? = null, - @JsonProperty("seasons") val seasons: ArrayList? = arrayListOf(), - @JsonProperty("videos") val videos: ResultsTrailer? = null, - @JsonProperty("external_ids") val external_ids: ExternalIds? = null, - @JsonProperty("credits") val credits: Credits? = null, - @JsonProperty("recommendations") val recommendations: ResultsRecommendations? = null, - @JsonProperty("alternative_titles") val alternative_titles: ResultsAltTitles? = null, - @JsonProperty("production_countries") val production_countries: ArrayList? = arrayListOf(), + @JsonProperty("id") val id: Int? = null, + @JsonProperty("imdb_id") val imdbId: String? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("name") val name: String? = null, + @JsonProperty("original_title") val originalTitle: String? = null, + @JsonProperty("original_name") val originalName: String? = null, + @JsonProperty("poster_path") val posterPath: String? = null, + @JsonProperty("backdrop_path") val backdropPath: String? = null, + @JsonProperty("release_date") val releaseDate: String? = null, + @JsonProperty("first_air_date") val firstAirDate: String? = null, + @JsonProperty("overview") val overview: String? = null, + @JsonProperty("runtime") val runtime: Int? = null, + @JsonProperty("vote_average") val vote_average: Any? = null, + @JsonProperty("original_language") val original_language: String? = null, + @JsonProperty("status") val status: String? = null, + @JsonProperty("genres") val genres: ArrayList? = arrayListOf(), + @JsonProperty("keywords") val keywords: KeywordResults? = null, + @JsonProperty("last_episode_to_air") val last_episode_to_air: LastEpisodeToAir? = null, + @JsonProperty("seasons") val seasons: ArrayList? = arrayListOf(), + @JsonProperty("videos") val videos: ResultsTrailer? = null, + @JsonProperty("external_ids") val external_ids: ExternalIds? = null, + @JsonProperty("credits") val credits: Credits? = null, + @JsonProperty("recommendations") val recommendations: ResultsRecommendations? = null, + @JsonProperty("alternative_titles") val alternative_titles: ResultsAltTitles? = null, + @JsonProperty("production_countries") val production_countries: ArrayList? = arrayListOf(), ) } diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt index 3b9e975f..2ea87243 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -29,7 +29,7 @@ import com.hexated.SoraExtractor.invokeShowflix import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeCinemaTv -import com.hexated.SoraExtractor.invokeFebbox +import com.hexated.SoraExtractor.invokeMMovies import com.hexated.SoraExtractor.invokeOmovies import com.hexated.SoraExtractor.invokeWatchCartoon import com.hexated.SoraExtractor.invokeWatchsomuch @@ -42,299 +42,121 @@ import com.lagradost.cloudstream3.utils.ExtractorLink class SoraStreamLite : SoraStream() { override var name = "SoraStream-Lite" - override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ): Boolean { + override suspend fun loadLinks(data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit): Boolean { val res = AppUtils.parseJson(data) argamap( -// { -// invokeFebbox( -// res.title, -// res.year, -// res.season, -// res.lastSeason, -// res.episode, -// callback -// ) -// }, - { - if (!res.isAnime) invokeWatchsomuch( - res.imdbId, - res.season, - res.episode, - subtitleCallback - ) - }, - { - invokeDumpStream( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeNinetv( - res.id, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - invokeGoku( - res.title, - res.year, - res.season, - res.lastSeason, - res.episode, - subtitleCallback, - callback - ) - }, - { - invokeVidSrc(res.id, res.season, res.episode, callback) - }, - { - invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) - }, - { - if (!res.isAnime && res.isCartoon) invokeWatchCartoon( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (res.isAnime) invokeAnimes( - res.title, - res.epsTitle, - res.date, - res.airedDate, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeDreamfilm( - res.title, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeFilmxy( - res.imdbId, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeOmovies( - res.title, - res.year, - res.season, - res.episode, - callback - ) - }, - { - if (!res.isAnime && res.isCartoon) invokeKimcartoon( - res.title, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeSmashyStream( - res.imdbId, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeVidsrcto( - res.imdbId, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (res.isAsian || res.isAnime) invokeKisskh( - res.title, - res.season, - res.episode, - res.isAnime, - res.lastSeason, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeLing( - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if(!res.isAnime) invokeM4uhd( - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback) - }, - { - invokeCinemaTv( - res.imdbId, - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeNowTv(res.id, res.imdbId, res.season, res.episode, callback) - }, - { - if (!res.isAnime) invokeAoneroom( - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime && res.season == null) invokeRidomovies( - res.id, - res.imdbId, - callback - ) - }, - { - if (!res.isAnime) invokeEmovies( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if(res.isBollywood) invokeMultimovies(multimoviesAPI, res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - if(res.isBollywood) invokeMultimovies(multimovies2API, res.title, res.season, res.episode, subtitleCallback, callback) - }, - { - invokeNetmovies( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) - }, - { - if (!res.isAnime && res.season == null) invokeDoomovies( - res.title, - subtitleCallback, - callback - ) - }, - { - if(res.isAsian) invokeDramaday( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if(!res.isAnime) invoke2embed( - res.imdbId, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - invokeZshow( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if (!res.isAnime) invokeShowflix( - res.title, - res.year, - res.season, - res.episode, - subtitleCallback, - callback - ) - }, - { - if(!res.isAnime) invokeSFMovies( - res.id, - res.title, - res.airedYear ?: res.year, - res.season, - res.episode, - callback - ) - } + { + if (!res.isAnime) invokeWatchsomuch(res.imdbId, res.season, res.episode, subtitleCallback) + }, + { + invokeDumpStream(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeNinetv(res.id, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeGoku(res.title, res.year, res.season, res.lastSeason, res.episode, subtitleCallback, callback) + }, + { + invokeVidSrc(res.id, res.season, res.episode, callback) + }, + { + invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime && res.isCartoon) invokeWatchCartoon(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (res.isAnime) invokeAnimes(res.title, res.epsTitle, res.date, res.airedDate, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeDreamfilm(res.title, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeFilmxy(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeOmovies(res.title, res.year, res.season, res.episode, callback) + }, + { + if (!res.isAnime && res.isCartoon) invokeKimcartoon(res.title, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeSmashyStream(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeVidsrcto(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + if (res.isAsian || res.isAnime) invokeKisskh(res.title, res.season, res.episode, res.isAnime, res.lastSeason, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeLing(res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeM4uhd(res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeRStream(res.id, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeFlixon(res.id, res.imdbId, res.season, res.episode, callback) + }, + { + invokeCinemaTv(res.imdbId, res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeNowTv(res.id, res.imdbId, res.season, res.episode, callback) + }, + { + if (!res.isAnime) invokeAoneroom(res.title, res.airedYear + ?: res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime && res.season == null) invokeRidomovies(res.id, res.imdbId, callback) + }, + { + if (!res.isAnime) invokeEmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (res.isBollywood) invokeMultimovies(multimoviesAPI, res.title, res.season, res.episode, subtitleCallback, callback) + }, + { + if (res.isBollywood) invokeMultimovies(multimovies2API, res.title, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeNetmovies(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeAllMovieland(res.imdbId, res.season, res.episode, callback) + }, + { + if (!res.isAnime && res.season == null) invokeDoomovies(res.title, subtitleCallback, callback) + }, + { + if (res.isAsian) invokeDramaday(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invoke2embed(res.imdbId, res.season, res.episode, subtitleCallback, callback) + }, + { + invokeZshow(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeShowflix(res.title, res.year, res.season, res.episode, subtitleCallback, callback) + }, + { + if (!res.isAnime) invokeSFMovies(res.id, res.title, res.airedYear + ?: res.year, res.season, res.episode, callback) + }, + { + invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback) + }, ) return true From 76c58dbfc386d3abd52b06404f3a113634552b34 Mon Sep 17 00:00:00 2001 From: alex Date: Wed, 3 Jan 2024 07:04:36 +0700 Subject: [PATCH 032/125] fix --- .../src/main/kotlin/com/hexated/SoraUtils.kt | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 22c68cac..dbbd51de 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -9,7 +9,6 @@ import com.hexated.SoraStream.Companion.gdbot import com.hexated.SoraStream.Companion.hdmovies4uAPI import com.hexated.SoraStream.Companion.malsyncAPI import com.hexated.SoraStream.Companion.tvMoviesAPI -import com.hexated.SoraStream.Companion.watchflxAPI import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.APIHolder.getCaptchaToken import com.lagradost.cloudstream3.APIHolder.unixTimeMS @@ -46,7 +45,6 @@ import javax.crypto.spec.SecretKeySpec import kotlin.collections.ArrayList import kotlin.math.min -var watchflxCookies: Map? = null var filmxyCookies: Map? = null var sfServer: String? = null @@ -711,23 +709,6 @@ suspend fun fetchFilmxyCookies(url: String): Map { return cookieJar.plus(defaultCookies) } -suspend fun getWatchflxCookies() = - watchflxCookies ?: fetchWatchflxCookies().also { watchflxCookies = it } - -suspend fun fetchWatchflxCookies(): Map { - session.get(watchflxAPI) - val cookies = session.baseClient.cookieJar.loadForRequest(watchflxAPI.toHttpUrl()) - .associate { it.name to it.value } - val loginUrl = "$watchflxAPI/cookie-based-login" - session.post( - loginUrl, data = mapOf( - "continue_as_temp" to "true" - ), cookies = cookies, headers = mapOf("X-Requested-With" to "XMLHttpRequest") - ) - return session.baseClient.cookieJar.loadForRequest(loginUrl.toHttpUrl()) - .associate { it.name to it.value } -} - fun Document.findTvMoviesIframe(): String? { return this.selectFirst("script:containsData(var seconds)")?.data()?.substringAfter("href='") ?.substringBefore("'>") From 7a343737e7a616d40a62160c5ad066e301a7edbc Mon Sep 17 00:00:00 2001 From: dontseehereStopMotion <149931560+dontseehereStopMotion@users.noreply.github.com> Date: Wed, 3 Jan 2024 05:47:43 +0530 Subject: [PATCH 033/125] Add Animedekho (#488) --- AnimeDekhoProvider/build.gradle.kts | 27 +++ .../src/main/AndroidManifest.xml | 2 + .../main/kotlin/com/anon/AnimeDekhoPlugin.kt | 21 ++ .../kotlin/com/anon/AnimeDekhoProvider.kt | 198 ++++++++++++++++++ 4 files changed, 248 insertions(+) create mode 100644 AnimeDekhoProvider/build.gradle.kts create mode 100644 AnimeDekhoProvider/src/main/AndroidManifest.xml create mode 100644 AnimeDekhoProvider/src/main/kotlin/com/anon/AnimeDekhoPlugin.kt create mode 100644 AnimeDekhoProvider/src/main/kotlin/com/anon/AnimeDekhoProvider.kt diff --git a/AnimeDekhoProvider/build.gradle.kts b/AnimeDekhoProvider/build.gradle.kts new file mode 100644 index 00000000..d50f2b6d --- /dev/null +++ b/AnimeDekhoProvider/build.gradle.kts @@ -0,0 +1,27 @@ +version = 1 + + +cloudstream { + language = "hi" + // All of these properties are optional, you can safely remove them + + description = "YOU HAVE SKIP ADS on the SITE each 24 hours, Hindi dubbed cartoons" + authors = listOf("anon") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "TvSeries", + "Movie", + "Anime", + "Cartoon" + ) + + iconUrl = "https://animedekho.com/wp-content/uploads/2023/07/AnimeDekho-Logo-300x-1.pngg" +} diff --git a/AnimeDekhoProvider/src/main/AndroidManifest.xml b/AnimeDekhoProvider/src/main/AndroidManifest.xml new file mode 100644 index 00000000..01dbafa1 --- /dev/null +++ b/AnimeDekhoProvider/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/AnimeDekhoProvider/src/main/kotlin/com/anon/AnimeDekhoPlugin.kt b/AnimeDekhoProvider/src/main/kotlin/com/anon/AnimeDekhoPlugin.kt new file mode 100644 index 00000000..4e71f19a --- /dev/null +++ b/AnimeDekhoProvider/src/main/kotlin/com/anon/AnimeDekhoPlugin.kt @@ -0,0 +1,21 @@ +package com.anon + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context +// import com.lagradost.cloudstream3.utils.ExtractorApi +// import com.lagradost.cloudstream3.utils.extractorApis + +@CloudstreamPlugin +class AnimeDekhoPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(AnimeDekhoProvider()) + //addExtractor(MultiQualityXYZ()) + } + + // private fun addExtractor(element: ExtractorApi) { + // element.sourcePlugin = __filename + // extractorApis.add(0, element) + // } +} diff --git a/AnimeDekhoProvider/src/main/kotlin/com/anon/AnimeDekhoProvider.kt b/AnimeDekhoProvider/src/main/kotlin/com/anon/AnimeDekhoProvider.kt new file mode 100644 index 00000000..cecd5719 --- /dev/null +++ b/AnimeDekhoProvider/src/main/kotlin/com/anon/AnimeDekhoProvider.kt @@ -0,0 +1,198 @@ +package com.anon + +import android.util.Log + +import com.fasterxml.jackson.annotation.JsonProperty + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.extractors.DoodLaExtractor +import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.AppUtils.parseJson +import com.lagradost.nicehttp.Requests +import com.lagradost.nicehttp.Session +import kotlinx.coroutines.delay +import org.jsoup.nodes.Element + +import com.lagradost.cloudstream3.network.WebViewResolver +import com.lagradost.nicehttp.requestCreator + +import org.jsoup.Jsoup +import java.util.regex.Pattern +import okhttp3.Interceptor +import okhttp3.Response + +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import com.lagradost.cloudstream3.utils.AppUtils.toJson +import com.lagradost.nicehttp.RequestBodyTypes +import okhttp3.RequestBody.Companion.toRequestBody + +import com.lagradost.cloudstream3.extractors.helper.AesHelper.cryptoAESHandler + + +class AnimeDekhoProvider : MainAPI() { // all providers must be an instance of MainAPI + override var mainUrl = "https://animedekho.com/" + override var name = "Anime Dekho" + + override val hasMainPage = true + + override var lang = "hi" + override val hasDownloadSupport = true + + override val supportedTypes = setOf( + TvType.TvSeries, + TvType.Movie + ) + + override val mainPage = mainPageOf( + "/series/" to "Series", + "/movie/" to "Movies", + "/category/anime/" to "Anime", + "/category/cartoon/" to "Cartoon", + ) + + override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { + val link = "$mainUrl${request.data}" + val document = app.get(link).document + //Log.d("TAGNAME", "$document") + val home = document.select("article").mapNotNull { + it.toSearchResult() + } + return newHomePageResponse(request.name, home) + } + + + + private fun Element.toSearchResult(): AnimeSearchResponse? { + //val href = fixUrl(this.selectFirst("a")?.attr("href") ?: return null) + val href = this.selectFirst("a.lnk-blk")?.attr("href") ?: "null" + var title = this.selectFirst("header h2")?.text() ?: "null" + val posterUrl = this.selectFirst("div figure img")?.attr("src") ?: "null" + + return newAnimeSearchResponse(title, href, TvType.Anime) { + this.posterUrl = posterUrl + } + } + + override suspend fun search(query: String): List { + val document = app.get("$mainUrl/?s=$query").document + //return document.select("div.post-filter-image").mapNotNull { + return document.select("ul[data-results] li article").mapNotNull { + it.toSearchResult() + } + } + + override suspend fun load(url: String): LoadResponse? { + + val document = app.get(url).document + + var title = document?.selectFirst("h1.entry-title")?.text()?.trim() ?: (document?.selectFirst("h3")?.text()?.trim() ?: "Null title") + val poster = document?.selectFirst("div.post-thumbnail figure img")?.attr("src") ?: "null" + val plot = document?.selectFirst("div.entry-content p")?.text()?.trim() ?: "null" + val year = document?.selectFirst("span.year")?.text()?.trim()?.toInt() ?: 1990 + + var episodes = mutableListOf() + + val items = document.select("ul.seasons-lst li").mapNotNull { + val name = it?.selectFirst("h3.title")?.text() ?: "null" + + val tempstring = it?.selectFirst("a")?.attr("href") ?: "null" + + episodes.add( Episode(tempstring, name) ) + } + + if(items.size==0){ + val vidtoonoid = document?.selectFirst("iframe")?.attr("src") ?: "NULL" + val vidlink = app.get(vidtoonoid)?.document?.selectFirst("div iframe")?.attr("src") ?: "null" + return newMovieLoadResponse(title, vidlink, TvType.Movie, vidlink) { + this.posterUrl = poster.toString() + this.plot = plot + this.year = year + //this.recommendations = recommendations + } + } + else{ + return newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { + this.posterUrl = poster.toString() + this.plot = plot + this.year = year + //this.recommendations = recommendations + } + } + + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + + var vidlink = "" + + if(data.contains("https://vidxstream.xyz")){ + vidlink = data + } + else{ + + val page1 = app.get(data).document + + val name = page1?.selectFirst("body")?.attr("class") ?: "null" + + var term = Regex("""\bterm-(\d+)\b""").find(name)?.value!!?.replace("term-","") + + + vidlink = app.get("https://animedekho.com/?trembed=0&trid="+term) + .document?.selectFirst("iframe")?.attr("src") ?: "null" + } + + //Log.d("TAGNAME", "vidlink $vidlink") //https://vidxstream.xyz/v/H0Rh3ixVLJKk/ + + val body = app.get(vidlink).text + + + val master = Regex("""JScript[\w+]?\s*=\s*'([^']+)""").find(body)!!.groupValues?.get(1) + + val decrypt = cryptoAESHandler(master ?: return false, "4MmH9EsZrq0WEekn".toByteArray(), false)?.replace("\\", "") ?: "ERROR" + + val vidfinal = Regex("""file:\s*\"(https:[^\"]+)\"""").find(decrypt)!!.groupValues?.get(1) + + + val headers = mapOf( + "accept" to "*/*", + "accept-language" to "en-US,en;q=0.5", + "Origin" to "https://vidxstream.xyz", + "Accept-Encoding" to "gzip, deflate, br", + "Connection" to "keep-alive", + //"Referer" to "https://vidxstream.xyz/", + "Sec-Fetch-Dest" to "empty", + "Sec-Fetch-Mode" to "cors", + "Sec-Fetch-Site" to "cross-site", + "user-agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/116.0", + ) + + callback.invoke( + ExtractorLink( + source = "Toon", + name = "Toon", + url = vidfinal!!, + referer = "https://vidxstream.xyz/", + quality = Qualities.Unknown.value, + isM3u8 = true, + headers = headers, + + ) + ) + + + + + return true + + + } + + +} + From 53d3519b8fff2e636e14aafc4453358453bb7eae Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 4 Jan 2024 15:29:33 +0700 Subject: [PATCH 034/125] fix #491 --- SoraStream/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Extractors.kt | 5 ---- .../main/kotlin/com/hexated/SoraExtractor.kt | 29 ++++++++++++------- .../kotlin/com/hexated/SoraStreamPlugin.kt | 1 - 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index f157e229..2bc22cc2 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 = 212 +version = 213 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt index 1674ebc2..880238b5 100644 --- a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -396,11 +396,6 @@ class Embedwish : Filesim() { override val name = "Embedwish" override var mainUrl = "https://embedwish.com" } - -class Vidplay2 : Vidplay() { - override val mainUrl = "https://vidplay.online" -} - class Flaswish : Filesim() { override val name = "Flaswish" override var mainUrl = "https://flaswish.com" diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 5e556735..8745e4e7 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -715,7 +715,7 @@ object SoraExtractor : SoraStream() { child.select("span").text().equals("Episode $episode", true) }?.attr("href") } - }.filter { it.first.contains(Regex("(2160p)|(1080p)")) } + }.filter { it.first.contains(Regex("(2160p)|(1080p)")) }.reversed().takeLast(3) iframeList.apmap { (quality, link) -> val driveLink = bypassHrefli(link ?: return@apmap) @@ -768,16 +768,25 @@ object SoraExtractor : SoraStream() { val hTag = if (season == null) "h5" else "h3" val aTag = if (season == null) "Download Now" else "V-Cloud" val sTag = if (season == null) "" else "(Season $season|S$seasonSlug)" - val entry = res.select("div.entry-content > $hTag:matches((?i)$sTag.*(1080p|2160p))").findLast { element -> !element.text().contains("Download", true) } - ?: return - val tags = """(?:1080p|2160p)(.*)""".toRegex().find(entry.text())?.groupValues?.get(1)?.trim() - val href = entry.nextElementSibling()?.select("a:contains($aTag)")?.attr("href") - val selector = if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)" - val server = app.get(href - ?: return, interceptor = wpredisInterceptor).document.selectFirst("div.entry-content > $selector")?.attr("href") - ?: return + val entries = res.select("div.entry-content > $hTag:matches((?i)$sTag.*(1080p|2160p))").filter { element -> !element.text().contains("Download", true) }.takeLast(2) + entries.apmap { + val tags = """(?:1080p|2160p)(.*)""".toRegex().find(it.text())?.groupValues?.get(1)?.trim() + val href = it.nextElementSibling()?.select("a:contains($aTag)")?.attr("href") + val selector = if (season == null) "p a:contains(V-Cloud)" else "h4:matches(0?$episode) + p a:contains(V-Cloud)" + val server = app.get( + href ?: return@apmap, interceptor = wpredisInterceptor + ).document.selectFirst("div.entry-content > $selector") + ?.attr("href") ?: return@apmap - loadCustomTagExtractor(tags, server, "$api/", subtitleCallback, callback, getIndexQuality(entry.text())) + loadCustomTagExtractor( + tags, + server, + "$api/", + subtitleCallback, + callback, + getIndexQuality(it.text()) + ) + } } suspend fun invokeHdmovies4u(title: String? = null, imdbId: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt index c6cd296e..d2456f6e 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt @@ -28,7 +28,6 @@ class SoraStreamPlugin: Plugin() { registerExtractorAPI(Wishfast()) registerExtractorAPI(Uploadever()) registerExtractorAPI(Netembed()) - registerExtractorAPI(Vidplay2()) registerExtractorAPI(Flaswish()) registerExtractorAPI(Comedyshow()) } From caca55f9ec65c2937720afcff0c04488cfcc8484 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 4 Jan 2024 17:47:26 +0700 Subject: [PATCH 035/125] Gomov: update domain --- Gomov/build.gradle.kts | 2 +- Gomov/src/main/kotlin/com/hexated/DutaMovie.kt | 2 +- Gomov/src/main/kotlin/com/hexated/Ngefilm.kt | 2 +- Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt | 2 +- Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index dd797cdd..d4cc776c 100644 --- a/Gomov/build.gradle.kts +++ b/Gomov/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.konan.properties.Properties // use an integer for version numbers -version = 29 +version = 30 android { defaultConfig { diff --git a/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt index 0643ffe2..64ebf253 100644 --- a/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt +++ b/Gomov/src/main/kotlin/com/hexated/DutaMovie.kt @@ -6,7 +6,7 @@ import com.lagradost.cloudstream3.utils.httpsify import com.lagradost.cloudstream3.utils.loadExtractor class DutaMovie : Gomov() { - override var mainUrl = "https://drama.dutamovie21.tech/" + override var mainUrl = "https://yandex.dutamovie21.tech" override var name = "DutaMovie" override val mainPage = mainPageOf( "category/box-office/page/%d/" to "Box Office", diff --git a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt index 5061d790..a54a5003 100644 --- a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt +++ b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt @@ -3,7 +3,7 @@ package com.hexated import com.lagradost.cloudstream3.mainPageOf class Ngefilm : Gomov() { - override var mainUrl = "https://tv2.ngefilm21.homes" + override var mainUrl = "https://tv3.ngefilm21.homes" 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", diff --git a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt index c697f403..90de7c15 100644 --- a/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt +++ b/Gomov/src/main/kotlin/com/hexated/Nodrakorid.kt @@ -9,7 +9,7 @@ import org.jsoup.nodes.Element import java.net.URI class Nodrakorid : Gomov() { - override var mainUrl = "https://no-dra-kor-id.shop" + override var mainUrl = "https://no1.nodrakor.store" override var name = "Nodrakorid" override val mainPage = mainPageOf( diff --git a/Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt b/Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt index aabb0ecd..e6053bf6 100644 --- a/Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt +++ b/Gomov/src/main/kotlin/com/hexated/Pusatfilm.kt @@ -6,7 +6,7 @@ import com.lagradost.cloudstream3.TvSeriesLoadResponse import com.lagradost.cloudstream3.* class Pusatfilm : Gomov() { - override var mainUrl = "https://tv2.pusatfilm21.art" + override var mainUrl = "https://pusatfilm21.vip" override var name = "Pusatfilm" override val mainPage = mainPageOf( "film-terbaru/page/%d/" to "Film Terbaru", From 0740da3b1aec660dc96d342d74b430b89d64b391 Mon Sep 17 00:00:00 2001 From: alex Date: Sat, 6 Jan 2024 09:15:23 +0700 Subject: [PATCH 036/125] fix #497 --- SoraStream/build.gradle.kts | 2 +- SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 2bc22cc2..7ee3b812 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 = 213 +version = 214 android { defaultConfig { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 8745e4e7..07b6c2cf 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1467,7 +1467,7 @@ object SoraExtractor : SoraStream() { "_ApplicationId": "SHOWFLIXAPPID", "_JavaScriptKey": "SHOWFLIXMASTERKEY", "_ClientVersion": "js3.4.1", - "_InstallationId": "6d19fd87-a0e8-47b2-a3c0-48c16add928b" + "_InstallationId": "d92d98d3-fa49-4103-8dcf-6347c86942a7" } """.trimIndent().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull()) From fd5d4afc228cf15617bc80e12a0507789dc249c6 Mon Sep 17 00:00:00 2001 From: alex Date: Sat, 6 Jan 2024 09:28:31 +0700 Subject: [PATCH 037/125] fix Samehadaku --- Samehadaku/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/Samehadaku.kt | 128 +++++++++--------- 2 files changed, 67 insertions(+), 63 deletions(-) diff --git a/Samehadaku/build.gradle.kts b/Samehadaku/build.gradle.kts index 0ef8f5ed..e816d7c9 100644 --- a/Samehadaku/build.gradle.kts +++ b/Samehadaku/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 19 +version = 20 cloudstream { diff --git a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt index b31f4c7e..666202be 100644 --- a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt +++ b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt @@ -4,6 +4,7 @@ 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.network.CloudflareKiller import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.loadExtractor @@ -16,11 +17,11 @@ class Samehadaku : MainAPI() { override var lang = "id" override val hasDownloadSupport = true override val supportedTypes = setOf( - TvType.Anime, - TvType.AnimeMovie, - TvType.OVA + TvType.Anime, + TvType.AnimeMovie, + TvType.OVA ) - + private val interceptor = CloudflareKiller() companion object { const val acefile = "https://acefile.co" @@ -40,18 +41,18 @@ class Samehadaku : MainAPI() { } override val mainPage = mainPageOf( - "$mainUrl/page/" to "Episode Terbaru", - "$mainUrl/" to "HomePage", + "$mainUrl/page/" to "Episode Terbaru", + "$mainUrl/" to "HomePage", ) override suspend fun getMainPage( - page: Int, - request: MainPageRequest + page: Int, + request: MainPageRequest ): HomePageResponse { val items = mutableListOf() if (request.name != "Episode Terbaru" && page <= 1) { - val doc = app.get(request.data).document + val doc = app.get(request.data, interceptor = interceptor).document 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 { @@ -62,7 +63,7 @@ class Samehadaku : MainAPI() { } if (request.name == "Episode Terbaru") { - val home = app.get(request.data + page).document.selectFirst("div.post-show")?.select("ul li") + val home = app.get(request.data + page, interceptor = interceptor).document.selectFirst("div.post-show")?.select("ul li") ?.mapNotNull { it.toSearchResult() } ?: throw ErrorLoadingException("No Media Found") @@ -75,19 +76,20 @@ class Samehadaku : MainAPI() { private fun Element.toSearchResult(): AnimeSearchResponse? { val title = this.selectFirst("div.title, h2.entry-title a, div.lftinfo h2")?.text()?.trim() - ?: return null + ?: return null val href = fixUrlNull(this.selectFirst("a")?.attr("href") ?: return null) val posterUrl = fixUrlNull(this.select("img").attr("src")) val epNum = this.selectFirst("div.dtla author")?.text()?.toIntOrNull() return newAnimeSearchResponse(title, href ?: return null, TvType.Anime) { this.posterUrl = posterUrl addSub(epNum) + posterHeaders = interceptor.getCookieHeaders(mainUrl).toMap() } } override suspend fun search(query: String): List { - val document = app.get("$mainUrl/?s=$query").document + val document = app.get("$mainUrl/?s=$query", interceptor = interceptor).document return document.select("main#main div.animepost").mapNotNull { it.toSearchResult() } @@ -97,10 +99,10 @@ class Samehadaku : MainAPI() { val fixUrl = if (url.contains("/anime/")) { url } else { - app.get(url).document.selectFirst("div.nvs.nvsc a")?.attr("href") + app.get(url, interceptor = interceptor).document.selectFirst("div.nvs.nvsc a")?.attr("href") } - val document = app.get(fixUrl ?: return null).document + val document = app.get(fixUrl ?: return null, interceptor = interceptor).document val title = document.selectFirst("h1.entry-title")?.text()?.removeBloat() ?: return null val poster = document.selectFirst("div.thumb > img")?.attr("src") val tags = document.select("div.genre-info > a").map { it.text() } @@ -108,11 +110,11 @@ class Samehadaku : MainAPI() { Regex("\\d,\\s(\\d*)").find(it)?.groupValues?.getOrNull(1)?.toIntOrNull() } val status = getStatus( - document.selectFirst("div.spe > span:contains(Status)")?.ownText() ?: return null + document.selectFirst("div.spe > span:contains(Status)")?.ownText() ?: return null ) val type = - getType(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") @@ -120,7 +122,7 @@ class Samehadaku : MainAPI() { val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull { val header = it.selectFirst("span.lchx > a") ?: return@mapNotNull null val episode = Regex("Episode\\s?(\\d+)").find(header.text())?.groupValues?.getOrNull(1) - ?.toIntOrNull() + ?.toIntOrNull() val link = fixUrl(header.attr("href")) Episode(link, episode = episode) }.reversed() @@ -145,73 +147,75 @@ class Samehadaku : MainAPI() { this.recommendations = recommendations addMalId(tracker?.malId) addAniListId(tracker?.aniId?.toIntOrNull()) + posterHeaders = interceptor.getCookieHeaders(mainUrl).toMap() } } override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit ): Boolean { - val document = app.get(data).document + val document = app.get(data, interceptor = interceptor).document argamap( - { - document.select("div#server ul li div").apmap { - val dataPost = it.attr("data-post") - val dataNume = it.attr("data-nume") - val dataType = it.attr("data-type") + { + document.select("div#server ul li div").apmap { + val dataPost = it.attr("data-post") + val dataNume = it.attr("data-nume") + val dataType = it.attr("data-type") - val iframe = app.post( - url = "$mainUrl/wp-admin/admin-ajax.php", - data = mapOf( - "action" to "player_ajax", - "post" to dataPost, - "nume" to dataNume, - "type" to dataType - ), - referer = data, - headers = mapOf("X-Requested-With" to "XMLHttpRequest"), - ).document.select("iframe").attr("src") + val iframe = app.post( + url = "$mainUrl/wp-admin/admin-ajax.php", + data = mapOf( + "action" to "player_ajax", + "post" to dataPost, + "nume" to dataNume, + "type" to dataType + ), + referer = data, + headers = mapOf("X-Requested-With" to "XMLHttpRequest"), + interceptor = interceptor + ).document.select("iframe").attr("src") - loadFixedExtractor(fixedIframe(iframe), it.text(), "$mainUrl/", subtitleCallback, callback) + loadFixedExtractor(fixedIframe(iframe), it.text(), "$mainUrl/", subtitleCallback, callback) - } - }, - { - document.select("div#downloadb li").map { el -> - el.select("a").apmap { - loadFixedExtractor(fixedIframe(it.attr("href")), el.select("strong").text(), "$mainUrl/", subtitleCallback, callback) + } + }, + { + document.select("div#downloadb li").map { el -> + el.select("a").apmap { + loadFixedExtractor(fixedIframe(it.attr("href")), el.select("strong").text(), "$mainUrl/", subtitleCallback, callback) + } } } - } ) return true } private suspend fun loadFixedExtractor( - url: String, - name: String, - referer: String? = null, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit + url: String, + name: 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, - name.fixQuality(), - link.type, - link.headers, - link.extractorData - ) + ExtractorLink( + link.name, + link.name, + link.url, + link.referer, + name.fixQuality(), + link.type, + link.headers, + link.extractorData + ) ) } } From 1f461af2a116ded2b4f372df85ebacab7d0c3a98 Mon Sep 17 00:00:00 2001 From: alex Date: Sat, 6 Jan 2024 13:00:38 +0700 Subject: [PATCH 038/125] fix #494 --- .../src/main/kotlin/com/hexated/Samehadaku.kt | 2 +- TimefourTv/build.gradle.kts | 2 +- .../src/main/kotlin/com/hexated/TimefourTv.kt | 304 ++++++++---------- .../kotlin/com/hexated/TimefourTvExtractor.kt | 136 -------- 4 files changed, 135 insertions(+), 309 deletions(-) delete mode 100644 TimefourTv/src/main/kotlin/com/hexated/TimefourTvExtractor.kt diff --git a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt index 666202be..144f8fd6 100644 --- a/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt +++ b/Samehadaku/src/main/kotlin/com/hexated/Samehadaku.kt @@ -21,7 +21,7 @@ class Samehadaku : MainAPI() { TvType.AnimeMovie, TvType.OVA ) - private val interceptor = CloudflareKiller() + private val interceptor by lazy { CloudflareKiller() } companion object { const val acefile = "https://acefile.co" diff --git a/TimefourTv/build.gradle.kts b/TimefourTv/build.gradle.kts index 7a9bafec..a5a44fd9 100644 --- a/TimefourTv/build.gradle.kts +++ b/TimefourTv/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 20 +version = 21 cloudstream { diff --git a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt index e301ae02..17256e0a 100644 --- a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt +++ b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt @@ -1,220 +1,182 @@ package com.hexated -import com.hexated.TimefourTvExtractor.getBaseUrl -import com.hexated.TimefourTvExtractor.getLink import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.AppUtils +import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.M3u8Helper -import org.jsoup.Jsoup import org.jsoup.nodes.Element +import java.net.URI -open class TimefourTv : MainAPI() { - final override var mainUrl = "https://time4tv.stream" - var daddyUrl = "https://daddylivehd.com" +class TimefourTv : MainAPI() { + override var mainUrl = "https://dlhd.sx" override var name = "Time4tv" override val hasDownloadSupport = false override val hasMainPage = true - private val time4tvPoster = "$mainUrl/images/logo.png" override val supportedTypes = setOf( - TvType.Live + TvType.Live ) + private val homePoster = + "https://cdn.discordapp.com/attachments/1109266606292488297/1193060449193840681/Screenshot_2024-01-06_at_12-14-16_Logo_Maker_Used_By_2.3_Million_Startups.png" + private val detailPoster = + "https://cdn.discordapp.com/attachments/1109266606292488297/1193060448929595454/Screenshot_2024-01-06_at_12-13-02_Logo_Maker_Used_By_2.3_Million_Startups.png" + override val mainPage = mainPageOf( -// "$mainUrl/tv-channels" to "All Channels", -// "$mainUrl/usa-channels" to "USA Channels", -// "$mainUrl/uk-channels" to "UK Channels", -// "$mainUrl/sports-channels" to "Sport Channels", -// "$mainUrl/live-sports-streams" to "Live Sport Channels", -// "$mainUrl/news-channels" to "News Channels", -// "$mainUrl/schedule.php" to "Schedule", - "$daddyUrl/24-7-channels.php" to "DaddyHD Channels" + "$mainUrl/24-7-channels.php" to "24/7 Channels", + "$mainUrl/schedule/schedule-generated.json" to "Schedule Channels" ) - private fun fixDetailLink(link: String?): String? { - if (link == null) return null - return if (link.startsWith("/")) "$daddyUrl$link" else link - } - override suspend fun getMainPage( - page: Int, - request: MainPageRequest + page: Int, + request: MainPageRequest ): HomePageResponse { val items = mutableListOf() - val nonPaged = request.name != "All Channels" && page <= 1 - if (nonPaged) { - val res = app.get("${request.data}.php").document - val home = res.select("div.tab-content ul li").mapNotNull { - it.toSearchResult() + if (request.name == "24/7 Channels") { + val req = app.get(request.data) + mainUrl = getBaseUrl(req.url) + val res = req.document + val channels = res.select("div.grid-container div.grid-item").mapNotNull { + it.toSearchResponse() } - if (home.isNotEmpty()) items.add(HomePageList(request.name, home, true)) - } - if (request.name == "All Channels") { - val res = if (page == 1) { - app.get("${request.data}.php").document - } else { - app.get("${request.data}${page.minus(1)}.php").document + if (channels.isNotEmpty()) items.add(HomePageList(request.name, channels, true)) + } else { + val res = app.get(request.data).parsedSafe>>>() + res?.forEach { tag -> + val header = tag.key + val channels = tag.value.mapNotNull { + LiveSearchResponse( + it.key, + Item(it.key, items = it.value.toJson()).toJson(), + this@TimefourTv.name, + TvType.Live, + posterUrl = homePoster, + ) + } + if (channels.isNotEmpty()) items.add(HomePageList(header, channels, true)) } - val home = res.select("div.tab-content ul li").mapNotNull { - it.toSearchResult() - } - if (home.isNotEmpty()) items.add(HomePageList(request.name, home, true)) } - if (nonPaged && request.name == "DaddyHD Channels") { - val res = app.get(request.data).document - val channelDaddy = res.select("div.grid-container div.grid-item").mapNotNull { - it.toSearchDaddy() - } - if (channelDaddy.isNotEmpty()) items.add(HomePageList(request.name, channelDaddy, true)) - } - - if (nonPaged && request.name == "Schedule") { - val res = app.get(request.data).document - val schedule = res.select("div.search_p h1,div.search_p h2").mapNotNull { - it.toSearchSchedule() - } - if (schedule.isNotEmpty()) items.add(HomePageList(request.name, schedule, true)) - } - - return newHomePageResponse(items) + return newHomePageResponse(items, false) } - private fun Element.toSearchDaddy(): LiveSearchResponse? { + private fun Element.toSearchResponse(): LiveSearchResponse { + val title = this.select("strong").text() + val href = fixUrl(this.select("a").attr("href")) return LiveSearchResponse( - this.select("strong").text() ?: return null, - fixDetailLink(this.select("a").attr("href")) ?: return null, - this@TimefourTv.name, - TvType.Live, - posterUrl = time4tvPoster + title, + Item(title, href).toJson(), + this@TimefourTv.name, + TvType.Live, + posterUrl = homePoster, ) } - private fun Element.toSearchSchedule(): LiveSearchResponse? { - return LiveSearchResponse( - this.text() ?: return null, - this.text(), - this@TimefourTv.name, - TvType.Live, - posterUrl = time4tvPoster - ) - } - - private fun Element.toSearchResult(): LiveSearchResponse? { - return LiveSearchResponse( - this.selectFirst("div.channelName")?.text() ?: return null, - fixUrl(this.selectFirst("a")!!.attr("href")), - this@TimefourTv.name, - TvType.Live, - fixUrlNull(this.selectFirst("img")?.attr("src")), - ) - - } - override suspend fun search(query: String): List { - val document = app.get("$daddyUrl/24-7-channels.php").document + val document = app.get("$mainUrl/24-7-channels.php").document return document.select("div.grid-container div.grid-item:contains($query)").mapNotNull { - it.toSearchDaddy() + it.toSearchResponse() } } - private suspend fun loadSchedule(url: String): LoadResponse { - val name = url.removePrefix("$mainUrl/") - val doc = app.get("$mainUrl/schedule.php").document - val episode = mutableListOf() - doc.selectFirst("div.search_p h2:contains($name)")?.nextElementSiblings()?.toString() - ?.substringBefore("")?.map { - val desc = it.substringBefore(""), "").replace("

", "") - Jsoup.parse(it).select("span").map { ele -> - val title = ele.select("a").text() - val href = ele.select("a").attr("href") - episode.add( - Episode( - href, - title, - description = desc, - posterUrl = time4tvPoster - ) - ) - } + + override suspend fun load(url: String): LoadResponse { + val data = AppUtils.parseJson(url) + val episodes = if (data.items.isNullOrEmpty()) { + listOf(Episode(arrayListOf(Channels(data.title, data.url)).toJson())) + } else { + val items = AppUtils.parseJson>(data.items) + items.mapNotNull { + Episode( + data = it.channels?.toJson() ?: return@mapNotNull null, + name = "${it.event} - Live", + description = it.time, + posterUrl = detailPoster, + ) } - - return newTvSeriesLoadResponse(name, url, TvType.TvSeries, episode) { } - } - - override suspend fun load(url: String): LoadResponse? { - - val res = app.get(url) - daddyUrl = getBaseUrl(res.url) - if (!res.isSuccessful) return loadSchedule(url) - - val document = res.document - val title = - document.selectFirst("div.channelHeading h1")?.text() ?: document.selectFirst("title") - ?.text()?.substringBefore("HD")?.trim() ?: return null - val poster = - fixUrlNull(document.selectFirst("meta[property=\"og:image\"]")?.attr("content")) ?: time4tvPoster - val description = document.selectFirst("div.tvText")?.text() - ?: document.selectFirst("meta[name=description]")?.attr("content") ?: return null - val episodes = document.selectFirst("div.playit")?.attr("onclick")?.substringAfter("open('") - ?.substringBefore("',")?.let { link -> - val doc = app.get(link).document.selectFirst("div.tv_palyer iframe")?.attr("src") - ?.let { iframe -> - app.get(fixUrl(iframe), referer = link).document - } - if (doc?.select("div.stream_button").isNullOrEmpty()) { - doc?.select("iframe")?.mapIndexed { eps, ele -> - Episode( - fixUrl(ele.attr("src")), - "Server ${eps.plus(1)}" - ) - } - } else { - doc?.select("div.stream_button a")?.map { - Episode( - fixUrl(it.attr("href")), - it.text() - ) - } - } - } ?: listOf( - newEpisode( - document.selectFirst("div#content iframe#thatframe")?.attr("src") ?: return null - ) { - this.name = title - } - ) ?: throw ErrorLoadingException("Refresh page") - return newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { - this.posterUrl = poster - this.plot = description + return newTvSeriesLoadResponse( + data.title ?: "", + url, + TvType.TvSeries, + episodes = episodes + ) { + posterUrl = homePoster } + } override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit ): Boolean { - val link = when { - data.contains("/channel") -> app.get(data).document.selectFirst("div.tv_palyer iframe") - ?.attr("src") - data.startsWith(mainUrl) -> app.get( - data, - allowRedirects = false - ).document.selectFirst("iframe")?.attr("src") - else -> data - } ?: throw ErrorLoadingException() - getLink(fixUrl(link))?.let { m3uLink -> - val url = app.get(m3uLink, referer = "$mainServer/") + val json = AppUtils.parseJson>(data) + + json.apmap { + val iframe = app.get( + fixChannelUrl( + it.channel_id ?: return@apmap + ) + ).document.selectFirst("iframe#thatframe")?.attr("src") + ?: throw ErrorLoadingException("No Iframe Found") + val host = getBaseUrl(iframe) + val video = extractVideo(iframe) + M3u8Helper.generateM3u8( - this.name, - url.url, - "$mainServer/", + it.channel_name ?: return@apmap, + video ?: return@apmap, + "$host/", ).forEach(callback) } + return true } + private suspend fun extractVideo(url: String): String? { + val res = app.get(url, referer = mainUrl) + return Regex("""source:['"](\S+.m3u8)['"],""").find(res.text)?.groupValues?.getOrNull( + 1 + ) ?: run { + val scriptData = + res.document.selectFirst("div#player")?.nextElementSibling()?.data() + ?.substringAfterLast("return(")?.substringBefore(".join") + scriptData?.removeSurrounding("[", "]")?.replace("\"", "")?.split(",") + ?.joinToString("") + } + } + + private fun fixChannelUrl(url: String): String { + return if (url.startsWith(mainUrl)) { + url + } else { + "$mainUrl/stream/stream-$url.php" + } + } + + private fun getBaseUrl(url: String): String { + return URI(url).let { + "${it.scheme}://${it.host}" + } + } + + data class Item( + val title: String? = null, + val url: String? = null, + val items: String? = null, + ) + + data class Items( + val time: String? = null, + val event: String? = null, + val channels: ArrayList? = arrayListOf(), + ) + + data class Channels( + val channel_name: String? = null, + val channel_id: String? = null, + ) + } \ No newline at end of file diff --git a/TimefourTv/src/main/kotlin/com/hexated/TimefourTvExtractor.kt b/TimefourTv/src/main/kotlin/com/hexated/TimefourTvExtractor.kt deleted file mode 100644 index 60c415cb..00000000 --- a/TimefourTv/src/main/kotlin/com/hexated/TimefourTvExtractor.kt +++ /dev/null @@ -1,136 +0,0 @@ -package com.hexated - -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.fixUrl -import com.lagradost.cloudstream3.utils.getAndUnpack -import com.lagradost.nicehttp.NiceResponse -import java.net.URI - -var mainServer: String? = null - -object TimefourTvExtractor : TimefourTv() { - - fun getBaseUrl(url: String): String { - return URI(url).let { - "${it.scheme}://${it.host}" - } - } - - private suspend fun getSportLink(url: String): String? { - val iframe = app.get(url, referer = "$mainUrl/").document.select("iframe").attr("src") - .let { fixUrl(it) } - val ref = getBaseUrl(url) - val data = app.get(iframe, referer = ref).document.select("script") - .find { it.data().contains("eval(function(p,a,c,k,e,d)") }?.data() - .let { getAndUnpack(it.toString()) } - - mainServer = getBaseUrl(iframe) - - return Regex("var\\ssrc=['|\"](.*?.m3u8.*?)['|\"];").find(data)?.groupValues?.get(1) - - } - - private suspend fun getCricfreeLink(url: String, ref: String): String? { - val doc = app.get(url, referer = ref).document - val iframe = doc.select("iframe").attr("src") - val channel = iframe.split("/").last().removeSuffix(".php") - val refTwo = getBaseUrl(url) - - val docTwo = - app.get(fixUrl(iframe), referer = refTwo).document.selectFirst("script[src*=embed.]") - ?.attr("src") - val refThree = getBaseUrl(iframe) - val linkTwo = fixUrl("${docTwo?.replace(".js", ".php")}?player=desktop&live=$channel") - - val docThree = app.get( - linkTwo, - referer = "$refThree/", - ) - mainServer = getBaseUrl(linkTwo) - - val scriptData = docThree.document.selectFirst("div#player")?.nextElementSibling()?.data() - ?.substringAfterLast("return(")?.substringBefore(".join") - val link = scriptData?.removeSurrounding("[", "]")?.replace("\"", "")?.split(",") - ?.joinToString("") ?: return null - return app.get(link, referer = "$mainUrl/").url - } - - private suspend fun getFootyhunter(url: String, ref: String): String? { - val doc = app.get(url, referer = ref).document - val iframe = doc.selectFirst("iframe")?.attr("src") ?: return null - val referer = getBaseUrl(url) - val docTwo = app.get(fixUrl(iframe), referer = "$referer/").text - mainServer = getBaseUrl(iframe) - val link = Regex("""source:['|"](\S+.m3u8)['|"],""").find(docTwo)?.groupValues?.getOrNull(1) - ?: return null - return app.get(link, referer = "$mainUrl/").url - } - - suspend fun getLink(url: String): String? { - - if (url.contains("sportzonline") || url.contains("sportsonline")) { - return getSportLink(url) - } - - val daddyHost = daddyUrl.getHost() - - if(url.contains(daddyHost, true)) { - mainServer = getBaseUrl(url) - return getFinalLink(app.get(url, referer = daddyUrl)) - } - - val (channel, iframe) = if (url.contains("width=") || url.contains("/link")) { - val doc = app.get(url, referer = "$mainUrl/").document - val tempIframe = doc.selectFirst("iframe")?.attr("src") ?: return null - - if (tempIframe.contains("cricfree")) { - return getCricfreeLink(tempIframe, getBaseUrl(url)) - } - if (tempIframe.contains("footyhunter")) { - return getFootyhunter(tempIframe, getBaseUrl(url)) - } - - val doctwo = app.get(fixUrl(tempIframe), referer = url).text - listOf( - tempIframe.split("?").last().removePrefix("id=").replace(".php", ""), - doctwo.substringAfterLast("