Controlling IM app statuses in one place

For my next trick, I was going to sling together a UI to help my wife manage Skype. But then I found that the Skype API is a little more painful than just RubyOSA.

I discovered that RubyOSA comes with a built in script to generate RDoc for any AppleScript-supporting application that has a defined AppleScript definition. How handy! “rdoc –name Skype” and off I went. Or so I thought. Skype’s AppleScript API is simple: they give you one command that accepts commands using their protocol.

Not entirely dissuaded, I started my campaign to create a script to change the status of my iChat, Adium, and Skype (yes, I need all three – don’t you???) simultaneously.

To automate things further, I deposited the script in ~/Library/Application Support/Quicksilver/Actions. I then input the command (on, off, or away) via Quicksilver using ‘.’ to let me enter a command and then my script shows up as a target. I then created Quicksilver hotkeys for online (CTRL-CMD-UP), offline (CTRL-CMD-DOWN), and away (CTRL-CMD-LEFT or “exit stage left” as I see it). So, finally, my IM status should reasonably reflect when I’m actually on or off.

If you want to use this script:

  • Bear in mind, your Ruby binary is probably installed somewhere other than /usr/local/bin/ruby so you’ll need to tweak that line.
  • You’ll need rubygems installed
  • You’ll need the RubyOSA gem installed

No, Steve, I was not up all night working on this.

[Download] (right click “Save Link As”)

Update (3/12/07): Since made some minor tweaks to support custom away messages for Adium and iTunes. Of course, to make this “sexy” (extensible), I’d scan a subdirectory for “plugins” that would manage the status per IM application allowing for you Mac users who use Fire instead of Adium, for example.

#!/usr/local/bin/ruby

require 'rubygems'
require 'rbosa'

def get_app(app_name)
  app = OSA.app(app_name)
  if app.nil?
    puts "#{app} does not exist"
    exit
  end
  app
end

$Adium = get_app "Adium"
$iChat = get_app "iChat"

$MESSAGE = {
  :on => "Available",
  :away => "Away",
  :off => "" # moot anyway
}

$STATUS = {
  :Skype => {
    :off => "OFFLINE",
    :on => "ONLINE",
    :away => "AWAY"
  },
  :Adium => {
    :off => OSA::Adium::ASST::OFFLINE,
    :on => OSA::Adium::ASST::AVAILABLE,
    :away => OSA::Adium::ASST::AWAY    
  },
  :iChat => {
    :off => OSA::IChat::MSTA::OFFLINE,
    :on => OSA::IChat::MSTA::AVAILABLE,
    :away => OSA::IChat::MSTA::AWAY
  }
}

def is_known_status?(app, status)
  $STATUS[app].has_key? status
end    

def set_Skype_status_to(status)
  if not is_known_status? :Skype, status
    # No custom statuses with Skype, sorry!
    status = :away
  end
  app = get_app "Skype"
  request = "SET USERSTATUS #{$STATUS[:Skype][status]}"
  app.send2 request, ""
end

def set_Adium_status_to(status)
  if is_known_status? :Adium, status
    $Adium.adium_controller.my_status_type = $STATUS[:Adium][status]
    $Adium.adium_controller.my_status_message = $MESSAGE[status]
  else
    $Adium.adium_controller.my_status_type = $STATUS[:Adium][:away]
    $Adium.adium_controller.my_status_message = status.to_s
  end    
  if status == :on
    $Adium.adium_controller.accounts.each { |a| a.connect }
  end
end

def set_iChat_status_to(status)
  if is_known_status? :iChat, status 
    $iChat.status = $STATUS[:iChat][status]    
    $iChat.status_message = $MESSAGE[status]
  else
    $iChat.status = $STATUS[:iChat][:away]
    $iChat.status_message = status
  end
end

status = ARGV[0].intern
set_Skype_status_to status
set_Adium_status_to status
set_iChat_status_to status  

Posted by evan on Tuesday, April 10, 2007

blog comments powered by Disqus