Get wikibanned, contributors, wikicontributors, etc.

Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
This commit is contained in:
Vartan Benohanian 2020-08-11 14:51:47 -04:00
parent 98c7909d9a
commit 67cd813e70
4 changed files with 296 additions and 114 deletions

View file

@ -26,28 +26,31 @@ type rootSubredditNames struct {
Names []string `json:"names,omitempty"` Names []string `json:"names,omitempty"`
} }
type rootModeratorList struct { // Relationship holds information about a relationship (friend/blocked).
Kind string `json:"kind,omitempty"` // todo: there's also banned, wikibanned, etc.
Data struct { type Relationship struct {
Moderators []Moderator `json:"children"` ID string `json:"rel_id,omitempty"`
} `json:"data"` User string `json:"name,omitempty"`
UserID string `json:"id,omitempty"`
Created *Timestamp `json:"date,omitempty"`
}
// Relationships is a listing of relationships.
type Relationships struct {
Relationships []*Relationship `json:"relationships"`
After string `json:"after"`
Before string `json:"before"`
} }
// Moderator is a user who moderates a subreddit. // Moderator is a user who moderates a subreddit.
type Moderator struct { type Moderator struct {
ID string `json:"id,omitempty"` *Relationship
Name string `json:"name,omitempty"`
Permissions []string `json:"mod_permissions"` Permissions []string `json:"mod_permissions"`
} }
// Ban represents a banned user and the ban information. // Ban represents a banned relationship.
type Ban struct { type Ban struct {
ID string `json:"rel_id,omitempty"` *Relationship
Created *Timestamp `json:"date,omitempty"`
User string `json:"name,omitempty"`
UserID string `json:"id,omitempty"`
// nil means the ban is permanent // nil means the ban is permanent
DaysLeft *int `json:"days_left"` DaysLeft *int `json:"days_left"`
Note string `json:"note,omitempty"` Note string `json:"note,omitempty"`
@ -60,22 +63,6 @@ type Bans struct {
Before string `json:"before"` 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) { func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) {
path := sort path := sort
if subreddit != "" { if subreddit != "" {
@ -416,24 +403,6 @@ func (s *SubredditService) getSticky(ctx context.Context, subreddit string, num
return root, resp, nil return root, resp, nil
} }
// Moderators returns the moderators of a subreddit.
func (s *SubredditService) Moderators(ctx context.Context, subreddit string) (interface{}, *Response, error) {
path := fmt.Sprintf("r/%s/about/moderators", subreddit)
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(rootModeratorList)
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Data.Moderators, resp, nil
}
// todo: sr_detail's NSFW indicator is over_18 instead of over18 // todo: sr_detail's NSFW indicator is over_18 instead of over18
func (s *SubredditService) random(ctx context.Context, nsfw bool) (*Subreddit, *Response, error) { func (s *SubredditService) random(ctx context.Context, nsfw bool) (*Subreddit, *Response, error) {
path := "r/random" path := "r/random"
@ -551,7 +520,7 @@ func (s *SubredditService) Banned(ctx context.Context, subreddit string, opts *L
} }
// Muted gets muted users from the subreddit. // Muted gets muted users from the subreddit.
func (s *SubredditService) Muted(ctx context.Context, subreddit string, opts *ListOptions) (*Mutes, *Response, error) { func (s *SubredditService) Muted(ctx context.Context, subreddit string, opts *ListOptions) (*Relationships, *Response, error) {
path := fmt.Sprintf("r/%s/about/muted", subreddit) path := fmt.Sprintf("r/%s/about/muted", subreddit)
path, err := addOptions(path, opts) path, err := addOptions(path, opts)
@ -564,9 +533,44 @@ func (s *SubredditService) Muted(ctx context.Context, subreddit string, opts *Li
return nil, nil, err return nil, nil, err
} }
root := new(struct {
Data struct {
Relationships []*Relationship `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
}
relationships := &Relationships{
Relationships: root.Data.Relationships,
After: root.Data.After,
Before: root.Data.Before,
}
return relationships, resp, nil
}
// WikiBanned gets banned users from the subreddit.
func (s *SubredditService) WikiBanned(ctx context.Context, subreddit string, opts *ListOptions) (*Bans, *Response, error) {
path := fmt.Sprintf("r/%s/about/wikibanned", 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 { var root struct {
Data struct { Data struct {
Mutes []*Mute `json:"children"` Bans []*Ban `json:"children"`
After string `json:"after"` After string `json:"after"`
Before string `json:"before"` Before string `json:"before"`
} `json:"data"` } `json:"data"`
@ -576,11 +580,103 @@ func (s *SubredditService) Muted(ctx context.Context, subreddit string, opts *Li
return nil, resp, err return nil, resp, err
} }
mutes := &Mutes{ bans := &Bans{
Mutes: root.Data.Mutes, Bans: root.Data.Bans,
After: root.Data.After, After: root.Data.After,
Before: root.Data.Before, Before: root.Data.Before,
} }
return mutes, resp, nil return bans, resp, nil
}
// Contributors gets contributors (also known as approved users) from the subreddit.
func (s *SubredditService) Contributors(ctx context.Context, subreddit string, opts *ListOptions) (*Relationships, *Response, error) {
path := fmt.Sprintf("r/%s/about/contributors", 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
}
root := new(struct {
Data struct {
Relationships []*Relationship `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
}
relationships := &Relationships{
Relationships: root.Data.Relationships,
After: root.Data.After,
Before: root.Data.Before,
}
return relationships, resp, nil
}
// WikiContributors gets contributors of the wiki from the subreddit.
func (s *SubredditService) WikiContributors(ctx context.Context, subreddit string, opts *ListOptions) (*Relationships, *Response, error) {
path := fmt.Sprintf("r/%s/about/wikicontributors", 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
}
root := new(struct {
Data struct {
Relationships []*Relationship `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
}
relationships := &Relationships{
Relationships: root.Data.Relationships,
After: root.Data.After,
Before: root.Data.Before,
}
return relationships, resp, nil
}
// Moderators gets the moderators of the subreddit.
func (s *SubredditService) Moderators(ctx context.Context, subreddit string) ([]*Moderator, *Response, error) {
path := fmt.Sprintf("r/%s/about/moderators", subreddit)
req, err := s.client.NewRequest(http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}
root := new(struct {
Data struct {
Moderators []*Moderator `json:"children"`
} `json:"data"`
})
resp, err := s.client.Do(ctx, req, root)
if err != nil {
return nil, resp, err
}
return root.Data.Moderators, resp, nil
} }

View file

@ -200,11 +200,6 @@ var expectedSearchPosts = &Posts{
After: "t3_hmwhd7", After: "t3_hmwhd7",
} }
var expectedModerators = []Moderator{
{ID: "t2_test1", Name: "testuser1", Permissions: []string{"all"}},
{ID: "t2_test2", Name: "testuser2", Permissions: []string{"all"}},
}
var expectedRandomSubreddit = &Subreddit{ var expectedRandomSubreddit = &Subreddit{
FullID: "t5_2wi4l", FullID: "t5_2wi4l",
Created: &Timestamp{time.Date(2013, 3, 1, 4, 4, 18, 0, time.UTC)}, Created: &Timestamp{time.Date(2013, 3, 1, 4, 4, 18, 0, time.UTC)},
@ -219,24 +214,47 @@ var expectedRandomSubreddit = &Subreddit{
Subscribers: 52357, Subscribers: 52357,
} }
var expectedRelationships3 = &Relationships{
Relationships: []*Relationship{
{
ID: "rel_id1",
Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 2, 0, time.UTC)},
User: "testuser1",
UserID: "t2_user1",
},
{
ID: "rel_id2",
Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 0, 0, time.UTC)},
User: "testuser2",
UserID: "t2_user2",
},
},
After: "",
Before: "",
}
var expectedBans = &Bans{ var expectedBans = &Bans{
Bans: []*Ban{ Bans: []*Ban{
{ {
Relationship: &Relationship{
ID: "rb_123", ID: "rb_123",
Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 2, 0, time.UTC)}, Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 2, 0, time.UTC)},
User: "testuser1", User: "testuser1",
UserID: "t2_user1", UserID: "t2_user1",
},
DaysLeft: Int(43), DaysLeft: Int(43),
Note: "Spam", Note: "Spam",
}, },
{ {
Relationship: &Relationship{
ID: "rb_456", ID: "rb_456",
Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 0, 0, time.UTC)}, Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 0, 0, time.UTC)},
User: "testuser2", User: "testuser2",
UserID: "t2_user2", UserID: "t2_user2",
},
DaysLeft: nil, DaysLeft: nil,
Note: "Spam", Note: "Spam",
@ -246,25 +264,25 @@ var expectedBans = &Bans{
Before: "", Before: "",
} }
var expectedMutes = &Mutes{ var expectedModerators = []*Moderator{
Mutes: []*Mute{
{ {
ID: "Mute_123", Relationship: &Relationship{
Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 2, 0, time.UTC)}, ID: "rb_tmatb9",
User: "testuser1", User: "testuser1",
UserID: "t2_user1", UserID: "t2_test1",
Created: &Timestamp{time.Date(2013, 7, 29, 20, 44, 27, 0, time.UTC)},
},
Permissions: []string{"all"},
}, },
{ {
ID: "Mute_456", Relationship: &Relationship{
Created: &Timestamp{time.Date(2020, 8, 11, 2, 35, 0, 0, time.UTC)}, ID: "rb_5c9s4d",
User: "testuser2", User: "testuser2",
UserID: "t2_user2", UserID: "t2_test2",
Created: &Timestamp{time.Date(2014, 3, 1, 18, 13, 53, 0, time.UTC)},
}, },
Permissions: []string{"all"},
}, },
After: "",
Before: "",
} }
func TestSubredditService_HotPosts(t *testing.T) { func TestSubredditService_HotPosts(t *testing.T) {
@ -791,23 +809,6 @@ func TestSubredditService_SearchPosts_InSubreddits(t *testing.T) {
assert.Equal(t, expectedSearchPosts, posts) assert.Equal(t, expectedSearchPosts, posts)
} }
func TestSubredditService_Moderators(t *testing.T) {
setup()
defer teardown()
blob, err := readFileContents("testdata/subreddit/moderators.json")
assert.NoError(t, err)
mux.HandleFunc("/r/test/about/moderators", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method)
fmt.Fprint(w, blob)
})
moderators, _, err := client.Subreddit.Moderators(ctx, "test")
assert.NoError(t, err)
assert.Equal(t, expectedModerators, moderators)
}
func TestSubredditService_Random(t *testing.T) { func TestSubredditService_Random(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
@ -901,7 +902,7 @@ func TestSubredditService_Muted(t *testing.T) {
setup() setup()
defer teardown() defer teardown()
blob, err := readFileContents("testdata/subreddit/muted-users.json") blob, err := readFileContents("testdata/subreddit/relationships.json")
assert.NoError(t, err) assert.NoError(t, err)
mux.HandleFunc("/r/test/about/muted", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/r/test/about/muted", func(w http.ResponseWriter, r *http.Request) {
@ -920,5 +921,98 @@ func TestSubredditService_Muted(t *testing.T) {
mutes, _, err := client.Subreddit.Muted(ctx, "test", &ListOptions{Before: "testbefore", Limit: 50}) mutes, _, err := client.Subreddit.Muted(ctx, "test", &ListOptions{Before: "testbefore", Limit: 50})
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, expectedMutes, mutes) assert.Equal(t, expectedRelationships3, mutes)
}
func TestSubredditService_WikiBanned(t *testing.T) {
setup()
defer teardown()
blob, err := readFileContents("testdata/subreddit/banned-users.json")
assert.NoError(t, err)
mux.HandleFunc("/r/test/about/wikibanned", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method)
form := url.Values{}
form.Set("after", "testafter")
form.Set("limit", "15")
err := r.ParseForm()
assert.NoError(t, err)
assert.Equal(t, form, r.Form)
fmt.Fprint(w, blob)
})
bans, _, err := client.Subreddit.WikiBanned(ctx, "test", &ListOptions{After: "testafter", Limit: 15})
assert.NoError(t, err)
assert.Equal(t, expectedBans, bans)
}
func TestSubredditService_Contributors(t *testing.T) {
setup()
defer teardown()
blob, err := readFileContents("testdata/subreddit/relationships.json")
assert.NoError(t, err)
mux.HandleFunc("/r/test/about/contributors", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method)
form := url.Values{}
form.Set("limit", "5")
err := r.ParseForm()
assert.NoError(t, err)
assert.Equal(t, form, r.Form)
fmt.Fprint(w, blob)
})
contributors, _, err := client.Subreddit.Contributors(ctx, "test", &ListOptions{Limit: 5})
assert.NoError(t, err)
assert.Equal(t, expectedRelationships3, contributors)
}
func TestSubredditService_WikiContributors(t *testing.T) {
setup()
defer teardown()
blob, err := readFileContents("testdata/subreddit/relationships.json")
assert.NoError(t, err)
mux.HandleFunc("/r/test/about/wikicontributors", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method)
form := url.Values{}
form.Set("limit", "99")
err := r.ParseForm()
assert.NoError(t, err)
assert.Equal(t, form, r.Form)
fmt.Fprint(w, blob)
})
contributors, _, err := client.Subreddit.WikiContributors(ctx, "test", &ListOptions{Limit: 99})
assert.NoError(t, err)
assert.Equal(t, expectedRelationships3, contributors)
}
func TestSubredditService_Moderators(t *testing.T) {
setup()
defer teardown()
blob, err := readFileContents("testdata/subreddit/moderators.json")
assert.NoError(t, err)
mux.HandleFunc("/r/test/about/moderators", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, http.MethodGet, r.Method)
fmt.Fprint(w, blob)
})
moderators, _, err := client.Subreddit.Moderators(ctx, "test")
assert.NoError(t, err)
assert.Equal(t, expectedModerators, moderators)
} }

View file

@ -6,13 +6,13 @@
"children": [ "children": [
{ {
"date": 1597113302.0, "date": 1597113302.0,
"rel_id": "Mute_123", "rel_id": "rel_id1",
"name": "testuser1", "name": "testuser1",
"id": "t2_user1" "id": "t2_user1"
}, },
{ {
"date": 1597113300.0, "date": 1597113300.0,
"rel_id": "Mute_456", "rel_id": "rel_id2",
"name": "testuser2", "name": "testuser2",
"id": "t2_user2" "id": "t2_user2"
} }

View file

@ -49,14 +49,6 @@ type UserSummary struct {
NSFW bool `json:"profile_over_18"` NSFW bool `json:"profile_over_18"`
} }
// Relationship holds information about a relationship (friend/blocked).
type Relationship struct {
ID string `json:"rel_id,omitempty"`
User string `json:"name,omitempty"`
UserID string `json:"id,omitempty"`
Created *Timestamp `json:"date,omitempty"`
}
// Blocked represents a blocked relationship. // Blocked represents a blocked relationship.
type Blocked struct { type Blocked struct {
Blocked string `json:"name,omitempty"` Blocked string `json:"name,omitempty"`