download-yt-feeds/download-yt-feeds

100 lines
3.0 KiB
Bash
Executable File

#!/bin/zsh
# Download YouTube-feeds as if they are podcasts.
# Error codes:
# 1 = Could not read file or directory.
# 2 = Configuration option not set.
# 3 = youtube-dl error.
# License: AGPL-3.0-only, see LICENSE.
function die()
{
[[ -n "${2}" ]] && echo "Error: ${2}" >&2
exit ${1}
}
# Return path of configuration directory.
function get_config_path()
{
local path
if [[ -n "${XDG_CONFIG_HOME}" ]]; then
path="${XDG_CONFIG_HOME}/download-yt-feeds"
else
path="${HOME}/.config/download-yt-feeds"
fi
[[ -d "${path}" ]] || mkdir -p "${path}"
[[ -r "${path}" ]] || die 1 "${path} is not readable."
echo "${path}"
}
# Return URLs of YouTube-feeds in feedlist.
# All lines that don't start with "http" are ignored.
function read_feedlist()
{
local feed_path="$(get_config_path)/feedlist"
[[ -r "${feed_path}" ]] || die 1 "${feed_path} is not readable."
local -a entries
while read line; do
if [[ "${line}" =~ "^http" ]]; then
local -a entry=("${(@s/ /)line}")
entries+=(${entry[1]})
fi
done <"${feed_path}"
print -r -- ${(qq)entries}
}
function main()
{
local config_path="$(get_config_path)/config"
[[ -r "${config_path}" ]] || die 1 "${config_path} is not readable."
source "${config_path}"
[[ -z "${download_dir}" ]] && die 2 "download_dir not specified."
[[ -z "${keep_for_days}" ]] && die 2 "keep_for_days not specified."
[[ -z "${ytdl_format}" ]] && local ytdl_format="best"
if [[ -z "${ytdl_binary}" ]]; then
if command -v yt-dlp > /dev/null; then
local ytdl_binary="yt-dlp"
else
local ytdl_binary="youtube-dl"
fi
fi
find "${download_dir}" -type f -mtime +"${keep_for_days}" -delete
find "${download_dir}" -maxdepth 1 -type d -exec \
rmdir --ignore-fail-on-non-empty {} \;
mkdir -p "${download_dir}"
local files_before="$(find "${download_dir}" -type f)"
local -a feedlist=("${(@Q)${(z)$(read_feedlist)}}")
for feed in ${feedlist}; do
${ytdl_binary} \
--download-archive "$(get_config_path)/downloaded" \
--dateafter "now-${keep_for_days}days" \
--output "${download_dir}/%(uploader)s/%(title)s.%(ext)s" \
--format "${ytdl_format}" \
${=ytdl_extra_args} \
"${feed}"
# [[ ${?} -eq 0 ]] || die 3 "${ytdl_binary} returned an error."
done
local files_after="$(find "${download_dir}" -type f)"
local time="$(date +'%F_%R')"
while read file; do
[[ "${file}" =~ "\.vtt$" ]] && continue # Skip subtitle files.
# https://stackoverflow.com/a/8811800/5965450
if [[ "${files_before#*${file}}" == "${files_before}" ]]; then
if [[ "${file}" =~ "#" ]]; then
local file_new="${file:gs/#/_}"
mv "${file}" "${file_new}"
file="${file_new}"
fi
echo "${file/${download_dir}\//}" \
>> "${download_dir}/New_${time}.m3u"
fi
done <<<"${files_after}"
}
main