Skip to content

Commit

Permalink
add GetGameList endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
joshraphael committed Nov 22, 2024
1 parent 622eecc commit 707e8e7
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 2 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,11 @@ For convenience, the API docs and examples can be found in the tables below
|Function|Description|Links|
|-|-|-|
|`GetGameLeaderboards()`|Gets a given games's list of leaderboards.|[docs](https://api-docs.retroachievements.org/v1/get-game-leaderboards.html) \| [example](examples/leaderboards/getgameleaderboards/getgameleaderboards.go)|
|`GetLeaderboardEntries()`|Gets a given leadboard's entries|[docs](https://api-docs.retroachievements.org/v1/get-leaderboard-entries.html) \| [example](examples/leaderboards/getleaderboardentries/getleaderboardentries.go)|
|`GetLeaderboardEntries()`|Gets a given leadboard's entries.|[docs](https://api-docs.retroachievements.org/v1/get-leaderboard-entries.html) \| [example](examples/leaderboards/getleaderboardentries/getleaderboardentries.go)|

<h3>System</h3>

|Function|Description|Links|
|-|-|-|
|`GetConsoleIDs()`|Gets the complete list of all system ID and name pairs on the site.|[docs](https://api-docs.retroachievements.org/v1/get-console-ids.html) \| [example](examples/system/getconsoleids/getconsoleids.go)|
|`GetConsoleIDs()`|Gets the complete list of all system ID and name pairs on the site.|[docs](https://api-docs.retroachievements.org/v1/get-console-ids.html) \| [example](examples/system/getconsoleids/getconsoleids.go)|
|`GetGameList()`|Gets the complete list of games for a specified console on the site.|[docs](https://api-docs.retroachievements.org/v1/get-game-list.html) \| [example](examples/system/getgamelist/getgamelist.go)|
30 changes: 30 additions & 0 deletions examples/system/getgamelist/getgamelist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// getgamelist

// Package getgamelist provides an example for getting the complete list of games for a specified console on the site.
package main

import (
"fmt"
"os"

"github.com/joshraphael/go-retroachievements"
"github.com/joshraphael/go-retroachievements/models"
)

/*
Test script, add RA_API_KEY to your env and use `go run getgamelist.go`
*/
func main() {
secret := os.Getenv("RA_API_KEY")

client := retroachievements.NewClient(secret)

resp, err := client.GetGameList(models.GetGameListParameters{
SystemID: 1,
})
if err != nil {
panic(err)
}

fmt.Printf("%+v\n", resp)
}
31 changes: 31 additions & 0 deletions models/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,34 @@ type GetConsoleIDs struct {
Active bool `json:"Active"`
IsGameSystem bool `json:"IsGameSystem"`
}

type GetGameListParameters struct {
// The target system ID
SystemID int

// [Optional] Only return games that have achievements (default: false)
HasAchievements *bool

// [Optional] Also return supported hashes for games (default: false)
IncludeHashes *bool

// [Optional] The number of records to return
Count *int

// [Optional] The number of entries to skip
Offset *int
}

type GetGameList struct {
Title string `json:"Title"`
ID int `json:"ID"`
ConsoleID int `json:"ConsoleID"`
ConsoleName string `json:"ConsoleName"`
ImageIcon string `json:"ImageIcon"`
NumAchievements int `json:"NumAchievements"`
NumLeaderboards int `json:"NumLeaderboards"`
Points int `json:"Points"`
DateModified *DateTime `json:"DateModified"`
ForumTopicID *int `json:"ForumTopicID"`
Hashes []string `json:"Hashes"`
}
39 changes: 39 additions & 0 deletions system.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,42 @@ func (c *Client) GetConsoleIDs(params models.GetConsoleIDsParameters) ([]models.
}
return resp, nil
}

// GetGameList gets the complete list of games for a specified console on the site.
func (c *Client) GetGameList(params models.GetGameListParameters) ([]models.GetGameList, error) {
details := []raHttp.RequestDetail{
raHttp.Method(http.MethodGet),
raHttp.Path("/API/API_GetGameList.php"),
raHttp.APIToken(c.Secret),
raHttp.I([]int{params.SystemID}),
}
if params.HasAchievements != nil {
f := 0
if *params.HasAchievements {
f = 1
}
details = append(details, raHttp.F(f))
}
if params.IncludeHashes != nil {
h := 0
if *params.IncludeHashes {
h = 1
}
details = append(details, raHttp.H(h))
}
if params.Count != nil {
details = append(details, raHttp.C(*params.Count))
}
if params.Offset != nil {
details = append(details, raHttp.O(*params.Offset))
}
r, err := c.do(details...)
if err != nil {
return nil, fmt.Errorf("calling endpoint: %w", err)
}
resp, err := raHttp.ResponseList[models.GetGameList](r)
if err != nil {
return nil, fmt.Errorf("parsing response list: %w", err)
}
return resp, nil
}
152 changes: 152 additions & 0 deletions system_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/joshraphael/go-retroachievements"
"github.com/joshraphael/go-retroachievements/models"
Expand Down Expand Up @@ -140,3 +141,154 @@ func TestGetConsoleIDs(tt *testing.T) {
})
}
}

func TestGetGameList(tt *testing.T) {
hasAchievements := true
includeHashes := true
count := 10
offset := 12
dateModified, err := time.Parse(time.DateTime, "2024-11-16 09:39:51")
require.NoError(tt, err)
forumTopic := 27761
tests := []struct {
name string
params models.GetGameListParameters
modifyURL func(url string) string
responseCode int
responseMessage []models.GetGameList
responseError models.ErrorResponse
response func(messageBytes []byte, errorBytes []byte) []byte
assert func(t *testing.T, resp []models.GetGameList, err error)
}{
{
name: "fail to call endpoint",
params: models.GetGameListParameters{
SystemID: 1,
HasAchievements: &hasAchievements,
IncludeHashes: &includeHashes,
Count: &count,
Offset: &offset,
},
modifyURL: func(url string) string {
return ""
},
responseCode: http.StatusOK,
response: func(messageBytes []byte, errorBytes []byte) []byte {
return messageBytes
},
assert: func(t *testing.T, resp []models.GetGameList, err error) {
require.Nil(t, resp)
require.EqualError(t, err, "calling endpoint: Get \"/API/API_GetGameList.php?c=10&f=1&h=1&i=1&o=12&y=some_secret\": unsupported protocol scheme \"\"")
},
},
{
name: "error response",
params: models.GetGameListParameters{
SystemID: 1,
HasAchievements: &hasAchievements,
IncludeHashes: &includeHashes,
Count: &count,
Offset: &offset,
},
modifyURL: func(url string) string {
return url
},
responseCode: http.StatusUnauthorized,
responseError: models.ErrorResponse{
Message: "test",
Errors: []models.ErrorDetail{
{
Status: http.StatusUnauthorized,
Code: "unauthorized",
Title: "Not Authorized",
},
},
},
response: func(messageBytes []byte, errorBytes []byte) []byte {
return errorBytes
},
assert: func(t *testing.T, resp []models.GetGameList, err error) {
require.Nil(t, resp)
require.EqualError(t, err, "parsing response list: error responses: [401] Not Authorized")
},
},
{
name: "success",
params: models.GetGameListParameters{
SystemID: 1,
HasAchievements: &hasAchievements,
IncludeHashes: &includeHashes,
Count: &count,
Offset: &offset,
},
modifyURL: func(url string) string {
return url
},
responseCode: http.StatusOK,
responseMessage: []models.GetGameList{
{
Title: "~Hack~ ~Demo~ Gatoslip: Chapter 0",
ID: 30734,
ConsoleID: 1,
ConsoleName: "Genesis/Mega Drive",
ImageIcon: "/Images/101272.png",
NumAchievements: 28,
NumLeaderboards: 1,
Points: 289,
DateModified: &models.DateTime{
Time: dateModified,
},
ForumTopicID: &forumTopic,
Hashes: []string{
"b4c6bcd0b0db9d2cc0f47e2fbb86a97b",
},
},
},
response: func(messageBytes []byte, errorBytes []byte) []byte {
return messageBytes
},
assert: func(t *testing.T, resp []models.GetGameList, err error) {
require.NotNil(t, resp)
require.Len(t, resp, 1)
require.Equal(t, "~Hack~ ~Demo~ Gatoslip: Chapter 0", resp[0].Title)
require.Equal(t, 30734, resp[0].ID)
require.Equal(t, 1, resp[0].ConsoleID)
require.Equal(t, "Genesis/Mega Drive", resp[0].ConsoleName)
require.Equal(t, "/Images/101272.png", resp[0].ImageIcon)
require.Equal(t, 28, resp[0].NumAchievements)
require.Equal(t, 1, resp[0].NumLeaderboards)
require.Equal(t, 289, resp[0].Points)
require.NotNil(t, resp[0].DateModified)
require.Equal(t, dateModified, resp[0].DateModified.Time)
require.NotNil(t, resp[0].ForumTopicID)
require.Equal(t, 27761, *resp[0].ForumTopicID)
require.Len(t, resp[0].Hashes, 1)
require.Equal(t, "b4c6bcd0b0db9d2cc0f47e2fbb86a97b", resp[0].Hashes[0])
require.NoError(t, err)
},
},
}
for _, test := range tests {
tt.Run(test.name, func(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
expectedPath := "/API/API_GetGameList.php"
if r.URL.Path != expectedPath {
t.Errorf("Expected to request '%s', got: %s", expectedPath, r.URL.Path)
}
w.WriteHeader(test.responseCode)
messageBytes, err := json.Marshal(test.responseMessage)
require.NoError(t, err)
errBytes, err := json.Marshal(test.responseError)
require.NoError(t, err)
resp := test.response(messageBytes, errBytes)
num, err := w.Write(resp)
require.NoError(t, err)
require.Equal(t, num, len(resp))
}))
defer server.Close()
client := retroachievements.New(test.modifyURL(server.URL), "go-retroachievements/v0.0.0", "some_secret")
resp, err := client.GetGameList(test.params)
test.assert(t, resp, err)
})
}
}

0 comments on commit 707e8e7

Please sign in to comment.