A community based topic aggregation platform built on atproto
1package communityFeed 2 3import ( 4 "Coves/internal/core/communityFeeds" 5 "encoding/json" 6 "log" 7 "net/http" 8 "strconv" 9) 10 11// GetCommunityHandler handles community feed retrieval 12type GetCommunityHandler struct { 13 service communityFeeds.Service 14} 15 16// NewGetCommunityHandler creates a new community feed handler 17func NewGetCommunityHandler(service communityFeeds.Service) *GetCommunityHandler { 18 return &GetCommunityHandler{ 19 service: service, 20 } 21} 22 23// HandleGetCommunity retrieves posts from a community with sorting 24// GET /xrpc/social.coves.communityFeed.getCommunity?community={did_or_handle}&sort=hot&limit=15&cursor=... 25func (h *GetCommunityHandler) HandleGetCommunity(w http.ResponseWriter, r *http.Request) { 26 if r.Method != http.MethodGet { 27 http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) 28 return 29 } 30 31 // Parse query parameters 32 req, err := h.parseRequest(r) 33 if err != nil { 34 writeError(w, http.StatusBadRequest, "InvalidRequest", err.Error()) 35 return 36 } 37 38 // Alpha: No viewer context needed for basic community sorting 39 // TODO(feed-generator): Extract viewer DID when implementing viewer-specific state 40 // (blocks, upvotes, saves) in feed generator skeleton 41 42 // Get community feed 43 response, err := h.service.GetCommunityFeed(r.Context(), req) 44 if err != nil { 45 handleServiceError(w, err) 46 return 47 } 48 49 // Return feed 50 w.Header().Set("Content-Type", "application/json") 51 w.WriteHeader(http.StatusOK) 52 if err := json.NewEncoder(w).Encode(response); err != nil { 53 // Log encoding errors but don't return error response (headers already sent) 54 log.Printf("ERROR: Failed to encode feed response: %v", err) 55 } 56} 57 58// parseRequest parses query parameters into GetCommunityFeedRequest 59func (h *GetCommunityHandler) parseRequest(r *http.Request) (communityFeeds.GetCommunityFeedRequest, error) { 60 req := communityFeeds.GetCommunityFeedRequest{} 61 62 // Required: community 63 req.Community = r.URL.Query().Get("community") 64 65 // Optional: sort (default: hot) 66 req.Sort = r.URL.Query().Get("sort") 67 if req.Sort == "" { 68 req.Sort = "hot" 69 } 70 71 // Optional: timeframe (default: day for top sort) 72 req.Timeframe = r.URL.Query().Get("timeframe") 73 if req.Timeframe == "" && req.Sort == "top" { 74 req.Timeframe = "day" 75 } 76 77 // Optional: limit (default: 15, max: 50) 78 req.Limit = 15 79 if limitStr := r.URL.Query().Get("limit"); limitStr != "" { 80 if limit, err := strconv.Atoi(limitStr); err == nil { 81 req.Limit = limit 82 } 83 } 84 85 // Optional: cursor 86 if cursor := r.URL.Query().Get("cursor"); cursor != "" { 87 req.Cursor = &cursor 88 } 89 90 return req, nil 91}