package main import ( "context" "encoding/json" "fmt" "github.com/bluesky-social/indigo/api/atproto" "github.com/bluesky-social/indigo/api/bsky" "github.com/bluesky-social/indigo/atproto/identity" "github.com/bluesky-social/indigo/atproto/syntax" "github.com/bluesky-social/indigo/xrpc" "github.com/bluesky-social/jetstream/pkg/models" ) func findUserPDS(ctx context.Context, did syntax.DID) (string, error) { id, err := identity.DefaultDirectory().LookupDID(ctx, did) if err != nil { return "", err } pdsURI := id.PDSEndpoint() if len(pdsURI) == 0 { return "", fmt.Errorf("no PDS URL was found in identity document") } return pdsURI, nil } func fetchRecord[v any](ctx context.Context, xrpcClient *xrpc.Client, val *v, event *models.Event) error { out, err := atproto.RepoGetRecord(ctx, xrpcClient, "", event.Commit.Collection, event.Did, event.Commit.RKey) if err != nil { return err } raw, _ := out.Value.MarshalJSON() if err := json.Unmarshal(raw, val); err != nil { return err } return nil } func fetchRecords[v any](ctx context.Context, xrpcClient *xrpc.Client, cb func(syntax.ATURI, v), collection string, did syntax.DID) error { if xrpcClient == nil { pdsURI, err := findUserPDS(ctx, did) if err != nil { return err } xrpcClient = &xrpc.Client{ Host: pdsURI, } } cursor := "" for { // todo: ratelimits?? idk what this does for those out, err := atproto.RepoListRecords(ctx, xrpcClient, collection, cursor, 100, string(did), false) if err != nil { return err } for _, record := range out.Records { raw, _ := record.Value.MarshalJSON() var val v if err := json.Unmarshal(raw, &val); err != nil { return err } cb(syntax.ATURI(record.Uri), val) } if out.Cursor == nil || *out.Cursor == "" { break } cursor = *out.Cursor break } return nil } func fetchFollows(ctx context.Context, xrpcClient *xrpc.Client, did syntax.DID) (map[syntax.RecordKey]bsky.GraphFollow, error) { out := make(map[syntax.RecordKey]bsky.GraphFollow) fetchRecords(ctx, xrpcClient, func(uri syntax.ATURI, f bsky.GraphFollow) { out[uri.RecordKey()] = f }, "app.bsky.graph.follow", did) return out, nil } func fetchRepostLikes(ctx context.Context, xrpcClient *xrpc.Client, did syntax.DID) (map[syntax.RecordKey]bsky.FeedLike, error) { out := make(map[syntax.RecordKey]bsky.FeedLike) fetchRecords(ctx, xrpcClient, func(uri syntax.ATURI, f bsky.FeedLike) { if f.Via != nil && syntax.ATURI(f.Via.Uri).Collection() == "app.bsky.feed.repost" { out[uri.RecordKey()] = f } }, "app.bsky.feed.like", did) return out, nil }