Use ListOptions for parameters instead of functional options

Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
This commit is contained in:
Vartan Benohanian 2020-08-05 13:25:09 -04:00
parent 23d572046c
commit 23ed51efcc
11 changed files with 325 additions and 307 deletions

View file

@ -27,10 +27,16 @@ func run() (err error) {
client.OnRequestCompleted(logResponse)
client.Subreddit.Search(ctx, "programming", reddit.SetLimit(10))
client.Subreddit.Search(ctx, "programming", nil)
client.Subreddit.SearchNames(ctx, "monitor")
client.Subreddit.SearchPosts(ctx, "react", "webdev", reddit.SortByNumberOfComments)
client.User.Posts(ctx, reddit.SetLimit(50))
client.Subreddit.SearchPosts(ctx, "react", "webdev", nil)
client.User.Posts(ctx, &reddit.ListUserOverviewOptions{
ListOptions: reddit.ListOptions{
Limit: 50,
},
Sort: "top",
Time: "month",
})
return
}

View file

@ -27,7 +27,12 @@ func run() (err error) {
// Let's get the top 200 posts of r/golang.
// Reddit returns a maximum of 100 posts at a time,
// so we'll need to separate this into 2 requests.
result, _, err := client.Subreddit.TopPosts(ctx, "golang", reddit.SetLimit(100), reddit.FromAllTime)
result, _, err := client.Subreddit.TopPosts(ctx, "golang", &reddit.ListPostOptions{
ListOptions: reddit.ListOptions{
Limit: 100,
},
Time: "all",
})
if err != nil {
return
}
@ -38,7 +43,13 @@ func run() (err error) {
// The SetAfter option sets the id of an item that Reddit
// will use as an anchor point for the returned listing.
result, _, err = client.Subreddit.TopPosts(ctx, "golang", reddit.SetLimit(100), reddit.FromAllTime, reddit.SetAfter(result.After))
result, _, err = client.Subreddit.TopPosts(ctx, "golang", &reddit.ListPostOptions{
ListOptions: reddit.ListOptions{
Limit: 100,
After: result.After,
},
Time: "all",
})
if err != nil {
return
}

View file

@ -41,11 +41,36 @@ type ModAction struct {
// GetActions gets a list of moderator actions on a subreddit.
// By default, the limit parameter is 25; max is 500.
func (s *ModerationService) GetActions(ctx context.Context, subreddit string, opts ...SearchOptionSetter) (*ModActions, *Response, error) {
form := newSearchOptions(opts...)
func (s *ModerationService) GetActions(ctx context.Context, subreddit string, opts *ListOptions) (*ModActions, *Response, error) {
return s.GetActionsByType(ctx, subreddit, "", opts)
}
// GetActionsByType gets a list of moderator actions of the specified type on a subreddit.
// By default, the limit parameter is 25; max is 500.
// The type should be one of: banuser, unbanuser, spamlink, removelink, approvelink, spamcomment,
// removecomment, approvecomment, addmoderator, showcomment, invitemoderator, uninvitemoderator,
// acceptmoderatorinvite, removemoderator, addcontributor, removecontributor, editsettings, editflair,
// distinguish, marknsfw, wikibanned, wikicontributor, wikiunbanned, wikipagelisted, removewikicontributor,
// wikirevise, wikipermlevel, ignorereports, unignorereports, setpermissions, setsuggestedsort, sticky,
// unsticky, setcontestmode, unsetcontestmode, lock, unlock, muteuser, unmuteuser, createrule, editrule,
// reorderrules, deleterule, spoiler, unspoiler, modmail_enrollment, community_styling, community_widgets,
// markoriginalcontent, collections, events, hidden_award, add_community_topics, remove_community_topics,
// create_scheduled_post, edit_scheduled_post, delete_scheduled_post, submit_scheduled_post, edit_post_requirements,
// invitesubscriber, submit_content_rating_survey.
func (s *ModerationService) GetActionsByType(ctx context.Context, subreddit string, actionType string, opts *ListOptions) (*ModActions, *Response, error) {
path := fmt.Sprintf("r/%s/about/log", subreddit)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
type params struct {
Type string `url:"type,omitempty"`
}
path, err = addOptions(path, params{actionType})
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -61,22 +86,6 @@ func (s *ModerationService) GetActions(ctx context.Context, subreddit string, op
return root.getModeratorActions(), resp, nil
}
// GetActionsByType gets a list of moderator actions of the specified type on a subreddit.
// By default, the limit parameter is 25; max is 500.
// The type should be one of: banuser, unbanuser, spamlink, removelink, approvelink, spamcomment,
// removecomment, approvecomment, addmoderator, showcomment, invitemoderator, uninvitemoderator,
// acceptmoderatorinvite, removemoderator, addcontributor, removecontributor, editsettings, editflair,
// distinguish, marknsfw, wikibanned, wikicontributor, wikiunbanned, wikipagelisted, removewikicontributor,
// wikirevise, wikipermlevel, ignorereports, unignorereports, setpermissions, setsuggestedsort, sticky,
// unsticky, setcontestmode, unsetcontestmode, lock, unlock, muteuser, unmuteuser, createrule, editrule,
// reorderrules, deleterule, spoiler, unspoiler, modmail_enrollment, community_styling, community_widgets,
// markoriginalcontent, collections, events, hidden_award, add_community_topics, remove_community_topics,
// create_scheduled_post, edit_scheduled_post, delete_scheduled_post, submit_scheduled_post, edit_post_requirements
func (s *ModerationService) GetActionsByType(ctx context.Context, subreddit string, actionType string, opts ...SearchOptionSetter) (*ModActions, *Response, error) {
opts = append(opts, setType(actionType))
return s.GetActions(ctx, subreddit, opts...)
}
// AcceptInvite accepts a pending invite to moderate the specified subreddit.
func (s *ModerationService) AcceptInvite(ctx context.Context, subreddit string) (*Response, error) {
path := fmt.Sprintf("r/%s/api/accept_moderator_invite", subreddit)

View file

@ -61,7 +61,7 @@ func TestModerationService_GetActions(t *testing.T) {
fmt.Fprint(w, blob)
})
result, _, err := client.Moderation.GetActions(ctx, "testsubreddit")
result, _, err := client.Moderation.GetActions(ctx, "testsubreddit", nil)
assert.NoError(t, err)
assert.Equal(t, expectedModActionsResult, result)
}
@ -86,7 +86,7 @@ func TestModerationService_GetActionsByType(t *testing.T) {
fmt.Fprint(w, blob)
})
result, _, err := client.Moderation.GetActionsByType(ctx, "testsubreddit", "testtype")
result, _, err := client.Moderation.GetActionsByType(ctx, "testsubreddit", "testtype", nil)
assert.NoError(t, err)
assert.Equal(t, expectedModActionsResult, result)
}

View file

@ -360,6 +360,68 @@ type ListOptions struct {
Before string `url:"before,omitempty"`
}
// Value returns the value stored in the pointer.
func (o *ListOptions) Value() ListOptions {
if o == nil {
return ListOptions{}
}
return *o
}
// GetLimit returns the limit option.
func (o *ListOptions) GetLimit() int {
if o == nil {
return 0
}
return o.Limit
}
// GetAfter returns the after option.
func (o *ListOptions) GetAfter() string {
if o == nil {
return ""
}
return o.After
}
// GetBefore returns the before option.
func (o *ListOptions) GetBefore() string {
if o == nil {
return ""
}
return o.Before
}
// ListSubredditOptions defines possible options used when searching for subreddits.
type ListSubredditOptions struct {
ListOptions
// One of: relevance, activity.
Sort string `url:"sort,omitempty"`
}
// ListPostOptions defines possible options used when getting posts from a subreddit.
type ListPostOptions struct {
ListOptions
// One of: hour, day, week, month, year, all.
Time string `url:"t,omitempty"`
}
// ListPostSearchOptions defines possible options used when searching for posts within a subreddit.
type ListPostSearchOptions struct {
ListPostOptions
// One of: relevance, hot, top, new, comments.
Sort string `url:"sort,omitempty"`
}
// ListUserOverviewOptions defines possible options used when getting a user's post and/or comments.
type ListUserOverviewOptions struct {
ListOptions
// One of: hot, new, top, controversial.
Sort string `url:"sort,omitempty"`
// One of: hour, day, week, month, year, all.
Time string `url:"t,omitempty"`
}
func addOptions(s string, opt interface{}) (string, error) {
v := reflect.ValueOf(opt)
if v.Kind() == reflect.Ptr && v.IsNil() {

View file

@ -60,6 +60,7 @@ type oauth2Config struct {
}
func oauth2Transport(c oauth2Config) *oauth2.Transport {
// todo: use oauth2.Config.PasswordCredentialsToken
params := url.Values{
"grant_type": {"password"},
"username": {c.username},

148
search.go
View file

@ -1,148 +0,0 @@
package reddit
import (
"fmt"
"net/url"
)
/*
For searches to include NSFW results, the user must
enable the following setting in their preferences:
"include not safe for work (NSFW) search results in searches"
Note: The "limit" parameter in searches is prone to inconsistent
behaviour, e.g. sometimes limit=1 returns nothing when it should.
*/
func newSearchOptions(opts ...SearchOptionSetter) url.Values {
searchOptions := make(url.Values)
for _, opt := range opts {
opt(searchOptions)
}
return searchOptions
}
// SearchOptionSetter sets values for the options.
type SearchOptionSetter func(opts url.Values)
// SetAfter sets the after option.
func SetAfter(v string) SearchOptionSetter {
return func(opts url.Values) {
opts.Set("after", v)
}
}
// SetBefore sets the before option.
func SetBefore(v string) SearchOptionSetter {
return func(opts url.Values) {
opts.Set("before", v)
}
}
// SetLimit sets the limit option.
// Warning: It seems like setting the limit to 1 sometimes returns 0 results.
func SetLimit(v int) SearchOptionSetter {
return func(opts url.Values) {
opts.Set("limit", fmt.Sprint(v))
}
}
// SortByHot sets the sort option to return the hottest results first.
func SortByHot(opts url.Values) {
opts.Set("sort", "hot")
}
// SortByBest sets the sort option to return the best results first.
func SortByBest(opts url.Values) {
opts.Set("sort", "best")
}
// SortByNew sets the sort option to return the newest results first.
func SortByNew(opts url.Values) {
opts.Set("sort", "new")
}
// SortByRising sets the sort option to return the rising results first.
func SortByRising(opts url.Values) {
opts.Set("sort", "rising")
}
// SortByControversial sets the sort option to return the most controversial results first.
func SortByControversial(opts url.Values) {
opts.Set("sort", "controversial")
}
// SortByTop sets the sort option to return the top results first.
func SortByTop(opts url.Values) {
opts.Set("sort", "top")
}
// SortByRelevance sets the sort option to return the most relevant results first.
// This can be used when searching for subreddits and users.
func SortByRelevance(opts url.Values) {
opts.Set("sort", "relevance")
}
// SortByActivity sets the sort option to return results with the most activity first.
// This can be used when searching for subreddits and users.
func SortByActivity(opts url.Values) {
opts.Set("sort", "activity")
}
// SortByNumberOfComments sets the sort option to return the results with the highest
// number of comments first.
// This can be used when searching for posts within a subreddit.
func SortByNumberOfComments(opts url.Values) {
opts.Set("sort", "comments")
}
// FromThePastHour sets the timespan option to return results from the past hour.
func FromThePastHour(opts url.Values) {
opts.Set("t", "hour")
}
// FromThePastDay sets the timespan option to return results from the past day.
func FromThePastDay(opts url.Values) {
opts.Set("t", "day")
}
// FromThePastWeek sets the timespan option to return results from the past week.
func FromThePastWeek(opts url.Values) {
opts.Set("t", "week")
}
// FromThePastMonth sets the timespan option to return results from the past month.
func FromThePastMonth(opts url.Values) {
opts.Set("t", "month")
}
// FromThePastYear sets the timespan option to return results from the past year.
func FromThePastYear(opts url.Values) {
opts.Set("t", "year")
}
// FromAllTime sets the timespan option to return results from all time.
func FromAllTime(opts url.Values) {
opts.Set("t", "all")
}
// setType sets the type option.
// For mod actions, it's for the type of action (e.g. "banuser", "spamcomment").
func setType(v string) SearchOptionSetter {
return func(opts url.Values) {
opts.Set("type", v)
}
}
// setQuery sets the q option.
func setQuery(v string) SearchOptionSetter {
return func(opts url.Values) {
opts.Set("q", v)
}
}
// setRestrict sets the restrict_sr option.
func setRestrict(opts url.Values) {
opts.Set("restrict_sr", "true")
}

View file

@ -40,14 +40,16 @@ type Moderator struct {
Permissions []string `json:"mod_permissions"`
}
func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) {
path := sort
if subreddit != "" {
path = fmt.Sprintf("r/%s/%s", subreddit, sort)
}
form := newSearchOptions(opts...)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -68,36 +70,36 @@ func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit
// If none are defined, it returns the ones from your subscribed subreddits.
// Note: when looking for hot posts in a subreddit, it will include the stickied
// posts (if any) PLUS posts from the limit parameter (25 by default).
func (s *SubredditService) HotPosts(ctx context.Context, subreddit string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
return s.getPosts(ctx, "hot", subreddit, opts...)
func (s *SubredditService) HotPosts(ctx context.Context, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) {
return s.getPosts(ctx, "hot", subreddit, opts)
}
// NewPosts returns the newest posts from the specified subreddit.
// To search through multiple, separate the names with a plus (+), e.g. "golang+test".
// If none are defined, it returns the ones from your subscribed subreddits.
func (s *SubredditService) NewPosts(ctx context.Context, subreddit string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
return s.getPosts(ctx, "new", subreddit, opts...)
func (s *SubredditService) NewPosts(ctx context.Context, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) {
return s.getPosts(ctx, "new", subreddit, opts)
}
// RisingPosts returns the rising posts from the specified subreddit.
// To search through multiple, separate the names with a plus (+), e.g. "golang+test".
// If none are defined, it returns the ones from your subscribed subreddits.
func (s *SubredditService) RisingPosts(ctx context.Context, subreddit string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
return s.getPosts(ctx, "rising", subreddit, opts...)
func (s *SubredditService) RisingPosts(ctx context.Context, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) {
return s.getPosts(ctx, "rising", subreddit, opts)
}
// ControversialPosts returns the most controversial posts from the specified subreddit.
// To search through multiple, separate the names with a plus (+), e.g. "golang+test".
// If none are defined, it returns the ones from your subscribed subreddits.
func (s *SubredditService) ControversialPosts(ctx context.Context, subreddit string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
return s.getPosts(ctx, "controversial", subreddit, opts...)
func (s *SubredditService) ControversialPosts(ctx context.Context, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) {
return s.getPosts(ctx, "controversial", subreddit, opts)
}
// TopPosts returns the top posts from the specified subreddit.
// To search through multiple, separate the names with a plus (+), e.g. "golang+test".
// If none are defined, it returns the ones from your subscribed subreddits.
func (s *SubredditService) TopPosts(ctx context.Context, subreddit string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
return s.getPosts(ctx, "top", subreddit, opts...)
func (s *SubredditService) TopPosts(ctx context.Context, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) {
return s.getPosts(ctx, "top", subreddit, opts)
}
// Get gets a subreddit by name.
@ -122,38 +124,38 @@ func (s *SubredditService) Get(ctx context.Context, name string) (*Subreddit, *R
}
// Popular returns popular subreddits.
func (s *SubredditService) Popular(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error) {
func (s *SubredditService) Popular(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) {
return s.getSubreddits(ctx, "subreddits/popular", opts)
}
// New returns new subreddits.
func (s *SubredditService) New(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error) {
func (s *SubredditService) New(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) {
return s.getSubreddits(ctx, "subreddits/new", opts)
}
// Gold returns gold subreddits (i.e. only accessible to users with gold).
// It seems like it returns an empty list if you don't have gold.
func (s *SubredditService) Gold(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error) {
func (s *SubredditService) Gold(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) {
return s.getSubreddits(ctx, "subreddits/gold", opts)
}
// Default returns default subreddits.
func (s *SubredditService) Default(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error) {
func (s *SubredditService) Default(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) {
return s.getSubreddits(ctx, "subreddits/default", opts)
}
// Subscribed returns the list of subreddits you are subscribed to.
func (s *SubredditService) Subscribed(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error) {
func (s *SubredditService) Subscribed(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) {
return s.getSubreddits(ctx, "subreddits/mine/subscriber", opts)
}
// Approved returns the list of subreddits you are an approved user in.
func (s *SubredditService) Approved(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error) {
func (s *SubredditService) Approved(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) {
return s.getSubreddits(ctx, "subreddits/mine/contributor", opts)
}
// Moderated returns the list of subreddits you are a moderator of.
func (s *SubredditService) Moderated(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error) {
func (s *SubredditService) Moderated(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) {
return s.getSubreddits(ctx, "subreddits/mine/moderator", opts)
}
@ -211,11 +213,21 @@ func (s *SubredditService) UnsubscribeByID(ctx context.Context, ids ...string) (
}
// Search searches for subreddits.
func (s *SubredditService) Search(ctx context.Context, query string, opts ...SearchOptionSetter) (*Subreddits, *Response, error) {
opts = append(opts, setQuery(query))
form := newSearchOptions(opts...)
func (s *SubredditService) Search(ctx context.Context, query string, opts *ListSubredditOptions) (*Subreddits, *Response, error) {
path := "subreddits/search"
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
type params struct {
Query string `url:"q"`
}
path, err = addOptions(path, params{query})
if err != nil {
return nil, nil, err
}
path := addQuery("subreddits/search", form)
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
@ -251,21 +263,27 @@ func (s *SubredditService) SearchNames(ctx context.Context, query string) ([]str
// SearchPosts searches for posts in the specified subreddit.
// To search through multiple, separate the names with a plus (+), e.g. "golang+test".
// If no subreddit is provided, the search is run against r/all.
func (s *SubredditService) SearchPosts(ctx context.Context, query string, subreddit string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
func (s *SubredditService) SearchPosts(ctx context.Context, query string, subreddit string, opts *ListPostSearchOptions) (*Posts, *Response, error) {
if subreddit == "" {
subreddit = "all"
}
notAll := !strings.EqualFold(subreddit, "all")
if notAll {
opts = append(opts, setRestrict)
path := fmt.Sprintf("r/%s/search", subreddit)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
opts = append(opts, setQuery(query))
form := newSearchOptions(opts...)
type params struct {
Query string `url:"q"`
RestrictSubreddits bool `url:"restrict_sr,omitempty"`
}
path := fmt.Sprintf("r/%s/search", subreddit)
path = addQuery(path, form)
notAll := !strings.EqualFold(subreddit, "all")
path, err = addOptions(path, params{query, notAll})
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -281,7 +299,7 @@ func (s *SubredditService) SearchPosts(ctx context.Context, query string, subred
return root.getPosts(), resp, nil
}
func (s *SubredditService) getSubreddits(ctx context.Context, path string, opts *ListOptions) (*Subreddits, *Response, error) {
func (s *SubredditService) getSubreddits(ctx context.Context, path string, opts *ListSubredditOptions) (*Subreddits, *Response, error) {
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err

View file

@ -219,7 +219,7 @@ var expectedRandomSubreddit = &Subreddit{
Subscribers: 52357,
}
func TestSubredditService_Hot(t *testing.T) {
func TestSubredditService_HotPosts(t *testing.T) {
setup()
defer teardown()
@ -231,12 +231,12 @@ func TestSubredditService_Hot(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.Subreddit.HotPosts(ctx, "test")
posts, _, err := client.Subreddit.HotPosts(ctx, "test", nil)
assert.NoError(t, err)
assert.Equal(t, expectedPosts, posts)
}
func TestSubredditService_New(t *testing.T) {
func TestSubredditService_NewPosts(t *testing.T) {
setup()
defer teardown()
@ -248,12 +248,12 @@ func TestSubredditService_New(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.Subreddit.NewPosts(ctx, "test")
posts, _, err := client.Subreddit.NewPosts(ctx, "test", nil)
assert.NoError(t, err)
assert.Equal(t, expectedPosts, posts)
}
func TestSubredditService_Rising(t *testing.T) {
func TestSubredditService_RisingPosts(t *testing.T) {
setup()
defer teardown()
@ -265,12 +265,12 @@ func TestSubredditService_Rising(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.Subreddit.RisingPosts(ctx, "test")
posts, _, err := client.Subreddit.RisingPosts(ctx, "test", nil)
assert.NoError(t, err)
assert.Equal(t, expectedPosts, posts)
}
func TestSubredditService_Controversial(t *testing.T) {
func TestSubredditService_ControversialPosts(t *testing.T) {
setup()
defer teardown()
@ -282,12 +282,12 @@ func TestSubredditService_Controversial(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.Subreddit.ControversialPosts(ctx, "test")
posts, _, err := client.Subreddit.ControversialPosts(ctx, "test", nil)
assert.NoError(t, err)
assert.Equal(t, expectedPosts, posts)
}
func TestSubredditService_Top(t *testing.T) {
func TestSubredditService_TopPosts(t *testing.T) {
setup()
defer teardown()
@ -299,7 +299,7 @@ func TestSubredditService_Top(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.Subreddit.TopPosts(ctx, "test")
posts, _, err := client.Subreddit.TopPosts(ctx, "test", nil)
assert.NoError(t, err)
assert.Equal(t, expectedPosts, posts)
}
@ -324,7 +324,7 @@ func TestSubredditService_Get(t *testing.T) {
assert.Equal(t, expectedSubreddit, subreddit)
}
func TestSubredditService_GetPopular(t *testing.T) {
func TestSubredditService_Popular(t *testing.T) {
setup()
defer teardown()
@ -341,7 +341,7 @@ func TestSubredditService_GetPopular(t *testing.T) {
assert.Equal(t, expectedSubreddits, subreddits)
}
func TestSubredditService_GetNew(t *testing.T) {
func TestSubredditService_New(t *testing.T) {
setup()
defer teardown()
@ -358,7 +358,7 @@ func TestSubredditService_GetNew(t *testing.T) {
assert.Equal(t, expectedSubreddits, subreddits)
}
func TestSubredditService_GetGold(t *testing.T) {
func TestSubredditService_Gold(t *testing.T) {
setup()
defer teardown()
@ -375,7 +375,7 @@ func TestSubredditService_GetGold(t *testing.T) {
assert.Equal(t, expectedSubreddits, subreddits)
}
func TestSubredditService_GetDefault(t *testing.T) {
func TestSubredditService_Default(t *testing.T) {
setup()
defer teardown()
@ -392,7 +392,7 @@ func TestSubredditService_GetDefault(t *testing.T) {
assert.Equal(t, expectedSubreddits, subreddits)
}
func TestSubredditService_GetSubscribed(t *testing.T) {
func TestSubredditService_Subscribed(t *testing.T) {
setup()
defer teardown()
@ -409,7 +409,7 @@ func TestSubredditService_GetSubscribed(t *testing.T) {
assert.Equal(t, expectedSubreddits, subreddits)
}
func TestSubredditService_GetApproved(t *testing.T) {
func TestSubredditService_Approved(t *testing.T) {
setup()
defer teardown()
@ -426,7 +426,7 @@ func TestSubredditService_GetApproved(t *testing.T) {
assert.Equal(t, expectedSubreddits, subreddits)
}
func TestSubredditService_GetModerated(t *testing.T) {
func TestSubredditService_Moderated(t *testing.T) {
setup()
defer teardown()
@ -579,6 +579,8 @@ func TestSubredditService_Search(t *testing.T) {
form := url.Values{}
form.Set("q", "golang")
form.Set("limit", "10")
form.Set("sort", "activity")
err := r.ParseForm()
assert.NoError(t, err)
@ -587,7 +589,12 @@ func TestSubredditService_Search(t *testing.T) {
fmt.Fprint(w, blob)
})
subreddits, _, err := client.Subreddit.Search(ctx, "golang")
subreddits, _, err := client.Subreddit.Search(ctx, "golang", &ListSubredditOptions{
ListOptions: ListOptions{
Limit: 10,
},
Sort: "activity",
})
assert.NoError(t, err)
assert.Equal(t, expectedSubreddits, subreddits)
}
@ -629,7 +636,6 @@ func TestSubredditService_SearchPosts(t *testing.T) {
form := url.Values{}
form.Set("q", "test")
form.Set("after", "t3_testpost")
err := r.ParseForm()
assert.NoError(t, err)
@ -638,7 +644,7 @@ func TestSubredditService_SearchPosts(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.Subreddit.SearchPosts(ctx, "test", "", SetAfter("t3_testpost"))
posts, _, err := client.Subreddit.SearchPosts(ctx, "test", "", nil)
assert.NoError(t, err)
assert.Equal(t, expectedSearchPosts, posts)
}
@ -656,7 +662,6 @@ func TestSubredditService_SearchPosts_InSubreddit(t *testing.T) {
form := url.Values{}
form.Set("q", "test")
form.Set("restrict_sr", "true")
form.Set("after", "t3_testpost")
err := r.ParseForm()
assert.NoError(t, err)
@ -665,7 +670,7 @@ func TestSubredditService_SearchPosts_InSubreddit(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.Subreddit.SearchPosts(ctx, "test", "test", SetAfter("t3_testpost"))
posts, _, err := client.Subreddit.SearchPosts(ctx, "test", "test", nil)
assert.NoError(t, err)
assert.Equal(t, expectedSearchPosts, posts)
}
@ -683,7 +688,6 @@ func TestSubredditService_SearchPosts_InSubreddits(t *testing.T) {
form := url.Values{}
form.Set("q", "test")
form.Set("restrict_sr", "true")
form.Set("after", "t3_testpost")
err := r.ParseForm()
assert.NoError(t, err)
@ -692,7 +696,7 @@ func TestSubredditService_SearchPosts_InSubreddits(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.Subreddit.SearchPosts(ctx, "test", "test+golang+nba", SetAfter("t3_testpost"))
posts, _, err := client.Subreddit.SearchPosts(ctx, "test", "test+golang+nba", nil)
assert.NoError(t, err)
assert.Equal(t, expectedSearchPosts, posts)
}

132
user.go
View file

@ -154,16 +154,17 @@ func (s *UserService) UsernameAvailable(ctx context.Context, username string) (b
}
// Overview returns a list of your posts and comments.
func (s *UserService) Overview(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Comments, *Response, error) {
return s.OverviewOf(ctx, s.client.Username, opts...)
func (s *UserService) Overview(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Comments, *Response, error) {
return s.OverviewOf(ctx, s.client.Username, opts)
}
// OverviewOf returns a list of the user's posts and comments.
func (s *UserService) OverviewOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Posts, *Comments, *Response, error) {
form := newSearchOptions(opts...)
func (s *UserService) OverviewOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Posts, *Comments, *Response, error) {
path := fmt.Sprintf("user/%s/overview", username)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -180,16 +181,17 @@ func (s *UserService) OverviewOf(ctx context.Context, username string, opts ...S
}
// Posts returns a list of your posts.
func (s *UserService) Posts(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
return s.PostsOf(ctx, s.client.Username, opts...)
func (s *UserService) Posts(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) {
return s.PostsOf(ctx, s.client.Username, opts)
}
// PostsOf returns a list of the user's posts.
func (s *UserService) PostsOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
func (s *UserService) PostsOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Posts, *Response, error) {
path := fmt.Sprintf("user/%s/submitted", username)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -206,16 +208,17 @@ func (s *UserService) PostsOf(ctx context.Context, username string, opts ...Sear
}
// Comments returns a list of your comments.
func (s *UserService) Comments(ctx context.Context, opts ...SearchOptionSetter) (*Comments, *Response, error) {
return s.CommentsOf(ctx, s.client.Username, opts...)
func (s *UserService) Comments(ctx context.Context, opts *ListUserOverviewOptions) (*Comments, *Response, error) {
return s.CommentsOf(ctx, s.client.Username, opts)
}
// CommentsOf returns a list of the user's comments.
func (s *UserService) CommentsOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Comments, *Response, error) {
form := newSearchOptions(opts...)
func (s *UserService) CommentsOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Comments, *Response, error) {
path := fmt.Sprintf("user/%s/comments", username)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -232,11 +235,12 @@ func (s *UserService) CommentsOf(ctx context.Context, username string, opts ...S
}
// Saved returns a list of the user's saved posts and comments.
func (s *UserService) Saved(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Comments, *Response, error) {
form := newSearchOptions(opts...)
func (s *UserService) Saved(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Comments, *Response, error) {
path := fmt.Sprintf("user/%s/saved", s.client.Username)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -253,17 +257,18 @@ func (s *UserService) Saved(ctx context.Context, opts ...SearchOptionSetter) (*P
}
// Upvoted returns a list of your upvoted posts.
func (s *UserService) Upvoted(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
return s.UpvotedOf(ctx, s.client.Username, opts...)
func (s *UserService) Upvoted(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) {
return s.UpvotedOf(ctx, s.client.Username, opts)
}
// UpvotedOf returns a list of the user's upvoted posts.
// The user's votes must be public for this to work.
func (s *UserService) UpvotedOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
// The user's votes must be public for this to work (unless the user is you).
func (s *UserService) UpvotedOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Posts, *Response, error) {
path := fmt.Sprintf("user/%s/upvoted", username)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -280,17 +285,18 @@ func (s *UserService) UpvotedOf(ctx context.Context, username string, opts ...Se
}
// Downvoted returns a list of your downvoted posts.
func (s *UserService) Downvoted(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
return s.DownvotedOf(ctx, s.client.Username, opts...)
func (s *UserService) Downvoted(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) {
return s.DownvotedOf(ctx, s.client.Username, opts)
}
// DownvotedOf returns a list of the user's downvoted posts.
// The user's votes must be public for this to work.
func (s *UserService) DownvotedOf(ctx context.Context, username string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
// The user's votes must be public for this to work (unless the user is you).
func (s *UserService) DownvotedOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Posts, *Response, error) {
path := fmt.Sprintf("user/%s/downvoted", username)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -307,11 +313,12 @@ func (s *UserService) DownvotedOf(ctx context.Context, username string, opts ...
}
// Hidden returns a list of the user's hidden posts.
func (s *UserService) Hidden(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
func (s *UserService) Hidden(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) {
path := fmt.Sprintf("user/%s/hidden", s.client.Username)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -328,11 +335,12 @@ func (s *UserService) Hidden(ctx context.Context, opts ...SearchOptionSetter) (*
}
// Gilded returns a list of the user's gilded posts.
func (s *UserService) Gilded(ctx context.Context, opts ...SearchOptionSetter) (*Posts, *Response, error) {
form := newSearchOptions(opts...)
func (s *UserService) Gilded(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) {
path := fmt.Sprintf("user/%s/gilded", s.client.Username)
path = addQuery(path, form)
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -517,9 +525,12 @@ func (s *UserService) TrophiesOf(ctx context.Context, username string) ([]Trophy
}
// Popular gets the user subreddits with the most activity.
func (s *UserService) Popular(ctx context.Context, opts ...SearchOptionSetter) (*Subreddits, *Response, error) {
form := newSearchOptions(opts...)
path := addQuery("users/popular", form)
func (s *UserService) Popular(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error) {
path := "users/popular"
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -536,9 +547,12 @@ func (s *UserService) Popular(ctx context.Context, opts ...SearchOptionSetter) (
}
// New gets the most recently created user subreddits.
func (s *UserService) New(ctx context.Context, opts ...SearchOptionSetter) (*Subreddits, *Response, error) {
form := newSearchOptions(opts...)
path := addQuery("users/new", form)
func (s *UserService) New(ctx context.Context, opts *ListUserOverviewOptions) (*Subreddits, *Response, error) {
path := "users/new"
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
@ -555,11 +569,21 @@ func (s *UserService) New(ctx context.Context, opts ...SearchOptionSetter) (*Sub
}
// Search searches for users.
func (s *UserService) Search(ctx context.Context, query string, opts ...SearchOptionSetter) (*Users, *Response, error) {
opts = append(opts, setQuery(query))
form := newSearchOptions(opts...)
// todo: maybe include the sort option? (relevance, activity)
func (s *UserService) Search(ctx context.Context, query string, opts *ListOptions) (*Users, *Response, error) {
path := "users/search"
path, err := addOptions(path, opts)
if err != nil {
return nil, nil, err
}
path := addQuery("users/search", form)
type params struct {
Query string `url:"q"`
}
path, err = addOptions(path, params{query})
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {

View file

@ -263,7 +263,7 @@ func TestUserService_Overview(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, comments, _, err := client.User.Overview(ctx)
posts, comments, _, err := client.User.Overview(ctx, nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -289,7 +289,7 @@ func TestUserService_OverviewOf(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, comments, _, err := client.User.OverviewOf(ctx, "user2")
posts, comments, _, err := client.User.OverviewOf(ctx, "user2", nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -325,7 +325,13 @@ func TestUserService_Overview_Options(t *testing.T) {
fmt.Fprint(w, blob)
})
_, _, _, err = client.User.Overview(ctx, SetLimit(5), SetAfter("t3_after"), SortByTop)
_, _, _, err = client.User.Overview(ctx, &ListUserOverviewOptions{
ListOptions: ListOptions{
Limit: 5,
After: "t3_after",
},
Sort: "top",
})
assert.NoError(t, err)
}
@ -341,7 +347,7 @@ func TestUserService_Posts(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.User.Posts(ctx)
posts, _, err := client.User.Posts(ctx, nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -362,7 +368,7 @@ func TestUserService_PostsOf(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.User.PostsOf(ctx, "user2")
posts, _, err := client.User.PostsOf(ctx, "user2", nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -392,7 +398,12 @@ func TestUserService_Posts_Options(t *testing.T) {
fmt.Fprint(w, blob)
})
_, _, err = client.User.Posts(ctx, SetLimit(10), SortByNew)
_, _, err = client.User.Posts(ctx, &ListUserOverviewOptions{
ListOptions: ListOptions{
Limit: 10,
},
Sort: "new",
})
assert.NoError(t, err)
}
@ -408,7 +419,7 @@ func TestUserService_Comments(t *testing.T) {
fmt.Fprint(w, blob)
})
comments, _, err := client.User.Comments(ctx)
comments, _, err := client.User.Comments(ctx, nil)
assert.NoError(t, err)
assert.Len(t, comments.Comments, 1)
@ -429,7 +440,7 @@ func TestUserService_CommentsOf(t *testing.T) {
fmt.Fprint(w, blob)
})
comments, _, err := client.User.CommentsOf(ctx, "user2")
comments, _, err := client.User.CommentsOf(ctx, "user2", nil)
assert.NoError(t, err)
assert.Len(t, comments.Comments, 1)
@ -459,7 +470,12 @@ func TestUserService_Comments_Options(t *testing.T) {
fmt.Fprint(w, blob)
})
_, _, err = client.User.Comments(ctx, SetLimit(100), SetBefore("t1_before"))
_, _, err = client.User.Comments(ctx, &ListUserOverviewOptions{
ListOptions: ListOptions{
Limit: 100,
Before: "t1_before",
},
})
assert.NoError(t, err)
}
@ -476,7 +492,7 @@ func TestUserService_Saved(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, comments, _, err := client.User.Saved(ctx)
posts, comments, _, err := client.User.Saved(ctx, nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -512,7 +528,12 @@ func TestUserService_Saved_Options(t *testing.T) {
fmt.Fprint(w, blob)
})
_, _, _, err = client.User.Saved(ctx, SetLimit(50), SortByControversial)
_, _, _, err = client.User.Saved(ctx, &ListUserOverviewOptions{
ListOptions: ListOptions{
Limit: 50,
},
Sort: "controversial",
})
assert.NoError(t, err)
}
func TestUserService_Upvoted(t *testing.T) {
@ -528,7 +549,7 @@ func TestUserService_Upvoted(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.User.Upvoted(ctx)
posts, _, err := client.User.Upvoted(ctx, nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -559,7 +580,12 @@ func TestUserService_Upvoted_Options(t *testing.T) {
fmt.Fprint(w, blob)
})
_, _, err = client.User.Upvoted(ctx, SetLimit(30), SetAfter("t3_after"))
_, _, err = client.User.Upvoted(ctx, &ListUserOverviewOptions{
ListOptions: ListOptions{
Limit: 30,
After: "t3_after",
},
})
assert.NoError(t, err)
}
@ -576,7 +602,7 @@ func TestUserService_UpvotedOf(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.User.UpvotedOf(ctx, "user2")
posts, _, err := client.User.UpvotedOf(ctx, "user2", nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -598,7 +624,7 @@ func TestUserService_Downvoted(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.User.Downvoted(ctx)
posts, _, err := client.User.Downvoted(ctx, nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -629,7 +655,12 @@ func TestUserService_Downvoted_Options(t *testing.T) {
fmt.Fprint(w, blob)
})
_, _, err = client.User.Downvoted(ctx, SetLimit(20), SetBefore("t3_before"))
_, _, err = client.User.Downvoted(ctx, &ListUserOverviewOptions{
ListOptions: ListOptions{
Limit: 20,
Before: "t3_before",
},
})
assert.NoError(t, err)
}
@ -646,7 +677,7 @@ func TestUserService_DownvotedOf(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.User.DownvotedOf(ctx, "user2")
posts, _, err := client.User.DownvotedOf(ctx, "user2", nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -668,7 +699,7 @@ func TestUserService_Hidden(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.User.Hidden(ctx)
posts, _, err := client.User.Hidden(ctx, nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -690,7 +721,7 @@ func TestUserService_Gilded(t *testing.T) {
fmt.Fprint(w, blob)
})
posts, _, err := client.User.Gilded(ctx)
posts, _, err := client.User.Gilded(ctx, nil)
assert.NoError(t, err)
assert.Len(t, posts.Posts, 1)
@ -899,7 +930,7 @@ func TestUserService_Popular(t *testing.T) {
fmt.Fprint(w, blob)
})
userSubreddits, _, err := client.User.Popular(ctx)
userSubreddits, _, err := client.User.Popular(ctx, nil)
assert.NoError(t, err)
assert.Equal(t, expectedUserSubreddits, userSubreddits)
}
@ -916,7 +947,7 @@ func TestUserService_New(t *testing.T) {
fmt.Fprint(w, blob)
})
userSubreddits, _, err := client.User.New(ctx)
userSubreddits, _, err := client.User.New(ctx, nil)
assert.NoError(t, err)
assert.Equal(t, expectedUserSubreddits, userSubreddits)
}
@ -941,7 +972,7 @@ func TestUserService_Search(t *testing.T) {
fmt.Fprint(w, blob)
})
users, _, err := client.User.Search(ctx, "test")
users, _, err := client.User.Search(ctx, "test", nil)
assert.NoError(t, err)
assert.Equal(t, expectedSearchUsers, users)
}