new edit
This commit is contained in:
parent
fee129c1ce
commit
b2ca3da31f
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,17 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class FivemovierulzPlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerExtractorAPI(Sbanh())
|
||||
registerExtractorAPI(Sendcm())
|
||||
registerExtractorAPI(Ncdnstm())
|
||||
registerExtractorAPI(StreamTapeAdblockUser())
|
||||
registerMainAPI(FivemovierulzProvider())
|
||||
}
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.extractors.StreamSB
|
||||
import com.lagradost.cloudstream3.extractors.StreamTape
|
||||
import com.lagradost.cloudstream3.extractors.XStreamCdn
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class FivemovierulzProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://5movierulz.cm"
|
||||
override var name = "5movierulz"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/category/featured/page/" to "Popular Movies",
|
||||
"$mainUrl/category/hollywood-movie-2021/page/" to "English",
|
||||
"$mainUrl/bollywood-movie-free/page/" to "Hindi",
|
||||
"$mainUrl/tamil-movie-free/page/" to "Tamil",
|
||||
"$mainUrl/telugu-movie/page/" to "Telugu",
|
||||
"$mainUrl/malayalam-movie-online/page/" to "Malayalam",
|
||||
"$mainUrl/category/bengali-movie/page/" to "Bengali",
|
||||
"$mainUrl/category/punjabi-movie/page/" to "Punjabi",
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select("#main .cont_display").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title =
|
||||
this.selectFirst("a")?.attr("title")?.trim()?.substringBefore("(") ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
||||
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query").document
|
||||
|
||||
return document.select("#main .cont_display").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
|
||||
val title = document.selectFirst("h2.entry-title")?.text()?.trim()?.substringBefore("(")
|
||||
?: return null
|
||||
val poster = fixUrlNull(document.selectFirst(".entry-content img")?.attr("src"))
|
||||
val tags =
|
||||
document.select("div.entry-content > p:nth-child(5)").text().substringAfter("Genres:")
|
||||
.substringBefore("Country:").split(",").map { it }
|
||||
val yearRegex = Regex("""\d{4}""")
|
||||
val year = yearRegex.find(
|
||||
document.select("h2.entry-title").text()
|
||||
)?.groupValues?.getOrNull(0)?.toIntOrNull()
|
||||
val description = document.select("div.entry-content > p:nth-child(6)").text().trim()
|
||||
val actors =
|
||||
document.select("div.entry-content > p:nth-child(5)").text()
|
||||
.substringAfter("Starring by:")
|
||||
.substringBefore("Genres:").split(",").map { it }
|
||||
|
||||
return newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
addActors(actors)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val sources = ArrayList<String>()
|
||||
app.get(data).document.select(".entry-content p a[target=_blank]")
|
||||
.mapNotNull {
|
||||
if (it.attr("href").startsWith("https://down")) {
|
||||
sources.add(
|
||||
app.get(it.attr("href")).document.select(".entry-content iframe")
|
||||
.attr("src")
|
||||
)
|
||||
} else {
|
||||
sources.add(it.attr("href"))
|
||||
}
|
||||
}
|
||||
sources.forEach { source ->
|
||||
val src = if (source.startsWith("https://stream")) source.replace(
|
||||
"/([a-z])/".toRegex(),
|
||||
"/e/"
|
||||
) else source
|
||||
loadExtractor(
|
||||
src,
|
||||
"$mainUrl/",
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class Sbanh : StreamSB() {
|
||||
override var mainUrl = "https://sbanh.com"
|
||||
}
|
||||
|
||||
class Ncdnstm : XStreamCdn() {
|
||||
override var mainUrl = "https://ncdnstm.xyz"
|
||||
}
|
||||
|
||||
class StreamTapeAdblockUser : StreamTape() {
|
||||
override var mainUrl = "https://streamtapeadblockuser.homes"
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.utils.ExtractorApi
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
|
||||
open class Sendcm: ExtractorApi() {
|
||||
override val name = "Sendcm"
|
||||
override val mainUrl = "https://send.cm"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
||||
val sources = mutableListOf<ExtractorLink>()
|
||||
val url = app.get(url).document.select("source").attr("src")
|
||||
sources.add(
|
||||
ExtractorLink(
|
||||
name = name,
|
||||
source = name,
|
||||
url = url,
|
||||
isM3u8 = false,
|
||||
quality = Qualities.Unknown.value,
|
||||
referer = url
|
||||
)
|
||||
)
|
||||
return sources
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
version = 5
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
description = "Please wait for 10seconds to bypass the ads"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
"Anime",
|
||||
"Cartoon"
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=anime-world.in&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,14 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class AnimeWorldPlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(AnimeWorldProvider())
|
||||
registerExtractorAPI(Vanfem())
|
||||
}
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import android.util.Log
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.extractors.XStreamCdn
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.nicehttp.Requests
|
||||
import com.lagradost.nicehttp.Session
|
||||
import kotlinx.coroutines.delay
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class AnimeWorldProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://anime-world.in"
|
||||
override var name = "AnimeWorld"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries,
|
||||
TvType.Anime,
|
||||
TvType.Cartoon
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/series/page/" to "Series",
|
||||
"$mainUrl/movies/page/" to "Movies",
|
||||
"$mainUrl/category/cartoon/page/" to "Cartoon",
|
||||
"$mainUrl/category/anime/page/" to "Anime",
|
||||
"$mainUrl/category/cartoon-network/page/" to "Cartoon Network",
|
||||
"$mainUrl/category/disney/page/" to "Disney",
|
||||
"$mainUrl/category/marvel-hq/page/" to "Marvel",
|
||||
"$mainUrl/category/hungama-tv/page/" to "Hungama TV",
|
||||
"$mainUrl/category/nickelodeon/page/" to "Nickelodeon",
|
||||
"$mainUrl/category/sonic/page/" to "Sonic",
|
||||
"$mainUrl/category/amazon-prime/page/" to "Amazon Prime",
|
||||
"$mainUrl/category/netflix/page/" to "Netflix",
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst(".entry-title")?.text()?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
||||
val year = this.select(".year").text().trim().toIntOrNull()
|
||||
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
this.year = year
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query").document
|
||||
|
||||
return document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
if (document.select("h2.title").text().contains("Skip Ad")) {
|
||||
val link = document.selectFirst(".glass-button")!!.attr("onclick").substringAfter("'")
|
||||
.substringBefore("'")
|
||||
bypassRockLinks(link)
|
||||
}
|
||||
val title = document.selectFirst(".entry-title")?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.selectFirst(".post-thumbnail img")?.attr("src"))
|
||||
val tags = document.select(".genres a").map { it.text() }
|
||||
val year = document.select(".year").text().trim().toIntOrNull()
|
||||
val tvType = if (document.select(".episodes button > span").isNullOrEmpty()
|
||||
) TvType.Movie else TvType.TvSeries
|
||||
val description = document.selectFirst(".description > p:nth-child(1)")?.text()?.trim()
|
||||
val trailer = fixUrlNull(document.select("iframe").attr("src"))
|
||||
val rating = document.select("span.num").text().toRatingInt()
|
||||
//val actors = document.select("#cast > div:nth-child(4)").map { it.text() }
|
||||
val recommendations = document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
||||
return if (tvType == TvType.TvSeries) {
|
||||
val episodes: MutableList<Episode> = mutableListOf()
|
||||
document.select(".choose-season ul.sub-menu a").mapNotNull { element ->
|
||||
val html = app.post(
|
||||
url = "$mainUrl/wp-admin/admin-ajax.php",
|
||||
data = mapOf(
|
||||
"action" to "action_select_season",
|
||||
"season" to element.attr("data-season"),
|
||||
"post" to element.attr("data-post")
|
||||
),
|
||||
referer = url,
|
||||
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
|
||||
).document
|
||||
|
||||
episodes += html.select("article").mapNotNull {
|
||||
val href = fixUrl(it.select("a").attr("href") ?: return null)
|
||||
val name = it.select("h2").text().trim()
|
||||
val thumbs = it.select("img").attr("src")
|
||||
val season = element.attr("data-season").toInt()
|
||||
val episode = it.select(".num-epi").text().split("x").last().toInt()
|
||||
Episode(
|
||||
href,
|
||||
name,
|
||||
season,
|
||||
episode,
|
||||
thumbs
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
this.rating = rating
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
} else {
|
||||
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
this.rating = rating
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
Log.d("test", data)
|
||||
|
||||
val document = app.get(data).document
|
||||
Log.d("test", document.select("h2.title").text())
|
||||
if (document.select("h2.title").text().contains("Skip Ad")) {
|
||||
val link = document.selectFirst(".glass-button")!!.attr("onclick").substringAfter("'")
|
||||
.substringBefore("'")
|
||||
bypassRockLinks(link)
|
||||
} else {
|
||||
val langPair = document.select(".aa-tbs li").associate {
|
||||
it.select("a").attr("href").replace("#", "") to it.select(".server").text()
|
||||
.split("-")
|
||||
.last().trim()
|
||||
}
|
||||
document.select(".aa-cn div").map { res ->
|
||||
|
||||
loadExtractor(
|
||||
res.select("iframe").attr("data-src"),
|
||||
referer = data,
|
||||
subtitleCallback,
|
||||
) { link ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
link.source,
|
||||
link.name + " " + langPair[res.attr("id")],
|
||||
link.url,
|
||||
link.referer,
|
||||
Qualities.Unknown.value,
|
||||
link.isM3u8,
|
||||
link.headers,
|
||||
link.extractorData
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private suspend fun bypassRockLinks(link: String) {
|
||||
val domain =
|
||||
if (link.contains("rocklinks")) "https://link.techyone.co" else "https://cac.teckypress.in"
|
||||
val baseUrl =
|
||||
if (link.contains("rocklinks")) "$domain/${link.substringAfterLast("/")}?quelle=" else "$domain/${
|
||||
link.substringAfterLast("/")
|
||||
}"
|
||||
val client = Requests().baseClient
|
||||
val session = Session(client)
|
||||
val html = session.get(url = baseUrl, referer = baseUrl)
|
||||
fun encode(input: String): String = java.net.URLEncoder.encode(input, "utf-8")
|
||||
val document = html.document
|
||||
val data = document.select("#go-link input")
|
||||
.mapNotNull { it.attr("name").toString() to encode(it.attr("value").toString()) }
|
||||
.toMap()
|
||||
|
||||
delay(10000L)
|
||||
val response = session.post(
|
||||
url = "$domain/links/go",
|
||||
headers = mapOf(
|
||||
"Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"X-Requested-With" to "XMLHttpRequest",
|
||||
"Accept" to "application/json, text/javascript, ; q=0.01",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
//"Accept-Encoding" to "gzip"
|
||||
),
|
||||
data = data,
|
||||
referer = baseUrl
|
||||
).text
|
||||
val bypassedLink = AppUtils.parseJson<Response>(response).url
|
||||
app.get(bypassedLink).document
|
||||
}
|
||||
|
||||
data class Response(
|
||||
@JsonProperty("url") var url: String
|
||||
)
|
||||
}
|
||||
|
||||
class Vanfem : XStreamCdn() {
|
||||
override val name: String = "Vanfem"
|
||||
override val mainUrl: String = "https://vanfem.com"
|
||||
override var domainUrl: String = "vanfem.com"
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
version = 1
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
// description = "Lorem Ipsum"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=bolly2tolly.desi/&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon" />
|
|
@ -1,15 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import android.content.Context
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
|
||||
@CloudstreamPlugin
|
||||
class Bolly2TollyPlugin : Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(Bolly2TollyProvider())
|
||||
registerExtractorAPI(NeoHD())
|
||||
registerExtractorAPI(NinjaHD())
|
||||
}
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import android.util.Log
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class Bolly2TollyProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://www.bolly2tolly.desi"
|
||||
override var name = "Bolly2Tolly"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/page/" to "Latest ",
|
||||
"$mainUrl/category/english-movies/page/" to "English",
|
||||
"$mainUrl/category/hindi-movies/page/" to "Hindi",
|
||||
"$mainUrl/category/telugu-movies/page/" to "Telugu",
|
||||
"$mainUrl/category/tamil-movies/page/" to "Tamil",
|
||||
"$mainUrl/category/kannada-movies/page/" to "Kannada",
|
||||
"$mainUrl/category/malayalam-movies/page/" to "Malayalam",
|
||||
"$mainUrl/category/bengali-movies/page/" to "Bengali"
|
||||
|
||||
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select("ul.MovieList article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = if (this.selectFirst("img")?.attr("alt").isNullOrEmpty())
|
||||
this.selectFirst("h3")?.text()?.substringBefore("(") else this.selectFirst("img")
|
||||
?.attr("alt")?.trim()
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
||||
|
||||
return newMovieSearchResponse(title ?: return null, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query").document
|
||||
|
||||
return document.select(".result-item").mapNotNull {
|
||||
val title = it.select("SubTitle").text().trim()
|
||||
val href = fixUrl(it.selectFirst(".title a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(it.selectFirst(".thumbnail img")?.attr("src"))
|
||||
val quality = getQualityFromString(it.select("span.quality").text())
|
||||
val tvtype = if (href.contains("tvshows")) TvType.TvSeries else TvType.Movie
|
||||
newMovieSearchResponse(title, href, tvtype) {
|
||||
this.posterUrl = posterUrl
|
||||
this.quality = quality
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
|
||||
val title = document.selectFirst(".SubTitle")?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.selectFirst(".Image img")?.attr("src"))
|
||||
val tags = document.select(".InfoList li:eq(2) a").map { it.text() }
|
||||
val year = document.select("span.Date").text().trim().toIntOrNull()
|
||||
val tvType =
|
||||
if (document.select(".AA-cont").isNullOrEmpty()) TvType.Movie else TvType.TvSeries
|
||||
val description = document.selectFirst(".Description p")?.text()?.trim()
|
||||
//val rating = document.select(".post-ratings strong").last()!!.text().toRatingInt()
|
||||
val actors = document.select(".ListCast a").map { it.text().trim() }
|
||||
val recommendations = document.select(".Wdgt ul.MovieList li").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
||||
return if (tvType == TvType.TvSeries) {
|
||||
val episodes = document.select("tbody tr").mapNotNull {
|
||||
val href = fixUrl(it.select(".MvTbTtl a").attr("href") ?: return null)
|
||||
Log.d("href", href)
|
||||
val name = it.select(".MvTbTtl a").text().trim()
|
||||
val thumbs = "https:" + it.select("img").attr("src")
|
||||
val season = document.select(".AA-Season").attr("data-tab").toInt()
|
||||
val episode = it.select("span.Num").text().toInt()
|
||||
Episode(
|
||||
href,
|
||||
name,
|
||||
season,
|
||||
episode,
|
||||
thumbs
|
||||
)
|
||||
}
|
||||
|
||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
//this.rating = rating
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
}
|
||||
} else {
|
||||
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
//this.rating = rating
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
println(data)
|
||||
val sources = mutableListOf<String>()
|
||||
val document = app.get(data).document
|
||||
sources.add(document.select(".TPlayer iframe").attr("src"))
|
||||
val srcRegex = Regex("""(https.*?)"\s""")
|
||||
srcRegex.find(
|
||||
document.select(".TPlayer").text()
|
||||
)?.groupValues?.map { sources.add(it.replace("#038;", "")) }
|
||||
println(sources)
|
||||
sources.forEach {
|
||||
val source = app.get(it, referer = data).document.select("iframe").attr("src")
|
||||
println(source)
|
||||
loadExtractor(
|
||||
source,
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.base64DecodeArray
|
||||
import com.lagradost.cloudstream3.base64Encode
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import java.security.DigestException
|
||||
import java.security.MessageDigest
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
import javax.crypto.spec.SecretKeySpec
|
||||
|
||||
class NinjaHD : NeoHD() {
|
||||
override var name = "NinjaHD"
|
||||
override var mainUrl = "https://ninjahd.one"
|
||||
}
|
||||
|
||||
open class NeoHD : ExtractorApi() {
|
||||
override val name = "NeoHD"
|
||||
override val mainUrl = "https://neohd.xyz"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
||||
val sources = mutableListOf<ExtractorLink>()
|
||||
val document = app.get(url).text
|
||||
val cryptoRegex = Regex("""var\s*playerConfig\s*=\s*([^;]+)""")
|
||||
val json = cryptoRegex.find(document)?.groupValues?.getOrNull(1).toString()
|
||||
val password = "F1r3b4Ll_GDP~5H".toByteArray()
|
||||
val data1 = parseJson<AesData>(json)
|
||||
val decryptedData =
|
||||
cryptoAESHandler(data1, password, false)?.replace("\\", "")?.substringAfter("\"")
|
||||
?.substringBeforeLast("\"")
|
||||
val apiQuery = parseJson<CryptoResponse>(decryptedData!!).apiQuery
|
||||
val doc = app.get(
|
||||
url = "https://ninjahd.one/api/?$apiQuery&_=${System.currentTimeMillis() * 1000}",
|
||||
headers = mapOf(
|
||||
"X-Requested-With" to "XMLHttpRequest",
|
||||
"Referer" to "https://ninjahd.one/embed/zilnv7x6da1s84"
|
||||
)
|
||||
).text
|
||||
val source = parseJson<VideoUrl>(doc).sources[0].file
|
||||
sources.add(
|
||||
ExtractorLink(
|
||||
name,
|
||||
name,
|
||||
source,
|
||||
"$mainUrl/",
|
||||
Qualities.Unknown.value,
|
||||
headers = mapOf("range" to "bytes=0-")
|
||||
)
|
||||
)
|
||||
return sources
|
||||
}
|
||||
|
||||
private fun GenerateKeyAndIv(
|
||||
password: ByteArray,
|
||||
salt: ByteArray,
|
||||
hashAlgorithm: String = "MD5",
|
||||
keyLength: Int = 32,
|
||||
ivLength: Int = 16,
|
||||
iterations: Int = 1
|
||||
): List<ByteArray>? {
|
||||
|
||||
val md = MessageDigest.getInstance(hashAlgorithm)
|
||||
val digestLength = md.digestLength
|
||||
val targetKeySize = keyLength + ivLength
|
||||
val requiredLength = (targetKeySize + digestLength - 1) / digestLength * digestLength
|
||||
val generatedData = ByteArray(requiredLength)
|
||||
var generatedLength = 0
|
||||
|
||||
try {
|
||||
md.reset()
|
||||
|
||||
while (generatedLength < targetKeySize) {
|
||||
if (generatedLength > 0)
|
||||
md.update(
|
||||
generatedData,
|
||||
generatedLength - digestLength,
|
||||
digestLength
|
||||
)
|
||||
|
||||
md.update(password)
|
||||
md.update(salt, 0, 8)
|
||||
md.digest(generatedData, generatedLength, digestLength)
|
||||
|
||||
for (i in 1 until iterations) {
|
||||
md.update(generatedData, generatedLength, digestLength)
|
||||
md.digest(generatedData, generatedLength, digestLength)
|
||||
}
|
||||
|
||||
generatedLength += digestLength
|
||||
}
|
||||
return listOf(
|
||||
generatedData.copyOfRange(0, keyLength),
|
||||
generatedData.copyOfRange(keyLength, targetKeySize)
|
||||
)
|
||||
} catch (e: DigestException) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.decodeHex(): ByteArray {
|
||||
check(length % 2 == 0) { "Must have an even length" }
|
||||
return chunked(2)
|
||||
.map { it.toInt(16).toByte() }
|
||||
.toByteArray()
|
||||
}
|
||||
|
||||
private fun cryptoAESHandler(
|
||||
data: AesData,
|
||||
pass: ByteArray,
|
||||
encrypt: Boolean = true
|
||||
): String? {
|
||||
val (key, iv) = GenerateKeyAndIv(pass, data.s.decodeHex()) ?: return null
|
||||
val cipher = Cipher.getInstance("AES/CBC/NoPadding")
|
||||
return if (!encrypt) {
|
||||
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
|
||||
String(cipher.doFinal(base64DecodeArray(data.ct)))
|
||||
} else {
|
||||
cipher.init(Cipher.DECRYPT_MODE, SecretKeySpec(key, "AES"), IvParameterSpec(iv))
|
||||
base64Encode(cipher.doFinal(data.ct.toByteArray()))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
data class AesData(
|
||||
@JsonProperty("ct") var ct: String,
|
||||
@JsonProperty("iv") var iv: String,
|
||||
@JsonProperty("s") var s: String
|
||||
)
|
||||
|
||||
data class CryptoResponse(
|
||||
@JsonProperty("apiQuery") var apiQuery: String
|
||||
)
|
||||
|
||||
data class VideoUrl(
|
||||
@JsonProperty("sources") var sources: ArrayList<Sources> = arrayListOf(),
|
||||
)
|
||||
|
||||
data class Sources(
|
||||
@JsonProperty("file") var file: String
|
||||
)
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
version = 2
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
description = "This website support English/Hindi/Kannada/Malayalam/Tamil/Telugu"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=ww1.cinevez.mx&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,15 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class CinevezPlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerExtractorAPI(StreamTapeTo())
|
||||
registerExtractorAPI(SlTube())
|
||||
registerMainAPI(CinevezProvider())
|
||||
}
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.extractors.StreamTape
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class CinevezProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://ww1.cinevez.mx"
|
||||
override var name = "Cinevez"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/featured/page/" to "Popular Movies",
|
||||
"$mainUrl/latest-series/page/" to "Popular Series",
|
||||
"$mainUrl/language/english/page/" to "English",
|
||||
"$mainUrl/language/hindi/page/" to "Hindi",
|
||||
"$mainUrl/language/tamil/page/" to "Tamil",
|
||||
"$mainUrl/language/telugu/page/" to "Telugu",
|
||||
"$mainUrl/language/malayalam/page/" to "Malayalam",
|
||||
"$mainUrl/language/kannada/page/" to "Kannada"
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select(".post-item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst("h2")?.text()?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
||||
val quality = getQualityFromString(this.select("span").text().substringBefore("-"))
|
||||
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
this.quality = quality
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query").document
|
||||
|
||||
return document.select(".post-item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
|
||||
val title = document.selectFirst(".box-title h1")?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.selectFirst(".post-image img")?.attr("src"))
|
||||
val tags = document.select("div:nth-child(3) > p.text-sm a").map { it.text() }
|
||||
val year = document.select("div:nth-child(2) > p.text-sm a").text().toIntOrNull()
|
||||
val description = document.selectFirst("div.text-left > div:nth-child(8)")?.text()
|
||||
?.replace("Story Plot:", "")?.trim()
|
||||
val actors =
|
||||
document.select("div:nth-child(5) > p.text-sm a").map { it.text() }
|
||||
val recommendations = document.select(".box-content .post-item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
val sourceUrl =
|
||||
if (document.select("div:nth-child(3) > div.box-title.border-dark").text().trim()
|
||||
.contains("Seasons")
|
||||
) document.select("div:nth-child(3) > div > div > div > a.rounded")
|
||||
.attr("href") else url
|
||||
return newMovieLoadResponse(title, url, TvType.Movie, sourceUrl) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
this.recommendations = recommendations
|
||||
addActors(actors)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
app.get(data).document.select(".list-episodes a.bg-button")
|
||||
.mapNotNull {
|
||||
if (it.attr("href").contains("send.cm")) {
|
||||
val url = app.get(it.attr("href")).document.select("source").attr("src")
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
url,
|
||||
mainUrl,
|
||||
quality = Qualities.Unknown.value,
|
||||
)
|
||||
)
|
||||
} else {
|
||||
loadExtractor(
|
||||
it.attr("href").replace("/([a-z])/".toRegex(),"/e/"),
|
||||
"$mainUrl/",
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class StreamTapeTo : StreamTape() {
|
||||
override var mainUrl = "https://streamtape.to"
|
||||
}
|
||||
|
||||
class SlTube : StreamTape() {
|
||||
override var mainUrl = "https://sltube.org"
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
version = 1
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "en"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
//description = "This website support English/Hindi/Kannada/Malayalam/Tamil/Telugu live channels and Hindi Old Movies/Malayalam Movies \n For language in Sports: Please check background image[country flag] of the episode"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* Status int as the following:
|
||||
* 0: Down
|
||||
* 1: Ok
|
||||
* 2: Slow
|
||||
* 3: Beta only
|
||||
* */
|
||||
status = 1 // will be 3 if unspecified
|
||||
tvTypes = listOf(
|
||||
"Live"
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=pc9.crichd.com&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon" />
|
|
@ -1,13 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class CricHDPlugin : Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(CricHDProvider())
|
||||
}
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class CricHDProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://pc9.crichd.com"
|
||||
override var name = "CricHD"
|
||||
override val hasMainPage = true
|
||||
override var lang = "en"
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Live
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
val pageSelectors = listOf(
|
||||
Pair("Leagues", ".CSSTableGenerator table tbody tr"),
|
||||
Pair("Channels", "#sidebar-right li"),
|
||||
)
|
||||
val pages = pageSelectors.apmap { (title, selector) ->
|
||||
val list = document.select(selector).mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
HomePageList(title, list)
|
||||
}
|
||||
return HomePageResponse(pages)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
if (this.selectFirst(".mobile-hide")?.text().isNullOrEmpty()) {
|
||||
val title =
|
||||
this.selectFirst("a")?.attr("title")?.substringBefore("Live")?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
||||
return newMovieSearchResponse(title, href, TvType.Live) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
} else {
|
||||
val title = this.selectFirst(".gametitle")?.text()?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("td:nth-child(3) > a")?.attr("href").toString())
|
||||
return newMovieSearchResponse(title, href, TvType.Live)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query").document
|
||||
|
||||
return document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
|
||||
val title = document.selectFirst("h1.heading-separator")?.text()?.trim() ?: return null
|
||||
val episodes = document.select("div > div:nth-child(2) > table > tbody tr")
|
||||
.mapIndexedNotNull { index, it ->
|
||||
val name = it.selectFirst("td")?.text()?.trim()
|
||||
val href = it.select("a").attr("href")
|
||||
Episode(
|
||||
href,
|
||||
name,
|
||||
season = 1,
|
||||
episode = index,
|
||||
)
|
||||
}
|
||||
|
||||
return newTvSeriesLoadResponse(
|
||||
title,
|
||||
url,
|
||||
TvType.TvSeries,
|
||||
episodes.asSequence().filterNot { it.name == "Channel Name" }
|
||||
.filterNot { it.data == "https://www.crichd.com/link.php" }
|
||||
.filter { it.data.isNotEmpty() && it.name!!.isNotEmpty() }.toList()
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
val document = app.get(url = data, referer = "$mainUrl/").document
|
||||
val fidRegex = Regex("""fid="(.*)"; v_w""")
|
||||
document.select("table.mobile-hide > tbody:nth-child(1) a:not([target=_blank])")
|
||||
.mapNotNull {
|
||||
val html = app.get(it.attr("href"), referer = data)
|
||||
val fid = fidRegex.find(html.text)?.groupValues?.getOrNull(1).toString()
|
||||
val script = html.document.select("script").attr("src")
|
||||
val link =
|
||||
app.get(fixUrl(script)).text.substringAfter("src=\"").substringBefore("'+fid")
|
||||
val sourceDoc = app.get("$link$fid", referer = "$link$fid").text
|
||||
val srcRegex = Regex("""[(sourceUrl: ')|(source: ')](https?.*?.)',""")
|
||||
val source =
|
||||
srcRegex.find(sourceDoc)?.groupValues?.getOrNull(1).toString()
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
url = source,
|
||||
referer = link.substringBefore("embed.php"),
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun fixUrl(url: String): String {
|
||||
if (url.isEmpty()) return ""
|
||||
|
||||
if (url.startsWith("//")) {
|
||||
return "http:$url"
|
||||
}
|
||||
if (!url.startsWith("http")) {
|
||||
return "http://$url"
|
||||
}
|
||||
return url
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
version = 1
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
description = "JioTV channels"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* Status int as the following:
|
||||
* 0: Down
|
||||
* 1: Ok
|
||||
* 2: Slow
|
||||
* 3: Beta only
|
||||
* */
|
||||
status = 0 // will be 3 if unspecified
|
||||
tvTypes = listOf(
|
||||
"Live",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=tv.googledrivelinks.com&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,14 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class GDJioTVPlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(GDJioTVProvider())
|
||||
|
||||
}
|
||||
}
|
|
@ -1,81 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class GDJioTVProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://tv.googledrivelinks.com"
|
||||
override var name = "GDJioTV"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = false
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Live,
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int, request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
|
||||
val document = app.get(mainUrl).document
|
||||
val home = document.select(".row .card").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(
|
||||
HomePageList(
|
||||
name = request.name,
|
||||
home,
|
||||
isHorizontalImages = true
|
||||
))
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse {
|
||||
val title = this.selectFirst("p.card-text")?.text()?.trim().toString()
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("data-src"))
|
||||
|
||||
return newMovieSearchResponse(title, title, TvType.Live) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get(mainUrl).document
|
||||
return document.select(".row .card:contains($query)").map {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document =
|
||||
app.get(mainUrl).document.selectFirst(".card:contains(${url.substringAfterLast("/")})")
|
||||
val title = document?.selectFirst("p.card-text")?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.select("img").attr("data-src"))
|
||||
val href = fixUrl("$mainUrl/" + document.selectFirst("a")?.attr("href").toString())
|
||||
return newMovieLoadResponse(title, url, TvType.Live, href) {
|
||||
this.posterUrl = poster
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val document = app.get(data).document
|
||||
val link = "$mainUrl/${document.selectFirst("source")?.attr("src")}"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
version = 3
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "te"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
// description = "Lorem Ipsum"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=ww2.ibomma.cx&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,13 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class IBommaPlugin : Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(IBommaProvider())
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import org.jsoup.nodes.Element
|
||||
import java.net.URLEncoder
|
||||
|
||||
class IBommaProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://ww2.ibomma.cx/telugu-movies"
|
||||
override var name = "IBomma"
|
||||
override val hasMainPage = true
|
||||
override var lang = "te"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie, TvType.TvSeries
|
||||
)
|
||||
|
||||
//pages
|
||||
//"#content > div > article" //Latest
|
||||
//"#content > article:lt(6)" //web series
|
||||
//"#content > article:gt(5):lt(6)" //foreign dub
|
||||
//"#content > article:gt(11)" //addon
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int, request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(mainUrl).document
|
||||
val pageSelectors = listOf(
|
||||
Pair("Latest", "#content > div > article"),
|
||||
Pair("Movies", "#content > article:nth-child(-n+13)"),
|
||||
)
|
||||
val pages = pageSelectors.apmap { (title, selector) ->
|
||||
val list = document.select(selector).mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
HomePageList(title, list)
|
||||
}
|
||||
return HomePageResponse(pages)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst("a")?.text()?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse>? {
|
||||
val searchUrl = app.get(mainUrl).document.select(".mob-search form").attr("action")
|
||||
fun String.encodeUri() = URLEncoder.encode(this, "utf8")
|
||||
val document = app.get("$searchUrl?label=telugu&q=${query.encodeUri()}").document
|
||||
val scriptData = document.select("script").find { it.data().contains("data=") }?.data()
|
||||
?.substringAfter("data= ")?.substringBefore("</script>") ?: return null
|
||||
val response = parseJson<Response>(scriptData)
|
||||
return response.hits?.hitslist?.map {
|
||||
val title = it.source?.title?.substringBefore("Movie") ?: return null
|
||||
val posterUrl = it.source?.imageLink ?: return null
|
||||
val href = it.source?.location ?: return null
|
||||
newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
|
||||
val document = app.get(url).document
|
||||
val title = document.selectFirst(".entry-title-movie")?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.selectFirst(".single-poster img")?.attr("src"))
|
||||
val year = document.select(".entry-tags-movies span").text().trim().toIntOrNull()
|
||||
val tvType =
|
||||
if (document.select("#eplist").isNullOrEmpty()) TvType.Movie else TvType.TvSeries
|
||||
val description =
|
||||
document.selectFirst(".additional-info")?.text()?.trim()!!.replace("Synopsis: ", "")
|
||||
val trailer = fixUrlNull(document.select(".button-trailer a").attr("src"))
|
||||
//val rating = document.select("div.gmr-meta-rating > span:nth-child(3)").text().toRatingInt()
|
||||
val actors =
|
||||
document.select("div.clearfix.content-moviedata > div:nth-child(7) a").map { it.text() }
|
||||
|
||||
return if (tvType == TvType.TvSeries) {
|
||||
val episodeUrls = getUrls(url) ?: return null
|
||||
val episodes = document.select("#eplist tr").mapNotNull { res ->
|
||||
val name = res.select("b").text().trim()
|
||||
//val season = name.substringAfter("S").substringBefore(' ').toInt()
|
||||
val episode = res.select("button").text().filter { it.isDigit() }.toInt()
|
||||
val href = episodeUrls[episode]
|
||||
Episode(
|
||||
data = href, name = name, episode = episode
|
||||
)
|
||||
}
|
||||
|
||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
rating
|
||||
addActors(actors)
|
||||
addTrailer(trailer)
|
||||
}
|
||||
} else {
|
||||
return newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
//this.tags = tags
|
||||
rating
|
||||
addActors(actors)
|
||||
addTrailer(trailer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
val urls: List<String> = if (data.startsWith(mainUrl.substringBeforeLast("/"))) {
|
||||
app.get(data).document.selectFirst("#main > script:nth-child(6)")?.data()
|
||||
?.substringAfter("const urls = [")?.substringBefore("]")?.trim()
|
||||
?.replace(",'',", "")?.split(",")?.map { it -> it.trim() } ?: return false
|
||||
} else {
|
||||
listOf(data)
|
||||
}
|
||||
urls.forEach { url ->
|
||||
val domainUrl = url.substringAfter("'").substringBefore("/player")
|
||||
val document = app.get(
|
||||
url = url.replace("'", ""), referer = mainUrl.substringBeforeLast("/")
|
||||
).document
|
||||
document.select("body script").mapNotNull {
|
||||
val srcRegex = Regex("""(file:")(https?.*?\.mp4)""")
|
||||
val source =
|
||||
srcRegex.find(it.select("script").toString())?.groupValues?.getOrNull(2)
|
||||
?.toString()
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
source.toString(),
|
||||
referer = domainUrl,
|
||||
quality = Qualities.Unknown.value,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private suspend fun getUrls(url: String): List<String>? {
|
||||
|
||||
return app.get(url).document.selectFirst("#ib-4-f > script:nth-child(4)")?.data()
|
||||
?.substringAfter("const urls = [")?.substringBefore("]")?.trim()?.replace(",'',", "")
|
||||
?.split(",")?.toList()
|
||||
}
|
||||
|
||||
data class Response(
|
||||
@JsonProperty("hits") var hits: Hits? = Hits()
|
||||
)
|
||||
|
||||
data class Hits(
|
||||
@JsonProperty("hits") var hitslist: ArrayList<HitsList> = arrayListOf()
|
||||
)
|
||||
|
||||
data class HitsList(
|
||||
@JsonProperty("_source") var source: Source? = Source()
|
||||
)
|
||||
|
||||
data class Source(
|
||||
@JsonProperty("location") var location: String? = null,
|
||||
@JsonProperty("title") var title: String? = null,
|
||||
@JsonProperty("image_link") var imageLink: String? = null,
|
||||
)
|
||||
}
|
|
@ -12,7 +12,7 @@ import org.jsoup.nodes.Element
|
|||
import kotlin.math.floor
|
||||
|
||||
class MHDTVProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://mhdtvworld.xyz"
|
||||
override var mainUrl = "https://mhdtvworld.me"
|
||||
override var name = "MHDTVWorld"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
version = 1
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
//description = "This website support English/Hindi/Kannada/Malayalam/Tamil/Telugu"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
"Anime"
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=moviesmod.net&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon" />
|
|
@ -1,13 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import android.content.Context
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
|
||||
@CloudstreamPlugin
|
||||
class MoviesModPlugin : Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(MoviesModProvider())
|
||||
}
|
||||
}
|
|
@ -1,267 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class MoviesModProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://moviesmod.net"
|
||||
override var name = "MoviesMod"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries,
|
||||
TvType.Anime
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/latest-released/page/" to "Popular Movies",
|
||||
"$mainUrl/movies/adult-movies/page/" to "Adult Movies",
|
||||
"$mainUrl/tv-series/page/" to "Popular Series",
|
||||
"$mainUrl/k-drama/page/" to "K-Drama",
|
||||
"$mainUrl/tv-series/hindi-tv-show/" to "Hindi Series",
|
||||
"$mainUrl/tv-series/english-tv-shows/page/" to "English Series",
|
||||
"$mainUrl/french-web-series/page/" to "French Series",
|
||||
"$mainUrl/spanish-series/page/" to "Spanish",
|
||||
"$mainUrl/anime/page/" to "Anime"
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst("h2")?.text()?.replace("""(\(.*${'$'})""".toRegex(), "")
|
||||
?.replace("Download", "")?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(getImageSrc(this.selectFirst("img")!!))
|
||||
val quality = getQualityFromString(title)
|
||||
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
this.quality = quality
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query").document
|
||||
|
||||
return document.select(".post-item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
val title =
|
||||
document.selectFirst(".thecontent li")?.text()?.trim()?.replace("Full Name: ", "")
|
||||
?: return null
|
||||
val year = """\((\d{4})""".toRegex()
|
||||
.find(document.select(".entry-title").text())?.groupValues?.get(1)
|
||||
?.toIntOrNull()
|
||||
val description = document.selectFirst(".thecontent > p:nth-child(8)")?.text()?.trim()
|
||||
val tvType = if (url.contains("season")) TvType.TvSeries else TvType.Movie
|
||||
val href1 =
|
||||
if (tvType == TvType.Movie) document.select("h4:contains(1080p), h4:contains(720p)") else document.select(
|
||||
"h3:contains(1080p):contains(S0),h3:contains(1080p):contains(Season), h3:contains(720p):contains(S0),h3:contains(720p):contains(Season)"
|
||||
)
|
||||
val episodeslist = mutableMapOf<Int, MutableList<String>>()
|
||||
var num = 0
|
||||
val episodeUrls = mutableMapOf<Int, MutableList<String>>()
|
||||
|
||||
val movieLinks = mutableListOf<String>()
|
||||
if (tvType == TvType.TvSeries) {
|
||||
href1.associate {
|
||||
it.text() to it.nextElementSibling()?.firstChild()?.attr("href")
|
||||
}.filterValues { it != null }
|
||||
.filterValues { it!!.contains("https://episodes.modlinks.xyz") }.map { (k, v) ->
|
||||
val s = """S(\d+)|.eason\s(\d+)""".toRegex().find(k)?.groupValues?.get(0)
|
||||
?.filter { it.isDigit() }?.toInt()!!
|
||||
|
||||
if (num == s) episodeUrls[s]?.plusAssign(v!!)
|
||||
else {
|
||||
num = s
|
||||
episodeUrls[s] = mutableListOf(v!!)
|
||||
}
|
||||
}
|
||||
val episodes = mutableListOf<Episode>()
|
||||
episodeUrls.forEach { (season, urls) ->
|
||||
var count = 0
|
||||
urls.forEach { url ->
|
||||
app.get(url).document.select("h3").mapNotNull { res ->
|
||||
val episode = res.select("strong").text().filter { it.isDigit() }.toInt()
|
||||
val href = res.select("a").attr("href")
|
||||
if (count == season) episodeslist[episode]?.plusAssign(href) else {
|
||||
episodeslist[episode] = mutableListOf(href)
|
||||
}
|
||||
}
|
||||
count = season
|
||||
}
|
||||
episodeslist.forEach { (e, u) ->
|
||||
episodes += Episode(
|
||||
data = u.toString(),
|
||||
episode = e,
|
||||
season = season
|
||||
)
|
||||
}
|
||||
}
|
||||
return newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.year = year
|
||||
this.plot = description
|
||||
}
|
||||
|
||||
} else {
|
||||
href1.associate {
|
||||
it.text() to it.nextElementSibling()?.firstChild()?.attr("href")
|
||||
}.filterValues { it != null }
|
||||
.filterValues { it!!.contains("modlinks.xyz") }.map { (k, v) ->
|
||||
val s =
|
||||
"""(1080)""".toRegex().find(k)?.groupValues?.get(0)?.filter { it.isDigit() }
|
||||
?.toInt()!!
|
||||
if (num == s) episodeUrls[s]?.plusAssign(v!!)
|
||||
else {
|
||||
num = s
|
||||
episodeUrls[s] = mutableListOf(v!!)
|
||||
}
|
||||
}
|
||||
episodeUrls[1080]?.map { u ->
|
||||
movieLinks += app.get(u).document.select("a:contains(Fast Server),a:contains(Google Drive)")
|
||||
.mapNotNull { it.attr("href") }
|
||||
}
|
||||
return newMovieLoadResponse(title, url, TvType.Movie, movieLinks) {
|
||||
//this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
data.splitToSequence(",").toList().forEach {
|
||||
val url = it.replace("\"", "").replace("[", "").replace("]", "")
|
||||
val source =
|
||||
if (it.contains("https://href.li/?")) driveHub(bypassHrefli(url)!!) else driveHub(
|
||||
url
|
||||
)
|
||||
if (source.contains("404")) return@forEach else
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
source,
|
||||
"",
|
||||
quality = Qualities.P1080.value,
|
||||
)
|
||||
)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private suspend fun bypassHrefli(url: String): String? {
|
||||
val direct = url.removePrefix("https://href.li/?")
|
||||
|
||||
val res = app.get(direct).document
|
||||
val formLink = res.select("form#landing").attr("action")
|
||||
val wpHttp = res.select("input[name=_wp_http]").attr("value")
|
||||
|
||||
val res2 = app.post(formLink, data = mapOf("_wp_http" to wpHttp)).document
|
||||
val formLink2 = res2.select("form#landing").attr("action")
|
||||
val wpHttp2 = res2.select("input[name=_wp_http2]").attr("value")
|
||||
val token = res2.select("input[name=token]").attr("value")
|
||||
|
||||
val res3 = app.post(
|
||||
formLink2, data = mapOf(
|
||||
"_wp_http2" to wpHttp2, "token" to token
|
||||
)
|
||||
).document
|
||||
|
||||
val script = res3.selectFirst("script:containsData(verify_button)")?.data()
|
||||
val directLink = script?.substringAfter("\"href\",\"")?.substringBefore("\")")
|
||||
val matchCookies =
|
||||
Regex("sumitbot_\\('(\\S+?)',\n|.?'(\\S+?)',").findAll(script ?: return null).map {
|
||||
it.groupValues[1] to it.groupValues[2]
|
||||
}.toList()
|
||||
|
||||
val cookeName = matchCookies.firstOrNull()?.second ?: return null
|
||||
val cookeValue = matchCookies.lastOrNull()?.second ?: return null
|
||||
|
||||
val cookies = mapOf(
|
||||
cookeName to cookeValue
|
||||
)
|
||||
return app.get(
|
||||
directLink ?: return null,
|
||||
cookies = cookies
|
||||
).document.selectFirst("meta[http-equiv=refresh]")?.attr("content")?.substringAfter("url=")
|
||||
}
|
||||
|
||||
private suspend fun driveHub(url: String): String {
|
||||
val domain =
|
||||
if (url.startsWith("https://drivehub.in")) "https://drivehub.in" else "http://driveroot.in"
|
||||
val path =
|
||||
app.get(url, allowRedirects = true).text.substringAfter("/").substringBefore("\"")
|
||||
if (path.contains("404")) return path
|
||||
val html = app.get("$domain/$path")
|
||||
val cookies = html.cookies
|
||||
val key = """key",\s+"(.*?)"""".toRegex().find(
|
||||
html.document.select("body > script:nth-child(8)").toString()
|
||||
)?.groupValues?.get(1)!!
|
||||
val fileId = html.document.select("div.card-body > div:nth-child(2) > a").attr("href")
|
||||
.substringAfterLast("/")
|
||||
val link = app.post(
|
||||
url = "$domain/file/${fileId}",
|
||||
cookies = cookies,
|
||||
data = mapOf(
|
||||
"action" to "direct",
|
||||
"key" to key,
|
||||
),
|
||||
headers = mapOf(
|
||||
"Content-Type" to "multipart/form-data; boundary=----",
|
||||
"x-token" to domain.substringAfter("//")
|
||||
),
|
||||
referer = "$domain/file/${fileId}"
|
||||
).parsed<DriveHub>().url
|
||||
return """worker_link\s=\s'(.*mkv)""".toRegex().find(
|
||||
app.get(link).document.select("body > script:nth-child(7)").toString()
|
||||
)?.groupValues?.get(1).toString()
|
||||
}
|
||||
|
||||
private fun getImageSrc(tag: Element): String {
|
||||
var image = ""
|
||||
val src = tag.attr("src")
|
||||
val lazySrc = tag.attr("data-pagespeed-lazy-src")
|
||||
val highResSrc = tag.attr("data-pagespeed-high-res-src")
|
||||
if (!src.isNullOrEmpty() and !src.startsWith("data") and !src.contains(".gif")) {
|
||||
image = tag.attr("src")
|
||||
} else if (!lazySrc.isNullOrEmpty() and !lazySrc.startsWith("data") and !lazySrc.contains(".gif")) {
|
||||
image = tag.attr("data-pagespeed-lazy-src")
|
||||
} else if (!highResSrc.isNullOrEmpty() and !highResSrc.startsWith("data") and !highResSrc.contains(
|
||||
".gif"
|
||||
)
|
||||
) {
|
||||
image = tag.attr("data-pagespeed-high-res-src")
|
||||
}
|
||||
return image
|
||||
}
|
||||
|
||||
data class DriveHub(
|
||||
@JsonProperty("url") var url: String
|
||||
|
||||
)
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
version = 2
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
description = "JioTV Plus channels"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* Status int as the following:
|
||||
* 0: Down
|
||||
* 1: Ok
|
||||
* 2: Slow
|
||||
* 3: Beta only
|
||||
* */
|
||||
status = 0 // will be 3 if unspecified
|
||||
tvTypes = listOf(
|
||||
"Live",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=nayeemparvez.chadasaniya.cf&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,14 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class NPJioTVPlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(NPJioTVProvider())
|
||||
|
||||
}
|
||||
}
|
|
@ -1,103 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
|
||||
class NPJioTVProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://nayeemparvez.chadasaniya.ml"
|
||||
override var name = "NPJioTV+"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = false
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Live,
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val categories = listOf(
|
||||
"Sports",
|
||||
"Entertainment",
|
||||
"Movies",
|
||||
"News",
|
||||
"Music",
|
||||
"Kids",
|
||||
"Infotainment",
|
||||
"Lifestyle",
|
||||
"Business",
|
||||
"Devotional",
|
||||
"Educational",
|
||||
"JioDarshan",
|
||||
"Shopping",
|
||||
)
|
||||
val items = ArrayList<HomePageList>()
|
||||
val document = app.get(mainUrl).document
|
||||
categories.forEach { cat ->
|
||||
val results: MutableList<SearchResponse> = mutableListOf()
|
||||
document.select(".card-parent .card:contains($cat)").mapNotNull {
|
||||
val title = it.selectFirst("h5")?.text()?.trim() ?: return@mapNotNull
|
||||
val posterUrl = fixUrlNull(it.selectFirst("img")?.attr("data-src"))
|
||||
results.add(
|
||||
newMovieSearchResponse(title, title, TvType.Live) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
)
|
||||
}
|
||||
items.add(
|
||||
HomePageList(
|
||||
capitalizeString(cat),
|
||||
results,
|
||||
isHorizontalImages = true
|
||||
)
|
||||
)
|
||||
}
|
||||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get(mainUrl).document
|
||||
val elements = document.select(".card-parent .card h5:contains($query)").map { it.parent()
|
||||
?.parent() }
|
||||
return elements.map {
|
||||
val title = it?.selectFirst("h5")?.text()?.trim().toString()
|
||||
val posterUrl = fixUrlNull(it?.selectFirst("img")?.attr("data-src"))
|
||||
newMovieSearchResponse(title, title, TvType.Live) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val document = app.get(mainUrl).document.selectFirst(".card:contains(${url.substringAfterLast("/")})")
|
||||
val title = url.substringAfterLast("/")
|
||||
val poster = fixUrlNull(document?.select("img")?.attr("data-src"))
|
||||
val href = fixUrl("$mainUrl/" + document?.selectFirst("a")?.attr("href").toString())
|
||||
return newMovieLoadResponse(title, url, TvType.Live, href) {
|
||||
this.posterUrl = poster
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val document = app.get(data).document
|
||||
val link = "$mainUrl/${document.selectFirst("source")?.attr("src")}"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
version = 1
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "en"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
// description = "Lorem Ipsum"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
"AsianDrama"
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=nollyverse.com&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,13 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class NollyVersePlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(NollyVerseProvider())
|
||||
}
|
||||
}
|
|
@ -1,212 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class NollyVerseProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://www.nollyverse.com"
|
||||
override var name = "NollyVerse"
|
||||
override val hasMainPage = true
|
||||
override var lang = "en"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries,
|
||||
TvType.AsianDrama
|
||||
)
|
||||
|
||||
private fun serializeData(element: Element): List<NollyVerseLink> {
|
||||
|
||||
val parsed = element.select("td").mapNotNull {
|
||||
try {
|
||||
val name = if (element.select("tr > td:eq(0)").text()
|
||||
.contains("Episode", ignoreCase = true)
|
||||
) it.text()
|
||||
else it.select("a").text()
|
||||
val url = it.select("a").attr("href")
|
||||
NollyVerseLink(name, url)
|
||||
} catch (e: Exception) {
|
||||
NollyVerseLink("", "")
|
||||
}
|
||||
}.filter { it.link != "" && it.name != "" }
|
||||
return parsed.reversed()
|
||||
}
|
||||
|
||||
data class NollyVerseLink(
|
||||
@JsonProperty("name") val name: String,
|
||||
@JsonProperty("url") val link: String
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/category/latest-movies/page/" to "Latest Movies",
|
||||
"$mainUrl/category/new-series/page/" to "Latest Series",
|
||||
"$mainUrl/category/popular-movies/page/" to "Popular Movies",
|
||||
"$mainUrl/category/korean-movies/page/" to "Korean Movies",
|
||||
"$mainUrl/category/korean-series/page/" to "Korean Series"
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val selector = if (request.data.contains("korean")) {
|
||||
".col-md-8 .post"
|
||||
} else if (request.data.contains("popular")) {
|
||||
".col-md-8 .post"
|
||||
} else {
|
||||
".post-row"
|
||||
}
|
||||
val home = document.select(selector).mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(
|
||||
list = HomePageList(
|
||||
name = request.name,
|
||||
list = home,
|
||||
isHorizontalImages = true
|
||||
),
|
||||
hasNext = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst(".post-title a")?.text()?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst(".post-img")?.attr("href").toString())
|
||||
val posterUrl = if (fixUrlNull(
|
||||
this.selectFirst(".post-img img")?.attr("src")
|
||||
)?.contains("blank") == true
|
||||
) fixUrlNull(
|
||||
this.selectFirst(".post-img img")
|
||||
?.attr("data-src")
|
||||
) else fixUrlNull(this.selectFirst(".post-img img")?.attr("src"))
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.post(
|
||||
url = "$mainUrl/livesearch.php",
|
||||
headers = mapOf(
|
||||
"X-Requested-With" to "XMLHttpRequest",
|
||||
"Content-Type" to "application/x-www-form-urlencoded; charset=UTF-8"
|
||||
),
|
||||
data = mapOf("name" to query)
|
||||
).document
|
||||
return document.select("a").mapNotNull {
|
||||
val title = it.text().trim()
|
||||
val href = fixUrl(it.attr("href").toString())
|
||||
val posterUrl =
|
||||
fixUrlNull("https://i.ibb.co/fdnLwRf/istockphoto-1071359118-612x612.jpg")
|
||||
val tvtype = if (href.contains("serie")) TvType.TvSeries else TvType.Movie
|
||||
newMovieSearchResponse(title, href, tvtype) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
val title = document.select("ol li").last()?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.selectFirst("meta[itemprop=image]")?.attr("content"))
|
||||
val tags =
|
||||
document.select("p:contains(Genre:)").text().substringAfter(" ").split(",").map { it }
|
||||
val year = Regex("([0-9]{4}?)").find(
|
||||
document.select("p:contains(Release Date:)").text().toString()
|
||||
)?.groupValues?.get(1)?.toIntOrNull()
|
||||
val tvType = if (document.select("table")
|
||||
.isNullOrEmpty()
|
||||
) TvType.Movie else TvType.TvSeries
|
||||
val description = document.selectFirst(".blockquote > small")?.text()?.trim()
|
||||
val trailer = fixUrlNull(
|
||||
"https://www.youtube.com/embed/" + document.selectFirst(".youtube")?.attr("data-embed")
|
||||
)
|
||||
val actors =
|
||||
document.select("p:contains(Stars:)").text().substringAfter(": ").split(",").map { it }
|
||||
val recommendations = document.select(".galery-widget ul a").mapNotNull {
|
||||
val title =
|
||||
document.selectFirst("img")?.attr("alt")?.substringBefore("-") ?: return null
|
||||
val href = fixUrl(document.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(document.selectFirst("img")?.attr("src"))
|
||||
newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
return if (tvType == TvType.TvSeries) {
|
||||
val seasons = document.select("tr a.btn-sm").mapNotNull { it.attr("href") }
|
||||
val episodes = ArrayList<Episode>()
|
||||
for (s in seasons) {
|
||||
val document = app.get(s).document
|
||||
document.select("tbody tr").mapNotNull {
|
||||
val season = s.substringAfter("-").toIntOrNull()
|
||||
val links = it
|
||||
val data = serializeData(links)
|
||||
episodes.add(newEpisode(data) {
|
||||
this.season = season
|
||||
this.episode = episode
|
||||
})
|
||||
}
|
||||
}
|
||||
episodes.reverse()
|
||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
this.rating = rating
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
} else {
|
||||
val doc = app.get(document.select(".section-row .row a").attr("href")).document
|
||||
val serialize =
|
||||
doc.selectFirst("tbody") ?: throw ErrorLoadingException("No links found")
|
||||
newMovieLoadResponse(title, url, TvType.Movie, serializeData(serialize)) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
val links = parseJson<List<NollyVerseLink>>(data)
|
||||
for (link in links) {
|
||||
val parsedLink = if (link.link.contains("anonfiles.com")) {
|
||||
app.get(link.link).document.selectFirst("#download-url")?.attr("href")
|
||||
} else {
|
||||
link.link
|
||||
} ?: return false
|
||||
val urlName = Regex("([0-9]+p)").find(parsedLink)?.groupValues?.get(1).toString()
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
urlName,
|
||||
parsedLink,
|
||||
"",
|
||||
getQualityFromName(parsedLink),
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
version = 1
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
// description = "Lorem Ipsum"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=111.90.159.132&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,13 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class OnlineMoviesHindiPlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(OnlineMoviesHindiProvider())
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
|
||||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class OnlineMoviesHindiProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://111.90.159.132"
|
||||
override var name = "Online Movies Hindi"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/year/2022/page/" to "Latest Movies",
|
||||
"$mainUrl/best-rating/page/" to "Popular Movies",
|
||||
"$mainUrl/hollywood-movies/page/" to "Hollywood Movies",
|
||||
"$mainUrl/bollywood-movies/page/" to "Bollywood Movies",
|
||||
"$mainUrl/tv-show/page/" to "TV Shows"
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst("p.entry-title")?.text()?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("article img")?.attr("src"))
|
||||
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query&post_type%5B%5D=post&post_type%5B%5D=tv").document
|
||||
|
||||
return document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
|
||||
val title = document.selectFirst("h2.entry-title")?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.selectFirst("div.gmr-movie-data img")?.attr("src"))
|
||||
val year = document.select("div.gmr-moviedata time").text().trim().split(" ").last()
|
||||
.toIntOrNull()
|
||||
val tvType = if (document.selectFirst("div.gmr-listseries a")?.text()
|
||||
?.contains(Regex("(?i)(Eps\\s?[0-9]+)|(episode\\s?[0-9]+)")) == true
|
||||
) TvType.TvSeries else TvType.Movie
|
||||
val description = document.selectFirst("div.entry-content p")?.text()?.trim()
|
||||
val trailer = fixUrlNull(document.select("iframe").attr("src"))
|
||||
val rating = document.select("div.gmr-meta-rating > span:nth-child(3)").text().toRatingInt()
|
||||
val actors = document.select("div.clearfix.content-moviedata > div:nth-child(7) a").map { it.text() }
|
||||
val recommendations = document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
||||
return if (tvType == TvType.TvSeries) {
|
||||
val episodes = document.select("div.gmr-listseries a").mapNotNull {
|
||||
val href = fixUrl(it.attr("href")?: return null)
|
||||
val name = it.text()?.trim()?: return null
|
||||
val season = name.substringAfter("S").substringBefore(' ').toInt() ?: return null
|
||||
val episode = name.substringAfterLast("Eps").toInt()?: return null
|
||||
Episode(
|
||||
href,
|
||||
name,
|
||||
season,
|
||||
episode
|
||||
)
|
||||
}
|
||||
|
||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.rating = rating
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
} else {
|
||||
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
//this.tags = tags
|
||||
this.rating = rating
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
val document = app.get(data).document
|
||||
document.select("video source").map { res ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
res.attr("src") ,
|
||||
referer = data,
|
||||
quality = Qualities.Unknown.value,
|
||||
//headers = mapOf("Range" to "bytes=0-"),
|
||||
)
|
||||
)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
version = 6
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
// description = "Lorem Ipsum"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=prmovies.bio&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,13 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class PrmoviesPlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(PrmoviesProvider())
|
||||
}
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
// https://github.com/hexated/cloudstream-extensions-hexated/blob/master/YomoviesProvider/src/main/kotlin/com/hexated/YomoviesProvider.kt
|
||||
|
||||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class PrmoviesProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://prmovies.bio"
|
||||
override var name = "Prmovies"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/most-favorites/page/" to "Most Viewed",
|
||||
"$mainUrl/director/netflix/page/" to "Netflix",
|
||||
"$mainUrl/director/amazon-prime/page/" to "Amazon Prime",
|
||||
"$mainUrl/director/altbalaji/page/" to "Alt Balaji",
|
||||
"$mainUrl/director/zee5/page/" to "Zee5",
|
||||
"$mainUrl/director/voot-originals/page/" to "Voot Originals",
|
||||
"$mainUrl/director/sonyliv-original/page/" to "Sonyliv Originals",
|
||||
"$mainUrl/director/hotstar/page/" to "Hotstar",
|
||||
"$mainUrl/director/viu-originals/page/" to "Viu Originals",
|
||||
"$mainUrl/director/discovery/page/" to "Discovery"
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = if (page == 1) {
|
||||
app.get(request.data.removeSuffix("page/")).document
|
||||
} else {
|
||||
app.get(request.data + page).document
|
||||
}
|
||||
val home = document.select("div.ml-item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst("h2")?.text()?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("data-original"))
|
||||
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query").document
|
||||
|
||||
return document.select("div.ml-item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
|
||||
val title = document.selectFirst("div.mvic-desc h3")?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.selectFirst("div.thumb.mvic-thumb img")?.attr("src"))
|
||||
val tags = document.select("div.mvici-left p:nth-child(1) a").map { it.text() }
|
||||
val year = document.select("div.mvici-right p:nth-child(3) a").text().trim()
|
||||
.toIntOrNull()
|
||||
val tvType = if (document.selectFirst("div.les-content")
|
||||
?.select("a")?.size!! > 1 || document.selectFirst("ul.idTabs li strong")?.text()
|
||||
?.contains(Regex("(?i)(EP\\s?[0-9]+)|(episode\\s?[0-9]+)")) == true
|
||||
) TvType.TvSeries else TvType.Movie
|
||||
val description = document.selectFirst("p.f-desc")?.text()?.trim()
|
||||
val trailer = fixUrlNull(document.select("iframe#iframe-trailer").attr("src"))
|
||||
val rating = document.select("div.mvici-right > div.imdb_r span").text().toRatingInt()
|
||||
val actors = document.select("div.mvici-left p:nth-child(3) a").map { it.text() }
|
||||
val recommendations = document.select("div.ml-item").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
||||
return if (tvType == TvType.TvSeries) {
|
||||
val episodes = if (document.selectFirst("div.les-title strong")?.text().toString()
|
||||
.contains(Regex("(?i)EP\\s?[0-9]+|Episode\\s?[0-9]+"))
|
||||
) {
|
||||
document.select("ul.idTabs li").map {
|
||||
val id = it.select("a").attr("href")
|
||||
Episode(
|
||||
data = fixUrl(document.select("div$id iframe").attr("src")),
|
||||
name = it.select("strong").text().replace("Server Ep", "Episode")
|
||||
)
|
||||
}
|
||||
} else {
|
||||
document.select("div.les-content a").map {
|
||||
Episode(
|
||||
data = it.attr("href"),
|
||||
name = it.text().replace("Server Ep", "Episode").trim(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
this.rating = rating
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
} else {
|
||||
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
this.rating = rating
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
if (data.startsWith(mainUrl)) {
|
||||
app.get(data).document.select("div.movieplay iframe").map { fixUrl(it.attr("src")) }
|
||||
.apmap { source ->
|
||||
safeApiCall {
|
||||
when {
|
||||
source.startsWith("https://membed.net") -> app.get(
|
||||
source,
|
||||
referer = "$mainUrl/"
|
||||
).document.select("ul.list-server-items li")
|
||||
.apmap {
|
||||
loadExtractor(
|
||||
it.attr("data-video").substringBefore("=https://msubload"),
|
||||
"$mainUrl/",
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
}
|
||||
else -> loadExtractor(source, "$mainUrl/", subtitleCallback, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
loadExtractor(data, "$mainUrl/", subtitleCallback, callback)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
version = 2
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
description = "This extension provide live channels from Sonyliv, Voot and Jiotv"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* Status int as the following:
|
||||
* 0: Down
|
||||
* 1: Ok
|
||||
* 2: Slow
|
||||
* 3: Beta only
|
||||
* */
|
||||
status = 0 // will be 3 if unspecified
|
||||
tvTypes = listOf(
|
||||
"Live",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=snehiptv.netlify.app&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,13 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class SnehIPTVPlugin : Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(SnehIPTVProvider())
|
||||
}
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
|
||||
class SnehIPTVProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://snehiptv.netlify.app"
|
||||
override var name = "SnehIPTV"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = false
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Live
|
||||
)
|
||||
|
||||
data class IPTV(
|
||||
@JsonProperty("id") var id: String? = null,
|
||||
@JsonProperty("tvgLogo") var tvgLogo: String? = null,
|
||||
@JsonProperty("title") var title: String? = null,
|
||||
@JsonProperty("url") var url: String? = null,
|
||||
@JsonProperty("url1") var url1: String? = null
|
||||
)
|
||||
|
||||
private suspend fun getScriptData(url: String): String {
|
||||
val html = app.get(url).document
|
||||
val script = html.select("script").last()?.attr("src")
|
||||
val doc = app.get("$mainUrl$script").text
|
||||
return doc.substringAfter("JSON.parse('").substringBefore("')},:")
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int, request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
|
||||
val categories = listOf(
|
||||
"dplus",
|
||||
"hungama",
|
||||
"sonyliv",
|
||||
"voot",
|
||||
"sunxt",
|
||||
"sports",
|
||||
"entertainment",
|
||||
"movies",
|
||||
"news",
|
||||
"music",
|
||||
"kids",
|
||||
"infotainment",
|
||||
"lifestyle",
|
||||
"business",
|
||||
"educational",
|
||||
"devotional"
|
||||
|
||||
)
|
||||
val items = ArrayList<HomePageList>()
|
||||
val scriptData = getScriptData(mainUrl)
|
||||
val response = parseJson<List<IPTV>>(scriptData)
|
||||
categories.forEach { cat ->
|
||||
val query = if (cat == "hungama") "hgmtv" else cat
|
||||
val results: MutableList<SearchResponse> = mutableListOf()
|
||||
val filtered = response.filter { it.title?.lowercase()?.contains(query) == true }
|
||||
filtered.forEach {
|
||||
val title = it.title?.replace(regex = "\\s\\[[A-Za-z]+]$".toRegex(), "").toString()
|
||||
val posterUrl = it.tvgLogo.toString()
|
||||
results.add(
|
||||
newMovieSearchResponse(title, title, TvType.Live) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
)
|
||||
}
|
||||
items.add(
|
||||
HomePageList(
|
||||
capitalizeString(cat),
|
||||
results,
|
||||
isHorizontalImages = true
|
||||
)
|
||||
)
|
||||
}
|
||||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
|
||||
val scriptData = getScriptData(mainUrl)
|
||||
val response = parseJson<List<IPTV>>(scriptData)
|
||||
val searchResults =
|
||||
response.filter { it.title?.lowercase()?.contains(query.lowercase()) == true }
|
||||
return searchResults.map {
|
||||
val title = it.title?.replace(regex = "\\s\\[[A-Za-z]+]$".toRegex(), "").toString()
|
||||
val posterUrl = it.tvgLogo.toString()
|
||||
newMovieSearchResponse(title, title, TvType.Live) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
|
||||
val scriptData = getScriptData(mainUrl)
|
||||
val response = parseJson<List<IPTV>>(scriptData)
|
||||
val searchResults =
|
||||
response.filter { it.title?.contains(url.substringAfterLast("/")) == true }
|
||||
val title =
|
||||
searchResults[0].title?.replace(regex = "\\s\\[[A-Za-z]+]$".toRegex(), "").toString()
|
||||
val posterUrl = searchResults[0].tvgLogo.toString()
|
||||
val href =
|
||||
if (searchResults[0].url.isNullOrEmpty()) searchResults[0].url1 else searchResults[0].url
|
||||
return newMovieLoadResponse(title, url, TvType.Live, href) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val link = if (data.contains("sonyliv") || data.contains("sunxt")) {
|
||||
app.get(data).document.selectFirst(".movie__credits a")?.attr("href").toString()
|
||||
} else if (data.contains("voot")) {
|
||||
app.get(data).document.selectFirst("source")?.attr("src").toString()
|
||||
} else {
|
||||
val html = app.get(data)
|
||||
if ( html.document.selectFirst("source")?.attr("src")
|
||||
!!.startsWith("http")
|
||||
) html.document.selectFirst("source")
|
||||
?.attr("src") else html.url.substringBeforeLast("/") + "/${
|
||||
html.document.selectFirst("source")?.attr("src")
|
||||
}"
|
||||
}.toString()
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
version = 2
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
description = " JioTV streams from different available sources"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* Status int as the following:
|
||||
* 0: Down
|
||||
* 1: Ok
|
||||
* 2: Slow
|
||||
* 3: Beta only
|
||||
* */
|
||||
status = 1 // will be 3 if unspecified
|
||||
tvTypes = listOf(
|
||||
"Live",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=jiotv.com&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,190 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
|
||||
|
||||
// credits: hexated
|
||||
//
|
||||
object SoraJioTVExtractor: SoraJioTVProvider() {
|
||||
|
||||
fun invokeGDL(
|
||||
id: String? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
){
|
||||
val link = "$GDLJioTV/autoq.php?c=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"GDLJioTV",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun invokeFS(
|
||||
id: String? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
){
|
||||
val link = "$FSJioTV/autoq.php?c=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"FSJioTV",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
fun invokeFH(
|
||||
id: String? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
){
|
||||
val link = "$FHJioTV/autoq.php?c=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"FHJioTV",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
fun invokeTS(
|
||||
id: String? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
){
|
||||
val link = "$TSJioTV/jtv/autoqtv.php?c=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"TSJioTV",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
fun invokeBF(
|
||||
id: String? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
){
|
||||
val link = "$BFJioTV/autoq.php?c=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"BFJioTV",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
fun invokeRPK(
|
||||
id: String? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
){
|
||||
val link = "$RPKJioTV/JIOTVx/autoq.php?c=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"RPKJioTV",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
suspend fun invokeTML(
|
||||
id: String? = null,
|
||||
category: Int? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
if (category == 30) {
|
||||
val link = "$TMLJioTV/zee5/zeeapi.php?c=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"TMLZee5",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
|
||||
} else if (category == 31) {
|
||||
val document = app.get("$TMLJioTV/sonyliv/channels/$id").document
|
||||
val link = document.select("source").attr("src")
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"TMLSonyLiv",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
|
||||
} else {
|
||||
val link = "$TMLJioTV/autoq.php?c=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"TMLJioTV",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun invokeSW(
|
||||
id: String? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val link = "$SWJioTV/app/master.php?id=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"SWJioTV",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun invokeZL(
|
||||
id: String? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val link = "$ZLZee5/api.php?c=$id"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"ZLZee5",
|
||||
link,
|
||||
referer = "",
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class SoraJioTVPlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(SoraJioTVProvider())
|
||||
}
|
||||
}
|
|
@ -1,235 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.darkdemon.SoraJioTVExtractor.invokeBF
|
||||
import com.darkdemon.SoraJioTVExtractor.invokeFH
|
||||
import com.darkdemon.SoraJioTVExtractor.invokeFS
|
||||
import com.darkdemon.SoraJioTVExtractor.invokeGDL
|
||||
import com.darkdemon.SoraJioTVExtractor.invokeRPK
|
||||
import com.darkdemon.SoraJioTVExtractor.invokeSW
|
||||
import com.darkdemon.SoraJioTVExtractor.invokeTML
|
||||
import com.darkdemon.SoraJioTVExtractor.invokeTS
|
||||
import com.darkdemon.SoraJioTVExtractor.invokeZL
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
|
||||
open class SoraJioTVProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var name = "SoraJioTV"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
override var lang = "hi"
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Live
|
||||
)
|
||||
|
||||
data class Channels(
|
||||
@JsonProperty("result") var result: ArrayList<Result> = arrayListOf()
|
||||
)
|
||||
|
||||
data class Result(
|
||||
@JsonProperty("channel_id") var channelId: String? = null,
|
||||
@JsonProperty("channel_order") var channelOrder: String? = null,
|
||||
@JsonProperty("channel_name") var channelName: String? = null,
|
||||
@JsonProperty("channelCategoryId") var channelCategoryId: Int? = null,
|
||||
@JsonProperty("channelLanguageId") var channelLanguageId: Int? = null,
|
||||
@JsonProperty("isHD") var isHD: Boolean? = null,
|
||||
@JsonProperty("broadcasterId") var broadcasterId: Int? = null,
|
||||
@JsonProperty("logoUrl") var logoUrl: String? = null
|
||||
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val jsonUrl =
|
||||
"https://raw.githubusercontent.com/daarkdemon/jiotvchannels/test/channels.json"
|
||||
const val GDLJioTV = "https://tv.googledrivelinks.com"
|
||||
const val FSJioTV = "https://tv.freeseries.eu.org"
|
||||
const val BFJioTV = "https://jio.buttflix.best"
|
||||
const val FHJioTV = "https://filmyhub.ga"
|
||||
const val TSJioTV = "https://tvstream.fun"
|
||||
const val RPKJioTV = "http://ranapk-nxt.ml"
|
||||
const val TMLJioTV = "http://techmaxlive.ml"
|
||||
const val SWJioTV = "https://spidyworld.ga"
|
||||
const val ZLZee5 = "https://zeeliv.tk"
|
||||
}
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val categories = mapOf(
|
||||
"Zee5" to 30,
|
||||
"Sonyliv" to 31,
|
||||
"Sports" to 8,
|
||||
"Entertainment" to 5,
|
||||
"Movies" to 6,
|
||||
"News" to 12,
|
||||
"Music" to 13,
|
||||
"Kids" to 7,
|
||||
"Lifestyle" to 9,
|
||||
"Infotainment" to 10,
|
||||
"Devotional" to 15,
|
||||
"Business" to 16,
|
||||
"Educational" to 17,
|
||||
"Shopping" to 18,
|
||||
"JioDarshan" to 19
|
||||
)
|
||||
val items = ArrayList<HomePageList>()
|
||||
val response = app.get(jsonUrl).parsed<Channels>().result
|
||||
categories.forEach { cat ->
|
||||
val results: MutableList<SearchResponse> = mutableListOf()
|
||||
val filtered = response.filter { it.channelCategoryId == cat.value }
|
||||
filtered.forEach {
|
||||
val title = it.channelName.toString()
|
||||
val posterUrl =
|
||||
if (it.logoUrl?.startsWith("https://") == true) it.logoUrl else "http://jiotv.catchup.cdn.jio.com/dare_images/images/${it.logoUrl}"
|
||||
val quality = if (it.isHD == true) "HD" else ""
|
||||
results.add(
|
||||
newMovieSearchResponse(title, it.channelId.toString(), TvType.Live) {
|
||||
this.posterUrl = posterUrl
|
||||
this.quality = getQualityFromString(quality)
|
||||
}
|
||||
)
|
||||
}
|
||||
items.add(
|
||||
HomePageList(
|
||||
capitalizeString(cat.key),
|
||||
results,
|
||||
isHorizontalImages = true
|
||||
)
|
||||
)
|
||||
}
|
||||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val response = app.get(jsonUrl).parsed<Channels>().result
|
||||
val searchResults =
|
||||
response.filter { it.channelName?.lowercase()?.contains(query.lowercase()) == true }
|
||||
|
||||
return searchResults.map {
|
||||
val title = it.channelName.toString()
|
||||
val posterUrl =
|
||||
if (it.logoUrl?.startsWith("https://") == true) it.logoUrl else "http://jiotv.catchup.cdn.jio.com/dare_images/images/${it.logoUrl}"
|
||||
newMovieSearchResponse(title, it.channelId.toString(), TvType.Live) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val response = app.get(jsonUrl).parsed<Channels>().result
|
||||
val searchResults =
|
||||
response.filter { it.channelId?.contains(url.substringAfterLast("/")) == true }
|
||||
val title = searchResults[0].channelName.toString()
|
||||
val posterUrl =
|
||||
"http://jiotv.catchup.cdn.jio.com/dare_images/images/${searchResults[0].logoUrl}"
|
||||
return newMovieLoadResponse(
|
||||
title, title, TvType.Live, Result(
|
||||
channelId = searchResults[0].channelId,
|
||||
channelName = title,
|
||||
channelCategoryId = searchResults[0].channelCategoryId,
|
||||
logoUrl = searchResults[0].logoUrl
|
||||
).toJson()
|
||||
) {
|
||||
this.posterUrl = posterUrl
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
val result = parseJson<Result>(data)
|
||||
when (result.channelCategoryId) {
|
||||
30 -> {
|
||||
argamap(
|
||||
{
|
||||
invokeZL(
|
||||
result.channelId,
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeTML(
|
||||
result.channelId,
|
||||
result.channelCategoryId,
|
||||
callback
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
31 -> {
|
||||
argamap(
|
||||
{
|
||||
invokeTML(
|
||||
result.logoUrl?.substringBefore(".png"),
|
||||
result.channelCategoryId,
|
||||
callback
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
else -> {
|
||||
argamap(
|
||||
{
|
||||
invokeGDL(
|
||||
result.logoUrl?.substringBefore(".png"),
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeFS(
|
||||
result.logoUrl?.substringBefore(".png"),
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeFH(
|
||||
result.logoUrl?.substringBefore(".png"),
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeTS(
|
||||
result.logoUrl?.substringBefore(".png"),
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeRPK(
|
||||
result.logoUrl?.substringBefore(".png"),
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeBF(
|
||||
result.logoUrl?.substringBefore(".png"),
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeTML(
|
||||
result.logoUrl?.substringBefore(".png"),
|
||||
result.channelCategoryId,
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeSW(
|
||||
result.logoUrl?.substringBefore(".png"),
|
||||
callback
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
version = 4
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
// description = "Lorem Ipsum"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=streamblasters.lol&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,13 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class StreamBlastersPlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(StreamBlastersProvider())
|
||||
}
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
|
||||
package com.darkdemon
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class StreamBlastersProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://streamblasters.art"
|
||||
override var name = "StreamBlasters"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/genre/english/page/" to "English",
|
||||
"$mainUrl/genre/hindi/page/" to "Hindi",
|
||||
"$mainUrl/genre/kannada/page/" to "Kannada",
|
||||
"$mainUrl/genre/malayalam/page/" to "Malayalam",
|
||||
"$mainUrl/genre/tamil/page/" to "Tamil",
|
||||
"$mainUrl/genre/telugu/page/" to "Telugu"
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst("img")?.attr("alt")?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("data-src"))
|
||||
val quality = getQualityFromString(this.select("span.quality").text())
|
||||
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
this.quality = quality
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query").document
|
||||
|
||||
return document.select(".result-item").mapNotNull {
|
||||
val title = it.select(".title a").text().trim()
|
||||
val href = fixUrl(it.selectFirst(".title a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(it.selectFirst(".thumbnail img")?.attr("src"))
|
||||
val quality = getQualityFromString(it.select("span.quality").text())
|
||||
val tvtype = if (href.contains("tvshows")) TvType.TvSeries else TvType.Movie
|
||||
newMovieSearchResponse(title, href, tvtype) {
|
||||
this.posterUrl = posterUrl
|
||||
this.quality = quality
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
|
||||
val title = document.selectFirst("div.sheader h1")?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.selectFirst("div.poster img")?.attr("src"))
|
||||
//val tags = document.select("div.mvici-left p:nth-child(1) a").map { it.text() }
|
||||
val year = document.select("span.date").text().trim().split(",").last()
|
||||
.toIntOrNull()
|
||||
val tvType = if (document.select("#seasons")
|
||||
.isNullOrEmpty()
|
||||
) TvType.Movie else TvType.TvSeries
|
||||
val description = document.selectFirst(".wp-content p")?.text()?.trim()
|
||||
val trailer = fixUrlNull(document.select("iframe").attr("src"))
|
||||
val rating = document.select("#info span strong").text().toRatingInt()
|
||||
val actors = document.select("#cast > div:nth-child(4)").map { it.text() }
|
||||
val recommendations = document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
||||
return if (tvType == TvType.TvSeries) {
|
||||
val episodes = document.select("ul.episodios li").mapNotNull {
|
||||
val href = fixUrl(it.select("a").attr("href")?: return null)
|
||||
val name = it.select("a").text().trim()
|
||||
val thumbs = it.select("img").attr("src")
|
||||
val season = it.select(".numerando").text().split(" - ").first().toInt()
|
||||
val episode = it.select(".numerando").text().split(" - ").last().toInt()
|
||||
Episode(
|
||||
href,
|
||||
name,
|
||||
season,
|
||||
episode,
|
||||
thumbs
|
||||
)
|
||||
}
|
||||
|
||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
//this.tags = tags
|
||||
this.rating = rating
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
} else {
|
||||
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
//this.tags = tags
|
||||
this.rating = rating
|
||||
addActors(actors)
|
||||
this.recommendations = recommendations
|
||||
addTrailer(trailer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
val document = app.get(data).document
|
||||
val id = document.select(".dooplay_player_option").attr("data-post")
|
||||
document.select("ul#playeroptionsul li#player-option-1").map {
|
||||
it.attr("data-nume")
|
||||
}.apmap { nume ->
|
||||
safeApiCall {
|
||||
val response = app.post(
|
||||
url = "$mainUrl/wp-admin/admin-ajax.php",
|
||||
data = mapOf(
|
||||
"action" to "doo_player_ajax",
|
||||
"post" to id,
|
||||
"nume" to nume,
|
||||
"type" to "movie"
|
||||
),
|
||||
referer = data,
|
||||
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
|
||||
).parsed<ResponseHash>().embed_url
|
||||
val source = if(response.contains("iframe")) Jsoup.parse(response).select("iframe").attr("src") else response
|
||||
loadExtractor(source, data, subtitleCallback, callback)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
data class ResponseHash(
|
||||
@JsonProperty("embed_url") val embed_url: String,
|
||||
@JsonProperty("type") val type: String?,
|
||||
)
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
version = 3
|
||||
|
||||
|
||||
cloudstream {
|
||||
language = "hi"
|
||||
// All of these properties are optional, you can safely remove them
|
||||
|
||||
// description = "Lorem Ipsum"
|
||||
authors = listOf("darkdemon")
|
||||
|
||||
/**
|
||||
* 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",
|
||||
)
|
||||
|
||||
iconUrl = "https://www.google.com/s2/favicons?domain=uwatchfree.be&sz=%size%"
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.darkdemon"/>
|
|
@ -1,15 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
|
||||
import com.lagradost.cloudstream3.plugins.Plugin
|
||||
import android.content.Context
|
||||
|
||||
@CloudstreamPlugin
|
||||
class UWatchFreePlugin: Plugin() {
|
||||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerExtractorAPI(DoodReExtractor())
|
||||
registerMainAPI(UWatchFreeProvider())
|
||||
|
||||
}
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
package com.darkdemon
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.extractors.DoodLaExtractor
|
||||
import com.lagradost.cloudstream3.extractors.XStreamCdn
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.nodes.Element
|
||||
|
||||
class UWatchFreeProvider : MainAPI() { // all providers must be an instance of MainAPI
|
||||
override var mainUrl = "https://uwatchfree.be/"
|
||||
override var name = "UWatchFree"
|
||||
override val hasMainPage = true
|
||||
override var lang = "hi"
|
||||
override val hasDownloadSupport = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries
|
||||
)
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/release-year/2022/page/" to "Latest",
|
||||
"$mainUrl/uwatchfree-movies/page/" to "Movies",
|
||||
"$mainUrl/watch-tv-series/page/" to "Series",
|
||||
"$mainUrl/watch-hindi-movies-online/page/" to "Hindi",
|
||||
"$mainUrl/tamil-movies/page/" to "Tamil",
|
||||
"$mainUrl/telugu-movies/page/" to "Telugu",
|
||||
"$mainUrl/hindi-dubbed-movies/page/" to "Hindi Dubbed"
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val document = app.get(request.data + page).document
|
||||
val home = document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
return newHomePageResponse(request.name, home)
|
||||
}
|
||||
|
||||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst("h2 a")?.text()?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")?.attr("href").toString())
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
||||
val quality = getQualityFromString(this.select(".mli-quality").text())
|
||||
|
||||
return newMovieSearchResponse(title, href, TvType.Movie) {
|
||||
this.posterUrl = posterUrl
|
||||
this.quality = quality
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val document = app.get("$mainUrl/?s=$query&submit=Search").document
|
||||
|
||||
return document.select("article").mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val document = app.get(url).document
|
||||
|
||||
val title = document.selectFirst(".entry-title")?.text()?.trim() ?: return null
|
||||
val poster = fixUrlNull(document.selectFirst(".moviemeta img")?.attr("src"))
|
||||
val tags = document.select("div.moviemeta > p:nth-child(4) a").map { it.text() }
|
||||
val yearRegex = Regex("""/(\d{4})/gm""")
|
||||
val year = yearRegex.find(
|
||||
document.select("div.moviemeta > p:nth-child(7)").text()
|
||||
)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
||||
val description = document.selectFirst("div.moviemeta > p:nth-child(9)")?.text()?.trim()
|
||||
val actors =
|
||||
document.select("div.moviemeta > p:nth-child(3) span[itemprop=name]").map { it.text() }
|
||||
val tvType = if (document.selectFirst(".tritem td:first-child")
|
||||
?.text()
|
||||
?.contains(Regex("(?i)(Episode\\s?[0-9]+)")) == true
|
||||
) TvType.TvSeries else TvType.Movie
|
||||
return if (tvType == TvType.TvSeries) {
|
||||
val episodes = document.select(".tritem").mapNotNull {
|
||||
val href = fixUrl(it.select("a").attr("href") ?: return null)
|
||||
val name = it.selectFirst("td")?.text()?.trim()
|
||||
val seasonRegex = Regex("""Season\s?([0-9]+)""")
|
||||
val season = seasonRegex.find(
|
||||
document.select(".entry-title").text()
|
||||
)?.groupValues?.getOrNull(1)?.toIntOrNull()
|
||||
val episode = name?.substringAfter("Episode 0")?.substringBefore(":")?.toIntOrNull()
|
||||
Episode(
|
||||
href,
|
||||
name,
|
||||
season,
|
||||
episode,
|
||||
)
|
||||
}
|
||||
|
||||
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
addActors(actors)
|
||||
}
|
||||
} else {
|
||||
newMovieLoadResponse(title, url, TvType.Movie, url) {
|
||||
this.posterUrl = poster
|
||||
this.year = year
|
||||
this.plot = description
|
||||
this.tags = tags
|
||||
addActors(actors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val doc = app.get(data).document
|
||||
val urls = ArrayList<String>()
|
||||
if (data.contains("player")) {
|
||||
urls.add(app.get(data).document.select("iframe").attr("src"))
|
||||
} else {
|
||||
doc.select(".magnet-link a").map { src ->
|
||||
if (src.attr("href").contains("send.cm")) {
|
||||
val url = app.get(src.attr("href")).document.select("source").attr("src")
|
||||
urls.add(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
doc.select("body a:contains(Click to Play)").map { fixUrl(it.attr("href")) }
|
||||
.apmap { source ->
|
||||
app.get(
|
||||
source,
|
||||
referer = data
|
||||
).document.select("iframe")
|
||||
.apmap {
|
||||
urls.add(it.attr("src"))
|
||||
}
|
||||
}
|
||||
println(urls)
|
||||
urls.forEach { url ->
|
||||
if (url.contains("send.cm")) {
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
url,
|
||||
mainUrl,
|
||||
quality = Qualities.Unknown.value,
|
||||
)
|
||||
)
|
||||
} else if (url.startsWith("https://0gomovies.top")) {
|
||||
val script = app.get(url).text
|
||||
println(script)
|
||||
val srcRegex = Regex("""(file: ")(https?.*?\.m3u8)""")
|
||||
val source =
|
||||
srcRegex.find(script.toString())?.groupValues?.getOrNull(2)
|
||||
?.toString()
|
||||
println(source)
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
source.toString(),
|
||||
referer = url,
|
||||
quality = Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
} else {
|
||||
loadExtractor(
|
||||
url,
|
||||
"$mainUrl/",
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
class DoodReExtractor : DoodLaExtractor() {
|
||||
override var mainUrl = "https://dood.re"
|
||||
}
|
Loading…
Reference in New Issue