1# 2# $Id: nickident.pl 1736 2007-02-01 14:13:24Z cb $ 3# 4# NickServ interface 5# Original code by Sami Haahtinen / ZaNaGa 6# Protected channel support added by David McNett <nugget@slacker.com> 7# Heavily patched by Christoph Berg <cb@df7cb.de> 8# 9 10use strict; 11use vars qw($VERSION %IRSSI); 12 13$VERSION = '20070201'; 14%IRSSI = ( 15 authors => 'Sami Haahtinen, Christoph Berg', 16 name => 'nickident', 17 description => 'identify to nickserv', 18 url => 'http://cvsweb.oftc.net/svn/oftc-tools/trunk/user/irssi/', 19 license => 'public domain', 20); 21 22my $name = "nickident"; 23my $nickserv_passfile = glob "~/.irssi/nickserv.users"; 24my $nickserv_chanfile = glob "~/.irssi/nickserv.channels"; 25my @users = (); 26my @chans = (); 27my %nickservs = ( 28 openprojects => [ 'NickServ', 'NickServ@services.' ], 29 sourceirc => [ 'NickServ', 'services@sourceirc.net' ], 30 cuckoonet => [ 'NickServ', 'services@irc.cuckoo.com' ], 31 slashnet => [ 'NickServ', 'services@services.slashnet.org' ], 32 roxnet => [ 'NickServ', 'services@ircsystems.net' ], 33 oftc => [ 'NickServ', 'services@services.oftc.net' ], 34 techno => [ 'NickServ', 'services@campus-sbg.at' ], 35 euirc => [ 'NickServ', 'anope@services.eu-irc.net' ], 36 cacert => [ 'NickServ', 'services@wireless' ], 37); 38 39use Irssi; 40use Irssi::Irc; 41 42sub join_channels { 43 my ($server) = @_; 44 my $current_ircnet = $server->{'tag'}; 45 46 #Irssi::print("$name: Joining channels for $current_ircnet"); 47 foreach $_ (@chans) { 48 my ($channel, $ircnet) = split(/:/); 49 if ($current_ircnet =~ /^$ircnet$/i) { 50 #Irssi::print("$name: Joining $channel"); 51 #$server->send_message("ChanServ", "UNBAN $channel", "-nick"); 52 #sleep 1; 53 Irssi::Server::channels_join($server, $channel, 0); 54 } 55 } 56} 57 58sub get_nickpass { 59 my ($current_nick, $current_ircnet) = @_; 60 61 foreach $_ (@users) { 62 my ($nick, $ircnet, $password) = split(/:/); 63 if ($current_nick =~ /^$nick$/i and $current_ircnet =~ /^$ircnet$/i) { 64 return $password; 65 } 66 } 67 return 0; 68} 69 70sub got_nickserv_msg { 71 my ($nick, $server, $text) = @_; 72 my $password; 73 74 if ($password = get_nickpass($server->{'nick'}, $server->{'tag'})) { 75 # The below is for OPN style.. i need to figure out a way to 76 # make this portable 77 if ($text =~ /This nickname is owned by someone else/i) { 78 Irssi::print("$name: Got authrequest from $nick/" . $server->{'tag'}); 79 $server->send_message("nickserv", "IDENTIFY $password", "-nick"); 80 Irssi::signal_stop(); 81 } elsif ($text =~ /^This nickname is registered and protected\. If it is your/) { 82 Irssi::print("$name: Got authrequest from $nick/" . $server->{'tag'}); 83 $server->send_message("nickserv", "IDENTIFY $password", "-nick"); 84 Irssi::signal_stop(); 85 # testnet: 86 # is a registered nickname and you are not on its access list 87 # authenticate yourself to services ^Bnow^B 88 } elsif ($text =~ /^This nick is registered\. Please choose another\.|is a registered nickname and you are not on its access list|authenticate yourself to services/) { 89 Irssi::print("$name: Got authrequest from $nick/" . $server->{'tag'}); 90 $server->send_message("nickserv", "IDENTIFY $password", "-nick"); 91 Irssi::signal_stop(); 92 } elsif ($text =~ /nick, type.+msg NickServ IDENTIFY.+password.+Otherwise,|please choose a different nick./i) { 93 Irssi::signal_stop(); 94 } elsif ($text =~ /Password accepted - you are now recognized./ || 95 $text =~ /Wow, you managed to remember your password. That's a miracle by your usual standard./ || 96 $text =~ /You are sucessfully identified as/ ) { 97 Irssi::print("$name: Got a positive response from $nick/" . $server->{'tag'}); 98 join_channels($server); 99 Irssi::signal_stop(); 100 } 101 } 102} 103 104sub event_nickserv_message { 105 my ($server, $data, $nick, $address) = @_; 106 my ($target, $text) = $data =~ /^(\S*)\s:(.*)/; 107 108 foreach my $key (keys %nickservs) { 109 if ( ($nickservs{$key}->[0] =~ /^$nick$/i) 110 and ($nickservs{$key}->[1] =~ /^$address$/i) ) { 111 got_nickserv_msg($nick, $server, $text) 112 } 113 } 114} 115 116sub cmd_nickident { 117 my ($data, $server, $witem) = @_; 118 if (my $password = get_nickpass($server->{'nick'}, $server->{'tag'})) { 119 $server->send_message("nickserv", "IDENTIFY $password", "-nick"); 120 } else { 121 Irssi::print("$name: No password for $server->{'nick'}/$server->{'tag'} found"); 122 } 123} 124 125sub create_users { 126 Irssi::print("$name: Creating basic userfile in $nickserv_passfile. please edit it and run /nickserv_read"); 127 if(!(open NICKUSERS, ">$nickserv_passfile")) { 128 Irssi::print("$name: Unable to create file $nickserv_passfile"); 129 } 130 131 print NICKUSERS "# This file should contain all your protected nicks\n"; 132 print NICKUSERS "# with the corresponding ircnet tag and password.\n"; 133 print NICKUSERS "#\n"; 134 print NICKUSERS "# Nick and IrcNet Tag are case insensitive\n"; 135 print NICKUSERS "#\n"; 136 print NICKUSERS "# Nick IrcNet Tag Password\n"; 137 print NICKUSERS "# -------- ---------- --------\n"; 138 139 close NICKUSERS; 140 chmod 0600, $nickserv_passfile; 141} 142 143sub create_chans { 144 Irssi::print("$name: Creating basic channelfile in $nickserv_chanfile. please edit it and run /nickserv_read"); 145 if(!(open NICKCHANS, ">$nickserv_chanfile")) { 146 Irssi::print("$name: Unable to create file $nickserv_chanfile"); 147 } 148 149 print NICKCHANS "# This file should contain a list of all channels\n"; 150 print NICKCHANS "# which you don't want to join until after you've\n"; 151 print NICKCHANS "# successfully identified with NickServ. This is\n"; 152 print NICKCHANS "# useful for channels which are access-controlled.\n"; 153 print NICKCHANS "#\n"; 154 print NICKCHANS "# Channel IrcNet Tag\n"; 155 print NICKCHANS "# -------- ----------\n"; 156 157 close NICKCHANS; 158 chmod 0600, $nickserv_chanfile; 159} 160 161sub read_users { 162 my $count = 0; 163 @users = (); 164 165 if (!(open NICKUSERS, "<$nickserv_passfile")) { 166 create_users; 167 }; 168 169 # first we test the file with mask 066 (we don't actually care if the 170 # file is executable by others.. what could they do with it =) 171 my $mode = (stat($nickserv_passfile))[2]; 172 if ($mode & 066) { 173 Irssi::print("$name: Your password file should be mode 0600. Go fix it!"); 174 Irssi::print("$name: Use command: chmod 0600 $nickserv_passfile"); 175 } 176 177 # apparently Irssi resets $/, so we set it here. 178 $/ = "\n"; 179 while( my $line = <NICKUSERS>) { 180 if ($line =~ /^\s*([^#]\S+)\s+(\S+)\s+(\S+)/) { 181 push @users, "$1:$2:$3"; 182 $count++; 183 } 184 } 185 Irssi::print("$name: Found $count accounts"); 186 187 close NICKUSERS; 188} 189 190sub read_chans { 191 my $count = 0; 192 @chans = (); 193 194 if (!(open NICKCHANS, "<$nickserv_chanfile")) { 195 create_chans; 196 }; 197 198 # first we test the file with mask 066 (we don't actually care if the 199 # file is executable by others.. what could they do with it =) 200 my $mode = (stat($nickserv_chanfile))[2]; 201 if ($mode & 066) { 202 Irssi::print("$name: Your channels file should be mode 0600. Go fix it!"); 203 Irssi::print("$name: Use command: chmod 0600 $nickserv_chanfile"); 204 } 205 206 # apparently Irssi resets $/, so we set it here. 207 $/ = "\n"; 208 while( my $line = <NICKCHANS>) { 209 next if /^#\s/; 210 if ($line =~ /^\s*(\S+)\s+(\S+)\s*$/) { 211 push @chans, "$1:$2"; 212 $count++; 213 } 214 } 215 Irssi::print("$name: Found $count channels"); 216 217 close NICKCHANS; 218} 219 220sub read_files { 221 read_users(); 222 read_chans(); 223} 224 225 226Irssi::signal_add("event notice", "event_nickserv_message"); 227Irssi::command_bind('nickident_read', 'read_files'); 228Irssi::command_bind('nickident', 'cmd_nickident'); 229 230read_files(); 231