diff options
Diffstat (limited to 'scripts/keepnick.pl')
-rw-r--r-- | scripts/keepnick.pl | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/scripts/keepnick.pl b/scripts/keepnick.pl new file mode 100644 index 0000000..5eb40f2 --- /dev/null +++ b/scripts/keepnick.pl @@ -0,0 +1,387 @@ +# +# Copyright (C) 2001-2021 by Peder Stray <peder.stray@gmail.com> +# + +use strict; +use Irssi 20011118.1727; +use Irssi::Irc; + +use vars qw{$VERSION %IRSSI}; +($VERSION) = '$Revision: 1.19.1 $' =~ / (\d+(\.\d+)+) /; +%IRSSI = ( + name => 'keepnick', + authors => 'Peder Stray', + contact => 'peder.stray@gmail.com', + url => 'https://github.com/pstray/irssi-keepnick', + license => 'GPL', + description => 'Try to get your nick back when it becomes available.', + ); + +my(%keepnick); # nicks we want to keep +my(%getnick); # nicks we are currently waiting for +my(%inactive); # inactive chatnets +my(%manual); # manual nickchanges + +sub change_nick { + my($server,$nick) = @_; + $server->redirect_event('keepnick nick', 1, ":$nick", -1, undef, + { + "event nick" => "redir keepnick nick", + "" => "event empty", + }); + $server->send_raw("NICK :$nick"); +} + +sub check_nick { + my($server,$net,$nick); + + %getnick = (); # clear out any old entries + + for $net (keys %keepnick) { + next if $inactive{$net}; + $server = Irssi::server_find_chatnet($net); + next unless $server; + next if lc $server->{nick} eq lc $keepnick{$net}; + + $getnick{$net} = $keepnick{$net}; + } + + for $net (keys %getnick) { + $server = Irssi::server_find_chatnet($net); + next unless $server; + next unless ref($server) eq 'Irssi::Irc::Server'; # this only work on IRC + $nick = $getnick{$net}; + if (lc $server->{nick} eq lc $nick) { + delete $getnick{$net}; + next; + } + $server->redirect_event('keepnick ison', 1, '', -1, undef, + { "event 303" => "redir keepnick ison" }); + $server->send_raw("ISON :$nick"); + } +} + +sub load_nicks { + my($file) = Irssi::get_irssi_dir."/keepnick"; + my($count) = 0; + local(*CONF); + + %keepnick = (); + open CONF, "<", $file; + while (<CONF>) { + my($net,$nick) = split; + if ($net && $nick) { + $keepnick{lc $net} = $nick; + $count++; + } + } + close CONF; + + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_crap', + "Loaded $count nicks from $file"); +} + +sub save_nicks { + my($auto) = @_; + my($file) = Irssi::get_irssi_dir."/keepnick"; + my($count) = 0; + local(*CONF); + + return if $auto && !Irssi::settings_get_bool('keepnick_autosave'); + + open CONF, ">", $file; + for my $net (sort keys %keepnick) { + print CONF "$net\t$keepnick{$net}\n"; + $count++; + } + close CONF; + + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_crap', + "Saved $count nicks to $file") + unless $auto; +} + +sub server_printformat { + my($server,$level,$format,@params) = @_; + my($emitted) = 0; + for my $win (Irssi::windows) { + for my $item ($win->items) { + next unless ref $item; + if ($item->{server}{chatnet} eq $server->{chatnet}) { + $item->printformat($level,$format,@params); + $emitted++; + last; + } + } + } + $server->printformat(undef,$level,$format,@params) + unless $emitted; +} + +# if anyone changes their nick, check if we want their old one. +sub sig_message_nick { + my($server,$newnick,$oldnick) = @_; + my($chatnet) = lc $server->{chatnet}; + if (lc $oldnick eq lc $getnick{$chatnet}) { + change_nick($server, $getnick{$chatnet}); + } +} + +# if we change our nick, check it to see if we wanted it and if so +# remove it from the list. +sub sig_message_own_nick { + my($server,$newnick,$oldnick) = @_; + my($chatnet) = lc $server->{chatnet}; + if (lc $newnick eq lc $keepnick{$chatnet}) { + delete $getnick{$chatnet}; + if ($inactive{$chatnet}) { + delete $inactive{$chatnet}; + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_unhold', + $newnick, $chatnet); + } + } elsif (lc $oldnick eq lc $keepnick{$chatnet} && + lc $newnick eq lc $manual{$chatnet}) { + $inactive{$chatnet} = 1; + delete $getnick{$chatnet}; + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_hold', + $oldnick, $chatnet); + } +} + +sub sig_message_own_nick_block { + my($server,$new,$old,$addr) = @_; + Irssi::signal_stop(); + if (Irssi::settings_get_bool('keepnick_quiet')) { + Irssi::printformat(MSGLEVEL_NICKS | MSGLEVEL_NO_ACT, + 'keepnick_got_nick', $new, $server->{chatnet}); + } else { + server_printformat($server, MSGLEVEL_NICKS | MSGLEVEL_NO_ACT, + 'keepnick_got_nick', $new, $server->{chatnet}); + } +} + +# if anyone quits, check if we want their nick. +sub sig_message_quit { + my($server,$nick) = @_; + my($chatnet) = lc $server->{chatnet}; + if (lc $nick eq lc $getnick{$chatnet}) { + change_nick($server, $getnick{$chatnet}); + } +} + +sub sig_redir_keepnick_ison { + my($server,$text) = @_; + my $nick = $getnick{lc $server->{chatnet}}; + change_nick($server, $nick) + unless $text =~ /:\Q$nick\E\s?$/i; +} + +sub sig_redir_keepnick_nick { + my($server,$args,$nick,$addr) = @_; + Irssi::signal_add_first('message own_nick', 'sig_message_own_nick_block'); + Irssi::signal_emit('event nick', @_); + Irssi::signal_remove('message own_nick', 'sig_message_own_nick_block'); +} + +# main setup is reread, so let us do it too +sub sig_setup_reread { + load_nicks; +} + +# main config is saved, and so we should save too +sub sig_setup_save { + my($mainconf,$auto) = @_; + save_nicks($auto); +} + +# Usage: /KEEPNICK [-net <chatnet>] [<nick>] +sub cmd_keepnick { + my(@params) = split " ", shift; + my($server) = @_; + my($chatnet,$nick,@opts); + + # parse named parameters from the parameterlist + while (@params) { + my($param) = shift @params; + if ($param =~ /^-(chat|irc)?net$/i) { + $chatnet = shift @params; + } elsif ($param =~ /^-/) { + Irssi::print("Unknown parameter $param"); + } else { + push @opts, $param; + } + } + $nick = shift @opts; + + # check if the ircnet specified (if any) is valid, and if so get the + # server for it + if ($chatnet) { + my($cn) = Irssi::chatnet_find($chatnet); + unless ($cn) { + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_crap', + "Unknown chat network: $chatnet"); + return; + } + $chatnet = $cn->{name}; + $server = Irssi::server_find_chatnet($chatnet); + } + + # if we need a server, check if the one we got is connected. + unless ($server || ($nick && $chatnet)) { + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_crap', + "Not connected to server"); + return; + } + + # lets get the chatnet, and the nick we want + $chatnet ||= $server->{chatnet}; + $nick ||= $server->{nick}; + + # check that we really have a chatnet + unless ($chatnet) { + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_crap', + "Unable to find server network, maybe you forgot /server add before connecting?"); + return; + } + + if ($inactive{lc $chatnet}) { + delete $inactive{lc $chatnet}; + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_unhold', + $nick, $chatnet); + } + + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_add', $nick, + $chatnet); + + $keepnick{lc $chatnet} = $nick; + + save_nicks(1); + check_nick(); +} + +# Usage: /UNKEEPNICK [<chatnet>] +sub cmd_unkeepnick { + my($chatnet,$server) = @_; + + # check if the ircnet specified (if any) is valid, and if so get the + # server for it + if ($chatnet) { + my($cn) = Irssi::chatnet_find($chatnet); + unless ($cn) { + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_crap', + "Unknown chat network: $chatnet"); + return; + } + $chatnet = $cn->{name}; + } else { + $chatnet = $server->{chatnet}; + } + + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_remove', + $keepnick{lc $chatnet}, $chatnet); + + delete $keepnick{lc $chatnet}; + delete $getnick{lc $chatnet}; + + save_nicks(1); +} + +# Usage: /LISTNICK +sub cmd_listnick { + my(@nets) = sort keys %keepnick; + my $net; + if (@nets) { + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_list_header'); + for (@nets) { + $net = Irssi::chatnet_find($_); + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_list_line', + $keepnick{$_}, + $net ? $net->{name} : ">$_<", + $inactive{$_}?'inactive':'active'); + } + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_list_footer'); + } else { + Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'keepnick_list_empty'); + } +} + +sub cmd_nick { + my($data,$server) = @_; + my($nick) = split " ", $data; + return unless $server; + $manual{lc $server->{chatnet}} = $nick; +} + +Irssi::settings_add_bool('keepnick', 'keepnick_autosave', 1); +Irssi::settings_add_bool('keepnick', 'keepnick_quiet', 0); + +Irssi::theme_register( +[ + 'keepnick_crap', + '{line_start}{hilight Keepnick:} $0', + + 'keepnick_add', + '{line_start}{hilight Keepnick:} Now keeping {nick $0} on [$1]', + + 'keepnick_remove', + '{line_start}{hilight Keepnick:} Stopped trying to keep {nick $0} on [$1]', + + 'keepnick_hold', + '{line_start}{hilight Keepnick:} Nickkeeping deactivated on [$1]', + + 'keepnick_unhold', + '{line_start}{hilight Keepnick:} Nickkeeping reactivated on [$1]', + + 'keepnick_list_empty', + '{line_start}{hilight Keepnick:} No nicks in keep list', + + 'keepnick_list_header', + '', + + 'keepnick_list_line', + '{line_start}{hilight Keepnick:} Keeping {nick $0} in [$1] ($2)', + + 'keepnick_list_footer', + '', + + 'keepnick_got_nick', + '{hilight Keepnick:} Nickstealer left [$1], got {nick $0} back', + +]); + +Irssi::signal_add('message quit', 'sig_message_quit'); +Irssi::signal_add('message nick', 'sig_message_nick'); +Irssi::signal_add('message own_nick', 'sig_message_own_nick'); + +Irssi::signal_add('redir keepnick ison', 'sig_redir_keepnick_ison'); +Irssi::signal_add('redir keepnick nick', 'sig_redir_keepnick_nick'); + +Irssi::signal_add('setup saved', 'sig_setup_save'); +Irssi::signal_add('setup reread', 'sig_setup_reread'); + +Irssi::command_bind("keepnick", "cmd_keepnick"); +Irssi::command_bind("unkeepnick", "cmd_unkeepnick"); +Irssi::command_bind("listnick", "cmd_listnick"); +Irssi::command_bind("nick", "cmd_nick"); + +Irssi::timeout_add(12000, 'check_nick', ''); + +Irssi::Irc::Server::redirect_register('keepnick ison', 0, 0, + undef, + { + "event 303" => -1, + }, + undef ); + +Irssi::Irc::Server::redirect_register('keepnick nick', 0, 0, + undef, + { + "event nick" => 0, + "event 432" => -1, # ERR_ERRONEUSNICKNAME + "event 433" => -1, # ERR_NICKNAMEINUSE + "event 437" => -1, # ERR_UNAVAILRESOURCE + "event 484" => -1, # ERR_RESTRICTED + }, + undef ); + +load_nicks; |