A community based topic aggregation platform built on atproto
1package community
2
3import (
4 "Coves/internal/atproto/pds"
5 "Coves/internal/core/communities"
6 "encoding/json"
7 "errors"
8 "log"
9 "net/http"
10)
11
12// XRPCError represents an XRPC error response
13type XRPCError struct {
14 Error string `json:"error"`
15 Message string `json:"message"`
16}
17
18// writeError writes an XRPC error response
19func writeError(w http.ResponseWriter, status int, error, message string) {
20 w.Header().Set("Content-Type", "application/json")
21 w.WriteHeader(status)
22 if err := json.NewEncoder(w).Encode(XRPCError{
23 Error: error,
24 Message: message,
25 }); err != nil {
26 log.Printf("Failed to encode error response: %v", err)
27 }
28}
29
30// handleServiceError converts service errors to appropriate HTTP responses
31func handleServiceError(w http.ResponseWriter, err error) {
32 switch {
33 case communities.IsNotFound(err):
34 writeError(w, http.StatusNotFound, "NotFound", err.Error())
35 case communities.IsConflict(err):
36 if err == communities.ErrHandleTaken {
37 writeError(w, http.StatusConflict, "NameTaken", "Community handle is already taken")
38 } else {
39 writeError(w, http.StatusConflict, "AlreadyExists", err.Error())
40 }
41 case communities.IsValidationError(err):
42 writeError(w, http.StatusBadRequest, "InvalidRequest", err.Error())
43 case err == communities.ErrUnauthorized:
44 writeError(w, http.StatusForbidden, "Forbidden", "You do not have permission to perform this action")
45 case err == communities.ErrMemberBanned:
46 writeError(w, http.StatusForbidden, "Blocked", "You are blocked from this community")
47 // PDS-specific errors (from DPoP authentication or PDS API calls)
48 case errors.Is(err, pds.ErrBadRequest):
49 writeError(w, http.StatusBadRequest, "InvalidRequest", "Invalid request to PDS")
50 case errors.Is(err, pds.ErrNotFound):
51 writeError(w, http.StatusNotFound, "NotFound", "Record not found on PDS")
52 case errors.Is(err, pds.ErrConflict):
53 writeError(w, http.StatusConflict, "Conflict", "Record was modified by another operation")
54 case errors.Is(err, pds.ErrUnauthorized), errors.Is(err, pds.ErrForbidden):
55 // PDS auth errors should prompt re-authentication
56 writeError(w, http.StatusUnauthorized, "AuthRequired", "Authentication required or session expired")
57 default:
58 // Internal server error - log the actual error for debugging
59 log.Printf("XRPC handler error: %v", err)
60 writeError(w, http.StatusInternalServerError, "InternalServerError", "An internal error occurred")
61 }
62}