114 lines
2.2 KiB
Go
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)
|
|
}
|