A community based topic aggregation platform built on atproto
at main 3.3 kB view raw
1package comments 2 3import ( 4 "Coves/internal/api/middleware" 5 "Coves/internal/core/comments" 6 "encoding/json" 7 "log" 8 "net/http" 9) 10 11// UpdateCommentHandler handles comment update requests 12type UpdateCommentHandler struct { 13 service comments.Service 14} 15 16// NewUpdateCommentHandler creates a new handler for updating comments 17func NewUpdateCommentHandler(service comments.Service) *UpdateCommentHandler { 18 return &UpdateCommentHandler{ 19 service: service, 20 } 21} 22 23// UpdateCommentInput matches the lexicon input schema for social.coves.community.comment.update 24type UpdateCommentInput struct { 25 URI string `json:"uri"` 26 Content string `json:"content"` 27 Facets []interface{} `json:"facets,omitempty"` 28 Embed interface{} `json:"embed,omitempty"` 29 Langs []string `json:"langs,omitempty"` 30 Labels interface{} `json:"labels,omitempty"` 31} 32 33// UpdateCommentOutput matches the lexicon output schema 34type UpdateCommentOutput struct { 35 URI string `json:"uri"` 36 CID string `json:"cid"` 37} 38 39// HandleUpdate handles comment update requests 40// POST /xrpc/social.coves.community.comment.update 41// 42// Request body: { "uri": "at://...", "content": "..." } 43// Response: { "uri": "at://...", "cid": "..." } 44func (h *UpdateCommentHandler) HandleUpdate(w http.ResponseWriter, r *http.Request) { 45 // 1. Check method is POST 46 if r.Method != http.MethodPost { 47 http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) 48 return 49 } 50 51 // 2. Limit request body size to prevent DoS attacks (100KB should be plenty for comments) 52 r.Body = http.MaxBytesReader(w, r.Body, 100*1024) 53 54 // 3. Parse JSON body into UpdateCommentInput 55 var input UpdateCommentInput 56 if err := json.NewDecoder(r.Body).Decode(&input); err != nil { 57 writeError(w, http.StatusBadRequest, "InvalidRequest", "Invalid request body") 58 return 59 } 60 61 // 4. Get OAuth session from context (injected by auth middleware) 62 session := middleware.GetOAuthSession(r) 63 if session == nil { 64 writeError(w, http.StatusUnauthorized, "AuthRequired", "Authentication required") 65 return 66 } 67 68 // 5. Convert labels interface{} to *comments.SelfLabels if provided 69 var labels *comments.SelfLabels 70 if input.Labels != nil { 71 labelsJSON, err := json.Marshal(input.Labels) 72 if err != nil { 73 writeError(w, http.StatusBadRequest, "InvalidLabels", "Invalid labels format") 74 return 75 } 76 var selfLabels comments.SelfLabels 77 if err := json.Unmarshal(labelsJSON, &selfLabels); err != nil { 78 writeError(w, http.StatusBadRequest, "InvalidLabels", "Invalid labels structure") 79 return 80 } 81 labels = &selfLabels 82 } 83 84 // 6. Convert input to UpdateCommentRequest 85 req := comments.UpdateCommentRequest{ 86 URI: input.URI, 87 Content: input.Content, 88 Facets: input.Facets, 89 Embed: input.Embed, 90 Langs: input.Langs, 91 Labels: labels, 92 } 93 94 // 7. Call service to update comment 95 response, err := h.service.UpdateComment(r.Context(), session, req) 96 if err != nil { 97 handleServiceError(w, err) 98 return 99 } 100 101 // 8. Return JSON response with URI and CID 102 output := UpdateCommentOutput{ 103 URI: response.URI, 104 CID: response.CID, 105 } 106 107 w.Header().Set("Content-Type", "application/json") 108 w.WriteHeader(http.StatusOK) 109 if err := json.NewEncoder(w).Encode(output); err != nil { 110 log.Printf("Failed to encode response: %v", err) 111 } 112}