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 logger := s.logger.With("name", "handleSyncGetBlocks")
22
23 var req ComAtprotoSyncGetBlocksRequest
24 if err := e.Bind(&req); err != nil {
25 return helpers.InputError(e, nil)
26 }
27
28 var cids []cid.Cid
29
30 for _, cs := range req.Cids {
31 c, err := cid.Cast([]byte(cs))
32 if err != nil {
33 return err
34 }
35
36 cids = append(cids, c)
37 }
38
39 urepo, err := s.getRepoActorByDid(ctx, req.Did)
40 if err != nil {
41 return helpers.ServerError(e, nil)
42 }
43
44 buf := new(bytes.Buffer)
45 rc, err := cid.Cast(urepo.Root)
46 if err != nil {
47 return err
48 }
49
50 hb, err := cbor.DumpObject(&car.CarHeader{
51 Roots: []cid.Cid{rc},
52 Version: 1,
53 })
54
55 if _, err := carstore.LdWrite(buf, hb); err != nil {
56 logger.Error("error writing to car", "error", err)
57 return helpers.ServerError(e, nil)
58 }
59
60 bs := s.getBlockstore(urepo.Repo.Did)
61
62 for _, c := range cids {
63 b, err := bs.Get(ctx, c)
64 if err != nil {
65 return err
66 }
67
68 if _, err := carstore.LdWrite(buf, b.Cid().Bytes(), b.RawData()); err != nil {
69 return err
70 }
71 }
72
73 return e.Stream(200, "application/vnd.ipld.car", bytes.NewReader(buf.Bytes()))
74}