#!/bin/bash

#Name: dl2.sh
Description="SaveTV-Download-Script v"
#Dependencies: curl, sleep, ps, tail, mv, let, tr, (screen)
#Author: Thomas Jungbauer
#Author-e-Mail: thomas@jungbauer-online.net
#License: WTFPL
#License-Text-Url: http://sam.zoy.org/wtfpl/COPYING
Version="2.10"
#Relase-Date: 02.06.2011
#Last-change-Date: 18.06.2011


########
#Config
########
TEMPDIR="./tmp-savetv"
LOOPSLEEP="2"
LOCKFILE="/tmp/dl-savetv.pid"
DLLINKSFILE="./download.txt"
MAXDONWLOADS="2"
KUNDENNUMMER="_123456789"
SPEED="250k"
DOWNLOADDIR="."
CURLWAITTIME="100"


########
#Funktionen: Hier kommen die Funktionen, welche später benutzt werden.
########

function exit_all {
#Diese Funktion wird bei STRG+C ausgeführt.
#Hier wird aufgeräumt und die CURL-Prozesse beendet.

echo "Heruntergeladen aufnahmen:"
cat $TEMPDIR/Logs/Last-Download.txt 2>/dev/null ||echo "-"

echo "Download-Script wird vorzeitig beendet!"

PID=`cat $LOCKFILE`
for CPID in `ps  h --ppid $PID  -o pid`; do
	#CPID von 1. Child Prozess (dl2.sh)
	for CURLPID in `ps  h --ppid $CPID  -o pid`; do
		kill -9 $CURLPID 2>/dev/null
	done
	kill -9 $CPID 2>/dev/null
done
exit 0
}
trap exit_all SIGINT


function create_temp_dirs {
#Diese Funktion erstellt die Temp-Ordner
TEMPSUBFOLDERS="01-New-Jobs 02-Queue 03-Queue2 04-Download 05-Finish 11-Retry-Later 12-Duplicate Logs DownloadTemp"
for SUBDIR in $TEMPSUBFOLDERS ; do
	if [ ! -d $TEMPDIR/$SUBDIR ]; then 
		mkdir --parents $TEMPDIR/$SUBDIR
	fi
done
}

function jobs_back_to_queue {
#Diese Funktion verschieb die unvollendeten Jobs zurück in die Warteschlange
if [ `ls -1 $TEMPDIR/04-Download/*.job 2>/dev/null |wc -l` != 0 ]; then
	mv $TEMPDIR/04-Download/*.job $TEMPDIR/03-Queue2/
fi
}


function add_jobs_to_queue {
#Diese Funktion teilt die $DLLINKFILE in einzeile Jobs auf.
count=0
if [ -f $DLLINKSFILE ]; then
	for LINK in `cat $DLLINKSFILE`; do 
		echo $LINK >$TEMPDIR/01-New-Jobs/`date +%Y%m%d-%H%M%S`-$count.job
		let count=count+1
		rm $DLLINKSFILE
		touch $DLLINKSFILE
	done
else
	touch $DLLINKSFILE
fi
echo $count "Jobs wurden der Download-Warteschlange hinzugefügt."
}


function filter_duplicate {
#Hier werden die Duplicate nach 12-Duplicate aussortiert.
#Die andern Job kommen nach 03-Queue2
if [ `ls -1r $TEMPDIR/02-Queue/*.job 2>/dev/null |wc -l` != 0 ]; then
        FILE=`ls -1r $TEMPDIR/02-Queue/*.job | tail -n 1`
	URL=`cat $FILE |grep http:`
	DUPLICATE=`cat $TEMPDIR/03-Queue2/*.job $TEMPDIR/04-Download/*.job $TEMPDIR/05-Finish/*.job 2>/dev/null | grep $URL | wc -l`

	if [ $DUPLICATE != 0 ]; then 
		#Duplicat: Datei wird nach 12-Duplicate verschoben
		echo "Bereits heruntergeladen:" `tail -n 1 $FILE` >>$TEMPDIR/Logs/Last-Download.txt
		mv $FILE $TEMPDIR/12-Duplicate
	else
		#Kein Duplicat: Datei wir nach 03-Queue2 verschoben
		mv $FILE $TEMPDIR/03-Queue2
	fi
fi
}


function add_filname_to_job {
#Diese Funktion fügt den Dateinamen dem Jobfile hinzu
#Manchmal bekommt man keinen Namen, dann wird der
#Job später nochmal probiert

URL=`cat $1 |grep http`

curl -s -g --head $URL >$TEMPDIR/headertmp.txt 2>/dev/null
FNAME=`cat $TEMPDIR/headertmp.txt | grep Content-Disposition | awk -F '[=\r]' '{print $2}'`
FSIZE=`cat $TEMPDIR/headertmp.txt | grep Content-Length | cut -c 17- `
FDATE=`cat $TEMPDIR/headertmp.txt | grep Last-Modified | cut -c 16- `
FETAG=`cat $TEMPDIR/headertmp.txt | grep Etag | cut -c 7- | xargs `

rm $TEMPDIR/headertmp.txt

#Umlaute un komische Zeichen werden durch _ Ersetzt
FNAME=`echo $FNAME | tr '\200'-'\377' _ `
#Kundennummer wird entfernt
FNAME=`echo ${FNAME//$KUNDENNUMMER/""}`

FNAMELENGTH=`echo $FNAME | wc -m`

#echo $FNAME

if [ $FNAMELENGTH -ge 3 ]; then
	#Die while-Schleifen sorgen dafür, das keine vorhandene Datei
	#überschrieben wird.
	#In seltenen Fällen kommt es vor, das 2 unterschiedliche 
	#URLs den gleichen Dateinamen ergeben.
	while [ -e $TEMPDIR/DownloadTemp/$FNAME ]; do
		FNAME=`echo $FNAME-1.avi`
	done
	
	while [ -e $DOWNLOADDIR/$FNAME ]; do
		FNAME=`echo $FNAME-2.avi`
	done

	#TODO: Hier müssen noch die Dateinamen von den Jobs in der Warteschlange
        ###### überprüft werden. (02-Queue und 03-Queue2)

	#Zeile 1: URL
	#Zeile 2: Filename
	#Zeile 3: Dateigröße
	#Zeile 4: Dateidatum
	#Zeile 5: Etag
	echo $FNAME >>$1
	echo $FSIZE >>$1
	echo $FDATE >>$1
	echo $FETAG >>$1
	mv $1 $TEMPDIR/02-Queue/
else
	mv $1 $TEMPDIR/11-Retry-Later/
fi
}



function get_filenames {
#Hohlt die Dateinamen vom Server.
#Pro Aufruf wir nur 1 Datei bearbeitet!!!

#Benötigt die folgenden Funktionen
#add_filname_to_job

if [ `ls -1r $TEMPDIR/01-New-Jobs/*.job 2>/dev/null |wc -l` != 0 ]; then
	FILE=`ls -1r $TEMPDIR/01-New-Jobs/*.job | tail -n 1`
	#Dateiname wird dem Job hinzugefügt
	add_filname_to_job $FILE
else
	#Es werden die Retrys zurück in den Ausgangsordner kopiert
	mv $TEMPDIR/11-Retry-Later/*.job $TEMPDIR/01-New-Jobs/ 2>/dev/null
fi
}


function start_download_file {
#Hier wird 1 Download-Job gestartet (Als Background-Job)

FILE=`ls -1r $TEMPDIR/03-Queue2/*.job | tail -n 1`
URL=`cat $FILE|grep http`
#FILENAME=`cat $FILE| tail -n 1`
FILENAME=`sed -n '2p' $FILE`
FDATE=`sed -n '4p' $FILE`

mv $FILE $TEMPDIR/04-Download
FILE=`echo ${FILE//"03-Queue2"/"04-Download"}`

while $stat  ; do
	curl -C -  --speed-limit 10k --limit-rate $SPEED $URL --output $TEMPDIR/DownloadTemp/$FILENAME 2>$TEMPDIR/Logs/$FILENAME.txt && stat=false || sleep $CURLWAITTIME
done 

touch -d "$FDATE" $TEMPDIR/DownloadTemp/$FILENAME 2>/dev/null
mv $TEMPDIR/DownloadTemp/$FILENAME $DOWNLOADDIR
mv $FILE $TEMPDIR/05-Finish

echo $FILENAME >>$TEMPDIR/Logs/Downloaded-Files.txt
echo $FILENAME >>$TEMPDIR/Logs/Last-Download.txt
}


function start_download {
#Downloads werden bei Bedarf gestartet

AKTIVEDL=`ls -1 $TEMPDIR/04-Download/*.job 2>/dev/null |wc -l `
QUEUEDL=`ls -1 $TEMPDIR/03-Queue2/*.job 2>/dev/null |wc -l `

clear
cat $TEMPDIR/Logs/Status.txt 2>/dev/null
#echo $Description$Version
#echo "Aktive Downloads: "$AKTIVEDL
#echo "Wartende Downloads: "$QUEUEDL
#echo

#echo "Laufende Downloads:"
#for DLFILES in `ls -1 $TEMPDIR/DownloadTemp/* 2>/dev/null `;do 
#	TMP=`du -h $DLFILES 2>/dev/null`
#	TMP=`echo ${TMP//$TEMPDIR/""}`
#	TMP=`echo ${TMP//DownloadTemp/""}`
#	TMP=`echo $TMP | tr -d '/' `
#	echo $TMP
#done

#echo
#echo "Fertige Downloads:"
#cat $TEMPDIR/Logs/Last-Download.txt 2>/dev/null ||echo "-"

if [ $QUEUEDL != 0 ]; then
	if [ $AKTIVEDL -lt $MAXDONWLOADS ]; then
		#Es wird 1 Download gestartet
		start_download_file &
		sleep 1
	fi
fi
}


function gen_status {

STATUSFILE="$TEMPDIR/Logs/Status.txt"
AKTIVEDL=`ls -1 $TEMPDIR/04-Download/*.job 2>/dev/null |wc -l `
QUEUEDL=`ls -1 $TEMPDIR/03-Queue2/*.job 2>/dev/null |wc -l `

#clear
echo $Description$Version >$STATUSFILE
echo -n "Aktive Downloads: "$AKTIVEDL >>$STATUSFILE
echo "   Wartende Downloads: "$QUEUEDL >>$STATUSFILE
echo >>$STATUSFILE


echo "Laufende Downloads:" >>$STATUSFILE
for DLFILES in `ls -1 $TEMPDIR/DownloadTemp/* 2>/dev/null `;do
        TMP=`du -h $DLFILES 2>/dev/null`
        TMP=`echo ${TMP//$TEMPDIR/""}`
        TMP=`echo ${TMP//DownloadTemp/""}`
        TMP=`echo $TMP | tr -d '/' `
        echo $TMP >>$STATUSFILE
done

echo >>$STATUSFILE
echo "Fertige Downloads:" >>$STATUSFILE
cat $TEMPDIR/Logs/Last-Download.txt 2>/dev/null ||echo "-" >>$STATUSFILE



}



#######
#Ab hier werden die Funktionen von oben aufgerufen
#######

#######
# Init: Hier wird die Umgebung geprüft
#######

#Mehrfach-Start überprüfen
#Lockfile setzen

#FIRSTSTART: Variable in der gespeichert wird, ob das Script schonmal gestartet wurde
#0 = script läuft noch nicht, 1 script läuft bereits
FIRSTSTART=0
if [ -f $LOCKFILE ]; then
	#LOCKFILE ist vorhanden
	PID=`cat $LOCKFILE`
	SCRIPTNAME=`echo $0`
	TMP=`ps h -p $PID |grep $SCRIPTNAME |grep $PID |wc -l `

	if [ $TMP != 0 ]; then
		#Prozess läuft
		FIRSTSTART=1
	else
		#Prozess läuft nicht
		FIRSTSTART=0
		echo $$ >$LOCKFILE
	fi
else
	#LOCKFILE nicht vorhanden, Prozess läuft nicht
	echo $$ >$LOCKFILE
	FIRSTSTART=0
fi

######
#INIT1: Nur bei erneutem Starten der Anwendung
######
if [ $FIRSTSTART = 1 ];then

#Job 1: Weiter Jobs hinzufügen
#Links splitten und in Warteschlange schieben.
#Später müssten Duplicate entfernt werden.
	add_jobs_to_queue

#Job 2: Allgemein Informationen ausgeben
	echo $0 läuf bereits. Die Links von $DLLINKSFILE wurden der Warteschlange hinzugefügt.
#ENDE!!! (keine Weitere Ausführung)
	exit 0
fi

######
#INIT2: Nur bei erststart der Anwendung
######
if [ $FIRSTSTART = 0 ];then

#Job 1: Temp-Verzeichnisse bei bedarf anlegen
	create_temp_dirs

#Job 2: Jobs von "In-Arbeit" zurück in die Warteschlange schieben
	jobs_back_to_queue

#Job 3: Weiter Jobs hinzufügen
#Links splitten und in Warteschlange schmeißen
#(Später müssten Duplicate entfernt werden)
#Input-Daten bereinigen / Löschen
	add_jobs_to_queue

	#Löschen der Last-Download-Log.txt
	rm $TEMPDIR/Logs/Last-Download.txt 2>/dev/null

#Danach wird der Loop ausgeführt
fi

########
# Main-Loop (läuft solange, wie Download arbeiten)
# Hier sind nur die Sachen, welche immer wieder ausgfeführt werden müssen
# Wird nur ausgeführt, wenn das Script noch nicht läuft
########

if [ $FIRSTSTART = 0 ];then
RUNLOOP=true
while $RUNLOOP ; do 

	#JOB 1: Dateiname ermitteln (Warteschlange erstellen)
	get_filenames

	#Job 2: Dublikat-Check
	filter_duplicate
	
	#JOB 3: Download-Jobs starten (bei bedarf)
	#Generieren von Status-Anzeige wird hier auch noch erledigt
	gen_status
	start_download

	#Job 5: Ermitteln, ob alle Aufgaben erledigt sind, und das Script beendet werden kann	
	ls -1 $TEMPDIR/0[1-4]*/*.job >/dev/null 2>/dev/null  ||RUNLOOP=false
	if [ $RUNLOOP = false ]; then
		echo "Warten auf Jobs"
		wait
		echo "Heruntergeladen aufnahmen:"
		cat $TEMPDIR/Logs/Last-Download.txt 2>/dev/null
	fi
	sleep $LOOPSLEEP
done
fi

exit 0
