This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / repoverify / verify.go
2.6 kB 78 lines
1package repoverify 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 "time" 9 10 "github.com/bluesky-social/indigo/atproto/syntax" 11 indigoxrpc "github.com/bluesky-social/indigo/xrpc" 12 "tangled.org/core/api/tangled" 13 "tangled.org/core/hostutil" 14 "tangled.org/core/idresolver" 15 "tangled.org/core/repoident" 16 "tangled.org/core/xrpc/xrpcclient" 17) 18 19type Result struct { 20 RepoDid repoident.RepoDid 21 OwnerDid repoident.OwnerDid 22 KnotURL repoident.KnotURL 23 // Rkey of the sh.tangled.repo record tracked by the knot; empty when the 24 // knot does not support describeRepo. 25 Rkey syntax.RecordKey 26} 27 28var ErrKnotAnswer = errors.New("knot returned an invalid describeRepo answer") 29 30func Describe(ctx context.Context, httpClient *http.Client, knot repoident.KnotURL, repoDid repoident.RepoDid) (Result, error) { 31 client := &indigoxrpc.Client{Host: knot.String(), Client: httpClient} 32 out, err := tangled.RepoDescribeRepo(ctx, client, repoDid.String()) 33 if xrpcErr := xrpcclient.HandleXrpcErr(err); xrpcErr != nil { 34 return Result{}, fmt.Errorf("describeRepo on %s: %w (%v)", knot, xrpcErr, err) 35 } 36 if out.RepoDid != repoDid.String() { 37 return Result{}, fmt.Errorf("%w: knot %s returned repoDid %q, want %q", ErrKnotAnswer, knot, out.RepoDid, repoDid) 38 } 39 ownerDid, err := repoident.NewOwnerDid(out.OwnerDid) 40 if err != nil { 41 return Result{}, fmt.Errorf("%w from knot %s: %w", ErrKnotAnswer, knot, err) 42 } 43 rkey, err := syntax.ParseRecordKey(out.Rkey) 44 if err != nil { 45 return Result{}, fmt.Errorf("%w: knot %s returned rkey %q: %w", ErrKnotAnswer, knot, out.Rkey, err) 46 } 47 return Result{RepoDid: repoDid, OwnerDid: ownerDid, KnotURL: knot, Rkey: rkey}, nil 48} 49 50type Verifier func(ctx context.Context, repoDid repoident.RepoDid) (Result, error) 51 52const verifyTimeout = 10 * time.Second 53 54func New(resolver *idresolver.Resolver, dev bool) Verifier { 55 httpClient := hostutil.SafeClient(dev, verifyTimeout) 56 policy := repoident.SchemeFor(dev) 57 58 return func(ctx context.Context, repoDid repoident.RepoDid) (Result, error) { 59 ctx, cancel := context.WithTimeout(ctx, verifyTimeout) 60 defer cancel() 61 62 ident, err := resolver.ResolveIdent(ctx, repoDid.String()) 63 if err != nil { 64 return Result{}, fmt.Errorf("resolve repoDid %s: %w", repoDid, err) 65 } 66 67 knot, err := repoident.KnotURLFromIdentity(ident, policy) 68 if err != nil { 69 return Result{}, fmt.Errorf("repoDid %s: %w", repoDid, err) 70 } 71 72 result, err := Describe(ctx, httpClient, knot, repoDid) 73 if errors.Is(err, xrpcclient.ErrXrpcUnsupported) { 74 return Result{RepoDid: repoDid, KnotURL: knot}, nil 75 } 76 return result, err 77 } 78}