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(""), ""), - 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(""), "") + 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 {