Files
keepassgo/internal/clipboard/service.go
2026-04-09 06:42:21 -07:00

102 lines
1.8 KiB
Go

package clipboard
import (
"errors"
systemclipboard "github.com/atotto/clipboard"
"git.julianfamily.org/keepassgo/internal/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
}