1package server
2
3import (
4 "bytes"
5
6 "github.com/bluesky-social/indigo/carstore"
7 "github.com/haileyok/cocoon/internal/helpers"
8 "github.com/ipfs/go-cid"
9 cbor "github.com/ipfs/go-ipld-cbor"
10 "github.com/ipld/go-car"
11 "github.com/labstack/echo/v4"
12)
13
14type ComAtprotoSyncGetBlocksRequest struct {
15 Did string `query:"did"`
16 Cids []string `query:"cids"`
17}
18
19func (s *Server) handleGetBlocks(e echo.Context) error {
20 ctx := e.Request().Context()
21
22 var req ComAtprotoSyncGetBlocksRequest
23 if err := e.Bind(&req); err != nil {
24 return helpers.InputError(e, nil)
25 }
26
27 var cids []cid.Cid
28
29 for _, cs := range req.Cids {
30 c, err := cid.Cast([]byte(cs))
31 if err != nil {
32 return err
33 }
34
35 cids = append(cids, c)
36 }
37
38 urepo, err := s.getRepoActorByDid(req.Did)
39 if err != nil {
40 return helpers.ServerError(e, nil)
41 }
42
43 buf := new(bytes.Buffer)
44 rc, err := cid.Cast(urepo.Root)
45 if err != nil {
46 return err
47 }
48
49 hb, err := cbor.DumpObject(&car.CarHeader{
50 Roots: []cid.Cid{rc},
51 Version: 1,
52 })
53
54 if _, err := carstore.LdWrite(buf, hb); err != nil {
55 s.logger.Error("error writing to car", "error", err)
56 return helpers.ServerError(e, nil)
57 }
58
59 bs := s.getBlockstore(urepo.Repo.Did)
60
61 for _, c := range cids {
62 b, err := bs.Get(ctx, c)
63 if err != nil {
64 return err
65 }
66
67 if _, err := carstore.LdWrite(buf, b.Cid().Bytes(), b.RawData()); err != nil {
68 return err
69 }
70 }
71
72 return e.Stream(200, "application/vnd.ipld.car", bytes.NewReader(buf.Bytes()))
73}