diff --git a/client.go b/client.go index a5727e4..499a817 100644 --- a/client.go +++ b/client.go @@ -1,6 +1,7 @@ package steam import ( + "encoding/json" "fmt" "net/http" "strconv" @@ -21,19 +22,47 @@ func (c *Client) Get(iface, method, version string) (*http.Response, error) { return http.Get(url) } -func (c *Client) GetFriendList(userid uint64) (*http.Response, error) { +func (c *Client) GetFriendList(userid uint64) ([]PlayerFriend, error) { url := fmt.Sprintf("https://api.steampowered.com/ISteamUser/GetFriendList/v1/?key=%s&steamid=%d", c.key, userid) - return http.Get(url) + res, err := http.Get(url) + if err != nil { + return nil, errorf(err, "unable to get friend list") + } + var response struct { + V struct { + Friends []PlayerFriend `json:"friends"` + } `json:"friendslist"` + } + if err := json.NewDecoder(res.Body).Decode(&response); err != nil { + return nil, errorf(err, "unable to parse friends list response") + } + return response.V.Friends, nil } -func (c *Client) ResolveVanityUrl(vanity string) (*http.Response, error) { +func (c *Client) ResolveVanityUrl(vanity string) (uint64, error) { + var v struct { + V struct { + Id uint64 `json:"steamid,string"` + Success int `json:"success"` + } `json:"response"` + } url := fmt.Sprintf("https://api.steampowered.com/ISteamUser/ResolveVanityURL/v0001/?key=%s&vanityurl=%s", c.key, vanity) - return http.Get(url) + res, err := http.Get(url) + if err != nil { + return 0, errorf(err, "unable to resolve vanity url") + } + if err := json.NewDecoder(res.Body).Decode(&v); err != nil { + return 0, errorf(err, "unable to decode vanity url response") + } + if v.V.Success != 1 { + return 0, errorf(err, "resolving vanity url returned non-1 status") + } + return v.V.Id, nil } -func (c *Client) GetPlayerSummaries(steamids ...uint64) (*http.Response, error) { +func (c *Client) GetPlayerSummaries(steamids ...uint64) ([]PlayerSummary, error) { if len(steamids) > 100 { - return nil, fmt.Errorf("GetPlayerSummaries accepts a max of 100 ids, saw %d", len(steamids)) + return nil, errorf(nil, "GetPlayerSummaries accepts a max of 100 ids, saw %d", len(steamids)) } ids_s := make([]string, len(steamids)) for i := range steamids { @@ -41,7 +70,19 @@ func (c *Client) GetPlayerSummaries(steamids ...uint64) (*http.Response, error) } ids := strings.Join(ids_s, ",") url := fmt.Sprintf("https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=%s&steamids=%s", c.key, ids) - return http.Get(url) + res, err := http.Get(url) + if err != nil { + return nil, errorf(err, "unable to call GetPlayerSummaries API") + } + var response struct { + V struct { + Players []PlayerSummary `json:"players"` + } `json:"response"` + } + if err := json.NewDecoder(res.Body).Decode(&response); err != nil { + return nil, errorf(err, "unable to parse GetPlayerSummaries response") + } + return response.V.Players, nil } /* diff --git a/cmd/steam/commands.go b/cmd/steam/commands.go index bfec4ef..9641d5d 100644 --- a/cmd/steam/commands.go +++ b/cmd/steam/commands.go @@ -8,6 +8,7 @@ import ( "os" "sort" "strconv" + "text/tabwriter" ) var commands map[string]command @@ -28,12 +29,24 @@ func init() { if err != nil { bail(1, "bad user id: %s", err) } - dump(c.GetFriendList(userid)) + friends, err := c.GetFriendList(userid) + if err != nil { + bail(1, "%v", err) + } + w := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0) + defer w.Flush() + for _, friend := range friends { + fmt.Fprintln(w, friend.Oneline()) + } }, }, "user-id": command{ handler: func(c *steam.Client, args ...string) { - dump(c.ResolveVanityUrl(args[0])) + userid, err := c.ResolveVanityUrl(args[0]) + if err != nil { + bail(1, err.Error()) + } + fmt.Println(userid) }, }, "user-details": command{ @@ -49,7 +62,15 @@ func init() { } ids = append(ids, userid) } - dump(c.GetPlayerSummaries(ids...)) + players, err := c.GetPlayerSummaries(ids...) + if err != nil { + bail(1, "%v", err) + } + w := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0) + defer w.Flush() + for _, player := range players { + fmt.Fprintln(w, player.Oneline()) + } }, }, "commands": command{ diff --git a/error.go b/error.go new file mode 100644 index 0000000..447b514 --- /dev/null +++ b/error.go @@ -0,0 +1,21 @@ +package steam + +import ( + "fmt" +) + +type ClientError struct { + msg string + parent error +} + +func (c ClientError) Error() string { + if c.parent == nil { + return fmt.Sprintf("steam client error: %s", c.msg) + } + return fmt.Sprintf("steam client error: %s: %v", c.msg, c.parent) +} + +func errorf(parent error, msg string, args ...interface{}) error { + return ClientError{msg: fmt.Sprintf(msg, args...), parent: parent} +} diff --git a/player.go b/player.go new file mode 100644 index 0000000..6bef8bf --- /dev/null +++ b/player.go @@ -0,0 +1,35 @@ +package steam + +import ( + "fmt" +) + +type PlayerSummary struct { + SteamId uint64 `json:"steamid,string"` + Visibility int `json:"communityvisibilitystate"` + ProfileState int `json:"profilestate"` + PersonaName string `json:"personaname"` + LastLogOff int64 `json:"lastlogoff"` + ProfileUrl string `json:"profileurl"` + Avatar string `json:"avatar"` + AvatarMedium string `json:"avatarmedium"` + AvatarFull string `json:"avatarfull"` + PersonaState int `json:"personastate"` + LocCountryCode string `json:"loccountrycode"` + LocStateCode string `json:"locstatecode"` + LocCityID int `json:"loccityid"` +} + +func (p PlayerSummary) Oneline() string { + return fmt.Sprintf("%d\t%s\t%s", p.SteamId, p.PersonaName, p.ProfileUrl) +} + +type PlayerFriend struct { + SteamId uint64 `json:"steamid,string"` + Relationship string `json:"relationship"` + FriendSince int `json:"friend_since"` +} + +func (p PlayerFriend) Oneline() string { + return fmt.Sprintf("%d\t%s\t%d", p.SteamId, p.Relationship, p.FriendSince) +}