From 6876d871e23977b64cf3241f1f27d2d1b31f24b3 Mon Sep 17 00:00:00 2001 From: Jace <54625750+Jacekun@users.noreply.github.com> Date: Sat, 1 Oct 2022 17:30:25 +0800 Subject: [PATCH] [Provider] Pinoy Movies Hub --- PinoyMoviesHub/build.gradle.kts | 27 +++ PinoyMoviesHub/src/main/AndroidManifest.xml | 2 + .../kotlin/com/lagradost/PinoyMoviesHub.kt | 223 ++++++++++++++++++ .../com/lagradost/PinoyMoviesHubPlugin.kt | 14 ++ 4 files changed, 266 insertions(+) create mode 100644 PinoyMoviesHub/build.gradle.kts create mode 100644 PinoyMoviesHub/src/main/AndroidManifest.xml create mode 100644 PinoyMoviesHub/src/main/kotlin/com/lagradost/PinoyMoviesHub.kt create mode 100644 PinoyMoviesHub/src/main/kotlin/com/lagradost/PinoyMoviesHubPlugin.kt diff --git a/PinoyMoviesHub/build.gradle.kts b/PinoyMoviesHub/build.gradle.kts new file mode 100644 index 0000000..a04c92a --- /dev/null +++ b/PinoyMoviesHub/build.gradle.kts @@ -0,0 +1,27 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + language = "tl" + // All of these properties are optional, you can safely remove them + + description = "Pinoy Movies Hub" + authors = listOf("Jace") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "Movie", + "TvSeries", + "AsianDrama", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=pinoymovieshub.ph&sz=%size%" +} \ No newline at end of file diff --git a/PinoyMoviesHub/src/main/AndroidManifest.xml b/PinoyMoviesHub/src/main/AndroidManifest.xml new file mode 100644 index 0000000..29aec9d --- /dev/null +++ b/PinoyMoviesHub/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/PinoyMoviesHub/src/main/kotlin/com/lagradost/PinoyMoviesHub.kt b/PinoyMoviesHub/src/main/kotlin/com/lagradost/PinoyMoviesHub.kt new file mode 100644 index 0000000..cc12dda --- /dev/null +++ b/PinoyMoviesHub/src/main/kotlin/com/lagradost/PinoyMoviesHub.kt @@ -0,0 +1,223 @@ +package com.lagradost + +import android.util.Log +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.mvvm.logError +import com.lagradost.cloudstream3.utils.AppUtils +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor +import org.jsoup.select.Elements + +class PinoyMoviesHub : MainAPI() { + //private val TAG = "Dev" + override var name = "Pinoy Movies Hub" + override var mainUrl = "https://pinoymovieshub.ph" + override var lang = "tl" + override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries, TvType.AsianDrama) + override val hasDownloadSupport = true + override val hasMainPage = true + override val hasQuickSearch = false + + override suspend fun getMainPage( + page: Int, + request: MainPageRequest + ): HomePageResponse { + val all = ArrayList() + val doc = app.get(mainUrl).document + val rows = mutableListOf( + Pair("Suggestion", "div.items.featured"), + Pair("Pinoy Movies and TV", "div.items.full"), + //Pair("Pinoy Teleserye and TV Series", "tvload"), + Pair("Action", "div#genre_action"), + Pair("Comedy", "div#genre_comedy"), + Pair("Romance", "div#genre_romance"), + Pair("Horror", "div#genre_horror"), + Pair("Drama", "div#genre_drama"), + ) + if (settingsForProvider.enableAdult) { + rows.add(Pair("Rated-R 18+", "genre_rated-r")) + } + //Log.i(TAG, "Parsing page..") + val maindoc = doc.selectFirst("div.module") + ?.select("div.content.full_width_layout.full") + + rows.forEach { pair -> + // Fetch row title + val title = pair.first + // Fetch list of items and map + //Log.i(TAG, "Title => $title") + maindoc?.select(pair.second)?.let { inner -> + //Log.i(TAG, "inner => $inner") + val results = inner.select("article").getResults(this.name) + if (results.isNotEmpty()) { + all.add( + HomePageList( + name = title, + list = results, + isHorizontalImages = false + ) + ) + } + } + } + return HomePageResponse(all) + } + + override suspend fun search(query: String): List { + val searchUrl = "${mainUrl}/?s=${query}" + return app.get(searchUrl).document + .selectFirst("div#archive-content") + ?.select("article") + .getResults(this.name) + } + + override suspend fun load(url: String): MovieLoadResponse { + //TODO: Load polishing + val doc = app.get(url).document + val body = doc.getElementsByTag("body").firstOrNull() + val sheader = body?.selectFirst("div.sheader") + + //Log.i(TAG, "Result => (url) ${url}") + val poster = sheader?.selectFirst("div.poster > img") + ?.attr("src") + + val title = sheader + ?.selectFirst("div.data > h1") + ?.text() ?: "" + val descript = body?.selectFirst("div#info div.wp-content")?.text() + val year = body?.selectFirst("span.date")?.text()?.trim()?.takeLast(4)?.toIntOrNull() + + //TODO: Parse episodes + val episodes = body?.select("div.page-content-listing.single-page") + ?.first()?.select("li") + val episodeList = episodes?.mapNotNull { + val innerA = it?.selectFirst("a") ?: return@mapNotNull null + val eplink = innerA.attr("href") ?: return@mapNotNull null + 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, + ) + } ?: listOf() + + val dataUrl = doc.selectFirst("link[rel='shortlink']") + ?.attr("href") + ?.substringAfter("?p=") ?: "" + //Log.i(TAG, "Result => (dataUrl) ${dataUrl}") + + //Log.i(TAG, "Result => (id) ${id}") + return MovieLoadResponse( + name = title, + url = url, + dataUrl = dataUrl, + apiName = this.name, + type = TvType.Movie, + posterUrl = poster, + year = year, + plot = descript, + ) + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + try { + //Log.i(TAG, "Loading ajax request..") + val requestLink = "${mainUrl}/wp-admin/admin-ajax.php" + val action = "doo_player_ajax" + val nume = "1" + val type = "movie" + val doc = app.post( + url = requestLink, + referer = mainUrl, + headers = mapOf( + Pair("User-Agent", USER_AGENT), + Pair("Sec-Fetch-Mode", "cors") + ), + data = mapOf( + Pair("action", action), + Pair("post", data), + Pair("nume", nume), + Pair("type", type) + ) + ) + //Log.i(TAG, "Response (${doc.code}) => ${doc.text}") + AppUtils.tryParseJson(doc.text)?.let { + val streamLink = it.embed_url ?: "" + //Log.i(TAG, "Response (streamLink) => ${streamLink}") + if (streamLink.isNotBlank()) { + loadExtractor( + url = streamLink, + referer = mainUrl, + callback = callback, + subtitleCallback = subtitleCallback + ) + } + } + } catch (e: Exception) { + //Log.i(TAG, "Error => $e") + logError(e) + return false + } + return true + } + + private fun Elements?.getResults(apiName: String): List { + return this?.mapNotNull { + val divPoster = it.selectFirst("div.poster") + val divData = it.selectFirst("div.data") + + val firstA = divData?.selectFirst("a") + val link = fixUrlNull(firstA?.attr("href")) ?: return@mapNotNull null + val qualString = divPoster?.select("span.quality")?.text()?.trim() ?: "" + val qual = getQualityFromString(qualString) + val tvtype = if (qualString.equals("TV")) { TvType.TvSeries } else { TvType.Movie } + + val name = divData?.selectFirst("a")?.text() ?: "" + val year = divData?.selectFirst("span")?.text() + ?.trim()?.takeLast(4)?.toIntOrNull() + + val imageDiv = divPoster?.selectFirst("img") + var image = imageDiv?.attr("src") + if (image.isNullOrBlank()) { + image = imageDiv?.attr("data-src") + } + + //Log.i(apiName, "Added => $name / $link") + if (tvtype == TvType.TvSeries) { + TvSeriesSearchResponse( + name = name, + url = link, + apiName = apiName, + type = tvtype, + posterUrl = image, + year = year, + quality = qual, + ) + } else { + MovieSearchResponse( + name = name, + url = link, + apiName = apiName, + type = tvtype, + posterUrl = image, + year = year, + quality = qual, + ) + } + } ?: listOf() + } + + private data class Response( + @JsonProperty("embed_url") val embed_url: String? + ) +} \ No newline at end of file diff --git a/PinoyMoviesHub/src/main/kotlin/com/lagradost/PinoyMoviesHubPlugin.kt b/PinoyMoviesHub/src/main/kotlin/com/lagradost/PinoyMoviesHubPlugin.kt new file mode 100644 index 0000000..02f0764 --- /dev/null +++ b/PinoyMoviesHub/src/main/kotlin/com/lagradost/PinoyMoviesHubPlugin.kt @@ -0,0 +1,14 @@ + +package com.lagradost + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class PinoyMoviesHubPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(PinoyMoviesHub()) + } +} \ No newline at end of file