1 // Low-level wrapper around the AniDB HTTP API.
2 // Only implements the 'anime' and 'categorylist' requests.
4 // This wrapper does not implement caching. The API requires
7 // http://wiki.anidb.info/w/HTTP_API_Definition
20 AniDBImageBaseURL = "http://img7.anidb.net/pics/anime/" // Base URL for the various Pictures in the response
22 DateFormat = "2006-01-02" // Use to convert the various YYYY-MM-DD timestamps to a time.Time.
26 aniDBHTTPAPIBaseURL = "http://api.anidb.net:9001/httpapi"
28 clientStr = "goanidbhttp"
32 // Requests information about the given Anime ID.
33 func GetAnime(AID int) (a Anime, err error) {
34 if res, err := doRequest("anime", reqMap{"aid": AID}); err != nil {
37 dec := xml.NewDecoder(res.Body)
41 a.Error = strings.TrimSpace(a.Error)
47 type reqMap map[string]interface{}
49 func doRequest(request string, reqMap reqMap) (*http.Response, error) {
51 v.Set("protover", fmt.Sprint(aniDBProtoVer))
52 v.Set("client", clientStr)
53 v.Set("clientver", fmt.Sprint(clientVer))
54 v.Set("request", request)
56 for k, val := range reqMap {
57 v.Add(k, fmt.Sprint(val))
60 u, _ := url.Parse(aniDBHTTPAPIBaseURL)
61 u.RawQuery = v.Encode()
62 log.Println(u.String())
63 return http.Get(u.String())
66 // Title with language and type identifier.
68 // Title with Lang = ja, Type = official is the official Kanji title.
70 // Title with Lang = x-jat, Type = main is the romanized version, also known in other APIs as the Primary Title.
71 type AnimeTitle struct {
72 Lang string `xml:"lang,attr"` // Language in ISO-ish format
73 Type string `xml:"type,attr"` // "official", "short", etc
74 Title string `xml:",chardata"`
77 type RelatedAnime struct {
78 ID int `xml:"id,attr"` // AID of the related anime
79 Type string `xml:"type,attr"` // "prequel", "sequel", etc
80 Title string `xml:",chardata"` // Primary title of the related anime
83 type SimilarAnime struct {
84 ID int `xml:"id,attr"` // AID of the similar anime
85 Approval int `xml:"approval,attr"` // How many users have approved of this connection
86 Total int `xml:"total,attr"` // Total of votes in this connection
87 Title string `xml:",chardata"` // Primary title of the recommended anime
90 type Recommendation struct {
91 Type string `xml:"type,attr"` // "Recommended", "Must See", etc
92 ID int `xml:"uid,attr"` // User ID of the recommending user
93 Text string `xml:",chardata"` // Text of the user's recommendation
97 ID int `xml:"id,attr"` // Creator ID
98 Type string `xml:"type,attr"`
99 Name string `xml:",chardata"` // Always romaji
102 // Separate from regular Rating because the XML structure is different.
103 type AnimeRating struct {
104 Count int `xml:"count,attr"` // Amount of votes/reviews
105 Rating float32 `xml:",chardata"` // Average
108 type AnimeRatings struct {
109 Permanent AnimeRating `xml:"permanent"` // Votes from people who watched everything
110 Temporary AnimeRating `xml:"temporary"` // Votes from people who are still watching it
111 Review AnimeRating `xml:"review"` // Votes from reviews
114 type Category struct {
115 ID int `xml:"id,attr"` // Category ID
116 ParentID int `xml:"parentid,attr"` // ID of the parent category
117 R18 bool `xml:"hentai,attr"` // Whether the category represents porn works or not
118 Weight int `xml:"weight,attr"` // Weight of the category for this anime
120 Name string `xml:"name"` // Category name
121 Description string `xml:"description"` // Category description
124 // Completely undocumented.
125 // Most entries just have one or two numbers as Identifiers.
127 // Type 4 appears to have the official URL in .URL[0]
129 // Type 7 appears to have the official name in .Identifiers[0]
130 type Resource struct {
131 Type int `xml:"type,attr"`
132 Identifiers []string `xml:"externalentity>identifier"`
133 URL []string `xml:"externalentity>url"`
137 ID int `xml:"id,attr"` // Tag ID
138 Approval int `xml:"approval,attr"` // How many users have approved of the tag
139 Spoiler bool `xml:"localspoiler,attr"` // undocumented
140 GlobalSpoiler bool `xml:"globalspoiler,attr"` // undocumented
141 Updated string `xml:"update,attr"` // YYYY-MM-DD
143 Name string `xml:"name"` // Tag name
144 Count int `xml:"count"` // undocumented
148 ID int `xml:"id,attr"` // Creator ID
149 Name string `xml:",chardata"` // Always romaji
150 Picture string `xml:"picture,attr"` // Picture basename; combine with AniDBImageBaseURL for full URL
153 type Character struct {
154 ID int `xml:"id,attr"` // Character ID
155 Type string `xml:"type,attr"` // "main character in", "secondary cast in", "appears in"
156 Updated string `xml:"update,attr"` // YYYY-MM-DD
158 Rating Rating `xml:"rating"`
159 Name string `xml:"name"` // Always romaji
160 Gender string `xml:"gender"` // "male", "female", "unknown", sometimes blank
161 Description string `xml:"description"`
162 CharacterType string `xml:"charactertype"` // "Character", "Organization", "Vessel", etc
163 Episodes string `xml:"episodes"` // List of episodes where character appears
164 Picture string `xml:"picture"` // Picture basename; combine with AniDBImageBaseURL for full URL
166 Seiyuu *Seiyuu `xml:"seiyuu"` // The voice actor, if present
169 type Characters []Character // Implements sort.Interface; groups by Type and sorts by Name
171 type EpisodeTitle struct {
172 Lang string `xml:"lang,attr"`
173 Title string `xml:",chardata"`
177 Votes int `xml:"votes,attr"`
178 Rating float32 `xml:",chardata"`
182 Type int `xml:"type,attr"` // 1 for regular episodes, 2 for specials, etc
183 EpNo string `xml:",chardata"` // Not necessarily a plain integer; may be prefixed by a single letter indicating the Type
186 type Episode struct {
187 ID int `xml:"id,attr"` // Episode ID
188 Updated string `xml:"update,attr"` // YYYY-MM-DD
190 EpNo EpNo `xml:"epno"`
191 Length int `xml:"length"` // Length in minutes (rounding method undocumented)
192 AirDate string `xml:"airdate"` // YYYY-MM-DD
193 Rating Rating `xml:"rating"`
194 Titles []EpisodeTitle `xml:"title"`
197 type Episodes []Episode // Implements sort.Interface; groups by EpNo.Type, orders by the integer portion of EpNo.EpNo
200 Error string `xml:",chardata"` // API request encountered an error if this is not ""
202 ID int `xml:"id,attr"` // AID of the anime
203 R18 bool `xml:"restricted,attr"` // Whether the anime is considered porn
205 Type string `xml:"type"` // "TV Series", "Movie", "OVA", etc
206 EpisodeCount int `xml:"episodecount"` // Unreliable, has a set value even when the total number is unknown
207 StartDate string `xml:"startdate"` // YYYY-MM-DD
208 EndDate string `xml:"enddate"` // YYYY-MM-DD
210 Titles []AnimeTitle `xml:"titles>title"`
211 RelatedAnime []RelatedAnime `xml:"relatedanime>anime"`
212 SimilarAnime []SimilarAnime `xml:"similaranime>anime"`
214 Recommendations []Recommendation `xml:"recommendations>recommendation"`
216 URL string `xml:"url"` // Official URL
218 Creators []Creator `xml:"creators>name"`
220 Description string `xml:"description"`
222 Ratings AnimeRatings `xml:"ratings"`
224 Picture string `xml:"picture"` // Picture basename; combine with AniDBImageBaseURL for full URL
226 Categories []Category `xml:"categories>category"` // Unsorted
227 Resources []Resource `xml:"resources>resource"` // undocumented
228 Tags []Tag `xml:"tags>tag"` // Unsorted
229 Characters Characters `xml:"characters>character"` // Unsorted
230 Episodes Episodes `xml:"episodes>episode"` // Unsorted