A community based topic aggregation platform built on atproto
1package discover
2
3import (
4 "context"
5 "fmt"
6)
7
8type discoverService struct {
9 repo Repository
10}
11
12// NewDiscoverService creates a new discover service
13func NewDiscoverService(repo Repository) Service {
14 return &discoverService{
15 repo: repo,
16 }
17}
18
19// GetDiscover retrieves posts from all communities (public feed)
20func (s *discoverService) GetDiscover(ctx context.Context, req GetDiscoverRequest) (*DiscoverResponse, error) {
21 // Validate request
22 if err := s.validateRequest(&req); err != nil {
23 return nil, err
24 }
25
26 // Fetch discover feed from repository (all posts from all communities)
27 feedPosts, cursor, err := s.repo.GetDiscover(ctx, req)
28 if err != nil {
29 return nil, fmt.Errorf("failed to get discover feed: %w", err)
30 }
31
32 // Return discover response
33 return &DiscoverResponse{
34 Feed: feedPosts,
35 Cursor: cursor,
36 }, nil
37}
38
39// validateRequest validates the discover request parameters
40func (s *discoverService) validateRequest(req *GetDiscoverRequest) error {
41 // Validate and set defaults for sort
42 if req.Sort == "" {
43 req.Sort = "hot"
44 }
45 validSorts := map[string]bool{"hot": true, "top": true, "new": true}
46 if !validSorts[req.Sort] {
47 return NewValidationError("sort", "sort must be one of: hot, top, new")
48 }
49
50 // Validate and set defaults for limit
51 if req.Limit <= 0 {
52 req.Limit = 15
53 }
54 if req.Limit > 50 {
55 return NewValidationError("limit", "limit must not exceed 50")
56 }
57
58 // Validate and set defaults for timeframe (only used with top sort)
59 if req.Sort == "top" && req.Timeframe == "" {
60 req.Timeframe = "day"
61 }
62 validTimeframes := map[string]bool{
63 "hour": true, "day": true, "week": true,
64 "month": true, "year": true, "all": true,
65 }
66 if req.Timeframe != "" && !validTimeframes[req.Timeframe] {
67 return NewValidationError("timeframe", "timeframe must be one of: hour, day, week, month, year, all")
68 }
69
70 return nil
71}