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 | } | ||