Difference between revisions of "Nanobot source"

From Insomnia 24/7 Wiki
Jump to: navigation, search
imported>Wikiadmin
(Git repository)
 
(9 intermediate revisions by one other user not shown)
Line 1: Line 1:
== Source code listing for nanobot ==
+
== Git repository ==
:Code with syntax highlighting can be found [http://www.insomnia247.nl/g/?dir=p&file=nanobot&ext=pl&type=perl here]
+
The info page is on our [https://git.insomnia247.nl/coolfire/nanobot4 Gitlab].
:Perl file can be found [http://www.insomnia247.nl/projects/nanobot.pl here]
 
  
<pre>
+
If you are looking to clone the repo:
# Copyright (c) 2010, Insomnia 24/7 All rights reserved.
+
  git clone https://git.insomnia247.nl/coolfire/nanobot4.git
# Redistribution and use in source and binary forms, with or without
+
 
# modification, are permitted provided that the following conditions are met:
+
== Download .tar.gz ==  
   
+
  https://gitlab.insomnia247.nl/coolfire/nanobot4/repository/archive.tar.gz
# 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
+
== Bugtracker ==
# the following disclaimer in the documentation and/or other materials
+
We use our own [http://insomnia247.nl/redmine/projects/nanobot4/ Redmine] to keep track of bugs and feature requests.
# 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";
 
$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";
 
&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);
 
}
 
</pre>
 

Latest revision as of 20:18, 8 June 2020

Git repository

The info page is on our Gitlab.

If you are looking to clone the repo:

git clone https://git.insomnia247.nl/coolfire/nanobot4.git

Download .tar.gz

https://gitlab.insomnia247.nl/coolfire/nanobot4/repository/archive.tar.gz


Bugtracker

We use our own Redmine to keep track of bugs and feature requests.