added webflix

This commit is contained in:
Cloudburst 2022-09-25 15:14:42 +02:00
parent f446545188
commit d8ed50157c
5 changed files with 269 additions and 0 deletions

26
WebFlix/build.gradle.kts Normal file
View 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 = "Adds multiple sites using WebFlix. This includes sites in English, Polish, Portuguese and Arabic"
authors = listOf("Cloudburst")
/**
* Status int as the following:
* 0: Down
* 1: Ok
* 2: Slow
* 3: Beta only
* */
status = 1 // will be 3 if unspecified
tvTypes = listOf(
"Movies",
"TvSeries",
"Live"
)
iconUrl = "https://raw.githubusercontent.com/recloudstream/cloudstream-extensions-multilinugal/master/WebFlix/icon.png"
}

BIN
WebFlix/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.lagradost"/>

View File

@ -0,0 +1,222 @@
package com.lagradost
import android.util.Base64
import android.util.Log
import com.lagradost.WebFlixProvider.Companion.toHomePageList
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 com.lagradost.cloudstream3.utils.loadExtractor
import java.net.URLEncoder
class WebFlixProvider(override var lang: String, override var mainUrl: String, override var name: String, override val supportedTypes: Set<TvType>) : MainAPI() {
val magicPath = base64Decode("NEY1QTlDM0Q5QTg2RkE1NEVBQ0VEREQ2MzUxODUvZDUwNmFiZmQtOWZlMi00YjcxLWI5NzktZmVmZjIxYmNhZDEzLw==")
override val hasMainPage = true
override val hasChromecastSupport = true
override suspend fun getMainPage(
page: Int,
request : MainPageRequest
): HomePageResponse? {
val res = tryParseJson<HomeResponse>(app.get("$mainUrl/api/first/$magicPath").text) ?: return null
return HomePageResponse(
res.getHomePageLists(this),
false
)
}
override suspend fun search(query: String): List<SearchResponse>? {
val res = tryParseJson<ApiSearchResponse>(app.get("$mainUrl/api/search/${query.encodeUri()}/$magicPath").text) ?: return null
return res.posters.map { it.toSearchResponse(this) }
}
override suspend fun load(url: String): LoadResponse? {
val data = tryParseJson<Entry>(app.get(url).text) ?: return null
return data.toLoadResponse(this)
}
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val sources = tryParseJson<List<Source>>(data) ?: return false
sources.forEach {
it.load(subtitleCallback, callback)
}
return true
}
private data class ApiSearchResponse(
val posters: List<Entry>
)
private data class HomeResponse(val genres: List<HomeReponseGenre>, val channels: List<Entry>, val slides: List<Entry>) {
fun getHomePageLists(provider: WebFlixProvider): List<HomePageList> {
val lists = mutableListOf<HomePageList>()
if (channels.isNotEmpty()) {
channels.forEach {
if (it.type == null) it.type = "channel"
}
lists.add(channels.toHomePageList("Channels", provider))
}
if (slides.isNotEmpty()) lists.add(slides.toHomePageList("Slides", provider))
lists.addAll(genres.map { it.toHomePageList(provider) })
return lists
}
}
private data class HomeReponseGenre(
val title: String,
val posters: List<Entry>
) {
fun toHomePageList(provider: WebFlixProvider) = posters.toHomePageList(title, provider)
}
data class Source(
val title: String?,
val url: String?,
val quality: String?,
) {
suspend fun load(subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit) {
if (url == null) return;
when (url.split(".").last()) {
"mp4", "m3u8", "mov" -> callback.invoke(
ExtractorLink(
quality ?: "",
title ?: "",
url,
"",
Qualities.Unknown.value,
isM3u8 = (url.endsWith("m3u8"))
))
else -> loadExtractor(url, subtitleCallback, callback)
}
}
}
private data class ApiEpisode(
val id: Int,
val title: String?,
val description: String?,
val sources: List<Source> = emptyList()
) {
fun toEpisode(season: Int, episode: Int) = Episode(
sources.toJson(),
title,
season,
episode,
null,
null,
description
)
}
private data class ApiSeason(
val title: String?,
val episodes: List<ApiEpisode> = emptyList()
) {
fun getEpisodes(season: Int): List<Episode> = episodes.mapIndexed { idx, episode -> episode.toEpisode(season, idx + 1) }
}
data class Entry(
val id: Int,
val title: String,
val label: String?,
val sublabel: String?,
val image: String?,
val description: String?,
var type: String?,
val year: String?,
val imdb: Double?,
val sources: List<Source> = emptyList()
) {
fun getTvType() = when (type) {
"serie" -> TvType.TvSeries
"movie" -> TvType.Movie
"channel", "4" -> TvType.Live
else -> {
Log.d("WebFlix", "other: $type")
TvType.Others
}
}
fun toSearchResponse(provider: WebFlixProvider): SearchResponse {
val entry = this
return when(getTvType()) {
TvType.Movie -> provider.newMovieSearchResponse(
title,
"${provider.mainUrl}/api/movie/by/$id/${provider.magicPath}",
getTvType(),
) {
posterUrl = image
year = entry.year?.toIntOrNull()
}
TvType.TvSeries -> provider.newTvSeriesSearchResponse(
title,
"${provider.mainUrl}/api/series/by/$id/${provider.magicPath}",
TvType.TvSeries
) {
posterUrl = image
//year = entry.year?.toIntOrNull()
}
TvType.Live -> provider.newMovieSearchResponse(
title,
"${provider.mainUrl}/api/channel/by/$id/${provider.magicPath}",
getTvType(),
) {
posterUrl = image
year = entry.year?.toIntOrNull()
}
else -> provider.newMovieSearchResponse(
title,
"${provider.mainUrl}/api/$type/by/$id/${provider.magicPath}",
getTvType(),
) {
posterUrl = image
year = entry.year?.toIntOrNull()
}
}
}
suspend fun toLoadResponse(provider: WebFlixProvider): LoadResponse? {
val entry = this
return when(getTvType()) {
TvType.TvSeries -> {
val res = tryParseJson<List<ApiSeason>>(app.get("${provider.mainUrl}/api/season/by/serie/${id}/${provider.magicPath}").text) ?: return null
provider.newTvSeriesLoadResponse(
title,
"",
TvType.TvSeries,
res.mapIndexed { idx, season -> season.getEpisodes(idx + 1) }
.flatten()
) {
this.posterUrl = entry.image
this.year = entry.year?.toIntOrNull()
this.plot = description
this.rating = if (entry.imdb != null) (entry.imdb*10).toInt() else null
}
}
else -> provider.newMovieLoadResponse(
title,
"",
getTvType(),
sources.toJson()
) {
this.posterUrl = entry.image
this.year = entry.year?.toIntOrNull()
this.plot = description
this.rating = if (entry.imdb != null) (entry.imdb*10).toInt() else null
}
}
}
}
companion object {
fun String.encodeUri() = URLEncoder.encode(this, "utf8")
fun List<Entry>.toHomePageList(name: String, provider: WebFlixProvider) = HomePageList(name, this.map { it.toSearchResponse(provider) })
}
}

View File

@ -0,0 +1,19 @@
package com.lagradost
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
import com.lagradost.cloudstream3.plugins.Plugin
import android.content.Context
import com.lagradost.cloudstream3.TvType
@CloudstreamPlugin
class WebFlixProviderPlugin: Plugin() {
override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(WebFlixProvider("en", "https://dhfilmtv.com", "DHFilmTv", setOf(TvType.Movie, TvType.TvSeries)))
registerMainAPI(WebFlixProvider("pl", "https://app.vodi.cc", "Vodi.cc", setOf(TvType.Movie, TvType.TvSeries)))
registerMainAPI(WebFlixProvider("fr", "http://www.vanflix.cm", "Vanflix", setOf(TvType.Movie, TvType.TvSeries, TvType.Live)))
registerMainAPI(WebFlixProvider("pt-pt", "https://www.brflix.xyz", "BrFlix", setOf(TvType.Movie, TvType.TvSeries, TvType.Live)))
registerMainAPI(WebFlixProvider("ar", "https://ifilm.live", "ifilm.live", setOf(TvType.Movie, TvType.TvSeries)))
}
}