Nanobot source
Revision as of 13:55, 4 March 2011 by imported>Wikiadmin
Source code listing for nanobot
# Copyright (c) 2010, Insomnia 24/7 All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. Redistributions in binary # form must reproduce the above copyright notice, this list of conditions and # the following disclaimer in the documentation and/or other materials # provided with the distribution. Neither the name of Insomnia 24/7 nor # the names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. #!/usr/local/bin/perl package nanobot; #use Socket; use IO::Socket::INET6; use Module::Load; $version = "Nanobot 3.0"; $server = 'irc.server.tld'; # Hostname, IPv4 or IPv6 address. $port = 6667; $sslport = 6697; $botnick = 'nanobot'; # Bots nickname $botuser = 'nanobot'; # Bots username $nsp = ''; # NickServ pasword (if not registered, leave empty) @channels = ("#bot", "#yourchan"); @opers = ("insomnia247.nl", "another.oper.com", "127.0.0.1"); # Oper(s) hostmask(s) $modchan = '#yourchan'; $datadir = 'botdata'; $moddir = 'modules'; @autoload = (); # List modules to load on startup. Example: @autoload("mymodule", "kickban"); $wisecrack_seen_botnick = "DURP!?"; $wisecrack_seen_self = "I can see you! You're right there! That's right, I can see."; $wait_for_ping = 0; # Set to 1 if your network requires a ping reply before allowing to join channels. $connect_timeout = 120; # Seconds to wait before giving up connnecting to the IRC server. $ping_timeout = 300; # Seconds to wait before assuming timeout and attempting reconnect. # These are set by the bot itself, do not modify $logging = 1; $debug = 0; $op_all = 0; $hop_all = 0; $voice_all = 0; $botstatus = 1; $startup = time; %seenlog = (); %seentime = (); $public_modules = 0; @modules = (); ##### Process commandline options ##### foreach $arg (@ARGV) { if ($arg eq "-h" or $arg eq "--help") { print "options:\n"; print " -h or --help Print this help.\n"; print " -v or --version Print version number and exit.\n"; print " -q or --quiet Activate silent mode (Nothing is printed to the screen.)\n"; print " -d or --debug Enable debugging output. (Use twice for greater effect.\n"; print " -s or --ssl Use ssl.\n"; print " -6 or --ipv6 Use IPv6 over IPv4.\n"; &shutd; } if ($arg eq "-v" or $arg eq "--version") { print "version: $version\n"; &shutd;} if ($arg eq "-q" or $arg eq "--quiet") {$logging = 0;} if ($arg eq "-d" or $arg eq "--debug") {$debug++;} if ($arg eq "-s" or $arg eq "--ssl") { $ssl = 1; $port = $sslport; use IO::Socket::SSL; } } ##### Kick things off ###### logts("Nanobot is starting...\n"); &directories; while(1) { &connct; sleep(2); } ##### Check for data and module directories ###### sub directories { logts("Data folder .......... "); if (-d $datadir) { logts("[OK]\n"); } else { if (mkdir $datadir) { logts("[CREATED]\n"); } else { logts("[FAILED]\n"); } } logts("Modules folder ....... "); if (-d $moddir) { logts("[OK]\n"); } else { if (mkdir $moddir) { logts("[CREATED]\n"); } else { logts("[FAILED]\n"); } } } ##### Screen output subroutine ##### sub logts { if ($logging == 1){ print STDOUT "$_[0]"; } } ##### Debug output subroutine ##### sub debug { if ($debug >= 1){ print STDOUT "$_[0]"; } } sub debug_extra { if ($debug == 2){ ($s,$m,$h,$d,$mo) = gmtime( time ); print STDOUT "[$h:$m:$s] $_[0]"; } } ##### Connect to server ###### sub connct { debug("Attempting connect.\n"); # Connect to server logts("Connecting ........... "); $sock = IO::Socket::INET6->new( PeerAddr => $server, PeerPort => $port, Proto => 'tcp', Domain => AF_UNSPEC, Timeout => $connect_timeout) or die "Connect error: $!\n"; logts("[OK]\n"); if($ssl) { logts("Starting SSL ......... "); IO::Socket::SSL->start_SSL( $sock, SSL_verify_mode => 0, # Do not verify certificate ) or die "SSL handshake failed: $SSL_ERROR"; logts("[OK]\n"); } debug("Connected to server: $server\non port: $port\n"); # Set nick and username logts("Sending user info .... "); snd("NICK $botnick"); snd("USER $botuser 8 * :$version"); logts("[OK]\n"); # Catch SIGALRM from the OS when timeout expired. local $SIG{ALRM} = sub {$sock->shutdown(0);}; # Send all incomming data to the parser while (<$sock>) { eval { alarm 0; &parse($_); alarm $ping_timeout; }; } debug("Closing socket.\n"); close $sock; logts("Error: Lost connection, reconnecting...\n"); $login = undef; } ##### Subroutine for sending data to the IRC server ##### sub snd { print $sock "$_[0]\n"; debug_extra("<== $_[0]\n"); } ##### Subroutine for sending messages to the IRC server ##### sub msg { snd("PRIVMSG $_[0] :$_[1]"); } ##### Subroutine for sending notices to the IRC server ##### sub ntc { snd("NOTICE $_[0] :$_[1]"); } ##### Socket input parser ##### sub parse { debug_extra("==> $_"); # Remove /r and /n chop($_); chop($_); # Do nickserv auth and channel join if(!$login && ($wait_for_ping == 0)) { &login; } # Handle PING and rejoin on kick if (/^PING \:(.+)/) { debug("Received PING request.\n"); snd("PONG :$1"); if(!$login && ($wait_for_ping == 1)) { &login; } debug("Sent PONG reply.\n"); return; } elsif (/^\:(.+?)!(.+?)@(.+?) KICK #(.+?) \Q$botnick\E \:(.+?)/) { snd("JOIN #$4"); debug("Rejoined channel $4 after kick.\n"); return; } # Hook for modules that want raw data foreach $module (@modules) { if( $module->can('raw') ) { $module->raw($_); } } # Process generic NOTICE if (/^\:(.+?)!(.+?)@(.+?) NOTICE (.+?) \:(.+)/) { # Hook for modules that want all messages foreach $module (@modules) { if( $module->can('notice') ) { $module->notice($1, $2, $3, $4, $modchan, $botnick, $5); } } return; } # Process generic JOIN actions if (/^\:(.+?)!(.+?)@(.+?) JOIN \:(.+)/) { # Parse regex results $join{from} = $1; $join{user} = $2; $join{host} = $3; $join{rcpt} = $4; $join{text} = $5; $args = $join{text}; $from = $join{from}; $uname = $join{user}; $host = $join{host}; $from_chan = $join{rcpt}; # Hook for modules that want join actions foreach $module (@modules) { if( $module->can('join') ) { $module->join($from, $uname, $host, $from_chan, $modchan, $botnick); } } return; } # Process autojoin actions for modchan if($botstatus == 1){ if (/^\:(.+?)!(.+?)@(.+?) JOIN \:$modchan/) { $join{from} = $1; $join{user} = $2; $join{host} = $3; $join{rcpt} = $4; $join{text} = $5; $args = $join{text}; $from = $join{from}; $send_host = $join{host}; if ($op_all == 1) { snd("MODE $modchan +o $1"); } else { foreach $aop (@aop) { chomp($aop); if ($aop eq $3) { snd("MODE $modchan +o $1"); logts("AOPped $1\n"); } } } if ($hop_all == 1) { snd("MODE $modchan +h $1"); } else { foreach $ahop (@ahop) { chomp($ahop); if ($ahop eq $3) { snd("MODE $modchan +h $1"); logts("AHOPped $1\n"); } } } if ($voice_all == 1) { snd("MODE $modchan +v $1"); } else { foreach $av (@av) { chomp($av); if ($av eq $3) { snd("MODE $modchan +v $1"); logts("AVoiced $1\n"); } } } foreach $ak (@ak) { chomp($ak); if ($ak eq $3) { snd("KICK $modchan $1"); logts("AKicked $1\n"); } } return; } } # Process messages if (/^\:(.+?)!(.+?)@(.+?) PRIVMSG (.+?) \:(.+)/) { $privmsg{from} = $1; $privmsg{user} = $2; $privmsg{host} = $3; $privmsg{rcpt} = $4; $privmsg{text} = $5; $args = $privmsg{text}; $from = $privmsg{from}; $uname = $privmsg{user}; $host = $privmsg{host}; $from_chan = $privmsg{rcpt}; # Log data for seen log if($args !~ /\a/) { $seenlog{lc $from} = $args; $seentime{lc $from} = time; debug("$from_chan <$from> $args\n"); } else { debug("Ignored term bell from $from for seen log.\n"); } # Parse commands if($args =~ /^!version/) { &version; } elsif($args =~ /^!uptime /) { &uptime; } elsif($args =~ /^!seen /) { &seen; } elsif($args =~ /^!help/) { &help; } elsif($args =~ /^!loaded/) { &loaded; } elsif($args =~ /^!available/) { &available; } elsif($args =~ /^!load /) { if($public_modules == 1) { &loadmodule; } } elsif($args =~ /^!unload /) { if($public_modules == 1) { &unloadmodule; } } elsif($args =~ /^!reload /) { if($public_modules == 1) { &unloadmodule; &loadmodule; } } elsif($args =~ /^!\w/) { &pubcmd; } else { # Hook for modules that want all messages foreach $module (@modules) { if( $module->can('mesg') ) { $module->mesg($from, $uname, $host, $from_chan, $modchan, $botnick, $args); } } } # Operator commands foreach $oper (@opers) { if ($oper eq $host) { if($args =~ /^!load /) { if($public_modules == 0) { &loadmodule; } } elsif($args =~ /^!unload /) { if($public_modules == 0) { &unloadmodule } } elsif($args =~ /^!reload /) { if($public_modules == 0) { &unloadmodule; &loadmodule; } } elsif($args =~ /^!raw /) { &raw; } elsif($args =~ /^!msg /) { &mesg; } elsif($args =~ /^!quit/) { &botquit; } elsif($args =~ /^!join /) { &joinchan; } elsif($args =~ /^!part /) { &partchan; } elsif($args =~ /^!nick /) { &nick; } elsif($args =~ /^!op/) { &oper; } elsif($args =~ /^!deop/) { &deoper; } elsif($args =~ /^!hop/) { &halfoper; } elsif($args =~ /^!dehop/) { &dehalfoper; } elsif($args =~ /^!voice/) { &voice; } elsif($args =~ /^!devoice/) { &devoice; } elsif($args =~ /^!kick /) { &kick; } elsif($args =~ /^!ban /) { &ban; } elsif($args =~ /^!unban /) { &unban; } elsif($args =~ /^!topic /) { &topic; } elsif($args =~ /^!mode /) { &mode; } elsif($args =~ /^!loadlist /) { &loadlists; } elsif($args =~ /^!modchan/) { &modchan; } elsif($args =~ /^!bot/) { &botswitch; } elsif($args =~ /^!pubmods/) { &pubmods; } elsif($args =~ /^!admin/) { &admin; } elsif($args =~ /^!all /) { &all; } elsif($args =~ /^!none /) { &none; } elsif($args =~ /^!add /) { &add; } elsif($args =~ /^!\w/) { &admincmd; } } } } } ##### Meta subroutine for initial join ###### sub login { debug("Entered initial join loop.\n"); # Attempt nickserv login &nickserv; # Join all listed channels &joinlist; # We've done login and join, no need to do it again next time $login = 1; } ##### NickServ AUTH ###### sub nickserv{ if ($nsp) { logts("Identifying nick ..... "); msg("NickServ", "identify $nsp"); logts("[OK]\n"); } } ##### Join listed channels ##### sub joinlist { logts("Joining channel(s) ... "); foreach $chan (@channels) { snd("JOIN $chan"); } logts("[OK]\n"); # Also call autoload modules now &autoload; } ##### Attempt to autoload specified modules ##### sub autoload { foreach $loadme (@autoload) { &autoloadmodule($loadme); } } ##### !version ##### sub version { debug("Received \"version\"-command.\n"); ntc("$from", "Running version: $version"); my $uptime = &diffString(time - $startup); ntc("$from", "Uptime: $uptime"); logts("Sending version to $from.\n"); } ##### !seen ##### sub seen { if($botstatus == 1) { debug("Received \"seen\"-command.\n"); if(!substr($args, 6)) { ntc("$from", "No user was specified!"); } else { $usr = substr($args, 6); $usr =~ s/\s+$//; if( lc $usr eq lc $botnick ) { msg("$from_chan", "$wisecrack_seen_botnick"); } elsif( lc $usr eq lc $from ) { msg("$from_chan", "$wisecrack_seen_self"); } else { # Check if we have a log for this user my $seen = 0; for my $key (keys(%seenlog)) { if ($key eq lc $usr) { $seen = 1; } } if ($seen == 1) { my $diff = &diffString(time - $seentime{lc $usr}); msg("$from_chan", "$usr was last seen $diff ago saying: "); msg("$from_chan", "$seenlog{lc $usr}"); logts("Sending seen info for $usr\n"); debug("$seenlog{lc $usr}"); } else { my $uptime = &diffString(time - $startup); ntc("$from", "No log for $usr"); ntc("$from", "Log goes back $uptime"); logts("No log entry for $usr found\n"); } } } } } ##### Translate difference in seconds to human readable string ##### sub diffString { ($s,$m,$h,$d,$mo) = gmtime( $_[0] ); if( $mo > 0 ) { $returnstring = "$mo months, $d days, $h hours, $m minutes and $s seconds"; } else { $d--; if( $d > 0 ) { $returnstring = "$d days, $h hours, $m minutes and $s seconds"; } else { if( $h > 0 ) { $returnstring = "$h hours, $m minutes and $s seconds"; } else { if( $m > 0 ) { $returnstring = "$m minutes and $s seconds"; } else { $returnstring = "$s seconds"; } } } } } ##### !help ##### sub help { if (substr($args, 6) eq "yes") { debug("Received \"help\"-command.\n"); ntc("$from", "Help for $botnick version $version."); ntc("$from", " "); ntc("$from", "�Public commands:�"); ntc("$from", "!help Get this help."); ntc("$from", "!version Get version number."); ntc("$from", "!seen [user] Get the last thing a user said."); ntc("$from", " "); ntc("$from", "�Oper only commands:�"); ntc("$from", "!quit [message] Stop bot."); ntc("$from", "!join [channel] Join channel."); ntc("$from", "!part [channel] Part channel."); ntc("$from", "!topic [topic] New topic."); ntc("$from", "!mode [user/chan] +/-mode"); ntc("$from", "!nick [botnick] Change the bots nickname."); ntc("$from", "!loadlist Load auto-lists."); ntc("$from", "!modchan [channel] Set active channel. Returms current active channel when none is given."); ntc("$from", "!bot [on|off] Switch bot on or off."); ntc("$from", "!all [op|hop|voice] Give status to every user to enter the channel."); ntc("$from", "!none [op|hop|voice] Stop the !all command."); ntc("$from", "!add [op|hop|voice|kick] [hostmask] Add hostmask to auto-list."); ntc("$from", "![op|deop|hop|dehop|voice|devoice|kick] [nick] Preform direct action."); ntc("$from", "![ban|unban] [hostmask] Ban hosts from the active channel."); ntc("$from", "!admin [add|del] [hostmask] Control admin access to the bot. (No args returns current list)"); ntc("$from", "!raw [data] Send raw commands to the IRC server."); ntc("$from", " "); ntc("$from", "�Module commands:�"); ntc("$from", "![load|unload|reload] [module] Load / unload / reload a module."); ntc("$from", "!loaded List currently loaded modules."); ntc("$from", "!available List all available modules."); ntc("$from", "!pubmods [on|off] Switch public usage of modules on or off."); ntc("$from", "!module.function Call a loaded modules functions."); logts("Sent help to $from.\n"); } else { ntc("$from", "This command sends about 30 lines of notices."); ntc("$from", "Use \"!help yes\" if you are sure you want to do this. Or visit http://wiki.insomnia247.nl/wiki/Nanobot"); } } ##### !raw ##### sub raw { debug("Received \"raw\"-command.\n"); my ($cmd,@data) = split(/ /, $args); snd("@data"); logts("Raw command was used by $from.\n"); } ##### !msg ##### sub mesg { debug("Received \"msg\"-command.\n"); my ($cmd, $to, @data) = split(/ /, $args); snd("PRIVMSG $to :@data"); logts("Msg command was used by $from.\n"); } ##### !join ##### sub joinchan { debug("Received \"join\"-command.\n"); if(!substr($args, 5)) { ntc("$from", "No channel was specified!"); } else { $chan = substr($args, 5); snd("JOIN $chan"); logts("Joining $chan...\n"); } } ##### !part ##### sub partchan { debug("Received \"part\"-command.\n"); if(!substr($args, 5)) { ntc("$from", "No channel was specified!"); } else { $chan = substr($args, 5); snd("PART $chan"); logts("Parting $chan...\n"); } } ##### !nick ##### sub nick { debug("Received \"nick\"-command.\n"); if(!substr($args, 5)) { ntc("$from", "No new nick was specified!"); } else { $botnick = substr($args, 5); snd("NICK $botnick"); logts("Changed bot nick to $botnick...\n"); } } ##### !modchan ##### sub modchan { debug("Received \"modchan\"-command.\n"); if(!substr($args, 9)) { debug("command was blank.\n"); ntc("$from", "Current active channel is: $modchan"); } else { $modchan = substr($args, 9); ntc("$from", "Setting active channel to $modchan..."); logts("Setting active channel to $modchan...\n"); } } ##### !bot ##### sub botswitch { debug("Received \"bot\"-command.\n"); if (!substr($args, 5)) { if($botstatus) { ntc("$from", "Bot is enabled."); } else { ntc("$from", "Bot is disabled."); } } else { $mode = substr($args, 5); if ($mode =~ /on/) { $botstatus = 1; msg("$modchan", "Bot enabled."); logts("Bot enabled by $from...\n"); } else { if ($mode =~ /off/) { $botstatus = 0; msg("$modchan", "Bot disabled."); logts("Bot disabled by $from...\n"); } } } } ##### !loaded ##### sub loaded { snd("NOTICE $from :Loaded modules: @modules"); } ##### !available ###### sub available { @available = <$moddir/*.pm>; my $i = 0; foreach $avail (@available) { my ($dir, $filename) = split(/\//, $avail); my ($modname, $ext) = split(/\./, $filename); $available[$i] = $modname; $i++; } snd("NOTICE $from :Available modules: @available"); } ##### !load ##### sub loadmodule { debug("Received \"load\"-command.\n"); my ($cmd,$module,@data) = split(/ /, $args); $i = 0; $found = 0; while($i <= @modules){ if($modules[$i] eq $module){ $found = 1; } $i++; } if( (-e "$moddir/$module.pm") && ( $found == 0 ) ) { my $retval = system( "perl -c $moddir/$module.pm" ); if( $retval == 0 ) { load "$moddir/$module.pm"; push(@modules,$module); ntc("$from", "Inserted: $module"); logts("Module $module loaded by $from.\n"); } else { ntc("$from", "Could not load module: $module (Not valid Perl)"); } } else { if( $found == 1 ) { ntc("$from", "Could not load module: $module (Module is already loaded)"); } else { ntc("$from", "Could not load module: $module (Cannot find module)"); } logts("Module $module loaded by $from FAILED.\n"); } } ##### autoload modules ##### sub autoloadmodule { debug("Attempting to load module $_[0].\n"); logts("Loading module ....... "); $module = $_[0]; $i = 0; $found = 0; while($i <= @modules){ if($modules[$i] eq $module){ $found = 1; } $i++; } if( (-e "$moddir/$module.pm") && ( $found == 0 ) ) { my $retval = system( "perl -c $moddir/$module.pm 2> $moddir/temp" ); unlink "$moddir/temp"; if( $retval == 0 ) { load "$moddir/$module.pm"; push(@modules,$module); logts("[$module OK]\n"); } else { logts("[$module FAILED] (not valid perl)\n"); } } else { if( $found == 1 ) { logts("[$module FAILED] (already loaded)\n"); } else { logts("[$module FAILED] (not found)\n"); } } } ##### !unload ##### sub unloadmodule { debug("Received \"unload\"-command.\n"); my ($cmd,$module,@data) = split(/ /, $args); $i = 0; $found = 0; while($i <= @modules){ if($modules[$i] eq $module){ $found = 1; delete $INC{"$moddir/$module.pm"}; delete $modules[$i]; splice(@modules, $i ,1); } $i++; } if( $found == 1 ) { ntc("$from", "Unloaded module: $module"); logts("Module $module unloaded by $from.\n"); } else { ntc("$from", "Could not unload module: $module (Module doesn't appear to be loaded)"); logts("Module $module unload by $from FAILED.\n"); } } ##### !pubmods ##### sub pubmods { debug("Received \"pubmods\"-command.\n"); if (!substr($args, 9)) { if($botstatus) { ntc("$from", "Public modules are enabled."); } else { ntc("$from", "Public modules are disabled."); } } else { $mode = substr($args, 5); if ($mode =~ /on/) { $public_modules = 1; msg("$modchan", "Public modules enabled."); logts("Public modules enabled by $from...\n"); } else { if ($mode =~ /off/) { $public_modules = 0; msg("$modchan", "Pulbic modules disabled."); logts("Public modules disabled by $from...\n"); } } } } ##### Public module commands ##### sub pubcmd { my($command, @data) = split(/ /,$args); $command = substr($command, 1); my($mod, $cmd) = split(/\./,$command); if(($mod =~ /^.+/) && ($cmd =~ /^.+/)) { $i = 0; while($i <= @modules){ if(($modules[$i] eq $mod) && ( $mod->can($cmd) )){ if( $public_modules == 1) { $mod->$cmd($from, $uname, $host, $from_chan, $modchan, $botnick, @data); } elsif( $mod->can('public') ){ @functions = $mod->public(); foreach $function (@functions) { if( ($function eq $cmd) ) { $mod->$cmd($from, $uname, $host, $from_chan, $modchan, $botnick, @data); } } } } $i++; } } elsif((($mod =~ /^.+/) && ($cmd !~ /^.+/)) && ( $mod->can('help') )) { $mod->help($from, $uname, $host, $from_chan, $modchan, $botnick, @data); } } ##### Admin module commands ##### sub admincmd { my($command, @data) = split(/ /,$args); $command = substr($command, 1); my($mod, $cmd) = split(/\./,$command); if(($mod =~ /^.+/) && ($cmd =~ /^.+/)) { $i = 0; while($i <= @modules){ if(($modules[$i] eq $mod) && ( $mod->can($cmd) )){ if( $mod->can('public') ) { @functions = $mod->public(); my $notPublic = 1; foreach $function (@functions) { if( ($function eq $cmd) ) { $notPublic = 0; } } if( $notPublic == 1 && $public_modules == 0 ) { $mod->$cmd($from, $uname, $host, $from_chan, $modchan, $botnick, @data); } } elsif ( $public_modules == 0) { $mod->$cmd($from, $uname, $host, $from_chan, $modchan, $botnick, @data); } } $i++; } } } ##### !loadlist ##### sub loadlists { debug("Received \"loadlist\"-command.\n"); debug("Using data directory \"$datadir\".\n"); open AOPLIST, "<$datadir/aop"; @aop = <AOPLIST>; close(AOPLIST); debug("AOP list loaded.\n"); open AHOPLIST, "<$datadir/ahop"; @ahop = <AHOPLIST>; close(AHOPLIST); debug("AHOP list loaded.\n"); open AVLIST, "<$datadir/av"; @av = <AVLIST>; close(AVLIST); debug("AVOICE list loaded.\n"); open AKLIST, "<$datadir/ak"; @ak = <AKLIST>; close(AKLIST); debug("AKICK list loaded.\n"); msg("$modchan", "Lists loaded."); logts("Loaded the lists...\n"); } ##### !add ##### sub add { debug("Received \"add\"-command "); my ($msg,$type,$toadd) = split(/ /, $args); debug("of type $type.\n"); if($type =~ /^op/) { open AOPLIST, ">>$datadir/aop"; print AOPLIST "$toadd\n"; close(AOPLIST); msg("$modchan", "$toadd added to auto-op list."); } elsif($type =~ /^hop/) { open AHOPLIST, ">>$datadir/ahop"; print AHOPLIST "$toadd\n"; close(AHOPLIST); msg("$modchan", "$toadd added auto-half-op list.."); } elsif($type =~ /^voice/) { open AVLIST, ">>$datadir/av"; print AVLIST "$toadd\n"; close(AVLIST); ntc("$modchan", "$toadd added auto-voice list."); } elsif($type =~ /^kick/) { open AKLIST, ">>$datadir/ak"; print AKLIST "$toadd\n"; close(AKLIST); ntc("$modchan", "$toadd added auto-kick list."); } } ##### !op ##### sub oper { debug("Received \"op\"-command.\n"); if(!substr($args, 4)) { snd("MODE $from_chan +o $from"); logts("Opered $from...\n"); } else { $user = substr($args, 4); snd("MODE $from_chan +o $user"); logts("Opered $user...\n"); } } ##### !deop ##### sub deoper { debug("Received \"deop\"-command.\n"); if(!substr($args, 6)) { snd("MODE $from_chan -o $from"); logts("Deopered $from...\n"); } else { $user = substr($args, 6); snd("MODE $from_chan -o $user"); logts("Deopered $user...\n"); } } ##### !hop ##### sub halfoper{ debug("Received \"hop\"-command.\n"); if(!substr($args, 5)) { snd("MODE $from_chan +h $from"); logts("Half-opered $from...\n"); } else { $user = substr($args, 5); snd("MODE $from_chan +h $user"); logts("Half-opered $user...\n"); } } ##### !dehop ##### sub dehalfoper { debug("Received \"dehop\"-command.\n"); if(!substr($args, 7)) { snd("MODE $from_chan -h $from"); logts("Dehalf-opered $from...\n"); } else { $user = substr($args, 7); snd("MODE $from_chan -h $user"); logts("Dehalf-opered $user...\n"); } } ##### !voice ##### sub voice { debug("Received \"voice\"-command.\n"); if(!substr($args, 6)) { snd("MODE $from_chan +v $from"); logts("Voiced $from...\n"); } else { $user = substr($args, 6); snd("MODE $from_chan +v $user"); logts("Voiced $user...\n"); } } ##### !devoice ##### sub devoice { debug("Received \"devoice\"-command.\n"); if(!substr($args, 8)) { snd("MODE $from_chan -v $from"); logts("Devoiced $from...\n"); } else { $user = substr($args, 8); snd("MODE $from_chan -v $user"); logts("Devoiced $user...\n"); } } ##### !all ##### sub all { debug("Received \"all\"-command "); my ($msg,$type) = split(/ /, $args); debug("of type $type.\n"); if($type =~ /^op/) { msg("$modchan", "Global Oper for $modchan users enabled."); $op_all = 1; logts("Enabled Op all on $modchan by $from.\n"); } elsif($type =~ /^hop/) { msg("$modchan", "Global Half-op for $modchan users enabled."); $hop_all = 1; logts("Enabled Half-Op all on $modchan by $from.\n"); } elsif($type =~ /^voice/) { msg("$modchan", "Global Voice for $modchan users enabled."); $voice_all = 1; logts("Enabled Voice all on $modchan by $from.\n"); } } ##### !none ##### sub none { debug("Received \"none\"-command "); my ($msg,$type) = split(/ /, $args); debug("of type $type.\n"); if($type =~ /^op/) { msg("$modchan", "Global Oper for $modchan users disabled."); $op_all = 0; logts("Enabled Op all on $modchan by $from.\n"); } elsif($type =~ /^hop/) { msg("$modchan", "Global Half-op for $modchan users disabled."); $hop_all = 0; logts("Enabled Half-Op all on $modchan by $from.\n"); } elsif($type =~ /^voice/) { msg("$modchan", "Global Voice for $modchan users disabled."); $voice_all = 0; logts("Enabled Voice all on $modchan by $from.\n"); } } ##### !kick ##### sub kick { debug("Received \"kick\"-command.\n"); if(!substr($args, 5)) { ntc("$from", "Commmand requires username to kick."); } else { $user = substr($args, 5); snd("KICK $from_chan $user (Requested.)"); logts("Kicked $user...\n"); } } ##### !ban ##### sub ban { debug("Received \"ban\"-command.\n"); if(!substr($args, 5)) { ntc("$from", "Command requires something to ban."); } else { $hostmask = substr($args, 5); snd("MODE $from_chan +b $hostmask"); logts("Banned $hostmask...\n"); } } ##### !unban ##### sub unban { debug("Received \"unban\"-command.\n"); if(!substr($args, 7)) { ntc("$from", "Command requires hostname to unban."); } else { $hostmask = substr($args, 7); snd("MODE $from_chan -b $hostmask"); logts("Unanned $hostmask...\n"); } } ##### !topic ##### sub topic { debug("Received \"topic\"-command.\n"); if(!substr($args, 7)) { ntc("$from", "No new topic specified."); } else { $new_topic = substr($args, 7); snd("TOPIC $from_chan :$new_topic"); logts("Set topic for $from_chan set to $new_topic\n"); } } ##### !mode ##### sub mode { debug("Received \"mode\"-command.\n"); if(!substr($args, 6)) { ntc("$from", "No arguments specified."); } else { $modes = substr($args, 6); snd("MODE $modes"); logts("Set modes $modes\n"); } } ##### !admin ##### sub admin { debug("Received \"admin\"-command.\n"); my ($msg,$type,$hostm) = split(/ /, $args); if ($type =~ /add/) { push(@opers,$hostm); ntc("$from", "Added $hostm to temp admin list."); logts("Added temp admin $hostm by $from\n"); debug("Oper list: "); foreach $oper (@opers) { debug("$oper "); } debug("\n"); } elsif ($type =~ /del/) { $i = 0; while($i <= @opers){ if($opers[$i] eq $hostm){ while($i < @opers){ $opers[$i] = $opers[$i+1]; $i++; } } $i++; } ntc("$from", "Removed $hostm from temp admin list."); logts("Removed temp admin $hostm by $from\n"); debug("Oper list: "); foreach $oper (@opers) { debug("$oper "); } debug("\n"); } else { snd("NOTICE $from :Current admins: @opers"); } } ##### !quit ##### sub botquit { debug("Received \"quit\"-command.\n"); logts("Quit command was issued by $from.\n"); my ($cmd,@msg) = split(/ /, $args); if($msg[0] eq "") { snd("QUIT $botnick was instructed to quit."); } else { snd("QUIT @msg"); } close($sock); &shutd; } ##### Process exit subroutine ##### sub shutd { logts("Shutting down.\n"); debug("Final line of code before exit call.\n"); exit(0); }