package reddit import ( "context" "fmt" "time" "github.com/vartanbeno/go-reddit/v2/reddit" "somegit.dev/vikingowl/reddit-reader/internal/domain" ) // Fetcher is the interface for fetching posts from a subreddit. type Fetcher interface { FetchPosts(ctx context.Context, subreddit, sort string, limit int) ([]domain.Post, error) } // Client wraps the go-reddit client behind the Fetcher interface. type Client struct { rc *reddit.Client } // NewClient creates an authenticated Reddit API client. func NewClient(clientID, clientSecret, username, password string) (*Client, error) { rc, err := reddit.NewClient(reddit.Credentials{ ID: clientID, Secret: clientSecret, Username: username, Password: password, }) if err != nil { return nil, fmt.Errorf("create reddit client: %w", err) } return &Client{rc: rc}, nil } // FetchPosts retrieves posts from the given subreddit using the specified sort order. // Supported sort values: "hot", "top", "rising", and anything else defaults to "new". func (c *Client) FetchPosts(ctx context.Context, subreddit, sort string, limit int) ([]domain.Post, error) { listOpts := &reddit.ListOptions{Limit: limit} listPostOpts := &reddit.ListPostOptions{ListOptions: *listOpts} var posts []*reddit.Post var err error switch sort { case "hot": posts, _, err = c.rc.Subreddit.HotPosts(ctx, subreddit, listOpts) case "top": posts, _, err = c.rc.Subreddit.TopPosts(ctx, subreddit, listPostOpts) case "rising": posts, _, err = c.rc.Subreddit.RisingPosts(ctx, subreddit, listOpts) default: posts, _, err = c.rc.Subreddit.NewPosts(ctx, subreddit, listOpts) } if err != nil { return nil, fmt.Errorf("fetch %s/%s: %w", subreddit, sort, err) } result := make([]domain.Post, len(posts)) for i, p := range posts { var created time.Time if p.Created != nil { created = p.Created.Time } result[i] = domain.Post{ ID: p.FullID, Subreddit: p.SubredditName, Title: p.Title, Author: p.Author, URL: p.URL, SelfText: p.Body, Score: p.Score, CreatedUTC: created, } } return result, nil }