diff --git a/api/api.go b/api/api.go index 95d09f6..70f9924 100644 --- a/api/api.go +++ b/api/api.go @@ -16,6 +16,7 @@ import ( "go.fifitido.net/twitch/api/entitlements" "go.fifitido.net/twitch/api/eventsub" "go.fifitido.net/twitch/api/extensions" + "go.fifitido.net/twitch/api/games" ) const HelixBaseUrl = "https://api.twitch.tv/helix" @@ -36,6 +37,7 @@ type API struct { Entitlements *entitlements.Entitlements Extensions *extensions.Extensions EventSub *eventsub.EventSub + Games *games.Games } func New() *API { @@ -58,5 +60,6 @@ func New() *API { Entitlements: entitlements.New(client, baseUrl), Extensions: extensions.New(client, baseUrl), EventSub: eventsub.New(client, baseUrl), + Games: games.New(client, baseUrl), } } diff --git a/api/games/games.go b/api/games/games.go new file mode 100644 index 0000000..3e78ce4 --- /dev/null +++ b/api/games/games.go @@ -0,0 +1,18 @@ +package games + +import ( + "net/http" + "net/url" +) + +type Games struct { + client *http.Client + baseUrl *url.URL +} + +func New(client *http.Client, baseUrl *url.URL) *Games { + return &Games{ + client: client, + baseUrl: baseUrl, + } +} diff --git a/api/games/get_games.go b/api/games/get_games.go new file mode 100644 index 0000000..55c7a60 --- /dev/null +++ b/api/games/get_games.go @@ -0,0 +1,58 @@ +package games + +import ( + "context" + "encoding/json" + "net/http" + "net/url" + + "github.com/google/go-querystring/query" +) + +type GetGamesParams struct { + // The ID of the category or game to get. Include this parameter for each category or game you want to get. For example, &id=1234&id=5678. + // You may specify a maximum of 100 IDs. The endpoint ignores duplicate and invalid IDs or IDs that weren’t found. + IDs []string `url:"id,omitempty"` + + // The name of the category or game to get. The name must exactly match the category’s or game’s title. + // Include this parameter for each category or game you want to get. For example, &name=foo&name=bar. + // You may specify a maximum of 100 names. The endpoint ignores duplicate names and names that weren’t found. + Names []string `url:"name,omitempty"` + + // The IGDB ID of the game to get. Include this parameter for each game you want to get. For example, &igdb_id=1234&igdb_id=5678. + // You may specify a maximum of 100 IDs. The endpoint ignores duplicate and invalid IDs or IDs that weren’t found. + IGDBIDs []string `url:"igdb_id,omitempty"` +} + +type GetGamesResponse struct { + // The list of categories and games. The list is empty if the specified categories and games weren’t found. + Data []Game `json:"data"` +} + +// Gets information about specified categories or games. +// +// You may get up to 100 categories or games by specifying their ID or name. You may specify all IDs, all names, or a combination of IDs and names. If you specify a combination of IDs and names, the total number of IDs and names must not exceed 100. +// +// Requires an app access token or user access token. +func (c *Games) GetGames(ctx context.Context, params *GetGamesParams) (*GetGamesResponse, error) { + v, _ := query.Values(params) + endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "games", RawQuery: v.Encode()}) + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil) + if err != nil { + return nil, err + } + + res, err := c.client.Do(req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + var data GetGamesResponse + if err := json.NewDecoder(res.Body).Decode(&data); err != nil { + return nil, err + } + + return &data, nil +} diff --git a/api/games/get_top_games.go b/api/games/get_top_games.go new file mode 100644 index 0000000..c9750cf --- /dev/null +++ b/api/games/get_top_games.go @@ -0,0 +1,61 @@ +package games + +import ( + "context" + "encoding/json" + "net/http" + "net/url" + + "github.com/google/go-querystring/query" + "go.fifitido.net/twitch/api/types" +) + +type GetTopGamesParams struct { + // The maximum number of items to return per page in the response. + // The minimum page size is 1 item per page and the maximum is 100 items per page. + // The default is 20. + First *int `url:"first,omitempty"` + + // The cursor used to get the next page of results. The Pagination object in the response contains the cursor’s value. + // Read More: https://dev.twitch.tv/docs/api/guide#pagination + After *types.Cursor `url:"after,omitempty"` + + // The cursor used to get the previous page of results. The Pagination object in the response contains the cursor’s value. + // Read More: https://dev.twitch.tv/docs/api/guide#pagination + Before *types.Cursor `url:"before,omitempty"` +} + +type GetTopGamesResponse struct { + // The list of broadcasts. The broadcasts are sorted by the number of viewers, with the most popular first. + Data []Game `json:"data"` + + // Contains the information used to page through the list of results. The object is empty if there are no more pages left to page through. + // Read More: https://dev.twitch.tv/docs/api/guide#pagination + Pagination *types.Pagination `json:"pagination"` +} + +// Gets information about all broadcasts on Twitch. +// +// Requires an app access token or user access token. +func (c *Games) GetTopGames(ctx context.Context, params *GetTopGamesParams) (*GetTopGamesResponse, error) { + v, _ := query.Values(params) + endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "games/top", RawQuery: v.Encode()}) + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil) + if err != nil { + return nil, err + } + + res, err := c.client.Do(req) + if err != nil { + return nil, err + } + defer res.Body.Close() + + var data GetTopGamesResponse + if err := json.NewDecoder(res.Body).Decode(&data); err != nil { + return nil, err + } + + return &data, nil +} diff --git a/api/games/models.go b/api/games/models.go new file mode 100644 index 0000000..dfe985a --- /dev/null +++ b/api/games/models.go @@ -0,0 +1,15 @@ +package games + +type Game struct { + // The ID that identifies the category or game. + ID string `json:"id"` + + // The category’s or game’s name. + Name string `json:"name"` + + // A URL to the category’s or game’s box art. You must replace the {width}x{height} placeholder with the size of image you want. + BoxArtURL string `json:"box_art_url"` + + // The ID that IGDB uses to identify this game. If the IGDB ID is not available to Twitch, this field is set to an empty string. + IGDBID string `json:"igdb_id"` +}