Subscribe and post RSS feeds to Bluesky
rss
bluesky
1package storage
2
3import (
4 "bufio"
5 "fmt"
6 "os"
7 "sync"
8)
9
10// Storage handles persistence of posted item GUIDs
11type Storage struct {
12 filePath string
13 posted map[string]bool
14 mu sync.RWMutex
15}
16
17// New creates a new storage instance
18func New(filePath string) (*Storage, error) {
19 s := &Storage{
20 filePath: filePath,
21 posted: make(map[string]bool),
22 }
23
24 // Load existing posted items
25 if err := s.load(); err != nil {
26 return nil, fmt.Errorf("failed to load storage: %w", err)
27 }
28
29 return s, nil
30}
31
32// load reads the posted items from disk
33func (s *Storage) load() error {
34 file, err := os.Open(s.filePath)
35 if err != nil {
36 if os.IsNotExist(err) {
37 // File doesn't exist yet, that's okay
38 return nil
39 }
40 return err
41 }
42 defer file.Close()
43
44 scanner := bufio.NewScanner(file)
45 for scanner.Scan() {
46 guid := scanner.Text()
47 if guid != "" {
48 s.posted[guid] = true
49 }
50 }
51
52 return scanner.Err()
53}
54
55// save writes the posted items to disk
56func (s *Storage) save() error {
57 file, err := os.Create(s.filePath)
58 if err != nil {
59 return err
60 }
61 defer file.Close()
62
63 writer := bufio.NewWriter(file)
64 for guid := range s.posted {
65 if _, err := writer.WriteString(guid + "\n"); err != nil {
66 return err
67 }
68 }
69
70 return writer.Flush()
71}
72
73// IsPosted checks if a GUID has been posted
74func (s *Storage) IsPosted(guid string) bool {
75 s.mu.RLock()
76 defer s.mu.RUnlock()
77 return s.posted[guid]
78}
79
80// MarkPosted marks a GUID as posted
81func (s *Storage) MarkPosted(guid string) error {
82 s.mu.Lock()
83 defer s.mu.Unlock()
84
85 s.posted[guid] = true
86 return s.save()
87}
88
89// Count returns the number of posted items
90func (s *Storage) Count() int {
91 s.mu.RLock()
92 defer s.mu.RUnlock()
93 return len(s.posted)
94}