From e9247d553f415981c8f3aeba74f836e1c0d66b07 Mon Sep 17 00:00:00 2001 From: antonydp <38143733+antonydp@users.noreply.github.com> Date: Thu, 26 Jan 2023 13:19:32 +0100 Subject: [PATCH 1/5] Fix CalcioStreaming, Starlive and Domain changes (#77) Co-authored-by: contusionglory <102427829+contusionglory@users.noreply.github.com> --- CalcioStreamingProvider/build.gradle.kts | 2 +- .../com/lagradost/CalcioStreamingProvider.kt | 58 ++++--- CineBlog01Provider/build.gradle.kts | 2 +- .../kotlin/com/lagradost/CineBlogProvider.kt | 2 +- EurostreamingProvider/build.gradle.kts | 2 +- .../com/lagradost/EurostreamingProvider.kt | 2 +- FilmpertuttiProvider/build.gradle.kts | 2 +- .../com/lagradost/FilmpertuttiProvider.kt | 2 +- StarLiveProvider/build.gradle.kts | 2 +- .../kotlin/com/lagradost/StarLiveProvider.kt | 141 +++++++++--------- TantiFilmProvider/build.gradle.kts | 2 +- .../kotlin/com/lagradost/TantiFilmProvider.kt | 2 +- 12 files changed, 118 insertions(+), 101 deletions(-) diff --git a/CalcioStreamingProvider/build.gradle.kts b/CalcioStreamingProvider/build.gradle.kts index 62e5f0b..a729e56 100644 --- a/CalcioStreamingProvider/build.gradle.kts +++ b/CalcioStreamingProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 1 +version = 2 cloudstream { diff --git a/CalcioStreamingProvider/src/main/kotlin/com/lagradost/CalcioStreamingProvider.kt b/CalcioStreamingProvider/src/main/kotlin/com/lagradost/CalcioStreamingProvider.kt index 857d054..e52a29b 100644 --- a/CalcioStreamingProvider/src/main/kotlin/com/lagradost/CalcioStreamingProvider.kt +++ b/CalcioStreamingProvider/src/main/kotlin/com/lagradost/CalcioStreamingProvider.kt @@ -2,7 +2,7 @@ package com.lagradost import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.utils.* - +import org.jsoup.nodes.Document class CalcioStreamingProvider : MainAPI() { override var lang = "it" @@ -58,12 +58,21 @@ class CalcioStreamingProvider : MainAPI() { poster, plot = Matchstart ) - - } + private fun matchFound(document: Document) : Boolean { + return Regex(""""((.|\n)*?).";""").containsMatchIn( + getAndUnpack( + document.toString() + )) + } - + private fun getUrl(document: Document):String{ + return Regex(""""((.|\n)*?).";""").find( + getAndUnpack( + document.toString() + ))!!.value.replace("""src="""", "").replace(""""""", "").replace(";", "") + } private suspend fun extractVideoLinks( url: String, @@ -71,25 +80,28 @@ class CalcioStreamingProvider : MainAPI() { ) { val document = app.get(url).document document.select("button.btn").forEach { button -> - val link1 = button.attr("data-link") - val doc2 = app.get(link1).document - val truelink = doc2.selectFirst("iframe")!!.attr("src") - val newpage = app.get(truelink, referer = link1).document - val streamurl = Regex(""""((.|\n)*?).";""").find( - getAndUnpack( - newpage.select("script")[6].childNode(0).toString() - ))!!.value.replace("""src="""", "").replace(""""""", "").replace(";", "") - - callback( - ExtractorLink( - this.name, - button.text(), - streamurl, - truelink, - quality = 0, - true - ) - ) + var link = button.attr("data-link") + var oldLink = link + var videoNotFound = true + while (videoNotFound) { + val doc = app.get(link).document + link = doc.selectFirst("iframe")?.attr("src") ?: break + val newpage = app.get(fixUrl(link), referer = oldLink).document + oldLink = link + if (newpage.select("script").size >= 6 && matchFound(newpage)){ + videoNotFound = false + callback( + ExtractorLink( + this.name, + button.text(), + getUrl(newpage), + fixUrl(link), + quality = 0, + true + ) + ) + } + } } } diff --git a/CineBlog01Provider/build.gradle.kts b/CineBlog01Provider/build.gradle.kts index 3d9175c..d380ea3 100644 --- a/CineBlog01Provider/build.gradle.kts +++ b/CineBlog01Provider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { diff --git a/CineBlog01Provider/src/main/kotlin/com/lagradost/CineBlogProvider.kt b/CineBlog01Provider/src/main/kotlin/com/lagradost/CineBlogProvider.kt index d2ba2d7..cdd6ba4 100644 --- a/CineBlog01Provider/src/main/kotlin/com/lagradost/CineBlogProvider.kt +++ b/CineBlog01Provider/src/main/kotlin/com/lagradost/CineBlogProvider.kt @@ -10,7 +10,7 @@ import org.jsoup.nodes.Element class CineBlog01Provider : MainAPI() { override var lang = "it" - override var mainUrl = "https://www.cineblog01.moe" + override var mainUrl = "https://www.cineblog01.mom" override var name = "CineBlog01" override val hasMainPage = true override val hasChromecastSupport = true diff --git a/EurostreamingProvider/build.gradle.kts b/EurostreamingProvider/build.gradle.kts index e977bcf..da7feb4 100644 --- a/EurostreamingProvider/build.gradle.kts +++ b/EurostreamingProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 2 +version = 3 cloudstream { language = "it" diff --git a/EurostreamingProvider/src/main/kotlin/com/lagradost/EurostreamingProvider.kt b/EurostreamingProvider/src/main/kotlin/com/lagradost/EurostreamingProvider.kt index ef507c0..e82bc73 100644 --- a/EurostreamingProvider/src/main/kotlin/com/lagradost/EurostreamingProvider.kt +++ b/EurostreamingProvider/src/main/kotlin/com/lagradost/EurostreamingProvider.kt @@ -11,7 +11,7 @@ import org.jsoup.nodes.Element class EurostreamingProvider : MainAPI() { override var lang = "it" - override var mainUrl = "https://eurostreaming.taxi" + override var mainUrl = "https://eurostreaming.expert" override var name = "Eurostreaming" override val hasMainPage = true override val hasChromecastSupport = true diff --git a/FilmpertuttiProvider/build.gradle.kts b/FilmpertuttiProvider/build.gradle.kts index b401629..ea939f5 100644 --- a/FilmpertuttiProvider/build.gradle.kts +++ b/FilmpertuttiProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/FilmpertuttiProvider/src/main/kotlin/com/lagradost/FilmpertuttiProvider.kt b/FilmpertuttiProvider/src/main/kotlin/com/lagradost/FilmpertuttiProvider.kt index 3cb9fc6..6f4c71d 100644 --- a/FilmpertuttiProvider/src/main/kotlin/com/lagradost/FilmpertuttiProvider.kt +++ b/FilmpertuttiProvider/src/main/kotlin/com/lagradost/FilmpertuttiProvider.kt @@ -16,7 +16,7 @@ import com.lagradost.cloudstream3.network.CloudflareKiller class FilmpertuttiProvider : MainAPI() { override var lang = "it" - override var mainUrl = "https://filmpertutti.skin" + override var mainUrl = "https://filmpertutti.tips" override var name = "FilmPerTutti" override val hasMainPage = true override val hasChromecastSupport = true diff --git a/StarLiveProvider/build.gradle.kts b/StarLiveProvider/build.gradle.kts index e02ba85..1ccc2e7 100644 --- a/StarLiveProvider/build.gradle.kts +++ b/StarLiveProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 1 +version = 2 cloudstream { diff --git a/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt b/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt index dd0068e..5ee622d 100644 --- a/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt +++ b/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt @@ -2,9 +2,11 @@ package com.lagradost import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.network.CloudflareKiller import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import org.jsoup.nodes.Element class StarLiveProvider : MainAPI() { override var mainUrl = "https://starlive.xyz" @@ -13,72 +15,51 @@ class StarLiveProvider : MainAPI() { override var lang = "it" override val hasChromecastSupport = true override val supportedTypes = setOf(TvType.Live) - - private data class LinkParser( - @JsonProperty("link") val link: String, - @JsonProperty("lang") val language: String, - @JsonProperty("name") val name: String - ) - - private data class MatchDataParser( - @JsonProperty("time") val time: String, - @JsonProperty("poster") val poster: String - ) - - private data class MatchParser( - @JsonProperty("linkData") val linkData: List, - @JsonProperty("matchData") val MatchData: MatchDataParser - ) - + private val interceptor = CloudflareKiller() override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { - val document = app.get(mainUrl).document - val sections = document.select("div.panel") + val document = app.get(mainUrl, interceptor = interceptor).document + val sections = document.select("div.panel").groupBy { it.selectFirst("h4 b")?.text() }.values if (sections.isEmpty()) throw ErrorLoadingException() + val prova = sections.map {elements -> + val home = elements.mapNotNull { it.toMainPageResult() } + HomePageList(elements.first()?.selectFirst("h4 b")?.text()?:"Altro", home) + } + return HomePageResponse(prova) + } - return HomePageResponse(sections.mapNotNull { sport -> - val dayMatch = sport.previousElementSiblings().toList().first { it.`is`("h3") }.text() - val categoryName = sport.selectFirst("h4")?.text() ?: "Other" - - val showsList = sport.select("tr").takeWhile { it.text().contains("Player").not() } - .filter { it.hasAttr("class") }.drop(1) - - val shows = showsList.groupBy { it.text().substringBeforeLast(" ") }.map { matchs -> - val posterUrl = fixUrl( - sport.selectFirst("h4")?.attr("style") - ?.substringAfter("(")?.substringBefore(")") ?: "" - ) - val hasDate = matchs.key.contains(":") - val matchName = if (hasDate) { matchs.key.substringAfter(" ")} - else { matchs.key } - - val href = matchs.value.map { match -> - val linkUrl = fixUrl(match.selectFirst("a")?.attr("href") ?: return@mapNotNull null) - val lang = match.attr("class") - LinkParser(linkUrl, lang, matchName) - } - - val date = if (hasDate) { - dayMatch + " - " + matchs.key.substringBefore(" ") - } else { - dayMatch - } - - LiveSearchResponse( - matchName, - MatchParser(href, MatchDataParser(date, posterUrl)).toJson(), - this@StarLiveProvider.name, - TvType.Live, - posterUrl, - ) - } - HomePageList( - categoryName, - shows - ) - - }) + private fun Element.toMainPageResult() : LiveSearchResponse { + val name = this.selectFirst("b")?.text()?:"Altro" + val links = this.select("tr") + .toList() + .filter { it.hasAttr("class") && it.attr("class") !in listOf("", "audio") } + .map { LinkParser( + fixUrl(it.selectFirst("a")?.attr("href")?:""), + it.attr("class"), + it.selectFirst("span")?.text()?:"" + ) } + val dayMatch = this.previousElementSiblings().toList().firstOrNull() { it.`is`("h3") }?.text() + val matchData = MatchDataParser( + dayMatch?.plus(" - ".plus(this.selectFirst("#evento")?.text()?.substringBefore(" ")))?:"no data", + fixUrl( + this.selectFirst("h4")?.attr("style") + ?.substringAfter("(")?.substringBefore(")") ?: "" + ), + this.selectFirst("#evento")?.text()?.substringAfter(" ")?:"Match in $name || $dayMatch" + ) + val href = MatchParser(links, matchData) + return LiveSearchResponse( + this.selectFirst("#evento")?.text()?.substringAfter(" ")?:"Match in $name", + href.toJson(), + this@StarLiveProvider.name, + TvType.Live, + fixUrl( + this.selectFirst("h4")?.attr("style") + ?.substringAfter("(")?.substringBefore(")") ?: "" + ), + posterHeaders = interceptor.getCookieHeaders(mainUrl).toMap() + ) } override suspend fun load(url: String): LoadResponse { @@ -88,10 +69,11 @@ class StarLiveProvider : MainAPI() { return LiveStreamLoadResponse( dataUrl = url, url = matchdata?.linkData?.firstOrNull()?.link ?: mainUrl, - name = matchdata?.linkData?.firstOrNull()?.name ?: "No name", + name = matchdata?.MatchData?.name ?: "No name", posterUrl = poster, plot = matchstart, - apiName = this@StarLiveProvider.name + apiName = this@StarLiveProvider.name, + posterHeaders = interceptor.getCookieHeaders(mainUrl).toMap() ) } @@ -99,11 +81,10 @@ class StarLiveProvider : MainAPI() { data: LinkParser, callback: (ExtractorLink) -> Unit ) { - val linktoStream = fixUrl(app.get(data.link).document.selectFirst("iframe")!!.attr("src")) - + val linktoStream = fixUrl(app.get(data.link, interceptor = interceptor).document.selectFirst("iframe")!!.attr("src")) val referrerLink = if (linktoStream.contains("starlive")) { - app.get(linktoStream, referer = data.link).document.selectFirst("iframe")?.attr("src") - ?: return + app.get(linktoStream, referer = data.link, interceptor = interceptor).document.selectFirst("iframe")?.attr("src") + ?: linktoStream } else { linktoStream } @@ -115,7 +96,13 @@ class StarLiveProvider : MainAPI() { false -> app.get(linktoStream, referer = data.link).document.select("script") .select("script").toString() } - val streamUrl = getAndUnpack(packed).substringAfter("var src=\"").substringBefore("\"") + var streamUrl = getAndUnpack(packed).substringAfter("var src=\"").substringBefore("\"") + if (streamUrl.contains("allowedDomains")){streamUrl = packed.substringAfter("source:'").substringBefore("'")} + if (!streamUrl.contains("m3u8")){ + val script = app.get(linktoStream, referer = data.link, interceptor = interceptor).document.selectFirst("body")?.selectFirst("script").toString() + streamUrl = Regex("source: [\\\"'](.*?)[\\\"']").find(script)?.groupValues?.last()?:"" + } + callback( ExtractorLink( source = this.name, @@ -142,4 +129,22 @@ class StarLiveProvider : MainAPI() { return true } + + private data class LinkParser( + @JsonProperty("link") val link: String, + @JsonProperty("lang") val language: String, + @JsonProperty("name") val name: String + ) + + private data class MatchDataParser( + @JsonProperty("time") val time: String, + @JsonProperty("poster") val poster: String, + @JsonProperty("name") val name: String + ) + + private data class MatchParser( + @JsonProperty("linkData") val linkData: List, + @JsonProperty("matchData") val MatchData: MatchDataParser + ) + } \ No newline at end of file diff --git a/TantiFilmProvider/build.gradle.kts b/TantiFilmProvider/build.gradle.kts index b4f799f..bae85da 100644 --- a/TantiFilmProvider/build.gradle.kts +++ b/TantiFilmProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/TantiFilmProvider/src/main/kotlin/com/lagradost/TantiFilmProvider.kt b/TantiFilmProvider/src/main/kotlin/com/lagradost/TantiFilmProvider.kt index ec350a6..63352a2 100644 --- a/TantiFilmProvider/src/main/kotlin/com/lagradost/TantiFilmProvider.kt +++ b/TantiFilmProvider/src/main/kotlin/com/lagradost/TantiFilmProvider.kt @@ -9,7 +9,7 @@ import com.lagradost.cloudstream3.network.CloudflareKiller class TantifilmProvider : MainAPI() { override var lang = "it" - override var mainUrl = "https://tantifilm.mobi" + override var mainUrl = "https://tantifilm.recipes" override var name = "Tantifilm" override val hasMainPage = true override val hasChromecastSupport = true From d037facb3dbab17cf68451a7c5d38d2847153956 Mon Sep 17 00:00:00 2001 From: antonydp <38143733+antonydp@users.noreply.github.com> Date: Sat, 28 Jan 2023 15:54:04 +0100 Subject: [PATCH 2/5] Update StarLiveProvider.kt Try to fix a issue. Not tested --- .../src/main/kotlin/com/lagradost/StarLiveProvider.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt b/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt index 5ee622d..567c958 100644 --- a/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt +++ b/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt @@ -36,7 +36,7 @@ class StarLiveProvider : MainAPI() { .map { LinkParser( fixUrl(it.selectFirst("a")?.attr("href")?:""), it.attr("class"), - it.selectFirst("span")?.text()?:"" + it.selectFirst("b")?.text()?:"" ) } val dayMatch = this.previousElementSiblings().toList().firstOrNull() { it.`is`("h3") }?.text() @@ -147,4 +147,4 @@ class StarLiveProvider : MainAPI() { @JsonProperty("matchData") val MatchData: MatchDataParser ) -} \ No newline at end of file +} From a4b3a9868808e78f66301391c60276825e56fda4 Mon Sep 17 00:00:00 2001 From: antonydp <38143733+antonydp@users.noreply.github.com> Date: Sat, 28 Jan 2023 16:44:29 +0100 Subject: [PATCH 3/5] Update StarLiveProvider.kt --- .../src/main/kotlin/com/lagradost/StarLiveProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt b/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt index 567c958..f80e995 100644 --- a/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt +++ b/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt @@ -107,7 +107,7 @@ class StarLiveProvider : MainAPI() { ExtractorLink( source = this.name, name = data.name + " - " + data.language, - url = streamUrl, + url = fixUrl(streamUrl), quality = Qualities.Unknown.value, referer = referrerLink, isM3u8 = true From b4ade98f031e4825126528e76eb47990be38b916 Mon Sep 17 00:00:00 2001 From: antonydp <38143733+antonydp@users.noreply.github.com> Date: Sat, 28 Jan 2023 17:07:26 +0100 Subject: [PATCH 4/5] Update StarLiveProvider.kt --- .../src/main/kotlin/com/lagradost/StarLiveProvider.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt b/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt index f80e995..374e4e6 100644 --- a/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt +++ b/StarLiveProvider/src/main/kotlin/com/lagradost/StarLiveProvider.kt @@ -123,7 +123,7 @@ class StarLiveProvider : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { - tryParseJson(data)?.linkData?.map { link -> + tryParseJson(data)?.linkData?.apmap { link -> extractVideoLinks(link, callback) } From 80c061473f4f88e053145215223ae173766d88a4 Mon Sep 17 00:00:00 2001 From: antonydp <38143733+antonydp@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:28:27 +0100 Subject: [PATCH 5/5] Fix Streaming Community --- StreamingcommunityProvider/build.gradle.kts | 4 +- .../lagradost/StreamingcommunityProvider.kt | 568 ++++++++---------- 2 files changed, 236 insertions(+), 336 deletions(-) diff --git a/StreamingcommunityProvider/build.gradle.kts b/StreamingcommunityProvider/build.gradle.kts index 61472f6..eb3acaa 100644 --- a/StreamingcommunityProvider/build.gradle.kts +++ b/StreamingcommunityProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { @@ -22,5 +22,5 @@ cloudstream { "Movie", ) - iconUrl = "https://www.google.com/s2/favicons?domain=streamingcommunity.best&sz=%size%" + iconUrl = "https://www.google.com/s2/favicons?domain=streamingcommunity.online&sz=%size%" } diff --git a/StreamingcommunityProvider/src/main/kotlin/com/lagradost/StreamingcommunityProvider.kt b/StreamingcommunityProvider/src/main/kotlin/com/lagradost/StreamingcommunityProvider.kt index 0fda93b..1aee6fe 100644 --- a/StreamingcommunityProvider/src/main/kotlin/com/lagradost/StreamingcommunityProvider.kt +++ b/StreamingcommunityProvider/src/main/kotlin/com/lagradost/StreamingcommunityProvider.kt @@ -7,9 +7,241 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.* import org.json.JSONObject -import java.net.URI import java.security.MessageDigest +class StreamingcommunityProvider: MainAPI() { + override var lang = "it" + override var mainUrl = "https://streamingcommunity.online" + override var name = "StreamingCommunity" + override val hasMainPage = true + override val hasChromecastSupport = true + override val supportedTypes = setOf( + TvType.Movie, + TvType.TvSeries, + ) + private val userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36" + + private fun translateNumber(num: Int): Int? { + return when (num) { + 67 -> 1 + 71 -> 2 + 72 -> 3 + 73 -> 4 + 74 -> 5 + 75 -> 6 + 76 -> 7 + 77 -> 8 + 78 -> 9 + 79 -> 10 + 133 -> 11 + else -> null + } + } + + private fun translateIp(num: Int): String? { + return when (num) { + 16 -> "sc-b1-01.scws-content.net" + 17 -> "sc-b1-02.scws-content.net" + 18 -> "sc-b1-03.scws-content.net" + 85 -> "sc-b1-04.scws-content.net" + 95 -> "sc-b1-05.scws-content.net" + 117 -> "sc-b1-06.scws-content.net" + 141 -> "sc-b1-07.scws-content.net" + 142 -> "sc-b1-08.scws-content.net" + 143 -> "sc-b1-09.scws-content.net" + 144 -> "sc-b1-10.scws-content.net" + else -> null + } + } + + override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { + val document = app.get(mainUrl, headers = mapOf("user-agent" to userAgent)).document + val items = document.select("slider-title").subList(0, 3).map { + val films = it.attr("titles-json") + val videoData = parseJson>(films) + val searchResponses = videoData.subList(0, 12).apmap { searchr -> + searchr.toSearchResponse() + } + HomePageList(it.attr("slider-name"),searchResponses) + } + if (items.isEmpty()) throw ErrorLoadingException() + return HomePageResponse(items) + } + + private suspend fun VideoElement.toSearchResponse() : MovieSearchResponse{ + val id = this.id + val name = this.slug + val img = this.images[0].url + val number = translateNumber(this.images[0].serverID.toInt()) + val ip = translateIp(this.images[0].proxyID.toInt()) + val posterUrl = "https://$ip/images/$number/$img" + val videoUrl = "$mainUrl/titles/$id-$name" + //posterMap[videourl] = posterurl + val data = app.post("$mainUrl/api/titles/preview/$id", referer = mainUrl, headers = mapOf("user-agent" to userAgent)).text + val datajs = parseJson(data) + val type: TvType = if (datajs.type == "movie") { + TvType.Movie + } else { + TvType.TvSeries + } + + return newMovieSearchResponse(datajs.name, videoUrl, type) { + this.posterUrl = posterUrl + this.year = + datajs.releaseDate.substringBefore("-").filter { it.isDigit() }.toIntOrNull() + } + } + + override suspend fun search(query: String): List { + val queryFormatted = query.replace(" ", "%20") + val url = "$mainUrl/search?q=$queryFormatted" + val document = app.get(url, headers = mapOf("user-agent" to userAgent)).document + + val films = + document.selectFirst("the-search-page")!!.attr("records-json").replace(""", """"""") + + val searchResults = parseJson>(films) + return searchResults.apmap { result -> + result.toSearchResponse() + } + + } + + override suspend fun load(url: String): LoadResponse { + + val document = app.get(url,headers = mapOf("user-agent" to userAgent)).document + val poster = Regex("url\\('(.*)'").find(document.selectFirst("div.title-wrap")?.attributes() + ?.get("style") ?: "")?.groupValues?.last() //posterMap[url] + val id = url.substringBefore("-").filter { it.isDigit() } + val data = app.post("$mainUrl/api/titles/preview/$id", referer = mainUrl, headers = mapOf("user-agent" to userAgent)).text + + val datajs = parseJson(data) + val type: TvType = if (datajs.type == "movie") { + TvType.Movie + } else { + TvType.TvSeries + } + val trailerInfoJs = document.select("slider-trailer").attr("videos") + val trailerInfo = parseJson>(trailerInfoJs) + val trailerUrl: String? = if (trailerInfo.isNotEmpty()) { + "https://www.youtube.com/watch?v=${trailerInfo[0].url}" + } else { + null + } + + val year = datajs.releaseDate.substringBefore("-") + val correlates = document.selectFirst("slider-title")!!.attr("titles-json") + val correlatesData = parseJson>(correlates) + val number : Int = if (correlatesData.size<=15) {correlatesData.size} else correlatesData.size-15 + + val correlatesList =correlatesData.take(number).apmap { + it.toSearchResponse() + } + + if (type == TvType.TvSeries) { + + val name = datajs.name + val episodeList = arrayListOf() + + val episodes = + Html.fromHtml(document.selectFirst("season-select")!!.attr("seasons")).toString() + val jsonEpisodes = parseJson>(episodes) + + jsonEpisodes.map { seasons -> + val season = seasons.number.toInt() + val sid = seasons.title_id + val episode = seasons.episodes + episode.map { ep -> + val href = "$mainUrl/watch/$sid?e=${ep.id}" + val postImage = if (ep.images.isNotEmpty()) { + ep.images.first().originalURL + } else { + "" + } + episodeList.add( + + newEpisode(href) { + this.name = ep.name + this.season = season + this.episode = ep.number.toInt() + this.description = ep.plot + this.posterUrl = postImage + } + ) + } + } + + + if (episodeList.isEmpty()) throw ErrorLoadingException("No Seasons Found") + + return newTvSeriesLoadResponse(name, url, type, episodeList) { + this.posterUrl = poster + this.year = year.filter { it.isDigit() }.toInt() + this.plot = document.selectFirst("div.plot-wrap > p")!!.text() + this.duration = datajs.runtime?.toInt() + this.rating = (datajs.votes[0].average.toFloatOrNull()?.times(1000))?.toInt() + this.tags = datajs.genres.map { it.name } + addTrailer(trailerUrl) + this.recommendations = correlatesList + } + + + } else { + + return newMovieLoadResponse( + document.selectFirst("div > div > h1")!!.text(), + document.select("a.play-hitzone").attr("href"), + type, + document.select("a.play-hitzone").attr("href") + ) { + posterUrl = fixUrlNull(poster) + this.year = year.filter { it.isDigit() }.toInt() + this.plot = document.selectFirst("p.plot")!!.text() + this.rating = datajs.votes[0].average.toFloatOrNull()?.times(1000)?.toInt() + this.tags = datajs.genres.map { it.name } + this.duration = datajs.runtime?.toInt() + addTrailer(trailerUrl) + this.recommendations = correlatesList + } + + } + } + + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val ip = app.get("https://api.ipify.org/").text + val videosPage = app.get(data, headers = mapOf("user-agent" to userAgent)).document + val scwsidJs = videosPage.select("video-player").attr("response").replace(""", """"""") + val jsn = JSONObject(scwsidJs) + val scwsid = jsn.getString("scws_id") + val expire = (System.currentTimeMillis() / 1000 + 172800).toString() + + val token0 = "$expire$ip Yc8U6r8KjAKAepEA".toByteArray() + val token1 = MessageDigest.getInstance("MD5").digest(token0) + val token2 = base64Encode(token1) + val token = token2.replace("=", "").replace("+", "-").replace("/", "_") + + val link = "https://scws.work/master/$scwsid?token=$token&expires=$expire&n=1" + + callback.invoke( + ExtractorLink( + name, + name, + link, + isM3u8 = true, + referer = mainUrl, + quality = Qualities.Unknown.value + ) + ) + return true + } +} + data class Moviedata( @JsonProperty("id") val id: Long, @JsonProperty("name") val name: String, @@ -20,30 +252,25 @@ data class Moviedata( @JsonProperty("votes") val votes: List, @JsonProperty("runtime") val runtime: Long? = null ) - data class Genre( @JsonProperty("name") val name: String, @JsonProperty("pivot") val pivot: Pivot, ) - data class Pivot( @JsonProperty("titleID") val titleID: Long, @JsonProperty("genreID") val genreID: Long, ) - data class Vote( @JsonProperty("title_id") val title_id: Long, @JsonProperty("average") val average: String, @JsonProperty("count") val count: Long, @JsonProperty("type") val type: String, ) - data class VideoElement( @JsonProperty("id") val id: Long, @JsonProperty("slug") val slug: String, @JsonProperty("images") val images: List, ) - data class Image( @JsonProperty("imageable_id") val imageableID: Long, @JsonProperty("imageable_type") val imageableType: String, @@ -55,9 +282,7 @@ data class Image( // @JsonProperty("proxy") val proxy: Proxy, // @JsonProperty("server") val server: Proxy ) - // Proxy is not used and crashes otherwise - //data class Proxy( // @JsonProperty("id") val id: Long, // @JsonProperty("type") val type: String, @@ -84,7 +309,6 @@ data class Season( @JsonProperty("updated_at") val updatedAt: String? = "", @JsonProperty("episodes") val episodes: List ) - data class Episodejson( @JsonProperty("id") val id: Long, @JsonProperty("number") val number: Long, @@ -93,7 +317,6 @@ data class Episodejson( @JsonProperty("season_id") val seasonID: Long, @JsonProperty("images") val images: List ) - data class ImageSeason( @JsonProperty("imageable_id") val imageableID: Long, @JsonProperty("imageable_type") val imageableType: String, @@ -103,7 +326,6 @@ data class ImageSeason( @JsonProperty("type") val type: String, @JsonProperty("original_url") val originalURL: String ) - data class TrailerElement( @JsonProperty("id") val id: Long? = null, @JsonProperty("url") val url: String? = null, @@ -123,326 +345,4 @@ data class TrailerElement( @JsonProperty("proxy_id") val proxyID: Any? = null, @JsonProperty("proxy_default_id") val proxyDefaultID: Any? = null, @JsonProperty("scws_id") val scwsID: Any? = null -) - - -class StreamingcommunityProvider: MainAPI() { - override var lang = "it" - override var mainUrl = "https://streamingcommunity.cheap" - override var name = "StreamingCommunity" - override val hasMainPage = true - override val hasChromecastSupport = true - override val supportedTypes = setOf( - TvType.Movie, - TvType.TvSeries, - ) - - private fun translatenumber(num: Int): Int? { - return when (num) { - 67 -> 1 - 71 -> 2 - 72 -> 3 - 73 -> 4 - 74 -> 5 - 75 -> 6 - 76 -> 7 - 77 -> 8 - 78 -> 9 - 79 -> 10 - 133 -> 11 - else -> null - } - } - - private fun translateip(num: Int): String? { - return when (num) { - 16 -> "sc-b1-01.scws-content.net" - 17 -> "sc-b1-02.scws-content.net" - 18 -> "sc-b1-03.scws-content.net" - 85 -> "sc-b1-04.scws-content.net" - 95 -> "sc-b1-05.scws-content.net" - 117 -> "sc-b1-06.scws-content.net" - 141 -> "sc-b1-07.scws-content.net" - 142 -> "sc-b1-08.scws-content.net" - 143 -> "sc-b1-09.scws-content.net" - 144 -> "sc-b1-10.scws-content.net" - else -> null - } - } - -// companion object { -// val posterMap = hashMapOf() -// } - - override suspend fun getMainPage(page: Int, request : MainPageRequest): HomePageResponse { - val items = ArrayList() - val document = app.get(mainUrl).document - document.select("slider-title").subList(0, 3).map { it -> - if (it.attr("slider-name") != "In arrivo") { - val films = it.attr("titles-json") - val lista = mutableListOf() - val videoData = parseJson>(films) - - videoData.subList(0, 12).apmap { searchr -> - val id = searchr.id - val name = searchr.slug - val img = searchr.images[0].url - val number = translatenumber(searchr.images[0].serverID.toInt()) - val ip = translateip(searchr.images[0].proxyID.toInt()) - val posterurl = "https://$ip/images/$number/$img" - val videourl = "$mainUrl/titles/$id-$name" - //posterMap[videourl] = posterurl - val data = app.post("$mainUrl/api/titles/preview/$id", referer = mainUrl).text - val datajs = parseJson(data) - val type: TvType = if (datajs.type == "movie") { - TvType.Movie - } else { - TvType.TvSeries - } - - lista.add( - MovieSearchResponse( - datajs.name, - videourl, - this.name, - type, - posterurl, - datajs.releaseDate.substringBefore("-").filter { it.isDigit() } - .toIntOrNull(), - null, - ) - ) - } - items.add(HomePageList(it.attr("slider-name"), lista)) - } - } - if (items.size <= 0) throw ErrorLoadingException() - return HomePageResponse(items) - } - - override suspend fun search(query: String): List { - val queryformatted = query.replace(" ", "%20") - val url = "$mainUrl/search?q=$queryformatted" - val document = app.get(url).document - - val films = - document.selectFirst("the-search-page")!!.attr("records-json").replace(""", """"""") - - val searchresults = parseJson>(films) - return searchresults.apmap { result -> - val id = result.id - val name = result.slug - val img = result.images[0].url - val number = translatenumber(result.images[0].serverID.toInt()) - val ip = translateip(result.images[0].proxyID.toInt()) - val data = app.post("$mainUrl/api/titles/preview/$id", referer = mainUrl).text - val datajs = parseJson(data) - val posterurl = "https://$ip/images/$number/$img" - val videourl = "$mainUrl/titles/$id-$name" - //posterMap[videourl] = posterurl - if (datajs.type == "movie") { - val type = TvType.Movie - MovieSearchResponse( - datajs.name, - videourl, - this.name, - type, - posterurl, - datajs.releaseDate.substringBefore("-").filter { it.isDigit() }.toIntOrNull(), - null, - ) - } else { - val type = TvType.TvSeries - TvSeriesSearchResponse( - datajs.name, - videourl, - this.name, - type, - posterurl, - datajs.releaseDate.substringBefore("-").filter { it.isDigit() }.toIntOrNull(), - null, - ) - } - - } - - } - - override suspend fun load(url: String): LoadResponse { - - val document = app.get(url).document - val poster = Regex("url\\('(.*)'").find(document.selectFirst("div.title-wrap")?.attributes() - ?.get("style") ?: "")?.groupValues?.last() //posterMap[url] - val id = url.substringBefore("-").filter { it.isDigit() } - val data = app.post("$mainUrl/api/titles/preview/$id", referer = mainUrl).text - - val datajs = parseJson(data) - val type: TvType = if (datajs.type == "movie") { - TvType.Movie - } else { - TvType.TvSeries - } - val trailerinfojs = document.select("slider-trailer").attr("videos") - val trailerinfo = parseJson>(trailerinfojs) - val trailerurl: String? = if (trailerinfo.isNotEmpty()) { - "https://www.youtube.com/watch?v=${trailerinfo[0].url}" - } else { - null - } - - val year = datajs.releaseDate.substringBefore("-") - - val correlatijs = document.selectFirst("slider-title")!!.attr("titles-json") - val listacorr = mutableListOf() - val correlatidata = parseJson>(correlatijs) - val number : Int = if (correlatidata.size<=15) {correlatidata.size} else correlatidata.size-15 - - correlatidata.take(number).apmap { searchr -> - val idcorr = searchr.id - val name = searchr.slug - val img = searchr.images[0].url - val number = translatenumber(searchr.images[0].serverID.toInt()) - val ip = translateip(searchr.images[0].proxyID.toInt()) - val datacorrel = app.post("$mainUrl/api/titles/preview/$idcorr", referer = mainUrl).text - val datajscorrel = parseJson(datacorrel) - val videourl = "$mainUrl/titles/$idcorr-$name" - val posterurl = "https://$ip/images/$number/$img" - - //posterMap[videourl] = posterurl - val typecorr: TvType = if (datajscorrel.type == "movie") { - TvType.Movie - } else { - TvType.TvSeries - } - - listacorr.add( - MovieSearchResponse( - datajscorrel.name, - videourl, - this.name, - typecorr, - posterurl, - datajscorrel.releaseDate.substringBefore("-").filter { it.isDigit() } - .toIntOrNull(), - null, - ) - ) - } - - if (type == TvType.TvSeries) { - - val name = datajs.name - val episodeList = arrayListOf() - - val episodes = - Html.fromHtml(document.selectFirst("season-select")!!.attr("seasons")).toString() - val jsonEpisodes = parseJson>(episodes) - - jsonEpisodes.map { seasons -> - val stagione = seasons.number.toInt() - val sid = seasons.title_id - val episodio = seasons.episodes - episodio.map { ep -> - val href = "$mainUrl/watch/$sid?e=${ep.id}" - val postimage = if (ep.images.isNotEmpty()) { - ep.images.first().originalURL - } else { - "" - } - episodeList.add( - - newEpisode(href) { - this.name = ep.name - this.season = stagione - this.episode = ep.number.toInt() - this.description = ep.plot - this.posterUrl = postimage - } - ) - } - } - - - if (episodeList.isEmpty()) throw ErrorLoadingException("No Seasons Found") - - return newTvSeriesLoadResponse(name, url, type, episodeList) { - this.posterUrl = poster - this.year = year.filter { it.isDigit() }.toInt() - this.plot = document.selectFirst("div.plot-wrap > p")!!.text() - this.duration = datajs.runtime?.toInt() - this.rating = (datajs.votes[0].average.toFloatOrNull()?.times(1000))?.toInt() - this.tags = datajs.genres.map { it.name } - addTrailer(trailerurl) - this.recommendations = listacorr - } - - - } else { - - return newMovieLoadResponse( - document.selectFirst("div > div > h1")!!.text(), - document.select("a.play-hitzone").attr("href"), - type, - document.select("a.play-hitzone").attr("href") - ) { - posterUrl = fixUrlNull(poster) - this.year = year.filter { it.isDigit() }.toInt() - this.plot = document.selectFirst("p.plot")!!.text() - this.rating = datajs.votes[0].average.toFloatOrNull()?.times(1000)?.toInt() - this.tags = datajs.genres.map { it.name } - this.duration = datajs.runtime?.toInt() - addTrailer(trailerurl) - this.recommendations = listacorr - } - - } - } - - - private suspend fun getM3u8Qualities( - m3u8Link: String, - referer: String, - qualityName: String, - ): List { - return M3u8Helper.generateM3u8( - this.name, - m3u8Link, - referer, - name = "${this.name} - $qualityName" - ) - } - - - override suspend fun loadLinks( - data: String, - isCasting: Boolean, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ): Boolean { - val ip = app.get("https://api.ipify.org/").text - val videors = app.get(data).document - val scwsidjs = videors.select("video-player").attr("response").replace(""", """"""") - val jsn = JSONObject(scwsidjs) - val scwsid = jsn.getString("scws_id") - val expire = (System.currentTimeMillis() / 1000 + 172800).toString() - - val token0 = "$expire$ip Yc8U6r8KjAKAepEA".toByteArray() - val token1 = MessageDigest.getInstance("MD5").digest(token0) - val token2 = base64Encode(token1) - val token = token2.replace("=", "").replace("+", "-").replace("/", "_") - - val link = "https://scws.work/master/$scwsid?token=$token&expires=$expire&n=1" - - callback.invoke( - ExtractorLink( - name, - name, - link, - isM3u8 = true, - referer = mainUrl, - quality = Qualities.Unknown.value - ) - ) - return true - } -} \ No newline at end of file +) \ No newline at end of file