# NOTE: Based on code by Kevin Lenzo & Patrick Cole (c) 1997
#
-if (&IsParam("useStrict")) { use strict; }
+use strict;
-use vars qw($nickserv);
-$nickserv = 0;
+use vars qw(%floodjoin %nuh %dcc %cache %channels %param %mask
+ %chanconf %orig %ircPort %ircstats %last %netsplit);
+use vars qw($irc $nickserv $ident $conn $msgType $who $talkchannel
+ $addressed);
+use vars qw($notcount $nottime $notsize $msgcount $msgtime $msgsize
+ $pubcount $pubtime $pubsize);
+use vars qw($b_blue $ob);
+use vars qw(@joinchan @ircServers);
# static scalar variables.
$mask{ip} = '(\d+)\.(\d+)\.(\d+)\.(\d+)';
$mask{nick} = "[$isnick1]{1}[$isnick1$isnick2]*";
$mask{nuh} = '\S*!\S*\@\S*';
+$nickserv = 0;
+
sub ircloop {
my $error = 0;
my $lastrun = 0;
Ircname => $param{'ircName'},
);
$args{'LocalAddr'} = $param{'ircHost'} if ($param{'ircHost'});
+ $args{'Password'} = $param{'ircPasswd'} if ($param{'ircPasswd'});
$conn = $irc->newconn(%args);
if (!defined $conn) {
- &ERROR("irc: conn was not created!defined!!!");
+ &ERROR("internal: perl IRC connection object does not exist.");
return 1;
}
$conn->add_handler('nick', \&on_nick);
$conn->add_handler('quit', \&on_quit);
$conn->add_handler('notice', \&on_notice);
- $conn->add_handler('whoisuser', \&on_whoisuser);
+ $conn->add_handler('whoischannels', \&on_whoischannels);
+ $conn->add_handler('useronchannel', \&on_useronchannel);
+ $conn->add_handler('whois', \&on_whois);
$conn->add_handler('other', \&on_other);
$conn->add_global_handler('disconnect', \&on_disconnect);
$conn->add_global_handler([251,252,253,254,255], \&on_init);
### $conn->add_global_handler([251,252,253,254,255,302], \&on_init);
+ $conn->add_global_handler(303, \&on_ison); # notify.
$conn->add_global_handler(315, \&on_endofwho);
+ $conn->add_global_handler(422, \&on_endofwho); # nomotd.
$conn->add_global_handler(324, \&on_modeis);
$conn->add_global_handler(333, \&on_topicinfo);
$conn->add_global_handler(352, \&on_who);
$conn->add_global_handler(473, \&on_inviteonly);
$conn->add_global_handler(474, \&on_banned);
$conn->add_global_handler(475, \&on_badchankey);
+ $conn->add_global_handler(443, \&on_useronchan);
# end of handler stuff.
$msgsize = length $msg;
}
- if ($msgType =~ /private/i) { # hack.
- $conn->privmsg($nick, $msg);
-
- } else {
- &DEBUG("msg: msgType is unknown!");
- }
+ $conn->privmsg($nick, $msg);
}
}
return;
}
- my $rawout = "PRIVMSG $target :\001ACTION $txt\001";
- if (length $rawout > 510) {
+ if (length $txt > 480) {
&status("action: txt too long; truncating.");
-
- chop($rawout) while (length($rawout) > 510);
- $rawout .= "\001";
+ chop($txt) while (length $txt > 480);
}
&status("* $ident/$target $txt");
- rawout($rawout);
+ $conn->me($target, $txt);
}
# Usage: ¬ice(nick || chan, txt);
}
sub joinchan {
- my ($chankey) = @_;
- my $chan = lc $chankey;
-
- if ($chankey =~ s/^($mask{chan}),\S+/ /) {
- $chan = lc $1;
- }
+ my ($chan) = @_;
+ my $key = &getChanConf("chankey", $chan) || "";
- &status("joining $b_blue$chan$ob");
+ # forgot for about 2 years to implement channel keys when moving
+ # over to Net::IRC...
+ # hopefully validChan is right.
if (&validChan($chan)) {
&status("join: already on $chan");
} else {
- if (!$conn->join($chan)) {
- &DEBUG("joinchan: join failed. trying connect!");
- $conn->connect();
- }
+ &status("joining $b_blue$chan$ob");
+
+ return if ($conn->join($chan, $key));
+
+ &DEBUG("joinchan: join failed. trying connect!");
+ &clearIRCVars();
+ $conn->connect();
}
}
next if ($chan eq "");
$chan =~ tr/A-Z/a-z/; # lowercase.
+ if ($chan !~ /^$mask{chan}$/) {
+ &WARN("part: chan is invalid ($chan)");
+ next;
+ }
+
&status("parting $chan");
if (!&validChan($chan)) {
&WARN("part: not on $chan; doing anyway");
# next;
}
- rawout("PART $chan");
+ $conn->part($chan);
# deletion of $channels{chan} is done in &entryEvt().
}
}
&DEBUG("mode: MODE $chan $modes");
+ # should move to use Net::IRC's $conn->mode()... but too lazy.
rawout("MODE $chan $modes");
}
foreach $chan (@chans) {
if (!&IsNickInChan($nick,$chan)) {
- &status("Kick: $nick is not on $chan.") if (scalar @chans == 1);
+ &status("kick: $nick is not on $chan.") if (scalar @chans == 1);
next;
}
if (!exists $channels{$chan}{o}{$ident}) {
- &status("Kick: do not have ops on $chan :(");
+ &status("kick: do not have ops on $chan :(");
next;
}
&status("Kicking $nick from $chan.");
- if ($msg eq "") {
- &rawout("KICK $chan $nick");
- } else {
- &rawout("KICK $chan $nick :$msg");
- }
+ $conn->kick($chan, $nick, $msg);
}
}
foreach $chan (@chans) {
if (!exists $channels{$chan}{o}{$ident}) {
- &status("Ban: do not have ops on $chan :(");
+ &status("ban: do not have ops on $chan :(");
next;
}
if ($bad) {
&WARN("Nick: not going to try and get my nick back. [".
scalar(localtime). "]");
- return;
+# hrm... over time we lose track of our own nick.
+# return;
}
if ($nick =~ /^$mask{nick}$/) {
if (defined $ident) {
&status("nick: Changing nick to $nick (from $ident)");
+ # following shouldn't be here :(
+ $ident = $nick;
} else {
&DEBUG("first time nick change.");
$ident = $nick;
sub invite {
my($who, $chan) = @_;
- rawout("INVITE $who $chan");
-}
+ # todo: check if $who or $chan are invalid.
+ $conn->invite($who, $chan);
+}
##########
# Channel related functions...
# Usage: &joinNextChan();
sub joinNextChan {
if (scalar @joinchan) {
- $chan = shift @joinchan;
+ my $chan = shift @joinchan;
&joinchan($chan);
if (my $i = scalar @joinchan) {
my $rate = sprintf("%.1f", $delta / @c);
delete $cache{joinTime};
- &DEBUG("time taken to join all chans: $timestr; rate: $rate sec/join");
+ &status("time taken to join all chans: $timestr; rate: $rate sec/join");
}
# chanserv check: global channels, in case we missed one.
sub IsNickInAnyChan {
my ($nick) = @_;
+ my $chan;
foreach $chan (keys %channels) {
next unless (grep /^\Q$nick\E$/i, keys %{ $channels{$chan}{''} });
# Usage: &validChan($chan);
sub validChan {
+ # todo: use $c instead?
my ($chan) = @_;
+ if (!defined $chan or $chan =~ /^\s*$/) {
+ return 0;
+ }
+
if (lc $chan ne $chan) {
&WARN("validChan: lc chan != chan. ($chan); fixing.");
$chan =~ tr/A-Z/a-z/;
}
- if (exists $channels{$chan}) {
+ # it's possible that this check creates the hash if empty.
+ if (defined $channels{$chan} or exists $channels{$chan}) {
+ if ($chan =~ /^_?default$/) {
+# &WARN("validC: chan cannot be _default! returning 0!");
+ return 0;
+ }
+
return 1;
} else {
return 0;
}
sub clearIRCVars {
-# &DEBUG("clearIRCVars() called!");
+ &DEBUG("clearIRCVars() called!");
undef %channels;
undef %floodjoin;
sub closeDCC {
# &DEBUG("closeDCC called.");
+ my $type;
foreach $type (keys %dcc) {
next if ($type ne uc($type));
+ my $nick;
foreach $nick (keys %{ $dcc{$type} }) {
next unless (defined $nick);
&status("DCC CHAT: closing DCC $type to $nick.");
### Clean it up.
my $delete = 0;
+ my $time = time();
foreach $chan (keys %floodjoin) {
foreach $who (keys %{ $floodjoin{$chan} }) {
- my $time = time() - $floodjoin{$chan}{$who}{Time};
- next unless ($time > 10);
+ my $t = $floodjoin{$chan}{$who}{Time};
+ next unless (defined $t);
+
+ my $delta = $time - $t;
+ next unless ($delta > 10);
+
delete $floodjoin{$chan}{$who};
$delete++;
}
return &makeHostMask($nuh{$n});
} else {
$cache{on_who_Hack} = 1;
- &rawout("WHO $n");
+ $conn->who($n);
}
}