Last active
March 28, 2018 19:08
-
-
Save jnovack/3714183 to your computer and use it in GitHub Desktop.
pushover.pl - Sends irssi notifications to Pushover
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use strict; | |
use warnings; | |
# {{{ DOCUMENTATION | |
##### | |
# A lot of code borrowed from the prowlnotify.pl script at | |
# http://www.denis.lemire.name/2009/07/07/prowl-irssi-hack/ | |
# and pushovernotify.pl (Daniel Johansson <[email protected]>) | |
# and http://www.geekfarm.org/wu/muse/scripts/growl-notify.txt | |
# | |
# https://gist.github.com/3714183 | |
# | |
# }}} | |
use Irssi; | |
use Irssi::Irc; | |
use vars qw($VERSION %IRSSI %config); | |
use HTTP::Request; | |
use LWP::UserAgent; | |
use JSON; | |
$VERSION = '0.3.1'; | |
%IRSSI = ( | |
authors => 'Justin J. Novack', | |
contact => '[email protected]', | |
name => 'pushover', | |
description => 'Send a Pushover notification', | |
license => 'GPLv2', | |
url => 'http://www.ozmonet.com' | |
); | |
# Awful updating hack - Remember to increase this number on each revision! | |
# This counts the number of gist revisions and compares to current version. | |
Irssi::settings_add_str($IRSSI{'name'}, 'pushover_gist', '6'); | |
# Generics | |
$config{away_level} = 0; | |
$config{awayreason} = 'Auto-away'; | |
$config{clientcount} = 0; | |
# Keep last message to not repeat it. | |
my $lastnick = ""; | |
my $lasttext = ""; | |
# {{{ PUBLIC FUNCTIONS | |
# {{{ message(text) | |
sub message | |
{ | |
my $text = shift; | |
Irssi::print('%b>> %B'.$IRSSI{'name'}."%n :: $text"); | |
} | |
# }}} | |
# {{{ error(text) | |
sub error | |
{ | |
my $text = shift; | |
error("%y[%YWARNING%y]%n :: $text"); | |
} | |
# }}} | |
# {{{ warning(text) | |
sub warning | |
{ | |
my $text = shift; | |
message("%y[%YWARNING%y]%n :: $text"); | |
} | |
# }}} | |
# {{{ debug(text) | |
sub debug | |
{ | |
my $text = shift; | |
return unless Irssi::settings_get_bool('pushover_debug'); | |
message("%w[%WDEBUG%w]%n :: $text"); | |
} | |
# }}} | |
# {{{ send_pushover(title, message) | |
sub send_pushover | |
{ | |
my ($title, $message) = @_; | |
my $api_usr = Irssi::settings_get_str('pushover_api_usr'); | |
my $api_app = Irssi::settings_get_str('pushover_api_app'); | |
if (!$api_usr || !$api_app) { | |
error('Notification not sent. » Missing pushover user or api key(s).'); | |
return; | |
} | |
my $response = LWP::UserAgent->new()->post( | |
'https://api.pushover.net/1/messages.json', | |
[ | |
token => $api_app, | |
user => $api_usr, | |
title => $title, | |
message => $message, | |
] | |
); | |
#my $response = $ua->request($req); | |
if ($response->is_success) { | |
debug("Notification successfully posted. » $message"); | |
} elsif ($response->code == 429) { | |
warning('Notification not permitted. » Application is over API limit.'); | |
} elsif ($response->code == 400) { | |
warning('Notification not posted. » Incorrect user or application key.'); | |
debug($response->content); | |
} else { | |
warning('Notification not posted. » ('.$response->code.') '.$response->decoded_content); | |
} | |
} | |
# }}} | |
# {{{ client_connect() | |
sub client_connect | |
{ | |
my (@servers) = Irssi::servers; | |
$config{clientcount}++; | |
debug('Client connected.'); | |
# setback | |
foreach my $server (@servers) { | |
# if you're away on that server send yourself back | |
if ($server->{usermode_away} == 1) { | |
$server->send_raw('AWAY :'); | |
} | |
} | |
} | |
# }}} | |
# {{{ client_disconnect() | |
sub client_disconnect | |
{ | |
my (@servers) = Irssi::servers; | |
debug('Client disconnected.'); | |
$config{clientcount}-- unless $config{clientcount} == 0; | |
# setaway | |
if ($config{clientcount} <= $config{away_level}) { | |
# we have the away_level of clients connected or less. | |
foreach my $server (@servers) { | |
if ($server->{usermode_away} == '0') { | |
# we are not away on this server. set the autoaway reason | |
$server->send_raw( | |
'AWAY :' . $config{awayreason} | |
); | |
} | |
} | |
} | |
} | |
# }}} | |
# {{{ msg_pub(server, data, nick, mask, target) | |
sub msg_pub | |
{ | |
my ($server, $data, $nick, $mask, $target) = @_; | |
my $safeNick = quotemeta($server->{nick}); | |
$data = _strip_formatting($data); | |
if ($server->{usermode_away} == '1' && $data =~ /$safeNick/i) { | |
debug('User is away?' . $server->{usermode_away}); | |
unless ( _supress_duplicates( $nick, $data) ) { | |
debug("Public Message » (".$server->{tag}.") $target : <$nick> $data"); | |
send_pushover($target,"<$nick> $data"); | |
} | |
} | |
} | |
# }}} | |
# {{{ msg_pri(server, data, nick, address) | |
sub msg_pri | |
{ | |
my ($server, $data, $nick, $address) = @_; | |
$data = _strip_formatting($data); | |
if ($server->{usermode_away} == '1') { | |
debug('User is away?' . $server->{usermode_away}); | |
unless ( _supress_duplicates( $nick, $data) ) { | |
debug("Private Message » (".$server->{tag}.") <$nick> $data"); | |
send_pushover($nick, $data); | |
} | |
} | |
} | |
# }}} | |
# {{{ msg_hi(dest, text, stripped) | |
sub msg_hi | |
{ | |
my ($dest, $text, $stripped) = @_; | |
my $target = ""; | |
my $hilights = Irssi::settings_get_bool('pushover_hilight'); | |
if (($dest->{level} & (MSGLEVEL_HILIGHT|MSGLEVEL_MSGS)) | |
&& ($dest->{level} & MSGLEVEL_NOHILIGHT) == 0 | |
&& $hilights) | |
{ | |
# Pull nick and text from $stripped | |
$stripped =~ m|^\<(.*?)\>\s+(.*)$|; | |
my ( $nick, $text ) = ( $1, $2 ); | |
if ($dest->{level} & MSGLEVEL_PUBLIC) { | |
$target = $dest->{target}; | |
} | |
return undef unless ( $nick && $text ); | |
unless ( _supress_duplicates( _strip_nick($nick), $text) ) { | |
debug("Highlight » $target <$nick> $text"); | |
send_pushover($target, "<$nick> $text"); | |
} | |
} | |
} | |
# }}} | |
# {{{ cmd_pushover(data, server, witem) | |
sub cmd_pushover | |
{ | |
my ($data, $server, $witem) = @_; | |
my ($op, $var1) = split " ", $data; | |
$op = lc $op; | |
if (!$op) { | |
message(" %9/pushover test%n - Sends a test message to pushover."); | |
message(" %9/pushover debug 0%n - Turns debugging off."); | |
message(" %9/pushover debug 1%n - Turns debugging on. (default)"); | |
message(" %9/pushover exact 0%n - Suppress repeat notifications from the same user."); | |
message(" %9/pushover exact 1%n - Only suppress exact duplicate messages. (default)"); | |
message(" %9/pushover hilight 0%n - Turns off hilight notifications. (default)"); | |
message(" %9/pushover hilight 1%n - Turns on hilight notifications."); | |
} elsif ($op eq "test") { | |
debug("A message is being sent to pushover, please confirm receipt."); | |
send_pushover("Testing", "It works! Yay!"); | |
} elsif ($op eq "debug" && $var1 == "0") { | |
Irssi::settings_set_bool('pushover_debug', 0); | |
message('Debugging has been turned %9OFF%n'); | |
} elsif ($op eq "debug" && $var1 == "1") { | |
Irssi::settings_set_bool('pushover_debug', 1); | |
message('Debugging has been turned %9ON%n'); | |
} elsif ($op eq "exact" && $var1 == "0") { | |
Irssi::settings_set_bool('pushover_exact', 0); | |
message('Duplicate checking is %9user%n based. If the last message sent was from the same user, it will be suppressed.'); | |
} elsif ($op eq "exact" && $var1 == "1") { | |
Irssi::settings_set_bool('pushover_exact', 1); | |
message('Duplicate checking is %9user+text%n based. Messages are only suppressed if they are exactly the same.'); | |
} elsif ($op eq "hilight" && $var1 == "0") { | |
Irssi::settings_set_bool('pushover_hilight', 0); | |
message('Sending Pushover notifications for hilights is %9OFF%n.'); | |
} elsif ($op eq "hilight" && $var1 == "1") { | |
Irssi::settings_set_bool('pushover_hilight', 1); | |
message('Sending Pushover notifications for hilights is %9ON%n.'); | |
} elsif ($op eq "last") { | |
message("\$lastnick was: $lastnick"); | |
message("\$lasttext was: $lasttext"); | |
} | |
} | |
# }}} | |
# }}} | |
# {{{ main() | |
Irssi::settings_add_str($IRSSI{'name'}, 'pushover_api_app', ''); | |
Irssi::settings_add_str($IRSSI{'name'}, 'pushover_api_usr', ''); | |
Irssi::settings_add_bool($IRSSI{'name'}, 'pushover_debug', 1); | |
Irssi::settings_add_bool($IRSSI{'name'}, 'pushover_exact', 1); | |
Irssi::settings_add_bool($IRSSI{'name'}, 'pushover_hilight', 0); | |
Irssi::signal_add_last('proxy client connected', 'client_connect'); | |
Irssi::signal_add_last('proxy client disconnected', 'client_disconnect'); | |
Irssi::signal_add_last('message public', 'msg_pub'); | |
Irssi::signal_add_last('message private', 'msg_pri'); | |
Irssi::signal_add_last("print text", "msg_hi"); | |
Irssi::command_bind('pushover',\&cmd_pushover); | |
Irssi::print('%G>>%n '.$IRSSI{name}.'%n v'.$VERSION.' loaded.'); | |
if (!Irssi::settings_get_str('pushover_api_usr')) { | |
warning('user api key is not set, set it with %9/set pushover_api_usr apikey'); | |
} | |
if (!Irssi::settings_get_str('pushover_api_app')) { | |
warning('app api key is not set, set it with %9/set pushover_api_app apikey'); | |
} | |
message('Type %9/pushover%n for help.'); | |
if (Irssi::settings_get_bool('pushover_debug') == "1") { | |
debug(' Debugging is on, type %9/pushover debug 0%n to turn off'); | |
} | |
if (Irssi::settings_get_bool('pushover_exact') == "1") { | |
message('Duplicate checking is %9user+text%n based. Messages are only suppressed if they are exactly the same.'); | |
} else { | |
message('Duplicate checking is %9user%n based. If the last message sent was from the same user, it will be suppressed.'); | |
} | |
if (Irssi::settings_get_bool('pushover_hilight') == "1") { | |
message('Sending Pushover notifications for hilights is %9ON%n.'); | |
} else { | |
message('Sending Pushover notifications for hilights is %9OFF%n.'); | |
} | |
### Check for Update | |
# This is an extremely AWFUL way to check for updates. | |
# Counts the revisions at github and compares to hardcoded value. | |
# | |
my $response = LWP::UserAgent->new()->get('https://api.github.com/gists/3714183'); | |
my $decoded_json = decode_json( $response->decoded_content ); | |
if (Irssi::settings_get_str('pushover_gist') != $#{$decoded_json->{history}}+1) { | |
warning('You are not up to date! Please download the newest version from %9https://gist.github.com/3714183%n'); | |
} | |
# }}} | |
# {{{ PRIVATE | |
# {{{ _supress_duplicates(nick, text) | |
# | |
# Store the last several messages. If we get a duplicate message, | |
# then avoid sending multiple pages. Duplicates occur when a message | |
# matches more than one message, e.g. a public message in a monitored | |
# channel that contains a hilighted word. | |
# | |
sub _supress_duplicates | |
{ | |
my ( $nick, $text ) = @_; | |
# Check both nick and text for matches only if pushover_exact is set | |
if ( Irssi::settings_get_bool('pushover_exact') eq "1" && | |
$lastnick && $nick eq $lastnick && | |
$lasttext && $text eq $lasttext | |
) | |
{ | |
# debug("supressed_duplicates(exact)"); | |
return 1; | |
} | |
# Otherwise, check just nick is set | |
elsif ( $lastnick && $nick eq $lastnick ) | |
{ | |
# debug("supressed_duplicates(loose)"); | |
return 1; | |
} | |
# debug("\$lastnick : $lastnick || \$nick : $nick"); | |
# debug("\$lasttext : $lasttext || \$text : $text"); | |
$lastnick = $nick; | |
$lasttext = $text; | |
# no match | |
return undef; | |
} | |
# }}} | |
# {{{ _strip_nick(nick) | |
# | |
# Strips the prepended spaces and modes from the nickname. The | |
# nick can contain modes, spaces or other characters if the | |
# hilight function adds formatting. This removes it so a dup | |
# message can be properly filtered out. | |
# | |
sub _strip_nick | |
{ | |
my ($nick) = shift; | |
$nick =~ tr/[^a-zA-Z0-9\-\_\[\]\{\}\|\`\^]+//cd; | |
return $nick; | |
} | |
# }}} | |
# {{{ _strip_formatting(msg) | |
# | |
# Strips formatting from the message so it can be cleanly | |
# debugged or sent to the client. | |
# | |
sub _strip_formatting | |
{ | |
my ($msg) = shift; | |
$msg =~ s/\x03[0-9]{0,2}(,[0-9]{1,2})?//g; | |
$msg =~ s/[^\x20-\xFF]//g; | |
$msg =~ s/\xa0/ /g; | |
return $msg; | |
} | |
# }}}}}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is there a way to specify some kind of delay before a notification is sent? For example, if I'm in my irssi session, talking with someone, I wouldn't want notifications to be sent at that point.