/
user-service.go
145 lines (122 loc) · 3.96 KB
/
user-service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package wavy
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/hashicorp/go-hclog"
)
// UserService Reference for accessing public user profiles.
// https://wavy.fm/developers/docs/v1beta/users
type UserService interface {
// GetProfile
// Retrieves the public profile of a wavy.fm user. Note that private profiles will not be returned at all by this endpoint, regardless of authorization scopes.
GetProfile(ctx context.Context, uri UserURI) (*GetUserProfileResponse, error)
// HistroyService this service gives access to the /history endpoints
HistroyService(uri UserURI) UserHistoryService
}
type userService struct {
c *client
logger hclog.Logger
}
func newUserService(c *client, logger hclog.Logger) UserService {
subLogger := logger.Named("user-service")
return &userService{
logger: subLogger,
c: c,
}
}
// GetProfile
// Retrieves the public profile of a wavy.fm user. Note that private profiles will not be returned at all by this endpoint, regardless of authorization scopes.
func (u *userService) GetProfile(ctx context.Context, uri UserURI) (*GetUserProfileResponse, error) {
u.logger.Trace("fetching user profile")
defer u.logger.Trace("finished fetching user profile")
res, err := u.c.get(fmt.Sprintf("/users/%s", uri.String()))
if err != nil {
return nil, fmt.Errorf("%s: failed to get user profile for %q: %w", u.logger.Name(), uri.String(), err)
}
var userProfile GetUserProfileResponse
err = json.NewDecoder(res.Body).Decode(&userProfile)
if err != nil {
return nil, fmt.Errorf("%s: failed to parse response body of user profile: %w", u.logger.Name(), err)
}
return &userProfile, nil
}
func (u *userService) HistroyService(uri UserURI) UserHistoryService {
return newUserHistryService(uri, u.c, u.logger)
}
// UserURI Represents a data strcut to build proper UserURI. Only one of the fields should be set.
// UserURI is explaned on this page: https://wavy.fm/developers/docs/v1beta/overview#user-uris
type UserURI struct {
Username string
UserID string
DiscordID string
}
func (u *UserURI) UnmarshalBinary(data []byte) error {
dataString := string(data)
pieces := strings.Split(dataString, ":")
if len(pieces) < 3 {
return fmt.Errorf("failed to parse UserURI: %q", dataString)
}
switch pieces[2] {
case "id":
u.UserID = pieces[3]
case "username":
u.Username = pieces[3]
case "discord":
u.DiscordID = pieces[3]
default:
return fmt.Errorf("failed to parse UserURI: %q", dataString)
}
return nil
}
// String returns a properly formatted uri depending on which field is set on the struct.
func (u *UserURI) String() string {
if u.UserID != "" {
return fmt.Sprintf("wavyfm:user:id:%s", u.UserID)
}
if u.Username != "" {
return fmt.Sprintf("wavyfm:user:username:%s", u.Username)
}
if u.DiscordID != "" {
return fmt.Sprintf("wavyfm:user:discord:%s", u.DiscordID)
}
return "<UserURI not set correcntly>"
}
// ParseUserURI takes a full uri string and parses it into a struct.
// The uri formats are explained at: https://wavy.fm/developers/docs/v1beta/overview#user-uris
func ParseUserURI(uri string) (*UserURI, error) {
r := &UserURI{}
err := r.UnmarshalBinary([]byte(uri))
if err != nil {
return nil, err
}
return r, nil
}
type GetUserProfileResponse struct {
URI string `json:"uri"`
ID string `json:"id"`
Username string `json:"username"`
JoinTime time.Time `json:"join_time"`
Profile Profile `json:"profile"`
}
type Spotify struct {
ID string `json:"id"`
DisplayName string `json:"display_name"`
}
type Discord struct {
ID string `json:"id"`
DisplayName string `json:"display_name"`
}
type Profile struct {
URL string `json:"url"`
Avatar string `json:"avatar"`
AvatarSmall string `json:"avatar_small"`
Country string `json:"country"`
Biography string `json:"biography"`
Twitter string `json:"twitter"`
Instagram string `json:"instagram"`
Spotify Spotify `json:"spotify"`
Discord Discord `json:"discord"`
}