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