its for when you want to get like notifications for your reposts
1package main
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7
8 "github.com/bluesky-social/indigo/api/atproto"
9 "github.com/bluesky-social/indigo/api/bsky"
10 "github.com/bluesky-social/indigo/atproto/identity"
11 "github.com/bluesky-social/indigo/atproto/syntax"
12 "github.com/bluesky-social/indigo/xrpc"
13 "github.com/bluesky-social/jetstream/pkg/models"
14)
15
16func findUserPDS(ctx context.Context, did syntax.DID) (string, error) {
17 id, err := identity.DefaultDirectory().LookupDID(ctx, did)
18 if err != nil {
19 return "", err
20 }
21 pdsURI := id.PDSEndpoint()
22 if len(pdsURI) == 0 {
23 return "", fmt.Errorf("no PDS URL was found in identity document")
24 }
25
26 return pdsURI, nil
27}
28
29func fetchRecord[v any](ctx context.Context, xrpcClient *xrpc.Client, val *v, event *models.Event) error {
30 out, err := atproto.RepoGetRecord(ctx, xrpcClient, "", event.Commit.Collection, event.Did, event.Commit.RKey)
31 if err != nil {
32 return err
33 }
34 raw, _ := out.Value.MarshalJSON()
35 if err := json.Unmarshal(raw, val); err != nil {
36 return err
37 }
38 return nil
39}
40
41func fetchRecords[v any](ctx context.Context, xrpcClient *xrpc.Client, cb func(syntax.ATURI, v), collection string, did syntax.DID) error {
42 if xrpcClient == nil {
43 pdsURI, err := findUserPDS(ctx, did)
44 if err != nil {
45 return err
46 }
47 xrpcClient = &xrpc.Client{
48 Host: pdsURI,
49 }
50 }
51
52 cursor := ""
53
54 for {
55 // todo: ratelimits?? idk what this does for those
56 out, err := atproto.RepoListRecords(ctx, xrpcClient, collection, cursor, 100, string(did), false)
57 if err != nil {
58 return err
59 }
60
61 for _, record := range out.Records {
62 raw, _ := record.Value.MarshalJSON()
63 var val v
64 if err := json.Unmarshal(raw, &val); err != nil {
65 return err
66 }
67 cb(syntax.ATURI(record.Uri), val)
68 }
69
70 if out.Cursor == nil || *out.Cursor == "" {
71 break
72 }
73 cursor = *out.Cursor
74
75 break
76 }
77
78 return nil
79}
80
81func fetchFollows(ctx context.Context, xrpcClient *xrpc.Client, did syntax.DID) (map[syntax.RecordKey]bsky.GraphFollow, error) {
82 out := make(map[syntax.RecordKey]bsky.GraphFollow)
83 fetchRecords(ctx, xrpcClient, func(uri syntax.ATURI, f bsky.GraphFollow) { out[uri.RecordKey()] = f }, "app.bsky.graph.follow", did)
84 return out, nil
85}
86
87func fetchRepostLikes(ctx context.Context, xrpcClient *xrpc.Client, did syntax.DID) (map[syntax.RecordKey]bsky.FeedLike, error) {
88 out := make(map[syntax.RecordKey]bsky.FeedLike)
89 fetchRecords(ctx, xrpcClient, func(uri syntax.ATURI, f bsky.FeedLike) {
90 if f.Via != nil && syntax.ATURI(f.Via.Uri).Collection() == "app.bsky.feed.repost" {
91 out[uri.RecordKey()] = f
92 }
93 }, "app.bsky.feed.like", did)
94 return out, nil
95}