Low-latency AT Protocol interaction indexer.
20

Configure Feed

Select the types of activity you want to include in your feed.

add getBacklinkDids

Aly Raffauf (Jul 2, 2026, 10:21 PM EDT) 2d9bc36e dd570b0c

+78
+44
internal/api/dids.go
··· 1 + package api 2 + 3 + import ( 4 + "encoding/json" 5 + "log" 6 + "net/http" 7 + "strconv" 8 + ) 9 + 10 + type backlinkDidsResponse struct { 11 + Total uint64 `json:"total"` 12 + LinkingDids []string `json:"linking_dids"` 13 + } 14 + 15 + func (s *Server) GetBacklinkDids(w http.ResponseWriter, r *http.Request) { 16 + subject := r.URL.Query().Get("subject") 17 + source := r.URL.Query().Get("source") 18 + 19 + collection, path, err := parseSource(source) 20 + if err != nil { 21 + http.Error(w, err.Error(), http.StatusBadRequest) 22 + return 23 + } 24 + 25 + limit := uint64(100) 26 + if raw := r.URL.Query().Get("limit"); raw != "" { 27 + parsed, err := strconv.ParseUint(raw, 10, 64) 28 + if err != nil || parsed == 0 || parsed > 1000 { 29 + http.Error(w, "limit must be a number between 1 and 1000", http.StatusBadRequest) 30 + return 31 + } 32 + limit = parsed 33 + } 34 + 35 + total, dids, err := s.Store.DistinctBacklinkDids(r.Context(), subject, collection, path, limit) 36 + if err != nil { 37 + log.Println("distinct backlink dids:", err) 38 + http.Error(w, "internal error", http.StatusInternalServerError) 39 + return 40 + } 41 + 42 + w.Header().Set("Content-Type", "application/json") 43 + json.NewEncoder(w).Encode(backlinkDidsResponse{Total: total, LinkingDids: dids}) 44 + }
+2
internal/api/server.go
··· 13 13 func (s *Server) Run(addr string) error { 14 14 mux := http.NewServeMux() 15 15 mux.HandleFunc("GET /xrpc/blue.microcosm.links.getBacklinksCount", s.GetBacklinksCount) 16 + mux.HandleFunc("GET /xrpc/blue.microcosm.links.getBacklinkDids", s.GetBacklinkDids) 17 + 16 18 17 19 return http.ListenAndServe(addr, mux) 18 20 }
+32
internal/store/query.go
··· 18 18 19 19 return total, nil 20 20 } 21 + 22 + func (s *Store) DistinctBacklinkDids(ctx context.Context, target, collection, fieldPath string, limit uint64) (total uint64, dids []string, err error) { 23 + err = s.db.QueryRowContext(ctx, 24 + `SELECT COUNT(DISTINCT actor_did) FROM links WHERE target = ? AND collection = ? AND field_path = ?`, 25 + target, collection, fieldPath, 26 + ).Scan(&total) 27 + if err != nil { 28 + return 0, nil, fmt.Errorf("count distinct dids: %w", err) 29 + } 30 + 31 + rows, err := s.db.QueryContext(ctx, 32 + `SELECT DISTINCT actor_did FROM links WHERE target = ? AND collection = ? AND field_path = ? LIMIT ?`, 33 + target, collection, fieldPath, limit, 34 + ) 35 + if err != nil { 36 + return 0, nil, fmt.Errorf("query distinct dids: %w", err) 37 + } 38 + defer rows.Close() 39 + 40 + for rows.Next() { 41 + var did string 42 + if err := rows.Scan(&did); err != nil { 43 + return 0, nil, fmt.Errorf("scan did: %w", err) 44 + } 45 + dids = append(dids, did) 46 + } 47 + if err := rows.Err(); err != nil { 48 + return 0, nil, fmt.Errorf("iterate dids: %w", err) 49 + } 50 + 51 + return total, dids, nil 52 + }