Live video on the AT Protocol

xrpc: implement com.atproto.sync.getRepo

+149 -1
+1 -1
Makefile
··· 385 385 && sed -i.bak 's/PlaceStreamMultistreamTarget\.Main/PlaceStreamMultistreamTarget\.Record/' $$(find ./js/streamplace/src/lexicons/types/place/stream -type f) \ 386 386 && sed -i.bak 's/PlaceStreamChatProfile\.Main/PlaceStreamChatProfile\.Record/' $$(find ./js/streamplace/src/lexicons/types/place/stream -type f) \ 387 387 && for x in $$(find ./js/streamplace/src/lexicons -type f -name '*.ts'); do \ 388 - echo 'import { AppBskyRichtextFacet, AppBskyGraphBlock, ComAtprotoRepoStrongRef, AppBskyActorDefs, ComAtprotoSyncListRepos, AppBskyActorGetProfile, AppBskyFeedGetFeedSkeleton, ComAtprotoIdentityResolveHandle, ComAtprotoModerationCreateReport, ComAtprotoRepoCreateRecord, ComAtprotoRepoDeleteRecord, ComAtprotoRepoDescribeRepo, ComAtprotoRepoGetRecord, ComAtprotoRepoListRecords, ComAtprotoRepoPutRecord, ComAtprotoRepoUploadBlob, ComAtprotoServerDescribeServer, ComAtprotoSyncGetRecord, ComAtprotoSyncListReposComAtprotoRepoCreateRecord, ComAtprotoRepoDeleteRecord, ComAtprotoRepoGetRecord, ComAtprotoRepoListRecords, ComAtprotoIdentityRefreshIdentity } from "@atproto/api"' >> $$x; \ 388 + echo 'import { ComAtprotoSyncGetRepo, AppBskyRichtextFacet, AppBskyGraphBlock, ComAtprotoRepoStrongRef, AppBskyActorDefs, ComAtprotoSyncListRepos, AppBskyActorGetProfile, AppBskyFeedGetFeedSkeleton, ComAtprotoIdentityResolveHandle, ComAtprotoModerationCreateReport, ComAtprotoRepoCreateRecord, ComAtprotoRepoDeleteRecord, ComAtprotoRepoDescribeRepo, ComAtprotoRepoGetRecord, ComAtprotoRepoListRecords, ComAtprotoRepoPutRecord, ComAtprotoRepoUploadBlob, ComAtprotoServerDescribeServer, ComAtprotoSyncGetRecord, ComAtprotoSyncListReposComAtprotoRepoCreateRecord, ComAtprotoRepoDeleteRecord, ComAtprotoRepoGetRecord, ComAtprotoRepoListRecords, ComAtprotoIdentityRefreshIdentity } from "@atproto/api"' >> $$x; \ 389 389 done \ 390 390 && npx prettier --ignore-unknown --write $$(find ./js/streamplace/src/lexicons -type f -name '*.ts') \ 391 391 && find . | grep bak$$ | xargs rm
+74
js/docs/src/content/docs/lex-reference/openapi.json
··· 1956 1956 ] 1957 1957 } 1958 1958 }, 1959 + "/xrpc/com.atproto.sync.getRepo": { 1960 + "get": { 1961 + "summary": "Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.", 1962 + "operationId": "com.atproto.sync.getRepo", 1963 + "tags": ["com.atproto.sync"], 1964 + "responses": { 1965 + "200": { 1966 + "description": "Success", 1967 + "content": { 1968 + "application/vnd.ipld.car": { 1969 + "schema": {} 1970 + } 1971 + } 1972 + }, 1973 + "400": { 1974 + "description": "Bad Request", 1975 + "content": { 1976 + "application/json": { 1977 + "schema": { 1978 + "type": "object", 1979 + "required": ["error", "message"], 1980 + "properties": { 1981 + "error": { 1982 + "type": "string", 1983 + "oneOf": [ 1984 + { 1985 + "const": "RepoNotFound" 1986 + }, 1987 + { 1988 + "const": "RepoTakendown" 1989 + }, 1990 + { 1991 + "const": "RepoSuspended" 1992 + }, 1993 + { 1994 + "const": "RepoDeactivated" 1995 + } 1996 + ] 1997 + }, 1998 + "message": { 1999 + "type": "string" 2000 + } 2001 + } 2002 + } 2003 + } 2004 + } 2005 + } 2006 + }, 2007 + "parameters": [ 2008 + { 2009 + "name": "did", 2010 + "in": "query", 2011 + "required": true, 2012 + "description": "The DID of the repo.", 2013 + "schema": { 2014 + "type": "string", 2015 + "description": "The DID of the repo.", 2016 + "format": "did" 2017 + } 2018 + }, 2019 + { 2020 + "name": "since", 2021 + "in": "query", 2022 + "required": false, 2023 + "description": "The revision ('rev') of the repo to create a diff from.", 2024 + "schema": { 2025 + "type": "string", 2026 + "description": "The revision ('rev') of the repo to create a diff from.", 2027 + "format": "tid" 2028 + } 2029 + } 2030 + ] 2031 + } 2032 + }, 1959 2033 "/xrpc/com.atproto.sync.listRepos": { 1960 2034 "get": { 1961 2035 "summary": "Enumerates all the DID, rev, and commit CID for all repos hosted by this service. Does not require auth; implemented by PDS and Relay.",
+35
lexicons/com/atproto/sync/getRepo.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "com.atproto.sync.getRepo", 4 + "defs": { 5 + "main": { 6 + "type": "query", 7 + "description": "Download a repository export as CAR file. Optionally only a 'diff' since a previous revision. Does not require auth; implemented by PDS.", 8 + "parameters": { 9 + "type": "params", 10 + "required": ["did"], 11 + "properties": { 12 + "did": { 13 + "type": "string", 14 + "format": "did", 15 + "description": "The DID of the repo." 16 + }, 17 + "since": { 18 + "type": "string", 19 + "format": "tid", 20 + "description": "The revision ('rev') of the repo to create a diff from." 21 + } 22 + } 23 + }, 24 + "output": { 25 + "encoding": "application/vnd.ipld.car" 26 + }, 27 + "errors": [ 28 + { "name": "RepoNotFound" }, 29 + { "name": "RepoTakendown" }, 30 + { "name": "RepoSuspended" }, 31 + { "name": "RepoDeactivated" } 32 + ] 33 + } 34 + } 35 + }
+12
pkg/atproto/lexicon_repo_queries.go
··· 126 126 Value: &lexutil.LexiconTypeDecoder{Val: rec}, 127 127 }, nil 128 128 } 129 + 130 + func LexiconRepoGetRepo(ctx context.Context, since string) ([]byte, error) { 131 + buf := bytes.Buffer{} 132 + 133 + repoLock.Lock() 134 + defer repoLock.Unlock() 135 + err := CarStore.ReadUserCar(ctx, RepoUser, since, true, &buf) 136 + if err != nil { 137 + return nil, fmt.Errorf("LexiconRepoGetRepo: failed to read user car: %w", err) 138 + } 139 + return buf.Bytes(), nil 140 + }
+11
pkg/spxrpc/com_atproto_sync.go
··· 46 46 }, 47 47 } 48 48 49 + func (s *Server) handleComAtprotoSyncGetRepo(ctx context.Context, did string, since string) (io.Reader, error) { 50 + if did != atproto.LexiconRepo.RepoDid() { 51 + return nil, echo.NewHTTPError(http.StatusNotFound, "RepoNotFound") 52 + } 53 + bs, err := atproto.LexiconRepoGetRepo(ctx, since) 54 + if err != nil { 55 + return nil, err 56 + } 57 + return bytes.NewReader(bs), nil 58 + } 59 + 49 60 func (s *Server) handleComAtprotoSyncSubscribeRepos(c echo.Context) error { 50 61 ctx := log.WithLogValues(c.Request().Context(), "client_ip", c.RealIP(), "user_agent", c.Request().UserAgent()) 51 62 cursor := c.QueryParam("cursor")
+16
pkg/spxrpc/stubs.go
··· 71 71 e.POST("/xrpc/com.atproto.repo.uploadBlob", s.HandleComAtprotoRepoUploadBlob) 72 72 e.GET("/xrpc/com.atproto.server.describeServer", s.HandleComAtprotoServerDescribeServer) 73 73 e.GET("/xrpc/com.atproto.sync.getRecord", s.HandleComAtprotoSyncGetRecord) 74 + e.GET("/xrpc/com.atproto.sync.getRepo", s.HandleComAtprotoSyncGetRepo) 74 75 e.GET("/xrpc/com.atproto.sync.listRepos", s.HandleComAtprotoSyncListRepos) 75 76 return nil 76 77 } ··· 230 231 var handleErr error 231 232 // func (s *Server) handleComAtprotoSyncGetRecord(ctx context.Context,collection string,did string,rkey string) (io.Reader, error) 232 233 out, handleErr = s.handleComAtprotoSyncGetRecord(ctx, collection, did, rkey) 234 + if handleErr != nil { 235 + return handleErr 236 + } 237 + return c.Stream(200, "application/vnd.ipld.car", out) 238 + } 239 + 240 + func (s *Server) HandleComAtprotoSyncGetRepo(c echo.Context) error { 241 + ctx, span := otel.Tracer("server").Start(c.Request().Context(), "HandleComAtprotoSyncGetRepo") 242 + defer span.End() 243 + did := c.QueryParam("did") 244 + since := c.QueryParam("since") 245 + var out io.Reader 246 + var handleErr error 247 + // func (s *Server) handleComAtprotoSyncGetRepo(ctx context.Context,did string,since string) (io.Reader, error) 248 + out, handleErr = s.handleComAtprotoSyncGetRepo(ctx, did, since) 233 249 if handleErr != nil { 234 250 return handleErr 235 251 }