diff options
| -rw-r--r-- | goanilist.go | 35 | ||||
| -rw-r--r-- | types.go | 119 |
2 files changed, 146 insertions, 8 deletions
diff --git a/goanilist.go b/goanilist.go index dc5d4b9..c280bb5 100644 --- a/goanilist.go +++ b/goanilist.go | |||
| @@ -9,6 +9,7 @@ import ( | |||
| 9 | "log" | 9 | "log" |
| 10 | "net/http" | 10 | "net/http" |
| 11 | "net/url" | 11 | "net/url" |
| 12 | "sort" | ||
| 12 | "time" | 13 | "time" |
| 13 | ) | 14 | ) |
| 14 | 15 | ||
| @@ -127,6 +128,39 @@ func (c *Client) User() (*UserResult, error) { | |||
| 127 | return res, nil | 128 | return res, nil |
| 128 | } | 129 | } |
| 129 | 130 | ||
| 131 | func (c *Client) Favourites(user int) (*FavouritesResult, error) { | ||
| 132 | if !c.IsCoupled { | ||
| 133 | return nil, ErrAnilistNotCoupled | ||
| 134 | } | ||
| 135 | if err := c.RenewToken(); err != nil { | ||
| 136 | return nil, err | ||
| 137 | } | ||
| 138 | res := &FavouritesResult{} | ||
| 139 | err := c.get(fmt.Sprintf("user/%d/favourites", user), res) | ||
| 140 | if err != nil { | ||
| 141 | return nil, err | ||
| 142 | } | ||
| 143 | if res.Characters != nil { | ||
| 144 | sort.Stable(res.Characters) | ||
| 145 | } | ||
| 146 | return res, nil | ||
| 147 | } | ||
| 148 | |||
| 149 | func (c *Client) CharacterPage(id int) (*CharacterPageResult, error) { | ||
| 150 | if !c.IsCoupled { | ||
| 151 | return nil, ErrAnilistNotCoupled | ||
| 152 | } | ||
| 153 | if err := c.RenewToken(); err != nil { | ||
| 154 | return nil, err | ||
| 155 | } | ||
| 156 | res := &CharacterPageResult{} | ||
| 157 | err := c.get(fmt.Sprintf("character/%d/page", id), res) | ||
| 158 | if err != nil { | ||
| 159 | return nil, err | ||
| 160 | } | ||
| 161 | return res, nil | ||
| 162 | } | ||
| 163 | |||
| 130 | func (c *Client) post(path string, values url.Values, result interface{}) error { | 164 | func (c *Client) post(path string, values url.Values, result interface{}) error { |
| 131 | resp, err := http.PostForm(fmt.Sprintf("%s%s", API_URL, path), values) | 165 | resp, err := http.PostForm(fmt.Sprintf("%s%s", API_URL, path), values) |
| 132 | if err != nil { | 166 | if err != nil { |
| @@ -154,6 +188,7 @@ func (c *Client) handleResponse(resp *http.Response, path string, values url.Val | |||
| 154 | return err | 188 | return err |
| 155 | } | 189 | } |
| 156 | err = json.Unmarshal(body, result) | 190 | err = json.Unmarshal(body, result) |
| 191 | //log.Println(string(body)) //Praktisch zum testen von neuen API-Funktionen | ||
| 157 | if err != nil { | 192 | if err != nil { |
| 158 | log.Println(string(body)) | 193 | log.Println(string(body)) |
| 159 | return err | 194 | return err |
| @@ -1,30 +1,49 @@ | |||
| 1 | package goanilist | 1 | package goanilist |
| 2 | 2 | ||
| 3 | import "encoding/json" | 3 | import ( |
| 4 | "encoding/json" | ||
| 5 | "strconv" | ||
| 6 | ) | ||
| 4 | 7 | ||
| 5 | type APIError interface { | 8 | type APIError interface { |
| 6 | Get() *FlexibleError | 9 | Get() *FlexibleError |
| 7 | } | 10 | } |
| 8 | 11 | ||
| 9 | type FlexibleError struct { | 12 | type FlexibleError struct { |
| 10 | RawError json.RawMessage `json:"error"` | 13 | RawError *json.RawMessage `json:"error"` |
| 11 | Error string | 14 | Error string |
| 12 | ErrorMessage string `json:"error_message"` | 15 | ErrorMessage string `json:"error_message"` |
| 13 | } | 16 | } |
| 14 | 17 | ||
| 15 | type complexError struct { | 18 | type complexError struct { |
| 16 | Error string `json:"error"` | 19 | Error string `json:"error"` |
| 17 | ErrorDescription string `json:"error_description"` | 20 | ErrorDescription string `json:"error_description"` |
| 21 | Status int `json:"status"` | ||
| 22 | Messages []string `json:"messages"` | ||
| 18 | } | 23 | } |
| 19 | 24 | ||
| 20 | func (e *FlexibleError) ParseRawError() { | 25 | func (e *FlexibleError) ParseRawError() { |
| 26 | if e.RawError == nil { | ||
| 27 | return | ||
| 28 | } | ||
| 21 | ce := complexError{} | 29 | ce := complexError{} |
| 22 | err := json.Unmarshal(e.RawError, &ce) | 30 | err := json.Unmarshal(*e.RawError, &ce) |
| 23 | if err == nil { | 31 | if err == nil { |
| 24 | e.Error = ce.Error | 32 | if ce.Error != "" { |
| 25 | e.ErrorMessage = ce.ErrorDescription | 33 | e.Error = ce.Error |
| 34 | e.ErrorMessage = ce.ErrorDescription | ||
| 35 | } else { | ||
| 36 | e.Error = strconv.Itoa(ce.Status) | ||
| 37 | e.ErrorMessage = "" | ||
| 38 | for k, v := range ce.Messages { | ||
| 39 | if k > 0 { | ||
| 40 | e.ErrorMessage += "\n" | ||
| 41 | } | ||
| 42 | e.ErrorMessage += v | ||
| 43 | } | ||
| 44 | } | ||
| 26 | } else { | 45 | } else { |
| 27 | e.Error = string(e.RawError) | 46 | e.Error = string(*e.RawError) |
| 28 | } | 47 | } |
| 29 | } | 48 | } |
| 30 | 49 | ||
| @@ -46,3 +65,87 @@ type UserResult struct { | |||
| 46 | ID int `json:"id"` | 65 | ID int `json:"id"` |
| 47 | DisplayName string `json:"display_name"` | 66 | DisplayName string `json:"display_name"` |
| 48 | } | 67 | } |
| 68 | |||
| 69 | type FavouritesResult struct { | ||
| 70 | FlexibleError | ||
| 71 | Characters CharacterResultCollection `json:"character"` | ||
| 72 | } | ||
| 73 | |||
| 74 | type CharacterResultCollection []CharacterResult | ||
| 75 | |||
| 76 | func (c CharacterResultCollection) Len() int { | ||
| 77 | return len(c) | ||
| 78 | } | ||
| 79 | |||
| 80 | func (c CharacterResultCollection) Less(i, j int) bool { | ||
| 81 | return c[i].Order < c[j].Order | ||
| 82 | } | ||
| 83 | |||
| 84 | func (c CharacterResultCollection) Swap(i, j int) { | ||
| 85 | c[i], c[j] = c[j], c[i] | ||
| 86 | } | ||
| 87 | |||
| 88 | type CharacterResult struct { | ||
| 89 | FlexibleError | ||
| 90 | ID int `json:"id"` | ||
| 91 | GivenName string `json:"name_first"` | ||
| 92 | FamilyName string `json:"name_last"` | ||
| 93 | JapaneseName string `json:"name_japanese"` | ||
| 94 | AlternativeName string `json:"name_alt"` | ||
| 95 | Info string `json:"info"` | ||
| 96 | Role string `json:"role"` | ||
| 97 | ImageURL string `json:"image_url_lge"` | ||
| 98 | ThumbURL string `json:"image_url_med"` | ||
| 99 | Order int `json:"order"` | ||
| 100 | } | ||
| 101 | |||
| 102 | type CharacterPageResult struct { | ||
| 103 | FlexibleError | ||
| 104 | CharacterResult | ||
| 105 | Anime []AnimeResult `json:"anime"` | ||
| 106 | Manga []MangaResult `json:"manga"` | ||
| 107 | } | ||
| 108 | |||
| 109 | type SeriesResult struct { | ||
| 110 | FlexibleError | ||
| 111 | ID int `json:"id"` | ||
| 112 | SeriesType string `json:"series_type"` | ||
| 113 | Type string `json:"type"` | ||
| 114 | TitleRomaji string `json:"title_romaji"` | ||
| 115 | TitleEnglish string `json:"title_english"` | ||
| 116 | TitleJapanese string `json:"title_japanese"` | ||
| 117 | Synonyms []string `json:"synonyms"` | ||
| 118 | Description string `json:"description"` | ||
| 119 | StartDate int64 `json:"start_date_fuzzy"` | ||
| 120 | EndDate int64 `json:"end_date_fuzzy"` | ||
| 121 | Season int `json:"season"` | ||
| 122 | Genres []string `json:"genres"` | ||
| 123 | Adult bool `json:"adult"` | ||
| 124 | AverageScore float32 `json:"average_score"` | ||
| 125 | Popularity int `json:"popularity"` | ||
| 126 | Favourite bool `json:"favourite"` | ||
| 127 | ImageURL string `json:"image_url_lge"` | ||
| 128 | ThumbSmallURL string `json:"image_url_sml"` | ||
| 129 | ThumbBigURL string `json:"image_url_med"` | ||
| 130 | BannerURL string `json:"image_url_banner"` | ||
| 131 | UpdatedAt int64 `json:"updated_at"` | ||
| 132 | } | ||
| 133 | |||
| 134 | type AnimeResult struct { | ||
| 135 | FlexibleError | ||
| 136 | SeriesResult | ||
| 137 | TotalEpisodes int `json:"total_episodes"` | ||
| 138 | EpisodeDuration int `json:"duration"` | ||
| 139 | AiringStatus string `json:"airing_status"` | ||
| 140 | YoutubeID string `json:"youtube_id"` | ||
| 141 | Hashtag string `json:"hashtag"` | ||
| 142 | Source string `json:"source"` | ||
| 143 | } | ||
| 144 | |||
| 145 | type MangaResult struct { | ||
| 146 | FlexibleError | ||
| 147 | SeriesResult | ||
| 148 | TotalChapters int `json:"total_chapters"` | ||
| 149 | TotalVolumes int `json:"total_volumes"` | ||
| 150 | PublishingStatus string `json:"publishing_status"` | ||
| 151 | } | ||
