Merge remote-tracking branch 'origin/master'

This commit is contained in:
LagradOst 2022-03-12 15:34:52 +01:00
commit 9eec4df8ba
8 changed files with 296 additions and 97 deletions

View File

@ -87,11 +87,13 @@ It merely scrapes 3rd-party websites that are publicly accessable via any regula
- [pinoy-hd.xyz](https://www.pinoy-hd.xyz)
- [pinoymovies.es](https://pinoymovies.es)
- [trailers.to](https://trailers.to)
- [2embed.ru](https://www.2embed.ru)
- [dramasee.net](https://dramasee.net)
- [watchasian.sh](https://watchasian.sh)
- [kdramahood.com](https://kdramahood.com)
- [akwam.io](https://akwam.io)
- [mycima.tv](https://mycima.tv)
- [egy.best](https://egy.best)
- [9anime.center](https://9anime.center)
- [animeworld.tv](https://www.animeworld.tv)
- [asiaflix.app](https://asiaflix.app)

View File

@ -81,11 +81,13 @@ object APIHolder {
PinoyHDXyzProvider(),
PinoyMoviesEsProvider(),
TrailersTwoProvider(),
TwoEmbedProvider(),
DramaSeeProvider(),
WatchAsianProvider(),
KdramaHoodProvider(),
AkwamProvider(),
MyCimaProvider(),
EgyBestProvider(),
AnimePaheProvider(),
NineAnimeProvider(),
AnimeWorldProvider(),

View File

@ -17,7 +17,7 @@ class StreamSB2 : StreamSB() {
}
class StreamSB3 : StreamSB() {
override val mainUrl = "https://sbplay.one"
override val mainUrl = "https://sbplay3.com"
}
class StreamSB4 : StreamSB() {

View File

@ -14,6 +14,11 @@ class Upstream: ZplayerV2() {
override val mainUrl: String = "https://upstream.to"
}
class Streamhub2: ZplayerV2() {
override val name: String = "Streamhub" //Here 'cause works
override val mainUrl: String = "https://streamhub.to"
}
open class ZplayerV2 : ExtractorApi() {
override val name = "Zplayer V2"
override val mainUrl = "https://v2.zplayer.live"

View File

@ -1,17 +1,11 @@
package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.LoadResponse.Companion.setDuration
import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.mvvm.logError
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.getPostForm
import com.lagradost.cloudstream3.utils.loadExtractor
import okio.Buffer
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.net.URLDecoder
class AllMoviesForYouProvider : MainAPI() {
companion object {
@ -27,11 +21,44 @@ class AllMoviesForYouProvider : MainAPI() {
// Fetching movies will not work if this link is outdated.
override val mainUrl = "https://allmoviesforyou.net"
override val name = "AllMoviesForYou"
override val hasMainPage = true
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries
)
override suspend fun getMainPage(): HomePageResponse {
val items = ArrayList<HomePageList>()
val soup = app.get(mainUrl).document
val urls = listOf(
Pair("Movies", "section[data-id=movies] article.TPost.B"),
Pair("TV Series", "section[data-id=series] article.TPost.B"),
)
for ((name, element) in urls) {
try {
val home = soup.select(element).map {
val title = it.selectFirst("h2.title").text()
val link = it.selectFirst("a").attr("href")
TvSeriesSearchResponse(
title,
link,
this.name,
TvType.Movie,
fixUrl(it.selectFirst("figure img").attr("data-src")),
null,
null,
)
}
items.add(HomePageList(name, home))
} catch (e: Exception) {
logError(e)
}
}
if (items.size <= 0) throw ErrorLoadingException()
return HomePageResponse(items)
}
override suspend fun search(query: String): List<SearchResponse> {
val url = "$mainUrl/?s=$query"
val document = app.get(url).document
@ -58,23 +85,23 @@ class AllMoviesForYouProvider : MainAPI() {
}
}
private fun getLink(document: Document): List<String>? {
val list = ArrayList<String>()
Regex("iframe src=\"(.*?)\"").find(document.html())?.groupValues?.get(1)?.let {
list.add(it)
}
document.select("div.OptionBx")?.forEach { element ->
val baseElement = element.selectFirst("> a.Button")
val elementText = element.selectFirst("> p.AAIco-dns")?.text()
if (elementText == "Streamhub" || elementText == "Dood") {
baseElement?.attr("href")?.let { href ->
list.add(href)
}
}
}
return if (list.isEmpty()) null else list
}
// private fun getLink(document: Document): List<String>? {
// val list = ArrayList<String>()
// Regex("iframe src=\"(.*?)\"").find(document.html())?.groupValues?.get(1)?.let {
// list.add(it)
// }
// document.select("div.OptionBx")?.forEach { element ->
// val baseElement = element.selectFirst("> a.Button")
// val elementText = element.selectFirst("> p.AAIco-dns")?.text()
// if (elementText == "Streamhub" || elementText == "Dood") {
// baseElement?.attr("href")?.let { href ->
// list.add(href)
// }
// }
// }
//
// return if (list.isEmpty()) null else list
// }
override suspend fun load(url: String): LoadResponse {
val type = getType(url)
@ -144,14 +171,11 @@ class AllMoviesForYouProvider : MainAPI() {
rating
)
} else {
val data = getLink(document)
?: throw ErrorLoadingException("No Links Found")
return newMovieLoadResponse(
title,
url,
type,
data.filter { it != "about:blank" }.toJson()
url
) {
posterUrl = backgroundPoster
this.year = year?.toIntOrNull()
@ -168,74 +192,17 @@ class AllMoviesForYouProvider : MainAPI() {
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
if (data.startsWith("$mainUrl/episode/")) {
val response = app.get(data).text
getLink(Jsoup.parse(response))?.let { links ->
for (link in links) {
if (link == data) continue
loadLinks(link, isCasting, subtitleCallback, callback)
val doc = app.get(data).document
val iframe = doc.select("body iframe").map { it.attr("src") }
iframe.apmap { id ->
if (id.contains("trembed")) {
val soup = app.get(id).document
soup.select("body iframe").map {
val link = it.attr("src").replace("streamhub.to/d/","streamhub.to/e/")
loadExtractor(link, data, callback)
}
return true
}
return false
} else if (data.startsWith(mainUrl) && data != mainUrl) {
val realDataUrl = URLDecoder.decode(data, "UTF-8")
if (data.contains("trdownload")) {
val request = app.get(data)
val requestUrl = request.url
if (requestUrl.startsWith("https://streamhub.to/d/")) {
val buffer = Buffer()
val source = request.body?.source()
var html = ""
var tries = 0 // 20 tries = 163840 bytes = 0.16mb
while (source?.exhausted() == false && tries < 20) {
// 8192 = max size
source.read(buffer, 8192)
tries += 1
html += buffer.readUtf8()
}
getPostForm(request.url, html)?.let { form ->
val postDocument = Jsoup.parse(form)
postDocument.selectFirst("a.downloadbtn")?.attr("href")?.let { url ->
callback(
ExtractorLink(
this.name,
this.name,
url,
mainUrl,
Qualities.Unknown.value
)
)
}
}
} else if (requestUrl.startsWith("https://dood")) {
loadExtractor(requestUrl, null, callback)
} else {
callback(
ExtractorLink(
this.name,
this.name,
realDataUrl,
mainUrl,
Qualities.Unknown.value
)
)
}
return true
}
val response = app.get(realDataUrl).text
Regex("<iframe.*?src=\"(.*?)\"").find(response)?.groupValues?.get(1)?.let { url ->
loadExtractor(url.trimStart(), realDataUrl, callback)
}
return true
} else {
val links = mapper.readValue<List<String>>(data)
for (link in links) {
loadLinks(link, isCasting, subtitleCallback, callback)
}
return true
} else loadExtractor(id, data, callback)
}
return true
}
}

View File

@ -0,0 +1,153 @@
package com.lagradost.cloudstream3.movieproviders
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.fasterxml.jackson.annotation.JsonProperty
import org.jsoup.nodes.Element
class EgyBestProvider : MainAPI() {
override val lang = "ar"
override val mainUrl = "https://egy.best"
override val name = "EgyBest"
override val usesWebView = false
override val hasMainPage = true
override val supportedTypes = setOf(TvType.TvSeries, TvType.Movie)
private fun String.getIntFromText(): Int? {
return Regex("""\d+""").find(this)?.groupValues?.firstOrNull()?.toIntOrNull()
}
private fun Element.toSearchResponse(): SearchResponse? {
val url = this.attr("href") ?: return null
val posterUrl = select("img")?.attr("src")
val title = select("span.title").text()
.replace("\\(.*\\)".toRegex(), "")
val year = select("span.title").text()
.replace(".*\\(|\\)".toRegex(), "")
val tvType = if (url.contains("/movie/")) TvType.Movie else TvType.TvSeries
// If you need to differentiate use the url.
return MovieSearchResponse(
title,
url,
this@EgyBestProvider.name,
tvType,
posterUrl,
year.toIntOrNull(),
null,
)
}
override suspend fun getMainPage(): HomePageResponse {
// url, title
val pagesUrl = listOf(
Pair("$mainUrl/movies/?page="+(0..25).random(), "Movies"),
Pair("$mainUrl/tv/?page="+(0..25).random(), "Series"),
)
val pages = pagesUrl.apmap { (url, name) ->
val doc = app.get(url).document
val list = doc.select("div.movies a").not("a.auto.load.btn.b").mapNotNull { element ->
element.toSearchResponse()
}
HomePageList(name, list)
}.sortedBy { it.name }
return HomePageResponse(pages)
}
override suspend fun search(query: String): List<SearchResponse> {
val q = query.replace(" ","%20")
val result = arrayListOf<SearchResponse>()
listOf("$mainUrl/explore/?q=$q").apmap { url ->
val d = app.get(url).document
d.select("div.movies a").not("a.auto.load.btn.b").mapNotNull {
it.toSearchResponse()?.let { it1 -> result.add(it1) }
}
}
return result.distinct().sortedBy { it.name }
}
override suspend fun load(url: String): LoadResponse {
val doc = app.get(url).document
val isMovie = url.contains("/movie/")
val posterUrl = doc.select("div.movie_img a img")?.attr("src")
val year = doc.select("div.movie_title h1 a")?.text()?.toIntOrNull()
val title = doc.select("div.movie_title h1 span[itemprop=\"name\"]").text()
val synopsis = doc.select("div.mbox").firstOrNull {
it.text().contains("القصة")
}?.text()?.replace("القصة ", "")
val tags = doc.select("table.movieTable tbody tr").firstOrNull {
it.text().contains("النوع")
}?.select("a")?.map { it.text() }
return if (isMovie) {
newMovieLoadResponse(
title,
url,
TvType.Movie,
url
) {
this.posterUrl = posterUrl
this.year = year
this.plot = synopsis
this.tags = tags
}
} else {
val episodes = ArrayList<TvSeriesEpisode>()
doc.select("#mainLoad > div:nth-child(2) > div.h_scroll > div a").map {
it.attr("href")
}.apmap {
val d = app.get(it).document
val season = Regex("season-(.....)").find(it)?.groupValues?.getOrNull(1)?.getIntFromText()
d.select("#mainLoad > div:nth-child(3) > div.movies_small a").map { eit ->
val ep = Regex("ep-(.....)").find(eit.attr("href"))?.groupValues?.getOrNull(1)?.getIntFromText()
episodes.add(
TvSeriesEpisode(
eit.select("span.title").text(),
season,
ep,
eit.attr("href"),
null,
null
)
)
}
}
newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes.distinct().sortedBy { it.episode }) {
this.posterUrl = posterUrl
this.tags = tags
this.year = year
this.plot = synopsis
}
}
}
data class Sources (
@JsonProperty("quality") val quality: Int?,
@JsonProperty("link") val link: String
)
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val requestJSON = app.get("https://zawmedia-api.herokuapp.com/egybest?url=$data").text
val jsonArray = parseJson<List<Sources>>(requestJSON)
for (i in jsonArray) {
val quality = i.quality
val link = i.link
callback.invoke(
ExtractorLink(
this.name,
this.name + " ${quality}p",
link,
this.mainUrl,
2,
true
)
)
}
return true
}
}

View File

@ -0,0 +1,69 @@
package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.APIHolder.getCaptchaToken
import com.lagradost.cloudstream3.metaproviders.TmdbLink
import com.lagradost.cloudstream3.metaproviders.TmdbProvider
import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor
class TwoEmbedProvider : TmdbProvider() {
override val apiName = "2Embed"
override val name = "2Embed"
override val mainUrl = "https://www.2embed.ru"
override val useMetaLoadResponse = true
override val instantLinkLoading = false
override val supportedTypes = setOf(
TvType.Movie,
TvType.TvSeries,
)
data class EmbedJson (
@JsonProperty("type") val type: String?,
@JsonProperty("link") val link: String,
@JsonProperty("sources") val sources: List<String?>,
@JsonProperty("tracks") val tracks: List<String>?
)
override suspend fun loadLinks(
data: String,
isCasting: Boolean,
subtitleCallback: (SubtitleFile) -> Unit,
callback: (ExtractorLink) -> Unit
): Boolean {
val mappedData = parseJson<TmdbLink>(data)
val (id, site) = if (mappedData.imdbID != null) listOf(
mappedData.imdbID,
"imdb"
) else listOf(mappedData.tmdbID.toString(), "tmdb")
val isMovie = mappedData.episode == null && mappedData.season == null
val embedUrl = if (isMovie) {
"$mainUrl/embed/$site/movie?id=$id"
} else {
val suffix = "$id&s=${mappedData.season ?: 1}&e=${mappedData.episode ?: 1}"
"$mainUrl/embed/$site/tv?id=$suffix"
}
val document = app.get(embedUrl).document
val captchaKey =
document.select("script[src*=https://www.google.com/recaptcha/api.js?render=]")
.attr("src").substringAfter("render=")
val servers = document.select(".dropdown-menu a[data-id]").map { it.attr("data-id") }
servers.apmap { serverID ->
val token = getCaptchaToken(embedUrl, captchaKey)
val ajax = app.get("$mainUrl/ajax/embed/play?id=$serverID&_token=$token", referer = embedUrl).text
val mappedservers = parseJson<EmbedJson>(ajax)
val iframeLink = mappedservers.link
if (iframeLink.contains("rabbitstream")) {
extractRabbitStream(iframeLink, subtitleCallback, callback) { it }
} else {
loadExtractor(iframeLink, embedUrl, callback)
}
}
return true
}
}

View File

@ -112,7 +112,8 @@ val extractorApis: Array<ExtractorApi> = arrayOf(
StreamSB7(),
StreamSB8(),
StreamSB9(),
Streamhub(),
// Streamhub(), cause Streamhub2() works
Streamhub2(),
FEmbed(),
FeHD(),