diff options
Diffstat (limited to 'scripts/findbot.pl')
| -rw-r--r-- | scripts/findbot.pl | 964 | 
1 files changed, 964 insertions, 0 deletions
| diff --git a/scripts/findbot.pl b/scripts/findbot.pl new file mode 100644 index 0000000..9f79259 --- /dev/null +++ b/scripts/findbot.pl @@ -0,0 +1,964 @@ +############################################################################### +# Find script that searches your local files and sends them to users +# Copyright (C) 2003  Thomas Karlsson +# +# Findbot script, which responds to @find commands in irc channels +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA +# +# Thomas Karlsson (findbot@planet.eu.org) +############################################################################### +# The file collection at the end of this file is made by Henrik Andreasson +# findbot@han.pp.se +#  +############################################################################### +# Description: +# +# This script loads into an Irssi client and then monitors selected channels +# and replies to public channel commands. +# The commands are: +# @find :	searches the summaryfile after file "@find birthday" looks for +#		a file containing birthday. +# @<botnick>-stats : Replies with the users queue. +# @<botnick>-remove : Will remove the users whole queue +# @<botnick>-remove 2 : Will remove queue position 2 from the queue +# @<botnick>-help : Will message the help to the user. +# !<botnick> <filename> :Will queue the file. For eg."!santa_claus jingle.bells.mp3" +# +############################################################################### +# Installation: +# +# AT THE END OF THIS FILE IS ALL INSTALLATION INSTRUCTIONS!! +#  +# Variables: +# findbot_channels - Space separated channels (#mp3 #othermp3) +# findbot_summaryfile - Full path to the "mymp3s.txt" file (/misc/mp3/mymp3s.txt) +# findbot_sendlist - Full path and filename to the list that is sent to clients +# findbot_maxresults - Max findresults returned to the requesting client +# findbot_maxqueue - Max files allowed in the queue +# findbot_maxsends - Max simultanous sends allowed +# findbot_maxuserqueue - Max queued files per Nick +# findbot_maxusersends - Max simultanous sends per Nick +# findbot_showbanner - Present a banner in every "findbot_channels" channel +# findbot_bannertime - How many seconds between each banner +# findbot_minspeed - Minimum CPS for a send, 10000 means 10kb/s, 0 means disabled +# findbot_mustbeinchannel - If ON, the user is required to be in the channel during download +# findbot_debuglevel - Debuglevel, Higher value equals more debugoutput +# findbot_enabled - Set ON or OFF +# findbot_timeslots - When the server should be enabled (sat=10:00-18:00sun=00:00-23:59) +#		      If a day can't be found the bot will be ON by default +# findbot_voicegetpriority - If ON then voiceuserusers and ops will get priority in the queue. +#			Ops get 20 in priority and voice gets 10. I.e ops are more prioritized than voice +# +# Admincommands: +# /findbotqueue  - Shows you the whole queue in the findbot window +# /findbotremove - Admin removes queueitems +# /findbotreset  - If you like you can specify how many sends the script thinks it have. This was just added +#                  if you wanted to send somefiles your self without the script sending files. +# /findbotreload - Reloads the summaryfile if you have added files +# /findbotactivesends - Show which users are currently having a download +# +############################################################################### +# TODO or maybe features +# +# * When requesting it SHOULD be case sensitive +# * Support CTCP SLOTS and CTCP MP3, seems unnecessary to help windows-mirc users :) +#   Slots Free Next Queues Max Sendspeed Files +#   4     4    NOW  0      999 0         120575 36856591362 0 1073595728 1 +# * Make an ignore and ban function +# * Should the users see the whole que or just their own files? +# * If there is a netsplit all downloads will be cancelled if an active user disappered +# * If one send is below like 4kb/s then change findbot_maxsends to one more, so we use the bandwidth +# * DONE Servers (i.e +v) should get priority, but how? First in queue? +# * DONE Fix admin_showqueue to really show VIP instead of 1 +############################################################################### +# CHANGES +# +# 1.57	* Added a VIP function which allows +v users to be first in line to get a file +# 	* Remove a users queue if they get kicked (only if findbot_mustbeinchannel is ON) +#	* Fixed a bug when a user with a download changed nick. +# 1.56  * The findbot_maxqueue now works +#	* Sending files with spaces in them, now works +# 1.55	* Minor changes +# 1.54	* Added support to update the mp3list without restarting the bot (/findbotreload) +# 1.53	* Fixed some debug output +# 1.52	* Fixed some typos +#	* Now people can't look for * . etc. Now a searchpattern MUST contain atleast 1 normal character +#	* Fixed so you can change banner time without restarting the bot +# 1.50	* Added a timeslot function +#	* Added logging support. Now logging to file. Must specify filename and path INSIDE this script +# 1.06	* "Optimized" search. Instead of opening and read the whole summaryfile everytime +#	  someone searched the script reads the file once at startup. +#	* Fixed more regular expressions +#	* Added multiserver support, i.e you can have the bot on two nets and two different channels +# 1.05	* Added a new perlscript at the end of this file. +#	  It searches your mp3s and makes the 2 necessary files. +#	  The script is made by Henrik Andreasson (findbot@han.pp.se) +# 1.04	* Changed so the files contains full path to mp3s +#	* findbot_maxsends was ignored under some circumstanses +#	* Added so debugoutput shows which file are sent +#	* Sending to client "Now sending you file...." only if they accually are in the channel +# 1.03	* Changed a "for-loop" one bit +#	* If findbot_minimumspeed was disabled, then the user could leave channel +#	  and still get files even if findbot_mustbeinchannel was enabled +#	* Forgot to write to debugwindow if someone downloaded the whole list +#	* Corrected some bad english :) +#	* Fixed more regular expressions +#	* The user will be told the queueposition when requesting a file +#	* Fixed some queueproblems +#	* Added some errormessages if someone types !nickname in a private message +# 1.01	* Do not reply with "no match" if no match was found to avoid unnecessary spam +#	* Removed alot of commented code +#	* Changed the description of the script +#	* Changed the "results found" string a bit. +#	* Added a new value findbot_sendlist and separated the filelist and the one which accually is sent to the users +#	* Fixed some regular expressions to fit the new searchfiles +#	* Bug fix. If someone resumed a file, they always will be under findbot_minspeed in the start +#	* Didn't search if someone typed @FIND (in uppercase) +#	* Ops the url wasn't right. There is no ~ in the address :) +# 1.0	Release +############################################################################### +use Irssi; +use Irssi::Irc; +use strict; +use vars qw($VERSION %IRSSI); + +$VERSION = "1.57"; + +%IRSSI = ( +    authors     =>  "Thomas Karlsson", +    contact     =>  "findbot\@planet.eu.org", +    name        =>  "Findbot", +    description =>  "Public command \@find script", +    license     =>  "GPL", +    url         =>  "http://hem.passagen.se/thka2315/", +); + +my %nickqueue = ();	# Queuenumber + nickname +my %filequeue = ();	# Queuenumber + filename +my %servertagqueue = (); # Queuenumber + array with servertag,voiceprio,extrafield +my %activesends = ();	# nickname + 1 The user is here if he has an active send +my $lastqueuenumber = 0;	# Holds the last queueitem +my %scriptdetect = (); +my $timeout_tag; +my $banner_timeout; +my $currentsends = 0; +my $servertag; +my $globalstart = 0; +my $globalvippos = 0; +my $debuglevel; +my %bannedpeople = ();	# This will contain banned people and time of ban +my @bigarray;		# In here the whole filelist will reside +my @daynames = qw(Sun Mon Tue Wed Thu Fri Sat); +my $logfile = "findbot.log"; +my $scriptdetecttime = "3"; # Three seconds must pass before a new filerequest is issued, after a DCC CLOSE +my $showscriptdetect = 1; +my $lastbannerprint = time();	# The last time the banner was printed into monitored channels + +sub timeslotenabled { +	my $weekday = shift;		# Save weekday +	my $slothour = shift;		# Save hours +	my $slotminute = shift;		# Save minutes + +	$weekday = $daynames[$weekday]; +	my $timeslotstring = Irssi::settings_get_str('findbot_timeslots'); +	if ( $timeslotstring =~ /$weekday/i ) { +		if ( $timeslotstring =~ m/.*$weekday=(.?.):(.?.)(a\.?m\.?|p\.?m\.?)?-(.?.):(.?.)(a\.?m\.?|p\.?m\.?)?.*/i ) { +			my $fromhour = $1; +			my $frommin = $2; +			my $fromampm = $3; +			my $tohour = $4; +			my $tomin = $5; +			my $toampm = $6; +			if ( $fromampm =~ /p/i ) { $fromhour += 12; }		# If it is a pm time add 12 to get 24h format +			if ( $toampm =~ /p/i ) { $tohour += 12; }		# If it is a pm time add 12 to get 24h format +			my $midnightfrom = ( $fromhour * 60 ) + $frommin;		# Get minutes from midnight +			my $midnightto = ( $tohour * 60 ) + $tomin;		# Get minutes from midnight +			my $inputtime = ( $slothour * 60 ) + $slotminute;		# Get minutes from midnight +			debugprint(20,"inputtime:$inputtime midfrom:$midnightfrom midto:$midnightto"); +			if ( $inputtime <= $midnightto && $inputtime >= $midnightfrom ) { +				return 1;					# The time is between the timeenabled slot +			} else { +				return 0;					# Time was outside. Bot should be off. +			} +		} else { +			return 0;	# Hmm didnt get the times in that day, maybe wrong input from user +		}	 +	} else { +		return 1;	# If the current day wasn't found in findbot_timeslots then return true, i.e bot is default ON. +	} +	return 0;		# Return false i.e  +} + +sub private_get { +	(my $server, my $message, my $nick, my $address) = @_; +	if ( $message =~ /^!$server->{nick}\ .*/i ) { +		$server->command("/MSG " . $nick . " Please request files in the channel, not personally to me. Type \@$server->{nick}-help in channel for help"); +	} elsif ( $message =~ /^\@$server->{nick}.*/i ) { +		$server->command("/MSG " . $nick . " Please request my filelist in the channel, not personally to me. Type \@$server->{nick}-help in channel for help"); +	} elsif ( $message =~ /^\@find.*/i ) { +		$server->command("/MSG " . $nick . " Please search files in the channel, not personally to me. Type \@$server->{nick}-help in channel for help"); +	} +} + +sub check_user_queued_items { +	my $user = shift;					# Get the nickname to check +	my $localsrvtag = shift; +	my $counter = 0;					# Reset the counter +	for ( my $i=1; $i <= $lastqueuenumber; $i++ ) { # Loop through entire queue +		if ( $nickqueue{$i} eq $user && $localsrvtag eq $servertagqueue{$i}[0] ) { +			$counter++; +		} +	} +	return $counter; +} + +sub already_queued_file { +	my $checknick = shift; +	my $checkfile = shift; +	my $srvtag = shift; +	my $alreadyqueued = 0; +	for ( my $i=1; $i <= $lastqueuenumber; $i++ ) {	# Loop through entire queue +		if ( $nickqueue{$i} eq $checknick && $filequeue{$i} eq $checkfile && $servertagqueue{$i}[0] eq $srvtag) { # Check if its queued +			$alreadyqueued = 1;		# Yep it was +		} +	} +	if ( $alreadyqueued ) { return 1; } else { return 0; } # Return true if queued else false +} + +sub add_file_to_queue { +	(my $addnick, my $addfile, my $srvtag, my $priority) = @_;			# Split nickname and filename into two variables +	$lastqueuenumber++; +	$nickqueue{$lastqueuenumber} = $addnick;	# for eg. $nickqueue{1} = 'El_Tomten' +	$filequeue{$lastqueuenumber} = $addfile;	# for eg. $filequeue{1} = '/misc/legal-mp3s/happy.birthday.mp3' +	if ( ! Irssi::settings_get_bool('findbot_voicegetpriority') ) { $priority = 0; } +	my @field = ($srvtag,$priority,"To be used later, maybe"); +	$servertagqueue{$lastqueuenumber} = \@field;	# for eg. $servertagqueue{1} = 'stockholm' +	if ( $priority > 1 ) {		# Did a priority user queued the file +		fix_vip_position($priority);	# Move vip position up to number one, or just after the last already existing vip position +	} +} + +sub fix_vip_position { +	my $priority = shift;		# Get priority from input +	my ($tnickqueue,$tfilequeue,$tservertagqueue); +	if ( $lastqueuenumber eq 1 ) { return; }	# If the queue only have one entry, why try to make it a priority? +	for ( my $i = $lastqueuenumber; $i > 1; $i--) { +		if ( $servertagqueue{$i-1}[1] >= $priority ) { $globalvippos = $i; last; } # Is the queue entry before a vip entry? Lets quit the prioritymove +		$tnickqueue = $nickqueue{$i-1};			# Backup entry +		$tfilequeue = $filequeue{$i-1}; +		$tservertagqueue = $servertagqueue{$i-1}; + +		$nickqueue{$i-1} = $nickqueue{$i};		# Move entry up +		$filequeue{$i-1} = $filequeue{$i}; +		$servertagqueue{$i-1} = $servertagqueue{$i}; +		 +		$nickqueue{$i} = $tnickqueue;			# Restore entry ( the two entris have now changed place ) +		$filequeue{$i} = $tfilequeue; +		$servertagqueue{$i} = $tservertagqueue; +	} +} + +sub remove_queueitem { +	my $queueitem = shift; +	if (defined($nickqueue{$queueitem}) && defined($filequeue{$queueitem} && defined($servertagqueue{$queueitem})) ) { # Is there really a queueitem here? +		for ( my $i = $queueitem; $i <= Irssi::settings_get_int('findbot_maxqueue'); $i++) { +			if ( defined($nickqueue{$i+1}) && defined($filequeue{$i+1}) && defined($servertagqueue{$i+1}) ) { # Move up in queue if there is one +				$nickqueue{$i} = $nickqueue{$i+1};			# Move up in queue +				$filequeue{$i} = $filequeue{$i+1};			# Move up in queue +				$servertagqueue{$i} = $servertagqueue{$i+1};		# Move up in queue +			} +				 +		} +		delete $nickqueue{$lastqueuenumber};		# Delete the last entry. It has been moved up one slot +		delete $filequeue{$lastqueuenumber};		# Delete the last entry. It has been moved up one slot +		delete $servertagqueue{$lastqueuenumber};	# Delete the last entry. It has been moved up one slot +		$lastqueuenumber--;				# Since we removed a queue item the lastqueuenumber decreases +	} else { debugprint(10,"debug: No remove $queueitem"); } +} + +sub user_have_max_active_sends { +	my $nickname = shift;					# Save the nick +	my $localserver = shift;				# Save current servertag +	if ( $activesends{$nickname} < Irssi::settings_get_int('findbot_maxusersends') ) { +		return 0;					# The user didn't have enough sends +	} else { +		return 1;					# The user have NOT an active send +	} +} + +sub user_is_in_active_channel { +	my $nickname = shift; +	my $srvtag = shift; +	my $find_channels = Irssi::settings_get_str('findbot_channels'); # What channels to monitor +        my @checkchannels = split (/ /, $find_channels); # Split into an array + +	foreach my $localserver ( Irssi::servers() ) {		# Loop through all connected servers +		foreach my $singlechan ( @checkchannels ) {	# Loop through all monitored channels +			my $channel = $localserver->channel_find($singlechan);	# Get a channelobject +			if ( defined($channel) && defined($channel->nick_find($nickname)) ) {	# Is the nick there? +				return 1;	# User are in monitored channels # Yep is was +			}  +        	} +	} +		return 0;	# User have left monitored channels + +} + +sub nicefilename { +        my $filename = shift; + +        if ( $filename =~ /.*\/(.*)\ *:.*/g ) { # If filelist is made by "file" +		debugprint(15,"Summary file is made by the program file"); +                return $1; +        } elsif ( $filename =~ /.*\/(.*)$/g ) { # If filelist is Not made by file +		debugprint(15,"Summary file is NOT made by the program file"); +                return $1; +        } +} + +sub strippath { +	my $filename = shift;			# Get parameter into $filename + +	$filename =~ s/.*\/(.*)/$1/g;		# Remove everything until the last / +	return $filename;			# Return the stripped line +} + +sub debugprint { +	(my $dbglvl,my $debugmessage) = @_;	# Save input to variables +	$debuglevel = Irssi::settings_get_int('findbot_debuglevel'); +	my $win; +	if ( ! ($win = Irssi::window_find_name($IRSSI{name})) ) { # If the windows doesn't exist +		$win = Irssi::Windowitem::window_create($IRSSI{name},1); +	} +	if ( $dbglvl <= $debuglevel ) { +		$win->set_name($IRSSI{name});	# Select the window +		$win->print($debugmessage,MSGLEVEL_CLIENTCRAP); +		my $debugtid = localtime(time); +		open (LOGFILE,">> $logfile"); +                print LOGFILE "$debugtid: $debugmessage\n"; +                close (LOGFILE); +	} +} + +sub process_queue { +	if (Irssi::settings_get_bool('findbot_enabled') ) { # Is the findbot enabled? +		my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); # Get current time +		if ( ! timeslotenabled($wday,$hour,$min) ) {		# If NOT true the bot is offline +			debugprint(15,"The bot is Offline due to timerestrictions in findbot_timeslots"); +			return 0; +		} +		print_banner(); +		if ( $currentsends < Irssi::settings_get_int('findbot_maxsends') ) {    # Check if we'll send another file simultanously +			my $i = 1; +			while ( $i <= $lastqueuenumber ) { +				if ( ! user_have_max_active_sends($nickqueue{$i},$servertagqueue{$i}[0]) ) { # If NOT user have max active sends +					my $nicefile = nicefilename($filequeue{$i}); +					if ( user_is_in_active_channel($nickqueue{$i},$servertagqueue{$i}[0]) ) { # Are the user in a monitored channel? +						debugprint(10,"[ADMIN] $nickqueue{$i} are in monitored channels, sending $nicefile"); +						my $localserver = Irssi::server_find_tag($servertagqueue{$i}[0]); +						$localserver->command("/QUOTE NOTICE " . $nickqueue{$i} . " :Sending you the requested file: $nicefile"); +						$localserver->command("/DCC SEND $nickqueue{$i} \"$filequeue{$i}\"" ); +						remove_queueitem($i); +						last;	# Exit the loop +					} else { +						debugprint(10,"[ADMIN] $nickqueue{$i} is NOT in monitored channels. Removing queueentry $filequeue{$i}"); +						remove_queueitem($i); +					 } # Remove the queued item if the user have parted the channel +				} else { # A user had too many sends, increase $i by one to check next queue pos. +					$i++;	# Increase by one so we can loop through whole queue +				} +			} # End while or for +		} +	} +	check_dcc_speed_and_in_channel();			# Check minimumspeed +} + +sub dcc_created { +	(my $dcc) = @_;	# Put active dcc in variable + +	debugprint(15,"dcc_created was called"); +	if ( $dcc->{type} eq "SEND" ) {				# Is it a SEND? +		if ( defined( $activesends{$dcc->{nick}} ) ) { +			$activesends{$dcc->{nick}} = $activesends{$dcc->{nick}} + 1; +		} else { +			$activesends{$dcc->{nick}} = 1; +		} +		$currentsends++; +	} +} + +sub dcc_closed { +	(my $dcc) = @_; # Put active dcc in variable + +	debugprint(15,"dcc_closed was called"); +	if ( $dcc->{type} eq "SEND" && defined ($activesends{$dcc->{nick}}) ) {	# Is it a SEND and a findbot SEND? +		my $tiden = time(); +		$tiden = $tiden - $dcc->{starttime}; +		if ( $tiden > 0 ) { +			my $kbsec = $dcc->{transfd} / $tiden; +		} else { +			$tiden = 1; +			my $kbsec = $dcc->{transfd} / $tiden; +		} +		if ( $dcc->{transfd} == 0 ) {		# If transfered byts are zero, then it was probably aborted +			debugprint(10,"[ADMIN] SEND aborted Nick: $dcc->{nick} File: $dcc->{arg}"); +		} else { +			debugprint(10,"[ADMIN] SEND done Nick: $dcc->{nick} File: $dcc->{arg} Bytes: $dcc->{transfd} Time(sec): $tiden Speed: " . calc_kb_sec($tiden,$dcc->{transfd}) . " KB/s"); +		} +		if ($activesends{$dcc->{nick}} == 1) { +			delete $activesends{$dcc->{nick}}; +		} else { +			 $activesends{$dcc->{nick}} = $activesends{$dcc->{nick}} - 1; +		} +		$currentsends--; +		$scriptdetect{$dcc->{nick}} = time();		# Record the time when dcc was closed +	} +} + +sub calc_kb_sec { +	my $seco = shift; +	my $bytest = shift; + +my 	$kbsec = $bytest / $seco / 1000; +	$kbsec =~ s/(.*\..?.?).*/$1/; + +	return $kbsec; +} + +sub dcc_destroyed { +        (my $dcc) = @_; # Put active dcc in variable + +	debugprint(15,"dcc_destroyed was called"); +} + +sub check_dcc_speed_and_in_channel { +#	my $localserver = Irssi::server_find_tag($servertag); # Get serverobject +	my $minimumspeed = Irssi::settings_get_int('findbot_minspeed'); +	my $channelcheck = Irssi::settings_get_bool('findbot_mustbeinchannel'); +	foreach my $dccconnection (Irssi::Irc::dccs()) { +		if ( $dccconnection->{type} eq "SEND" &&  defined($activesends{$dccconnection->{nick}}) && ($dccconnection->{transfd} - $dccconnection->{skipped}) > 50000) { # Check if its a findbot send. +			my $bytetransferred = $dccconnection->{transfd} - $dccconnection->{skipped}; +			my $timedownloaded = time() - $dccconnection->{starttime}; +			if ( $timedownloaded == 0 ) { $timedownloaded++; } # Fix for Illegal division by zero +			my $currentcps = sprintf("%02d",($bytetransferred / $timedownloaded)); # Get current CPS +			if ( $currentcps < $minimumspeed && $minimumspeed > 0 ) {	# Check if below minimumspeed +				my $localserver = Irssi::server_find_tag($dccconnection->{servertag}); +				$localserver->command("/QUOTE NOTICE $dccconnection->{nick} :Minimum CPS is $minimumspeed and you only have $currentcps. Closing your connection"); +				$localserver->command("/DCC CLOSE SEND $dccconnection->{nick}"); +				debugprint(10,"[ADMIN] $dccconnection->{nick} ($currentcps) is below minimumspeed($minimumspeed). Closing..."); +			} elsif ( $channelcheck ) { +				if ( ! user_is_in_active_channel($dccconnection->{nick},$dccconnection->{servertag}) ) { +					debugprint(10,"[ADMIN] $dccconnection->{nick} has LEFT monitored channels, closing SEND"); +					my $localserver = Irssi::server_find_tag($dccconnection->{servertag}); +					$localserver->command("/DCC CLOSE SEND $dccconnection->{nick}"); +					# Just close without warning, why bother to tell him if he's left. +				} +			} +		} +	} +} + +sub nickname_changed { +	my ($chan, $newnick, $oldnick) = @_; + +	foreach my $queuepos (keys(%nickqueue)) {	# Go through all nicks in my queuelist to see if we're affected +		if ( $nickqueue{$queuepos} eq $oldnick ) {	# Check the nick +			$nickqueue{$queuepos} = $newnick->{nick};	# Insert the new nick in that position +			debugprint(10,"[ADMIN] Nickchange $nickqueue{$queuepos} -> $newnick->{nick}"); +		} +	} +	if ( defined($activesends{$oldnick}) ) {		# He has an active send +		$activesends{$newnick->{nick}} = $activesends{$oldnick}; # Make a new entry so he can't evade the dcc speed check +		delete $activesends{$oldnick}; +	} +} + +sub user_got_kicked { +	my ($kchannel,$knick,$kkicker,$kaddress,$kreason) = @_; +	my $mustbeinchannel = Irssi::settings_get_bool('findbot_mustbeinchannel'); +	 +	if ( $mustbeinchannel ) {				# Are we to punish this kicked user? +		foreach my $queuepos (keys(%nickqueue)) {	# Go through all nicks in my queuelist to see if we're affected +			if ( $nickqueue{$queuepos} eq $knick ) {	# Check the nick if the kicked user has a queue. +				debugprint(10,"[ADMIN] $knick was KICKED. Removing queueposition $queuepos $filequeue{$queuepos}"); +				remove_queueitem($queuepos);	# Removes the users queue +			} +		} +	} +} + +sub print_banner { +	my $timenow = time(); +	my $timecalc = Irssi::settings_get_str('findbot_bannertime') + $lastbannerprint; +#	debugprint(10,"print_banner function... now: $timenow last: $lastbannerprint timecalc: $timecalc"); +	if ( $timenow > $timecalc ) { +		$lastbannerprint = time();		# Reset timer +		my $find_channels = Irssi::settings_get_str('findbot_channels'); # What channels to monitor +		my @checkchannels = split (/ /, $find_channels); # Split into an array +		if ( Irssi::settings_get_bool('findbot_showbanner') ) { # Check if I will print the banner +			debugprint(10,"[ADMIN] Sending banner to monitored channels"); +			my $showvoiceprio = "OFF"; +			if (Irssi::settings_get_bool('findbot_voicegetpriority') ) { +				$showvoiceprio = "ON"; +			} +			foreach my $localserver ( Irssi::servers() ) { +				my $bannerad = "For my list of $#bigarray files type: \@" . $localserver->{nick} . ", Sends: $currentsends/" . Irssi::settings_get_int('findbot_maxsends') . " , Queue: $lastqueuenumber/" . Irssi::settings_get_int('findbot_maxqueue') . ", Voicepriority: $showvoiceprio, For help: \@" . $localserver->{nick} . "-help"; +				foreach my $singlechan ( @checkchannels ) {	# Loop through all monitored channels +					my $channel = $localserver->channel_find($singlechan);	# Get the channelobject +					if ( defined($channel) ) { # Am I in the specific channel, if so its defined +						$channel->command("/MSG $singlechan $bannerad" . " Using: Irssi " . $IRSSI{name} . " v$VERSION"); # Print banner +					} # End if +				} # End foreach channel +			} # End foreach server +		} # End if +	} # End check if I'll print the banner +} + +sub admin_showqueue { +	debugprint(10,"[ADMIN] Show queue"); +	debugprint(10,"[ADMIN] Current sends are: $currentsends"); +	for ( my $i = 1; $i <= $lastqueuenumber; $i++ ) { # Loop through the queue +		debugprint(10,"[ADMIN] ($i) $nickqueue{$i}:$filequeue{$i}:$servertagqueue{$i}[0]:Prio $servertagqueue{$i}[1]"); +#		if ( $servertagqueue{$i}[1] > 0 ) {	# Is this a VIP entry? +#			debugprint(10,"[ADMIN] ($i) $nickqueue{$i}:$filequeue{$i}:$servertagqueue{$i}[0]:VIP queued($servertagqueue{$i}[1])"); +#		} else { +#			debugprint(10,"[ADMIN] ($i) $nickqueue{$i}:$filequeue{$i}:$servertagqueue{$i}[0]:Normal queued"); +#		} +	} +	debugprint(10,"[ADMIN] End of list"); +} + +sub admin_reset { +	my $howmany = shift; +	if ( $howmany =~ /\d+/ ) { +		$currentsends = $howmany;	# Reset current sends +		debugprint(10,"[ADMIN] Current sends are now set to $currentsends"); +	} else { +		debugprint(10,"[ADMIN] Specify how many sends there are now"); +	} +} + +#sub start_findbot { +#	my($data,$localserver,$witem) = @_; + +#	if ( $localserver != 0 ) { +#		$servertag = $localserver->{tag};		# Remeber on which server the findbot is on +#		$globalstart = 1; +#		debugprint(10,"Findserver is started"); +#	} else { +#		debugprint(10,"Please start the server in a window where I can get hold of a servertag"); +#3	} +#} + +sub admin_removequeue { +	my $queueposition = shift; +	if ( $queueposition =~ /\d+/ ) { +		remove_queueitem($queueposition); +		debugprint(10,"[ADMIN] Removed position $queueposition"); +	} else { +		debugprint(10,"[ADMIN] Specify which queueitem should be removed"); +	} +} + +sub admin_activesends { +		debugprint(10,"[ADMIN] Listing active dccsends"); +	foreach my $send (keys(%activesends)) { +		debugprint(10,"[ADMIN] $send ($activesends{$send})"); +	} +		debugprint(10,"[ADMIN] End of list"); +} + +sub admin_reload { +	if ( -r Irssi::settings_get_str('findbot_summaryfile') ) { +	        open (FINDFILE,Irssi::settings_get_str('findbot_summaryfile')); # Open the file +	        @bigarray = <FINDFILE>;                         # Load it whole into memory :) +	        close (FINDFILE); +		debugprint(10,"[ADMIN] Summary file has been reloaded into memory."); +	} else {         +	        debugprint(10,"[ADMIN] The Summaryfile cannot be read. Please check if the path is correct and the file is accually there."); +	} +} + +sub send_ctcp_slots { +# Not implemented yet +} + +sub sanitize_input { +	my $tainted_input = shift; +	$tainted_input =~ s/[\^\\\[\]\$\(\)\?\+\/\|\'\}\{]+/\./g; # Translate ^\[]$()?+ to . +	return $tainted_input;		# Return regularexpression sanitized input +} + +sub find_public { +	my ($server, $msg, $nick, $address, $targetchan) = @_;		# Save all input to variables +	my $find_channels = Irssi::settings_get_str('findbot_channels');# What channels to monitor +	my $find_file = Irssi::settings_get_str('findbot_summaryfile');	# Filename which holds all the files +	my $mp3list = Irssi::settings_get_str('findbot_sendlist');	# The nice list which is sent to users +	my $max_results = Irssi::settings_get_int('findbot_maxresults');# Get max results retured to client +	my $userqueuelimit = Irssi::settings_get_int('findbot_maxuserqueue'); # Get userqueue limit +	my $serverqueuelimit = Irssi::settings_get_int('findbot_maxqueue'); # Get server maxqueue +	my @checkchannels = split (/ /, $find_channels);		# Split into an array + +	my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); # Get current time + +	my $validchan = 0; +	foreach my $singlechan ( @checkchannels ) { +		if ( $singlechan eq $targetchan ) { +			$validchan = 1; +		} +	} + +	if ( $validchan && Irssi::settings_get_bool('findbot_enabled') && timeslotenabled($wday,$hour,$min) ) {	# Did the user say something in one of our channels? +		my $mynick = $server->{nick}; +		if ( $msg =~ /^\ *\@find\ +.+/i ) { 			# Was it a @find command? +			$msg =~ s/^\ *\@find\ (.*)/$1/i;		# Remove @find space spaces infront of it +			$msg =~ tr/*/\ /;				# Translate * to spaces +			$msg =~ s/[\ \+]+/\.\*/g;			# Translate ALL spaces to .* +			$msg = sanitize_input($msg); +			debugprint(10,"$nick is searching for $msg"); +			my @matched; +#			if ( length($msg) > 2  && $msg =~ m/[a-z]+/i) { # MUST be over 2 chars and contain atleast 1 or more normal characters +				@matched = grep (/$msg/i,@bigarray);		# Search for the matches +#			} else { +#				debugprint(10,"[ADMIN] $nick tried to search with too wide searchpattern ($msg)"); +#				return; +#			} +			my $matchcount = 0;				# Reset a counter +			my $found_results = $#matched;			# Return how many hits +			$found_results++;				# If nomatch then it is -1 +			if ( $found_results > 0 ) {	# Print number of results to the user +				debugprint(10,"Found $found_results matches"); +				$server->command("/QUOTE PRIVMSG " . $nick . " :Found $found_results matching files. Using: $IRSSI{name} v$VERSION for Irssi"); +			} +			foreach my $match (@matched) {			# Loop through each file match +				$match = strippath($match);		# Remove the path and keep filename and mp3info +				$match =~ s/:/\ \ \ :\ \ /;		# Replace the ":" with "   :  " +				if ( $matchcount < $max_results ) { 	# Is the matchlimit reached and is it a mp3 file? +					$matchcount++;			# Increase by one +					$server->command("/QUOTE PRIVMSG " . $nick . " :!$mynick $match"); +				} else {				# Limit reached! +					$server->command("/QUOTE PRIVMSG " . $nick . " :Resultlimit by " . $max_results . " reached. Download my list for more, by typing \@$server->{nick}"); +					close (FINDFILE); +					return; +				} +			} +#			if ( $matchcount == 0 ) { +#				$server->command("/QUOTE NOTICE " . $nick . " :No match found."); +#			} +		} elsif ( $msg =~ /^\ *!$server->{nick}.*/i ) {		# Send file trigger +			my $localsrvtag = $server->{tag};		# Get current servertag +			debugprint(20,"$nick tries to queue $msg");	# Just debugoutput +			$msg =~ s/\ *!$server->{nick}\ *(.*)/$1/;	# Remove the trigger +			$msg =~ tr/\(\)/\.\./;				# Translate all () to . (any char) +			$msg = sanitize_input($msg); +			my @matched = grep (/$msg/i,@bigarray);		# Get the real path from the file +			if ( $matched[0] eq "" ) { +				$server->command("/QUOTE NOTICE " . $nick . " :That file does not exist"); +				return; +			} +			my $realfile = $matched[0]; 			# Append the real path to the relative path +			$realfile =~ s/(.*)\ +:.*/$1/;			# Remove : and beyoned +			 +			my $scriptrequest = time() - $scriptdetect{$nick}; +			if ( $scriptrequest <= $scriptdetecttime && $showscriptdetect ) { +				debugprint(10,"[ADMIN] Requestscript detected on $nick"); +				# return;	#  +			} +			chomp ($realfile); +			if ( check_user_queued_items($nick,$localsrvtag) < $userqueuelimit ) { # Is it below allowed user queue limit +				if ( already_queued_file($nick,$realfile,$localsrvtag) ) { +					$server->command("/QUOTE PRIVMSG " . $nick . " :You have already queued that file!"); +				} else { +					my $priority = 1;			# Default prio +					if ( $lastqueuenumber < $serverqueuelimit ) { +						foreach my $vchannel ($server->channels()) {	# Loop through all joined channels +							if ( $vchannel->{name} eq $targetchan ) {	# Did he say it in a monitored channel +								my $nickrec = $vchannel->nick_find($nick); +								if ( $nickrec->{voice} ) { +									$priority = 10;	# A voiced user get 10 prioritypoints +								} # Voiced user? +								if ( $nickrec->{op} ) { +									$priority = 20; # An op get 20 prioritypoints +								} +								last;		# Skip rest of loop +							} +						} +						add_file_to_queue($nick,$realfile,$localsrvtag,$priority);	# Add file to queue +						if ( Irssi::settings_get_bool('findbot_voicegetpriority') && $priority > 1 ) { +							$server->command("/QUOTE PRIVMSG " . $nick . " :Added file to VIP queueposition $globalvippos."); +							debugprint(10,"[ADMIN] $nick VIP queued: $realfile"); +						} else { +							$server->command("/QUOTE PRIVMSG " . $nick . " :Added file to queueposition $lastqueuenumber."); +							debugprint(10,"[ADMIN] $nick queued: $realfile"); +						} +					} else { +						$server->command("/QUOTE PRIVMSG " . $nick . " :The serverqueue is full. Please try again in a few minutes."); +						debugprint(10,"[ADMIN] Queue is FULL."); +					} +				} +			} else {						# Tell the user the user queue limit is reached +				$server->command("/QUOTE PRIVMSG " . $nick . " :You have reached the " . $userqueuelimit . " files queue limit."); +				debugprint(10,"[ADMIN] $nick has reached his queuelimit"); +			} +		} elsif ( ($msg =~ /^\ *\@$server->{nick}-stats.*/i) || ($msg =~ /^\ *\@$server->{nick}-que.*/i) ) { +			debugprint(10,"[ADMIN] $nick checked queuepositions"); +			$server->command("/QUOTE PRIVMSG " . $nick . " :Sending you, your queuepositions"); +			for ( my $i = 1; $i <= $lastqueuenumber; $i++ ) { # Loop through the queue +				if ( $nickqueue{$i} eq $nick ) { +					my $nicefile = nicefilename($filequeue{$i}); +					$server->command("/QUOTE PRIVMSG " . $nick . " :Pos $i, $nicefile"); +				} +			} +		} elsif ( $msg =~ /^\ *\@$server->{nick}-remove.*/i ) { +			if ( $msg =~ /\ *\@$server->{nick}-remove\ *([\d]+)/ ) { # We have a number +				my $qitem = $1; +				debugprint(10,"[ADMIN] $nick is trying to remove queueposition $qitem"); +				if ( $nickqueue{$qitem} eq $nick ) {	# Check if the item is owned by the user +					remove_queueitem($qitem);	# Remove the requested queueitem +					$server->command("/QUOTE NOTICE " . $nick . " :Item $qitem has"); +				} else {	# Unauthorized removal +					debugprint(10,"[ADMIN] $nick tried to remove other peoples files from queue"); +					$server->command("/QUOTE NOTICE " . $nick . " :You can't remove other peoples queueitems"); +				} +			} else {			# We dont have a number, ie remove the whole user queue +				debugprint(10,"[ADMIN] $nick has removed all own queueitems"); +				for ( my $i = 1; $i <= $lastqueuenumber; $i++ ) { # Loop through the queue +					if ( $nickqueue{$i} eq $nick ) { +						remove_queueitem($i); +					} +				} +				$server->command("/QUOTE NOTICE " . $nick . " :Your whole queue have been deleted"); +			} +		} elsif ( $msg =~ /^\ *\@$server->{nick}$/i ) { +			if ( -r $mp3list ) {				# Check if the file is still there +				debugprint(10,"[ADMIN] $nick requested my list: $mp3list"); +				$server->command("/QUOTE NOTICE " . $nick . " :Sending you my full list..."); +				$server->command("/DCC SEND $nick $mp3list" ); +			} else { +				debugprint(5,"[WARNING] the $mp3list doesn't exist!"); +				$server->command("/QUOTE NOTICE " . $nick . " :Something wicked happened. My list has disappeared and i have notified the bot owner."); +			} +		} elsif ( ($msg =~ /^\ *\@$server->{nick}\ *help\ *$/i) || ($msg =~ /^\ *\@$server->{nick}-help\ *$/i) ) { +			debugprint(10,"[ADMIN] $nick requested HELP"); +			$server->command("/QUOTE PRIVMSG " . $nick . " :Public channel commands:"); +			$server->command("/QUOTE PRIVMSG " . $nick . " :\@find [searchpattern] : Searches my database for that file"); +			$server->command("/QUOTE PRIVMSG " . $nick . " :!$server->{nick} [file] : Queues that file and it will be sent to you when its your turn"); +			$server->command("/QUOTE PRIVMSG " . $nick . " :\@$server->{nick}-stats : Shows you your queuepositions"); +			$server->command("/QUOTE PRIVMSG " . $nick . " :\@$server->{nick}-que : Shows you your queuepositions"); +			$server->command("/QUOTE PRIVMSG " . $nick . " :\@$server->{nick}-remove : Clears all your queued files"); +			$server->command("/QUOTE PRIVMSG " . $nick . " :\@$server->{nick}-remove 2 : Clear your queueposition 2"); +			$server->command("/QUOTE PRIVMSG " . $nick . " :$IRSSI{name} v$VERSION $IRSSI{url}"); +		} else { +			return; # Just ordinary chatter +		} +	} +	return;	# Just in case +} + +sub check_vital_configuration { +	my $configerror = 0; +	if ( Irssi::settings_get_str('findbot_channels') eq "" ) { +		$configerror = 1; +		Irssi::print("The setting findbot_channels is empty."); +	} elsif (  Irssi::settings_get_str('findbot_summaryfile') eq "" ) { +		$configerror = 1; +                Irssi::print("The setting findbot_summaryfile is empty."); +	} elsif (  Irssi::settings_get_str('findbot_sendlist') eq "" ) { +		$configerror = 1; +                Irssi::print("The setting findbot_sendlist is empty."); +	} elsif (  Irssi::settings_get_int('findbot_maxresults') == 0 ) { +                $configerror = 1;          +                Irssi::print("The setting findbot_maxresults is empty."); +        } elsif (  Irssi::settings_get_int('findbot_maxqueue') == 0 ) { +                $configerror = 1;          +                Irssi::print("The setting findbot_maxqueue is empty."); +        } elsif (  Irssi::settings_get_int('findbot_maxsends') == 0 ) { +                $configerror = 1;          +                Irssi::print("The setting findbot_maxsends is empty."); +        } elsif (  Irssi::settings_get_int('findbot_maxuserqueue') == 0 ) { +                $configerror = 1;          +                Irssi::print("The setting findbot_maxuserqueue is empty."); +        } elsif (  Irssi::settings_get_int('findbot_maxusersends') == 0 ) { +                $configerror = 1;          +                Irssi::print("The setting findbot_maxusersends is empty."); +        } elsif (  Irssi::settings_get_int('findbot_bannertime') == 0 ) { +                $configerror = 1; +                Irssi::print("The setting findbot_bannertime is empty."); +        } +	if ($configerror) { +		Irssi::print("Please correct the settings first. The server will be disabled"); +		Irssi::print("You have to reload the script when the settings are correct"); +		Irssi::timeout_remove($timeout_tag); +		Irssi::timeout_remove($banner_timeout); +	} +} + +######## +# Main # +######## + +Irssi::settings_add_str("misc", "findbot_channels", "");	# Add a variable inside of irssi +Irssi::settings_add_str("misc", "findbot_summaryfile", "");	# Add a variable inside of irssi +Irssi::settings_add_int("misc", "findbot_maxresults", "");	# Add a variable inside of irssi +Irssi::settings_add_str("misc", "findbot_sendlist", "");	# Add a variable inside of irssi +Irssi::settings_add_int("misc", "findbot_maxqueue", "");	# Add a variable inside of irssi +Irssi::settings_add_int("misc", "findbot_maxsends", "");	# Add a variable inside of irssi +Irssi::settings_add_int("misc", "findbot_maxuserqueue", "");	# Add a variable inside of irssi +Irssi::settings_add_int("misc", "findbot_maxusersends", "");	# Add a variable inside of irssi +Irssi::settings_add_bool("misc", "findbot_showbanner", "");	# Add a variable inside of irssi +Irssi::settings_add_int("misc", "findbot_bannertime", "");	# Add a variable inside of irssi +Irssi::settings_add_bool("misc", "findbot_enabled", "");	# Add a variable inside of irssi +Irssi::settings_add_bool("misc", "findbot_voicegetpriority", "");	# Add a variable inside of irssi +Irssi::settings_add_int("misc", "findbot_minspeed", "");	# Add a variable inside of irssi +Irssi::settings_add_int("misc", "findbot_debuglevel", 10);	# Add a variable inside of irssi +Irssi::settings_add_bool("misc", "findbot_mustbeinchannel", ""); +Irssi::settings_add_str("misc", "findbot_timeslots", "");	# Add a variable inside of irssi +Irssi::signal_add_last('message public', 'find_public');	# Hook up a function to public chatter +Irssi::signal_add_last('message private', 'private_get');	# Hook up a function to public chatter +Irssi::signal_add_last('dcc created', 'dcc_created');		# Hook when a dcc is created +Irssi::signal_add_last('dcc closed', 'dcc_closed');		# Hook when a dcc is closed +Irssi::signal_add_last('dcc destroyed', 'dcc_destroyed'); +Irssi::signal_add('nicklist changed', 'nickname_changed'); +Irssi::signal_add('message kick', 'user_got_kicked'); +Irssi::command_bind('findbotqueue', 'admin_showqueue'); +Irssi::command_bind('findbotremove', 'admin_removequeue'); +Irssi::command_bind('findbotreset', 'admin_reset'); +Irssi::command_bind('findbotreload', 'admin_reload'); +Irssi::command_bind('findbotactivesends', 'admin_activesends'); + +check_vital_configuration();	# Run a subroutine to check all variables before starting +if ( -r Irssi::settings_get_str('findbot_summaryfile') ) { +	open (FINDFILE,Irssi::settings_get_str('findbot_summaryfile'));	# Open the file +	@bigarray = <FINDFILE>; 			# Load it whole into memory :) +	close (FINDFILE); +} else { +	debugprint(10,"The Summaryfile cannot be read. Please check if the path is correct and the file is accually there."); +} +# my $slots_timeout = Irssi::timeout_add(600000, "send_ctcp_slots", ""); # Not implemented yet +$timeout_tag = Irssi::timeout_add(5000, "process_queue", "");	# Add a timeout value the process the queue +#my $bannertime = Irssi::settings_get_int('findbot_bannertime'); +#$banner_timeout = Irssi::timeout_add($bannertime * 1000, "print_banner", ""); # Set timeout for banner +Irssi::print("Findbot script v$VERSION by $IRSSI{'authors'} loaded!"); # Show version and stuff when it has been loaded + +if ( Irssi::settings_get_bool('findbot_enabled') ) { +	Irssi::print("Findserver is Online"); +} else { +	Irssi::print("Findserver is Offline"); +} +debugprint (5,"[ADMIN] Findbot fileserver has been loaded!"); + + +############################# +# INSTALLATION INSTRUCTIONS +############################# +# - Making of the "findbot_summaryfile" and "findbot_sendlist" +# 	Run the perlscript below to create the summaryfile and sendlist +# +# - Install it in Irssi +# 	Put the script in your Irssi scripts directory (~.irssi/scripts) +# 	Start Irssi and load it. (/run findbot.pl) +# 	Now start setting all vital variables by using the command /set +#	set the "findbot_summaryfile" and "findbot_sendlist" to the files you just have created with +#	the perlscript below. +#	Dont forget to set all the other variables + + +####### Here is the script ######### + +# #!/usr/bin/perl  + +# if not supplied on cmd line this is the values +#$MP3PATH = "/misc/glftpd/site/mp3/"; +#$NICK    = "Donken"; +#($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +# +#$year    = sprintf("%04d",$year+1900); +#$mon     = sprintf("%02d",$mon + 1); +#$mday    = sprintf("%02d",$mday); +#$DATE    = "$year-$mon-$mday"; +#$LIST    = $NICK . "_mp3s_list.txt"; +#$CMD     = $NICK . "_mp3s_cmd.txt"; +#$padding = 50;	# How many pad-characters should it be +# +#if( "x" ne  "x$ARGV[0]" ){ $NICK    = $ARGV[0]; } +#if( "x" ne  "x$ARGV[1]" ){ $MP3PATH = $ARGV[1]; } +#if( "x" ne  "x$ARGV[2]" ){ $LIST    = $ARGV[2]; } +#if( "x" ne  "x$ARGV[3]" ){ $CMD     = $ARGV[3]; } +# +#print "Using nick: $NICK\n"; +#print "Finding under supplied mp3path $MP3PATH\n"; +#@INPUT=`find $MP3PATH -follow -type f`; +#print "Find done\n"; +#print "Summaryfile: $LIST\n"; +#print "Sendlist:    $CMD\n"; +# +#print "Generating lists done/total mp3 files\n"; +#open(LIST,">$LIST");  +#open(CMD,">$CMD"); +# +#print LIST "### List generated: $DATE I have a total of $#INPUT mp3s ###\n"; +#print CMD  "### List generated: $DATE I have a total of $#INPUT mp3s ###\r\n"; +#print CMD  "### This list was created by Findbot for Irssi\r\n"; +#print CMD  "### http://irssi.org/scripts\r\n"; +# +#$CHECKDIR="";  +#$CNT=0; +# +## arrays start 0 and If I have 10 mp3 without +1 it would stat you have 9 ... +#$TOTAL = $#INPUT + 1;  +# +#sub padline { +#	$filename = shift; +#	$filelength = length($filename); +#	$paddchar = "="; +#	if ( $filelength <= $padding ) { +#		for ( $counter = $filelength; $counter < $padding; $counter++ ) { +#			$paddchar .= "="; +#		} +#	} +#	return $paddchar; +#} +# +#foreach( @INPUT ){ +#        $CNT++;  +#	print "\r$CNT/" . $TOTAL; +#        chomp $_;  +# +#	$FILE=$_;  +#	$DIR=$_;  +#	$FILEwPATH=$_; +# +#        $FILE =~ s/.*\/(.*)/$1/g; # only the file +#        $DIR =~ s/(.*)\/.*/$1/g; # only the dir +# +#        $STAT_OF_FILE = `file -b "$FILEwPATH"`; # the info about the file +#	$STAT_OF_FILE =~ s#/##gio; # remove / +#        chomp $STAT_OF_FILE; +# +#        print LIST "$FILEwPATH : $STAT_OF_FILE\n"; # output to the LIST-file +#	if( "$DIR" ne "$CHECKDIR" ){  +#	        # output to the CMD-file  +#		print CMD "\r\n=================================================\r\n"; +#		$CHECKDIR = $DIR; print CMD "Files in $DIR\r\n";  +#		print CMD "=================================================\r\n\r\n"; +#	} +#        print CMD "!$NICK $FILE " . padline($FILE) . " $STAT_OF_FILE\r\n"; # output to the CMD-file +#} +#print CMD "EOF\r\n"; +#print LIST "EOF\r\n"; +#close LIST,CMD; +#print "\nList generation done\n"; + | 
