838db037b9
Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
163 lines
4.1 KiB
Go
163 lines
4.1 KiB
Go
package reddit
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// SearchService handles communication with the search
|
|
// related methods of the Reddit API.
|
|
//
|
|
// 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.
|
|
//
|
|
// Reddit API docs: https://www.reddit.com/dev/api/#section_search
|
|
type SearchService service
|
|
|
|
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))
|
|
}
|
|
}
|
|
|
|
// SetSort sets the sort option.
|
|
func SetSort(v Sort) SearchOptionSetter {
|
|
return func(opts url.Values) {
|
|
opts.Set("sort", v.String())
|
|
}
|
|
}
|
|
|
|
// SetTimespan sets the timespan option.
|
|
func SetTimespan(v Timespan) SearchOptionSetter {
|
|
return func(opts url.Values) {
|
|
opts.Set("timespan", v.String())
|
|
}
|
|
}
|
|
|
|
// setType sets the type option.
|
|
// It could be user, link, sr (subreddit).
|
|
// 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")
|
|
}
|
|
|
|
// Posts searches for posts.
|
|
// If the list of subreddits provided is empty, the search is run against r/all.
|
|
func (s *SearchService) Posts(ctx context.Context, query string, subreddits []string, opts ...SearchOptionSetter) (*Posts, *Response, error) {
|
|
opts = append(opts, setType("link"), setQuery(query))
|
|
|
|
path := "search"
|
|
if len(subreddits) > 0 {
|
|
path = fmt.Sprintf("r/%s/search", strings.Join(subreddits, "+"))
|
|
opts = append(opts, setRestrict)
|
|
}
|
|
|
|
form := newSearchOptions(opts...)
|
|
path = addQuery(path, form)
|
|
|
|
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
root := new(rootListing)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
|
|
return root.getPosts(), resp, nil
|
|
}
|
|
|
|
// Subreddits searches for subreddits.
|
|
// The Sort and Timespan options don't affect the results for this search.
|
|
func (s *SearchService) Subreddits(ctx context.Context, query string, opts ...SearchOptionSetter) (*Subreddits, *Response, error) {
|
|
opts = append(opts, setType("sr"), setQuery(query))
|
|
form := newSearchOptions(opts...)
|
|
|
|
path := "search"
|
|
path = addQuery(path, form)
|
|
|
|
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
root := new(rootListing)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
|
|
return root.getSubreddits(), resp, nil
|
|
}
|
|
|
|
// Users searches for users.
|
|
// The Sort and Timespan options don't affect the results for this search.
|
|
func (s *SearchService) Users(ctx context.Context, query string, opts ...SearchOptionSetter) (*Users, *Response, error) {
|
|
opts = append(opts, setType("user"), setQuery(query))
|
|
form := newSearchOptions(opts...)
|
|
|
|
path := "search"
|
|
path = addQuery(path, form)
|
|
|
|
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
root := new(rootListing)
|
|
resp, err := s.client.Do(ctx, req, root)
|
|
if err != nil {
|
|
return nil, resp, err
|
|
}
|
|
|
|
return root.getUsers(), resp, nil
|
|
}
|