config.go raw
1 package main
2
3 import (
4 "os"
5 "path/filepath"
6 "strings"
7 "time"
8
9 "go-simpler.org/env"
10 "next.orly.dev/pkg/lol/chk"
11 "next.orly.dev/pkg/lol/log"
12 )
13
14 // Config holds the ACL server configuration.
15 type Config struct {
16 // Listen is the gRPC server listen address
17 Listen string `env:"ORLY_ACL_LISTEN" default:"127.0.0.1:50052" usage:"gRPC server listen address"`
18
19 // ACLMode is the active ACL mode (none, follows, managed, curating)
20 ACLMode string `env:"ORLY_ACL_MODE" default:"none" usage:"ACL mode: none, follows, managed, curating"`
21
22 // LogLevel is the logging level
23 LogLevel string `env:"ORLY_ACL_LOG_LEVEL" default:"info" usage:"log level (trace, debug, info, warn, error)"`
24
25 // Database configuration
26 DBType string `env:"ORLY_ACL_DB_TYPE" default:"badger" usage:"database type: badger or grpc"`
27 GRPCDBServer string `env:"ORLY_ACL_GRPC_DB_SERVER" usage:"gRPC database server address (when DB_TYPE=grpc)"`
28 DataDir string `env:"ORLY_DATA_DIR" usage:"database data directory (when DB_TYPE=badger)"`
29
30 // Badger configuration (when DB_TYPE=badger)
31 BlockCacheMB int `env:"ORLY_DB_BLOCK_CACHE_MB" default:"1024" usage:"block cache size in MB"`
32 IndexCacheMB int `env:"ORLY_DB_INDEX_CACHE_MB" default:"512" usage:"index cache size in MB"`
33 ZSTDLevel int `env:"ORLY_DB_ZSTD_LEVEL" default:"3" usage:"ZSTD compression level"`
34 QueryCacheSizeMB int `env:"ORLY_DB_QUERY_CACHE_SIZE_MB" default:"256" usage:"query cache size in MB"`
35 QueryCacheMaxAge time.Duration `env:"ORLY_DB_QUERY_CACHE_MAX_AGE" default:"5m" usage:"query cache max age"`
36 QueryCacheDisabled bool `env:"ORLY_DB_QUERY_CACHE_DISABLED" default:"false" usage:"disable query cache"`
37 SerialCachePubkeys int `env:"ORLY_SERIAL_CACHE_PUBKEYS" default:"100000" usage:"serial cache pubkeys capacity"`
38 SerialCacheEventIds int `env:"ORLY_SERIAL_CACHE_EVENT_IDS" default:"500000" usage:"serial cache event IDs capacity"`
39
40 // ACL configuration
41 Owners string `env:"ORLY_OWNERS" usage:"comma-separated list of owner npubs"`
42 Admins string `env:"ORLY_ADMINS" usage:"comma-separated list of admin npubs"`
43 BootstrapRelays string `env:"ORLY_BOOTSTRAP_RELAYS" usage:"comma-separated list of bootstrap relays"`
44 RelayAddresses string `env:"ORLY_RELAY_ADDRESSES" usage:"comma-separated list of relay addresses (self)"`
45
46 // Follows ACL configuration
47 FollowListFrequency time.Duration `env:"ORLY_FOLLOW_LIST_FREQUENCY" default:"1h" usage:"follow list sync frequency"`
48 FollowsThrottleEnabled bool `env:"ORLY_FOLLOWS_THROTTLE_ENABLED" default:"false" usage:"enable progressive throttle for non-followed users"`
49 FollowsThrottlePerEvent time.Duration `env:"ORLY_FOLLOWS_THROTTLE_PER_EVENT" default:"25ms" usage:"throttle delay increment per event"`
50 FollowsThrottleMaxDelay time.Duration `env:"ORLY_FOLLOWS_THROTTLE_MAX_DELAY" default:"60s" usage:"maximum throttle delay"`
51 }
52
53 // loadConfig loads configuration from environment variables.
54 func loadConfig() *Config {
55 cfg := &Config{}
56 if err := env.Load(cfg, nil); chk.E(err) {
57 log.E.F("failed to load config: %v", err)
58 os.Exit(1)
59 }
60
61 // Set default data directory if not specified
62 if cfg.DataDir == "" {
63 home, err := os.UserHomeDir()
64 if chk.E(err) {
65 log.E.F("failed to get home directory: %v", err)
66 os.Exit(1)
67 }
68 cfg.DataDir = filepath.Join(home, ".local", "share", "ORLY")
69 }
70
71 // Ensure data directory exists (for badger mode)
72 if cfg.DBType == "badger" {
73 if err := os.MkdirAll(cfg.DataDir, 0700); chk.E(err) {
74 log.E.F("failed to create data directory %s: %v", cfg.DataDir, err)
75 os.Exit(1)
76 }
77 }
78
79 return cfg
80 }
81
82 // GetOwners returns the list of owner pubkeys
83 func (c *Config) GetOwners() []string {
84 if c.Owners == "" {
85 return nil
86 }
87 return strings.Split(c.Owners, ",")
88 }
89
90 // GetAdmins returns the list of admin pubkeys
91 func (c *Config) GetAdmins() []string {
92 if c.Admins == "" {
93 return nil
94 }
95 return strings.Split(c.Admins, ",")
96 }
97
98 // GetBootstrapRelays returns the list of bootstrap relays
99 func (c *Config) GetBootstrapRelays() []string {
100 if c.BootstrapRelays == "" {
101 return nil
102 }
103 return strings.Split(c.BootstrapRelays, ",")
104 }
105
106 // GetRelayAddresses returns the list of relay addresses (self)
107 func (c *Config) GetRelayAddresses() []string {
108 if c.RelayAddresses == "" {
109 return nil
110 }
111 return strings.Split(c.RelayAddresses, ",")
112 }
113