#!/bin/bash # # ytcache - helper script for downloading/caching youtube videos # Copyright (C) 2013 Claire Xenia Wolf # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # # ------------------------------------------------------------------- # # The following bookmarklet can be used to create a list of YouTube URLs from the Pocket Queue (getpocket.com): : << "EOT" javascript:(function(){ var n = 0, text = "", list = document.getElementsByClassName('original_url'); for (var i = 0; i < list.length; i++) { var u = decodeURIComponent(list[i].getAttribute('href')), k = u.search("url=http"); if (k) u = u.substr(k+4); u = u.replace(/^https:/, "http:"); if (u.search("youtube.com/watch") > 0) { text = u.replace(/&.*/, "") + "\n" + text; n++; } } document.write("
" + text + n); })()
EOT

# see "man youtube-dl" for a list of available formats
# add them to this variable in order of preference
formats="18 35 22"

urls=()
url_count=0
echo "Enter (paste) YouTube URLs (empty line for end):"
while read url; [ -n "$url" ]; do
	urls=("${urls[@]}" "$url")
	(( url_count++ ))
done

echo "CREATE TABLE IF NOT EXISTS ytcache (id TEXT UNIQUE NOT NULL, state INTEGER NOT NULL, url TEXT NOT NULL, file TEXT NOT NULL);" | sqlite3 ytcache.db
echo "UPDATE ytcache SET state = state + 10 WHERE state < 10;" | sqlite3 ytcache.db

cache_get()
{
	local id="$( echo "$1" | sed 's,.*v=,,; s,&.*,,;' )"
	echo "SELECT $2 FROM ytcache WHERE id = '$id';" | sqlite3 ytcache.db
}

cache_set()
{
	local id="$( echo "$1" | sed 's,.*v=,,; s,&.*,,;' )"
	echo "UPDATE ytcache SET $2 = '${3//"'"/''}' WHERE id = '$id';" | sqlite3 ytcache.db
}

cache_info()
{
	local id="$( echo "$1" | sed 's,.*v=,,; s,&.*,,;' )"
	echo "UPDATE ytcache SET state = state - 10 WHERE state >= 10 AND id = '$id';" | sqlite3 ytcache.db

	local filename="$( cache_get $1 file )"
	[ -z "$filename" ] || return 0

	filename="$( youtube-dl -t --get-filename "$1" )"
	[ -n "$filename" ] || return 1

	index=$(( $(echo "select max(file) from ytcache;" | sqlite3 ytcache.db | sed 's,_.*,,') + 1 ))
	if [ $index -lt 1000 ]; then index=1000; fi

	filename="${filename%.flv}"
	filename="${filename%.mp4}"
	filename="${index}_${filename}"

	for fmt in $formats; do
		dl_url="$( youtube-dl -g -f $fmt "$url" )"
		if [ -n "$dl_url" ]; then
			[ $fmt -eq 18 ] && filename="${filename}.mp4"
			[ $fmt -eq 22 ] && filename="${filename}.mp4"
			[ $fmt -eq 37 ] && filename="${filename}.mp4"
			[ $fmt -eq 34 ] && filename="${filename}.flv"
			[ $fmt -eq 35 ] && filename="${filename}.flv"
			echo "INSERT OR IGNORE INTO ytcache (id, state, url, file) VALUES ('$id', 0, '', '');" | sqlite3 ytcache.db
			cache_set $1 file "$filename"
			cache_set $1 url "$dl_url"
			return 0
		fi
	done

	return 1
}

echo "Got $url_count URLs. Downloading now.."
for url in "${urls[@]}"; do
	echo; echo
	echo "---------------------------------------------"
	echo "$url"
	if cache_info "$url"; then
		filename="$( cache_get "$url" "file" )"
		echo "$filename"
		if [ "$( cache_get "$url" state )" -eq 0 ]; then
			dl_url="$( cache_get "$url" "url" )"
			if wget -c -O "$filename" "$dl_url"; then
				cache_set "$url" state 1
			fi
		fi
	fi
done

echo; echo
echo "---------------------------------------------"
echo "Removing local files that vanished from list:"
while read filename; do
	rm -vf "$filename"
done < <( echo "SELECT file FROM ytcache WHERE state >= 10;" | sqlite3 ytcache.db )
echo "DELETE FROM ytcache WHERE state >= 10;" | sqlite3 ytcache.db

echo; echo
echo "---------------------------------------------"
echo "Finding files from list that have been removed locally:"
linecount=0
while read filename; do
	if [ ! -f "$filename" ]; then
		echo "Removed by user: $filename"
		if [ $((++linecount)) -eq 5 ]; then echo; linecount=0; fi
	fi
done < <( echo "SELECT file FROM ytcache WHERE state = 1 ORDER BY file DESC;" | sqlite3 ytcache.db )

echo; echo
echo "READY."