From cb16d45ecb5cff1c52fe24936d130ef482fa4092 Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 25 Jun 2016 12:15:58 +0200 Subject: [PATCH 1/2] Better abstraction & https://golang.org/doc/effective_go.html#commentary --- api_methods.go | 8 +++--- client.go | 46 ++++++++++++++++++++++++++------- req_fixture.go | 10 +++---- req_fixtures.go | 14 +++++----- req_soccerseason.go | 6 ++--- req_soccerseason_fixtures.go | 14 +++++----- req_soccerseason_leaguetable.go | 10 +++---- req_soccerseason_teams.go | 6 ++--- req_soccerseasons.go | 10 +++---- req_team.go | 6 ++--- req_team_fixtures.go | 18 ++++++------- req_team_players.go | 6 ++--- 12 files changed, 91 insertions(+), 63 deletions(-) diff --git a/api_methods.go b/api_methods.go index f10ab2a..8e61b90 100644 --- a/api_methods.go +++ b/api_methods.go @@ -6,11 +6,11 @@ import ( ) type request struct { - c *Client - p string - v url.Values + fdClient *client + path string + urlValues url.Values } func (r request) doJson(method string) (*json.Decoder, ResponseMeta, error) { - return r.c.doJson(method, r.p, r.v) + return r.fdClient.doJson(method, r.path, r.urlValues) } diff --git a/client.go b/client.go index b6eb582..d19c415 100644 --- a/client.go +++ b/client.go @@ -15,24 +15,52 @@ 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 +type Client interface { + Fixture(id uint64) FixtureRequest + Fixtures() FixturesRequest + SoccerSeason(id uint64) SoccerSeasonRequest + FixturesOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonFixturesRequest + LeagueTableOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonLeagueTableRequest + TeamsOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonTeamsRequest + SoccerSeasons() SoccerSeasonsRequest + Team(id uint64) TeamRequest + FixturesOfTeam(id uint64) TeamFixturesRequest + + SetToken(authToken string) +} + +/* +Provides a high-level client implementation to talk to the API that football-data.org offers. + +To create an instance please use NewClient(h). +*/ +type client struct { + httpClient *http.Client // Insert an API token here if you have one. It will be sent across with all requests. - AuthToken string + AuthToken string } -// Creates a new Client instance that wraps around the given HTTP client. -func NewClient(h *http.Client) *Client { - return &Client{h: h} +// NewClient Creates a new Client instance that wraps around the given HTTP client. +// +// Call SetToken to add your token. +func NewClient(h *http.Client) Client { + return &client{httpClient: h} } -func (c *Client) req(path string, pathValues ...interface{}) request { +// SetToken Set the authentication token +// Calling this method is *optional* +func (c* client) SetToken(authToken string) { + c.AuthToken=authToken +} + + +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) { +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, @@ -48,7 +76,7 @@ func (c *Client) doJson(method string, path string, values url.Values) (j *json. req.Header.Set("User-Agent", "go-footballdata/0.0") // Execute request - resp, err := c.h.Do(req) + resp, err := c.httpClient.Do(req) if err != nil { return } diff --git a/req_fixture.go b/req_fixture.go index 897f491..8d456e6 100644 --- a/req_fixture.go +++ b/req_fixture.go @@ -4,13 +4,13 @@ import "fmt" type FixtureRequest struct{ request } -// Modifies the request to specify the number of former games to be analyzed (normally 10). +// Head2Head 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("%d", num)) + r.urlValues.Set("head2head", fmt.Sprintf("%d", num)) return r } -// Executes the request. +// Do Executes the request. func (r FixtureRequest) Do() (s Fixture, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -21,7 +21,7 @@ func (r FixtureRequest) Do() (s Fixture, err error) { return } -// Prepares a request to fetch the fixtures of a soccer season. -func (c *Client) Fixture(id uint64) FixtureRequest { +// Fixture Prepares a request to fetch the fixtures of a soccer season. +func (c *client) Fixture(id uint64) FixtureRequest { return FixtureRequest{c.req("fixture/%d", id)} } diff --git a/req_fixtures.go b/req_fixtures.go index 8ba685a..dac81dc 100644 --- a/req_fixtures.go +++ b/req_fixtures.go @@ -7,19 +7,19 @@ import ( type FixturesRequest struct{ request } -// Modifies the request to specify a specific time frame. +// TimeFrame Modifies the request to specify a specific time frame. func (r FixturesRequest) TimeFrame(timeframe time.Duration) FixturesRequest { - r.v.Set("timeFrame", durationToTimeFrame(timeframe)) + r.urlValues.Set("timeFrame", durationToTimeFrame(timeframe)) return r } -// Modifies the request to specify a list of leagues by their code. +// League 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, ",")) + r.urlValues.Set("league", strings.Join(leagueCodes, ",")) return r } -// Executes the request. +// Do Executes the request. func (r FixturesRequest) Do() (s FixturesResponse, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -30,7 +30,7 @@ func (r FixturesRequest) Do() (s FixturesResponse, err error) { return } -// Prepares a request to fetch the fixtures of a soccer season. -func (c *Client) Fixtures() FixturesRequest { +// Fixtures Prepares a request to fetch the fixtures of a soccer season. +func (c *client) Fixtures() FixturesRequest { return FixturesRequest{c.req("fixtures")} } diff --git a/req_soccerseason.go b/req_soccerseason.go index 85008ff..3fa03df 100644 --- a/req_soccerseason.go +++ b/req_soccerseason.go @@ -2,7 +2,7 @@ package footballdata type SoccerSeasonRequest struct{ request } -// Executes the request. +// Do Executes the request. func (r SoccerSeasonRequest) Do() (s SoccerSeason, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -13,7 +13,7 @@ func (r SoccerSeasonRequest) Do() (s SoccerSeason, err error) { return } -// Prepares a request to fetch the complete list of soccer seasons. -func (c *Client) SoccerSeason(id uint64) SoccerSeasonRequest { +// SoccerSeason Prepares a request to fetch the complete list of soccer seasons. +func (c *client) SoccerSeason(id uint64) SoccerSeasonRequest { return SoccerSeasonRequest{c.req("soccerseasons/%d", id)} } diff --git a/req_soccerseason_fixtures.go b/req_soccerseason_fixtures.go index b4d0f93..74010d7 100644 --- a/req_soccerseason_fixtures.go +++ b/req_soccerseason_fixtures.go @@ -7,19 +7,19 @@ import ( type SoccerSeasonFixturesRequest struct{ request } -// Modifies the request to specify a match day. +// Matchday Modifies the request to specify a match day. func (r SoccerSeasonFixturesRequest) Matchday(matchday uint16) SoccerSeasonFixturesRequest { - r.v.Set("matchday", fmt.Sprintf("%d", matchday)) + r.urlValues.Set("matchday", fmt.Sprintf("%d", matchday)) return r } -// Modifies the request to specify a specific time frame. +// TimeFrame Modifies the request to specify a specific time frame. func (r SoccerSeasonFixturesRequest) TimeFrame(timeframe time.Duration) SoccerSeasonFixturesRequest { - r.v.Set("timeFrame", durationToTimeFrame(timeframe)) + r.urlValues.Set("timeFrame", durationToTimeFrame(timeframe)) return r } -// Executes the request. +// Do Executes the request. func (r SoccerSeasonFixturesRequest) Do() (s FixtureList, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -30,7 +30,7 @@ func (r SoccerSeasonFixturesRequest) Do() (s FixtureList, err error) { return } -// Prepares a request to fetch the fixtures of a soccer season. -func (c *Client) FixturesOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonFixturesRequest { +// FixturesOfSoccerSeason Prepares a request to fetch the fixtures of a soccer season. +func (c *client) FixturesOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonFixturesRequest { return SoccerSeasonFixturesRequest{c.req("soccerseasons/%d/fixtures", soccerSeasonId)} } diff --git a/req_soccerseason_leaguetable.go b/req_soccerseason_leaguetable.go index 1c811d9..cda202c 100644 --- a/req_soccerseason_leaguetable.go +++ b/req_soccerseason_leaguetable.go @@ -4,13 +4,13 @@ import "fmt" type SoccerSeasonLeagueTableRequest struct{ request } -// Modifies the request to specify a match day. +// Matchday Modifies the request to specify a match day. func (r SoccerSeasonLeagueTableRequest) Matchday(matchday uint16) SoccerSeasonLeagueTableRequest { - r.v.Set("matchday", fmt.Sprintf("%d", matchday)) + r.urlValues.Set("matchday", fmt.Sprintf("%d", matchday)) return r } -// Executes the request. +// Do Executes the request. func (r SoccerSeasonLeagueTableRequest) Do() (s SoccerSeason, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -21,7 +21,7 @@ func (r SoccerSeasonLeagueTableRequest) Do() (s SoccerSeason, err error) { return } -// Prepares a new request to fetch the league table of a given soccer season. -func (c *Client) LeagueTableOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonLeagueTableRequest { +// LeagueTableOfSoccerSeason 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/%d/leagueTable", soccerSeasonId)} } diff --git a/req_soccerseason_teams.go b/req_soccerseason_teams.go index bfa214e..cea43dd 100644 --- a/req_soccerseason_teams.go +++ b/req_soccerseason_teams.go @@ -2,7 +2,7 @@ package footballdata type SoccerSeasonTeamsRequest struct{ request } -// Executes the request. +// Do Executes the request. func (r SoccerSeasonTeamsRequest) Do() (s TeamList, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -13,7 +13,7 @@ func (r SoccerSeasonTeamsRequest) Do() (s TeamList, err error) { return } -// Prepares a new request to fetch the league table of a given soccer season. -func (c *Client) TeamsOfSoccerSeason(soccerSeasonId uint64) SoccerSeasonTeamsRequest { +// TeamsOfSoccerSeason 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/%d/leagueTable", soccerSeasonId)} } diff --git a/req_soccerseasons.go b/req_soccerseasons.go index 8f83fa7..529cb23 100644 --- a/req_soccerseasons.go +++ b/req_soccerseasons.go @@ -4,13 +4,13 @@ import "fmt" type SoccerSeasonsRequest struct{ request } -// Modifies the request to specify a season. +// Season Modifies the request to specify a season. func (r SoccerSeasonsRequest) Season(num uint32) SoccerSeasonsRequest { - r.v.Set("season", fmt.Sprintf("%d", num)) + r.urlValues.Set("season", fmt.Sprintf("%d", num)) return r } -// Executes the request. +// Do Executes the request. func (r SoccerSeasonsRequest) Do() (s SoccerSeasonList, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -21,7 +21,7 @@ func (r SoccerSeasonsRequest) Do() (s SoccerSeasonList, err error) { return } -// Prepares a request to fetch the complete list of soccer seasons. -func (c *Client) SoccerSeasons() SoccerSeasonsRequest { +// SoccerSeasons Prepares a request to fetch the complete list of soccer seasons. +func (c *client) SoccerSeasons() SoccerSeasonsRequest { return SoccerSeasonsRequest{c.req("soccerseasons")} } diff --git a/req_team.go b/req_team.go index db46823..3940862 100644 --- a/req_team.go +++ b/req_team.go @@ -5,7 +5,7 @@ type TeamRequest struct { id uint64 } -// Executes the request. +// Do Executes the request. func (r TeamRequest) Do() (s Team, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -20,7 +20,7 @@ func (r TeamRequest) Do() (s Team, err error) { return } -// Prepares a request to fetch a team's information. -func (c *Client) Team(id uint64) TeamRequest { +// Team Prepares a request to fetch a team's information. +func (c *client) Team(id uint64) TeamRequest { return TeamRequest{c.req("teams/%d", id), id} } diff --git a/req_team_fixtures.go b/req_team_fixtures.go index 4bb8c09..2f552a7 100644 --- a/req_team_fixtures.go +++ b/req_team_fixtures.go @@ -7,25 +7,25 @@ import ( type TeamFixturesRequest struct{ request } -// Modifies the request to specify a specific time frame. +// TimeFrame Modifies the request to specify a specific time frame. func (r TeamFixturesRequest) TimeFrame(timeframe time.Duration) TeamFixturesRequest { - r.v.Set("timeFrame", durationToTimeFrame(timeframe)) + r.urlValues.Set("timeFrame", durationToTimeFrame(timeframe)) return r } -// Modifies the request to specify a list of leagues by their code. +// Season 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("%d", season)) + r.urlValues.Set("season", fmt.Sprintf("%d", season)) return r } -// Modifies the request to specify a venue. +// Venue Modifies the request to specify a venue. func (r TeamFixturesRequest) Venue(venue Venue) TeamFixturesRequest { - r.v.Set("venue", string(venue)) + r.urlValues.Set("venue", string(venue)) return r } -// Executes the request. +// Do Executes the request. func (r TeamFixturesRequest) Do() (s FixturesResponse, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -36,7 +36,7 @@ func (r TeamFixturesRequest) Do() (s FixturesResponse, err error) { return } -// Prepares a request to fetch the fixtures of a soccer season. -func (c *Client) FixturesOfTeam(id uint64) TeamFixturesRequest { +// FixturesOfTeam Prepares a request to fetch the fixtures of a soccer season. +func (c *client) FixturesOfTeam(id uint64) TeamFixturesRequest { return TeamFixturesRequest{c.req("teams/%d/fixtures", id)} } diff --git a/req_team_players.go b/req_team_players.go index 285af22..5508132 100644 --- a/req_team_players.go +++ b/req_team_players.go @@ -2,7 +2,7 @@ package footballdata type TeamPlayersRequest struct{ request } -// Executes the request. +// Do Executes the request. func (r TeamPlayersRequest) Do() (s PlayerList, err error) { d, _, err := r.doJson("GET") if err != nil { @@ -13,7 +13,7 @@ func (r TeamPlayersRequest) Do() (s PlayerList, err error) { return } -// Prepares a request to fetch a team's players. -func (c *Client) PlayersOfTeam(id uint64) TeamPlayersRequest { +// PlayersOfTeam Prepares a request to fetch a team's players. +func (c *client) PlayersOfTeam(id uint64) TeamPlayersRequest { return TeamPlayersRequest{c.req("teams/%d/players", id)} } From 0ae7a5f5b6c1afbc6527053dd0acf1b6f5dc2cbd Mon Sep 17 00:00:00 2001 From: Christian Date: Sat, 25 Jun 2016 12:29:32 +0200 Subject: [PATCH 2/2] Failing test due to API divergence --- example_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example_test.go b/example_test.go index ff662a6..d37119f 100644 --- a/example_test.go +++ b/example_test.go @@ -12,7 +12,7 @@ func Example() { client := footballdata.NewClient(http.DefaultClient) // Tell it to use our API token - client.AuthToken = "" + client.SetToken("") // Get list of seasons... seasons, err := client.SoccerSeasons().Do()