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