forked from recloudstream/cloudstream
api stuff
This commit is contained in:
parent
22f2a8810e
commit
0fa16e3bbc
8 changed files with 228 additions and 94 deletions
|
@ -143,6 +143,8 @@ interface LoadResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
data class AnimeLoadResponse(
|
data class AnimeLoadResponse(
|
||||||
|
val engName: String?,
|
||||||
|
val japName: String?,
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val url: String,
|
override val url: String,
|
||||||
override val apiName: String,
|
override val apiName: String,
|
||||||
|
@ -151,9 +153,8 @@ data class AnimeLoadResponse(
|
||||||
override val posterUrl: String?,
|
override val posterUrl: String?,
|
||||||
override val year: Int?,
|
override val year: Int?,
|
||||||
|
|
||||||
val dubEpisodes: ArrayList<String>?,
|
val dubEpisodes: ArrayList<Any>?,
|
||||||
val subEpisodes: ArrayList<String>?,
|
val subEpisodes: ArrayList<Any>?,
|
||||||
val otherName: String?,
|
|
||||||
val showStatus: ShowStatus?,
|
val showStatus: ShowStatus?,
|
||||||
|
|
||||||
val tags: ArrayList<String>?,
|
val tags: ArrayList<String>?,
|
||||||
|
|
|
@ -5,11 +5,21 @@ import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
import com.lagradost.cloudstream3.*
|
import com.lagradost.cloudstream3.*
|
||||||
import java.net.URLEncoder
|
import java.net.URLEncoder
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
|
|
||||||
class ShiroProvider : MainAPI() {
|
class ShiroProvider : MainAPI() {
|
||||||
companion object {
|
companion object {
|
||||||
var token: String? = null
|
var token: String? = null
|
||||||
|
|
||||||
|
fun getType(t: String): TvType {
|
||||||
|
return when (t) {
|
||||||
|
"TV" -> TvType.Anime
|
||||||
|
"OVA" -> TvType.ONA
|
||||||
|
"movie" -> TvType.Movie
|
||||||
|
else -> TvType.Anime
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun autoLoadToken(): Boolean {
|
fun autoLoadToken(): Boolean {
|
||||||
|
@ -45,7 +55,7 @@ class ShiroProvider : MainAPI() {
|
||||||
@JsonProperty("episodeCount") val episodeCount: String,
|
@JsonProperty("episodeCount") val episodeCount: String,
|
||||||
@JsonProperty("language") val language: String,
|
@JsonProperty("language") val language: String,
|
||||||
@JsonProperty("type") val type: String,
|
@JsonProperty("type") val type: String,
|
||||||
@JsonProperty("year") val year: String,
|
@JsonProperty("year") val year: String?,
|
||||||
@JsonProperty("canonicalTitle") val canonicalTitle: String,
|
@JsonProperty("canonicalTitle") val canonicalTitle: String,
|
||||||
@JsonProperty("english") val english: String?,
|
@JsonProperty("english") val english: String?,
|
||||||
)
|
)
|
||||||
|
@ -72,8 +82,51 @@ class ShiroProvider : MainAPI() {
|
||||||
@JsonProperty("status") val status: String,
|
@JsonProperty("status") val status: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class ShiroVideo(
|
||||||
|
@JsonProperty("video_id") val video_id: String,
|
||||||
|
@JsonProperty("host") val host: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class ShiroEpisodes(
|
||||||
|
@JsonProperty("anime") val anime: AnimePageData?,
|
||||||
|
@JsonProperty("anime_slug") val anime_slug: String,
|
||||||
|
@JsonProperty("create") val create: String,
|
||||||
|
@JsonProperty("dayOfTheWeek") val dayOfTheWeek: String,
|
||||||
|
@JsonProperty("episode_number") val episode_number: Int,
|
||||||
|
@JsonProperty("slug") val slug: String,
|
||||||
|
@JsonProperty("update") val update: String,
|
||||||
|
@JsonProperty("_id") val _id: String,
|
||||||
|
@JsonProperty("videos") val videos: List<ShiroVideo>,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AnimePageData(
|
||||||
|
@JsonProperty("banner") val banner: String?,
|
||||||
|
@JsonProperty("canonicalTitle") val canonicalTitle: String?,
|
||||||
|
@JsonProperty("episodeCount") val episodeCount: String,
|
||||||
|
@JsonProperty("genres") val genres: List<String>?,
|
||||||
|
@JsonProperty("image") val image: String,
|
||||||
|
@JsonProperty("japanese") val japanese: String?,
|
||||||
|
@JsonProperty("english") val english: String?,
|
||||||
|
@JsonProperty("language") val language: String,
|
||||||
|
@JsonProperty("name") val name: String,
|
||||||
|
@JsonProperty("slug") val slug: String,
|
||||||
|
@JsonProperty("synopsis") val synopsis: String,
|
||||||
|
@JsonProperty("type") val type: String?,
|
||||||
|
@JsonProperty("views") val views: Int?,
|
||||||
|
@JsonProperty("year") val year: String?,
|
||||||
|
@JsonProperty("_id") val _id: String,
|
||||||
|
@JsonProperty("episodes") var episodes: List<ShiroEpisodes>?,
|
||||||
|
@JsonProperty("synonyms") var synonyms: List<String>?,
|
||||||
|
@JsonProperty("status") val status: String?,
|
||||||
|
@JsonProperty("schedule") val schedule: String?,
|
||||||
|
)
|
||||||
|
|
||||||
|
data class AnimePage(
|
||||||
|
@JsonProperty("data") val data: AnimePageData,
|
||||||
|
@JsonProperty("status") val status: String,
|
||||||
|
)
|
||||||
|
|
||||||
override fun search(query: String): ArrayList<Any>? {
|
override fun search(query: String): ArrayList<Any>? {
|
||||||
try {
|
|
||||||
if (!autoLoadToken()) return null
|
if (!autoLoadToken()) return null
|
||||||
val returnValue: ArrayList<Any> = ArrayList()
|
val returnValue: ArrayList<Any> = ArrayList()
|
||||||
val response = khttp.get("https://tapi.shiro.is/advanced?search=${
|
val response = khttp.get("https://tapi.shiro.is/advanced?search=${
|
||||||
|
@ -82,16 +135,11 @@ class ShiroProvider : MainAPI() {
|
||||||
"UTF-8"
|
"UTF-8"
|
||||||
)
|
)
|
||||||
}&token=$token".replace("+", "%20"))
|
}&token=$token".replace("+", "%20"))
|
||||||
println(response.text)
|
if (response.text == "{\"status\":\"Found\",\"data\":[]}") return returnValue // OR ELSE WILL CAUSE WEIRD ERROR
|
||||||
|
|
||||||
val mapped = response.let { mapper.readValue<ShiroFullSearchResponse>(it.text) }
|
val mapped = response.let { mapper.readValue<ShiroFullSearchResponse>(it.text) }
|
||||||
for (i in mapped.data.nav.currentPage.items) {
|
for (i in mapped.data.nav.currentPage.items) {
|
||||||
|
val type = getType(i.type)
|
||||||
val type = when (i.type) {
|
|
||||||
"TV" -> TvType.Anime
|
|
||||||
"OVA" -> TvType.ONA
|
|
||||||
"movie" -> TvType.Movie
|
|
||||||
else -> TvType.Anime
|
|
||||||
}
|
|
||||||
val isDubbed = i.language == "dubbed"
|
val isDubbed = i.language == "dubbed"
|
||||||
val set: EnumSet<DubStatus> = EnumSet.noneOf(DubStatus::class.java)
|
val set: EnumSet<DubStatus> = EnumSet.noneOf(DubStatus::class.java)
|
||||||
|
|
||||||
|
@ -107,7 +155,7 @@ class ShiroProvider : MainAPI() {
|
||||||
this.name,
|
this.name,
|
||||||
type,
|
type,
|
||||||
"https://cdn.shiro.is/${i.image}",
|
"https://cdn.shiro.is/${i.image}",
|
||||||
i.year.toInt(),
|
i.year?.toIntOrNull(),
|
||||||
i.canonicalTitle,
|
i.canonicalTitle,
|
||||||
set,
|
set,
|
||||||
if (isDubbed) episodeCount else null,
|
if (isDubbed) episodeCount else null,
|
||||||
|
@ -115,8 +163,40 @@ class ShiroProvider : MainAPI() {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
return returnValue
|
return returnValue
|
||||||
} catch (e: Exception) {
|
}
|
||||||
return null
|
|
||||||
}
|
override fun load(url: String): Any? {
|
||||||
|
if (!autoLoadToken()) return null
|
||||||
|
val rurl = "https://tapi.shiro.is/anime/slug/${url}?token=${token}"
|
||||||
|
val response = khttp.get(rurl, timeout = 120.0)
|
||||||
|
val mapped = response.let { mapper.readValue<AnimePage>(it.text) }
|
||||||
|
val data = mapped.data
|
||||||
|
val isDubbed = data.language == "dubbed"
|
||||||
|
val episodes = ArrayList<Any>(data.episodes ?: ArrayList())
|
||||||
|
val status = when (data.status) {
|
||||||
|
"current" -> ShowStatus.Ongoing
|
||||||
|
"finished" -> ShowStatus.Completed
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
return AnimeLoadResponse(
|
||||||
|
data.english,
|
||||||
|
data.japanese,
|
||||||
|
data.canonicalTitle ?: data.name.replace("Dubbed", ""),
|
||||||
|
url,
|
||||||
|
this.name,
|
||||||
|
getType(data.type ?: ""),
|
||||||
|
"https://cdn.shiro.is/${data.image}",
|
||||||
|
data.year?.toIntOrNull(),
|
||||||
|
if (isDubbed) episodes else null,
|
||||||
|
if (!isDubbed) episodes else null,
|
||||||
|
status,
|
||||||
|
ArrayList(data.genres ?: ArrayList()),
|
||||||
|
data.synopsis,
|
||||||
|
ArrayList(data.synonyms ?: ArrayList()),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.lagradost.cloudstream3.ui.result
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import com.lagradost.cloudstream3.R
|
||||||
|
|
||||||
|
class ResultFragment : Fragment() {
|
||||||
|
private lateinit var viewModel: ResultViewModel
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
viewModel =
|
||||||
|
ViewModelProvider(this).get(ResultViewModel::class.java)
|
||||||
|
|
||||||
|
return inflater.inflate(R.layout.fragment_result, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.lagradost.cloudstream3.ui.result
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
|
||||||
|
class ResultViewModel : ViewModel() {
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,15 @@
|
||||||
package com.lagradost.cloudstream3.ui.search
|
package com.lagradost.cloudstream3.ui.search
|
||||||
|
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
@ -22,8 +19,9 @@ import com.lagradost.cloudstream3.APIHolder.getApiSettings
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar
|
||||||
import com.lagradost.cloudstream3.UIHelper.getGridIsCompact
|
import com.lagradost.cloudstream3.UIHelper.getGridIsCompact
|
||||||
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
|
import com.lagradost.cloudstream3.mvvm.observe
|
||||||
import kotlinx.android.synthetic.main.fragment_search.*
|
import kotlinx.android.synthetic.main.fragment_search.*
|
||||||
import kotlin.concurrent.thread
|
|
||||||
|
|
||||||
class SearchFragment : Fragment() {
|
class SearchFragment : Fragment() {
|
||||||
|
|
||||||
|
@ -106,19 +104,7 @@ class SearchFragment : Fragment() {
|
||||||
override fun onQueryTextSubmit(query: String): Boolean {
|
override fun onQueryTextSubmit(query: String): Boolean {
|
||||||
search_exit_icon.alpha = 0f
|
search_exit_icon.alpha = 0f
|
||||||
search_loading_bar.alpha = 1f
|
search_loading_bar.alpha = 1f
|
||||||
thread {
|
searchViewModel.search(query)
|
||||||
val data = allApi.search(query)//MainActivity.activeAPI.search(query)
|
|
||||||
activity?.runOnUiThread {
|
|
||||||
if (data == null) {
|
|
||||||
Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
|
||||||
} else {
|
|
||||||
(cardSpace.adapter as SearchAdapter).cardList = data
|
|
||||||
(cardSpace.adapter as SearchAdapter).notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
search_exit_icon.alpha = 1f
|
|
||||||
search_loading_bar.alpha = 0f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,6 +113,20 @@ class SearchFragment : Fragment() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
observe(searchViewModel.searchResponse) {
|
||||||
|
when (it) {
|
||||||
|
is Resource.Success -> {
|
||||||
|
(cardSpace.adapter as SearchAdapter).cardList = it.value
|
||||||
|
(cardSpace.adapter as SearchAdapter).notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
is Resource.Failure -> {
|
||||||
|
Toast.makeText(activity, "Server error", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
search_exit_icon.alpha = 1f
|
||||||
|
search_loading_bar.alpha = 0f
|
||||||
|
}
|
||||||
|
|
||||||
main_search.onActionViewExpanded()
|
main_search.onActionViewExpanded()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,20 +3,24 @@ package com.lagradost.cloudstream3.ui.search
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.lagradost.cloudstream3.APIHolder.apis
|
import com.lagradost.cloudstream3.APIHolder.apis
|
||||||
import com.lagradost.cloudstream3.MainAPI
|
import com.lagradost.cloudstream3.MainAPI
|
||||||
|
import com.lagradost.cloudstream3.mvvm.Resource
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class SearchViewModel : ViewModel() {
|
class SearchViewModel : ViewModel() {
|
||||||
|
|
||||||
private val _text = MutableLiveData<String>().apply {
|
|
||||||
value = "This is dashboard Fragment"
|
|
||||||
}
|
|
||||||
val text: LiveData<String> = _text
|
|
||||||
|
|
||||||
val api: MainAPI = apis[0]
|
val api: MainAPI = apis[0]
|
||||||
|
|
||||||
suspend fun search(query: String) = safeApiCall {
|
private val _searchResponse: MutableLiveData<Resource<ArrayList<Any>>> = MutableLiveData()
|
||||||
|
val searchResponse: LiveData<Resource<ArrayList<Any>>> get() = _searchResponse
|
||||||
|
|
||||||
|
fun search(query: String) = viewModelScope.launch {
|
||||||
|
val data = safeApiCall {
|
||||||
api.search(query)
|
api.search(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_searchResponse.postValue(data as Resource<ArrayList<Any>>?)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,35 +1,42 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<FrameLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/container"
|
android:id="@+id/container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
|
||||||
android:paddingTop="0dp">
|
android:paddingTop="0dp">
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/homeRoot"
|
||||||
|
>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout android:layout_height="match_parent"
|
||||||
|
android:layout_width="match_parent">
|
||||||
|
|
||||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
android:id="@+id/nav_view"
|
android:id="@+id/nav_view"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="0dp"
|
|
||||||
android:layout_marginEnd="0dp"
|
|
||||||
android:background="@color/darkBackground"
|
android:background="@color/darkBackground"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:itemRippleColor="@color/colorRipple"
|
||||||
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
app:menu="@menu/bottom_nav_menu"/>
|
app:menu="@menu/bottom_nav_menu"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/nav_host_fragment"
|
android:id="@+id/nav_host_fragment"
|
||||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="0dp"
|
||||||
app:defaultNavHost="true"
|
app:defaultNavHost="true"
|
||||||
app:layout_constraintBottom_toTopOf="@id/nav_view"
|
app:layout_constraintBottom_toTopOf="@+id/nav_view"
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:navGraph="@navigation/mobile_navigation"
|
app:navGraph="@navigation/mobile_navigation"
|
||||||
/>
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
</FrameLayout>
|
||||||
|
</FrameLayout>
|
6
app/src/main/res/layout/fragment_result.xml
Normal file
6
app/src/main/res/layout/fragment_result.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in a new issue