Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue-7 -- Add GetUsersFollowingMe endpoint #9

Merged
merged 1 commit into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
![coverage](https://raw.githubusercontent.com/joshraphael/go-retroachievements/badges/.badges/main/coverage.svg)
[![Go Report Card](https://goreportcard.com/badge/github.com/joshraphael/go-retroachievements)](https://goreportcard.com/report/github.com/joshraphael/go-retroachievements)
[![GitHub Tag](https://img.shields.io/github/v/tag/joshraphael/go-retroachievements)](https://github.com/joshraphael/go-retroachievements/tags)
[![GitHub repo size](https://img.shields.io/github/repo-size/joshraphael/go-retroachievements)](https://github.com/joshraphael/go-retroachievements/archive/master.zip)
[![GitHub repo size](https://img.shields.io/github/repo-size/joshraphael/go-retroachievements)](https://github.com/joshraphael/go-retroachievements/archive/main.zip)

## Installation
Use go get to install the latest version of the library.
Expand Down Expand Up @@ -71,6 +71,7 @@ For convenience, the API docs and examples can be found in the tables below
|`GetUserCompletedGames()`|[Deprecated] Get hardcore and softcore completion metadata about games a user has played.|[docs](https://api-docs.retroachievements.org/v1/get-user-completed-games.html) \| [example](examples/user/getusercompletedgames/getusercompletedgames.go)|
|`GetUserWantToPlayList()`|Get a user's "Want to Play Games" list.|[docs](https://api-docs.retroachievements.org/v1/get-user-want-to-play-list.html) \| [example](examples/user/getuserwanttoplaylist/getuserwanttoplaylist.go)|
|`GetUsersIFollow()`|Get the caller's "Following" users list.|[docs](https://api-docs.retroachievements.org/v1/get-users-i-follow.html) \| [example](examples/user/getusersifollow/getusersifollow.go)|
|`GetUsersFollowingMe()`|Get the caller's "Followers" users list.|[docs](https://api-docs.retroachievements.org/v1/get-users-following-me.html) \| [example](examples/user/getusersfollowingme/getusersfollowingme.go)|
|`GetUserSetRequests()`|Get a user's list of set requests.|[docs](https://api-docs.retroachievements.org/v1/get-user-set-requests.html) \| [example](examples/user/getusersetrequests/getusersetrequests.go)|

<h3>Game</h3>
Expand Down
31 changes: 31 additions & 0 deletions examples/user/getusersfollowingme/getusersfollowingme.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Package getusersfollowingme provides an example for the caller's "Followers" users list.
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 getusersfollowingme.go`
*/
func main() {
secret := os.Getenv("RA_API_KEY")

client := retroachievements.NewClient(secret)

count := 1
offset := 1
resp, err := client.GetUsersFollowingMe(models.GetUsersFollowingMeParameters{
Count: &count,
Offset: &offset,
})
if err != nil {
panic(err)
}

fmt.Printf("%+v\n", resp)
}
21 changes: 21 additions & 0 deletions models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,27 @@ type GetUsersIFollowResult struct {
IsFollowingMe bool `json:"IsFollowingMe"`
}

type GetUsersFollowingMeParameters struct {
// [Optional] The number of records to return (default: 100, max: 500).
Count *int

// [Optional] The number of entries to skip (default: 0).
Offset *int
}

type GetUsersFollowingMe struct {
Count int `json:"Count"`
Total int `json:"Total"`
Results []GetUsersFollowingMeResult `json:"Results"`
}

type GetUsersFollowingMeResult struct {
User string `json:"User"`
Points int `json:"Points"`
PointsSoftcore int `json:"PointsSoftcore"`
AmIFollowing bool `json:"AmIFollowing"`
}

type GetUserSetRequestsParameters struct {
// The target username.
Username string
Expand Down
25 changes: 25 additions & 0 deletions user.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,31 @@ func (c *Client) GetUsersIFollow(params models.GetUsersIFollowParameters) (*mode
return resp, nil
}

// GetUsersIFollow gets the caller's "Followers" users list.
func (c *Client) GetUsersFollowingMe(params models.GetUsersFollowingMeParameters) (*models.GetUsersFollowingMe, error) {
details := []raHttp.RequestDetail{
raHttp.Method(http.MethodGet),
raHttp.UserAgent(c.UserAgent),
raHttp.Path("/API/API_GetUsersFollowingMe.php"),
raHttp.APIToken(c.Secret),
}
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.ResponseObject[models.GetUsersFollowingMe](r)
if err != nil {
return nil, fmt.Errorf("parsing response object: %w", err)
}
return resp, nil
}

// GetUserSetRequests gets a user's list of set requests.
func (c *Client) GetUserSetRequests(params models.GetUserSetRequestsParameters) (*models.GetUserSetRequests, error) {
details := []raHttp.RequestDetail{
Expand Down
132 changes: 132 additions & 0 deletions user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2610,6 +2610,138 @@ func TestGetUsersIFollow(tt *testing.T) {
}
}

func TestGetUsersFollowingMe(tt *testing.T) {
count := 10
offset := 23
tests := []struct {
name string
params models.GetUsersFollowingMeParameters
modifyURL func(url string) string
responseCode int
responseMessage models.GetUsersFollowingMe
responseError models.ErrorResponse
response func(messageBytes []byte, errorBytes []byte) []byte
assert func(t *testing.T, resp *models.GetUsersFollowingMe, err error)
}{
{
name: "fail to call endpoint",
params: models.GetUsersFollowingMeParameters{
Count: &count,
Offset: &offset,
},
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.GetUsersFollowingMe, err error) {
require.Nil(t, resp)
require.EqualError(t, err, "calling endpoint: Get \"/API/API_GetUsersFollowingMe.php?c=10&o=23&y=some_secret\": unsupported protocol scheme \"\"")
},
},
{
name: "error response",
params: models.GetUsersFollowingMeParameters{
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.GetUsersFollowingMe, 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.GetUsersFollowingMeParameters{
Count: &count,
Offset: &offset,
},
modifyURL: func(url string) string {
return url
},
responseCode: http.StatusOK,
responseMessage: models.GetUsersFollowingMe{
Count: 20,
Total: 120,
Results: []models.GetUsersFollowingMeResult{
{
User: "zuliman92",
Points: 1882,
PointsSoftcore: 258,
AmIFollowing: true,
},
},
},
response: func(messageBytes []byte, errorBytes []byte) []byte {
return messageBytes
},
assert: func(t *testing.T, resp *models.GetUsersFollowingMe, err error) {
require.NotNil(t, resp)
require.Equal(t, 20, resp.Count)
require.Equal(t, 120, resp.Total)
require.Len(t, resp.Results, 1)
require.Equal(t, "zuliman92", resp.Results[0].User)
require.Equal(t, 1882, resp.Results[0].Points)
require.Equal(t, 258, resp.Results[0].PointsSoftcore)
require.True(t, resp.Results[0].AmIFollowing)
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_GetUsersFollowingMe.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), "go-retroachievements/v0.0.0", "some_secret")
resp, err := client.GetUsersFollowingMe(test.params)
test.assert(t, resp, err)
})
}
}

func TestGetUserSetRequests(tt *testing.T) {
all := true
tests := []struct {
Expand Down
Loading