summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--config-default/commands.xml66
-rwxr-xr-xmeta.pl7
-rw-r--r--modules/classes.pl40
-rw-r--r--modules/event.pl57
-rw-r--r--modules/inspect.pl15
-rw-r--r--modules/log.pl4
-rw-r--r--modules/mysql.pl8
-rw-r--r--modules/services.pl10
-rw-r--r--modules/util.pl5
-rw-r--r--modules/xml.pl7
11 files changed, 195 insertions, 26 deletions
diff --git a/.gitignore b/.gitignore
index 7b17a3f..2a08b2c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
/config
/config-main
/config-backup
+/actionlogs
+HTTP_ACCESS*
*.stor
*~
diff --git a/config-default/commands.xml b/config-default/commands.xml
index 9cffe50..83a583f 100644
--- a/config-default/commands.xml
+++ b/config-default/commands.xml
@@ -68,11 +68,23 @@
$upstr = $upstr . int($up/1) . 's';
$up = $up % 1;
}
+ my ($tx, $rx);
+ if ($conn->{_tx}/1024 > 1024) {
+ $tx = sprintf("%.2fMB", $conn->{_tx}/(1024*1024));
+ } else {
+ $tx = sprintf("%.2fKB", $conn->{_tx}/1024);
+ }
+ if ($conn->{_rx}/1024 > 1024) {
+ $rx = sprintf("%.2fMB", $conn->{_rx}/(1024*1024));
+ } else {
+ $rx = sprintf("%.2fKB", $conn->{_rx}/1024);
+ }
$conn->privmsg($event->replyto, "This bot has been running for " . $upstr .
", is tracking " . (scalar (keys %::sn)) . " nicks" .
" across " . (scalar (keys %::sc)) . " tracked channels." .
" It is using " . $size . "KB of RAM" .
- " and has used " . $cputime . " of CPU time.");
+ ", has used $cputime of CPU time" .
+ ", has sent $tx of data, and received $rx of data.");
]]>
</command>
<command cmd="^;mship (\S+)$" flag="s">
@@ -462,6 +474,11 @@
$conn->quit($1);
]]>
</command>
+ <command cmd="^;exit ?(.*)" flag="a">
+ <![CDATA[
+ $conn->quit($1);
+ ]]>
+ </command>
<command cmd="^;ev (.*)" flag="d">
<![CDATA[
eval $1; warn $@ if $@;
@@ -561,7 +578,7 @@
my $txtz = "[\x02$tgt\x02] - $event->{nick} wants op attention";
if ((time-$::sc{$tgt}{users}{lc $event->{nick}}{jointime}) > 90) {
# return; #they've been on the channel for less than 90 seconds, probably nuisance botspam
- $txtz = $txtz . " ($msg) " . $hilite;
+ $txtz = "$txtz ($msg) $hilite !att-$tgt-opalert";
}
my @tgts = ASM::Util->getAlert($tgt, 'opalert', 'msgs');
ASM::Util->sendLongMsg($conn, \@tgts, $txtz);
@@ -586,7 +603,7 @@
else {
my @tgts = ASM::Util->getAlert($tgt, 'opalert', 'msgs');
foreach my $chan (@tgts) {
- $conn->privmsg($chan, $event->{nick} . " tried to use the ops trigger but is restricted from doing so.");
+ $conn->privmsg($chan, $event->{nick} . " tried to use the ops trigger for $tgt but is restricted from doing so.");
}
}
]]>
@@ -594,9 +611,23 @@
<command cmd="^;blacklist (.*)" flag="o">
<![CDATA[
my $str = lc $1;
- push(@::string_blacklist, $str);
- "$str\n" >> io 'string_blacklist.txt';
- $conn->privmsg($event->replyto, "$str blacklisted");
+# push(@::string_blacklist, $str);
+# "$str\n" >> io 'string_blacklist.txt';
+ use String::CRC32;
+ my $id = sprintf("%08x", crc32($str));
+ $::blacklist->{string}->{$id} = { "content" => $str, "setby" => $event->nick };
+ ASM::XML->writeBlacklist();
+ $conn->privmsg($event->replyto, "$str blacklisted with id $id, please use ;blreason $id reasonGoesHere to set a reason");
+ ]]>
+ </command>
+ <command cmd="^;unblacklist ([0-9a-f]+)$" flag="o">
+ <![CDATA[
+ my $id = $1;
+ if (defined($::blacklist->{string}->{$id})) {
+ delete $::blacklist->{string}->{$id};
+ $conn->privmsg($event->replyto, "blacklist id $id removed");
+ ASM::XML->writeBlacklist();
+ } else { $conn->privmsg($event->replyto, "invalid id"); }
]]>
</command>
<command cmd="^;plugin (\S+) (\S+) (.*)" flag="p">
@@ -618,4 +649,27 @@
}
]]>
</command>
+ <command cmd="^;sync (\S+)" flag="a">
+ <![CDATA[
+ my $chan = $1;
+ $conn->sl("MODE $chan bq");
+ $conn->sl("MODE $chan");
+ $conn->sl("WHO $chan %tcnuhra,314");
+ ]]>
+ </command>
+ <command cmd="^;ping$">
+ <![CDATA[
+ $conn->privmsg($event->replyto, "pong");
+ ]]>
+ </command>
+ <command cmd="^;blreason ([0-9a-f]+) (.*)" flag="o">
+ <![CDATA[
+ my $id = $1; my $reason = $2;
+ if (defined($::blacklist->{string}->{$id})) {
+ $::blacklist->{string}->{$id}->{reason} = $reason;
+ $conn->privmsg($event->replyto, "Reason set");
+ ASM::XML->writeBlacklist();
+ } else { $conn->privmsg($event->replyto, "ID is invalid"); }
+ ]]>
+ </command>
</commands>
diff --git a/meta.pl b/meta.pl
index aa38fc4..356b6a1 100755
--- a/meta.pl
+++ b/meta.pl
@@ -15,6 +15,7 @@ use POSIX qw(strftime);
use Term::ANSIColor qw(:constants);
use File::Monitor;
use feature qw(say);
+use HTTP::Async;
$Data::Dumper::Useqq=1;
@@ -28,12 +29,13 @@ $::cset = '';
$::pacealerts = 1;
$::settingschanged = 0;
%::wordlist = ();
+%::httpRequests = ();
## debug variables. 0 to turn off debugging, else set it to a Term::ANSIColor constant.
%::debugx = (
"dnsbl" => 0,
"pingpong" => 0, #BLUE,
- "services" => YELLOW,
+ "snotice" => YELLOW,
"sync" => CYAN,
"chanstate" => MAGENTA,
"restrictions" => BLUE,
@@ -87,6 +89,7 @@ sub init {
mkdir($::settings->{log}->{dir});
$::log = ASM::Log->new($::settings->{log});
$::pass = $::settings->{pass} if $::pass eq '';
+ $::async = HTTP::Async->new();
$host = ${$::settings->{server}}[rand @{$::settings->{server}}];
ASM::Util->dprint( "Connecting to $host", "startup");
$irc->debug($::debug);
@@ -132,7 +135,7 @@ sub init {
$::wordlist{lc $item} = 1;
}
$::fm = File::Monitor->new();
- foreach my $file ("channels", "commands", "dnsbl", "mysql", "restrictions", "rules", "settings", "users") {
+ foreach my $file ("channels", "commands", "dnsbl", "mysql", "restrictions", "rules", "settings", "users", "blacklist") {
$::fm->watch("./" . $::cset . '/' . $file . ".xml");
}
$::fm->watch("string_blacklist.txt");
diff --git a/modules/classes.pl b/modules/classes.pl
index 4fbfb94..5cafdbd 100644
--- a/modules/classes.pl
+++ b/modules/classes.pl
@@ -14,6 +14,7 @@ sub new
my $self = {};
my $tbl = {
"strbl" => \&strbl,
+ "strblnew" => \&strblnew,
"dnsbl" => \&dnsbl,
"floodqueue" => \&floodqueue,
"floodqueue2" => \&floodqueue2,
@@ -34,7 +35,8 @@ sub new
"joinmsgquit" => \&joinmsgquit,
"garbagemeter" => \&garbagemeter,
"cyclebotnet" => \&cyclebotnet,
- "banevade" => \&banevade
+ "banevade" => \&banevade,
+ "urlcrunch" => \&urlcrunch
};
$self->{ftbl} = $tbl;
bless($self);
@@ -76,6 +78,20 @@ sub joinmsgquit
return 1;
}
+sub urlcrunch
+{
+ my ($chk, $id, $event, $chan, $response) = @_;
+ return 0 unless defined($response);
+ return 0 unless ref($response);
+ return 0 unless defined($response->{_previous});
+ return 0 unless defined($response->{_previous}->{_headers});
+ return 0 unless defined($response->{_previous}->{_headers}->{location});
+ if ($response->{_previous}->{_headers}->{location} =~ /$chk->{content}/i) {
+ return 1;
+ }
+ return 0;
+}
+
sub check
{
my $self = shift;
@@ -367,6 +383,23 @@ sub strbl {
return 0;
}
+sub strblnew {
+ my ($chk, $xid, $event, $chan) = @_;
+ my $match = lc $event->{args}->[0];
+ foreach my $id (keys %{$::blacklist->{string}}) {
+ my $line = lc $::blacklist->{string}->{$id}->{content};
+ my $idx = index $match, $line;
+ if ( $idx != -1 ) {
+ my $setby = $::blacklist->{string}->{$id}->{setby};
+ $setby = substr($setby, 0, 1) . "\x02\x02" . substr($setby, 1);
+ return defined($::blacklist->{string}->{$id}->{reason}) ?
+ "id $id added by $setby because $::blacklist->{string}->{$id}->{reason}" :
+ "id $id added by $setby for no reason";
+ }
+ }
+ return 0;
+}
+
sub nick {
my ($chk, $id, $event, $chan) = @_;
if ( lc $event->{nick} eq lc $chk->{content} ) {
@@ -407,6 +440,11 @@ sub nuhg {
return 0;
}
+sub invite {
+ my ( $chk, $id, $event, $chan) = @_;
+ return 1;
+}
+
my $sfc = 0;
sub flood_add
diff --git a/modules/event.pl b/modules/event.pl
index 3c41df4..d3e3fa5 100644
--- a/modules/event.pl
+++ b/modules/event.pl
@@ -7,6 +7,7 @@ use Text::LevenshteinXS qw(distance);
use IO::All;
use POSIX qw(strftime);
use Regexp::Wildcards;
+use HTTP::Request;
sub cs {
my ($chan) = @_;
@@ -71,6 +72,8 @@ sub new
$conn->add_handler('statsdebug', \&on_statsdebug);
$conn->add_handler('endofstats', \&on_endofstats);
$conn->add_handler('channelurlis', \&on_channelurlis);
+ $conn->add_handler('480', \&on_jointhrottled);
+ $conn->add_handler('invite', \&blah); # This doesn't need to be fancy; I just need it to go through inspect
bless($self);
return $self;
}
@@ -79,6 +82,16 @@ my $clearstatsp = 1;
my %statsp = ();
my %oldstatsp = ();
+sub on_jointhrottled
+{
+ my ($conn, $event) = @_;
+ my $chan = $event->{args}->[1];
+ ASM::Util->dprint("$event->{nick}: $chan: $event->{args}->[2]", 'snotice');
+ if ($event->{args}->[2] =~ /throttle exceeded, try again later/) {
+ $conn->schedule(5, sub { $conn->join($chan); });
+ }
+}
+
sub on_statsdebug
{
my ($conn, $event) = @_;
@@ -222,7 +235,7 @@ sub on_connect {
$conn->sl("MODE $event->{args}->[0] +Q-i");
if (lc $event->{args}->[0] ne lc $::settings->{nick}) {
ASM::Util->dprint('Attempting to regain my main nick', 'startup');
- $conn->privmsg( 'NickServ', "regain $::settings->{nick} $::settings->{pass}" );
+ $conn->privmsg( 'NickServ@services.', "regain $::settings->{nick} $::settings->{pass}" );
}
$conn->sl('CAP REQ :extended-join multi-prefix account-notify'); #god help you if you try to use this bot off freenode
}
@@ -325,10 +338,38 @@ sub on_public
$::sc{lc $event->{to}->[0]}{users}{lc $event->{nick}}{msgtime} = time;
$::log->logg( $event );
$::db->logg( $event );
+# if ($event->{args}->[0] =~ /(https?:\/\/bitly.com\/\w+)|(https?:\/\/bit.ly\/\w+)|(https?:\/\/j.mp\/\w+)/i) {
+# my $reqid = $::async->add( HTTP::Request->new( GET => $1 ) );
+# $::httpRequests{$reqid} = $event;
+# my ($response, $id) = $::async->wait_for_next_response( 1 );
+# if (defined($response)) {
+# on_httpResponse($conn, $id, $response);
+# }
+# else { $conn->schedule( 1, sub { checkHTTP($conn); } ); }
+# }
$::inspector->inspect( $conn, $event );
$::commander->command( $conn, $event );
}
+sub checkHTTP
+{
+ my ($conn) = @_;
+ my ($response, $id) = $::async->next_response();
+ if (defined ($response)) {
+ on_httpResponse($conn, $id, $response);
+ }
+ $conn->schedule( 1, sub { checkHTTP($conn); } );
+}
+
+sub on_httpResponse
+{
+ my ($conn, $id, $response) = @_;
+ my $event = $::httpRequests{$id};
+ delete $::httpRequests{$id};
+ $::inspector->inspect( $conn, $event, $response );
+}
+# if ($response->{_previous}->{_headers}->{location} =~ /^https?:\/\/bitly.com\/a\/warning/)
+
sub on_notice
{
my ($conn, $event) = @_;
@@ -778,11 +819,23 @@ sub on_whoxover
my $size = `ps -p $$ h -o size`;
my $cputime = `ps -p $$ h -o time`;
chomp $size; chomp $cputime;
+ my ($tx, $rx);
+ if ($conn->{_tx}/1024 > 1024) {
+ $tx = sprintf("%.2fMB", $conn->{_tx}/(1024*1024));
+ } else {
+ $tx = sprintf("%.2fKB", $conn->{_tx}/1024);
+ }
+ if ($conn->{_rx}/1024 > 1024) {
+ $rx = sprintf("%.2fMB", $conn->{_rx}/(1024*1024));
+ } else {
+ $rx = sprintf("%.2fKB", $conn->{_rx}/1024);
+ }
$conn->privmsg($::settings->{masterchan}, "Finished syncing after " . (time - $::starttime) . " seconds. " .
"I'm tracking " . (scalar (keys %::sn)) . " nicks" .
" across " . (scalar (keys %::sc)) . " tracked channels." .
" I'm using " . $size . "KB of RAM" .
- " and have used " . $cputime . " of CPU time.");
+ ", have used " . $cputime . " of CPU time" .
+ ", have sent $tx of data, and received $rx of data.");
my %x = ();
foreach my $c (@{$::settings->{autojoins}}) { $x{$c} = 1; }
foreach my $cx (keys %::sc) { delete $x{$cx}; }
diff --git a/modules/inspect.pl b/modules/inspect.pl
index 3b72a3a..f5914cb 100644
--- a/modules/inspect.pl
+++ b/modules/inspect.pl
@@ -17,7 +17,7 @@ sub new
}
sub inspect {
- our ($self, $conn, $event) = @_;
+ our ($self, $conn, $event, $response) = @_;
my (%aonx, %dct, $rev, $chan, $id);
%aonx=(); %dct=(); $chan=""; $id="";
my (@dnsbl, @uniq);
@@ -43,7 +43,14 @@ sub inspect {
foreach $id (keys %aonx) {
next unless ( grep { $event->{type} eq $_ } split(/[,:; ]+/, $aonx{$id}{type}) );
next if ($aonx{$id}{class} eq 'dnsbl') && ($event->{host} =~ /(fastwebnet\.it|fastres\.net)$/); #this is a bad hack
- $xresult = $::classes->check($aonx{$id}{class}, $aonx{$id}, $id, $event, $chan, $rev); # this is another bad hack done for dnsbl-related stuff
+ if (defined($response)) {
+ print Dumper($response);
+ if ($aonx{$id}{class} ne 'urlcrunch') { next; } #don't run our regular checks if this is being called from a URL checking function
+ else { $xresult = $::classes->check($aonx{$id}{class}, $aonx{$id}, $id, $event, $chan, $response); }
+ }
+ else {
+ $xresult = $::classes->check($aonx{$id}{class}, $aonx{$id}, $id, $event, $chan, $rev); # this is another bad hack done for dnsbl-related stuff
+ }
next unless (defined($xresult)) && ($xresult ne 0);
ASM::Util->dprint(Dumper($xresult), 'inspector');
$dct{$id} = $aonx{$id};
@@ -81,10 +88,10 @@ sub inspect {
) {
my @tgts = ASM::Util->getAlert($chan, $dct{$id}{risk}, 'msgs');
ASM::Util->sendLongMsg($conn, \@tgts, $txtz);
+ $conn->schedule(45, sub { delete($::ignored{$chan})}) unless defined($::ignored{$chan});
$::ignored{$chan} = $::RISKS{$dct{$id}{risk}};
- $conn->schedule(45, sub { delete($::ignored{$chan})});
}
- $::log->incident($chan, "$chan: $dct{$id}{risk} risk: $event->{nick} - $nicereason\n");
+# $::log->incident($chan, "$chan: $dct{$id}{risk} risk: $event->{nick} - $nicereason\n");
delete $dct{$id}{xresult};
}
}
diff --git a/modules/log.pl b/modules/log.pl
index fe92159..72e0972 100644
--- a/modules/log.pl
+++ b/modules/log.pl
@@ -63,6 +63,10 @@ sub logg
if (substr($chan, 0, 1) eq '@') {
$chan = substr($chan, 1);
}
+ if ($chan eq '*') {
+ ASM::Util->dprint("$event->{nick}: $event->{args}->[0]", 'snotice');
+ next;
+ }
my $path = ">>$cfg->{dir}${chan}/${chan}" . strftime($cfg->{filefmt}, @time);
$_ = '';
$_ = "<$event->{nick}> $event->{args}->[0]" if $event->{type} eq 'public';
diff --git a/modules/mysql.pl b/modules/mysql.pl
index 4ff4441..85e0c6f 100644
--- a/modules/mysql.pl
+++ b/modules/mysql.pl
@@ -196,10 +196,10 @@ sub logg
$string = 'INSERT INTO `quit` (nick, user, host, geco, ip, account, content1) VALUES (' .
$dbh->quote($event->{nick}) . ',' . $dbh->quote($event->{user}) . ',' .
$dbh->quote($event->{host}) . ',' . $dbh->quote($::sn{lc $event->{nick}}->{gecos}) . ',';
- my $ip = ASM::Util->getNickIP(lc $event->{nick});
+ my $ip = ASM::Util->getNickIP(lc $event->{nick}, $event->{host});
if (defined($ip)) { $ip = $dbh->quote($ip); } else { $ip = 'NULL'; }
my $account = $::sn{lc $event->{nick}}->{account};
- if (($account eq '0') or ($account eq '*')) {
+ if (!defined($account) or ($account eq '0') or ($account eq '*')) {
$account = 'NULL';
} else {
$account = $dbh->quote($account);
@@ -213,10 +213,10 @@ sub logg
$dbh->quote($event->{to}->[0]) . ',' .
$dbh->quote($event->{nick}) . ',' . $dbh->quote($event->{user}) . ',' .
$dbh->quote($event->{host}) . ',' . $dbh->quote($::sn{lc $event->{nick}}->{gecos}) . ',';
- my $ip = ASM::Util->getNickIP(lc $event->{nick});
+ my $ip = ASM::Util->getNickIP(lc $event->{nick}, $event->{host});
if (defined($ip)) { $ip = $dbh->quote($ip); } else { $ip = 'NULL'; }
my $account = $::sn{lc $event->{nick}}->{account};
- if (($account eq '0') or ($account eq '*')) {
+ if (!defined($account) or ($account eq '0') or ($account eq '*')) {
$account = 'NULL';
} else {
$account = $dbh->quote($account);
diff --git a/modules/services.pl b/modules/services.pl
index 4783d2b..528901d 100644
--- a/modules/services.pl
+++ b/modules/services.pl
@@ -17,10 +17,10 @@ sub doServices {
my $i = 1;
if ($event->{from} eq 'NickServ!NickServ@services.')
{
- ASM::Util->dprint("NickServ: $event->{args}->[0]", 'services');
+ ASM::Util->dprint("NickServ: $event->{args}->[0]", 'snotice');
if ( $event->{args}->[0] =~ /^This nickname is registered/ )
{
- $conn->privmsg( 'NickServ', "identify $::settings->{nick} $::settings->{pass}" );
+ $conn->privmsg( 'NickServ@services.', "identify $::settings->{nick} $::settings->{pass}" );
}
elsif ( $event->{args}->[0] =~ /^You are now identified/ )
{
@@ -41,12 +41,12 @@ sub doServices {
}
elsif ($event->{args}->[0] =~ /has been (killed|released)/ )
{
- ASM::Util->dprint('Got kill/release successful from NickServ!', 'services');
+# ASM::Util->dprint('Got kill/release successful from NickServ!', 'snotice');
$conn->nick( $::settings->{nick} );
}
elsif ($event->{args}->[0] =~ /has been regained/ )
{
- ASM::Util->dprint('Got regain successful from nickserv!', 'services');
+# ASM::Util->dprint('Got regain successful from nickserv!', 'snotice');
}
elsif ($event->{args}->[0] =~ /Password Incorrect/ )
{
@@ -58,7 +58,7 @@ sub doServices {
if ( $event->{args}->[0] =~ /^\[#/ ) {
return;
}
- ASM::Util->dprint('ChanServ: '. Dumper($event->{args}->[0]), 'services');
+ ASM::Util->dprint("ChanServ: $event->{args}->[0]", 'snotice');
if ( $event->{args}->[0] =~ /^All.*bans matching.*have been cleared on(.*)/)
{
$conn->join($1);
diff --git a/modules/util.pl b/modules/util.pl
index 35a66ae..375d2e5 100644
--- a/modules/util.pl
+++ b/modules/util.pl
@@ -5,6 +5,7 @@ use warnings;
use strict;
use Term::ANSIColor qw (:constants);
use Socket qw( inet_aton inet_ntoa );
+use Data::Dumper;
%::RISKS =
(
@@ -225,13 +226,13 @@ sub getHostIP
sub getNickIP
{
- my ($module, $nick) = @_;
+ my ($module, $nick, $host) = @_;
$nick = lc $nick;
return unless defined($::sn{$nick});
if (defined($::sn{$nick}{ip})) {
return $::sn{$nick}{ip};
}
- my $host = $::sn{$nick}{host};
+ $host = $::sn{$nick}{host} if (!defined($host));
my $ip = getHostIP(undef, $host);
if (defined($ip)) {
$::sn{$nick}{ip} = $ip;
diff --git a/modules/xml.pl b/modules/xml.pl
index 551dc3f..a3c6e85 100644
--- a/modules/xml.pl
+++ b/modules/xml.pl
@@ -20,6 +20,7 @@ sub readXML {
$::dnsbl = $::xs1->XMLin( "$p/dnsbl.xml", ForceArray => []);
$::rules = $::xs1->XMLin( "$p/rules.xml", ForceArray => []);
$::restrictions = $::xs1->XMLin( "$p/restrictions.xml", ForceArray => ['host', 'nick', 'account']);
+ $::blacklist = $::xs1->XMLin( "$p/blacklist.xml", ForceArray => 'string');
}
sub writeXML {
@@ -27,6 +28,7 @@ sub writeXML {
writeChannels();
writeUsers();
writeRestrictions();
+ writeBlacklist();
# $::xs1->XMLout($::commands, RootName => 'commands', KeyAttr => ['id']) > io("$::cset/commands.xml");
}
@@ -52,4 +54,9 @@ sub writeRestrictions {
GroupTags => { hosts => "host", nicks => "nick", accounts => "account"}) > io("$::cset/restrictions.xml");
}
+sub writeBlacklist {
+ $::settingschanged=1;
+ $::xs1->XMLout($::blacklist, RootName => 'blacklist', KeyAttr => ['id']) > io("$::cset/blacklist.xml");
+}
+
return 1;