fork of indigo with slightly nicer lexgen

automod: basic set storage API

Changed files
+46 -16
automod
cmd
+10 -11
automod/engine.go
··· 5 5 "fmt" 6 6 "log/slog" 7 7 "strings" 8 - "sync" 9 8 10 9 appbsky "github.com/bluesky-social/indigo/api/bsky" 11 10 "github.com/bluesky-social/indigo/atproto/identity" 12 11 "github.com/bluesky-social/indigo/atproto/syntax" 13 - "github.com/bluesky-social/indigo/xrpc" 14 12 ) 15 13 16 14 // runtime for executing rules, managing state, and recording moderation actions. 17 15 // 18 16 // TODO: careful when initializing: several fields should not be null or zero, even though they are pointer type. 19 17 type Engine struct { 20 - Logger *slog.Logger 18 + Logger *slog.Logger 21 19 Directory identity.Directory 22 20 // current rule sets. will eventually be possible to swap these out at runtime 23 - RulesMap sync.Map 21 + // TODO: RulesMap sync.Map 24 22 // used to persist moderation actions in mod service (optional) 25 - AdminClient *xrpc.Client 26 - CountStore CountStore 23 + // TODO: AdminClient *xrpc.Client 24 + Counters CountStore 25 + Sets SetStore 27 26 } 28 27 29 28 func (e *Engine) ProcessIdentityEvent(ctx context.Context, t string, did syntax.DID) error { ··· 92 91 93 92 func (e *Engine) NewPostEvent(ident *identity.Identity, path string, post *appbsky.FeedPost) PostEvent { 94 93 return PostEvent{ 95 - RecordEvent { 94 + RecordEvent{ 96 95 Event{ 97 96 Engine: e, 98 97 Account: AccountMeta{Identity: ident}, ··· 119 118 } 120 119 121 120 func (e *Engine) GetCount(key, period string) (int, error) { 122 - return e.CountStore.GetCount(context.TODO(), key, period) 121 + return e.Counters.GetCount(context.TODO(), key, period) 123 122 } 124 123 125 - func (e *Engine) InSet(setName, val string) (bool, error) { 126 - // XXX: implement 127 - return false, nil 124 + // checks if `val` is an element of set `name` 125 + func (e *Engine) InSet(name, val string) (bool, error) { 126 + return e.Sets.InSet(context.TODO(), name, val) 128 127 }
+30
automod/setstore.go
··· 1 + package automod 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + ) 7 + 8 + type SetStore interface { 9 + InSet(ctx context.Context, name, val string) (bool, error) 10 + } 11 + 12 + // TODO: this implementation isn't race-safe (yet)! 13 + type MemSetStore struct { 14 + Sets map[string]map[string]bool 15 + } 16 + 17 + func NewMemSetStore() MemSetStore { 18 + return MemSetStore{ 19 + Sets: make(map[string]map[string]bool), 20 + } 21 + } 22 + 23 + func (s MemSetStore) InSet(ctx context.Context, name, val string) (bool, error) { 24 + set, ok := s.Sets[name] 25 + if !ok { 26 + return false, fmt.Errorf("not a known set: %s", name) 27 + } 28 + _, ok = set[val] 29 + return ok, nil 30 + }
+3 -3
cmd/hepa/otel.go
··· 1 1 package main 2 2 3 3 import ( 4 - "os" 5 - "log/slog" 6 - "log" 7 4 "context" 5 + "log" 6 + "log/slog" 7 + "os" 8 8 "time" 9 9 10 10 "go.opentelemetry.io/otel"
+3 -2
cmd/hepa/server.go
··· 38 38 } 39 39 40 40 engine := automod.Engine{ 41 - Logger: logger, 41 + Logger: logger, 42 42 Directory: dir, 43 - CountStore: automod.NewMemCountStore(), 43 + Counters: automod.NewMemCountStore(), 44 + Sets: automod.NewMemSetStore(), 44 45 // TODO: RulesMap (loaded/config from somewhere) 45 46 // TODO: AdminClient (XRPC with mod access) 46 47 }