diff --git a/README.md b/README.md index b8ffa13..2f35532 100644 --- a/README.md +++ b/README.md @@ -125,4 +125,5 @@ For convenience, the API docs and examples can be found in the tables below |`GetMostTicketedGames()`|Gets the games on the site with the highest count of opened achievement tickets.|[docs](https://api-docs.retroachievements.org/v1/get-ticket-data/get-most-ticketed-games.html) \| [example](examples/ticket/getmostticketedgames/getmostticketedgames.go)| |`GetMostRecentTickets()`|Gets ticket metadata information about the latest opened achievement tickets on RetroAchievements.|[docs](https://api-docs.retroachievements.org/v1/get-ticket-data/get-most-recent-tickets.html) \| [example](examples/ticket/getmostrecenttickets/getmostrecenttickets.go)| |`GetGameTicketStats()`|Gets ticket stats for a game, targeted by that game's unique ID.|[docs](https://api-docs.retroachievements.org/v1/get-ticket-data/get-game-ticket-stats.html) \| [example](examples/ticket/getgameticketstats/getgameticketstats.go)| -|`GetDeveloperTicketStats()`|Gets ticket stats for a developer, targeted by that developer's site username.|[docs](https://api-docs.retroachievements.org/v1/get-ticket-data/get-developer-ticket-stats.html) \| [example](examples/ticket/getdeveloperticketstats/getdeveloperticketstats.go)| \ No newline at end of file +|`GetDeveloperTicketStats()`|Gets ticket stats for a developer, targeted by that developer's site username.|[docs](https://api-docs.retroachievements.org/v1/get-ticket-data/get-developer-ticket-stats.html) \| [example](examples/ticket/getdeveloperticketstats/getdeveloperticketstats.go)| +|`GetAchievementTicketStats()`|Gets ticket stats for an achievement, targeted by that achievement's unique ID.|[docs](https://api-docs.retroachievements.org/v1/get-ticket-data/get-achievement-ticket-stats.html) \| [example](examples/ticket/getachievementticketstats/getachievementticketstats.go)| \ No newline at end of file diff --git a/examples/ticket/getachievementticketstats/getachievementticketstats.go b/examples/ticket/getachievementticketstats/getachievementticketstats.go new file mode 100644 index 0000000..f65c6a0 --- /dev/null +++ b/examples/ticket/getachievementticketstats/getachievementticketstats.go @@ -0,0 +1,28 @@ +// Package getachievementticketstats provides an example for getting ticket stats for an achievement, targeted by that achievement's unique ID. +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 getachievementticketstats.go` +*/ +func main() { + secret := os.Getenv("RA_API_KEY") + + client := retroachievements.NewClient(secret) + + resp, err := client.GetAchievementTicketStats(models.GetAchievementTicketStatsParameters{ + AchievementID: 284759, + }) + if err != nil { + panic(err) + } + + fmt.Printf("%+v\n", resp) +} diff --git a/examples/ticket/getdeveloperticketstats/getdeveloperticketstats.go b/examples/ticket/getdeveloperticketstats/getdeveloperticketstats.go index e863fcd..b468179 100644 --- a/examples/ticket/getdeveloperticketstats/getdeveloperticketstats.go +++ b/examples/ticket/getdeveloperticketstats/getdeveloperticketstats.go @@ -1,5 +1,3 @@ -// getdeveloperticketstats - // Package getdeveloperticketstats provides an example for getting ticket stats for a developer, targeted by that developer's site username. package main diff --git a/models/ticket.go b/models/ticket.go index 756225f..5e4ba65 100644 --- a/models/ticket.go +++ b/models/ticket.go @@ -149,3 +149,17 @@ type GetDeveloperTicketStats struct { Total int `json:"Total"` URL string `json:"URL"` } + +type GetAchievementTicketStatsParameters struct { + // The target achievement ID + AchievementID int +} + +type GetAchievementTicketStats struct { + AchievementID int `json:"AchievementID"` + AchievementTitle string `json:"AchievementTitle"` + AchievementDescription string `json:"AchievementDescription"` + AchievementType *string `json:"AchievementType"` + URL string `json:"URL"` + OpenTickets int `json:"OpenTickets"` +} diff --git a/ticket.go b/ticket.go index e575855..10b5c5e 100644 --- a/ticket.go +++ b/ticket.go @@ -120,3 +120,21 @@ func (c *Client) GetDeveloperTicketStats(params models.GetDeveloperTicketStatsPa } return resp, nil } + +// GetDeveloperTicketStats gets ticket stats for an achievement, targeted by that achievement's unique ID. +func (c *Client) GetAchievementTicketStats(params models.GetAchievementTicketStatsParameters) (*models.GetAchievementTicketStats, error) { + r, err := c.do( + raHttp.Method(http.MethodGet), + raHttp.Path("/API/API_GetTicketData.php"), + raHttp.APIToken(c.Secret), + raHttp.A(params.AchievementID), + ) + if err != nil { + return nil, fmt.Errorf("calling endpoint: %w", err) + } + resp, err := raHttp.ResponseObject[models.GetAchievementTicketStats](r) + if err != nil { + return nil, fmt.Errorf("parsing response object: %w", err) + } + return resp, nil +} diff --git a/ticket_test.go b/ticket_test.go index ebd0739..9a3c291 100644 --- a/ticket_test.go +++ b/ticket_test.go @@ -751,3 +751,117 @@ func TestGetDeveloperTicketStats(tt *testing.T) { }) } } + +func TestGetAchievementTicketStats(tt *testing.T) { + achievementType := "progression" + tests := []struct { + name string + params models.GetAchievementTicketStatsParameters + modifyURL func(url string) string + responseCode int + responseMessage models.GetAchievementTicketStats + responseError models.ErrorResponse + response func(messageBytes []byte, errorBytes []byte) []byte + assert func(t *testing.T, resp *models.GetAchievementTicketStats, err error) + }{ + { + name: "fail to call endpoint", + params: models.GetAchievementTicketStatsParameters{ + AchievementID: 284759, + }, + 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.GetAchievementTicketStats, err error) { + require.Nil(t, resp) + require.EqualError(t, err, "calling endpoint: Get \"/API/API_GetTicketData.php?a=284759&y=some_secret\": unsupported protocol scheme \"\"") + }, + }, + { + name: "error response", + params: models.GetAchievementTicketStatsParameters{ + AchievementID: 284759, + }, + 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.GetAchievementTicketStats, err error) { + require.Nil(t, resp) + require.EqualError(t, err, "parsing response object: error code 401 returned: {\"message\":\"test\",\"errors\":[{\"status\":401,\"code\":\"unauthorized\",\"title\":\"Not Authorized\"}]}") + }, + }, + { + name: "success", + params: models.GetAchievementTicketStatsParameters{ + AchievementID: 284759, + }, + modifyURL: func(url string) string { + return url + }, + responseCode: http.StatusOK, + responseMessage: models.GetAchievementTicketStats{ + AchievementID: 284759, + AchievementTitle: "The End of the Beginning", + AchievementDescription: "Receive the package from the King of Baron, and begin your quest to the Mist Cavern.", + AchievementType: &achievementType, + URL: "https://retroachievements.org/achievement/284759/tickets", + OpenTickets: 0, + }, + response: func(messageBytes []byte, errorBytes []byte) []byte { + return messageBytes + }, + assert: func(t *testing.T, resp *models.GetAchievementTicketStats, err error) { + require.NotNil(t, resp) + require.Equal(t, 284759, resp.AchievementID) + require.Equal(t, "The End of the Beginning", resp.AchievementTitle) + require.Equal(t, "Receive the package from the King of Baron, and begin your quest to the Mist Cavern.", resp.AchievementDescription) + require.NotNil(t, resp.AchievementType) + require.Equal(t, achievementType, *resp.AchievementType) + require.Equal(t, "https://retroachievements.org/achievement/284759/tickets", resp.URL) + require.Equal(t, 0, resp.OpenTickets) + 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_GetTicketData.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.GetAchievementTicketStats(test.params) + test.assert(t, resp, err) + }) + } +}