Replace references to "link" by "post"

Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
This commit is contained in:
Vartan Benohanian 2020-06-22 21:52:34 -04:00
parent b70253ec48
commit f649216b9d
15 changed files with 191 additions and 221 deletions

View file

@ -8,7 +8,7 @@ import (
)
// CommentService handles communication with the comment
// related methods of the Reddit API
// related methods of the Reddit API.
type CommentService interface {
Submit(ctx context.Context, id string, text string) (*Comment, *Response, error)
Edit(ctx context.Context, id string, text string) (*Comment, *Response, error)
@ -18,7 +18,7 @@ type CommentService interface {
Unsave(ctx context.Context, id string) (*Response, error)
}
// CommentServiceOp implements the CommentService interface
// CommentServiceOp implements the CommentService interface.
type CommentServiceOp struct {
client *Client
}
@ -29,7 +29,7 @@ func (s *CommentServiceOp) isCommentID(id string) bool {
return strings.HasPrefix(id, kindComment+"_")
}
// Submit submits a comment as a reply to a link or to another comment
// Submit submits a comment as a reply to a post or to another comment.
func (s *CommentServiceOp) Submit(ctx context.Context, id string, text string) (*Comment, *Response, error) {
path := "api/comment"
@ -53,11 +53,11 @@ func (s *CommentServiceOp) Submit(ctx context.Context, id string, text string) (
return root, resp, nil
}
// Edit edits the comment with the id provided
// todo: don't forget to do this for links (i.e. posts)
// Edit edits the comment with the id provided.
// todo: don't forget to do this for posts
func (s *CommentServiceOp) Edit(ctx context.Context, id string, text string) (*Comment, *Response, error) {
if !s.isCommentID(id) {
return nil, nil, fmt.Errorf("must provide comment id (starting with t1_); id provided: %q", id)
return nil, nil, fmt.Errorf("must provide comment id (starting with %s_); id provided: %q", kindComment, id)
}
path := "api/editusertext"
@ -82,12 +82,11 @@ func (s *CommentServiceOp) Edit(ctx context.Context, id string, text string) (*C
return root, resp, nil
}
// Delete deletes a comment via the id
// todo: don't forget to do this for links (i.e. posts)
// Seems like this always returns {} as a response, no matter if an id is even provided
// Delete deletes a comment via the id.
// todo: don't forget to do this for posts.
func (s *CommentServiceOp) Delete(ctx context.Context, id string) (*Response, error) {
if !s.isCommentID(id) {
return nil, fmt.Errorf("must provide comment id (starting with t1_); id provided: %q", id)
return nil, fmt.Errorf("must provide comment id (starting with %s_); id provided: %q", kindComment, id)
}
path := "api/del"
@ -108,11 +107,10 @@ func (s *CommentServiceOp) Delete(ctx context.Context, id string) (*Response, er
return resp, nil
}
// Save saves a comment
// Seems like this just returns {} on success
// Save saves a comment.
func (s *CommentServiceOp) Save(ctx context.Context, id string) (*Response, error) {
if !s.isCommentID(id) {
return nil, fmt.Errorf("must provide comment id (starting with t1_); id provided: %q", id)
return nil, fmt.Errorf("must provide comment id (starting with %s_); id provided: %q", kindComment, id)
}
path := "api/save"
@ -133,8 +131,7 @@ func (s *CommentServiceOp) Save(ctx context.Context, id string) (*Response, erro
return resp, nil
}
// Unsave unsaves a comment
// Seems like this just returns {} on success
// Unsave unsaves a comment.
func (s *CommentServiceOp) Unsave(ctx context.Context, id string) (*Response, error) {
if !s.isCommentID(id) {
return nil, fmt.Errorf("must provide comment id (starting with t1_); id provided: %q", id)

View file

@ -32,9 +32,10 @@ var expectedCommentSubmitOrEdit = &Comment{
Controversiality: 0,
Created: &Timestamp{time.Date(2020, 4, 29, 0, 9, 47, 0, time.UTC)},
Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)},
// todo: this should just be nil
Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)},
LinkID: "t3_link1",
PostID: "t3_link1",
}
func TestCommentServiceOp_Submit(t *testing.T) {

View file

@ -93,8 +93,8 @@ type Client struct {
Comment CommentService
Flair FlairService
Link LinkService
Listings ListingsService
Post PostService
Search SearchService
Subreddit SubredditService
User UserService
@ -122,8 +122,8 @@ func newClient(httpClient *http.Client) *Client {
c.Comment = &CommentServiceOp{client: c}
c.Flair = &FlairServiceOp{client: c}
c.Link = &LinkServiceOp{client: c}
c.Listings = &ListingsServiceOp{client: c}
c.Post = &PostServiceOp{client: c}
c.Search = &SearchServiceOp{client: c}
c.Subreddit = &SubredditServiceOp{client: c}
c.User = &UserServiceOp{client: c}

View file

@ -68,8 +68,8 @@ func testClientServices(t *testing.T, c *Client) {
services := []string{
"Comment",
"Flair",
"Link",
"Listings",
"Post",
"Subreddit",
"User",
"Vote",

View file

@ -8,23 +8,23 @@ import (
"strings"
)
// ListingsService handles communication with the link (post)
// related methods of the Reddit API
// ListingsService handles communication with the post
// related methods of the Reddit API.
type ListingsService interface {
Get(ctx context.Context, ids ...string) ([]Comment, []Link, []Subreddit, *Response, error)
GetLinks(ctx context.Context, ids ...string) ([]Link, *Response, error)
GetLink(ctx context.Context, id string) (*LinkAndComments, *Response, error)
Get(ctx context.Context, ids ...string) ([]Post, []Comment, []Subreddit, *Response, error)
GetPosts(ctx context.Context, ids ...string) ([]Post, *Response, error)
GetPost(ctx context.Context, id string) (*PostAndComments, *Response, error)
}
// ListingsServiceOp implements the Vote interface
// ListingsServiceOp implements the Vote interface.
type ListingsServiceOp struct {
client *Client
}
var _ ListingsService = &ListingsServiceOp{}
// Get returns comments, links, and subreddits from their IDs
func (s *ListingsServiceOp) Get(ctx context.Context, ids ...string) ([]Comment, []Link, []Subreddit, *Response, error) {
// Get returns posts, comments, and subreddits from their IDs.
func (s *ListingsServiceOp) Get(ctx context.Context, ids ...string) ([]Post, []Comment, []Subreddit, *Response, error) {
type query struct {
IDs []string `url:"id,comma"`
}
@ -46,15 +46,15 @@ func (s *ListingsServiceOp) Get(ctx context.Context, ids ...string) ([]Comment,
return nil, nil, nil, resp, err
}
posts := root.getPosts().Posts
comments := root.getComments().Comments
links := root.getLinks().Links
subreddits := root.getSubreddits().Subreddits
return comments, links, subreddits, resp, nil
return posts, comments, subreddits, resp, nil
}
// GetLinks returns links from their full IDs
func (s *ListingsServiceOp) GetLinks(ctx context.Context, ids ...string) ([]Link, *Response, error) {
// GetPosts returns posts from their full IDs.
func (s *ListingsServiceOp) GetPosts(ctx context.Context, ids ...string) ([]Post, *Response, error) {
if len(ids) == 0 {
return nil, nil, errors.New("must provide at least 1 id")
}
@ -71,18 +71,18 @@ func (s *ListingsServiceOp) GetLinks(ctx context.Context, ids ...string) ([]Link
return nil, resp, err
}
return root.getLinks().Links, resp, nil
return root.getPosts().Posts, resp, nil
}
// GetLink returns a link with its comments
func (s *ListingsServiceOp) GetLink(ctx context.Context, id string) (*LinkAndComments, *Response, error) {
// GetPost returns a post with its comments.
func (s *ListingsServiceOp) GetPost(ctx context.Context, id string) (*PostAndComments, *Response, error) {
path := fmt.Sprintf("comments/%s", id)
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(LinkAndComments)
root := new(PostAndComments)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err

View file

@ -9,9 +9,9 @@ import (
"github.com/google/go-querystring/query"
)
// LinkService handles communication with the link (post)
// related methods of the Reddit API
type LinkService interface {
// PostService handles communication with the link (post)
// related methods of the Reddit API.
type PostService interface {
SubmitSelf(ctx context.Context, opts SubmitSelfOptions) (*Submitted, *Response, error)
SubmitURL(ctx context.Context, opts SubmitURLOptions) (*Submitted, *Response, error)
@ -28,12 +28,12 @@ type LinkService interface {
Unhide(ctx context.Context, ids ...string) (*Response, error)
}
// LinkServiceOp implements the LinkService interface
type LinkServiceOp struct {
// PostServiceOp implements the PostService interface.
type PostServiceOp struct {
client *Client
}
var _ LinkService = &LinkServiceOp{}
var _ PostService = &PostServiceOp{}
type submittedLinkRoot struct {
JSON struct {
@ -41,14 +41,14 @@ type submittedLinkRoot struct {
} `json:"json"`
}
// Submitted is a newly submitted post on Reddit
// Submitted is a newly submitted post on Reddit.
type Submitted struct {
ID string `json:"id,omitempty"`
FullID string `json:"name,omitempty"`
URL string `json:"url,omitempty"`
}
// SubmitSelfOptions are options used for selftext posts
// SubmitSelfOptions are options used for selftext posts.
type SubmitSelfOptions struct {
Subreddit string `url:"sr,omitempty"`
Title string `url:"title,omitempty"`
@ -62,7 +62,7 @@ type SubmitSelfOptions struct {
Spoiler bool `url:"spoiler,omitempty"`
}
// SubmitURLOptions are options used for link posts
// SubmitURLOptions are options used for link posts.
type SubmitURLOptions struct {
Subreddit string `url:"sr,omitempty"`
Title string `url:"title,omitempty"`
@ -77,8 +77,8 @@ type SubmitURLOptions struct {
Spoiler bool `url:"spoiler,omitempty"`
}
// SubmitSelf submits a self text post
func (s *LinkServiceOp) SubmitSelf(ctx context.Context, opts SubmitSelfOptions) (*Submitted, *Response, error) {
// SubmitSelf submits a self text post.
func (s *PostServiceOp) SubmitSelf(ctx context.Context, opts SubmitSelfOptions) (*Submitted, *Response, error) {
type submit struct {
SubmitSelfOptions
Kind string `url:"kind,omitempty"`
@ -86,8 +86,8 @@ func (s *LinkServiceOp) SubmitSelf(ctx context.Context, opts SubmitSelfOptions)
return s.submit(ctx, &submit{opts, "self"})
}
// SubmitURL submits a link post
func (s *LinkServiceOp) SubmitURL(ctx context.Context, opts SubmitURLOptions) (*Submitted, *Response, error) {
// SubmitURL submits a link post.
func (s *PostServiceOp) SubmitURL(ctx context.Context, opts SubmitURLOptions) (*Submitted, *Response, error) {
type submit struct {
SubmitURLOptions
Kind string `url:"kind,omitempty"`
@ -95,7 +95,7 @@ func (s *LinkServiceOp) SubmitURL(ctx context.Context, opts SubmitURLOptions) (*
return s.submit(ctx, &submit{opts, "link"})
}
func (s *LinkServiceOp) submit(ctx context.Context, v interface{}) (*Submitted, *Response, error) {
func (s *PostServiceOp) submit(ctx context.Context, v interface{}) (*Submitted, *Response, error) {
path := "api/submit"
form, err := query.Values(v)
@ -118,9 +118,8 @@ func (s *LinkServiceOp) submit(ctx context.Context, v interface{}) (*Submitted,
return root.JSON.Data, resp, nil
}
// EnableReplies enables inbox replies for a thing created by the client
// Always returns {}
func (s *LinkServiceOp) EnableReplies(ctx context.Context, id string) (*Response, error) {
// EnableReplies enables inbox replies for a thing created by the client.
func (s *PostServiceOp) EnableReplies(ctx context.Context, id string) (*Response, error) {
path := "api/sendreplies"
form := url.Values{}
@ -135,9 +134,8 @@ func (s *LinkServiceOp) EnableReplies(ctx context.Context, id string) (*Response
return s.client.Do(ctx, req, nil)
}
// DisableReplies dsables inbox replies for a thing created by the client
// Always returns {}
func (s *LinkServiceOp) DisableReplies(ctx context.Context, id string) (*Response, error) {
// DisableReplies dsables inbox replies for a thing created by the client.
func (s *PostServiceOp) DisableReplies(ctx context.Context, id string) (*Response, error) {
path := "api/sendreplies"
form := url.Values{}
@ -152,9 +150,8 @@ func (s *LinkServiceOp) DisableReplies(ctx context.Context, id string) (*Respons
return s.client.Do(ctx, req, nil)
}
// MarkNSFW marks a post as NSFW
// {} on success
func (s *LinkServiceOp) MarkNSFW(ctx context.Context, id string) (*Response, error) {
// MarkNSFW marks a post as NSFW.
func (s *PostServiceOp) MarkNSFW(ctx context.Context, id string) (*Response, error) {
path := "api/marknsfw"
form := url.Values{}
@ -168,9 +165,8 @@ func (s *LinkServiceOp) MarkNSFW(ctx context.Context, id string) (*Response, err
return s.client.Do(ctx, req, nil)
}
// UnmarkNSFW unmarks a post as NSFW
// {} on success
func (s *LinkServiceOp) UnmarkNSFW(ctx context.Context, id string) (*Response, error) {
// UnmarkNSFW unmarks a post as NSFW.
func (s *PostServiceOp) UnmarkNSFW(ctx context.Context, id string) (*Response, error) {
path := "api/unmarknsfw"
form := url.Values{}
@ -184,9 +180,8 @@ func (s *LinkServiceOp) UnmarkNSFW(ctx context.Context, id string) (*Response, e
return s.client.Do(ctx, req, nil)
}
// Spoiler marks a post as a spoiler
// {} on success
func (s *LinkServiceOp) Spoiler(ctx context.Context, id string) (*Response, error) {
// Spoiler marks a post as a spoiler.
func (s *PostServiceOp) Spoiler(ctx context.Context, id string) (*Response, error) {
path := "api/spoiler"
form := url.Values{}
@ -200,9 +195,8 @@ func (s *LinkServiceOp) Spoiler(ctx context.Context, id string) (*Response, erro
return s.client.Do(ctx, req, nil)
}
// Unspoiler unmarks a post as a spoiler
// {} on success
func (s *LinkServiceOp) Unspoiler(ctx context.Context, id string) (*Response, error) {
// Unspoiler unmarks a post as a spoiler.
func (s *PostServiceOp) Unspoiler(ctx context.Context, id string) (*Response, error) {
path := "api/unspoiler"
form := url.Values{}
@ -216,9 +210,8 @@ func (s *LinkServiceOp) Unspoiler(ctx context.Context, id string) (*Response, er
return s.client.Do(ctx, req, nil)
}
// Hide hides links with the specified ids
// On successful calls, it just returns {}
func (s *LinkServiceOp) Hide(ctx context.Context, ids ...string) (*Response, error) {
// Hide hides links with the specified ids.
func (s *PostServiceOp) Hide(ctx context.Context, ids ...string) (*Response, error) {
if len(ids) == 0 {
return nil, errors.New("must provide at least 1 id")
}
@ -236,9 +229,8 @@ func (s *LinkServiceOp) Hide(ctx context.Context, ids ...string) (*Response, err
return s.client.Do(ctx, req, nil)
}
// Unhide unhides links with the specified ids
// On successful calls, it just returns {}
func (s *LinkServiceOp) Unhide(ctx context.Context, ids ...string) (*Response, error) {
// Unhide unhides links with the specified ids.
func (s *PostServiceOp) Unhide(ctx context.Context, ids ...string) (*Response, error) {
if len(ids) == 0 {
return nil, errors.New("must provide at least 1 id")
}

View file

@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
)
func TestLinkServiceOp_Hide(t *testing.T) {
func TestPostServiceOp_Hide(t *testing.T) {
setup()
defer teardown()
@ -26,15 +26,15 @@ func TestLinkServiceOp_Hide(t *testing.T) {
fmt.Fprint(w, `{}`)
})
_, err := client.Link.Hide(ctx)
_, err := client.Post.Hide(ctx)
assert.EqualError(t, err, "must provide at least 1 id")
res, err := client.Link.Hide(ctx, "1", "2", "3")
res, err := client.Post.Hide(ctx, "1", "2", "3")
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, res.StatusCode)
}
func TestLinkServiceOp_Unhide(t *testing.T) {
func TestPostServiceOp_Unhide(t *testing.T) {
setup()
defer teardown()
@ -51,10 +51,10 @@ func TestLinkServiceOp_Unhide(t *testing.T) {
fmt.Fprint(w, `{}`)
})
_, err := client.Link.Unhide(ctx)
_, err := client.Post.Unhide(ctx)
assert.EqualError(t, err, "must provide at least 1 id")
res, err := client.Link.Unhide(ctx, "1", "2", "3")
res, err := client.Post.Unhide(ctx, "1", "2", "3")
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, res.StatusCode)
}

View file

@ -16,7 +16,7 @@ import (
// Note: The "limit" parameter in searches is prone to inconsistent
// behaviour.
type SearchService interface {
Posts(ctx context.Context, query string, subreddits []string, opts ...SearchOptionSetter) (*Links, *Response, error)
Posts(ctx context.Context, query string, subreddits []string, opts ...SearchOptionSetter) (*Posts, *Response, error)
Subreddits(ctx context.Context, query string, opts ...SearchOptionSetter) (*Subreddits, *Response, error)
Users(ctx context.Context, query string, opts ...SearchOptionSetter) (*Users, *Response, error)
}
@ -99,7 +99,7 @@ func setRestrict(opts SearchOptions) {
// Posts searches for posts.
// If the list of subreddits is empty, the search is run against r/all.
func (s *SearchServiceOp) Posts(ctx context.Context, query string, subreddits []string, opts ...SearchOptionSetter) (*Links, *Response, error) {
func (s *SearchServiceOp) Posts(ctx context.Context, query string, subreddits []string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
opts = append(opts, setType("link"), setQuery(query))
path := "search"
@ -122,7 +122,7 @@ func (s *SearchServiceOp) Posts(ctx context.Context, query string, subreddits []
return nil, resp, err
}
return root.getLinks(), resp, nil
return root.getPosts(), resp, nil
}
// Subreddits searches for subreddits.

View file

@ -25,8 +25,8 @@ type SubredditService interface {
GetApproved(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error)
GetModerated(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error)
GetSticky1(ctx context.Context, subreddit string) (*LinkAndComments, *Response, error)
GetSticky2(ctx context.Context, subreddit string) (*LinkAndComments, *Response, error)
GetSticky1(ctx context.Context, subreddit string) (*PostAndComments, *Response, error)
GetSticky2(ctx context.Context, subreddit string) (*PostAndComments, *Response, error)
Subscribe(ctx context.Context, subreddits ...string) (*Response, error)
SubscribeByID(ctx context.Context, ids ...string) (*Response, error)
@ -126,17 +126,16 @@ func (s *SubredditServiceOp) GetModerated(ctx context.Context, opts *ListOptions
}
// GetSticky1 returns the first stickied post on a subreddit (if it exists).
func (s *SubredditServiceOp) GetSticky1(ctx context.Context, name string) (*LinkAndComments, *Response, error) {
func (s *SubredditServiceOp) GetSticky1(ctx context.Context, name string) (*PostAndComments, *Response, error) {
return s.getSticky(ctx, name, sticky1)
}
// GetSticky2 returns the second stickied post on a subreddit (if it exists).
func (s *SubredditServiceOp) GetSticky2(ctx context.Context, name string) (*LinkAndComments, *Response, error) {
func (s *SubredditServiceOp) GetSticky2(ctx context.Context, name string) (*PostAndComments, *Response, error) {
return s.getSticky(ctx, name, sticky2)
}
// Subscribe subscribes to subreddits based on their names.
// Returns {} on success.
func (s *SubredditServiceOp) Subscribe(ctx context.Context, subreddits ...string) (*Response, error) {
form := url.Values{}
form.Set("action", "sub")
@ -145,7 +144,6 @@ func (s *SubredditServiceOp) Subscribe(ctx context.Context, subreddits ...string
}
// SubscribeByID subscribes to subreddits based on their id.
// Returns {} on success.
func (s *SubredditServiceOp) SubscribeByID(ctx context.Context, ids ...string) (*Response, error) {
form := url.Values{}
form.Set("action", "sub")
@ -154,7 +152,6 @@ func (s *SubredditServiceOp) SubscribeByID(ctx context.Context, ids ...string) (
}
// Unsubscribe unsubscribes from subreddits based on their names.
// Returns {} on success.
func (s *SubredditServiceOp) Unsubscribe(ctx context.Context, subreddits ...string) (*Response, error) {
form := url.Values{}
form.Set("action", "unsub")
@ -163,7 +160,6 @@ func (s *SubredditServiceOp) Unsubscribe(ctx context.Context, subreddits ...stri
}
// UnsubscribeByID unsubscribes from subreddits based on their id.
// Returns {} on success.
func (s *SubredditServiceOp) UnsubscribeByID(ctx context.Context, ids ...string) (*Response, error) {
form := url.Values{}
form.Set("action", "unsub")
@ -255,7 +251,7 @@ func (s *SubredditServiceOp) getSubreddits(ctx context.Context, path string, opt
// Num should be equal to 1 or 2, depending on which one you want.
// If it's <= 1, it's 1.
// If it's >= 2, it's 2.
func (s *SubredditServiceOp) getSticky(ctx context.Context, subreddit string, num sticky) (*LinkAndComments, *Response, error) {
func (s *SubredditServiceOp) getSticky(ctx context.Context, subreddit string, num sticky) (*PostAndComments, *Response, error) {
type query struct {
Num sticky `url:"num"`
}
@ -271,7 +267,7 @@ func (s *SubredditServiceOp) getSticky(ctx context.Context, subreddit string, nu
return nil, nil, err
}
root := new(LinkAndComments)
root := new(PostAndComments)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
@ -337,7 +333,7 @@ func (f *PostFinder) Timespan(timespan Timespan) *PostFinder {
}
// Do conducts the search.
func (f *PostFinder) Do(ctx context.Context) (*Links, *Response, error) {
func (f *PostFinder) Do(ctx context.Context) (*Posts, *Response, error) {
path := f.sort
if len(f.subreddits) > 0 {
path = fmt.Sprintf("r/%s/%s", strings.Join(f.subreddits, "+"), f.sort)
@ -359,5 +355,5 @@ func (f *PostFinder) Do(ctx context.Context) (*Links, *Response, error) {
return nil, resp, err
}
return root.getLinks(), resp, nil
return root.getPosts(), resp, nil
}

View file

@ -81,8 +81,8 @@ var expectedSubreddits = &Subreddits{
},
}
var expectedStickyPost = &LinkAndComments{
Link: Link{
var expectedSticky = &PostAndComments{
Post: Post{
ID: "hcl9gq",
FullID: "t3_hcl9gq",
Created: &Timestamp{time.Date(2020, 6, 20, 12, 8, 57, 0, time.UTC)},
@ -255,9 +255,9 @@ func TestSubredditServiceOp_GetSticky1(t *testing.T) {
fmt.Fprint(w, blob)
})
post, _, err := client.Subreddit.GetSticky1(ctx, "nba")
sticky, _, err := client.Subreddit.GetSticky1(ctx, "nba")
assert.NoError(t, err)
assert.Equal(t, expectedStickyPost.Link, post.Link)
// b, _ := json.MarshalIndent(post.Comments, "", " ")
assert.Equal(t, expectedSticky.Post, sticky.Post)
// b, _ := json.MarshalIndent(sticky.Comments, "", " ")
// fmt.Println(string(b))
}

View file

@ -8,7 +8,7 @@ import (
const (
kindComment = "t1"
kindAccount = "t2"
kindLink = "t3"
kindLink = "t3" // a link is a post
kindMessage = "t4"
kindSubreddit = "t5"
kindAward = "t6"
@ -108,11 +108,11 @@ type Listing struct {
Before string `json:"before"`
}
// Things are stuff!
// Things are objects/entities coming from the Reddit API.
type Things struct {
Comments []Comment `json:"comments,omitempty"`
Users []User `json:"users,omitempty"`
Links []Link `json:"links,omitempty"`
Posts []Post `json:"posts,omitempty"`
Subreddits []Subreddit `json:"subreddits,omitempty"`
// todo: add the other kinds of things
}
@ -127,9 +127,9 @@ type userRoot struct {
Data *User `json:"data,omitempty"`
}
type linkRoot struct {
type postRoot struct {
Kind string `json:"kind,omitempty"`
Data *Link `json:"data,omitempty"`
Data *Post `json:"data,omitempty"`
}
type subredditRoot struct {
@ -138,7 +138,7 @@ type subredditRoot struct {
}
// UnmarshalJSON implements the json.Unmarshaler interface.
func (l *Things) UnmarshalJSON(b []byte) error {
func (t *Things) UnmarshalJSON(b []byte) error {
var children []map[string]interface{}
if err := json.Unmarshal(b, &children); err != nil {
return err
@ -151,23 +151,23 @@ func (l *Things) UnmarshalJSON(b []byte) error {
case kindComment:
root := new(commentRoot)
if err := json.Unmarshal(byteValue, root); err == nil && root.Data != nil {
l.Comments = append(l.Comments, *root.Data)
t.Comments = append(t.Comments, *root.Data)
}
case kindAccount:
root := new(userRoot)
if err := json.Unmarshal(byteValue, root); err == nil && root.Data != nil {
l.Users = append(l.Users, *root.Data)
t.Users = append(t.Users, *root.Data)
}
case kindLink:
root := new(linkRoot)
root := new(postRoot)
if err := json.Unmarshal(byteValue, root); err == nil && root.Data != nil {
l.Links = append(l.Links, *root.Data)
t.Posts = append(t.Posts, *root.Data)
}
case kindMessage:
case kindSubreddit:
root := new(subredditRoot)
if err := json.Unmarshal(byteValue, root); err == nil && root.Data != nil {
l.Subreddits = append(l.Subreddits, *root.Data)
t.Subreddits = append(t.Subreddits, *root.Data)
}
case kindAward:
}
@ -203,13 +203,13 @@ type Comment struct {
Score int `json:"score"`
Controversiality int `json:"controversiality"`
LinkID string `json:"link_id,omitempty"`
PostID string `json:"link_id,omitempty"`
// These don't appear when submitting a comment
LinkTitle string `json:"link_title,omitempty"`
LinkPermalink string `json:"link_permalink,omitempty"`
LinkAuthor string `json:"link_author,omitempty"`
LinkNumComments int `json:"num_comments"`
PostTitle string `json:"link_title,omitempty"`
PostPermalink string `json:"link_permalink,omitempty"`
PostAuthor string `json:"link_author,omitempty"`
PostNumComments int `json:"num_comments"`
IsSubmitter bool `json:"is_submitter"`
ScoreHidden bool `json:"score_hidden"`
@ -242,8 +242,8 @@ func (r *Replies) UnmarshalJSON(data []byte) error {
return nil
}
// Link is a submitted post on Reddit
type Link struct {
// Post is a submitted post on Reddit.
type Post struct {
ID string `json:"id,omitempty"`
FullID string `json:"name,omitempty"`
Created *Timestamp `json:"created_utc,omitempty"`
@ -332,10 +332,10 @@ func (rl *rootListing) getUsers() *Users {
return v
}
func (rl *rootListing) getLinks() *Links {
v := new(Links)
func (rl *rootListing) getPosts() *Posts {
v := new(Posts)
if rl != nil && rl.Data != nil {
v.Links = rl.Data.Things.Links
v.Posts = rl.Data.Things.Posts
v.After = rl.Data.After
v.Before = rl.Data.Before
}
@ -373,31 +373,16 @@ type Subreddits struct {
Before string `json:"before"`
}
// Links is a list of links
type Links struct {
Links []Link `json:"submissions,omitempty"`
// Posts is a list of posts.
type Posts struct {
Posts []Post `json:"submissions,omitempty"`
After string `json:"after"`
Before string `json:"before"`
}
// CommentsLinks is a list of comments and links
type CommentsLinks struct {
Comments []Comment `json:"comments,omitempty"`
Links []Link `json:"links,omitempty"`
After string `json:"after"`
Before string `json:"before"`
}
// CommentsLinksSubreddits is a list of comments, links, and subreddits
type CommentsLinksSubreddits struct {
Comments []Comment `json:"comments,omitempty"`
Links []Link `json:"links,omitempty"`
Subreddits []Subreddit `json:"subreddits,omitempty"`
}
// LinkAndComments is a link and its comments
type LinkAndComments struct {
Link Link `json:"link,omitempty"`
// PostAndComments is a post and its comments
type PostAndComments struct {
Post Post `json:"post,omitempty"`
Comments []Comment `json:"comments,omitempty"`
}
@ -405,7 +390,7 @@ type LinkAndComments struct {
// When getting a sticky post, you get an array of 2 Listings
// The 1st one contains the single post in its children array
// The 2nd one contains the comments to the post
func (rl *LinkAndComments) UnmarshalJSON(data []byte) error {
func (pc *PostAndComments) UnmarshalJSON(data []byte) error {
var l []rootListing
err := json.Unmarshal(data, &l)
@ -414,14 +399,14 @@ func (rl *LinkAndComments) UnmarshalJSON(data []byte) error {
}
if len(l) < 2 {
return errors.New("unexpected json response when getting link")
return errors.New("unexpected json response when getting post")
}
stickyLink := l[0].getLinks().Links[0]
stickyComments := l[1].getComments().Comments
post := l[0].getPosts().Posts[0]
comments := l[1].getComments().Comments
rl.Link = stickyLink
rl.Comments = stickyComments
pc.Post = post
pc.Comments = comments
return nil
}

View file

@ -26,7 +26,7 @@ func (t *Timestamp) MarshalJSON() ([]byte, error) {
func (t *Timestamp) UnmarshalJSON(data []byte) (err error) {
str := string(data)
// "edited" for comments and links is either false, or a timestamp
// "edited" for posts and comments is either false, or a timestamp.
if str == "false" {
return
}

77
user.go
View file

@ -10,26 +10,26 @@ import (
)
// UserService handles communication with the user
// related methods of the Reddit API
// related methods of the Reddit API.
type UserService interface {
Get(ctx context.Context, username string) (*User, *Response, error)
GetMultipleByID(ctx context.Context, ids ...string) (map[string]*UserShort, *Response, error)
UsernameAvailable(ctx context.Context, username string) (bool, *Response, error)
Overview(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Comments, *Response, error)
OverviewOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Links, *Comments, *Response, error)
Overview(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Comments, *Response, error)
OverviewOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Posts, *Comments, *Response, error)
Posts(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error)
PostsOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Links, *Response, error)
Posts(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error)
PostsOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Posts, *Response, error)
Comments(ctx context.Context, opts ...SearchOptionSetter) (*Comments, *Response, error)
CommentsOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Comments, *Response, error)
Saved(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Comments, *Response, error)
Upvoted(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error)
Downvoted(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)
Saved(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Comments, *Response, error)
Upvoted(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error)
Downvoted(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error)
Hidden(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error)
Gilded(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error)
GetFriendship(ctx context.Context, username string) (*Friendship, *Response, error)
Friend(ctx context.Context, username string) (*Friendship, *Response, error)
@ -44,21 +44,21 @@ type UserService interface {
TrophiesOf(ctx context.Context, username string) (Trophies, *Response, error)
}
// UserServiceOp implements the UserService interface
// UserServiceOp implements the UserService interface.
type UserServiceOp struct {
client *Client
}
var _ UserService = &UserServiceOp{}
// User represents a Reddit user
// User represents a Reddit user.
type User struct {
// this is not the full ID, watch out
// this is not the full ID, watch out.
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Created *Timestamp `json:"created_utc,omitempty"`
LinkKarma int `json:"link_karma"`
PostKarma int `json:"link_karma"`
CommentKarma int `json:"comment_karma"`
IsFriend bool `json:"is_friend"`
@ -68,13 +68,13 @@ type User struct {
IsSuspended bool `json:"is_suspended"`
}
// UserShort represents a Reddit user, but contains fewer pieces of information
// It is returned from the GET /api/user_data_by_account_ids endpoint
// UserShort represents a Reddit user, but
// contains fewer pieces of information.
type UserShort struct {
Name string `json:"name,omitempty"`
Created *Timestamp `json:"created_utc,omitempty"`
LinkKarma int `json:"link_karma"`
PostKarma int `json:"link_karma"`
CommentKarma int `json:"comment_karma"`
NSFW bool `json:"profile_over_18"`
@ -153,7 +153,7 @@ func (t *Trophies) UnmarshalJSON(b []byte) error {
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) {
path := fmt.Sprintf("user/%s/about", username)
req, err := s.client.NewRequest(http.MethodGet, path, nil)
@ -170,7 +170,7 @@ func (s *UserServiceOp) Get(ctx context.Context, username string) (*User, *Respo
return root.Data, resp, nil
}
// GetMultipleByID returns multiple users from their full IDs
// GetMultipleByID returns multiple users from their full IDs.
// The response body is a map where the keys are the IDs (if they exist), and the value is the user
func (s *UserServiceOp) GetMultipleByID(ctx context.Context, ids ...string) (map[string]*UserShort, *Response, error) {
type query struct {
@ -197,8 +197,7 @@ func (s *UserServiceOp) GetMultipleByID(ctx context.Context, ids ...string) (map
return *root, resp, nil
}
// UsernameAvailable checks whether a username is available for registration
// If a valid username is provided, this endpoint returns a body with just "true" or "false"
// UsernameAvailable checks whether a username is available for registration.
func (s *UserServiceOp) UsernameAvailable(ctx context.Context, username string) (bool, *Response, error) {
type query struct {
User string `url:"user,omitempty"`
@ -224,13 +223,13 @@ func (s *UserServiceOp) UsernameAvailable(ctx context.Context, username string)
return *root, resp, nil
}
// Overview returns a list of the client's comments and links
func (s *UserServiceOp) Overview(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Comments, *Response, error) {
// Overview returns a list of the client's posts and comments.
func (s *UserServiceOp) Overview(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Comments, *Response, error) {
return s.OverviewOf(ctx, s.client.Username, opts...)
}
// OverviewOf returns a list of the user's comments and links
func (s *UserServiceOp) OverviewOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Links, *Comments, *Response, error) {
// OverviewOf returns a list of the user's posts and comments.
func (s *UserServiceOp) OverviewOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Posts, *Comments, *Response, error) {
form := newSearchOptions(opts...)
path := fmt.Sprintf("user/%s/overview", username)
@ -247,16 +246,16 @@ func (s *UserServiceOp) OverviewOf(ctx context.Context, username string, opts ..
return nil, nil, resp, err
}
return root.getLinks(), root.getComments(), resp, nil
return root.getPosts(), root.getComments(), resp, nil
}
// Posts returns a list of the client's posts.
func (s *UserServiceOp) Posts(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error) {
func (s *UserServiceOp) Posts(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
return s.PostsOf(ctx, s.client.Username, opts...)
}
// PostsOf returns a list of the user's posts.
func (s *UserServiceOp) PostsOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Links, *Response, error) {
func (s *UserServiceOp) PostsOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
path := fmt.Sprintf("user/%s/submitted", username)
@ -273,7 +272,7 @@ func (s *UserServiceOp) PostsOf(ctx context.Context, username string, opts ...Se
return nil, resp, err
}
return root.getLinks(), resp, nil
return root.getPosts(), resp, nil
}
// Comments returns a list of the client's comments.
@ -303,7 +302,7 @@ func (s *UserServiceOp) CommentsOf(ctx context.Context, username string, opts ..
}
// Saved returns a list of the user's saved posts and comments.
func (s *UserServiceOp) Saved(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Comments, *Response, error) {
func (s *UserServiceOp) Saved(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Comments, *Response, error) {
form := newSearchOptions(opts...)
path := fmt.Sprintf("user/%s/saved", s.client.Username)
@ -320,11 +319,11 @@ func (s *UserServiceOp) Saved(ctx context.Context, opts ...SearchOptionSetter) (
return nil, nil, resp, err
}
return root.getLinks(), root.getComments(), resp, nil
return root.getPosts(), root.getComments(), resp, nil
}
// Upvoted returns a list of the user's upvoted posts.
func (s *UserServiceOp) Upvoted(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error) {
func (s *UserServiceOp) Upvoted(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
path := fmt.Sprintf("user/%s/upvoted", s.client.Username)
@ -341,11 +340,11 @@ func (s *UserServiceOp) Upvoted(ctx context.Context, opts ...SearchOptionSetter)
return nil, resp, err
}
return root.getLinks(), resp, nil
return root.getPosts(), resp, nil
}
// Downvoted returns a list of the user's downvoted posts.
func (s *UserServiceOp) Downvoted(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error) {
func (s *UserServiceOp) Downvoted(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
path := fmt.Sprintf("user/%s/downvoted", s.client.Username)
@ -362,11 +361,11 @@ func (s *UserServiceOp) Downvoted(ctx context.Context, opts ...SearchOptionSette
return nil, resp, err
}
return root.getLinks(), resp, nil
return root.getPosts(), resp, nil
}
// Hidden returns a list of the user's hidden posts.
func (s *UserServiceOp) Hidden(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error) {
func (s *UserServiceOp) Hidden(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
path := fmt.Sprintf("user/%s/hidden", s.client.Username)
@ -383,11 +382,11 @@ func (s *UserServiceOp) Hidden(ctx context.Context, opts ...SearchOptionSetter)
return nil, resp, err
}
return root.getLinks(), resp, nil
return root.getPosts(), resp, nil
}
// Gilded returns a list of the user's gilded posts.
func (s *UserServiceOp) Gilded(ctx context.Context, opts ...SearchOptionSetter) (*Links, *Response, error) {
func (s *UserServiceOp) Gilded(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
path := fmt.Sprintf("user/%s/gilded", s.client.Username)
@ -404,7 +403,7 @@ func (s *UserServiceOp) Gilded(ctx context.Context, opts ...SearchOptionSetter)
return nil, resp, err
}
return root.getLinks(), resp, nil
return root.getPosts(), resp, nil
}
// GetFriendship returns friendship details with the specified user.

View file

@ -16,7 +16,7 @@ var expectedUser = &User{
Name: "Test_User",
Created: &Timestamp{time.Date(2012, 10, 18, 10, 11, 11, 0, time.UTC)},
LinkKarma: 8239,
PostKarma: 8239,
CommentKarma: 130514,
HasVerifiedEmail: true,
@ -26,27 +26,27 @@ var expectedUsers = map[string]*UserShort{
"t2_1": {
Name: "test_user_1",
Created: &Timestamp{time.Date(2017, 3, 12, 2, 1, 47, 0, time.UTC)},
LinkKarma: 488,
PostKarma: 488,
CommentKarma: 22223,
NSFW: false,
},
"t2_2": {
Name: "test_user_2",
Created: &Timestamp{time.Date(2015, 12, 20, 18, 12, 51, 0, time.UTC)},
LinkKarma: 8277,
PostKarma: 8277,
CommentKarma: 131948,
NSFW: false,
},
"t2_3": {
Name: "test_user_3",
Created: &Timestamp{time.Date(2013, 3, 4, 15, 46, 31, 0, time.UTC)},
LinkKarma: 126887,
PostKarma: 126887,
CommentKarma: 81918,
NSFW: true,
},
}
var expectedPost = Link{
var expectedPost = Post{
ID: "gczwql",
FullID: "t3_gczwql",
Created: &Timestamp{time.Date(2020, 5, 3, 22, 46, 25, 0, time.UTC)},
@ -96,11 +96,11 @@ var expectedComment = Comment{
Score: 1,
Controversiality: 0,
LinkID: "t3_d7ejpn",
LinkTitle: "I'm giving away an iPhone 11 Pro to a commenter at random to celebrate Apollo for Reddit's new iOS 13 update and as a thank you to the community! Just leave a comment on this post and the winner will be selected randomly and announced tomorrow at 8 PM GMT. Details inside, and good luck!",
LinkPermalink: "https://www.reddit.com/r/apple/comments/d7ejpn/im_giving_away_an_iphone_11_pro_to_a_commenter_at/",
LinkAuthor: "iamthatis",
LinkNumComments: 89751,
PostID: "t3_d7ejpn",
PostTitle: "I'm giving away an iPhone 11 Pro to a commenter at random to celebrate Apollo for Reddit's new iOS 13 update and as a thank you to the community! Just leave a comment on this post and the winner will be selected randomly and announced tomorrow at 8 PM GMT. Details inside, and good luck!",
PostPermalink: "https://www.reddit.com/r/apple/comments/d7ejpn/im_giving_away_an_iphone_11_pro_to_a_commenter_at/",
PostAuthor: "iamthatis",
PostNumComments: 89751,
}
var expectedFriendship = &Friendship{
@ -200,8 +200,8 @@ func TestUserService_Overview(t *testing.T) {
assert.NotNil(t, posts)
assert.NotNil(t, comments)
assert.Len(t, posts.Links, 1)
assert.Equal(t, expectedPost, posts.Links[0])
assert.Len(t, posts.Posts, 1)
assert.Equal(t, expectedPost, posts.Posts[0])
assert.Equal(t, "t1_f0zsa37", posts.After)
assert.Equal(t, "", posts.Before)
@ -227,8 +227,8 @@ func TestUserService_OverviewOf(t *testing.T) {
assert.NotNil(t, posts)
assert.NotNil(t, comments)
assert.Len(t, posts.Links, 1)
assert.Equal(t, expectedPost, posts.Links[0])
assert.Len(t, posts.Posts, 1)
assert.Equal(t, expectedPost, posts.Posts[0])
assert.Equal(t, "t1_f0zsa37", posts.After)
assert.Equal(t, "", posts.Before)
@ -278,8 +278,8 @@ func TestUserService_Posts(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, posts)
assert.Len(t, posts.Links, 1)
assert.Equal(t, expectedPost, posts.Links[0])
assert.Len(t, posts.Posts, 1)
assert.Equal(t, expectedPost, posts.Posts[0])
assert.Equal(t, "t3_gczwql", posts.After)
assert.Equal(t, "", posts.Before)
}
@ -299,8 +299,8 @@ func TestUserService_PostsOf(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, posts)
assert.Len(t, posts.Links, 1)
assert.Equal(t, expectedPost, posts.Links[0])
assert.Len(t, posts.Posts, 1)
assert.Equal(t, expectedPost, posts.Posts[0])
assert.Equal(t, "t3_gczwql", posts.After)
assert.Equal(t, "", posts.Before)
}
@ -412,8 +412,8 @@ func TestUserService_Saved(t *testing.T) {
assert.NotNil(t, posts)
assert.NotNil(t, comments)
assert.Len(t, posts.Links, 1)
assert.Equal(t, expectedPost, posts.Links[0])
assert.Len(t, posts.Posts, 1)
assert.Equal(t, expectedPost, posts.Posts[0])
assert.Equal(t, "t1_f0zsa37", posts.After)
assert.Equal(t, "", posts.Before)
@ -463,8 +463,8 @@ func TestUserService_Upvoted(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, posts)
assert.Len(t, posts.Links, 1)
assert.Equal(t, expectedPost, posts.Links[0])
assert.Len(t, posts.Posts, 1)
assert.Equal(t, expectedPost, posts.Posts[0])
assert.Equal(t, "t3_gczwql", posts.After)
assert.Equal(t, "", posts.Before)
}
@ -509,8 +509,8 @@ func TestUserService_Downvoted(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, posts)
assert.Len(t, posts.Links, 1)
assert.Equal(t, expectedPost, posts.Links[0])
assert.Len(t, posts.Posts, 1)
assert.Equal(t, expectedPost, posts.Posts[0])
assert.Equal(t, "t3_gczwql", posts.After)
assert.Equal(t, "", posts.Before)
}
@ -556,8 +556,8 @@ func TestUserService_Hidden(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, posts)
assert.Len(t, posts.Links, 1)
assert.Equal(t, expectedPost, posts.Links[0])
assert.Len(t, posts.Posts, 1)
assert.Equal(t, expectedPost, posts.Posts[0])
assert.Equal(t, "t3_gczwql", posts.After)
assert.Equal(t, "", posts.Before)
}
@ -578,8 +578,8 @@ func TestUserService_Gilded(t *testing.T) {
assert.NoError(t, err)
assert.NotNil(t, posts)
assert.Len(t, posts.Links, 1)
assert.Equal(t, expectedPost, posts.Links[0])
assert.Len(t, posts.Posts, 1)
assert.Equal(t, expectedPost, posts.Posts[0])
assert.Equal(t, "t3_gczwql", posts.After)
assert.Equal(t, "", posts.Before)
}

10
vote.go
View file

@ -7,14 +7,14 @@ import (
)
// VoteService handles communication with the upvote/downvote
// related methods of the Reddit API
// related methods of the Reddit API.
type VoteService interface {
Up(ctx context.Context, id string) (*Response, error)
Down(ctx context.Context, id string) (*Response, error)
Remove(ctx context.Context, id string) (*Response, error)
}
// VoteServiceOp implements the Vote interface
// VoteServiceOp implements the Vote interface.
type VoteServiceOp struct {
client *Client
}
@ -46,17 +46,17 @@ func (s *VoteServiceOp) vote(ctx context.Context, id string, vote vote) (*Respon
return s.client.Do(ctx, req, nil)
}
// Up upvotes a link or a comment
// Up upvotes a post or a comment.
func (s *VoteServiceOp) Up(ctx context.Context, id string) (*Response, error) {
return s.vote(ctx, id, upvote)
}
// Down downvotes a link or a comment
// Down downvotes a post or a comment.
func (s *VoteServiceOp) Down(ctx context.Context, id string) (*Response, error) {
return s.vote(ctx, id, downvote)
}
// Remove removes the user's vote on a link or a comment
// Remove removes the user's vote on a post or a comment.
func (s *VoteServiceOp) Remove(ctx context.Context, id string) (*Response, error) {
return s.vote(ctx, id, novote)
}