#!/usr/bin/perl use Socket; use Time::Local; use Sys::Hostname; use Time::HiRes qw(sleep); use Unicode::String qw(latin1 utf8); use LWP::Simple; use IO::Handle; use URI::URL; use warnings; use threads; use Meteoalarm; open(DATEI, "channels.txt"); $diachans = ; $diachans =~ s/##*/#/g; @channels = split(" ",$diachans); my $debug = 1; my $master = 'majo'; my $master2 = 'Master'; my $master3 = 'thom'; my $schan="#sys-thx"; $uptimer=time(); my %conf; $SIG{CHLD} = 'IGNORE'; my $hostname = Sys::Hostname::hostname(); my $nick = "ChannelWatcher"; my $pw = "27742774"; @joininfo=('ChannelWatcher - To Protect and Serve (c) 2017'); my ($remote, $local, $port, $iaddr, $paddr, $proto, $line, $myhost); my $nl = "\015\012"; # You should specify a default server in $remote $remote = shift || '127.0.0.1'; $local = "127.0.0.1"; $port = shift || 6669; my $uptimechan = shift || '#sys-thx'; my %chans; $chans{lc $uptimechan} = 1; if ($port =~ /\D/) { $port = getservbyname($port, 'tcp') } die "No port" unless $port; $iaddr = inet_aton($remote) || die "no host: $remote"; $paddr = sockaddr_in($port, $iaddr); $proto = getprotobyname('tcp'); if (not $debug) { exit if fork(); } close(STDIN) unless $debug; close(STDOUT) unless $debug; socket(IRC, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; bind(IRC, sockaddr_in(0, inet_aton($local))) unless $local == undef; connect(IRC, $paddr) || die "connect: $!"; #IRC->autoflush(1); { my $ofh = select(IRC); $|=1; select($ofh); } sub gracefully_die { my ($restarting) = @_; if ($restarting) { exec "perl sBot-restarter.pl"; } else { exit; } } ircsend("NICK $nick"); ircsend("USER Cygnus ServerBot $hostname :ServerAdmin / ServerBot"); #handle the first ping. #this one is really important to get right #b/c it is used by the server to make sure you're #not just spoofing (or using certain kinds of blind proxies) while(my $line = ) { print " >> $line" if $debug; if($line =~ /^PING :(\S+)/ || $line =~ /^PING\s*(\S*)/ || $line =~ /^PING/ || $line=~ /^PING \:(.*)/) { # if($line =~ /^PING\s*(\S*)/i) { ircsend("PONG :$1"); } # if server tells us we're logged in, break loop #els if($line =~ /(376|422) $nick/) { last; } } ircsend("NickServ IDENTIFY"); #timer do "timers.pl"; foreach(@channels){ my @channels=quotemeta($_); $_=utf8($_)->latin1; ircsend("JOIN $_"); privmsg($_, "@joininfo"); } #start the pingtimer and #set the handler for the #alarm signal as the pingtimer $SIG{ALRM} = \&pingtimer; # nee sigalrm alarm 60; irchandle(); #shouldn't ever get here, as irchandle becomes the main loop. close(IRC); sub ircsend { my $a = shift; $a=utf8($a)->latin1; print IRC $a, $nl; print " << ", $a, "\n" if $debug; } sub notice { my $user = shift; $x=utf8($x)->latin1; while(my $x=shift) { ircsend("NOTICE $user :$x");} } sub privmsg { my $user = shift; $x=utf8($x)->latin1; while(my $x=shift) { ircsend("PRIVMSG $user :$x");} } sub writeHash { my $hash = $_[0]; my $file = $_[1]; open HASH, ">$file"; my @keys = keys(%$hash); my @values = values(%$hash); for(my $i=0; $i<@keys; $i++) { if($values[$i][0]) { chomp $keys[$i]; print HASH $keys[$i], " =[ "; foreach my $atom (@{$values[$i]}) { print HASH $atom, ", "; } print HASH "\n"; } else { chomp $keys[$i]; chomp $values[$i]; print HASH $keys[$i], " = ", $values[$i], "\n"; } } close HASH; } sub readHash { my $file = $_[0]; my %hash; open HASH, $file; while(my $line = ) { if($line =~ / =\[ /) { my ($key, $value) = split(/ =\[ /, $line); chomp $key; chomp $value; $hash{$key} = [ split(/, /, $value) ]; } else { my ($key, $value) = split(/ = /, $line); chomp $key; chomp $value; $hash{$key} = $value; } } close HASH; return (%hash); } sub auth($) { my ($in) = @_; #$in =~ /^:(.+?)\s/; #my $ident = $1; my @ident = split(/\!|\@/, $in); foreach my $x (@auth) { my @x = split(/\!|\@/, $x); my $ok = 1; for(my $i=0; $i<@x; $i++) { if($x[$i] eq "*") { next; } elsif($x[$i] =~ /^\*(.*)/) { $ok=0 unless $ident[$i] =~ /$1$/i; } elsif($x[$i] =~ /(.*)\*$/) { $ok=0 unless $ident[$i] =~ /^$1/i; } else { $ok=0 unless lc $ident[$i] eq lc $x[$i]; } last unless $ok; } return 1 if $ok == 1; } return 0; } $start=time; ######################################### sub irchandle() { my $in = shift; LINE: while(my $in = ) { chomp $in; $in =~ s/\r//g; print " >> $in\n" if $debug; if ($in =~ /^PING \:(.*)/ || $in =~ /^PING :/) { ircsend("PONG :$1"); } if($in =~ /^:(.*?)!.* NICK :(\S+)/) { if($nick eq $1) { $nick = $2; } next; } $myhost = $1 if($in =~ /^:(\S+) 001 \Q$nick\E/); if($in =~ /:(.*?)!.*(PRIVMSG|NOTICE) $nick\s*:\001(\S+) (.*?)\001?$/i) { my ($user, $op, $msg) = ($1, $3, $4); notice($conf{"Debugger"}, $user, $msg) if $conf{"Debug"}; next LINE; } #diverse scripte do "subs.pl"; #Lastseen saving if($in =~ /:(.*?)!.* JOIN \s*:(.*)/i or $in =~ /:(.*?)!.* PART \s*(.*)/i or $in =~ /:(.*?)!.* QUIT \s*(.*)/i or $in =~ /:(.*?)!.* KICK \s*(.*)/i) { my ($juser, $jchan, $jmsg) = ($1, $2, $3); ($host,$statein,$bchan)=split(/ /,$in); lastseenup("$juser/$jchan/$statein/$host"); } #(#\S+)\s* channel #(.*) oder \s*(.*) user if($in =~ /:(.*?)!.*MODE (#\S+)\s* -o (.*)/i) { my ($user, $chan, $msg, $vict) = ($1, $2, $3, $4); #vict übergabe an script do "reopscript.pl"; } if($in =~ /:(.*?)!.* JOIN \s*:(.*)/i) { do "userstate.pl"; } #if($in =~ /311 $nick \s*(.*) (.*) (.*) :(.*)/i) { # my ($user, $msg, $vict, $reln) = ($1, $2, $3, $4); #vict übergabe an script #privmsg($schan, "[WhoisScript] >> Host $msg $vict"); # } if($in =~ /319 $nick \s*(.*) (.*)/i) { my ($user, $chan, $msg, $vict) = ($1, $2, $3, $4); #vict übergabe an script privmsg($lastchan, "[WhoisScript] >> Channels $user"); } #if($in =~ /312 $nick \s*(.*) (.*)/i) { save wegen zeichen if($in =~ /307 $nick \s*(.*) :(.*)/i) { my ($user, $vict) = ($1, $2, $3, $4); #vict übergabe an script $vict =~ s/is a registered nick/Yes/; privmsg($lastchan, "[WhoisScript] >> Registered? $vict"); } if($in =~ /378 $nick \s*(.*) :(.*)/i) { my ($user, $vict) = ($1, $2, $3, $4); #vict übergabe an script ($host,$statein,$bchan,$hos,$rip)=split(/ /,$vict); privmsg($lastchan, "[WhoisScript] >> Host $host $statein $bchan $hos"); privmsg($lastchan, "[WhoisScript] >> IP $rip"); } if($in =~ /353 $nick = (#\S+)\s* :(.*)/i) { my ($user, $vict) = ($1, $2, $3, $4); #vict übergabe an script if ($lastchan eq ""){ privmsg($schan, "[InfoScript] >> Channel: $user"); privmsg($schan, "[InfoScript] >> Users: $vict"); }else{ privmsg($lastchan, "[InfoScript] >> Channel: $user"); privmsg($lastchan, "[InfoScript] >> Users: $vict"); }} if($in =~ /:(.*?)!.* KICK (#\S+)\s*:(.*)/i) { my ($user, $chan, $msg) = ($1, $2, $3); privmsg($chan, "1.kick"); $kickcount=0; push(@kicked,$jldat[2]); foreach $_ (@kicked){ #if (lc($_) eq lc(@jldat[2])){ if (lc($_) eq lc($jldat[2])){ $kickcount++; privmsg($chan, "2.kick"); }} if ($kickcount == 3){ privmsg($chan, "Floodversuch erkannt! 3x gekickt nun Ban!"); ircsend("KICK $chan $_"); foreach $_ (@kicked){ #if (lc($_) ne lc(@jldat[2])){ if (lc($_) ne lc($jldat[2])){ push(@newkicked,$_); }} @kicked=@newkicked; @newkicked=(); }} ###badworderkennung ######################################################DIA######################################################################################## ############################################################################################################################################## $tes = '#sys-thx'; if($in =~ /:(.*?)!.*PRIVMSG $nick :(.*)/i) { $dia = 1; my ($diauser, $diatext, $msg) = ($1, $2, $3); if ($dia == 1){ privmsg($tes, "(DiaScript) >> ($diauser): $diatext "); } } ######################################################DIA ENDE######################################################################################## ############################################################################################################################################## if($in =~ /:(.*?)!.*PRIVMSG (#\S+)\s*:(.*)/i) { my ($user, $chan, $msg) = ($1, $2, $3); do "badwordscript.pl"; do "floodproscript.pl"; } if($in =~ /:(.*?)!.*PRIVMSG (#\S+)\s*:(.*)/i) { my ($user, $chan, $msg) = ($1, $2, $3); #print "$user, $chan, $msg"; #uscom do 'uscom.pl'; #zugangskontrolle do "zugangskontrolle.pl"; #datenbanken do "datenbanken.pl"; #switches do "switches.pl"; #newsletter #do "newsle.pl"; #versuchsscript #do "versuch.pl"; #normale channelcommands do "chacom.pl"; #wetterscript do "wetter.pl"; #load telegram modul do "telegr.pl"; ####Master-Admin-Befehle if(lc($user) eq lc($master) || lc($user) eq lc($master2)){ if (lc(substr($msg,0,6)) eq "!close" || lc(substr($msg,0,9)) eq "!shutdown" || lc(substr($msg,0,5)) eq "!kill" || lc(substr($msg,0,5)) eq "!quit"){ privmsg($chan, "(ShutDown-System) (Beende alle verbindungen...)"); die "closed by $user"; } if (lc(substr($msg,0,8)) eq "!restart" || lc(substr($msg,0,7)) eq "!reboot"){ privmsg($chan, "(Shutdown-System) (Bot startet neu!)"); sleep(1); privmsg($chan, "(Shutdown-System) (Beende alle aktiven Module...)"); do "sBot-restarter.pl"; die "closed by master"; } }#ende master if(($msg =~ /^lusers/i) or ($msg =~ /^!lusers/i)) { my $users = qx/users/; $users =~ s/\n//; $users = join(' ', unique(split(/ /, $users))); privmsg($chan, "Users logged onto $hostname: ".$users); next; } } # if($in =~ /:$myhost .*(PRIVMSG|NOTICE) $nick\s*:(.*)/i) { if($in =~ /:$remote .*(PRIVMSG|NOTICE) $nick\s*:(.*)/i) { my $msg = $2; } } gracefully_die(1); } sub writeArray { my $array = $_[0]; my $file = $_[1]; open ARRAY, ">$file"; foreach my $x (@$array) { print ARRAY $x . "\n"; } close ARRAY; } sub readArray { my $file = $_[0]; my @array; open ARRAY, $file; while(my $x = ) { chomp $x; push @array, $x; } close ARRAY; return (@array); } sub pingtimer { # nee sigalrm ircsend("PING :$remote"); alarm 60; } #we don't actually call this from anywhere #but the SCnet implementation seems to need #it to handle when the socket is closed on us #due to a kill. sub sigpipe { graceful_die(1); #if $child; } sub unique(@) { my (@input_array) = @_; my %seen; foreach my $item (@input_array) { $seen{$item}++; } #return sort(keys(%seen)); return map("$_($seen{$_})", sort(keys(%seen))); } undef $alv; undef $propthread;