#!/usr/bin/env bash
# Desc: Download YouTube videos
# Usage: $ ./bkytpldl-generic
# Version: 4.1.1

declare -a args; # array for yt-dlp arguments
declare -a urls urls_rand; # array for YouTube playlist URLs

# Settings
dir_out="~/Videos/";
urls+=("https://www.youtube.com/playlist?list=PLxxx"); # Adjust me. YouTube playlist URL goes here
urls+=("https://www.youtube.com/playlist?list=PLxxx"); # Adjust me. YouTube playlist URL goes here
urls+=("https://www.youtube.com/playlist?list=PLxxx"); # Adjust me. YouTube playlist URL goes here

yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails

# check dependencies
if ! command -v yt-dlp 1>/dev/random 2>&1; then die "FATAL:yt-dlp not found."; fi;

# Donʼt run multiple yt-dlp instances
if pgrep "^yt-dlp$" 1>/dev/random 2>&1; then die "FATAL:yt-dlp already running."; fi;

# Check directories
if [[ ! -d $dir_out ]]; then mkdir -p "$dir_out"; fi;

# == Assemble options ==

# yt-dlp output options
## Restrict file name character set
#args+=("--restrict-filenames");  # Remove non-ASCII characters
args+=("--trim-filenames=120");   # Use in tandem with `%(title).120B`

## Request to write accompanying files
args+=("--write-subs"); # Write subtitles file
args+=("--write-auto-subs"); # Write subtitles file
#args+=("--all-subs"); # Download all available subtitles (causes many requests)
#subLangs="en.*,ja.*,id.*,es.*,zh-Hans.*,zh-Hant.*,sv.*,el.*,hi.*,ru.*,bn.*,fr.*,ko.*,ar.*,nv.*"; # custom language list
subLangs="en,en-orig,en.*"; # custom language list
args+=("--sub-langs" "$subLangs");
args+=("--write-info-json"); # Write accompanying json file
args+=("--no-overwrites"); # Don't overwrite files
args+=("--write-thumbnail"); # Write thumbnail

## Only download metadata
#args+=("--no-download"); # Don't download video file.

## Save meta-data
args+=("--write-comments"); # Get comments
### Limit comments
###   comment_sort values:
###     top                     : use YouTube top comment algorithm
###     new                     : get newest comments (default)
###   max_comments values:
###     max-comments            : max number of parent comments or replies
###     max-parents             : max number of comment threads
###     max-replies             : max number of replies across all threads
###     max-replies-per-thread  : max number of replies per thread
args+=("--extractor-args" "youtube:comment_sort=top;max_comments=10000,100,10000,100");

## Randomize order in which playlist items are downloaded
args+=("--playlist-random");

## Delay between downloads
minSleep="30";
maxSleep="$(( minSleep + (RANDOM + RANDOM + RANDOM) / ( 3 * 400) ))"; # roughly 60 seconds
args+=("--min-sleep-interval" "$minSleep");
args+=("--max-sleep-interval" "$maxSleep");
args+=("--sleep-requests" "2"); # delay on metadata requests
args+=("--sleep-subtitles" "10"); # delay for subtitles

## Remember downloaded videos to avoid redownload attempts
pathDA="$dir_out"/.bkytpldl_history.txt;
args+=("--download-archive" "$pathDA");

## Use firefox 'default-release' profile cookies
##   Example: Linux: from ~/.mozilla/firefox/deadbeef.default-release/
#args+=("--cookies-from-browser");
#args+=("firefox:deadbeef.default-release"); Default Firefox profile name

## Specify output filename format
##   Note: `$(title).120B` shortens title to 120 bytes (useful for
##     titles with UTF-8 characters.
args+=("-o");
args+=("%(playlist)s/%(upload_date)s.%(channel)s.%(channel_id)s.%(title).120B.%(id)s.%(ext)s");

## Limit download resolution to 1080p
args+=("-S" "res:1080");

## Specify playlist URLs to download
### Shuffle playlist download order
mapfile -t urls_rand < <(printf "%s\n" "${urls[@]}" | shuf);
for url in "${urls_rand[@]}"; do
    args+=("$url");
done;

# Change working directory to output dir
pushd "$dir_out" || die "FATAL:Failed to change pwd to:dir_out:$dir_out";

# == Download videos ==

#yell "DEBUG:args:$(declare -p args)";  # debug command
must yt-dlp "${args[@]}";  # execute command
popd || die "FATAL:Failed to return from dir_out:$dir_out";

# Author: Steven Baltakatei Sandoval
# License; GPLv3+