aboutsummaryrefslogtreecommitdiff
path: root/cmd/stealthmountain
diff options
context:
space:
mode:
authorXe Iaso <me@xeiaso.net>2024-10-25 14:06:42 -0400
committerXe Iaso <me@xeiaso.net>2024-10-25 14:06:42 -0400
commitafa4bc6c01297af78885bf0562e2dae7ff83605b (patch)
tree97a1149d5646cf9b1c7aa2892d6e849c589219cc /cmd/stealthmountain
parent797eec6d94e193ae684db977179ea4a422b2499f (diff)
downloadx-afa4bc6c01297af78885bf0562e2dae7ff83605b.tar.xz
x-afa4bc6c01297af78885bf0562e2dae7ff83605b.zip
cmd: add amano and stealthmountain
Signed-off-by: Xe Iaso <me@xeiaso.net>
Diffstat (limited to 'cmd/stealthmountain')
-rw-r--r--cmd/stealthmountain/main.go152
1 files changed, 152 insertions, 0 deletions
diff --git a/cmd/stealthmountain/main.go b/cmd/stealthmountain/main.go
new file mode 100644
index 0000000..a8a17fb
--- /dev/null
+++ b/cmd/stealthmountain/main.go
@@ -0,0 +1,152 @@
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "log/slog"
+ "os"
+ "regexp"
+ "time"
+
+ comatproto "github.com/bluesky-social/indigo/api/atproto"
+ bskyData "github.com/bluesky-social/indigo/api/bsky"
+ jsModels "github.com/bluesky-social/jetstream/pkg/models"
+ bsky "github.com/danrusei/gobot-bsky"
+ "github.com/goccy/go-json"
+ "github.com/nats-io/nats.go"
+ "within.website/x/internal"
+)
+
+const (
+ PostTopic = "amano:commit:app.bsky.feed.post"
+)
+
+var (
+ blueskyAuthkey = flag.String("bsky-authkey", "", "Bluesky authkey")
+ blueskyHandle = flag.String("bsky-handle", "", "Bluesky handle")
+ blueskyPDS = flag.String("bsky-pds", "https://bsky.social", "Bluesky PDS")
+ natsURL = flag.String("nats-url", "nats://localhost:4222", "nats url")
+
+ sneakPeakRegex = regexp.MustCompile("(?i)sneak peak")
+)
+
+func main() {
+ internal.HandleStartup()
+
+ slog.Info("starting up",
+ "have-bsky-authkey", *blueskyAuthkey != "",
+ "bsky-handle", *blueskyHandle,
+ "bsky-pds", *blueskyPDS,
+ "nats-url", *natsURL,
+ )
+
+ nc, err := nats.Connect(*natsURL)
+ if err != nil {
+ slog.Error("can't connect to NATS", "err", err)
+ os.Exit(1)
+ }
+ defer nc.Close()
+ slog.Info("connected to NATS")
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ bsAgent, err := bskyAuth(ctx, *blueskyPDS, *blueskyHandle, *blueskyAuthkey)
+ if err != nil {
+ slog.Error("can't auth to bluesky", "err", err)
+ os.Exit(1)
+ }
+
+ sub, err := nc.SubscribeSync(PostTopic)
+ if err != nil {
+ slog.Error("can't subscribe to post feed", "err", err)
+ os.Exit(1)
+ }
+ defer sub.Drain()
+
+ for {
+ m, err := sub.NextMsg(time.Second)
+ if err != nil {
+ slog.Error("can't read message", "err", err)
+ continue
+ }
+
+ var commit jsModels.Commit
+ if err := json.Unmarshal(m.Data, &commit); err != nil {
+ slog.Error("can't unmarshal commit", "err", err)
+ continue
+ }
+
+ if commit.Operation == "delete" {
+ continue
+ }
+
+ var post bskyData.FeedPost
+ if err := json.Unmarshal(commit.Record, &post); err != nil {
+ slog.Error("can't unmarshal post", "err", err)
+ continue
+ }
+
+ if sneakPeakRegex.MatchString(post.Text) {
+ actorID := m.Header.Get("bsky-actor-did")
+ slog.Info("found a stealth mountain!", "id", commit.Rev, "actor", actorID)
+ reply, err := bsky.NewPostBuilder(`I think you mean "sneak peek"`).Build()
+ if err != nil {
+ slog.Error("can't build reply post", "err", err)
+ }
+ parent := comatproto.RepoStrongRef{
+ LexiconTypeID: "app.bsky.feed.post",
+ Uri: fmt.Sprintf("at://%s/app.bsky.feed.post/%s", actorID, commit.RKey),
+ Cid: commit.CID,
+ }
+ root := parent
+
+ if post.Reply != nil {
+ root = *post.Reply.Root
+ }
+
+ reply.Reply = &bskyData.FeedPost_ReplyRef{
+ Parent: &parent,
+ Root: &root,
+ }
+
+ reply.CreatedAt = time.Now().UTC().Format(time.RFC3339)
+
+ cid, uri, err := bsAgent.PostToFeed(ctx, reply)
+ if err != nil {
+ slog.Error("cannot post to feed", "err", err)
+ continue
+ }
+
+ slog.Info("posted to bluesky", "bluesky_cid", cid, "bluesky_uri", uri)
+ }
+ }
+}
+
+func bskyAuth(ctx context.Context, pds, handle, authkey string) (*bsky.BskyAgent, error) {
+ bluesky := bsky.NewAgent(ctx, pds, handle, authkey)
+ if err := bluesky.Connect(ctx); err != nil {
+ slog.Error("failed to connect to bluesky", "err", err)
+ return nil, err
+ }
+
+ go func() {
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+ t := time.NewTicker(5 * time.Minute)
+ defer t.Stop()
+ for range t.C {
+ if err := bluesky.Connect(ctx); err != nil {
+ slog.Error("can't reauth to bluesky", "err", err)
+ }
+ }
+ }()
+
+ if err := bluesky.Connect(ctx); err != nil {
+ slog.Error("failed to connect to bluesky", "err", err)
+ return nil, err
+ }
+
+ return &bluesky, nil
+}