···
// HandleList lists communities with filters
23
-
// GET /xrpc/social.coves.community.list?limit={n}&cursor={offset}&visibility={public|unlisted}&sortBy={created_at|member_count}
23
+
// GET /xrpc/social.coves.community.list?limit={n}&cursor={str}&sort={popular|active|new|alphabetical}&visibility={public|unlisted|private}
func (h *ListHandler) HandleList(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
···
// Parse query parameters
33
+
// Parse limit (1-100, default 50)
if limitStr := query.Get("limit"); limitStr != "" {
35
-
if l, err := strconv.Atoi(limitStr); err == nil && l > 0 {
36
+
if l, err := strconv.Atoi(limitStr); err == nil {
47
+
// Parse cursor (offset-based for now)
if cursorStr := query.Get("cursor"); cursorStr != "" {
if o, err := strconv.Atoi(cursorStr); err == nil && o >= 0 {
···
55
+
// Parse sort enum (default: popular)
56
+
sort := query.Get("sort")
61
+
// Validate sort value
62
+
validSorts := map[string]bool{
66
+
"alphabetical": true,
68
+
if !validSorts[sort] {
69
+
http.Error(w, "Invalid sort value. Must be: popular, active, new, or alphabetical", http.StatusBadRequest)
73
+
// Validate visibility value if provided
74
+
visibility := query.Get("visibility")
75
+
if visibility != "" {
76
+
validVisibilities := map[string]bool{
81
+
if !validVisibilities[visibility] {
82
+
http.Error(w, "Invalid visibility value. Must be: public, unlisted, or private", http.StatusBadRequest)
req := communities.ListCommunitiesRequest{
50
-
Visibility: query.Get("visibility"),
51
-
HostedBy: query.Get("hostedBy"),
52
-
SortBy: query.Get("sortBy"),
53
-
SortOrder: query.Get("sortOrder"),
91
+
Visibility: visibility,
92
+
Category: query.Get("category"),
93
+
Language: query.Get("language"),
// Get communities from AppView DB
57
-
results, total, err := h.service.ListCommunities(r.Context(), req)
97
+
results, err := h.service.ListCommunities(r.Context(), req)
handleServiceError(w, err)
105
+
if len(results) == limit {
106
+
// More results available - return next cursor
107
+
cursor = strconv.Itoa(offset + len(results))
109
+
// If len(results) < limit, we've reached the end - cursor remains empty string
response := map[string]interface{}{
66
-
"cursor": offset + len(results),
w.Header().Set("Content-Type", "application/json")