Files
klp/internal/service/monitor.go
2026-01-27 22:01:30 -06:00

114 lines
2.2 KiB
Go

package service
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"github.com/yeho/klp/internal/clipboard"
"github.com/yeho/klp/internal/config"
"github.com/yeho/klp/internal/database"
)
type Monitor struct {
cfg *config.Config
db *database.Database
clipboard clipboard.Clipboard
}
func NewMonitor(cfg *config.Config, db *database.Database) (*Monitor, error) {
clip, err := clipboard.New()
if err != nil {
return nil, fmt.Errorf("failed to initialize clipboard: %w", err)
}
return &Monitor{
cfg: cfg,
db: db,
clipboard: clip,
}, nil
}
func (m *Monitor) Run() error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Handle shutdown signals
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGINT)
go func() {
<-sigChan
fmt.Println("\nShutting down...")
cancel()
}()
fmt.Println("Clipboard monitor started. Press Ctrl+C to stop.")
changes := m.clipboard.Watch(ctx)
for {
select {
case <-ctx.Done():
return nil
case content, ok := <-changes:
if !ok {
return nil
}
if err := m.handleChange(content); err != nil {
fmt.Fprintf(os.Stderr, "Error handling clipboard change: %v\n", err)
}
}
}
}
func (m *Monitor) handleChange(content string) error {
// Skip empty content
if content == "" {
return nil
}
// Check max entry size if configured
if m.cfg.MaxEntrySize > 0 && len(content) > m.cfg.MaxEntrySize {
return nil
}
// Skip if duplicate of most recent entry
recent := m.db.MostRecent()
if recent != nil && recent.Value == content {
return nil
}
// Add to database
entry, err := m.db.Add(content)
if err != nil {
return err
}
// Log the addition (truncate for display)
preview := content
if len(preview) > 50 {
preview = preview[:50] + "..."
}
// Replace newlines for cleaner display
preview = replaceNewlines(preview)
fmt.Printf("Added [%s]: %s\n", entry.ID, preview)
return nil
}
func replaceNewlines(s string) string {
result := make([]byte, 0, len(s))
for i := 0; i < len(s); i++ {
if s[i] == '\n' {
result = append(result, ' ')
} else if s[i] == '\r' {
// skip
} else {
result = append(result, s[i])
}
}
return string(result)
}