Friday, August 05, 2011

IRSSI Notification Mod

If anyone still uses IRC these days (and you should because it's cheap, flexible group chat with support for file transfer, private messaging and pretty much everything else) you might appreciate some of the work I've done to increase the utility of IRC in this Smartphone age.

1. I'm running IRSSI off a Linux server I have set up from home. This is pretty par for the course for IRSSI but one of the easiest and most liberating thing you can do with it is run it inside of a program called "screen" and setup SSH on the Linux server. Whenever I'm at a Terminal (in Linux or OSX) or have access to PuTTY (Windows) I can SSH into my home server and open up screen to have full access to the IRC client (among any other programs I have running on the server). You can even extend this functionality to your Smartphone in at least two different ways, one if you have an SSH App (i use iSSH on my iPhone) or if you want to set up IRSSI to run as a proxy you can use any decent IRC app to login to that proxy and go from there. The proxy tends to be faster and easier to type on as every SSH app I've ever used has some terrible lag on the keyboard or has some other annoying twitch. Even iSSH cuts some of the terminal window off if you hold the iPhone portrait style and if you hold it landscape it makes the keyboard see-through and puts it over where you're reading the text.



The other major mod you can do is to have IRSSI look for any time you're name (or other keywords) are mentioned then it can log them and even send them to you via email. For me this is ideal as my phone always notifies me when I have new email and I use Gmail which is flexible enough for me to tag emails and sort them in case I want to skip the inbox so i don't get notifications. Here's how I've set it up.

1) Set IRSSI to hilight your nick with /HILIGHT
2) Install 2 plugins: FNotify.pl and Screen-Away.pl.
3) Modify them slightly to improve functionality. I'll post my mods here.

FNotify.pl
Install SSMTP with "SUDO APT-GET INSTALL SSMTP" or whatever your Linux distro supports. [Update:You need to set up ssmtp with your email information: see this tutorial for more]

In FNotify.pl, change the $EMAIL and maybe $SSMTP to your email address and the location of SSMTP. Email should be in the format [username]\@domain.com. Note the slash between the username and the @.

This adjustment on Joel Bastos' mod is to improve the email that's sent to include the message that triggered the notification.

Screen-Away.pl
These modifications are to remove some of the annoying things that screen-away did when I was using it. This mod will load FNotify when it sets away and unloads it when you come back. This prevents you from getting messages when you're still using IRC (you can also /SET BEEP_MSG_LEVEL HILIGHT in IRSSI to enable notifications when you're active and press [CTRL+A,CTRL+G] when in Screen until it says "switched to audible bell." to enable a small system notice noise when someone mentions your name in chat.

FNotify.pl
# todo: grap topic changes

use strict;
use vars qw($VERSION %IRSSI);

use Irssi;
$VERSION = '0.0.3';
%IRSSI = (
authors => 'Thorsten Leemhuis',
contact => 'fedora@leemhuis.info',
name => 'fnotify',
description => 'Write a notification to a file that shows who is talking to you in which channel.',
url => 'http://www.leemhuis.info/files/fnotify/',
license => 'GNU General Public License',
changed => '$Date: 2007-01-13 12:00:00 +0100 (Sat, 13 Jan 2007) $'
);

#--------------------------------------------------------------------
# In parts based on knotify.pl 0.1.1 by Hugo Haas
# http://larve.net/people/hugo/2005/01/knotify.pl
# which is based on osd.pl 0.3.3 by Jeroen Coekaerts, Koenraad Heijlen
# http://www.irssi.org/scripts/scripts/osd.pl
#
# Other parts based on notify.pl from Luke Macken
# http://fedora.feedjack.org/user/918/
#
# ssmtp email notification support added by Joel Bastos
# http://kintoandar.blogspot.com
#
#--------------------------------------------------------------------

# Please set the variables (don't forget to escape "\" the "@" symbol like the example)
my $EMAIL = "[username]\@domain.com";
my $SSMTP = "/usr/sbin/ssmtp";

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

sub priv_msg {
my ($server,$msg,$nick,$address,$target) = @_;
filewrite($nick." " .$msg );
}

#--------------------------------------------------------------------
# Printing hilight's
#--------------------------------------------------------------------

sub hilight {
my ($dest, $text, $stripped) = @_;
if ($dest->{level} & MSGLEVEL_HILIGHT) {
filewrite($dest->{target}. " " .$stripped );
}
}

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

sub filewrite {
my ($text) = @_;
# FIXME: there is probably a better way to get the irssi-dir...
open(FILE,">$ENV{HOME}/.irssi/fnotify");
print FILE "\n" . $text . "\n";
close (FILE);
my $mail=`echo "Subject: IRSSI"|cat - $ENV{HOME}/.irssi/fnotify|$SSMTP $EMAIL`;
}

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

Irssi::signal_add_last("message private", "priv_msg");
Irssi::signal_add_last("print text", "hilight");

Screen-Away.pl
use Irssi; use strict; use FileHandle; use vars qw($VERSION %IRSSI); $VERSION = "0.9.7.1"; %IRSSI = (
authors => 'Andreas \'ads\' Scherbaum ',
name => 'screen_away',
description => 'set (un)away, if screen is attached/detached',
license => 'GPL v2',
url => 'none', );
# screen_away irssi module
#
# written by Andreas 'ads' Scherbaum
#
# changes:
# 07.02.2004 fix error with away mode
# thanks to Michael Schiansky for reporting and fixing this one 07.08.2004 new function for
# changing nick on away 24.08.2004 fixing bug where the away nick was not storedcorrectly
# thanks for Harald Wurpts for help debugging this one 17.09.2004 rewrote init part to use
# $ENV{'STY'} 05.12.2004 add patch for remember away state
# thanks to Jilles Tjoelker change "chatnet" to "tag" 18.05.2007 fix '-one' for
# SILC networks
#
#
# usage:
#
# put this script into your autorun directory and/or load it with
# /SCRIPT LOAD
#
# there are 5 settings available:
#
# /set screen_away_active ON/OFF/TOGGLE /set screen_away_repeat /set screen_away_message
# /set screen_away_window /set screen_away_nick
#
# active means, that you will be only set away/unaway, if this
# flag is set, default is ON repeat is the number of seconds, after the script will check the screen status
# again, default is 5 seconds message is the away message sent to the server, default: not here ... window is
# a window number or name, if set, the script will switch
# to this window, if it sets you away, default is '1' nick is the new nick, if the script goes away will
# only be used it not empty
#
# normal you should be able to rename the script to something other than 'screen_away' (as example, if you
# dont like the name) by simple changing the 'name' parameter in the %IRSSI hash at the top of this script
# variables
my $timer_name = undef; my $away_status = 0; my %old_nicks = (); my %away = ();
# Register formats
Irssi::theme_register( [
'screen_away_crap',
'{line_start}{hilight ' . $IRSSI{'name'} . ':} $0' ]);
# if we are running
my $screen_away_used = 0;
# try to find out, if we are running in a screen (see, if $ENV{STY} is set
if (!defined($ENV{STY})) {
# just return, we will never be called again
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
"could not open status file for parent process (pid: " . getppid() . "): $!"
);
return;
}
my ($socket_name, $socket_path);
# search for socket normal we could search the socket file, ... if we know the path but so we have to call one
# time the screen executable disable locale the quotes around C force perl 5.005_03 to use the shell thanks to
# Jilles Tjoelker for pointing this out
my $socket = `LC_ALL="C" screen -ls`; my $running_in_screen = 0;
# locale doesnt seems to be an problem (yet)
if ($socket !~ /^No Sockets found/s) {
# ok, should have only one socket
$socket_name = $ENV{'STY'};
$socket_path = $socket;
$socket_path =~ s/^.+\d+ Sockets? in ([^\n]+)\.\n.+$/$1/s;
if (length($socket_path) != length($socket)) {
# only activate, if string length is different (to make sure, we really got a dir name)
$screen_away_used = 1;
} else {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
"error reading screen informations from:");
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
"$socket");
return;
}
}
# last check
if ($screen_away_used == 0) {
# we will never be called again
return;
}
# build complete socket name
$socket = $socket_path . "/" . $socket_name;
# register config variables
Irssi::settings_add_bool('misc', $IRSSI{'name'} . '_active', 1); Irssi::settings_add_int('misc',
$IRSSI{'name'} . '_repeat', 5); Irssi::settings_add_str('misc', $IRSSI{'name'} . '_message', "not here ...");
Irssi::settings_add_str('misc', $IRSSI{'name'} . '_window', "1"); Irssi::settings_add_str('misc',
$IRSSI{'name'} . '_nick', "");
# init process
screen_away();
# screen_away()
#
# check, set or reset the away status
#
# parameter:
# none return: 0 (OK)
sub screen_away {
my ($away, @screen, $screen);
# only run, if activated
if (Irssi::settings_get_bool($IRSSI{'name'} . '_active') == 1) {
if ($away_status == 0) {
# display init message at first time
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
"activating $IRSSI{'name'} (interval: " . Irssi::settings_get_int($IRSSI{'name'} . '_repeat') . "
seconds)");
}
# get actual screen status
my @screen = stat($socket);
# 00100 is the mode for "user has execute permissions", see stat.h
if (($screen[2] & 00100) == 0) {
# no execute permissions, Detached
$away = 1;
} else {
# execute permissions, Attached
$away = 2;
}
# check if status has changed
if ($away == 1 and $away_status != 1) {
# set away
if (length(Irssi::settings_get_str($IRSSI{'name'} . '_window')) > 0) {
# if length of window is greater then 0, make this window active
# Irssi::command('window goto ' . Irssi::settings_get_str($IRSSI{'name'} . '_window'));
}
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
"Set away");
my $message = Irssi::settings_get_str($IRSSI{'name'} . '_message');
if (length($message) == 0) {
# we have to set a message or we wouldnt go away
$message = "not here ...";
}
my ($server);
foreach $server (Irssi::servers()) {
if (!$server->{usermode_away}) {
# user isnt yet away
$away{$server->{'tag'}} = 0;
$server->command("AWAY " . (($server->{chat_type} ne 'SILC') ? "-one " : "") . "$message") if
(!$server->{usermode_away});
$server->command("SCRIPT load fnotify.pl");
if (length(Irssi::settings_get_str($IRSSI{'name'} . '_nick')) > 0) {
# only change, if actual nick isnt already the away nick
if (Irssi::settings_get_str($IRSSI{'name'} . '_nick') ne $server->{nick}) {
# keep old nick
$old_nicks{$server->{'tag'}} = $server->{nick};
# set new nick
$server->command("NICK " . Irssi::settings_get_str($IRSSI{'name'} . '_nick'));
}
}
} else {
# user is already away, remember this
$away{$server->{'tag'}} = 1;
}
}
$away_status = $away;
} elsif ($away == 2 and $away_status != 2) {
# unset away
Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'screen_away_crap',
"Reset away");
my ($server);
foreach $server (Irssi::servers()) {
if ($away{$server->{'tag'}} == 1) {
# user was already away, dont reset away
$away{$server->{'tag'}} = 0;
next;
}
$server->command("AWAY" . (($server->{chat_type} ne 'SILC') ? " -one" : "")) if
($server->{usermode_away});
$server->command("SCRIPT unload fnotify.pl");
# $server->command("WINDOW goto #dece");
if (defined($old_nicks{$server->{'tag'}}) and length($old_nicks{$server->{'tag'}}) > 0) {
# set old nick
$server->command("NICK " . $old_nicks{$server->{'tag'}});
$old_nicks{$server->{'tag'}} = "";
}
}
$away_status = $away;
}
}
# but everytimes install a new timer
register_screen_away_timer();
return 0;
}
# register_screen_away_timer()
#
# remove old timer and install a new one
#
# parameter:
# none return: none
sub register_screen_away_timer {
if (defined($timer_name)) {
# remove old timer, if defined
Irssi::timeout_remove($timer_name);
}
# add new timer with new timeout (maybe the timeout has been changed)
$timer_name = Irssi::timeout_add(Irssi::settings_get_int($IRSSI{'name'} . '_repeat') * 1000, 'screen_away',
'');
}

1 comment:

Safdar Ali said...

Last month i have changed this. It would be so helpful for me. desktop notification software