forked from recloudstream/cloudstream
[Feature] Add Recommendations and Tags to various providers. (#583)
* PinoyMoviePedia: Add recommendations and tags. * PinoyMoviesEs: Add recs and tags. * pinoyHD: Add tags. Fetch hidden links in movie description. * DramaSee: Add tags and recs. * WatchAsian: Load tags from details page of url. * Kdramahood: Add recs. * [skip ci] Replace isNotEmpty() with isNotBlank() * Minor refactor to PinoyHD and PinoyMoviesEs HomePage entries.
This commit is contained in:
parent
11e10a9bd8
commit
765aa7c5af
10 changed files with 350 additions and 190 deletions
|
@ -15,7 +15,7 @@ class UpstreamExtractor: ExtractorApi() {
|
||||||
//Log.i(this.name, "Result => (no extractor) ${url}")
|
//Log.i(this.name, "Result => (no extractor) ${url}")
|
||||||
val sources: MutableList<ExtractorLink> = mutableListOf()
|
val sources: MutableList<ExtractorLink> = mutableListOf()
|
||||||
val doc = app.get(url, referer = referer).text
|
val doc = app.get(url, referer = referer).text
|
||||||
if (doc.isNotEmpty()) {
|
if (doc.isNotBlank()) {
|
||||||
var reg = Regex("(?<=master)(.*)(?=hls)")
|
var reg = Regex("(?<=master)(.*)(?=hls)")
|
||||||
val result = reg.find(doc)?.groupValues?.map {
|
val result = reg.find(doc)?.groupValues?.map {
|
||||||
it.trim('|')
|
it.trim('|')
|
||||||
|
|
|
@ -21,7 +21,7 @@ open class VoeExtractor : ExtractorApi() {
|
||||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
||||||
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
|
val extractedLinksList: MutableList<ExtractorLink> = mutableListOf()
|
||||||
val doc = app.get(url).text
|
val doc = app.get(url).text
|
||||||
if (doc.isNotEmpty()) {
|
if (doc.isNotBlank()) {
|
||||||
val start = "const sources ="
|
val start = "const sources ="
|
||||||
var src = doc.substring(doc.indexOf(start))
|
var src = doc.substring(doc.indexOf(start))
|
||||||
src = src.substring(start.length, src.indexOf(";"))
|
src = src.substring(start.length, src.indexOf(";"))
|
||||||
|
|
|
@ -16,7 +16,7 @@ class AsianEmbedHelper {
|
||||||
links.apmap {
|
links.apmap {
|
||||||
val datavid = it.attr("data-video") ?: ""
|
val datavid = it.attr("data-video") ?: ""
|
||||||
//Log.i("AsianEmbed", "Result => (datavid) ${datavid}")
|
//Log.i("AsianEmbed", "Result => (datavid) ${datavid}")
|
||||||
if (datavid.isNotEmpty()) {
|
if (datavid.isNotBlank()) {
|
||||||
val res = loadExtractor(datavid, url, callback)
|
val res = loadExtractor(datavid, url, callback)
|
||||||
Log.i("AsianEmbed", "Result => ($res) (datavid) $datavid")
|
Log.i("AsianEmbed", "Result => ($res) (datavid) $datavid")
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ class VstreamhubHelper {
|
||||||
val startString = "window.open(["
|
val startString = "window.open(["
|
||||||
val bb = aa.substring(aa.indexOf(startString))
|
val bb = aa.substring(aa.indexOf(startString))
|
||||||
val datavid = bb.substring(startString.length, bb.indexOf("]")).removeSurrounding("\"")
|
val datavid = bb.substring(startString.length, bb.indexOf("]")).removeSurrounding("\"")
|
||||||
if (datavid.isNotEmpty()) {
|
if (datavid.isNotBlank()) {
|
||||||
loadExtractor(datavid, url, callback)
|
loadExtractor(datavid, url, callback)
|
||||||
//Log.i(baseName, "Result => (datavid) ${datavid}")
|
//Log.i(baseName, "Result => (datavid) ${datavid}")
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,8 +91,24 @@ class DramaSeeProvider : MainAPI() {
|
||||||
val year = if (title.length > 5) { title.substring(title.length - 5)
|
val year = if (title.length > 5) { title.substring(title.length - 5)
|
||||||
.trim().trimEnd(')').toIntOrNull() } else { null }
|
.trim().trimEnd(')').toIntOrNull() } else { null }
|
||||||
//Log.i(this.name, "Result => (year) ${title.substring(title.length - 5)}")
|
//Log.i(this.name, "Result => (year) ${title.substring(title.length - 5)}")
|
||||||
val descript = body?.select("div.series-body")?.firstOrNull()
|
val seriesBody = body?.select("div.series-body")
|
||||||
?.select("div.js-content")?.text()
|
val descript = seriesBody?.firstOrNull()?.select("div.js-content")?.text()
|
||||||
|
val tags = seriesBody?.select("div.series-tags > a")?.mapNotNull { it?.text()?.trim() ?: return@mapNotNull null }
|
||||||
|
val recs = body?.select("ul.series > li")?.mapNotNull {
|
||||||
|
val a = it.select("a.series-img") ?: return@mapNotNull null
|
||||||
|
val aUrl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null
|
||||||
|
val aImg = fixUrlNull(a.select("img")?.attr("src"))
|
||||||
|
val aName = a.select("img")?.attr("alt") ?: return@mapNotNull null
|
||||||
|
val aYear = aName.trim().takeLast(5).removeSuffix(")").toIntOrNull()
|
||||||
|
MovieSearchResponse(
|
||||||
|
url = aUrl,
|
||||||
|
name = aName,
|
||||||
|
type = TvType.Movie,
|
||||||
|
posterUrl = aImg,
|
||||||
|
year = aYear,
|
||||||
|
apiName = this.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Episodes Links
|
// Episodes Links
|
||||||
val episodeList = ArrayList<TvSeriesEpisode>()
|
val episodeList = ArrayList<TvSeriesEpisode>()
|
||||||
|
@ -101,7 +117,7 @@ class DramaSeeProvider : MainAPI() {
|
||||||
val count = innerA.select("span.episode")?.text()?.toIntOrNull() ?: 0
|
val count = innerA.select("span.episode")?.text()?.toIntOrNull() ?: 0
|
||||||
val epLink = fixUrlNull(innerA.attr("href")) ?: return@forEach
|
val epLink = fixUrlNull(innerA.attr("href")) ?: return@forEach
|
||||||
//Log.i(this.name, "Result => (epLink) ${epLink}")
|
//Log.i(this.name, "Result => (epLink) ${epLink}")
|
||||||
if (epLink.isNotEmpty()) {
|
if (epLink.isNotBlank()) {
|
||||||
// Fetch video links
|
// Fetch video links
|
||||||
val epVidLinkEl = app.get(epLink, referer = mainUrl).document
|
val epVidLinkEl = app.get(epLink, referer = mainUrl).document
|
||||||
val ajaxUrl = epVidLinkEl.select("div#js-player")?.attr("embed")
|
val ajaxUrl = epVidLinkEl.select("div#js-player")?.attr("embed")
|
||||||
|
@ -111,7 +127,7 @@ class DramaSeeProvider : MainAPI() {
|
||||||
val listOfLinks = mutableListOf<String>()
|
val listOfLinks = mutableListOf<String>()
|
||||||
innerPage.select("div.player.active > main > div")?.forEach { em ->
|
innerPage.select("div.player.active > main > div")?.forEach { em ->
|
||||||
val href = fixUrlNull(em.attr("src")) ?: ""
|
val href = fixUrlNull(em.attr("src")) ?: ""
|
||||||
if (href.isNotEmpty()) {
|
if (href.isNotBlank()) {
|
||||||
listOfLinks.add(href)
|
listOfLinks.add(href)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,20 +149,30 @@ class DramaSeeProvider : MainAPI() {
|
||||||
|
|
||||||
//If there's only 1 episode, consider it a movie.
|
//If there's only 1 episode, consider it a movie.
|
||||||
if (episodeList.size == 1) {
|
if (episodeList.size == 1) {
|
||||||
return MovieLoadResponse(title, url, this.name, TvType.Movie, episodeList[0].data, poster, year, descript, null, null)
|
return MovieLoadResponse(
|
||||||
|
name = title,
|
||||||
|
url = url,
|
||||||
|
apiName = this.name,
|
||||||
|
type = TvType.Movie,
|
||||||
|
dataUrl = episodeList[0].data,
|
||||||
|
posterUrl = poster,
|
||||||
|
year = year,
|
||||||
|
plot = descript,
|
||||||
|
recommendations = recs,
|
||||||
|
tags = tags
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return TvSeriesLoadResponse(
|
return TvSeriesLoadResponse(
|
||||||
title,
|
name = title,
|
||||||
url,
|
url = url,
|
||||||
this.name,
|
apiName = this.name,
|
||||||
TvType.TvSeries,
|
type = TvType.TvSeries,
|
||||||
episodeList.reversed(),
|
episodes = episodeList.reversed(),
|
||||||
poster,
|
posterUrl = poster,
|
||||||
year,
|
year = year,
|
||||||
descript,
|
plot = descript,
|
||||||
null,
|
recommendations = recs,
|
||||||
null,
|
tags = tags
|
||||||
null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,24 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
res
|
res
|
||||||
} catch (e: Exception) { null }
|
} catch (e: Exception) { null }
|
||||||
|
|
||||||
|
val recs = doc.select("div.sidebartv > div.tvitemrel")?.mapNotNull {
|
||||||
|
val a = it?.select("a") ?: return@mapNotNull null
|
||||||
|
val aUrl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null
|
||||||
|
val aImg = a.select("img")
|
||||||
|
val aCover = fixUrlNull(aImg?.attr("src")) ?: fixUrlNull(aImg?.attr("data-src"))
|
||||||
|
val aNameYear = a.select("div.datatvrel") ?: return@mapNotNull null
|
||||||
|
val aName = aNameYear.select("h4")?.text() ?: aImg?.attr("alt") ?: return@mapNotNull null
|
||||||
|
val aYear = aName.trim().takeLast(5).removeSuffix(")").toIntOrNull()
|
||||||
|
MovieSearchResponse(
|
||||||
|
url = aUrl,
|
||||||
|
name = aName,
|
||||||
|
type = TvType.Movie,
|
||||||
|
posterUrl = aCover,
|
||||||
|
year = aYear,
|
||||||
|
apiName = this.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Episodes Links
|
// Episodes Links
|
||||||
val episodeList = inner?.select("ul.episodios > li")?.mapNotNull { ep ->
|
val episodeList = inner?.select("ul.episodios > li")?.mapNotNull { ep ->
|
||||||
//Log.i(this.name, "Result => (ep) ${ep}")
|
//Log.i(this.name, "Result => (ep) ${ep}")
|
||||||
|
@ -119,7 +137,7 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
//Log.i(this.name, "Result => (innerA) ${innerA}")
|
//Log.i(this.name, "Result => (innerA) ${innerA}")
|
||||||
val epLink = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
|
val epLink = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null
|
||||||
//Log.i(this.name, "Result => (epLink) ${epLink}")
|
//Log.i(this.name, "Result => (epLink) ${epLink}")
|
||||||
if (epLink.isNotEmpty()) {
|
if (epLink.isNotBlank()) {
|
||||||
// Fetch video links
|
// Fetch video links
|
||||||
val epVidLinkEl = app.get(epLink, referer = mainUrl).document
|
val epVidLinkEl = app.get(epLink, referer = mainUrl).document
|
||||||
val epLinksContent = epVidLinkEl.selectFirst("div.player_nav > script")?.html()
|
val epLinksContent = epVidLinkEl.selectFirst("div.player_nav > script")?.html()
|
||||||
|
@ -131,20 +149,10 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
Jsoup.parse(epLinksContent)?.select("div")?.forEach { em ->
|
Jsoup.parse(epLinksContent)?.select("div")?.forEach { em ->
|
||||||
val href = em?.html()?.trim()?.removePrefix("'") ?: return@forEach
|
val href = em?.html()?.trim()?.removePrefix("'") ?: return@forEach
|
||||||
//Log.i(this.name, "Result => (ep#$count link) $href")
|
//Log.i(this.name, "Result => (ep#$count link) $href")
|
||||||
if (href.isNotEmpty()) {
|
if (href.isNotBlank()) {
|
||||||
listOfLinks.add(fixUrl(href))
|
listOfLinks.add(fixUrl(href))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Doesn't get all links for some reasons
|
|
||||||
val rex = Regex("(?<=ifr_target.src =)(.*)(?=';)")
|
|
||||||
rex.find(epLinksContent)?.groupValues?.forEach { em ->
|
|
||||||
val href = em.trim()
|
|
||||||
Log.i(this.name, "Result => (ep #$count href) $href")
|
|
||||||
if (href.isNotEmpty()) {
|
|
||||||
listOfLinks.add(href)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TvSeriesEpisode(
|
TvSeriesEpisode(
|
||||||
|
@ -159,20 +167,28 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
|
|
||||||
//If there's only 1 episode, consider it a movie.
|
//If there's only 1 episode, consider it a movie.
|
||||||
if (episodeList.size == 1) {
|
if (episodeList.size == 1) {
|
||||||
return MovieLoadResponse(title, url, this.name, TvType.Movie, episodeList[0].data, poster, year, descript, null, null)
|
return MovieLoadResponse(
|
||||||
|
name = title,
|
||||||
|
url = url,
|
||||||
|
apiName = this.name,
|
||||||
|
type = TvType.Movie,
|
||||||
|
dataUrl = episodeList[0].data,
|
||||||
|
posterUrl = poster,
|
||||||
|
year = year,
|
||||||
|
plot = descript,
|
||||||
|
recommendations = recs
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return TvSeriesLoadResponse(
|
return TvSeriesLoadResponse(
|
||||||
title,
|
name = title,
|
||||||
url,
|
url = url,
|
||||||
this.name,
|
apiName = this.name,
|
||||||
TvType.TvSeries,
|
type = TvType.TvSeries,
|
||||||
episodeList.reversed(),
|
episodes = episodeList.reversed(),
|
||||||
poster,
|
posterUrl = poster,
|
||||||
year,
|
year = year,
|
||||||
descript,
|
plot = descript,
|
||||||
null,
|
recommendations = recs
|
||||||
null,
|
|
||||||
null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +200,7 @@ class KdramaHoodProvider : MainAPI() {
|
||||||
): Boolean {
|
): Boolean {
|
||||||
var count = 0
|
var count = 0
|
||||||
mapper.readValue<List<String>>(data).apmap { item ->
|
mapper.readValue<List<String>>(data).apmap { item ->
|
||||||
if (item.isNotEmpty()) {
|
if (item.isNotBlank()) {
|
||||||
count++
|
count++
|
||||||
var url = item.trim()
|
var url = item.trim()
|
||||||
if (url.startsWith("//")) {
|
if (url.startsWith("//")) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.lagradost.cloudstream3.movieproviders
|
package com.lagradost.cloudstream3.movieproviders
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||||
|
@ -23,38 +24,31 @@ class PinoyHDXyzProvider : MainAPI() {
|
||||||
|
|
||||||
mainbody?.select("div.section-cotent.col-md-12.bordert")?.forEach { row ->
|
mainbody?.select("div.section-cotent.col-md-12.bordert")?.forEach { row ->
|
||||||
val title = row?.select("div.title-section.tt")?.text() ?: "<Row>"
|
val title = row?.select("div.title-section.tt")?.text() ?: "<Row>"
|
||||||
val inner = row?.select("li.img_frame.preview-tumb7")
|
val elements = row?.select("li.img_frame.preview-tumb7")?.mapNotNull {
|
||||||
if (inner != null) {
|
// Get inner div from article
|
||||||
val elements: List<SearchResponse> = inner.map {
|
val innerBody = it?.selectFirst("a") ?: return@mapNotNull null
|
||||||
// Get inner div from article
|
// Fetch details
|
||||||
val innerBody = it?.select("a")?.firstOrNull()
|
val name = it.text()
|
||||||
// Fetch details
|
if (name.isNullOrBlank()) { return@mapNotNull null }
|
||||||
val name = it?.text() ?: ""
|
|
||||||
val link = innerBody?.attr("href") ?: ""
|
val link = innerBody.attr("href") ?: return@mapNotNull null
|
||||||
val imgsrc = innerBody?.select("img")?.attr("src")
|
val image = fixUrlNull(innerBody.select("img")?.attr("src"))
|
||||||
val image = when (!imgsrc.isNullOrEmpty()) {
|
//Log.i(this.name, "Result => (innerBody, image) ${innerBody} / ${image}")
|
||||||
true -> "${mainUrl}${imgsrc}"
|
// Get Year from Link
|
||||||
false -> null
|
val rex = Regex("_(\\d+)_")
|
||||||
}
|
val year = rex.find(link)?.value?.replace("_", "")?.toIntOrNull()
|
||||||
//Log.i(this.name, "Result => (innerBody, image) ${innerBody} / ${image}")
|
//Log.i(this.name, "Result => (yearRes, year) ${yearRes} / ${year}")
|
||||||
// Get Year from Link
|
MovieSearchResponse(
|
||||||
val rex = Regex("_(\\d+)_")
|
name = name,
|
||||||
val yearRes = rex.find(link)?.value ?: ""
|
url = link,
|
||||||
val year = yearRes.replace("_", "").toIntOrNull()
|
apiName = this.name,
|
||||||
//Log.i(this.name, "Result => (yearRes, year) ${yearRes} / ${year}")
|
type = TvType.Movie,
|
||||||
MovieSearchResponse(
|
posterUrl = image,
|
||||||
name,
|
year = year
|
||||||
link,
|
)
|
||||||
this.name,
|
}?.distinctBy { c -> c.url } ?: listOf()
|
||||||
TvType.Movie,
|
// Add to Homepage
|
||||||
image,
|
if (elements.isNotEmpty()) {
|
||||||
year,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
}.filter { a -> a.url.isNotEmpty() }
|
|
||||||
.filter { b -> b.name.isNotEmpty() }
|
|
||||||
.distinctBy { c -> c.url }
|
|
||||||
// Add
|
|
||||||
all.add(
|
all.add(
|
||||||
HomePageList(
|
HomePageList(
|
||||||
title, elements
|
title, elements
|
||||||
|
@ -78,12 +72,12 @@ class PinoyHDXyzProvider : MainAPI() {
|
||||||
val image = null // site provides no image on search page
|
val image = null // site provides no image on search page
|
||||||
|
|
||||||
MovieSearchResponse(
|
MovieSearchResponse(
|
||||||
title,
|
name = title,
|
||||||
link,
|
url = link,
|
||||||
this.name,
|
apiName = this.name,
|
||||||
TvType.Movie,
|
type = TvType.Movie,
|
||||||
image,
|
posterUrl = image,
|
||||||
year
|
year = year
|
||||||
)
|
)
|
||||||
}?.distinctBy { c -> c.url } ?: listOf()
|
}?.distinctBy { c -> c.url } ?: listOf()
|
||||||
}
|
}
|
||||||
|
@ -93,29 +87,57 @@ class PinoyHDXyzProvider : MainAPI() {
|
||||||
val body = doc.getElementsByTag("body")
|
val body = doc.getElementsByTag("body")
|
||||||
val inner = body?.select("div.info")
|
val inner = body?.select("div.info")
|
||||||
|
|
||||||
|
// Video links
|
||||||
|
val listOfLinks: MutableList<String> = mutableListOf()
|
||||||
|
|
||||||
// Video details
|
// Video details
|
||||||
val imgLinkCode = inner?.select("div.portfolio-tumb.ph-link > img")?.attr("src")
|
var title = ""
|
||||||
val poster = if (!imgLinkCode.isNullOrEmpty()) { "${mainUrl}${imgLinkCode}" } else { null }
|
var year: Int? = null
|
||||||
|
var tags: List<String>? = null
|
||||||
|
val poster = fixUrlNull(inner?.select("div.portfolio-tumb.ph-link > img")?.attr("src"))
|
||||||
//Log.i(this.name, "Result => (imgLinkCode) ${imgLinkCode}")
|
//Log.i(this.name, "Result => (imgLinkCode) ${imgLinkCode}")
|
||||||
val title = inner?.select("td.trFon2.entt")?.firstOrNull()?.text() ?: "<Untitled>"
|
inner?.select("table")?.select("tr")?.forEach {
|
||||||
var yearRes = inner?.select("td.trFon2")?.toString()
|
val td = it?.select("td") ?: return@forEach
|
||||||
val year = if (!yearRes.isNullOrEmpty()) {
|
val caption = td[0].text()?.lowercase()
|
||||||
if (yearRes.contains("var year =")) {
|
//Log.i(this.name, "Result => (caption) $caption")
|
||||||
yearRes = yearRes.substring(yearRes.indexOf("var year =") + "var year =".length)
|
when (caption) {
|
||||||
//Log.i(this.name, "Result => (yearRes) $yearRes")
|
"name" -> {
|
||||||
yearRes = yearRes.substring(0, yearRes.indexOf(';'))
|
title = td[1].text()
|
||||||
.trim().removeSurrounding("'")
|
}
|
||||||
|
"year" -> {
|
||||||
|
var yearRes = td[1].toString()
|
||||||
|
year = if (yearRes.isNotBlank()) {
|
||||||
|
if (yearRes.contains("var year =")) {
|
||||||
|
yearRes = yearRes.substring(yearRes.indexOf("var year =") + "var year =".length)
|
||||||
|
//Log.i(this.name, "Result => (yearRes) $yearRes")
|
||||||
|
yearRes = yearRes.substring(0, yearRes.indexOf(';'))
|
||||||
|
.trim().removeSurrounding("'")
|
||||||
|
}
|
||||||
|
yearRes.toIntOrNull()
|
||||||
|
} else { null }
|
||||||
|
}
|
||||||
|
"genre" -> {
|
||||||
|
tags = td[1].select("a")?.mapNotNull { tag ->
|
||||||
|
tag?.text()?.trim() ?: return@mapNotNull null
|
||||||
|
}?.filter { a -> a.isNotBlank() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
yearRes.toIntOrNull()
|
}
|
||||||
} else { null }
|
|
||||||
|
|
||||||
var descript = body?.select("div.eText")?.text()
|
var descript = body?.select("div.eText")?.text()
|
||||||
if (!descript.isNullOrEmpty()) {
|
if (!descript.isNullOrEmpty()) {
|
||||||
try {
|
try {
|
||||||
descript = descript.substring(0, descript.indexOf("_x_Polus1"))
|
descript = "(undefined_x_Polus+[.\\d+])".toRegex().replace(descript, "")
|
||||||
.replace("_x_Polus1", "")
|
descript = "(_x_Polus+[.\\d+])".toRegex().replace(descript, "")
|
||||||
|
descript = descript.trim().removeSuffix("undefined").trim()
|
||||||
} catch (e: java.lang.Exception) { }
|
} catch (e: java.lang.Exception) { }
|
||||||
}
|
}
|
||||||
|
// Add links hidden in description
|
||||||
|
listOfLinks.addAll(fetchUrls(descript))
|
||||||
|
listOfLinks.forEach { link ->
|
||||||
|
//Log.i(this.name, "Result => (hidden link) $link")
|
||||||
|
descript = descript?.replace(link, "")
|
||||||
|
}
|
||||||
|
|
||||||
// Try looking for episodes, for series
|
// Try looking for episodes, for series
|
||||||
val episodeList = ArrayList<TvSeriesEpisode>()
|
val episodeList = ArrayList<TvSeriesEpisode>()
|
||||||
|
@ -145,22 +167,19 @@ class PinoyHDXyzProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
if (episodeList.size > 0) {
|
if (episodeList.size > 0) {
|
||||||
return TvSeriesLoadResponse(
|
return TvSeriesLoadResponse(
|
||||||
title,
|
name = title,
|
||||||
url,
|
url = url,
|
||||||
this.name,
|
apiName = this.name,
|
||||||
TvType.TvSeries,
|
type = TvType.TvSeries,
|
||||||
episodeList,
|
episodes = episodeList,
|
||||||
poster,
|
posterUrl = poster,
|
||||||
year,
|
year = year,
|
||||||
descript,
|
plot = descript,
|
||||||
null,
|
tags = tags
|
||||||
null,
|
|
||||||
null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Video links for Movie
|
// Video links for Movie
|
||||||
val listOfLinks: MutableList<String> = mutableListOf()
|
|
||||||
body?.select("div.tabcontent > iframe")?.forEach {
|
body?.select("div.tabcontent > iframe")?.forEach {
|
||||||
val linkMain = it?.attr("src")
|
val linkMain = it?.attr("src")
|
||||||
if (!linkMain.isNullOrEmpty()) {
|
if (!linkMain.isNullOrEmpty()) {
|
||||||
|
@ -181,7 +200,17 @@ class PinoyHDXyzProvider : MainAPI() {
|
||||||
|
|
||||||
val streamLinks = listOfLinks.distinct().toJson()
|
val streamLinks = listOfLinks.distinct().toJson()
|
||||||
//Log.i(this.name, "Result => (streamLinks) streamLinks")
|
//Log.i(this.name, "Result => (streamLinks) streamLinks")
|
||||||
return MovieLoadResponse(title, url, this.name, TvType.Movie, streamLinks, poster, year, descript, null, null)
|
return MovieLoadResponse(
|
||||||
|
name = title,
|
||||||
|
url = url,
|
||||||
|
apiName = this.name,
|
||||||
|
type = TvType.Movie,
|
||||||
|
dataUrl = streamLinks,
|
||||||
|
posterUrl = poster,
|
||||||
|
year = year,
|
||||||
|
plot = descript,
|
||||||
|
tags = tags
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
override suspend fun loadLinks(
|
||||||
|
@ -191,11 +220,12 @@ class PinoyHDXyzProvider : MainAPI() {
|
||||||
callback: (ExtractorLink) -> Unit
|
callback: (ExtractorLink) -> Unit
|
||||||
): Boolean {
|
): Boolean {
|
||||||
var count = 0
|
var count = 0
|
||||||
mapper.readValue<List<String>>(data).apmap { item ->
|
mapper.readValue<List<String>>(data).forEach { item ->
|
||||||
if (item.isNotEmpty()) {
|
val url = item.trim()
|
||||||
val url = item.trim()
|
if (url.isNotBlank()) {
|
||||||
loadExtractor(url, mainUrl, callback)
|
if (loadExtractor(url, mainUrl, callback)) {
|
||||||
count++
|
count++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count > 0
|
return count > 0
|
||||||
|
|
|
@ -113,13 +113,33 @@ class PinoyMoviePediaProvider : MainAPI() {
|
||||||
val isTvSeries = doc.select("title")?.text()?.lowercase()?.contains("full episode -") ?: false
|
val isTvSeries = doc.select("title")?.text()?.lowercase()?.contains("full episode -") ?: false
|
||||||
|
|
||||||
// Video details
|
// Video details
|
||||||
|
val data = inner?.select("div.data")
|
||||||
val poster = inner?.select("div.poster > img")?.attr("src")
|
val poster = inner?.select("div.poster > img")?.attr("src")
|
||||||
val title = inner?.select("div.data > h1")?.firstOrNull()?.text() ?: ""
|
val title = data?.select("h1")?.firstOrNull()?.text() ?: ""
|
||||||
val descript = body?.select("div#info > div.wp-content")?.text()
|
val descript = body?.select("div#info > div.wp-content")
|
||||||
|
?.select("p")?.get(0)?.text()
|
||||||
val rex = Regex("\\((\\d+)")
|
val rex = Regex("\\((\\d+)")
|
||||||
val yearRes = rex.find(title)?.value ?: ""
|
val yearRes = rex.find(title)?.value ?: ""
|
||||||
//Log.i(this.name, "Result => (yearRes) ${yearRes}")
|
//Log.i(this.name, "Result => (yearRes) ${yearRes}")
|
||||||
val year = yearRes.replace("(", "").toIntOrNull()
|
val year = yearRes.replace("(", "").toIntOrNull()
|
||||||
|
val tags = data?.select("div.sgeneros > a")?.mapNotNull { tag ->
|
||||||
|
tag?.text()?.trim() ?: return@mapNotNull null
|
||||||
|
}?.toList()
|
||||||
|
val recList = body?.select("div#single_relacionados > article")?.mapNotNull {
|
||||||
|
val a = it.select("a") ?: return@mapNotNull null
|
||||||
|
val aUrl = a.attr("href") ?: return@mapNotNull null
|
||||||
|
val aImg = a.select("img")?.attr("src")
|
||||||
|
val aName = a.select("img")?.attr("alt") ?: return@mapNotNull null
|
||||||
|
val aYear = aName.trim().takeLast(5).removeSuffix(")").toIntOrNull()
|
||||||
|
MovieSearchResponse(
|
||||||
|
url = aUrl,
|
||||||
|
name = aName,
|
||||||
|
type = TvType.Movie,
|
||||||
|
posterUrl = aImg,
|
||||||
|
year = aYear,
|
||||||
|
apiName = this.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Video links
|
// Video links
|
||||||
val playcontainer = body?.select("div#playcontainer")
|
val playcontainer = body?.select("div#playcontainer")
|
||||||
|
@ -162,21 +182,31 @@ class PinoyMoviePediaProvider : MainAPI() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TvSeriesLoadResponse(
|
return TvSeriesLoadResponse(
|
||||||
title,
|
name = title,
|
||||||
url,
|
url = url,
|
||||||
this.name,
|
apiName = this.name,
|
||||||
TvType.TvSeries,
|
type = TvType.TvSeries,
|
||||||
episodeList,
|
episodes = episodeList,
|
||||||
poster,
|
posterUrl = poster,
|
||||||
year,
|
year = year,
|
||||||
descript,
|
plot = descript,
|
||||||
null,
|
tags = tags,
|
||||||
null,
|
recommendations = recList
|
||||||
null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val streamlinks = listOfLinks.distinct().toJson()
|
val streamlinks = listOfLinks.distinct().toJson()
|
||||||
return MovieLoadResponse(title, url, this.name, TvType.Movie, streamlinks, poster, year, descript, null, null)
|
return MovieLoadResponse(
|
||||||
|
name = title,
|
||||||
|
url = url,
|
||||||
|
apiName = this.name,
|
||||||
|
type = TvType.Movie,
|
||||||
|
dataUrl = streamlinks,
|
||||||
|
posterUrl = poster,
|
||||||
|
year = year,
|
||||||
|
plot = descript,
|
||||||
|
tags = tags,
|
||||||
|
recommendations = recList
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
override suspend fun loadLinks(
|
||||||
|
|
|
@ -29,45 +29,49 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
val all = mutableListOf<HomePageList>()
|
val all = mutableListOf<HomePageList>()
|
||||||
for (item in rows) {
|
for (item in rows) {
|
||||||
val title = item.first
|
val title = item.first
|
||||||
val inner = mainbody.select("div${sep}${item.second} > article")
|
val elements = mainbody.select("div${sep}${item.second} > article")?.mapNotNull {
|
||||||
if (inner != null) {
|
// Get inner div from article
|
||||||
val elements: List<SearchResponse> = inner.map {
|
var urlTitle = it?.select("div.data.dfeatur")
|
||||||
// Get inner div from article
|
if (urlTitle.isNullOrEmpty()) {
|
||||||
var urlTitle = it?.select("div.data.dfeatur")
|
urlTitle = it?.select("div.data")
|
||||||
if (urlTitle.isNullOrEmpty()) {
|
|
||||||
urlTitle = it?.select("div.data")
|
|
||||||
}
|
|
||||||
// Fetch details
|
|
||||||
val link = urlTitle?.select("a")?.attr("href") ?: ""
|
|
||||||
val image = it?.select("div.poster > img")?.attr("data-src")
|
|
||||||
|
|
||||||
// Get Title and Year
|
|
||||||
val name = urlTitle?.select("h3")?.text() ?: ""
|
|
||||||
var year = urlTitle?.select("span")?.text()?.toIntOrNull()
|
|
||||||
|
|
||||||
if (year == null) {
|
|
||||||
// Get year from name
|
|
||||||
val rex = Regex("\\((\\d+)")
|
|
||||||
year = rex.find(name)?.value?.replace("(", "")?.toIntOrNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
MovieSearchResponse(
|
|
||||||
name,
|
|
||||||
link,
|
|
||||||
this.name,
|
|
||||||
TvType.Movie,
|
|
||||||
image,
|
|
||||||
year,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
}.filter { a -> a.url.isNotEmpty() }
|
|
||||||
.filter { b -> b.name.isNotEmpty() }
|
|
||||||
.distinctBy { c -> c.url }
|
|
||||||
if (!elements.isNullOrEmpty()) {
|
|
||||||
all.add(HomePageList(
|
|
||||||
title, elements
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
if (urlTitle.isNullOrEmpty()) { return@mapNotNull null }
|
||||||
|
// Fetch details
|
||||||
|
val link = fixUrlNull(urlTitle.select("a")?.attr("href"))
|
||||||
|
if (link.isNullOrBlank()) { return@mapNotNull null }
|
||||||
|
|
||||||
|
val image = it?.select("div.poster > img")?.attr("data-src")
|
||||||
|
|
||||||
|
// Get Title and Year
|
||||||
|
val name = urlTitle.select("h3")?.text()
|
||||||
|
?: urlTitle.select("h2")?.text()
|
||||||
|
?: urlTitle.select("h1")?.text()
|
||||||
|
if (name.isNullOrBlank()) { return@mapNotNull null }
|
||||||
|
|
||||||
|
var year = urlTitle.select("span")?.text()?.toIntOrNull()
|
||||||
|
|
||||||
|
if (year == null) {
|
||||||
|
// Get year from name
|
||||||
|
val rex = Regex("\\((\\d+)")
|
||||||
|
year = rex.find(name)?.value?.replace("(", "")?.toIntOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
MovieSearchResponse(
|
||||||
|
name = name,
|
||||||
|
url = link,
|
||||||
|
apiName = this.name,
|
||||||
|
type = TvType.Movie,
|
||||||
|
posterUrl = image,
|
||||||
|
year = year
|
||||||
|
)
|
||||||
|
}?.distinctBy { c -> c.url } ?: listOf()
|
||||||
|
//Add to list of homepages
|
||||||
|
if (!elements.isNullOrEmpty()) {
|
||||||
|
all.add(
|
||||||
|
HomePageList(
|
||||||
|
title, elements
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return all
|
return all
|
||||||
|
@ -136,12 +140,30 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
|
|
||||||
val descript = body?.select("div#info > div.wp-content")?.text()
|
val descript = body?.select("div#info > div.wp-content")?.text()
|
||||||
val poster = body?.select("div.poster > img")?.attr("src")
|
val poster = body?.select("div.poster > img")?.attr("src")
|
||||||
|
val tags = data?.select("div.sgeneros > a")?.mapNotNull { tag ->
|
||||||
|
tag?.text() ?: return@mapNotNull null
|
||||||
|
}?.toList()
|
||||||
|
val recList = body?.select("div#single_relacionados > article")?.mapNotNull {
|
||||||
|
val a = it.select("a") ?: return@mapNotNull null
|
||||||
|
val aUrl = a.attr("href") ?: return@mapNotNull null
|
||||||
|
val aImg = a.select("img")?.attr("data-src")
|
||||||
|
val aName = a.select("img")?.attr("alt") ?: return@mapNotNull null
|
||||||
|
val aYear = aName.trim().takeLast(5).removeSuffix(")").toIntOrNull()
|
||||||
|
MovieSearchResponse(
|
||||||
|
url = aUrl,
|
||||||
|
name = aName,
|
||||||
|
type = TvType.Movie,
|
||||||
|
posterUrl = aImg,
|
||||||
|
year = aYear,
|
||||||
|
apiName = this.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Video links
|
// Video links
|
||||||
val listOfLinks: MutableList<String> = mutableListOf()
|
val listOfLinks: MutableList<String> = mutableListOf()
|
||||||
val postlist = body?.select("div#playeroptions > ul > li")?.mapNotNull {
|
val postlist = body?.select("div#playeroptions > ul > li")?.mapNotNull {
|
||||||
it?.attr("data-post") ?: return@mapNotNull null
|
it?.attr("data-post") ?: return@mapNotNull null
|
||||||
}?.filter { it.isNotEmpty() }?.distinct() ?: listOf()
|
}?.filter { it.isNotBlank() }?.distinct() ?: listOf()
|
||||||
|
|
||||||
postlist.apmap { datapost ->
|
postlist.apmap { datapost ->
|
||||||
//Log.i(this.name, "Result => (datapost) ${datapost}")
|
//Log.i(this.name, "Result => (datapost) ${datapost}")
|
||||||
|
@ -159,7 +181,18 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
listOfLinks.add(embedData.embed_url)
|
listOfLinks.add(embedData.embed_url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return MovieLoadResponse(title, url, this.name, TvType.Movie, listOfLinks.toJson(), poster, year, descript, null, null)
|
return MovieLoadResponse(
|
||||||
|
name = title,
|
||||||
|
url = url,
|
||||||
|
apiName = this.name,
|
||||||
|
type = TvType.Movie,
|
||||||
|
dataUrl = listOfLinks.toJson(),
|
||||||
|
posterUrl = poster,
|
||||||
|
year = year,
|
||||||
|
plot = descript,
|
||||||
|
tags = tags,
|
||||||
|
recommendations = recList
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadLinks(
|
override suspend fun loadLinks(
|
||||||
|
@ -170,19 +203,22 @@ class PinoyMoviesEsProvider : MainAPI() {
|
||||||
): Boolean {
|
): Boolean {
|
||||||
// parse movie servers
|
// parse movie servers
|
||||||
var count = 0
|
var count = 0
|
||||||
mapper.readValue<List<String>>(data).apmap { link ->
|
mapper.readValue<List<String>>(data).forEach { link ->
|
||||||
count++
|
|
||||||
//Log.i(this.name, "Result => (link) $link")
|
//Log.i(this.name, "Result => (link) $link")
|
||||||
if (link.startsWith("https://vstreamhub.com")) {
|
if (link.startsWith("https://vstreamhub.com")) {
|
||||||
VstreamhubHelper.getUrls(link, callback)
|
VstreamhubHelper.getUrls(link, callback)
|
||||||
|
count++
|
||||||
} else if (link.contains("fembed.com")) {
|
} else if (link.contains("fembed.com")) {
|
||||||
val extractor = FEmbed()
|
val extractor = FEmbed()
|
||||||
extractor.domainUrl = "diasfem.com"
|
extractor.domainUrl = "diasfem.com"
|
||||||
extractor.getUrl(data).forEach {
|
extractor.getUrl(data).forEach {
|
||||||
callback.invoke(it)
|
callback.invoke(it)
|
||||||
|
count++
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
loadExtractor(link, mainUrl, callback)
|
if (loadExtractor(link, mainUrl, callback)) {
|
||||||
|
count++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count > 0
|
return count > 0
|
||||||
|
|
|
@ -98,6 +98,7 @@ class WatchAsianProvider : MainAPI() {
|
||||||
var title = ""
|
var title = ""
|
||||||
var descript : String? = null
|
var descript : String? = null
|
||||||
var year : Int? = null
|
var year : Int? = null
|
||||||
|
var tags : List<String>? = null
|
||||||
if (isDramaDetail) {
|
if (isDramaDetail) {
|
||||||
val main = body.select("div.details")
|
val main = body.select("div.details")
|
||||||
val inner = main?.select("div.info")
|
val inner = main?.select("div.info")
|
||||||
|
@ -105,14 +106,20 @@ class WatchAsianProvider : MainAPI() {
|
||||||
poster = fixUrlNull(main?.select("div.img > img")?.attr("src")) ?: ""
|
poster = fixUrlNull(main?.select("div.img > img")?.attr("src")) ?: ""
|
||||||
//Log.i(this.name, "Result => (imgLinkCode) ${imgLinkCode}")
|
//Log.i(this.name, "Result => (imgLinkCode) ${imgLinkCode}")
|
||||||
title = inner?.select("h1")?.firstOrNull()?.text() ?: ""
|
title = inner?.select("h1")?.firstOrNull()?.text() ?: ""
|
||||||
year = if (title.length > 5) {
|
|
||||||
title.replace(")", "").replace("(", "").substring(title.length - 5)
|
|
||||||
.trim().trimEnd(')').toIntOrNull()
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
//Log.i(this.name, "Result => (year) ${title.substring(title.length - 5)}")
|
//Log.i(this.name, "Result => (year) ${title.substring(title.length - 5)}")
|
||||||
descript = inner?.text()
|
descript = inner?.text()
|
||||||
|
|
||||||
|
inner?.select("p")?.forEach { p ->
|
||||||
|
val caption = p?.selectFirst("span")?.text()?.trim()?.lowercase()?.removeSuffix(":")?.trim() ?: return@forEach
|
||||||
|
when (caption) {
|
||||||
|
"genre" -> {
|
||||||
|
tags = p.select("a")?.mapNotNull { it?.text()?.trim() }
|
||||||
|
}
|
||||||
|
"released" -> {
|
||||||
|
year = p.select("a")?.text()?.trim()?.toIntOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
poster = body.select("meta[itemprop=\"image\"]")?.attr("content") ?: ""
|
poster = body.select("meta[itemprop=\"image\"]")?.attr("content") ?: ""
|
||||||
title = body.selectFirst("div.block.watch-drama")?.selectFirst("h1")
|
title = body.selectFirst("div.block.watch-drama")?.selectFirst("h1")
|
||||||
|
@ -120,6 +127,13 @@ class WatchAsianProvider : MainAPI() {
|
||||||
year = null
|
year = null
|
||||||
descript = body.select("meta[name=\"description\"]")?.attr("content")
|
descript = body.select("meta[name=\"description\"]")?.attr("content")
|
||||||
}
|
}
|
||||||
|
//Fallback year from title
|
||||||
|
if (year == null) {
|
||||||
|
year = if (title.length > 5) {
|
||||||
|
title.replace(")", "").replace("(", "").substring(title.length - 5)
|
||||||
|
.trim().trimEnd(')').toIntOrNull()
|
||||||
|
} else { null }
|
||||||
|
}
|
||||||
|
|
||||||
// Episodes Links
|
// Episodes Links
|
||||||
//Log.i(this.name, "Result => (all eps) ${body.select("ul.list-episode-item-2.all-episode > li")}")
|
//Log.i(this.name, "Result => (all eps) ${body.select("ul.list-episode-item-2.all-episode > li")}")
|
||||||
|
@ -147,20 +161,28 @@ class WatchAsianProvider : MainAPI() {
|
||||||
title = title.trim().removeSuffix("Episode 1")
|
title = title.trim().removeSuffix("Episode 1")
|
||||||
val streamlink = getServerLinks(episodeList[0].data)
|
val streamlink = getServerLinks(episodeList[0].data)
|
||||||
//Log.i(this.name, "Result => (streamlink) $streamlink")
|
//Log.i(this.name, "Result => (streamlink) $streamlink")
|
||||||
return MovieLoadResponse(title, url, this.name, TvType.Movie, streamlink, poster, year, descript, null, null)
|
return MovieLoadResponse(
|
||||||
|
name = title,
|
||||||
|
url = url,
|
||||||
|
apiName = this.name,
|
||||||
|
type = TvType.Movie,
|
||||||
|
dataUrl = streamlink,
|
||||||
|
posterUrl = poster,
|
||||||
|
year = year,
|
||||||
|
plot = descript,
|
||||||
|
tags = tags
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return TvSeriesLoadResponse(
|
return TvSeriesLoadResponse(
|
||||||
title,
|
name = title,
|
||||||
url,
|
url = url,
|
||||||
this.name,
|
apiName = this.name,
|
||||||
TvType.TvSeries,
|
type = TvType.TvSeries,
|
||||||
episodeList.reversed(),
|
episodes = episodeList.reversed(),
|
||||||
poster,
|
posterUrl = poster,
|
||||||
year,
|
year = year,
|
||||||
descript,
|
plot = descript,
|
||||||
null,
|
tags = tags
|
||||||
null,
|
|
||||||
null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue