/
match.go
147 lines (133 loc) · 4.46 KB
/
match.go
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
package lol
import (
"fmt"
"time"
log "github.com/sirupsen/logrus"
"github.com/KnutZuidema/golio/api"
"github.com/KnutZuidema/golio/internal"
)
// MatchClient provides methods for the match endpoints of the League of Legends API.
type MatchClient struct {
c *internal.Client
}
// MatchListOptions providing additional options for List
type MatchListOptions struct {
// Filter the list of match ids by a specific queue id. This filter is mutually inclusive
// of the type filter meaning any match ids returned must match both the queue and type filters.
Queue *int
// Filter the list of match ids by the type of match. This filter is mutually inclusive of
// the queue filter meaning any match ids returned must match both the queue and type
// filters. (see static.GameType.Type).
Type string
// Filter the list of matches by start and/or end time. The matchlist started storing timestamps
// on June 16th, 2021. Any matches played before June 16th, 2021 won't be included in the results
// if the StartTime filter is set.
StartTime, EndTime time.Time
}
func (mo *MatchListOptions) buildParam() string {
var param string
if mo.Queue != nil {
param += "&queue=" + fmt.Sprint(*mo.Queue)
}
if mo.Type != "" {
param += "&type=" + mo.Type
}
if !mo.StartTime.IsZero() {
param += "&startTime=" + fmt.Sprint(mo.StartTime.Unix())
}
if !mo.EndTime.IsZero() {
param += "&endTime=" + fmt.Sprint(mo.EndTime.Unix())
}
return param
}
// Get returns a match specified by its ID
func (m *MatchClient) Get(id string) (*Match, error) {
logger := m.logger().WithField("method", "Get")
c := *m.c // copy client
c.Region = api.Region(api.RegionToRoute[c.Region]) // Match v5 uses a route instead of a region
var match *Match
if err := c.GetInto(fmt.Sprintf(endpointGetMatch, id), &match); err != nil {
logger.Debug(err)
return nil, err
}
return match, nil
}
// List returns a list of match ids by puuid
func (m *MatchClient) List(puuid string, start, count int, options ...*MatchListOptions) (
[]string, error,
) {
logger := m.logger().WithField("method", "List")
c := *m.c // copy client
c.Region = api.Region(api.RegionToRoute[c.Region]) // Match v5 uses a route instead of a region
var matches []string
endpoint := fmt.Sprintf(endpointGetMatchIDs, puuid, start, count)
if len(options) != 0 {
endpoint += options[0].buildParam()
}
if err := c.GetInto(endpoint, &matches); err != nil {
logger.Debug(err)
return nil, err
}
return matches, nil
}
// MatchStreamValue value returned by ListStream, containing either a reference to a match or an error
type MatchStreamValue struct {
MatchID string
Error error
}
// ListStream returns all matches played on this account as a stream, requesting new until there are no
// more new games
func (m *MatchClient) ListStream(puuid string, options ...*MatchListOptions) <-chan MatchStreamValue {
logger := m.logger().WithField("method", "ListStream")
cMatches := make(chan MatchStreamValue, 100)
// Copy the input options to prevent caller modification while streaming
opts := make([]*MatchListOptions, 0)
for _, o := range options {
// Copy the value in case the caller modifies it after we return
queue := *options[0].Queue
// Shallow copy the other values
newOpt := *o
newOpt.Queue = &queue
opts = append(opts, &newOpt)
}
if len(options) != 0 && options[0].Queue != nil {
// Copy the value in case the caller modifies it after we return
queue := *options[0].Queue
options[0].Queue = &queue
}
go func() {
defer close(cMatches)
start := 0
for {
matches, err := m.List(puuid, start, 100, opts...)
if err != nil {
logger.Debug(err)
cMatches <- MatchStreamValue{Error: err}
return
}
for _, match := range matches {
cMatches <- MatchStreamValue{MatchID: match}
}
if len(matches) < 100 {
return
}
start += 100
}
}()
return cMatches
}
// GetTimeline returns the timeline for the given match
// NOTE: timelines are not available for every match
// TODO: update to v5 when struct is documented
func (m *MatchClient) GetTimeline(id string) (*MatchTimeline, error) {
logger := m.logger().WithField("method", "GetTimeline")
var timeline MatchTimeline
if err := m.c.GetInto(fmt.Sprintf(endpointGetMatchTimeline, id), &timeline); err != nil {
logger.Debug(err)
return nil, err
}
return &timeline, nil
}
func (m *MatchClient) logger() log.FieldLogger {
return m.c.Logger().WithField("category", "match")
}