181 lines
3.4 KiB
Go
181 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"github.com/dhowden/tag"
|
|
)
|
|
|
|
const ID3_TEMPLATE = "{{.Artist}} // {{.Album}} // {{.Title}}"
|
|
|
|
type Tags struct {
|
|
Title string
|
|
Album string
|
|
Artist string
|
|
AlbumArtist string
|
|
Composer string
|
|
Genre string
|
|
Year int
|
|
Track int
|
|
TrackCount int
|
|
Disc int
|
|
DiscCount int
|
|
}
|
|
|
|
func (t *Tags) Validate() error {
|
|
if t.Title == "" {
|
|
return errors.New("missing Title")
|
|
}
|
|
if t.Album == "" {
|
|
return errors.New("missing Album")
|
|
}
|
|
if t.Artist == "" {
|
|
return errors.New("missing Artist")
|
|
}
|
|
if t.AlbumArtist == "" {
|
|
return errors.New("missing AlbumArtist")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
err := mainErr()
|
|
if err != nil {
|
|
log.Fatal("ERROR: ", err)
|
|
}
|
|
}
|
|
|
|
func mainErr() error {
|
|
// file from arg
|
|
playlistFile := os.Args[1]
|
|
|
|
newFileLines, err := loadPlaylistFile(playlistFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newFileContent := strings.Join(newFileLines, "\n")
|
|
|
|
return writeFile(playlistFile, newFileContent)
|
|
}
|
|
|
|
// returns array of all id3 tags
|
|
func loadPlaylistFile(playlistFile string) ([]string, error) {
|
|
file, err := os.Open(playlistFile)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer file.Close()
|
|
|
|
playlistTags := make([]string, 0)
|
|
lineNumber := 0
|
|
|
|
scanner := bufio.NewScanner(file)
|
|
for scanner.Scan() {
|
|
// line by line
|
|
line := scanner.Text()
|
|
tags, err := loadPlaylistFileLine(line)
|
|
if err != nil {
|
|
// return nil, fmt.Errorf("%s line %d: %s", playlistFile, lineNumber+1, err)
|
|
errMsg := fmt.Errorf("line %d (from %s:%d): %s", len(playlistTags)+1, playlistFile, lineNumber+1, err)
|
|
fmt.Println(errMsg)
|
|
playlistTags = append(playlistTags, fmt.Sprintf("BAD LINE --- %s", line))
|
|
} else if tags != nil {
|
|
playlistTags = append(playlistTags, *tags)
|
|
}
|
|
|
|
lineNumber++
|
|
}
|
|
|
|
if err := scanner.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return playlistTags, nil
|
|
}
|
|
|
|
// ignore m3u8 tags
|
|
func loadPlaylistFileLine(line string) (*string, error) {
|
|
line = strings.TrimSpace(line)
|
|
|
|
if []rune(line)[1] == '#' {
|
|
return nil, nil
|
|
}
|
|
if len(line) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
tags, err := loadSongFile(line)
|
|
return &tags, err
|
|
}
|
|
|
|
// returns id3 tags
|
|
func loadSongFile(fileName string) (string, error) {
|
|
// load file
|
|
file, err := os.Open(fileName)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer file.Close()
|
|
|
|
tags, err := tag.ReadFrom(file)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// parse tags
|
|
track, trackCount := tags.Track()
|
|
disc, discCount := tags.Disc()
|
|
|
|
loadedTags := Tags{
|
|
Title: tags.Title(),
|
|
Album: tags.Album(),
|
|
Artist: tags.Artist(),
|
|
AlbumArtist: tags.AlbumArtist(),
|
|
Composer: tags.Composer(),
|
|
Genre: tags.Genre(),
|
|
Year: tags.Year(),
|
|
Track: track,
|
|
TrackCount: trackCount,
|
|
Disc: disc,
|
|
DiscCount: discCount,
|
|
}
|
|
|
|
err = loadedTags.Validate()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return id3Template(loadedTags)
|
|
}
|
|
|
|
// converts an id3 tag into a string
|
|
func id3Template(tags Tags) (string, error) {
|
|
tmpl := template.Must(template.New("id3template").Parse(ID3_TEMPLATE))
|
|
|
|
bufPath := bytes.NewBufferString("")
|
|
err := tmpl.Execute(bufPath, tags)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return bufPath.String(), nil
|
|
}
|
|
|
|
// outputs all strings as a file
|
|
func writeFile(inFileName string, fileContent string) error {
|
|
inFileExt := path.Ext(inFileName)
|
|
extIndex := strings.LastIndex(inFileName, inFileExt)
|
|
newFileName := inFileName[:extIndex] + ".txt"
|
|
|
|
return os.WriteFile(newFileName, []byte(fileContent), 0666)
|
|
}
|