this repo has no description
1package server 2 3import ( 4 "strconv" 5 6 "github.com/Azure/go-autorest/autorest/to" 7 "github.com/bluesky-social/indigo/atproto/atdata" 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 "github.com/haileyok/cocoon/internal/helpers" 10 "github.com/haileyok/cocoon/models" 11 "github.com/labstack/echo/v4" 12) 13 14type ComAtprotoRepoListRecordsRequest struct { 15 Repo string `query:"repo" validate:"required"` 16 Collection string `query:"collection" validate:"required,atproto-nsid"` 17 Limit int64 `query:"limit"` 18 Cursor string `query:"cursor"` 19 Reverse bool `query:"reverse"` 20} 21 22type ComAtprotoRepoListRecordsResponse struct { 23 Cursor *string `json:"cursor,omitempty"` 24 Records []ComAtprotoRepoListRecordsRecordItem `json:"records"` 25} 26 27type ComAtprotoRepoListRecordsRecordItem struct { 28 Uri string `json:"uri"` 29 Cid string `json:"cid"` 30 Value map[string]any `json:"value"` 31} 32 33func getLimitFromContext(e echo.Context, def int) (int, error) { 34 limit := def 35 limitstr := e.QueryParam("limit") 36 37 if limitstr != "" { 38 l64, err := strconv.ParseInt(limitstr, 10, 32) 39 if err != nil { 40 return 0, err 41 } 42 limit = int(l64) 43 } 44 45 return limit, nil 46} 47 48func (s *Server) handleListRecords(e echo.Context) error { 49 ctx := e.Request().Context() 50 51 var req ComAtprotoRepoListRecordsRequest 52 if err := e.Bind(&req); err != nil { 53 s.logger.Error("could not bind list records request", "error", err) 54 return helpers.ServerError(e, nil) 55 } 56 57 if err := e.Validate(req); err != nil { 58 return helpers.InputError(e, nil) 59 } 60 61 if req.Limit <= 0 { 62 req.Limit = 50 63 } else if req.Limit > 100 { 64 req.Limit = 100 65 } 66 67 limit, err := getLimitFromContext(e, 50) 68 if err != nil { 69 return helpers.InputError(e, nil) 70 } 71 72 sort := "DESC" 73 dir := "<" 74 cursorquery := "" 75 76 if req.Reverse { 77 sort = "ASC" 78 dir = ">" 79 } 80 81 did := req.Repo 82 if _, err := syntax.ParseDID(did); err != nil { 83 actor, err := s.getActorByHandle(ctx, req.Repo) 84 if err != nil { 85 return helpers.InputError(e, to.StringPtr("RepoNotFound")) 86 } 87 did = actor.Did 88 } 89 90 params := []any{did, req.Collection} 91 if req.Cursor != "" { 92 params = append(params, req.Cursor) 93 cursorquery = "AND created_at " + dir + " ?" 94 } 95 params = append(params, limit) 96 97 var records []models.Record 98 if err := s.db.Raw(ctx, "SELECT * FROM records WHERE did = ? AND nsid = ? "+cursorquery+" ORDER BY created_at "+sort+" limit ?", nil, params...).Scan(&records).Error; err != nil { 99 s.logger.Error("error getting records", "error", err) 100 return helpers.ServerError(e, nil) 101 } 102 103 items := []ComAtprotoRepoListRecordsRecordItem{} 104 for _, r := range records { 105 val, err := atdata.UnmarshalCBOR(r.Value) 106 if err != nil { 107 return err 108 } 109 110 items = append(items, ComAtprotoRepoListRecordsRecordItem{ 111 Uri: "at://" + r.Did + "/" + r.Nsid + "/" + r.Rkey, 112 Cid: r.Cid, 113 Value: val, 114 }) 115 } 116 117 var newcursor *string 118 if len(records) == limit { 119 newcursor = to.StringPtr(records[len(records)-1].CreatedAt) 120 } 121 122 return e.JSON(200, ComAtprotoRepoListRecordsResponse{ 123 Cursor: newcursor, 124 Records: items, 125 }) 126}