mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	Added 2 New Italian Providers (#973) By Adippe
This commit is contained in:
		
							parent
							
								
									fd50e2cccb
								
							
						
					
					
						commit
						c48e45c9c6
					
				
					 4 changed files with 695 additions and 24 deletions
				
			
		| 
						 | 
				
			
			@ -83,6 +83,8 @@ object APIHolder {
 | 
			
		|||
            SoaptwoDayProvider(),
 | 
			
		||||
            HDMProvider(),// disabled due to cloudflare
 | 
			
		||||
            TheFlixToProvider(),
 | 
			
		||||
            StreamingcommunityProvider(),
 | 
			
		||||
            TantifilmProvider(),
 | 
			
		||||
 | 
			
		||||
            // Metadata providers
 | 
			
		||||
            //TmdbProvider(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,29 +29,19 @@ open class DoodLaExtractor : ExtractorApi() {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? {
 | 
			
		||||
        val id = url.removePrefix("$mainUrl/e/").removePrefix("$mainUrl/d/")
 | 
			
		||||
        val trueUrl = getExtractorUrl(id)
 | 
			
		||||
        val response = app.get(trueUrl).text
 | 
			
		||||
        Regex("href=\".*/download/(.*?)\"").find(response)?.groupValues?.get(1)?.let { link ->
 | 
			
		||||
            if (link.isEmpty()) return null
 | 
			
		||||
            delay(5000) // might need this to not trigger anti bot
 | 
			
		||||
            val downloadLink = "$mainUrl/download/$link"
 | 
			
		||||
            val downloadResponse = app.get(downloadLink).text
 | 
			
		||||
            Regex("onclick=\"window\\.open\\((['\"])(.*?)(['\"])").find(downloadResponse)?.groupValues?.get(2)
 | 
			
		||||
                ?.let { trueLink ->
 | 
			
		||||
                    return listOf(
 | 
			
		||||
                        ExtractorLink(
 | 
			
		||||
                            trueLink,
 | 
			
		||||
                            this.name,
 | 
			
		||||
                            trueLink,
 | 
			
		||||
                            mainUrl,
 | 
			
		||||
                            Qualities.Unknown.value,
 | 
			
		||||
                            false
 | 
			
		||||
                        )
 | 
			
		||||
                    ) // links are valid in 8h
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
        val response0 = app.get(url).text // html of DoodStream page to look for /pass_md5/...
 | 
			
		||||
        val md5 =mainUrl+(Regex("/pass_md5/[^']*").find(response0)?.value ?: return null)  // get https://dood.ws/pass_md5/...
 | 
			
		||||
        val trueUrl = app.get(md5, referer = url).text + "zUEJeL3mUN?token=" + md5.substringAfterLast("/")   //direct link to extract  (zUEJeL3mUN is random)
 | 
			
		||||
        return listOf(
 | 
			
		||||
            ExtractorLink(
 | 
			
		||||
                trueUrl,
 | 
			
		||||
                this.name,
 | 
			
		||||
                trueUrl,
 | 
			
		||||
                mainUrl,
 | 
			
		||||
                Qualities.Unknown.value,
 | 
			
		||||
                false
 | 
			
		||||
            )
 | 
			
		||||
        ) // links are valid in 8h
 | 
			
		||||
 | 
			
		||||
        return null
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,436 @@
 | 
			
		|||
package com.lagradost.cloudstream3.movieproviders
 | 
			
		||||
 | 
			
		||||
import android.text.Html
 | 
			
		||||
import com.fasterxml.jackson.annotation.*
 | 
			
		||||
import com.lagradost.cloudstream3.*
 | 
			
		||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
 | 
			
		||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
 | 
			
		||||
import com.lagradost.cloudstream3.utils.*
 | 
			
		||||
import org.json.JSONObject
 | 
			
		||||
import java.net.URI
 | 
			
		||||
import java.security.MessageDigest
 | 
			
		||||
 | 
			
		||||
data class Moviedata(
 | 
			
		||||
    @JsonProperty("id") val id: Long,
 | 
			
		||||
    @JsonProperty("name") val name: String,
 | 
			
		||||
    @JsonProperty("type") val type: String,
 | 
			
		||||
    @JsonProperty("release_date") val releaseDate: String,
 | 
			
		||||
    @JsonProperty("seasons_count") val seasonsCount: Long? = null,
 | 
			
		||||
    @JsonProperty("genres") val genres: List<Genre>,
 | 
			
		||||
    @JsonProperty("votes") val votes: List<Vote>,
 | 
			
		||||
    @JsonProperty("runtime") val runtime: Long? = null
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class Genre(
 | 
			
		||||
    @JsonProperty("name") val name: String,
 | 
			
		||||
    @JsonProperty("pivot") val pivot: Pivot,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class Pivot(
 | 
			
		||||
    @JsonProperty("titleID") val titleID: Long,
 | 
			
		||||
    @JsonProperty("genreID") val genreID: Long,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class Vote(
 | 
			
		||||
    @JsonProperty("title_id") val title_id: Long,
 | 
			
		||||
    @JsonProperty("average") val average: String,
 | 
			
		||||
    @JsonProperty("count") val count: Long,
 | 
			
		||||
    @JsonProperty("type") val type: String,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class VideoElement(
 | 
			
		||||
    @JsonProperty("id") val id: Long,
 | 
			
		||||
    @JsonProperty("slug") val slug: String,
 | 
			
		||||
    @JsonProperty("images") val images: List<Image>,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class Image(
 | 
			
		||||
    @JsonProperty("imageable_id") val imageableID: Long,
 | 
			
		||||
    @JsonProperty("imageable_type") val imageableType: String,
 | 
			
		||||
    @JsonProperty("server_id") val serverID: Long,
 | 
			
		||||
    @JsonProperty("proxy_id") val proxyID: Long,
 | 
			
		||||
    @JsonProperty("url") val url: String,
 | 
			
		||||
    @JsonProperty("type") val type: String,
 | 
			
		||||
    @JsonProperty("sc_url") val scURL: String,
 | 
			
		||||
    @JsonProperty("proxy") val proxy: Proxy,
 | 
			
		||||
    @JsonProperty("server") val server: Proxy
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class Proxy(
 | 
			
		||||
    @JsonProperty("id") val id: Long,
 | 
			
		||||
    @JsonProperty("type") val type: String,
 | 
			
		||||
    @JsonProperty("ip") val ip: String,
 | 
			
		||||
    @JsonProperty("number") val number: Long,
 | 
			
		||||
    @JsonProperty("storage") val storage: Long,
 | 
			
		||||
    @JsonProperty("max_storage") val maxStorage: Long,
 | 
			
		||||
    @JsonProperty("max_conversions") val maxConversions: Any? = null,
 | 
			
		||||
    @JsonProperty("max_publications") val maxPublications: Any? = null,
 | 
			
		||||
    @JsonProperty("created_at") val createdAt: String,
 | 
			
		||||
    @JsonProperty("updated_at") val updatedAt: String,
 | 
			
		||||
    @JsonProperty("upload_bandwidth") val uploadBandwidth: Any? = null,
 | 
			
		||||
    @JsonProperty("upload_bandwidth_limit") val uploadBandwidthLimit: Any? = null
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class Season(
 | 
			
		||||
    @JsonProperty("id") val id: Long,
 | 
			
		||||
    @JsonProperty("name") val name: String? = "",
 | 
			
		||||
    @JsonProperty("plot") val plot: String? = "",
 | 
			
		||||
    @JsonProperty("date") val date: String? = "",
 | 
			
		||||
    @JsonProperty("number") val number: Long,
 | 
			
		||||
    @JsonProperty("title_id") val title_id: Long,
 | 
			
		||||
    @JsonProperty("createdAt") val createdAt: String? = "",
 | 
			
		||||
    @JsonProperty("updated_at") val updatedAt: String? = "",
 | 
			
		||||
    @JsonProperty("episodes") val episodes: List<Episodejson>
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class Episodejson(
 | 
			
		||||
    @JsonProperty("id") val id: Long,
 | 
			
		||||
    @JsonProperty("number") val number: Long,
 | 
			
		||||
    @JsonProperty("name") val name: String? = "",
 | 
			
		||||
    @JsonProperty("plot") val plot: String? = "",
 | 
			
		||||
    @JsonProperty("season_id") val seasonID: Long,
 | 
			
		||||
    @JsonProperty("images") val images: List<ImageSeason>
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class ImageSeason(
 | 
			
		||||
    @JsonProperty("imageable_id") val imageableID: Long,
 | 
			
		||||
    @JsonProperty("imageable_type") val imageableType: String,
 | 
			
		||||
    @JsonProperty("server_id") val serverID: Long,
 | 
			
		||||
    @JsonProperty("proxy_id") val proxyID: Long,
 | 
			
		||||
    @JsonProperty("url") val url: String,
 | 
			
		||||
    @JsonProperty("type") val type: String,
 | 
			
		||||
    @JsonProperty("original_url") val originalURL: String
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
data class TrailerElement(
 | 
			
		||||
    @JsonProperty("id") val id: Long? = null,
 | 
			
		||||
    @JsonProperty("url") val url: String? = null,
 | 
			
		||||
    @JsonProperty("host") val host: String? = null,
 | 
			
		||||
    @JsonProperty("videoable_id") val videoableID: Long? = null,
 | 
			
		||||
    @JsonProperty("videoable_type") val videoableType: String? = null,
 | 
			
		||||
    @JsonProperty("created_at") val createdAt: String? = null,
 | 
			
		||||
    @JsonProperty("updated_at") val updatedAt: String? = null,
 | 
			
		||||
    @JsonProperty("size") val size: String? = null,
 | 
			
		||||
    @JsonProperty("created_by") val createdBy: String? = null,
 | 
			
		||||
    @JsonProperty("server_id") val serverID: Long? = null,
 | 
			
		||||
    @JsonProperty("name") val name: String? = null,
 | 
			
		||||
    @JsonProperty("quality") val quality: String? = null,
 | 
			
		||||
    @JsonProperty("original_name") val originalName: Any? = null,
 | 
			
		||||
    @JsonProperty("views") val views: Long? = null,
 | 
			
		||||
    @JsonProperty("public") val public: Long? = null,
 | 
			
		||||
    @JsonProperty("proxy_id") val proxyID: Any? = null,
 | 
			
		||||
    @JsonProperty("proxy_default_id") val proxyDefaultID: Any? = null,
 | 
			
		||||
    @JsonProperty("scws_id") val scwsID: Any? = null
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class StreamingcommunityProvider : MainAPI() {
 | 
			
		||||
    override val lang = "it"
 | 
			
		||||
    override var mainUrl = "https://streamingcommunity.top"
 | 
			
		||||
    override var name = "Streamingcommunity"
 | 
			
		||||
    override val hasMainPage = true
 | 
			
		||||
    override val hasChromecastSupport = true
 | 
			
		||||
    override val supportedTypes = setOf(
 | 
			
		||||
        TvType.Movie,
 | 
			
		||||
        TvType.TvSeries,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    private fun translatenumber(num: Int): Int? {
 | 
			
		||||
        return when (num) {
 | 
			
		||||
            67 -> 1
 | 
			
		||||
            71 -> 2
 | 
			
		||||
            72 -> 3
 | 
			
		||||
            73 -> 4
 | 
			
		||||
            74 -> 5
 | 
			
		||||
            75 -> 6
 | 
			
		||||
            76 -> 7
 | 
			
		||||
            77 -> 8
 | 
			
		||||
            78 -> 9
 | 
			
		||||
            79 -> 10
 | 
			
		||||
            133 -> 11
 | 
			
		||||
            else -> null
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun translateip(num: Int): String? {
 | 
			
		||||
        return when (num) {
 | 
			
		||||
            16 -> "sc-b1-01.scws-content.net"
 | 
			
		||||
            17 -> "sc-b1-02.scws-content.net"
 | 
			
		||||
            18 -> "sc-b1-03.scws-content.net"
 | 
			
		||||
            85 -> "sc-b1-04.scws-content.net"
 | 
			
		||||
            95 -> "sc-b1-05.scws-content.net"
 | 
			
		||||
            117 -> "sc-b1-06.scws-content.net"
 | 
			
		||||
            141 -> "sc-b1-07.scws-content.net"
 | 
			
		||||
            142 -> "sc-b1-08.scws-content.net"
 | 
			
		||||
            143 -> "sc-b1-09.scws-content.net"
 | 
			
		||||
            144 -> "sc-b1-10.scws-content.net"
 | 
			
		||||
            else -> null
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
        val posterMap = hashMapOf<String, String>()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun getMainPage(): HomePageResponse {
 | 
			
		||||
        val items = ArrayList<HomePageList>()
 | 
			
		||||
        val document = app.get(mainUrl).document
 | 
			
		||||
        document.select("slider-title").subList(2, 6).map { it ->
 | 
			
		||||
            if (it.attr("slider-name") != "In arrivo") {
 | 
			
		||||
                val films = it.attr("titles-json")
 | 
			
		||||
                val lista = mutableListOf<MovieSearchResponse>()
 | 
			
		||||
                val videoData = parseJson<List<VideoElement>>(films)
 | 
			
		||||
 | 
			
		||||
                videoData.subList(0, 12).map { searchr ->
 | 
			
		||||
                    val id = searchr.id
 | 
			
		||||
                    val name = searchr.slug
 | 
			
		||||
                    val img = searchr.images[0].url
 | 
			
		||||
                    val number = translatenumber(searchr.images[0].serverID.toInt())
 | 
			
		||||
                    val ip = translateip(searchr.images[0].proxyID.toInt())
 | 
			
		||||
                    val posterurl = "https://$ip/images/$number/$img"
 | 
			
		||||
                    val videourl = "$mainUrl/titles/$id-$name"
 | 
			
		||||
                    posterMap[videourl] = posterurl
 | 
			
		||||
                    val data = app.post("$mainUrl/api/titles/preview/$id", referer = mainUrl).text
 | 
			
		||||
                    val datajs = parseJson<Moviedata>(data)
 | 
			
		||||
                    val type: TvType = if (datajs.type == "movie") {
 | 
			
		||||
                        TvType.Movie
 | 
			
		||||
                    } else {
 | 
			
		||||
                        TvType.TvSeries
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    lista.add(
 | 
			
		||||
                        MovieSearchResponse(
 | 
			
		||||
                            datajs.name,
 | 
			
		||||
                            videourl,
 | 
			
		||||
                            this.name,
 | 
			
		||||
                            type,
 | 
			
		||||
                            posterurl,
 | 
			
		||||
                            datajs.releaseDate.substringBefore("-").filter { it.isDigit() }
 | 
			
		||||
                                .toIntOrNull(),
 | 
			
		||||
                            null,
 | 
			
		||||
                        )
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                items.add(HomePageList(it.attr("slider-name"), lista))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (items.size <= 0) throw ErrorLoadingException()
 | 
			
		||||
        return HomePageResponse(items)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun search(query: String): List<SearchResponse> {
 | 
			
		||||
        val queryformatted = query.replace(" ", "%20")
 | 
			
		||||
        val url = "$mainUrl/search?q=$queryformatted"
 | 
			
		||||
        val document = app.get(url).document
 | 
			
		||||
 | 
			
		||||
        val films =
 | 
			
		||||
            document.selectFirst("the-search-page").attr("records-json").replace(""", """"""")
 | 
			
		||||
 | 
			
		||||
        val searchresults = parseJson<List<VideoElement>>(films)
 | 
			
		||||
        return searchresults.map { result ->
 | 
			
		||||
            val id = result.id
 | 
			
		||||
            val name = result.slug
 | 
			
		||||
            val img = result.images[0].url
 | 
			
		||||
            val number = translatenumber(result.images[0].serverID.toInt())
 | 
			
		||||
            val ip = translateip(result.images[0].proxyID.toInt())
 | 
			
		||||
            val data = app.post("$mainUrl/api/titles/preview/$id", referer = mainUrl).text
 | 
			
		||||
            val datajs = parseJson<Moviedata>(data)
 | 
			
		||||
            val posterurl = "https://$ip/images/$number/$img"
 | 
			
		||||
            val videourl = "$mainUrl/titles/$id-$name"
 | 
			
		||||
            posterMap[videourl] = posterurl
 | 
			
		||||
            if (datajs.type == "movie") {
 | 
			
		||||
                val type = TvType.Movie
 | 
			
		||||
                MovieSearchResponse(
 | 
			
		||||
                    datajs.name,
 | 
			
		||||
                    videourl,
 | 
			
		||||
                    this.name,
 | 
			
		||||
                    type,
 | 
			
		||||
                    posterurl,
 | 
			
		||||
                    datajs.releaseDate.substringBefore("-").filter { it.isDigit() }.toIntOrNull(),
 | 
			
		||||
                    null,
 | 
			
		||||
                )
 | 
			
		||||
            } else {
 | 
			
		||||
                val type = TvType.TvSeries
 | 
			
		||||
                TvSeriesSearchResponse(
 | 
			
		||||
                    datajs.name,
 | 
			
		||||
                    videourl,
 | 
			
		||||
                    this.name,
 | 
			
		||||
                    type,
 | 
			
		||||
                    posterurl,
 | 
			
		||||
                    datajs.releaseDate.substringBefore("-").filter { it.isDigit() }.toIntOrNull(),
 | 
			
		||||
                    null,
 | 
			
		||||
                )
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun load(url: String): LoadResponse {
 | 
			
		||||
 | 
			
		||||
        val document = app.get(url).document
 | 
			
		||||
        val poster = posterMap[url]
 | 
			
		||||
        val id = url.substringBefore("-").filter { it.isDigit() }
 | 
			
		||||
        val data = app.post("$mainUrl/api/titles/preview/$id", referer = mainUrl).text
 | 
			
		||||
 | 
			
		||||
        val datajs = parseJson<Moviedata>(data)
 | 
			
		||||
        val type: TvType = if (datajs.type == "movie") {
 | 
			
		||||
            TvType.Movie
 | 
			
		||||
        } else {
 | 
			
		||||
            TvType.TvSeries
 | 
			
		||||
        }
 | 
			
		||||
        val trailerinfojs = document.select("slider-trailer").attr("videos")
 | 
			
		||||
        val trailerinfo = parseJson<List<TrailerElement>>(trailerinfojs)
 | 
			
		||||
        val trailerurl: String? = if (trailerinfo.isNotEmpty()) {
 | 
			
		||||
            "https://www.youtube.com/watch?v=${trailerinfo[0].id}"
 | 
			
		||||
        } else {
 | 
			
		||||
            null
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        val year = datajs.releaseDate.substringBefore("-")
 | 
			
		||||
 | 
			
		||||
        val correlatijs = document.selectFirst("slider-title").attr("titles-json")
 | 
			
		||||
        val listacorr = mutableListOf<MovieSearchResponse>()
 | 
			
		||||
        val correlatidata = parseJson<List<VideoElement>>(correlatijs)
 | 
			
		||||
        val number : Int = if (correlatidata.size<=15) {correlatidata.size} else correlatidata.size-15
 | 
			
		||||
 | 
			
		||||
        correlatidata.take(number).map { searchr ->
 | 
			
		||||
            val idcorr = searchr.id
 | 
			
		||||
            val name = searchr.slug
 | 
			
		||||
            val img = searchr.images[0].url
 | 
			
		||||
            val number = translatenumber(searchr.images[0].serverID.toInt())
 | 
			
		||||
            val ip = translateip(searchr.images[0].proxyID.toInt())
 | 
			
		||||
            val datacorrel = app.post("$mainUrl/api/titles/preview/$idcorr", referer = mainUrl).text
 | 
			
		||||
            val datajscorrel = parseJson<Moviedata>(datacorrel)
 | 
			
		||||
            val videourl = "$mainUrl/titles/$idcorr-$name"
 | 
			
		||||
            val posterurl = "https://$ip/images/$number/$img"
 | 
			
		||||
 | 
			
		||||
            posterMap[videourl] = posterurl
 | 
			
		||||
            val typecorr: TvType = if (datajscorrel.type == "movie") {
 | 
			
		||||
                TvType.Movie
 | 
			
		||||
            } else {
 | 
			
		||||
                TvType.TvSeries
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            listacorr.add(
 | 
			
		||||
                MovieSearchResponse(
 | 
			
		||||
                    datajscorrel.name,
 | 
			
		||||
                    videourl,
 | 
			
		||||
                    this.name,
 | 
			
		||||
                    typecorr,
 | 
			
		||||
                    posterurl,
 | 
			
		||||
                    datajscorrel.releaseDate.substringBefore("-").filter { it.isDigit() }
 | 
			
		||||
                        .toIntOrNull(),
 | 
			
		||||
                    null,
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (type == TvType.TvSeries) {
 | 
			
		||||
 | 
			
		||||
            val name = datajs.name
 | 
			
		||||
            val episodeList = arrayListOf<Episode>()
 | 
			
		||||
 | 
			
		||||
            val episodes =
 | 
			
		||||
                Html.fromHtml(document.selectFirst("season-select").attr("seasons")).toString()
 | 
			
		||||
            val jsonEpisodes = parseJson<List<Season>>(episodes)
 | 
			
		||||
 | 
			
		||||
            jsonEpisodes.map { seasons ->
 | 
			
		||||
                val stagione = seasons.number.toInt()
 | 
			
		||||
                val sid = seasons.title_id
 | 
			
		||||
                val episodio = seasons.episodes
 | 
			
		||||
                episodio.map { ep ->
 | 
			
		||||
                    val href = "$mainUrl/watch/$sid?e=${ep.id}"
 | 
			
		||||
                    val postimage = if (ep.images.isNotEmpty()) {
 | 
			
		||||
                        ep.images.first().originalURL
 | 
			
		||||
                    } else {
 | 
			
		||||
                        ""
 | 
			
		||||
                    }
 | 
			
		||||
                    episodeList.add(
 | 
			
		||||
 | 
			
		||||
                        newEpisode(href) {
 | 
			
		||||
                            this.name = ep.name
 | 
			
		||||
                            this.season = stagione
 | 
			
		||||
                            this.episode = ep.number.toInt()
 | 
			
		||||
                            this.description = ep.plot
 | 
			
		||||
                            this.posterUrl = postimage
 | 
			
		||||
                        }
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            if (episodeList.isEmpty()) throw ErrorLoadingException("No Seasons Found")
 | 
			
		||||
 | 
			
		||||
            return newTvSeriesLoadResponse(name, url, type, episodeList) {
 | 
			
		||||
                this.posterUrl = poster
 | 
			
		||||
                this.year = year.filter { it.isDigit() }.toInt()
 | 
			
		||||
                this.plot = document.selectFirst("div.plot-wrap > p").text()
 | 
			
		||||
                this.duration = datajs.runtime?.toInt()
 | 
			
		||||
                this.rating = (datajs.votes[0].average.toFloatOrNull()?.times(1000))?.toInt()
 | 
			
		||||
                this.tags = datajs.genres.map { it.name }
 | 
			
		||||
                addTrailer(trailerurl)
 | 
			
		||||
                this.recommendations = listacorr
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
 | 
			
		||||
            return newMovieLoadResponse(
 | 
			
		||||
                document.selectFirst("div > div > h1").text(),
 | 
			
		||||
                document.select("a.play-hitzone").attr("href"),
 | 
			
		||||
                type,
 | 
			
		||||
                document.select("a.play-hitzone").attr("href")
 | 
			
		||||
            ) {
 | 
			
		||||
                posterUrl = fixUrlNull(poster)
 | 
			
		||||
                this.year = year.filter { it.isDigit() }.toInt()
 | 
			
		||||
                this.plot = document.selectFirst("p.plot").text()
 | 
			
		||||
                this.rating = datajs.votes[0].average.toFloatOrNull()?.times(1000)?.toInt()
 | 
			
		||||
                this.tags = datajs.genres.map { it.name }
 | 
			
		||||
                this.duration = datajs.runtime?.toInt()
 | 
			
		||||
                addTrailer(trailerurl)
 | 
			
		||||
                this.recommendations = listacorr
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private fun getM3u8Qualities(
 | 
			
		||||
        m3u8Link: String,
 | 
			
		||||
        referer: String,
 | 
			
		||||
        qualityName: String,
 | 
			
		||||
    ): List<ExtractorLink> {
 | 
			
		||||
        return M3u8Helper.generateM3u8(
 | 
			
		||||
            this.name,
 | 
			
		||||
            m3u8Link,
 | 
			
		||||
            referer,
 | 
			
		||||
            name = "${this.name} - $qualityName"
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    override suspend fun loadLinks(
 | 
			
		||||
        data: String,
 | 
			
		||||
        isCasting: Boolean,
 | 
			
		||||
        subtitleCallback: (SubtitleFile) -> Unit,
 | 
			
		||||
        callback: (ExtractorLink) -> Unit
 | 
			
		||||
    ): Boolean {
 | 
			
		||||
        val ip = app.get("https://api.ipify.org/").text
 | 
			
		||||
        val videors = app.get(data).document
 | 
			
		||||
        val scwsidjs = videors.select("video-player").attr("response").replace(""", """"""")
 | 
			
		||||
        val jsn = JSONObject(scwsidjs)
 | 
			
		||||
        val scwsid = jsn.getString("scws_id")
 | 
			
		||||
        val expire = (System.currentTimeMillis() / 1000 + 172800).toString()
 | 
			
		||||
 | 
			
		||||
        val uno = "$expire$ip Yc8U6r8KjAKAepEA".toByteArray()
 | 
			
		||||
        val due = MessageDigest.getInstance("MD5").digest(uno)
 | 
			
		||||
        val tre = base64Encode(due)
 | 
			
		||||
        val token = tre.replace("=", "").replace("+", "-").replace("/", "_")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        val link = "https://scws.xyz/master/$scwsid?token=$token&expires=$expire&n=1&n=1"
 | 
			
		||||
        getM3u8Qualities(link, data, URI(link).host).forEach(callback)
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,243 @@
 | 
			
		|||
package com.lagradost.cloudstream3.movieproviders
 | 
			
		||||
 | 
			
		||||
import com.lagradost.cloudstream3.*
 | 
			
		||||
import com.lagradost.cloudstream3.mvvm.logError
 | 
			
		||||
import com.lagradost.cloudstream3.app
 | 
			
		||||
import com.lagradost.cloudstream3.utils.*
 | 
			
		||||
 | 
			
		||||
class TantifilmProvider : MainAPI() {
 | 
			
		||||
    override val lang = "it"
 | 
			
		||||
    override var mainUrl = "https://www.tantifilm.rodeo"
 | 
			
		||||
    override var name = "Tantifilm"
 | 
			
		||||
    override val hasMainPage = true
 | 
			
		||||
    override val hasChromecastSupport = true
 | 
			
		||||
    override val supportedTypes = setOf(
 | 
			
		||||
        TvType.Movie,
 | 
			
		||||
        TvType.TvSeries,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    override suspend fun getMainPage(): HomePageResponse {
 | 
			
		||||
        val items = ArrayList<HomePageList>()
 | 
			
		||||
        val urls = listOf(
 | 
			
		||||
            Pair("$mainUrl/watch-genre/serie-tv/", "Serie Tv"),
 | 
			
		||||
            Pair("$mainUrl/watch-genre/azione/", "Azione"),
 | 
			
		||||
            Pair("$mainUrl/watch-genre/avventura/", "Avventura"),
 | 
			
		||||
        )
 | 
			
		||||
        for ((url, name) in urls) {
 | 
			
		||||
            try {
 | 
			
		||||
                val soup = app.get(url).document
 | 
			
		||||
                val home = soup.select("div.media3").map {
 | 
			
		||||
                    val title = it.selectFirst("p").text().substringBefore("(")
 | 
			
		||||
                    val link = it.selectFirst("a").attr("href")
 | 
			
		||||
                    TvSeriesSearchResponse(
 | 
			
		||||
                        title,
 | 
			
		||||
                        link,
 | 
			
		||||
                        this.name,
 | 
			
		||||
                        TvType.Movie,
 | 
			
		||||
                        it.selectFirst("img").attr("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 queryformatted = query.replace(" ", "+")
 | 
			
		||||
        val url = "$mainUrl/search/$queryformatted"
 | 
			
		||||
        val doc = app.get(url).document
 | 
			
		||||
        return doc.select("div.film.film-2").map {
 | 
			
		||||
            val href = it.selectFirst("a").attr("href")
 | 
			
		||||
            val poster = it.selectFirst("img").attr("src")
 | 
			
		||||
            val name = it.selectFirst("a").text().substringBefore("(")
 | 
			
		||||
            MovieSearchResponse(
 | 
			
		||||
                name,
 | 
			
		||||
                href,
 | 
			
		||||
                this.name,
 | 
			
		||||
                TvType.Movie,
 | 
			
		||||
                poster,
 | 
			
		||||
                null
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    override suspend fun load(url: String): LoadResponse {
 | 
			
		||||
        val document = app.get(url).document
 | 
			
		||||
        val type = if (document.selectFirst("div.category-film").text().contains("Serie")
 | 
			
		||||
                .not()
 | 
			
		||||
        ) TvType.Movie else TvType.TvSeries
 | 
			
		||||
        val title = document.selectFirst("div.title-film-left").text().substringBefore("(")
 | 
			
		||||
        val descipt = document.select("div.content-left-film > p").map { it.text() }
 | 
			
		||||
        val rating =
 | 
			
		||||
            document.selectFirst("div.star-rating.star-rating-f > span > span")
 | 
			
		||||
                .attr("data-rateit-value")?.toFloatOrNull()
 | 
			
		||||
                ?.times(2857)?.toInt()?.let { minOf(it, 10000) }
 | 
			
		||||
 | 
			
		||||
        var year = document.selectFirst("div.title-film-left").text().substringAfter("(")
 | 
			
		||||
            .filter { it.isDigit() }
 | 
			
		||||
        if (year.length > 4) {
 | 
			
		||||
            year = year.dropLast(4)
 | 
			
		||||
        } else {
 | 
			
		||||
            year = year
 | 
			
		||||
        }
 | 
			
		||||
        // ?: does not wor
 | 
			
		||||
        val poster = document.selectFirst("div.image-right-film > img").attr("src")
 | 
			
		||||
 | 
			
		||||
        val recomm = document.select("div.mediaWrap.mediaWrapAlt.recomended_videos").map {
 | 
			
		||||
            val href = it.selectFirst("a").attr("href")
 | 
			
		||||
            val poster = it.selectFirst("img").attr("src")
 | 
			
		||||
            val name = it.selectFirst("a").attr("title").substringBeforeLast("(")
 | 
			
		||||
            MovieSearchResponse(
 | 
			
		||||
                name,
 | 
			
		||||
                href,
 | 
			
		||||
                this.name,
 | 
			
		||||
                TvType.Movie,
 | 
			
		||||
                poster,
 | 
			
		||||
                null
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        if (type == TvType.TvSeries) {
 | 
			
		||||
            val list = ArrayList<Pair<Int, String>>()
 | 
			
		||||
            val urlvideocontainer = document.selectFirst("iframe").attr("src")
 | 
			
		||||
            val videocontainer = app.get(urlvideocontainer).document
 | 
			
		||||
            videocontainer.select("nav.nav1 > select > option").forEach { element ->
 | 
			
		||||
                val season = element.text()?.toIntOrNull()
 | 
			
		||||
                val href = element.attr("value")
 | 
			
		||||
                if (season != null && season > 0 && !href.isNullOrBlank()) {
 | 
			
		||||
                    list.add(Pair(season, fixUrl(href)))
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (list.isEmpty()) throw ErrorLoadingException("No Seasons Found")
 | 
			
		||||
 | 
			
		||||
            val episodeList = ArrayList<Episode>()
 | 
			
		||||
 | 
			
		||||
            for ((season,seasonurl) in list) {
 | 
			
		||||
                val seasonDocument = app.get(seasonurl).document
 | 
			
		||||
                val episodes = seasonDocument.select("nav.second_nav > select > option")
 | 
			
		||||
                if (episodes.isNotEmpty()) {
 | 
			
		||||
                    episodes.forEach { episode ->
 | 
			
		||||
                        val href = episode.attr("value")
 | 
			
		||||
                        val epNum = episode.text()?.toIntOrNull()
 | 
			
		||||
                        episodeList.add(
 | 
			
		||||
                            Episode(
 | 
			
		||||
                                href,
 | 
			
		||||
                                title,
 | 
			
		||||
                                season,
 | 
			
		||||
                                epNum,
 | 
			
		||||
                            )
 | 
			
		||||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return TvSeriesLoadResponse(
 | 
			
		||||
                title,
 | 
			
		||||
                url,
 | 
			
		||||
                this.name,
 | 
			
		||||
                type,
 | 
			
		||||
                episodeList,
 | 
			
		||||
                fixUrlNull(poster),
 | 
			
		||||
                year?.toIntOrNull(),
 | 
			
		||||
                descipt[0],
 | 
			
		||||
                null,
 | 
			
		||||
                rating,
 | 
			
		||||
                null,
 | 
			
		||||
                null,
 | 
			
		||||
                null,
 | 
			
		||||
                recomm
 | 
			
		||||
            )
 | 
			
		||||
        } else {
 | 
			
		||||
            val url2 = document.selectFirst("iframe").attr("src")
 | 
			
		||||
            val actorpagelink =
 | 
			
		||||
                document.select("div.content-left-film > p:nth-child(2) > a").attr("href")
 | 
			
		||||
            val actorpagelink2 = document.select("div.content-left-film > p > a").attr("href")
 | 
			
		||||
            val Linkactor: String = if (actorpagelink.isNotEmpty()) {
 | 
			
		||||
                actorpagelink
 | 
			
		||||
            } else {
 | 
			
		||||
                actorpagelink2
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val actors: List<ActorData>? = if (Linkactor.isNotEmpty()) {
 | 
			
		||||
                val actorpage = app.get(Linkactor + "cast/").document
 | 
			
		||||
                actorpage.select("article.membro-cast")?.filter {
 | 
			
		||||
                    it.selectFirst("img")
 | 
			
		||||
                        ?.attr("src") != "https://www.filmtv.it/imgbank/DUMMY/no_portrait.jpg"
 | 
			
		||||
                }?.mapNotNull { it ->
 | 
			
		||||
                    val name = it.selectFirst("div.info > h3").text()
 | 
			
		||||
                    val image = it.selectFirst("img")?.attr("src")
 | 
			
		||||
                    val roleString: String = if (it.selectFirst("h2")?.text() == "Regia") {
 | 
			
		||||
                        "Regia"
 | 
			
		||||
                    } else {
 | 
			
		||||
                        "Attore"
 | 
			
		||||
                    }
 | 
			
		||||
                    val mainActor = Actor(name, image)
 | 
			
		||||
                    ActorData(actor = mainActor, roleString = roleString)
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                null
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            val duratio: Int? = if (descipt.size == 2) {
 | 
			
		||||
                descipt[0].filter { it.isDigit() }.toInt()
 | 
			
		||||
            } else {
 | 
			
		||||
                null
 | 
			
		||||
            }
 | 
			
		||||
            val tags: List<String>? = if (descipt.size == 2) {
 | 
			
		||||
                descipt[0].let { mutableListOf(it.substringBefore(" ")) }
 | 
			
		||||
            } else {
 | 
			
		||||
                null
 | 
			
		||||
            }
 | 
			
		||||
            val plot: String = if (descipt.size == 2) {
 | 
			
		||||
                descipt[1]
 | 
			
		||||
            } else {
 | 
			
		||||
                descipt[0]
 | 
			
		||||
            }
 | 
			
		||||
            return newMovieLoadResponse(
 | 
			
		||||
                title,
 | 
			
		||||
                url2,
 | 
			
		||||
                type,
 | 
			
		||||
                url2
 | 
			
		||||
            ) {
 | 
			
		||||
                posterUrl = fixUrlNull(poster)
 | 
			
		||||
                this.year = year?.toIntOrNull()
 | 
			
		||||
                this.plot = plot
 | 
			
		||||
                this.rating = rating
 | 
			
		||||
                this.recommendations = recomm
 | 
			
		||||
                this.tags = tags
 | 
			
		||||
                this.duration = duratio
 | 
			
		||||
                this.actors = actors
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun loadLinks(
 | 
			
		||||
        data: String,
 | 
			
		||||
        isCasting: Boolean,
 | 
			
		||||
        subtitleCallback: (SubtitleFile) -> Unit,
 | 
			
		||||
        callback: (ExtractorLink) -> Unit
 | 
			
		||||
    ): Boolean {
 | 
			
		||||
        val doc = app.get(data).document
 | 
			
		||||
        val iframe =
 | 
			
		||||
            doc.select("option").map { fixUrl(it.attr("value")) }.filter { it.contains("label") }
 | 
			
		||||
        iframe.forEach { id ->
 | 
			
		||||
            val doc2 = app.get(id).document
 | 
			
		||||
            val id2 = app.get(doc2.selectFirst("iframe").attr("src")).url
 | 
			
		||||
            loadExtractor(id2, data, callback)
 | 
			
		||||
        }
 | 
			
		||||
        return true
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue