add notify.pl desktop notification plugin
This commit is contained in:
388
notify.pl
Normal file
388
notify.pl
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
|
||||||
|
# TODO: non expensively detect that X is running
|
||||||
|
|
||||||
|
# TODO: if we have tornado of notifications it looks like when script hits upper
|
||||||
|
# threads amount limit, some notifications "slip away", and irssi became cpu hog :(
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
# i do not use warnings pragma, because of irssi (perl) i-threads always generate warnings,
|
||||||
|
# maybe there is other way to make async jobs in irssi?
|
||||||
|
#use warnings "all";
|
||||||
|
use threads;
|
||||||
|
use threads::shared;
|
||||||
|
use MIME::Base64;
|
||||||
|
use Irssi qw (
|
||||||
|
command_bind
|
||||||
|
settings_get_bool settings_add_bool
|
||||||
|
settings_get_str settings_add_str
|
||||||
|
);
|
||||||
|
use vars qw($VERSION %IRSSI);
|
||||||
|
|
||||||
|
sub notify;
|
||||||
|
sub hookfn;
|
||||||
|
sub timeraction;
|
||||||
|
sub encodestr;
|
||||||
|
sub notify_set;
|
||||||
|
sub loadlist($);
|
||||||
|
sub savelist(@);
|
||||||
|
sub uniq(@);
|
||||||
|
|
||||||
|
$VERSION = '1.01';
|
||||||
|
%IRSSI = (
|
||||||
|
authors => 'Eleksir',
|
||||||
|
contact => 'eleksir@exs-elm.ru',
|
||||||
|
name => 'notify.pl',
|
||||||
|
description => 'Desktop notifications.',
|
||||||
|
license => 'MIT',
|
||||||
|
changed => 'Sun Apr 16 21:15:25 MSK 2017',
|
||||||
|
);
|
||||||
|
|
||||||
|
my $help = 'Usage:
|
||||||
|
/notify enable nick|chan|net - enables apropriate whitelist
|
||||||
|
/notify disable nick|chan|net - disables apropriate whitelist
|
||||||
|
/notify status - shows statuses of whitelists
|
||||||
|
/notify show - shows whitelists and their statuses
|
||||||
|
/notify add this chan|net - adds currently open channel|network to apropriate whitelist
|
||||||
|
/notify add nick|chan|net <name> - adds <name> to apropriate whitelist, <name> can be \'.\' for currently open chan or net
|
||||||
|
/notify del nick|chan|net <name> - removes <name> from apropriate whitelist, <name> can be \'.\' for currently open chan or net';
|
||||||
|
|
||||||
|
Irssi::command_bind( 'notify' => 'notify_set' );
|
||||||
|
|
||||||
|
Irssi::signal_add_last("message public", "hookfn");
|
||||||
|
Irssi::signal_add_last("message private", "hookfn");
|
||||||
|
|
||||||
|
# looks like 'notify' here is placeholder, all settings landing to section settings{"perl/core/scripts" = { ->IN_HERE<-} }
|
||||||
|
Irssi::settings_add_str('notify', 'nicklist', '');
|
||||||
|
Irssi::settings_add_str('notify', 'chanlist', '');
|
||||||
|
Irssi::settings_add_str('notify', 'netlist', '');
|
||||||
|
Irssi::settings_add_bool('notify', 'nicklist_enable', 0);
|
||||||
|
Irssi::settings_add_bool('notify', 'chanlist_enable', 0);
|
||||||
|
Irssi::settings_add_bool('notify', 'netlist_enable', 0);
|
||||||
|
# irssi save settings (via /save) to it's config only if at least one parameter is not default!
|
||||||
|
|
||||||
|
Irssi::signal_emit('setup changed'); # a good practice. irssi actually reads config only if this signal emited,
|
||||||
|
# so, if someone uses this script' settings, it will use renewed settings
|
||||||
|
|
||||||
|
my $active = 0; share($active);
|
||||||
|
my $threads = 0; share($threads);
|
||||||
|
my $THREADS_MAX = 30;
|
||||||
|
my $hook;
|
||||||
|
|
||||||
|
sub notify {
|
||||||
|
my ($topic, $message) = @_;
|
||||||
|
threads->detach();
|
||||||
|
$topic =~ s/\\/\\\\/g;
|
||||||
|
$topic =~ s/\'/\\'/g;
|
||||||
|
$message =~ s/\\/\\\\/g;
|
||||||
|
$message =~ s/\'/\\'/g;
|
||||||
|
system("notify-send", "-u", "normal", "-t", "12000", "-a", "hexchat", $topic, "-i", "hexchat", $message);
|
||||||
|
$active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub notify_set {
|
||||||
|
my ($argstring, $serverhref, $channelhref) = @_;
|
||||||
|
my $msg = undef;
|
||||||
|
|
||||||
|
if ($argstring eq 'status') {
|
||||||
|
my $nicklist = Irssi::settings_get_bool('nicklist');
|
||||||
|
my $chanlist = Irssi::settings_get_bool('chanlist');
|
||||||
|
my $netlist = Irssi::settings_get_bool('netlist');
|
||||||
|
|
||||||
|
if (($nicklist == 0) and ($chanlist == 0) and ($netlist == 0)) {
|
||||||
|
$msg = sprint("All whitelists are disabled, notifications will not appear.");
|
||||||
|
} else {
|
||||||
|
$msg = '';
|
||||||
|
|
||||||
|
if ($nicklist == 0) { $msg .= "Nicks whitelist: disabled\n"; }
|
||||||
|
else { $msg .= "Nicks whitelist: enabled\n"; }
|
||||||
|
|
||||||
|
if ($chanlist == 0) { $msg .= "Channel whitelist: disabled\n"; }
|
||||||
|
else { $msg .= "Channel whitelist: enabled\n"; }
|
||||||
|
|
||||||
|
if ($netlist == 0) { $msg .= "Networks whitelist: disabled"; }
|
||||||
|
else { $msg .= "Networks whitelist: enabled"; }
|
||||||
|
}
|
||||||
|
} elsif ($argstring eq 'show') {
|
||||||
|
$msg = '';
|
||||||
|
|
||||||
|
if (Irssi::settings_get_bool('nicklist_enable') == 0) {
|
||||||
|
$msg .= "Nick whitelist: disabled\n";
|
||||||
|
} else {
|
||||||
|
$msg .= "Nick whitelist: enabled\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg .= "Whitelisted nicks = " . join( ', ', loadlist('nicklist')) ."\n";
|
||||||
|
|
||||||
|
if (Irssi::settings_get_bool('chanlist_enable') == 0) {
|
||||||
|
$msg .= "Channel whitelist: disabled\n";
|
||||||
|
} else {
|
||||||
|
$msg .= "Channel whitelist: enabled\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg .= "Whitelisted channels = " . join( ', ', loadlist('chanlist')) . "\n";
|
||||||
|
|
||||||
|
if (Irssi::settings_get_bool('netlist_enable') == 0) {
|
||||||
|
$msg .= "Networks whitelist: disabled\n";
|
||||||
|
} else {
|
||||||
|
$msg .= "Networks whitelist: enabled\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg .= "Whitelisted networks = " . join( ', ', loadlist('netlist'));
|
||||||
|
} elsif ($argstring =~ /^enable /) {
|
||||||
|
if((split(/ +/, $argstring))[1] eq 'nick') {
|
||||||
|
Irssi::settings_set_bool('nicklist_enable', '1');
|
||||||
|
$msg = "Nick whitelist now enabled";
|
||||||
|
} elsif ((split(/ +/, $argstring))[1] eq 'chan') {
|
||||||
|
Irssi::settings_set_bool('chanlist_enable', '1');
|
||||||
|
$msg = "Channel whitelist now enabled";
|
||||||
|
} elsif ((split(/ +/, $argstring))[1] eq 'net') {
|
||||||
|
Irssi::settings_set_bool('netlist_enable', '1');
|
||||||
|
$msg = "Net whitelist now enabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
} elsif ($argstring =~ /^disable /) {
|
||||||
|
if((split(/ +/, $argstring))[1] eq 'nick') {
|
||||||
|
Irssi::settings_set_bool('nicklist_enable', '0');
|
||||||
|
$msg = "Nick whitelist now disabled";
|
||||||
|
} elsif ((split(/ +/, $argstring))[1] eq 'chan') {
|
||||||
|
Irssi::settings_set_bool('chanlist_enable', '0');
|
||||||
|
$msg = "Channel whitelist now disabled";
|
||||||
|
} elsif ((split(/ +/, $argstring))[1] eq 'net') {
|
||||||
|
Irssi::settings_set_bool('netlist_enable', '0');
|
||||||
|
$msg = "Net whitelist now disabled";
|
||||||
|
}
|
||||||
|
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
} elsif ($argstring =~ /^add /) {
|
||||||
|
my (undef, $entity, $who) = split(/ +/, $argstring, 3);
|
||||||
|
|
||||||
|
if($entity eq 'nick') {
|
||||||
|
my @nicks = uniq(loadlist('nicklist'), $who);
|
||||||
|
savelist('nicklist', @nicks);
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Nick whitelist now: %s", join(', ', loadlist('nicklist')));
|
||||||
|
} elsif ($entity eq 'chan') {
|
||||||
|
my @chans = uniq(loadlist('chanlist'), $who);
|
||||||
|
savelist('chanlist', @chans);
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Chan whitelist now: %s", join(', ', loadlist('chanlist')));
|
||||||
|
} elsif($entity eq 'net') {
|
||||||
|
my @nets = uniq(loadlist('netlist'), $who);
|
||||||
|
savelist('netlist', @nets);
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Net whitelist now: %s", join(', ', loadlist('netlist')));
|
||||||
|
} elsif ($entity eq 'this') {
|
||||||
|
if ($who eq 'net') {
|
||||||
|
if (defined($serverhref)) {
|
||||||
|
my @nets = uniq(loadlist('netlist'), $serverhref->{'chatnet'});
|
||||||
|
savelist('netlist', @nets);
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Net whitelist now: %s", join(', ', loadlist('netlist')));
|
||||||
|
} else {
|
||||||
|
$msg = 'Run this command on server or channel window.';
|
||||||
|
}
|
||||||
|
} elsif ($who eq 'chan') {
|
||||||
|
if (defined($channelhref)) {
|
||||||
|
my @chans = uniq(loadlist('chanlist'), $channelhref->{'name'});
|
||||||
|
savelist('chanlist', @chans);
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Chan whitelist now: %s", join(', ', loadlist('chanlist')));
|
||||||
|
} else {
|
||||||
|
$msg = 'You\'re not in a channel window.';
|
||||||
|
}
|
||||||
|
} elsif ($who eq 'nick') {
|
||||||
|
# looks like if you're chatting with person $channelhref->{'topic'} is not defined
|
||||||
|
if ((defined($channelhref)) and (! defined($channelhref->{'topic'}))) {
|
||||||
|
my @nicks = uniq(loadlist('nicklist'), $channelhref->{'name'});
|
||||||
|
savelist('nicklist', @nicks);
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Nick whitelist now: %s", join(', ', loadlist('nicklist')));
|
||||||
|
} else {
|
||||||
|
$msg = 'You\'re not chatting with person.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elsif ($argstring =~ /^del /) {
|
||||||
|
my (undef, $entity, $who) = split(/ +/, $argstring, 3);
|
||||||
|
|
||||||
|
if($entity eq 'nick') {
|
||||||
|
savelist( 'nicklist', map { $_ eq $who ? () : $_ } loadlist('nicklist'));
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Nick whitelist now: %s", join(', ', loadlist('nicklist')));
|
||||||
|
} elsif ($entity eq 'chan') {
|
||||||
|
savelist( 'chanlist', map { $_ eq $who ? () : $_; } loadlist('chanlist'));
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Chan whitelist now: %s", join(', ', loadlist('chanlist')));
|
||||||
|
} elsif ($entity eq 'net') {
|
||||||
|
savelist( 'netlist', map { $_ eq $who ? () : $_; } loadlist('netlist'));
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Net whitelist now: %s", join(', ', loadlist('netlist')));
|
||||||
|
} elsif ($entity eq 'this') {
|
||||||
|
if ($who eq 'net') {
|
||||||
|
if (defined($serverhref)) {
|
||||||
|
savelist( 'netlist', map { $_ eq $serverhref->{'chatnet'} ? () : $_; } loadlist('netlist'));
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Net whitelist now: %s", join(', ', loadlist('netlist')));
|
||||||
|
} else {
|
||||||
|
$msg = 'Run this command on server or channel window.';
|
||||||
|
}
|
||||||
|
} elsif ($who eq 'chan') {
|
||||||
|
if (defined($channelhref)) {
|
||||||
|
savelist( 'chanlist', map { $_ eq $channelhref->{'name'} ? () : $_; } loadlist('chanlist'));
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Chan whitelist now: %s", join(', ', loadlist('chanlist')));
|
||||||
|
} else {
|
||||||
|
$msg = 'You\'re not in a channel window.';
|
||||||
|
}
|
||||||
|
} elsif ($who eq 'nick') {
|
||||||
|
if ((defined($channelhref)) and (! defined($channelhref->{'topic'}))) {
|
||||||
|
savelist( 'nicklist', map { $_ eq $channelhref->{'name'} ? () : $_; } loadlist('nicklist'));
|
||||||
|
Irssi::signal_emit('setup changed');
|
||||||
|
$msg = sprintf("Nick whitelist now: %s", join(', ', loadlist('nicklist')));
|
||||||
|
} else {
|
||||||
|
$msg = 'You\'re not chatting with person.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$msg = $help;
|
||||||
|
}
|
||||||
|
|
||||||
|
Irssi::active_win()->print($msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub hookfn {
|
||||||
|
my ($server, $message, $nick, $nick_address, $chan) = @_;
|
||||||
|
my $nicklist_enable = Irssi::settings_get_bool('nicklist_enable');
|
||||||
|
my $chanlist_enable = Irssi::settings_get_bool('chanlist_enable');
|
||||||
|
my $netlist_enable = Irssi::settings_get_bool('netlist_enable');
|
||||||
|
my $flag = 1; # show notification
|
||||||
|
$flag = 0 if (($nicklist_enable != 1) or ($chanlist_enable != 1) or ($netlist_enable != 1));
|
||||||
|
|
||||||
|
if (($nicklist_enable != 0) and ($flag == 0)) {
|
||||||
|
my @nicklist = loadlist('nicklist');
|
||||||
|
|
||||||
|
foreach (@nicklist) {
|
||||||
|
next unless(defined($_));
|
||||||
|
next if($_ eq '');
|
||||||
|
|
||||||
|
if ($_ eq $nick) {
|
||||||
|
$flag = 1;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@nicklist = -1; undef @nicklist;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($chanlist_enable != 0) and ($flag == 0)) {
|
||||||
|
my @chanlist = loadlist('chanlist');
|
||||||
|
|
||||||
|
foreach (@chanlist) {
|
||||||
|
next unless(defined($_));
|
||||||
|
next if($_ eq '');
|
||||||
|
|
||||||
|
if ($_ eq $chan) {
|
||||||
|
$flag = 1;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@chanlist = -1; undef @chanlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (($netlist_enable != 0) and ($flag == 0)) {
|
||||||
|
my @netlist = loadlist('netlist');
|
||||||
|
|
||||||
|
foreach (@netlist) {
|
||||||
|
next unless(defined($_));
|
||||||
|
next if($_ eq '');
|
||||||
|
|
||||||
|
if ($_ eq $server){
|
||||||
|
$flag = 1;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@netlist = -1; undef @netlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($flag == 1) {
|
||||||
|
$active = 1;
|
||||||
|
$message = Irssi::strip_codes($message);
|
||||||
|
$message = encodestr($message);
|
||||||
|
$nick = Irssi::strip_codes($nick);
|
||||||
|
my $topic = sprintf("%s at %s says:\n", $nick, $chan);
|
||||||
|
|
||||||
|
# perl can create limited amount of threads, so if there are a lot of notifications
|
||||||
|
# we have to use infinite loop with sleep
|
||||||
|
my $caught = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
eval { threads->create(\¬ify, $topic, $message) or die; };
|
||||||
|
|
||||||
|
if ($@) {
|
||||||
|
$caught = 1;
|
||||||
|
sleep 1;
|
||||||
|
} else {
|
||||||
|
$caught = 0;
|
||||||
|
}
|
||||||
|
} while ( $caught == 1 );
|
||||||
|
|
||||||
|
if ($active == 1) {
|
||||||
|
# implement async action
|
||||||
|
$hook = Irssi::timeout_add(250, "timeraction", '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
undef $nicklist_enable; undef $chanlist_enable; undef $netlist_enable;
|
||||||
|
undef $flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub timeraction {
|
||||||
|
if (($active == 0) and (defined($hook))) {
|
||||||
|
Irssi::timeout_remove($hook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub encodestr {
|
||||||
|
my $str = shift;
|
||||||
|
$str = join('', map {
|
||||||
|
if ($_ eq '<') { $_ = '<'; }
|
||||||
|
elsif ($_ eq '>') { $_ = '>'; }
|
||||||
|
elsif ($_ eq '&') { $_ = '&'; }
|
||||||
|
elsif ($_ eq '"') { $_ = '"'}
|
||||||
|
else { $_ = $_; }
|
||||||
|
} split(//, $str));
|
||||||
|
|
||||||
|
return $str;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub loadlist($){
|
||||||
|
my $setting = shift;
|
||||||
|
my @values;
|
||||||
|
my $val = Irssi::settings_get_str($setting) or do {
|
||||||
|
Irssi::settings_set_str($setting, '');
|
||||||
|
undef $setting;
|
||||||
|
return @values; # empty array :)
|
||||||
|
};
|
||||||
|
|
||||||
|
@values = map { decode_base64($_); } split(/ /, $val);
|
||||||
|
undef $setting; undef $val;
|
||||||
|
return @values;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub savelist(@) {
|
||||||
|
my $setting = shift;
|
||||||
|
my @list = map { encode_base64($_, ''); } @_;
|
||||||
|
my $value = join(' ', @list);
|
||||||
|
Irssi::settings_set_str($setting, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub uniq(@) {
|
||||||
|
my %hash = map { $_ => 1 } @_;
|
||||||
|
return keys %hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
# vim: set noai ts=4 sw=4:
|
||||||
Reference in New Issue
Block a user