snoobert/post.go
Vartan Benohanian ec7e8abe8e Create PostAndCommentService, holds common methods
Some functionality such as saving, voting, deleting, etc. is common to
both posts and comments, so this service will hold such methods.

Tweaked the separate post/comment services accordingly. Fixed tests.

Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
2020-07-13 23:05:24 -04:00

223 lines
5.2 KiB
Go

package reddit
import (
"context"
"errors"
"net/http"
"net/url"
"strings"
"github.com/google/go-querystring/query"
)
// PostService handles communication with the post
// related methods of the Reddit API.
//
// Reddit API docs: https://www.reddit.com/dev/api/#section_links_and_comments
type PostService service
type submittedLinkRoot struct {
JSON struct {
Data *Submitted `json:"data,omitempty"`
} `json:"json"`
}
// 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"`
}
// SubmitTextOptions are options used for text posts.
type SubmitTextOptions struct {
Subreddit string `url:"sr,omitempty"`
Title string `url:"title,omitempty"`
Text string `url:"text,omitempty"`
FlairID string `url:"flair_id,omitempty"`
FlairText string `url:"flair_text,omitempty"`
SendReplies *bool `url:"sendreplies,omitempty"`
NSFW bool `url:"nsfw,omitempty"`
Spoiler bool `url:"spoiler,omitempty"`
}
// SubmitLinkOptions are options used for link posts.
type SubmitLinkOptions struct {
Subreddit string `url:"sr,omitempty"`
Title string `url:"title,omitempty"`
URL string `url:"url,omitempty"`
FlairID string `url:"flair_id,omitempty"`
FlairText string `url:"flair_text,omitempty"`
SendReplies *bool `url:"sendreplies,omitempty"`
Resubmit bool `url:"resubmit,omitempty"`
NSFW bool `url:"nsfw,omitempty"`
Spoiler bool `url:"spoiler,omitempty"`
}
func (s *PostService) submit(ctx context.Context, v interface{}) (*Submitted, *Response, error) {
path := "api/submit"
form, err := query.Values(v)
if err != nil {
return nil, nil, err
}
form.Set("api_type", "json")
req, err := s.client.NewRequestWithForm(http.MethodPost, path, form)
if err != nil {
return nil, nil, err
}
root := new(submittedLinkRoot)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.JSON.Data, resp, nil
}
// SubmitText submits a text post.
func (s *PostService) SubmitText(ctx context.Context, opts SubmitTextOptions) (*Submitted, *Response, error) {
type submit struct {
SubmitTextOptions
Kind string `url:"kind,omitempty"`
}
return s.submit(ctx, &submit{opts, "self"})
}
// SubmitLink submits a link post.
func (s *PostService) SubmitLink(ctx context.Context, opts SubmitLinkOptions) (*Submitted, *Response, error) {
type submit struct {
SubmitLinkOptions
Kind string `url:"kind,omitempty"`
}
return s.submit(ctx, &submit{opts, "link"})
}
// Edit edits a post.
func (s *PostService) Edit(ctx context.Context, id string, text string) (*Post, *Response, error) {
path := "api/editusertext"
form := url.Values{}
form.Set("api_type", "json")
form.Set("return_rtjson", "true")
form.Set("thing_id", id)
form.Set("text", text)
req, err := s.client.NewRequestWithForm(http.MethodPost, path, form)
if err != nil {
return nil, nil, err
}
root := new(Post)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root, resp, nil
}
// Hide hides posts.
func (s *PostService) Hide(ctx context.Context, ids ...string) (*Response, error) {
if len(ids) == 0 {
return nil, errors.New("must provide at least 1 id")
}
path := "api/hide"
form := url.Values{}
form.Set("id", strings.Join(ids, ","))
req, err := s.client.NewRequestWithForm(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Unhide unhides posts.
func (s *PostService) Unhide(ctx context.Context, ids ...string) (*Response, error) {
if len(ids) == 0 {
return nil, errors.New("must provide at least 1 id")
}
path := "api/unhide"
form := url.Values{}
form.Set("id", strings.Join(ids, ","))
req, err := s.client.NewRequestWithForm(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// MarkNSFW marks a post as NSFW.
func (s *PostService) MarkNSFW(ctx context.Context, id string) (*Response, error) {
path := "api/marknsfw"
form := url.Values{}
form.Set("id", id)
req, err := s.client.NewRequestWithForm(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// UnmarkNSFW unmarks a post as NSFW.
func (s *PostService) UnmarkNSFW(ctx context.Context, id string) (*Response, error) {
path := "api/unmarknsfw"
form := url.Values{}
form.Set("id", id)
req, err := s.client.NewRequestWithForm(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Spoiler marks a post as a spoiler.
func (s *PostService) Spoiler(ctx context.Context, id string) (*Response, error) {
path := "api/spoiler"
form := url.Values{}
form.Set("id", id)
req, err := s.client.NewRequestWithForm(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Unspoiler unmarks a post as a spoiler.
func (s *PostService) Unspoiler(ctx context.Context, id string) (*Response, error) {
path := "api/unspoiler"
form := url.Values{}
form.Set("id", id)
req, err := s.client.NewRequestWithForm(http.MethodPost, path, form)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}