add categories support to Crunchyroll.browse()

This commit is contained in:
Jannik 2022-04-16 17:23:53 +02:00
parent c48328723b
commit 1ebc1194e6
Signed by: Seil0
GPG Key ID: E8459F3723C52C24
3 changed files with 70 additions and 11 deletions

View File

@ -42,7 +42,6 @@ import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.put import kotlinx.serialization.json.put
import org.mosad.teapod.preferences.EncryptedPreferences import org.mosad.teapod.preferences.EncryptedPreferences
import org.mosad.teapod.preferences.Preferences import org.mosad.teapod.preferences.Preferences
import org.mosad.teapod.util.concatenate
private val json = Json { ignoreUnknownKeys = true } private val json = Json { ignoreUnknownKeys = true }
@ -102,7 +101,6 @@ object Crunchyroll {
var success = false// is false var success = false// is false
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
// TODO handle exceptions
Log.i(TAG, "getting token ...") Log.i(TAG, "getting token ...")
val status = try { val status = try {
@ -117,7 +115,7 @@ object Crunchyroll {
if (status == HttpStatusCode.Unauthorized) { if (status == HttpStatusCode.Unauthorized) {
Log.e(TAG, "Could not complete login: " + Log.e(TAG, "Could not complete login: " +
"${status.value} ${status.description}. " + "${status.value} ${status.description}. " +
"Propably wrong username or password") "Probably wrong username or password")
} }
status status
@ -255,7 +253,6 @@ object Crunchyroll {
* General element/media functions: browse, search, objects, season_list * General element/media functions: browse, search, objects, season_list
*/ */
// TODO categories
/** /**
* Browse the media available on crunchyroll. * Browse the media available on crunchyroll.
* *
@ -265,13 +262,14 @@ object Crunchyroll {
* @return A **[BrowseResult]** object is returned. * @return A **[BrowseResult]** object is returned.
*/ */
suspend fun browse( suspend fun browse(
categories: List<Categories> = emptyList(),
sortBy: SortBy = SortBy.ALPHABETICAL, sortBy: SortBy = SortBy.ALPHABETICAL,
seasonTag: String = "", seasonTag: String = "",
start: Int = 0, start: Int = 0,
n: Int = 10 n: Int = 10
): BrowseResult { ): BrowseResult {
val browseEndpoint = "/content/v1/browse" val browseEndpoint = "/content/v1/browse"
val noneOptParams = listOf( val parameters = mutableListOf(
"locale" to Preferences.preferredLocale.toLanguageTag(), "locale" to Preferences.preferredLocale.toLanguageTag(),
"sort_by" to sortBy.str, "sort_by" to sortBy.str,
"start" to start, "start" to start,
@ -279,10 +277,13 @@ object Crunchyroll {
) )
// if a season tag is present add it to the parameters // if a season tag is present add it to the parameters
val parameters = if (seasonTag.isNotEmpty()) { if (seasonTag.isNotEmpty()) {
concatenate(noneOptParams, listOf("season_tag" to seasonTag)) parameters.add("season_tag" to seasonTag)
} else { }
noneOptParams
// if a season tag is present add it to the parameters
if (categories.isNotEmpty()) {
parameters.add("categories" to categories.joinToString(",") { it.str })
} }
val browseResult: BrowseResult = try { val browseResult: BrowseResult = try {
@ -412,6 +413,12 @@ object Crunchyroll {
} }
} }
/**
* Get all available seasons for a series.
*
* @param seriesId The series id for which to get the seasons
* @return A **[Seasons]** object with a list of **[Season]**
*/
suspend fun seasons(seriesId: String): Seasons { suspend fun seasons(seriesId: String): Seasons {
val seasonsEndpoint = "/cms/v2/${token.country}/M3/crunchyroll/seasons" val seasonsEndpoint = "/cms/v2/${token.country}/M3/crunchyroll/seasons"
val parameters = listOf( val parameters = listOf(
@ -430,6 +437,12 @@ object Crunchyroll {
} }
} }
/**
* Get all available episodes for a season.
*
* @param seasonId The season id for which to get the episodes
* @return A **[Episodes]** object with a list of **[Episode]**
*/
suspend fun episodes(seasonId: String): Episodes { suspend fun episodes(seasonId: String): Episodes {
val episodesEndpoint = "/cms/v2/${token.country}/M3/crunchyroll/episodes" val episodesEndpoint = "/cms/v2/${token.country}/M3/crunchyroll/episodes"
val parameters = listOf( val parameters = listOf(
@ -448,6 +461,12 @@ object Crunchyroll {
} }
} }
/**
* Get all available subtitles and streams of a episode.
*
* @param url The playback url of a episode
* @return A **[Playback]** object
*/
suspend fun playback(url: String): Playback { suspend fun playback(url: String): Playback {
return try { return try {
requestGet("", url = url) requestGet("", url = url)
@ -546,6 +565,13 @@ object Crunchyroll {
requestPost(playheadsEndpoint, parameters, json) requestPost(playheadsEndpoint, parameters, json)
} }
/**
* Get similar media for a show/movie.
*
* @param seriesId The crunchyroll series id of the media
* @param n The maximum number of results to return, default = 10
* @return A **[SimilarToResult]** object
*/
suspend fun similarTo(seriesId: String, n: Int = 10): SimilarToResult { suspend fun similarTo(seriesId: String, n: Int = 10): SimilarToResult {
val similarToEndpoint = "/content/v1/$accountID/similar_to" val similarToEndpoint = "/content/v1/$accountID/similar_to"
val parameters = listOf( val parameters = listOf(
@ -615,6 +641,11 @@ object Crunchyroll {
* Account/Profile functions * Account/Profile functions
*/ */
/**
* Get profile information for the currently logged in account.
*
* @return A **[Profile]** object
*/
suspend fun profile(): Profile { suspend fun profile(): Profile {
val profileEndpoint = "/accounts/v1/me/profile" val profileEndpoint = "/accounts/v1/me/profile"
@ -626,6 +657,11 @@ object Crunchyroll {
} }
} }
/**
* Post the preferred content subtitle language.
*
* @param languageTag the preferred language as language tag
*/
suspend fun postPrefSubLanguage(languageTag: String) { suspend fun postPrefSubLanguage(languageTag: String) {
val profileEndpoint = "/accounts/v1/me/profile" val profileEndpoint = "/accounts/v1/me/profile"
val json = buildJsonObject { val json = buildJsonObject {

View File

@ -50,6 +50,25 @@ enum class SortBy(val str: String) {
POPULARITY("popularity") POPULARITY("popularity")
} }
@Suppress("unused")
enum class Categories(val str: String) {
ACTION("action"),
ADVENTURE("adventure"),
COMEDY("comedy"),
DRAMA("drama"),
FANTASY("fantasy"),
MUSIC("music"),
ROMANCE("romance"),
SCI_FI("sci-fi"),
SEINEN("seinen"),
SHOJO("shojo"),
SHONEN("shonen"),
SLICE_OF_LIFE("slice+of+life"),
SPORTS("sports"),
SUPERNATURAL("supernatural"),
THRILLER("thriller")
}
/** /**
* token, index, account. This must pe present for the app to work! * token, index, account. This must pe present for the app to work!
*/ */
@ -206,7 +225,12 @@ val NoneSimilarToResult = SimilarToResult(0, emptyList())
val NoneDiscSeasonList = DiscSeasonList(0, emptyList()) val NoneDiscSeasonList = DiscSeasonList(0, emptyList())
val NoneContinueWatchingList = ContinueWatchingList(0, emptyList()) val NoneContinueWatchingList = ContinueWatchingList(0, emptyList())
val NoneUpNextSeriesItem = UpNextSeriesItem(0, false, false, NoneEpisodePanel) val NoneUpNextSeriesItem = UpNextSeriesItem(
playhead = 0,
fullyWatched = false,
neverWatched = false,
panel = NoneEpisodePanel
)
/** /**
* series data class * series data class

View File

@ -61,7 +61,6 @@ class HomeViewModel : ViewModel() {
uiState.emit(UiState.Loading) uiState.emit(UiState.Loading)
try { try {
// run the loading in parallel to speed up the process // run the loading in parallel to speed up the process
val upNextJob = viewModelScope.async { Crunchyroll.upNextAccount().items } val upNextJob = viewModelScope.async { Crunchyroll.upNextAccount().items }
val watchlistJob = viewModelScope.async { Crunchyroll.watchlist(50).items } val watchlistJob = viewModelScope.async { Crunchyroll.watchlist(50).items }
val recentlyAddedJob = viewModelScope.async { val recentlyAddedJob = viewModelScope.async {