From 4c28c0567c6de6e8d1e8093df25277737674e1ff Mon Sep 17 00:00:00 2001 From: Bnyro <82752168+Bnyro@users.noreply.github.com> Date: Sun, 27 Aug 2023 01:12:26 +0200 Subject: [PATCH] add German FilmPalast provider (#241) --- FilmPalast/build.gradle.kts | 24 ++++++ FilmPalast/src/main/AndroidManifest.xml | 2 + .../com/example/FilmpalastExtractors.kt | 30 +++++++ .../kotlin/com/example/FilmpalastPlugin.kt | 18 ++++ .../kotlin/com/example/FilmpalastProvider.kt | 82 +++++++++++++++++++ 5 files changed, 156 insertions(+) create mode 100644 FilmPalast/build.gradle.kts create mode 100644 FilmPalast/src/main/AndroidManifest.xml create mode 100644 FilmPalast/src/main/kotlin/com/example/FilmpalastExtractors.kt create mode 100644 FilmPalast/src/main/kotlin/com/example/FilmpalastPlugin.kt create mode 100644 FilmPalast/src/main/kotlin/com/example/FilmpalastProvider.kt diff --git a/FilmPalast/build.gradle.kts b/FilmPalast/build.gradle.kts new file mode 100644 index 00000000..6f3a4bdc --- /dev/null +++ b/FilmPalast/build.gradle.kts @@ -0,0 +1,24 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + // All of these properties are optional, you can safely remove them + + description = "German Filmpalast provider" + authors = listOf("Bnyro") + + /** + * 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("TvSeries", "Movie") +} diff --git a/FilmPalast/src/main/AndroidManifest.xml b/FilmPalast/src/main/AndroidManifest.xml new file mode 100644 index 00000000..1863f02a --- /dev/null +++ b/FilmPalast/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/FilmPalast/src/main/kotlin/com/example/FilmpalastExtractors.kt b/FilmPalast/src/main/kotlin/com/example/FilmpalastExtractors.kt new file mode 100644 index 00000000..11611566 --- /dev/null +++ b/FilmPalast/src/main/kotlin/com/example/FilmpalastExtractors.kt @@ -0,0 +1,30 @@ +package com.example + +import com.lagradost.cloudstream3.extractors.Filesim +import com.lagradost.cloudstream3.extractors.StreamTape +import com.lagradost.cloudstream3.extractors.Streamhub +import com.lagradost.cloudstream3.extractors.Voe + +class StreamTapeTo : StreamTape() { + override var mainUrl = "https://streamtape.com" +} + +class StreamHubGg : Streamhub() { + override var name = "Streamhub Gg" + override var mainUrl = "https://streamhub.gg" +} + +class VoeSx: Voe() { + override val name = "Voe Sx" + override val mainUrl = "https://voe.sx" +} + +class MetaGnathTuggers : Voe() { + override val name = "Metagnathtuggers" + override val mainUrl = "https://metagnathtuggers.com" +} + +class FileLions : Filesim() { + override val name = "Filelions" + override var mainUrl = "https://filelions.to" +} diff --git a/FilmPalast/src/main/kotlin/com/example/FilmpalastPlugin.kt b/FilmPalast/src/main/kotlin/com/example/FilmpalastPlugin.kt new file mode 100644 index 00000000..023c0f59 --- /dev/null +++ b/FilmPalast/src/main/kotlin/com/example/FilmpalastPlugin.kt @@ -0,0 +1,18 @@ +package com.example + +import com.lagradost.cloudstream3.plugins.CloudstreamPlugin +import com.lagradost.cloudstream3.plugins.Plugin +import android.content.Context + +@CloudstreamPlugin +class FilmpalastPlugin: Plugin() { + override fun load(context: Context) { + // All providers should be added in this manner. Please don't edit the providers list directly. + registerMainAPI(FilmpalastProvider()) + registerExtractorAPI(StreamTapeTo()) + registerExtractorAPI(StreamHubGg()) + registerExtractorAPI(VoeSx()) + registerExtractorAPI(MetaGnathTuggers()) + registerExtractorAPI(FileLions()) + } +} \ No newline at end of file diff --git a/FilmPalast/src/main/kotlin/com/example/FilmpalastProvider.kt b/FilmPalast/src/main/kotlin/com/example/FilmpalastProvider.kt new file mode 100644 index 00000000..7c606967 --- /dev/null +++ b/FilmPalast/src/main/kotlin/com/example/FilmpalastProvider.kt @@ -0,0 +1,82 @@ +package com.example + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.AppUtils.parseJson +import com.lagradost.cloudstream3.utils.AppUtils.toJson +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor +import org.jsoup.nodes.Element +import org.jsoup.select.Elements + +class FilmpalastProvider : MainAPI() { + override var mainUrl = "https://filmpalast.to" + override var name = "Filmpalast" + override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries) + + override var lang = "de" + override val hasMainPage = true + + private fun Element.toSearchResponse(): SearchResponse { + val title = select("cite a.rb").text() + val url = select("a.rb").attr("href") + val posterPath = select("img.cover-opacity").attr("src") + return newMovieSearchResponse(title, type = TvType.Movie, url = url).apply { + this.posterUrl = "$mainUrl$posterPath" + } + } + + override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse { + val movies = app.get("$mainUrl/movies/top").document + val movieResults = movies.select("#content .liste.rb").mapNotNull { + it.toSearchResponse() + } + val series = app.get("$mainUrl/serien/view").document + val seriesResults = series.select("#content .liste.rb").mapNotNull { + it.toSearchResponse() + } + val homePageLists = listOf(HomePageList("Movies", movieResults), HomePageList("Series", seriesResults)) + return newHomePageResponse(homePageLists, hasNext = false) + } + + override suspend fun search(query: String): List { + val document = app.get("$mainUrl/search/title/$query").document + return document.select("#content .glowliste").mapNotNull { + it.toSearchResponse() + } + } + + override suspend fun load(url: String): LoadResponse { + val document = app.get(url).document.select("#content") + + val title = document.select("h2.rb.bgDark").text() + val imagePath = document.select(".detail.rb img.cover2").attr("src") + val description = document.select("span[itemprop=description]").text() + val details = document.select("detail-content-list li") + val year = details.first()?.html()?.split("
")?.getOrNull(1)?.filter { it.isDigit() }?.toIntOrNull() + val duration = details.select("em").first()?.ownText()?.filter { it.isDigit() }?.toIntOrNull() + + val links = document.select(".currentStreamLinks a.iconPlay").mapNotNull { + it.attr("href") ?: it.attr("data-player-url") + } + return newMovieLoadResponse(title, url, TvType.Movie, links.toJson()).apply { + this.posterUrl = "$mainUrl$imagePath" + this.plot = description + this.duration = duration + this.year = year + } + } + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val links = parseJson>(data) + links.apmap { + val link = fixUrlNull(it) ?: return@apmap null + loadExtractor(link, "$mainUrl/", subtitleCallback, callback) + } + return links.isNotEmpty() + } +}