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>
| |