package clipboard import ( "errors" systemclipboard "github.com/atotto/clipboard" "git.julianfamily.org/keepassgo/vault" ) var ErrUnsupportedTarget = errors.New("unsupported clipboard target") var ErrWriteFailed = errors.New("clipboard write failed") type Target string const ( TargetUsername Target = "username" TargetPassword Target = "password" TargetURL Target = "url" ) type Writer interface { WriteText(text string) error } type Service struct { Writer Writer } func (s Service) Copy(model vault.Model, entryID string, target Target) error { entry, err := findEntry(model, entryID) if err != nil { return err } content, err := contentForTarget(entry, target) if err != nil { return err } if err := s.writer().WriteText(content); err != nil { return writeError{err: err} } return nil } func (s Service) writer() Writer { if s.Writer != nil { return s.Writer } return systemWriter{} } func WriteText(text string) error { return systemWriter{}.WriteText(text) } func findEntry(model vault.Model, entryID string) (vault.Entry, error) { for _, entry := range model.Entries { if entry.ID == entryID { return entry, nil } } return vault.Entry{}, vault.ErrEntryNotFound } func contentForTarget(entry vault.Entry, target Target) (string, error) { switch target { case TargetUsername: return entry.Username, nil case TargetPassword: return entry.Password, nil case TargetURL: return entry.URL, nil default: return "", ErrUnsupportedTarget } } type systemWriter struct{} func (systemWriter) WriteText(text string) error { return systemclipboard.WriteAll(text) } type writeError struct { err error } func (e writeError) Error() string { return ErrWriteFailed.Error() } func (e writeError) Unwrap() error { return e.err } func (e writeError) Is(target error) bool { return target == ErrWriteFailed }