lookmovie almost done

This commit is contained in:
LagradOst 2021-06-24 19:45:59 +02:00
parent 7060843ebc
commit 5c3691ee2e
5 changed files with 211 additions and 12 deletions

View file

@ -7,7 +7,8 @@ import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.lagradost.cloudstream3.animeproviders.DubbedAnimeProvider import com.lagradost.cloudstream3.animeproviders.DubbedAnimeProvider
import com.lagradost.cloudstream3.animeproviders.ShiroProvider import com.lagradost.cloudstream3.animeproviders.ShiroProvider
import com.lagradost.cloudstream3.movieproviders.HDMMoveProvider import com.lagradost.cloudstream3.movieproviders.HDMProvider
import com.lagradost.cloudstream3.movieproviders.LookMovieProvider
import com.lagradost.cloudstream3.movieproviders.MeloMovieProvider import com.lagradost.cloudstream3.movieproviders.MeloMovieProvider
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import java.util.* import java.util.*
@ -30,7 +31,8 @@ object APIHolder {
ShiroProvider(), ShiroProvider(),
MeloMovieProvider(), MeloMovieProvider(),
DubbedAnimeProvider(), DubbedAnimeProvider(),
HDMMoveProvider(), HDMProvider(),
LookMovieProvider(),
) )
fun getApiFromName(apiName: String?): MainAPI { fun getApiFromName(apiName: String?): MainAPI {
@ -73,6 +75,12 @@ abstract class MainAPI {
} }
} }
fun parseRating(ratingString : String?) : Int? {
if(ratingString == null) return null
val floatRating = ratingString.toFloatOrNull() ?: return null
return (floatRating * 10).toInt()
}
fun MainAPI.fixUrl(url: String): String { fun MainAPI.fixUrl(url: String): String {
if(url.startsWith("http")) { if(url.startsWith("http")) {
return url return url
@ -168,6 +176,7 @@ interface LoadResponse {
val posterUrl: String? val posterUrl: String?
val year: Int? val year: Int?
val plot: String? val plot: String?
val rating : Int? // 0-100
} }
fun LoadResponse?.isEpisodeBased(): Boolean { fun LoadResponse?.isEpisodeBased(): Boolean {
@ -203,6 +212,7 @@ data class AnimeLoadResponse(
val malId: Int? = null, val malId: Int? = null,
val anilistId: Int? = null, val anilistId: Int? = null,
override val rating: Int? = null,
) : LoadResponse ) : LoadResponse
data class MovieLoadResponse( data class MovieLoadResponse(
@ -217,6 +227,7 @@ data class MovieLoadResponse(
override val plot: String?, override val plot: String?,
val imdbId: Int?, val imdbId: Int?,
override val rating: Int? = null,
) : LoadResponse ) : LoadResponse
data class TvSeriesEpisode(val name: String?, val season: Int?, val episode: Int?, val data: String) data class TvSeriesEpisode(val name: String?, val season: Int?, val episode: Int?, val data: String)
@ -234,4 +245,5 @@ data class TvSeriesLoadResponse(
val showStatus: ShowStatus?, val showStatus: ShowStatus?,
val imdbId: Int?, val imdbId: Int?,
override val rating: Int? = null,
) : LoadResponse ) : LoadResponse

View file

@ -174,10 +174,8 @@ class ShiroProvider : MainAPI() {
) )
}?token=$token".replace("+", "%20")) }?token=$token".replace("+", "%20"))
if (response.text == "{\"status\":\"Found\",\"data\":[]}") return returnValue // OR ELSE WILL CAUSE WEIRD ERROR if (response.text == "{\"status\":\"Found\",\"data\":[]}") return returnValue // OR ELSE WILL CAUSE WEIRD ERROR
println("QUICK: " + response.text)
val mapped = response.let { mapper.readValue<ShiroSearchResponse>(it.text) } val mapped = response.let { mapper.readValue<ShiroSearchResponse>(it.text) }
println("SIZE: " + mapped.data.size)
println("TOTAL: " + mapped)
for (i in mapped.data) { for (i in mapped.data) {
returnValue.add(turnSearchIntoResponse(i)) returnValue.add(turnSearchIntoResponse(i))
} }

View file

@ -5,7 +5,7 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import org.jsoup.Jsoup import org.jsoup.Jsoup
class HDMMoveProvider : MainAPI() { class HDMProvider : MainAPI() {
override val name: String override val name: String
get() = "HD Movies" get() = "HD Movies"
override val mainUrl: String override val mainUrl: String

View file

@ -0,0 +1,187 @@
package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.ExtractorLink
import org.jsoup.Jsoup
class LookMovieProvider : MainAPI() {
override val hasQuickSearch: Boolean
get() = true
override val name: String
get() = "LookMovie"
override val mainUrl: String
get() = "https://lookmovie.io"
data class LookMovieSearchResult(
@JsonProperty("backdrop") val backdrop: String?,
@JsonProperty("imdb_rating") val imdb_rating: String,
@JsonProperty("poster") val poster: String?,
@JsonProperty("slug") val slug: String,
@JsonProperty("title") val title: String,
@JsonProperty("year") val year: String?,
// @JsonProperty("flag_quality") val flag_quality: Int?,
)
data class LookMovieSearchResultRoot(
// @JsonProperty("per_page") val per_page: Int?,
// @JsonProperty("total") val total: Int?,
@JsonProperty("result") val result: List<LookMovieSearchResult>?,
)
data class LookMovieEpisode(
@JsonProperty("title") var title: String,
@JsonProperty("index") var index: String,
@JsonProperty("episode") var episode: String,
@JsonProperty("id_episode") var idEpisode: Int,
@JsonProperty("season") var season: String,
)
override fun quickSearch(query: String): ArrayList<SearchResponse>? {
val movieUrl = "$mainUrl/api/v1/movies/search/?q=$query"
val movieResponse = khttp.get(movieUrl)
val movies = mapper.readValue<LookMovieSearchResultRoot>(movieResponse.text).result
val showsUrl = "$mainUrl/api/v1/shows/search/?q=$query"
val showsResponse = khttp.get(showsUrl)
val shows = mapper.readValue<LookMovieSearchResultRoot>(showsResponse.text).result
val returnValue = ArrayList<SearchResponse>()
if (!movies.isNullOrEmpty()) {
for (m in movies) {
val url = "$mainUrl/movies/view/${m.slug}"
returnValue.add(MovieSearchResponse(m.title,
url,
url,//m.slug,
this.name,
TvType.Movie,
m.poster ?: m.backdrop,
m.year?.toIntOrNull()))
}
}
if (!shows.isNullOrEmpty()) {
for (s in shows) {
val url = "$mainUrl/shows/view/${s.slug}"
returnValue.add(MovieSearchResponse(s.title,
url,
url,//s.slug,
this.name,
TvType.TvSeries,
s.poster ?: s.backdrop,
s.year?.toIntOrNull()))
}
}
return returnValue
}
override fun search(query: String): ArrayList<SearchResponse> {
fun search(query: String, isMovie: Boolean): ArrayList<SearchResponse> {
val url = "$mainUrl/${if (isMovie) "movies" else "shows"}/search/?q=$query"
val response = khttp.get(url)
val document = Jsoup.parse(response.text)
val items = document.select("div.flex-wrap-movielist > div.movie-item-style-1")
val returnValue = ArrayList<SearchResponse>()
items.forEach { item ->
val titleHolder = item.selectFirst("> div.mv-item-infor > h6 > a")
val href = fixUrl(titleHolder.attr("href"))
val name = titleHolder.text()
val posterHolder = item.selectFirst("> div.image__placeholder > a")
val poster = posterHolder.selectFirst("> img")?.attr("data-src")
val year = posterHolder.selectFirst("> p.year")?.text()?.toIntOrNull()
returnValue.add(if (isMovie) {
MovieSearchResponse(
name, href, href, this.name, TvType.Movie, poster, year
)
} else
TvSeriesSearchResponse(
name, href, href, this.name, TvType.TvSeries, poster, year, null
)
)
}
return returnValue
}
val movieList = search(query, true)
val seriesList = search(query, false)
movieList.addAll(seriesList)
return movieList
}
override fun loadLinks(data: String, isCasting: Boolean, callback: (ExtractorLink) -> Unit): Boolean {
return super.loadLinks(data, isCasting, callback)
}
override fun load(slug: String): LoadResponse? {
val response = khttp.get(slug)
val document = Jsoup.parse(response.text)
val isMovie = slug.contains("/movies/")
val watchHeader = document.selectFirst("div.watch-heading")
val nameHeader = watchHeader.selectFirst("> h1.bd-hd")
val year = nameHeader.selectFirst("> span")?.text()?.toIntOrNull()
val name = nameHeader.ownText()
val rating = parseRating(watchHeader.selectFirst("> div.movie-rate > div.rate > p > span").text())
val img = document.selectFirst("div.movie-img > p.movie__poster")?.attr("style")
val poster = if (img.isNullOrEmpty()) null else "url\\((.*?)\\)".toRegex().find(img)?.groupValues?.get(1)
val descript = document.selectFirst("p.description-short").text()
val id = "${if (isMovie) "id_movie" else "id_show"}:(.*?),".toRegex().find(response.text)?.groupValues?.get(1)?.replace(" ", "")
?: return null
val realSlug = slug.replace("$mainUrl/${if (isMovie) "movies" else "shows"}/view/", "")
val realUrl =
"$mainUrl/api/v1/security/${if (isMovie) "movie" else "show"}-access?${if (isMovie) "id_movie=$id" else "slug=$realSlug"}&token=1&sk=&step=1"
println("URLLLL:::: " + realUrl)
//https://lookmovie.io/api/v1/security/show-access?slug=9140554-loki-2021&token=&sk=null&step=1
//https://lookmovie.io/api/v1/security/movie-access?id_movie=11582&token=1&sk=&step=1
if (isMovie) {
return MovieLoadResponse(name, slug, this.name, TvType.Movie, id, poster, year, descript, null, rating)
} else {
val window =
"window\\[\\'show_storage\\'\\] =((.|\\n)*?\\<)".toRegex().find(response.text)?.groupValues?.get(1)
?: return null
// val id = "id_show:(.*?),".toRegex().find(response.text)?.groupValues?.get(1) ?: return null
val season = "seasons:.*\\[((.|\\n)*?)]".toRegex().find(window)?.groupValues?.get(1) ?: return null
fun String.fixSeasonJson(replace: String): String {
return this.replace("$replace:", "\"$replace\":")
}
//https://lookmovie.io/api/v1/security/show-access?slug=9140554-loki-2021&token=&sk=null&step=1
//https://lookmovie.io/manifests/shows/json/TGv3dO0pcwomftMrywOnmw/1624571222/128848/master.m3u8
//https://lookmovie.io/api/v1/shows/episode-subtitles/?id_episode=128848
val json = season
.replace("\'", "\"")
.fixSeasonJson("title")
.fixSeasonJson("id_episode")
.fixSeasonJson("episode")
.fixSeasonJson("index")
.fixSeasonJson("season")
val realJson = "[" + json.substring(0,json.lastIndexOf(',')) + "]"
val episodes = mapper.readValue<List<LookMovieEpisode>>(realJson).map {
TvSeriesEpisode(it.title, it.season.toIntOrNull(), it.episode.toIntOrNull(), it.idEpisode.toString())
}.toList()
return TvSeriesLoadResponse(name,
slug,
this.name,
TvType.TvSeries,
ArrayList(episodes),
poster,
year,
descript,
null,
null,
rating)
}
//watch-heading
}
}

View file

@ -94,6 +94,7 @@ class SearchAdapter(
cardText.text = card.name cardText.text = card.name
//imageTextProvider.text = card.apiName //imageTextProvider.text = card.apiName
if (!card.posterUrl.isNullOrEmpty()) {
val glideUrl = val glideUrl =
GlideUrl(card.posterUrl) GlideUrl(card.posterUrl)
@ -102,6 +103,7 @@ class SearchAdapter(
.load(glideUrl) .load(glideUrl)
.into(cardView) .into(cardView)
} }
}
bg.setOnClickListener { bg.setOnClickListener {
(activity as AppCompatActivity).loadResult(card.url, card.slug, card.apiName) (activity as AppCompatActivity).loadResult(card.url, card.slug, card.apiName)