this repo has no description
1package main
2
3import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "log/slog"
8 "time"
9
10 apibsky "github.com/bluesky-social/indigo/api/bsky"
11 "github.com/bluesky-social/jetstream/pkg/models"
12 "github.com/bugsnag/bugsnag-go/v2"
13 "github.com/willdot/bskyfeedgen/store"
14)
15
16type HandlerStore interface {
17 AddRepliedPost(replyPost store.ReplyPost) error
18 GetBookmarksForPost(postURI string) ([]string, error)
19}
20
21type handler struct {
22 store HandlerStore
23}
24
25func (h *handler) HandleEvent(ctx context.Context, event *models.Event) error {
26 if event.Commit == nil {
27 return nil
28 }
29
30 switch event.Commit.Operation {
31 case models.CommitOperationCreate:
32 return h.handleCreateEvent(ctx, event)
33 default:
34 return nil
35 }
36}
37
38func (h *handler) handleCreateEvent(_ context.Context, event *models.Event) error {
39 if event.Commit.Collection != "app.bsky.feed.post" {
40 return nil
41 }
42
43 var post apibsky.FeedPost
44 if err := json.Unmarshal(event.Commit.Record, &post); err != nil {
45 // ignore this
46 return nil
47 }
48
49 // we only care about posts that have parents which are replies
50 if post.Reply == nil || post.Reply.Parent == nil || post.Reply.Parent.Uri == "" {
51 return nil
52 }
53
54 subscribedPostURI := post.Reply.Parent.Uri
55
56 // see if the post is a reply to a post we are subscribed to
57 subscribedDids := h.getSubscribedDidsForPost(subscribedPostURI)
58 if len(subscribedDids) == 0 {
59 return nil
60 }
61
62 slog.Info("post is a reply to a post that users are subscribed to", "subscribed post URI", subscribedPostURI, "dids", subscribedDids, "RKey", event.Commit.RKey)
63
64 createdAt, err := time.Parse(time.RFC3339, post.CreatedAt)
65 if err != nil {
66 slog.Error("parsing createdAt time from post", "error", err, "timestamp", post.CreatedAt)
67 createdAt = time.Now().UTC()
68 }
69
70 replyPostURI := fmt.Sprintf("at://%s/app.bsky.feed.post/%s", event.Did, event.Commit.RKey)
71 h.createReplyPostForSubscribedUsers(subscribedDids, replyPostURI, subscribedPostURI, createdAt.UnixMilli())
72 return nil
73}
74
75func (h *handler) getSubscribedDidsForPost(postURI string) []string {
76 // dids, err := h.store.GetSubscriptionsForPost(postURI)
77 dids, err := h.store.GetBookmarksForPost(postURI)
78 if err != nil {
79 slog.Error("getting bookmarks for post", "error", err)
80 _ = bugsnag.Notify(err)
81 }
82
83 return dids
84}
85
86func (h *handler) createReplyPostForSubscribedUsers(usersDids []string, replyPostURI, subscribedPostURI string, createdAt int64) {
87 for _, did := range usersDids {
88 repliedPost := store.ReplyPost{
89 ReplyURI: replyPostURI,
90 UserDID: did,
91 SubscribedPostURI: subscribedPostURI,
92 CreatedAt: createdAt,
93 }
94 err := h.store.AddRepliedPost(repliedPost)
95 if err != nil {
96 slog.Error("add users replied post", "error", err, "did", did, "reply post URI", replyPostURI)
97 _ = bugsnag.Notify(err)
98 continue
99 }
100 }
101}