From 9ddb4b9b96ec13e3b10db2a3dc2cbb9846ebec47 Mon Sep 17 00:00:00 2001 From: KillerDogeEmpire Date: Mon, 12 Feb 2024 17:12:07 -0800 Subject: [PATCH] New Source FullPorner --- FullPorner/build.gradle.kts | 18 ++ FullPorner/src/main/AndroidManifest.xml | 2 + .../kotlin/com/KillerDogeEmpire/FullPorner.kt | 162 ++++++++++++++++++ .../KillerDogeEmpire/FullPornerProvider.kt | 12 ++ 4 files changed, 194 insertions(+) create mode 100644 FullPorner/build.gradle.kts create mode 100644 FullPorner/src/main/AndroidManifest.xml create mode 100644 FullPorner/src/main/kotlin/com/KillerDogeEmpire/FullPorner.kt create mode 100644 FullPorner/src/main/kotlin/com/KillerDogeEmpire/FullPornerProvider.kt diff --git a/FullPorner/build.gradle.kts b/FullPorner/build.gradle.kts new file mode 100644 index 0000000..1dce6ab --- /dev/null +++ b/FullPorner/build.gradle.kts @@ -0,0 +1,18 @@ +version = 4 + +cloudstream { + authors = listOf("KillerDogeEmpire, Coxju") + language = "en" + description = "FullPorner is the best free full length porn video site. Choose from millions of hardcore videos that stream quickly and in high quality and only full length" + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + **/ + status = 1 // will be 3 if unspecified + tvTypes = listOf("NSFW") + iconUrl = "https://www.google.com/s2/favicons?domain=fullporner.com&sz=%size%" +} diff --git a/FullPorner/src/main/AndroidManifest.xml b/FullPorner/src/main/AndroidManifest.xml new file mode 100644 index 0000000..3f4d39b --- /dev/null +++ b/FullPorner/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/FullPorner/src/main/kotlin/com/KillerDogeEmpire/FullPorner.kt b/FullPorner/src/main/kotlin/com/KillerDogeEmpire/FullPorner.kt new file mode 100644 index 0000000..071e9eb --- /dev/null +++ b/FullPorner/src/main/kotlin/com/KillerDogeEmpire/FullPorner.kt @@ -0,0 +1,162 @@ +package com.KillerDogeEmpire + +import org.jsoup.nodes.Element +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.network.WebViewResolver +import com.lagradost.cloudstream3.LoadResponse.Companion.addActors +import org.jsoup.Jsoup + +class FullPorner : MainAPI() { + override var mainUrl = "https://fullporner.com" + override var name = "FullPorner" + override val hasMainPage = true + override var lang = "en" + override val hasQuickSearch = false + override val hasDownloadSupport = true + override val hasChromecastSupport = true + override val supportedTypes = setOf(TvType.NSFW) + override val vpnStatus = VPNStatus.MightBeNeeded + + override val mainPage = mainPageOf( + "${mainUrl}/home/" to "Featured", + "${mainUrl}/category/amateur/" to "Amateur", + "${mainUrl}/category/teen/" to "Teen", + "${mainUrl}/category/cumshot/" to "CumShot", + "${mainUrl}/category/deepthroat/" to "DeepThroat", + "${mainUrl}/category/orgasm/" to "Orgasm", + "${mainUrl}/category/threesome/" to "ThreeSome", + "${mainUrl}/category/group-sex/" to "Group Sex", + ) + + override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { + val document = app.get("${request.data}${page}").document + val home = document.select("div.video-block div.video-card").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.video-card div.video-card-body div.video-title a")?.text() ?: return null + val href = fixUrl(this.selectFirst("div.video-card div.video-card-body div.video-title a")!!.attr("href")) + val posterUrl = fixUrlNull(this.select("div.video-card div.video-card-image a 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 1..15) { + val document = app.get("${mainUrl}/search?q=${query.replace(" ", "+")}&p=$i").document + + val results = document.select("div.video-block div.video-card").mapNotNull { it.toSearchResult() } + + searchResponse.addAll(results) + + if (results.isEmpty()) break + } + + return searchResponse + } + + override suspend fun load(url: String): LoadResponse { + val document = app.get(url).document + + val title = document.selectFirst("div.video-block div.single-video-left div.single-video-title h2")?.text()?.trim().toString() + val iframeUrl = fixUrlNull(document.selectFirst("div.video-block div.single-video-left div.single-video iframe")?.attr("src")) ?: "" + + val poster: String? + val posterHeaders: Map + if (iframeUrl.contains("videoh")) { + val iframeDocument = app.get(iframeUrl, interceptor = WebViewResolver(Regex("""mydaddy"""))).document + + val videoHtml = iframeDocument.selectXpath("//script[contains(text(),'poster')]").first()?.html()?.substringAfter("else{ \$(\"#jw\").html(\"")?.substringBefore("\");}if(hasAdblock)")?.replace("\\", "") + val video = Jsoup.parse(videoHtml.toString()).selectFirst("video") + + poster = fixUrlNull(video?.attr("poster")) + posterHeaders = mapOf(Pair("referer", "https://mydaddy.cc/")) + } else { + val iframeDocument = app.get(iframeUrl).document + val videoDocument = Jsoup.parse("") + "") + + poster = fixUrlNull(videoDocument.selectFirst("video")?.attr("poster").toString()) + posterHeaders = mapOf(Pair("referer", "https://xiaoshenke.net/")) + } + + val tags = document.select("div.video-blockdiv.single-video-left div.single-video-title p.tag-link span a").map { it.text() } + val description = document.selectFirst("div.video-block div.single-video-left div.single-video-title h2")?.text()?.trim().toString() + val actors = document.select("div.video-block div.single-video-left div.single-video-info-content p a").map { it.text() } + val recommendations = document.select("div.video-block div.video-recommendation div.video-card").mapNotNull { it.toSearchResult() } + + return newMovieLoadResponse(title, url, TvType.NSFW, url) { + this.posterUrl = poster + this.posterHeaders = posterHeaders + this.plot = description + this.tags = tags + this.recommendations = recommendations + addActors(actors) + } + } + + override suspend fun loadLinks(data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit): Boolean { + val document = app.get(data).document + + val iframeUrl = fixUrlNull(document.selectFirst("div.video-block div.single-video-left div.single-video iframe")?.attr("src")) ?: "" + + val extlinkList = mutableListOf() + if (iframeUrl.contains("videoh")) { + val iframeDocument = app.get(iframeUrl, interceptor = WebViewResolver(Regex("""mydaddy"""))).document + val videoDocument = Jsoup.parse("") + "") + + videoDocument.select("source").map { res -> + extlinkList.add(ExtractorLink( + name, + name, + fixUrl(res.attr("src")), + referer = data, + quality = Regex("(\\d+.)").find(res.attr("title"))?.groupValues?.get(1).let { getQualityFromName(it) } + )) + } + } else if (iframeUrl.contains("xiaoshenke")) { + val iframeDocument = app.get(iframeUrl).document + val videoID = Regex("""var id = \"(.+?)\"""").find(iframeDocument.html())?.groupValues?.get(1) + + val pornTrexDocument = app.get("https://www.porntrex.com/embed/${videoID}").document + val video_url = fixUrlNull(Regex("""video_url: \'(.+?)\',""").find(pornTrexDocument.html())?.groupValues?.get(1)) + if (video_url != null) { + extlinkList.add(ExtractorLink( + name, + name, + video_url, + referer = data, + quality = Qualities.Unknown.value + )) + } + } else { + val iframeDocument = app.get(iframeUrl).document + val videoDocument = Jsoup.parse("") + "") + + videoDocument.select("source").map { res -> + extlinkList.add(ExtractorLink( + this.name, + this.name, + fixUrl(res.attr("src")), + referer = mainUrl, + quality = Regex("(\\d+.)").find(res.attr("title"))?.groupValues?.get(1).let { getQualityFromName(it) } + )) + } + } + + extlinkList.forEach(callback) + + return true + } +} \ No newline at end of file diff --git a/FullPorner/src/main/kotlin/com/KillerDogeEmpire/FullPornerProvider.kt b/FullPorner/src/main/kotlin/com/KillerDogeEmpire/FullPornerProvider.kt new file mode 100644 index 0000000..5ff8087 --- /dev/null +++ b/FullPorner/src/main/kotlin/com/KillerDogeEmpire/FullPornerProvider.kt @@ -0,0 +1,12 @@ +package com.KillerDogeEmpire + +import android.content.Context +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin + +@CloudstreamPlugin +class FullPornerProvider : Plugin() { + override fun load(context: Context) { + registerMainAPI(FullPorner()) + } +} \ No newline at end of file