now | writings | rss | github | twitter | contact

Pipe Event Plugin for Adium

posted to writings on dec 27th, 2010 with tags adium, mac, nerd, and pidgin and commented on nine times

Back when I used OpenBSD on my laptop and Pidgin for instant messaging, I wrote a D-Bus script to watch incoming messages and forward any to my cell phone that were received while my screen was locked. The script forwarded messages to Prowl's web API, which would forward them to my iPhone using push notifications.

The last time I switched back to a Mac desktop, I had to switch back to Adium and lost the ability to selectively forward messages. While Adium does have an event action to run an AppleScript, there's no way of passing the actual event text to the script, so it has to talk back to Adium and try to find the newest message. The only option was to generate Growl notifications for all messages and then configure Growl to forward them to Prowl. I got fed up with that pretty quickly, so I modified Adium to create a new event type for "messages received while away". That way I could have the Growl notification only on that event, so I would only get messages forwarded while away. That worked better, but it prevented me from being able to go away while still at my computer without getting a bunch of messages queued up on my phone.

After that I switched back to OpenBSD, so I was back to my D-Bus script. Then I switched back to an Android phone so I couldn't use Prowl and had to forward messages to my phone through T-Mobile's e-mail-to-SMS gateway. I recently switched back to a Mac so now I'm back to Adium with no easy way of forwarding messages to Android.

I spent a few hours this evening writing an Adium plugin that can execute an arbitrary command and pipe the event text to it. Now I can have a script receive every incoming message but only forward them when the screen is locked or some other condition. Once Notifo finally comes out with their Android client, I'll be able to make it forward messages using their web API.

Instructions

  1. Click the "Install" link on the plugin's Adium Xtras page. Adium should notify you that the plugin has been installed and you may have to restart Adium.
  2. In Adium's Preferences, choose Events. You can also create a per-contact alert by double-clicking on a contact and clicking the Events icon.
  3. Click an event, such as "Message received", and click the [+] button. Select "Pipe event to command". Enter the full path to your command and hit OK.

The command is executed every time the event triggers (like when a message is received), has its STDOUT and STDERR closed, and then has the full content of the event/message written to its STDIN (for easier scripting, the event/message has a trailing newline appended). The title of the event is passed to the command as its first argument (for received messages, this is the name of the sender).

A simple ruby script that will write every received message to a file:

#!/usr/bin/ruby
File.open("#{ENV["HOME"]}/adium.log", "a+") do |f|
  f.puts "#{Time.now}: from #{ARGV[0]} - #{STDIN.read.strip}"
end

Note: make sure the command is executable (chmod +x).

The BSD-licensed source code is on github.

Comments? Contact me via Twitter or e-mail.

9 Comments

Sterling Hanenkamp (authentic) on january 4th, 2011 at 08:44:12:

This is super. This may allow me to finally be able to get my custom speak-chat script running with Adium rather than just iChat.

I have a few suggestions: (1) make it a little easier to debug by providing some way to get at the stderr of the script to see why it fails (work around is to use a simple bash wrapper that sends STDERR to a log file), (2) it would be nice if you passed the name of the groupchat on the command-line after the name of the buddy, (3) allow arguments to be specified like "/usr/local/bin/my-script foo" so you can reuse the same script more easily for different kinds of messages.

Thanks again. This is great.

joshua (authentic) on january 4th, 2011 at 09:19:16:

doing something with stderr would be possible, though it might be annoying in some instances to have to constantly dismiss a dialog. for debugging my own scripts, i just logged stdin and the args to a /tmp file until i figured out what it wasn't doing properly.

passing the group name as the second arg should be fairly easy to implement.

to pass your own arguments to the script from adium, it would have to invoke the command with 'sh -c' to let sh parse the passed arguments. but since the plugin is also appending the sender name (and possible group name) as arguments that would be passed to 'sh -c', it would have to escape meta chars and spaces and other funkiness in them to avoid any security problems with passing arbitrary text (a sender name or group name) to 'sh -c'. this is avoided currently due to the plugin passing the arguments directly to the executable without an intermediate shell.

so it's possible, but it would take some code to handle this securely.

Caglar Oral (authentic) on january 31st, 2011 at 22:31:37:

Does it support Unicode? I couldnt manage to get messages with Unicode characters

Craig (not authenticated) on november 4th, 2011 at 16:57:34:

Any chance you can have this return the contact name instead of the display name (alias)? I can't seem to find a way to get adium to convert a display name to a contact name.

monoclast (not authenticated) on november 18th, 2011 at 02:36:55:

Trying to get version 1.1. for Lion from http://adiumxtras.com/index.php?a=xtras&xtra_id=7852, and the Install link crashes Adium 1.4.3. What's up with that? Also, the Download link doesn't work.

Chris (authentic) on february 3rd, 2012 at 05:09:25:

Hi,
I'm trying to use your plugin with a ruby script making an oauth request to an online service before making a post request to this same service, but nothing happen, how can I debug all this ?
When I launch manually my ruby script in command line all work fine...

Skrimchst (authentic) on april 15th, 2012 at 16:47:26:

I've tried, but can't manage to get the message text.

I pipe any received message to this script:

#!/usr/bin/python
import sys
a = sys.stdin.readlines()
f = open('out.txt','w')
print >>f, a

But get no results :( If i run the script manually, it keeps in an infinite loop when reading from STDIN. I've also tried using any simple script that does anything without using STDIN (Something like print "hello") and it doesn't work, it seems that the pipe event only pipes the message, but doesn't execute the command assigned (I've given +x permission to the file)

Any idea?

Skirmchst (authentic) on april 15th, 2012 at 16:49:38:

I forgot... i'm using v 1.5 of Adium, i think that maybe the problem is there...

Please, if someone has managed to get the plugin to work with v1.5, post the script u're using to get the output.

Thx in advance!!

x (not authenticated) on may 19th, 2012 at 23:14:19:

This does not work wit adium 1.5
Crashed adium on message recieved.