get OSD messages from remote host

e.g. osd notify with remote irssi

If you feel the same and your irssi is running local, check the irssi-osd script http://scripts.irssi.org/#osd.pl and skip reading this page. But if your irssi runs remote (e.g. in a screen session) have a look at my solution.


table of contents

  1. dependencies
  2. the big picture
  3. remote setup
  4. local setup
  5. script overview

1. dependencies

2. the big picture

I use a notify plugin on the irssi runnig on the remote host, this plugin append the notifications on a logfile. There is a tail -f running against this file and send the output via sendxmpp vi a dedicated jabber account to an other dedicated jabber account.

On the client server (where irssi is runnig in a ssh session) there is a perl script connected to the jabber account (that account where the messages are posted on). This script forward all incomming messages to osd_cat.

3. remote setup

4. local setup

5. script overview

m2l.pl
use strict;
use IO::Handle;
use vars qw($VERSION %IRSSI);

use Irssi;
$VERSION = '0.0.1';
%IRSSI = (
	authors     => 'Jeroen Coekaerts, Koenraad Heijlen, Wulf Coulmann',
	contact     => 'grenouille@c-base.org',
	name        => 'm2l',
	description => 'write who is talking to you, on what IRC Network to a logfiel, so you can use this for xmpp -> osd messeges.',
	license     => 'BSD',
	url         => 'http://gpl.coulmann.de/remote-osd.html',
	changed     => '2008-11-09'
);

# based on osd.pl  
# url         => 'http://scripts.irssi.org/#osd.pl',



#--------------------------------------------------------------------
# Public Variables
#--------------------------------------------------------------------
my %myHELP = ();

#--------------------------------------------------------------------
# Settings
#--------------------------------------------------------------------

my $send_file = '/var/log/osd_msg';  # where we are logging.
my $regex = qr/(foo|bar)/;           # change foo bar to terms you whant to be notifyed about (beside messages with your nic as recipient)


#--------------------------------------------------------------------
# Help function
#--------------------------------------------------------------------
sub cmd_help { 
	my ($about) = @_;

	%myHELP = (
		osd_test => "
osd_test

Displays a small test message on screen
",
		m2l => "
M2L 

* your notification will be written to ".$send_file."
* you get info on ".$regex." (beside messages with your nic as recipient)
change this to your need in the script 

* osd_showactivechannel	(default: yes)
Currently the setting is: " . Irssi::settings_get_str('m2l_showactivechannel') . "


",


);

	if ( $about =~ /(osd_test|m2l)/i ) { 
		Irssi::print($myHELP{lc($1)});
	} 
}

#--------------------------------------------------------------------
# Irssi::Settings
#--------------------------------------------------------------------

Irssi::settings_add_str('M2L', 'm2l_showactivechannel', "yes");


#--------------------------------------------------------------------
# initialize the pipe, test it.
#--------------------------------------------------------------------

sub init {
	osdprint("M2L Loaded.");
}


#--------------------------------------------------------------------
# Private message parsing
#--------------------------------------------------------------------

sub priv_msg {
	my ($server,$msg,$nick,$address,$target) = @_;
        print LOG "privat";
	if ((Irssi::settings_get_str('m2l_showactivechannel') =~ /yes/) or
	   not (Irssi::active_win()->get_active_name() eq "$nick") ) {
                        $nick =~ s/\@.*//;
			osdprint($server->{chatnet}.":$nick -- $msg");
	}
}

#--------------------------------------------------------------------
# Public message parsing
#--------------------------------------------------------------------

sub pub_msg {
	my ($server,$msg,$nick,$address, $channel) = @_;
	my $show;
        print LOG "public";

	if (Irssi::settings_get_str('m2l_showactivechannel') =~ /yes/) {
		$show = 1;
	} elsif(uc(Irssi::active_win()->get_active_name()) eq uc($channel)) {
		$show = 0;
	}

	if ($show) {
	#if (0 == 0) {
		my $onick= quotemeta "$server->{nick}";
		my $pat ='(\:|\,|\s)'; # option...
		if($msg =~ /^$onick\s*$pat/i){
			osdprint("$channel".":$nick -- $msg");
		}elsif($msg =~ /$regex/i && not $channel =~ /bitlbee/ ){
			osdprint("you mentiond by $channel".":$nick -- $msg");
		}
	}
}

#--------------------------------------------------------------------
# The actual printing
#--------------------------------------------------------------------

sub osdprint {
	my ($text) = @_;
        $text =~ s/public#//;
        $text =~ s/\n/##/;
        $text =~ s/##.*$//;
        $text =~ s/'/`/g;
 
	open( MSG, '>>'.$send_file ) 
		or print "unable to open $send_file\n ";
        print MSG $text."\n"; 
        close MSG; 
}

#--------------------------------------------------------------------
# A test command.
#--------------------------------------------------------------------

sub cmd_osd_test {
	osdprint("Testing OSD");
}


#--------------------------------------------------------------------
# Irssi::signal_add_last / Irssi::command_bind
#--------------------------------------------------------------------

Irssi::signal_add_last("message public", "pub_msg");
Irssi::signal_add_last("message private", "priv_msg");

Irssi::command_bind("osd_test","cmd_osd_test", "M2L");
Irssi::command_bind("help","cmd_help", "Irssi commands");

#--------------------------------------------------------------------
# The command that's executed at load time.
#--------------------------------------------------------------------

init();

#--------------------------------------------------------------------
# This text is printed at Load time.
#--------------------------------------------------------------------

Irssi::print("Use /help m2l for more information."); 


#- end


client.pl
#!/usr/bin/perl -w 

# copyright Wulf Coulmann <scripts at gpl.coulmann dot de>

# GNU GPL
# http://www.gnu.org/licenses/gpl.html
#
# Download me here: http://gpl.coulmann.de/

# Based on the client example from teh Net::XMPP package.

# Version 0.0.1 (this is basic and proof of concept)

use Net::XMPP;
use strict;

#use Data::Dumper;

# ---------- config ----------------

my $debug = 0;                     # swich to 1, to make the script more verbose
my $server = 'JABBER_SERVER';
my $port = '5222';
my $username = 'USER_NAME';
my $password = 'PASSWORD';
my $osd_cfg = '/home/system/etc/osd.cfg'; 
# this file holds the default config for osd_cat, we read only first line.
# use xfontsel to determine your -f values
# first line schould look similar to (without # at the begining)
#
# /usr/bin/osd_cat -f -*-lucidatypewriter-bold-*-*-*-*-120-*-*-*-*-*-* -p top -c green -d 0 -A center 


# if you like to run autostart via scripts or cron you need propper enviroment to connect your display
# on most systems this should run without changeing the next two lines
$ENV{DISPLAY} = ':0.0';
$ENV{XAUTHORITY} = '/home/'.$ENV{'USER'}.'/.Xauthority';

# ---------- go for it -------------

# read some system settings
open CFG, '<'.$osd_cfg || print 'unable to open '.$osd_cfg;
my @cfg = <CFG>;
my $osd_command = $cfg[0];
$osd_command =~ s/\n//;
close CFG;

open CFG, '</etc/hostname' || print '/etc/hostname ';
@cfg = <CFG>;
my $resource = $cfg[0];
$resource =~ s/\n//;
close CFG;




$SIG{HUP} = \&Stop;
$SIG{KILL} = \&Stop;
$SIG{TERM} = \&Stop;
$SIG{INT} = \&Stop;

my $Connection = new Net::XMPP::Client();

$Connection->SetCallBacks(message=>\&InMessage,
                          # presence=>\&InPresence,
                          # iq=>\&InIQ,
                          );

my $status = $Connection->Connect(hostname=>$server,
                                  port=>$port,
                                  tls=>1 );

if (!(defined($status)))
{
    print "ERROR:  Jabber server is down or connection was not allowed.\n";
    print "        ($!)\n";
    exit(0);
}

my @result = $Connection->AuthSend(username=>$username,
                                   password=>$password,
                                   resource=>$resource);

if ($result[0] ne "ok")
{
    print "ERROR: Authorization failed: $result[0] - $result[1]\n";
    exit(0);
}

print "Logged in to $server:$port...\n" if $debug;

$Connection->RosterGet();

print "Getting Roster to tell server to send presence info...\n" if $debug;

$Connection->PresenceSend();

print "Sending presence to tell world that we are logged in...\n" if $debug;

while(defined($Connection->Process())) { }

print "ERROR: The connection was killed...\n";

exit(0);


sub Stop
{
    print "Exiting...\n";
    $Connection->Disconnect();
    system('echo -n \'osd_client disconnected\' | '.$osd_command.'&');
    exit(0);
}


sub InMessage
{
    my $sid = shift;
    my $message = shift;
    
    my $type = $message->GetType();
    my $fromJID = $message->GetFrom("jid");
    
    my $from = $fromJID->GetUserID();
    my $resource = $fromJID->GetResource();
    my $subject = $message->GetSubject();
    my $body = $message->GetBody();
    if ($debug) {
      print "InMessage\n";
      print "===\n";
      print "Message ($type)\n";
      print "  From: $from ($resource)\n";
      print "  Subject: $subject\n";
      print "  Body: $body\n";
      print "===\n";
      print $message->GetXML(),"\n";
      print "===\n";
    }

    system("killall osd_cat 2>/dev/null");
    system('echo -n \''.$body.'\' | '.$osd_command.'&');
 

}


sub InIQ
{
    my $sid = shift;
    my $iq = shift;
    print "InIQ\n";
    
    my $from = $iq->GetFrom();
    my $type = $iq->GetType();
    my $query = $iq->GetQuery();
    my $xmlns = $query->GetXMLNS();
    print "===\n";
    print "IQ\n";
    print "  From $from\n";
    print "  Type: $type\n";
    print "  XMLNS: $xmlns";
    print "===\n";
    print $iq->GetXML(),"\n";
    print "===\n";
}

sub InPresence
{
    my $sid = shift;
    my $presence = shift;
    
    print "InPresence\n";
    my $from = $presence->GetFrom();
    my $type = $presence->GetType();
    my $status = $presence->GetStatus();
    print "===\n";
    print "Presence\n";
    print "  From $from\n";
    print "  Type: $type\n";
    print "  Status: $status\n";
    print "===\n";
    print $presence->GetXML(),"\n";
    print "===\n";
}




The homepage for this howto is http://gpl.coulmann.de/remote-osd.html. Maybe you like to check out http://gpl.coulmann.de