diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/DoodExtractor.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/DoodExtractor.kt new file mode 100644 index 00000000..0a04baaa --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/DoodExtractor.kt @@ -0,0 +1,42 @@ +package com.lagradost.cloudstream3.extractors + +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities +import java.lang.Thread.sleep + +class DoodToExtractor : DoodLaExtractor() { + override val mainUrl: String + get() = "https://dood.to" +} + +open class DoodLaExtractor : ExtractorApi() { + override val name: String + get() = "DoodStream" + override val mainUrl: String + get() = "https://dood.la" + override val requiresReferer: Boolean + get() = false + + override fun getExtractorUrl(id: String): String { + return "$mainUrl/d/$id" + } + + override fun getUrl(url: String, referer: String?): List? { + val id = url.removePrefix("$mainUrl/e/").removePrefix("$mainUrl/d/") + val trueUrl = getExtractorUrl(id) + val response = khttp.get(trueUrl) + Regex("href=\".*/download/(.*?)\"").find(response.text)?.groupValues?.get(1)?.let { link -> + if (link.isEmpty()) return null + sleep(5000) // might need this to not trigger anti bot + val downloadLink = "$mainUrl/download/$link" + val downloadResponse = khttp.get(downloadLink) + Regex("onclick=\"window\\.open\\((['\"])(.*?)(['\"])").find(downloadResponse.text)?.groupValues?.get(2) + ?.let { trueLink -> + return listOf(ExtractorLink(trueLink, this.name, trueLink, mainUrl, Qualities.Unknown.value, false)) // links are valid in 8h + } + } + + return null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AllMoviesForYouProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AllMoviesForYouProvider.kt index 80b3fdda..fd1330ac 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AllMoviesForYouProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/AllMoviesForYouProvider.kt @@ -17,13 +17,13 @@ class AllMoviesForYouProvider : MainAPI() { } override val mainUrl: String - get() = "https://allmoviesforyou.co/" + get() = "https://allmoviesforyou.co" override val name: String get() = "AllMoviesForYou" override val supportedTypes: Set get() = setOf( TvType.Movie, - // TvType.TvSeries + TvType.TvSeries ) override fun search(query: String): List { @@ -41,41 +41,100 @@ class AllMoviesForYouProvider : MainAPI() { if (type == TvType.Movie) { returnValue.add(MovieSearchResponse(title, href, this.name, type, img, null)) } else if (type == TvType.TvSeries) { - // returnValue.add(TvSeriesSearchResponse(title, href, this.name, type, img, null, null)) + returnValue.add(TvSeriesSearchResponse(title, href, this.name, type, img, null, null)) } } return returnValue } + private fun getLink(document: String): String? { + return Regex("iframe src=\"(.*?)\"").find(document)?.groupValues?.get(1) + } + override fun load(url: String): LoadResponse { val type = getType(url) - if(type == TvType.TvSeries) throw ErrorLoadingException("TvSeries not implemented yet") + val response = khttp.get(url) val document = Jsoup.parse(response.text) + val title = document.selectFirst("h1.Title").text() val descipt = document.selectFirst("div.Description > p").text() val rating = document.selectFirst("div.Vote > div.post-ratings > span")?.text()?.toFloatOrNull()?.times(10)?.toInt() - val year = document.selectFirst("span.Date").text() + val year = document.selectFirst("span.Date")?.text() val duration = document.selectFirst("span.Time").text() val backgroundPoster = fixUrl(document.selectFirst("div.Image > figure > img").attr("src")) - val data = Regex("iframe src=\"(.*?)\"").find(response.text)?.groupValues?.get(1) - ?: throw ErrorLoadingException("No Links Found") + if (type == TvType.TvSeries) { + val list = ArrayList>() - return MovieLoadResponse( - title, - url, - this.name, - type, - data, - backgroundPoster, - year.toIntOrNull(), - descipt, - null, - rating, - duration = duration - ) + document.select("main > section.SeasonBx > div > div.Title > a").forEach { element -> + val season = element.selectFirst("> span")?.text()?.toIntOrNull() + val href = element.attr("href") + if (season != null && season > 0 && !href.isNullOrBlank()) { + list.add(Pair(season, fixUrl(href))) + } + } + if (list.isEmpty()) throw ErrorLoadingException("No Seasons Found") + + val episodeList = ArrayList() + + for (season in list) { + val seasonResponse = khttp.get(season.second) + val seasonDocument = Jsoup.parse(seasonResponse.text) + val episodes = seasonDocument.select("table > tbody > tr") + if (episodes.isNotEmpty()) { + episodes.forEach { episode -> + val epNum = episode.selectFirst("> td > span.Num")?.text()?.toIntOrNull() + val poster = episode.selectFirst("> td.MvTbImg > a > img")?.attr("src") + val aName = episode.selectFirst("> td.MvTbTtl > a") + val name = aName.text() + val href = aName.attr("href") + val date = episode.selectFirst("> td.MvTbTtl > span")?.text() + episodeList.add( + TvSeriesEpisode( + name, + season.first, + epNum, + href, + if (poster != null) fixUrl(poster) else null, + date + ) + ) + } + } + } + return TvSeriesLoadResponse( + title, + url, + this.name, + type, + episodeList, + backgroundPoster, + year?.toIntOrNull(), + descipt, + null, + null, + rating + ) + } else { + val data = getLink(response.text) + ?: throw ErrorLoadingException("No Links Found") + + return MovieLoadResponse( + title, + url, + this.name, + type, + data, + backgroundPoster, + year?.toIntOrNull(), + descipt, + null, + rating, + duration = duration + ) + } } override fun loadLinks( @@ -84,8 +143,15 @@ class AllMoviesForYouProvider : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { + if (data.startsWith("$mainUrl/episode/")) { + val response = khttp.get(data) + val link = getLink(response.text) + if (link == null || link == data) return false + return loadLinks(link, isCasting, subtitleCallback, callback) + } + if (data.startsWith(mainUrl) && data != mainUrl) { - val response = khttp.get(data.replace("&","&")) + val response = khttp.get(data.replace("&", "&")) Regex(" loadExtractor(url.trimStart(), data, callback) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt index 8395ee20..add2763a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt @@ -103,7 +103,7 @@ class ResultViewModel : ViewModel() { seasonTypes[i.season] = true } } - val seasons = seasonTypes.toList().map { it.first } + val seasons = seasonTypes.toList().map { it.first }.sortedBy { it } seasonSelections.postValue(seasons) if (seasons.isEmpty()) { // WHAT THE FUCK DID YOU DO????? HOW DID YOU DO THIS _publicEpisodes.postValue(ArrayList()) diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt index 8bb10e00..12a6503a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -72,6 +72,8 @@ val extractorApis: Array = arrayOf( XStreamCdn(), StreamSB(), Streamhub(), + DoodLaExtractor(), + DoodToExtractor(), ) fun getExtractorApiFromName(name: String): ExtractorApi {