Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@wodim
Last active February 4, 2019 10:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wodim/9527266 to your computer and use it in GitHub Desktop.
Save wodim/9527266 to your computer and use it in GitHub Desktop.
Irssi script that implements a notify list using the WATCH command
use Irssi;
use strict;
use vars qw($VERSION %IRSSI);
# Changelog
# 0.9: initial release
# 0.91: show online/offline notifications in query windows if open
# 0.92: fix connection time in stopped_watching_host_last
# 0.93: fix removal of nicks from the notify list
# 0.94: reduced the max length of WATCH commands
# 0.95: disallows the use of /watch in networks not in watch_networks
# 0.96: added an option to beep when someone comes online
$VERSION = "0.96";
%IRSSI = (
authors => "wodim",
contact => 'wodim@vortigaunt.net',
name => "Watch-NG",
description => "Implements a notify list using the WATCH command",
license => "BSD",
url => "",
);
our $locked = 0;
our $extended = 0;
our @current_online;
our @current_offline;
sub is_locked {
($locked > (time - 5));
}
sub clean_setting {
my ($string) = @_;
$string =~ s/^\s+|\s+$//g;
$string =~ s/\s{2,}/ /g;
$string;
}
sub setting_add {
my ($setting, $params) = @_;
my $new_setting = Irssi::settings_get_str($setting);
foreach (my @parts = split(/ /, $params)) {
if ($new_setting !~ m/\Q\b$_\b/) {
$new_setting = "$new_setting $_";
}
}
Irssi::settings_set_str($setting, clean_setting($new_setting));
}
sub setting_del {
my ($setting, $params) = @_;
my $new_setting = Irssi::settings_get_str($setting);
foreach (my @parts = split(/ /, $params)) {
$new_setting =~ s/\b\Q$_\E\b//ig;
}
Irssi::settings_set_str($setting, clean_setting($new_setting));
}
sub command_watch {
my ($args) = @_;
my ($command, $params) = split(/\s+/, $args, 2);
my $server = Irssi::active_server();
if ($command =~ m/^enable$/i) {
$params = $server->{tag} if not $params;
setting_add("watch_networks", $params);
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "watch_enabled", $params);
}
if ($command =~ m/^disable$/i) {
$params = $server->{tag} if not $params;
setting_del("watch_networks", $params);
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "watch_disabled", $params);
}
if (Irssi::settings_get_str("watch_networks") !~ m/\b$server->{tag}\b/i) {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "watch_not_enabled", $server->{tag});
return;
}
if ($command =~ m/^add|del|delete|rem|remove$/i) {
return unless $params;
my $nicklen = int(Irssi::active_server()->isupport("NICKLEN"));
my @nicks = split(/\s+/, $params);
my $pre_nick;
if ($command =~ m/^add$/i) {
setting_add("watch_nicks", $params);
$pre_nick = "+";
} elsif ($command =~ m/^del|delete|rem|remove$/i) {
setting_del("watch_nicks", $params);
$pre_nick = "-";
}
my @commands = divider("QUOTE WATCH ", $pre_nick, $nicklen, @nicks);
foreach (@commands) {
Irssi::active_server()->command($_);
}
} elsif ($command =~ m/^help$/i) {
Irssi::print(<<"SCRIPTHELP_EOF", MSGLEVEL_CLIENTCRAP);
WATCH
WATCH LIST
WATCH ADD [nicks]
WATCH DEL [nicks]
WATCH ENABLE [network]
WATCH DISABLE [network]
A more detailed list of users is shown when using the LIST parameter, including the date of last connection.
SCRIPTHELP_EOF
} else {
return if is_locked() or ($command !~ m/^(list|)$/i);
undef @current_online;
undef @current_offline;
$locked = time;
$extended = ($command =~ m/^list$/i);
Irssi::active_server()->command("QUOTE WATCH L");
}
}
sub went_online {
my ($server, $data) = @_;
my ($me, $nick, $username, $host, $lastnick) = split(/ /, $data);
my $query_window = $server->query_find($nick);
if ($query_window) {
$query_window->printformat(MSGLEVEL_CLIENTNOTICE, "went_online", $nick, $username, $host);
} else {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "went_online", $nick, $username, $host);
}
if (Irssi::settings_get_bool("watch_beep")) {
Irssi::command("beep")
}
}
sub went_offline {
my ($server, $data) = @_;
my ($me, $nick, $username, $host, $lastnick) = split(/ /, $data);
my $query_window = $server->query_find($nick);
if ($query_window) {
$query_window->printformat(MSGLEVEL_CLIENTNOTICE, "went_offline", $nick, $username, $host);
} else {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "went_offline", $nick, $username, $host);
}
}
sub stopped_watching {
my ($server, $data) = @_;
my ($me, $nick, $username, $host, $lastnick) = split(/ /, $data);
if ($username eq "*" && $host eq "*") {
if ($lastnick eq "0") {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "stopped_watching", $nick);
} else {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "stopped_watching_last", $nick, scalar localtime($lastnick));
}
} else {
if ($lastnick eq "0") {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "stopped_watching_host", $nick, $username, $host);
} else {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "stopped_watching_host_last", $nick, $username, $host, scalar localtime($lastnick));
}
}
}
sub is_online {
my ($server, $data) = @_;
my ($me, $nick, $username, $host, $lastnick) = split(/ /, $data);
if (is_locked()) {
push @current_online, $data;
} else {
if ($lastnick eq "0") {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "is_online", $nick, $username, $host);
} else {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "is_online_last", $nick, $username, $host, scalar localtime($lastnick));
}
}
}
sub is_offline {
my ($server, $data) = @_;
my ($me, $nick, $username, $host, $lastnick) = split(/ /, $data);
if (is_locked()) {
push @current_offline, $data;
} else {
if ($lastnick eq "0") {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "is_offline", $nick, $username, $host);
} else {
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "is_offline_last", $nick, $username, $host, scalar localtime($lastnick));
}
}
}
sub end_of_list {
my ($server, $data) = @_;
if ($extended) {
foreach (@current_online) {
my ($me, $nick, $username, $host, $lastnick) = split(/ /, $_);
if ($lastnick) {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, "is_online_last", $nick, $username, $host, scalar localtime($lastnick));
} else {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, "is_online", $nick, $username, $host);
}
}
foreach (@current_offline) {
my ($me, $nick, $username, $host, $lastnick) = split(/ /, $_);
if ($lastnick) {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, "is_offline_last", $nick, $username, $host, scalar localtime($lastnick));
} else {
Irssi::printformat(MSGLEVEL_CLIENTCRAP, "is_offline", $nick, $username, $host);
}
}
} else {
my (@online_list, @offline_list);
foreach (@current_online) {
my ($me, $nick, $username, $host, $lastnick) = split(/ /, $_);
push @online_list, $nick;
}
foreach (@current_offline) {
my ($me, $nick, $username, $host, $lastnick) = split(/ /, $_);
push @offline_list, $nick;
}
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "watch_online", join(", ", @online_list));
Irssi::printformat(MSGLEVEL_CLIENTNOTICE, "watch_offline", join(", ", @offline_list));
}
$locked = 0;
}
sub watch_setup {
my ($server) = @_;
return unless (Irssi::settings_get_str("watch_networks") =~ m/\b$server->{tag}\b/i);
my $nicklen = int($server->isupport("NICKLEN"));
my @nicks = split(/\s+/, Irssi::settings_get_str("watch_nicks"));
my @commands = divider("QUOTE WATCH ", "+", $nicklen, @nicks);
foreach (@commands) {
$server->command($_);
}
}
sub divider {
my ($pre_line, $pre_nick, $nicklen, @nicks) = @_;
my @commands;
while (@nicks) {
my $line = $pre_line;
while (@nicks && length($line) < (450 - ($nicklen + 1 + length($pre_nick)))) {
my $nick = pop @nicks;
$line .= "$pre_nick$nick ";
}
push @commands, $line;
}
@commands;
}
Irssi::theme_register([
"is_online_last", 'Online: {nick $0} [$1@$2] (joined: $3)',
"is_offline_last", 'Offline: {nick $0} (last seen: $3)',
"is_online", 'Online: {nick $0} [$1@$2]',
"is_offline", 'Offline: {nick $0}',
"watch_online", 'Online: {hilight $0}',
"watch_offline", 'Offline: $0',
"went_online", '{nick $0} [$1@$2] has connected',
"went_offline", '{nick $0} [$1@$2] has disconnected',
"stopped_watching", '{nick $0} is no longer being watched',
"stopped_watching_host", '{nick $0} [$1@$2] is no longer being watched',
"stopped_watching_last", '{nick $0} is no longer being watched (joined or last seen: $1)',
"stopped_watching_host_last", '{nick $0} [$1@$2] is no longer being watched (joined or last seen: $3)',
"watch_not_enabled", 'WATCH is not enabled for $0. Use /WATCH ENABLE to enable it',
"watch_enabled", 'WATCH has been enabled for $0',
"watch_disabled", 'WATCH has been disabled for $0',
]);
Irssi::settings_add_str("watch", "watch_nicks", "");
Irssi::settings_add_str("watch", "watch_networks", "");
Irssi::settings_add_bool("watch", "watch_beep", 1);
Irssi::command_bind("watch", "command_watch");
Irssi::signal_add("event 600", "went_online");
Irssi::signal_add("event 601", "went_offline");
Irssi::signal_add("event 602", "stopped_watching");
Irssi::signal_add("event 604", "is_online");
Irssi::signal_add("event 605", "is_offline");
Irssi::signal_add("event 607", "end_of_list");
Irssi::signal_add_last("event connected", "watch_setup");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment