Initial commit.
commit
055b2a4227
|
@ -0,0 +1,24 @@
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
|
@ -0,0 +1,17 @@
|
||||||
|
language: go
|
||||||
|
go:
|
||||||
|
- 1.3.3
|
||||||
|
- 1.4.3
|
||||||
|
- 1.5.4
|
||||||
|
- 1.6.2
|
||||||
|
- release
|
||||||
|
- tip
|
||||||
|
|
||||||
|
install:
|
||||||
|
- export GOPATH="$HOME/gopath"
|
||||||
|
- mkdir -p "$GOPATH/src/github.com/icedream"
|
||||||
|
- mv "$TRAVIS_BUILD_DIR" "$GOPATH/src/github.com/icedream"
|
||||||
|
- go get -v -t -d github.com/icedream/go-footballdata/...
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -v github.com/icedream/go-footballdata/...
|
|
@ -0,0 +1,47 @@
|
||||||
|
# Football-Data API for Golang
|
||||||
|
|
||||||
|
[](https://travis-ci.org/icedream/go-footballdata)
|
||||||
|
[](https://godoc.org/github.com/icedream/go-footballdata)
|
||||||
|
|
||||||
|
This library provides functionality to communicate with the API provided by http://football-api.org. This way programs can use data provided by the API in order to show information about football/soccer games from various seasons for free.
|
||||||
|
|
||||||
|
## How to use this library?
|
||||||
|
|
||||||
|
Before you use this library please [register for a free API key](http://api.football-data.org/register) in order to increase your usage limits. The library also works without an API key.
|
||||||
|
|
||||||
|
You can install this library by running:
|
||||||
|
|
||||||
|
go get github.com/icedream/go-footballdata
|
||||||
|
|
||||||
|
Afterwards you can use this library like this:
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/icedream/go-footballdata"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Create client
|
||||||
|
client := footballdata.NewClient(http.DefaultClient)
|
||||||
|
|
||||||
|
// Tell it to use our API token
|
||||||
|
client.AuthToken = "<insert your api token here>"
|
||||||
|
|
||||||
|
// Get list of seasons...
|
||||||
|
seasons, err := client.SoccerSeasons().Do()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...and print them
|
||||||
|
for _, season := range seasons {
|
||||||
|
fmt.Println(season.Id, season.Caption)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
|
@ -0,0 +1,16 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type request struct {
|
||||||
|
c *Client
|
||||||
|
p string
|
||||||
|
v url.Values
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r request) doJson(method string) (*json.Decoder, ResponseMeta, error) {
|
||||||
|
return r.c.doJson(method, r.p, r.v)
|
||||||
|
}
|
|
@ -0,0 +1,124 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type FixtureStatus string
|
||||||
|
|
||||||
|
const (
|
||||||
|
FixtureStatus_Timed FixtureStatus = "TIMED"
|
||||||
|
FixtureStatus_InPlay FixtureStatus = "IN_PLAY"
|
||||||
|
FixtureStatus_Finished FixtureStatus = "FINISHED"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Describes the venue.
|
||||||
|
type Venue string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// The home venue.
|
||||||
|
Venue_Home Venue = "home"
|
||||||
|
// The away venue.
|
||||||
|
Venue_Away Venue = "away"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Contains the list of soccer seasons returned by the API.
|
||||||
|
type SoccerSeasonList []SoccerSeason
|
||||||
|
|
||||||
|
// Contains information about a soccer season.
|
||||||
|
type SoccerSeason struct {
|
||||||
|
Id uint64
|
||||||
|
Caption string
|
||||||
|
League string
|
||||||
|
Year string
|
||||||
|
CurrentMatchday uint16
|
||||||
|
NumberOfMatchdays uint16
|
||||||
|
NumberOfTeams uint16
|
||||||
|
NumberOfGames uint16
|
||||||
|
LastUpdates time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains the fixture and the head to head information delivered by the API
|
||||||
|
// for a wanted fixture.
|
||||||
|
type FixtureResponse struct {
|
||||||
|
Fixture Fixture
|
||||||
|
Head2Head Head2Head
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains head to head information.
|
||||||
|
type Head2Head struct {
|
||||||
|
Count uint64
|
||||||
|
TimeFrameStart time.Time
|
||||||
|
TimeFrameEnd time.Time
|
||||||
|
HomeTeamWins uint64
|
||||||
|
AwayTeamWins uint64
|
||||||
|
Draws uint64
|
||||||
|
LastHomeWinHomeTeam *Fixture
|
||||||
|
LastWinHomeTeam *Fixture
|
||||||
|
LastAwayWinAwayTeam *Fixture
|
||||||
|
Fixtures []Fixture
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains information about a fixture.
|
||||||
|
type Fixture struct {
|
||||||
|
Date time.Time
|
||||||
|
Status FixtureStatus
|
||||||
|
Matchday uint16
|
||||||
|
HomeTeamName string
|
||||||
|
AwayTeamName string
|
||||||
|
Result FixtureResult
|
||||||
|
|
||||||
|
//HomeTeamId uint64
|
||||||
|
//AwayTeamId uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains a list of fixtures.
|
||||||
|
type FixtureList struct {
|
||||||
|
Count uint64
|
||||||
|
Fixtures []Fixture
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains information about a list of fixtures as returned by the API.
|
||||||
|
type FixturesResponse struct {
|
||||||
|
FixtureList
|
||||||
|
|
||||||
|
TimeFrameStart time.Time
|
||||||
|
TimeFrameEnd time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains information about a fixture's results.
|
||||||
|
type FixtureResult struct {
|
||||||
|
GoalsHomeTeam uint16
|
||||||
|
GoalsAwayTeam uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains a list of teams.
|
||||||
|
type TeamList struct {
|
||||||
|
Count uint64
|
||||||
|
Teams []Team
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains information about a team.
|
||||||
|
type Team struct {
|
||||||
|
Id uint64
|
||||||
|
Name string
|
||||||
|
ShortName string
|
||||||
|
SquadMarketValue string
|
||||||
|
CrestUrl string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains a list of players.
|
||||||
|
type PlayerList struct {
|
||||||
|
Count uint64
|
||||||
|
Players []Player
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains information about a player.
|
||||||
|
type Player struct {
|
||||||
|
Id uint64
|
||||||
|
Name string
|
||||||
|
Position string
|
||||||
|
JerseyNumber uint8
|
||||||
|
DateOfBirth time.Time
|
||||||
|
Nationality string
|
||||||
|
ContractUntil time.Time
|
||||||
|
MarketValue string
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import "net/url"
|
||||||
|
|
||||||
|
const (
|
||||||
|
baseUrl = "http://api.football-data.org/v1/"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resolveRelativeUrl(path string, values url.Values) *url.URL {
|
||||||
|
if values == nil {
|
||||||
|
values = url.Values{}
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := url.Parse(baseUrl)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ru := &url.URL{Path: path, RawQuery: values.Encode()}
|
||||||
|
|
||||||
|
return u.ResolveReference(ru)
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Provides a high-level client to talk to the API that football-data.org offers.
|
||||||
|
|
||||||
|
To create an instance please use NewClient(h).
|
||||||
|
*/
|
||||||
|
type Client struct {
|
||||||
|
h *http.Client
|
||||||
|
|
||||||
|
// Insert an API token here if you have one. It will be sent across with all requests.
|
||||||
|
AuthToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new Client instance that wraps around the given HTTP client.
|
||||||
|
func NewClient(h *http.Client) *Client {
|
||||||
|
return &Client{h: h}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) req(path string, pathValues ...interface{}) request {
|
||||||
|
return request{c, fmt.Sprintf(path, pathValues...), url.Values{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes an HTTP request with given parameters and on success returns the response wrapped in a JSON decoder.
|
||||||
|
func (c *Client) doJson(method string, path string, values url.Values) (j *json.Decoder, meta ResponseMeta, err error) {
|
||||||
|
// Create request
|
||||||
|
req := &http.Request{
|
||||||
|
Method: method,
|
||||||
|
URL: resolveRelativeUrl(path, values),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set request headers
|
||||||
|
if len(c.AuthToken) > 0 {
|
||||||
|
req.Header.Set("X-Auth-Token", c.AuthToken)
|
||||||
|
}
|
||||||
|
req.Header.Set("X-Response-Control", "minified")
|
||||||
|
req.Header.Set("User-Agent", "go-footballdata/0.0")
|
||||||
|
|
||||||
|
// Execute request
|
||||||
|
resp, err := c.h.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save metadata from headers
|
||||||
|
meta = responseMetaFromHeaders(resp.Header)
|
||||||
|
|
||||||
|
// Download to buffer to allow passing back a fully prepared decoder
|
||||||
|
defer resp.Body.Close()
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
io.Copy(buf, resp.Body)
|
||||||
|
|
||||||
|
// Wrap JSON decoder around buffered data
|
||||||
|
j = json.NewDecoder(buf)
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package footballdata_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/icedream/go-footballdata"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Example() {
|
||||||
|
// Create client
|
||||||
|
client := footballdata.NewClient(http.DefaultClient)
|
||||||
|
|
||||||
|
// Tell it to use our API token
|
||||||
|
client.AuthToken = "<insert your api token here>"
|
||||||
|
|
||||||
|
// Get list of seasons...
|
||||||
|
seasons, err := client.SoccerSeasons().Do()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...and print them
|
||||||
|
for _, season := range seasons {
|
||||||
|
fmt.Println(season.Id, season.Caption)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type FixtureRequest struct{ request }
|
||||||
|
|
||||||
|
// Modifies the request to specify the number of former games to be analyzed (normally 10).
|
||||||
|
func (r FixtureRequest) Head2Head(num uint16) FixtureRequest {
|
||||||
|
r.v.Set("head2head", fmt.Sprintf("%i", num))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r FixtureRequest) Do() (s Fixture, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a request to fetch the fixtures of a soccer season.
|
||||||
|
func (c *Client) Fixture(id uint64) FixtureRequest {
|
||||||
|
return FixtureRequest{c.req("fixture/%i", id)}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FixturesRequest struct{ request }
|
||||||
|
|
||||||
|
// Modifies the request to specify a specific time frame.
|
||||||
|
func (r FixturesRequest) TimeFrame(timeframe time.Duration) FixturesRequest {
|
||||||
|
r.v.Set("timeFrame", durationToTimeFrame(timeframe))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modifies the request to specify a list of leagues by their code.
|
||||||
|
func (r FixturesRequest) League(leagueCodes ...string) FixturesRequest {
|
||||||
|
r.v.Set("league", strings.Join(leagueCodes, ","))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r FixturesRequest) Do() (s FixturesResponse, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a request to fetch the fixtures of a soccer season.
|
||||||
|
func (c *Client) Fixtures() FixturesRequest {
|
||||||
|
return FixturesRequest{c.req("fixtures")}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
type SoccerSeasonRequest struct{ request }
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r SoccerSeasonRequest) Do() (s SoccerSeason, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a request to fetch the complete list of soccer seasons.
|
||||||
|
func (c *Client) SoccerSeason(id uint64) SoccerSeasonRequest {
|
||||||
|
return SoccerSeasonRequest{c.req("soccerseasons/%i", id)}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SoccerSeasonFixturesRequest struct{ request }
|
||||||
|
|
||||||
|
// Modifies the request to specify a match day.
|
||||||
|
func (r SoccerSeasonFixturesRequest) Matchday(matchday uint16) SoccerSeasonFixturesRequest {
|
||||||
|
r.v.Set("matchday", fmt.Sprintf("%i", matchday))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modifies the request to specify a specific time frame.
|
||||||
|
func (r SoccerSeasonFixturesRequest) TimeFrame(timeframe time.Duration) SoccerSeasonFixturesRequest {
|
||||||
|
r.v.Set("timeFrame", durationToTimeFrame(timeframe))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r SoccerSeasonFixturesRequest) Do() (s SoccerSeason, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a request to fetch the fixtures of a soccer season.
|
||||||
|
func (c *Client) FixturesOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonFixturesRequest {
|
||||||
|
return SoccerSeasonFixturesRequest{c.req("soccerseasons/%i/fixtures", soccerSeasonId)}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type SoccerSeasonLeagueTableRequest struct{ request }
|
||||||
|
|
||||||
|
// Modifies the request to specify a match day.
|
||||||
|
func (r SoccerSeasonLeagueTableRequest) Matchday(matchday uint16) SoccerSeasonLeagueTableRequest {
|
||||||
|
r.v.Set("matchday", fmt.Sprintf("%i", matchday))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r SoccerSeasonLeagueTableRequest) Do() (s SoccerSeason, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a new request to fetch the league table of a given soccer season.
|
||||||
|
func (c *Client) LeagueTableOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonLeagueTableRequest {
|
||||||
|
return SoccerSeasonLeagueTableRequest{c.req("soccerseasons/%i/leagueTable", soccerSeasonId)}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
type SoccerSeasonTeamsRequest struct{ request }
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r SoccerSeasonTeamsRequest) Do() (s TeamList, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a new request to fetch the league table of a given soccer season.
|
||||||
|
func (c *Client) TeamsOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonTeamsRequest {
|
||||||
|
return SoccerSeasonTeamsRequest{c.req("soccerseasons/%i/leagueTable", soccerSeasonId)}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type SoccerSeasonsRequest struct{ request }
|
||||||
|
|
||||||
|
// Modifies the request to specify a season.
|
||||||
|
func (r SoccerSeasonsRequest) Season(num uint32) SoccerSeasonsRequest {
|
||||||
|
r.v.Set("season", fmt.Sprintf("%i", num))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r SoccerSeasonsRequest) Do() (s SoccerSeasonList, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a request to fetch the complete list of soccer seasons.
|
||||||
|
func (c *Client) SoccerSeasons() SoccerSeasonsRequest {
|
||||||
|
return SoccerSeasonsRequest{c.req("soccerseasons")}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
type TeamRequest struct {
|
||||||
|
request
|
||||||
|
id uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r TeamRequest) Do() (s Team, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
if err != nil {
|
||||||
|
// Fill up data not returned by the server
|
||||||
|
s.Id = r.id
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a request to fetch a team's information.
|
||||||
|
func (c *Client) Team(id uint64) TeamRequest {
|
||||||
|
return TeamRequest{c.req("teams/%i", id), id}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TeamFixturesRequest struct{ request }
|
||||||
|
|
||||||
|
// Modifies the request to specify a specific time frame.
|
||||||
|
func (r TeamFixturesRequest) TimeFrame(timeframe time.Duration) TeamFixturesRequest {
|
||||||
|
r.v.Set("timeFrame", durationToTimeFrame(timeframe))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modifies the request to specify a list of leagues by their code.
|
||||||
|
func (r TeamFixturesRequest) Season(season uint64) TeamFixturesRequest {
|
||||||
|
r.v.Set("season", fmt.Sprintf("%i", season))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modifies the request to specify a venue.
|
||||||
|
func (r TeamFixturesRequest) Venue(venue Venue) TeamFixturesRequest {
|
||||||
|
r.v.Set("venue", string(venue))
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r TeamFixturesRequest) Do() (s FixturesResponse, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a request to fetch the fixtures of a soccer season.
|
||||||
|
func (c *Client) FixturesOfTeam(id uint64) TeamFixturesRequest {
|
||||||
|
return TeamFixturesRequest{c.req("teams/%i/fixtures", id)}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
type TeamPlayersRequest struct{ request }
|
||||||
|
|
||||||
|
// Executes the request.
|
||||||
|
func (r TeamPlayersRequest) Do() (s PlayerList, err error) {
|
||||||
|
d, _, err := r.doJson("GET")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = d.Decode(&s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepares a request to fetch a team's players.
|
||||||
|
func (c *Client) PlayersOfTeam(id uint64) TeamPlayersRequest {
|
||||||
|
return TeamPlayersRequest{c.req("teams/%i/players", id)}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Contains additional information returned by the Football-Data API in the HTTP headers.
|
||||||
|
// This includes the currently authenticated user and information about the rate limitation.
|
||||||
|
type ResponseMeta struct {
|
||||||
|
// Indicates the recognized user or returns "anonymous" if not authenticated.
|
||||||
|
AuthenticatedClient string
|
||||||
|
|
||||||
|
// Defines the seconds left to reset your request counter.
|
||||||
|
RequestCounterReset uint64
|
||||||
|
|
||||||
|
// Indicates the requests left.
|
||||||
|
RequestsAvailable uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func responseMetaFromHeaders(h http.Header) (r ResponseMeta) {
|
||||||
|
if v := h.Get("X-Authenticated-Client"); v != "" {
|
||||||
|
r.AuthenticatedClient = v
|
||||||
|
}
|
||||||
|
if v := h.Get("X-RequestCounter-Reset"); v != "" {
|
||||||
|
i, err := strconv.ParseUint(v, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
r.RequestCounterReset = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v := h.Get("X-Requests-Available"); v != "" {
|
||||||
|
i, err := strconv.ParseUint(v, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
r.RequestsAvailable = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
day = 24 * time.Hour
|
||||||
|
week = 7 * day
|
||||||
|
)
|
||||||
|
|
||||||
|
func durationToTimeFrame(d time.Duration) (r string) {
|
||||||
|
if d < 0 {
|
||||||
|
r = "p"
|
||||||
|
d = -d
|
||||||
|
} else if d > 0 {
|
||||||
|
r = "n"
|
||||||
|
}
|
||||||
|
r += fmt.Sprint(d.Hours() / 24)
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package footballdata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_durationToTimeFrame_Zero(t *testing.T) {
|
||||||
|
assert.Equal(t, "0", durationToTimeFrame(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_durationToTimeFrame_Negative7Days(t *testing.T) {
|
||||||
|
assert.Equal(t, "p7", durationToTimeFrame(-7*day))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_durationToTimeFrame_Positive7Days(t *testing.T) {
|
||||||
|
assert.Equal(t, "n7", durationToTimeFrame(7*day))
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_durationToTimeFrame_PositiveHalfDay(t *testing.T) {
|
||||||
|
assert.Equal(t, "n0.5", durationToTimeFrame(12*time.Hour))
|
||||||
|
}
|
Loading…
Reference in New Issue