2022-03-12 12:56:30 +00:00
package com.lagradost.cloudstream3.movieproviders
2022-04-09 14:50:04 +00:00
import com.fasterxml.jackson.annotation.JsonProperty
2022-03-12 12:56:30 +00:00
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
2022-04-09 14:50:04 +00:00
import com.lagradost.cloudstream3.utils.ExtractorLink
2022-03-12 12:56:30 +00:00
import org.jsoup.nodes.Element
class EgyBestProvider : MainAPI ( ) {
override val lang = " ar "
2022-04-11 14:16:22 +00:00
override var mainUrl = " https://www.egy.best "
2022-03-16 15:29:11 +00:00
override var name = " EgyBest "
2022-03-12 12:56:30 +00:00
override val usesWebView = false
override val hasMainPage = true
2022-04-20 20:05:06 +00:00
override val supportedTypes = setOf ( TvType . TvSeries , TvType . Movie , TvType . Anime )
2022-03-12 12:56:30 +00:00
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 " )
2022-03-17 15:39:26 +00:00
var title = select ( " span.title " ) . text ( )
val year = title . getYearFromTitle ( )
val isMovie = Regex ( " .*/movie/.*|.*/masrahiya/.* " ) . matches ( url )
val tvType = if ( isMovie ) TvType . Movie else TvType . TvSeries
title = if ( year !== null ) title else title . split ( " ( " ) [ 0 ] . trim ( )
2022-04-11 14:16:22 +00:00
val quality = select ( " span.ribbon span " ) . text ( ) . replace ( " - " , " " )
2022-03-12 12:56:30 +00:00
// If you need to differentiate use the url.
return MovieSearchResponse (
title ,
url ,
this @EgyBestProvider . name ,
tvType ,
posterUrl ,
2022-03-17 15:39:26 +00:00
year ,
2022-03-12 12:56:30 +00:00
null ,
2022-04-11 14:16:22 +00:00
quality = getQualityFromString ( quality )
2022-03-12 12:56:30 +00:00
)
}
override suspend fun getMainPage ( ) : HomePageResponse {
// url, title
2022-03-17 15:39:26 +00:00
val doc = app . get ( mainUrl ) . document
2022-04-11 14:16:22 +00:00
val pages = arrayListOf < HomePageList > ( )
2022-04-24 21:26:09 +00:00
doc . select ( " #mainLoad div.mbox " ) . apmap {
2022-03-17 15:39:26 +00:00
val name = it . select ( " .bdb.pda > strong " ) . text ( )
2022-05-02 16:58:27 +00:00
if ( it . select ( " .movie " ) . first ( ) ?. attr ( " href " ) ?. contains ( " season-(.....)|ep-(.....) " . toRegex ( ) ) == true ) return @apmap
2022-04-11 14:16:22 +00:00
val list = arrayListOf < SearchResponse > ( )
it . select ( " .movie " ) . map { element ->
list . add ( element . toSearchResponse ( ) !! )
2022-03-12 12:56:30 +00:00
}
2022-04-11 14:16:22 +00:00
pages . add ( HomePageList ( name , list ) )
2022-03-17 15:39:26 +00:00
}
2022-03-12 12:56:30 +00:00
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 }
}
2022-03-17 15:39:26 +00:00
private fun String . getYearFromTitle ( ) : Int ? {
return Regex ( """ \(\d{4}\) """ ) . find ( this ) ?. groupValues ?. firstOrNull ( ) ?. toIntOrNull ( )
}
2022-03-12 12:56:30 +00:00
override suspend fun load ( url : String ) : LoadResponse {
val doc = app . get ( url ) . document
2022-03-17 15:39:26 +00:00
val isMovie = Regex ( " .*/movie/.*|.*/masrahiya/.* " ) . matches ( url )
2022-03-12 12:56:30 +00:00
val posterUrl = doc . select ( " div.movie_img a img " ) ?. attr ( " src " )
val year = doc . select ( " div.movie_title h1 a " ) ?. text ( ) ?. toIntOrNull ( )
2022-04-11 14:16:22 +00:00
val title = doc . select ( " div.movie_title h1 span " ) . text ( )
2022-03-12 12:56:30 +00:00
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 ( ) }
2022-05-02 16:58:27 +00:00
val actors = doc . select ( " div.cast_list .cast_item " ) . mapNotNull {
2022-03-17 15:39:26 +00:00
val name = it . selectFirst ( " div > a > img " ) ?. attr ( " alt " ) ?: return @mapNotNull null
val image = it . selectFirst ( " div > a > img " ) ?. attr ( " src " ) ?: return @mapNotNull null
2022-05-02 16:58:27 +00:00
val roleString = it . selectFirst ( " div > span " ) !! . text ( )
2022-03-17 15:39:26 +00:00
val mainActor = Actor ( name , image )
ActorData ( actor = mainActor , roleString = roleString )
}
2022-03-12 12:56:30 +00:00
return if ( isMovie ) {
2022-05-02 16:58:27 +00:00
val recommendations = doc . select ( " .movies_small .movie " ) . mapNotNull { element ->
2022-03-17 15:39:26 +00:00
element . toSearchResponse ( )
}
2022-03-12 12:56:30 +00:00
newMovieLoadResponse (
title ,
url ,
TvType . Movie ,
url
) {
this . posterUrl = posterUrl
this . year = year
2022-03-17 15:39:26 +00:00
this . recommendations = recommendations
2022-03-12 12:56:30 +00:00
this . plot = synopsis
this . tags = tags
2022-03-17 15:39:26 +00:00
this . actors = actors
2022-03-12 12:56:30 +00:00
}
} else {
2022-04-09 14:50:04 +00:00
val episodes = ArrayList < Episode > ( )
2022-03-12 12:56:30 +00:00
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 ( )
2022-04-24 21:26:09 +00:00
if ( d . select ( " tr.published " ) . isNotEmpty ( ) ) {
d . select ( " tr.published " ) . map { element ->
val ep = Regex ( " ep-(.....) " ) . find ( element . select ( " .ep_title a " ) . attr ( " href " ) ) ?. groupValues ?. getOrNull ( 1 ) ?. getIntFromText ( )
episodes . add (
Episode (
element . select ( " .ep_title a " ) . attr ( " href " ) ,
name = element . select ( " td.ep_title " ) . html ( ) . replace ( " .*</span>|</a> " . toRegex ( ) , " " ) ,
season ,
ep ,
rating = element . select ( " td.tam:not(.date, .ep_len) " ) . text ( ) . getIntFromText ( )
)
2022-03-12 12:56:30 +00:00
)
2022-04-24 21:26:09 +00:00
}
} else {
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 (
Episode (
eit . attr ( " href " ) ,
eit . select ( " span.title " ) . text ( ) ,
season ,
ep ,
)
)
}
2022-03-12 12:56:30 +00:00
}
}
newTvSeriesLoadResponse ( title , url , TvType . TvSeries , episodes . distinct ( ) . sortedBy { it . episode } ) {
this . posterUrl = posterUrl
this . tags = tags
this . year = year
this . plot = synopsis
2022-03-17 15:39:26 +00:00
this . actors = actors
2022-03-12 12:56:30 +00:00
}
}
}
data class Sources (
@JsonProperty ( " quality " ) val quality : Int ? ,
@JsonProperty ( " link " ) val link : String
)
2022-05-05 21:50:08 +00:00
2022-03-12 12:56:30 +00:00
override suspend fun loadLinks (
data : String ,
isCasting : Boolean ,
subtitleCallback : ( SubtitleFile ) -> Unit ,
callback : ( ExtractorLink ) -> Unit
) : Boolean {
2022-05-05 21:50:08 +00:00
/ * val baseURL = data . split ( " / " ) [ 0 ] + " // " + data . split ( " / " ) [ 2 ]
val episodeSoup = app . get ( data ) . document
val vidstreamURL = fixUrlNull ( episodeSoup . selectFirst ( " iframe.auto-size " ) ?. attr ( " src " ) ) ?: throw ErrorLoadingException ( " No iframe " )
val videoSoup = app . get ( vidstreamURL ) . document
fixUrlNull ( videoSoup . select ( " source " ) . firstOrNull { it . hasAttr ( " src " ) } ?. attr ( " src " ) ) ?. let {
callback . invoke ( ExtractorLink ( this . name , this . name , it , " " , Qualities . Unknown . value , it . contains ( " .m3u8 " ) ) )
} ?: run {
var jsCode = videoSoup . select ( " script " ) [ 1 ] . data ( )
val verificationToken = Regex ( " {'[0-9a-zA-Z_]*':'ok'} " ) . findAll ( jsCode ) [ 0 ] [ 2 : - 7 ]
val encodedAdLinkVar = Regex ( " ([0-9a-zA-Z_]{2,12} \ [Math " ) . findAll ( jsCode ) [ 0 ] [ 1 : - 5 ]
val encodingArraysRegEx = Regex ( " ,[0-9a-zA-Z_]{2,12}= \ [ \ ] " ) . findAll ( jsCode )
val firstEncodingArray = encodingArraysRegEx [ 1 ] [ 1 : - 3 ]
val secondEncodingArray = encodingArraysRegEx [ 2 ] [ 1 : - 3 ]
jsCode = Regex ( " ^<script type= \" text/javascript \" > " , " " , jsCode )
jsCode = Regex ( " [;,] \$ \ (' \ *' \ )(.*) $ " , " ; " , jsCode )
jsCode = Regex ( " ,ismob=(.*) \ (navigator \ [(.*) \ ] \ )[,;] " , " ; " , jsCode )
jsCode = Regex ( " var a0b=function \ ( \ )(.*)a0a \ ( \ ); " , ) . findAll ( jsCode )
jsCode += " var link = ''; for (var i = 0; i <= $secondEncodingArray ['length']; i++) { link += $firstEncodingArray [ $secondEncodingArray [i]] || ''; } return [link, $encodedAdLinkVar [0]] } "
val jsCodeReturn = executeJS ( jsCode ) ( )
val verificationPath = jsCodeReturn [ 0 ]
val encodedAdPath = jsCodeReturn [ 1 ]
val adLink = baseURL + " / " + str ( decode ( encodedAdPath + " = " * ( - len ( encodedAdPath ) % 4 ) ) , " utf-8 " )
val session . get ( adLink )
val verificationLink = baseURL + " /tvc.php?verify= " + verificationPath
val session . post ( verificationLink , data = { verificationToken : " ok " } )
val vidstreamResponseText = session . get ( vidstreamURL ) . text
val videoSoup = BeautifulSoup ( vidstreamResponseText , features = " html.parser " )
val qualityLinksFileURL = baseURL + videoSoup . body . find ( " source " ) . get ( " src " )
}
return true * /
2022-04-24 21:26:09 +00:00
val requestJSON = app . get ( " https://api.zr5.repl.co/egybest?url= $data " ) . text
2022-03-12 12:56:30 +00:00
val jsonArray = parseJson < List < Sources > > ( requestJSON )
for ( i in jsonArray ) {
val quality = i . quality
val link = i . link
2022-04-24 21:26:09 +00:00
callback . invoke (
ExtractorLink (
this . name ,
this . name ,
link ,
this . mainUrl ,
quality !! ,
true
2022-03-12 12:56:30 +00:00
)
2022-04-24 21:26:09 +00:00
)
2022-03-12 12:56:30 +00:00
}
return true
}
}