TeeFury on your desktop

The script below grabs the latest design from TeeFury and creates a file you can easily place on your desktop, a bit like this example.

Comments are invited on ways to improve this script (as it doesn’t always work due to the RegEx) and follow general best practice.
For the script to work you’ll need to install the ImageMagick libraries, as well as grab this image (or just make yer own!)

Update 1: fixed some issues with grep/RegEx.
Update 2: added ‘testMode’ and scaling.

#!/bin/bash
#
# Copyright 2013 Jason Irwin
#
# License:
#  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 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# Description:
#  This grabs the latest TeeFury page and brings down the design, applies formatting and generates a file that can be displayed.
#  I use KDE's Picture Frame widget, but it could equally be conky or something else.
#  This script will create a "tmp" folder under the location where it is installed.
#
#  It was written as an exercise to learn some bash scripting and is intentionally over commented for this reason.
#  This is also why some commands that could be piped aren't.
#
# Pre-requisites:
#  The ImageMagick libraries must be installed
#  You need an icon for the design battles in the same folder as this script

# Where to store things - set these to wherever suits
workingFolder=~/scripts
tempFolder=${workingFolder}/tmp

# Don't make this less than 86400 or you'll be hitting the website for no reason
# This could be done in a crontab I guess - I run it at log-in
maxage=72000 #20 hours as seconds

# Set both of these to 0 to skip scaling the image
width=760 #The desired width in pixels (set to zero to scale with height)
height=0 #The desired height in pixels (set to zero to scale with width)

# These values should not require changing
lockFile=${tempFolder}/.lock
html=${tempFolder}/teefury.html
sourceLeft=${tempFolder}/teeCurrentLeft.png
sourceRight=${tempFolder}/teeCurrentRight.png
sourceVersus=${workingFolder}/teeFuryVersus.png
output=${tempFolder}/teeCurrent.png
battleBorder=8
tempfiles=( )
update=false

testMode=

# Fetches a picture from the TeeFury website and applies the background colour
function fetchPicture() #container-css[1] output-file[2]
{
  # Find the image within the HTML
  # -P - Perl compatible regex
  # -z - Changes new line to null (char 0) rather then newline (\n).  With -P this makes it easy to match on \n; (?s) in the regex should also work
  # -o - Only output the actual match, no other cruft
  # -a - Process a binary file as text.  DoOn't ask me why, but sometimes it considers the HTML to be binary.  Very odd.
  # -m - Limit output to n matches
  # Then pipe that into a second grep to pull out
  pictureName=`grep -Pzoa -m 1 ${1}.*\\\\n.*.png ${html} | grep -o http.*png`
  # Another way to do the same thing
  # -A - Return n lines after match
  # pictureName=`grep -a -A 1 -m 1 ${1} ${html} | grep -o http.*png`
  #echo pictureName: ${pictureName}

  if [ -z "${pictureName}" ]; then
    notify-send 'teeFury' "No image found, not updating.  Targets were: ${1}.*\\\\n.*.png and then http.*png"
    exit 1
  else
    #echo Fetching picture: ${pictureName}
    wget -O ${2} ${pictureName}
    tempfiles+=( ${2} )

    # Now try to find the colour information.  I am pretty sure this can be done in a single regex without having to resort to the strig manipulation that follows
    colour=`grep -o ${1}\".style=\"background-color:.\#...... ${html}`

    # Now find the colour.
    # Start by calculating where the colour information should start in the string we got above
    colourStart=`expr ${#1} + 27`

    # Strip the stting down to just the colour info, i.e. #rrggbb
    colour=${colour:${colourStart}:7}
    #echo colour: ${colour}

    # And now apply it as a background colour to our image
    convert ${2} -background "${colour}" -flatten ${2}
  fi
}

# This will remove all the temporary files on script exit
function cleanUp()
{
  # TODO Not too clear on this syntax, but it works
  rm -f ${tempfiles[@]}
}

# TODO Is there a better way to handle errors encountered in functions or the main body?
trap fetchPicture ERR
# TODO Is there a better way to ensure this always gets called?
trap cleanUp 0

# See if the lock file exists, if it does another instance of the script is already running
if [ -f ${lockFile} ]; then
  notify-send 'teeFury' "Lock file exists, aborting"
  exit 1
else
  touch ${lockFile}
  tempfiles+=( ${lockFile} )
fi

# No new html files will be fecthed in testMode
if [ $testMode ]; then
  echo RUNNING IN TEST MODE - html check
else
  # If we already have a copy of the HTML from TeeFury, check it's age and abort if it is less than maxage seconds old
  if [ -f ${html} ]; then
    fileage=$(($(date +%s) - $(stat -c '%Y' "${html}")))

    if [ ${fileage} -lt ${maxage} ]; then
      unset update
      # A small bit of modulous arithmetic gives us nice, human readable output
      notify-send 'teeFury' "Image too recent, only `expr ${fileage} / 3600` hours `expr ${fileage} % 3600 / 60` mins old"
    fi
  fi
fi

if [ ${update} ]; then
  # No new html files will be fecthed in testMode
  if [ ! ${testMode} ]; then
    # Cool, we're updating.  Nuke the current file if it exists
    if [ -f ${html} ]; then
      rm -f ${html}
    fi

    # Fetch the latest HTML
    wget -O ${html} http://www.teefury.com/
  fi

  # Is this a normal tee, or is it a battle?
  # Decide this by counting the number of times we can match on this regex, that's what "-c" does; it gives us a count
  # I don't actually like this regex, but it isn't a huge issue here
  picCount=`grep -c http.*products_large_images/battle/[0-9]*_.*\\.png ${html}`
  #echo picCount: ${picCount}

  tempPhoto=${tempFolder}/tempPhoto.png
  
  # If we have 4 or more, it is a battle
  if [ ${picCount} -gt 3 ]; then
    # Get the name of the left t-shirt design in the battle.
    #echo Getting battle left
    fetchPicture "colors-tst-left-img-container" "${sourceLeft}"

    # Rinse and repeat for the right-hand side
    #echo Getting battle right
    fetchPicture "colors-tst-right-img-container" "${sourceRight}"

    # We have left and right images we can work with

    # Join them, adding a small border to the left and right of both
    # This will be doubled in the middle where they join
    # TODO This results in the following message getting spat out (twice)
    #   Fontconfig warning: "/etc/fonts/conf.d/50-user.conf", line 9: reading configurations from ~/.fonts.conf is deprecated.
    # How the heck do I get rid of that?
    montage -geometry +${battleBorder}+0 -gravity center ${sourceLeft} ${sourceRight} ${tempPhoto}
    # Is there a better way to manage temp files than doing this all the time?
    tempfiles+=( "${tempPhoto}" )

    # Take the temporary file create aboved and layer the versus image centrally over the top
    convert ${tempPhoto} ${sourceVersus} -gravity center -composite ${tempPhoto}

    # Now trim the border, leaving just the border in the middle so it looks good
    # This will also update the file that's displayed
    # "-crop" appears twice as we are removing the border on the left (first) and then on the right (second)
    # Note the + and  - before ${battleBorder}
    convert ${tempPhoto} -crop +${battleBorder}+0 -crop -${battleBorder}+0 ${tempPhoto}
  else
    # For a single design we just need the one function call
    # echo Getting single
    fetchPicture "main-artwork-image-container" "${tempPhoto}"
  fi
  
  # Now do any scaling that may be required
  if [ ${width} -gt 0 -o ${height} -gt 0 ]; then
    #echo Scaling
    picWidth=`identify -format %w ${tempPhoto}`
    picHeight=`identify -format %h ${tempPhoto}`
    
    #echo Orig W x H: ${picWidth} x ${picHeight}
    
    if [ ${width} -eq 0 ]; then
      width=$((picWidth*height/picHeight))
    else
      height=$((picHeight*width/picWidth))
    fi
    
    #echo Target W x H: ${width} x ${height}
    
    convert ${tempPhoto} -thumbnail ${width}x${height} ${tempPhoto}
  fi
  
  rm -f ${output}
  mv ${tempPhoto} ${output}
fi

exit 0

Leave a Reply