From eda947f6b5240e1941515f28ca92438a634457b8 Mon Sep 17 00:00:00 2001 From: Vartan Benohanian Date: Sat, 16 May 2020 21:46:16 -0400 Subject: [PATCH] Use method chaining for searches Signed-off-by: Vartan Benohanian --- search.go | 328 ++++++++++++++++++++++++--------------------------- subreddit.go | 71 +++++++++-- things.go | 66 ++++++++--- user.go | 16 +-- 4 files changed, 278 insertions(+), 203 deletions(-) diff --git a/search.go b/search.go index 3e24d29..0989997 100644 --- a/search.go +++ b/search.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "net/http" + "strings" ) // SearchService handles communication with the search @@ -12,20 +13,9 @@ import ( // user must check the following in their preferences: // "include not safe for work (NSFW) search results in searches" type SearchService interface { - Users(ctx context.Context, q string, opts *ListOptions) (*Users, *Response, error) - - LinksByRelevance(ctx context.Context, q string, opts *ListOptions) (*Links, *Response, error) - LinksByHottest(ctx context.Context, q string, opts *ListOptions) (*Links, *Response, error) - LinksByTop(ctx context.Context, q string, opts *ListOptions) (*Links, *Response, error) - LinksByComments(ctx context.Context, q string, opts *ListOptions) (*Links, *Response, error) - LinksByRelevanceInSubreddit(ctx context.Context, subreddit, q string, opts *ListOptions) (*Links, *Response, error) - LinksByHottestInSubreddit(ctx context.Context, subreddit, q string, opts *ListOptions) (*Links, *Response, error) - LinksByTopInSubreddit(ctx context.Context, subreddit, q string, opts *ListOptions) (*Links, *Response, error) - LinksByCommentsInSubreddit(ctx context.Context, subreddit, q string, opts *ListOptions) (*Links, *Response, error) - - Subreddits(ctx context.Context, q string, opts *ListOptions) (*Subreddits, *Response, error) - SubredditNames(ctx context.Context, q string) ([]string, *Response, error) - SubredditInfo(ctx context.Context, q string) ([]SubredditShort, *Response, error) + Posts(query string) *PostSearchBuilder + Subreddits(query string) *SubredditSearchBuilder + Users(query string) *UserSearchBuilder } // SearchServiceOp implements the VoteService interface @@ -35,153 +25,161 @@ type SearchServiceOp struct { var _ SearchService = &SearchServiceOp{} -type searchQuery struct { - ListOptions - Query string `url:"q,omitempty"` - Type string `url:"type,omitempty"` - Sort string `url:"sort,omitempty"` +// Posts searches for posts. +// By default, it searches for the most relevant posts of all time. +// To change the sorting, use PostSearchBuilder.Sort(). +// Possible sort options: relevance, hot, top, new, comments. +// To change the timespan, use PostSearchBuilder.Timespan(). +// Possible timespan options: hour, day, week, month, year, all. +func (s *SearchServiceOp) Posts(query string) *PostSearchBuilder { + b := new(PostSearchBuilder) + b.client = s.client + b.opts.Query = query + b.opts.Type = "link" + b.opts.Sort = SortRelevance.String() + b.opts.Timespan = TimespanAll.String() + return b } -type subredditNamesRoot struct { - Names []string `json:"names,omitempty"` +// Subreddits searches for subreddits. +func (s *SearchServiceOp) Subreddits(query string) *SubredditSearchBuilder { + b := new(SubredditSearchBuilder) + b.client = s.client + b.opts.Query = query + b.opts.Type = "sr" + return b } -type subredditShortsRoot struct { - Subreddits []SubredditShort `json:"subreddits,omitempty"` +// Users searches for users. +func (s *SearchServiceOp) Users(query string) *UserSearchBuilder { + b := new(UserSearchBuilder) + b.client = s.client + b.opts.Query = query + b.opts.Type = "user" + return b } -// SubredditShort represents minimal information about a subreddit -type SubredditShort struct { - Name string `json:"name,omitempty"` - Subscribers int `json:"subscriber_count"` - ActiveUsers int `json:"active_user_count"` +type searchOpts struct { + Query string `url:"q"` + Type string `url:"type,omitempty"` + After string `url:"after,omitempty"` + Before string `url:"before,omitempty"` + Limit int `url:"limit,omitempty"` + RestrictSubreddits bool `url:"restrict_sr,omitempty"` + Sort string `url:"sort,omitempty"` + Timespan string `url:"t,omitempty"` } -func newSearchQuery(query, _type, sort string, opts *ListOptions) *searchQuery { - if opts == nil { - opts = &ListOptions{} +// PostSearchBuilder helps conducts searches that return posts. +type PostSearchBuilder struct { + client *Client + subreddits []string + opts searchOpts +} + +// After sets the after option. +func (b *PostSearchBuilder) After(after string) *PostSearchBuilder { + b.opts.After = after + return b +} + +// Before sets the before option. +func (b *PostSearchBuilder) Before(before string) *PostSearchBuilder { + b.opts.Before = before + return b +} + +// Limit sets the limit option. +func (b *PostSearchBuilder) Limit(limit int) *PostSearchBuilder { + b.opts.Limit = limit + return b +} + +// InSubreddits restricts the search to happen in the specified subreddits only. +// If none are set, the search is run against r/all. +func (b *PostSearchBuilder) InSubreddits(subreddits ...string) *PostSearchBuilder { + b.subreddits = subreddits + b.opts.RestrictSubreddits = len(subreddits) > 0 + return b +} + +// Sort sets the sort option. +func (b *PostSearchBuilder) Sort(sort Sort) *PostSearchBuilder { + b.opts.Sort = sort.String() + return b +} + +// Timespan sets the timespan option. +func (b *PostSearchBuilder) Timespan(timespan Timespan) *PostSearchBuilder { + b.opts.Timespan = timespan.String() + return b +} + +// Do conducts the search. +func (b *PostSearchBuilder) Do(ctx context.Context) (*Links, *Response, error) { + path := "search" + if len(b.subreddits) > 0 { + path = fmt.Sprintf("r/%s/search", strings.Join(b.subreddits, "+")) } - return &searchQuery{ - ListOptions: *opts, - Query: query, - Type: _type, - Sort: sort, - } -} -// Users searches for users -func (s *SearchServiceOp) Users(ctx context.Context, q string, opts *ListOptions) (*Users, *Response, error) { - query := newSearchQuery(q, "user", "", opts) - - root, resp, err := s.search(ctx, "", query) + path, err := addOptions(path, b.opts) if err != nil { return nil, nil, err } - return root.getUsers(), resp, nil -} - -// LinksByRelevance searches for links sorted by relevance to the search query in all of Reddit -func (s *SearchServiceOp) LinksByRelevance(ctx context.Context, q string, opts *ListOptions) (*Links, *Response, error) { - query := newSearchQuery(q, "link", sorts[sortRelevance], opts) - - root, resp, err := s.search(ctx, "", query) + req, err := b.client.NewRequest(http.MethodGet, path, nil) if err != nil { return nil, nil, err } + root := new(rootListing) + resp, err := b.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.getLinks(), resp, nil } -// LinksByHottest searches for the hottest links in all of Reddit -func (s *SearchServiceOp) LinksByHottest(ctx context.Context, q string, opts *ListOptions) (*Links, *Response, error) { - query := newSearchQuery(q, "link", sorts[sortHot], opts) +// SubredditSearchBuilder helps conducts searches that return subreddits. +type SubredditSearchBuilder struct { + client *Client + opts searchOpts +} - root, resp, err := s.search(ctx, "", query) +// After sets the after option. +func (b *SubredditSearchBuilder) After(after string) *SubredditSearchBuilder { + b.opts.After = after + return b +} + +// Before sets the before option. +func (b *SubredditSearchBuilder) Before(before string) *SubredditSearchBuilder { + b.opts.Before = before + return b +} + +// Limit sets the limit option. +func (b *SubredditSearchBuilder) Limit(limit int) *SubredditSearchBuilder { + b.opts.Limit = limit + return b +} + +// Do conducts the search. +func (b *SubredditSearchBuilder) Do(ctx context.Context) (*Subreddits, *Response, error) { + path := "search" + path, err := addOptions(path, b.opts) if err != nil { return nil, nil, err } - return root.getLinks(), resp, nil -} - -// LinksByTop searches for the top links in all of Reddit -func (s *SearchServiceOp) LinksByTop(ctx context.Context, q string, opts *ListOptions) (*Links, *Response, error) { - query := newSearchQuery(q, "link", sorts[sortTop], opts) - - root, resp, err := s.search(ctx, "", query) + req, err := b.client.NewRequest(http.MethodGet, path, nil) if err != nil { return nil, nil, err } - return root.getLinks(), resp, nil -} - -// LinksByComments searches for links with the highest number of comments in all of Reddit -func (s *SearchServiceOp) LinksByComments(ctx context.Context, q string, opts *ListOptions) (*Links, *Response, error) { - query := newSearchQuery(q, "link", sorts[sortComments], opts) - - root, resp, err := s.search(ctx, "", query) - if err != nil { - return nil, nil, err - } - - return root.getLinks(), resp, nil -} - -// LinksByRelevanceInSubreddit searches for link sorted by relevance to the search query in the specified subreddit -func (s *SearchServiceOp) LinksByRelevanceInSubreddit(ctx context.Context, subreddit, q string, opts *ListOptions) (*Links, *Response, error) { - query := newSearchQuery(q, "link", sorts[sortRelevance], opts) - - root, resp, err := s.search(ctx, subreddit, query) - if err != nil { - return nil, nil, err - } - - return root.getLinks(), resp, nil -} - -// LinksByHottestInSubreddit searches for the hottest links in the specified subreddit -func (s *SearchServiceOp) LinksByHottestInSubreddit(ctx context.Context, subreddit, q string, opts *ListOptions) (*Links, *Response, error) { - query := newSearchQuery(q, "link", sorts[sortHot], opts) - - root, resp, err := s.search(ctx, subreddit, query) - if err != nil { - return nil, nil, err - } - - return root.getLinks(), resp, nil -} - -// LinksByTopInSubreddit searches for the top links in the specified subreddit -func (s *SearchServiceOp) LinksByTopInSubreddit(ctx context.Context, subreddit, q string, opts *ListOptions) (*Links, *Response, error) { - query := newSearchQuery(q, "link", sorts[sortTop], opts) - - root, resp, err := s.search(ctx, subreddit, query) - if err != nil { - return nil, nil, err - } - - return root.getLinks(), resp, nil -} - -// LinksByCommentsInSubreddit searches for links with the highest number of comments in the specified subreddit -func (s *SearchServiceOp) LinksByCommentsInSubreddit(ctx context.Context, subreddit, q string, opts *ListOptions) (*Links, *Response, error) { - query := newSearchQuery(q, "link", sorts[sortComments], opts) - - root, resp, err := s.search(ctx, subreddit, query) - if err != nil { - return nil, nil, err - } - - return root.getLinks(), resp, nil -} - -// Subreddits searches for subreddits -func (s *SearchServiceOp) Subreddits(ctx context.Context, q string, opts *ListOptions) (*Subreddits, *Response, error) { - query := newSearchQuery(q, "sr", "", opts) - - root, resp, err := s.search(ctx, "", query) + root := new(rootListing) + resp, err := b.client.Do(ctx, req, root) if err != nil { return nil, resp, err } @@ -189,64 +187,48 @@ func (s *SearchServiceOp) Subreddits(ctx context.Context, q string, opts *ListOp return root.getSubreddits(), resp, nil } -// SubredditNames searches for subreddits with names beginning with the query provided -func (s *SearchServiceOp) SubredditNames(ctx context.Context, q string) ([]string, *Response, error) { - path := fmt.Sprintf("api/search_reddit_names?query=%s", q) - - req, err := s.client.NewRequest(http.MethodGet, path, nil) - if err != nil { - return nil, nil, err - } - - root := new(subredditNamesRoot) - resp, err := s.client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - - return root.Names, resp, nil +// UserSearchBuilder helps conducts searches that return posts. +type UserSearchBuilder struct { + client *Client + opts searchOpts } -// SubredditInfo searches for subreddits with names beginning with the query provided -// They hold a bit more info that just the name -func (s *SearchServiceOp) SubredditInfo(ctx context.Context, q string) ([]SubredditShort, *Response, error) { - path := fmt.Sprintf("api/search_subreddits?query=%s", q) - - req, err := s.client.NewRequest(http.MethodPost, path, nil) - if err != nil { - return nil, nil, err - } - - root := new(subredditShortsRoot) - resp, err := s.client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - - return root.Subreddits, resp, nil +// After sets the after option. +func (b *UserSearchBuilder) After(after string) *UserSearchBuilder { + b.opts.After = after + return b } -func (s *SearchServiceOp) search(ctx context.Context, subreddit string, opts *searchQuery) (*rootListing, *Response, error) { +// Before sets the before option. +func (b *UserSearchBuilder) Before(before string) *UserSearchBuilder { + b.opts.Before = before + return b +} + +// Limit sets the limit option. +func (b *UserSearchBuilder) Limit(limit int) *UserSearchBuilder { + b.opts.Limit = limit + return b +} + +// Do conducts the search. +func (b *UserSearchBuilder) Do(ctx context.Context) (*Users, *Response, error) { path := "search" - if subreddit != "" { - path = fmt.Sprintf("r/%s/search?restrict_sr=true", subreddit) - } - - path, err := addOptions(path, opts) + path, err := addOptions(path, b.opts) if err != nil { return nil, nil, err } - req, err := s.client.NewRequest(http.MethodGet, path, nil) + req, err := b.client.NewRequest(http.MethodGet, path, nil) if err != nil { return nil, nil, err } root := new(rootListing) - resp, err := s.client.Do(ctx, req, root) + resp, err := b.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root, resp, nil + return root.getUsers(), resp, nil } diff --git a/subreddit.go b/subreddit.go index c35254e..4615a54 100644 --- a/subreddit.go +++ b/subreddit.go @@ -38,6 +38,9 @@ type SubredditService interface { SubscribeByID(ctx context.Context, ids ...string) (*Response, error) Unsubscribe(ctx context.Context, subreddits ...string) (*Response, error) UnsubscribeByID(ctx context.Context, ids ...string) (*Response, error) + + SearchSubredditNames(ctx context.Context, query string) ([]string, *Response, error) + SearchSubredditInfo(ctx context.Context, query string) ([]SubredditShort, *Response, error) } // SubredditServiceOp implements the SubredditService interface @@ -47,6 +50,21 @@ type SubredditServiceOp struct { var _ SubredditService = &SubredditServiceOp{} +type subredditNamesRoot struct { + Names []string `json:"names,omitempty"` +} + +type subredditShortsRoot struct { + Subreddits []SubredditShort `json:"subreddits,omitempty"` +} + +// SubredditShort represents minimal information about a subreddit +type SubredditShort struct { + Name string `json:"name,omitempty"` + Subscribers int `json:"subscriber_count"` + ActiveUsers int `json:"active_user_count"` +} + // GetByName gets a subreddit by name func (s *SubredditServiceOp) GetByName(ctx context.Context, subreddit string) (*Subreddit, *Response, error) { if subreddit == "" { @@ -113,7 +131,7 @@ func (s *SubredditServiceOp) GetMineWhereStreams(ctx context.Context, opts *List // IMPORTANT: for subreddits, this will include the stickied posts (if any) // PLUS the number of posts from the limit parameter (which is 25 by default) func (s *SubredditServiceOp) GetHotLinks(ctx context.Context, opts *ListOptions, subreddits ...string) (*Links, *Response, error) { - return s.getLinks(ctx, sortHot, opts, subreddits...) + return s.getLinks(ctx, SortHot, opts, subreddits...) } // GetBestLinks returns the best links @@ -121,31 +139,31 @@ func (s *SubredditServiceOp) GetHotLinks(ctx context.Context, opts *ListOptions, // IMPORTANT: for subreddits, this will include the stickied posts (if any) // PLUS the number of posts from the limit parameter (which is 25 by default) func (s *SubredditServiceOp) GetBestLinks(ctx context.Context, opts *ListOptions, subreddits ...string) (*Links, *Response, error) { - return s.getLinks(ctx, sortBest, opts, subreddits...) + return s.getLinks(ctx, SortBest, opts, subreddits...) } // GetNewLinks returns the new links // If no subreddit are provided, then it runs the search against all those the client is subscribed to func (s *SubredditServiceOp) GetNewLinks(ctx context.Context, opts *ListOptions, subreddits ...string) (*Links, *Response, error) { - return s.getLinks(ctx, sortNew, opts, subreddits...) + return s.getLinks(ctx, SortNew, opts, subreddits...) } // GetRisingLinks returns the rising links // If no subreddit are provided, then it runs the search against all those the client is subscribed to func (s *SubredditServiceOp) GetRisingLinks(ctx context.Context, opts *ListOptions, subreddits ...string) (*Links, *Response, error) { - return s.getLinks(ctx, sortRising, opts, subreddits...) + return s.getLinks(ctx, SortRising, opts, subreddits...) } // GetControversialLinks returns the controversial links // If no subreddit are provided, then it runs the search against all those the client is subscribed to func (s *SubredditServiceOp) GetControversialLinks(ctx context.Context, opts *ListOptions, subreddits ...string) (*Links, *Response, error) { - return s.getLinks(ctx, sortControversial, opts, subreddits...) + return s.getLinks(ctx, SortControversial, opts, subreddits...) } // GetTopLinks returns the top links // If no subreddit are provided, then it runs the search against all those the client is subscribed to func (s *SubredditServiceOp) GetTopLinks(ctx context.Context, opts *ListOptions, subreddits ...string) (*Links, *Response, error) { - return s.getLinks(ctx, sortTop, opts, subreddits...) + return s.getLinks(ctx, SortTop, opts, subreddits...) } // GetSticky1 returns the first stickied post on a subreddit (if it exists) @@ -194,6 +212,43 @@ func (s *SubredditServiceOp) UnsubscribeByID(ctx context.Context, ids ...string) return s.handleSubscription(ctx, form) } +// SearchSubredditNames searches for subreddits with names beginning with the query provided +func (s *SubredditServiceOp) SearchSubredditNames(ctx context.Context, query string) ([]string, *Response, error) { + path := fmt.Sprintf("api/search_reddit_names?query=%s", query) + + req, err := s.client.NewRequest(http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(subredditNamesRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.Names, resp, nil +} + +// SearchSubredditInfo searches for subreddits with names beginning with the query provided. +// They hold a bit more info that just the name, but still not much. +func (s *SubredditServiceOp) SearchSubredditInfo(ctx context.Context, query string) ([]SubredditShort, *Response, error) { + path := fmt.Sprintf("api/search_subreddits?query=%s", query) + + req, err := s.client.NewRequest(http.MethodPost, path, nil) + if err != nil { + return nil, nil, err + } + + root := new(subredditShortsRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + + return root.Subreddits, resp, nil +} + func (s *SubredditServiceOp) handleSubscription(ctx context.Context, form url.Values) (*Response, error) { path := "api/subscribe" req, err := s.client.NewPostForm(path, form) @@ -237,10 +292,10 @@ func (s *SubredditServiceOp) getSubreddits(ctx context.Context, path string, opt return l, resp, nil } -func (s *SubredditServiceOp) getLinks(ctx context.Context, sort sort, opts *ListOptions, subreddits ...string) (*Links, *Response, error) { +func (s *SubredditServiceOp) getLinks(ctx context.Context, sort Sort, opts *ListOptions, subreddits ...string) (*Links, *Response, error) { path := sorts[sort] if len(subreddits) > 0 { - path = fmt.Sprintf("r/%s/%s", strings.Join(subreddits, "+"), sorts[sort]) + path = fmt.Sprintf("r/%s/%s", strings.Join(subreddits, "+"), sort) } path, err := addOptions(path, opts) diff --git a/things.go b/things.go index 8d2aa5e..fabd8c1 100644 --- a/things.go +++ b/things.go @@ -17,18 +17,8 @@ const ( kindMode = "more" ) -type sort int - -const ( - sortHot sort = iota - sortBest - sortNew - sortRising - sortControversial - sortTop - sortRelevance - sortComments -) +// Sort is a sorting option. +type Sort int var sorts = [...]string{ "hot", @@ -37,12 +27,60 @@ var sorts = [...]string{ "rising", "controversial", "top", - - // for search queries "relevance", "comments", } +// Different sorting options. +const ( + SortHot Sort = iota + SortBest + SortNew + SortRising + SortControversial + SortTop + SortRelevance + SortComments +) + +func (s Sort) String() string { + if s < SortHot || s > SortComments { + return "" + } + return sorts[s] +} + +// Timespan is a timespan option. +// E.g. "hour" means in the last hour, "all" means all-time. +// It is used when conducting searches. +type Timespan int + +var timespans = [...]string{ + "hour", + "day", + "week", + "month", + "year", + "all", +} + +// Different timespan options. +const ( + TimespanHour Timespan = iota + TimespanDay + TimespanWeek + TimespanMonth + TimespanYear + TimespanAll +) + +func (t Timespan) String() string { + if t < TimespanHour || t > TimespanAll { + return "" + } + return timespans[t] +} + type sticky int const ( diff --git a/user.go b/user.go index 449d5c7..525c83d 100644 --- a/user.go +++ b/user.go @@ -191,25 +191,25 @@ func (s *UserServiceOp) GetControversialLinks(ctx context.Context, opts *ListOpt // GetHotLinksOf returns a list of the user's hottest submissions func (s *UserServiceOp) GetHotLinksOf(ctx context.Context, username string, opts *ListOptions) (*Links, *Response, error) { - path := fmt.Sprintf("user/%s/submitted?sort=%s", username, sorts[sortHot]) + path := fmt.Sprintf("user/%s/submitted?sort=%s", username, SortHot) return s.getLinks(ctx, path, opts) } // GetNewLinksOf returns a list of the user's newest submissions func (s *UserServiceOp) GetNewLinksOf(ctx context.Context, username string, opts *ListOptions) (*Links, *Response, error) { - path := fmt.Sprintf("user/%s/submitted?sort=%s", username, sorts[sortNew]) + path := fmt.Sprintf("user/%s/submitted?sort=%s", username, SortNew) return s.getLinks(ctx, path, opts) } // GetTopLinksOf returns a list of the user's top submissions func (s *UserServiceOp) GetTopLinksOf(ctx context.Context, username string, opts *ListOptions) (*Links, *Response, error) { - path := fmt.Sprintf("user/%s/submitted?sort=%s", username, sorts[sortTop]) + path := fmt.Sprintf("user/%s/submitted?sort=%s", username, SortTop) return s.getLinks(ctx, path, opts) } // GetControversialLinksOf returns a list of the user's most controversial submissions func (s *UserServiceOp) GetControversialLinksOf(ctx context.Context, username string, opts *ListOptions) (*Links, *Response, error) { - path := fmt.Sprintf("user/%s/submitted?sort=%s", username, sorts[sortControversial]) + path := fmt.Sprintf("user/%s/submitted?sort=%s", username, SortControversial) return s.getLinks(ctx, path, opts) } @@ -265,25 +265,25 @@ func (s *UserServiceOp) GetControversialComments(ctx context.Context, opts *List // GetHotCommentsOf returns a list of the user's hottest comments func (s *UserServiceOp) GetHotCommentsOf(ctx context.Context, username string, opts *ListOptions) (*Comments, *Response, error) { - path := fmt.Sprintf("user/%s/comments?sort=%s", username, sorts[sortHot]) + path := fmt.Sprintf("user/%s/comments?sort=%s", username, SortHot) return s.getComments(ctx, path, opts) } // GetNewCommentsOf returns a list of the user's newest comments func (s *UserServiceOp) GetNewCommentsOf(ctx context.Context, username string, opts *ListOptions) (*Comments, *Response, error) { - path := fmt.Sprintf("user/%s/comments?sort=%s", username, sorts[sortNew]) + path := fmt.Sprintf("user/%s/comments?sort=%s", username, SortNew) return s.getComments(ctx, path, opts) } // GetTopCommentsOf returns a list of the user's top comments func (s *UserServiceOp) GetTopCommentsOf(ctx context.Context, username string, opts *ListOptions) (*Comments, *Response, error) { - path := fmt.Sprintf("user/%s/comments?sort=%s", username, sorts[sortTop]) + path := fmt.Sprintf("user/%s/comments?sort=%s", username, SortTop) return s.getComments(ctx, path, opts) } // GetControversialCommentsOf returns a list of the user's most controversial comments func (s *UserServiceOp) GetControversialCommentsOf(ctx context.Context, username string, opts *ListOptions) (*Comments, *Response, error) { - path := fmt.Sprintf("user/%s/comments?sort=%s", username, sorts[sortControversial]) + path := fmt.Sprintf("user/%s/comments?sort=%s", username, SortControversial) return s.getComments(ctx, path, opts) }