this repo has no description
0
fork

Configure Feed

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

at main 145 lines 3.6 kB view raw
1package main 2 3import ( 4 "encoding/json" 5 "fmt" 6 "log/slog" 7 "net/http" 8 "strconv" 9) 10 11type FeedReponse struct { 12 Cursor string `json:"cursor"` 13 Feed []FeedItem `json:"feed"` 14} 15 16type FeedItem struct { 17 Post string `json:"post"` 18 FeedContext string `json:"feedContext"` 19} 20 21type WellKnownResponse struct { 22 Context []string `json:"@context"` 23 Id string `json:"id"` 24 Service []WellKnownService `json:"service"` 25} 26 27type WellKnownService struct { 28 Id string `json:"id"` 29 Type string `json:"type"` 30 ServiceEndpoint string `json:"serviceEndpoint"` 31} 32 33func (s *Server) HandleGetFeedSkeleton(w http.ResponseWriter, r *http.Request) { 34 slog.Info("got request for feed skeleton", "host", r.RemoteAddr) 35 params := r.URL.Query() 36 37 feed := params.Get("feed") 38 if feed == "" { 39 slog.Error("missing feed query param", "host", r.RemoteAddr) 40 http.Error(w, "missing feed query param", http.StatusBadRequest) 41 return 42 } 43 slog.Info("request for feed", "feed", feed) 44 45 limitStr := params.Get("limit") 46 limit := 50 47 if limitStr != "" { 48 var err error 49 limit, err = strconv.Atoi(limitStr) 50 if err != nil { 51 slog.Error("convert limit query param", "error", err) 52 http.Error(w, "invalid limit query param", http.StatusBadRequest) 53 return 54 } 55 if limit < 1 || limit > 100 { 56 limit = 50 57 } 58 } 59 60 cursor := params.Get("cursor") 61 usersDID, err := getRequestUserDID(r) 62 if err != nil { 63 slog.Error("validate auth", "error", err) 64 http.Error(w, "validate auth", http.StatusUnauthorized) 65 return 66 } 67 if usersDID == "" { 68 slog.Error("missing users DID from request") 69 http.Error(w, "validate auth", http.StatusUnauthorized) 70 return 71 } 72 73 resp, err := s.feeder.GetFeed(r.Context(), usersDID, feed, cursor, limit) 74 if err != nil { 75 slog.Error("get feed", "error", err, "feed", feed) 76 http.Error(w, "error getting feed", http.StatusInternalServerError) 77 return 78 } 79 80 b, err := json.Marshal(resp) 81 if err != nil { 82 slog.Error("marshall error", "error", err, "host", r.RemoteAddr) 83 http.Error(w, "failed to encode resp", http.StatusInternalServerError) 84 return 85 } 86 87 w.Header().Set("Content-Type", "application/json") 88 89 _, _ = w.Write(b) 90} 91 92type DescribeFeedResponse struct { 93 DID string `json:"did"` 94 Feeds []FeedRespsonse `json:"feeds"` 95} 96 97type FeedRespsonse struct { 98 URI string `json:"uri"` 99} 100 101func (s *Server) HandleDescribeFeedGenerator(w http.ResponseWriter, r *http.Request) { 102 slog.Info("got request for describe feed", "host", r.RemoteAddr) 103 resp := DescribeFeedResponse{ 104 DID: fmt.Sprintf("did:web:%s", s.feedHost), 105 Feeds: []FeedRespsonse{ 106 { 107 URI: fmt.Sprintf("at://%s/app.bsky.feed.generator/bookmark-replies", s.feedDidBase), 108 }, 109 { 110 URI: fmt.Sprintf("at://%s/app.bsky.feed.generator/bookmarks", s.feedDidBase), 111 }, 112 }, 113 } 114 115 b, err := json.Marshal(resp) 116 if err != nil { 117 http.Error(w, "failed to encode resp", http.StatusInternalServerError) 118 return 119 } 120 121 _, _ = w.Write(b) 122} 123 124func (s *Server) HandleWellKnown(w http.ResponseWriter, r *http.Request) { 125 slog.Info("got request for well known", "host", r.RemoteAddr) 126 resp := WellKnownResponse{ 127 Context: []string{"https://www.w3.org/ns/did/v1"}, 128 Id: fmt.Sprintf("did:web:%s", s.feedHost), 129 Service: []WellKnownService{ 130 { 131 Id: "#bsky_fg", 132 Type: "BskyFeedGenerator", 133 ServiceEndpoint: fmt.Sprintf("https://%s", s.feedHost), 134 }, 135 }, 136 } 137 138 b, err := json.Marshal(resp) 139 if err != nil { 140 http.Error(w, "failed to encode resp", http.StatusInternalServerError) 141 return 142 } 143 144 _, _ = w.Write(b) 145}