From 9c32a7917d2657caa1160772d3fd672f9bc1ba44 Mon Sep 17 00:00:00 2001 From: KillerDogeEmpire Date: Mon, 12 Feb 2024 17:20:01 -0800 Subject: [PATCH] New Source SxyPrn --- SxyPrn/build.gradle.kts | 28 ++++ SxyPrn/src/main/AndroidManifest.xml | 2 + .../kotlin/com/KillerDogeEmpire/SxyPrn.kt | 143 ++++++++++++++++++ .../com/KillerDogeEmpire/SxyPrnProvider.kt | 14 ++ 4 files changed, 187 insertions(+) create mode 100644 SxyPrn/build.gradle.kts create mode 100644 SxyPrn/src/main/AndroidManifest.xml create mode 100644 SxyPrn/src/main/kotlin/com/KillerDogeEmpire/SxyPrn.kt create mode 100644 SxyPrn/src/main/kotlin/com/KillerDogeEmpire/SxyPrnProvider.kt diff --git a/SxyPrn/build.gradle.kts b/SxyPrn/build.gradle.kts new file mode 100644 index 0000000..8a7f093 --- /dev/null +++ b/SxyPrn/build.gradle.kts @@ -0,0 +1,28 @@ +// use an integer for version numbers +version = 5 + + +cloudstream { + // All of these properties are optional, you can safely remove them + + description = "sxyprn" + authors = listOf("Coxju") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + + // List of video source types. Users are able to filter for extensions in a given category. + // You can find a list of avaliable types here: + // https://recloudstream.github.io/cloudstream/html/app/com.lagradost.cloudstream3/-tv-type/index.html + tvTypes = listOf("NSFW") + + iconUrl = "https://www.google.com/s2/favicons?domain=sxyprn.com&sz=%size%" + + language = "en" +} diff --git a/SxyPrn/src/main/AndroidManifest.xml b/SxyPrn/src/main/AndroidManifest.xml new file mode 100644 index 0000000..0862a59 --- /dev/null +++ b/SxyPrn/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/SxyPrn/src/main/kotlin/com/KillerDogeEmpire/SxyPrn.kt b/SxyPrn/src/main/kotlin/com/KillerDogeEmpire/SxyPrn.kt new file mode 100644 index 0000000..b5b50dc --- /dev/null +++ b/SxyPrn/src/main/kotlin/com/KillerDogeEmpire/SxyPrn.kt @@ -0,0 +1,143 @@ +package com.KillerDogeEmpire + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.AppUtils +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities +import org.jsoup.nodes.Element + +class SxyPrn : MainAPI() { + override var mainUrl = "https://sxyprn.com" + override var name = "Sxyprn" + override val hasMainPage = true + override val hasDownloadSupport = true + override val vpnStatus = VPNStatus.MightBeNeeded + override val supportedTypes = setOf(TvType.NSFW) + + override val mainPage = mainPageOf( + "$mainUrl/new.html?page=" to "New Videos", + "$mainUrl/new.html?sm=trending&page=" to "Trending", + "$mainUrl/new.html?sm=views&page=" to "Most Viewed", + "$mainUrl/popular/top-viewed.html?p=day" to "Popular - Day", + "$mainUrl/popular/top-viewed.html" to "Popular - Week", + "$mainUrl/popular/top-viewed.html?p=month" to "Popular - Month", + "$mainUrl/popular/top-viewed.html?p=all" to "Popular - All Time" + ) + + override suspend fun getMainPage( + page: Int, request: MainPageRequest + ): HomePageResponse { + var pageStr = ((page - 1) * 30).toString() + + val document = if ("page=" in request.data) { + app.get(request.data + pageStr).document + } else if ("/blog/" in request.data) { + pageStr = ((page - 1) * 20).toString() + app.get(request.data.replace(".html", "$pageStr.html")).document + } else { + app.get(request.data.replace(".html", ".html/$pageStr")).document + } + val home = document.select("div.main_content div.post_el_small").mapNotNull { + it.toSearchResult() + } + return newHomePageResponse( + list = HomePageList( + name = request.name, list = home, isHorizontalImages = true + ), hasNext = true + ) + } + + private fun Element.toSearchResult(): SearchResponse? { + val title = this.selectFirst("div.post_text")?.text() ?: return null + val href = fixUrl(this.selectFirst("a.js-pop")!!.attr("href")) + var posterUrl = fixUrl(this.select("div.vid_container div.post_vid_thumb img").attr("src")) + if (posterUrl == "") { + posterUrl = + fixUrl(this.select("div.vid_container div.post_vid_thumb img").attr("data-src")) + } + return newMovieSearchResponse(title, href, TvType.Movie) { + this.posterUrl = posterUrl + } + } + + override suspend fun search(query: String): List { + val searchResponse = mutableListOf() + for (i in 0 until 15) { + val document = app.get( + "$mainUrl/${query.replace(" ", "-")}.html?page=${i * 30}" + ).document + val results = document.select("div.main_content div.post_el_small").mapNotNull { + it.toSearchResult() + } + if (!searchResponse.containsAll(results)) { + searchResponse.addAll(results) + } else { + break + } + if (results.isEmpty()) break + } + return searchResponse + } + + override suspend fun load(url: String): LoadResponse { + val document = app.get(url).document + val title = document.selectFirst("div.post_text")?.text()?.trim().toString() + val poster = fixUrlNull( + document.selectFirst("div#vid_container_id meta[itemprop=thumbnailUrl]") + ?.attr("content") + ) + + val recommendations = document.select("div.main_content div div.post_el_small").mapNotNull { + it.toSearchResult() + } + + return newMovieLoadResponse(title, url, TvType.NSFW, url) { + this.posterUrl = poster + this.recommendations = recommendations + } + } + + private fun updateUrl(arg: MutableList): MutableList { + arg[5] = + (Integer.parseInt(arg[5]) - (generateNumber(arg[6]) + generateNumber(arg[7]))).toString() + return arg + } + + private fun generateNumber(arg: String): Int { + val str = arg.replace(Regex("\\D"), "") + var sut = 0 + for (element in str) { + sut += Integer.parseInt(element.toString(), 10) + } + return sut + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val document = app.get(data).document + val parsed = AppUtils.parseJson>( + document.select("span.vidsnfo").attr("data-vnfo") + ) + parsed[parsed.keys.toList()[0]] + var url = parsed[parsed.keys.toList()[0]].toString() + + var tmp = url.split("/").toMutableList() + tmp[1] += "8" + tmp = updateUrl(tmp) + + url = fixUrl(tmp.joinToString("/")) + + callback.invoke( + ExtractorLink( + this.name, this.name, url, referer = data, quality = Qualities.Unknown.value + ) + ) + + return true + } + +} \ No newline at end of file diff --git a/SxyPrn/src/main/kotlin/com/KillerDogeEmpire/SxyPrnProvider.kt b/SxyPrn/src/main/kotlin/com/KillerDogeEmpire/SxyPrnProvider.kt new file mode 100644 index 0000000..80830ca --- /dev/null +++ b/SxyPrn/src/main/kotlin/com/KillerDogeEmpire/SxyPrnProvider.kt @@ -0,0 +1,14 @@ +package com.KillerDogeEmpire + +import android.content.Context +import com.KillerDogeEmpire.SxyPrn +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin + +@CloudstreamPlugin +class SxyPrnProvider : Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(SxyPrn()) + } +} \ No newline at end of file