diff --git a/bin/convert-opml-to-newsboat-urls b/bin/convert-opml-to-newsboat-urls new file mode 100755 index 0000000..7d7a33e --- /dev/null +++ b/bin/convert-opml-to-newsboat-urls @@ -0,0 +1,18 @@ +#!/usr/bin/env python + +# TODO: +# Given a OPML file, convert the OPML into a `urls` file compatible for newsboat. +# It could also accept an OPML through stdin. + +import itertools +from pathlib import Path +import sys +import xml.etree.ElementTree as ET + +filename = sys.argv[1] +opml = ET.parse(filename) +for outline in opml.findall("body/outline"): + categories = [category.strip("/") for category in outline.get("category", "").split(",") if category] + print('{xmlUrl} "~{text}" {category}'.format(xmlUrl = outline.get("xmlUrl"), + text = outline.get("text"), + category = " ".join([ f'"{tag}"' for tag in categories ]) if len(categories) else " ")) diff --git a/bin/edit-file-metadata b/bin/edit-file-metadata index aadd9a9..bc720a2 100755 --- a/bin/edit-file-metadata +++ b/bin/edit-file-metadata @@ -4,6 +4,13 @@ # 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. +# Dependencies: +# * Oil shell v0.8.8 +# * vorbis-tools v1.4.2 +# * exiftool v12.16 +# * file 5.38 +# * coreutils 8.32 + shopt --set strict:all var help_section = "A script for embedding metadata and renaming them files. @@ -36,7 +43,7 @@ while test $# -gt 0 { case $1 { -h|--help) echo $help_section - shift + exit 0 ;; -a|--author) set author = $2 @@ -94,6 +101,7 @@ proc file_parse(path, :out) { 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|") + set file['mime_type'] = $(file --mime-type --brief $path) setref out = file } @@ -115,7 +123,8 @@ if (not skip) { # 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}" + vorbiscomment --write $path --tag "TITLE=${title}" --tag "ARTIST=${author}" --tag "DATE=${pub_date}" || + opustags $path --in-place --delete-all --add "TITLE=${title}" --add "ARTIST=${author}" --add "DATE=${pub_date}" ;; *) exiftool -title="${title}" -author="${author}" -date="${pub_date}" ${path} @@ -134,5 +143,5 @@ if (json_data) { } if (move) { - mv $path "${file_info['dir']}/$(kebab-case $title).${file_info['ext']}" + mv $path "${file_info['dir']}/$(kebab-case $title)${file_info['ext']}" } diff --git a/bin/split-album b/bin/split-album index 0cca7b7..d16e07b 100755 --- a/bin/split-album +++ b/bin/split-album @@ -6,7 +6,7 @@ # * coreutils v8.32 # * file 5-32 # * ffmpeg v4.3.1 -# * ripgrep v12.1.1 with SIMD runtime +# * ripgrep v12.1.1 shopt --set strict:all @@ -16,7 +16,7 @@ split-album [options...] -tf \$TIMESTAMP_FILE -af \$ALBUM_FILE Options: -h, --help Show the help section. - --descriptive-help Show a helpful tutorial-esque description of the program. + --tutorial Show a helpful tutorial-esque description of the program. -af, --audio-file [file] Set the audio file to be split. -tf, --timestamp-file [file] Set the timestamp file to be used for splitting. -t, --title [title] Set the title of the album. @@ -32,24 +32,29 @@ Environment variables: When any of the required metadata is missing (i.e., title, date, author), it will be prompted. " -const show_descriptive_help = "Split an album with a timestamp file. -The timestamp file contains a starting timestamp (any format that ffmpeg accepts in seeking but it is recommended in HH:MM:SS) and the title of the chapter/track. +const show_descriptive_help = "This script splits an album with a timestamp file. +You're always going to see using this script like the following: + +split-album -af \$AUDIO_FILE -tf \$TIMESTAMP_FILE + +The timestamp file contains a starting timestamp (in HH:MM:SS[.MS]) and the title of the chapter/track. For more information, see https://trac.ffmpeg.org/wiki/Seeking. Lines starting with '#' and empty lines will be ignored. +It's for the best and you don't want some future migraines. :) The following is an example of the content of a timestamp file. \`\`\` 00:00:00 Introduction 00:03:54 It's the R-rated scene -00:05:43 Boring exposition at the cafe -00:16:54 Expedition time -00:21:51 Fighting time -00:22:22 Shower scene +00:25:43 Boring exposition at the cafe +00:36:54 Expedition time +00:41:51 Fighting time +00:42:22 Shower scene \`\`\` You can also create a timestamp file in JSON format. -It is the equivalent of '.chapters' from the JSON output (i.e., '--json'). +It is the equivalent of the 'chapters' key from the JSON output (i.e., '--json'). The equivalent JSON of the previous example would be this: \`\`\` @@ -63,19 +68,19 @@ The equivalent JSON of the previous example would be this: \"title\": \"It's the R-rated scene\" }, { - \"timestamp\": \"00:05:43\", + \"timestamp\": \"00:25:43\", \"title\": \"Boring exposition at the cafe\" }, { - \"timestamp\": \"00:16:54\", + \"timestamp\": \"00:36:54\", \"title\": \"Expedition time\" }, { - \"timestamp\": \"00:21:51\", + \"timestamp\": \"00:41:51\", \"title\": \"Fighting time\" }, { - \"timestamp\": \"00:22:22\", + \"timestamp\": \"00:42:22\", \"title\": \"Shower scene\" } ] @@ -85,7 +90,7 @@ There will be a folder created with the safe name of the album (in kebab-case) c The original file will be kept, do what you want with it. " -const EXTENSION = ${EXTENSION:-"ogg"} +const EXTENSION = ${EXTENSION:-"opus"} var audio_file = '' var timestamp_file = '' @@ -103,7 +108,7 @@ while test $len(ARGV) -gt 0 { write -- $show_help exit ;; - --descriptive-help) + --tutorial) write -- $show_descriptive_help exit ;; @@ -170,16 +175,22 @@ test $pub_date || prompt "When is the album published?" :pub_date const output_data = {} set output_data['file'] = $audio_file set output_data['chapters'] = [] +set output_data['album'] = $album +set output_data['author'] = $author +set output_data['date'] = $pub_date +set output_data['extension'] = $EXTENSION -const timestamp_regex = / %start digit{2,} ':' digit{2} ':' digit{2} %end / +const timestamp_regex = / %start digit{2,} ':' digit{2} ':' digit{2} <'.' digit+>? %end / var has_error = false -# Also cleans up the timestamp file with comments and empty lines. -# I just want to improve the timestamp format (a little bit). case $(file --mime-type --brief $timestamp_file) { "application/json") - json read :output_data['chapters'] < $audio_file + json read :chapters < $timestamp_file + set output_data['chapters'] = chapters ;; + + # Also cleans up the timestamp file with comments and empty lines. + # I just want to improve the timestamp format (a little bit). "text/plain") cat $timestamp_file | sed --regexp-extended --expression '/^\s*$/d' --expression '/^#/d' | while read --line { var chapter = {} @@ -200,6 +211,7 @@ case $(file --mime-type --brief $timestamp_file) { if (strict_mode and has_error) { exit 1 } const title_slug = $(kebab-case $album) +set output_data['directory'] = title_slug mkdir -p $title_slug const chapter_len = len(output_data['chapters']) @@ -208,13 +220,14 @@ for index in @(seq $[chapter_len]) { set chapter = output_data['chapters'][Int(index) - 1] var start = chapter['timestamp'] var end = output_data['chapters'][Int(index)]['timestamp'] if Int(index) != chapter_len else null - var filename = $(printf "%s/%.2d-%s.%s" $title_slug $index $(kebab-case ${chapter['title']}) $EXTENSION) + var filename = $(printf "%.2d-%s.%s" $index $(kebab-case ${chapter['title']}) $EXTENSION) + set output_data['chapters'][Int(index) - 1]['file'] = filename - warnf "[%d/%d] %s\\r" ${index} ${chapter_len} ${chapter['title']} + warnf "[%d/%d] %s" ${index} ${chapter_len} ${chapter['title']} if (Int(index) != chapter_len) { - ffmpeg -loglevel quiet -nostdin -i $audio_file -ss $start -to $end $filename + ffmpeg -loglevel quiet -nostdin -i $audio_file -ss $start -to $end "${title_slug}/${filename}" } else { - ffmpeg -loglevel quiet -nostdin -i $audio_file -ss $start $filename + ffmpeg -loglevel quiet -nostdin -i $audio_file -ss $start "${title_slug}/${filename}" } }