diff --git a/main.go b/main.go index 0218ecd..da80ca3 100644 --- a/main.go +++ b/main.go @@ -10,13 +10,19 @@ import ( flag "github.com/spf13/pflag" ) -func processFile(filePath string) error { +func processFile(filePath string, outputDir string) error { + // skip if the extension is not .ncm + if filePath[len(filePath)-4:] != ".ncm" { + return nil + } + + // process the file currentFile, err := ncmcrypt.NewNeteaseCloudMusic(filePath) if err != nil { utils.ErrorPrintfln("Reading '%s' failed: %s", filePath, err.Error()) return err } - dump, err := currentFile.Dump(filepath.Dir(filePath)) + dump, err := currentFile.Dump(outputDir) if err != nil { utils.ErrorPrintfln("Processing '%s' failed: %s", filePath, err.Error()) return err @@ -33,10 +39,13 @@ func processFile(filePath string) error { } func main() { - var folderPath string + var sourceDir string + var outputDir string showHelp := flag.BoolP("help", "h", false, "Display help message") showVersion := flag.BoolP("version", "v", false, "Display version information") - flag.StringVarP(&folderPath, "dir", "d", "", "Process all files in the directory") + processRecursive := flag.BoolP("recursive", "r", false, "Process all files in the directory recursively") + flag.StringVarP(&outputDir, "output", "o", "", "Output directory for the dump files") + flag.StringVarP(&sourceDir, "dir", "d", "", "Process all files in the directory") flag.Parse() if len(os.Args) == 1 { @@ -54,51 +63,82 @@ func main() { os.Exit(0) } - if folderPath != "" { - // check if the folder exists - info, err := os.Stat(folderPath) - if err != nil { - utils.ErrorPrintfln("Unable to access directory: '%s'", folderPath) - os.Exit(1) - } + if !flag.Lookup("dir").Changed && sourceDir == "" && len(flag.Args()) == 0 { + flag.Usage() + os.Exit(1) + } - if !info.IsDir() { - utils.ErrorPrintfln("Not a directory: %s", folderPath) - os.Exit(1) - } + if flag.Lookup("recursive").Changed && !flag.Lookup("dir").Changed { + utils.ErrorPrintfln("The -r option can only be used with the -d option") + os.Exit(1) + } - // dump files in the folder - files, err := os.ReadDir(folderPath) - if err != nil { - utils.ErrorPrintfln("Unable to read directory: '%s'", folderPath) - os.Exit(1) - } + outputDirSpecified := flag.Lookup("output").Changed - for _, file := range files { - if file.IsDir() { - continue + if outputDirSpecified { + if utils.PathExists(outputDir) { + if !utils.IsDir(outputDir) { + utils.ErrorPrintfln("Output directory '%s' is not valid.", outputDir) + os.Exit(1) } + } else { + _ = os.MkdirAll(outputDir, os.ModePerm) + } + } - filePath := filepath.Join(folderPath, file.Name()) - // skip if the extension is not .ncm - if filePath[len(filePath)-4:] != ".ncm" { - continue - } - err = processFile(filePath) + if sourceDir != "" { + if !utils.IsDir(sourceDir) { + utils.ErrorPrintfln("The source directory '%s' is not valid.", sourceDir) + os.Exit(1) + } + + if *processRecursive { + _ = filepath.WalkDir(sourceDir, func(p string, d os.DirEntry, err_ error) error { + if !outputDirSpecified { + outputDir = sourceDir + } + relativePath := utils.GetRelativePath(sourceDir, p) + destinationPath := filepath.Join(outputDir, relativePath) + + if utils.IsRegularFile(p) { + parentDir := filepath.Dir(destinationPath) + _ = os.MkdirAll(parentDir, os.ModePerm) + _ = processFile(p, parentDir) + } + return nil + }) + } else { + // dump files in the folder + files, err := os.ReadDir(sourceDir) if err != nil { - continue + utils.ErrorPrintfln("Unable to read directory: '%s'", sourceDir) + os.Exit(1) + } + + for _, file := range files { + if file.IsDir() { + continue + } + + filePath := filepath.Join(sourceDir, file.Name()) + if outputDirSpecified { + _ = processFile(filePath, outputDir) + } else { + _ = processFile(filePath, sourceDir) + } } } } else { - // dump file from args + // process files from args for _, filePath := range flag.Args() { // skip if the extension is not .ncm if filePath[len(filePath)-4:] != ".ncm" { continue } - err := processFile(filePath) - if err != nil { - continue + if outputDirSpecified { + _ = processFile(filePath, outputDir) + } else { + _ = processFile(filePath, sourceDir) } } } diff --git a/utils/file.go b/utils/file.go index 91000bb..ca4cb72 100644 --- a/utils/file.go +++ b/utils/file.go @@ -1,6 +1,7 @@ package utils import ( + "os" "path/filepath" "strings" ) @@ -9,3 +10,39 @@ func ReplaceExtension(filepathStr, newExt string) string { ext := filepath.Ext(filepathStr) return strings.TrimSuffix(filepathStr, ext) + newExt } + +func PathExists(path string) bool { + _, err := os.Stat(path) + if err == nil { + return true + } + if os.IsNotExist(err) { + return false + } + return false +} + +func IsDir(path string) bool { + s, err := os.Stat(path) + if err != nil { + + return false + } + return s.IsDir() +} + +func GetRelativePath(from, to string) string { + rel, err := filepath.Rel(from, to) + if err != nil { + return "" + } + return rel +} + +func IsRegularFile(path string) bool { + s, err := os.Stat(path) + if err != nil { + return false + } + return s.Mode().IsRegular() +}