Implement api/flaircsv
Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
This commit is contained in:
parent
c37b934c01
commit
8a9e41181d
3 changed files with 162 additions and 4 deletions
|
@ -1,7 +1,9 @@
|
||||||
package reddit
|
package reddit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/csv"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -48,9 +50,9 @@ type FlairChoice struct {
|
||||||
CSSClass string `json:"flair_css_class"`
|
CSSClass string `json:"flair_css_class"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigureFlairRequest represents a request to configure a subreddit's flair settings.
|
// RequestConfigureFlair represents a request to configure a subreddit's flair settings.
|
||||||
// Not setting an attribute can have unexpected side effects, so assign every one just in case.
|
// Not setting an attribute can have unexpected side effects, so assign every one just in case.
|
||||||
type ConfigureFlairRequest struct {
|
type RequestConfigureFlair struct {
|
||||||
// Enable user flair in the subreddit.
|
// Enable user flair in the subreddit.
|
||||||
UserFlairEnabled *bool `url:"flair_enabled,omitempty"`
|
UserFlairEnabled *bool `url:"flair_enabled,omitempty"`
|
||||||
// One of: left, right.
|
// One of: left, right.
|
||||||
|
@ -120,6 +122,23 @@ type FlairSelectRequest struct {
|
||||||
Text string `url:"text,omitempty"`
|
Text string `url:"text,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FlairChangeRequest represents a request to change a user's flair.
|
||||||
|
// If Text and CSSClass are empty, the request will just clear the user's flair.
|
||||||
|
type FlairChangeRequest struct {
|
||||||
|
User string
|
||||||
|
Text string
|
||||||
|
CSSClass string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlairChangeResponse represents a response to a FlairChangeRequest.
|
||||||
|
type FlairChangeResponse struct {
|
||||||
|
// Whether or not the request was successful.
|
||||||
|
OK bool `json:"ok"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Warnings map[string]string `json:"warnings,omitempty"`
|
||||||
|
Errors map[string]string `json:"errors,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetUserFlairs returns the user flairs from the subreddit.
|
// GetUserFlairs returns the user flairs from the subreddit.
|
||||||
func (s *FlairService) GetUserFlairs(ctx context.Context, subreddit string) ([]*Flair, *Response, error) {
|
func (s *FlairService) GetUserFlairs(ctx context.Context, subreddit string) ([]*Flair, *Response, error) {
|
||||||
path := fmt.Sprintf("r/%s/api/user_flair_v2", subreddit)
|
path := fmt.Sprintf("r/%s/api/user_flair_v2", subreddit)
|
||||||
|
@ -177,7 +196,7 @@ func (s *FlairService) ListUserFlairs(ctx context.Context, subreddit string) ([]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure the subreddit's flair settings.
|
// Configure the subreddit's flair settings.
|
||||||
func (s *FlairService) Configure(ctx context.Context, subreddit string, request *ConfigureFlairRequest) (*Response, error) {
|
func (s *FlairService) Configure(ctx context.Context, subreddit string, request *RequestConfigureFlair) (*Response, error) {
|
||||||
if request == nil {
|
if request == nil {
|
||||||
return nil, errors.New("request: cannot be nil")
|
return nil, errors.New("request: cannot be nil")
|
||||||
}
|
}
|
||||||
|
@ -482,6 +501,7 @@ func (s *FlairService) SelectForPost(ctx context.Context, postID string, request
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveFromPost removes the flair from the post.
|
// RemoveFromPost removes the flair from the post.
|
||||||
|
// If the post isn't yours, you have to be a moderator of the post's subreddit for this to work.
|
||||||
func (s *FlairService) RemoveFromPost(ctx context.Context, postID string) (*Response, error) {
|
func (s *FlairService) RemoveFromPost(ctx context.Context, postID string) (*Response, error) {
|
||||||
path := "api/selectflair"
|
path := "api/selectflair"
|
||||||
|
|
||||||
|
@ -496,3 +516,47 @@ func (s *FlairService) RemoveFromPost(ctx context.Context, postID string) (*Resp
|
||||||
|
|
||||||
return s.client.Do(ctx, req, nil)
|
return s.client.Do(ctx, req, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Change the flair of multiple users in the subreddit at once.
|
||||||
|
// You have to be a moderator of the subreddit for this to work.
|
||||||
|
func (s *FlairService) Change(ctx context.Context, subreddit string, requests []FlairChangeRequest) ([]*FlairChangeResponse, *Response, error) {
|
||||||
|
if len(requests) == 0 || len(requests) > 100 {
|
||||||
|
return nil, nil, errors.New("requests: must provide between 1 and 100")
|
||||||
|
}
|
||||||
|
|
||||||
|
records := make([][]string, len(requests))
|
||||||
|
for i, req := range requests {
|
||||||
|
records[i] = []string{req.User, req.Text, req.CSSClass}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
w := csv.NewWriter(buf)
|
||||||
|
|
||||||
|
err := w.WriteAll(records)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = w.Error()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
path := fmt.Sprintf("r/%s/api/flaircsv", subreddit)
|
||||||
|
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("flair_csv", buf.String())
|
||||||
|
|
||||||
|
req, err := s.client.NewRequest(http.MethodPost, path, form)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var root []*FlairChangeResponse
|
||||||
|
resp, err := s.client.Do(ctx, req, &root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return root, resp, nil
|
||||||
|
}
|
||||||
|
|
|
@ -122,6 +122,35 @@ var expectedFlairChoice = &FlairChoice{
|
||||||
CSSClass: "",
|
CSSClass: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var expectedFlairChanges = []*FlairChangeResponse{
|
||||||
|
{
|
||||||
|
OK: false,
|
||||||
|
Status: "skipped",
|
||||||
|
Warnings: map[string]string{},
|
||||||
|
Errors: map[string]string{
|
||||||
|
"user": "unable to resolve user `testuser1', ignoring",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
OK: true,
|
||||||
|
Status: "added flair for user testuser2",
|
||||||
|
Warnings: map[string]string{},
|
||||||
|
Errors: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
OK: true,
|
||||||
|
Status: "added flair for user testuser3",
|
||||||
|
Warnings: map[string]string{},
|
||||||
|
Errors: map[string]string{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
OK: true,
|
||||||
|
Status: "removed flair for user testuser4",
|
||||||
|
Warnings: map[string]string{},
|
||||||
|
Errors: map[string]string{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func TestFlairService_GetUserFlairs(t *testing.T) {
|
func TestFlairService_GetUserFlairs(t *testing.T) {
|
||||||
client, mux, teardown := setup()
|
client, mux, teardown := setup()
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
@ -196,7 +225,7 @@ func TestFlairService_Configure(t *testing.T) {
|
||||||
_, err := client.Flair.Configure(ctx, "testsubreddit", nil)
|
_, err := client.Flair.Configure(ctx, "testsubreddit", nil)
|
||||||
require.EqualError(t, err, "request: cannot be nil")
|
require.EqualError(t, err, "request: cannot be nil")
|
||||||
|
|
||||||
_, err = client.Flair.Configure(ctx, "testsubreddit", &ConfigureFlairRequest{
|
_, err = client.Flair.Configure(ctx, "testsubreddit", &RequestConfigureFlair{
|
||||||
UserFlairEnabled: Bool(true),
|
UserFlairEnabled: Bool(true),
|
||||||
UserFlairPosition: "right",
|
UserFlairPosition: "right",
|
||||||
UserFlairSelfAssignEnabled: Bool(false),
|
UserFlairSelfAssignEnabled: Bool(false),
|
||||||
|
@ -656,3 +685,40 @@ func TestFlairService_RemoveFromPost(t *testing.T) {
|
||||||
_, err := client.Flair.RemoveFromPost(ctx, "t3_123")
|
_, err := client.Flair.RemoveFromPost(ctx, "t3_123")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFlairService_Change(t *testing.T) {
|
||||||
|
client, mux, teardown := setup()
|
||||||
|
defer teardown()
|
||||||
|
|
||||||
|
blob, err := readFileContents("../testdata/flair/csv-change.json")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
mux.HandleFunc("/r/testsubreddit/api/flaircsv", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
require.Equal(t, http.MethodPost, r.Method)
|
||||||
|
|
||||||
|
form := url.Values{}
|
||||||
|
form.Set("flair_csv", `testuser1,testtext1,testclass1
|
||||||
|
testuser2,testtext2,testclass2
|
||||||
|
testuser3,testtext3,testclass3
|
||||||
|
testuser4,testtext4,testclass4
|
||||||
|
`)
|
||||||
|
|
||||||
|
err := r.ParseForm()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, form, r.PostForm)
|
||||||
|
|
||||||
|
fmt.Fprint(w, blob)
|
||||||
|
})
|
||||||
|
|
||||||
|
_, _, err = client.Flair.Change(ctx, "testsubreddit", nil)
|
||||||
|
require.EqualError(t, err, "requests: must provide between 1 and 100")
|
||||||
|
|
||||||
|
changes, _, err := client.Flair.Change(ctx, "testsubreddit", []FlairChangeRequest{
|
||||||
|
{"testuser1", "testtext1", "testclass1"},
|
||||||
|
{"testuser2", "testtext2", "testclass2"},
|
||||||
|
{"testuser3", "testtext3", "testclass3"},
|
||||||
|
{"testuser4", "testtext4", "testclass4"},
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, expectedFlairChanges, changes)
|
||||||
|
}
|
||||||
|
|
28
testdata/flair/csv-change.json
vendored
Normal file
28
testdata/flair/csv-change.json
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"errors": {
|
||||||
|
"user": "unable to resolve user `testuser1', ignoring"
|
||||||
|
},
|
||||||
|
"ok": false,
|
||||||
|
"status": "skipped",
|
||||||
|
"warnings": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"errors": {},
|
||||||
|
"ok": true,
|
||||||
|
"status": "added flair for user testuser2",
|
||||||
|
"warnings": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"errors": {},
|
||||||
|
"ok": true,
|
||||||
|
"status": "added flair for user testuser3",
|
||||||
|
"warnings": {}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"errors": {},
|
||||||
|
"ok": true,
|
||||||
|
"status": "removed flair for user testuser4",
|
||||||
|
"warnings": {}
|
||||||
|
}
|
||||||
|
]
|
Loading…
Reference in a new issue