dotfiles/scripts/.local/bin/vidl
Marty Oehme 3e00e84319
scripts: Add queue functionality to vidl
When adding new links to vidl, it will now put them in a queue (file)
from which it then begins downloading links one after the other. Only
one downloading instance of vidl will ever be running, but you can still
add more links by invoking it again while it is.

Added one new command line option `-c` to quickly empty the queue and
start over.

Fixes #8.
2022-03-15 11:54:32 +01:00

192 lines
4.5 KiB
Bash
Executable file

#!/usr/bin/env bash
# download a file if it does not exist in the archive alread
# otherwise just re-link it from the archive
show_help() {
printf """
archive.sh: Hard linking your stuff.
vidl: Video downloader
Simple wrapper for youtube-dl (or yt-dlp or similar).
Usage: vidl [OPTION] <link>
Point it to a link you want downloaded.
Options:
-h Display this help.
-d Directory to check for existence of file and archive to if needed.
If this is passed will not download existing archived files again.
-f Directory to download to.
-c Clear existing download queue.
-t Point to youtube-dl command to use. Can be command or absolute link.
By default will use \`yt-dlp\` which is a more up to date fork of the
youtube-dl program.
"""
}
urls=("$@")
while getopts "t:f:d:hc" opt; do
case "$opt" in
# v) verbose=1
# ;;
f)
DL_FOLDER="$OPTARG"
;;
t)
YT_DL_CMD="$OPTARG"
;;
d)
ARCHIVE_FOLDER="$OPTARG"
;;
c)
ONLY_DO=clear
;;
h | \? | *)
show_help
exit 0
;;
esac
done
shift $((OPTIND - 1))
get_ytdl_fname() {
yt_dl_fname=$("$YT_DL_CMD" --get-filename -o "$YT_DL_TITLE" "$*")
if [ -z "$yt_dl_fname" ]; then
echo Could not get video filename, error with youtube-dl.
exit 1
fi
}
_call_archive() { # 1=new_file, 2=archive_location
command -v archive >/dev/null 2>&1 || {
echo "archive command not found."
exit 1
}
archive -d "$2" -a "$1"
}
vid_ext="\(mp4\|avi\|webm\|mkv\|mpe?g\|3gp\|m4a\)"
_findfile() { # 1=directory, 2=file
find "$1" -type f -name "$2.*" | sed -ne "/$2\.$vid_ext$/Ip"
}
_alreadyexists() { # 1=video_regex
if [ ! -d "$ARCHIVE_FOLDER" ]; then return 0; fi
local found
found=$(_findfile "$ARCHIVE_FOLDER" "$1")
if [ -n "$found" ]; then
return 0
else
return 1
fi
}
_download_cmd() {
"$YT_DL_CMD" \
-o "$DL_FOLDER/$YT_DL_TITLE.%(ext)s" \
"${YT_DL_OPTS[@]}" \
"$*"
}
download() { # 1=url
# # download the video to download folder
if ! _alreadyexists "$yt_dl_fname"; then
_download_cmd "$*"
# yt-dl never knows the exact filename in advance
file=$(_findfile "$DL_FOLDER" "$yt_dl_fname")
if [ -z "$file" ]; then exit 1; fi
_call_archive "$file" "$ARCHIVE_FOLDER"
# only link old file if one exists
else
archive_file=$(_findfile "$ARCHIVE_FOLDER" "$yt_dl_fname")
echo "$archive_file" | while read -r file; do
echo "file $file exists, not downloading duplicate"
_call_archive "$file" "$DL_FOLDER"
done
fi
}
setup() {
DL_FOLDER="${DL_FOLDER:-${XDG_VIDEOS_DIR:-$HOME/videos}}/inbox"
ARCHIVE_FOLDER="${ARCHIVE_FOLDER:-${XDG_VIDEOS_DIR:-$HOME/videos}}/archive"
YT_DL_CMD="${YT_DL_CMD:-yt-dlp}"
yt_default_opts=(-f "best[height\<=1080]" --retries 15 --embed-subs --sub-lang "en,de,es,fr")
declare -a YT_DL_OPTS=${YT_DL_OPTS:-( "${yt_default_opts[@]}" )}
YT_DL_TITLE="${YT_DL_TITLE:-%(channel)s_%(title)s_%(id)s}" # this title needs to be without extension
queue_file="${XDG_CACHE_HOME:-$HOME/.cache}/vidl_queue"
if [ ! -f "$queue_file" ]; then
mkdir -p $(dirname "$queue_file")
touch "$queue_file"
fi
lock_dir="${XDG_CACHE_HOME:-$HOME/.cache}/vidl_lock"
}
is_in_queue() { # 1=url
[ -f "$queue_file" ] || return 1
grep -q "$1" "$queue_file"
}
add_to_queue() { # 1=url
if is_in_queue "$1"; then return; fi
echo "$1" >>"$queue_file"
echo "added $url to queue."
}
remove_from_queue() { # 1=url
sed -i.bak -e "\|$1|d" "$queue_file"
}
clear_queue() {
rm "$queue_file"
}
remove_lock() {
if ! rmdir $lock_dir; then
echo "Failed to remove lock '$lock_dir'. Please remove manually before next run."
exit 1
fi
}
is_only_instance() {
if mkdir $lock_dir 2>/dev/null; then
trap "remove_lock" EXIT
return 0
else
return 1
fi
}
main() {
setup
if [ "$ONLY_DO" = "clear" ]; then
clear_queue
exit
fi
for url in $*; do
add_to_queue "$url"
done
if is_only_instance; then
echo "Download starting..."
while read -r line; do
get_ytdl_fname "$line"
download "$line"
remove_from_queue "$line"
done <"$queue_file"
else
echo "Download already running, only adding to queue."
fi
echo "Download done..."
}
main "${urls[@]}"