Skip to content

Commit

Permalink
add GetAchievementCount endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
joshraphael committed Nov 19, 2024
1 parent 3d288bf commit d88f2bf
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 1 deletion.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ For convenience, the API docs and examples can be found in the tables below
|-|-|-|
|`GetGame()`|Get basic metadata about a game.|[docs](https://api-docs.retroachievements.org/v1/get-game.html) \| [example](examples/game/getgame/getgame.go)|
|`GetGameExtended()`|Get extended metadata about a game.|[docs](https://api-docs.retroachievements.org/v1/get-game-extended.html) \| [example](examples/game/getgameextended/getgameextended.go)|
|`GetGameHashes()`|Get the hashes linked to a game.|[docs](https://api-docs.retroachievements.org/v1/get-game-hashes.html) \| [example](examples/game/getgamehashes/getgamehashes.go)|
|`GetGameHashes()`|Get the hashes linked to a game.|[docs](https://api-docs.retroachievements.org/v1/get-game-hashes.html) \| [example](examples/game/getgamehashes/getgamehashes.go)|
|`GetAchievementCount()`|Get the list of achievement IDs for a game.|[docs](https://api-docs.retroachievements.org/v1/get-achievement-count.html) \| [example](examples/game/getachievementcount/getachievementcount.go)|
28 changes: 28 additions & 0 deletions examples/game/getachievementcount/getachievementcount.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Package getachievementcount provides an example for getting the list of achievement IDs for a game.
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 getachievementcount.go`
*/
func main() {
secret := os.Getenv("RA_API_KEY")

client := retroachievements.NewClient(secret)

resp, err := client.GetAchievementCount(models.GetAchievementCountParameters{
GameID: 515,
})
if err != nil {
panic(err)
}

fmt.Printf("%+v\n", resp)
}
18 changes: 18 additions & 0 deletions game.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,21 @@ func (c *Client) GetGameHashes(params models.GetGameHashesParameters) (*models.G
}
return resp, nil
}

// GetAchievementCount the list of achievement IDs for a game.
func (c *Client) GetAchievementCount(params models.GetAchievementCountParameters) (*models.GetAchievementCount, error) {
r, err := c.do(
raHttp.Method(http.MethodGet),
raHttp.Path("/API/API_GetAchievementCount.php"),
raHttp.APIToken(c.Secret),
raHttp.IDs([]int{params.GameID}),
)
if err != nil {
return nil, fmt.Errorf("calling endpoint: %w", err)
}
resp, err := raHttp.ResponseObject[models.GetAchievementCount](r)
if err != nil {
return nil, fmt.Errorf("parsing response object: %w", err)
}
return resp, nil
}
136 changes: 136 additions & 0 deletions game_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,3 +528,139 @@ func TestGetGameHashes(tt *testing.T) {
})
}
}

func TestGetAchievementCount(tt *testing.T) {
tests := []struct {
name string
params models.GetAchievementCountParameters
modifyURL func(url string) string
responseCode int
responseMessage models.GetAchievementCount
responseError models.ErrorResponse
response func(messageBytes []byte, errorBytes []byte) []byte
assert func(t *testing.T, game *models.GetAchievementCount, err error)
}{
{
name: "fail to call endpoint",
params: models.GetAchievementCountParameters{
GameID: 14402,
},
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.GetAchievementCount, err error) {
require.Nil(t, resp)
require.EqualError(t, err, "calling endpoint: Get \"/API/API_GetAchievementCount.php?i=14402&y=some_secret\": unsupported protocol scheme \"\"")
},
},
{
name: "error response",
params: models.GetAchievementCountParameters{
GameID: 14402,
},
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.GetAchievementCount, err error) {
require.Nil(t, resp)
require.EqualError(t, err, "parsing response object: error responses: [401] Not Authorized")
},
},
{
name: "success",
params: models.GetAchievementCountParameters{
GameID: 14402,
},
modifyURL: func(url string) string {
return url
},
responseCode: http.StatusOK,
responseMessage: models.GetAchievementCount{
GameID: 14402,
AchievementIDs: []int{
79434,
79435,
79436,
79437,
79438,
79439,
79440,
79441,
79442,
79443,
79444,
79445,
325413,
325414,
325415,
},
},
response: func(messageBytes []byte, errorBytes []byte) []byte {
return messageBytes
},
assert: func(t *testing.T, resp *models.GetAchievementCount, err error) {
require.NotNil(t, resp)
require.Equal(t, 14402, resp.GameID)
require.Len(t, resp.AchievementIDs, 15)
require.Equal(t, 79434, resp.AchievementIDs[0])
require.Equal(t, 79435, resp.AchievementIDs[1])
require.Equal(t, 79436, resp.AchievementIDs[2])
require.Equal(t, 79437, resp.AchievementIDs[3])
require.Equal(t, 79438, resp.AchievementIDs[4])
require.Equal(t, 79439, resp.AchievementIDs[5])
require.Equal(t, 79440, resp.AchievementIDs[6])
require.Equal(t, 79441, resp.AchievementIDs[7])
require.Equal(t, 79442, resp.AchievementIDs[8])
require.Equal(t, 79443, resp.AchievementIDs[9])
require.Equal(t, 79444, resp.AchievementIDs[10])
require.Equal(t, 79445, resp.AchievementIDs[11])
require.Equal(t, 325413, resp.AchievementIDs[12])
require.Equal(t, 325414, resp.AchievementIDs[13])
require.Equal(t, 325415, resp.AchievementIDs[14])
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_GetAchievementCount.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), "some_secret")
resp, err := client.GetAchievementCount(test.params)
test.assert(t, resp, err)
})
}
}
10 changes: 10 additions & 0 deletions models/game.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,13 @@ type GetGameHashesResult struct {
Labels []string `json:"Labels"`
PatchUrl *string `json:"PatchUrl"`
}

type GetAchievementCountParameters struct {
// The target game ID
GameID int
}

type GetAchievementCount struct {
GameID int `json:"GameID"`
AchievementIDs []int `json:"AchievementIDs"`
}

0 comments on commit d88f2bf

Please sign in to comment.