Update Here is a Cocoa version that is…

Update: Here is a Cocoa version that is easier to use!

May did a good job selling us on Twitter, so now you can see my twittr status in the sidebar.. I wished that changing my Twitter status was as easy as changing my iChat status, so I hacked up this bit of perl that will update it when your iChat status changes. It runs every five minutes via launchd, and uses the newly-announced Twitter API.

#!/usr/bin/perl
use strict;
use warnings;
use URI::Escape;
 
my $user = 'user@example.com';
my $pass = 'pin';
 
my $isAvailable = `osascript -e 'tell application "iChat" to status'`;
chomp $isAvailable;
 
exit if ('available' ne $isAvailable);
 
my $status = `osascript -e 'tell application "iChat" to status message'`;
chomp $status;
 
if ('' eq $status) {
	$status = 'lazy';
}
 
my $savedStatusFile = 'savedStatus.txt';
 
my $savedStatus = '';
if (-e $savedStatusFile) {	
	$savedStatus = `cat $savedStatusFile`;
}
 
if ($status ne $savedStatus) {
	#status changed, update twitter
 
	my $encStatus = 'status=' . uri_escape($status, "^A-Za-z0-9"); 
 
	`curl -s -d '$encStatus' -u $user:$pass http://twitter.com/statuses/update.xml`;
 
	open (FILE, ">$savedStatusFile") or die "can't open $savedStatusFile for writing";
	print FILE $status;
	close FILE;		
}

You can get launchd to run the script every five minutes by creating a file called ~/Library/LaunchAgents/net.tikirobot.status.plist that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.
com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>net.tikirobot.status</string>
    <key>ProgramArguments</key>
    <array>
            <string>/Users/user/status.pl</string>
    </array>
    <key>StartInterval</key>
    <integer>300</integer>
</dict>
</plist>

And then load the job using:
launchctl load ~/Library/LaunchAgents/net.tikirobot.status.plist

Update: The script now uses URI::URL and POST. Fixed a typo.
Update2: Now uses URI::Escape