imported>Wikiadmin |
imported>Wikiadmin |
(2 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
− | == Source code listing for nanobot ==
| |
− | Code with syntax highlighting can be found here
| |
| | | |
− | <pre>
| |
− | # Copyright (c) 2011, 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 IO::Socket::INET6;
| |
− | use Module::Load;
| |
− |
| |
− | $version = "Nanobot 3.0 beta 5";
| |
− | $server = 'irc.insomnia247.nl'; # Hostname, IPv4 or IPv6 address.
| |
− | $port = 6667;
| |
− | $sslport = 6669;
| |
− | $botnick = 'nanobot'; # Bots nickname
| |
− | $botuser = 'nanobot'; # Bots username
| |
− | $nsp = ''; # NickServ pasword (if not registered, leave empty)
| |
− | @channels = ("#bots", "#yourchannel");
| |
− | @opers = ("insomnia247.nl", "rootedker.nl", "fbi.gov", "eye.spy"); # Oper(s) hostmask(s)
| |
− | $modchan = '#yourchannel';
| |
− | $datadir = 'botdata';
| |
− | $moddir = 'modules';
| |
− | @autoload = (); # List modules to load on startup. Example: @autoload("mymodule", "kickban");
| |
− | $wisecrack_seen_botnick = "I'm right here. I mean ... really, how did you miss that one?";
| |
− | $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 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.");
| |
− | }
| |
− | }
| |
− |
| |
− | ##### !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);
| |
− | }
| |
− | </pre>
| |