package com.hexated import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.network.WebViewResolver import com.lagradost.cloudstream3.utils.* import com.lagradost.nicehttp.requestCreator import java.net.URI import java.util.ArrayList object SoraExtractor : SoraStream() { suspend fun invokeLocalSources( url: String, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { val doc = app.get( url, headers = mapOf("User-Agent" to RandomUserAgent.getRandomUserAgent()) ).document val script = doc.select("script").find { it.data().contains("\"sources\":[") }?.data() val sourcesData = script?.substringAfter("\"sources\":[")?.substringBefore("],") val subData = script?.substringAfter("\"subtitles\":[")?.substringBefore("],") AppUtils.tryParseJson>("[$sourcesData]")?.map { source -> callback.invoke( ExtractorLink( this.name, this.name, source.url ?: return@map null, "$mainServerAPI/", source.quality?.toIntOrNull() ?: Qualities.Unknown.value, isM3u8 = source.isM3U8, headers = mapOf("Origin" to mainServerAPI) ) ) } AppUtils.tryParseJson>("[$subData]")?.map { sub -> subtitleCallback.invoke( SubtitleFile( sub.lang.toString(), sub.url ?: return@map null ) ) } } suspend fun invokeTwoEmbed( id: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { val url = if (season == null) { "$twoEmbedAPI/embed/tmdb/movie?id=$id" } else { "$twoEmbedAPI/embed/tmdb/tv?id=$id&s=$season&e=$episode" } val document = app.get(url).document val captchaKey = document.select("script[src*=https://www.google.com/recaptcha/api.js?render=]") .attr("src").substringAfter("render=") document.select(".dropdown-menu a[data-id]").map { it.attr("data-id") }.apmap { serverID -> val token = APIHolder.getCaptchaToken(url, captchaKey) app.get( "$twoEmbedAPI/ajax/embed/play?id=$serverID&_token=$token", referer = url ).parsedSafe()?.let { source -> loadExtractor( source.link ?: return@let null, twoEmbedAPI, subtitleCallback, callback ) } } } suspend fun invokeVidSrc( id: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { val url = if (season == null) { "$vidSrcAPI/embed/$id" } else { "$vidSrcAPI/embed/$id/${season}-${episode}" } loadExtractor(url, null, subtitleCallback) { link -> callback.invoke( ExtractorLink( link.name, link.name, link.url, link.referer, Qualities.P1080.value, link.isM3u8, link.headers, link.extractorData ) ) } } suspend fun invokeOlgply( id: Int? = null, season: Int? = null, episode: Int? = null, callback: (ExtractorLink) -> Unit ) { val url = "https://olgply.xyz/${id}${season?.let { "/$it" } ?: ""}${episode?.let { "/$it" } ?: ""}" loadLinksWithWebView(url, callback) } suspend fun invokeDbgo( id: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { var iframeDbgo: String? = null 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() } val source = Regex("['|\"]file['|\"]:\\s['|\"](#\\S+?)['|\"]").find(script.toString())?.groupValues?.get( 1 ) val subtitle = Regex("['|\"]subtitle['|\"]:\\s['|\"](\\S+?)['|\"]").find(script.toString())?.groupValues?.get( 1 ) decryptStreamUrl(source.toString()).split(",").map { links -> val quality = Regex("\\[([0-9]*p.*?)]").find(links)?.groupValues?.getOrNull(1).toString().trim() 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, "${getBaseUrl(iframeDbgo)}/", getQuality(quality), isM3u8 = link.contains(".m3u8"), headers = mapOf( "Origin" to getBaseUrl(iframeDbgo) ) ) ) } } subtitle?.split(",")?.map { sub -> val language = Regex("\\[(.*)]").find(sub)?.groupValues?.getOrNull(1) .toString() val link = sub.replace("[$language]", "").trim() subtitleCallback.invoke( SubtitleFile( language, link ) ) } } suspend fun invoke123Movie( tmdbId: Int? = null, imdbId: String? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { val url = if (season == null) { "$movie123API/imdb.php?imdb=$imdbId&server=vcu" } else { "$movie123API/tmdb_api.php?se=$season&ep=$episode&tmdb=$tmdbId&server_name=vcu" } val iframe = app.get(url).document.selectFirst("iframe")?.attr("src") val doc = app.get( "$iframe", referer = url, headers = mapOf("Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8") ).document doc.select("ul.list-server-items li.linkserver").mapNotNull { server -> server.attr("data-video").let { Regex("(.*?)((\\?cap)|(\\?sub)|(#cap)|(#sub))").find(it)?.groupValues?.get(1) } }.apmap { link -> loadExtractor( link, "https://123moviesjr.cc/", subtitleCallback, callback ) } } suspend fun invokeMovieHab( id: Int? = null, season: Int? = null, episode: Int? = null, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ) { val url = if (season == null) { "$movieHabAPI/embed/movie?tmdb=$id" } else { "$movieHabAPI/embed/series?tmdb=$id&sea=$season&epi=$episode" } val doc = app.get(url, referer = "$movieHabAPI/").document val movieId = doc.select("div#embed-player").attr("data-movie-id") doc.select("div.dropdown-menu a").apmap { val dataId = it.attr("data-id") app.get( "$movieHabAPI/ajax/get_stream_link?id=$dataId&movie=$movieId&is_init=true&captcha=&ref=", referer = url, headers = mapOf("X-Requested-With" to "XMLHttpRequest") ).parsedSafe()?.data?.let { res -> loadExtractor( res.link ?: return@let null, movieHabAPI, subtitleCallback, callback ) } } } } private fun getQuality(str: String): Int { return when (str) { "360p" -> Qualities.P240.value "480p" -> Qualities.P360.value "720p" -> Qualities.P480.value "1080p" -> Qualities.P720.value "1080p Ultra" -> Qualities.P1080.value else -> getQualityFromName(str) } } private fun getBaseUrl(url: String): String { return URI(url).let { "${it.scheme}://${it.host}" } } private 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) } suspend fun loadLinksWithWebView( url: String, callback: (ExtractorLink) -> Unit ) { val foundVideo = WebViewResolver( Regex("""\.m3u8|i7njdjvszykaieynzsogaysdgb0hm8u1mzubmush4maopa4wde\.com""") ).resolveUsingWebView( requestCreator( "GET", url, referer = "https://olgply.com/" ) ).first ?: return callback.invoke( ExtractorLink( "Olgply", "Olgply", foundVideo.url.toString(), "", Qualities.P1080.value, true ) ) } private data class MovieHabData( @JsonProperty("link") val link: String? = null, @JsonProperty("token") val token: String? = null, ) private data class MovieHabRes( @JsonProperty("data") val data: MovieHabData? = null, )