migrate more api calls to v2
This commit is contained in:
parent
8b7fb3ac5f
commit
2e7db26d1d
|
@ -322,6 +322,8 @@ object Crunchyroll {
|
||||||
* Search fo a query term.
|
* Search fo a query term.
|
||||||
* Note: currently this function only supports series/tv shows.
|
* Note: currently this function only supports series/tv shows.
|
||||||
*
|
*
|
||||||
|
* TODO migrate to v2
|
||||||
|
*
|
||||||
* @param query The query term as String
|
* @param query The query term as String
|
||||||
* @param n The maximum number of results to return, default = 10
|
* @param n The maximum number of results to return, default = 10
|
||||||
* @return A **[SearchResult]** object
|
* @return A **[SearchResult]** object
|
||||||
|
@ -370,22 +372,6 @@ object Crunchyroll {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* List all available seasons as **[SeasonListItem]**.
|
|
||||||
*/
|
|
||||||
@Suppress("unused")
|
|
||||||
suspend fun seasonList(): DiscSeasonList {
|
|
||||||
val seasonListEndpoint = "/content/v1/season_list"
|
|
||||||
val parameters = listOf("locale" to Preferences.preferredSubtitleLocale.toLanguageTag())
|
|
||||||
|
|
||||||
return try {
|
|
||||||
requestGet(seasonListEndpoint, parameters)
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
Log.e(TAG, "Exception in seasonList().", ex)
|
|
||||||
NoneDiscSeasonList
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main media functions: series, season, episodes, playback
|
* Main media functions: series, season, episodes, playback
|
||||||
*/
|
*/
|
||||||
|
@ -394,12 +380,10 @@ object Crunchyroll {
|
||||||
* series id == crunchyroll id?
|
* series id == crunchyroll id?
|
||||||
*/
|
*/
|
||||||
suspend fun series(seriesId: String): Series {
|
suspend fun series(seriesId: String): Series {
|
||||||
val seriesEndpoint = "/cms/v2/${token.country}/M3/crunchyroll/series/$seriesId"
|
val seriesEndpoint = "/content/v2/cms/series/$seriesId"
|
||||||
val parameters = listOf(
|
val parameters = listOf(
|
||||||
"locale" to Preferences.preferredSubtitleLocale.toLanguageTag(),
|
"preferred_audio_language" to Preferences.preferredAudioLocale.toLanguageTag(),
|
||||||
"Signature" to signature,
|
"locale" to Preferences.preferredSubtitleLocale.toLanguageTag()
|
||||||
"Policy" to policy,
|
|
||||||
"Key-Pair-Id" to keyPairID
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
|
@ -413,6 +397,8 @@ object Crunchyroll {
|
||||||
/**
|
/**
|
||||||
* Get the next episode for a series.
|
* Get the next episode for a series.
|
||||||
*
|
*
|
||||||
|
* FIXME up_next returns no content if the is no next episode
|
||||||
|
*
|
||||||
* @param seriesId The series id for which to call up next
|
* @param seriesId The series id for which to call up next
|
||||||
* @return A **[UpNextSeriesItem]** with a Panel representing the up next episode
|
* @return A **[UpNextSeriesItem]** with a Panel representing the up next episode
|
||||||
*/
|
*/
|
||||||
|
@ -425,6 +411,9 @@ object Crunchyroll {
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
requestGet(upNextSeriesEndpoint, parameters)
|
requestGet(upNextSeriesEndpoint, parameters)
|
||||||
|
} catch (ex: NoTransformationFoundException) {
|
||||||
|
// should be 204 No Content
|
||||||
|
NoneUpNextSeriesList
|
||||||
} catch (ex: JsonConvertException) {
|
} catch (ex: JsonConvertException) {
|
||||||
Log.e(TAG, "JsonConvertException in upNextSeries() with seriesId=$seriesId", ex)
|
Log.e(TAG, "JsonConvertException in upNextSeries() with seriesId=$seriesId", ex)
|
||||||
NoneUpNextSeriesList
|
NoneUpNextSeriesList
|
||||||
|
@ -512,12 +501,16 @@ object Crunchyroll {
|
||||||
* @return **[Boolean]**: ture if it was found, else false
|
* @return **[Boolean]**: ture if it was found, else false
|
||||||
*/
|
*/
|
||||||
suspend fun isWatchlist(seriesId: String): Boolean {
|
suspend fun isWatchlist(seriesId: String): Boolean {
|
||||||
val watchlistSeriesEndpoint = "/content/v1/watchlist/$accountID/$seriesId"
|
val watchlistSeriesEndpoint = "/content/v2/$accountID/watchlist"
|
||||||
val parameters = listOf("locale" to Preferences.preferredSubtitleLocale.toLanguageTag())
|
val parameters = listOf(
|
||||||
|
"content_ids" to seriesId,
|
||||||
|
"preferred_audio_language" to Preferences.preferredAudioLocale.toLanguageTag(),
|
||||||
|
"locale" to Preferences.preferredSubtitleLocale.toLanguageTag()
|
||||||
|
)
|
||||||
|
|
||||||
return try {
|
return try {
|
||||||
(requestGet(watchlistSeriesEndpoint, parameters) as JsonObject)
|
(requestGet(watchlistSeriesEndpoint, parameters) as Collection2<IsWatchlistItem>)
|
||||||
.containsKey(seriesId)
|
.total == 1
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
Log.e(TAG, "Exception in isWatchlist() with seriesId = $seriesId", ex)
|
Log.e(TAG, "Exception in isWatchlist() with seriesId = $seriesId", ex)
|
||||||
false
|
false
|
||||||
|
@ -530,8 +523,11 @@ object Crunchyroll {
|
||||||
* @param seriesId The crunchyroll series id of the media to check
|
* @param seriesId The crunchyroll series id of the media to check
|
||||||
*/
|
*/
|
||||||
suspend fun postWatchlist(seriesId: String) {
|
suspend fun postWatchlist(seriesId: String) {
|
||||||
val watchlistPostEndpoint = "/content/v1/watchlist/$accountID"
|
val watchlistPostEndpoint = "/content/v2/$accountID/watchlist"
|
||||||
val parameters = listOf("locale" to Preferences.preferredSubtitleLocale.toLanguageTag())
|
val parameters = listOf(
|
||||||
|
"preferred_audio_language" to Preferences.preferredAudioLocale.toLanguageTag(),
|
||||||
|
"locale" to Preferences.preferredSubtitleLocale.toLanguageTag()
|
||||||
|
)
|
||||||
|
|
||||||
val json = buildJsonObject {
|
val json = buildJsonObject {
|
||||||
put("content_id", seriesId)
|
put("content_id", seriesId)
|
||||||
|
@ -542,7 +538,6 @@ object Crunchyroll {
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
Log.e(TAG, "Exception in postWatchlist() with seriesId = $seriesId", ex)
|
Log.e(TAG, "Exception in postWatchlist() with seriesId = $seriesId", ex)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -551,15 +546,17 @@ object Crunchyroll {
|
||||||
* @param seriesId The crunchyroll series id of the media to check
|
* @param seriesId The crunchyroll series id of the media to check
|
||||||
*/
|
*/
|
||||||
suspend fun deleteWatchlist(seriesId: String) {
|
suspend fun deleteWatchlist(seriesId: String) {
|
||||||
val watchlistDeleteEndpoint = "/content/v1/watchlist/$accountID/$seriesId"
|
val watchlistDeleteEndpoint = "/content/v2/$accountID/watchlist/$seriesId"
|
||||||
val parameters = listOf("locale" to Preferences.preferredSubtitleLocale.toLanguageTag())
|
val parameters = listOf(
|
||||||
|
"preferred_audio_language" to Preferences.preferredAudioLocale.toLanguageTag(),
|
||||||
|
"locale" to Preferences.preferredSubtitleLocale.toLanguageTag()
|
||||||
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
requestDelete(watchlistDeleteEndpoint, parameters)
|
requestDelete(watchlistDeleteEndpoint, parameters)
|
||||||
} catch (ex: Exception) {
|
} catch (ex: Exception) {
|
||||||
Log.e(TAG, "Exception in deleteWatchlist() with seriesId = $seriesId", ex)
|
Log.e(TAG, "Exception in deleteWatchlist() with seriesId = $seriesId", ex)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -127,7 +127,6 @@ typealias SearchResult = Collection<SearchCollection>
|
||||||
typealias SearchCollection = Collection<Item>
|
typealias SearchCollection = Collection<Item>
|
||||||
typealias BrowseResult = Collection<Item>
|
typealias BrowseResult = Collection<Item>
|
||||||
typealias SimilarToResult = Collection<Item>
|
typealias SimilarToResult = Collection<Item>
|
||||||
typealias DiscSeasonList = Collection<SeasonListItem>
|
|
||||||
typealias Watchlist = Collection2<WatchlistItem>
|
typealias Watchlist = Collection2<WatchlistItem>
|
||||||
typealias HistoryList = Collection2<UpNextAccountItem>
|
typealias HistoryList = Collection2<UpNextAccountItem>
|
||||||
typealias UpNextSeriesList = Collection2<UpNextSeriesItem>
|
typealias UpNextSeriesList = Collection2<UpNextSeriesItem>
|
||||||
|
@ -159,21 +158,6 @@ data class Images(val poster_tall: List<List<Poster>>, val poster_wide: List<Lis
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Poster(val height: Int, val width: Int, val source: String, val type: String)
|
data class Poster(val height: Int, val width: Int, val source: String, val type: String)
|
||||||
|
|
||||||
/**
|
|
||||||
* season list data classes
|
|
||||||
*/
|
|
||||||
@Serializable
|
|
||||||
data class SeasonListItem(
|
|
||||||
@SerialName("id") val id: String,
|
|
||||||
@SerialName("localization") val localization: SeasonListLocalization
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class SeasonListLocalization(
|
|
||||||
@SerialName("title") val title: String,
|
|
||||||
@SerialName("description") val description: String,
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* continue_watching_item data classes
|
* continue_watching_item data classes
|
||||||
*/
|
*/
|
||||||
|
@ -188,6 +172,13 @@ data class WatchlistItem(
|
||||||
@SerialName("is_favorite") val isFavorite: Boolean,
|
@SerialName("is_favorite") val isFavorite: Boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class IsWatchlistItem(
|
||||||
|
@SerialName("id") val id: String,
|
||||||
|
@SerialName("is_favorite") val isFavorite: Boolean,
|
||||||
|
@SerialName("date_added") val dateAdded: String
|
||||||
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class UpNextAccountItem(
|
data class UpNextAccountItem(
|
||||||
@SerialName("panel") val panel: EpisodePanel,
|
@SerialName("panel") val panel: EpisodePanel,
|
||||||
|
@ -229,15 +220,10 @@ data class EpisodeMetadata(
|
||||||
@SerialName("series_title") val seriesTitle: String,
|
@SerialName("series_title") val seriesTitle: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
val NoneItem = Item("", "", "", "", "", Images(emptyList(), emptyList()))
|
|
||||||
val NoneEpisodeMetadata = EpisodeMetadata(0, 0, "", 0, "", "", "")
|
|
||||||
val NoneEpisodePanel = EpisodePanel("", "", "", "", "", NoneEpisodeMetadata, Thumbnail(listOf())) //, "")
|
|
||||||
|
|
||||||
val NoneCollection = Collection<Item>(0, emptyList())
|
val NoneCollection = Collection<Item>(0, emptyList())
|
||||||
val NoneSearchResult = SearchResult(0, emptyList())
|
val NoneSearchResult = SearchResult(0, emptyList())
|
||||||
val NoneBrowseResult = BrowseResult(0, emptyList())
|
val NoneBrowseResult = BrowseResult(0, emptyList())
|
||||||
val NoneSimilarToResult = SimilarToResult(0, emptyList())
|
val NoneSimilarToResult = SimilarToResult(0, emptyList())
|
||||||
val NoneDiscSeasonList = DiscSeasonList(0, emptyList())
|
|
||||||
val NoneWatchlist = Watchlist(0, emptyList())
|
val NoneWatchlist = Watchlist(0, emptyList())
|
||||||
val NoneHistoryList = HistoryList(0, emptyList())
|
val NoneHistoryList = HistoryList(0, emptyList())
|
||||||
val NoneUpNextSeriesList = UpNextSeriesList(0, emptyList())
|
val NoneUpNextSeriesList = UpNextSeriesList(0, emptyList())
|
||||||
|
@ -247,15 +233,23 @@ val NoneBenefits = Benefits(0, emptyList())
|
||||||
/**
|
/**
|
||||||
* series data class
|
* series data class
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typealias Series = Collection2<SeriesItem>
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Series(
|
data class SeriesItem(
|
||||||
@SerialName("id") val id: String,
|
@SerialName("id") val id: String,
|
||||||
@SerialName("title") val title: String,
|
@SerialName("title") val title: String,
|
||||||
@SerialName("description") val description: String,
|
@SerialName("description") val description: String,
|
||||||
@SerialName("images") val images: Images,
|
@SerialName("images") val images: Images,
|
||||||
@SerialName("maturity_ratings") val maturityRatings: List<String>
|
@SerialName("is_simulcast") val isSimulcast: Boolean,
|
||||||
|
@SerialName("maturity_ratings") val maturityRatings: List<String>,
|
||||||
|
@SerialName("audio_locales") val audioLocales: List<String>
|
||||||
|
|
||||||
)
|
)
|
||||||
val NoneSeries = Series("", "", "", Images(emptyList(), emptyList()), emptyList())
|
|
||||||
|
val NoneSeriesItem = SeriesItem("", "", "", Images(emptyList(), emptyList()), false, emptyList(), emptyList())
|
||||||
|
val NoneSeries = Series(1, listOf(NoneSeriesItem))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seasons data classes
|
* Seasons data classes
|
||||||
|
@ -264,17 +258,7 @@ val NoneSeries = Series("", "", "", Images(emptyList(), emptyList()), emptyList(
|
||||||
data class Seasons(
|
data class Seasons(
|
||||||
@SerialName("total") val total: Int,
|
@SerialName("total") val total: Int,
|
||||||
@SerialName("data") val data: List<Season>
|
@SerialName("data") val data: List<Season>
|
||||||
) {
|
)
|
||||||
fun getPreferredSeasonByLocal(local: Locale): Season {
|
|
||||||
return data.firstOrNull { season ->
|
|
||||||
// try to get the the first seasons which matches the preferred local
|
|
||||||
season.slugTitle.endsWith("${local.getDisplayLanguage(Locale.ENGLISH)}-dub", true)
|
|
||||||
} ?: data.firstOrNull { season ->
|
|
||||||
// if there is no season with the preferred local, try to find a subbed season
|
|
||||||
season.isSubbed
|
|
||||||
} ?: data.first() // if no preferred language and no sub, use the first season
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Season(
|
data class Season(
|
||||||
|
|
|
@ -6,7 +6,6 @@ import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.coroutines.joinAll
|
import kotlinx.coroutines.joinAll
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.mosad.teapod.parser.crunchyroll.*
|
import org.mosad.teapod.parser.crunchyroll.*
|
||||||
import org.mosad.teapod.preferences.Preferences
|
|
||||||
import org.mosad.teapod.util.DataTypes.MediaType
|
import org.mosad.teapod.util.DataTypes.MediaType
|
||||||
import org.mosad.teapod.util.tmdb.*
|
import org.mosad.teapod.util.tmdb.*
|
||||||
|
|
||||||
|
@ -16,7 +15,7 @@ import org.mosad.teapod.util.tmdb.*
|
||||||
*/
|
*/
|
||||||
class MediaFragmentViewModel(application: Application) : AndroidViewModel(application) {
|
class MediaFragmentViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
|
||||||
var seriesCrunchy = NoneSeries // movies are also series
|
var seriesCrunchy = NoneSeriesItem // movies are also series
|
||||||
internal set
|
internal set
|
||||||
var seasonsCrunchy = NoneSeasons
|
var seasonsCrunchy = NoneSeasons
|
||||||
internal set
|
internal set
|
||||||
|
@ -50,7 +49,7 @@ class MediaFragmentViewModel(application: Application) : AndroidViewModel(applic
|
||||||
suspend fun loadCrunchy(crunchyId: String) {
|
suspend fun loadCrunchy(crunchyId: String) {
|
||||||
// load series and seasons info in parallel
|
// load series and seasons info in parallel
|
||||||
listOf(
|
listOf(
|
||||||
viewModelScope.launch { seriesCrunchy = Crunchyroll.series(crunchyId) },
|
viewModelScope.launch { seriesCrunchy = Crunchyroll.series(crunchyId).data.first() },
|
||||||
viewModelScope.launch { seasonsCrunchy = Crunchyroll.seasons(crunchyId) },
|
viewModelScope.launch { seasonsCrunchy = Crunchyroll.seasons(crunchyId) },
|
||||||
viewModelScope.launch { isWatchlist = Crunchyroll.isWatchlist(crunchyId) },
|
viewModelScope.launch { isWatchlist = Crunchyroll.isWatchlist(crunchyId) },
|
||||||
viewModelScope.launch { upNextSeries = Crunchyroll.upNextSeries(crunchyId) },
|
viewModelScope.launch { upNextSeries = Crunchyroll.upNextSeries(crunchyId) },
|
||||||
|
@ -58,10 +57,15 @@ class MediaFragmentViewModel(application: Application) : AndroidViewModel(applic
|
||||||
).joinAll()
|
).joinAll()
|
||||||
|
|
||||||
// load the preferred season:
|
// load the preferred season:
|
||||||
// next episode > preferred language (language per season, not per stream)
|
// next episode > first season
|
||||||
currentSeasonCrunchy = seasonsCrunchy.data.firstOrNull{ season ->
|
currentSeasonCrunchy = if (upNextSeries != NoneUpNextSeriesList) {
|
||||||
season.id == upNextSeries.data.first().panel.episodeMetadata.seasonId
|
seasonsCrunchy.data.firstOrNull{ season ->
|
||||||
} ?: seasonsCrunchy.getPreferredSeasonByLocal(Preferences.preferredSubtitleLocale)
|
season.id == upNextSeries.data.first().panel.episodeMetadata.seasonId
|
||||||
|
} ?: seasonsCrunchy.data.first()
|
||||||
|
} else {
|
||||||
|
seasonsCrunchy.data.first()
|
||||||
|
}
|
||||||
|
|
||||||
// Note: if we need to query metaDB, do it now
|
// Note: if we need to query metaDB, do it now
|
||||||
|
|
||||||
// load episodes and metaDB in parallel (tmdb needs mediaType, which is set via episodes)
|
// load episodes and metaDB in parallel (tmdb needs mediaType, which is set via episodes)
|
||||||
|
|
|
@ -171,10 +171,6 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
|
||||||
playCurrentMedia(player.currentPosition)
|
playCurrentMedia(player.currentPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
println(newSubtitleLocale != currentSubtitleLocale)
|
|
||||||
println("currentSubtitleLocale: $currentSubtitleLocale")
|
|
||||||
println("newSubtitleLocale: $newSubtitleLocale")
|
|
||||||
|
|
||||||
// else nothing has changed so no need do do anything
|
// else nothing has changed so no need do do anything
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +231,6 @@ class PlayerViewModel(application: Application) : AndroidViewModel(application)
|
||||||
|
|
||||||
currentStreams = Crunchyroll.streamsFromMediaGUID(currentVersion.mediaGUID)
|
currentStreams = Crunchyroll.streamsFromMediaGUID(currentVersion.mediaGUID)
|
||||||
Log.d(classTag, currentVersion.toString())
|
Log.d(classTag, currentVersion.toString())
|
||||||
println("stream: $currentStreams")
|
|
||||||
},
|
},
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
Crunchyroll.playheads(listOf(currentEpisode.id))[currentEpisode.id]?.let {
|
Crunchyroll.playheads(listOf(currentEpisode.id))[currentEpisode.id]?.let {
|
||||||
|
|
Loading…
Reference in New Issue