about summary refs log tree commit diff
path: root/tools/music-organizer
diff options
context:
space:
mode:
authorFranck Cuny <franck@fcuny.net>2024-03-06 06:29:24 -0800
committerFranck Cuny <franck@fcuny.net>2024-03-06 06:29:24 -0800
commit1e4a5aa09c1c8f43722c9c260f011398799a8e8f (patch)
treecd73e0fb8ba53bd21cee6ccf2dcc85639bbbb93f /tools/music-organizer
parentset correct git email in the profiles (diff)
downloadworld-1e4a5aa09c1c8f43722c9c260f011398799a8e8f.tar.gz
rename `tools` to `packages` to follow convention
The convention is to use `pkgs` or `packages` for overlays and
definition of custom packages. Since I'm already using `pkg` for go,
I prefer to use `packages` for my scripts.
Diffstat (limited to 'tools/music-organizer')
-rw-r--r--tools/music-organizer/README.org21
-rw-r--r--tools/music-organizer/default.nix15
-rw-r--r--tools/music-organizer/go.mod5
-rw-r--r--tools/music-organizer/go.sum4
-rw-r--r--tools/music-organizer/main.go271
5 files changed, 0 insertions, 316 deletions
diff --git a/tools/music-organizer/README.org b/tools/music-organizer/README.org
deleted file mode 100644
index a42a196..0000000
--- a/tools/music-organizer/README.org
+++ /dev/null
@@ -1,21 +0,0 @@
-#+TITLE: music organizer
-
-the tool takes a couple of arguments:
-- ~-dest~: where will the music be stored
-- a list of directories to scan
-
-all files that have tags that can be read will be processed and moved to the specified destination.
-
-files are organized like this: ={artist}/{album}/{track number} {track title}.{track format}=
-
-the tool ensures that files are not already present in the destination.  if there's already a file with the same name, it checks that the md5 sum of the files are identical.  if they are not, it logs a message.
-
-* build
-#+BEGIN_SRC sh
-go build
-#+END_SRC
-
-* install
-#+BEGIN_SRC sh
-go install
-#+END_SRC
diff --git a/tools/music-organizer/default.nix b/tools/music-organizer/default.nix
deleted file mode 100644
index 1242e34..0000000
--- a/tools/music-organizer/default.nix
+++ /dev/null
@@ -1,15 +0,0 @@
-{ pkgs, ... }:
-
-pkgs.buildGoModule rec {
-  name = "music-organizer";
-  src = ./.;
-  vendorSha256 = "sha256-pQpattmS9VmO3ZIQUFn66az8GSmB4IvYhTTCFn6SUmo=";
-  nativeBuildInputs = with pkgs; [ go ];
-
-  meta = with pkgs.lib; {
-    description = "CLI to organize my music in folders.";
-    license = licenses.mit;
-    platforms = platforms.linux;
-    maintainers = [ ];
-  };
-}
diff --git a/tools/music-organizer/go.mod b/tools/music-organizer/go.mod
deleted file mode 100644
index ba9a1b8..0000000
--- a/tools/music-organizer/go.mod
+++ /dev/null
@@ -1,5 +0,0 @@
-module golang.fcuny.org/music-organizer
-
-go 1.17
-
-require github.com/dhowden/tag v0.0.0-20220617232555-e66a190c9f5b
diff --git a/tools/music-organizer/go.sum b/tools/music-organizer/go.sum
deleted file mode 100644
index 3383f0e..0000000
--- a/tools/music-organizer/go.sum
+++ /dev/null
@@ -1,4 +0,0 @@
-github.com/dhowden/itl v0.0.0-20170329215456-9fbe21093131/go.mod h1:eVWQJVQ67aMvYhpkDwaH2Goy2vo6v8JCMfGXfQ9sPtw=
-github.com/dhowden/plist v0.0.0-20141002110153-5db6e0d9931a/go.mod h1:sLjdR6uwx3L6/Py8F+QgAfeiuY87xuYGwCDqRFrvCzw=
-github.com/dhowden/tag v0.0.0-20220617232555-e66a190c9f5b h1:TG8R5ZZgd1Sj7iFWnkk5dNy94RG8fP8M4l24UYR8/HY=
-github.com/dhowden/tag v0.0.0-20220617232555-e66a190c9f5b/go.mod h1:Z3Lomva4pyMWYezjMAU5QWRh0p1VvO4199OHlFnyKkM=
diff --git a/tools/music-organizer/main.go b/tools/music-organizer/main.go
deleted file mode 100644
index 253afef..0000000
--- a/tools/music-organizer/main.go
+++ /dev/null
@@ -1,271 +0,0 @@
-package main
-
-import (
-	"archive/zip"
-	"crypto/md5"
-	"encoding/hex"
-	"flag"
-	"fmt"
-	"io"
-	"io/ioutil"
-	"log"
-	"os"
-	"path/filepath"
-	"strings"
-
-	"github.com/dhowden/tag"
-)
-
-const (
-	// the max lenght for a track can only be 255 characters minus 3 for the
-	// track number (followed by a space), and 4 for the format. The limit of
-	// 255 is coming from HFS+.
-	TrackTitleMaxLenght = 255 - 3 - 4
-)
-
-var musicDest = flag.String("dest", fmt.Sprintf("%s/media/music", os.Getenv("HOME")), "where to store the music")
-
-// replace slashes with dashes
-func stripSlash(s string) string {
-	return strings.ReplaceAll(s, "/", "-")
-}
-
-// return the name of the artist, album and the title of the track
-// the title of the track has the following format:
-//
-//	{track #} {track title}.{track format}
-func generatePath(m tag.Metadata) (string, string, string) {
-	var artist, album, title string
-	var track int
-
-	// if there's no artist, let's fallback to "Unknown Artists"
-	if len(m.Artist()) == 0 {
-		artist = "Unknown Artists"
-	} else {
-		artist = stripSlash(m.Artist())
-	}
-
-	// if there's no album name, let's fallback to "Unknown Album"
-	if len(m.Album()) == 0 {
-		album = "Unknown Album"
-	} else {
-		album = stripSlash(m.Album())
-	}
-
-	track, _ = m.Track()
-
-	// ok, there must be a better way
-	format := strings.ToLower(string(m.FileType()))
-
-	title = fmt.Sprintf("%02d %s.%s", track, stripSlash(m.Title()), format)
-	if len(title) > TrackTitleMaxLenght {
-		r := []rune(title)
-		title = string(r[0:255])
-	}
-
-	return artist, album, title
-}
-
-// create all the required directories.  if we fail to create one, we die
-func makeParents(path string) error {
-	if err := os.MkdirAll(path, 0o777); err != nil {
-		return fmt.Errorf("failed to create %s: %v", path, err)
-	}
-	return nil
-}
-
-func md5sum(path string) (string, error) {
-	var sum string
-	f, err := os.Open(path)
-	if err != nil {
-		return sum, err
-	}
-
-	defer f.Close()
-
-	h := md5.New()
-	if _, err := io.Copy(h, f); err != nil {
-		return sum, err
-	}
-	sum = hex.EncodeToString(h.Sum(nil)[:16])
-	return sum, nil
-}
-
-func makeCopy(src, dst string) error {
-	f, err := os.Open(src)
-	if err != nil {
-		return err
-	}
-	defer f.Close()
-
-	t, err := os.OpenFile(dst, os.O_RDWR|os.O_CREATE, 0o666)
-	if err != nil {
-		return err
-	}
-	defer t.Close()
-
-	_, err = io.Copy(t, f)
-	if err != nil {
-		return err
-	}
-	log.Printf("copied %s → %s\n", src, dst)
-	return nil
-}
-
-// ensure the file is named correctly and is moved to the correct destination
-// before we can do that, we need to:
-//  1. check if the track already exists, if it does, does it have the same md5 ?
-//     if they are similar, we skip them.  if they are not, we log and don't do
-//     anything
-//  2. we can move the file to the destination
-//  3. we can delete the original file
-func renameFile(originalPath string, artist, album, title string) error {
-	directories := filepath.Join(*musicDest, artist, album)
-	destination := filepath.Join(directories, title)
-
-	// check if the file is present
-	_, err := os.Stat(destination)
-	if err == nil {
-		var originalSum, destinationSum string
-		if originalSum, err = md5sum(originalPath); err != nil {
-			return err
-		}
-		if destinationSum, err = md5sum(destination); err != nil {
-			return err
-		}
-
-		if destinationSum != originalSum {
-			log.Printf("md5 sum are different: %s(%s) %s(%s)", originalPath, originalSum, destination, destinationSum)
-		}
-		return nil
-	}
-
-	if err := makeParents(directories); err != nil {
-		return err
-	}
-
-	if err := makeCopy(originalPath, destination); err != nil {
-		return err
-	}
-
-	// TODO delete original file
-	// os.Remove(originalPath)
-	return nil
-}
-
-// we try to open any files and read the metadata.
-// if the file has metadata we can read, we will try to move the file to the
-// correct destination
-func processFile(path string) error {
-	f, err := os.Open(path)
-	if err != nil {
-		return err
-	}
-
-	defer f.Close()
-	m, err := tag.ReadFrom(f)
-	if err != nil {
-		// this is fine, this might not be a music file
-		log.Printf("SKIP failed to read tags from %s: %v", path, err)
-		return nil
-	}
-
-	var artist, album, title string
-	artist, album, title = generatePath(m)
-	if err := renameFile(path, artist, album, title); err != nil {
-		return fmt.Errorf("failed to move %s: %v", path, err)
-	}
-	return nil
-}
-
-func processPath(path string, f os.FileInfo, err error) error {
-	if stat, err := os.Stat(path); err == nil && !stat.IsDir() {
-		if err := processFile(path); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// unzip takes two paths, a source and destination. The source is the
-// name of the archive and we will extract the content into the
-// destination directory. The destination directory has to already
-// exists, we are not going to create it here or delete it at the end.
-func unzip(src, dst string) error {
-	r, err := zip.OpenReader(src)
-	if err != nil {
-		return err
-	}
-
-	defer r.Close()
-
-	for _, f := range r.File {
-		fpath := filepath.Join(dst, f.Name)
-		outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
-		if err != nil {
-			return err
-		}
-
-		rc, err := f.Open()
-		if err != nil {
-			return err
-		}
-
-		_, err = io.Copy(outFile, rc)
-		if err != nil {
-			log.Printf("failed to copy %s: %s", outFile.Name(), err)
-		}
-
-		outFile.Close()
-		rc.Close()
-	}
-	return nil
-}
-
-func main() {
-	flag.Parse()
-
-	if *musicDest == "" {
-		log.Fatal("-dest is required")
-	}
-
-	paths := make([]string, flag.NArg())
-
-	// For our temp directory, we use what ever the value of
-	// XDG_RUNTIME_DIR is. If the value is unset, we will default to
-	// the system default temp directory.
-	tmpDir := os.Getenv("XDG_RUNTIME_DIR")
-
-	for i, d := range flag.Args() {
-		if filepath.Ext(d) == ".zip" {
-			// If we have an extension and it's '.zip', we consider the
-			// path to be an archive. In this case we want to create a new
-			// temporary directory and extract the content of the archive
-			// in that path. The temporary directory is removed once we're
-			// done.
-			out, err := ioutil.TempDir(tmpDir, "music-organizer")
-			if err != nil {
-				log.Printf("failed to create a temp directory to extract %s: %v", d, err)
-				continue
-			}
-			defer os.RemoveAll(out)
-
-			if err := unzip(d, out); err != nil {
-				log.Printf("failed to extract %s: %v", d, err)
-				continue
-			}
-			paths[i] = out
-		} else {
-			paths[i] = d
-		}
-	}
-
-	for _, d := range paths {
-		// XXX deal with filenames that are too long
-		// scan the directory and try to find any file that we want to move
-		err := filepath.Walk(d, processPath)
-		if err != nil {
-			log.Fatalf("error while processing files: %v", err)
-		}
-	}
-}