diff --git a/go.mod b/go.mod index 74a2662..c864fcb 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/bugsnag/bugsnag-go/v2 v2.5.1 github.com/glebarez/go-sqlite v1.22.0 github.com/golang-jwt/jwt/v5 v5.2.1 + github.com/stretchr/testify v1.9.0 ) require ( @@ -16,6 +17,7 @@ require ( github.com/bugsnag/panicwrap v1.3.4 // indirect github.com/carlmjohnson/versioninfo v0.22.5 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect @@ -54,6 +56,7 @@ require ( github.com/multiformats/go-varint v0.0.7 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect @@ -77,6 +80,7 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect modernc.org/libc v1.37.6 // indirect modernc.org/mathutil v1.6.0 // indirect diff --git a/hander_test.go b/hander_test.go new file mode 100644 index 0000000..657b049 --- /dev/null +++ b/hander_test.go @@ -0,0 +1,106 @@ +package main + +import ( + "context" + "encoding/json" + "testing" + + "github.com/bluesky-social/indigo/api/atproto" + apibsky "github.com/bluesky-social/indigo/api/bsky" + "github.com/bluesky-social/jetstream/pkg/models" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/willdot/bskyfeedgen/store" +) + +func TestHandlerReceivesSubscribeMessage(t *testing.T) { + db, err := store.New(":memory:") + require.NoError(t, err) + + handler := handler{ + store: db, + } + + record := apibsky.FeedPost{ + Text: "/subscribe", + Reply: &apibsky.FeedPost_ReplyRef{ + Parent: &atproto.RepoStrongRef{ + Uri: "parent-uri", + }, + }, + } + + recordB, err := json.Marshal(record) + require.NoError(t, err) + + event := &models.Event{ + Did: myDid, + Commit: &models.Commit{ + Operation: models.CommitOperationCreate, + Collection: "app.bsky.feed.post", + RKey: "subscribe-post-rkey", + Record: recordB, + }, + } + + // send the event twice to simulate subscribing to the same post twice, to check only + // 1 subscription is created + err = handler.HandleEvent(context.Background(), event) + require.NoError(t, err) + err = handler.HandleEvent(context.Background(), event) + require.NoError(t, err) + + subs, err := db.GetSubscriptionsForPost("parent-uri") + require.NoError(t, err) + + assert.Len(t, subs, 1) + assert.Equal(t, myDid, subs[0]) +} + +func TestHandlerReceivesReplyToASubscribedPost(t *testing.T) { + db, err := store.New(":memory:") + require.NoError(t, err) + + handler := handler{ + store: db, + } + + // add the subscription + err = db.AddSubscriptionForPost("parent-uri", myDid, "subscribe-post-rkey") + require.NoError(t, err) + + record := apibsky.FeedPost{ + Text: "this is a reply to a post that was subscribed to", + Reply: &apibsky.FeedPost_ReplyRef{ + Parent: &atproto.RepoStrongRef{ + Uri: "parent-uri", + }, + }, + } + + recordB, err := json.Marshal(record) + require.NoError(t, err) + + event := &models.Event{ + Did: myDid, + Commit: &models.Commit{ + Operation: models.CommitOperationCreate, + Collection: "app.bsky.feed.post", + RKey: "reply-post-rkey", + Record: recordB, + }, + } + + // send the event twice to simulate subscribing to the same post twice, to check only + // 1 subscription is created + err = handler.HandleEvent(context.Background(), event) + require.NoError(t, err) + err = handler.HandleEvent(context.Background(), event) + require.NoError(t, err) + + subs, err := db.GetSubscriptionsForPost("some-uri") + require.NoError(t, err) + + assert.Len(t, subs, 1) + assert.Equal(t, myDid, subs[0]) +} diff --git a/handler.go b/handler.go index 0f68395..6cecdae 100644 --- a/handler.go +++ b/handler.go @@ -13,6 +13,10 @@ import ( "github.com/willdot/bskyfeedgen/store" ) +const ( + myDid = "did:plc:dadhhalkfcq3gucaq25hjqon" +) + type HandlerStore interface { AddFeedPost(feedItem store.FeedPost) error GetSubscriptionsForPost(postURI string) ([]string, error) @@ -62,7 +66,7 @@ func (h *handler) handleCreateEvent(_ context.Context, event *models.Event) erro // look for posts that are "subscribe" so that we can add the post URI to a list of posts we want to find replies for if strings.Contains(post.Text, "/subscribe") { // For now just look for me - if event.Did != "did:plc:dadhhalkfcq3gucaq25hjqon" { + if event.Did != myDid { return nil } slog.Info("a post that's subscribing to another post. Adding to posts to look for", "subscribed post URI", subscribedPostURI) diff --git a/store/database.go b/store/database.go index c5dd212..ce2d5be 100644 --- a/store/database.go +++ b/store/database.go @@ -15,9 +15,11 @@ type Store struct { } func New(dbPath string) (*Store, error) { - err := createDbFile(dbPath) - if err != nil { - return nil, fmt.Errorf("create db file: %w", err) + if dbPath != ":memory:" { + err := createDbFile(dbPath) + if err != nil { + return nil, fmt.Errorf("create db file: %w", err) + } } db, err := sql.Open("sqlite", dbPath)