Redmage/api/reddit/get_posts.go

73 lines
1.8 KiB
Go

package reddit
import (
"context"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"strings"
"github.com/tigorlazuardi/redmage/pkg/errs"
)
type SubredditType int
const (
SubredditTypeSub SubredditType = iota
SubredditTypeUser
)
func (s SubredditType) Code() string {
switch s {
case SubredditTypeUser:
return "user"
default:
return "r"
}
}
type GetPostsParam struct {
Subreddit string
Limit int
After string
SubredditType SubredditType
}
func (reddit *Reddit) GetPosts(ctx context.Context, params GetPostsParam) (posts Listing, err error) {
url := fmt.Sprintf("https://reddit.com/%s/%s.json?limit=%d&after=%s", params.SubredditType.Code(), params.Subreddit, params.Limit, params.After)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody)
if err != nil {
return posts, errs.Wrapw(err, "reddit: failed to create http request instance", "url", url, "params", params)
}
res, err := reddit.Client.Do(req)
if err != nil {
return posts, errs.Wrapw(err, "reddit: failed to execute http request", "url", url, "params", params)
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
body, _ := io.ReadAll(res.Body)
return posts, errs.Fail("reddit: unexpected status code when executing GetPosts",
slog.Group("request", "url", url, "params", params),
slog.Group("response", "status_code", res.StatusCode, "body", formatLogBody(res, body)),
).Code(res.StatusCode)
}
err = json.NewDecoder(res.Body).Decode(&posts)
if err != nil {
return posts, errs.Wrapw(err, "reddit: failed to parse response body when getting posts from reddit", "url", url, "params", params)
}
return posts, nil
}
func formatLogBody(res *http.Response, body []byte) any {
if strings.HasPrefix(res.Header.Get("Content-Type"), "application/json") {
return json.RawMessage(body)
}
return string(body)
}