From 98c7909d9a368c5a62a6d19fcebe5d7ecbf50946 Mon Sep 17 00:00:00 2001 From: Vartan Benohanian Date: Tue, 11 Aug 2020 00:44:19 -0400 Subject: [PATCH] Fav/unfav subreddits, get banned and muted users Signed-off-by: Vartan Benohanian --- subreddit.go | 140 ++++++++++++++++++++++++++ subreddit_test.go | 142 +++++++++++++++++++++++++++ testdata/subreddit/banned-users.json | 27 +++++ testdata/subreddit/muted-users.json | 23 +++++ 4 files changed, 332 insertions(+) create mode 100644 testdata/subreddit/banned-users.json create mode 100644 testdata/subreddit/muted-users.json diff --git a/subreddit.go b/subreddit.go index bad97a2..9b5395e 100644 --- a/subreddit.go +++ b/subreddit.go @@ -40,6 +40,42 @@ type Moderator struct { Permissions []string `json:"mod_permissions"` } +// Ban represents a banned user and the ban information. +type Ban struct { + ID string `json:"rel_id,omitempty"` + Created *Timestamp `json:"date,omitempty"` + + User string `json:"name,omitempty"` + UserID string `json:"id,omitempty"` + + // nil means the ban is permanent + DaysLeft *int `json:"days_left"` + Note string `json:"note,omitempty"` +} + +// Bans is a listing of bans. +type Bans struct { + Bans []*Ban `json:"bans"` + After string `json:"after"` + Before string `json:"before"` +} + +// Mute represents a muted user and the mute information. +type Mute struct { + ID string `json:"rel_id,omitempty"` + Created *Timestamp `json:"date,omitempty"` + + User string `json:"name,omitempty"` + UserID string `json:"id,omitempty"` +} + +// Mutes is a listing of Mute. +type Mutes struct { + Mutes []*Mute `json:"mutes"` + After string `json:"after"` + Before string `json:"before"` +} + func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) { path := sort if subreddit != "" { @@ -212,6 +248,40 @@ func (s *SubredditService) UnsubscribeByID(ctx context.Context, ids ...string) ( return s.handleSubscription(ctx, form) } +// Favorite favorites the subreddit. +func (s *SubredditService) Favorite(ctx context.Context, subreddit string) (*Response, error) { + path := "api/favorite" + + form := url.Values{} + form.Set("sr_name", subreddit) + form.Set("make_favorite", "true") + form.Set("api_type", "json") + + req, err := s.client.NewRequestWithForm(http.MethodPost, path, form) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + +// Unfavorite unfavorites the subreddit. +func (s *SubredditService) Unfavorite(ctx context.Context, subreddit string) (*Response, error) { + path := "api/favorite" + + form := url.Values{} + form.Set("sr_name", subreddit) + form.Set("make_favorite", "false") + form.Set("api_type", "json") + + req, err := s.client.NewRequestWithForm(http.MethodPost, path, form) + if err != nil { + return nil, err + } + + return s.client.Do(ctx, req, nil) +} + // Search searches for subreddits. func (s *SubredditService) Search(ctx context.Context, query string, opts *ListSubredditOptions) (*Subreddits, *Response, error) { path := "subreddits/search" @@ -444,3 +514,73 @@ func (s *SubredditService) SubmissionText(ctx context.Context, name string) (str return root.Text, resp, err } + +// Banned gets banned users from the subreddit. +func (s *SubredditService) Banned(ctx context.Context, subreddit string, opts *ListOptions) (*Bans, *Response, error) { + path := fmt.Sprintf("r/%s/about/banned", subreddit) + + path, err := addOptions(path, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + var root struct { + Data struct { + Bans []*Ban `json:"children"` + After string `json:"after"` + Before string `json:"before"` + } `json:"data"` + } + resp, err := s.client.Do(ctx, req, &root) + if err != nil { + return nil, resp, err + } + + bans := &Bans{ + Bans: root.Data.Bans, + After: root.Data.After, + Before: root.Data.Before, + } + + return bans, resp, nil +} + +// Muted gets muted users from the subreddit. +func (s *SubredditService) Muted(ctx context.Context, subreddit string, opts *ListOptions) (*Mutes, *Response, error) { + path := fmt.Sprintf("r/%s/about/muted", subreddit) + + path, err := addOptions(path, opts) + if err != nil { + return nil, nil, err + } + + req, err := s.client.NewRequest(http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + + var root struct { + Data struct { + Mutes []*Mute `json:"children"` + After string `json:"after"` + Before string `json:"before"` + } `json:"data"` + } + resp, err := s.client.Do(ctx, req, &root) + if err != nil { + return nil, resp, err + } + + mutes := &Mutes{ + Mutes: root.Data.Mutes, + After: root.Data.After, + Before: root.Data.Before, + } + + return mutes, resp, nil +} diff --git a/subreddit_test.go b/subreddit_test.go index 73cb2c8..b5e49f4 100644 --- a/subreddit_test.go +++ b/subreddit_test.go @@ -219,6 +219,54 @@ var expectedRandomSubreddit = &Subreddit{ Subscribers: 52357, } +var expectedBans = &Bans{ + Bans: []*Ban{ + { + ID: "rb_123", + Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 2, 0, time.UTC)}, + + User: "testuser1", + UserID: "t2_user1", + + DaysLeft: Int(43), + Note: "Spam", + }, + { + ID: "rb_456", + Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 0, 0, time.UTC)}, + + User: "testuser2", + UserID: "t2_user2", + + DaysLeft: nil, + Note: "Spam", + }, + }, + After: "", + Before: "", +} + +var expectedMutes = &Mutes{ + Mutes: []*Mute{ + { + ID: "Mute_123", + Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 2, 0, time.UTC)}, + + User: "testuser1", + UserID: "t2_user1", + }, + { + ID: "Mute_456", + Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 0, 0, time.UTC)}, + + User: "testuser2", + UserID: "t2_user2", + }, + }, + After: "", + Before: "", +} + func TestSubredditService_HotPosts(t *testing.T) { setup() defer teardown() @@ -567,6 +615,48 @@ func TestSubredditService_UnsubscribeByID(t *testing.T) { assert.NoError(t, err) } +func TestSubredditService_Favorite(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/api/favorite", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method) + + form := url.Values{} + form.Set("sr_name", "testsubreddit") + form.Set("make_favorite", "true") + form.Set("api_type", "json") + + err := r.ParseForm() + assert.NoError(t, err) + assert.Equal(t, form, r.Form) + }) + + _, err := client.Subreddit.Favorite(ctx, "testsubreddit") + assert.NoError(t, err) +} + +func TestSubredditService_Unfavorite(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/api/favorite", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodPost, r.Method) + + form := url.Values{} + form.Set("sr_name", "testsubreddit") + form.Set("make_favorite", "false") + form.Set("api_type", "json") + + err := r.ParseForm() + assert.NoError(t, err) + assert.Equal(t, form, r.Form) + }) + + _, err := client.Subreddit.Unfavorite(ctx, "testsubreddit") + assert.NoError(t, err) +} + func TestSubredditService_Search(t *testing.T) { setup() defer teardown() @@ -780,3 +870,55 @@ func TestSubredditService_SubmissionText(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "this is a test", text) } + +func TestSubredditService_Banned(t *testing.T) { + setup() + defer teardown() + + blob, err := readFileContents("testdata/subreddit/banned-users.json") + assert.NoError(t, err) + + mux.HandleFunc("/r/test/about/banned", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method) + + form := url.Values{} + form.Set("after", "testafter") + form.Set("limit", "10") + + err := r.ParseForm() + assert.NoError(t, err) + assert.Equal(t, form, r.Form) + + fmt.Fprint(w, blob) + }) + + bans, _, err := client.Subreddit.Banned(ctx, "test", &ListOptions{After: "testafter", Limit: 10}) + assert.NoError(t, err) + assert.Equal(t, expectedBans, bans) +} + +func TestSubredditService_Muted(t *testing.T) { + setup() + defer teardown() + + blob, err := readFileContents("testdata/subreddit/muted-users.json") + assert.NoError(t, err) + + mux.HandleFunc("/r/test/about/muted", func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, http.MethodGet, r.Method) + + form := url.Values{} + form.Set("before", "testbefore") + form.Set("limit", "50") + + err := r.ParseForm() + assert.NoError(t, err) + assert.Equal(t, form, r.Form) + + fmt.Fprint(w, blob) + }) + + mutes, _, err := client.Subreddit.Muted(ctx, "test", &ListOptions{Before: "testbefore", Limit: 50}) + assert.NoError(t, err) + assert.Equal(t, expectedMutes, mutes) +} diff --git a/testdata/subreddit/banned-users.json b/testdata/subreddit/banned-users.json new file mode 100644 index 0000000..dc83fc4 --- /dev/null +++ b/testdata/subreddit/banned-users.json @@ -0,0 +1,27 @@ +{ + "kind": "Listing", + "data": { + "modhash": null, + "dist": null, + "children": [ + { + "name": "testuser1", + "days_left": 43, + "note": "Spam", + "date": 1597113302.0, + "rel_id": "rb_123", + "id": "t2_user1" + }, + { + "name": "testuser2", + "days_left": null, + "note": "Spam", + "date": 1597113300.0, + "rel_id": "rb_456", + "id": "t2_user2" + } + ], + "after": null, + "before": null + } +} diff --git a/testdata/subreddit/muted-users.json b/testdata/subreddit/muted-users.json new file mode 100644 index 0000000..a362d09 --- /dev/null +++ b/testdata/subreddit/muted-users.json @@ -0,0 +1,23 @@ +{ + "kind": "Listing", + "data": { + "modhash": null, + "dist": null, + "children": [ + { + "date": 1597113302.0, + "rel_id": "Mute_123", + "name": "testuser1", + "id": "t2_user1" + }, + { + "date": 1597113300.0, + "rel_id": "Mute_456", + "name": "testuser2", + "id": "t2_user2" + } + ], + "after": null, + "before": null + } +}