Skype mood message countdown on the Mac

Posted by Patrice Neff Tue, 09 Jan 2007

I’m currently counting down to one of the most important events in my life. Most of my friends by now know what I’m talking about. But I always forgot to update my Skype mood message – that’s where my friend circle counts days nowadays.

The following 8-line Ruby script takes the problem away from me.

#!/usr/bin/env ruby
deadline = Time.local(2007, 01, 20, 22, 05)
seconds = deadline -
days = (seconds / 60 / 60 / 24 * 1000).round / 1000.0
cmdline = "osascript " +
  "-e 'tell application \"Skype\"' " +
  "-e 'send command \"SET PROFILE MOOD_TEXT " + days.to_s + " days left\" script name \"Countdown\"' " +
  "-e 'end tell'"

Save that and put the following into your crontab (accessible with crontab -e on the command line):

*/2 * * * * /Users/pneff/bin/skype-countdown.rb

Of course you can change both the time difference and the rounding.

The event I’m counting down to occurs on January 20 at 22:05.

The only thing that needs explanation is the invocation of the osascript command. That’s a command line tool that OS X provides to execute Apple Script. The whole thing could also be programmed in AppleScript, but Ruby is my script language of choice – and this way I was able to do that in five minutes – less time than it took to document that here.

To get started with the Skype API for AppleScript, see Skype AppleScript API (just a short intro) and the Skype API reference.

Thanks to Apple and Skype for providing such interfaces.

Custom photo importing on the Mac

Posted by Patrice Neff Sun, 24 Dec 2006

I’m quite picky about my photo management. The thing I’m most picky about is my folder structure as I want to be able to live independent of a single photo management application. So far iPhoto did not allow me to keep my own structure and still use it. But that became possible with version 6 of iPhoto and as it came pre-installed on my MacBook Pro I’m now using it.

Today I spent a short while to get it nicely integrated into my workflow. Without my strict folder naming requirements I could just set iPhoto to download my photos automatically and import them whenever I connect my camera. To move them into my own structure it’s a little bit more work – but not much.

First I created the following Ruby script and saved it as ~/bin/organize-pictures.rb.

require 'rubygems’
require 'exifr’

TARGET_DIR = “/Users/pneff/Pictures/Digicam/”

ARGV.each do |pic| obj = if not obj.nil? picdate = obj.exif.date_time picdir = TARGET_DIR + picdate.strftime(”%Y/%Y-%m-%d”) picname = picdir + “/” + File.basename(pic) begin Dir.mkdir(picdir) unless File.exists?(picdir) File.rename(pic, picname) puts picname rescue puts “Could not rename #{pic}” end end

For the script to work the “exifr” module must be installed. You can do that by executing sudo gem install exifr on the command line.

This script accepts a list of file names as command line parameters. It parses the EXIF tags of each file to determine the photo’s date and then moves it into the folder specified with TARGET_DIR. The folder naming is configured inside the strftime. In my case it’s a basic folder with the year and inside that a folder with year-month-day. The script will probably fail if the year folder does not exist yet, I may fix that in the future.

Replace the value of the TARGET_DIR constant with your own folder where you store the pictures.

Afterwards I created an application using Automator with the following three actions:

  1. “Download Pictures” from the application Image Capture. You can optionally check the “Delete images from camera after download” checkbox, but I chose to leave it unchecked until I really trust that setup.
  2. “Run Shell Script” from the application Automator. Put in this script: /Users/pneff/bin/organize-pictures.rb “$@”
  3. “Import photos” from the application iPhoto. Choose the album where pictures should be imported.

Save that script as an application. I chose to save it into my bin directory in the home as well. You can test that application now by double-clicking it. The pictures should be moved to the correct folder and then imported into iPhoto.

Once everything works, launch the application Image Capture. In the preferences you can select an action that will be executed when you connect a camera. Select the application you just created with Automator.

Update August 23, 2007

Rob wrote me an e-mail with the following comment:

It looks like the version of automator included with 10.4.10 adds some fancy stuff to the first and last file in the argument list (strange quotes) which of courses messes up the file processing.

Here’s my hacky fix:

 ARGV.each do |pic|
   # clean up the crap automator adds to the first and last filename
   pic = pic.sub(/^[^\/]*\//, '/')
   pic = pic.sub(/\.JPG.*$/, '.JPG') 
   obj =

It’s hacky because it relies on a “/” to indicate the start of the filename and they have to end in .JPG but it works for my needs and might help someone else out there. updates

Posted by Patrice Neff Thu, 07 Sep 2006

This morning in the train I finally came around to fix a few issues with that had prevented a release for a while. The big change: search is now fast!

the search uses a Ferret index with the acts_as_ferret module. Ferret is basically the Ruby version of Lucene.

And the URLs are normalized when a new entry is added. This should leave us with far fewer duplicates than we now have. I find most of the duplicates when checking the new submissions but it still was an annoyance.

Technische Limitierung verhindert höhere Benzinpreise

Posted by Patrice Neff Wed, 28 Sep 2005

Die folgende Story ist zwar bereits ein wenig her, aber immer noch interessant. Nach dem Wirbelsturm welcher New Orleans versenkte, stiegen die Benzinpreise offenbar ziemlich hoch. Da ich kein Auto fahre bin ich davon nicht persönlich betroffen. Deshalb habe ich keine Ahnung, wie teuer Benzin normalerweise ist und habe darum noch das "offenbar" eingefügt. In dem Zusammenhang habe ich eine auf den ersten Blick witzige Story gelesen: einige Tankstellen konnten den Preis nicht auf die über drei Dollars pro Fass hochschrauben. Ihre Zapfsäulen waren zu alt dafür.

About 200 gas sellers in rural Vermont own pumps too old to compute the higher prices, state authorities said on Friday, causing some to shut their pumps when prices spiked above $3 after the devastation of Hurricane Katrina.

"I knew my pump was old but I didn't expect prices to rise this fast," said Bill MacDonald, owner of central Vermont's Waits River General Store, whose 25-year-old pumps can't display any price above $2.99 a gallon.

Daraus können wir als Software-Entwickler selbstverständlich etwas lernen: möglichst wenig Limitierungen für Werte die nicht fix limitiert sind. Also so etwas wie Preise, Zeiten, Dateigrössen, Texteingaben, etc. Nun fordern aber die meisten Programmiersprache vom Programmierer bei der Deklaration einer Variable eine Entscheidung für eine Datengrösse: int, long, double und so weiter lassen grüssen. Doch lassen sich durch ein wenig (oder viel - je nach Umgebung) Abstraktion und Fleiss diese Variablen durchaus auch endlos wachsen - jedenfalls so lange wie der RAM mitmacht.

Ein Beispiel dafür ist die Programmiersprache Ruby. Diese konvertiert automatisch zwischen den beiden Datentypen Fixnum und Bignum. Ich zitiere aus dem Ruby "Pickaxe" Buch:

Ruby supports integers and floating point numbers. Integers can be any length (up to a maximum determined by the amount of free memory on your system). Integers within a certain range (normally -230 to 230-1 or -262 to 262-1) are held internally in binary form, and are objects of class Fixnum. Integers outside this range are stored in objects of class Bignum (currently implemented as a variable-length set of short integers). This process is transparent, and Ruby automatically manages the conversion back and forth.

Zurück zu meinem Eingangsbeispiel. Bei mechanischen Komponenten ist die Sachlage natürlich anders. Zudem gibt es ja auch bei Software-Projekten oft eine Spezifikation à la, "der Preis wird nie höher als drei Dollar sein", an welche sich der Entwickler hält. Erstaunt hat mich so oder so, dass der Preis nicht auf die logischeren 9.99 Dollars limitiert ist.

Wahrscheinlich sind das also drei Rädchen für den Preis, eines mit den Ziffern Null, Eins und Zwei und die anderen beiden mit den Ziffern von Null bis Neun. Bei meiner Mutter zu Hause steht so eine alte Zapfsäule und ich werde mir die irgendwann nochmals genauer anschauen.