forked from recloudstream/cloudstream
fixing anilist stuff
This commit is contained in:
parent
2a663ccef1
commit
a933aa8493
8 changed files with 192 additions and 105 deletions
|
@ -7,11 +7,9 @@ import com.lagradost.cloudstream3.utils.ExtractorLink
|
|||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import org.jsoup.Jsoup
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
||||
class AnimekisaProvider : MainAPI() {
|
||||
|
||||
override var mainUrl = "https://animekisa.in"
|
||||
override var name = "Animekisa"
|
||||
override val hasMainPage = true
|
||||
|
@ -23,7 +21,7 @@ class AnimekisaProvider : MainAPI() {
|
|||
TvType.Anime,
|
||||
)
|
||||
|
||||
data class Response (
|
||||
data class Response(
|
||||
@JsonProperty("html") val html: String
|
||||
)
|
||||
|
||||
|
@ -72,11 +70,15 @@ class AnimekisaProvider : MainAPI() {
|
|||
if (items.size <= 0) throw ErrorLoadingException()
|
||||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
return app.get("$mainUrl/search/?keyword=$query").document.select("div.flw-item").map {
|
||||
val title = it.selectFirst("h3 a").text()
|
||||
val url = it.selectFirst("a.film-poster-ahref").attr("href")
|
||||
.replace("watch/","anime/").replace(Regex("(-episode-(\\d+)\\/\$|-episode-(\\d+)\$|-episode-full|-episode-.*-.(\\/|))"),"")
|
||||
.replace("watch/", "anime/").replace(
|
||||
Regex("(-episode-(\\d+)\\/\$|-episode-(\\d+)\$|-episode-full|-episode-.*-.(\\/|))"),
|
||||
""
|
||||
)
|
||||
val poster = it.selectFirst(".film-poster img").attr("data-src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
|
@ -91,18 +93,24 @@ class AnimekisaProvider : MainAPI() {
|
|||
)
|
||||
}.toList()
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url, timeout = 120).document
|
||||
val poster = doc.selectFirst(".mb-2 img").attr("src") ?: doc.selectFirst("head meta[property=og:image]").attr("content")
|
||||
val poster = doc.selectFirst(".mb-2 img").attr("src")
|
||||
?: doc.selectFirst("head meta[property=og:image]").attr("content")
|
||||
val title = doc.selectFirst("h1.heading-name a").text()
|
||||
val description = doc.selectFirst("div.description p").text().trim()
|
||||
val genres = doc.select("div.row-line a").map { it.text() }
|
||||
val test = if (doc.selectFirst("div.dp-i-c-right").toString().contains("Airing")) ShowStatus.Ongoing else ShowStatus.Completed
|
||||
val test = if (doc.selectFirst("div.dp-i-c-right").toString()
|
||||
.contains("Airing")
|
||||
) ShowStatus.Ongoing else ShowStatus.Completed
|
||||
val episodes = doc.select("div.tab-content ul li.nav-item").map {
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
AnimeEpisode(link)
|
||||
}
|
||||
val type = if (doc.selectFirst(".dp-i-stats").toString().contains("Movies")) TvType.AnimeMovie else TvType.Anime
|
||||
val type = if (doc.selectFirst(".dp-i-stats").toString()
|
||||
.contains("Movies")
|
||||
) TvType.AnimeMovie else TvType.Anime
|
||||
return newAnimeLoadResponse(title, url, type) {
|
||||
posterUrl = poster
|
||||
addEpisodes(DubStatus.Subbed, episodes)
|
||||
|
|
|
@ -70,7 +70,9 @@ interface SyncAPI : OAuth2API {
|
|||
var nextAiring: SyncNextAiring? = null,
|
||||
var studio: List<String>? = null,
|
||||
var genres: List<String>? = null,
|
||||
var synonyms: List<String>? = null,
|
||||
var trailerUrl: String? = null,
|
||||
var isAdult : Boolean? = null,
|
||||
|
||||
/** In unixtime */
|
||||
var startDate: Long? = null,
|
||||
|
|
|
@ -2,10 +2,12 @@ package com.lagradost.cloudstream3.syncproviders
|
|||
|
||||
import com.lagradost.cloudstream3.ErrorLoadingException
|
||||
import com.lagradost.cloudstream3.mvvm.Resource
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
|
||||
class SyncRepo(private val repo: SyncAPI) {
|
||||
val idPrefix get() = repo.idPrefix
|
||||
val idPrefix = repo.idPrefix
|
||||
val name = repo.name
|
||||
|
||||
suspend fun score(id: String, status: SyncAPI.SyncStatus): Resource<Boolean> {
|
||||
return safeApiCall { repo.score(id, status) }
|
||||
|
@ -22,4 +24,8 @@ class SyncRepo(private val repo: SyncAPI) {
|
|||
suspend fun search(query : String) : Resource<List<SyncAPI.SyncSearchResult>> {
|
||||
return safeApiCall { repo.search(query) ?: throw ErrorLoadingException() }
|
||||
}
|
||||
|
||||
fun hasAccount() : Boolean {
|
||||
return normalSafeApiCall { repo.loginInfo() != null } ?: false
|
||||
}
|
||||
}
|
|
@ -73,9 +73,9 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
|
||||
override suspend fun search(name: String): List<SyncAPI.SyncSearchResult>? {
|
||||
val data = searchShows(name) ?: return null
|
||||
return data.data.Page.media.map {
|
||||
return data.data?.Page?.media?.map {
|
||||
SyncAPI.SyncSearchResult(
|
||||
it.title.romaji,
|
||||
it.title.romaji ?: return null,
|
||||
this.name,
|
||||
it.id.toString(),
|
||||
"$mainUrl/anime/${it.id}",
|
||||
|
@ -92,10 +92,15 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
season.id.toString(),
|
||||
nextAiring = season.nextAiringEpisode?.let {
|
||||
SyncAPI.SyncNextAiring(
|
||||
it.episode,
|
||||
it.timeUntilAiring + unixTime
|
||||
it.episode ?: return@let null,
|
||||
(it.timeUntilAiring ?: return@let null) + unixTime
|
||||
)
|
||||
},
|
||||
genres = season.genres,
|
||||
synonyms = season.synonyms,
|
||||
isAdult = season.isAdult,
|
||||
totalEpisodes = season.episodes,
|
||||
//synopsis = season.
|
||||
//TODO REST
|
||||
)
|
||||
}
|
||||
|
@ -107,7 +112,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
return SyncAPI.SyncStatus(
|
||||
score = data.score,
|
||||
watchedEpisodes = data.episodes,
|
||||
status = data.type.value,
|
||||
status = data.type?.value ?: return null,
|
||||
isFavorite = data.isFavourite,
|
||||
)
|
||||
}
|
||||
|
@ -254,7 +259,9 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
)
|
||||
}
|
||||
filtered?.forEach {
|
||||
if (fixName(it.title.romaji) == fixName(name)) return it
|
||||
it.title.romaji?.let { romaji ->
|
||||
if (fixName(romaji) == fixName(name)) return it
|
||||
}
|
||||
}
|
||||
|
||||
return filtered?.firstOrNull()
|
||||
|
@ -267,7 +274,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
Paused(2),
|
||||
Dropped(3),
|
||||
Planning(4),
|
||||
Rewatching(5),
|
||||
ReWatching(5),
|
||||
None(-1)
|
||||
}
|
||||
|
||||
|
@ -279,7 +286,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
2 -> AniListStatusType.Paused
|
||||
3 -> AniListStatusType.Dropped
|
||||
4 -> AniListStatusType.Planning
|
||||
5 -> AniListStatusType.Rewatching
|
||||
5 -> AniListStatusType.ReWatching
|
||||
else -> AniListStatusType.None
|
||||
}
|
||||
}
|
||||
|
@ -290,22 +297,26 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
|
||||
|
||||
private suspend fun getSeason(id: Int): SeasonResponse? {
|
||||
val q: String = """
|
||||
val q = """
|
||||
query (${'$'}id: Int = $id) {
|
||||
Media (id: ${'$'}id, type: ANIME) {
|
||||
id
|
||||
idMal
|
||||
coverImage
|
||||
duration
|
||||
episodes
|
||||
genres
|
||||
synonyms
|
||||
averageScore
|
||||
isAdult
|
||||
trailer
|
||||
relations {
|
||||
edges {
|
||||
id
|
||||
relationType(version: 2)
|
||||
node {
|
||||
id
|
||||
format
|
||||
nextAiringEpisode {
|
||||
timeUntilAiring
|
||||
episode
|
||||
}
|
||||
coverImage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -369,8 +380,8 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
val data = postApi(q, true)
|
||||
val d = mapper.readValue<GetDataRoot>(data ?: return null)
|
||||
|
||||
val main = d.data.Media
|
||||
if (main.mediaListEntry != null) {
|
||||
val main = d.data?.Media
|
||||
if (main?.mediaListEntry != null) {
|
||||
return AniListTitleHolder(
|
||||
title = main.title,
|
||||
id = id,
|
||||
|
@ -382,11 +393,11 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
)
|
||||
} else {
|
||||
return AniListTitleHolder(
|
||||
title = main.title,
|
||||
title = main?.title,
|
||||
id = id,
|
||||
isFavourite = main.isFavourite,
|
||||
isFavourite = main?.isFavourite,
|
||||
progress = 0,
|
||||
episodes = main.episodes,
|
||||
episodes = main?.episodes,
|
||||
score = 0,
|
||||
type = AniListStatusType.None,
|
||||
)
|
||||
|
@ -420,14 +431,14 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
|
||||
data class MediaRecommendation(
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("title") val title: Title,
|
||||
@JsonProperty("title") val title: Title?,
|
||||
@JsonProperty("idMal") val idMal: Int?,
|
||||
@JsonProperty("coverImage") val coverImage: CoverImage,
|
||||
@JsonProperty("coverImage") val coverImage: CoverImage?,
|
||||
@JsonProperty("averageScore") val averageScore: Int?
|
||||
)
|
||||
|
||||
data class FullAnilistList(
|
||||
@JsonProperty("data") val data: Data
|
||||
@JsonProperty("data") val data: Data?
|
||||
)
|
||||
|
||||
data class CompletedAt(
|
||||
|
@ -448,7 +459,7 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
)
|
||||
|
||||
data class CoverImage(
|
||||
@JsonProperty("medium") val medium: String,
|
||||
@JsonProperty("medium") val medium: String?,
|
||||
@JsonProperty("large") val large: String?
|
||||
)
|
||||
|
||||
|
@ -629,11 +640,11 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
val data = postApi(q)
|
||||
if (data == "") return null
|
||||
val userData = mapper.readValue<AniListRoot>(data ?: return null)
|
||||
val u = userData.data.Viewer
|
||||
val u = userData.data?.Viewer
|
||||
val user = AniListUser(
|
||||
u.id,
|
||||
u.name,
|
||||
u.avatar.large,
|
||||
u?.id,
|
||||
u?.name,
|
||||
u?.avatar?.large,
|
||||
)
|
||||
if (setSettings) {
|
||||
setKey(accountId, ANILIST_USER_KEY, user)
|
||||
|
@ -652,9 +663,9 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
val season = getSeason(id)
|
||||
if (season != null) {
|
||||
seasons.add(season)
|
||||
if (season.data.Media.format?.startsWith("TV") == true) {
|
||||
season.data.Media.relations.edges.forEach {
|
||||
if (it.node.format != null) {
|
||||
if (season.data?.Media?.format?.startsWith("TV") == true) {
|
||||
season.data.Media.relations?.edges?.forEach {
|
||||
if (it.node?.format != null) {
|
||||
if (it.relationType == "SEQUEL" && it.node.format.startsWith("TV")) {
|
||||
getSeasonRecursive(it.node.id)
|
||||
return@forEach
|
||||
|
@ -669,34 +680,56 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
}
|
||||
|
||||
data class SeasonResponse(
|
||||
@JsonProperty("data") val data: SeasonData,
|
||||
@JsonProperty("data") val data: SeasonData?,
|
||||
)
|
||||
|
||||
data class SeasonData(
|
||||
@JsonProperty("Media") val Media: SeasonMedia,
|
||||
@JsonProperty("Media") val Media: SeasonMedia?,
|
||||
)
|
||||
|
||||
data class SeasonMedia(
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("id") val id: Int?,
|
||||
@JsonProperty("idMal") val idMal: Int?,
|
||||
@JsonProperty("format") val format: String?,
|
||||
@JsonProperty("nextAiringEpisode") val nextAiringEpisode: SeasonNextAiringEpisode?,
|
||||
@JsonProperty("relations") val relations: SeasonEdges,
|
||||
@JsonProperty("relations") val relations: SeasonEdges?,
|
||||
@JsonProperty("coverImage") val coverImage: MediaCoverImage?,
|
||||
@JsonProperty("duration") val duration: Int?,
|
||||
@JsonProperty("episodes") val episodes: Int?,
|
||||
@JsonProperty("genres") val genres: List<String>?,
|
||||
@JsonProperty("synonyms") val synonyms: List<String>?,
|
||||
@JsonProperty("averageScore") val averageScore: Int?,
|
||||
@JsonProperty("isAdult") val isAdult: Boolean?,
|
||||
@JsonProperty("trailer") val trailer: MediaTrailer?,
|
||||
|
||||
)
|
||||
|
||||
data class MediaTrailer(
|
||||
@JsonProperty("id") val id: String?,
|
||||
@JsonProperty("site") val site: String?,
|
||||
@JsonProperty("thumbnail") val thumbnail: String?,
|
||||
)
|
||||
|
||||
data class MediaCoverImage(
|
||||
@JsonProperty("extraLarge") val extraLarge: String?,
|
||||
@JsonProperty("large") val large: String?,
|
||||
@JsonProperty("medium") val medium: String?,
|
||||
@JsonProperty("color") val color: String?,
|
||||
)
|
||||
|
||||
data class SeasonNextAiringEpisode(
|
||||
@JsonProperty("episode") val episode: Int,
|
||||
@JsonProperty("timeUntilAiring") val timeUntilAiring: Int,
|
||||
@JsonProperty("episode") val episode: Int?,
|
||||
@JsonProperty("timeUntilAiring") val timeUntilAiring: Int?,
|
||||
)
|
||||
|
||||
data class SeasonEdges(
|
||||
@JsonProperty("edges") val edges: List<SeasonEdge>,
|
||||
@JsonProperty("edges") val edges: List<SeasonEdge>?,
|
||||
)
|
||||
|
||||
data class SeasonEdge(
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("relationType") val relationType: String,
|
||||
@JsonProperty("node") val node: SeasonNode,
|
||||
@JsonProperty("id") val id: Int?,
|
||||
@JsonProperty("relationType") val relationType: String?,
|
||||
@JsonProperty("node") val node: SeasonNode?,
|
||||
)
|
||||
|
||||
data class AniListFavoritesMediaConnection(
|
||||
|
@ -710,121 +743,121 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
data class SeasonNode(
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("format") val format: String?,
|
||||
@JsonProperty("title") val title: Title,
|
||||
@JsonProperty("title") val title: Title?,
|
||||
@JsonProperty("idMal") val idMal: Int?,
|
||||
@JsonProperty("coverImage") val coverImage: CoverImage,
|
||||
@JsonProperty("coverImage") val coverImage: CoverImage?,
|
||||
@JsonProperty("averageScore") val averageScore: Int?
|
||||
// @JsonProperty("nextAiringEpisode") val nextAiringEpisode: SeasonNextAiringEpisode?,
|
||||
)
|
||||
|
||||
data class AniListAvatar(
|
||||
@JsonProperty("large") val large: String,
|
||||
@JsonProperty("large") val large: String?,
|
||||
)
|
||||
|
||||
data class AniListViewer(
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("name") val name: String,
|
||||
@JsonProperty("avatar") val avatar: AniListAvatar,
|
||||
@JsonProperty("favourites") val favourites: AniListFavourites,
|
||||
@JsonProperty("id") val id: Int?,
|
||||
@JsonProperty("name") val name: String?,
|
||||
@JsonProperty("avatar") val avatar: AniListAvatar?,
|
||||
@JsonProperty("favourites") val favourites: AniListFavourites?,
|
||||
)
|
||||
|
||||
data class AniListData(
|
||||
@JsonProperty("Viewer") val Viewer: AniListViewer,
|
||||
@JsonProperty("Viewer") val Viewer: AniListViewer?,
|
||||
)
|
||||
|
||||
data class AniListRoot(
|
||||
@JsonProperty("data") val data: AniListData,
|
||||
@JsonProperty("data") val data: AniListData?,
|
||||
)
|
||||
|
||||
data class AniListUser(
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("name") val name: String,
|
||||
@JsonProperty("picture") val picture: String,
|
||||
@JsonProperty("id") val id: Int?,
|
||||
@JsonProperty("name") val name: String?,
|
||||
@JsonProperty("picture") val picture: String?,
|
||||
)
|
||||
|
||||
data class LikeNode(
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("id") val id: Int?,
|
||||
//@JsonProperty("idMal") public int idMal;
|
||||
)
|
||||
|
||||
data class LikePageInfo(
|
||||
@JsonProperty("total") val total: Int,
|
||||
@JsonProperty("currentPage") val currentPage: Int,
|
||||
@JsonProperty("lastPage") val lastPage: Int,
|
||||
@JsonProperty("perPage") val perPage: Int,
|
||||
@JsonProperty("hasNextPage") val hasNextPage: Boolean,
|
||||
@JsonProperty("total") val total: Int?,
|
||||
@JsonProperty("currentPage") val currentPage: Int?,
|
||||
@JsonProperty("lastPage") val lastPage: Int?,
|
||||
@JsonProperty("perPage") val perPage: Int?,
|
||||
@JsonProperty("hasNextPage") val hasNextPage: Boolean?,
|
||||
)
|
||||
|
||||
data class LikeAnime(
|
||||
@JsonProperty("nodes") val nodes: List<LikeNode>,
|
||||
@JsonProperty("pageInfo") val pageInfo: LikePageInfo,
|
||||
@JsonProperty("nodes") val nodes: List<LikeNode>?,
|
||||
@JsonProperty("pageInfo") val pageInfo: LikePageInfo?,
|
||||
)
|
||||
|
||||
data class LikeFavourites(
|
||||
@JsonProperty("anime") val anime: LikeAnime,
|
||||
@JsonProperty("anime") val anime: LikeAnime?,
|
||||
)
|
||||
|
||||
data class LikeViewer(
|
||||
@JsonProperty("favourites") val favourites: LikeFavourites,
|
||||
@JsonProperty("favourites") val favourites: LikeFavourites?,
|
||||
)
|
||||
|
||||
data class LikeData(
|
||||
@JsonProperty("Viewer") val Viewer: LikeViewer,
|
||||
@JsonProperty("Viewer") val Viewer: LikeViewer?,
|
||||
)
|
||||
|
||||
data class LikeRoot(
|
||||
@JsonProperty("data") val data: LikeData,
|
||||
@JsonProperty("data") val data: LikeData?,
|
||||
)
|
||||
|
||||
data class Recommendation(
|
||||
@JsonProperty("title") val title: String,
|
||||
@JsonProperty("idMal") val idMal: Int,
|
||||
@JsonProperty("poster") val poster: String,
|
||||
@JsonProperty("title") val title: String?,
|
||||
@JsonProperty("idMal") val idMal: Int?,
|
||||
@JsonProperty("poster") val poster: String?,
|
||||
@JsonProperty("averageScore") val averageScore: Int?
|
||||
)
|
||||
|
||||
data class AniListTitleHolder(
|
||||
@JsonProperty("title") val title: Title,
|
||||
@JsonProperty("isFavourite") val isFavourite: Boolean,
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("progress") val progress: Int,
|
||||
@JsonProperty("episodes") val episodes: Int,
|
||||
@JsonProperty("score") val score: Int,
|
||||
@JsonProperty("type") val type: AniListStatusType,
|
||||
@JsonProperty("title") val title: Title?,
|
||||
@JsonProperty("isFavourite") val isFavourite: Boolean?,
|
||||
@JsonProperty("id") val id: Int?,
|
||||
@JsonProperty("progress") val progress: Int?,
|
||||
@JsonProperty("episodes") val episodes: Int?,
|
||||
@JsonProperty("score") val score: Int?,
|
||||
@JsonProperty("type") val type: AniListStatusType?,
|
||||
)
|
||||
|
||||
data class GetDataMediaListEntry(
|
||||
@JsonProperty("progress") val progress: Int,
|
||||
@JsonProperty("status") val status: String,
|
||||
@JsonProperty("score") val score: Int,
|
||||
@JsonProperty("progress") val progress: Int?,
|
||||
@JsonProperty("status") val status: String?,
|
||||
@JsonProperty("score") val score: Int?,
|
||||
)
|
||||
|
||||
data class Nodes(
|
||||
@JsonProperty("id") val id: Int,
|
||||
@JsonProperty("id") val id: Int?,
|
||||
@JsonProperty("mediaRecommendation") val mediaRecommendation: MediaRecommendation?
|
||||
)
|
||||
|
||||
data class GetDataMedia(
|
||||
@JsonProperty("isFavourite") val isFavourite: Boolean,
|
||||
@JsonProperty("episodes") val episodes: Int,
|
||||
@JsonProperty("title") val title: Title,
|
||||
@JsonProperty("isFavourite") val isFavourite: Boolean?,
|
||||
@JsonProperty("episodes") val episodes: Int?,
|
||||
@JsonProperty("title") val title: Title?,
|
||||
@JsonProperty("mediaListEntry") val mediaListEntry: GetDataMediaListEntry?
|
||||
)
|
||||
|
||||
data class Recommendations(
|
||||
@JsonProperty("nodes") val nodes: List<Nodes>
|
||||
@JsonProperty("nodes") val nodes: List<Nodes>?
|
||||
)
|
||||
|
||||
data class GetDataData(
|
||||
@JsonProperty("Media") val Media: GetDataMedia,
|
||||
@JsonProperty("Media") val Media: GetDataMedia?,
|
||||
)
|
||||
|
||||
data class GetDataRoot(
|
||||
@JsonProperty("data") val data: GetDataData,
|
||||
@JsonProperty("data") val data: GetDataData?,
|
||||
)
|
||||
|
||||
data class GetSearchTitle(
|
||||
@JsonProperty("romaji") val romaji: String,
|
||||
@JsonProperty("romaji") val romaji: String?,
|
||||
)
|
||||
|
||||
data class TrailerObject(
|
||||
|
@ -845,18 +878,18 @@ class AniListApi(index: Int) : AccountManager(index), SyncAPI {
|
|||
@JsonProperty("trailer") val trailer: TrailerObject?,
|
||||
@JsonProperty("nextAiringEpisode") val nextAiringEpisode: SeasonNextAiringEpisode?,
|
||||
@JsonProperty("recommendations") val recommendations: Recommendations?,
|
||||
@JsonProperty("relations") val relations: SeasonEdges
|
||||
@JsonProperty("relations") val relations: SeasonEdges?
|
||||
)
|
||||
|
||||
data class GetSearchPage(
|
||||
@JsonProperty("Page") val Page: GetSearchData,
|
||||
@JsonProperty("Page") val Page: GetSearchData?,
|
||||
)
|
||||
|
||||
data class GetSearchData(
|
||||
@JsonProperty("media") val media: List<GetSearchMedia>,
|
||||
@JsonProperty("media") val media: List<GetSearchMedia>?,
|
||||
)
|
||||
|
||||
data class GetSearchRoot(
|
||||
@JsonProperty("data") val data: GetSearchPage,
|
||||
@JsonProperty("data") val data: GetSearchPage?,
|
||||
)
|
||||
}
|
|
@ -1191,19 +1191,24 @@ class ResultFragment : Fragment(), PanelsChildGestureRegionObserver.GestureRegio
|
|||
syncModel.setEpisodesDelta(-1)
|
||||
}
|
||||
|
||||
result_sync_current_episodes?.doOnTextChanged { text, start, before, count ->
|
||||
if(count == before) return@doOnTextChanged
|
||||
result_sync_current_episodes?.doOnTextChanged { text, _, before, count ->
|
||||
if (count == before) return@doOnTextChanged
|
||||
text?.toString()?.toIntOrNull()?.let { ep ->
|
||||
syncModel.setEpisodes(ep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
observe(syncModel.synced) { list ->
|
||||
result_sync_names?.text =
|
||||
list.filter { it.isSynced && it.hasAccount }.joinToString { it.name }
|
||||
}
|
||||
|
||||
observe(syncModel.metadata) { meta ->
|
||||
when (meta) {
|
||||
is Resource.Success -> {
|
||||
val d = meta.value
|
||||
result_sync_episodes?.max = (d.totalEpisodes ?: 0)*1000
|
||||
result_sync_episodes?.max = (d.totalEpisodes ?: 0) * 1000
|
||||
normalSafeApiCall {
|
||||
val ctx = result_sync_max_episodes?.context
|
||||
result_sync_max_episodes?.text =
|
||||
|
|
|
@ -13,6 +13,13 @@ import com.lagradost.cloudstream3.utils.SyncUtil
|
|||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
data class CurrentSynced(
|
||||
val name: String,
|
||||
val idPrefix: String,
|
||||
val isSynced: Boolean,
|
||||
val hasAccount: Boolean,
|
||||
)
|
||||
|
||||
class SyncViewModel : ViewModel() {
|
||||
private val repos = SyncApis
|
||||
|
||||
|
@ -29,19 +36,42 @@ class SyncViewModel : ViewModel() {
|
|||
// prefix, id
|
||||
private val syncIds = hashMapOf<String, String>()
|
||||
|
||||
private val _currentSynced: MutableLiveData<List<CurrentSynced>> =
|
||||
MutableLiveData(getMissing())
|
||||
|
||||
// pair of name idPrefix isSynced
|
||||
val synced: LiveData<List<CurrentSynced>> get() = _currentSynced
|
||||
|
||||
private fun getMissing(): List<CurrentSynced> {
|
||||
return repos.map {
|
||||
CurrentSynced(
|
||||
it.name,
|
||||
it.idPrefix,
|
||||
syncIds.containsKey(it.idPrefix),
|
||||
it.hasAccount()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSynced() {
|
||||
_currentSynced.postValue(getMissing())
|
||||
}
|
||||
|
||||
fun setMalId(id: String?) {
|
||||
syncIds[malApi.idPrefix] = id ?: return
|
||||
updateSynced()
|
||||
}
|
||||
|
||||
fun setAniListId(id: String?) {
|
||||
syncIds[aniListApi.idPrefix] = id ?: return
|
||||
updateSynced()
|
||||
}
|
||||
|
||||
fun addFromUrl(url : String?) = viewModelScope.launch {
|
||||
fun addFromUrl(url: String?) = viewModelScope.launch {
|
||||
SyncUtil.getIdsFromUrl(url)?.let { (malId, aniListId) ->
|
||||
setMalId(malId)
|
||||
setAniListId(aniListId)
|
||||
if(malId != null || aniListId != null) {
|
||||
if (malId != null || aniListId != null) {
|
||||
updateMetaAndUser()
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +131,7 @@ class SyncViewModel : ViewModel() {
|
|||
updateUserData()
|
||||
}
|
||||
|
||||
fun updateUserData() = viewModelScope.launch {
|
||||
private fun updateUserData() = viewModelScope.launch {
|
||||
_userDataResponse.postValue(Resource.Loading())
|
||||
var lastError: Resource<SyncAPI.SyncStatus> = Resource.Failure(false, null, null, "No data")
|
||||
for ((prefix, id) in syncIds) {
|
||||
|
@ -118,7 +148,7 @@ class SyncViewModel : ViewModel() {
|
|||
_userDataResponse.postValue(lastError)
|
||||
}
|
||||
|
||||
fun updateMetadata() = viewModelScope.launch {
|
||||
private fun updateMetadata() = viewModelScope.launch {
|
||||
_metaResponse.postValue(Resource.Loading())
|
||||
var lastError: Resource<SyncAPI.SyncResult> = Resource.Failure(false, null, null, "No data")
|
||||
for ((prefix, id) in syncIds) {
|
||||
|
|
|
@ -3,9 +3,12 @@ package com.lagradost.cloudstream3.ui.search
|
|||
import com.lagradost.cloudstream3.SearchQuality
|
||||
import com.lagradost.cloudstream3.SearchResponse
|
||||
import com.lagradost.cloudstream3.TvType
|
||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API
|
||||
import com.lagradost.cloudstream3.syncproviders.SyncAPI
|
||||
|
||||
class SyncSearchViewModel {
|
||||
private val repos = OAuth2API.SyncApis
|
||||
|
||||
data class SyncSearchResultSearchResponse(
|
||||
override val name: String,
|
||||
override val url: String,
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:visibility="gone"
|
||||
android:id="@+id/result_sync_names"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginBottom="10dp"
|
||||
|
|
Loading…
Reference in a new issue