mirror of
https://github.com/Jacekun/cs3xxx-repo.git
synced 2024-08-14 23:57:09 +00:00
[Provider] JavTube
- Disable Example plugin
This commit is contained in:
parent
455d555d83
commit
f572acbf7e
6 changed files with 288 additions and 3 deletions
|
@ -15,12 +15,12 @@ cloudstream {
|
|||
* 2: Slow
|
||||
* 3: Beta only
|
||||
* */
|
||||
status = 1 // will be 3 if unspecified
|
||||
status = 0 // 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 = ""
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=example.com&sz=%size%"
|
||||
}
|
||||
|
|
|
@ -4,5 +4,6 @@ import com.lagradost.cloudstream3.MainAPI
|
|||
import com.lagradost.cloudstream3.TvType
|
||||
|
||||
class Example : MainAPI() {
|
||||
private val globalTvType = TvType.Movie
|
||||
private val DEV = "DevDebug"
|
||||
private val globaltvType = TvType.Movie
|
||||
}
|
26
JavTube/build.gradle.kts
Normal file
26
JavTube/build.gradle.kts
Normal file
|
@ -0,0 +1,26 @@
|
|||
// use an integer for version numbers
|
||||
version = 1
|
||||
|
||||
|
||||
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%"
|
||||
}
|
2
JavTube/src/main/AndroidManifest.xml
Normal file
2
JavTube/src/main/AndroidManifest.xml
Normal file
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.lagradost"/>
|
243
JavTube/src/main/kotlin/com/jacekun/JavTube.kt
Normal file
243
JavTube/src/main/kotlin/com/jacekun/JavTube.kt
Normal file
|
@ -0,0 +1,243 @@
|
|||
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.AppUtils.toJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.Jsoup
|
||||
|
||||
class JavTube : MainAPI() {
|
||||
private val DEV = "DevDebug"
|
||||
private val globaltvType = TvType.Movie
|
||||
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<HomePageList>()
|
||||
|
||||
// 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<SearchResponse> = 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<MovieSearchResponse> {
|
||||
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<JsonRequest?>(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 doc = Jsoup.parse(postreq.text)
|
||||
val src = doc.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<JsonResponse?>(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<JsonResponseData>?
|
||||
)
|
||||
private data class JsonResponseData(
|
||||
@JsonProperty("file") val file: String,
|
||||
@JsonProperty("label") val label: String,
|
||||
//val type: String // Mp4
|
||||
)
|
||||
}
|
13
JavTube/src/main/kotlin/com/jacekun/JavTubePlugin.kt
Normal file
13
JavTube/src/main/kotlin/com/jacekun/JavTubePlugin.kt
Normal file
|
@ -0,0 +1,13 @@
|
|||
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())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue