diff --git a/account.go b/account.go new file mode 100644 index 0000000..f6f87f1 --- /dev/null +++ b/account.go @@ -0,0 +1,27 @@ +package crunchyroll + +// Account contains information about a crunchyroll account. +type Account struct { + AccountID string `json:"account_id"` + ExternalID string `json:"external_id"` + EmailVerified bool `json:"email_verified"` + Created string `json:"created"` + + Avatar string `json:"avatar"` + CrBetaOptIn bool `json:"cr_beta_opt_in"` + Email string `json:"email"` + MatureContentFlagManga string `json:"mature_content_flag_manga"` + MaturityRating string `json:"maturity_rating"` + OptOutAndroidInAppMarketing bool `json:"opt_out_android_in_app_marketing"` + OptOutFreeTrials bool `json:"opt_out_free_trials"` + OptOutNewMediaQueueUpdates bool `json:"opt_out_new_media_queue_updates"` + OptOutNewsletters bool `json:"opt_out_newsletters"` + OptOutPmUpdates bool `json:"opt_out_pm_updates"` + OptOutPromotionalUpdates bool `json:"opt_out_promotional_updates"` + OptOutQueueUpdates bool `json:"opt_out_queue_updates"` + OptOutStoreDeals bool `json:"opt_out_store_deals"` + PreferredCommunicationLanguage LOCALE `json:"preferred_communication_language"` + PreferredContentSubtitleLanguage LOCALE `json:"preferred_content_subtitle_language"` + QaUser bool `json:"qa_user"` + Username string `json:"username"` +} diff --git a/crunchyroll.go b/crunchyroll.go index aefce1a..4e5a436 100644 --- a/crunchyroll.go +++ b/crunchyroll.go @@ -30,15 +30,6 @@ const ( AR = "ar-SA" ) -// SortOrder represents a sort order. -type SortOrder string - -const ( - POPULARITY SortOrder = "popularity" - NEWLYADDED = "newly_added" - ALPHABETICAL = "alphabetical" -) - // MediaType represents a media type. type MediaType string @@ -47,6 +38,15 @@ const ( MOVIELISTING = "movie_listing" ) +// SortType represents a sort type. +type SortType string + +const ( + POPULARITY SortType = "popularity" + NEWLYADDED = "newly_added" + ALPHABETICAL = "alphabetical" +) + type Crunchyroll struct { // Client is the http.Client to perform all requests over. Client *http.Client @@ -79,25 +79,25 @@ type Crunchyroll struct { // BrowseOptions represents options for browsing the crunchyroll catalog. type BrowseOptions struct { - // Categories specifies the categories of the results. + // Categories specifies the categories of the entries. Categories []string `param:"categories"` - // IsDubbed specifies whether the results should be dubbed. + // IsDubbed specifies whether the entries should be dubbed. IsDubbed bool `param:"is_dubbed"` - // IsSubbed specifies whether the results should be subbed. + // IsSubbed specifies whether the entries should be subbed. IsSubbed bool `param:"is_subbed"` - // SimulcastID specifies a particular simulcast season in which the results have been aired. - SimulcastID string `param:"season_tag"` + // Simulcast specifies a particular simulcast season by id in which the entries have been aired. + Simulcast string `param:"season_tag"` - // SortBy specifies how the results should be sorted. - SortBy SortOrder `param:"sort_by"` + // Sort specifies how the entries should be sorted. + Sort SortType `param:"sort_by"` - // Start specifies the index from which the results should be returned. + // Start specifies the index from which the entries should be returned. Start uint `param:"start"` - // Type specifies the media type of the results. + // Type specifies the media type of the entries. Type MediaType `param:"type"` } @@ -672,7 +672,7 @@ func (c *Crunchyroll) Recommendations(limit uint) (s []*Series, m []*Movie, err return s, m, nil } -// UpNext returns the episodes that are up next based on your account within the given limit. +// UpNext returns the episodes that are up next based on the currently logged in account within the given limit. func (c *Crunchyroll) UpNext(limit uint) (e []*Episode, err error) { upNextAccountEndpoint := fmt.Sprintf("https://beta-api.crunchyroll.com/content/v1/%s/up_next_account?n=%d&locale=%s", c.Config.AccountID, limit, c.Locale) @@ -703,7 +703,7 @@ func (c *Crunchyroll) UpNext(limit uint) (e []*Episode, err error) { return e, nil } -// SimilarTo returns similar series and movies according to crunchyroll to the one specified by id within the given limits. +// SimilarTo returns similar series and movies according to crunchyroll to the one specified by id within the given limit. func (c *Crunchyroll) SimilarTo(id string, limit uint) (s []*Series, m []*Movie, err error) { similarToEndpoint := fmt.Sprintf("https://beta-api.crunchyroll.com/content/v1/%s/similar_to?guid=%s&n=%d&locale=%s", c.Config.AccountID, id, limit, c.Locale) @@ -747,7 +747,7 @@ func (c *Crunchyroll) SimilarTo(id string, limit uint) (s []*Series, m []*Movie, return s, m, nil } -// WatchHistory returns the history of watched episodes based on your account from the given page with the given size. +// WatchHistory returns the history of watched episodes based on the currently logged in account from the given page with the given size. func (c *Crunchyroll) WatchHistory(page uint, size uint) (e []*HistoryEpisode, err error) { watchHistoryEndpoint := fmt.Sprintf("https://beta-api.crunchyroll.com/content/v1/watch-history/%s?page=%d&page_size=%d&locale=%s", c.Config.AccountID, page, size, c.Locale) @@ -784,3 +784,35 @@ func (c *Crunchyroll) WatchHistory(page uint, size uint) (e []*HistoryEpisode, e return e, nil } + +// Account returns information about the currently logged in crunchyroll account. +func (c *Crunchyroll) Account() (*Account, error) { + resp, err := c.request("https://beta.crunchyroll.com/accounts/v1/me") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var jsonBody map[string]interface{} + if err = json.NewDecoder(resp.Body).Decode(&jsonBody); err != nil { + return nil, fmt.Errorf("failed to parse 'me' response: %w", err) + } + + resp, err = c.request("https://beta.crunchyroll.com/accounts/v1/me/profile") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if err = json.NewDecoder(resp.Body).Decode(&jsonBody); err != nil { + return nil, fmt.Errorf("failed to parse 'profile' response: %w", err) + } + + account := &Account{} + + if err := decodeMapToStruct(jsonBody, account); err != nil { + return nil, err + } + + return account, nil +}