From 2a1806ec3334e1d25a96f2e2b3b6520ea010d55f Mon Sep 17 00:00:00 2001 From: Vartan Benohanian Date: Sat, 29 Aug 2020 14:20:30 -0400 Subject: [PATCH] Revamp listing decoding, include after/before anchors in response Now, instead of returning an object containing a list of results + the anchors, we return just the list. The anchors are available in the response object. Much cleaner this way in my opinion go-github and godo do it this way too. They include some meta information in the returned response objects Signed-off-by: Vartan Benohanian --- README.md | 4 +- examples/get-top-posts/main.go | 12 +- reddit/emoji.go | 2 +- reddit/listings.go | 13 +- reddit/moderation.go | 14 +- reddit/moderation_test.go | 83 ++++----- reddit/post.go | 11 +- reddit/post_test.go | 91 +++++----- reddit/reddit.go | 15 ++ reddit/stream.go | 24 +-- reddit/subreddit.go | 48 ++--- reddit/subreddit_test.go | 315 +++++++++++++++++---------------- reddit/things.go | 154 ++++++---------- reddit/user.go | 76 ++++---- reddit/user_test.go | 237 ++++++++++++------------- 15 files changed, 520 insertions(+), 579 deletions(-) diff --git a/README.md b/README.md index 25f313b..a6a70b7 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ if err != nil { Get r/golang's top 5 posts of all time. ```go -result, _, err := client.Subreddit.TopPosts(context.Background(), "golang", &reddit.ListPostOptions{ +posts, _, err := client.Subreddit.TopPosts(context.Background(), "golang", &reddit.ListPostOptions{ ListOptions: reddit.ListOptions{ Limit: 5, }, @@ -99,7 +99,7 @@ result, _, err := client.Subreddit.TopPosts(context.Background(), "golang", &red if err != nil { return err } -fmt.Printf("Received %d posts.\n", len(result.Posts)) +fmt.Printf("Received %d posts.\n", len(posts)) ``` diff --git a/examples/get-top-posts/main.go b/examples/get-top-posts/main.go index bc876b7..6a797f1 100644 --- a/examples/get-top-posts/main.go +++ b/examples/get-top-posts/main.go @@ -20,7 +20,7 @@ func run() (err error) { // Let's get the top 200 posts of r/golang. // Reddit returns a maximum of 100 posts at a time, // so we'll need to separate this into 2 requests. - result, _, err := reddit.DefaultClient.Subreddit.TopPosts(ctx, "golang", &reddit.ListPostOptions{ + posts, resp, err := reddit.DefaultClient.Subreddit.TopPosts(ctx, "golang", &reddit.ListPostOptions{ ListOptions: reddit.ListOptions{ Limit: 100, }, @@ -30,16 +30,16 @@ func run() (err error) { return } - for _, post := range result.Posts { + for _, post := range posts { fmt.Println(post.Title) } - // The SetAfter option sets the id of an item that Reddit + // The After option sets the id of an item that Reddit // will use as an anchor point for the returned listing. - result, _, err = reddit.DefaultClient.Subreddit.TopPosts(ctx, "golang", &reddit.ListPostOptions{ + posts, _, err = reddit.DefaultClient.Subreddit.TopPosts(ctx, "golang", &reddit.ListPostOptions{ ListOptions: reddit.ListOptions{ Limit: 100, - After: result.After, + After: resp.After, }, Time: "all", }) @@ -47,7 +47,7 @@ func run() (err error) { return } - for _, post := range result.Posts { + for _, post := range posts { fmt.Println(post.Title) } diff --git a/reddit/emoji.go b/reddit/emoji.go index b33d77a..81d2386 100644 --- a/reddit/emoji.go +++ b/reddit/emoji.go @@ -252,7 +252,7 @@ func (s *EmojiService) Upload(ctx context.Context, subreddit string, createReque err = CheckResponse(httpResponse) if err != nil { - return &Response{httpResponse}, err + return newResponse(httpResponse), err } return s.upload(ctx, subreddit, createRequest, fields["key"]) diff --git a/reddit/listings.go b/reddit/listings.go index ba889f2..9fd3228 100644 --- a/reddit/listings.go +++ b/reddit/listings.go @@ -24,17 +24,13 @@ func (s *ListingsService) Get(ctx context.Context, ids ...string) ([]*Post, []*C return nil, nil, nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, nil, nil, resp, err } - posts := root.getPosts().Posts - comments := root.getComments().Comments - subreddits := root.getSubreddits().Subreddits - - return posts, comments, subreddits, resp, nil + return root.Posts, root.Comments, root.Subreddits, resp, nil } // GetPosts returns posts from their full IDs. @@ -46,12 +42,11 @@ func (s *ListingsService) GetPosts(ctx context.Context, ids ...string) ([]*Post, return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - posts := root.getPosts().Posts - return posts, resp, nil + return root.Posts, resp, nil } diff --git a/reddit/moderation.go b/reddit/moderation.go index 92ebdd4..f6bbb5b 100644 --- a/reddit/moderation.go +++ b/reddit/moderation.go @@ -42,8 +42,8 @@ type ModAction struct { SubredditID string `json:"sr_id36,omitempty"` } -// GetActions gets a list of moderator actions on a subreddit. -func (s *ModerationService) GetActions(ctx context.Context, subreddit string, opts *ListModActionOptions) (*ModActions, *Response, error) { +// Actions gets a list of moderator actions on a subreddit. +func (s *ModerationService) Actions(ctx context.Context, subreddit string, opts *ListModActionOptions) ([]*ModAction, *Response, error) { path := fmt.Sprintf("r/%s/about/log", subreddit) path, err := addOptions(path, opts) if err != nil { @@ -60,13 +60,13 @@ func (s *ModerationService) GetActions(ctx context.Context, subreddit string, op return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getModActions(), resp, nil + return root.ModActions, resp, nil } // AcceptInvite accepts a pending invite to moderate the specified subreddit. @@ -162,7 +162,7 @@ func (s *ModerationService) LeaveContributor(ctx context.Context, subredditID st } // Edited gets posts and comments that have been edited recently. -func (s *ModerationService) Edited(ctx context.Context, subreddit string, opts *ListOptions) (*Posts, *Comments, *Response, error) { +func (s *ModerationService) Edited(ctx context.Context, subreddit string, opts *ListOptions) ([]*Post, []*Comment, *Response, error) { path := fmt.Sprintf("r/%s/about/edited", subreddit) path, err := addOptions(path, opts) @@ -175,13 +175,13 @@ func (s *ModerationService) Edited(ctx context.Context, subreddit string, opts * return nil, nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, nil, nil, err } - return root.getPosts(), root.getComments(), resp, nil + return root.Posts, root.Comments, resp, nil } // IgnoreReports prevents reports on a post or comment from causing notifications. diff --git a/reddit/moderation_test.go b/reddit/moderation_test.go index 1191352..4ccc2b0 100644 --- a/reddit/moderation_test.go +++ b/reddit/moderation_test.go @@ -10,46 +10,42 @@ import ( "github.com/stretchr/testify/require" ) -var expectedModActions = &ModActions{ - ModActions: []*ModAction{ - { - ID: "ModAction_b4e7979a-c4ad-11ea-8440-0ea1b7c2b8f9", - Action: "spamcomment", - Created: &Timestamp{time.Date(2020, 7, 13, 2, 8, 14, 0, time.UTC)}, +var expectedModActions = []*ModAction{ + { + ID: "ModAction_b4e7979a-c4ad-11ea-8440-0ea1b7c2b8f9", + Action: "spamcomment", + Created: &Timestamp{time.Date(2020, 7, 13, 2, 8, 14, 0, time.UTC)}, - Moderator: "v_95", - ModeratorID: "164ab8", + Moderator: "v_95", + ModeratorID: "164ab8", - TargetAuthor: "testuser", - TargetID: "t1_fxw10aa", - TargetPermalink: "/r/helloworldtestt/comments/hq6r3t/yo/fxw10aa/", - TargetBody: "hi", + TargetAuthor: "testuser", + TargetID: "t1_fxw10aa", + TargetPermalink: "/r/helloworldtestt/comments/hq6r3t/yo/fxw10aa/", + TargetBody: "hi", - Subreddit: "helloworldtestt", - SubredditID: "2uquw1", - }, - { - ID: "ModAction_a0408162-c4ad-11ea-8239-0e3b48262e8b", - Action: "sticky", - Created: &Timestamp{time.Date(2020, 7, 13, 2, 7, 38, 0, time.UTC)}, - - Moderator: "v_95", - ModeratorID: "164ab8", - - TargetAuthor: "testuser", - TargetID: "t3_hq6r3t", - TargetTitle: "yo", - TargetPermalink: "/r/helloworldtestt/comments/hq6r3t/yo/", - - Subreddit: "helloworldtestt", - SubredditID: "2uquw1", - }, + Subreddit: "helloworldtestt", + SubredditID: "2uquw1", + }, + { + ID: "ModAction_a0408162-c4ad-11ea-8239-0e3b48262e8b", + Action: "sticky", + Created: &Timestamp{time.Date(2020, 7, 13, 2, 7, 38, 0, time.UTC)}, + + Moderator: "v_95", + ModeratorID: "164ab8", + + TargetAuthor: "testuser", + TargetID: "t3_hq6r3t", + TargetTitle: "yo", + TargetPermalink: "/r/helloworldtestt/comments/hq6r3t/yo/", + + Subreddit: "helloworldtestt", + SubredditID: "2uquw1", }, - After: "ModAction_a0408162-c4ad-11ea-8239-0e3b48262e8b", - Before: "", } -func TestModerationService_GetActions(t *testing.T) { +func TestModerationService_Actions(t *testing.T) { client, mux, teardown := setup() defer teardown() @@ -70,9 +66,10 @@ func TestModerationService_GetActions(t *testing.T) { fmt.Fprint(w, blob) }) - modActions, _, err := client.Moderation.GetActions(ctx, "testsubreddit", &ListModActionOptions{Type: "testtype", Moderator: "testmod"}) + modActions, resp, err := client.Moderation.Actions(ctx, "testsubreddit", &ListModActionOptions{Type: "testtype", Moderator: "testmod"}) require.NoError(t, err) require.Equal(t, expectedModActions, modActions) + require.Equal(t, "ModAction_a0408162-c4ad-11ea-8239-0e3b48262e8b", resp.After) } func TestModerationService_AcceptInvite(t *testing.T) { @@ -209,18 +206,16 @@ func TestModerationService_Edited(t *testing.T) { fmt.Fprint(w, blob) }) - posts, comments, _, err := client.Moderation.Edited(ctx, "testsubreddit", nil) + posts, comments, resp, err := client.Moderation.Edited(ctx, "testsubreddit", nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t1_f0zsa37", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) + require.Equal(t, "t1_f0zsa37", resp.After) - require.Len(t, comments.Comments, 1) - require.Equal(t, expectedComment, comments.Comments[0]) - require.Equal(t, "t1_f0zsa37", comments.After) - require.Equal(t, "", comments.Before) + require.Len(t, comments, 1) + require.Equal(t, expectedComment, comments[0]) + require.Equal(t, "t1_f0zsa37", resp.After) } func TestModerationService_IgnoreReports(t *testing.T) { diff --git a/reddit/post.go b/reddit/post.go index f510e65..98f13ed 100644 --- a/reddit/post.go +++ b/reddit/post.go @@ -84,7 +84,7 @@ func (s *PostService) Get(ctx context.Context, id string) (*PostAndComments, *Re // Duplicates returns the post with the id, and a list of its duplicates. // id is the ID36 of the post, not its full id. // Example: instead of t3_abc123, use abc123. -func (s *PostService) Duplicates(ctx context.Context, id string, opts *ListDuplicatePostOptions) (*Post, *Posts, *Response, error) { +func (s *PostService) Duplicates(ctx context.Context, id string, opts *ListDuplicatePostOptions) (*Post, []*Post, *Response, error) { path := fmt.Sprintf("duplicates/%s", id) path, err := addOptions(path, opts) if err != nil { @@ -96,14 +96,17 @@ func (s *PostService) Duplicates(ctx context.Context, id string, opts *ListDupli return nil, nil, nil, err } - var root [2]rootListing + var root [2]listing resp, err := s.client.Do(ctx, req, &root) if err != nil { return nil, nil, resp, err } - post := root[0].Data.Things.Posts[0] - duplicates := root[1].getPosts() + post := root[0].Posts[0] + duplicates := root[1].Posts + + resp.After = root[1].after + resp.Before = root[1].after return post, duplicates, resp, nil } diff --git a/reddit/post_test.go b/reddit/post_test.go index d50aedf..ee12658 100644 --- a/reddit/post_test.go +++ b/reddit/post_test.go @@ -155,59 +155,55 @@ var expectedPost2 = &Post{ AuthorID: "t2_164ab8", } -var expectedPostDuplicates = &Posts{ - Posts: []*Post{ - { - ID: "8kbs85", - FullID: "t3_8kbs85", - Created: &Timestamp{time.Date(2018, 5, 18, 9, 10, 18, 0, time.UTC)}, - Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, +var expectedPostDuplicates = []*Post{ + { + ID: "8kbs85", + FullID: "t3_8kbs85", + Created: &Timestamp{time.Date(2018, 5, 18, 9, 10, 18, 0, time.UTC)}, + Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, - Permalink: "/r/test/comments/8kbs85/test/", - URL: "http://example.com", + Permalink: "/r/test/comments/8kbs85/test/", + URL: "http://example.com", - Title: "test", + Title: "test", - Likes: nil, + Likes: nil, - Score: 1, - UpvoteRatio: 0.66, - NumberOfComments: 1, + Score: 1, + UpvoteRatio: 0.66, + NumberOfComments: 1, - SubredditName: "test", - SubredditNamePrefixed: "r/test", - SubredditID: "t5_2qh23", + SubredditName: "test", + SubredditNamePrefixed: "r/test", + SubredditID: "t5_2qh23", - Author: "GarlicoinAccount", - AuthorID: "t2_d2v1r90", - }, - { - ID: "le1tc", - FullID: "t3_le1tc", - Created: &Timestamp{time.Date(2011, 10, 16, 13, 26, 40, 0, time.UTC)}, - Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, - - Permalink: "/r/test/comments/le1tc/test_to_see_if_this_fixes_the_problem_of_my_likes/", - URL: "http://www.example.com", - - Title: "Test to see if this fixes the problem of my \"likes\" from the last 7 months vanishing.", - - Likes: nil, - - Score: 2, - UpvoteRatio: 1, - NumberOfComments: 1, - - SubredditName: "test", - SubredditNamePrefixed: "r/test", - SubredditID: "t5_2qh23", - - Author: "prog101", - AuthorID: "t2_8dyo", - }, + Author: "GarlicoinAccount", + AuthorID: "t2_d2v1r90", + }, + { + ID: "le1tc", + FullID: "t3_le1tc", + Created: &Timestamp{time.Date(2011, 10, 16, 13, 26, 40, 0, time.UTC)}, + Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, + + Permalink: "/r/test/comments/le1tc/test_to_see_if_this_fixes_the_problem_of_my_likes/", + URL: "http://www.example.com", + + Title: "Test to see if this fixes the problem of my \"likes\" from the last 7 months vanishing.", + + Likes: nil, + + Score: 2, + UpvoteRatio: 1, + NumberOfComments: 1, + + SubredditName: "test", + SubredditNamePrefixed: "r/test", + SubredditID: "t5_2qh23", + + Author: "prog101", + AuthorID: "t2_8dyo", }, - After: "t3_le1tc", - Before: "", } func TestPostService_Get(t *testing.T) { @@ -248,7 +244,7 @@ func TestPostService_Duplicates(t *testing.T) { fmt.Fprint(w, blob) }) - post, postDuplicates, _, err := client.Post.Duplicates(ctx, "abc123", &ListDuplicatePostOptions{ + post, postDuplicates, resp, err := client.Post.Duplicates(ctx, "abc123", &ListDuplicatePostOptions{ ListOptions: ListOptions{ Limit: 2, }, @@ -257,6 +253,7 @@ func TestPostService_Duplicates(t *testing.T) { require.NoError(t, err) require.Equal(t, expectedPost2, post) require.Equal(t, expectedPostDuplicates, postDuplicates) + require.Equal(t, "t3_le1tc", resp.After) } func TestPostService_SubmitText(t *testing.T) { diff --git a/reddit/reddit.go b/reddit/reddit.go index 616c9a6..cddf059 100644 --- a/reddit/reddit.go +++ b/reddit/reddit.go @@ -269,6 +269,12 @@ func (c *Client) NewRequestWithForm(method string, path string, form url.Values) // Response is a Reddit response. This wraps the standard http.Response returned from Reddit. type Response struct { *http.Response + + // Pagination anchor indicating there are more results after this id. + After string + // Pagination anchor indicating there are more results before this id. + // todo: not sure yet if responses ever contain this + Before string } // newResponse creates a new Response for the provided http.Response. @@ -277,6 +283,11 @@ func newResponse(r *http.Response) *Response { return &response } +func (r *Response) populateAnchors(a anchor) { + r.After = a.After() + r.Before = a.Before() +} + // Do sends an API request and returns the API response. The API response is JSON decoded and stored in the value // pointed to by v, or returned as an error if an API error has occurred. If v implements the io.Writer interface, // the raw response will be written to v, without attempting to decode it. @@ -310,6 +321,10 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Res return nil, err } } + + if anchor, ok := v.(anchor); ok { + response.populateAnchors(anchor) + } } return response, nil diff --git a/reddit/stream.go b/reddit/stream.go index 0f75f0e..14f5b85 100644 --- a/reddit/stream.go +++ b/reddit/stream.go @@ -29,15 +29,15 @@ func (s *StreamService) Posts(subreddit string, opts ...StreamOpt) (<-chan *Post } ticker := time.NewTicker(streamConfig.Interval) - posts := make(chan *Post) - errs := make(chan error) + postsCh := make(chan *Post) + errsCh := make(chan error) var once sync.Once stop := func() { once.Do(func() { ticker.Stop() - close(posts) - close(errs) + close(postsCh) + close(errsCh) }) } @@ -54,16 +54,16 @@ func (s *StreamService) Posts(subreddit string, opts ...StreamOpt) (<-chan *Post for ; ; <-ticker.C { n++ - result, err := s.getPosts(subreddit) + posts, err := s.getPosts(subreddit) if err != nil { - errs <- err + errsCh <- err if !infinite && n >= streamConfig.MaxRequests { break } continue } - for _, post := range result.Posts { + for _, post := range posts { id := post.FullID // if this post id is already part of the set, it means that it and the ones @@ -78,7 +78,7 @@ func (s *StreamService) Posts(subreddit string, opts ...StreamOpt) (<-chan *Post break } - posts <- post + postsCh <- post } if !infinite && n >= streamConfig.MaxRequests { @@ -87,12 +87,12 @@ func (s *StreamService) Posts(subreddit string, opts ...StreamOpt) (<-chan *Post } }() - return posts, errs, stop + return postsCh, errsCh, stop } -func (s *StreamService) getPosts(subreddit string) (*Posts, error) { - result, _, err := s.client.Subreddit.NewPosts(context.Background(), subreddit, &ListOptions{Limit: 100}) - return result, err +func (s *StreamService) getPosts(subreddit string) ([]*Post, error) { + posts, _, err := s.client.Subreddit.NewPosts(context.Background(), subreddit, &ListOptions{Limit: 100}) + return posts, err } type set map[string]struct{} diff --git a/reddit/subreddit.go b/reddit/subreddit.go index 3641749..4fb0348 100644 --- a/reddit/subreddit.go +++ b/reddit/subreddit.go @@ -63,7 +63,7 @@ type Bans struct { } // todo: interface{}, seriously? -func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit string, opts interface{}) (*Posts, *Response, error) { +func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit string, opts interface{}) ([]*Post, *Response, error) { path := sort if subreddit != "" { path = fmt.Sprintf("r/%s/%s", subreddit, sort) @@ -79,13 +79,13 @@ func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getPosts(), resp, nil + return root.Posts, resp, nil } // HotPosts returns the hottest posts from the specified subreddit. @@ -95,7 +95,7 @@ func (s *SubredditService) getPosts(ctx context.Context, sort string, subreddit // To search through all and filter out subreddits, provide "all-name1-name2". // Note: when looking for hot posts in a subreddit, it will include the stickied // posts (if any) PLUS posts from the limit parameter (25 by default). -func (s *SubredditService) HotPosts(ctx context.Context, subreddit string, opts *ListOptions) (*Posts, *Response, error) { +func (s *SubredditService) HotPosts(ctx context.Context, subreddit string, opts *ListOptions) ([]*Post, *Response, error) { return s.getPosts(ctx, "hot", subreddit, opts) } @@ -104,7 +104,7 @@ func (s *SubredditService) HotPosts(ctx context.Context, subreddit string, opts // If none are defined, it returns the ones from your subscribed subreddits. // To search through all, just specify "all". // To search through all and filter out subreddits, provide "all-name1-name2". -func (s *SubredditService) NewPosts(ctx context.Context, subreddit string, opts *ListOptions) (*Posts, *Response, error) { +func (s *SubredditService) NewPosts(ctx context.Context, subreddit string, opts *ListOptions) ([]*Post, *Response, error) { return s.getPosts(ctx, "new", subreddit, opts) } @@ -113,7 +113,7 @@ func (s *SubredditService) NewPosts(ctx context.Context, subreddit string, opts // If none are defined, it returns the ones from your subscribed subreddits. // To search through all, just specify "all". // To search through all and filter out subreddits, provide "all-name1-name2". -func (s *SubredditService) RisingPosts(ctx context.Context, subreddit string, opts *ListOptions) (*Posts, *Response, error) { +func (s *SubredditService) RisingPosts(ctx context.Context, subreddit string, opts *ListOptions) ([]*Post, *Response, error) { return s.getPosts(ctx, "rising", subreddit, opts) } @@ -122,7 +122,7 @@ func (s *SubredditService) RisingPosts(ctx context.Context, subreddit string, op // If none are defined, it returns the ones from your subscribed subreddits. // To search through all, just specify "all". // To search through all and filter out subreddits, provide "all-name1-name2". -func (s *SubredditService) ControversialPosts(ctx context.Context, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) { +func (s *SubredditService) ControversialPosts(ctx context.Context, subreddit string, opts *ListPostOptions) ([]*Post, *Response, error) { return s.getPosts(ctx, "controversial", subreddit, opts) } @@ -131,7 +131,7 @@ func (s *SubredditService) ControversialPosts(ctx context.Context, subreddit str // If none are defined, it returns the ones from your subscribed subreddits. // To search through all, just specify "all". // To search through all and filter out subreddits, provide "all-name1-name2". -func (s *SubredditService) TopPosts(ctx context.Context, subreddit string, opts *ListPostOptions) (*Posts, *Response, error) { +func (s *SubredditService) TopPosts(ctx context.Context, subreddit string, opts *ListPostOptions) ([]*Post, *Response, error) { return s.getPosts(ctx, "top", subreddit, opts) } @@ -157,38 +157,38 @@ func (s *SubredditService) Get(ctx context.Context, name string) (*Subreddit, *R } // Popular returns popular subreddits. -func (s *SubredditService) Popular(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) { +func (s *SubredditService) Popular(ctx context.Context, opts *ListSubredditOptions) ([]*Subreddit, *Response, error) { return s.getSubreddits(ctx, "subreddits/popular", opts) } // New returns new subreddits. -func (s *SubredditService) New(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) { +func (s *SubredditService) New(ctx context.Context, opts *ListSubredditOptions) ([]*Subreddit, *Response, error) { return s.getSubreddits(ctx, "subreddits/new", opts) } // Gold returns gold subreddits (i.e. only accessible to users with gold). // It seems like it returns an empty list if you don't have gold. -func (s *SubredditService) Gold(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) { +func (s *SubredditService) Gold(ctx context.Context, opts *ListSubredditOptions) ([]*Subreddit, *Response, error) { return s.getSubreddits(ctx, "subreddits/gold", opts) } // Default returns default subreddits. -func (s *SubredditService) Default(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) { +func (s *SubredditService) Default(ctx context.Context, opts *ListSubredditOptions) ([]*Subreddit, *Response, error) { return s.getSubreddits(ctx, "subreddits/default", opts) } // Subscribed returns the list of subreddits you are subscribed to. -func (s *SubredditService) Subscribed(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) { +func (s *SubredditService) Subscribed(ctx context.Context, opts *ListSubredditOptions) ([]*Subreddit, *Response, error) { return s.getSubreddits(ctx, "subreddits/mine/subscriber", opts) } // Approved returns the list of subreddits you are an approved user in. -func (s *SubredditService) Approved(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) { +func (s *SubredditService) Approved(ctx context.Context, opts *ListSubredditOptions) ([]*Subreddit, *Response, error) { return s.getSubreddits(ctx, "subreddits/mine/contributor", opts) } // Moderated returns the list of subreddits you are a moderator of. -func (s *SubredditService) Moderated(ctx context.Context, opts *ListSubredditOptions) (*Subreddits, *Response, error) { +func (s *SubredditService) Moderated(ctx context.Context, opts *ListSubredditOptions) ([]*Subreddit, *Response, error) { return s.getSubreddits(ctx, "subreddits/mine/moderator", opts) } @@ -280,7 +280,7 @@ func (s *SubredditService) Unfavorite(ctx context.Context, subreddit string) (*R } // Search for subreddits. -func (s *SubredditService) Search(ctx context.Context, query string, opts *ListSubredditOptions) (*Subreddits, *Response, error) { +func (s *SubredditService) Search(ctx context.Context, query string, opts *ListSubredditOptions) ([]*Subreddit, *Response, error) { path := "subreddits/search" path, err := addOptions(path, opts) if err != nil { @@ -300,13 +300,13 @@ func (s *SubredditService) Search(ctx context.Context, query string, opts *ListS return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getSubreddits(), resp, nil + return root.Subreddits, resp, nil } // SearchNames searches for subreddits with names beginning with the query provided. @@ -330,7 +330,7 @@ func (s *SubredditService) SearchNames(ctx context.Context, query string) ([]str // SearchPosts searches for posts in the specified subreddit. // To search through multiple, separate the names with a plus (+), e.g. "golang+test". // If no subreddit is provided, the search is run against r/all. -func (s *SubredditService) SearchPosts(ctx context.Context, query string, subreddit string, opts *ListPostSearchOptions) (*Posts, *Response, error) { +func (s *SubredditService) SearchPosts(ctx context.Context, query string, subreddit string, opts *ListPostSearchOptions) ([]*Post, *Response, error) { if subreddit == "" { subreddit = "all" } @@ -357,16 +357,16 @@ func (s *SubredditService) SearchPosts(ctx context.Context, query string, subred return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getPosts(), resp, nil + return root.Posts, resp, nil } -func (s *SubredditService) getSubreddits(ctx context.Context, path string, opts *ListSubredditOptions) (*Subreddits, *Response, error) { +func (s *SubredditService) getSubreddits(ctx context.Context, path string, opts *ListSubredditOptions) ([]*Subreddit, *Response, error) { path, err := addOptions(path, opts) if err != nil { return nil, nil, err @@ -377,13 +377,13 @@ func (s *SubredditService) getSubreddits(ctx context.Context, path string, opts return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getSubreddits(), resp, nil + return root.Subreddits, resp, nil } // getSticky returns one of the 2 stickied posts of the subreddit (if they exist). diff --git a/reddit/subreddit_test.go b/reddit/subreddit_test.go index 2488da3..8519a8b 100644 --- a/reddit/subreddit_test.go +++ b/reddit/subreddit_test.go @@ -10,59 +10,55 @@ import ( "github.com/stretchr/testify/require" ) -var expectedPosts = &Posts{ - Posts: []*Post{ - { - ID: "agi5zf", - FullID: "t3_agi5zf", - Created: &Timestamp{time.Date(2019, 1, 16, 5, 57, 51, 0, time.UTC)}, - Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, +var expectedPosts = []*Post{ + { + ID: "agi5zf", + FullID: "t3_agi5zf", + Created: &Timestamp{time.Date(2019, 1, 16, 5, 57, 51, 0, time.UTC)}, + Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, - Permalink: "/r/test/comments/agi5zf/test/", - URL: "https://www.reddit.com/r/test/comments/agi5zf/test/", + Permalink: "/r/test/comments/agi5zf/test/", + URL: "https://www.reddit.com/r/test/comments/agi5zf/test/", - Title: "test", - Body: "test", + Title: "test", + Body: "test", - Score: 253, - UpvoteRatio: 0.99, - NumberOfComments: 1634, + Score: 253, + UpvoteRatio: 0.99, + NumberOfComments: 1634, - SubredditName: "test", - SubredditNamePrefixed: "r/test", - SubredditID: "t5_2qh23", + SubredditName: "test", + SubredditNamePrefixed: "r/test", + SubredditID: "t5_2qh23", - Author: "kmiller0112", - AuthorID: "t2_30a5ktgt", + Author: "kmiller0112", + AuthorID: "t2_30a5ktgt", - IsSelfPost: true, - Stickied: true, - }, - { - ID: "hyhquk", - FullID: "t3_hyhquk", - Created: &Timestamp{time.Date(2020, 7, 27, 0, 5, 10, 0, time.UTC)}, - Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, - - Permalink: "/r/test/comments/hyhquk/veggies/", - URL: "https://i.imgur.com/LrN2mPw.jpg", - - Title: "Veggies", - - Score: 4, - UpvoteRatio: 1, - NumberOfComments: 0, - - SubredditName: "test", - SubredditNamePrefixed: "r/test", - SubredditID: "t5_2qh23", - - Author: "MuckleMcDuckle", - AuthorID: "t2_6fqntbwq", - }, + IsSelfPost: true, + Stickied: true, + }, + { + ID: "hyhquk", + FullID: "t3_hyhquk", + Created: &Timestamp{time.Date(2020, 7, 27, 0, 5, 10, 0, time.UTC)}, + Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, + + Permalink: "/r/test/comments/hyhquk/veggies/", + URL: "https://i.imgur.com/LrN2mPw.jpg", + + Title: "Veggies", + + Score: 4, + UpvoteRatio: 1, + NumberOfComments: 0, + + SubredditName: "test", + SubredditNamePrefixed: "r/test", + SubredditID: "t5_2qh23", + + Author: "MuckleMcDuckle", + AuthorID: "t2_6fqntbwq", }, - After: "t3_hyhquk", - Before: "", } var expectedSubreddit = &Subreddit{ @@ -84,63 +80,59 @@ var expectedSubreddit = &Subreddit{ Subscribed: true, } -var expectedSubreddits = &Subreddits{ - After: "t5_2qh0u", - Before: "", - Subreddits: []*Subreddit{ - { - ID: "2qs0k", - FullID: "t5_2qs0k", - Created: &Timestamp{time.Date(2009, 1, 25, 2, 25, 57, 0, time.UTC)}, +var expectedSubreddits = []*Subreddit{ + { + ID: "2qs0k", + FullID: "t5_2qs0k", + Created: &Timestamp{time.Date(2009, 1, 25, 2, 25, 57, 0, time.UTC)}, - URL: "/r/Home/", - Name: "Home", - NamePrefixed: "r/Home", - Title: "Home", - Type: "public", + URL: "/r/Home/", + Name: "Home", + NamePrefixed: "r/Home", + Title: "Home", + Type: "public", - Subscribers: 15336, - NSFW: false, - UserIsMod: false, - Subscribed: true, - Favorite: false, - }, - { - ID: "2qh1i", - FullID: "t5_2qh1i", - Created: &Timestamp{time.Date(2008, 1, 25, 3, 52, 15, 0, time.UTC)}, + Subscribers: 15336, + NSFW: false, + UserIsMod: false, + Subscribed: true, + Favorite: false, + }, + { + ID: "2qh1i", + FullID: "t5_2qh1i", + Created: &Timestamp{time.Date(2008, 1, 25, 3, 52, 15, 0, time.UTC)}, - URL: "/r/AskReddit/", - Name: "AskReddit", - NamePrefixed: "r/AskReddit", - Title: "Ask Reddit...", - Description: "r/AskReddit is the place to ask and answer thought-provoking questions.", - Type: "public", + URL: "/r/AskReddit/", + Name: "AskReddit", + NamePrefixed: "r/AskReddit", + Title: "Ask Reddit...", + Description: "r/AskReddit is the place to ask and answer thought-provoking questions.", + Type: "public", - Subscribers: 28449174, - NSFW: false, - UserIsMod: false, - Subscribed: true, - Favorite: true, - }, - { - ID: "2qh0u", - FullID: "t5_2qh0u", - Created: &Timestamp{time.Date(2008, 1, 25, 0, 31, 9, 0, time.UTC)}, + Subscribers: 28449174, + NSFW: false, + UserIsMod: false, + Subscribed: true, + Favorite: true, + }, + { + ID: "2qh0u", + FullID: "t5_2qh0u", + Created: &Timestamp{time.Date(2008, 1, 25, 0, 31, 9, 0, time.UTC)}, - URL: "/r/pics/", - Name: "pics", - NamePrefixed: "r/pics", - Title: "Reddit Pics", - Description: "A place for pictures and photographs.", - Type: "public", + URL: "/r/pics/", + Name: "pics", + NamePrefixed: "r/pics", + Title: "Reddit Pics", + Description: "A place for pictures and photographs.", + Type: "public", - Subscribers: 24987753, - NSFW: false, - UserIsMod: false, - Subscribed: false, - Favorite: false, - }, + Subscribers: 24987753, + NSFW: false, + UserIsMod: false, + Subscribed: false, + Favorite: false, }, } @@ -154,54 +146,51 @@ var expectedSubredditNames = []string{ "golang_jobs", } -var expectedSearchPosts = &Posts{ - Posts: []*Post{ - { - ID: "hybow9", - FullID: "t3_hybow9", - Created: &Timestamp{time.Date(2020, 7, 26, 18, 14, 24, 0, time.UTC)}, - Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, +var expectedSearchPosts = []*Post{ + { + ID: "hybow9", + FullID: "t3_hybow9", + Created: &Timestamp{time.Date(2020, 7, 26, 18, 14, 24, 0, time.UTC)}, + Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, - Permalink: "/r/WatchPeopleDieInside/comments/hybow9/pregnancy_test/", - URL: "https://v.redd.it/ra4qnt8bt8d51", + Permalink: "/r/WatchPeopleDieInside/comments/hybow9/pregnancy_test/", + URL: "https://v.redd.it/ra4qnt8bt8d51", - Title: "Pregnancy test", + Title: "Pregnancy test", - Score: 103829, - UpvoteRatio: 0.88, - NumberOfComments: 3748, + Score: 103829, + UpvoteRatio: 0.88, + NumberOfComments: 3748, - SubredditName: "WatchPeopleDieInside", - SubredditNamePrefixed: "r/WatchPeopleDieInside", - SubredditID: "t5_3h4zq", + SubredditName: "WatchPeopleDieInside", + SubredditNamePrefixed: "r/WatchPeopleDieInside", + SubredditID: "t5_3h4zq", - Author: "chocolat_ice_cream", - AuthorID: "t2_3p32m02", - }, - { - ID: "hmwhd7", - FullID: "t3_hmwhd7", - Created: &Timestamp{time.Date(2020, 7, 7, 15, 19, 42, 0, time.UTC)}, - Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, - - Permalink: "/r/worldnews/comments/hmwhd7/brazilian_president_jair_bolsonaro_tests_positive/", - URL: "https://www.theguardian.com/world/2020/jul/07/jair-bolsonaro-coronavirus-positive-test-brazil-president", - - Title: "Brazilian president Jair Bolsonaro tests positive for coronavirus", - - Score: 149238, - UpvoteRatio: 0.94, - NumberOfComments: 7415, - - SubredditName: "worldnews", - SubredditNamePrefixed: "r/worldnews", - SubredditID: "t5_2qh13", - - Author: "Jeremy_Martin", - AuthorID: "t2_wgrkg", - }, + Author: "chocolat_ice_cream", + AuthorID: "t2_3p32m02", + }, + { + ID: "hmwhd7", + FullID: "t3_hmwhd7", + Created: &Timestamp{time.Date(2020, 7, 7, 15, 19, 42, 0, time.UTC)}, + Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)}, + + Permalink: "/r/worldnews/comments/hmwhd7/brazilian_president_jair_bolsonaro_tests_positive/", + URL: "https://www.theguardian.com/world/2020/jul/07/jair-bolsonaro-coronavirus-positive-test-brazil-president", + + Title: "Brazilian president Jair Bolsonaro tests positive for coronavirus", + + Score: 149238, + UpvoteRatio: 0.94, + NumberOfComments: 7415, + + SubredditName: "worldnews", + SubredditNamePrefixed: "r/worldnews", + SubredditID: "t5_2qh13", + + Author: "Jeremy_Martin", + AuthorID: "t2_wgrkg", }, - After: "t3_hmwhd7", } var expectedRandomSubreddit = &Subreddit{ @@ -301,9 +290,10 @@ func TestSubredditService_HotPosts(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.Subreddit.HotPosts(ctx, "test", nil) + posts, resp, err := client.Subreddit.HotPosts(ctx, "test", nil) require.NoError(t, err) require.Equal(t, expectedPosts, posts) + require.Equal(t, "t3_hyhquk", resp.After) } func TestSubredditService_NewPosts(t *testing.T) { @@ -318,9 +308,10 @@ func TestSubredditService_NewPosts(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.Subreddit.NewPosts(ctx, "test", nil) + posts, resp, err := client.Subreddit.NewPosts(ctx, "test", nil) require.NoError(t, err) require.Equal(t, expectedPosts, posts) + require.Equal(t, "t3_hyhquk", resp.After) } func TestSubredditService_RisingPosts(t *testing.T) { @@ -335,9 +326,10 @@ func TestSubredditService_RisingPosts(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.Subreddit.RisingPosts(ctx, "test", nil) + posts, resp, err := client.Subreddit.RisingPosts(ctx, "test", nil) require.NoError(t, err) require.Equal(t, expectedPosts, posts) + require.Equal(t, "t3_hyhquk", resp.After) } func TestSubredditService_ControversialPosts(t *testing.T) { @@ -352,9 +344,10 @@ func TestSubredditService_ControversialPosts(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.Subreddit.ControversialPosts(ctx, "test", nil) + posts, resp, err := client.Subreddit.ControversialPosts(ctx, "test", nil) require.NoError(t, err) require.Equal(t, expectedPosts, posts) + require.Equal(t, "t3_hyhquk", resp.After) } func TestSubredditService_TopPosts(t *testing.T) { @@ -369,9 +362,10 @@ func TestSubredditService_TopPosts(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.Subreddit.TopPosts(ctx, "test", nil) + posts, resp, err := client.Subreddit.TopPosts(ctx, "test", nil) require.NoError(t, err) require.Equal(t, expectedPosts, posts) + require.Equal(t, "t3_hyhquk", resp.After) } func TestSubredditService_Get(t *testing.T) { @@ -406,9 +400,10 @@ func TestSubredditService_Popular(t *testing.T) { fmt.Fprint(w, blob) }) - subreddits, _, err := client.Subreddit.Popular(ctx, nil) + subreddits, resp, err := client.Subreddit.Popular(ctx, nil) require.NoError(t, err) require.Equal(t, expectedSubreddits, subreddits) + require.Equal(t, "t5_2qh0u", resp.After) } func TestSubredditService_New(t *testing.T) { @@ -423,9 +418,10 @@ func TestSubredditService_New(t *testing.T) { fmt.Fprint(w, blob) }) - subreddits, _, err := client.Subreddit.New(ctx, nil) + subreddits, resp, err := client.Subreddit.New(ctx, nil) require.NoError(t, err) require.Equal(t, expectedSubreddits, subreddits) + require.Equal(t, "t5_2qh0u", resp.After) } func TestSubredditService_Gold(t *testing.T) { @@ -440,9 +436,10 @@ func TestSubredditService_Gold(t *testing.T) { fmt.Fprint(w, blob) }) - subreddits, _, err := client.Subreddit.Gold(ctx, nil) + subreddits, resp, err := client.Subreddit.Gold(ctx, nil) require.NoError(t, err) require.Equal(t, expectedSubreddits, subreddits) + require.Equal(t, "t5_2qh0u", resp.After) } func TestSubredditService_Default(t *testing.T) { @@ -457,9 +454,10 @@ func TestSubredditService_Default(t *testing.T) { fmt.Fprint(w, blob) }) - subreddits, _, err := client.Subreddit.Default(ctx, nil) + subreddits, resp, err := client.Subreddit.Default(ctx, nil) require.NoError(t, err) require.Equal(t, expectedSubreddits, subreddits) + require.Equal(t, "t5_2qh0u", resp.After) } func TestSubredditService_Subscribed(t *testing.T) { @@ -474,9 +472,10 @@ func TestSubredditService_Subscribed(t *testing.T) { fmt.Fprint(w, blob) }) - subreddits, _, err := client.Subreddit.Subscribed(ctx, nil) + subreddits, resp, err := client.Subreddit.Subscribed(ctx, nil) require.NoError(t, err) require.Equal(t, expectedSubreddits, subreddits) + require.Equal(t, "t5_2qh0u", resp.After) } func TestSubredditService_Approved(t *testing.T) { @@ -491,9 +490,10 @@ func TestSubredditService_Approved(t *testing.T) { fmt.Fprint(w, blob) }) - subreddits, _, err := client.Subreddit.Approved(ctx, nil) + subreddits, resp, err := client.Subreddit.Approved(ctx, nil) require.NoError(t, err) require.Equal(t, expectedSubreddits, subreddits) + require.Equal(t, "t5_2qh0u", resp.After) } func TestSubredditService_Moderated(t *testing.T) { @@ -508,9 +508,10 @@ func TestSubredditService_Moderated(t *testing.T) { fmt.Fprint(w, blob) }) - subreddits, _, err := client.Subreddit.Moderated(ctx, nil) + subreddits, resp, err := client.Subreddit.Moderated(ctx, nil) require.NoError(t, err) require.Equal(t, expectedSubreddits, subreddits) + require.Equal(t, "t5_2qh0u", resp.After) } func TestSubredditService_GetSticky1(t *testing.T) { @@ -701,7 +702,7 @@ func TestSubredditService_Search(t *testing.T) { fmt.Fprint(w, blob) }) - subreddits, _, err := client.Subreddit.Search(ctx, "golang", &ListSubredditOptions{ + subreddits, resp, err := client.Subreddit.Search(ctx, "golang", &ListSubredditOptions{ ListOptions: ListOptions{ Limit: 10, }, @@ -709,6 +710,7 @@ func TestSubredditService_Search(t *testing.T) { }) require.NoError(t, err) require.Equal(t, expectedSubreddits, subreddits) + require.Equal(t, "t5_2qh0u", resp.After) } func TestSubredditService_SearchNames(t *testing.T) { @@ -756,9 +758,10 @@ func TestSubredditService_SearchPosts(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.Subreddit.SearchPosts(ctx, "test", "", nil) + posts, resp, err := client.Subreddit.SearchPosts(ctx, "test", "", nil) require.NoError(t, err) require.Equal(t, expectedSearchPosts, posts) + require.Equal(t, "t3_hmwhd7", resp.After) } func TestSubredditService_SearchPosts_InSubreddit(t *testing.T) { @@ -782,9 +785,10 @@ func TestSubredditService_SearchPosts_InSubreddit(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.Subreddit.SearchPosts(ctx, "test", "test", nil) + posts, resp, err := client.Subreddit.SearchPosts(ctx, "test", "test", nil) require.NoError(t, err) require.Equal(t, expectedSearchPosts, posts) + require.Equal(t, "t3_hmwhd7", resp.After) } func TestSubredditService_SearchPosts_InSubreddits(t *testing.T) { @@ -808,9 +812,10 @@ func TestSubredditService_SearchPosts_InSubreddits(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.Subreddit.SearchPosts(ctx, "test", "test+golang+nba", nil) + posts, resp, err := client.Subreddit.SearchPosts(ctx, "test", "test+golang+nba", nil) require.NoError(t, err) require.Equal(t, expectedSearchPosts, posts) + require.Equal(t, "t3_hmwhd7", resp.After) } func TestSubredditService_Random(t *testing.T) { diff --git a/reddit/things.go b/reddit/things.go index a8049cb..5266848 100644 --- a/reddit/things.go +++ b/reddit/things.go @@ -20,24 +20,56 @@ const ( ) // thing is an entity on Reddit. -// Its kind reprsents what it is and what is stored in the Data field +// Its kind reprsents what it is and what is stored in the Data field. // e.g. t1 = comment, t2 = user, t3 = post, etc. type thing struct { Kind string `json:"kind"` Data json.RawMessage `json:"data"` } -type rootListing struct { - Kind string `json:"kind"` - Data listing `json:"data"` +type anchor interface { + After() string + Before() string } -// listing holds things coming from the Reddit API -// It also contains the after/before anchors useful for subsequent requests +// listing holds things coming from the Reddit API. +// It also contains the after/before anchors useful for subsequent requests. type listing struct { - Things things `json:"children"` - After string `json:"after"` - Before string `json:"before"` + things + after string + before string +} + +var _ anchor = &listing{} + +func (l *listing) After() string { + return l.after +} + +func (l *listing) Before() string { + return l.before +} + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (l *listing) UnmarshalJSON(b []byte) error { + root := new(struct { + Data struct { + Things things `json:"children"` + After string `json:"after"` + Before string `json:"before"` + } `json:"data"` + }) + + err := json.Unmarshal(b, root) + if err != nil { + return err + } + + l.things = root.Data.Things + l.after = root.Data.After + l.before = root.Data.Before + + return nil } type things struct { @@ -199,14 +231,16 @@ func (r *Replies) UnmarshalJSON(data []byte) error { return nil } - root := new(rootListing) + root := new(listing) err := json.Unmarshal(data, root) if err != nil { return err } - r.Comments = root.Data.Things.Comments - r.More = root.getFirstMore() + r.Comments = root.Comments + if len(root.Mores) > 0 { + r.More = root.Mores[0] + } return nil } @@ -289,88 +323,6 @@ type Subreddit struct { Favorite bool `json:"user_has_favorited"` } -func (l *rootListing) getComments() *Comments { - return &Comments{ - Comments: l.Data.Things.Comments, - After: l.Data.After, - Before: l.Data.Before, - } -} - -func (l *rootListing) getFirstMore() *More { - if len(l.Data.Things.Mores) == 0 { - return nil - } - return l.Data.Things.Mores[0] -} - -func (l *rootListing) getUsers() *Users { - return &Users{ - Users: l.Data.Things.Users, - After: l.Data.After, - Before: l.Data.Before, - } -} - -func (l *rootListing) getPosts() *Posts { - return &Posts{ - Posts: l.Data.Things.Posts, - After: l.Data.After, - Before: l.Data.Before, - } -} - -func (l *rootListing) getSubreddits() *Subreddits { - return &Subreddits{ - Subreddits: l.Data.Things.Subreddits, - After: l.Data.After, - Before: l.Data.Before, - } -} - -func (l *rootListing) getModActions() *ModActions { - return &ModActions{ - ModActions: l.Data.Things.ModActions, - After: l.Data.After, - Before: l.Data.Before, - } -} - -// Comments is a list of comments -type Comments struct { - Comments []*Comment `json:"comments"` - After string `json:"after"` - Before string `json:"before"` -} - -// Users is a list of users -type Users struct { - Users []*User `json:"users"` - After string `json:"after"` - Before string `json:"before"` -} - -// Subreddits is a list of subreddits -type Subreddits struct { - Subreddits []*Subreddit `json:"subreddits"` - After string `json:"after"` - Before string `json:"before"` -} - -// Posts is a list of posts. -type Posts struct { - Posts []*Post `json:"posts"` - After string `json:"after"` - Before string `json:"before"` -} - -// ModActions is a list of moderator actions. -type ModActions struct { - ModActions []*ModAction `json:"moderator_actions"` - After string `json:"after"` - Before string `json:"before"` -} - // PostAndComments is a post and its comments. type PostAndComments struct { Post *Post `json:"post"` @@ -383,20 +335,18 @@ type PostAndComments struct { // The 1st one contains the single post in its children array // The 2nd one contains the comments to the post func (pc *PostAndComments) UnmarshalJSON(data []byte) error { - var l [2]rootListing + var l [2]listing err := json.Unmarshal(data, &l) if err != nil { return err } - post := l[0].getPosts().Posts[0] - comments := l[1].getComments().Comments - moreComments := l[1].getFirstMore() - - pc.Post = post - pc.Comments = comments - pc.More = moreComments + pc.Post = l[0].Posts[0] + pc.Comments = l[1].Comments + if len(l[1].Mores) > 0 { + pc.More = l[1].Mores[0] + } return nil } diff --git a/reddit/user.go b/reddit/user.go index c27b507..1b8633c 100644 --- a/reddit/user.go +++ b/reddit/user.go @@ -146,12 +146,12 @@ func (s *UserService) UsernameAvailable(ctx context.Context, username string) (b } // Overview returns a list of your posts and comments. -func (s *UserService) Overview(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Comments, *Response, error) { +func (s *UserService) Overview(ctx context.Context, opts *ListUserOverviewOptions) ([]*Post, []*Comment, *Response, error) { return s.OverviewOf(ctx, s.client.Username, opts) } // OverviewOf returns a list of the user's posts and comments. -func (s *UserService) OverviewOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Posts, *Comments, *Response, error) { +func (s *UserService) OverviewOf(ctx context.Context, username string, opts *ListUserOverviewOptions) ([]*Post, []*Comment, *Response, error) { path := fmt.Sprintf("user/%s/overview", username) path, err := addOptions(path, opts) if err != nil { @@ -163,22 +163,22 @@ func (s *UserService) OverviewOf(ctx context.Context, username string, opts *Lis return nil, nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, nil, resp, err } - return root.getPosts(), root.getComments(), resp, nil + return root.Posts, root.Comments, resp, nil } // Posts returns a list of your posts. -func (s *UserService) Posts(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) { +func (s *UserService) Posts(ctx context.Context, opts *ListUserOverviewOptions) ([]*Post, *Response, error) { return s.PostsOf(ctx, s.client.Username, opts) } // PostsOf returns a list of the user's posts. -func (s *UserService) PostsOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Posts, *Response, error) { +func (s *UserService) PostsOf(ctx context.Context, username string, opts *ListUserOverviewOptions) ([]*Post, *Response, error) { path := fmt.Sprintf("user/%s/submitted", username) path, err := addOptions(path, opts) if err != nil { @@ -190,22 +190,22 @@ func (s *UserService) PostsOf(ctx context.Context, username string, opts *ListUs return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getPosts(), resp, nil + return root.Posts, resp, nil } // Comments returns a list of your comments. -func (s *UserService) Comments(ctx context.Context, opts *ListUserOverviewOptions) (*Comments, *Response, error) { +func (s *UserService) Comments(ctx context.Context, opts *ListUserOverviewOptions) ([]*Comment, *Response, error) { return s.CommentsOf(ctx, s.client.Username, opts) } // CommentsOf returns a list of the user's comments. -func (s *UserService) CommentsOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Comments, *Response, error) { +func (s *UserService) CommentsOf(ctx context.Context, username string, opts *ListUserOverviewOptions) ([]*Comment, *Response, error) { path := fmt.Sprintf("user/%s/comments", username) path, err := addOptions(path, opts) if err != nil { @@ -217,17 +217,17 @@ func (s *UserService) CommentsOf(ctx context.Context, username string, opts *Lis return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getComments(), resp, nil + return root.Comments, resp, nil } // Saved returns a list of the user's saved posts and comments. -func (s *UserService) Saved(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Comments, *Response, error) { +func (s *UserService) Saved(ctx context.Context, opts *ListUserOverviewOptions) ([]*Post, []*Comment, *Response, error) { path := fmt.Sprintf("user/%s/saved", s.client.Username) path, err := addOptions(path, opts) if err != nil { @@ -239,23 +239,23 @@ func (s *UserService) Saved(ctx context.Context, opts *ListUserOverviewOptions) return nil, nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, nil, resp, err } - return root.getPosts(), root.getComments(), resp, nil + return root.Posts, root.Comments, resp, nil } // Upvoted returns a list of your upvoted posts. -func (s *UserService) Upvoted(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) { +func (s *UserService) Upvoted(ctx context.Context, opts *ListUserOverviewOptions) ([]*Post, *Response, error) { return s.UpvotedOf(ctx, s.client.Username, opts) } // UpvotedOf returns a list of the user's upvoted posts. // The user's votes must be public for this to work (unless the user is you). -func (s *UserService) UpvotedOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Posts, *Response, error) { +func (s *UserService) UpvotedOf(ctx context.Context, username string, opts *ListUserOverviewOptions) ([]*Post, *Response, error) { path := fmt.Sprintf("user/%s/upvoted", username) path, err := addOptions(path, opts) if err != nil { @@ -267,23 +267,23 @@ func (s *UserService) UpvotedOf(ctx context.Context, username string, opts *List return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getPosts(), resp, nil + return root.Posts, resp, nil } // Downvoted returns a list of your downvoted posts. -func (s *UserService) Downvoted(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) { +func (s *UserService) Downvoted(ctx context.Context, opts *ListUserOverviewOptions) ([]*Post, *Response, error) { return s.DownvotedOf(ctx, s.client.Username, opts) } // DownvotedOf returns a list of the user's downvoted posts. // The user's votes must be public for this to work (unless the user is you). -func (s *UserService) DownvotedOf(ctx context.Context, username string, opts *ListUserOverviewOptions) (*Posts, *Response, error) { +func (s *UserService) DownvotedOf(ctx context.Context, username string, opts *ListUserOverviewOptions) ([]*Post, *Response, error) { path := fmt.Sprintf("user/%s/downvoted", username) path, err := addOptions(path, opts) if err != nil { @@ -295,17 +295,17 @@ func (s *UserService) DownvotedOf(ctx context.Context, username string, opts *Li return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getPosts(), resp, nil + return root.Posts, resp, nil } // Hidden returns a list of the user's hidden posts. -func (s *UserService) Hidden(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) { +func (s *UserService) Hidden(ctx context.Context, opts *ListUserOverviewOptions) ([]*Post, *Response, error) { path := fmt.Sprintf("user/%s/hidden", s.client.Username) path, err := addOptions(path, opts) if err != nil { @@ -317,17 +317,17 @@ func (s *UserService) Hidden(ctx context.Context, opts *ListUserOverviewOptions) return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getPosts(), resp, nil + return root.Posts, resp, nil } // Gilded returns a list of the user's gilded posts. -func (s *UserService) Gilded(ctx context.Context, opts *ListUserOverviewOptions) (*Posts, *Response, error) { +func (s *UserService) Gilded(ctx context.Context, opts *ListUserOverviewOptions) ([]*Post, *Response, error) { path := fmt.Sprintf("user/%s/gilded", s.client.Username) path, err := addOptions(path, opts) if err != nil { @@ -339,13 +339,13 @@ func (s *UserService) Gilded(ctx context.Context, opts *ListUserOverviewOptions) return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getPosts(), resp, nil + return root.Posts, resp, nil } // GetFriendship returns relationship details with the specified user. @@ -517,7 +517,7 @@ func (s *UserService) TrophiesOf(ctx context.Context, username string) ([]Trophy } // Popular gets the user subreddits with the most activity. -func (s *UserService) Popular(ctx context.Context, opts *ListOptions) (*Subreddits, *Response, error) { +func (s *UserService) Popular(ctx context.Context, opts *ListOptions) ([]*Subreddit, *Response, error) { path := "users/popular" path, err := addOptions(path, opts) if err != nil { @@ -529,17 +529,17 @@ func (s *UserService) Popular(ctx context.Context, opts *ListOptions) (*Subreddi return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getSubreddits(), resp, nil + return root.Subreddits, resp, nil } // New gets the most recently created user subreddits. -func (s *UserService) New(ctx context.Context, opts *ListUserOverviewOptions) (*Subreddits, *Response, error) { +func (s *UserService) New(ctx context.Context, opts *ListUserOverviewOptions) ([]*Subreddit, *Response, error) { path := "users/new" path, err := addOptions(path, opts) if err != nil { @@ -551,18 +551,18 @@ func (s *UserService) New(ctx context.Context, opts *ListUserOverviewOptions) (* return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getSubreddits(), resp, nil + return root.Subreddits, resp, nil } // Search for users. // todo: maybe include the sort option? (relevance, activity) -func (s *UserService) Search(ctx context.Context, query string, opts *ListOptions) (*Users, *Response, error) { +func (s *UserService) Search(ctx context.Context, query string, opts *ListOptions) ([]*User, *Response, error) { path := "users/search" path, err := addOptions(path, opts) if err != nil { @@ -582,11 +582,11 @@ func (s *UserService) Search(ctx context.Context, query string, opts *ListOption return nil, nil, err } - root := new(rootListing) + root := new(listing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - return root.getUsers(), resp, nil + return root.Users, resp, nil } diff --git a/reddit/user_test.go b/reddit/user_test.go index 443b8b3..8bbca25 100644 --- a/reddit/user_test.go +++ b/reddit/user_test.go @@ -129,61 +129,55 @@ var expectedTrophies = []Trophy{ }, } -var expectedUserSubreddits = &Subreddits{ - Subreddits: []*Subreddit{ - { - ID: "3kefx", - FullID: "t5_3kefx", - Created: &Timestamp{time.Date(2017, 5, 11, 16, 37, 16, 0, time.UTC)}, +var expectedUserSubreddits = []*Subreddit{ + { + ID: "3kefx", + FullID: "t5_3kefx", + Created: &Timestamp{time.Date(2017, 5, 11, 16, 37, 16, 0, time.UTC)}, - URL: "/user/nickofnight/", - Name: "u_nickofnight", - NamePrefixed: "u/nickofnight", - Title: "nickofnight", - Description: "Stories written for Writing Prompts, NoSleep, and originals. Current series: The Carnival of Night ", - Type: "user", - }, - { - ID: "3knn1", - FullID: "t5_3knn1", - Created: &Timestamp{time.Date(2017, 5, 18, 2, 15, 55, 0, time.UTC)}, - - URL: "/user/shittymorph/", - Name: "u_shittymorph", - NamePrefixed: "u/shittymorph", - Title: "shittymorph", - Description: "In nineteen ninety eight the undertaker threw mankind off hеll in a cell, and plummeted sixteen feet through an announcer's table.", - Type: "user", - SuggestedCommentSort: "qa", - }, + URL: "/user/nickofnight/", + Name: "u_nickofnight", + NamePrefixed: "u/nickofnight", + Title: "nickofnight", + Description: "Stories written for Writing Prompts, NoSleep, and originals. Current series: The Carnival of Night ", + Type: "user", + }, + { + ID: "3knn1", + FullID: "t5_3knn1", + Created: &Timestamp{time.Date(2017, 5, 18, 2, 15, 55, 0, time.UTC)}, + + URL: "/user/shittymorph/", + Name: "u_shittymorph", + NamePrefixed: "u/shittymorph", + Title: "shittymorph", + Description: "In nineteen ninety eight the undertaker threw mankind off hеll in a cell, and plummeted sixteen feet through an announcer's table.", + Type: "user", + SuggestedCommentSort: "qa", }, - After: "t5_3knn1", } -var expectedSearchUsers = &Users{ - Users: []*User{ - { - ID: "179965", - Name: "washingtonpost", - Created: &Timestamp{time.Date(2017, 4, 20, 21, 23, 58, 0, time.UTC)}, +var expectedSearchUsers = []*User{ + { + ID: "179965", + Name: "washingtonpost", + Created: &Timestamp{time.Date(2017, 4, 20, 21, 23, 58, 0, time.UTC)}, - PostKarma: 1075227, - CommentKarma: 339569, + PostKarma: 1075227, + CommentKarma: 339569, - HasVerifiedEmail: true, - }, - { - ID: "11kowl2w", - Name: "reuters", - Created: &Timestamp{time.Date(2018, 3, 15, 1, 50, 4, 0, time.UTC)}, - - PostKarma: 76744, - CommentKarma: 42717, - - HasVerifiedEmail: true, - }, + HasVerifiedEmail: true, + }, + { + ID: "11kowl2w", + Name: "reuters", + Created: &Timestamp{time.Date(2018, 3, 15, 1, 50, 4, 0, time.UTC)}, + + PostKarma: 76744, + CommentKarma: 42717, + + HasVerifiedEmail: true, }, - After: "t2_11kowl2w", } func TestUserService_Get(t *testing.T) { @@ -263,18 +257,16 @@ func TestUserService_Overview(t *testing.T) { fmt.Fprint(w, blob) }) - posts, comments, _, err := client.User.Overview(ctx, nil) + posts, comments, resp, err := client.User.Overview(ctx, nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t1_f0zsa37", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) - require.Len(t, comments.Comments, 1) - require.Equal(t, expectedComment, comments.Comments[0]) - require.Equal(t, "t1_f0zsa37", comments.After) - require.Equal(t, "", comments.Before) + require.Len(t, comments, 1) + require.Equal(t, expectedComment, comments[0]) + + require.Equal(t, "t1_f0zsa37", resp.After) } func TestUserService_OverviewOf(t *testing.T) { @@ -289,18 +281,16 @@ func TestUserService_OverviewOf(t *testing.T) { fmt.Fprint(w, blob) }) - posts, comments, _, err := client.User.OverviewOf(ctx, "user2", nil) + posts, comments, resp, err := client.User.OverviewOf(ctx, "user2", nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t1_f0zsa37", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) - require.Len(t, comments.Comments, 1) - require.Equal(t, expectedComment, comments.Comments[0]) - require.Equal(t, "t1_f0zsa37", comments.After) - require.Equal(t, "", comments.Before) + require.Len(t, comments, 1) + require.Equal(t, expectedComment, comments[0]) + + require.Equal(t, "t1_f0zsa37", resp.After) } func TestUserService_Overview_Options(t *testing.T) { @@ -347,13 +337,12 @@ func TestUserService_Posts(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.User.Posts(ctx, nil) + posts, resp, err := client.User.Posts(ctx, nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t3_gczwql", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) + require.Equal(t, "t3_gczwql", resp.After) } func TestUserService_PostsOf(t *testing.T) { @@ -368,13 +357,12 @@ func TestUserService_PostsOf(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.User.PostsOf(ctx, "user2", nil) + posts, resp, err := client.User.PostsOf(ctx, "user2", nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t3_gczwql", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) + require.Equal(t, "t3_gczwql", resp.After) } func TestUserService_Posts_Options(t *testing.T) { @@ -419,13 +407,12 @@ func TestUserService_Comments(t *testing.T) { fmt.Fprint(w, blob) }) - comments, _, err := client.User.Comments(ctx, nil) + comments, resp, err := client.User.Comments(ctx, nil) require.NoError(t, err) - require.Len(t, comments.Comments, 1) - require.Equal(t, expectedComment, comments.Comments[0]) - require.Equal(t, "t1_f0zsa37", comments.After) - require.Equal(t, "", comments.Before) + require.Len(t, comments, 1) + require.Equal(t, expectedComment, comments[0]) + require.Equal(t, "t1_f0zsa37", resp.After) } func TestUserService_CommentsOf(t *testing.T) { @@ -440,13 +427,12 @@ func TestUserService_CommentsOf(t *testing.T) { fmt.Fprint(w, blob) }) - comments, _, err := client.User.CommentsOf(ctx, "user2", nil) + comments, resp, err := client.User.CommentsOf(ctx, "user2", nil) require.NoError(t, err) - require.Len(t, comments.Comments, 1) - require.Equal(t, expectedComment, comments.Comments[0]) - require.Equal(t, "t1_f0zsa37", comments.After) - require.Equal(t, "", comments.Before) + require.Len(t, comments, 1) + require.Equal(t, expectedComment, comments[0]) + require.Equal(t, "t1_f0zsa37", resp.After) } func TestUserService_Comments_Options(t *testing.T) { @@ -492,18 +478,16 @@ func TestUserService_Saved(t *testing.T) { fmt.Fprint(w, blob) }) - posts, comments, _, err := client.User.Saved(ctx, nil) + posts, comments, resp, err := client.User.Saved(ctx, nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t1_f0zsa37", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) - require.Len(t, comments.Comments, 1) - require.Equal(t, expectedComment, comments.Comments[0]) - require.Equal(t, "t1_f0zsa37", comments.After) - require.Equal(t, "", comments.Before) + require.Len(t, comments, 1) + require.Equal(t, expectedComment, comments[0]) + + require.Equal(t, "t1_f0zsa37", resp.After) } func TestUserService_Saved_Options(t *testing.T) { @@ -549,13 +533,12 @@ func TestUserService_Upvoted(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.User.Upvoted(ctx, nil) + posts, resp, err := client.User.Upvoted(ctx, nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t3_gczwql", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) + require.Equal(t, "t3_gczwql", resp.After) } func TestUserService_Upvoted_Options(t *testing.T) { @@ -602,13 +585,12 @@ func TestUserService_UpvotedOf(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.User.UpvotedOf(ctx, "user2", nil) + posts, resp, err := client.User.UpvotedOf(ctx, "user2", nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t3_gczwql", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) + require.Equal(t, "t3_gczwql", resp.After) } func TestUserService_Downvoted(t *testing.T) { @@ -624,13 +606,12 @@ func TestUserService_Downvoted(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.User.Downvoted(ctx, nil) + posts, resp, err := client.User.Downvoted(ctx, nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t3_gczwql", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) + require.Equal(t, "t3_gczwql", resp.After) } func TestUserService_Downvoted_Options(t *testing.T) { @@ -677,13 +658,12 @@ func TestUserService_DownvotedOf(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.User.DownvotedOf(ctx, "user2", nil) + posts, resp, err := client.User.DownvotedOf(ctx, "user2", nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t3_gczwql", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) + require.Equal(t, "t3_gczwql", resp.After) } func TestUserService_Hidden(t *testing.T) { @@ -699,13 +679,12 @@ func TestUserService_Hidden(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.User.Hidden(ctx, nil) + posts, resp, err := client.User.Hidden(ctx, nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t3_gczwql", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) + require.Equal(t, "t3_gczwql", resp.After) } func TestUserService_Gilded(t *testing.T) { @@ -721,13 +700,12 @@ func TestUserService_Gilded(t *testing.T) { fmt.Fprint(w, blob) }) - posts, _, err := client.User.Gilded(ctx, nil) + posts, resp, err := client.User.Gilded(ctx, nil) require.NoError(t, err) - require.Len(t, posts.Posts, 1) - require.Equal(t, expectedPost, posts.Posts[0]) - require.Equal(t, "t3_gczwql", posts.After) - require.Equal(t, "", posts.Before) + require.Len(t, posts, 1) + require.Equal(t, expectedPost, posts[0]) + require.Equal(t, "t3_gczwql", resp.After) } func TestUserService_GetFriendship(t *testing.T) { @@ -930,9 +908,10 @@ func TestUserService_Popular(t *testing.T) { fmt.Fprint(w, blob) }) - userSubreddits, _, err := client.User.Popular(ctx, nil) + userSubreddits, resp, err := client.User.Popular(ctx, nil) require.NoError(t, err) require.Equal(t, expectedUserSubreddits, userSubreddits) + require.Equal(t, "t5_3knn1", resp.After) } func TestUserService_New(t *testing.T) { @@ -947,9 +926,10 @@ func TestUserService_New(t *testing.T) { fmt.Fprint(w, blob) }) - userSubreddits, _, err := client.User.New(ctx, nil) + userSubreddits, resp, err := client.User.New(ctx, nil) require.NoError(t, err) require.Equal(t, expectedUserSubreddits, userSubreddits) + require.Equal(t, "t5_3knn1", resp.After) } func TestUserService_Search(t *testing.T) { @@ -972,7 +952,8 @@ func TestUserService_Search(t *testing.T) { fmt.Fprint(w, blob) }) - users, _, err := client.User.Search(ctx, "test", nil) + users, resp, err := client.User.Search(ctx, "test", nil) require.NoError(t, err) require.Equal(t, expectedSearchUsers, users) + require.Equal(t, "t2_11kowl2w", resp.After) }