User service done
Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
This commit is contained in:
@@ -46,7 +46,7 @@ func cloneRequest(r *http.Request) *http.Request {
|
|||||||
return r2
|
return r2
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets the User-Agent header for requests
|
// Sets the User-Agent header for requests.
|
||||||
type userAgentTransport struct {
|
type userAgentTransport struct {
|
||||||
ua string
|
ua string
|
||||||
Base http.RoundTripper
|
Base http.RoundTripper
|
||||||
@@ -70,12 +70,12 @@ func (t *userAgentTransport) base() http.RoundTripper {
|
|||||||
return http.DefaultTransport
|
return http.DefaultTransport
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestCompletionCallback defines the type of the request callback function
|
// RequestCompletionCallback defines the type of the request callback function.
|
||||||
type RequestCompletionCallback func(*http.Request, *http.Response)
|
type RequestCompletionCallback func(*http.Request, *http.Response)
|
||||||
|
|
||||||
// Client manages communication with the Reddit API
|
// Client manages communication with the Reddit API.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
// HTTP client used to communicate with the Reddit API
|
// HTTP client used to communicate with the Reddit API.
|
||||||
client *http.Client
|
client *http.Client
|
||||||
|
|
||||||
BaseURL *url.URL
|
BaseURL *url.URL
|
||||||
@@ -88,6 +88,9 @@ type Client struct {
|
|||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
|
|
||||||
|
// This is the client's user ID in Reddit's database.
|
||||||
|
redditID string
|
||||||
|
|
||||||
Comment CommentService
|
Comment CommentService
|
||||||
Flair FlairService
|
Flair FlairService
|
||||||
Link LinkService
|
Link LinkService
|
||||||
@@ -102,7 +105,7 @@ type Client struct {
|
|||||||
onRequestCompleted RequestCompletionCallback
|
onRequestCompleted RequestCompletionCallback
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnRequestCompleted sets the client's request completion callback
|
// OnRequestCompleted sets the client's request completion callback.
|
||||||
func (c *Client) OnRequestCompleted(rc RequestCompletionCallback) {
|
func (c *Client) OnRequestCompleted(rc RequestCompletionCallback) {
|
||||||
c.onRequestCompleted = rc
|
c.onRequestCompleted = rc
|
||||||
}
|
}
|
||||||
@@ -129,7 +132,7 @@ func newClient(httpClient *http.Client) *Client {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a client that can make requests to the Reddit API
|
// NewClient returns a client that can make requests to the Reddit API.
|
||||||
func NewClient(httpClient *http.Client, opts ...Opt) (c *Client, err error) {
|
func NewClient(httpClient *http.Client, opts ...Opt) (c *Client, err error) {
|
||||||
c = newClient(httpClient)
|
c = newClient(httpClient)
|
||||||
|
|
||||||
@@ -158,9 +161,9 @@ func NewClient(httpClient *http.Client, opts ...Opt) (c *Client, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRequest creates an API request
|
// NewRequest creates an API request.
|
||||||
// The path is the relative URL which will be resolves to the BaseURL of the Client
|
// The path is the relative URL which will be resolves to the BaseURL of the Client.
|
||||||
// It should always be specified without a preceding slash
|
// It should always be specified without a preceding slash.
|
||||||
func (c *Client) NewRequest(method, path string, body interface{}) (*http.Request, error) {
|
func (c *Client) NewRequest(method, path string, body interface{}) (*http.Request, error) {
|
||||||
u, err := c.BaseURL.Parse(path)
|
u, err := c.BaseURL.Parse(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -187,9 +190,9 @@ func (c *Client) NewRequest(method, path string, body interface{}) (*http.Reques
|
|||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPostForm creates an API request with a POST form
|
// NewPostForm creates an API request with a POST form.
|
||||||
// The path is the relative URL which will be resolves to the BaseURL of the Client
|
// The path is the relative URL which will be resolves to the BaseURL of the Client.
|
||||||
// It should always be specified without a preceding slash
|
// It should always be specified without a preceding slash.
|
||||||
func (c *Client) NewPostForm(path string, form url.Values) (*http.Request, error) {
|
func (c *Client) NewPostForm(path string, form url.Values) (*http.Request, error) {
|
||||||
u, err := c.BaseURL.Parse(path)
|
u, err := c.BaseURL.Parse(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -212,7 +215,7 @@ type Response struct {
|
|||||||
*http.Response
|
*http.Response
|
||||||
}
|
}
|
||||||
|
|
||||||
// newResponse creates a new Response for the provided http.Response
|
// newResponse creates a new Response for the provided http.Response.
|
||||||
func newResponse(r *http.Response) *Response {
|
func newResponse(r *http.Response) *Response {
|
||||||
response := Response{Response: r}
|
response := Response{Response: r}
|
||||||
return &response
|
return &response
|
||||||
@@ -260,6 +263,21 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Res
|
|||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRedditID returns the client's Reddit ID.
|
||||||
|
func (c *Client) GetRedditID(ctx context.Context) (string, error) {
|
||||||
|
if c.redditID != "" {
|
||||||
|
return c.redditID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self, _, err := c.User.Get(ctx, c.Username)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
c.redditID = fmt.Sprintf("%s_%s", kindAccount, self.ID)
|
||||||
|
return c.redditID, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DoRequest submits an HTTP request.
|
// DoRequest submits an HTTP request.
|
||||||
func DoRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
|
func DoRequest(ctx context.Context, req *http.Request) (*http.Response, error) {
|
||||||
return DoRequestWithClient(ctx, http.DefaultClient, req)
|
return DoRequestWithClient(ctx, http.DefaultClient, req)
|
||||||
@@ -304,7 +322,7 @@ func CheckResponse(r *http.Response) error {
|
|||||||
return errorResponse
|
return errorResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListOptions are the optional parameters to the various endpoints that return lists
|
// ListOptions are the optional parameters to the various endpoints that return lists.
|
||||||
type ListOptions struct {
|
type ListOptions struct {
|
||||||
// For getting submissions
|
// For getting submissions
|
||||||
// all, year, month, week, day, hour
|
// all, year, month, week, day, hour
|
||||||
|
|||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"date": 1592326190.0,
|
||||||
|
"icon_img": "https://www.redditstatic.com/avatars/avatar_default_08_C18D42.png",
|
||||||
|
"id": "t2_3v9o1yoi",
|
||||||
|
"name": "test123"
|
||||||
|
}
|
||||||
Vendored
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"date": 1592512594.0,
|
||||||
|
"rel_id": "r9_tqfqp8",
|
||||||
|
"name": "test123",
|
||||||
|
"id": "t2_7b8q1eob"
|
||||||
|
}
|
||||||
Vendored
+31
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"kind": "TrophyList",
|
||||||
|
"data": {
|
||||||
|
"trophies": [
|
||||||
|
{
|
||||||
|
"kind": "t6",
|
||||||
|
"data": {
|
||||||
|
"icon_70": "https://www.redditstatic.com/awards2/3_year_club-70.png",
|
||||||
|
"name": "Three-Year Club",
|
||||||
|
"url": null,
|
||||||
|
"icon_40": "https://www.redditstatic.com/awards2/3_year_club-40.png",
|
||||||
|
"award_id": null,
|
||||||
|
"id": null,
|
||||||
|
"description": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"kind": "t6",
|
||||||
|
"data": {
|
||||||
|
"icon_70": "https://www.redditstatic.com/awards2/verified_email-70.png",
|
||||||
|
"name": "Verified Email",
|
||||||
|
"url": null,
|
||||||
|
"icon_40": "https://www.redditstatic.com/awards2/verified_email-40.png",
|
||||||
|
"award_id": "o",
|
||||||
|
"id": "1q1tez",
|
||||||
|
"description": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,15 +6,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
kindComment = "t1"
|
kindComment = "t1"
|
||||||
kindAccount = "t2"
|
kindAccount = "t2"
|
||||||
kindLink = "t3"
|
kindLink = "t3"
|
||||||
kindMessage = "t4"
|
kindMessage = "t4"
|
||||||
kindSubreddit = "t5"
|
kindSubreddit = "t5"
|
||||||
kindAward = "t6"
|
kindAward = "t6"
|
||||||
kindListing = "Listing"
|
kindListing = "Listing"
|
||||||
kindUserList = "UserList"
|
kingTrophyList = "TrophyList"
|
||||||
kindMode = "more"
|
kindUserList = "UserList"
|
||||||
|
kindMode = "more"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Sort is a sorting option.
|
// Sort is a sorting option.
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package geddit
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -29,9 +31,17 @@ type UserService interface {
|
|||||||
Hidden(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error)
|
Hidden(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error)
|
||||||
Gilded(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error)
|
Gilded(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error)
|
||||||
|
|
||||||
Friend(ctx context.Context, username string, note string) (interface{}, *Response, error)
|
GetFriendship(ctx context.Context, username string) (*Friendship, *Response, error)
|
||||||
Unblock(ctx context.Context, username string) (*Response, error)
|
Friend(ctx context.Context, username string) (*Friendship, *Response, error)
|
||||||
Unfriend(ctx context.Context, username string) (*Response, error)
|
Unfriend(ctx context.Context, username string) (*Response, error)
|
||||||
|
|
||||||
|
Block(ctx context.Context, username string) (*Blocked, *Response, error)
|
||||||
|
// BlockByID(ctx context.Context, id string) (*Blocked, *Response, error)
|
||||||
|
Unblock(ctx context.Context, username string) (*Response, error)
|
||||||
|
// UnblockByID(ctx context.Context, id string) (*Response, error)
|
||||||
|
|
||||||
|
GetTrophies(ctx context.Context) (Trophies, *Response, error)
|
||||||
|
GetTrophiesOf(ctx context.Context, username string) (Trophies, *Response, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserServiceOp implements the UserService interface
|
// UserServiceOp implements the UserService interface
|
||||||
@@ -70,6 +80,79 @@ type UserShort struct {
|
|||||||
NSFW bool `json:"profile_over_18"`
|
NSFW bool `json:"profile_over_18"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Friendship represents a friend relationship.
|
||||||
|
type Friendship struct {
|
||||||
|
ID string `json:"rel_id,omitempty"`
|
||||||
|
Friend string `json:"name,omitempty"`
|
||||||
|
FriendID string `json:"id,omitempty"`
|
||||||
|
Created *Timestamp `json:"date,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blocked represents a blocked relationship.
|
||||||
|
type Blocked struct {
|
||||||
|
Blocked string `json:"name,omitempty"`
|
||||||
|
BlockedID string `json:"id,omitempty"`
|
||||||
|
Created *Timestamp `json:"date,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type rootTrophyListing struct {
|
||||||
|
Kind string `json:"kind,omitempty"`
|
||||||
|
Trophies Trophies `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trophy is a Reddit award.
|
||||||
|
type Trophy struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trophies is a list of trophies.
|
||||||
|
type Trophies []Trophy
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
|
func (t *Trophies) UnmarshalJSON(b []byte) error {
|
||||||
|
var data map[string]interface{}
|
||||||
|
if err := json.Unmarshal(b, &data); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
trophies, ok := data["trophies"]
|
||||||
|
if !ok {
|
||||||
|
return errors.New("data does not contain trophies")
|
||||||
|
}
|
||||||
|
|
||||||
|
trophyList, ok := trophies.([]interface{})
|
||||||
|
if !ok {
|
||||||
|
return errors.New("unexpected type for list of trophies")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, trophyData := range trophyList {
|
||||||
|
trophyInfo, ok := trophyData.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
info, ok := trophyInfo["data"]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
infoBytes, err := json.Marshal(info)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var trophy Trophy
|
||||||
|
err = json.Unmarshal(infoBytes, &trophy)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
*t = append(*t, trophy)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get returns information about the user
|
// Get returns information about the user
|
||||||
func (s *UserServiceOp) Get(ctx context.Context, username string) (*User, *Response, error) {
|
func (s *UserServiceOp) Get(ctx context.Context, username string) (*User, *Response, error) {
|
||||||
path := fmt.Sprintf("user/%s/about", username)
|
path := fmt.Sprintf("user/%s/about", username)
|
||||||
@@ -324,58 +407,113 @@ func (s *UserServiceOp) Gilded(ctx context.Context, opts ...SearchOptionSetter)
|
|||||||
return root.getLinks(), resp, nil
|
return root.getLinks(), resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Friend creates or updates a "friend" relationship
|
// GetFriendship returns friendship details with the specified user.
|
||||||
// // Request body contains JSON data with:
|
// If the user is not your friend, it will return an error.
|
||||||
// // name: existing Reddit username
|
func (s *UserServiceOp) GetFriendship(ctx context.Context, username string) (*Friendship, *Response, error) {
|
||||||
// // note: a string no longer than 300 characters
|
path := fmt.Sprintf("api/v1/me/friends/%s", username)
|
||||||
// func (s *UserServiceOp) Friend(ctx context.Context, username string, note string) (interface{}, *Response, error) {
|
|
||||||
// type request struct {
|
|
||||||
// Username string `url:"name"`
|
|
||||||
// Note string `url:"note"`
|
|
||||||
// }
|
|
||||||
|
|
||||||
// path := fmt.Sprintf("api/v1/me/friends/%s", username)
|
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
||||||
// body := request{Username: username, Note: note}
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// _, err := s.client.NewRequest(http.MethodPut, path, body)
|
root := new(Friendship)
|
||||||
// if err != nil {
|
resp, err := s.client.Do(ctx, req, root)
|
||||||
// return false, nil, err
|
if err != nil {
|
||||||
// }
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
// // todo: requires gold
|
return root, resp, nil
|
||||||
// return nil, nil, nil
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// Friend creates or updates a "friend" relationship
|
// Friend friends a user.
|
||||||
// Request body contains JSON data with:
|
func (s *UserServiceOp) Friend(ctx context.Context, username string) (*Friendship, *Response, error) {
|
||||||
// name: existing Reddit username
|
|
||||||
// note: a string no longer than 300 characters
|
|
||||||
func (s *UserServiceOp) Friend(ctx context.Context, username string, note string) (interface{}, *Response, error) {
|
|
||||||
type request struct {
|
type request struct {
|
||||||
Username string `url:"name"`
|
Username string `json:"name"`
|
||||||
Note string `url:"note"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
path := fmt.Sprintf("api/v1/me/friends/%s", username)
|
path := fmt.Sprintf("api/v1/me/friends/%s", username)
|
||||||
body := request{Username: username, Note: note}
|
body := request{username}
|
||||||
|
|
||||||
_, err := s.client.NewRequest(http.MethodPut, path, body)
|
req, err := s.client.NewRequest(http.MethodPut, path, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: requires gold
|
root := new(Friendship)
|
||||||
return nil, nil, nil
|
resp, err := s.client.Do(ctx, req, root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return root, resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unblock unblocks a user
|
// Unfriend unfriends a user.
|
||||||
|
func (s *UserServiceOp) Unfriend(ctx context.Context, username string) (*Response, error) {
|
||||||
|
path := fmt.Sprintf("api/v1/me/friends/%s", username)
|
||||||
|
req, err := s.client.NewRequest(http.MethodDelete, path, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return s.client.Do(ctx, req, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block blocks a user.
|
||||||
|
func (s *UserServiceOp) Block(ctx context.Context, username string) (*Blocked, *Response, error) {
|
||||||
|
path := "api/block_user"
|
||||||
|
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("name", username)
|
||||||
|
|
||||||
|
req, err := s.client.NewPostForm(path, form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
root := new(Blocked)
|
||||||
|
resp, err := s.client.Do(ctx, req, root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return root, resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// // BlockByID blocks a user via their full id.
|
||||||
|
// func (s *UserServiceOp) BlockByID(ctx context.Context, id string) (*Blocked, *Response, error) {
|
||||||
|
// path := "api/block_user"
|
||||||
|
|
||||||
|
// form := url.Values{}
|
||||||
|
// form.Set("account_id", id)
|
||||||
|
|
||||||
|
// req, err := s.client.NewPostForm(path, form)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// root := new(Blocked)
|
||||||
|
// resp, err := s.client.Do(ctx, req, root)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, resp, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return root, resp, nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Unblock unblocks a user.
|
||||||
func (s *UserServiceOp) Unblock(ctx context.Context, username string) (*Response, error) {
|
func (s *UserServiceOp) Unblock(ctx context.Context, username string) (*Response, error) {
|
||||||
|
selfID, err := s.client.GetRedditID(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
path := "api/unfriend"
|
path := "api/unfriend"
|
||||||
|
|
||||||
form := url.Values{}
|
form := url.Values{}
|
||||||
form.Set("name", username)
|
form.Set("name", username)
|
||||||
form.Set("type", "enemy")
|
form.Set("type", "enemy")
|
||||||
form.Set("container", "todo: this should be the current user's full id")
|
form.Set("container", selfID)
|
||||||
|
|
||||||
req, err := s.client.NewPostForm(path, form)
|
req, err := s.client.NewPostForm(path, form)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -385,13 +523,47 @@ func (s *UserServiceOp) Unblock(ctx context.Context, username string) (*Response
|
|||||||
return s.client.Do(ctx, req, nil)
|
return s.client.Do(ctx, req, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unfriend unfriends a user
|
// // UnblockByID unblocks a user via their full id.
|
||||||
func (s *UserServiceOp) Unfriend(ctx context.Context, username string) (*Response, error) {
|
// func (s *UserServiceOp) UnblockByID(ctx context.Context, id string) (*Response, error) {
|
||||||
path := fmt.Sprintf("api/v1/me/friends/%s", username)
|
// selfID, err := s.client.GetRedditID(ctx)
|
||||||
req, err := s.client.NewRequest(http.MethodDelete, path, nil)
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// path := "api/unfriend"
|
||||||
|
|
||||||
|
// form := url.Values{}
|
||||||
|
// form.Set("id", id)
|
||||||
|
// form.Set("type", "enemy")
|
||||||
|
// form.Set("container", selfID)
|
||||||
|
|
||||||
|
// req, err := s.client.NewPostForm(path, form)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return s.client.Do(ctx, req, nil)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// GetTrophies returns a list of your trophies.
|
||||||
|
func (s *UserServiceOp) GetTrophies(ctx context.Context) (Trophies, *Response, error) {
|
||||||
|
return s.GetTrophiesOf(ctx, s.client.Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTrophiesOf returns a list of the specified user's trophies.
|
||||||
|
func (s *UserServiceOp) GetTrophiesOf(ctx context.Context, username string) (Trophies, *Response, error) {
|
||||||
|
path := fmt.Sprintf("api/v1/user/%s/trophies", username)
|
||||||
|
|
||||||
|
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.client.Do(ctx, req, nil)
|
root := new(rootTrophyListing)
|
||||||
|
resp, err := s.client.Do(ctx, req, root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return root.Trophies, resp, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+201
@@ -1,6 +1,7 @@
|
|||||||
package geddit
|
package geddit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -102,6 +103,24 @@ var expectedComment = Comment{
|
|||||||
LinkNumComments: 89751,
|
LinkNumComments: 89751,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var expectedFriendship = &Friendship{
|
||||||
|
ID: "r9_tqfqp8",
|
||||||
|
Friend: "test123",
|
||||||
|
FriendID: "t2_7b8q1eob",
|
||||||
|
Created: &Timestamp{time.Date(2020, 6, 18, 20, 36, 34, 0, time.UTC)},
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedBlocked = &Blocked{
|
||||||
|
Blocked: "test123",
|
||||||
|
BlockedID: "t2_3v9o1yoi",
|
||||||
|
Created: &Timestamp{time.Date(2020, 6, 16, 16, 49, 50, 0, time.UTC)},
|
||||||
|
}
|
||||||
|
|
||||||
|
var expectedTrophies = Trophies{
|
||||||
|
{Name: "Three-Year Club"},
|
||||||
|
{Name: "Verified Email"},
|
||||||
|
}
|
||||||
|
|
||||||
func TestUserService_Get(t *testing.T) {
|
func TestUserService_Get(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
@@ -564,3 +583,185 @@ func TestUserService_Gilded(t *testing.T) {
|
|||||||
assert.Equal(t, "t3_gczwql", posts.After)
|
assert.Equal(t, "t3_gczwql", posts.After)
|
||||||
assert.Equal(t, "", posts.Before)
|
assert.Equal(t, "", posts.Before)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserService_GetFriendship(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
blob := readFileContents(t, "testdata/user/friend.json")
|
||||||
|
|
||||||
|
mux.HandleFunc("/api/v1/me/friends/test123", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodGet, r.Method)
|
||||||
|
fmt.Fprint(w, blob)
|
||||||
|
})
|
||||||
|
|
||||||
|
friendship, _, err := client.User.GetFriendship(ctx, "test123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedFriendship, friendship)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserService_Friend(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
blob := readFileContents(t, "testdata/user/friend.json")
|
||||||
|
|
||||||
|
mux.HandleFunc("/api/v1/me/friends/test123", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodPut, r.Method)
|
||||||
|
|
||||||
|
type request struct {
|
||||||
|
Username string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var req request
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&req)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "test123", req.Username)
|
||||||
|
|
||||||
|
fmt.Fprint(w, blob)
|
||||||
|
})
|
||||||
|
|
||||||
|
friendship, _, err := client.User.Friend(ctx, "test123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedFriendship, friendship)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserService_Unfriend(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
mux.HandleFunc("/api/v1/me/friends/test123", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodDelete, r.Method)
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
})
|
||||||
|
|
||||||
|
res, err := client.User.Unfriend(ctx, "test123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, http.StatusNoContent, res.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserService_Block(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
blob := readFileContents(t, "testdata/user/block.json")
|
||||||
|
|
||||||
|
mux.HandleFunc("/api/block_user", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodPost, r.Method)
|
||||||
|
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("name", "test123")
|
||||||
|
|
||||||
|
err := r.ParseForm()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, form, r.Form)
|
||||||
|
|
||||||
|
fmt.Fprint(w, blob)
|
||||||
|
})
|
||||||
|
|
||||||
|
blocked, _, err := client.User.Block(ctx, "test123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedBlocked, blocked)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func TestUserService_BlockByID(t *testing.T) {
|
||||||
|
// setup()
|
||||||
|
// defer teardown()
|
||||||
|
|
||||||
|
// blob := readFileContents(t, "testdata/user/block.json")
|
||||||
|
|
||||||
|
// mux.HandleFunc("/api/block_user", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// assert.Equal(t, http.MethodPost, r.Method)
|
||||||
|
|
||||||
|
// form := url.Values{}
|
||||||
|
// form.Set("account_id", "abc123")
|
||||||
|
|
||||||
|
// err := r.ParseForm()
|
||||||
|
// assert.NoError(t, err)
|
||||||
|
// assert.Equal(t, form, r.Form)
|
||||||
|
|
||||||
|
// fmt.Fprint(w, blob)
|
||||||
|
// })
|
||||||
|
|
||||||
|
// blocked, _, err := client.User.BlockByID(ctx, "abc123")
|
||||||
|
// assert.NoError(t, err)
|
||||||
|
// assert.Equal(t, expectedBlocked, blocked)
|
||||||
|
// }
|
||||||
|
|
||||||
|
func TestUserService_Unblock(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
client.redditID = "self123"
|
||||||
|
|
||||||
|
mux.HandleFunc("/api/unfriend", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodPost, r.Method)
|
||||||
|
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("name", "test123")
|
||||||
|
form.Set("type", "enemy")
|
||||||
|
form.Set("container", client.redditID)
|
||||||
|
|
||||||
|
err := r.ParseForm()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, form, r.Form)
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err := client.User.Unblock(ctx, "test123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// func TestUserService_UnblockByID(t *testing.T) {
|
||||||
|
// setup()
|
||||||
|
// defer teardown()
|
||||||
|
|
||||||
|
// client.redditID = "self123"
|
||||||
|
|
||||||
|
// mux.HandleFunc("/api/unfriend", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// assert.Equal(t, http.MethodPost, r.Method)
|
||||||
|
|
||||||
|
// form := url.Values{}
|
||||||
|
// form.Set("id", "abc123")
|
||||||
|
// form.Set("type", "enemy")
|
||||||
|
// form.Set("container", client.redditID)
|
||||||
|
|
||||||
|
// err := r.ParseForm()
|
||||||
|
// assert.NoError(t, err)
|
||||||
|
// assert.Equal(t, form, r.Form)
|
||||||
|
// })
|
||||||
|
|
||||||
|
// _, err := client.User.UnblockByID(ctx, "abc123")
|
||||||
|
// assert.NoError(t, err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
func TestUserService_GetTrophies(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
blob := readFileContents(t, "testdata/user/trophies.json")
|
||||||
|
|
||||||
|
mux.HandleFunc("/api/v1/user/user1/trophies", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodGet, r.Method)
|
||||||
|
fmt.Fprint(w, blob)
|
||||||
|
})
|
||||||
|
|
||||||
|
trophies, _, err := client.User.GetTrophies(ctx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedTrophies, trophies)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUserService_GetTrophiesOf(t *testing.T) {
|
||||||
|
setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
blob := readFileContents(t, "testdata/user/trophies.json")
|
||||||
|
|
||||||
|
mux.HandleFunc("/api/v1/user/test123/trophies", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
assert.Equal(t, http.MethodGet, r.Method)
|
||||||
|
fmt.Fprint(w, blob)
|
||||||
|
})
|
||||||
|
|
||||||
|
trophies, _, err := client.User.GetTrophiesOf(ctx, "test123")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, expectedTrophies, trophies)
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,12 +43,7 @@ func (s *VoteServiceOp) vote(ctx context.Context, id string, vote vote) (*Respon
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := s.client.Do(ctx, req, nil)
|
return s.client.Do(ctx, req, nil)
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Up upvotes a link or a comment
|
// Up upvotes a link or a comment
|
||||||
|
|||||||
Reference in New Issue
Block a user