musicutil/commands/copy/copy.go

272 lines
5.8 KiB
Go
Raw Normal View History

2022-02-22 14:02:58 +00:00
package copy
import (
"fmt"
"io"
"os"
"github.com/akamensky/argparse"
"github.com/rs/zerolog/log"
"gitlab.com/ChaotiCryptidz/musicutil/types"
"gitlab.com/ChaotiCryptidz/musicutil/utils"
"gitlab.com/ChaotiCryptidz/musicutil/utils/transcoder"
)
type CopyCommandArgs struct {
Source *string
Dest *string
TranscodePreset *string
SkipExisting *bool
SingleDirectory *bool
}
func dirNotExistValidator(directory string) error {
fileInfo, err := os.Stat(directory)
if err != nil {
return fmt.Errorf("%s does not exist", directory)
}
if !fileInfo.IsDir() {
return fmt.Errorf("%s is not a directory", directory)
}
return nil
}
func fileExists(filepath string) bool {
if _, err := os.Stat(filepath); err == nil {
return true
} else {
return false
}
}
func copyFile(src, dest string) error {
_, err := os.Stat(src)
if err != nil {
return err
}
source, err := os.Open(src)
if err != nil {
return err
}
defer source.Close()
destination, err := os.Create(dest)
if err != nil {
return err
}
defer destination.Close()
_, err = io.Copy(destination, source)
return err
}
func RegisterCopyCommand(parser *argparse.Parser) (*argparse.Command, *CopyCommandArgs) {
cmd := parser.NewCommand("copy", "copies files with or without transcoding")
arguments := &CopyCommandArgs{}
arguments.Source = cmd.String("s", "src", &argparse.Options{
Required: true,
Validate: func(args []string) error {
return dirNotExistValidator(args[0])
},
})
arguments.Dest = cmd.String("d", "dest", &argparse.Options{
Required: true,
Validate: func(args []string) error {
return dirNotExistValidator(args[0])
},
})
arguments.TranscodePreset = cmd.String("p", "transcode-preset", &argparse.Options{
Required: true,
Validate: func(args []string) error {
if args[0] == "list" {
transcoder.PrintTranscodePresets()
os.Exit(0)
} else if args[0] == "copy" {
return nil
}
if _, err := transcoder.GetPresetByName(args[0]); err != nil {
return fmt.Errorf("Preset does not exist")
}
return nil
},
})
arguments.SkipExisting = cmd.Flag("", "skip-existing", &argparse.Options{
Default: false,
})
arguments.SingleDirectory = cmd.Flag("", "single-directory", &argparse.Options{
Default: false,
})
return cmd, arguments
}
type CopyCommand struct {
Args *CopyCommandArgs
Files []*types.File
}
func NewCopyCommand(args *CopyCommandArgs) *CopyCommand {
return &CopyCommand{
Args: args,
Files: make([]*types.File, 0),
}
}
func (c *CopyCommand) scan_for_music() {
log.Info().Msg("Scanning For Music")
files, err := utils.ScanForMusic(*c.Args.Source)
if err != nil {
panic(err)
}
c.Files = files
}
func (c *CopyCommand) check_for_duplicates() {
log.Info().Msg("Creating For Duplicates")
seen := make(map[string]bool)
dupes := make([]string, 0)
for _, file := range c.Files {
filename := file.JoinFilename()
if _, ok := seen[filename]; ok {
dupes = append(dupes, filename)
} else {
seen[filename] = true
}
}
if len(dupes) > 0 {
log.Fatal().Strs("dupes", dupes).Msg("Duplicates Found, please rename/remove.")
}
}
func (c *CopyCommand) create_directories() {
log.Info().Msg("Creating Directories")
directories := make(map[string]bool)
for _, file := range c.Files {
directories[file.PathFromSource] = true
}
for dir := range directories {
if file_info, err := os.Stat(*c.Args.Dest + "/" + dir); err == nil {
if file_info.IsDir() {
continue
}
}
log.Info().Str("dir", dir).Msg("Creating Directory")
err := os.MkdirAll(*c.Args.Dest+"/"+dir, os.ModePerm)
if err != nil {
log.Fatal().Err(err).Msg("Could not create directory")
}
}
}
func (c *CopyCommand) _transcode_file(file *types.File, trans_config *transcoder.TranscodeConfig) {
new_filename := file.Filename + "." + trans_config.FileExtension
dest_filepath := *c.Args.Dest + "/"
if *c.Args.SingleDirectory {
dest_filepath = dest_filepath + new_filename
} else {
dest_filepath = dest_filepath + file.PathFromSource + "/" + new_filename
}
if *c.Args.SkipExisting && fileExists(dest_filepath) {
log.Info().Str("file", new_filename).
Msg("Skipping transcode as file already exists")
return
} else {
log.Info().Str("file", new_filename).Msg("Transcoding File")
}
2022-08-04 15:59:06 +01:00
output, err := transcoder.Transcode(file, trans_config, nil, dest_filepath)
2022-02-22 14:02:58 +00:00
if err != nil {
log.Fatal().Err(err).Str("output", output).Msg("Transcode Failed")
}
}
func (c *CopyCommand) transcode_files() {
log.Info().Msg("Transcoding Files")
// TODO: Implement custom transcode config file
trans_preset, err :=
transcoder.GetPresetByName(*c.Args.TranscodePreset)
if err != nil {
log.Fatal().Err(err).Msg("Could not get transcode preset")
}
for _, file := range c.Files {
c._transcode_file(file, trans_preset.Config)
}
}
func (c *CopyCommand) _copy_file(file *types.File) {
src_filepath := file.JoinPathTo()
dest_filepath := ""
if *c.Args.SingleDirectory {
dest_filepath = *c.Args.Dest + "/" + file.JoinFilename()
} else {
dest_filepath = *c.Args.Dest + "/" + file.JoinPathFromSource()
}
exists := fileExists(dest_filepath)
if exists {
log.Info().Str("file", dest_filepath).
Msg("Skipping as already exists in destination")
} else {
log.Info().
Str("file", file.JoinFilename()).
Msg("Copying File")
err := copyFile(src_filepath, dest_filepath)
if err != nil {
log.Panic().
Err(err).
Str("file", file.JoinFilename()).
Msg("Error Copying File")
}
}
}
func (c *CopyCommand) copy_files() {
log.Info().Msg("Copying Files Into Dest")
for _, file := range c.Files {
c._copy_file(file)
}
}
func (c *CopyCommand) Run() {
log.Info().Msg("Copying Files")
c.scan_for_music()
if !*c.Args.SingleDirectory {
c.create_directories()
} else {
c.check_for_duplicates()
}
if *c.Args.TranscodePreset == "copy" {
c.copy_files()
} else {
c.transcode_files()
}
}