From 54d2195b76ccc2f7e7c59237d2fa2fceebf698ee Mon Sep 17 00:00:00 2001 From: Niklas Kapelle Date: Sat, 2 May 2026 23:13:30 +0200 Subject: [PATCH] added fix-comment subcommand move the spotify url from comments to own tag (spotify) --- cmd/ripsort.go | 14 ++++- internal/fixComment.go | 103 ++++++++++++++++++++++++++++++++++ internal/metadata/metadata.go | 1 + internal/metadata/vobis.go | 4 ++ 4 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 internal/fixComment.go diff --git a/cmd/ripsort.go b/cmd/ripsort.go index 4226660..7dc1f46 100644 --- a/cmd/ripsort.go +++ b/cmd/ripsort.go @@ -16,10 +16,16 @@ type SortCmd struct { Path string `arg:"positional,required"` } +type FixCommentCmd struct { + Path string `arg:"positional,required"` +} + type args struct { - Info *InfoCmd `arg:"subcommand:info"` - Sort *SortCmd `arg:"subcommand:sort"` - Verbose bool `arg:"-v" default:"false"` + Info *InfoCmd `arg:"subcommand:info"` + Sort *SortCmd `arg:"subcommand:sort"` + FixCommentTag *FixCommentCmd `arg:"subcommand:fix-comment"` + Verbose bool `arg:"-v" default:"false"` + DryRun bool `arg:"--dry-run" default:"false"` } func Run() { @@ -35,6 +41,8 @@ func Run() { ripsort.Scan(args.Info.File) case args.Sort != nil: ripsort.Sort(args.Sort.Dst, args.Sort.Path) + case args.FixCommentTag != nil: + ripsort.FixComment(args.FixCommentTag.Path, args.DryRun) default: p.Fail("Must specify command") } diff --git a/internal/fixComment.go b/internal/fixComment.go new file mode 100644 index 0000000..840f959 --- /dev/null +++ b/internal/fixComment.go @@ -0,0 +1,103 @@ +package ripsort + +import ( + "io/fs" + "log/slog" + "os" + "path/filepath" + "regexp" + + "git.kapelle.org/niklas/ripsort/internal/metadata" +) + +func FixComment(path string, dry bool) { + + info, err := os.Stat(path) + if err != nil { + slog.Error("Failed to stat path", "file", path, "err", err) + os.Exit(1) + } + + // Handle single file + if !info.IsDir() { + if !fileSupported(path) { + slog.Error("Unsupported file format", "file", path) + os.Exit(1) + } + + err = fixCommentForFile(path, dry) + if err != nil { + slog.Error("Failed to fix comment on file", "file", path, "err", err) + os.Exit(1) + } + + return + } + + // Handle directory + err = filepath.WalkDir(path, func(p string, d fs.DirEntry, err error) error { + if err != nil { + slog.Error("Failed to walk path", "path", path, "file", p, "err", err) + return err + } + + if !d.IsDir() { + if !fileSupported(p) { + return nil + } + err = fixCommentForFile(p, dry) + if err != nil { + slog.Error("Failed to fix comment on file", "file", path, "err", err) + os.Exit(1) + } + + } + + return nil + }) + + if err != nil { + os.Exit(1) + } +} + +func fixCommentForFile(file string, dry bool) error { + + info, err := metadata.ReadAudioTags(file) + if err != nil { + return err + } + + var re = regexp.MustCompile(`(?m)(https:\/\/open\.spotify\.com\/track\/)(.*)`) + + if info.Comment == nil { + slog.Debug("Song does not contain comment", "file", file) + return nil + } + + matches := re.FindAllStringSubmatch(*info.Comment, -1) + + if len(matches) != 1 { + slog.Debug("Song does not match regex", "file", file, "comment", info.Comment) + return nil + } + + id := matches[0][2] + + slog.Debug("Spotify tag found", "file", file, "id", id) + + if dry { + slog.Info("Dryrun: Don't wite id", "file", file, "id", id) + return nil + } + + info.SpotifyID = &id + info.Comment = nil + + err = metadata.UpdateMetadata(file, file, *info) + if err != nil { + return err + } + + return nil +} diff --git a/internal/metadata/metadata.go b/internal/metadata/metadata.go index 5e1e88b..d861965 100644 --- a/internal/metadata/metadata.go +++ b/internal/metadata/metadata.go @@ -20,6 +20,7 @@ type Metadata struct { Comment *string ISRC *string Date *string + SpotifyID *string } func ReadAudioTags(filePath string) (*Metadata, error) { diff --git a/internal/metadata/vobis.go b/internal/metadata/vobis.go index 2ac89cc..a6fc95b 100644 --- a/internal/metadata/vobis.go +++ b/internal/metadata/vobis.go @@ -183,5 +183,9 @@ func createVorbisMetaBlock(m Metadata) flacvorbis.MetaDataBlockVorbisComment { vorbisMeta.Add("ALBUMARTIST", albumArtist) } + if m.SpotifyID != nil { + vorbisMeta.Add("SPOTIFY", *m.SpotifyID) + } + return *vorbisMeta }