After completing my script to deliver Irssi notifications to the Linux desktop using Perl (IPC::Message::Minivan and Desktop::Notify), I wondered if this framework could be extended to Windows (since I have a Windows desktop at work).

I have previously looked at Growl (on Linux) and think it is cumbersome to get the notifications across the network – but ended up using it anyway since it’s an easy way to display notifications in Windows (and probably in MacOS as well). There is a another Growl script for Irssi but I wanted to make my own that plugs into Minivan because I wanted the pop ups to look the same on all computers (at least the wording).

On Windows

  1. Download Grow for Windows and install it.
  2. Download MyEnTunnel and install it.
  3. If you haven’t already (which I am guessing you have) then download Putty SSH client and install it
  4. Configure MyEnTunnel to match your configuration, create a remote tunnel: <random port number>:localhost:23053 – The random port is important and will be used later

On the server running Irssi

  1. Install the Minivan – See this article
  2. Install Growl::GNTP
    $ sudo apt-get install libcrypt-cbc-perl libdata-uuid-perl
    $ sudo perl -MCPAN -e 'Growl::GNTP'
  3. Install the script

    # The IRC icon is from here:

    use strict;
    use warnings;
    use IPC::Message::Minivan;
    use Encode;
    use Growl::GNTP;
    use Data::Dumper;

    if ($#ARGV != 0) {
        print "Usage: <port number>\n";

    my $port = $ARGV[0];

    my $van = IPC::Message::Minivan->new(host => 'localhost');

    my $growl = Growl::GNTP->new(
            AppName => "Irssi",
            PeerHost => "localhost",
            PeerPort => $port,
            Password => "",
            AppIcon => ""

            { Name => "irssi", },

                    Event => "irssi",
                    Title => "Minivan",
                    Message => "Connection established"

    while (1) {
            if (my $cmd = $van->get(5,[])) {
                    if ($cmd->[0] eq '#irssi') {
                            my $c=$cmd->[1];

                            my $message = $c->{msg};
                            my $summary = $c->{summary};
                                            Event => "irssi",
                                            Title => $summary,
                                            Message => $message,


    Copy the script to ~/bin/

  4. Make the script executable and run it as <port number>

    The port number is the one you chose on the Windows machine for your remote tunnel – You need to run an instance of the script for each Growl-client.

I was pretty happy with solution to get notifications from Irssi though it had some shortcomings.

A couple of days ago a colleague made me aware of a Perl modules written by another colleague (Anton Berezin) called IPC::Message::Minivan which, it turns out, is perfect for my notification script. Basing the notifications on Minivan combine the speed of using something like Dbus locally (instant notifications) with the convenience of my previous script (notifications over the network, able to handle multiple clients).

This setup consists of three parts: The Minivan daemon, the Irssi script and the notification script.

As always my instructions are based on Ubuntu but should work on most Linux and Unix systems.

Installing the Minivan

IPC::Message::Minivan is not yet available directly through CPAN so we need to install it manually

  1. Download IPC::Messaging and IPC::Message::Minivan (and unpack them).
  2. Install dependencies: sudo apt-get install libjson-xs-perl libregexp-common-perl
  3. One could use dh-make-perl but I chose to install the two modules manually
    Basically run “perl && sudo make install
    :~/devel/IPC-Messaging-0.01_12$ perl Makefile.PL
    Cannot determine license info from lib/IPC/
    *** Module::AutoInstall version 1.03
    *** Checking for Perl dependencies...
    [Core Features]
    - Test::More                ...loaded. (0.72)
    - B::Generate               ...missing.
    - IO::Socket::UNIX          ...loaded. (1.23)
    - IO::Socket::INET          ...loaded. (1.31)
    - Storable                  ...loaded. (2.18)
    - Time::HiRes               ...loaded. (1.9711)
    - IO::Select                ...loaded. (1.17)
    - Module::Load::Conditional ...loaded. (0.22)
    ==> Auto-install the 1 mandatory module(s) from CPAN? [y] y
    *** Dependencies will be installed the next time you type 'make'.
        (You may need to do that as the 'root' user.)
    *** Module::AutoInstall configuration finished.
    Checking if your kit is complete...
    Looks good
    Warning: prerequisite B::Generate 0 not found.
    Writing Makefile for IPC::Messaging
    :~/devel/IPC-Messaging-0.01_12$ sudo make install
    [sudo] password for alj:
    /usr/bin/perl "-Iinc" Makefile.PL --config= --installdeps=B::Generate,0
    Cannot determine license info from lib/IPC/
    *** Installing dependencies...
    [MSG] No '/home/alj/.cpanplus/custom-sources' dir, skipping custom sources
    [MSG] No '/home/alj/.cpanplus/custom-sources' dir, skipping custom sources
    [MSG] No '/home/alj/.cpanplus/custom-sources' dir, skipping custom sources
    *** Installing B::Generate...
    Running [/usr/bin/perl /usr/bin/cpanp-run-perl /home/alj/.cpanplus/5.10.0/build/B-Generate-1.26/Makefile.PL INSTALLDIRS=site]...
    # running Build.PL installdirs=site
    /usr/bin/perl Build.PL installdirs=site
    Creating custom builder _build/lib/My/ in _build/lib/My
    Checking whether your kit is complete...
    Looks good

    Checking prerequisites...
    Looks good

    Creating new 'Build' script for 'B-Generate' version '1.26'
    Unknown 'build_class', defaulting to 'Module::Build'
    Running [/usr/bin/make test UNINST=1]...
    make[1]: Entering directory `/home/alj/.cpanplus/5.10.0/build/B-Generate-1.26'
    /usr/bin/perl Build --makefile_env_macros 1 test
            2/10 skipped: various reasons
    All tests successful, 2 subtests skipped.
    Files=6, Tests=721,  0 wallclock secs ( 0.24 cusr +  0.21 csys =  0.45 CPU)
    make[1]: Leaving directory `/home/alj/.cpanplus/5.10.0/build/B-Generate-1.26'

    *** B::Generate successfully installed.
    *** Module::AutoInstall installation finished.
    cp lib/IPC/ blib/lib/IPC/
    Manifying blib/man3/IPC::Messaging.3pm
    Installing /usr/local/share/perl/5.10.0/IPC/
    Installing /usr/local/man/man3/IPC::Messaging.3pm
    Writing /usr/local/lib/perl/5.10.0/auto/IPC/Messaging/.packlist
    Appending installation info to /usr/local/lib/perl/5.10.0/perllocal.pod
    :~/devel/IPC-Message-Minivan-0.01_08$ perl Makefile.PL
    Cannot determine license info from lib/IPC/Message/
    Writing Makefile for IPC::Message::Minivan
    :~/devel/IPC-Message-Minivan-0.01_08$ sudo make install
    cp lib/IPC/Message/ blib/lib/IPC/Message/
    cp minivan blib/script/minivan
    /usr/bin/perl "-Iinc" "-MExtUtils::MY" -e "MY->fixin(shift)" blib/script/minivan
    Manifying blib/man1/minivan.1p
    Manifying blib/man3/IPC::Message::Minivan.3pm
    Installing /usr/local/share/perl/5.10.0/IPC/Message/
    Installing /usr/local/man/man1/minivan.1p
    Installing /usr/local/man/man3/IPC::Message::Minivan.3pm
    Installing /usr/local/bin/minivan
    Writing /usr/local/lib/perl/5.10.0/auto/IPC/Message/Minivan/.packlist
    Appending installation info to /usr/local/lib/perl/5.10.0/perllocal.pod
  4. Create an Upstart script for the Minivan daemon
    $ cat /etc/init/minivan.conf
    # minivan - minimalistic message bus

    description     "minimalistic message bus"

    start on runlevel [2345]
    stop on runlevel [!2345]

    expect fork

    exec /usr/local/bin/minivan -l /var/log/minivan -d
  5. Start the Minivan daemon
    $ sudo start minivan

Install the Irssi script

  1. Copy the script to ~/.irssi/scripts/ (the script below is just for reference, it might not be up to date)
    ## Put me in ~/.irssi/scripts, and then execute the following in irssi:
    ##       /load perl
    ##       /script load notifier-minivan

    use strict;
    use Irssi;
    use vars qw($VERSION %IRSSI);
    use HTML::Entities;
    use IPC::Message::Minivan;

    $VERSION = "0.01";
    %IRSSI = (
        authors     => 'Allan Willems Joergensen',
        origauthors => 'Luke Macken, Paul W. Frields, Jared Quinn, Anton Berezin, Kristoffer Larsen',
        contact     => '[email protected],dk',
        name        => '',
        description => 'Alert the user of new messages or hilights through IPC::Message::Minivan',
        license     => 'Beerware',
        url         => '',

    # Default settings in Irssi
    Irssi::settings_add_str('notifier','minivan_host', 'localhost');
    Irssi::settings_add_str('notifier','minivan_port', 6826);

    # Fetch settings from Irssi
    my $minivan_host = Irssi::settings_get_str('minivan_host');
    my $minivan_port = Irssi::settings_get_str('minivan_port');
    my $minivan_channel = Irssi::settings_get_str('minivan_channel');

    # Connect to the Minivan
    our $van = IPC::Message::Minivan->new(host => $minivan_host, port => $minivan_port);

    sub notify {
        my ($server, $summary, $message) = @_;

        # Encode certain characters using HTML
        my $safemsg = HTML::Entities::encode($message, '<>&"');

        # Load everyone into the minivan
        $van->msg($minivan_channel, {summary => $summary, msg => $safemsg});

    sub print_text_notify {
        my ($dest, $text, $stripped) = @_;
        my $server = $dest->{server};
        return if (!$server || !($dest->{level} & MSGLEVEL_HILIGHT));
        my $sender = $stripped;
        $sender =~ s/^\<.([^\>]+)\>.+/\1/ ;
        $stripped =~ s/^\<.[^\>]+\>.// ;
        my $summary = "Hilite in " . $dest->{target};
        notify($server, $summary, $stripped);

    sub message_private_notify {
        my ($server, $msg, $nick, $address) = @_;
        return if (!$server);
        notify($server, "Private message from ".$nick, $msg);

    sub dcc_request_notify {
        my ($dcc, $sendaddr) = @_;
        my $server = $dcc->{server};

        return if (!$dcc);
        notify($server, "DCC ".$dcc->{type}." request", $dcc->{nick});

    Irssi::signal_add('print text', 'print_text_notify');
    Irssi::signal_add('message private', 'message_private_notify');
    Irssi::signal_add('dcc request', 'dcc_request_notify');
  2. Load the script inside Irssi: /script load
  3. If your Minivan is not running on the same machine as Irssi, change the configuration inside Irssi:
    /set minivan_host your_hostname – IPC::Message::Minivan is tunnel-able through ssh, see client configuration
  4. Auto-load the script:
    ln -sf ~/.irssi/scripts/ ~/.irssi/scripts/autoload/

The stuff running on your local machine

It is possible to use autossh to automatically setup the tunnel but since I am always connected to my server (at least when I am in front of a computer) I chose to use normal ssh port forwarding.

In ~/.ssh/config I have

Host my.server.bogus
        LocalForward 6826 localhost:6826

The stuff that actually shows the notifications

I did not want to bother trying to make the script error proof so I simply call the Perl script from a shell script like so


while true

    let wait=$wait+5
    if [ $wait -ge 30 ]
        sleep 30
        sleep $wait

Save the script as ~/bin/

The notification script requires Desktop::Notify – It is available in the Ubuntu repositories but it is an old version, so let’s use a newer:

$ sudo apt-get install dh-make-perl libnet-dbus-perl
$ cpan2deb Desktop::Notify
$ sudo dpkg -i ~/.cpan/libdesktop-notify-perl*.deb

The script


use strict;
use warnings;
use Desktop::Notify;
use IPC::Message::Minivan;
use Encode;

my $notify_timeout = 500;
my $icon = "/usr/share/pixmaps/pidgin/protocols/scalable/irc.svg";
#my $icon = "gnome-irc.png";

my $van = IPC::Message::Minivan->new(host => 'localhost');
our $notify = Desktop::Notify->new();
my $notification = $notify->create(summary => 'Minivan', body => 'Connection established', timeout => $notify_timeout, app_icon => $icon);

while (1) {
    if (my $cmd = $van->get(5,[])) {
        if ($cmd->[0] eq '#irssi') {
            my $c=$cmd->[1];
            my $message = Encode::encode("utf-8",$c->{msg});
            my $summary = $c->{summary};


Copy the script to ~/bin/

Remember to make both scripts executable.

The final thing to do is to add the notify client to your desktop environment’s autostart

In GNOME: System -> Preferences -> Startup Applications

Add Startup Program

Add Startup Program

Facebook now supports XMPP. Yay.

Using Facebook Chat in bitlbee is pretty straight forward (I am running 1.2.4, older versions of bitlbee require a bit more tweaking, consult the manual).

For Facebook Chat through XMPP to work you need to set a Facebook username.

In the &bitlbee channel

account add jabber <username>> <Facebook password>
account on

that’s it.

Edit (04-03-2011): As some has pointed out, you need to input your username in lowercase.

Facebook users are listed by their Facebook user id (uXXXXXXX) so you have to rename them manually, unless you are using irssi.

Download this script to ~/.irssi/scripts and load it

/script load bitlbee_rename

(Note: This script only renames your Facebook contacts – The original version which renames all contact but does not handle international characters really well is available here)

Now each of your contacts will be renamed based on their real name in their vCard.

Remember to symlink to script to ~/.irssi/scripts/autorun if you wish to auto-load it.

Since I run irssi all the time, packing as many features into it as possible seems like a nice idea.

So I use bitlbee to connect to Messenger, Google Talk/Jabber and ICQ and I have been using tircd (Twitter/irc gateway) and (Twitter/Google Talk gateway) to connect to Twitter; but none of them works like I want them to.

Today I stumbled across Twirssi, a script for irssi to interact with Twitter.

Out of the box twirssi expects input to be UTF-8 which caused some grief because my terminal is ISO-8859-15.

First, lets install required modules for twirssi

I run Ubuntu Karmic Koala so Net::Twitter is available as a package

$ sudo apt-get install libnet-twitter-perl

If you run an older Ubuntu release or another Linux/Unix variant that does not have a native package, install it from CPAN (I will not go into the configuration of CPAN here – have a look at this article for more information).

$ sudo perl -MCPAN -e shell
cpan[1]> install Net::Twitter

Answer yes to all dependencies.

Next step is to install a Perl module for the URL shortening service you wish to use; I use so let’s install the module

$ sudo perl -MCPAN -e shell
cpan[1]> install WWW::Shorten::Bitly

Now, let’s install twirssi

Head to irssi’s scripts directory

$ cd ~/.irssi/scripts

Download the script

$ wget

Make sure the script is autoloaded at startup

$ cd autorun
$ ln -sf ../ .

Patch twirssi to support other charsets than UTF-8

$ cd ~/.irssi/scripts
$ wget
$ patch -p1 < twirssi_charset.diff

Finally, configure twirssi

The configuration is done from inside irssi

  1. Create a new window for twirssi
    /win new hidden
  2. Name the new window
     /win name twitter
  3. Optional: Move the new window to another location
    /win move <number>
  4. Optional: Save new window layout
    /layout save
  5. Load twirssi
    /script load
  6. Configure URL shortening service
    /set short_url_provider Bitly

    /set short_url_args "Bitly API key"
  7. Configure Twitter usename
    /set twitter_usernames Your_Twitter_Username

    /set twitter_passwords Your_Twitter_Password

    (Note: This will store your Twitter password in clear text in irssi’s configuration)

  8. Set charset to use
    /set twirssi_charset ISO-8859-15
  9. Reload the script to pickup autologin to Twitter
    /script load

More information on how to use twirssi is available here