if (&IsParam("useStrict")) { use strict; }
+use vars qw($nickserv);
+$nickserv = 0;
+
# static scalar variables.
$mask{ip} = '(\d+)\.(\d+)\.(\d+)\.(\d+)';
$mask{host} = '[\d\w\_\-\/]+\.[\.\d\w\_\-\/]+';
-$mask{chan} = '[\#\&\+]\S*';
+$mask{chan} = '[\#\&]\S*|_default';
my $isnick1 = 'a-zA-Z\[\]\{\}\_\`\^\|\\\\';
my $isnick2 = '0-9\-';
$mask{nick} = "[$isnick1]{1}[$isnick1$isnick2]*";
+$mask{nuh} = '\S*!\S*\@\S*';
sub ircloop {
my $error = 0;
my $lastrun = 0;
- while (1) {
+loop:;
+ while (my $host = shift @ircServers) {
# JUST IN CASE. irq was complaining about this.
if ($lastrun == time()) {
- &DEBUG("hrm... lastrun == time()");
+ &DEBUG("ircloop: hrm... lastrun == time()");
$error++;
sleep 10;
next;
}
- foreach (@ircServers) {
- if (!defined $_) {
- &DEBUG("ircloop: ircServers[x] = NULL.");
- $lastrun = time();
- next;
- }
- next unless (exists $ircPort{$_});
+ if (!defined $host) {
+ &DEBUG("ircloop: ircServers[x] = NULL.");
+ $lastrun = time();
+ next;
+ }
+ next unless (exists $ircPort{$host});
- my $retval = &irc($_, $ircPort{$_});
- next unless (defined $retval and $retval == 0);
- $error++;
- if ($error % 3 == 0 and $error != 0) {
- &ERROR("CANNOT connect to this server; next!");
- next;
- }
+ my $retval = &irc($host, $ircPort{$host});
+ &DEBUG("ircloop: after irc()");
- if ($error >= 3*3) {
- &ERROR("CANNOT connect to any irc server; stopping.");
- exit 1;
- }
+ next unless (defined $retval and $retval == 0);
+
+ $error++;
+
+ if ($error % 3 == 0 and $error != 0) {
+ &ERROR("CANNOT connect to this server; next!");
+ next;
+ }
+
+ if ($error >= 3*3) {
+ &ERROR("CANNOT connect to any irc server; stopping.");
+ exit 1;
}
}
+
+ &DEBUG("ircloop: end... going back.");
+ &loadIRCServers();
+ goto loop;
}
sub irc {
my $resolve = inet_ntoa($packed);
&status(" resolved to $resolve.");
+ ### warning in Sys/Hostname line 78???
+ ### caused inside Net::IRC?
}
$irc = new Net::IRC;
$conn->add_handler('cping', \&on_ping);
$conn->add_handler('crping', \&on_ping_reply);
$conn->add_handler('cversion', \&on_version);
-
+ $conn->add_handler('crversion', \&on_crversion);
$conn->add_handler('dcc_open', \&on_dcc_open);
$conn->add_handler('dcc_close', \&on_dcc_close);
$conn->add_handler('chat', \&on_chat);
$conn->add_global_handler(376, \&on_endofmotd); # on_connect.
$conn->add_global_handler(433, \&on_nick_taken);
$conn->add_global_handler(439, \&on_targettoofast);
+ # for proper joinnextChan behaviour
+ $conn->add_global_handler(471, \&on_chanfull);
+ $conn->add_global_handler(473, \&on_inviteonly);
+ $conn->add_global_handler(474, \&on_banned);
+ $conn->add_global_handler(475, \&on_badchankey);
+
# end of handler stuff.
$irc->start;
sub say {
my ($msg) = @_;
- if (!defined $msg or $msg eq $noreply) {
+ if (!defined $msg) {
$msg ||= "NULL";
- &DEBUG("say: msg == $msg.");
- return;
- }
-
- if ($msg eq $last{say} and length($msg) > 256) {
- &status("say: detected repeated message; skipping.");
+ &WARN("say: msg == $msg.");
return;
}
- $last{say} = $msg;
&status("</$talkchannel> $msg");
if (&whatInterface() =~ /IRC/) {
- $msg = "zero" if ($msg =~ /^0+$/);
+ $msg = "zero" if ($msg =~ /^0+$/);
+ my $t = time();
+
+ if ($t == $pubtime) {
+ $pubcount++;
+ $pubsize += length $msg;
+
+ if ( ($pubcount % 4) == 0 and $pubcount) {
+ sleep 1;
+ } elsif ($pubsize > 1500) {
+ sleep 1;
+ $pubsize -= 1500;
+ }
+
+ } else {
+ $pubcount = 0;
+ $pubtime = $t;
+ $pubsize = length $msg;
+ }
$conn->privmsg($talkchannel, $msg);
}
return;
}
- if (!defined $msg or $msg eq $noreply) {
+ if (!defined $msg) {
$msg ||= "NULL";
- &DEBUG("msg: msg == $msg.");
+ &WARN("msg: msg == $msg.");
return;
}
- if ($msg eq $last{msg} and length($msg) > 256) {
- &status("msg: detected repeated message; skipping.");
- return;
- }
- $last{msg} = $msg;
-
&status(">$nick< $msg");
- $conn->privmsg($nick, $msg) if (&whatInterface() =~ /IRC/);
+
+ if (&whatInterface() =~ /IRC/) {
+ my $t = time();
+
+ if ($t == $msgtime) {
+ $msgcount++;
+ $msgsize += length $msg;
+
+ if ( ($msgcount % 4) == 0 and $msgcount) {
+ sleep 1;
+ } elsif ($msgsize > 1000) {
+ sleep 1;
+ $msgsize -= 1000;
+ }
+
+ } else {
+ $msgcount = 0;
+ $msgtime = $t;
+ $msgsize = length $msg;
+ }
+
+ $conn->privmsg($nick, $msg);
+ }
}
# Usage: &action(nick || chan, txt);
sub action {
my ($target, $txt) = @_;
if (!defined $txt) {
- &DEBUG("action: txt == NULL.");
+ &WARN("action: txt == NULL.");
return;
}
rawout($rawout);
}
-# Usage: &action(nick || chan, txt);
-sub notice{
+# Usage: ¬ice(nick || chan, txt);
+sub notice {
my ($target, $txt) = @_;
if (!defined $txt) {
- &DEBUG("action: txt == NULL.");
+ &WARN("notice: txt == NULL.");
return;
}
&status("-$target- $txt");
+ my $t = time();
+
+ if ($t == $nottime) {
+ $notcount++;
+ $notsize += length $txt;
+
+ if ( ($notcount % 4) == 0 and $notcount) {
+ sleep 1;
+ } elsif ($notsize > 1500) {
+ sleep 1;
+ $notsize -= 1500;
+ }
+
+ } else {
+ $notcount = 0;
+ $nottime = $t;
+ $notsize = length $txt;
+ }
+
$conn->notice($target, $txt);
}
sub DCCBroadcast {
- my ($txt) = @_;
+ my ($txt,$flag) = @_;
+
+ ### FIXME: flag not supported yet.
- foreach (keys %{$dcc{'CHAT'}}) {
+ foreach (keys %{ $dcc{'CHAT'} }) {
$conn->privmsg($dcc{'CHAT'}{$_}, $txt);
}
}
&performReply(@_);
}
+sub pSReply {
+ &performStrictReply(@_);
+}
+
# Usage: &performStrictReply($reply);
sub performStrictReply {
my ($reply) = @_;
} elsif ($msgType eq 'public') {
&say($reply);
} elsif ($msgType eq 'chat') {
- &dccsay($who,$reply);
+ &dccsay(lc $who,$reply);
} else {
&ERROR("pSR: msgType invalid? ($msgType).");
}
-
- return '';
}
sub dccsay {
return '';
}
+ &status("=>$who<= $reply"); # dcc chat.
$conn->privmsg($dcc{'CHAT'}{$who}, $reply);
}
foreach $type (keys %dcc) {
&FIXME("dcc_close: $who");
- my @who = grep /^\Q$who\E$/i, keys %{$dcc{$type}};
+ my @who = grep /^\Q$who\E$/i, keys %{ $dcc{$type} };
next unless (scalar @who);
$who = $who[0];
}
if (&validChan($chan)) {
&status("join: already on $chan");
} else {
- $conn->join($chan);
+ if (!$conn->join($chan)) {
+ &DEBUG("joinchan: join failed. trying connect!");
+ $conn->connect();
+ }
}
}
return;
}
- &DEBUG("MODE $chan $modes");
+ &DEBUG("mode: MODE $chan $modes");
rawout("MODE $chan $modes");
}
my ($chan, @who) = @_;
my $os = "o" x scalar(@who);
- &mode($chan, "+$os ".@who);
+ &mode($chan, "+$os @who");
}
sub deop {
sub ban {
my ($mask,$chan) = @_;
- my (@chans) = ($chan eq "") ? (keys %channels) : lc($chan);
+ my (@chans) = ($chan =~ /^\*?$/) ? (keys %channels) : lc($chan);
+ my $ban = 0;
- if ($chan ne "" and &validChan($chan) == 0) {
+ if ($chan !~ /^\*?$/ and &validChan($chan) == 0) {
&ERROR("ban: invalid channel $chan.");
return;
}
- $nick =~ tr/A-Z/a-z/;
-
foreach $chan (@chans) {
- if (!&IsNickInChan($nick,$chan) and scalar @chans == 1) {
- &status("Ban: $nick is not on $chan.");
- next;
- }
-
if (!exists $channels{$chan}{o}{$ident}) {
&status("Ban: do not have ops on $chan :(");
next;
&status("Banning $mask from $chan.");
&rawout("MODE $chan +b $mask");
+ $ban++;
+ }
+
+ return $ban;
+}
+
+sub unban {
+ my ($mask,$chan) = @_;
+ my (@chans) = ($chan =~ /^\*?$/) ? (keys %channels) : lc($chan);
+ my $ban = 0;
+
+ &DEBUG("unban: mask = $mask, chan = @chans");
+
+ foreach $chan (@chans) {
+ if (!exists $channels{$chan}{o}{$ident}) {
+ &status("unBan: do not have ops on $chan :(");
+ next;
+ }
+
+ &status("Removed ban $mask from $chan.");
+ &rawout("MODE $chan -b $mask");
+ $ban++;
}
+
+ return $ban;
}
sub quit {
my ($nick) = @_;
if ($nick =~ /^$mask{nick}$/) {
+ &DEBUG("nick: Changing nick to $nick (from $ident)");
rawout("NICK ".$nick);
return 1;
}
+ &DEBUG("nick: failed... why oh why (nick => $nick)");
return 0;
}
# Usage: &joinNextChan();
sub joinNextChan {
+ &DEBUG("joinNextChan called.");
+
if (scalar @joinchan) {
- my $chan = shift @joinchan;
+ $chan = shift @joinchan;
&joinchan($chan);
if (my $i = scalar @joinchan) {
&status("joinNextChan: $i chans to join.");
}
- } else {
- return unless (&IsParam("chanServ_ops"));
- if (!$nickserv) {
- &DEBUG("jNC: nickserv/chanserv not up?");
- }
- my @chans = split(/[\s\t]+/, $param{'chanServ_ops'});
- foreach $chan (keys %channels) {
- next unless (grep /^$chan$/i, @chans);
+ # chanserv check: channel specific.
+ &chanServCheck($chan);
- if (!exists $channels{$chan}{'o'}{$ident}) {
- &status("ChanServ ==> Requesting ops for $chan.");
- &rawout("PRIVMSG ChanServ :OP $chan $ident");
- }
+ } else {
+ # chanserv check: global channels, in case we missed one.
+
+ foreach ( &ChanConfList("chanServ_ops") ) {
+ &chanServCheck($_);
}
}
}
my @array;
foreach (keys %channels) {
- next unless (grep /^\Q$nick\E$/i, keys %{$channels{$_}{''}});
+ next unless (grep /^\Q$nick\E$/i, keys %{ $channels{$_}{''} });
push(@array, $_);
}
return @array;
}
+# Usage: &GetNicksInChan($chan);
+sub GetNicksInChan {
+ my ($chan) = @_;
+ my @array;
+
+ return keys %{ $channels{$chan}{''} };
+}
+
sub IsNickInChan {
my ($nick,$chan) = @_;
return 0;
}
- if (grep /^\Q$nick\E$/i, keys %{$channels{$chan}{''}}) {
+ if (grep /^\Q$nick\E$/i, keys %{ $channels{$chan}{''} }) {
return 1;
} else {
foreach (keys %channels) {
next unless (/[A-Z]/);
- &DEBUG("hash channels contains mixed cased chan!!!");
+ &DEBUG("iNIC: hash channels contains mixed cased chan!!!");
}
return 0;
}
my ($nick) = @_;
foreach $chan (keys %channels) {
- next unless (grep /^\Q$nick\E$/i, keys %{$channels{$chan}{''}});
+ next unless (grep /^\Q$nick\E$/i, keys %{ $channels{$chan}{''} });
return 1;
}
return 0;
my ($mode,$chan);
foreach $chan (@chans) {
- foreach $mode (keys %{$channels{$chan}}) {
+ foreach $mode (keys %{ $channels{$chan} }) {
# use grep here?
next unless (exists $channels{$chan}{$mode}{$nick});
}
sub clearIRCVars {
- &DEBUG("clearIRCVars() called!");
- %channels = ();
- @joinchan = split /[\t\s]+/, $param{'join_channels'};
+### &DEBUG("clearIRCVars() called!");
+ undef %channels;
+ undef %floodjoin;
+
+ @joinchan = &getJoinChans();
}
-sub makeChanList {
- my ($str) = @_;
- my $inverse = 0;
+sub getJoinChans {
my @chans;
+ my @skip;
+
+ foreach (keys %chanconf) {
+ next if ($_ eq "_default");
- if ($str eq "ALL") {
- return(keys %channels);
- } elsif ($str =~ s/^ALL but //i) {
- @chans = keys %channels;
- foreach (split /[\s\t\,]+/, lc $str) {
- @chans = grep !/^$_$/, @chans;
+ my $val = $chanconf{$_}{autojoin};
+ my $skip = 0;
+
+ if (defined $val) {
+ $skip++ if ($val eq "0");
+ } else {
+ $skip++;
}
- } else {
- foreach (split /[\s\t\,]+/, lc $str) {
- next unless (&validChan($_));
- push(@chans, $_);
+
+ if ($skip) {
+ push(@skip, $_);
+ next;
}
+
+ push(@chans, $_);
+ }
+
+ if (scalar @skip) {
+ &status("gJC: channels not auto-joining: @skip");
+ } else {
+ &status("gJC: auto-joining all chans.");
}
- @chans;
+ return @chans;
}
sub closeDCC {
- &DEBUG("closeDCC called.");
+### &DEBUG("closeDCC called.");
foreach $type (keys %dcc) {
next if ($type ne uc($type));
- foreach (keys %{$dcc{$type}}) {
- &DEBUG("closing DCC $type to $_ (FIXME).");
- $dcc{$type}{$_}->close();
+ foreach $nick (keys %{ $dcc{$type} }) {
+ next unless (defined $nick);
+ &DEBUG("closing DCC $type to $nick (FIXME).");
+ next unless (defined $dcc{$type}{$nick});
+
+ my $ref = $dcc{$type}{$nick};
+ &DEBUG("ref => $ref");
+
+# $dcc{$type}{$nick}->close();
}
}
}
sub joinfloodCheck {
my($who,$chan,$userhost) = @_;
- return unless (&IsParam("joinfloodCheck"));
+ return unless (&IsChanConf("joinfloodCheck"));
if (exists $netsplit{lc $who}) { # netsplit join.
- &DEBUG("jfC: $who was in netsnipe; not checking.");
+ &DEBUG("joinfloodCheck: $who was in netsplit; not checking.");
}
if (exists $floodjoin{$chan}{$who}{Time}) {
my $c = $_;
my $count = scalar keys %{ $floodjoin{$c} };
next unless ($count > 5);
- &DEBUG("count => $count");
+ &DEBUG("joinflood: count => $count");
my $time;
foreach (keys %{ $floodjoin{$c} }) {
$time += $floodjoin{$c}{$_}{Time};
}
- &DEBUG("time => $time");
+ &DEBUG("joinflood: time => $time");
$time /= $count;
- &DEBUG("new time => $time");
+ &DEBUG("joinflood: new time => $time");
}
### Clean it up.
}
}
- &DEBUG("jfC: $delete deleted.") if ($delete);
+ &DEBUG("joinfloodCheck: $delete deleted.") if ($delete);
+}
+
+sub getHostMask {
+ my($n) = @_;
+
+ &FIXME("getHostMask...");
}
1;