diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4e558ec6..6a9cc822 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,7 +54,7 @@ jobs: ZSHOW_API: ${{ secrets.ZSHOW_API }} SFMOVIES_API: ${{ secrets.SFMOVIES_API }} CINEMATV_API: ${{ secrets.CINEMATV_API }} - OMOVIES_API: ${{ secrets.OMOVIES_API }} + GHOSTX_API: ${{ secrets.GHOSTX_API }} SUPERSTREAM_FIRST_API: ${{ secrets.SUPERSTREAM_FIRST_API }} SUPERSTREAM_SECOND_API: ${{ secrets.SUPERSTREAM_SECOND_API }} SUPERSTREAM_THIRD_API: ${{ secrets.SUPERSTREAM_THIRD_API }} @@ -73,7 +73,7 @@ jobs: echo ZSHOW_API=$ZSHOW_API >> local.properties echo SFMOVIES_API=$SFMOVIES_API >> local.properties echo CINEMATV_API=$CINEMATV_API >> local.properties - echo OMOVIES_API=$OMOVIES_API >> local.properties + echo GHOSTX_API=$GHOSTX_API >> local.properties echo SUPERSTREAM_FIRST_API=$SUPERSTREAM_FIRST_API >> local.properties echo SUPERSTREAM_SECOND_API=$SUPERSTREAM_SECOND_API >> local.properties echo SUPERSTREAM_THIRD_API=$SUPERSTREAM_THIRD_API >> local.properties diff --git a/Anichi/build.gradle.kts b/Anichi/build.gradle.kts index 643809b0..4201a7b2 100644 --- a/Anichi/build.gradle.kts +++ b/Anichi/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.konan.properties.Properties // use an integer for version numbers -version = 9 +version = 10 android { defaultConfig { @@ -38,5 +38,5 @@ cloudstream { "OVA", ) - iconUrl = "https://media.discordapp.net/attachments/1059306855865782282/1123970193274712096/Anichi.png" + iconUrl = "https://cdn.discordapp.com/attachments/1109266606292488297/1200425504432472176/Anichi.png" } \ No newline at end of file diff --git a/Anichi/src/main/kotlin/com/hexated/Anichi.kt b/Anichi/src/main/kotlin/com/hexated/Anichi.kt index bbad3ae7..0ddfae48 100644 --- a/Anichi/src/main/kotlin/com/hexated/Anichi.kt +++ b/Anichi/src/main/kotlin/com/hexated/Anichi.kt @@ -1,6 +1,5 @@ package com.hexated -import com.hexated.AnichiExtractors.invokeExternalSources import com.hexated.AnichiExtractors.invokeInternalSources import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addActors @@ -214,25 +213,12 @@ open class Anichi : MainAPI() { val loadData = parseJson(data) - argamap( - { - invokeInternalSources( - loadData.hash, - loadData.dubStatus, - loadData.episode, - subtitleCallback, - callback - ) - }, - { - invokeExternalSources( - loadData.idMal, - loadData.dubStatus, - loadData.episode, - subtitleCallback, - callback - ) - } + invokeInternalSources( + loadData.hash, + loadData.dubStatus, + loadData.episode, + subtitleCallback, + callback ) return true @@ -245,7 +231,6 @@ open class Anichi : MainAPI() { const val anilistApi = "https://graphql.anilist.co" const val jikanApi = "https://api.jikan.moe/v4" - const val marinHost = "https://marin.moe" private const val mainHash = "e42a4466d984b2c0a2cecae5dd13aa68867f634b16ee0f17b380047d14482406" private const val popularHash = "31a117653812a2547fd981632e8c99fa8bf8a75c4ef1a77a1567ef1741a7ab9c" diff --git a/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt b/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt index 86d452ed..a41b2c54 100644 --- a/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt +++ b/Anichi/src/main/kotlin/com/hexated/AnichiExtractors.kt @@ -121,67 +121,6 @@ object AnichiExtractors : Anichi() { } } - suspend fun invokeExternalSources( - idMal: Int? = null, - dubStatus: String, - episode: String, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, - ) { - val ids = app.get("https://api.malsync.moe/mal/anime/${idMal ?: return}") - .parsedSafe()?.sites - - if (dubStatus == "sub") invokeMarin(ids?.marin?.keys?.firstOrNull(), episode, callback) - - } - - private suspend fun invokeMarin( - id: String? = null, - episode: String, - callback: (ExtractorLink) -> Unit - ) { - val url = "$marinHost/anime/${id ?: return}/$episode" - val cookies = app.get( - "$marinHost/anime", - headers = mapOf( - "Cookie" to "__ddg1_=;__ddg2_=;" - ), - referer = "$marinHost/anime", - ).cookies.let { - decode(it["XSRF-TOKEN"].toString()) to decode(it["marin_session"].toString()) - } - - val json = app.get( - url, - headers = mapOf( - "Accept" to "text/html, application/xhtml+xml", - "Cookie" to "__ddg1=;__ddg2_=;XSRF-TOKEN=${cookies.first};marin_session=${cookies.second};", - "X-XSRF-TOKEN" to cookies.first - ), - referer = "$marinHost/anime/$id" - ).document.selectFirst("div#app")?.attr("data-page") - tryParseJson(json)?.props?.video?.data?.mirror?.map { video -> - callback.invoke( - ExtractorLink( - "Marin", - "Marin", - video.code?.file ?: return@map, - url, - video.code.height ?: Qualities.Unknown.value, - headers = mapOf( - "Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5", - "Accept-Language" to "en-US,en;q=0.5", - "Cookie" to "__ddg1=;__ddg2_=; XSRF-TOKEN=${cookies.first}; marin_session=${cookies.second};", - "Connection" to "keep-alive", - "Sec-Fetch-Dest" to "video", - "Sec-Fetch-Mode" to "cors", - "Sec-Fetch-Site" to "cross-site", - ) - ) - ) - } - } - private suspend fun invokeGogo( link: String, subtitleCallback: (SubtitleFile) -> Unit, diff --git a/Anichi/src/main/kotlin/com/hexated/AnichiParser.kt b/Anichi/src/main/kotlin/com/hexated/AnichiParser.kt index 6cbe56ec..8b9165eb 100644 --- a/Anichi/src/main/kotlin/com/hexated/AnichiParser.kt +++ b/Anichi/src/main/kotlin/com/hexated/AnichiParser.kt @@ -240,7 +240,6 @@ data class PageStatus( @JsonProperty("__typename") val _typename: String? = null ) - data class Recommendations( @JsonProperty("anyCard") val anyCard: AnyCard? = null, @JsonProperty("pageStatus") val pageStatus: PageStatus? = PageStatus(), @@ -255,38 +254,4 @@ data class QueryPopular( data class DataPopular( @JsonProperty("queryPopular") val queryPopular: QueryPopular? = QueryPopular() -) - -data class MALSyncSites( - @JsonProperty("Zoro") val zoro: HashMap>? = hashMapOf(), - @JsonProperty("Marin") val marin: HashMap>? = hashMapOf(), -) - -data class MALSyncResponses( - @JsonProperty("Sites") val sites: MALSyncSites? = null, -) - -data class MarinCode( - @JsonProperty("file") val file: String? = null, - @JsonProperty("height") val height: Int? = null, -) - -data class MarinMirror( - @JsonProperty("code") val code: MarinCode? = null, -) - -data class MarinData( - @JsonProperty("mirror") val mirror: ArrayList? = arrayListOf(), -) - -data class MarinVideos( - @JsonProperty("data") val data: MarinData? = null, -) - -data class MarinProps( - @JsonProperty("video") val video: MarinVideos? = null, -) - -data class MarinResponses( - @JsonProperty("props") val props: MarinProps? = null, ) \ No newline at end of file diff --git a/Gomov/build.gradle.kts b/Gomov/build.gradle.kts index d4cc776c..b9ed7bbb 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 = 30 +version = 31 android { defaultConfig { diff --git a/Gomov/src/main/kotlin/com/hexated/Gomov.kt b/Gomov/src/main/kotlin/com/hexated/Gomov.kt index b3eadaf1..908f2b62 100644 --- a/Gomov/src/main/kotlin/com/hexated/Gomov.kt +++ b/Gomov/src/main/kotlin/com/hexated/Gomov.kt @@ -10,7 +10,7 @@ import org.jsoup.nodes.Element import java.net.URI open class Gomov : MainAPI() { - override var mainUrl = "https://gomov.bio" + override var mainUrl = "https://gomov.co" private var directUrl: String? = null override var name = "Gomov" override val hasMainPage = true diff --git a/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt b/Gomov/src/main/kotlin/com/hexated/Ngefilm.kt index a54a5003..9ae96908 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://tv3.ngefilm21.homes" + override var mainUrl = "https://tv4.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 e6053bf6..02709fbc 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://pusatfilm21.vip" + override var mainUrl = "https://pf21.vip" override var name = "Pusatfilm" override val mainPage = mainPageOf( "film-terbaru/page/%d/" to "Film Terbaru", diff --git a/KuramanimeProvider/build.gradle.kts b/KuramanimeProvider/build.gradle.kts index 7d620269..ae77707b 100644 --- a/KuramanimeProvider/build.gradle.kts +++ b/KuramanimeProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 36 +version = 39 cloudstream { diff --git a/LayarKacaProvider/build.gradle.kts b/LayarKacaProvider/build.gradle.kts index 17b5bf69..2b098a66 100644 --- a/LayarKacaProvider/build.gradle.kts +++ b/LayarKacaProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 19 +version = 20 cloudstream { diff --git a/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt b/LayarKacaProvider/src/main/kotlin/com/hexated/LayarKacaProvider.kt index 05b9dcd0..60321ed5 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://tv7.lk21official.wiki" - private var seriesUrl = "https://tv9.nontondrama.click" + override var mainUrl = "https://tv10.lk21official.wiki" + private var seriesUrl = "https://tv11.nontondrama.click" override var name = "LayarKaca" override val hasMainPage = true override var lang = "id" diff --git a/Minioppai/src/main/kotlin/com/hexated/Extractors.kt b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt index 02582a4e..3b8b8470 100644 --- a/Minioppai/src/main/kotlin/com/hexated/Extractors.kt +++ b/Minioppai/src/main/kotlin/com/hexated/Extractors.kt @@ -36,12 +36,16 @@ open class Streampai : ExtractorApi() { val res = app.get(url, referer = referer).document val data = res.selectFirst("script:containsData(player =)")?.data() ?: return - val sources = data.substringAfter("sources: [").substringBefore("]").replace("\'", "\"") + val sources = data.substringAfter("sources: [").substringBefore("]") .addMarks("src") .addMarks("type") .addMarks("size") .replace("\'", "\"") + val tracks = data.substringAfter("tracks: [").substringBefore("]") + .replace("\'", "\"") + + tryParseJson>("[$sources]")?.forEach { callback.invoke( ExtractorLink( @@ -56,6 +60,15 @@ open class Streampai : ExtractorApi() { ) ) } + + tryParseJson>("[$tracks]")?.forEach { + subtitleCallback.invoke( + SubtitleFile( + fixTitle(it.label ?: return@forEach), + fixUrl(it.src) + ) + ) + } } private fun String.addMarks(str: String): String { @@ -65,6 +78,7 @@ open class Streampai : ExtractorApi() { data class Responses( @JsonProperty("src") val src: String, @JsonProperty("type") val type: String?, + @JsonProperty("label") val label: String?, @JsonProperty("size") val size: Int? ) diff --git a/Movierulzhd/build.gradle.kts b/Movierulzhd/build.gradle.kts index 71cc3ee9..a160c2b4 100644 --- a/Movierulzhd/build.gradle.kts +++ b/Movierulzhd/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 60 +version = 61 cloudstream { diff --git a/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt b/Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt index 11ceac40..d1dd6ce4 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.dog" + override var mainUrl = "https://movierulzhd.party" var directUrl = "" override var name = "Movierulzhd" override val hasMainPage = true diff --git a/Nimegami/build.gradle.kts b/Nimegami/build.gradle.kts index 9febe32e..29da8e82 100644 --- a/Nimegami/build.gradle.kts +++ b/Nimegami/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 9 +version = 11 cloudstream { diff --git a/Nimegami/src/main/kotlin/com/hexated/Extractors.kt b/Nimegami/src/main/kotlin/com/hexated/Extractors.kt index 3452bf15..f67b59d6 100644 --- a/Nimegami/src/main/kotlin/com/hexated/Extractors.kt +++ b/Nimegami/src/main/kotlin/com/hexated/Extractors.kt @@ -1,12 +1,8 @@ package com.hexated import com.fasterxml.jackson.annotation.JsonProperty -import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.ExtractorApi -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.INFER_TYPE -import com.lagradost.cloudstream3.utils.Qualities +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.* open class Mitedrive : ExtractorApi() { override val name = "Mitedrive" @@ -79,4 +75,21 @@ open class Berkasdrive : ExtractorApi() { } +} + +open class Videogami : ExtractorApi() { + override val name = "Videogami" + override val mainUrl = "https://video.nimegami.id" + override val requiresReferer = false + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val id = base64Decode(url.substringAfter("url=")).substringAfterLast("/") + loadExtractor("https://hxfile.co/embed-$id.html", "$mainUrl/", subtitleCallback, callback) + } + } \ No newline at end of file diff --git a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt index 88b16a36..8c8079cf 100644 --- a/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt +++ b/Nimegami/src/main/kotlin/com/hexated/Nimegami.kt @@ -81,7 +81,7 @@ class Nimegami : MainAPI() { override suspend fun search(query: String): List { val searchResponse = mutableListOf() for (i in 1..2) { - val res = app.get("$mainUrl/page/$i/?s=gintama&post_type=post").document.select("div.archive article") + val res = app.get("$mainUrl/page/$i/?s=$query&post_type=post").document.select("div.archive article") .mapNotNull { it.toSearchResult() } diff --git a/Nimegami/src/main/kotlin/com/hexated/NimegamiPlugin.kt b/Nimegami/src/main/kotlin/com/hexated/NimegamiPlugin.kt index 87802ce3..fe6de7b7 100644 --- a/Nimegami/src/main/kotlin/com/hexated/NimegamiPlugin.kt +++ b/Nimegami/src/main/kotlin/com/hexated/NimegamiPlugin.kt @@ -12,5 +12,6 @@ class NimegamiPlugin: Plugin() { registerMainAPI(Nimegami()) registerExtractorAPI(Mitedrive()) registerExtractorAPI(Berkasdrive()) + registerExtractorAPI(Videogami()) } } \ No newline at end of file diff --git a/OploverzProvider/build.gradle.kts b/OploverzProvider/build.gradle.kts index c847f3ae..bc8d4a59 100644 --- a/OploverzProvider/build.gradle.kts +++ b/OploverzProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 27 +version = 28 cloudstream { diff --git a/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt b/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt index 02a8f86d..dc673cb2 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/Extractors.kt @@ -27,10 +27,7 @@ open class Qiwi : ExtractorApi() { "$mainUrl/", getIndexQuality(title), headers = mapOf( - "Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5", "Range" to "bytes=0-", - "Sec-Fetch-Dest" to "video", - "Sec-Fetch-Mode" to "no-cors", ) ) ) @@ -42,39 +39,4 @@ 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 c2505aa9..00cd0b41 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.cool" + override var mainUrl = "https://oploverz.bio" 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 a635a694..ba7c0b85 100644 --- a/OploverzProvider/src/main/kotlin/com/hexated/OploverzProviderPlugin.kt +++ b/OploverzProvider/src/main/kotlin/com/hexated/OploverzProviderPlugin.kt @@ -11,6 +11,5 @@ 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/RebahinProvider/build.gradle.kts b/RebahinProvider/build.gradle.kts index 6f308335..0108e9c8 100644 --- a/RebahinProvider/build.gradle.kts +++ b/RebahinProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 8 +version = 9 cloudstream { diff --git a/RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt b/RebahinProvider/src/main/kotlin/com/hexated/Cgvindo.kt index da0cb643..945e4eca 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://198.54.124.245" + override var mainUrl = "http://cgvindo.lol" override var name = "Cgvindo" } diff --git a/SoraStream/build.gradle.kts b/SoraStream/build.gradle.kts index 12d64480..41837eab 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 = 218 +version = 220 android { defaultConfig { @@ -9,7 +9,7 @@ android { properties.load(project.rootProject.file("local.properties").inputStream()) buildConfigField("String", "TMDB_API", "\"${properties.getProperty("TMDB_API")}\"") - buildConfigField("String", "OMOVIES_API", "\"${properties.getProperty("OMOVIES_API")}\"") + buildConfigField("String", "GHOSTX_API", "\"${properties.getProperty("GHOSTX_API")}\"") buildConfigField("String", "CINEMATV_API", "\"${properties.getProperty("CINEMATV_API")}\"") buildConfigField("String", "SFMOVIES_API", "\"${properties.getProperty("SFMOVIES_API")}\"") buildConfigField("String", "ZSHOW_API", "\"${properties.getProperty("ZSHOW_API")}\"") diff --git a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt index b11a7d31..8026449c 100644 --- a/SoraStream/src/main/kotlin/com/hexated/Extractors.kt +++ b/SoraStream/src/main/kotlin/com/hexated/Extractors.kt @@ -436,9 +436,9 @@ class Streamwish : Filesim() { override var mainUrl = "https://streamwish.to" } -class Wishfast : Filesim() { - override val name = "Wishfast" - override var mainUrl = "https://wishfast.top" +class UqloadsXyz : Filesim() { + override val name = "Uqloads" + override var mainUrl = "https://uqloads.xyz" } class FilelionsTo : Filesim() { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 8cdb4848..b48cc5e1 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -1,7 +1,6 @@ package com.hexated import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.APIHolder.unixTime import com.lagradost.cloudstream3.APIHolder.unixTimeMS import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson @@ -125,8 +124,8 @@ object SoraExtractor : SoraStream() { httpsify(srcrcp), referer = iframedoc ).document.selectFirst("script:containsData(Playerjs)")?.data() - val video = script?.substringAfter("file:\"#2")?.substringBefore("\"") - ?.replace(Regex("/.*?=?="), "")?.let { base64Decode(it) } + val video = script?.substringAfter("file:\"#9")?.substringBefore("\"") + ?.replace(Regex("/@#@\\S+?=?="), "")?.let { base64Decode(it) } callback.invoke( ExtractorLink( @@ -136,66 +135,6 @@ object SoraExtractor : SoraStream() { ) } - 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() - } 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() - } ?: 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 ref = getBaseUrl(iframeDbgo) - decryptStreamUrl(source).split(",").map { links -> - val quality = Regex("\\[(\\d*p.*?)]").find(links)?.groupValues?.getOrNull(1)?.trim() - ?: 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) - ) - ) - } - } - - 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)) - } - - } - suspend fun invokeDreamfilm( title: String? = null, season: Int? = null, @@ -1788,21 +1727,21 @@ object SoraExtractor : SoraStream() { } suspend fun invokeSmashyStream( - imdbId: String? = null, + tmdbId: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { val url = if (season == null) { - "$smashyStreamAPI/playere.php?imdb=$imdbId" + "$smashyStreamAPI/playere.php?tmdb=$tmdbId" } else { - "$smashyStreamAPI/playere.php?imdb=$imdbId&season=$season&episode=$episode" + "$smashyStreamAPI/playere.php?tmdb=$tmdbId&season=$season&episode=$episode" } app.get( url, - referer = "https://smashystream.com/" + referer = "https://smashystream.xyz/" ).document.select("div#_default-servers a.server").map { it.attr("data-url") to it.text() }.apmap { @@ -1810,9 +1749,8 @@ object SoraExtractor : SoraStream() { "Player F" -> { invokeSmashyFfix(it.second, it.first, url, subtitleCallback, callback) } - - "Player D (Hindi)" -> { - invokeSmashyD(it.first, url, callback) + "Player SU" -> { + invokeSmashySu(it.second, it.first, url, callback) } else -> return@apmap @@ -1821,6 +1759,52 @@ object SoraExtractor : SoraStream() { } + suspend fun invokeMoflix( + tmdbId: Int? = null, + season: Int? = null, + episode: Int? = null, + callback: (ExtractorLink) -> Unit + ) { + val id = (if(season == null) { + "tmdb|movie|$tmdbId" + } else { + "tmdb|series|$tmdbId" + }).let { base64Encode(it.toByteArray()) } + + val loaderUrl = "$moflixAPI/api/v1/titles/$id?loader=titlePage" + val url = if(season == null) { + loaderUrl + } else { + val mediaId = app.get(loaderUrl, referer = "$moflixAPI/").parsedSafe()?.title?.id + "$moflixAPI/api/v1/titles/$mediaId/seasons/$season/episodes/$episode?loader=episodePage" + } + + val res = app.get(url, referer = "$moflixAPI/").parsedSafe() + (res?.episode ?: res?.title)?.videos?.filter { it.category.equals("full", true) }?.apmap { iframe -> + val response = app.get(iframe.src ?: return@apmap, referer = "$moflixAPI/") + val host = getBaseUrl(iframe.src) + val doc = response.document.selectFirst("script:containsData(sources:)")?.data() + val script = if (doc.isNullOrEmpty()) { + getAndUnpack(response.text) + } else { + doc + } + val m3u8 = Regex("file:\\s*\"(.*?m3u8.*?)\"").find(script ?: return@apmap)?.groupValues?.getOrNull(1) + if(m3u8?.haveDub("$host/") == false) return@apmap + callback.invoke( + ExtractorLink( + "Moflix", + "Moflix [${iframe.name}]", + m3u8 ?: return@apmap, + "$host/", + iframe.quality?.filter { it.isDigit() }?.toIntOrNull() ?: Qualities.Unknown.value, + INFER_TYPE + ) + ) + } + + } + //TODO only subs suspend fun invokeWatchsomuch( imdbId: String? = null, @@ -2100,11 +2084,11 @@ object SoraExtractor : SoraStream() { ?: return val ref = getBaseUrl(framesrc) val id = framesrc.substringAfter("id=").substringBefore("&") - loadExtractor("https://wishfast.top/e/$id", "$ref/", subtitleCallback, callback) + loadExtractor("https://uqloads.xyz/e/$id", "$ref/", subtitleCallback, callback) } - suspend fun invokeOmovies( + suspend fun invokeGhostx( title: String? = null, year: Int? = null, season: Int? = null, @@ -2117,8 +2101,8 @@ object SoraExtractor : SoraStream() { season, episode, callback, - BuildConfig.OMOVIES_API, - "Omovies", + BuildConfig.GHOSTX_API, + "Ghostx", base64Decode("X3NtUWFtQlFzRVRi"), base64Decode("X3NCV2NxYlRCTWFU") ) @@ -2136,7 +2120,7 @@ object SoraExtractor : SoraStream() { episodeSelector: String, ) { fun String.decrypt(key: String): List? { - return tryParseJson>(base64Decode(this).decodePrimewireXor(key)) + return tryParseJson>(base64Decode(this).xorDecrypt(key)) } val slug = getEpisodeSlug(season, episode) @@ -2148,8 +2132,10 @@ object SoraExtractor : SoraStream() { val savedCookies = mapOf( base64Decode("X2lkZW50aXR5Z29tb3ZpZXM3") to base64Decode("NTJmZGM3MGIwMDhjMGIxZDg4MWRhYzBmMDFjY2E4MTllZGQ1MTJkZTAxY2M4YmJjMTIyNGVkNGFhZmI3OGI1MmElM0EyJTNBJTdCaSUzQTAlM0JzJTNBMTglM0ElMjJfaWRlbnRpdHlnb21vdmllczclMjIlM0JpJTNBMSUzQnMlM0E1MiUzQSUyMiU1QjIwNTAzNjYlMkMlMjJIblZSUkFPYlRBU09KRXI0NVl5Q004d2lIb2wwVjFrbyUyMiUyQzI1OTIwMDAlNUQlMjIlM0IlN0Q="), ) - val req = app.get("$api/search/$query") - val doc = req.document + + var res = app.get("$api/search/$query") + val cookies = savedCookies + res.cookies + val doc = res.document val media = doc.select("div.$mediaSelector").map { Triple(it.attr("data-filmName"), it.attr("data-year"), it.select("a").attr("href")) }.let { el -> @@ -2172,45 +2158,38 @@ 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})") + app.get(fixUrl(media.third, api), cookies = cookies) + .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("-") } - 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) - } ?: return - val cookies = savedCookies + res.cookies + + res = app.get(fixUrl(iframe ?: return, api), cookies = cookies) 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 (serverId, episodeId) = if (season == null) { + url.substringAfterLast("/") to "0" + } else { + url.substringBeforeLast("/").substringAfterLast("/") to url.substringAfterLast("/") + .substringBefore("-") + } val serverRes = app.get( - "$api/user/servers/${users.first}?ep=${users.second}", + "$api/user/servers/$serverId?ep=$episodeId", 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 -> + ).document + serverRes.select("ul li").apmap { el -> val server = el.attr("data-value") val encryptedData = app.get( - "${fixUrl(serverUrl, api)}?server=$server&_=$unixTimeMS", + "$url?server=$server&_=$unixTimeMS", cookies = cookies, referer = url, headers = headers ).text - val links = encryptedData.decrypt(key) ?: encryptedData.decrypt(key2) ?: return@amap - links.forEach { video -> + val links = encryptedData.decrypt(base64Decode("MTEx")) + links?.forEach { video -> qualities.filter { it <= video.max.toInt() }.forEach { callback( ExtractorLink( @@ -2291,43 +2270,23 @@ object SoraExtractor : SoraStream() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { - val id = imdbId?.removePrefix("tt") - val slug = title.createSlug() - val url = if (season == null) { - "$cinemaTvAPI/movies/play/$id-$slug-$year" + val media = app.get("$cinemaTvAPI/v1/${if (season == null) "movies" else "shows"}?filters[q]=$title") + .parsedSafe()?.items?.find { + it.imdb_id?.removePrefix("tt") + .equals(imdbId?.removePrefix("tt")) || (it.title.equals( + title, + true + ) && it.year == year) + } ?: return + + val mediaId = if (season == null) { + media.id_movie } else { - "$cinemaTvAPI/shows/play/$id-$slug-$year" - } + app.get("$cinemaTvAPI/v1/shows?expand=episodes&id=${media.id_show}") + .parsedSafe()?.episodes?.find { it.episode == episode && it.season == season }?.id + } ?: return - 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", - ) - - val doc = app.get(url, headers = headers).document - val script = doc.selectFirst("script:containsData(hash:)")?.data() - val hash = Regex("hash:\\s*['\"](\\S+)['\"]").find(script ?: return)?.groupValues?.get(1) - val expires = Regex("expires:\\s*(\\d+)").find(script)?.groupValues?.get(1) - val episodeId = (if (season == null) { - """id_movie:\s*(\d+)""" - } else { - """episode:\s*['"]$episode['"],[\n\s]+id_episode:\s*(\d+),[\n\s]+season:\s*['"]$season['"]""" - }).let { it.toRegex().find(script)?.groupValues?.get(1) } - - val videoUrl = if (season == null) { - "$cinemaTvAPI/api/v1/security/movie-access?id_movie=$episodeId&hash=$hash&expires=$expires" - } else { - "$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("$cinemaTvAPI/v1/${if (season == null) "movies" else "episodes"}/view?expand=streams,subtitles&id=$mediaId").parsedSafe() sources?.streams?.mapKeys { source -> callback.invoke( @@ -2335,19 +2294,18 @@ object SoraExtractor : SoraStream() { "CinemaTv", "CinemaTv", source.value, - "$cinemaTvAPI/", + "", getQualityFromName(source.key), true ) ) } - sources?.subtitles?.map { sub -> - val file = sub.file.toString() + sources?.subtitles?.map { subtitleCallback.invoke( SubtitleFile( - sub.language ?: return@map, - if (file.startsWith("[")) return@map else fixUrl(file, cinemaTvAPI), + it.language ?: return@map, + fixUrl(it.url ?: return@map, cinemaTvAPI) ) ) } @@ -2410,37 +2368,25 @@ object SoraExtractor : SoraStream() { suspend fun invokeRidomovies( tmdbId: Int? = null, imdbId: String? = null, - title: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit, ) { - val slug = if (season == null) { - app.get("$ridomoviesAPI/core/api/search?q=$imdbId") - .parsedSafe()?.data?.items?.find { - it.contentable?.tmdbId == tmdbId || it.contentable?.imdbId == imdbId - }?.slug - } else { - app.get("$ridomoviesAPI/tv/${title.createSlug()}/season-$season/episode-$episode").text.substringAfterLast( - """postid\":\"""" - ).substringBefore("""\"""") - } ?: return - val url = if (season == null) { - "$ridomoviesAPI/core/api/movies/$slug/videos" - } else { - "$ridomoviesAPI/core/api/episodes/$slug/videos" - } + val mediaSlug = app.get("$ridomoviesAPI/core/api/search?q=$imdbId").parsedSafe()?.data?.items?.find { + it.contentable?.tmdbId == tmdbId || it.contentable?.imdbId == imdbId + }?.slug ?: return + + val id = season?.let { + val episodeUrl = "$ridomoviesAPI/tv/$mediaSlug/season-$it/episode-$episode" + app.get(episodeUrl).text.substringAfterLast("""postid\":\"""").substringBefore("""\""") + } ?: mediaSlug + + val url = "$ridomoviesAPI/core/api/${if (season == null) "movies" else "episodes"}/$id/videos" app.get(url).parsedSafe()?.data?.apmap { link -> val iframe = Jsoup.parse(link.url ?: return@apmap).select("iframe").attr("data-src") if (iframe.startsWith("https://closeload.top")) { - val unpacked = - getAndUnpack( - app.get( - iframe, - referer = "$ridomoviesAPI/" - ).text - ) + val unpacked = getAndUnpack(app.get(iframe, referer = "$ridomoviesAPI/").text) val video = Regex("=\"(aHR.*?)\";").find(unpacked)?.groupValues?.get(1) callback.invoke( ExtractorLink( diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt index fd388fbc..b09fa747 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraParser.kt @@ -47,6 +47,23 @@ data class AniwaveServer( } } +data class MoflixResponse( + @JsonProperty("title") val title: Episode? = null, + @JsonProperty("episode") val episode: Episode? = null, +) { + data class Episode( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("videos") val videos: ArrayList? = arrayListOf(), + ) { + data class Videos( + @JsonProperty("name") val name: String? = null, + @JsonProperty("category") val category: String? = null, + @JsonProperty("src") val src: String? = null, + @JsonProperty("quality") val quality: String? = null, + ) + } +} + data class AniMedia( @JsonProperty("id") var id: Int? = null, @JsonProperty("idMal") var idMal: Int? = null @@ -174,15 +191,31 @@ data class JikanResponse( @JsonProperty("data") val data: JikanData? = null, ) -data class CinemaTvSubtitles( - @JsonProperty("language") val language: String? = null, - @JsonProperty("file") val file: Any? = null, -) - data class CinemaTvResponse( + @JsonProperty("items") val items: ArrayList? = arrayListOf(), + @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf(), @JsonProperty("streams") val streams: HashMap? = null, - @JsonProperty("subtitles") val subtitles: ArrayList? = arrayListOf(), -) + @JsonProperty("subtitles") val subtitles: ArrayList? = arrayListOf(), + ) { + data class Items( + @JsonProperty("id_movie") val id_movie: Int? = null, + @JsonProperty("id_show") val id_show: Int? = null, + @JsonProperty("title") val title: String? = null, + @JsonProperty("year") val year: Int? = null, + @JsonProperty("imdb_id") val imdb_id: String? = null, + ) + + data class Episodes( + @JsonProperty("id") val id: Int? = null, + @JsonProperty("season") val season: Int? = null, + @JsonProperty("episode") val episode: Int? = null, + ) + + data class Subtitles( + @JsonProperty("language") val language: String? = null, + @JsonProperty("url") val url: String? = null, + ) +} data class VidsrctoResult( @JsonProperty("id") val id: String? = null, @@ -427,15 +460,6 @@ data class SmashySources( @JsonProperty("subtitleUrls") var subtitleUrls: String? = null, ) -data class SmashyDSources( - @JsonProperty("sourceUrls") var sourceUrls: ArrayList? = arrayListOf(), -) - -data class SmashyDSourcesUrls( - @JsonProperty("file") var file: String? = null, - @JsonProperty("title") var title: String? = null, -) - data class AoneroomResponse( @JsonProperty("data") val data: Data? = null, ) { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt index 9fdb1441..8d3033c4 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStream.kt @@ -6,7 +6,6 @@ import com.hexated.SoraExtractor.invokeAllMovieland import com.hexated.SoraExtractor.invokeAnimes import com.hexated.SoraExtractor.invokeAoneroom import com.hexated.SoraExtractor.invokeBollyMaza -import com.hexated.SoraExtractor.invokeDbgo import com.hexated.SoraExtractor.invokeFilmxy import com.hexated.SoraExtractor.invokeKimcartoon import com.hexated.SoraExtractor.invokeVidSrc @@ -36,15 +35,14 @@ import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeHdmovies4u import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies -import com.hexated.SoraExtractor.invokeSFMovies import com.hexated.SoraExtractor.invokeShowflix import com.hexated.SoraExtractor.invokeTvMovies import com.hexated.SoraExtractor.invokeUhdmovies import com.hexated.SoraExtractor.invokeVegamovies import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeCinemaTv -import com.hexated.SoraExtractor.invokeMMovies -import com.hexated.SoraExtractor.invokeOmovies +import com.hexated.SoraExtractor.invokeMoflix +import com.hexated.SoraExtractor.invokeGhostx import com.hexated.SoraExtractor.invokeWatchCartoon import com.hexated.SoraExtractor.invokeWatchsomuch import com.hexated.SoraExtractor.invokeZshow @@ -119,6 +117,7 @@ open class SoraStream : TmdbProvider() { const val aoneroomAPI = "https://api3.aoneroom.com" const val mMoviesAPI = "https://multimovies.uno" const val watchCartoonAPI = "https://www1.watchcartoononline.bz" + const val moflixAPI = "https://moflix-stream.xyz" const val fdMoviesAPI = "https://freedrivemovie.com" const val uhdmoviesAPI = "https://uhdmovies.zip" @@ -384,9 +383,6 @@ open class SoraStream : TmdbProvider() { { 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 @@ -466,7 +462,7 @@ open class SoraStream : TmdbProvider() { ) }, { - if (!res.isAnime) invokeOmovies( + if (!res.isAnime) invokeGhostx( res.title, res.year, res.season, @@ -547,7 +543,7 @@ open class SoraStream : TmdbProvider() { }, { if (!res.isAnime) invokeSmashyStream( - res.imdbId, + res.id, res.season, res.episode, subtitleCallback, @@ -587,7 +583,6 @@ open class SoraStream : TmdbProvider() { if (!res.isAnime) invokeRidomovies( res.id, res.imdbId, - res.title, res.season, res.episode, subtitleCallback, @@ -716,13 +711,7 @@ open class SoraStream : TmdbProvider() { ) }, { - 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) + if (!res.isAnime) invokeMoflix(res.id, 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 8bd35537..9c09c047 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamLite.kt @@ -4,7 +4,6 @@ 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 import com.hexated.SoraExtractor.invokeDoomovies import com.hexated.SoraExtractor.invokeDramaday import com.hexated.SoraExtractor.invokeDreamfilm @@ -24,13 +23,12 @@ import com.hexated.SoraExtractor.invokeDumpStream import com.hexated.SoraExtractor.invokeEmovies import com.hexated.SoraExtractor.invokeMultimovies import com.hexated.SoraExtractor.invokeNetmovies -import com.hexated.SoraExtractor.invokeSFMovies import com.hexated.SoraExtractor.invokeShowflix import com.hexated.SoraExtractor.invokeVidSrc import com.hexated.SoraExtractor.invokeVidsrcto import com.hexated.SoraExtractor.invokeCinemaTv -import com.hexated.SoraExtractor.invokeMMovies -import com.hexated.SoraExtractor.invokeOmovies +import com.hexated.SoraExtractor.invokeMoflix +import com.hexated.SoraExtractor.invokeGhostx import com.hexated.SoraExtractor.invokeWatchCartoon import com.hexated.SoraExtractor.invokeWatchsomuch import com.hexated.SoraExtractor.invokeZshow @@ -52,6 +50,9 @@ class SoraStreamLite : SoraStream() { val res = AppUtils.parseJson(data) argamap( + { + if (!res.isAnime) invokeMoflix(res.id, res.season, res.episode, callback) + }, { if (!res.isAnime) invokeWatchsomuch( res.imdbId, @@ -93,9 +94,6 @@ class SoraStreamLite : SoraStream() { { 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, @@ -137,7 +135,7 @@ class SoraStreamLite : SoraStream() { ) }, { - if (!res.isAnime) invokeOmovies( + if (!res.isAnime) invokeGhostx( res.title, res.year, res.season, @@ -156,7 +154,7 @@ class SoraStreamLite : SoraStream() { }, { if (!res.isAnime) invokeSmashyStream( - res.imdbId, + res.id, res.season, res.episode, subtitleCallback, @@ -226,7 +224,6 @@ class SoraStreamLite : SoraStream() { if (!res.isAnime) invokeRidomovies( res.id, res.imdbId, - res.title, res.season, res.episode, subtitleCallback, @@ -322,15 +319,6 @@ class SoraStreamLite : SoraStream() { 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 diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt index abc461c1..32957fd2 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraStreamPlugin.kt @@ -25,7 +25,7 @@ class SoraStreamPlugin: Plugin() { registerExtractorAPI(Streamwish()) registerExtractorAPI(FilelionsTo()) registerExtractorAPI(Embedwish()) - registerExtractorAPI(Wishfast()) + registerExtractorAPI(UqloadsXyz()) registerExtractorAPI(Uploadever()) registerExtractorAPI(Netembed()) registerExtractorAPI(Flaswish()) diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt index 6c7fde38..f6b3f13d 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraUtils.kt @@ -18,17 +18,12 @@ import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.nicehttp.NiceResponse import com.lagradost.nicehttp.RequestBodyTypes -import com.lagradost.nicehttp.Requests.Companion.await import com.lagradost.nicehttp.requestCreator import kotlinx.coroutines.delay import okhttp3.FormBody import okhttp3.HttpUrl.Companion.toHttpUrl -import okhttp3.Interceptor import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.OkHttpClient -import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody -import okhttp3.Response import org.jsoup.nodes.Document import java.math.BigInteger import java.net.* @@ -38,7 +33,6 @@ import java.security.spec.PKCS8EncodedKeySpec import java.security.spec.X509EncodedKeySpec import java.text.SimpleDateFormat import java.util.* -import java.util.concurrent.TimeUnit import javax.crypto.Cipher import javax.crypto.spec.GCMParameterSpec import javax.crypto.spec.IvParameterSpec @@ -427,21 +421,28 @@ suspend fun invokeSmashyFfix( } -suspend fun invokeSmashyD( +suspend fun invokeSmashySu( + name: String, url: String, ref: String, callback: (ExtractorLink) -> Unit, ) { val json = app.get(url, referer = ref, headers = mapOf("X-Requested-With" to "XMLHttpRequest")) - .parsedSafe() - json?.sourceUrls?.apmap { - M3u8Helper.generateM3u8( - "Smashy [Player D ${it.title}]", - it.file ?: return@apmap, - "" - ).forEach(callback) + .parsedSafe() + json?.sourceUrls?.firstOrNull()?.removeSuffix(",")?.split(",")?.forEach { links -> + val quality = Regex("\\[(\\S+)]").find(links)?.groupValues?.getOrNull(1) ?: return@forEach + val trimmedLink = links.removePrefix("[$quality]").trim() + callback.invoke( + ExtractorLink( + "Smashy [$name]", + "Smashy [$name]", + trimmedLink, + "", + getQualityFromName(quality), + INFER_TYPE + ) + ) } - } suspend fun getDumpIdAndType(title: String?, year: Int?, season: Int?): Pair { @@ -800,6 +801,10 @@ suspend fun getCrunchyrollIdFromMalSync(aniId: String?): String? { ?: regex.find("$crunchyroll")?.groupValues?.getOrNull(1) } +suspend fun String.haveDub(referer: String) : Boolean { + return app.get(this,referer=referer).text.contains("TYPE=AUDIO") +} + suspend fun convertTmdbToAnimeId( title: String?, date: String?, @@ -1034,7 +1039,7 @@ fun decodeIndexJson(json: String): String { return base64Decode(slug.substring(0, slug.length - 20)) } -fun String.decodePrimewireXor(key: String): String { +fun String.xorDecrypt(key: String): String { val sb = StringBuilder() var i = 0 while (i < this.length) { @@ -1060,9 +1065,9 @@ fun vidsrctoDecrypt(text: String): String { } fun String?.createSlug(): String? { - return this?.replace(Regex("[^\\w\\s-]"), "") - ?.replace(" ", "-") - ?.replace(Regex("( – )|( -)|(- )|(--)"), "-") + return this?.filter { it.isWhitespace() || it.isLetterOrDigit() } + ?.trim() + ?.replace("\\s+".toRegex(), "-") ?.lowercase() } @@ -1148,14 +1153,6 @@ fun getVipLanguage(str: String): String { } } -fun getDbgoLanguage(str: String): String { - return when (str) { - "Русский" -> "Russian" - "Українська" -> "Ukrainian" - else -> str - } -} - fun fixCrunchyrollLang(language: String?): String? { return SubtitleHelper.fromTwoLettersToLanguage(language ?: return null) ?: SubtitleHelper.fromTwoLettersToLanguage(language.substringBefore("-")) @@ -1212,37 +1209,6 @@ fun base64DecodeAPI(api: String): String { return api.chunked(4).map { base64Decode(it) }.reversed().joinToString("") } -fun decryptStreamUrl(data: String): String { - - fun getTrash(arr: List, item: Int): List { - val trash = ArrayList>() - for (i in 1..item) { - trash.add(arr) - } - return trash.reduce { acc, list -> - val temp = ArrayList() - acc.forEach { ac -> - list.forEach { li -> - temp.add(ac.plus(li)) - } - } - return@reduce temp - } - } - - val trashList = listOf("@", "#", "!", "^", "$") - val trashSet = getTrash(trashList, 2) + getTrash(trashList, 3) - var trashString = data.replace("#2", "").split("//_//").joinToString("") - - trashSet.forEach { - val temp = base64Encode(it.toByteArray()) - trashString = trashString.replace(temp, "") - } - - return base64Decode(trashString) - -} - fun fixUrl(url: String, domain: String): String { if (url.startsWith("http")) { return url diff --git a/Superstream/build.gradle.kts b/Superstream/build.gradle.kts index 6109c0eb..2bf7d8a9 100644 --- a/Superstream/build.gradle.kts +++ b/Superstream/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.konan.properties.Properties // use an integer for version numbers -version = 1 +version = 3 android { defaultConfig { diff --git a/Superstream/src/main/kotlin/com/hexated/Extractors.kt b/Superstream/src/main/kotlin/com/hexated/Extractors.kt index 73a21ff6..1d0fd0e3 100644 --- a/Superstream/src/main/kotlin/com/hexated/Extractors.kt +++ b/Superstream/src/main/kotlin/com/hexated/Extractors.kt @@ -1,7 +1,9 @@ package com.hexated import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import com.lagradost.cloudstream3.utils.* +import java.net.URL object Extractors : Superstream() { @@ -66,45 +68,44 @@ object Extractors : Superstream() { callback: (ExtractorLink) -> Unit, ) { val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode) - val shareKey = app.get( - "$fourthAPI/index/share_link?id=${mediaId}&type=$type" - ).parsedSafe()?.data?.link?.substringAfterLast("/") + val shareKey = app.get("$fourthAPI/index/share_link?id=${mediaId}&type=$type") + .parsedSafe()?.data?.link?.substringAfterLast("/") ?: return val headers = mapOf("Accept-Language" to "en") - val shareRes = app.get( - "$thirdAPI/file/file_share_list?share_key=${shareKey ?: return}", - headers = headers - ).parsedSafe()?.data + val shareRes = app.get("$thirdAPI/file/file_share_list?share_key=$shareKey", headers = headers) + .parsedSafe()?.data ?: return val fids = if (season == null) { - shareRes?.file_list + shareRes.file_list } else { - val parentId = - shareRes?.file_list?.find { it.file_name.equals("season $season", true) }?.fid - app.get( - "$thirdAPI/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 parentId = shareRes.file_list?.find { it.file_name.equals("season $season", true) }?.fid + app.get("$thirdAPI/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 + } + } ?: return - fids?.apmapIndexed { index, fileList -> + fids.apmapIndexed { index, fileList -> val player = app.get("$thirdAPI/file/player?fid=${fileList.fid}&share_key=$shareKey").text - val video = """"(https.*?m3u8.*?)"""".toRegex().find(player)?.groupValues?.get(1) - callback.invoke( - ExtractorLink( - "External", - "External [Server ${index + 1}]", - video?.replace("\\/", "/") ?: return@apmapIndexed, - "$thirdAPI/", - getIndexQuality(fileList.file_name), - isM3u8 = true - ) - ) + val sources = "sources\\s*=\\s*(.*);".toRegex().find(player)?.groupValues?.get(1) + val qualities = "quality_list\\s*=\\s*(.*);".toRegex().find(player)?.groupValues?.get(1) + listOf(sources, qualities).forEach { + AppUtils.tryParseJson>(it)?.forEach org@{ source -> + val format = if (source.type == "video/mp4") ExtractorLinkType.VIDEO else ExtractorLinkType.M3U8 + val label = if (format == ExtractorLinkType.M3U8) "Hls" else "Mp4" + if(!(source.label == "AUTO" || format == ExtractorLinkType.VIDEO)) return@org + callback.invoke( + ExtractorLink( + "External", + "External $label [Server ${index + 1}]", + (source.m3u8_url ?: source.file)?.replace("\\/", "/") ?: return@org, + "", + getIndexQuality(if (format == ExtractorLinkType.M3U8) fileList.file_name else source.label), + type = format, + ) + ) + } + } } } diff --git a/Superstream/src/main/kotlin/com/hexated/Superstream.kt b/Superstream/src/main/kotlin/com/hexated/Superstream.kt index 525e3607..bd971a67 100644 --- a/Superstream/src/main/kotlin/com/hexated/Superstream.kt +++ b/Superstream/src/main/kotlin/com/hexated/Superstream.kt @@ -623,7 +623,6 @@ open class Superstream : MainAPI() { } } - private data class LinkData( val id: Int, val type: Int, @@ -633,7 +632,6 @@ open class Superstream : MainAPI() { val imdbId: String?, ) - data class LinkDataProp( @JsonProperty("code") val code: Int? = null, @JsonProperty("msg") val msg: String? = null, @@ -776,6 +774,13 @@ open class Superstream : MainAPI() { } } + data class ExternalSources( + @JsonProperty("m3u8_url") val m3u8_url: String? = null, + @JsonProperty("file") val file: String? = null, + @JsonProperty("label") val label: String? = null, + @JsonProperty("type") val type: String? = null, + ) + data class WatchsomuchTorrents( @JsonProperty("id") val id: Int? = null, @JsonProperty("movieId") val movieId: Int? = null, diff --git a/TimefourTv/build.gradle.kts b/TimefourTv/build.gradle.kts index f160d38c..a28f5bbf 100644 --- a/TimefourTv/build.gradle.kts +++ b/TimefourTv/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 22 +version = 23 cloudstream { diff --git a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt index 45f25ec2..53eef45d 100644 --- a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt +++ b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt @@ -4,7 +4,7 @@ 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 com.lagradost.cloudstream3.utils.Qualities import org.jsoup.nodes.Element import java.net.URI @@ -14,22 +14,22 @@ class TimefourTv : MainAPI() { override val hasDownloadSupport = false override val hasMainPage = true 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" + "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" + "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/24-7-channels.php" to "24/7 Channels", - "$mainUrl/schedule/schedule-generated.json" to "Schedule Channels" + "$mainUrl/24-7-channels.php" to "24/7 Channels", + "$mainUrl/schedule/schedule-generated.json" to "Schedule Channels" ) override suspend fun getMainPage( - page: Int, - request: MainPageRequest + page: Int, + request: MainPageRequest ): HomePageResponse { val items = mutableListOf() if (request.name == "24/7 Channels") { @@ -46,11 +46,11 @@ class TimefourTv : MainAPI() { 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, + 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)) @@ -64,11 +64,11 @@ class TimefourTv : MainAPI() { val title = this.select("strong").text() val href = fixUrl(this.select("a").attr("href")) return LiveSearchResponse( - title, - Item(title, href).toJson(), - this@TimefourTv.name, - TvType.Live, - posterUrl = homePoster, + title, + Item(title, href).toJson(), + this@TimefourTv.name, + TvType.Live, + posterUrl = homePoster, ) } @@ -88,18 +88,18 @@ class TimefourTv : MainAPI() { val items = AppUtils.parseJson>(data.items) items.mapNotNull { eps -> Episode( - data = eps.channels?.toJson() ?: return@mapNotNull null, - name = "${eps.event} • ${eps.time}", - description = eps.channels.map { it.channel_name }.joinToString(" • "), - posterUrl = detailPoster, + data = eps.channels?.toJson() ?: return@mapNotNull null, + name = "${eps.event} • ${eps.time}", + description = eps.channels.map { it.channel_name }.joinToString(" • "), + posterUrl = detailPoster, ) } } return newTvSeriesLoadResponse( - data.title ?: "", - url, - TvType.TvSeries, - episodes = episodes + data.title ?: "", + url, + TvType.TvSeries, + episodes = episodes ) { posterUrl = homePoster } @@ -107,29 +107,34 @@ class TimefourTv : 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 json = AppUtils.parseJson>(data) json.apmap { val iframe = app.get( - fixChannelUrl( - it.channel_id ?: return@apmap - ) + fixChannelUrl( + it.channel_id ?: return@apmap + ) ).document.selectFirst("iframe#thatframe")?.attr("src") - ?: throw ErrorLoadingException("No Iframe Found") + ?: throw ErrorLoadingException("No Iframe Found") val host = getBaseUrl(iframe) val video = extractVideo(iframe) - M3u8Helper.generateM3u8( + callback.invoke( + ExtractorLink( + this.name, it.channel_name ?: return@apmap, video ?: return@apmap, "$host/", - ).forEach(callback) + Qualities.Unknown.value, + isM3u8 = true, + ) + ) } return true @@ -138,13 +143,13 @@ class TimefourTv : MainAPI() { 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 + 1 ) ?: run { val scriptData = - res.document.selectFirst("div#player")?.nextElementSibling()?.data() - ?.substringAfterLast("return(")?.substringBefore(".join") + res.document.selectFirst("div#player")?.nextElementSibling()?.data() + ?.substringAfterLast("return(")?.substringBefore(".join") scriptData?.removeSurrounding("[", "]")?.replace("\"", "")?.split(",") - ?.joinToString("") + ?.joinToString("") } } @@ -163,20 +168,20 @@ class TimefourTv : MainAPI() { } data class Item( - val title: String? = null, - val url: String? = null, - val items: String? = null, + 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(), + 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, + val channel_name: String? = null, + val channel_id: String? = null, ) } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index f0d0f5c1..6e28f8fa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -77,7 +77,7 @@ subprojects { // https://github.com/recloudstream/cloudstream/blob/master/app/build.gradle implementation(kotlin("stdlib")) // adds standard kotlin features, like listOf, mapOf etc - implementation("com.github.Blatzar:NiceHttp:0.4.4") // http library + implementation("com.github.Blatzar:NiceHttp:0.4.5") // http library implementation("org.jsoup:jsoup:1.17.2") // html parser implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.16.1") implementation("io.karn:khttp-android:0.1.2")