summaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorLibravatarWilliam Heimbigner <william.heimbigner@gmail.com>2012-08-16 06:58:14 +0000
committerLibravatarWilliam Heimbigner <william.heimbigner@gmail.com>2012-08-16 06:58:14 +0000
commit6cf8963cfc8dc562f7ec8f3c5d538f05a0e7a0be (patch)
tree2f54ae3d0f4a21ae6026e401832fffd053b79da6 /modules
parent5154f3cac3c3537d94b748c365dce88f3805b4a7 (diff)
Disabled message-sending-throttling
Added a command to view uptime/cpu/ram usage statistics The hilight/dehilight commands can accept a comma-separated list of nicks The exempt command is now deprecated A restriction-system has been added to replace the old exemption system, and also includes additional restrictions that can be added, such as "don't let this account use !ops" Added a plugin command, so other bots can have ASM generate alerts Updated users and flags Updated channel hilights Replaced code that shows up in several places to split a long privmsg into two parts with a utility function Added a detection class for fuzzy-matching against a nick blacklist Fixed some major memory leaks, the bot stays stable around 30MB rather than shooting up to 65MB after a couple of days The bot now uses nickserv REGAIN instead of ghost/release/nick Added channel modes, ban lists, and quiet lists to state tracking Ignore chanserv in netsplit detections Track time/setter when a topic is changed in a channel Monitor if a channel is set +r and is still +r 45 minutes later, if so generate an alert Print status and how long it took to sync once the bot has started and synced, and warn about failed syncings.
Diffstat (limited to 'modules')
-rw-r--r--modules/classes.pl49
-rw-r--r--modules/event.pl145
-rw-r--r--modules/inspect.pl18
-rw-r--r--modules/services.pl8
-rw-r--r--modules/util.pl41
-rw-r--r--modules/xml.pl40
6 files changed, 254 insertions, 47 deletions
diff --git a/modules/classes.pl b/modules/classes.pl
index fc80da1..c8dcc54 100644
--- a/modules/classes.pl
+++ b/modules/classes.pl
@@ -25,7 +25,8 @@ sub new
"gecos" => \&gecos,
"nuhg" => \&nuhg,
"levenflood" => \&levenflood,
- "proxy" => \&proxy
+ "proxy" => \&proxy,
+ "nickbl" => \&nickbl
};
$self->{ftbl} = $tbl;
bless($self);
@@ -84,6 +85,21 @@ sub levenflood
return $ret;
}
+sub nickbl
+{
+ my ($chk, $id, $event, $chan) = @_;
+ my $nick = $event->{nick};
+ $nick = $event->{args}->[0] if ($event->{type} eq 'nick');
+ my ($fuzzy, $match) = split(/:/, $chk->{content});
+ my @nicks = split(/,/, $match);
+ foreach my $item (@nicks) {
+ if (distance(lc $nick, lc $item) <= $fuzzy) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
sub dnsbl
{
my ($chk, $id, $event, $chan, $rev) = @_;
@@ -147,8 +163,13 @@ sub process_cf
foreach my $host ( keys %{$cf{$nid}{$xchan}} ) {
next unless defined $cf{$nid}{$xchan}{$host}[0];
while ( time >= $cf{$nid}{$xchan}{$host}[0] + $cf{$nid}{'timeout'} ) {
- last if ( $#{ $cf{$nid}{$xchan}{$host} } == 0 );
shift ( @{$cf{$nid}{$xchan}{$host}} );
+ if ( (scalar @{$cf{$nid}{$xchan}{$host}}) == 0 ) {
+ delete $cf{$nid}{$xchan}{$host};
+ last;
+ }
+# last if ( $#{ $cf{$nid}{$xchan}{$host} } == 0 );
+# shift ( @{$cf{$nid}{$xchan}{$host}} );
}
}
}
@@ -305,12 +326,34 @@ sub flood_process
for my $host ( keys %{$sf{$id}{$chan}} ) {
next unless defined $sf{$id}{$chan}{$host}[0];
while ( time >= $sf{$id}{$chan}{$host}[0] + $sf{$id}{'timeout'} ) {
- last if ( $#{ $sf{$id}{$chan}{$host} } == 0 );
shift ( @{$sf{$id}{$chan}{$host}} );
+ if ( (scalar @{$sf{$id}{$chan}{$host}}) == 0 ) {
+ delete $sf{$id}{$chan}{$host};
+ last;
+ }
+# last if ( $#{ $sf{$id}{$chan}{$host} } == 0 );
+# shift ( @{$sf{$id}{$chan}{$host}} );
}
}
}
}
}
+sub dump
+{
+ #%sf, %ls, %cf, %bs
+ open(FH, ">", "sf.txt");
+ print FH Dumper(\%sf);
+ close(FH);
+ open(FH, ">", "ls.txt");
+ print FH Dumper(\%ls);
+ close(FH);
+ open(FH, ">", "cf.txt");
+ print FH Dumper(\%cf);
+ close(FH);
+ open(FH, ">", "bs.txt");
+ print FH Dumper(\%bs);
+ close(FH);
+}
+
1;
diff --git a/modules/event.pl b/modules/event.pl
index f9888e5..a0b3385 100644
--- a/modules/event.pl
+++ b/modules/event.pl
@@ -70,6 +70,8 @@ sub new
$conn->add_handler('banlist', \&on_banlist);
$conn->add_handler('dcc_open', \&dcc_open);
$conn->add_handler('chat', \&on_dchat);
+ $conn->add_handler('channelmodeis', \&on_channelmodeis);
+ $conn->add_handler('quietlist', \&on_quietlist);
$conn->add_handler('pong', \&on_pong);
bless($self);
return $self;
@@ -132,8 +134,9 @@ sub on_connect {
my ($conn, $event) = @_; # need to check for no services
$conn->sl('MODE AntiSpamMeta +Q');
if (lc $event->{args}->[0] ne lc $::settings->{nick}) {
- $conn->privmsg( 'NickServ', "ghost $::settings->{nick} $::settings->{pass}" );
- $conn->privmsg( 'NickServ', "release $::settings->{nick} $::settings->{pass}" );
+ $conn->privmsg( 'NickServ', "regain $::settings->{nick} $::settings->{pass}" );
+# $conn->privmsg( 'NickServ', "ghost $::settings->{nick} $::settings->{pass}" );
+# $conn->privmsg( 'NickServ', "release $::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
}
@@ -150,6 +153,8 @@ sub on_join {
$::synced{$chan} = 0;
unless ( @::syncqueue ) {
$conn->sl('who ' . $chan . ' %tcnuhra,314');
+ $conn->sl('mode ' . $chan);
+ $conn->sl('mode ' . $chan . ' bq');
}
push @::syncqueue, $chan;
}
@@ -211,7 +216,9 @@ sub on_msg
my ($conn, $event) = @_;
$::commander->command($conn, $event);
print strftime("%F %T ", gmtime) . "(msg) " . $event->{from} . " - " . $event->{args}->[0] . "\n";
- $conn->privmsg('#antispammeta', $event->{from} . ' told me: ' . $event->{args}->[0]);
+ if (ASM::Util->notRestricted($event->{nick}, "nomsgs")) {
+ $conn->privmsg('#antispammeta', $event->{from} . ' told me: ' . $event->{args}->[0]);
+ }
}
sub on_public
@@ -259,7 +266,7 @@ sub on_quit
}
$event->{to} = \@channels;
$::db->logg( $event );
- if (($::netsplit == 0) && ($event->{args}->[0] eq "*.net *.split")) { #special, netsplit situation
+ if (($::netsplit == 0) && ($event->{args}->[0] eq "*.net *.split") && (lc $event->{nick} ne 'chanserv')) { #special, netsplit situation
$conn->privmsg("#antispammeta", "Entering netsplit mode - JOIN and QUIT inspection will be disabled for 60 minutes");
$::netsplit = 1;
$conn->schedule(60*60, sub { $::netsplit = 0; $conn->privmsg('#antispammeta', 'Returning to regular operation'); });
@@ -301,21 +308,25 @@ sub irc_topic {
$::inspector->inspect($conn, $event) if ($event->{format} ne 'server');
if ($event->{format} eq 'server')
{
+ my $chan = lc $event->{args}->[1];
if ($event->{type} eq 'topic')
{
- $::sc{lc $event->{args}->[1]}{topic}{text} = $event->{args}->[2];
+ $::sc{$chan}{topic}{text} = $event->{args}->[2];
}
elsif ($event->{type} eq 'topicinfo')
{
- $::sc{lc $event->{args}->[1]}{topic}{time} = $event->{args}->[3];
- $::sc{lc $event->{args}->[1]}{topic}{by} = $event->{args}->[2];
+ $::sc{$chan}{topic}{time} = $event->{args}->[3];
+ $::sc{$chan}{topic}{by} = $event->{args}->[2];
}
}
else
{
if ($event->{type} eq 'topic')
{
- $::sc{lc $event->{to}->[0]}{topic}{text} = $event->{args}->[0];
+ my $chan = lc $event->{args}->[1];
+ $::sc{$chan}{topic}{text} = $event->{args}->[0];
+ $::sc{$chan}{topic}{time} = time;
+ $::sc{$chan}{topic}{by} = $event->{from};
}
$::log->logg($event);
$::db->logg( $event );
@@ -381,11 +392,11 @@ sub parse_modes
if (($c eq '-') || ($c eq '+')) {
$t=$c;
}
- else {
- if ( defined( grep( /[abdefhIJkloqv]/,($c) ) ) ) { #modes that take args
+ else { #eIbq,k,flj,CFLMPQcgimnprstz
+ if ( grep( /[eIbqkfljov]/,($c) ) ) { #modes that take args
push (@new_modes, [$t.$c, shift @args]);
}
- elsif ( defined( grep( /[cgijLmnpPQrRstz]/, ($c) ) ) ) {
+ elsif ( grep( /[CFLMPQcgimnprstz]/, ($c) ) ) {
push (@new_modes, [$t.$c]);
}
else {
@@ -396,6 +407,29 @@ sub parse_modes
return \@new_modes;
}
+sub on_channelmodeis
+{
+ my ($conn, $event) = @_;
+ my $chan = lc $event->{args}->[1];
+ my @temp = @{$event->{args}};
+ shift @temp; shift @temp;
+ my @modes = @{parse_modes(\@temp)};
+ foreach my $line ( @modes ) {
+ my @ex = @{$line};
+ my ($what, $mode) = split (//, $ex[0]);
+ if ($what eq '+') {
+ if (defined($ex[1])) {
+ push @{$::sc{$chan}{modes}}, $mode . ' ' . $ex[1];
+ } else {
+ push @{$::sc{$chan}{modes}}, $mode;
+ }
+ } else {
+ my @modes = grep {!/^$mode/} @{$::sc{$chan}{modes}};
+ $::sc{$chan}{modes} = \@modes;
+ }
+ }
+}
+
sub on_mode
{
my ($conn, $event) = @_;
@@ -416,11 +450,79 @@ sub on_mode
elsif ( $ex[0] eq '-v' ) {
$::sc{$chan}{users}{lc $ex[1]}{voice}=0;
}
+ elsif ( $ex[0] eq '+b') {
+ $::sc{$chan}{bans}{$ex[1]} = { bannedBy => $event->{from}, bannedOn => time };
+ }
+ elsif ( $ex[0] eq '-b') {
+ delete $::sc{$chan}{bans}{$ex[1]};
+ }
+ elsif ( $ex[0] eq '+q') {
+ $::sc{$chan}{quiets}{$ex[1]} = { bannedBy => $event->{from}, bannedOn => time };
+ }
+ elsif ( $ex[0] eq '-q') {
+ delete $::sc{$chan}{quiets}{$ex[1]};
+ }
+ else {
+ my ($what, $mode) = split (//, $ex[0]);
+ if ($what eq '+') {
+ push @{$::sc{$chan}{modes}}, $mode . ' ' . $ex[1];
+ } else {
+ my @modes = grep {!/^$mode/} @{$::sc{$chan}{modes}};
+ $::sc{$chan}{modes} = \@modes;
+ }
+ if ( ($ex[0] eq '+r') && (! defined($::watchRegged{$chan})) ) {
+ $::watchRegged{$chan} = 1;
+ $conn->schedule(60*45, sub { checkRegged($conn, $chan); });
+ }
+ }
}
$::log->logg($event);
}
}
+sub checkRegged
+{
+ my ($conn, $chan) = @_;
+ if (grep {/r/} @{$::sc{$chan}{modes}}) {
+ my $tgt = $chan;
+ my $risk = "debug";
+ my $hilite=ASM::Util->commaAndify(ASM::Util->getAlert($tgt, $risk, 'hilights'));
+ my $txtz ="\x03" . $::RCOLOR{$::RISKS{$risk}} . "\u$risk\x03 risk threat [\x02$chan\x02] - channel appears to still be +r after 45 minutes; $hilite";
+ my @tgts = ASM::Util->getAlert($tgt, $risk, 'msgs');
+ ASM::Util->sendLongMsg($conn, \@tgts, $txtz)
+ }
+ delete $::watchRegged{$chan};
+}
+
+sub on_banlist
+{
+ my ($conn, $event) = @_;
+# 'args' => [
+# 'AntiSpamMetaBeta',
+# '#antispammeta',
+# 'test!*@*',
+# 'fn-troll!icxcnika@freenode/weird-exception/network-troll/afterdeath',
+# '1344235684'
+# ],
+ my ($me, $chan, $ban, $banner, $bantime) = @{$event->{args}};
+ $::sc{lc $chan}{bans}{$ban} = { bannedBy => $banner, bannedOn => $bantime };
+}
+
+sub on_quietlist
+{
+ my ($conn, $event) = @_;
+# 'args' => [
+# 'AntiSpamMetaBeta',
+# '#antispammeta',
+# 'q',
+# 'loltest!*@*',
+# 'fn-troll!icxcnika@freenode/weird-exception/network-troll/afterdeath',
+# '1344755722'
+# ],
+ my ($me, $chan, $mode, $ban, $banner, $bantime) = @{$event->{args}};
+ $::sc{lc $chan}{quiets}{$ban} = { bannedBy => $banner, bannedOn => $bantime };
+}
+
sub on_ctcp
{
my ($conn, $event) = @_;
@@ -481,6 +583,23 @@ sub on_whoxover
$::synced{$event->{args}->[1]} = 1;
if (defined($chan) ){
$conn->sl('who ' . $chan . ' %tcnuhra,314');
+ $conn->sl('mode ' . $chan);
+ $conn->sl('mode ' . $chan . ' bq');
+ } else {
+ my $size = `ps -p $$ h -o size`;
+ my $cputime = `ps -p $$ h -o time`;
+ chomp $size; chomp $cputime;
+ $conn->privmsg("#antispammeta", "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.");
+ my %x = ();
+ foreach my $c (@{$::settings->{autojoins}}) { $x{$c} = 1; }
+ foreach my $cx (keys %::sc) { delete $x{$cx}; }
+ if (scalar (keys %x)) {
+ $conn->privmsg("#antispammeta", "Syncing appears to have failed for " . ASM::Util->commaAndify(keys %x));
+ }
}
}
@@ -491,10 +610,6 @@ sub on_whofuckedup
print "on_whofuckedup called!\n";
}
}
-sub on_banlist
-{
- my ($conn, $event) = @_;
-}
sub on_bannedfromchan {
my ($conn, $event) = @_;
diff --git a/modules/inspect.pl b/modules/inspect.pl
index 6a4afec..02a6b35 100644
--- a/modules/inspect.pl
+++ b/modules/inspect.pl
@@ -25,7 +25,11 @@ sub inspect {
my $nick = lc $event->{nick};
my $xresult;
return if (index($nick, ".") != -1);
- return if (defined($::eline{$nick}) || defined($::eline{lc $event->{user}}) || defined($::eline{lc $event->{host}}));
+ return unless (ASM::Util->notRestricted($nick, "notrigger"));
+ if (defined($::eline{$nick}) || defined($::eline{lc $event->{user}}) || defined($::eline{lc $event->{host}})) {
+ print "Deprecated eline found for $nick / $event->{user} / $event->{host} !\n";
+ return;
+ }
if ( $event->{host} =~ /gateway\/web\// ) {
if ( $event->{user} =~ /([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})/ ) {
$rev = sprintf("%d.%d.%d.%d.", hex($4), hex($3), hex($2), hex($1));
@@ -63,7 +67,7 @@ sub inspect {
$xresult = $dct{$id}{xresult};
my $nicereason = interpolate($dct{$id}{reason});
$::db->record($chan, $event->{nick}, $event->{user}, $event->{host}, $::sn{lc $event->{nick}}->{gecos}, $dct{$id}{risk}, $id, $nicereason);
- $txtz = "\x03" . $::RCOLOR{$::RISKS{$dct{$id}{risk}}} . "\u$dct{$id}{risk}\x03 risk threat [\x02$chan\x02]: ".
+ $txtz = "\x03" . $::RCOLOR{$::RISKS{$dct{$id}{risk}}} . "\u$dct{$id}{risk}\x03 risk threat [\x02$chan\x02] - ".
"\x02$event->{nick}\x02 - ${nicereason}; ping ";
$txtz = $txtz . ASM::Util->commaAndify(ASM::Util->getAlert(lc $chan, $dct{$id}{risk}, 'hilights')) if (ASM::Util->getAlert(lc $chan, $dct{$id}{risk}, 'hilights'));
$txtz = $txtz . ' !att-' . $chan . '-' . $dct{$id}{risk};
@@ -72,15 +76,7 @@ sub inspect {
}
unless (defined($::ignored{$chan}) && ($::ignored{$chan} >= $::RISKS{$dct{$id}{risk}})) {
my @tgts = ASM::Util->getAlert($chan, $dct{$id}{risk}, 'msgs');
-# foreach my $tgt (@tgts) { #unfortunately wikipedia has way too many ops, and it breaks things
- if (length($txtz) <= 380) {
- $conn->privmsg(\@tgts, $txtz);
- } else {
- my $splitpart = rindex($txtz, " ", 380);
- $conn->privmsg(\@tgts, substr($txtz, 0, $splitpart));
- $conn->privmsg(\@tgts, substr($txtz, $splitpart));
- }
-# }
+ ASM::Util->sendLongMsg($conn, \@tgts, $txtz);
$::ignored{$chan} = $::RISKS{$dct{$id}{risk}};
$conn->schedule(45, sub { delete($::ignored{$chan})});
}
diff --git a/modules/services.pl b/modules/services.pl
index aafe68e..d2b3d31 100644
--- a/modules/services.pl
+++ b/modules/services.pl
@@ -15,9 +15,9 @@ sub doServices {
if ($event->{from} eq 'NickServ!NickServ@services.')
{
print "NickServ: $event->{args}->[0]\n";
- if ( $event->{args}->[0] eq 'This nickname is registered' )
+ if ( $event->{args}->[0] =~ /^This nickname is registered/ )
{
- $conn->privmsg( 'NickServ', "identify $::settings->{pass}" );
+ $conn->privmsg( 'NickServ', "identify $::settings->{nick} $::settings->{pass}" );
}
elsif ( $event->{args}->[0] =~ /^You are now identified/ )
{
@@ -37,6 +37,10 @@ sub doServices {
print "Got kill/release successful from nickserv!\n" if $::debugx{services};
$conn->nick( $::settings->{nick} );
}
+ elsif ($event->{args}->[0] =~ /has been regained/ )
+ {
+ print "Got regain successful from nickserv!\n" if $::debugx{services};
+ }
elsif ($event->{args}->[0] =~ /Password Incorrect/ )
{
die("NickServ password invalid.")
diff --git a/modules/util.pl b/modules/util.pl
index 109882b..7a111b5 100644
--- a/modules/util.pl
+++ b/modules/util.pl
@@ -137,6 +137,18 @@ sub flood_process {
}
}
+# If $tgts="#antispammeta" that's fine, and if $tgts = ["#antispammeta", "##linux-ops"] that's cool too
+sub sendLongMsg {
+ my ($module, $conn, $tgts, $txtz) = @_;
+ if (length($txtz) <= 380) {
+ $conn->privmsg($tgts, $txtz);
+ } else {
+ my $splitpart = rindex($txtz, " ", 380);
+ $conn->privmsg($tgts, substr($txtz, 0, $splitpart));
+ $conn->privmsg($tgts, substr($txtz, $splitpart));
+ }
+}
+
sub getAlert {
my ($module, $c, $risk, $t) = @_;
my @disable = ();
@@ -183,4 +195,33 @@ sub dprint {
print $text if $::debug;
}
+sub notRestricted {
+ my ($module, $nick, $restriction) = @_;
+ $nick = lc $nick;
+ my $host = $::sn{$nick}{host};
+ my $account = lc $::sn{$nick}{account};
+ my $ret = 1;
+ if (defined($::restrictions->{nicks}->{nick}->{$nick})) {
+ if (defined($::restrictions->{nicks}->{nick}->{$nick}->{$restriction})) {
+ $ret= 0;
+ }
+ }
+ if ((defined($host)) && (defined($account))) {
+ if (defined($::restrictions->{accounts}->{account}->{$account})) {
+ if (defined($::restrictions->{accounts}->{account}->{$account}->{$restriction})) {
+ $ret= 0;
+ }
+ }
+ if (defined($::restrictions->{hosts}->{host}->{$host})) {
+ if (defined($::restrictions->{hosts}->{host}->{$host}->{$restriction})) {
+ $ret= 0;
+ }
+ }
+ }
+ if (($ret == 0) && ($::debugx{restrictions})) {
+ print "Restriction $restriction found for $nick\n";
+ }
+ return $ret;
+}
+
return 1;
diff --git a/modules/xml.pl b/modules/xml.pl
index 14f5826..a23df77 100644
--- a/modules/xml.pl
+++ b/modules/xml.pl
@@ -10,24 +10,26 @@ $::xs1 = XML::Simple->new( KeyAttr => ['id'], Cache => [ qw/storable memcopy/ ])
sub readXML {
my ( $p ) = $::cset;
my @fchan = ( 'event', keys %::RISKS );
- $::settings = $::xs1->XMLin( "$p/settings.xml", ForceArray => ['host'], 'GroupTags' => { altnicks => 'altnick', server => 'host', autojoins => 'autojoin' });
- $::channels = $::xs1->XMLin( "$p/channels.xml", ForceArray => \@fchan );
- $::users = $::xs1->XMLin( "$p/users.xml", ForceArray => 'person');
- $::commands = $::xs1->XMLin( "$p/commands.xml", ForceArray => [qw/command/]);
- $::mysql = $::xs1->XMLin( "$p/mysql.xml", ForceArray => []);
- $::dnsbl = $::xs1->XMLin( "$p/dnsbl.xml", ForceArray => []);
- $::rules = $::xs1->XMLin( "$p/rules.xml", ForceArray => []);
+ $::settings = $::xs1->XMLin( "$p/settings.xml", ForceArray => ['host'], 'GroupTags' => { altnicks => 'altnick', server => 'host', autojoins => 'autojoin' });
+ $::channels = $::xs1->XMLin( "$p/channels.xml", ForceArray => \@fchan );
+ $::users = $::xs1->XMLin( "$p/users.xml", ForceArray => 'person');
+ $::commands = $::xs1->XMLin( "$p/commands.xml", ForceArray => [qw/command/]);
+ $::mysql = $::xs1->XMLin( "$p/mysql.xml", ForceArray => []);
+ $::dnsbl = $::xs1->XMLin( "$p/dnsbl.xml", ForceArray => []);
+ $::rules = $::xs1->XMLin( "$p/rules.xml", ForceArray => []);
+ $::restrictions = $::xs1->XMLin( "$p/restrictions.xml", ForceArray => ['host', 'nick', 'account']);
}
sub writeXML {
- $::xs1->XMLout($::settings, RootName => 'settings', KeyAttr => ['id'],
- GroupTags => { altnicks => 'altnick', server => 'host', autojoins => 'autojoin' },
- ValueAttr => { debug => 'content', nick => 'content', port => 'content',
- realname => 'content', username => 'content', dir => 'content',
- zone => 'content', filefmt => 'content', timefmt => 'content'}) > io("$::cset/settings.xml");
- $::xs1->XMLout($::channels, RootName => 'channels', KeyAttr => ['id'], NumericEscape => 2) > io("$::cset/channels.xml");
- $::xs1->XMLout($::users, RootName => 'people', KeyAttr => ['id']) > io("$::cset/users.xml");
- $::xs1->XMLout($::commands, RootName => 'commands', KeyAttr => ['id']) > io("$::cset/commands.xml");
+ $::xs1->XMLout($::settings, RootName => 'settings', KeyAttr => ['id'],
+ GroupTags => { altnicks => 'altnick', server => 'host', autojoins => 'autojoin' },
+ ValueAttr => { debug => 'content', nick => 'content', port => 'content',
+ realname => 'content', username => 'content', dir => 'content',
+ zone => 'content', filefmt => 'content', timefmt => 'content'}) > io("$::cset/settings.xml");
+ writeChannels();
+ writeUsers();
+ writeRestrictions();
+ $::xs1->XMLout($::commands, RootName => 'commands', KeyAttr => ['id']) > io("$::cset/commands.xml");
}
sub writeChannels {
@@ -39,7 +41,13 @@ sub writeUsers {
}
sub writeSettings {
- $::xs1->XMLout($::settings, RootName => 'settings', GroupTags => { altnicks => 'altnick', server => 'host', autojoins => 'autojoin' }, NoAttr => 1) > io("$::cset/settings.xml");
+ $::xs1->XMLout($::settings, RootName => 'settings',
+ GroupTags => { altnicks => 'altnick', server => 'host', autojoins => 'autojoin' }, NoAttr => 1) > io("$::cset/settings.xml");
+}
+
+sub writeRestrictions {
+ $::xs1->XMLout($::restrictions, RootName => 'restrictions', KeyAttr => ['id'],
+ GroupTags => { hosts => "host", nicks => "nick", accounts => "account"}) > io("$::cset/restrictions.xml");
}
return 1;