Jellyfin + yt-dlp + long flight = Magic
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

168 lines
4.3 KiB

#!/usr/bin/env bash
# Exit 1 if any command errors
set -e
# $1 here is the first argument to this script
BATCH_FILE="$1"
DOWNLOAD_DIR="/export/jellyfin"
YTDLP_LOG_FILE="/export/ytdlp.log"
# 'cat << 'EOF"' is used here to allow for newlines in the command
YTDLP_COMMAND=$(cat << EOF
/srv/.local/bin/yt-dlp
-P $DOWNLOAD_DIR
--sub-format srt
--write-subs
--write-thumbnail
EOF
)
printUsage() {
cat << EOF
Usage: $(basename "$0") <batch.txt>
EOF
}
# log() takes a log level and log line and uses the LOG_LEVEL env var to
# control how/when it is logged
# To enable debug logging set LOG_LEVEL=debug as an env var
log() {
# '$1' is the first argument passed to this function
passed_level="$1"
# '$2' is the first argument passed to this function
log_line="$2"
# This is passed from the env as 'LOG_LEVEL='
env_level="$LOG_LEVEL"
# Convert env_level to int
case $env_level in
"DEBUG")
min_level_int=0;;
"INFO")
min_level_int=1;;
"ERROR")
min_level_int=2;;
*)
min_level_int=1;;
esac
# Convert passed_level to int
case $passed_level in
"DEBUG")
log_level_int=0;;
"INFO")
log_level_int=1;;
"ERROR")
log_level_int=1;;
*)
log_level_int=99;;
esac
if [ $log_level_int -ge $min_level_int ]; then
echo "[$passed_level] $log_line"
fi
}
validate_args() {
# If no argument specified, exit 1
if [ -z "$BATCH_FILE" ]; then
printUsage
exit 1
fi
# Exit 1 if passed batch file is not a file (or doesn't exist)
if [ ! -f "$BATCH_FILE" ]; then
echo "Error: Batch file '$BATCH_FILE' not found"
printUsage
exit 1
fi
# Exit 0 if passed file contains no urls
if ! grep -q "^.*http.*" "$BATCH_FILE"; then
echo "File '$BATCH_FILE' contains no URLs"
exit 1
fi
if [[ ! -O "$BATCH_FILE" ]]; then
echo "File '$BATCH_FILE' is not owned by user ID '${UID}'"
echo "Run 'chown ${UID} $BATCH_FILE' before mounting"
exit 1
fi
if [[ ! -O "$DOWNLOAD_DIR" ]]; then
echo "Directory '$DOWNLOAD_DIR' is not owned by user ID '${UID}'"
echo "Run 'chown -R ${UID} $DOWNLOAD_DIR' before mounting"
exit 1
fi
}
process_batchfile() {
# Using `read` parse each line of the file as a '$line' while setting IFS=''
# to prevent lines containing things such as `\n` from being parsed as a
# literal newline
while IFS='' read -r line; do
# Ignore any commented lines RegEx explanation: https://regexr.com/7hs52
regex_match_leading_comment='^\s*[#].*$'
if [[ "$line" =~ $regex_match_leading_comment ]]; then
# RegEx explanation: https://regexr.com/7i073
line_without_comment=$(echo "$line" | sed 's/^\s*[#]\s*\(.*\)$/\1/')
log "INFO" "Skipping: $line_without_comment"
continue
fi
log "INFO" "Downloading: $line"
# Temporarily allow commands to fail without exiting
set +e
# Run the command with $line as an argument
# Quotes are used here as a measure to protect against "\n" and the like
# '>' is used to overwrite the log file each call so only the last commands
# output is shown
$YTDLP_COMMAND "$line" > $YTDLP_LOG_FILE 2>&1
# Save the exit code of the last command
exit_code="$?"
# Re-enable exiting 1 on command failure
set -e
if [ "$exit_code" -ne "0" ]; then
log "ERROR" "Command failed: '$YTDLP_COMMAND'"
cat $YTDLP_LOG_FILE
continue
fi
log "INFO" "Finished downloading '$line'"
# By here we can assume the file was downloaded successfully, thus we can
# comment out the line in the file
log "DEBUG" "Commenting out '$line' in '$BATCH_FILE'"
# Prepend a '#" on the current line in the file
# '|' is used because URLs contain '/' which is the usual sed delimiter
# 'cp' to a buffer file is used because sed cannot modify the mounted
# file's inode when using Docker ('-c' is not available in Ubuntu's sed)
new_file="/export/$(basename "$BATCH_FILE").new"
cp "$BATCH_FILE" "$new_file"
sed -i "s|\($line\)|# \1|" "$new_file"
cp "$new_file" "$BATCH_FILE"
log "DEBUG" "Finished commenting '$line' from '$BATCH_FILE'"
done <<< "$(cat "$BATCH_FILE")"
}
main() {
validate_args
log "INFO" "Processing $BATCH_FILE"
process_batchfile
log "INFO" "Finished processing $BATCH_FILE"
}
# Run main()
main