diff --git a/README.md b/README.md index 55fbf2f..ef70a2a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![build status](https://github.com/sizovilya/go-psn-api/actions/workflows/golangci-lint.yml/badge.svg?branch=main)

-# go-psn-api(WIP) +# go-psn-api A Playstation Network API wrapper written in Go. ## Read first Corresponding to my research how PSN works you need npsso to interact with Sony servers. @@ -44,10 +44,11 @@ Copy this js code: - After the login flow is completed, you should see a new log in the developer console that looks like: found npsso <64 character code>. Copy that 64 character code. -### Functions at this moment +### Functionality - You can get user profile info - You can get trophy titles - You can get trophy groups +- You can get trophies ### Example ```go @@ -60,9 +61,9 @@ import ( func main() { ctx := context.Background() - lang := "ru" // known list here https://github.com/sizovilya/go-psn-api/blob/main/langs.go, some languages in list are wrong and unsupported now, feel free to investigate for your own - region := "ru" // known list here https://github.com/sizovilya/go-psn-api/blob/main/regions.go, some regions in list are wrong and unsupported now, feel free to investigate for your own - npsso := "your npsso" + lang := "ru" // known list here https://github.com/sizovilya/go-psn-api/blob/main/langs.go, some languages in list are wrong and unsupported now, feel free to investigate for your own and add it to list + region := "ru" // known list here https://github.com/sizovilya/go-psn-api/blob/main/regions.go, some regions in list are wrong and unsupported now, feel free to investigate for your own and add it to list + npsso := "" psnApi, err := psn.NewPsnApi( lang, region, @@ -71,7 +72,7 @@ func main() { panic(err) } - // This request will get access token and refresh token from Sony's servers + // This request will get access and refresh tokens from Sony's servers err = psnApi.AuthWithNPSSO(ctx, npsso) if err != nil { panic(err) @@ -80,7 +81,7 @@ func main() { // If you obtain refresh token you may use it for next logins. // Next logins should be like this: // refreshToken, _ := psnApi.GetRefreshToken() // store refresh token somewhere for future logins by psnApi.AuthWithRefreshToken method - err = psnApi.AuthWithRefreshToken(ctx, "your token") // get new access token + err = psnApi.AuthWithRefreshToken(ctx, "") // will get new access token, feel free to manage tokens by yourself if err != nil { panic(err) } @@ -106,6 +107,18 @@ func main() { panic(err) } fmt.Println(trophyGroups) + + // How to get trophies in certain trophy title and trophy group + trophies, err := psnApi.GetTrophies( + ctx, + "NPWR13348_00", // The Last Of Us 2 + "001", // trophy group with id = 001 + "geeek_52rus", + ) + if err != nil { + panic(err) + } + fmt.Println(trophies) } ``` diff --git a/trophy.go b/trophy.go new file mode 100644 index 0000000..6776d80 --- /dev/null +++ b/trophy.go @@ -0,0 +1,54 @@ +package psn + +import ( + "context" + "fmt" +) + +const trophiesApi = "-tpy.np.community.playstation.net/trophy/v1/trophyTitles/" + +type TrophiesResponse struct { + Trophies []struct { + TrophyID int `json:"trophyId"` + TrophyHidden bool `json:"trophyHidden"` + TrophyType string `json:"trophyType"` + TrophyName string `json:"trophyName"` + TrophyDetail string `json:"trophyDetail"` + TrophyIconURL string `json:"trophyIconUrl"` + TrophySmallIconURL string `json:"trophySmallIconUrl"` + TrophyRare int `json:"trophyRare"` + TrophyEarnedRate string `json:"trophyEarnedRate"` + FromUser struct { + OnlineID string `json:"onlineId"` + Earned bool `json:"earned"` + } `json:"fromUser,omitempty"` + } `json:"trophies"` +} + +// Method retrieves user's trophies +func (p *psn) GetTrophies(ctx context.Context, trophyTitleId, trophyGroupId, username string) (*TrophiesResponse, error) { + var h = headers{} + h["authorization"] = fmt.Sprintf("Bearer %s", p.accessToken) + h["Accept"] = "*/*" + h["Accept-Encoding"] = "gzip, deflate, br" + + trophiesResponse := TrophiesResponse{} + err := p.get( + ctx, + fmt.Sprintf( + "https://%s%s%s/trophyGroups/%s/trophies?fields=@default,trophyRare,trophyEarnedRate,trophySmallIconUrl&visibleType=1&comparedUser=%s&npLanguage=%s", + p.region, + trophiesApi, + trophyTitleId, + trophyGroupId, + username, + p.lang, + ), + h, + &trophiesResponse, + ) + if err != nil { + return nil, fmt.Errorf("can't do GET request: %w", err) + } + return &trophiesResponse, nil +} diff --git a/trophy_group.go b/trophy_group.go index 64823b0..b40d97c 100644 --- a/trophy_group.go +++ b/trophy_group.go @@ -46,14 +46,14 @@ type TrophyGroupResponse struct { } // Method retrieves user's trophy groups -func (p *psn) GetTrophyGroups(ctx context.Context, trophyTitleId, username string) (profile *TrophyGroupResponse, err error) { +func (p *psn) GetTrophyGroups(ctx context.Context, trophyTitleId, username string) (*TrophyGroupResponse, error) { var h = headers{} h["authorization"] = fmt.Sprintf("Bearer %s", p.accessToken) h["Accept"] = "*/*" h["Accept-Encoding"] = "gzip, deflate, br" - trophyTitleResponse := TrophyGroupResponse{} - err = p.get( + response := TrophyGroupResponse{} + err := p.get( ctx, fmt.Sprintf( "https://%s%s%s/trophyGroups?fields=@default,trophyGroupSmallIconUrl&comparedUser=%s&npLanguage=%s", @@ -64,10 +64,10 @@ func (p *psn) GetTrophyGroups(ctx context.Context, trophyTitleId, username strin p.lang, ), h, - &trophyTitleResponse, + &response, ) if err != nil { return nil, fmt.Errorf("can't do GET request: %w", err) } - return &trophyTitleResponse, nil + return &response, nil } diff --git a/trophy_title.go b/trophy_title.go index 7ca5dda..9dea6f1 100644 --- a/trophy_title.go +++ b/trophy_title.go @@ -53,15 +53,14 @@ type TrophyTitleResponse struct { } // Method retrieves user's trophy titles -func (p *psn) GetTrophyTitles(ctx context.Context, username string, limit, offset int32) (profile *TrophyTitleResponse, err error) { +func (p *psn) GetTrophyTitles(ctx context.Context, username string, limit, offset int32) (*TrophyTitleResponse, error) { var h = headers{} h["authorization"] = fmt.Sprintf("Bearer %s", p.accessToken) - //h["accept-language"] = "en-US" h["Accept"] = "*/*" h["Accept-Encoding"] = "gzip, deflate, br" - trophyTitleResponse := TrophyTitleResponse{} - err = p.get( + response := TrophyTitleResponse{} + err := p.get( ctx, fmt.Sprintf( "https://%s%sfields=@default,trophyTitleSmallIconUrl&platform=PS3,PS4,PSVITA&limit=%d&offset=%d&comparedUser=%s&npLanguage=%s", @@ -73,10 +72,10 @@ func (p *psn) GetTrophyTitles(ctx context.Context, username string, limit, offse p.lang, ), h, - &trophyTitleResponse, + &response, ) if err != nil { return nil, fmt.Errorf("can't do GET request: %w", err) } - return &trophyTitleResponse, nil + return &response, nil }