this repo has no description
1package main 2 3import ( 4 "bytes" 5 "context" 6 "fmt" 7 "log/slog" 8 "net/http" 9 "os" 10 "os/signal" 11 12 comatproto "github.com/bluesky-social/indigo/api/atproto" 13 "github.com/fxamacker/cbor/v2" 14 "github.com/gorilla/websocket" 15 "github.com/redis/go-redis/v9" 16 "github.com/urfave/cli/v2" 17) 18 19const ( 20 BskyModDid = `did:plc:ar7c4by46qjdydhdevvrndac` // @moderation.bsky.app 21 BskyModLabelEndpoint = `wss://mod.bsky.app/xrpc/com.atproto.label.subscribeLabels` 22 23 ActionsConfig = `bskymodactions:config` 24 LabelsAdded = `bskymodactions:added` 25 LabelsRemoved = `bskymodactions:removed` 26) 27 28func main() { 29 app := cli.App{ 30 Name: "bsky-modactions", 31 } 32 33 app.Action = func(cctx *cli.Context) error { 34 ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) 35 defer stop() 36 37 rdb := redis.NewClient(&redis.Options{ 38 Addr: "localhost:6379", 39 Password: "", 40 DB: 0, 41 }) 42 43 url := BskyModLabelEndpoint 44 seq, err := rdb.HGet(ctx, ActionsConfig, "seq").Result() 45 if err == nil && seq != "" { // err check reversed 46 url += fmt.Sprintf("?cursor=%s", seq) 47 } 48 slog.Info("connecting to websocket", "url", url) 49 50 wsconn, _, err := websocket.DefaultDialer.DialContext(ctx, url, http.Header{ 51 "User-Agent": []string{"bsky-modactions/0.1 (@bskycharts.edavis.dev)"}, 52 }) 53 if err != nil { 54 return err 55 } 56 57 go func() { 58 for { 59 select { 60 case <-ctx.Done(): 61 return 62 default: 63 } 64 65 _, p, err := wsconn.ReadMessage() 66 if err != nil { 67 slog.Error("error reading message from websocket", "err", err) 68 continue 69 } 70 71 var info comatproto.LabelSubscribeLabels_Info 72 rest, err := cbor.UnmarshalFirst(p, &info) 73 if err != nil { 74 slog.Error("error unmarshalling info", "err", err) 75 continue 76 } 77 78 var labels comatproto.LabelSubscribeLabels_Labels 79 err = labels.UnmarshalCBOR(bytes.NewReader(rest)) 80 if err != nil { 81 slog.Error("error unmarshalling label", "err", err) 82 continue 83 } 84 for _, label := range labels.Labels { 85 if label.Src != BskyModDid { 86 continue 87 } 88 89 key := LabelsAdded 90 if label.Neg != nil && *label.Neg { 91 key = LabelsRemoved 92 } 93 94 if err := rdb.ZIncrBy(ctx, key, 1, label.Val).Err(); err != nil { 95 slog.Error("error incrementing key", "key", key) 96 } 97 } 98 99 if err := rdb.HSet(ctx, ActionsConfig, "seq", labels.Seq).Err(); err != nil { 100 slog.Error("error updating seq", "err", err) 101 } 102 } 103 }() 104 105 <-ctx.Done() 106 stop() 107 slog.Info("shutting down") 108 109 return nil 110 } 111 112 if err := app.Run(os.Args); err != nil { 113 slog.Error("error running app", "err", err) 114 } 115}