Mint Serena 64 bit using the Mate desktop environment. Most of the following scripts will run on this machine, although some have only been tested with the Gnome desktop. Extra software requirements can be met by the Ubuntu and safe PPA repositories. Scripts may be re-written or added to from time to time, the date serves as the version number. Syntax highlighting on these pages is provided by GVim's "Convert to HTML" option.


# Filename:
# Version: 290716
# Author: robz
# WARNING! this works on my system it may break yours, read, check, tweak ##
# A torrent box script for a headless Raspberry Pi model B, it auto downloads
# media files for show episodes followed, then renames and transfers to NAS.
# You may need to "apt-get install gvfs-bin" for the mount and move daemons,
# also tvnamer, xmllint, transmission-daemon and transmission-remote.
# Enable the "Watch" and "Incomplete" directories in transmission-daemon's
# settings.json, this can also be done using the web interface.
# http://<your-pi's-net-address-192.168.0.etc>:9091/transmission/web/#all
# No login required no gui, just power up pi whenever or leave on all the time.
# Downloads will occur at random times 01:00-05:00 ie. during off peak hours.
# List show names in the "followed-shows.txt" file one entry per line.
# Manually added links are copy/pasted to the "add-magnet.txt", one per line.
# Make script executable and run it first in /home/<user> i.e. ./

# Directory might not be standard in your pi, create it before running script.
cd "$HOME/Downloads" || exit                        # Go to working directory.

smb="smb://wdmycloud/media/Cloud TV"                # My samba path to NAS.
trk="$HOME/.config/transmission-daemon"             # The daemon's config file.
mag="scripts/add-magnet.txt"                        # Any extra magnet links.
don="scripts/done-shows.txt"                        # Done downloads list.
rss="scripts/rss.txt"                               # Feed file rss listing.
rlg="log/$(date +%a-%-d%b)-runlog.txt"              # This session, statistics.
rec="log/rec.txt"                                   # Recently downloaded list.
mod="log/motd.txt"                                  # Message for ssh login.
cdn="0"                                             # Count/countdown variable.
export trk                                          # Give access for subshell.

set -x                                              # Generate debug output.
exec > "log/$(date +%a-%-d%b)-debug.txt" 2>&1       # Route debug to debug log.
date > "$rlg"                                       # Start a new session log.
> "$mod"                                            # Blank motd.txt.
# Script started via cron schedule, expand that enviroment so gvfs will work.
[ -z "$DBUS_SESSION_BUS_ADDRESS" ] && eval \
"$(dbus-launch --sh-syntax --exit-with-session)"    # Make gvfs & cron buddies.
# If script fails kill daemon to avoid possible bandwidth overruns.
trap "killall -q transmission-daemon; sync; exit" SIGINT SIGTERM SIGHUP EXIT
# Timer will wait for "Incomplete" to empty or for a file to appear dependant
# on whether the $swh variable is set or not, or it'll just time out.
run_timer ()
while [ "$cdn" -gt "1" ]; do
    [[ ! "$swh" && "$(ls Incomplete)" ]] && break
    [[ "$swh" && ! "$(ls Incomplete)" ]] && break
    (( cdn-=5 )); sleep 5
done 2> /dev/null
# Strip unwanted characters from filenames, magnet links and xml input.
strip_title ()
sed -e 's/\(S[0-9]*E[0-9]*\).*\<.*/\1/;s/.*>//;s/[.+]/ /g;s/.*dn=//;s/New.*: //'
# This part of the script executes once to create the directory/file structure
# in ##> Downloads <##, it also installs the random time run-script crontab.
if [ ! -e scripts/"$(basename $0)" ]; then
    set -o noclobber
    mkdir -p {Complete,Incomplete,Watch,temp,scripts,log,ted}
    &> /dev/null > scripts/followed-shows.txt
    &> /dev/null > "$mag"
    &> /dev/null > "$don"
    &> /dev/null > "$rss"
    t0='# Randomly between 01:00 and 05:00 run it.'
    t1='00 00 * * * /bin/sleep $(((RANDOM\%10800)+3600)); '
    t2="/home/pi/Downloads/scripts/$(basename $0); sudo reboot"
    (crontab -u "$USER" -l; echo -e "\n$t0\n$t1$t2\n" ) | crontab -u "$USER" -
    cp "$0" scripts; mv "$0" "$0".backup
    echo "Now add some shows to the followed-shows.txt"
    echo "### File exists, no action taken ###"
# Housekeeping, clean up old downloads and logs.    # NB. subshell used here.
echo "$(tail -30 "$rec")" > "$rec"
find log -mtime +14 -type f -delete
find Complete -mindepth 1 -mtime +4 -delete
find "$trk" -mtime +4 -name *.torrent -type f -delete -execdir bash -c\
    'del="{}"; del="${del##*/}"; rm -f "$trk/resume/${del%.*}.resume"' \;
# Check the "Watch" directory for extras or one off shows.
[ "$(ls Watch)" ] && \
for lnk in Watch/*; do
    basename "$lnk" | strip_title >> "$don"

transmission-daemon -g "$trk"
echo "$(date +%T) - Transmission-daemon started." >> "$rlg"
# Check "add.magnet" file for extras or one off shows.
[ -s "$mag" ] && \
sleep 5 && \
while read lnk; do
    transmission-remote --add "$lnk"
    strip_title <<< "$lnk" >> "$don"
done < "$mag"
> "$mag"
# Download rss feeds, pretty print to seperate lines allowing parsing.
# Two feeds? I've found that the feed listings are slightly different between
# the old and new sites, so yes, two feeds for now.
> "$rss"                                            # Empty old rss feed file.
wget -q -O - "" | xmllint --format - >> "$rss"
wget -q -O - "" | xmllint --format - >> "$rss"
# Check followed-shows list against new rss feed file, standard def. not HD. If
# you want HD versions you'll have to modify the "sed" statments, alternatively
# you could use the "add.magnets" file or the "Watch" directory for a one off.
## NB. GNU sed is being used in this script, BSD/POSIX versions won't do.##
## TODO Code chokes here if the show name format is not "Show Name S01E01" ##
if [ -s "$rss" ]; then
    while read shw; do
        if [[ "${shw:0:1}" != "#" && "$shw" != "" ]]; then
            epi=$(sed -n "/720\|1080/d;/description.*$shw/Ip" "$rss" | sed q)
            [ -z "$epi" ] && continue
            if ! grep -iq "$(strip_title <<< "$epi")" "$don"; then
                strip_title <<< "$epi" >> "$don"
                lnk="$(sed 's/.*href=\"//;s/\".*//' <<< "$epi")"
                transmission-remote --add "$lnk"
    done < scripts/followed-shows.txt
    grep "raw.*title" "$rss" | sed "/720\|1080/d" | strip_title | sort -u \
    > log/rss-today.txt
    echo ' ## ERROR no rss feed.' | tee -a "$rlg" "$mod"

sort -u "$don" -o "$don"                            # Tidy up done-shows list.
# Wait for first link to start downloading, skipped if incomplete files exist.
[ -z "${lnk+x}" ] || \
(echo "$(date +%T) - Wait for links or resume incompletes." >> "$rlg";
cdn="420"; swh=""; run_timer)                       # Set to wait for link load.
# If torrents are downloading start session timer.
if [ "$(ls Incomplete)" ]; then
    cdn="3600"; swh="1"                             # Timer max & function.
    transmission-remote --torrent all --start
    echo "$(date +%T) - Proceeding with download $((cdn/60))m max." >> "$rlg"
    echo "$(date +%T) - Seed for another 10 minutes." >> "$rlg"
    sleep 600
    transmission-remote --torrent all --stop
    transmission-remote --session-stats | sed '3,6!d' >> "$rlg"
    echo "$(date +%T) - End of $(date +%A)'s downloads."
    [ "$(ls Incomplete)" ] && echo 'Incomplete download(s):' && ls Incomplete
    ) >> "$rlg"
    echo " PVR session...: $(awk '/Downloaded/{print $1,$2$3}' "$rlg")" > "$mod"
    echo "Rename & tranfer to network storage." >> "$rlg"

transmission-remote --exit
# Leaving original torrents to seed for a few runs, just the main video files
# are copied (ignoring previews and promos) to "temp" then renamed. Now create 
# directories if needed on network drive and transfer the media files there.
new="$(find Complete -size +50M -daystart -mtime -1)"
if [ "$new" ]; then                                 # Do we have episodes.
    gvfs-mount "$smb"; sleep 60                     # Mount network drive.
    while read -r vid; do
        cp "$vid" temp/
        tvnamer -b temp/
        ls temp/ | sed 's/^/  /;s/....$//' | tee -a "$rlg" "$mod" |\
        sed "s/^/$(date +%a-%d)/;s/$/  \:$(du -h temp/ | cut -f1)/"\
        >> "$rec"
        dir="$(basename "$(ls temp/)")"
        dir="${dir% - [*}"/"Season $(echo "${dir##*[}" |\
        cut -dx -f1 | sed 's/^0//')"                # Determine directory tree.
        gvfs-mkdir -p "$smb"/"$dir"                 # Create directory on NAS.
        gvfs-move temp/* "$smb"/"$dir"
        (( cdn+=1 ))                                # Increment LED indicator.
    done <<< "$new"
# This works in conjunction with the "" script if it exists.
new="$(find ted -type f)"
if [ "$new" ]; then
    echo " TED session...: Downloaded "$(du -hs ted | cut -f1)"B" |\
    tee -a "$rlg" "$mod"
    while read -r vid; do
        [ -e "$vid" ] && mv "$vid"\
        ted/"$(grep "${vid##*/}" scripts/ted-donelist.txt | cut -d"|" -f1-2 |\
        tr -cd [:alnum:][:blank:]).mp4"             # Make a sane filename.
        (( cdn+=1 ))
    done <<< "$new"
    ls ted | sed 's/^/  /;s/.mp4//' | cut -c1-77 | tee -a "$rlg" "$mod"
    if ! gvfs-mount -l | grep $(dirname "$smb"); then
        gvfs-mount "$smb"; sleep 60                 # Mount if not mounted.
    gvfs-move ted/* "$smb"/TED-talks
# Finish up.
echo "$cdn" > scripts/flash.txt                     # Flash LED $cdn times.
if [ "$cdn" -lt "1" ]; then
    echo " This session..: $(date +%A) nothing new." | tee -a "$rlg" "$mod"
    echo "$(date +%T) - File(s) transfer completed." >> "$rlg"
    echo " Script runtime: $(date -d@"$SECONDS" -u +%H:%M:%S)" |\
    tee -a "$rlg" "$mod"
    gvfs-mount -u "$smb"

# exit - see trap.

No comments: