From 4d8c548a2f553f81516ed6c47702062da19880bf Mon Sep 17 00:00:00 2001 From: hexated Date: Sun, 14 May 2023 02:56:34 +0700 Subject: [PATCH] added Dubbindo --- Dubbindo/build.gradle.kts | 27 ++++ .../src/main/kotlin/com/hexated/Dubbindo.kt | 129 ++++++++++++++++++ .../main/kotlin/com/hexated/DubbindoPlugin.kt | 14 ++ 3 files changed, 170 insertions(+) create mode 100644 Dubbindo/build.gradle.kts create mode 100644 Dubbindo/src/main/kotlin/com/hexated/Dubbindo.kt create mode 100644 Dubbindo/src/main/kotlin/com/hexated/DubbindoPlugin.kt diff --git a/Dubbindo/build.gradle.kts b/Dubbindo/build.gradle.kts new file mode 100644 index 00000000..d92b972b --- /dev/null +++ b/Dubbindo/build.gradle.kts @@ -0,0 +1,27 @@ +// use an integer for version numbers +version = 1 + +cloudstream { + language = "id" + // All of these properties are optional, you can safely remove them + + // description = "Lorem Ipsum" + authors = listOf("Hexated") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "TvSeries", + "Movie", + "Cartoon", + "Anime", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=www.dubbindo.xyz&sz=%size%" +} \ No newline at end of file diff --git a/Dubbindo/src/main/kotlin/com/hexated/Dubbindo.kt b/Dubbindo/src/main/kotlin/com/hexated/Dubbindo.kt new file mode 100644 index 00000000..7f846ff6 --- /dev/null +++ b/Dubbindo/src/main/kotlin/com/hexated/Dubbindo.kt @@ -0,0 +1,129 @@ +package com.hexated + +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.Qualities +import org.jsoup.nodes.Element + +class Dubbindo : MainAPI() { + override var mainUrl = "https://www.dubbindo.xyz" + override var name = "Dubbindo" + override val hasMainPage = true + override var lang = "id" + override val hasDownloadSupport = true + + override val supportedTypes = setOf( + TvType.TvSeries, + TvType.Movie, + TvType.Cartoon, + TvType.Anime, + ) + + override val mainPage = mainPageOf( + "$mainUrl/videos/category/1" to "Movie", + "$mainUrl/videos/category/3" to "TV Series", + "$mainUrl/videos/category/5" to "Anime Series", + "$mainUrl/videos/category/4" to "Anime Movie", + "$mainUrl/videos/category/other" to "Other", + ) + + override suspend fun getMainPage( + page: Int, + request: MainPageRequest + ): HomePageResponse { + val document = app.get("${request.data}?page_id=$page").document + val home = document.select("div.videos-latest-list.pt_timeline_vids div.video-wrapper") + .mapNotNull { + it.toSearchResult() + } + return newHomePageResponse( + list = HomePageList( + name = request.name, + list = home, + isHorizontalImages = true + ), + hasNext = true + ) + } + + private fun Element.toSearchResult(): TvSeriesSearchResponse? { + val title = this.selectFirst("h4,div.video-title")?.text()?.trim() ?: "" + val href = this.selectFirst("a")?.attr("href") ?: return null + val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) + return newTvSeriesSearchResponse(title, href, TvType.TvSeries) { + this.posterUrl = posterUrl + } + } + + override suspend fun search(query: String): List { + val searchResponse = mutableListOf() + for (i in 1..10) { + val document = + app.get( + "$mainUrl/search?keyword=$query&page_id=$i", + ).document + val results = document.select("div.videos-latest-list.row div.video-wrapper") + .mapNotNull { + it.toSearchResult() + } + searchResponse.addAll(results) + if (results.isEmpty()) break + } + return searchResponse + } + + override suspend fun load(url: String): LoadResponse? { + val document = app.get(url).document + + val title = document.selectFirst("div.video-big-title h1")?.text() ?: return null + val poster = document.selectFirst("meta[property=og:image]")?.attr("content") + val tags = document.select("div.pt_categories li a").map { it.text() } + val description = document.select("div.watch-video-description p").text() + val recommendations = document.select("div.related-video-wrapper").mapNotNull { + it.toSearchResult() + } + val video = document.select("video#my-video source").map { + Video( + it.attr("src"), + it.attr("size"), + ) + } + + return newMovieLoadResponse(title, url, TvType.Movie, video.toJson()) { + posterUrl = poster + plot = description + this.tags = tags + this.recommendations = recommendations + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + + tryParseJson>(data)?.map { video -> + callback.invoke( + ExtractorLink( + this.name, + this.name, + video.src ?: return@map, + "", + video.res?.toIntOrNull() ?: Qualities.Unknown.value, + ) + ) + } + + return true + } + + data class Video( + val src: String? = null, + val res: String? = null, + ) + +} \ No newline at end of file diff --git a/Dubbindo/src/main/kotlin/com/hexated/DubbindoPlugin.kt b/Dubbindo/src/main/kotlin/com/hexated/DubbindoPlugin.kt new file mode 100644 index 00000000..22d3b82d --- /dev/null +++ b/Dubbindo/src/main/kotlin/com/hexated/DubbindoPlugin.kt @@ -0,0 +1,14 @@ + +package com.hexated + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class DubbindoPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(Dubbindo()) + } +} \ No newline at end of file