forked from sgt-kabukiman/srapi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathseries.go
More file actions
149 lines (118 loc) · 4.34 KB
/
series.go
File metadata and controls
149 lines (118 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) 2015, Sgt. Kabukiman | MIT licensed
package srapi
import "net/url"
// Series represents a series.
type Series struct {
// unique ID
ID string
// names, international is always set, japanese sometimes
Names struct {
International string
Japanese string
}
// unique abbreviation of the game, e.g. "gta" for Grand Theft Auto
Abbreviation string
// link to the series page on speedrun.com
Weblink string
// list of assets (images) for the series page design on speedrun.com, like
// icons for trophies, background images etc.
Assets map[string]*AssetLink
// API links to related resources
Links []Link
// do not use this field directly, use the available methods
ModeratorsData interface{} `json:"moderators"`
}
// seriesResponse models the actual API response from the server
type seriesResponse struct {
// the one series contained in the response
Data Series
}
// SeriesByID tries to fetch a single series, identified by its ID.
// When an error is returned, the returned series is nil.
func SeriesByID(id string, embeds string) (*Series, *Error) {
return fetchOneSeries(request{"GET", "/series/" + id, nil, nil, nil, embeds})
}
// SeriesByAbbreviation tries to fetch a single series, identified by its
// abbreviation. This is convenient for resolving abbreviations, but as they can
// change (in constrast to the ID, which is fixed), it should be used with
// caution.
// When an error is returned, the returned series is nil.
func SeriesByAbbreviation(abbrev string, embeds string) (*Series, *Error) {
return SeriesByID(abbrev, embeds)
}
// Games fetches the list of games for the series, optionally filtering it.
func (s *Series) Games(filter *GameFilter, sort *Sorting, embeds string) (*GameCollection, *Error) {
return fetchGamesLink(firstLink(s, "games"), filter, sort, embeds)
}
// ModeratorMap returns a map of user IDs to their respective moderation levels.
// Note that due to limitations of the speedrun.com API, the mod levels are not
// available when moderators have been embedded. In this case, the resulting
// map containts UnknownModLevel for every user. If you need both, there is no
// other way than to perform two requests.
func (s *Series) ModeratorMap() map[string]GameModLevel {
return recastToModeratorMap(s.ModeratorsData)
}
// Moderators returns a list of users that are moderators of the series. If
// moderators were not embedded, they will be fetched individually from the
// network.
func (s *Series) Moderators() (*UserCollection, *Error) {
return recastToModerators(s.ModeratorsData)
}
// for the 'hasLinks' interface
func (s *Series) links() []Link {
return s.Links
}
// SeriesFilter represents the possible filtering options when fetching a list
// of series.
type SeriesFilter struct {
Name string
Abbreviation string
Moderator string
}
// applyToURL merged the filter into a URL.
func (sf *SeriesFilter) applyToURL(u *url.URL) {
if sf == nil {
return
}
values := u.Query()
if len(sf.Name) > 0 {
values.Set("name", sf.Name)
}
if len(sf.Abbreviation) > 0 {
values.Set("abbreviation", sf.Abbreviation)
}
if len(sf.Moderator) > 0 {
values.Set("moderator", sf.Moderator)
}
u.RawQuery = values.Encode()
}
// ManySeries retrieves a collection of series.
func ManySeries(f *SeriesFilter, s *Sorting, c *Cursor, embeds string) (*SeriesCollection, *Error) {
return fetchManySeries(request{"GET", "/series", f, s, c, embeds})
}
// fetchOneSeries fetches a single series from the network. If the request failed,
// the returned series is nil. Otherwise, the error is nil.
func fetchOneSeries(request request) (*Series, *Error) {
result := &seriesResponse{}
err := httpClient.do(request, result)
if err != nil {
return nil, err
}
return &result.Data, nil
}
// fetchOneSeriesLink tries to fetch a given link and interpret the response as
// a single series. If the link is nil or the series could not be fetched,
// nil is returned.
func fetchOneSeriesLink(link requestable, embeds string) (*Series, *Error) {
if !link.exists() {
return nil, nil
}
return fetchOneSeries(link.request(nil, nil, embeds))
}
// fetchManySeries fetches a list of series from the network. It always
// returns a collection, even when an error is returned.
func fetchManySeries(request request) (*SeriesCollection, *Error) {
result := &SeriesCollection{}
err := httpClient.do(request, result)
return result, err
}