From 5bb7a155def2c4f7d75ca0715271e4e86bad12e1 Mon Sep 17 00:00:00 2001 From: Vartan Benohanian Date: Tue, 1 Sep 2020 19:30:05 -0400 Subject: [PATCH] Return bool when type casting, include trophies in thing struct Signed-off-by: Vartan Benohanian --- reddit/account.go | 12 ++----- reddit/multi.go | 12 ++++--- reddit/reddit.go | 6 ++-- reddit/subreddit.go | 3 +- reddit/things.go | 80 ++++++++++++++++++++++++++++++++------------- reddit/user.go | 29 ++++------------ reddit/user_test.go | 2 +- 7 files changed, 81 insertions(+), 63 deletions(-) diff --git a/reddit/account.go b/reddit/account.go index 7595195..6d242de 100644 --- a/reddit/account.go +++ b/reddit/account.go @@ -293,7 +293,7 @@ func (s *AccountService) UpdateSettings(ctx context.Context, settings *Settings) } // Trophies returns a list of your trophies. -func (s *AccountService) Trophies(ctx context.Context) ([]Trophy, *Response, error) { +func (s *AccountService) Trophies(ctx context.Context) ([]*Trophy, *Response, error) { path := "api/v1/me/trophies" req, err := s.client.NewRequest(http.MethodGet, path, nil) @@ -301,19 +301,13 @@ func (s *AccountService) Trophies(ctx context.Context) ([]Trophy, *Response, err return nil, nil, err } - root := new(rootTrophyListing) + root := new(thing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - var trophies []Trophy - for _, trophy := range root.Data.Trophies { - if trophy.Data != nil { - trophies = append(trophies, *trophy.Data) - } - } - + trophies, _ := root.TrophyList() return trophies, resp, nil } diff --git a/reddit/multi.go b/reddit/multi.go index 7e94aae..6844cf4 100644 --- a/reddit/multi.go +++ b/reddit/multi.go @@ -129,7 +129,8 @@ func (s *MultiService) Get(ctx context.Context, multiPath string) (*Multi, *Resp return nil, resp, err } - return root.Multi(), resp, nil + multi, _ := root.Multi() + return multi, resp, nil } // Mine returns your multireddits. @@ -192,7 +193,8 @@ func (s *MultiService) Copy(ctx context.Context, copyRequest *MultiCopyRequest) return nil, resp, err } - return root.Multi(), resp, nil + multi, _ := root.Multi() + return multi, resp, nil } // Create a multireddit. @@ -214,7 +216,8 @@ func (s *MultiService) Create(ctx context.Context, createRequest *MultiCreateOrU return nil, resp, err } - return root.Multi(), resp, nil + multi, _ := root.Multi() + return multi, resp, nil } // Update a multireddit. @@ -237,7 +240,8 @@ func (s *MultiService) Update(ctx context.Context, multiPath string, updateReque return nil, resp, err } - return root.Multi(), resp, nil + multi, _ := root.Multi() + return multi, resp, nil } // Delete a multireddit. diff --git a/reddit/reddit.go b/reddit/reddit.go index 79e93ee..17202f2 100644 --- a/reddit/reddit.go +++ b/reddit/reddit.go @@ -190,7 +190,7 @@ func (c *Client) redirect(req *http.Request, via []*http.Request) error { } // The readonly Reddit url needs .json at the end of its path to return responses in JSON instead of HTML. -func (c *Client) appendJSONExtensionToRequestPath(req *http.Request) { +func (c *Client) appendJSONExtensionToRequestURLPath(req *http.Request) { readonlyURL, err := url.Parse(defaultBaseURLReadonly) if err != nil { return @@ -238,7 +238,7 @@ func (c *Client) NewRequest(method string, path string, body interface{}) (*http return nil, err } - c.appendJSONExtensionToRequestPath(req) + c.appendJSONExtensionToRequestURLPath(req) req.Header.Add(headerContentType, mediaTypeJSON) req.Header.Add(headerAccept, mediaTypeJSON) @@ -259,7 +259,7 @@ func (c *Client) NewRequestWithForm(method string, path string, form url.Values) return nil, err } - c.appendJSONExtensionToRequestPath(req) + c.appendJSONExtensionToRequestURLPath(req) req.Header.Add(headerContentType, mediaTypeForm) req.Header.Add(headerAccept, mediaTypeJSON) diff --git a/reddit/subreddit.go b/reddit/subreddit.go index 97b6656..91dd827 100644 --- a/reddit/subreddit.go +++ b/reddit/subreddit.go @@ -134,7 +134,8 @@ func (s *SubredditService) Get(ctx context.Context, name string) (*Subreddit, *R return nil, resp, err } - return root.Subreddit(), resp, nil + sr, _ := root.Subreddit() + return sr, resp, nil } // Popular returns popular subreddits. diff --git a/reddit/things.go b/reddit/things.go index fe7b14f..2b51e0c 100644 --- a/reddit/things.go +++ b/reddit/things.go @@ -11,7 +11,7 @@ const ( kindPost = "t3" kindMessage = "t4" kindSubreddit = "t5" - kindAward = "t6" + kindTrophy = "t6" kindListing = "Listing" kindKarmaList = "KarmaList" kindTrophyList = "TrophyList" @@ -59,6 +59,10 @@ func (t *thing) UnmarshalJSON(b []byte) error { v = new(ModAction) case kindMulti: v = new(Multi) + case kindTrophy: + v = new(Trophy) + case kindTrophyList: + v = new(trophyList) default: return fmt.Errorf("unrecognized kind: %q", t.Kind) } @@ -72,39 +76,49 @@ func (t *thing) UnmarshalJSON(b []byte) error { return nil } -func (t *thing) Comment() *Comment { - v, _ := t.Data.(*Comment) - return v +func (t *thing) Comment() (v *Comment, ok bool) { + v, ok = t.Data.(*Comment) + return } -func (t *thing) More() *More { - v, _ := t.Data.(*More) - return v +func (t *thing) More() (v *More, ok bool) { + v, ok = t.Data.(*More) + return } -func (t *thing) User() *User { - v, _ := t.Data.(*User) - return v +func (t *thing) User() (v *User, ok bool) { + v, ok = t.Data.(*User) + return } -func (t *thing) Post() *Post { - v, _ := t.Data.(*Post) - return v +func (t *thing) Post() (v *Post, ok bool) { + v, ok = t.Data.(*Post) + return } -func (t *thing) Subreddit() *Subreddit { - v, _ := t.Data.(*Subreddit) - return v +func (t *thing) Subreddit() (v *Subreddit, ok bool) { + v, ok = t.Data.(*Subreddit) + return } -func (t *thing) ModAction() *ModAction { - v, _ := t.Data.(*ModAction) - return v +func (t *thing) ModAction() (v *ModAction, ok bool) { + v, ok = t.Data.(*ModAction) + return } -func (t *thing) Multi() *Multi { - v, _ := t.Data.(*Multi) - return v +func (t *thing) Multi() (v *Multi, ok bool) { + v, ok = t.Data.(*Multi) + return +} + +func (t *thing) Trophy() (v *Trophy, ok bool) { + v, ok = t.Data.(*Trophy) + return +} + +func (t *thing) TrophyList() ([]*Trophy, bool) { + v, ok := t.Data.(*trophyList) + return *v, ok } type anchor interface { @@ -205,6 +219,28 @@ func (t *things) add(things ...thing) { } } +type trophyList []*Trophy + +// UnmarshalJSON implements the json.Unmarshaler interface. +func (l *trophyList) UnmarshalJSON(b []byte) error { + root := new(struct { + Trophies []thing `json:"trophies"` + }) + + err := json.Unmarshal(b, root) + if err != nil { + return err + } + + for _, thing := range root.Trophies { + if trophy, ok := thing.Trophy(); ok { + *l = append(*l, trophy) + } + } + + return nil +} + // Comment is a comment posted by a user. type Comment struct { ID string `json:"id,omitempty"` diff --git a/reddit/user.go b/reddit/user.go index f79985a..07f97c7 100644 --- a/reddit/user.go +++ b/reddit/user.go @@ -51,18 +51,6 @@ type Blocked struct { Created *Timestamp `json:"date,omitempty"` } -type rootTrophyListing struct { - Kind string `json:"kind,omitempty"` - Data struct { - Trophies []rootTrophy `json:"trophies"` - } `json:"data"` -} - -type rootTrophy struct { - Kind string `json:"kind,omitempty"` - Data *Trophy `json:"data,omitempty"` -} - // Trophy is a Reddit award. type Trophy struct { ID string `json:"id"` @@ -84,7 +72,8 @@ func (s *UserService) Get(ctx context.Context, username string) (*User, *Respons return nil, resp, err } - return root.User(), resp, nil + user, _ := root.User() + return user, resp, nil } // GetMultipleByID returns multiple users from their full IDs. @@ -482,12 +471,12 @@ func (s *UserService) UnblockByID(ctx context.Context, id string) (*Response, er } // Trophies returns a list of your trophies. -func (s *UserService) Trophies(ctx context.Context) ([]Trophy, *Response, error) { +func (s *UserService) Trophies(ctx context.Context) ([]*Trophy, *Response, error) { return s.TrophiesOf(ctx, s.client.Username) } // TrophiesOf returns a list of the specified user's trophies. -func (s *UserService) TrophiesOf(ctx context.Context, username string) ([]Trophy, *Response, error) { +func (s *UserService) TrophiesOf(ctx context.Context, username string) ([]*Trophy, *Response, error) { path := fmt.Sprintf("api/v1/user/%s/trophies", username) req, err := s.client.NewRequest(http.MethodGet, path, nil) @@ -495,19 +484,13 @@ func (s *UserService) TrophiesOf(ctx context.Context, username string) ([]Trophy return nil, nil, err } - root := new(rootTrophyListing) + root := new(thing) resp, err := s.client.Do(ctx, req, root) if err != nil { return nil, resp, err } - var trophies []Trophy - for _, trophy := range root.Data.Trophies { - if trophy.Data != nil { - trophies = append(trophies, *trophy.Data) - } - } - + trophies, _ := root.TrophyList() return trophies, resp, nil } diff --git a/reddit/user_test.go b/reddit/user_test.go index a6c5267..ea825d7 100644 --- a/reddit/user_test.go +++ b/reddit/user_test.go @@ -116,7 +116,7 @@ var expectedBlocked = &Blocked{ Created: &Timestamp{time.Date(2020, 6, 16, 16, 49, 50, 0, time.UTC)}, } -var expectedTrophies = []Trophy{ +var expectedTrophies = []*Trophy{ { ID: "", Name: "Three-Year Club",