# $Id: remotegrowl.pl,v 1.14 2014/01/27 16:51:35 cbellot Exp $
#
# remotegrowl : an irssi perl script (plugin)
#
# It sends notifications (queries/hilights) to a remote growl host. It can
# be a predifined host are also be the one you are connecting from and 
# attaching to the irssi screen.
#
# Growl is a powerfull notification system for MacOSX.
#
# First of all you have to have growl installed and have to enable remote growl 
# notifications: see system preferences, growl, network and check "incoming
# notifications", "allow register of remote applications" and set a password.
#
# Notifications are sent to the defaults host. See:
# 	remotegrowl_server
# 	remotegrowl_port
# 	remotegrowl_password
# 	remotegrowl_timeout
#	remotegrowl_private_blacklist
# Set theses values according to the settings defined before.
#
# If you choose to report notification to the host you use to connect to your
# irssi host using screen, you should set remotegrowl_screenspy = 1 and
# launch a screen with a name like this :
#   screen -S irc1
# then launch irssi in this screen and set remotegrowl_screenname to 'irc1'
# the remotegrowl plugin will then :
#   - send notifications to the default host if screen is detached
#   - send notifications to the connected host if screen is attached
#     be aware that remotegrowl_port should be opened or redirected to your
#     host (nat) if you really wish to receive them
#
# Blacklist private messages nicks can be added to remotegrowl_private_blacklist
# like : 
#   /set remotegrowl_private_blacklist jdoe
#   /set remotegrowl_private_blacklist jdoe|nagios|twitter
#
# You can check the current server used for notifications with :
#  /remotegrowl
#
# You can test notifications with :
#  /remotegrowl_test
#
# remotegrowl is ipv6 ready :-p
#

use Irssi 20020121.2020 ();
$VERSION = "1.1";
%IRSSI = (
	  authors     => 'Cyril Bellot',
	  contact     => 'jcpp\@users.sourceforge.net',
	  name        => 'remotegrowl',
	  description => 'Send notifies to a remote Growl server',
	  license     => 'GPL',
	  changed     => '$Date: 2014/01/27 16:51:35 $ ',
);

use Irssi::Irc;
use strict;
use Net::Growl;
use IO::Socket::INET6;

my $lastpubmessagedate = 0;
my $lastprivmessagedate = 0;


sub getremote () {
    my $server = "";
    # If notification needs to be sent to host that attached screen
    if (Irssi::settings_get_str("remotegrowl_screenspy")) {
	# Look at screen list to see if we are attached
	my $nm = Irssi::settings_get_str("remotegrowl_screenname");
	open(SC, "screen -list|grep \"\.$nm\t\" |");
	my $sc = <SC>; close(SC);
	if ($sc =~ /Attached/) {
	    # We are attached. Find the hostname attaching the screen
	    # First the pts:
	    my $pts = `ps a|grep "screen.*$nm"|grep -v "screen.*x.*$nm"|grep -v grep|awk '{print \$2}'`;
	    chomp($pts);
	    # Then the originating hostname
	    if ($pts ne "") {
		open(F, "last -ai|grep \"$pts.*still logged in\"".
			"|awk '{print \$10}'|");
		$server = <F>; close(F); chomp($server);
	    }
	} else {
	    # We are not attached : default host is used
	    $server = Irssi::settings_get_str("remotegrowl_server");
	}
    } else {
        # We do not need to check screen stuff. So we use server from config
        $server = Irssi::settings_get_str("remotegrowl_server");
    }
    return $server;

}

sub cmd_printremote {
    print "Remote growl server : ".getremote();
}

sub remotegrowl_send ($$$) {
    my $title = shift;
    my $text = shift;
    my $prio = shift;
    my $server = "";

    # If notification needs to be sent to host that attached screen
    $server = getremote();

    # If we are :
    # - checking that screen is currently attached
    # - not checking screen stuff
    if ($server ne "") {
        my %addr;
        # awfull check of family (AF_INET/AF_INET6) because IO::Socket::INET6
        # is not able to handle it correctly in vservers
        if ($server =~ /([0-9a-f]+):+/) {
            %addr = (PeerAddr =>  $server,
                    PeerPort =>   Irssi::settings_get_str("remotegrowl_port"),
                    LocalAddr => '::',
                    Proto => 'udp');
        } else {
            %addr = (PeerAddr =>  $server,
                    PeerPort =>   Irssi::settings_get_str("remotegrowl_port"),
                    LocalAddr => '0.0.0.0',
                    Proto => 'udp');
        }
	my $s = IO::Socket::INET6->new ( %addr ) || 
	    die "Could not create socket: $!\n" ;
	# Register growl app
	my $p = Net::Growl::RegistrationPacket->new( 
	    application=>"Remote irssi growl", 
	    password => Irssi::settings_get_str("remotegrowl_password")
	);
	$p->addNotification();
	print ($s $p->payload());

	# Send growl notification
	$p = Net::Growl::NotificationPacket->new( 
	    application => "Remote irssi growl",
	    title => $title,
	    description => $text,
	    priority => $prio,
	    sticky => 'True',
	    password => Irssi::settings_get_str("remotegrowl_password"),
	);
	print $s $p->payload();
	close($s);
    }
}

sub cmd_testmessage {
    remotegrowl_send("Test message","sent from remotegrowl irssi script",2);
}

sub pubmessage {
    my ($server, $msg, $nick, $address, $target) = @_;
    my $moi = $server->{nick};
    # channel name
    my $chanid = $server->channel_find($target);
    return if (!$chanid);
    my $win = $chanid->window();
    my $chan = $win->get_active_name();

    my $re_bl = Irssi::settings_get_str("remotegrowl_private_blacklist");
    if (!($chan =~ /$re_bl/)) {
	# public message talking to/about me
	if ($msg =~ /$moi/) {
	    if (time() - $lastpubmessagedate > 
	    Irssi::settings_get_str("remotegrowl_timeout")) {
		my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
		$year += 1900; $mon++;
		remotegrowl_send("Mention","par $nick sur $chan ($hour:$min)",2);
		$lastpubmessagedate = time();
	    }
	}
    }
}

sub privmessage {
    my ($server, $msg, $nick, $address) = @_;
    # private message to me
    my $re_bl = Irssi::settings_get_str("remotegrowl_private_blacklist");
    if (time() - $lastprivmessagedate > 
    Irssi::settings_get_str("remotegrowl_timeout")) {
    	if (!($nick =~ /$re_bl/)) {
	    my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
	    $year += 1900; $mon++; 
	    $hour =~ s/^(\d)$/0$1/; 
	    $min =~ s/^(\d)$/0$1/;
	    remotegrowl_send("Message privé","de $nick ($hour:$min)",2);
	    $lastprivmessagedate = time();
	}
    }
}

Irssi::command_bind("remotegrowl", "cmd_printremote");
Irssi::command_bind("remotegrowl_test", "cmd_testmessage");

Irssi::settings_add_str("misc",	"remotegrowl_server", "localhost");
Irssi::settings_add_str("misc",	"remotegrowl_port", "9887");
Irssi::settings_add_str("misc",	"remotegrowl_password", "NotSet");
Irssi::settings_add_str("misc",	"remotegrowl_timeout", "600");
Irssi::settings_add_str("misc",	"remotegrowl_screenspy", "0");
Irssi::settings_add_str("misc",	"remotegrowl_screenname", "irssi");
Irssi::settings_add_str("misc",	"remotegrowl_private_blacklist", "");

Irssi::signal_add_priority("message private", \&privmessage,
			   Irssi::SIGNAL_PRIORITY_LOW + 1);
Irssi::signal_add_priority("message public", \&pubmessage,
			   Irssi::SIGNAL_PRIORITY_LOW + 1);

