1package server
2
3import (
4 "strconv"
5 "strings"
6
7 "github.com/Azure/go-autorest/autorest/to"
8 "github.com/bluesky-social/indigo/atproto/data"
9 "github.com/haileyok/cocoon/internal/helpers"
10 "github.com/haileyok/cocoon/models"
11 "github.com/labstack/echo/v4"
12)
13
14type ComAtprotoRepoListRecordsResponse struct {
15 Cursor *string `json:"cursor,omitempty"`
16 Records []ComAtprotoRepoListRecordsRecordItem `json:"records"`
17}
18
19type ComAtprotoRepoListRecordsRecordItem struct {
20 Uri string `json:"uri"`
21 Cid string `json:"cid"`
22 Value map[string]any `json:"value"`
23}
24
25func getLimitFromContext(e echo.Context, def int) (int, error) {
26 limit := def
27 limitstr := e.QueryParam("limit")
28
29 if limitstr != "" {
30 l64, err := strconv.ParseInt(limitstr, 10, 32)
31 if err != nil {
32 return 0, err
33 }
34 limit = int(l64)
35 }
36
37 return limit, nil
38}
39
40func (s *Server) handleListRecords(e echo.Context) error {
41 did := e.QueryParam("repo")
42 collection := e.QueryParam("collection")
43 cursor := e.QueryParam("cursor")
44 reverse := e.QueryParam("reverse")
45 limit, err := getLimitFromContext(e, 50)
46 if err != nil {
47 return helpers.InputError(e, nil)
48 }
49
50 sort := "DESC"
51 dir := "<"
52 cursorquery := ""
53
54 if strings.ToLower(reverse) == "true" {
55 sort = "ASC"
56 dir = ">"
57 }
58
59 params := []any{did, collection}
60 if cursor != "" {
61 params = append(params, cursor)
62 cursorquery = "AND created_at " + dir + " ?"
63 }
64 params = append(params, limit)
65
66 var records []models.Record
67 if err := s.db.Raw("SELECT * FROM records WHERE did = ? AND nsid = ? "+cursorquery+" ORDER BY created_at "+sort+" limit ?", params...).Scan(&records).Error; err != nil {
68 s.logger.Error("error getting records", "error", err)
69 return helpers.ServerError(e, nil)
70 }
71
72 items := []ComAtprotoRepoListRecordsRecordItem{}
73 for _, r := range records {
74 val, err := data.UnmarshalCBOR(r.Value)
75 if err != nil {
76 return err
77 }
78
79 items = append(items, ComAtprotoRepoListRecordsRecordItem{
80 Uri: "at://" + r.Did + "/" + r.Nsid + "/" + r.Rkey,
81 Cid: r.Cid,
82 Value: val,
83 })
84 }
85
86 var newcursor *string
87 if len(records) == limit {
88 newcursor = to.StringPtr(records[len(records)-1].CreatedAt)
89 }
90
91 return e.JSON(200, ComAtprotoRepoListRecordsResponse{
92 Cursor: newcursor,
93 Records: items,
94 })
95}