1
0
forked from um/cli
cli/cmd/um/main.go

154 lines
3.8 KiB
Go
Raw Permalink Normal View History

2020-12-26 15:22:39 +00:00
package main
import (
"errors"
2021-03-02 10:16:19 +00:00
"github.com/unlock-music/cli/algo/common"
_ "github.com/unlock-music/cli/algo/kgm"
_ "github.com/unlock-music/cli/algo/kwm"
_ "github.com/unlock-music/cli/algo/ncm"
_ "github.com/unlock-music/cli/algo/qmc"
_ "github.com/unlock-music/cli/algo/tm"
_ "github.com/unlock-music/cli/algo/xm"
"github.com/unlock-music/cli/internal/logging"
2020-12-26 15:22:39 +00:00
"github.com/urfave/cli/v2"
"go.uber.org/zap"
"os"
"path/filepath"
"strings"
)
2021-05-16 09:21:20 +00:00
var AppVersion = "0.0.4"
2021-05-16 04:30:48 +00:00
2020-12-26 15:22:39 +00:00
func main() {
app := cli.App{
Name: "Unlock Music CLI",
HelpName: "um",
Usage: "Unlock your encrypted music file https://github.com/unlock-music/cli",
2021-05-16 04:30:48 +00:00
Version: AppVersion,
2020-12-26 15:22:39 +00:00
Flags: []cli.Flag{
2021-05-16 08:59:49 +00:00
&cli.StringFlag{Name: "input", Aliases: []string{"i"}, Usage: "path to input file or dir", Required: false},
&cli.StringFlag{Name: "output", Aliases: []string{"o"}, Usage: "path to output dir", Required: false},
2020-12-26 15:22:39 +00:00
},
2021-05-16 08:59:49 +00:00
2020-12-26 15:22:39 +00:00
Action: appMain,
2021-05-16 09:21:20 +00:00
Copyright: "Copyright (c) 2020 - 2021 Unlock Music https://github.com/unlock-music/cli/blob/master/LICENSE",
2020-12-26 15:22:39 +00:00
HideHelpCommand: true,
2021-05-16 09:21:20 +00:00
UsageText: "um [-o /path/to/output/dir] [-i] /path/to/input",
2020-12-26 15:22:39 +00:00
}
err := app.Run(os.Args)
if err != nil {
2021-05-16 08:59:49 +00:00
logging.Log().Fatal("run app failed", zap.Error(err))
2020-12-26 15:22:39 +00:00
}
}
func appMain(c *cli.Context) error {
input := c.String("input")
2021-05-16 08:59:49 +00:00
if input == "" && c.Args().Present() {
input = c.Args().Get(c.Args().Len() - 1)
}
2020-12-26 15:22:39 +00:00
output := c.String("output")
2021-05-16 08:59:49 +00:00
if output == "" {
var err error
output, err = os.Getwd()
if err != nil {
return err
}
}
2020-12-26 15:22:39 +00:00
inputStat, err := os.Stat(input)
if err != nil {
return err
}
outputStat, err := os.Stat(output)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
err = os.MkdirAll(output, 0755)
}
if err != nil {
return err
}
} else if !outputStat.IsDir() {
return errors.New("output should be a writable directory")
}
if inputStat.IsDir() {
return dealDirectory(input, output)
} else {
ext := strings.TrimLeft(filepath.Ext(inputStat.Name()), ".")
allDec := common.GetDecoder(ext)
if len(allDec) == 0 {
logging.Log().Fatal("skipping while no suitable decoder")
}
return tryDecFile(input, output, allDec)
}
}
func dealDirectory(inputDir string, outputDir string) error {
items, err := os.ReadDir(inputDir)
if err != nil {
return err
}
for _, item := range items {
if item.IsDir() {
continue
}
ext := strings.TrimLeft(filepath.Ext(item.Name()), ".")
allDec := common.GetDecoder(ext)
if len(allDec) == 0 {
logging.Log().Info("skipping while no suitable decoder", zap.String("file", item.Name()))
continue
}
err := tryDecFile(filepath.Join(inputDir, item.Name()), outputDir, allDec)
if err != nil {
logging.Log().Error("conversion failed", zap.String("source", item.Name()))
}
}
return nil
}
func tryDecFile(inputFile string, outputDir string, allDec []common.NewDecoderFunc) error {
file, err := os.ReadFile(inputFile)
if err != nil {
return err
}
var dec common.Decoder
for _, decFunc := range allDec {
dec = decFunc(file)
if err := dec.Validate(); err == nil {
break
}
logging.Log().Warn("try decode failed", zap.Error(err))
dec = nil
}
if dec == nil {
return errors.New("no any decoder can resolve the file")
}
if err := dec.Decode(); err != nil {
return errors.New("failed while decoding: " + err.Error())
}
2021-05-16 04:18:19 +00:00
outData := dec.GetAudioData()
2020-12-26 15:22:39 +00:00
outExt := dec.GetAudioExt()
if outExt == "" {
2021-05-16 04:18:19 +00:00
if ext, ok := common.SniffAll(outData); ok {
outExt = ext
} else {
outExt = ".mp3"
}
2020-12-26 15:22:39 +00:00
}
filenameOnly := strings.TrimSuffix(filepath.Base(inputFile), filepath.Ext(inputFile))
2021-05-16 04:18:19 +00:00
outPath := filepath.Join(outputDir, filenameOnly+outExt)
err = os.WriteFile(outPath, outData, 0644)
2020-12-26 15:22:39 +00:00
if err != nil {
return err
}
logging.Log().Info("successfully converted",
zap.String("source", inputFile), zap.String("destination", outPath))
return nil
}