diff --git a/reddit/reddit.go b/reddit/reddit.go index 700dc28..3638fdf 100644 --- a/reddit/reddit.go +++ b/reddit/reddit.go @@ -2,12 +2,10 @@ package reddit import ( "bytes" - "compress/gzip" "context" "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "reflect" @@ -36,9 +34,9 @@ const ( headerAccept = "Accept" headerUserAgent = "User-Agent" - headerRateLimitRemaining = "x-ratelimit-remaining" - headerRateLimitUsed = "x-ratelimit-used" - headerRateLimitReset = "x-ratelimit-reset" + headerRateLimitRemaining = "X-Ratelimit-Remaining" + headerRateLimitUsed = "X-Ratelimit-Used" + headerRateLimitReset = "X-Ratelimit-Reset" ) var defaultClient, _ = NewReadonlyClient() @@ -115,13 +113,14 @@ func newClient() *Client { surf_client := surf.NewClient(). Builder(). Impersonate(). - RandomOS(). + Windows(). Firefox(). Session(). Build(). - Unwrap() + Unwrap(). + Std() - client := &Client{client: surf_client.Std(), BaseURL: baseURL, TokenURL: tokenURL} + client := &Client{client: surf_client, BaseURL: baseURL, TokenURL: tokenURL} client.Account = &AccountService{client: client} client.Collection = &CollectionService{client: client} @@ -377,32 +376,21 @@ func (c *Client) Do(ctx context.Context, req *http.Request, v interface{}) (*Res return response, err } + body, err := ResponseReader(resp) + if err != nil { + return response, err + } + w, ok := v.(io.Writer) if ok { - _, err = io.Copy(w, response.Body) + _, err = io.Copy(w, body) if err != nil { return response, err } } else { - if response.Header.Get("Content-Encoding") == "gzip" { - gzipReader, err := gzip.NewReader(resp.Body) - if err != nil { - return response, fmt.Errorf("Error creating gzip reader: %s", err) - } - defer gzipReader.Close() - b, err := io.ReadAll(gzipReader) - if err != nil { - return response, fmt.Errorf("Error decoding gzip json: %s", err) - } - err = json.Unmarshal(b, v) - if err != nil { - return response, fmt.Errorf("Error unmarshalling json: %s", err) - } - } else { - err = json.NewDecoder(response.Body).Decode(v) - if err != nil { - return response, err - } + err = json.NewDecoder(body).Decode(v) + if err != nil { + return response, err } } @@ -425,7 +413,7 @@ func (c *Client) checkRateLimitBeforeDo(req *http.Request) *RateLimitError { StatusCode: http.StatusTooManyRequests, Request: req, Header: make(http.Header), - Body: ioutil.NopCloser(strings.NewReader("")), + Body: io.NopCloser(strings.NewReader("")), } return &RateLimitError{ Rate: rate, @@ -478,7 +466,7 @@ func CheckResponse(r *http.Response) error { jsonErrorResponse := &JSONErrorResponse{Response: r} - data, err := ioutil.ReadAll(r.Body) + data, err := io.ReadAll(r.Body) if err == nil && len(data) > 0 { json.Unmarshal(data, jsonErrorResponse) if len(jsonErrorResponse.JSON.Errors) > 0 { @@ -487,14 +475,14 @@ func CheckResponse(r *http.Response) error { } // reset response body - r.Body = ioutil.NopCloser(bytes.NewBuffer(data)) + r.Body = io.NopCloser(bytes.NewBuffer(data)) if c := r.StatusCode; c >= 200 && c <= 299 { return nil } errorResponse := &ErrorResponse{Response: r} - data, err = ioutil.ReadAll(r.Body) + data, err = io.ReadAll(r.Body) if err == nil && len(data) > 0 { err := json.Unmarshal(data, errorResponse) if err != nil { diff --git a/reddit/things.go b/reddit/things.go index 90d15c1..1a591fd 100644 --- a/reddit/things.go +++ b/reddit/things.go @@ -434,6 +434,10 @@ type Comment struct { CanGild bool `json:"can_gild"` NSFW bool `json:"over_18"` + Distinguished string `json:"distinguished"` + Depth int `json:"depth"` + BodyHtml string `json:"body_html"` + Replies Replies `json:"replies"` } @@ -442,6 +446,11 @@ func (c *Comment) HasMore() bool { return c.Replies.More != nil && len(c.Replies.More.Children) > 0 } +// Denotes whether the comment was written by a moderator +func (c *Comment) IsModerator() bool { + return c.Distinguished == "moderator" +} + // addCommentToReplies traverses the comment tree to find the one // that the 2nd comment is replying to. It then adds it to its replies. func (c *Comment) addCommentToReplies(comment *Comment) { @@ -569,13 +578,32 @@ type Post struct { PollData *PollData `json:"poll_data"` } -type PollData struct { +type PollDataInner struct { Timestamp int `json:"voting_end_timestamp"` Options []PollOption `json:"options"` IsPrediction bool `json:"is_prediction"` TotalVoteCount int `json:"total_vote_count"` } +type PollData struct { + PollDataInner +} + +func (d *PollData) UnmarshalJSON(data []byte) error { + var junk bool + err := json.Unmarshal(data, &junk) + if err == nil { + return nil + } + inner := new(PollDataInner) + err = json.Unmarshal(data, inner) + if err != nil { + return err + } + d.PollDataInner = *inner + return nil +} + type PollOption struct { Text string `json:"text"` Id string `json:"id"`