2024-09-14 22:39:50 +08:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2024-09-15 21:37:11 +08:00
|
|
|
"github.com/taurusxin/ncmdump-go/ncmcrypt"
|
|
|
|
"github.com/taurusxin/ncmdump-go/utils"
|
2024-09-14 22:39:50 +08:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2024-09-15 08:59:07 +08:00
|
|
|
|
|
|
|
flag "github.com/spf13/pflag"
|
2024-09-14 22:39:50 +08:00
|
|
|
)
|
|
|
|
|
2024-09-27 22:22:56 +08:00
|
|
|
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
|
2024-09-14 22:39:50 +08:00
|
|
|
currentFile, err := ncmcrypt.NewNeteaseCloudMusic(filePath)
|
|
|
|
if err != nil {
|
2024-09-15 21:58:12 +08:00
|
|
|
utils.ErrorPrintfln("Reading '%s' failed: %s", filePath, err.Error())
|
2024-09-14 22:39:50 +08:00
|
|
|
return err
|
|
|
|
}
|
2024-09-27 22:22:56 +08:00
|
|
|
dump, err := currentFile.Dump(outputDir)
|
2024-09-14 22:39:50 +08:00
|
|
|
if err != nil {
|
2024-09-15 21:58:12 +08:00
|
|
|
utils.ErrorPrintfln("Processing '%s' failed: %s", filePath, err.Error())
|
2024-09-14 22:39:50 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
if dump {
|
2024-09-15 21:37:11 +08:00
|
|
|
metadata, err := currentFile.FixMetadata(true)
|
2024-09-14 22:39:50 +08:00
|
|
|
if !metadata {
|
2024-09-15 21:58:12 +08:00
|
|
|
utils.WarningPrintfln("Fix metadata for '%s' failed: %s", filePath, err.Error())
|
2024-09-14 22:39:50 +08:00
|
|
|
return err
|
|
|
|
}
|
2024-09-15 08:59:07 +08:00
|
|
|
utils.DonePrintfln("'%s' -> '%s'", filePath, currentFile.GetDumpFilePath())
|
2024-09-14 22:39:50 +08:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
2024-09-27 22:22:56 +08:00
|
|
|
var sourceDir string
|
|
|
|
var outputDir string
|
2024-09-14 22:39:50 +08:00
|
|
|
showHelp := flag.BoolP("help", "h", false, "Display help message")
|
|
|
|
showVersion := flag.BoolP("version", "v", false, "Display version information")
|
2024-09-27 22:22:56 +08:00
|
|
|
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")
|
2024-09-14 22:39:50 +08:00
|
|
|
flag.Parse()
|
|
|
|
|
|
|
|
if len(os.Args) == 1 {
|
|
|
|
flag.Usage()
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
if *showHelp {
|
|
|
|
flag.Usage()
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
|
|
|
if *showVersion {
|
|
|
|
fmt.Println("ncmdump version 1.5.0")
|
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2024-09-27 22:22:56 +08:00
|
|
|
if !flag.Lookup("dir").Changed && sourceDir == "" && len(flag.Args()) == 0 {
|
|
|
|
flag.Usage()
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
2024-09-14 22:39:50 +08:00
|
|
|
|
2024-09-27 22:22:56 +08:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
|
|
|
outputDirSpecified := flag.Lookup("output").Changed
|
|
|
|
|
|
|
|
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)
|
2024-09-14 22:39:50 +08:00
|
|
|
}
|
2024-09-27 22:22:56 +08:00
|
|
|
}
|
2024-09-14 22:39:50 +08:00
|
|
|
|
2024-09-27 22:22:56 +08:00
|
|
|
if sourceDir != "" {
|
|
|
|
if !utils.IsDir(sourceDir) {
|
|
|
|
utils.ErrorPrintfln("The source directory '%s' is not valid.", sourceDir)
|
2024-09-14 22:39:50 +08:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
2024-09-27 22:22:56 +08:00
|
|
|
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)
|
2024-09-14 22:39:50 +08:00
|
|
|
|
2024-09-27 22:22:56 +08:00
|
|
|
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)
|
2024-09-14 22:39:50 +08:00
|
|
|
if err != nil {
|
2024-09-27 22:22:56 +08:00
|
|
|
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)
|
|
|
|
}
|
2024-09-14 22:39:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2024-09-27 22:22:56 +08:00
|
|
|
// process files from args
|
2024-09-14 22:39:50 +08:00
|
|
|
for _, filePath := range flag.Args() {
|
|
|
|
// skip if the extension is not .ncm
|
|
|
|
if filePath[len(filePath)-4:] != ".ncm" {
|
|
|
|
continue
|
|
|
|
}
|
2024-09-27 22:22:56 +08:00
|
|
|
if outputDirSpecified {
|
|
|
|
_ = processFile(filePath, outputDir)
|
|
|
|
} else {
|
|
|
|
_ = processFile(filePath, sourceDir)
|
2024-09-14 22:39:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|