From 5e2c225b19adac522b41d9979564be0c0dd6826e Mon Sep 17 00:00:00 2001
From: Jace <54625750+Jacekun@users.noreply.github.com>
Date: Sun, 7 Sep 2025 18:33:45 +0800
Subject: [PATCH 1/4] Removed HpJav -> Moved to new domain Javtiful
---
HpJav/build.gradle.kts | 28 -----
HpJav/src/main/AndroidManifest.xml | 2 -
HpJav/src/main/kotlin/com/jacekun/HpJav.kt | 118 ------------------
.../main/kotlin/com/jacekun/HpJavPlugin.kt | 13 --
4 files changed, 161 deletions(-)
delete mode 100644 HpJav/build.gradle.kts
delete mode 100644 HpJav/src/main/AndroidManifest.xml
delete mode 100644 HpJav/src/main/kotlin/com/jacekun/HpJav.kt
delete mode 100644 HpJav/src/main/kotlin/com/jacekun/HpJavPlugin.kt
diff --git a/HpJav/build.gradle.kts b/HpJav/build.gradle.kts
deleted file mode 100644
index c113cb44..00000000
--- a/HpJav/build.gradle.kts
+++ /dev/null
@@ -1,28 +0,0 @@
-// use an integer for version numbers
-version = 4
-
-
-cloudstream {
- // All of these properties are optional, you can safely remove them
-
- description = ""
- authors = listOf("Jace")
-
- /**
- * Status int as the following:
- * 0: Down
- * 1: Ok
- * 2: Slow
- * 3: Beta only
- * */
- status = 3 // 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=hpjav.tv&sz=%size%"
-
- language = "en"
-}
diff --git a/HpJav/src/main/AndroidManifest.xml b/HpJav/src/main/AndroidManifest.xml
deleted file mode 100644
index 29aec9de..00000000
--- a/HpJav/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/HpJav/src/main/kotlin/com/jacekun/HpJav.kt b/HpJav/src/main/kotlin/com/jacekun/HpJav.kt
deleted file mode 100644
index eed83311..00000000
--- a/HpJav/src/main/kotlin/com/jacekun/HpJav.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.jacekun
-
-import com.lagradost.cloudstream3.MainAPI
-import com.lagradost.cloudstream3.TvType
-import com.lagradost.cloudstream3.*
-import com.lagradost.cloudstream3.app
-import org.jsoup.Jsoup
-
-class HpJav : MainAPI() {
- private val DEV = "DevDebug"
- private val globaltvType = TvType.NSFW
-
- override var name = "HpJav TV"
- override var mainUrl = "https://hpjav.tv"
- override val supportedTypes = setOf(TvType.NSFW)
- override val hasDownloadSupport = false
- override val hasMainPage = true
- override val hasQuickSearch = false
-
- override suspend fun getMainPage(
- page: Int,
- request: MainPageRequest
- ): HomePageResponse {
- val document = app.get(mainUrl).document
- val all = ArrayList()
- document.getElementsByTag("body")?.select("div.container")?.forEach { it2 ->
- // Fetch row title
- val title = it2.select("div.category-count > h3")?.text() ?: ""
- // Fetch list of items and map
- val elements = it2.select("div.post-list > div")?.mapNotNull {
- //Fetch entries
- val aa = it.selectFirst("div.video-item > div > a") ?: return@mapNotNull null
- val linkTitle = it.select("div.entry-title > a") ?: return@mapNotNull null
- val link = fixUrlNull(linkTitle.attr("href")) ?: return@mapNotNull null
- val name = linkTitle.text() ?: ""
- val image = if (link != "") { aa.select("img")?.attr("data-original") } else { null }
- val year = null
- //Log.i(DEV, "Result => (image) ${image} , (linkCode) ${linkCode}, (link) ${link}")
-
- MovieSearchResponse(
- name,
- link,
- this.name,
- globaltvType,
- image,
- year,
- null,
- )
- }?.distinctBy { it.url } ?: listOf()
- if (elements.isNotEmpty()) {
- all.add(
- HomePageList(
- title, elements
- )
- )
- }
- }
- return HomePageResponse(all.filter { hp -> hp.list.isNotEmpty() })
- }
-
- //TODO: Fix search
- override suspend fun search(query: String): List {
- val url = "$mainUrl/?s=$query"
- val document = app.get(url).document.getElementsByTag("body")
- .select("div.container > div > div.post-list")
- .select("div.col-md-3.col-sm-6.col-xs-6")
- //Log.i(DEV, "Result => $document")
- return document.map {
- val content = it.select("div.video-item > div > a").firstOrNull()
- //Log.i(DEV, "Result => $content")
- val linkCode = content?.attr("href") ?: ""
- val href = fixUrl(linkCode)
- val imgContent = content?.select("img")
- val title = imgContent?.attr("alt") ?: ""
- val image = imgContent?.attr("data-original")?.trim('\'')
- val year = null
- //Log.i(DEV, "Result => Title: ${title}, Image: ${image}")
-
- MovieSearchResponse(
- title,
- href,
- this.name,
- globaltvType,
- image,
- year
- )
- }
- }
- //TODO: Fix load
- override suspend fun load(url: String): LoadResponse {
- val response = app.get(url).text
- val document = Jsoup.parse(response)
- //Log.i(DEV, "Url => ${url}")
- val body = document.getElementsByTag("body")
- .select("div.video-box-ather.container > div.container > div")
- .select("div > div > img")?.firstOrNull()
- //Log.i(DEV, "Result => ${body}")
- // Video details
- val poster = body?.attr("src")
- val title = body?.attr("alt") ?: ""
- val descript = ""
- val year = null
-
- // Video link
- val streamUrl = ""
- return MovieLoadResponse(
- name = title,
- url = url,
- apiName = this.name,
- type = globaltvType,
- dataUrl = streamUrl,
- posterUrl = poster,
- year = year,
- plot = descript,
- comingSoon = true
- )
- }
-}
\ No newline at end of file
diff --git a/HpJav/src/main/kotlin/com/jacekun/HpJavPlugin.kt b/HpJav/src/main/kotlin/com/jacekun/HpJavPlugin.kt
deleted file mode 100644
index 0c6b1aca..00000000
--- a/HpJav/src/main/kotlin/com/jacekun/HpJavPlugin.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.jacekun
-
-import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
-import com.lagradost.cloudstream3.plugins.Plugin
-import android.content.Context
-
-@CloudstreamPlugin
-class HpJavPlugin: Plugin() {
- override fun load(context: Context) {
- // All providers should be added in this manner. Please don't edit the providers list directly.
- registerMainAPI(HpJav())
- }
-}
\ No newline at end of file
From 6fd92fbb4f282437e5dbe0ea468c2955186cb935 Mon Sep 17 00:00:00 2001
From: Jace <54625750+Jacekun@users.noreply.github.com>
Date: Sun, 7 Sep 2025 18:34:05 +0800
Subject: [PATCH 2/4] Removed JavTube -> Domain expired.
---
JavTube/build.gradle.kts | 28 --
JavTube/src/main/AndroidManifest.xml | 2 -
.../src/main/kotlin/com/jacekun/JavTube.kt | 240 ------------------
.../main/kotlin/com/jacekun/JavTubePlugin.kt | 13 -
4 files changed, 283 deletions(-)
delete mode 100644 JavTube/build.gradle.kts
delete mode 100644 JavTube/src/main/AndroidManifest.xml
delete mode 100644 JavTube/src/main/kotlin/com/jacekun/JavTube.kt
delete mode 100644 JavTube/src/main/kotlin/com/jacekun/JavTubePlugin.kt
diff --git a/JavTube/build.gradle.kts b/JavTube/build.gradle.kts
deleted file mode 100644
index 917a3e90..00000000
--- a/JavTube/build.gradle.kts
+++ /dev/null
@@ -1,28 +0,0 @@
-// use an integer for version numbers
-version = 5
-
-
-cloudstream {
- // All of these properties are optional, you can safely remove them
-
- description = "Watch Jav Tube FULL HD"
- authors = listOf("Jace")
-
- /**
- * 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=javtube.watch&sz=%size%"
-
- language = "en"
-}
diff --git a/JavTube/src/main/AndroidManifest.xml b/JavTube/src/main/AndroidManifest.xml
deleted file mode 100644
index 29aec9de..00000000
--- a/JavTube/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/JavTube/src/main/kotlin/com/jacekun/JavTube.kt b/JavTube/src/main/kotlin/com/jacekun/JavTube.kt
deleted file mode 100644
index 1092e198..00000000
--- a/JavTube/src/main/kotlin/com/jacekun/JavTube.kt
+++ /dev/null
@@ -1,240 +0,0 @@
-package com.jacekun
-
-import android.util.Log
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.lagradost.cloudstream3.*
-import com.lagradost.cloudstream3.app
-import com.lagradost.cloudstream3.utils.AppUtils
-import com.lagradost.cloudstream3.utils.ExtractorLink
-import com.lagradost.cloudstream3.utils.loadExtractor
-import org.jsoup.Jsoup
-
-class JavTube : MainAPI() {
- private val DEV = "DevDebug"
- private val globaltvType = TvType.NSFW
- override var name = "JavTube"
- override var mainUrl = "https://javtube.watch"
- override val supportedTypes = setOf(TvType.NSFW)
- override val hasDownloadSupport = true
- override val hasMainPage = true
- override val hasQuickSearch = false
-
- override suspend fun getMainPage(
- page: Int,
- request: MainPageRequest
- ): HomePageResponse {
- val document = app.get(mainUrl).document
- val all = ArrayList()
-
- // Fetch row title
- val title = "Latest videos"
- // Fetch list of items and map
- val inner = document.selectFirst("div.videos-list")?.select("article") ?: return HomePageResponse(all)
- //Log.i(DEV, "Inner => $inner")
- val elements: List = inner.mapNotNull {
-
- //Log.i(DEV, "Inner content => $innerArticle")
- val aa = it.select("a").last() ?: return@mapNotNull null
- val link = fixUrlNull(aa.attr("href")) ?: return@mapNotNull null
-
- val imgArticle = aa.select("img")
- val name = imgArticle.attr("alt") ?: ""
- var image = imgArticle.attr("data-src")
- if (image.isNullOrEmpty()) {
- image = imgArticle.attr("src")
- }
-
- MovieSearchResponse(
- name = name,
- url = link,
- apiName = this.name,
- type = globaltvType,
- posterUrl = image,
- year = null,
- id = null,
- )
- }.distinctBy { a -> a.url }
-
- all.add(
- HomePageList(
- title, elements
- )
- )
-
- return HomePageResponse(all.filter { a -> a.list.isNotEmpty() })
- }
-
- override suspend fun search(query: String): List {
- val url = "$mainUrl/search/$query"
- val document = app.get(url).document.select("article#post")
-
- return document.mapNotNull {
- val innerA = it?.selectFirst("a") ?: return@mapNotNull null
- val linkUrl = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
- if (linkUrl.startsWith("https://javtube.watch/tag/")) {
- //Log.i(DEV, "Result => (innerA) $innerA")
- return@mapNotNull null
- }
-
- val title = innerA.select("header.entry-header").text()
- val imgLink = innerA.select("img")
- var image = imgLink.attr("data-src")
- if (image.isNullOrEmpty()) {
- image = imgLink.attr("src")
- }
- val year = null
-
- MovieSearchResponse(
- name = title,
- url = linkUrl,
- apiName = this.name,
- type = globaltvType,
- posterUrl = image,
- year = year
- )
- }
- }
-
- override suspend fun load(url: String): LoadResponse {
- val document = app.get(url).document
- //Log.i(DEV, "Result => ${body}")
-
- // Video details
- val content = document.selectFirst("article#post")?.select("div.video-player")
- //Log.i(DEV, "Result => (content) $content")
- val title = content?.select("meta[itemprop=\"name\"]")?.attr("content") ?: ""
- val descript =content?.select("meta[itemprop=\"description\"]")?.attr("content")
- //Log.i(DEV, "Result => (descript) $descript")
- val year = null
-
- // Poster Image
- val poster = content?.select("meta[itemprop=\"thumbnailUrl\"]")?.attr("content")
- //Log.i(DEV, "Result => (poster) $poster")
-
- //TODO: Fetch links
- //Video stream
- val streamUrl: String = try {
- val strPost = "post(\"https://javtube.watch/hash-javtubewatch\""
- val scripts = document.select("script").toString()
- val idxA = scripts.indexOf(strPost)
- val firstParse = scripts.substring(idxA)
- val idxB = firstParse.indexOf("function")
-
- val secondParse = firstParse.substring(strPost.length, idxB).trim().trim(',')
- .replace("num:", "\"num\":")
- .replace(":'", ":\"")
- .replace("'}", "\"}")
- .trim().trim(',')
- .trimEnd('}')
- "$secondParse,\"url\":\"${url}\"}"
- } catch (e: Exception) {
- Log.i(DEV, "Result => Exception (load) $e")
- ""
- }
- Log.i(DEV, "streamUrl => $streamUrl")
- return MovieLoadResponse(
- name = title,
- url = url,
- apiName = this.name,
- type = globaltvType,
- dataUrl = streamUrl,
- posterUrl = poster,
- year = year,
- plot = descript,
- )
- }
-
- //TODO: LoadLinks
- override suspend fun loadLinks(
- data: String,
- isCasting: Boolean,
- subtitleCallback: (SubtitleFile) -> Unit,
- callback: (ExtractorLink) -> Unit
- ): Boolean {
- if (data.isEmpty()) return false
- if (data == "about:blank") return false
-
- AppUtils.tryParseJson(data)?.let { reqdata ->
- Log.i(DEV, "Referer => ${reqdata.url}")
- app.post(
- url = "$mainUrl/hash-javtubewatch",
- referer = reqdata.url,
- data = mapOf(
- Pair("migboob", reqdata.migboob),
- Pair("mix", reqdata.mix),
- Pair("num", reqdata.num),
- ),
- headers = mapOf(
- Pair("Origin", mainUrl),
- Pair("Sec-Fetch-Mode", "cors"),
- Pair("User-Agent", USER_AGENT),
- )
- ).let { postreq ->
- Log.i(DEV, "Post => (${postreq.code}) ${postreq.text}")
-
- val src = Jsoup.parse(postreq.text).selectFirst("iframe")?.attr("src") ?: ""
- Log.i(DEV, "Post Url => $src")
-
- val id = src.trimEnd('/').split("/").last()
- val newUrl = "https://fembed-hd.com/api/source/${id}"
- Log.i(DEV, "newUrl => $newUrl")
- loadExtractor(
- url = newUrl,
- referer = reqdata.url,
- callback = callback,
- subtitleCallback = subtitleCallback
- )
- //TODO: Fix headers, returning 403 Forbidden
- /*val headers = mapOf(
- Pair("Host", "javjav.top"),
- Pair("Origin", src),
- Pair("Referer", reqdata.url),
- Pair("User-Agent", USER_AGENT),
- )
- Log.i(DEV, "headers => ${headers.toJson()}")
- val postlink = app.post(
- url = newUrl,
- headers = mapOf(
- Pair("Host", "javjav.top"),
- Pair("Origin", src),
- Pair("Referer", reqdata.url),
- Pair("User-Agent", USER_AGENT),
- )
- )
- Log.i(DEV, "Post Link => (${postlink.code}) ${postlink.text}")
-
- val streamLinks = AppUtils.tryParseJson(postlink.text)?.data ?: listOf()
- streamLinks.forEach{ stream ->
- callback.invoke(
- ExtractorLink(
- source = "JavTube",
- name = name,
- url = stream.file,
- referer = reqdata.url,
- quality = getQualityFromName(stream.label)
- )
- )
- }*/
- }
- }
-
- return true
- }
-
- private data class JsonRequest(
- @JsonProperty("migboob") val migboob: String,
- @JsonProperty("mix") val mix: String,
- @JsonProperty("num") val num: String,
- @JsonProperty("url") val url: String
- )
-
- private data class JsonResponse(
- @JsonProperty("success") val success: Boolean,
- @JsonProperty("data") val data: List?
- )
- private data class JsonResponseData(
- @JsonProperty("file") val file: String,
- @JsonProperty("label") val label: String,
- //val type: String // Mp4
- )
-}
\ No newline at end of file
diff --git a/JavTube/src/main/kotlin/com/jacekun/JavTubePlugin.kt b/JavTube/src/main/kotlin/com/jacekun/JavTubePlugin.kt
deleted file mode 100644
index 9c8ba7f1..00000000
--- a/JavTube/src/main/kotlin/com/jacekun/JavTubePlugin.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.jacekun
-
-import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
-import com.lagradost.cloudstream3.plugins.Plugin
-import android.content.Context
-
-@CloudstreamPlugin
-class JavTubePlugin: Plugin() {
- override fun load(context: Context) {
- // All providers should be added in this manner. Please don't edit the providers list directly.
- registerMainAPI(JavTube())
- }
-}
\ No newline at end of file
From 0b414c0fb19b0b0936c4f30df03675d86a1d0946 Mon Sep 17 00:00:00 2001
From: Jace <54625750+Jacekun@users.noreply.github.com>
Date: Sun, 7 Sep 2025 18:34:38 +0800
Subject: [PATCH 3/4] Removed JavSub -> Domain expired.
---
JavSubProvider/build.gradle.kts | 28 --
JavSubProvider/src/main/AndroidManifest.xml | 2 -
.../main/kotlin/com/jacekun/JavSubProvider.kt | 253 ------------------
.../com/jacekun/JavSubProviderPlugin.kt | 13 -
4 files changed, 296 deletions(-)
delete mode 100644 JavSubProvider/build.gradle.kts
delete mode 100644 JavSubProvider/src/main/AndroidManifest.xml
delete mode 100644 JavSubProvider/src/main/kotlin/com/jacekun/JavSubProvider.kt
delete mode 100644 JavSubProvider/src/main/kotlin/com/jacekun/JavSubProviderPlugin.kt
diff --git a/JavSubProvider/build.gradle.kts b/JavSubProvider/build.gradle.kts
deleted file mode 100644
index b828aca6..00000000
--- a/JavSubProvider/build.gradle.kts
+++ /dev/null
@@ -1,28 +0,0 @@
-// use an integer for version numbers
-version = 7
-
-
-cloudstream {
- // All of these properties are optional, you can safely remove them
-
- description = "High quality JAV with English sub"
- authors = listOf("Jace")
-
- /**
- * 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://javsub.co/wp-content/uploads/2021/09/jav-sub.png"
-
- language = "en"
-}
diff --git a/JavSubProvider/src/main/AndroidManifest.xml b/JavSubProvider/src/main/AndroidManifest.xml
deleted file mode 100644
index 29aec9de..00000000
--- a/JavSubProvider/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/JavSubProvider/src/main/kotlin/com/jacekun/JavSubProvider.kt b/JavSubProvider/src/main/kotlin/com/jacekun/JavSubProvider.kt
deleted file mode 100644
index 6285b33e..00000000
--- a/JavSubProvider/src/main/kotlin/com/jacekun/JavSubProvider.kt
+++ /dev/null
@@ -1,253 +0,0 @@
-package com.jacekun
-
-import android.util.Log
-import com.fasterxml.jackson.annotation.JsonProperty
-import com.lagradost.cloudstream3.*
-import com.lagradost.cloudstream3.utils.AppUtils.toJson
-import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
-import com.lagradost.cloudstream3.utils.ExtractorLink
-import com.lagradost.cloudstream3.utils.loadExtractor
-import org.jsoup.Jsoup
-
-class JavSubProvider : MainAPI() {
- override var name = "JavSub"
- override var mainUrl = "https://javsub.co"
- override val supportedTypes: Set get() = setOf(TvType.NSFW)
- override val hasDownloadSupport: Boolean get() = true
- override val hasMainPage: Boolean get() = true
- override val hasQuickSearch: Boolean get() = false
-
- private val prefixTag = "dummyTag" //For use on stream links to differentiate links
- private val globalTvType = TvType.NSFW
-
- data class ResponseMovieDetails(
- @JsonProperty("name") val name: String?,
- @JsonProperty("description") val description: String?,
- @JsonProperty("thumbnailUrl") val thumbnailUrl: String?,
- @JsonProperty("uploadDate") val uploadDate: String?,
- @JsonProperty("contentUrl") val contentUrl: String?
- )
-
- override val mainPage = mainPageOf(
- "$mainUrl/page/" to "Main Page",
- )
-
- override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse {
- val categoryData = request.data
- val categoryName = request.name
- val pagedlink = if (page > 0) categoryData + page else categoryData
- val document = app.get(pagedlink).document
- val homepage = document.select("main#main-content").map { it2 ->
- val inner = it2?.select("article > div.post-item-wrap") ?: return@map null
- //Log.i(this.name, "inner => $inner")
- val elements: List = inner.mapNotNull {
- //Log.i(this.name, "Inner content => $innerArticle")
- val innerA = it.selectFirst("div.blog-pic-wrap > a")?: return@mapNotNull null
- val link = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
-
- val imgArticle = innerA.selectFirst("img")
- val name = innerA.attr("title") ?: imgArticle?.attr("alt") ?: ""
- val image = imgArticle?.attr("data-src")
- val year = null
- //Log.i(this.name, "image => $image")
-
- MovieSearchResponse(
- name = name,
- url = link,
- apiName = this.name,
- type = globalTvType,
- posterUrl = image,
- year = year
- )
- }.distinctBy { a -> a.url }
-
- HomePageList(
- name = categoryName,
- list = elements,
- isHorizontalImages = true
- )
- }.filterNotNull().filter { a -> a.list.isNotEmpty() }
- //TODO: Replace 'homepage.first()' with 'homepage' after adding overload on newHomePageResponse()
- if (homepage.isNotEmpty()) {
- return newHomePageResponse(
- list = homepage.first(),
- hasNext = true
- )
- }
- throw ErrorLoadingException("No homepage data found!")
- }
-
- override suspend fun search(query: String): List {
- val url = "$mainUrl/?s=${query}"
- val document = app.get(url).document.getElementsByTag("body")
- .select("main#main-content").select("article")
-
- return document.mapNotNull {
- if (it == null) { return@mapNotNull null }
- val innerA = it.selectFirst("div.blog-pic-wrap > a")?: return@mapNotNull null
- val link = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
-
- val imgArticle = innerA.selectFirst("img")
- val title = innerA.attr("title") ?: imgArticle?.attr("alt") ?: ""
- val image = imgArticle?.attr("data-src")
- val year = null
-
- MovieSearchResponse(
- name = title,
- url = link,
- apiName = this.name,
- type = globalTvType,
- posterUrl = image,
- year = year
- )
- }.distinctBy { b -> b.url }
- }
-
- override suspend fun load(url: String): LoadResponse {
- val document = app.get(url).document
- val body = document.getElementsByTag("body")
-
- // Default values
- var title = ""
- var poster : String? = null
- var year : Int? = null
- var descript : String? = null
-
- // Video details
- var scriptJson = ""
- run breaking@{
- body.select("script").forEach {
- val scrAttr = it?.attr("type") ?: return@forEach
- if (scrAttr.equals("application/ld+json", ignoreCase = true)) {
- scriptJson = it.html() ?: ""
- return@breaking
- }
- }
- }
- //Log.i(this.name, "Result => (scriptJson) $scriptJson")
-
- // Video stream
- val playerIframes: MutableList = try {
- //Note: Fetch all multi-link urls
- document.selectFirst("div.series-listing")?.select("a")?.mapNotNull {
- it?.attr("href") ?: return@mapNotNull null
- }?.toMutableList() ?: mutableListOf()
- } catch (e: Exception) {
- Log.i(this.name, "Result => Exception (load) $e")
- mutableListOf()
- }
-
- // JAV Info
- tryParseJson(scriptJson)?.let {
- //val contentUrl = it.contentUrl
- title = it.name ?: ""
- poster = it.thumbnailUrl
- year = it.uploadDate?.take(4)?.toIntOrNull()
- descript = "Title: $title ${System.lineSeparator()} ${it.description}"
-
- // Add additional links, Raw link without needing to fetch from JavSub API
- //if (!contentUrl.isNullOrBlank()) {
- //playerIframes.add("$prefixTag$contentUrl")
- //}
- //Log.i(this.name, "Result => (contentUrl) $contentUrl")
- Log.i(this.name, "Result => (playerIframes) ${playerIframes.toJson()}")
-
- return MovieLoadResponse(
- name = title,
- url = url,
- apiName = this.name,
- type = globalTvType,
- dataUrl = playerIframes.toJson(),
- posterUrl = poster,
- year = year,
- plot = descript
- )
- }
-
- Log.i(this.name, "Result => (playerIframes) ${playerIframes.toJson()}")
-
- return MovieLoadResponse(
- name = title,
- url = url,
- apiName = this.name,
- type = globalTvType,
- dataUrl = playerIframes.toJson(),
- posterUrl = poster,
- year = year,
- plot = descript
- )
- }
-
- override suspend fun loadLinks(
- data: String,
- isCasting: Boolean,
- subtitleCallback: (SubtitleFile) -> Unit,
- callback: (ExtractorLink) -> Unit
- ): Boolean {
-
- var count = 0
- tryParseJson>(data)?.apmap { link ->
- Log.i(this.name, "Result => (link) $link")
- if (link.startsWith(prefixTag)) {
- val linkUrl = link.removePrefix(prefixTag)
- val success = extractStreamLink(linkUrl, subtitleCallback, callback)
- if (success) {
- count++
- }
- }
- else {
- val innerDoc =
- app.get(link).document.selectFirst("script#beeteam368_obj_wes-js-extra")
- var innerText = innerDoc?.html() ?: ""
- if (innerText.isNotBlank()) {
- "(?<=single_video_url\":)(.*)(?=,)".toRegex().find(innerText)
- ?.groupValues?.get(0)?.let { iframe ->
- innerText = iframe.trim().trim('"')
- }
- Jsoup.parse(innerText).selectFirst("iframe")?.attr("src")?.let { server ->
- val serverLink = server.replace("\\", "").replace("\"", "")
- val success = extractStreamLink(serverLink, subtitleCallback, callback)
- if (success) {
- count++
- }
- Log.i(this.name, "Result => (streamLink add) $serverLink")
- }
- }
- }
- }
- //Log.i(this.name, "Result => count: $count")
- return count > 0
- }
-
- private suspend fun extractStreamLink(
- link: String,
- subtitleCallback: (SubtitleFile) -> Unit,
- callback: (ExtractorLink) -> Unit) : Boolean {
-
- if (link.isNotBlank()) {
- when {
- link.contains("watch-jav") -> {
- val editedLink = link.removePrefix("https://")
- val idx = editedLink.indexOf('/', 0) + 1
- val finalLink = "https://embedsito.com/${editedLink.substring(idx)}"
- //Log.i(this.name, "WatchJav link => $finalLink / $link")
- return loadExtractor(
- url = finalLink,
- referer = mainUrl,
- subtitleCallback = subtitleCallback,
- callback = callback
- )
- }
- else -> {
- return loadExtractor(
- url = link,
- referer = mainUrl,
- subtitleCallback = subtitleCallback,
- callback = callback
- )
- }
- }
- }
- return false
- }
-}
\ No newline at end of file
diff --git a/JavSubProvider/src/main/kotlin/com/jacekun/JavSubProviderPlugin.kt b/JavSubProvider/src/main/kotlin/com/jacekun/JavSubProviderPlugin.kt
deleted file mode 100644
index 8e82d6d9..00000000
--- a/JavSubProvider/src/main/kotlin/com/jacekun/JavSubProviderPlugin.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.jacekun
-
-import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
-import com.lagradost.cloudstream3.plugins.Plugin
-import android.content.Context
-
-@CloudstreamPlugin
-class TestPlugin: Plugin() {
- override fun load(context: Context) {
- // All providers should be added in this manner. Please don't edit the providers list directly.
- registerMainAPI(JavSubProvider())
- }
-}
\ No newline at end of file
From 25b4c426485c01818be5db64552314ed88c26e9c Mon Sep 17 00:00:00 2001
From: Jace <54625750+Jacekun@users.noreply.github.com>
Date: Sun, 7 Sep 2025 18:35:28 +0800
Subject: [PATCH 4/4] Fixed build issues by handling deprecation of classes.
---
Chatrubate/build.gradle.kts | 2 +-
.../com/Chatrubate/ChatrubateProvider.kt | 32 +++----
DesiXFlix/build.gradle.kts | 2 +-
.../kotlin/com/rowdyCSExtensions/DesiXFlix.kt | 16 +++-
Hahomoe/build.gradle.kts | 2 +-
.../src/main/kotlin/com/jacekun/Hahomoe.kt | 89 ++++++++++---------
Hanime/build.gradle.kts | 2 +-
Hanime/src/main/kotlin/com/jacekun/Hanime.kt | 83 +++++++++--------
HentaiHaven/build.gradle.kts | 2 +-
.../main/kotlin/com/jacekun/HentaiHaven.kt | 46 +++++-----
JavFreeProvider/build.gradle.kts | 2 +-
.../kotlin/com/jacekun/JavFreeProvider.kt | 37 ++++----
JavGuru/build.gradle.kts | 2 +-
.../src/main/kotlin/com/jacekun/JavGuru.kt | 57 ++++++------
JavMost/build.gradle.kts | 2 +-
.../src/main/kotlin/com/jacekun/JavMost.kt | 69 +++++++-------
OpJav/build.gradle.kts | 2 +-
OpJav/src/main/kotlin/com/jacekun/OpJav.kt | 68 +++++++-------
Vlxx/build.gradle.kts | 2 +-
Vlxx/src/main/kotlin/com/jacekun/Vlxx.kt | 2 +-
20 files changed, 278 insertions(+), 241 deletions(-)
diff --git a/Chatrubate/build.gradle.kts b/Chatrubate/build.gradle.kts
index 2b12bd2a..707dd697 100644
--- a/Chatrubate/build.gradle.kts
+++ b/Chatrubate/build.gradle.kts
@@ -1,4 +1,4 @@
-version = 2
+version = 3
cloudstream {
authors = listOf("luck731")
diff --git a/Chatrubate/src/main/kotlin/com/Chatrubate/ChatrubateProvider.kt b/Chatrubate/src/main/kotlin/com/Chatrubate/ChatrubateProvider.kt
index cb0cb844..98956507 100644
--- a/Chatrubate/src/main/kotlin/com/Chatrubate/ChatrubateProvider.kt
+++ b/Chatrubate/src/main/kotlin/com/Chatrubate/ChatrubateProvider.kt
@@ -34,14 +34,14 @@ class ChatrubateProvider : MainAPI() {
offset = 90 * (page - 1)
}
val responseList = app.get("$mainUrl${request.data}&offset=$offset").parsedSafe()!!.rooms.map { room ->
- LiveSearchResponse(
+ newLiveSearchResponse(
name = room.username,
url = "$mainUrl/${room.username}",
- apiName = this@ChatrubateProvider.name,
type = TvType.Live,
- posterUrl = room.img,
- lang = null
- )
+ ).apply {
+ this.posterUrl = room.img
+ this.lang = null
+ }
}
return newHomePageResponse(HomePageList(request.name, responseList, isHorizontalImages = true),hasNext = true)
@@ -53,14 +53,14 @@ class ChatrubateProvider : MainAPI() {
for (i in 0..3) {
val results = app.get("$mainUrl/api/ts/roomlist/room-list/?hashtags=$query&limit=90&offset=${i*90}").parsedSafe()!!.rooms.map { room ->
- LiveSearchResponse(
+ newLiveSearchResponse(
name = room.username,
url = "$mainUrl/${room.username}",
- apiName = this@ChatrubateProvider.name,
- type = TvType.Live,
- posterUrl = room.img,
- lang = null
- )
+ ).apply {
+ this.type = TvType.Live
+ this.posterUrl = room.img
+ this.lang = null
+ }
}
if (!searchResponse.containsAll(results)) {
searchResponse.addAll(results)
@@ -83,14 +83,14 @@ class ChatrubateProvider : MainAPI() {
val description = document.selectFirst("meta[property=og:description]")?.attr("content")?.trim()
- return LiveStreamLoadResponse(
+ return newLiveStreamLoadResponse(
name = title,
url = url,
- apiName = this.name,
dataUrl = url,
- posterUrl = poster,
- plot = description,
- )
+ ).apply {
+ this.posterUrl = poster
+ this.plot = description
+ }
}
override suspend fun loadLinks(data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit): Boolean {
diff --git a/DesiXFlix/build.gradle.kts b/DesiXFlix/build.gradle.kts
index cddddec6..8226604c 100644
--- a/DesiXFlix/build.gradle.kts
+++ b/DesiXFlix/build.gradle.kts
@@ -3,7 +3,7 @@ dependencies {
implementation("androidx.recyclerview:recyclerview:1.3.2")
}
// use an integer for version numbers
-version = 3
+version = 4
cloudstream {
diff --git a/DesiXFlix/src/main/kotlin/com/rowdyCSExtensions/DesiXFlix.kt b/DesiXFlix/src/main/kotlin/com/rowdyCSExtensions/DesiXFlix.kt
index cb0e8444..ce6034ed 100644
--- a/DesiXFlix/src/main/kotlin/com/rowdyCSExtensions/DesiXFlix.kt
+++ b/DesiXFlix/src/main/kotlin/com/rowdyCSExtensions/DesiXFlix.kt
@@ -5,6 +5,7 @@ import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.MainAPI
import com.lagradost.cloudstream3.SearchResponse
import com.lagradost.cloudstream3.TvType
+import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.utils.*
import org.jsoup.nodes.Document
@@ -80,8 +81,19 @@ class DesiXFlix(val plugin: DesiXFlixPlugin) :
D0000dExtractor().getUrl(data, data)?.forEach { link -> callback.invoke(link) }
}
data.contains("hotxseries") -> {
- var serverName = "HotxSeries"
- callback.invoke(ExtractorLink(serverName, serverName, data, "", 0))
+ val serverName = "HotxSeries"
+ try {
+ callback.invoke(
+ newExtractorLink(
+ source = serverName,
+ name = serverName,
+ url = data,
+ )
+ )
+ } catch (e: Exception) {
+ logError(e)
+ }
+
}
else -> loadExtractor(data, subtitleCallback, callback)
}
diff --git a/Hahomoe/build.gradle.kts b/Hahomoe/build.gradle.kts
index 79a2c547..aa3cceb3 100644
--- a/Hahomoe/build.gradle.kts
+++ b/Hahomoe/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 6
+version = 7
cloudstream {
diff --git a/Hahomoe/src/main/kotlin/com/jacekun/Hahomoe.kt b/Hahomoe/src/main/kotlin/com/jacekun/Hahomoe.kt
index 22256806..796e520a 100644
--- a/Hahomoe/src/main/kotlin/com/jacekun/Hahomoe.kt
+++ b/Hahomoe/src/main/kotlin/com/jacekun/Hahomoe.kt
@@ -6,7 +6,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.getQualityFromName
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.utils.newExtractorLink
-import okhttp3.*
import java.text.SimpleDateFormat
import java.util.*
import org.jsoup.Jsoup
@@ -46,14 +45,14 @@ class Hahomoe : MainAPI() {
top.select("li > a").mapNotNull {
val epTitle = it.selectFirst(".thumb-title")?.text() ?: ""
val url = fixUrlNull(it?.attr("href")) ?: return@mapNotNull null
- AnimeSearchResponse(
+ newAnimeSearchResponse(
name = epTitle,
url = url,
- apiName = this.name,
type = globalTvType,
- posterUrl = it.selectFirst("img")?.attr("src"),
- dubStatus = EnumSet.of(DubStatus.Subbed),
- )
+ ).apply {
+ posterUrl = it.selectFirst("img")?.attr("src")
+ dubStatus = EnumSet.of(DubStatus.Subbed)
+ }
}
items.add(HomePageList(title, anime))
}
@@ -63,14 +62,14 @@ class Hahomoe : MainAPI() {
section.select("li > a").mapNotNull {
val epTitle = it.selectFirst(".thumb-title")?.text() ?: ""
val url = fixUrlNull(it?.attr("href")) ?: return@mapNotNull null
- AnimeSearchResponse(
+ newAnimeSearchResponse(
name = epTitle,
url = url,
- apiName = this.name,
type = globalTvType,
- posterUrl = it.selectFirst("img")?.attr("src"),
- dubStatus = EnumSet.of(DubStatus.Subbed),
- )
+ ).apply {
+ this.posterUrl = it.selectFirst("img")?.attr("src")
+ this.dubStatus = EnumSet.of(DubStatus.Subbed)
+ }
}
items.add(HomePageList(title, anime))
}
@@ -80,7 +79,7 @@ class Hahomoe : MainAPI() {
}
}
if (items.size <= 0) throw ErrorLoadingException()
- return HomePageResponse(items)
+ return newHomePageResponse(items)
}
private fun getIsMovie(type: String, id: Boolean = false): Boolean {
@@ -102,21 +101,22 @@ class Hahomoe : MainAPI() {
if (href.isNotBlank()) {
returnValue.add(
if (getIsMovie(href, true)) {
- MovieSearchResponse(
+ newMovieSearchResponse(
name = title,
url = href,
- apiName = this.name,
type = globalTvType,
- )
+ ).apply {
+ this.posterUrl = img
+ }
} else {
- AnimeSearchResponse(
+ newAnimeSearchResponse(
name = title,
url = href,
- apiName = this.name,
type = globalTvType,
- posterUrl = img,
- dubStatus = EnumSet.of(DubStatus.Subbed),
- )
+ ).apply {
+ this.posterUrl = img
+ this.dubStatus = EnumSet.of(DubStatus.Subbed)
+ }
}
)
}
@@ -188,12 +188,14 @@ class Hahomoe : MainAPI() {
val episodes = episodeNodes.mapNotNull {
val dataUrl = it?.attr("href") ?: return@mapNotNull null
- val epi = Episode(
- data = dataUrl,
- name = it.selectFirst(".episode-title")?.text()?.trim(),
- posterUrl = it.selectFirst("img")?.attr("src"),
- description = it.attr("data-content").trim(),
- )
+ val epi = newEpisode(
+ url = dataUrl,
+ ).apply {
+ this.data = dataUrl
+ this.name = it.selectFirst(".episode-title")?.text()?.trim()
+ this.posterUrl = it.selectFirst("img")?.attr("src")
+ this.description = it.attr("data-content").trim()
+ }
epi.addDate(it.selectFirst(".episode-date")?.text()?.trim())
epi
}
@@ -221,23 +223,24 @@ class Hahomoe : MainAPI() {
it?.text()?.trim().toString()
}
- return AnimeLoadResponse(
- englishTitle,
- japaneseTitle,
- canonicalTitle ?: "",
- url,
- this.name,
- getType(type ?: ""),
- poster,
- year.toIntOrNull(),
- hashMapOf(DubStatus.Subbed to episodes),
- status,
- synopsis,
- ArrayList(genre),
- ArrayList(synonyms),
- null,
- null,
- )
+ return newAnimeLoadResponse(
+ name = canonicalTitle ?: "",
+ url = url,
+ type = getType(type ?: ""),
+ ).apply {
+ this.engName = englishTitle
+ this.japName = japaneseTitle
+ this.apiName = this@Hahomoe.name
+ this.posterUrl = poster
+ this.episodes = hashMapOf(DubStatus.Subbed to episodes)
+ this.showStatus = status
+ this.plot = synopsis
+ this.tags = ArrayList(genre)
+ this.synonyms = ArrayList(synonyms)
+ this.rating = null
+ this.duration = null
+ this.year = year.toIntOrNull()
+ }
}
override suspend fun loadLinks(
diff --git a/Hanime/build.gradle.kts b/Hanime/build.gradle.kts
index 416f054a..8bccae29 100644
--- a/Hanime/build.gradle.kts
+++ b/Hanime/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 6
+version = 7
cloudstream {
diff --git a/Hanime/src/main/kotlin/com/jacekun/Hanime.kt b/Hanime/src/main/kotlin/com/jacekun/Hanime.kt
index 3d5b4f17..bbc8652a 100644
--- a/Hanime/src/main/kotlin/com/jacekun/Hanime.kt
+++ b/Hanime/src/main/kotlin/com/jacekun/Hanime.kt
@@ -114,15 +114,16 @@ class Hanime : MainAPI() {
val title = getTitle(hentai.name)
if (!titles.contains(title)) {
titles.add(title)
- AnimeSearchResponse(
- title,
- "https://hanime.tv/videos/hentai/${hentai.slug}?id=${hentai.id}&title=${title}",
- this.name,
- globalTvType,
- hentai.coverUrl,
- null,
- EnumSet.of(DubStatus.Subbed),
- )
+ newAnimeSearchResponse(
+ name = title,
+ url = "https://hanime.tv/videos/hentai/${hentai.slug}?id=${hentai.id}&title=${title}",
+ type = globalTvType,
+ ).apply {
+ //this.apiName = this@Hanime.name
+ this.posterUrl = hentai.coverUrl
+ this.year = null
+ this.dubStatus = EnumSet.of(DubStatus.Subbed)
+ }
} else {
null
}
@@ -131,7 +132,7 @@ class Hanime : MainAPI() {
}
if (items.size <= 0) throw ErrorLoadingException()
- return HomePageResponse(items)
+ return newHomePageResponse(items)
}
data class HanimeSearchResult (
@@ -179,16 +180,17 @@ class Hanime : MainAPI() {
if (!titles.contains(title)) {
titles.add(title)
searchResults.add(
- AnimeSearchResponse(
- title,
- "https://hanime.tv/videos/hentai/${it.slug}?id=${it.id}&title=${title}",
- this.name,
- globalTvType,
- it.coverUrl,
- unixToYear(it.releasedAt),
- EnumSet.of(DubStatus.Subbed),
- it.titles?.get(0),
- )
+ newAnimeSearchResponse(
+ name = title,
+ url = "https://hanime.tv/videos/hentai/${it.slug}?id=${it.id}&title=${title}",
+ type = globalTvType,
+ ).apply {
+ //this.apiName = this@Hanime.name
+ this.posterUrl = it.coverUrl
+ this.year = unixToYear(it.releasedAt)
+ this.dubStatus = EnumSet.of(DubStatus.Subbed)
+ this.otherName = it.titles?.get(0)
+ }
)
}
}
@@ -252,27 +254,30 @@ class Hanime : MainAPI() {
val tags = data.hentaiTags.map { it.text }
val episodes = data.hentaiFranchiseHentaiVideos.map {
- Episode(
- data = "$mainUrl/api/v8/video?id=${it.id}&",
- name = it.name,
- posterUrl = it.posterUrl
- )
+ newEpisode(
+ url = "$mainUrl/api/v8/video?id=${it.id}&",
+ ).apply {
+ this.data = "$mainUrl/api/v8/video?id=${it.id}&"
+ this.name = it.name
+ this.posterUrl = it.posterUrl
+ }
}
- return AnimeLoadResponse(
- title,
- null,
- title,
- url,
- this.name,
- globalTvType,
- data.hentaiVideo.coverUrl,
- unixToYear(data.hentaiVideo.releasedAtUnix),
- hashMapOf(DubStatus.Subbed to episodes),
- null,
- data.hentaiVideo.description.replace(Regex("?p>"), ""),
- tags,
- )
+ return newAnimeLoadResponse(
+ name = title,
+ url = url,
+ type = globalTvType,
+ ).apply {
+ this.engName = title
+ this.japName = null
+ this.apiName = this@Hanime.name
+ this.posterUrl = data.hentaiVideo.coverUrl
+ this.year = unixToYear(data.hentaiVideo.releasedAtUnix)
+ this.episodes = hashMapOf(DubStatus.Subbed to episodes)
+ this.showStatus = null
+ this.plot = data.hentaiVideo.description.replace(Regex("?p>"), "")
+ this.tags = tags
+ }
}
override suspend fun loadLinks(
diff --git a/HentaiHaven/build.gradle.kts b/HentaiHaven/build.gradle.kts
index 47b22ea7..6e6c308d 100644
--- a/HentaiHaven/build.gradle.kts
+++ b/HentaiHaven/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 6
+version = 7
cloudstream {
diff --git a/HentaiHaven/src/main/kotlin/com/jacekun/HentaiHaven.kt b/HentaiHaven/src/main/kotlin/com/jacekun/HentaiHaven.kt
index 808b0813..4a861ae7 100644
--- a/HentaiHaven/src/main/kotlin/com/jacekun/HentaiHaven.kt
+++ b/HentaiHaven/src/main/kotlin/com/jacekun/HentaiHaven.kt
@@ -42,7 +42,7 @@ class HentaiHaven : MainAPI() {
)
}
}
- return HomePageResponse(all)
+ return newHomePageResponse(all)
}
override suspend fun search(query: String): List {
@@ -73,31 +73,34 @@ class HentaiHaven : MainAPI() {
val episodeList = episodes?.mapNotNull {
val innerA = it?.selectFirst("a") ?: return@mapNotNull null
- val eplink = innerA.attr("href") ?: return@mapNotNull null
+ val eplink = innerA.attr("href")
val epCount = innerA.text().trim().filter { a -> a.isDigit() }.toIntOrNull()
val imageEl = innerA.selectFirst("img")
val epPoster = imageEl?.attr("src") ?: imageEl?.attr("data-src")
- Episode(
- name = innerA.text(),
- data = eplink,
- posterUrl = epPoster,
- episode = epCount,
- )
+ newEpisode(
+ url = eplink,
+ ).apply {
+ this.name = innerA.text()
+ this.data = eplink
+ this.posterUrl = epPoster
+ this.episode = epCount
+ }
} ?: listOf()
//Log.i(this.name, "Result => (id) ${id}")
- return AnimeLoadResponse(
+ return newAnimeLoadResponse(
name = title,
url = url,
- apiName = this.name,
type = globalTvType,
- posterUrl = poster,
- year = year,
- plot = descript,
- episodes = mutableMapOf(
+ ).apply {
+ this.apiName = this@HentaiHaven.name
+ this.posterUrl = poster
+ this.year = year
+ this.plot = descript
+ this.episodes = mutableMapOf(
Pair(DubStatus.Subbed, episodeList.reversed())
)
- )
+ }
}
override suspend fun loadLinks(
@@ -205,15 +208,16 @@ class HentaiHaven : MainAPI() {
Pair(DubStatus.Subbed, latestEp)
)
- AnimeSearchResponse(
+ newAnimeSearchResponse(
name = name,
url = link,
- apiName = apiName,
type = globalTvType,
- posterUrl = image,
- year = year,
- episodes = dubStatus
- )
+ ).apply {
+ //this.apiName = apiName
+ this.posterUrl = image
+ this.year = year
+ this.episodes = dubStatus
+ }
} ?: listOf()
}
diff --git a/JavFreeProvider/build.gradle.kts b/JavFreeProvider/build.gradle.kts
index 6dd60262..730700f6 100644
--- a/JavFreeProvider/build.gradle.kts
+++ b/JavFreeProvider/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 8
+version = 9
cloudstream {
diff --git a/JavFreeProvider/src/main/kotlin/com/jacekun/JavFreeProvider.kt b/JavFreeProvider/src/main/kotlin/com/jacekun/JavFreeProvider.kt
index 3bd729ab..bf6e4c9b 100644
--- a/JavFreeProvider/src/main/kotlin/com/jacekun/JavFreeProvider.kt
+++ b/JavFreeProvider/src/main/kotlin/com/jacekun/JavFreeProvider.kt
@@ -46,14 +46,15 @@ class JavFreeProvider : MainAPI() {
}
val year = null
- MovieSearchResponse(
+ newMovieSearchResponse(
name = name,
url = link,
- apiName = this.name,
type = globalTvType,
- posterUrl = image,
- year = year
- )
+ ).apply {
+ //this.apiName = this@JavFreeProvider.name
+ this.posterUrl = image
+ this.year = year
+ }
}
all.add(
@@ -65,7 +66,7 @@ class JavFreeProvider : MainAPI() {
)
}
}
- return HomePageResponse(all)
+ return newHomePageResponse(all)
}
override suspend fun search(query: String): List {
@@ -83,14 +84,15 @@ class JavFreeProvider : MainAPI() {
aa.select("div").select("video").attr("poster").toString()
}
- MovieSearchResponse(
+ newMovieSearchResponse(
name = title,
url = url,
- apiName = this.name,
type = globalTvType,
- posterUrl = image,
- year = year
- )
+ ).apply {
+ //this.apiName = this@JavFreeProvider.name
+ this.posterUrl = image
+ this.year = year
+ }
}
}
@@ -121,16 +123,17 @@ class JavFreeProvider : MainAPI() {
}
}
//Log.i(this.name, "Result => (id) ${id}")
- return MovieLoadResponse(
+ return newMovieLoadResponse(
name = title,
url = url,
- apiName = this.name,
type = globalTvType,
dataUrl = streamUrl,
- posterUrl = poster,
- year = year,
- plot = descript
- )
+ ).apply {
+ this.apiName = this@JavFreeProvider.name
+ this.posterUrl = poster
+ this.year = year
+ this.plot = descript
+ }
}
override suspend fun loadLinks(
diff --git a/JavGuru/build.gradle.kts b/JavGuru/build.gradle.kts
index 9d517442..a89e40ed 100644
--- a/JavGuru/build.gradle.kts
+++ b/JavGuru/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 5
+version = 6
cloudstream {
diff --git a/JavGuru/src/main/kotlin/com/jacekun/JavGuru.kt b/JavGuru/src/main/kotlin/com/jacekun/JavGuru.kt
index c252e5ca..2f466b60 100644
--- a/JavGuru/src/main/kotlin/com/jacekun/JavGuru.kt
+++ b/JavGuru/src/main/kotlin/com/jacekun/JavGuru.kt
@@ -44,15 +44,16 @@ class JavGuru : MainAPI() {
val image = imgArticle?.attr("src")
val year = null
- MovieSearchResponse(
- name,
- link,
- this.name,
- globaltvType,
- image,
- year,
- null,
- )
+ newMovieSearchResponse(
+ name = name,
+ url = link,
+ type = globaltvType,
+ ).apply {
+ //this.apiName = this@JavGuru.name
+ this.posterUrl = image
+ this.year = year
+ this.id = null
+ }
}
all.add(
@@ -61,7 +62,7 @@ class JavGuru : MainAPI() {
)
)
}
- return HomePageResponse(all)
+ return newHomePageResponse(all)
}
override suspend fun search(query: String): List {
@@ -71,8 +72,8 @@ class JavGuru : MainAPI() {
.select("main.site-main").select("div.row").mapNotNull {
val aa = it.select("div.column").select("div.inside-article")
- .select("div.imgg").select("a") ?: return@mapNotNull null
- val imgrow = aa.select("img") ?: return@mapNotNull null
+ .select("div.imgg").select("a")
+ val imgrow = aa.select("img")
val href = fixUrlNull(aa.attr("href")) ?: return@mapNotNull null
val title = imgrow.attr("alt")
@@ -80,14 +81,15 @@ class JavGuru : MainAPI() {
val year = Regex("(?<=\\/)(.[0-9]{3})(?=\\/)")
.find(image)?.groupValues?.get(1)?.toIntOrNull()
- MovieSearchResponse(
- title,
- href,
- this.name,
- globaltvType,
- image,
- year
- )
+ newMovieSearchResponse(
+ name = title,
+ url = href,
+ type = globaltvType,
+ ).apply {
+ //this.apiName = this@JavGuru.name
+ this.posterUrl = image
+ this.year = year
+ }
}
}
@@ -109,16 +111,17 @@ class JavGuru : MainAPI() {
val infometa_list = body.select("div.infometa > div.infoleft > ul > li")
val year = infometa_list.getOrNull(1)?.text()?.takeLast(10)?.substring(0, 4)?.toIntOrNull()
- return MovieLoadResponse(
+ return newMovieLoadResponse(
name = title,
url = url,
- apiName = this.name,
type = globaltvType,
dataUrl = streamUrl,
- posterUrl = poster,
- year = year,
- plot = descript,
- comingSoon = true
- )
+ ).apply {
+ this.apiName = this@JavGuru.name
+ this.posterUrl = poster
+ this.year = year
+ this.plot = descript
+ this.comingSoon = true
+ }
}
}
\ No newline at end of file
diff --git a/JavMost/build.gradle.kts b/JavMost/build.gradle.kts
index 08fb73cf..4f875bae 100644
--- a/JavMost/build.gradle.kts
+++ b/JavMost/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 5
+version = 6
cloudstream {
diff --git a/JavMost/src/main/kotlin/com/jacekun/JavMost.kt b/JavMost/src/main/kotlin/com/jacekun/JavMost.kt
index 0f2e115e..45326dec 100644
--- a/JavMost/src/main/kotlin/com/jacekun/JavMost.kt
+++ b/JavMost/src/main/kotlin/com/jacekun/JavMost.kt
@@ -49,15 +49,16 @@ class JavMost : MainAPI() {
?.substring(0, 20)?.replace("Release", "")?.trim()
?.substring(0, 4)?.toIntOrNull()
- MovieSearchResponse(
- name,
- link,
- this.name,
- globaltvType,
- image,
- year,
- null,
- )
+ newMovieSearchResponse(
+ name = name,
+ url = link,
+ type = globaltvType,
+ ).apply {
+ //this.apiName = this@JavMost.name
+ this.posterUrl = image
+ this.year = year
+ this.id = null
+ }
}
all.add(
@@ -66,14 +67,14 @@ class JavMost : MainAPI() {
)
)
- return HomePageResponse(all)
+ return newHomePageResponse(all)
}
override suspend fun search(query: String): List? {
val document = app.get("$mainUrl/search/${query}/").document
val mainbody = document.getElementsByTag("body")
- ?.select("div#page-container > div#content > div#content-update > div")
- ?.select("div.col-md-4.col-sm-6")
+ .select("div#page-container > div#content > div#content-update > div")
+ .select("div.col-md-4.col-sm-6")
//Log.i(DEV, "Result => $document")
if (mainbody != null) {
return mainbody.map {
@@ -99,29 +100,30 @@ class JavMost : MainAPI() {
val yearP = content?.select("div.card-block")?.firstOrNull()?.select("p")
//Log.i(DEV, "Result => (yearP) ${yearP}")
val yearElem = when(yearP != null) {
- true -> yearP?.filter { yearit -> yearit.text()?.contains("Release") == true }
+ true -> yearP.filter { yearit -> yearit.text().contains("Release") == true }
false -> null
}
val yearString = when (yearElem?.size!! > 0) {
- true -> yearElem?.get(0)?.text()?.substring(0, 22)?.trim()
+ true -> yearElem.get(0)?.text()?.substring(0, 22)?.trim()
?.replace("Release", "")?.trim()
false -> null
}
//Log.i(DEV, "Result => (yearString) ${yearString}")
if (yearString != null) {
val maxSize = if (yearString.length > 4) { 4 } else { yearString.length }
- year = yearString?.substring(0, maxSize)?.toIntOrNull()
+ year = yearString.substring(0, maxSize).toIntOrNull()
}
//Log.i(DEV, "Result => (year) ${year}")
- MovieSearchResponse(
- title,
- href,
- this.name,
- globaltvType,
- image,
- year
- )
+ newMovieSearchResponse(
+ name = title,
+ url = href,
+ type = globaltvType,
+ ).apply {
+ //this.apiName = this@JavMost.name
+ this.posterUrl = image
+ this.year = year
+ }
}
}
return null
@@ -133,24 +135,25 @@ class JavMost : MainAPI() {
val body = document.getElementsByTag("head")
//Log.i(DEV, "Result => ${body}")
- var poster = body?.select("meta[property=og:image]")?.firstOrNull()?.attr("content")
+ var poster = body.select("meta[property=og:image]").firstOrNull()?.attr("content")
if (poster != null) { poster = fixUrl(poster) }
//Log.i(DEV, "Result (image) => ${poster}")
- val title = body?.select("meta[property=og:title]")?.firstOrNull()?.attr("content") ?: ""
- val descript = body?.select("meta[property=og:description]")?.firstOrNull()?.attr("content") ?: ""
+ val title = body.select("meta[property=og:title]").firstOrNull()?.attr("content") ?: ""
+ val descript = body.select("meta[property=og:description]").firstOrNull()?.attr("content") ?: ""
//Log.i(DEV, "Result => ${descript}")
val streamUrl = ""
val year = null
- return MovieLoadResponse(
+ return newMovieLoadResponse(
name = title,
url = url,
- apiName = this.name,
type = globaltvType,
dataUrl = streamUrl,
- posterUrl = poster,
- year = year,
- plot = descript,
- comingSoon = true
- )
+ ).apply {
+ this.apiName = this@JavMost.name
+ this.posterUrl = poster
+ this.year = year
+ this.plot = descript
+ this.comingSoon = true
+ }
}
}
\ No newline at end of file
diff --git a/OpJav/build.gradle.kts b/OpJav/build.gradle.kts
index 67dd0a2a..a20d04a4 100644
--- a/OpJav/build.gradle.kts
+++ b/OpJav/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 6
+version = 7
cloudstream {
diff --git a/OpJav/src/main/kotlin/com/jacekun/OpJav.kt b/OpJav/src/main/kotlin/com/jacekun/OpJav.kt
index 94435ee2..28e5d02b 100644
--- a/OpJav/src/main/kotlin/com/jacekun/OpJav.kt
+++ b/OpJav/src/main/kotlin/com/jacekun/OpJav.kt
@@ -2,6 +2,7 @@ package com.jacekun
import android.util.Log
import com.lagradost.cloudstream3.*
+import com.lagradost.cloudstream3.amap
import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.extractors.XStreamCdn
import com.lagradost.cloudstream3.utils.AppUtils.toJson
@@ -33,7 +34,7 @@ class OpJav : MainAPI() {
val selectorSimple = "div.list-film-simple > div.item"
val selectorRows = "div.list-film.row > div"
- body?.select("div.content")?.forEach {
+ body.select("div.content").forEach {
if (it != null) {
if (it.select(selectorRows).isNullOrEmpty()) {
rows.add(Pair(selectorSimple, it))
@@ -68,17 +69,18 @@ class OpJav : MainAPI() {
val poster = inner.select("a.poster") ?: return@mapNotNull null
link = fixUrlNull(poster.attr("href")) ?: return@mapNotNull null
name = it.text().trim().removePrefix("HD")
- image = poster.select("img")?.attr("src")
- year = inner.select("dfn")?.get(1)?.text()?.toIntOrNull()
+ image = poster.select("img").attr("src")
+ year = inner.select("dfn").get(1)?.text()?.toIntOrNull()
}
- MovieSearchResponse(
+ newMovieSearchResponse(
name = name,
url = link,
- apiName = this.name,
type = globalTvType,
- posterUrl = image,
- year = year
- )
+ ).apply {
+ //this.apiName = this@OpJav.name
+ this.posterUrl = image
+ this.year = year
+ }
}.distinctBy { a -> a.url }
if (elements.isNotEmpty()) {
all.add(
@@ -89,7 +91,7 @@ class OpJav : MainAPI() {
)
}
}
- return HomePageResponse(all)
+ return newHomePageResponse(all)
}
override suspend fun search(query: String): List {
@@ -109,14 +111,15 @@ class OpJav : MainAPI() {
val year = inner.select("dfn").last()?.text()?.trim()?.toIntOrNull()
//Log.i(this.name, "Result => $")
- MovieSearchResponse(
+ newMovieSearchResponse(
name = title,
url = link,
- apiName = this.name,
type = globalTvType,
- posterUrl = image,
- year = year
- )
+ ).apply {
+ //this.apiName = this@OpJav.name
+ this.posterUrl = image
+ this.year = year
+ }
}.distinctBy { it.url }
}
@@ -135,7 +138,7 @@ class OpJav : MainAPI() {
//Fetch server links
val watchlink = ArrayList()
- val mainLink = doc.select("div.buttons.row a").attr("href") ?: ""
+ val mainLink = doc.select("div.buttons.row a").attr("href")
//Log.i(this.name, "Result => (mainLink) $mainLink")
//Fetch episode links from mainlink
@@ -158,11 +161,11 @@ class OpJav : MainAPI() {
} catch (e: Exception) { }*/
//Fetch server links
epsDoc.select("div.block.servers li").mapNotNull {
- val inner = it?.selectFirst("a") ?: return@mapNotNull null
- val linkUrl = inner.attr("href") ?: return@mapNotNull null
- val linkId = inner.attr("id") ?: return@mapNotNull null
- Pair(linkUrl, linkId)
- }.apmap {
+ val inner = it?.selectFirst("a") ?: return@mapNotNull null
+ val linkUrl = inner.attr("href")
+ val linkId = inner.attr("id")
+ Pair(linkUrl, linkId)
+ }.amap {
//First = Url, Second = EpisodeID
//Log.i(this.name, "Result => (eplink-Id) $it")
val ajaxHead = mapOf(
@@ -179,28 +182,29 @@ class OpJav : MainAPI() {
)
app.post("$mainUrl/ajax", headers = ajaxHead, data = ajaxData)
.document.select("iframe").forEach { iframe ->
- val serverLink = iframe?.attr("src")?.trim().orEmpty()
- if (serverLink.isNotBlank()) {
- watchlink.add(serverLink)
- Log.i(this.name, "Result => (serverLink) $serverLink")
+ val serverLink = iframe?.attr("src")?.trim().orEmpty()
+ if (serverLink.isNotBlank()) {
+ watchlink.add(serverLink)
+ Log.i(name, "Result => (serverLink) $serverLink")
+ }
}
- }
}
}
}
val streamUrl = watchlink.distinct().toJson()
Log.i(this.name, "Result => (streamUrl) $streamUrl")
- return MovieLoadResponse(
+ return newMovieLoadResponse(
name = title,
url = url,
- apiName = this.name,
type = globalTvType,
dataUrl = streamUrl,
- posterUrl = poster,
- year = year,
- plot = descript,
- tags = tags
- )
+ ).apply {
+ this.apiName = this@OpJav.name
+ this.posterUrl = poster
+ this.year = year
+ this.plot = descript
+ this.tags = tags
+ }
}
override suspend fun loadLinks(
diff --git a/Vlxx/build.gradle.kts b/Vlxx/build.gradle.kts
index cf466e13..4b0e5651 100644
--- a/Vlxx/build.gradle.kts
+++ b/Vlxx/build.gradle.kts
@@ -1,5 +1,5 @@
// use an integer for version numbers
-version = 6
+version = 7
cloudstream {
diff --git a/Vlxx/src/main/kotlin/com/jacekun/Vlxx.kt b/Vlxx/src/main/kotlin/com/jacekun/Vlxx.kt
index e6e9c55c..31436ca2 100644
--- a/Vlxx/src/main/kotlin/com/jacekun/Vlxx.kt
+++ b/Vlxx/src/main/kotlin/com/jacekun/Vlxx.kt
@@ -73,7 +73,7 @@ class Vlxx : MainAPI() {
)
)
}
- return HomePageResponse(all)
+ return newHomePageResponse(all)
}
override suspend fun search(query: String): List {