Compare commits
2 commits
82efc8994e
...
c35f74ea03
Author | SHA1 | Date | |
---|---|---|---|
c35f74ea03 | |||
2d200e5f0d |
4 changed files with 65 additions and 13 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1 +1 @@
|
||||||
tagcleaner
|
id3tool
|
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
|
@ -9,7 +9,9 @@
|
||||||
"program": "${workspaceFolder}/main.go",
|
"program": "${workspaceFolder}/main.go",
|
||||||
"args": [
|
"args": [
|
||||||
"--debug",
|
"--debug",
|
||||||
"/home/velvettear/downloads/test"
|
"--timeout",
|
||||||
|
"5",
|
||||||
|
"/tmp/share/music"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,6 +2,7 @@ package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.velvettear.de/velvettear/loggo"
|
"git.velvettear.de/velvettear/loggo"
|
||||||
|
@ -9,6 +10,7 @@ import (
|
||||||
|
|
||||||
var Directory string
|
var Directory string
|
||||||
var FramesToKeep []string
|
var FramesToKeep []string
|
||||||
|
var Timeout int
|
||||||
|
|
||||||
// check program arguments and set variables accordingly
|
// check program arguments and set variables accordingly
|
||||||
func CheckArguments() {
|
func CheckArguments() {
|
||||||
|
@ -24,6 +26,10 @@ func CheckArguments() {
|
||||||
fallthrough
|
fallthrough
|
||||||
case "--frames":
|
case "--frames":
|
||||||
framesToKeep = strings.Split(os.Args[index+1], ",")
|
framesToKeep = strings.Split(os.Args[index+1], ",")
|
||||||
|
case "-t":
|
||||||
|
fallthrough
|
||||||
|
case "--timeout":
|
||||||
|
Timeout, _ = strconv.Atoi(os.Args[index+1])
|
||||||
case "-h":
|
case "-h":
|
||||||
fallthrough
|
fallthrough
|
||||||
case "--help":
|
case "--help":
|
||||||
|
@ -38,6 +44,9 @@ func CheckArguments() {
|
||||||
FramesToKeep = append(FramesToKeep, strings.ToUpper(strings.TrimSpace(frame)))
|
FramesToKeep = append(FramesToKeep, strings.ToUpper(strings.TrimSpace(frame)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if Timeout <= 0 {
|
||||||
|
Timeout = 30
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// print the help
|
// print the help
|
||||||
|
|
63
main.go
63
main.go
|
@ -5,8 +5,10 @@ import (
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.velvettear.de/velvettear/id3tool/internal/config"
|
"git.velvettear.de/velvettear/id3tool/internal/config"
|
||||||
|
@ -14,6 +16,12 @@ import (
|
||||||
"github.com/bogem/id3v2/v2"
|
"github.com/bogem/id3v2/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var taskLimiter = make(chan struct{}, runtime.NumCPU())
|
||||||
|
var taskCommunication = make(chan task)
|
||||||
|
var waitGroup = sync.WaitGroup{}
|
||||||
|
var counter int
|
||||||
|
var taskState = make(map[int]task)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
loggo.SetLogFormat("[$LOGLEVEL$] > $MESSAGE$ ($EXTRAS$) [$TIMEDIFF$]")
|
loggo.SetLogFormat("[$LOGLEVEL$] > $MESSAGE$ ($EXTRAS$) [$TIMEDIFF$]")
|
||||||
|
|
||||||
|
@ -31,39 +39,66 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
filepath.WalkDir(config.Directory, filterValidFiles)
|
filepath.WalkDir(config.Directory, filterValidFiles)
|
||||||
|
waitGroup.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterValidFiles(path string, dir fs.DirEntry, err error) error {
|
func filterValidFiles(path string, dir fs.DirEntry, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tmp := filepath.Clean(path)
|
|
||||||
loggo.Debug(tmp)
|
|
||||||
extension := filepath.Ext(path)
|
extension := filepath.Ext(path)
|
||||||
if dir.IsDir() || (extension != ".flac" && extension != ".mp3") {
|
if dir.IsDir() || (extension != ".flac" && extension != ".mp3") {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cleanFrames(path)
|
|
||||||
|
counter++
|
||||||
|
waitGroup.Add(1)
|
||||||
|
taskLimiter <- struct{}{}
|
||||||
|
tmp := task{counter, path, false}
|
||||||
|
go func(tmp task) {
|
||||||
|
go func(tmp task) {
|
||||||
|
time.Sleep(time.Duration(config.Timeout) * time.Second)
|
||||||
|
tmp.timeout = true
|
||||||
|
taskCommunication <- tmp
|
||||||
|
<-taskLimiter
|
||||||
|
}(tmp)
|
||||||
|
cleanFrames(tmp.id, tmp.file)
|
||||||
|
tmp.timeout = false
|
||||||
|
taskCommunication <- tmp
|
||||||
|
<-taskLimiter
|
||||||
|
}(tmp)
|
||||||
|
|
||||||
|
result := <-taskCommunication
|
||||||
|
check := taskState[result.id]
|
||||||
|
if check.id == 0 {
|
||||||
|
taskState[result.id] = result
|
||||||
|
if result.timeout {
|
||||||
|
loggo.Warning("(" + strconv.Itoa(result.id) + ") cleaning of file's '" + result.file + "' id3 tags timed out")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
waitGroup.Done()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanFrames(file string) {
|
func cleanFrames(id int, file string) {
|
||||||
if len(file) == 0 {
|
if len(file) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp := time.Now()
|
timestamp := time.Now()
|
||||||
loggo.Info("cleaning file's '" + file + "' id3 tags...")
|
loggo.Info("(" + strconv.Itoa(id) + ") cleaning file's '" + file + "' id3 tags...")
|
||||||
|
|
||||||
tag, err := id3v2.Open(file, id3v2.Options{Parse: true})
|
tag, err := id3v2.Open(file, id3v2.Options{Parse: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loggo.Error("encountered an error opening the file '"+file+"' for reading the id3 tags", err.Error())
|
loggo.Error("("+strconv.Itoa(id)+") encountered an error opening the file '"+file+"' for reading the id3 tags", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer tag.Close()
|
defer tag.Close()
|
||||||
|
|
||||||
deleted := 0
|
deleted := 0
|
||||||
for key, _ := range tag.AllFrames() {
|
for key := range tag.AllFrames() {
|
||||||
filter := frameFilter(key)
|
filter := frameFilter(key)
|
||||||
if !filter {
|
if !filter {
|
||||||
continue
|
continue
|
||||||
|
@ -73,16 +108,16 @@ func cleanFrames(file string) {
|
||||||
|
|
||||||
}
|
}
|
||||||
if deleted > 0 {
|
if deleted > 0 {
|
||||||
loggo.Debug("saving modified id3 tags (" + strconv.Itoa(deleted) + " deleted) to file '" + file + "'...")
|
loggo.Debug("(" + strconv.Itoa(id) + ") saving modified id3 tags (" + strconv.Itoa(deleted) + " deleted) to file '" + file + "'...")
|
||||||
err := tag.Save()
|
err := tag.Save()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loggo.Error("encountered an error saving the modified id3 tags to file '"+file+"'", err.Error())
|
loggo.Error("("+strconv.Itoa(id)+") encountered an error saving the modified id3 tags to file '"+file+"'", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
loggo.DebugTimed("deleted "+strconv.Itoa(deleted)+" tags", timestamp.UnixMilli())
|
loggo.DebugTimed("("+strconv.Itoa(id)+") deleted "+strconv.Itoa(deleted)+" tag(s) from file '"+file+"'", timestamp.UnixMilli())
|
||||||
}
|
}
|
||||||
|
|
||||||
loggo.DebugTimed("finished cleaning file", timestamp.UnixMilli())
|
loggo.DebugTimed("("+strconv.Itoa(id)+") finished cleaning file's '"+file+"' id3 tags", timestamp.UnixMilli())
|
||||||
}
|
}
|
||||||
|
|
||||||
func frameFilter(frame string) bool {
|
func frameFilter(frame string) bool {
|
||||||
|
@ -93,3 +128,9 @@ func frameFilter(frame string) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type task struct {
|
||||||
|
id int
|
||||||
|
file string
|
||||||
|
timeout bool
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue