quick search

This commit is contained in:
LagradOst 2021-06-17 18:20:05 +02:00
parent 850be93a8b
commit 9e434030a4
8 changed files with 179 additions and 42 deletions

View file

@ -1,6 +1,8 @@
package com.lagradost.cloudstream3
import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.mvvm.safeApiCall
class AllProvider : MainAPI() {
override val name: String
@ -8,11 +10,51 @@ class AllProvider : MainAPI() {
var providersActive = HashSet<String>()
override fun quickSearch(query: String): ArrayList<Any>? {
val list = apis.filter { a ->
a.name != this.name && (providersActive.size == 0 || providersActive.contains(a.name))
}.filter { a -> a.hasQuickSearch }.pmap { a ->
normalSafeApiCall {
a.quickSearch(query)
}
}
var maxCount = 0
var providerCount = 0
for (res in list) {
if (res != null) {
if (res.size > maxCount) {
maxCount = res.size
}
providerCount++
}
}
println("PROV: " + providerCount + "|" + maxCount)
if (providerCount == 0) return null
if (maxCount == 0) return ArrayList()
val result = ArrayList<Any>()
for (i in 0..maxCount) {
for (res in list) {
if (res != null) {
if (i < res.size) {
result.add(res[i])
}
}
}
}
return result
}
override fun search(query: String): ArrayList<Any>? {
val list = apis.filter { a ->
a.name != this.name && (providersActive.size == 0 || providersActive.contains(a.name))
}.pmap { a ->
a.search(query)
normalSafeApiCall {
a.search(query)
}
}
var maxCount = 0

View file

@ -17,6 +17,9 @@ val mapper = JsonMapper.builder().addModule(KotlinModule())
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build()!!
object APIHolder {
val unixTime: Long
get() = System.currentTimeMillis() / 1000L
val allApi = AllProvider()
private const val defProvider = 0
@ -47,10 +50,15 @@ abstract class MainAPI {
open val name = "NONE"
open val mainUrl = "NONE"
open val instantLinkLoading = false // THIS IS IF THE LINK IS STORED IN THE "DATA"
open val hasQuickSearch = false
open fun search(query: String): ArrayList<Any>? { // SearchResponse
return null
}
open fun quickSearch(query: String) : ArrayList<Any>? {
return null
}
open fun load(slug: String): Any? { //LoadResponse
return null
}
@ -74,13 +82,6 @@ fun sortUrls(urls: List<ExtractorLink>): List<ExtractorLink> {
return urls.sortedBy { t -> -t.quality }
}
data class Link(
val name: String,
val url: String,
val quality: Int?,
val referer: String?,
)
enum class ShowStatus {
Completed,
Ongoing,

View file

@ -0,0 +1,30 @@
package com.lagradost.cloudstream3.animeproviders
import com.lagradost.cloudstream3.APIHolder.unixTime
import com.lagradost.cloudstream3.MainAPI
import com.lagradost.cloudstream3.mapper
class DubbedAnimeProvider : MainAPI() {
override val mainUrl: String
get() = "https://bestdubbedanime.com"
override val name: String
get() = "DubbedAnime"
override val hasQuickSearch: Boolean
get() = true
override fun quickSearch(query: String): ArrayList<Any>? {
val url = "$mainUrl/xz/searchgrid.php?p=1&limit=12&s=$query&_=${unixTime}"
val response = khttp.get(url)
return super.quickSearch(query)
}
/*
override fun search(query: String): ArrayList<Any>? {
val url = "$mainUrl/search/$query"
mapper.readValue<>()
return super.search(query)
}*/
}

View file

@ -14,7 +14,7 @@ class ShiroProvider : MainAPI() {
companion object {
var token: String? = null
fun getType(t: String): TvType {
fun getType(t: String?): TvType {
return when (t) {
"TV" -> TvType.Anime
"OVA" -> TvType.ONA
@ -52,14 +52,17 @@ class ShiroProvider : MainAPI() {
override val name: String
get() = "Shiro"
override val hasQuickSearch: Boolean
get() = true
data class ShiroSearchResponseShow(
@JsonProperty("image") val image: String,
@JsonProperty("_id") val _id: String,
@JsonProperty("slug") val slug: String,
@JsonProperty("name") val name: String,
@JsonProperty("episodeCount") val episodeCount: String,
@JsonProperty("language") val language: String,
@JsonProperty("type") val type: String,
@JsonProperty("episodeCount") val episodeCount: String?,
@JsonProperty("language") val language: String?,
@JsonProperty("type") val type: String?,
@JsonProperty("year") val year: String?,
@JsonProperty("canonicalTitle") val canonicalTitle: String,
@JsonProperty("english") val english: String?,
@ -131,6 +134,56 @@ class ShiroProvider : MainAPI() {
@JsonProperty("status") val status: String,
)
private fun turnSearchIntoResponse(data: ShiroSearchResponseShow): AnimeSearchResponse {
val type = getType(data.type)
val isDubbed =
if (data.language != null)
data.language == "dubbed"
else
data.slug.contains("dubbed")
val set: EnumSet<DubStatus> = EnumSet.noneOf(DubStatus::class.java)
if (isDubbed)
set.add(DubStatus.Dubbed)
else
set.add(DubStatus.Subbed)
val episodeCount = data.episodeCount?.toIntOrNull()
return AnimeSearchResponse(
data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle,
"$mainUrl/anime/${data.slug}",
data.slug,
this.name,
type,
"https://cdn.shiro.is/${data.image}",
data.year?.toIntOrNull(),
data.canonicalTitle,
set,
if (isDubbed) episodeCount else null,
if (!isDubbed) episodeCount else null,
)
}
override fun quickSearch(query: String): ArrayList<Any> {
val returnValue: ArrayList<Any> = ArrayList()
val response = khttp.get("https://tapi.shiro.is/anime/auto-complete/${
URLEncoder.encode(
query,
"UTF-8"
)
}?token=$token".replace("+", "%20"))
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) }
println("SIZE: " + mapped.data.size)
println("TOTAL: " + mapped)
for (i in mapped.data) {
returnValue.add(turnSearchIntoResponse(i))
}
return returnValue
}
override fun search(query: String): ArrayList<Any>? {
if (!autoLoadToken()) return null
val returnValue: ArrayList<Any> = ArrayList()
@ -144,29 +197,7 @@ class ShiroProvider : MainAPI() {
val mapped = response.let { mapper.readValue<ShiroFullSearchResponse>(it.text) }
for (i in mapped.data.nav.currentPage.items) {
val type = getType(i.type)
val isDubbed = i.language == "dubbed"
val set: EnumSet<DubStatus> = EnumSet.noneOf(DubStatus::class.java)
if (isDubbed)
set.add(DubStatus.Dubbed)
else
set.add(DubStatus.Subbed)
val episodeCount = i.episodeCount.toInt()
returnValue.add(AnimeSearchResponse(
i.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle,
"$mainUrl/anime/${i.slug}",
i.slug,
this.name,
type,
"https://cdn.shiro.is/${i.image}",
i.year?.toIntOrNull(),
i.canonicalTitle,
set,
if (isDubbed) episodeCount else null,
if (!isDubbed) episodeCount else null,
))
returnValue.add(turnSearchIntoResponse(i))
}
return returnValue
}

View file

@ -15,6 +15,8 @@ class MeloMovieProvider : MainAPI() {
get() = "https://melomovie.com"
override val instantLinkLoading: Boolean
get() = true
override val hasQuickSearch: Boolean
get() = true
data class MeloMovieSearchResult(
@JsonProperty("id") val id: Int,
@ -27,6 +29,10 @@ class MeloMovieProvider : MainAPI() {
data class MeloMovieLink(val name: String, val link: String)
override fun quickSearch(query: String): ArrayList<Any>? {
return search(query)
}
override fun search(query: String): ArrayList<Any>? {
val url = "$mainUrl/movie/search/?name=$query"
val returnValue: ArrayList<Any> = ArrayList()

View file

@ -29,6 +29,23 @@ sealed class Resource<out T> {
data class Loading(val url : String? = null) : Resource<Nothing>()
}
fun logError(throwable: Throwable) {
Log.d("ApiError", "-------------------------------------------------------------------")
Log.d("ApiError", "safeApiCall: " + throwable.localizedMessage)
Log.d("ApiError", "safeApiCall: " + throwable.message)
throwable.printStackTrace()
Log.d("ApiError", "-------------------------------------------------------------------")
}
fun<T> normalSafeApiCall(apiCall : () -> T) : T? {
return try {
apiCall.invoke()
} catch (throwable: Throwable) {
logError(throwable)
return null
}
}
suspend fun <T> safeApiCall(
apiCall: suspend () -> T,
): Resource<T> {
@ -36,11 +53,7 @@ suspend fun <T> safeApiCall(
try {
Resource.Success(apiCall.invoke())
} catch (throwable: Throwable) {
Log.d("ApiError", "-------------------------------------------------------------------")
Log.d("ApiError", "safeApiCall: " + throwable.localizedMessage)
Log.d("ApiError", "safeApiCall: " + throwable.message)
throwable.printStackTrace()
Log.d("ApiError", "-------------------------------------------------------------------")
logError(throwable)
when (throwable) {
/*is HttpException -> {
Resource.Failure(false, throwable.code(), throwable.response()?.errorBody(), throwable.localizedMessage)

View file

@ -119,6 +119,7 @@ class SearchFragment : Fragment() {
}
override fun onQueryTextChange(newText: String): Boolean {
searchViewModel.quickSearch(newText)
return true
}
})

View file

@ -5,8 +5,6 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.lagradost.cloudstream3.APIHolder.allApi
import com.lagradost.cloudstream3.APIHolder.apis
import com.lagradost.cloudstream3.MainAPI
import com.lagradost.cloudstream3.mvvm.Resource
import com.lagradost.cloudstream3.mvvm.safeApiCall
import kotlinx.coroutines.launch
@ -14,13 +12,28 @@ import kotlinx.coroutines.launch
class SearchViewModel : ViewModel() {
private val _searchResponse: MutableLiveData<Resource<ArrayList<Any>>> = MutableLiveData()
val searchResponse: LiveData<Resource<ArrayList<Any>>> get() = _searchResponse
var searchCounter = 0
fun search(query: String) = viewModelScope.launch {
searchCounter++
val localSearchCounter = searchCounter
_searchResponse.postValue(Resource.Loading())
val data = safeApiCall {
allApi.search(query)
}
if(localSearchCounter != searchCounter) return@launch
_searchResponse.postValue(data as Resource<ArrayList<Any>>?)
}
fun quickSearch(query: String) = viewModelScope.launch {
searchCounter++
val localSearchCounter = searchCounter
_searchResponse.postValue(Resource.Loading())
val data = safeApiCall {
allApi.quickSearch(query)
}
if(localSearchCounter != searchCounter) return@launch
_searchResponse.postValue(data as Resource<ArrayList<Any>>?)
}
}