diff --git a/CasaCinemaProvider/build.gradle.kts b/CasaCinemaProvider/build.gradle.kts index 9290fe2..914b7eb 100644 --- a/CasaCinemaProvider/build.gradle.kts +++ b/CasaCinemaProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { @@ -22,4 +22,5 @@ cloudstream { "Movie", ) + iconUrl = "https://www.google.com/s2/favicons?domain=casacinema.lol&sz=%size%" } diff --git a/CasaCinemaProvider/src/main/kotlin/com/lagradost/CasaCinemaProvider.kt b/CasaCinemaProvider/src/main/kotlin/com/lagradost/CasaCinemaProvider.kt index 795448b..e9533cd 100644 --- a/CasaCinemaProvider/src/main/kotlin/com/lagradost/CasaCinemaProvider.kt +++ b/CasaCinemaProvider/src/main/kotlin/com/lagradost/CasaCinemaProvider.kt @@ -23,42 +23,143 @@ class CasaCinemaProvider : MainAPI() { // all providers must be an instance of M private val interceptor = CloudflareKiller() override val mainPage = - mainPageOf( - "$mainUrl/category/serie-tv/page/" to "Ultime Serie Tv", - "$mainUrl/category/film/page/" to "Ultimi Film", - ) + mainPageOf( + "$mainUrl/category/serie-tv/page/" to "Ultime Serie Tv", + "$mainUrl/category/film/page/" to "Ultimi Film", + ) + + private fun fixTitle(element: Element?): String { + return element?.text() + ?.trim() + ?.substringBefore("Streaming") + ?.replace("[HD]", "") + ?.replace("\\(\\d{4}\\)".toRegex(), "") + ?: "No Title found" + } + + private fun Element?.isMovie(): Boolean { + return (this + ?.text() ?: "") + .contains("\\(\\d{4}\\)".toRegex()) + } override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { val url = request.data + page - val soup = app.get(url).document + val soup = app.get(url, referer = mainUrl).document val home = soup.select("ul.posts>li").mapNotNull { it.toSearchResult() } val hasNext = soup.select("div.navigation>ul>li>a").last()?.text() == "Pagina successiva ยป" return newHomePageResponse(arrayListOf(HomePageList(request.name, home)), hasNext = hasNext) } + + override suspend fun search(query: String): List { + val queryFormatted = query.replace(" ", "+") + val url = "$mainUrl/?s=$queryFormatted" + val doc = app.get(url, referer = mainUrl, interceptor = interceptor).document + return doc.select("ul.posts>li").map { it.toSearchResult() } + } + private fun Element.toSearchResult(): SearchResponse { - val title = - this.selectFirst(".title")?.text()?.replace("[HD]", "")?.substringBefore("(") - ?: "No title" - val isMovie = (this.selectFirst(".title")?.text() ?: "").contains("\\(\\d{4}\\)".toRegex()) + val title = fixTitle(this.selectFirst(".title")) + val isMovie = this.selectFirst(".title").isMovie() val link = - this.selectFirst("a")?.attr("href") ?: throw ErrorLoadingException("No Link found") + this.selectFirst("a")?.attr("href") ?: throw ErrorLoadingException("No Link found") val quality = this.selectFirst("div.hd")?.text() - val posterUrl = this.selectFirst("a")?.attr("data-thumbnail") - if (isMovie) { - return newMovieSearchResponse(title, link, TvType.Movie) { + return if (isMovie) { + newMovieSearchResponse(title, link, TvType.Movie) { + addPoster(posterUrl) + quality?.let { addQuality(it) } + } + } else { + newTvSeriesSearchResponse(title, link, TvType.TvSeries) { + addPoster(posterUrl) + quality?.let { addQuality(it) } + } + } + } + + override suspend fun load(url: String): LoadResponse { + val document = app.get(url, referer = mainUrl).document + val type = + if (document.select("div.seasons-wraper").isNotEmpty()) TvType.TvSeries + else TvType.Movie + val title = fixTitle(document.selectFirst("div.row > h1")) + val description = document.select("div.element").last()?.text() + val year = document.selectFirst("div.element>a.tag") + ?.text() + ?.substringBefore("-") + ?.substringAfter(",") + ?.filter { it.isDigit() } + val poster = document.selectFirst("img.thumbnail")?.attr("src") + val rating = document.selectFirst("div.rating>div.value")?.text()?.trim()?.toRatingInt() + val recomm = document.select("div.crp_related>ul>li").map { it.toRecommendResult() } + if (type == TvType.TvSeries) { + val episodeList = + document.select("div.accordion>div.accordion-item") + .map { element -> + val season = + element.selectFirst("li.s_title>span.season-title") + ?.text() + ?.toIntOrNull() + ?: 0 + element.select("div.episode-wrap").map { episode -> + episode.toEpisode(season) + } + } + .flatten() + + return newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodeList) { + this.year = year?.toIntOrNull() + this.plot = description + this.recommendations = recomm + addPoster(poster) + addRating(rating) + } + } else { + val actors: List = + document.select("div.cast_wraper>ul>li").map { actordata -> + val actorName = actordata.selectFirst("strong")?.text() ?: "" + val actorImage: String = + actordata.selectFirst("figure>img")?.attr("src") ?: "" + ActorData(actor = Actor(actorName, image = actorImage)) + } + val data = document.select(".embed-player").map { it.attr("data-id") }.toJson() + return newMovieLoadResponse(title, data, TvType.Movie, data) { + this.year = year?.toIntOrNull() + this.plot = description + this.actors = actors + this.recommendations = recomm + addPoster(poster) + addRating(rating) + } + } + } + + private fun Element.toRecommendResult(): SearchResponse { + val title = + fixTitle(this.selectFirst("span.crp_title")) + val isMovie = this.selectFirst("span.crp_title").isMovie() + val link = + this.selectFirst("a")?.attr("href") ?: throw ErrorLoadingException("No Link found") + + val quality = + this.selectFirst("span.crp_title")?.text()?.substringAfter("[")?.substringBefore("]") + val posterUrl = this.selectFirst("img")?.attr("src") + + return if (isMovie) { + newMovieSearchResponse(title, link, TvType.Movie) { addPoster(posterUrl) if (quality != null) { addQuality(quality) } } } else { - return newTvSeriesSearchResponse(title, link, TvType.TvSeries) { + newTvSeriesSearchResponse(title, link, TvType.TvSeries) { addPoster(posterUrl) if (quality != null) { addQuality(quality) @@ -69,82 +170,31 @@ class CasaCinemaProvider : MainAPI() { // all providers must be an instance of M private fun Element.toEpisode(season: Int): Episode { val data = - this.select("div.fix-table>table>tbody>tr>td>a[target=_blank]") - .map { it.attr("href") } - .toJson() // isecure.link - val epTitle = this.selectFirst("li.other_link>a")?.text() ?: "No Ep. Title 0" - val epNum = epTitle.substringAfter("Episodio ").toInt() - return Episode(data, epTitle, season, epNum) - } + this.select("div.fix-table>table>tbody>tr>td>a[target=_blank]") + .map { it.attr("href") } + .toJson() // isecure.link + val epNum = + this.selectFirst("li.season-no") + ?.text() + ?.substringAfter("x") + ?.substringBefore(" ") + ?.filter { it.isDigit() } + .orEmpty().ifBlank { "0" } - override suspend fun search(query: String): List { - val queryFormatted = query.replace(" ", "+") - val url = "$mainUrl/?s=$queryFormatted" - val doc = app.get(url, referer = mainUrl, interceptor = interceptor).document - return doc.select("ul.posts>li").map { it.toSearchResult() } - } - - override suspend fun load(url: String): LoadResponse { - val document = app.get(url).document - val type = - if (document.selectFirst("h3")?.text() == "Altri Film:") TvType.Movie - else TvType.TvSeries - val title = - document.selectFirst("div.row > h1") - ?.text() - ?.replace("[HD]", "") - ?.substringBefore("(") - ?: "No Title found" - val description = document.select("div.element").last()?.text() - val year = document.selectFirst("div.element>a.tag")?.text()?.substringBefore("-") - val poster = document.selectFirst("img.thumbnail")?.attr("src") - val rating = document.selectFirst("div.rating>div.value")?.text()?.trim()?.toRatingInt() - - if (type == TvType.TvSeries) { - val episodeList = - document.select("div.accordion>div.accordion-item") - .map { element -> - val season = - element.selectFirst("li.s_title>span.season-title") - ?.text() - ?.toIntOrNull() - ?: 0 - element.select("div.episode-wrap").map { episode -> - episode.toEpisode(season) - } - } - .flatten() - - return newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodeList) { - this.year = year?.toIntOrNull() - this.plot = description - addPoster(poster) - addRating(rating) + val epTitle = + this.selectFirst("li.other_link>a")?.text().orEmpty().ifBlank { + "Episodio $epNum" } - } else { - val actors: List = - document.select("div.cast_wraper>ul>li").map { actordata -> - val actorName = actordata.selectFirst("strong")?.text() ?: "" - val actorImage: String? = - actordata.selectFirst("figure>img")?.attr("src") ?: "" - ActorData(actor = Actor(actorName, image = actorImage)) - } - val data = document.select(".embed-player").map { it.attr("data-id") }.toJson() - return newMovieLoadResponse(title, data, TvType.Movie, data) { - this.year = year?.toIntOrNull() - this.plot = description - this.actors = actors - addPoster(poster) - addRating(rating) - } - } + val posterUrl = this.selectFirst("figure>img")?.attr("src") + return Episode(data, epTitle, season, epNum.toInt(), posterUrl = posterUrl) } + 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 { parseJson>(data).map { videoUrl -> loadExtractor(unshorten(videoUrl), data, subtitleCallback, callback)