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}