From 85603bd00a0d34955d1bdbe5efbba7d5aa98eaab Mon Sep 17 00:00:00 2001
From: Gabriel Arazas <foo.dogsquared@gmail.com>
Date: Fri, 9 Apr 2021 19:21:26 +0800
Subject: [PATCH] Port the update metadata script to Oil

---
 bin/edit-file-metadata | 167 ++++++++++++++++++++++++++++++-----------
 1 file changed, 124 insertions(+), 43 deletions(-)

diff --git a/bin/edit-file-metadata b/bin/edit-file-metadata
index 5f10bfc..aadd9a9 100755
--- a/bin/edit-file-metadata
+++ b/bin/edit-file-metadata
@@ -1,57 +1,138 @@
-#!/usr/bin/env perl
+#!/usr/bin/env oil
 
-# A quick script on moving a document with the embedded metadata.
-# It uses exiftool for embedding so be sure to have it installed.
-# Only needs an argument of a filename to be converted.
+# A quick script on moving a file with embedded data.
+# It can only detect certain files and write the metadata with a certain program.
+# For the argument, it needs the path of the files to be moved.
 
-# TODO: Create --title (-t) option that automatically skips the title prompt.
-# TODO: Create --author (-a) option that automatically skips the author prompt.
-# TODO: Create --date (-d) option that automatically skips the date prompt.
+shopt --set strict:all
 
-use File::Basename;
-use File::Copy;
-use Modern::Perl;
+var help_section = "A script for embedding metadata and renaming them files.
 
-# Create a simple prompt returning with the given answer.
-sub prompt {
-  my ($msg) = @_;
-  say $msg;
-  print ">> ";
-  return <STDIN>;
+edit-file-metadata [options...] FILE
+
+Options:
+    -h, --help              Show the help section.
+    -a, --author [AUTHOR]   Set the author.
+    -d, --date [DATE]       Set the date.
+    -t, --title [TITLE]     Set the title.
+    --skip                  Skip the prompt for missing metadata
+                            and only change the needed metadata.
+                            This only works if you've set any
+                            of the metadata in the command line.
+    --json                  Return a JSON object on stdout.
+    --move                  Move the filename from the kebab-case
+                            of the title.
+"
+
+var path = ''
+var author = ''
+var title = ''
+var pub_date = ''
+var skip = false
+var json_data = false
+var move = false
+
+while test $# -gt 0 {
+  case $1 {
+    -h|--help)
+      echo $help_section
+      shift
+      ;;
+    -a|--author)
+      set author = $2
+      shift 2
+      ;;
+    -t|--title)
+      set title = $2
+      shift 2
+      ;;
+    -d|--date)
+      set pub_date = $2
+      shift 2
+      ;;
+    --skip)
+      set skip = true
+      shift
+      ;;
+    --json)
+      set json_data = true
+      shift
+      ;;
+    --move)
+      set move = true
+      shift
+      ;;
+    *)
+      set path = $1
+      shift
+      ;;
+  }
 }
 
-# This implementation of kebab-case conversion is opinionated.
-# It converts into lowercase and removes all non-alphanumeric characters.
-sub kebab_case {
-  my ($string) = @_;
+proc kebab-case(word) {
+    # Convert into lower case.
+    set word = $(echo $word | tr '[:upper:]' '[:lower:]')
 
-  # Convert into lowercase.
-  $string = lc($string);
+    # What happens to this line:
+    # * Convert all whitespace and dashes into a single dash.
+    # * Remove all invalid characters (all that are not alphanumeric characters and dashes).
+    # * Remove leading and trailing dashes.
+    set word = $(echo $word | sed --regexp-extended --expression 's/\s+|-+/-/g' --expression 's/[^.a-z0-9-]//g' --expression 's/^-+|-+\$//g')
 
-  # Substitute all spaces and extra dashes as one dash.
-  $string =~ s/\s+|-+/-/g;
-
-  # Remove all invalid characters.
-  $string =~ s/[^a-z0-9-]//g;
-
-  # Remove all leading and trailing dashes.
-  $string =~ s/^-+|-+$//g;
-
-  return $string;
+    echo $word
 }
 
-my $file = $ARGV[0] ? $ARGV[0] : exit 1;
+proc prompt(string, :out, prefix = ">> ") {
+    >&2 printf "%s\\n%s" $string $prefix
+    read --line
+    setref out = $_line
+}
 
-# Prompt for all the required information.
-my $title = prompt "Title of the document?";
-my $author = prompt "Author?";
-my $publication_date = prompt "Publication date?";
+proc file_parse(path, :out) {
+    var extension_regex = / '.' ![ '.' ]+ %end /
+    var file = {}
+    set file['dir'] = $(dirname $path)
+    set file['name'] = $(basename $path | sed --regexp-extended "s|(.+)${extension_regex}|\\1|")
+    set file['ext'] = $(basename $path | sed --regexp-extended "s|.+(${extension_regex})|\\1|")
 
-# Overwrite the file metadata.
-system "exiftool -title=\"${title}\" -author=\"${author}\" -date=\"${publication_date}\" \"$file\"";
+    setref out = file
+}
 
-# Once the file metadata has been written, it is time to move the file into its kebab-case equivalent.
-my ($filename, $dirs, $suffix) = fileparse($file, '\.[^.]+$');
-my $file_slug = $dirs . kebab_case($title) . $suffix;
-move($file, $file_slug);
+test -f $path || {
+    >&2 echo "${path} is not a regular file"
+    exit 1
+}
 
+# Prompt for the missing metadata (if it's configured to not skip, anyways).
+if (not skip) {
+    test $title || prompt "What is the title?" :title
+    test $author || prompt "Who are the authors?" :author
+    test $pub_date || prompt "When this file published?" :pub_date
+}
+
+# Writing up the metadata time!
+# Each file type has a different way of embedding metadata so it needs different tools.
+# We'll use exiftool as a catch-all since it supports the most out of... 15 file types I considered.
+case $(file --mime-type --brief $path) {
+  "audio/ogg")
+    vorbiscomment --write $path --tag "TITLE=${title}" --tag "ARTIST=${author}" --tag "DATE=${pub_date}"
+    ;;
+  *)
+    exiftool -title="${title}" -author="${author}" -date="${pub_date}" ${path}
+    ;;
+}
+
+file_parse $path :file_info
+
+if (json_data) {
+    var metadata = {}
+    set metadata['file'] = file_info
+    set metadata['title'] = $title
+    set metadata['author'] = $author
+    set metadata['date'] = $pub_date
+    json write :metadata
+}
+
+if (move) {
+    mv $path "${file_info['dir']}/$(kebab-case $title).${file_info['ext']}"
+}