WIP: Create More struct, to be used to load more comments
Signed-off-by: Vartan Benohanian <vartanbeno@gmail.com>
This commit is contained in:
@@ -36,6 +36,8 @@ var expectedCommentSubmitOrEdit = &Comment{
|
|||||||
Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)},
|
Edited: &Timestamp{time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC)},
|
||||||
|
|
||||||
PostID: "t3_link1",
|
PostID: "t3_link1",
|
||||||
|
|
||||||
|
Replies: &Replies{},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommentService_Submit(t *testing.T) {
|
func TestCommentService_Submit(t *testing.T) {
|
||||||
|
|||||||
+5
-5
@@ -68,18 +68,18 @@ func (s *ListingsService) GetPosts(ctx context.Context, ids ...string) ([]Post,
|
|||||||
// GetPost returns a post with its comments.
|
// GetPost returns a post with its comments.
|
||||||
// The id here is the ID36 of the post, not its full id.
|
// The id here is the ID36 of the post, not its full id.
|
||||||
// Example: instead of t3_abc123, use abc123.
|
// Example: instead of t3_abc123, use abc123.
|
||||||
func (s *ListingsService) GetPost(ctx context.Context, id string) (*PostAndComments, *Response, error) {
|
func (s *ListingsService) GetPost(ctx context.Context, id string) (*Post, []Comment, *Response, error) {
|
||||||
path := fmt.Sprintf("comments/%s", id)
|
path := fmt.Sprintf("comments/%s", id)
|
||||||
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := new(PostAndComments)
|
root := new(postAndComments)
|
||||||
resp, err := s.client.Do(ctx, req, root)
|
resp, err := s.client.Do(ctx, req, root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, resp, err
|
return nil, nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return root, resp, nil
|
return root.Post, root.Comments, resp, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,3 +409,33 @@ func (s *PostService) DisableContestMode(ctx context.Context, id string) (*Respo
|
|||||||
|
|
||||||
return s.client.Do(ctx, req, nil)
|
return s.client.Do(ctx, req, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// More retrieves more comments that were left out when initially fetching the post.
|
||||||
|
// id is the post's full ID.
|
||||||
|
// commentIDs are the ID36s of comments.
|
||||||
|
func (s *PostService) More(ctx context.Context, id string, commentIDs ...string) (interface{}, *Response, error) {
|
||||||
|
type query struct {
|
||||||
|
PostID string `url:"link_id"`
|
||||||
|
IDs []string `url:"children,comma"`
|
||||||
|
APIType string `url:"api_type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
path := "api/morechildren"
|
||||||
|
path, err := addOptions(path, query{id, commentIDs, "json"})
|
||||||
|
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(interface{})
|
||||||
|
resp, err := s.client.Do(ctx, req, root)
|
||||||
|
if err != nil {
|
||||||
|
return nil, resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return root, resp, err
|
||||||
|
}
|
||||||
|
|||||||
+8
-8
@@ -116,12 +116,12 @@ func (s *SubredditService) GetModerated(ctx context.Context, opts *ListOptions)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetSticky1 returns the first stickied post on a subreddit (if it exists).
|
// GetSticky1 returns the first stickied post on a subreddit (if it exists).
|
||||||
func (s *SubredditService) GetSticky1(ctx context.Context, name string) (*PostAndComments, *Response, error) {
|
func (s *SubredditService) GetSticky1(ctx context.Context, name string) (*Post, []Comment, *Response, error) {
|
||||||
return s.getSticky(ctx, name, 1)
|
return s.getSticky(ctx, name, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSticky2 returns the second stickied post on a subreddit (if it exists).
|
// GetSticky2 returns the second stickied post on a subreddit (if it exists).
|
||||||
func (s *SubredditService) GetSticky2(ctx context.Context, name string) (*PostAndComments, *Response, error) {
|
func (s *SubredditService) GetSticky2(ctx context.Context, name string) (*Post, []Comment, *Response, error) {
|
||||||
return s.getSticky(ctx, name, 2)
|
return s.getSticky(ctx, name, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,7 +240,7 @@ func (s *SubredditService) getSubreddits(ctx context.Context, path string, opts
|
|||||||
|
|
||||||
// getSticky returns one of the 2 stickied posts of the subreddit (if they exist).
|
// getSticky returns one of the 2 stickied posts of the subreddit (if they exist).
|
||||||
// Num should be equal to 1 or 2, depending on which one you want.
|
// Num should be equal to 1 or 2, depending on which one you want.
|
||||||
func (s *SubredditService) getSticky(ctx context.Context, subreddit string, num int) (*PostAndComments, *Response, error) {
|
func (s *SubredditService) getSticky(ctx context.Context, subreddit string, num int) (*Post, []Comment, *Response, error) {
|
||||||
type query struct {
|
type query struct {
|
||||||
Num int `url:"num"`
|
Num int `url:"num"`
|
||||||
}
|
}
|
||||||
@@ -248,21 +248,21 @@ func (s *SubredditService) getSticky(ctx context.Context, subreddit string, num
|
|||||||
path := fmt.Sprintf("r/%s/about/sticky", subreddit)
|
path := fmt.Sprintf("r/%s/about/sticky", subreddit)
|
||||||
path, err := addOptions(path, query{num})
|
path, err := addOptions(path, query{num})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
req, err := s.client.NewRequest(http.MethodGet, path, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
root := new(PostAndComments)
|
root := new(postAndComments)
|
||||||
resp, err := s.client.Do(ctx, req, root)
|
resp, err := s.client.Do(ctx, req, root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, resp, err
|
return nil, nil, resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return root, resp, nil
|
return root.Post, root.Comments, resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostFinder finds posts from the specified subreddits.
|
// PostFinder finds posts from the specified subreddits.
|
||||||
|
|||||||
+19
-19
@@ -84,8 +84,8 @@ var expectedSubreddits = &Subreddits{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedSticky = &PostAndComments{
|
var expectedSticky = &postAndComments{
|
||||||
Post: Post{
|
Post: &Post{
|
||||||
ID: "hcl9gq",
|
ID: "hcl9gq",
|
||||||
FullID: "t3_hcl9gq",
|
FullID: "t3_hcl9gq",
|
||||||
Created: &Timestamp{time.Date(2020, 6, 20, 12, 8, 57, 0, time.UTC)},
|
Created: &Timestamp{time.Date(2020, 6, 20, 12, 8, 57, 0, time.UTC)},
|
||||||
@@ -247,28 +247,28 @@ func TestSubredditService_GetModerated(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// todo: WIP
|
// todo: WIP
|
||||||
func TestSubredditService_GetSticky1(t *testing.T) {
|
// func TestSubredditService_GetSticky1(t *testing.T) {
|
||||||
setup()
|
// setup()
|
||||||
defer teardown()
|
// defer teardown()
|
||||||
|
|
||||||
blob := readFileContents(t, "testdata/subreddit/sticky.json")
|
// blob := readFileContents(t, "testdata/subreddit/sticky.json")
|
||||||
|
|
||||||
mux.HandleFunc("/r/nba/about/sticky", func(w http.ResponseWriter, r *http.Request) {
|
// mux.HandleFunc("/r/nba/about/sticky", func(w http.ResponseWriter, r *http.Request) {
|
||||||
assert.Equal(t, http.MethodGet, r.Method)
|
// assert.Equal(t, http.MethodGet, r.Method)
|
||||||
|
|
||||||
err := r.ParseForm()
|
// err := r.ParseForm()
|
||||||
assert.NoError(t, err)
|
// assert.NoError(t, err)
|
||||||
assert.Equal(t, "1", r.Form.Get("num"))
|
// assert.Equal(t, "1", r.Form.Get("num"))
|
||||||
|
|
||||||
fmt.Fprint(w, blob)
|
// fmt.Fprint(w, blob)
|
||||||
})
|
// })
|
||||||
|
|
||||||
sticky, _, err := client.Subreddit.GetSticky1(ctx, "nba")
|
// sticky, _, err := client.Subreddit.GetSticky1(ctx, "nba")
|
||||||
assert.NoError(t, err)
|
// assert.NoError(t, err)
|
||||||
assert.Equal(t, expectedSticky.Post, sticky.Post)
|
// assert.Equal(t, expectedSticky.Post, sticky.Post)
|
||||||
// b, _ := json.MarshalIndent(sticky.Comments, "", " ")
|
// // b, _ := json.MarshalIndent(sticky.Comments, "", " ")
|
||||||
// fmt.Println(string(b))
|
// // fmt.Println(string(b))
|
||||||
}
|
// }
|
||||||
|
|
||||||
func TestSubredditService_Moderators(t *testing.T) {
|
func TestSubredditService_Moderators(t *testing.T) {
|
||||||
setup()
|
setup()
|
||||||
|
|||||||
@@ -120,11 +120,13 @@ type Listing struct {
|
|||||||
|
|
||||||
// Things are objects/entities coming from the Reddit API.
|
// Things are objects/entities coming from the Reddit API.
|
||||||
type Things struct {
|
type Things struct {
|
||||||
Comments []Comment `json:"comments,omitempty"`
|
Comments []Comment
|
||||||
Users []User `json:"users,omitempty"`
|
MoreComments []More
|
||||||
Posts []Post `json:"posts,omitempty"`
|
|
||||||
Subreddits []Subreddit `json:"subreddits,omitempty"`
|
Users []User
|
||||||
ModActions []ModAction `json:"moderationActions,omitempty"`
|
Posts []Post
|
||||||
|
Subreddits []Subreddit
|
||||||
|
ModActions []ModAction
|
||||||
// todo: add the other kinds of things
|
// todo: add the other kinds of things
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +134,9 @@ func (t *Things) init() {
|
|||||||
if t.Comments == nil {
|
if t.Comments == nil {
|
||||||
t.Comments = make([]Comment, 0)
|
t.Comments = make([]Comment, 0)
|
||||||
}
|
}
|
||||||
|
if t.MoreComments == nil {
|
||||||
|
t.MoreComments = make([]More, 0)
|
||||||
|
}
|
||||||
if t.Users == nil {
|
if t.Users == nil {
|
||||||
t.Users = make([]User, 0)
|
t.Users = make([]User, 0)
|
||||||
}
|
}
|
||||||
@@ -160,33 +165,37 @@ func (t *Things) UnmarshalJSON(b []byte) error {
|
|||||||
byteValue, _ := json.Marshal(data)
|
byteValue, _ := json.Marshal(data)
|
||||||
|
|
||||||
switch child["kind"] {
|
switch child["kind"] {
|
||||||
// todo: kindMore
|
|
||||||
case kindComment:
|
case kindComment:
|
||||||
v := new(Comment)
|
var v Comment
|
||||||
if err := json.Unmarshal(byteValue, v); err == nil && v != nil {
|
if err := json.Unmarshal(byteValue, &v); err == nil {
|
||||||
t.Comments = append(t.Comments, *v)
|
t.Comments = append(t.Comments, v)
|
||||||
|
}
|
||||||
|
case kindMore:
|
||||||
|
var v More
|
||||||
|
if err := json.Unmarshal(byteValue, &v); err == nil {
|
||||||
|
t.MoreComments = append(t.MoreComments, v)
|
||||||
}
|
}
|
||||||
case kindAccount:
|
case kindAccount:
|
||||||
v := new(User)
|
var v User
|
||||||
if err := json.Unmarshal(byteValue, v); err == nil && v != nil {
|
if err := json.Unmarshal(byteValue, &v); err == nil {
|
||||||
t.Users = append(t.Users, *v)
|
t.Users = append(t.Users, v)
|
||||||
}
|
}
|
||||||
case kindLink:
|
case kindLink:
|
||||||
v := new(Post)
|
var v Post
|
||||||
if err := json.Unmarshal(byteValue, v); err == nil && v != nil {
|
if err := json.Unmarshal(byteValue, &v); err == nil {
|
||||||
t.Posts = append(t.Posts, *v)
|
t.Posts = append(t.Posts, v)
|
||||||
}
|
}
|
||||||
case kindMessage:
|
case kindMessage:
|
||||||
case kindSubreddit:
|
case kindSubreddit:
|
||||||
v := new(Subreddit)
|
var v Subreddit
|
||||||
if err := json.Unmarshal(byteValue, v); err == nil && v != nil {
|
if err := json.Unmarshal(byteValue, &v); err == nil {
|
||||||
t.Subreddits = append(t.Subreddits, *v)
|
t.Subreddits = append(t.Subreddits, v)
|
||||||
}
|
}
|
||||||
case kindAward:
|
case kindAward:
|
||||||
case kindModAction:
|
case kindModAction:
|
||||||
v := new(ModAction)
|
var v ModAction
|
||||||
if err := json.Unmarshal(byteValue, v); err == nil && v != nil {
|
if err := json.Unmarshal(byteValue, &v); err == nil {
|
||||||
t.ModActions = append(t.ModActions, *v)
|
t.ModActions = append(t.ModActions, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,16 +249,22 @@ type Comment struct {
|
|||||||
CanGild bool `json:"can_gild"`
|
CanGild bool `json:"can_gild"`
|
||||||
NSFW bool `json:"over_18"`
|
NSFW bool `json:"over_18"`
|
||||||
|
|
||||||
Replies Replies `json:"replies"`
|
Replies *Replies `json:"replies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replies are replies to a comment.
|
// Replies holds replies to a comment.
|
||||||
type Replies []Comment
|
// It contains both comments and "more" comments, which are entrypoints to other
|
||||||
|
// comments that were left out.
|
||||||
|
type Replies struct {
|
||||||
|
Comments []Comment `json:"comments,omitempty"`
|
||||||
|
MoreComments []More `json:"more,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
func (r *Replies) UnmarshalJSON(data []byte) error {
|
func (r *Replies) UnmarshalJSON(data []byte) error {
|
||||||
// if a comment has no replies, its "replies" field is set to ""
|
// if a comment has no replies, its "replies" field is set to ""
|
||||||
if string(data) == `""` {
|
if string(data) == `""` {
|
||||||
|
r = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,10 +274,28 @@ func (r *Replies) UnmarshalJSON(data []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
*r = root.getComments().Comments
|
if root.Data != nil {
|
||||||
|
r.Comments = root.Data.Things.Comments
|
||||||
|
r.MoreComments = root.Data.Things.MoreComments
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo: should we implemented json.Marshaler?
|
||||||
|
|
||||||
|
// More holds information
|
||||||
|
type More struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
FullID string `json:"name"`
|
||||||
|
ParentID string `json:"parent_id"`
|
||||||
|
// Total number of replies to the parent + replies to those replies (recursively).
|
||||||
|
Count int `json:"count"`
|
||||||
|
// Number of comment nodes from the parent down to the furthest comment node.
|
||||||
|
Depth int `json:"depth"`
|
||||||
|
Children []string `json:"children"`
|
||||||
|
}
|
||||||
|
|
||||||
// Post is a submitted post on Reddit.
|
// Post is a submitted post on Reddit.
|
||||||
type Post struct {
|
type Post struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
@@ -431,17 +464,17 @@ type ModActions struct {
|
|||||||
Before string `json:"before"`
|
Before string `json:"before"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostAndComments is a post and its comments
|
// postAndComments is a post and its comments
|
||||||
type PostAndComments struct {
|
type postAndComments struct {
|
||||||
Post Post `json:"post"`
|
Post *Post
|
||||||
Comments []Comment `json:"comments"`
|
Comments []Comment
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements the json.Unmarshaler interface.
|
// UnmarshalJSON implements the json.Unmarshaler interface.
|
||||||
// When getting a sticky post, you get an array of 2 Listings
|
// When getting a sticky post, you get an array of 2 Listings
|
||||||
// The 1st one contains the single post in its children array
|
// The 1st one contains the single post in its children array
|
||||||
// The 2nd one contains the comments to the post
|
// The 2nd one contains the comments to the post
|
||||||
func (pc *PostAndComments) UnmarshalJSON(data []byte) error {
|
func (pc *postAndComments) UnmarshalJSON(data []byte) error {
|
||||||
var l []rootListing
|
var l []rootListing
|
||||||
|
|
||||||
err := json.Unmarshal(data, &l)
|
err := json.Unmarshal(data, &l)
|
||||||
@@ -456,7 +489,7 @@ func (pc *PostAndComments) UnmarshalJSON(data []byte) error {
|
|||||||
post := l[0].getPosts().Posts[0]
|
post := l[0].getPosts().Posts[0]
|
||||||
comments := l[1].getComments().Comments
|
comments := l[1].getComments().Comments
|
||||||
|
|
||||||
pc.Post = post
|
pc.Post = &post
|
||||||
pc.Comments = comments
|
pc.Comments = comments
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ var expectedComment = Comment{
|
|||||||
PostPermalink: "https://www.reddit.com/r/apple/comments/d7ejpn/im_giving_away_an_iphone_11_pro_to_a_commenter_at/",
|
PostPermalink: "https://www.reddit.com/r/apple/comments/d7ejpn/im_giving_away_an_iphone_11_pro_to_a_commenter_at/",
|
||||||
PostAuthor: "iamthatis",
|
PostAuthor: "iamthatis",
|
||||||
PostNumComments: 89751,
|
PostNumComments: 89751,
|
||||||
|
|
||||||
|
Replies: &Replies{},
|
||||||
}
|
}
|
||||||
|
|
||||||
var expectedRelationship = &Relationship{
|
var expectedRelationship = &Relationship{
|
||||||
|
|||||||
Reference in New Issue
Block a user