Subscribe and post RSS feeds to Bluesky
rss
bluesky
1package config
2
3import (
4 "fmt"
5 "os"
6 "strings"
7 "time"
8
9 "gopkg.in/yaml.v3"
10)
11
12// Config represents the application configuration
13type Config struct {
14 Accounts []Account `yaml:"accounts"`
15 Interval time.Duration `yaml:"interval,omitempty"`
16 Storage string `yaml:"storage,omitempty"`
17}
18
19// Account represents a Bluesky account with its associated feeds
20type Account struct {
21 Handle string `yaml:"handle"`
22 Password string `yaml:"password,omitempty"`
23 PDS string `yaml:"pds,omitempty"`
24 Feeds []string `yaml:"feeds"`
25 Storage string `yaml:"storage,omitempty"` // Optional per-account storage file
26}
27
28// LoadFromFile loads configuration from a YAML file
29func LoadFromFile(path string) (*Config, error) {
30 data, err := os.ReadFile(path)
31 if err != nil {
32 return nil, fmt.Errorf("failed to read config file: %w", err)
33 }
34
35 var cfg Config
36 if err := yaml.Unmarshal(data, &cfg); err != nil {
37 return nil, fmt.Errorf("failed to parse config file: %w", err)
38 }
39
40 if err := cfg.Validate(); err != nil {
41 return nil, fmt.Errorf("invalid configuration: %w", err)
42 }
43
44 // Process environment variables in passwords
45 for i := range cfg.Accounts {
46 cfg.Accounts[i].Password = expandEnvVar(cfg.Accounts[i].Password)
47 }
48
49 // Set defaults
50 if cfg.Interval == 0 {
51 cfg.Interval = 15 * time.Minute
52 }
53 if cfg.Storage == "" {
54 cfg.Storage = "posted_items.txt"
55 }
56
57 return &cfg, nil
58}
59
60// Validate checks if the configuration is valid
61func (c *Config) Validate() error {
62 if len(c.Accounts) == 0 {
63 return fmt.Errorf("at least one account is required")
64 }
65
66 for i, account := range c.Accounts {
67 if account.Handle == "" {
68 return fmt.Errorf("account %d: handle is required", i)
69 }
70 if len(account.Feeds) == 0 {
71 return fmt.Errorf("account %d (%s): at least one feed is required", i, account.Handle)
72 }
73 if account.Password == "" {
74 return fmt.Errorf("account %d (%s): password is required", i, account.Handle)
75 }
76 }
77
78 return nil
79}
80
81// expandEnvVar expands environment variable references in the format ${VAR_NAME} or $VAR_NAME
82func expandEnvVar(value string) string {
83 if value == "" {
84 return value
85 }
86
87 // Handle ${VAR_NAME} format
88 if strings.HasPrefix(value, "${") && strings.HasSuffix(value, "}") {
89 varName := value[2 : len(value)-1]
90 if envVal := os.Getenv(varName); envVal != "" {
91 return envVal
92 }
93 return value
94 }
95
96 // Handle $VAR_NAME format
97 if strings.HasPrefix(value, "$") {
98 varName := value[1:]
99 if envVal := os.Getenv(varName); envVal != "" {
100 return envVal
101 }
102 return value
103 }
104
105 return value
106}