diff --git a/README.md b/README.md
index 1072277..38d0ca9 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,7 @@ For convenience, the API docs and examples can be found in the tables below
|`GetUserPoints()`|Get a user's total hardcore and softcore points.|[docs](https://api-docs.retroachievements.org/v1/get-user-points.html) \| [example](examples/user/getuserpoints/getuserpoints.go)|
|`GetUserProgress()`|Get a user's progress on a list of specified games.|[docs](https://api-docs.retroachievements.org/v1/get-user-progress.html) \| [example](examples/user/getuserprogress/getuserprogress.go)|
|`GetUserRecentlyPlayedGames()`|Get a list of games a user has recently played.|[docs](https://api-docs.retroachievements.org/v1/get-user-recently-played-games.html) \| [example](examples/user/getuserrecentlyplayedgames/getuserrecentlyplayedgames.go)|
+|`GetUserSummary()`|Get a user's profile metadata.|[docs](https://api-docs.retroachievements.org/v1/get-user-summary.html) \| [example](examples/user/getusersummary/getusersummary.go)|
Game
diff --git a/examples/user/getusersummary/getusersummary.go b/examples/user/getusersummary/getusersummary.go
new file mode 100644
index 0000000..49cece9
--- /dev/null
+++ b/examples/user/getusersummary/getusersummary.go
@@ -0,0 +1,32 @@
+// Package getusersummary provides an example for a users summary info
+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 getusersummary.go`
+*/
+func main() {
+ secret := os.Getenv("RA_API_KEY")
+
+ client := retroachievements.NewClient(secret)
+
+ games := 10
+ achievements := 10
+ resp, err := client.GetUserSummary(models.GetUserSummaryParameters{
+ Username: "jamiras",
+ GamesCount: &games,
+ AchievementsCount: &achievements,
+ })
+ if err != nil {
+ panic(err)
+ }
+
+ fmt.Printf("%+v\n", resp)
+}
diff --git a/http/request.go b/http/request.go
index 3489d92..7118e5d 100644
--- a/http/request.go
+++ b/http/request.go
@@ -99,10 +99,10 @@ func IDs(ids []int) RequestDetail {
})
}
-// GameID adds a target game id to the query parameters
-func GameID(gameId int) RequestDetail {
+// Game adds a target game id to the query parameters
+func Game(game int) RequestDetail {
return requestDetailFn(func(r *Request) {
- r.Params["g"] = strconv.Itoa(gameId)
+ r.Params["g"] = strconv.Itoa(game)
})
}
@@ -120,14 +120,14 @@ func Offset(offset int) RequestDetail {
})
}
-// AwardMetadata adds a target game id to the query parameters
-func AwardMetadata(awardMetadata bool) RequestDetail {
+// Achievement adds a achievement number query parameter
+func Achievement(achievement int) RequestDetail {
return requestDetailFn(func(r *Request) {
- a := "0"
- if awardMetadata {
- a = "1"
- }
- r.Params["a"] = a
+ // a := "0"
+ // if awardMetadata {
+ // a = "1"
+ // }
+ r.Params["a"] = strconv.Itoa(achievement)
})
}
diff --git a/http/request_test.go b/http/request_test.go
index 6ed30f5..350ca2a 100644
--- a/http/request_test.go
+++ b/http/request_test.go
@@ -25,8 +25,8 @@ func TestNewRequest(t *testing.T) {
raHttp.To(later.Unix()),
raHttp.Date(now),
raHttp.IDs([]int{2837, 4535}),
- raHttp.GameID(345),
- raHttp.AwardMetadata(true),
+ raHttp.Game(345),
+ raHttp.Achievement(1),
raHttp.Count(20),
raHttp.Offset(34),
)
diff --git a/models/achievements.go b/models/achievements.go
deleted file mode 100644
index f716985..0000000
--- a/models/achievements.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package models
-
-// UnlockedAchievement is a representation of achievements unlocked by a user
-type UnlockedAchievement struct {
- Achievement
- // The date the achievement was unlocked
- Date DateTime `json:"Date"`
-
- // Mode the achievement was unlocked in: 1 if in hardcore mode, 0 if not
- HardcoreMode int `json:"HardcoreMode"`
-
- // The ID of the achievement
- AchievementID int `json:"AchievementID"`
-
- // Name of the padge resource
- BadgeName string `json:"BadgeName"`
-
- // Type of achievement (standard, missable, progression, win_condition)
- Type string `json:"Type"`
-
- // Title of the game
- GameTitle string `json:"GameTitle"`
-
- // URL resource of the game icon
- GameIcon string `json:"GameIcon"`
-
- // ID of the game
- GameID int `json:"GameID"`
-
- // Common name of the console
- ConsoleName string `json:"ConsoleName"`
-
- // URL resource to the image used for the achievment badge
- BadgeURL string `json:"BadgeURL"`
-
- // URL resource to the game page
- GameURL string `json:"GameURL"`
-}
-
-// GameAchievement is a representation of an achievement in a game
-type GameAchievement struct {
- Achievement
- ID int `json:"ID"`
- NumAwarded int `json:"NumAwarded"`
- NumAwardedHardcore int `json:"NumAwardedHardcore"`
- DateModified DateTime `json:"DateModified"`
- DateCreated DateTime `json:"DateCreated"`
- BadgeName string `json:"BadgeName"`
- DisplayOrder int `json:"DisplayOrder"`
- MemAddr string `json:"MemAddr"`
- Type string `json:"type"`
- DateEarnedHardcore *DateTime `json:"DateEarnedHardcore"`
- DateEarned *DateTime `json:"DateEarned"`
-}
-
-// Achievement is a common representation of an achievement
-type Achievement struct {
- // Title of the achievement
- Title string `json:"Title"`
-
- // Description of the achievement
- Description string `json:"Description"`
- // Points awarded
- Points int `json:"Points"`
-
- // Ratio of points the achievemnet is worth
- TrueRatio int `json:"TrueRatio"`
-
- // Username of the author of the achievement
- Author string `json:"Author"`
-}
diff --git a/models/awards.go b/models/awards.go
deleted file mode 100644
index b58b59f..0000000
--- a/models/awards.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package models
-
-type UserAwards struct {
- TotalAwardsCount int `json:"TotalAwardsCount"`
- HiddenAwardsCount int `json:"HiddenAwardsCount"`
- MasteryAwardsCount int `json:"MasteryAwardsCount"`
- CompletionAwardsCount int `json:"CompletionAwardsCount"`
- BeatenHardcoreAwardsCount int `json:"BeatenHardcoreAwardsCount"`
- BeatenSoftcoreAwardsCount int `json:"BeatenSoftcoreAwardsCount"`
- EventAwardsCount int `json:"EventAwardsCount"`
- SiteAwardsCount int `json:"SiteAwardsCount"`
- VisibleUserAwards []Award `json:"VisibleUserAwards"`
-}
diff --git a/models/claims.go b/models/claims.go
deleted file mode 100644
index 2579efe..0000000
--- a/models/claims.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package models
-
-type Claim struct {
- User string `json:"User"`
- SetType int `json:"SetType"`
- GameID int `json:"GameID"`
- ClaimType int `json:"ClaimType"`
- Created DateTime `json:"Created"`
- Expiration DateTime `json:"Expiration"`
-}
diff --git a/models/old_game.go b/models/old_game.go
deleted file mode 100644
index 2c48765..0000000
--- a/models/old_game.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package models
-
-import "time"
-
-type Game struct {
- Title string `json:"Title"`
- ConsoleID int `json:"ConsoleID"`
- ForumTopicID *int `json:"ForumTopicID"`
- Flags *int `json:"Flags"`
- ImageIcon string `json:"ImageIcon"`
- ImageTitle string `json:"ImageTitle"`
- ImageIngame string `json:"ImageIngame"`
- ImageBoxArt string `json:"ImageBoxArt"`
- Publisher string `json:"Publisher"`
- Developer string `json:"Developer"`
- Genre string `json:"Genre"`
- Released LongMonthDate `json:"Released"`
-}
-
-type GameInfo struct {
- Game
- GameTitle string `json:"GameTitle"`
- ConsoleName string `json:"ConsoleName"`
- Console string `json:"Console"`
- GameIcon string `json:"GameIcon"`
-}
-
-type ExtentedGameInfo struct {
- Game
- ID int `json:"ID"`
- IsFinal int `json:"IsFinal"`
- RichPresencePatch string `json:"RichPresencePatch"`
- GuideURL *string `json:"GuideURL"`
- Updated *time.Time `json:"Updated,omitempty"`
- ConsoleName string `json:"ConsoleName"`
- ParentGameID *int `json:"ParentGameID"`
- NumDistinctPlayers int `json:"NumDistinctPlayers"`
- NumAchievements int `json:"NumAchievements"`
- Achievements map[int]GameAchievement `json:"Achievements"`
- Claims []Claim `json:"Claims,omitempty"`
- NumDistinctPlayersCasual int `json:"NumDistinctPlayersCasual"`
- NumDistinctPlayersHardcore int `json:"NumDistinctPlayersHardcore"`
-}
-
-type UserGameProgress struct {
- ExtentedGameInfo
- ReleasedAt *time.Time `json:"released_at"`
- ReleasedAtGranularity *string `json:"released_at_granularity"`
- PlayersTotal int `json:"players_total"`
- AchievementsPublished int `json:"achievements_published"`
- PointsTotal int `json:"points_total"`
- NumAwardedToUser int `json:"NumAwardedToUser"`
- NumAwardedToUserHardcore int `json:"NumAwardedToUserHardcore"`
- UserCompletion string `json:"UserCompletion"`
- UserCompletionHardcore string `json:"UserCompletionHardcore"`
- HighestAwardKind *string `json:"HighestAwardKind"`
- HighestAwardDate *RFC3339NumColonTZ `json:"HighestAwardDate"`
-}
diff --git a/models/profile.go b/models/profile.go
deleted file mode 100644
index d9574be..0000000
--- a/models/profile.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package models
-
-// Profile describes elements of a users profile
-type Profile struct {
- User string `json:"User"`
- UserPic string `json:"UserPic"`
- MemberSince DateTime `json:"MemberSince"`
- RichPresenceMsg string `json:"RichPresenceMsg"`
- LastGameID int `json:"LastGameID"`
- ContribCount int `json:"ContribCount"`
- ContribYield int `json:"ContribYield"`
- TotalPoints int `json:"TotalPoints"`
- TotalSoftcorePoints int `json:"TotalSoftcorePoints"`
- TotalTruePoints int `json:"TotalTruePoints"`
- Permissions int `json:"Permissions"`
- Untracked int `json:"Untracked"`
- ID int `json:"ID"`
- UserWallActive bool `json:"UserWallActive"`
- Motto string `json:"Motto"`
-}
diff --git a/models/user.go b/models/user.go
index bd5850d..9249e21 100644
--- a/models/user.go
+++ b/models/user.go
@@ -465,3 +465,100 @@ type GetUserRecentlyPlayedGames struct {
LastPlayed DateTime `json:"LastPlayed"`
AchievementsTotal int `json:"AchievementsTotal"`
}
+
+type GetUserSummaryParameters struct {
+ // The target username
+ Username string
+
+ // [Optional] The number of recent games to return (default: 0).
+ GamesCount *int
+
+ // [Optional] The number of recent achievements to return (default: 10)
+ AchievementsCount *int
+}
+
+type GetUserSummary struct {
+ User string `json:"User"`
+ UserPic string `json:"UserPic"`
+ TotalRanked int `json:"TotalRanked"`
+ Status string `json:"Status"`
+ RichPresenceMsg string `json:"RichPresenceMsg"`
+ LastGameID int `json:"LastGameID"`
+ ContribCount int `json:"ContribCount"`
+ ContribYield int `json:"ContribYield"`
+ TotalPoints int `json:"TotalPoints"`
+ TotalSoftcorePoints int `json:"TotalSoftcorePoints"`
+ TotalTruePoints int `json:"TotalTruePoints"`
+ Permissions int `json:"Permissions"`
+ Untracked int `json:"Untracked"`
+ ID int `json:"ID"`
+ UserWallActive int `json:"UserWallActive"`
+ Motto string `json:"Motto"`
+ RecentlyPlayedCount int `json:"RecentlyPlayedCount"`
+ Rank *int `json:"Rank"`
+ MemberSince DateTime `json:"MemberSince"`
+ LastActivity GetUserSummaryLastActivity `json:"LastActivity"`
+ RecentlyPlayed []GetUserSummaryRecentlyPlayed `json:"RecentlyPlayed"`
+ Awarded map[string]GetUserSummaryAwarded `json:"Awarded"`
+ RecentAchievements map[string]map[string]GetUserSummaryRecentAchievements `json:"RecentAchievements"`
+ LastGame GetUserSummaryLastGame `json:"LastGame"`
+}
+
+type GetUserSummaryLastActivity struct {
+ ID int `json:"ID"`
+ User string `json:"User"`
+}
+
+type GetUserSummaryRecentlyPlayed struct {
+ GameID int `json:"GameID"`
+ ConsoleID int `json:"ConsoleID"`
+ ConsoleName string `json:"ConsoleName"`
+ Title string `json:"Title"`
+ ImageIcon string `json:"ImageIcon"`
+ ImageTitle string `json:"ImageTitle"`
+ ImageIngame string `json:"ImageIngame"`
+ ImageBoxArt string `json:"ImageBoxArt"`
+ LastPlayed DateTime `json:"LastPlayed"`
+ AchievementsTotal int `json:"AchievementsTotal"`
+}
+
+type GetUserSummaryAwarded struct {
+ NumPossibleAchievements int `json:"NumPossibleAchievements"`
+ PossibleScore int `json:"PossibleScore"`
+ NumAchieved int `json:"NumAchieved"`
+ ScoreAchieved int `json:"ScoreAchieved"`
+ NumAchievedHardcore int `json:"NumAchievedHardcore"`
+ ScoreAchievedHardcore int `json:"ScoreAchievedHardcore"`
+}
+
+type GetUserSummaryRecentAchievements struct {
+ ID int `json:"ID"`
+ GameID int `json:"GameID"`
+ GameTitle string `json:"GameTitle"`
+ Title string `json:"Title"`
+ Description string `json:"Description"`
+ Points int `json:"Points"`
+ Type *string `json:"Type"`
+ BadgeName string `json:"BadgeName"`
+ IsAwarded string `json:"IsAwarded"`
+ DateAwarded DateTime `json:"DateAwarded"`
+ HardcoreAchieved int `json:"HardcoreAchieved"`
+}
+
+type GetUserSummaryLastGame struct {
+ ID int `json:"ID"`
+ Title string `json:"Title"`
+ ConsoleID int `json:"ConsoleID"`
+ ConsoleName string `json:"ConsoleName"`
+ ForumTopicID int `json:"ForumTopicID"`
+ Flags int `json:"Flags"`
+ ImageIcon string `json:"ImageIcon"`
+ ImageTitle string `json:"ImageTitle"`
+ ImageIngame string `json:"ImageIngame"`
+ ImageBoxArt string `json:"ImageBoxArt"`
+ Publisher string `json:"Publisher"`
+ Developer string `json:"Developer"`
+ Genre string `json:"Genre"`
+ Released LongMonthDate `json:"Released"`
+ IsFinal int `json:"IsFinal"`
+}
diff --git a/user.go b/user.go
index b35768b..a5de24e 100644
--- a/user.go
+++ b/user.go
@@ -94,10 +94,10 @@ func (c *Client) GetGameInfoAndUserProgress(params models.GetGameInfoAndUserProg
raHttp.Path("/API/API_GetGameInfoAndUserProgress.php"),
raHttp.APIToken(c.Secret),
raHttp.Username(params.Username),
- raHttp.GameID(params.GameID),
+ raHttp.Game(params.GameID),
}
- if params.IncludeAwardMetadata != nil {
- details = append(details, raHttp.AwardMetadata(*params.IncludeAwardMetadata))
+ if params.IncludeAwardMetadata != nil && *params.IncludeAwardMetadata {
+ details = append(details, raHttp.Achievement(1))
}
resp, err := c.do(details...)
if err != nil {
@@ -171,7 +171,7 @@ func (c *Client) GetUserGameRankAndScore(params models.GetUserGameRankAndScorePa
raHttp.Path("/API/API_GetUserGameRankAndScore.php"),
raHttp.APIToken(c.Secret),
raHttp.Username(params.Username),
- raHttp.GameID(params.GameID),
+ raHttp.Game(params.GameID),
)
if err != nil {
return nil, fmt.Errorf("calling endpoint: %w", err)
@@ -244,3 +244,28 @@ func (c *Client) GetUserRecentlyPlayedGames(params models.GetUserRecentlyPlayedG
}
return recentlyPlayed, nil
}
+
+// GetUserSummary get summary information about a given user.
+func (c *Client) GetUserSummary(params models.GetUserSummaryParameters) (*models.GetUserSummary, error) {
+ details := []raHttp.RequestDetail{
+ raHttp.Method(http.MethodGet),
+ raHttp.Path("/API/API_GetUserSummary.php"),
+ raHttp.APIToken(c.Secret),
+ raHttp.Username(params.Username),
+ }
+ if params.GamesCount != nil {
+ details = append(details, raHttp.Game(*params.GamesCount))
+ }
+ if params.AchievementsCount != nil {
+ details = append(details, raHttp.Achievement(*params.AchievementsCount))
+ }
+ resp, err := c.do(details...)
+ if err != nil {
+ return nil, fmt.Errorf("calling endpoint: %w", err)
+ }
+ recentlyPlayed, err := raHttp.ResponseObject[models.GetUserSummary](resp)
+ if err != nil {
+ return nil, fmt.Errorf("parsing response object: %w", err)
+ }
+ return recentlyPlayed, nil
+}
diff --git a/user_test.go b/user_test.go
index aea0167..77f095a 100644
--- a/user_test.go
+++ b/user_test.go
@@ -1023,7 +1023,7 @@ func TestGetUserAwards(tt *testing.T) {
params models.GetUserAwardsParameters
modifyURL func(url string) string
responseCode int
- responseMessage models.UserAwards
+ responseMessage models.GetUserAwards
responseError models.ErrorResponse
response func(messageBytes []byte, errorBytes []byte) []byte
assert func(t *testing.T, userAwards *models.GetUserAwards, err error)
@@ -1091,7 +1091,7 @@ func TestGetUserAwards(tt *testing.T) {
return url
},
responseCode: http.StatusOK,
- responseMessage: models.UserAwards{
+ responseMessage: models.GetUserAwards{
TotalAwardsCount: 9,
HiddenAwardsCount: 0,
MasteryAwardsCount: 4,
@@ -1932,3 +1932,291 @@ func TestGetUserRecentlyPlayedGames(tt *testing.T) {
})
}
}
+
+func TestGetUserSummary(tt *testing.T) {
+ gameCount := 10
+ achievementCount := 5
+ rank := 130
+ memberSince, err := time.Parse(time.DateTime, "2017-06-18 18:49:00")
+ require.NoError(tt, err)
+ lastPlayed, err := time.Parse(time.DateTime, "2024-11-17 04:00:35")
+ require.NoError(tt, err)
+ releaseDate, err := time.Parse(models.LongMonthDateFormat, "September 27, 2011")
+ require.NoError(tt, err)
+ cheevoType := "progression"
+ tests := []struct {
+ name string
+ params models.GetUserSummaryParameters
+ modifyURL func(url string) string
+ responseCode int
+ responseMessage models.GetUserSummary
+ responseError models.ErrorResponse
+ response func(messageBytes []byte, errorBytes []byte) []byte
+ assert func(t *testing.T, resp *models.GetUserSummary, err error)
+ }{
+ {
+ name: "fail to call endpoint",
+ params: models.GetUserSummaryParameters{
+ Username: "Test",
+ GamesCount: &gameCount,
+ AchievementsCount: &achievementCount,
+ },
+ modifyURL: func(url string) string {
+ return ""
+ },
+ 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.GetUserSummary, err error) {
+ require.Nil(t, resp)
+ require.EqualError(t, err, "calling endpoint: Get \"/API/API_GetUserSummary.php?a=5&g=10&u=Test&y=some_secret\": unsupported protocol scheme \"\"")
+ },
+ },
+ {
+ name: "error response",
+ params: models.GetUserSummaryParameters{
+ Username: "Test",
+ GamesCount: &gameCount,
+ AchievementsCount: &achievementCount,
+ },
+ 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.GetUserSummary, err error) {
+ require.Nil(t, resp)
+ require.EqualError(t, err, "parsing response object: error responses: [401] Not Authorized")
+ },
+ },
+ {
+ name: "success",
+ params: models.GetUserSummaryParameters{
+ Username: "Test",
+ GamesCount: &gameCount,
+ AchievementsCount: &achievementCount,
+ },
+ modifyURL: func(url string) string {
+ return url
+ },
+ responseCode: http.StatusOK,
+ responseMessage: models.GetUserSummary{
+ User: "Jamiras",
+ RichPresenceMsg: "In Chapter 3: The Paladin Clan • 3h13 • Level 5 • 3 • 4918 Rings • 12/83",
+ LastGameID: 9404,
+ ContribCount: 179822,
+ ContribYield: 1208742,
+ TotalPoints: 116649,
+ TotalSoftcorePoints: 1350,
+ TotalTruePoints: 322472,
+ Permissions: 4,
+ Untracked: 0,
+ ID: 43495,
+ UserWallActive: 0,
+ Motto: "",
+ RecentlyPlayedCount: 1,
+ UserPic: "/UserPic/jamiras.png",
+ TotalRanked: 78332,
+ Status: "Offline",
+ Rank: &rank,
+ MemberSince: models.DateTime{
+ Time: memberSince,
+ },
+ LastActivity: models.GetUserSummaryLastActivity{
+ ID: 0,
+ User: "jamiras",
+ },
+ RecentlyPlayed: []models.GetUserSummaryRecentlyPlayed{
+ {
+ GameID: 9404,
+ ConsoleID: 18,
+ ConsoleName: "Nintendo DS",
+ Title: "Solatorobo: Red the Hunter",
+ ImageIcon: "/Images/088320.png",
+ ImageTitle: "/Images/073286.png",
+ ImageIngame: "/Images/073287.png",
+ ImageBoxArt: "/Images/028653.png",
+ LastPlayed: models.DateTime{
+ Time: lastPlayed,
+ },
+ AchievementsTotal: 133,
+ },
+ },
+ Awarded: map[string]models.GetUserSummaryAwarded{
+ "9404": {
+ NumPossibleAchievements: 133,
+ PossibleScore: 935,
+ NumAchieved: 16,
+ ScoreAchieved: 95,
+ NumAchievedHardcore: 16,
+ ScoreAchievedHardcore: 95,
+ },
+ },
+ RecentAchievements: map[string]map[string]models.GetUserSummaryRecentAchievements{
+ "9404": {
+ "328833": {
+ ID: 328833,
+ GameID: 9404,
+ GameTitle: "Solatorobo: Red the Hunter",
+ Title: "Chapter 3: The Paladin Clan",
+ Description: "Complete the Chapter 3",
+ Points: 10,
+ Type: &cheevoType,
+ BadgeName: "368292",
+ IsAwarded: "1",
+ DateAwarded: models.DateTime{
+ Time: lastPlayed,
+ },
+ HardcoreAchieved: 1,
+ },
+ },
+ },
+ LastGame: models.GetUserSummaryLastGame{
+ ID: 9404,
+ Title: "Solatorobo: Red the Hunter",
+ ConsoleID: 18,
+ ConsoleName: "Nintendo DS",
+ ForumTopicID: 21569,
+ Flags: 0,
+ ImageIcon: "/Images/088320.png",
+ ImageTitle: "/Images/073286.png",
+ ImageIngame: "/Images/073287.png",
+ ImageBoxArt: "/Images/028653.png",
+ Publisher: "XSEED Games",
+ Developer: "CyberConnect2 | CyberConnect",
+ Genre: "Action RPG",
+ Released: models.LongMonthDate{
+ Time: releaseDate,
+ },
+ IsFinal: 0,
+ },
+ },
+ response: func(messageBytes []byte, errorBytes []byte) []byte {
+ return messageBytes
+ },
+ assert: func(t *testing.T, resp *models.GetUserSummary, err error) {
+ require.NoError(t, err)
+ require.Equal(t, "Jamiras", resp.User)
+ require.Equal(t, "In Chapter 3: The Paladin Clan • 3h13 • Level 5 • 3 • 4918 Rings • 12/83", resp.RichPresenceMsg)
+ require.Equal(t, 9404, resp.LastGameID)
+ require.Equal(t, 179822, resp.ContribCount)
+ require.Equal(t, 1208742, resp.ContribYield)
+ require.Equal(t, 116649, resp.TotalPoints)
+ require.Equal(t, 1350, resp.TotalSoftcorePoints)
+ require.Equal(t, 322472, resp.TotalTruePoints)
+ require.Equal(t, 4, resp.Permissions)
+ require.Equal(t, 0, resp.Untracked)
+ require.Equal(t, 43495, resp.ID)
+ require.Equal(t, 0, resp.UserWallActive)
+ require.Equal(t, "", resp.Motto)
+ require.Equal(t, 1, resp.RecentlyPlayedCount)
+ require.Equal(t, "/UserPic/jamiras.png", resp.UserPic)
+ require.Equal(t, 78332, resp.TotalRanked)
+ require.Equal(t, "Offline", resp.Status)
+ require.NotNil(t, resp.Rank)
+ require.Equal(t, 130, *resp.Rank)
+ require.Equal(t, memberSince, resp.MemberSince.Time)
+ require.Equal(t, 0, resp.LastActivity.ID)
+ require.Equal(t, "jamiras", resp.LastActivity.User)
+ require.Len(t, resp.RecentlyPlayed, 1)
+ require.Equal(t, 9404, resp.RecentlyPlayed[0].GameID)
+ require.Equal(t, 18, resp.RecentlyPlayed[0].ConsoleID)
+ require.Equal(t, "Nintendo DS", resp.RecentlyPlayed[0].ConsoleName)
+ require.Equal(t, "Solatorobo: Red the Hunter", resp.RecentlyPlayed[0].Title)
+ require.Equal(t, "/Images/088320.png", resp.RecentlyPlayed[0].ImageIcon)
+ require.Equal(t, "/Images/073286.png", resp.RecentlyPlayed[0].ImageTitle)
+ require.Equal(t, "/Images/073287.png", resp.RecentlyPlayed[0].ImageIngame)
+ require.Equal(t, "/Images/028653.png", resp.RecentlyPlayed[0].ImageBoxArt)
+ require.Equal(t, 133, resp.RecentlyPlayed[0].AchievementsTotal)
+ require.Len(t, resp.Awarded, 1)
+ award, ok := resp.Awarded["9404"]
+ require.True(t, ok)
+ require.Equal(t, 133, award.NumPossibleAchievements)
+ require.Equal(t, 935, award.PossibleScore)
+ require.Equal(t, 16, award.NumAchieved)
+ require.Equal(t, 95, award.ScoreAchieved)
+ require.Equal(t, 16, award.NumAchievedHardcore)
+ require.Equal(t, 95, award.ScoreAchievedHardcore)
+ require.Len(t, resp.RecentAchievements, 1)
+ recent, ok := resp.RecentAchievements["9404"]
+ require.True(t, ok)
+ require.Len(t, recent, 1)
+ cheevo, ok := recent["328833"]
+ require.True(t, ok)
+ require.Equal(t, 328833, cheevo.ID)
+ require.Equal(t, 9404, cheevo.GameID)
+ require.Equal(t, "Solatorobo: Red the Hunter", cheevo.GameTitle)
+ require.Equal(t, "Chapter 3: The Paladin Clan", cheevo.Title)
+ require.Equal(t, "Complete the Chapter 3", cheevo.Description)
+ require.Equal(t, 10, cheevo.Points)
+ require.Equal(t, "368292", cheevo.BadgeName)
+ require.Equal(t, "1", cheevo.IsAwarded)
+ require.Equal(t, 1, cheevo.HardcoreAchieved)
+ require.NotNil(t, cheevo.Type)
+ require.Equal(t, cheevoType, *cheevo.Type)
+ require.Equal(t, lastPlayed, cheevo.DateAwarded.Time)
+ require.Equal(t, 9404, resp.LastGame.ID)
+ require.Equal(t, "Solatorobo: Red the Hunter", resp.LastGame.Title)
+ require.Equal(t, 18, resp.LastGame.ConsoleID)
+ require.Equal(t, "Nintendo DS", resp.LastGame.ConsoleName)
+ require.Equal(t, 21569, resp.LastGame.ForumTopicID)
+ require.Equal(t, 0, resp.LastGame.Flags)
+ require.Equal(t, "/Images/088320.png", resp.LastGame.ImageIcon)
+ require.Equal(t, "/Images/073286.png", resp.LastGame.ImageTitle)
+ require.Equal(t, "/Images/073287.png", resp.LastGame.ImageIngame)
+ require.Equal(t, "/Images/028653.png", resp.LastGame.ImageBoxArt)
+ require.Equal(t, "XSEED Games", resp.LastGame.Publisher)
+ require.Equal(t, "CyberConnect2 | CyberConnect", resp.LastGame.Developer)
+ require.Equal(t, "Action RPG", resp.LastGame.Genre)
+ require.Equal(t, releaseDate, resp.LastGame.Released.Time)
+ require.Equal(t, 0, resp.LastGame.IsFinal)
+ },
+ },
+ }
+ 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_GetUserSummary.php"
+ if r.URL.Path != expectedPath {
+ t.Errorf("Expected to request '%s', got: %s", expectedPath, r.URL.Path)
+ }
+ w.WriteHeader(test.responseCode)
+ responseMessage, err := json.Marshal(test.responseMessage)
+ require.NoError(t, err)
+ errBytes, err := json.Marshal(test.responseError)
+ require.NoError(t, err)
+ resp := test.response(responseMessage, 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.GetUserSummary(test.params)
+ test.assert(t, resp, err)
+ })
+ }
+}