#########
# @Find`r 1.1.0 by MC_8 for #warez4free <gregory@worldinter.net>
# report bugs to gregory@worldinter.net
# ######
#  If you don't like the header, SUCK IT!
# ######
# Thanks to:
#  BASS - helped me a bunch
#  IsP  - if he will ever fuken look at the script, he migh modify it a lil more!!
########
# What does this script do, hmm, well... lets say someone is looking for a star trek game,
# well.. IF (and only if) soneone has inputed into the data base where they can get a 
# star trek game at, then it will return it to them, eg:
#
# ADDING it:
#-> *oCHANMAXo* addfind star trek the series, multimedia game, version 1.5, you can /msg MC_8 for it or ftp to 209.228.55.48
#-oCHANMAXo- Adding {star trek the series, multimedia game, version 1.5, you can /msg MC_8 for it or ftp to 209.228.55.48}...
#-oCHANMAXo- Done...
#
# FINDING it:
#<MC_8> @find *star*trek*
#-oCHANMAXo- I found 1 match to your search for '*star*trek*'...
#-oCHANMAXo- 1) star trek the series, multimedia game, version 1.5, you can /msg mc_8 for it or ftp to 209.228.55.48
#-oCHANMAXo- --to add something, do: /msg oCHANMAXo addfind <something>
#
# there, pretty simple eh? if you have any suggestions or comments or bad thoughts
# about this script, e`mail me at gregory@worldinter.net .. I would like to hear!
#
# DO NOT ERASE ANYTHING ON THIS FILE, IF YOU MODIFY IT, PLEASE SEND A COPY TO ME AND ADD YOUR
# NAME TO THE TITLE, AND ADD YOUR INFO STUFF TO THE VERSION CHANGES BELOW
# BASICLY I OWN THIS NOT YOU, BUT GOOD SCRIPTS DON'T STEAL NOW DAYS.. DO THEY?
#
#########
#  Version Changes:
#
# V. 1.1.0
# - added the wildcards on search (should of done that first of all du!)
# - added dcc command 'findstat'
# - added flood protection, thanks to bseen1.4.0.tcl
# - fixed the msg FINDADD...
# - fixed it's dcc putloglev
# - fixed bugs on the 'match_limit'
# - added a not found list (to let ya know what your search`r is lacking)
# - added database limit, over write older files on exceed limit  (suggested by Bass <=- dat f00l know's more dan you so shut up!)
# - added a command so +o users can down load the search file, making it easier to see everything
#
# V. 1.0.0
# - first release
#
#  To Do:
#
#
#########
#  COMMANDS
#
# DCC
#  (anyone)   : find <*what*ever*>      - finds stuff du
#  (anyone)   : search <*what*ever*>    - finds stuff du
#  (anyone)   : addfind <product name> [keywords] [description] <where it can be found at>
#                                       - adds an entrie
#  (anyone)   : findadd <product name> [keywords] [description] <where it can be found at>
#                                       - adds an entrie
#  (+o users) : dllist <to who>         - download the list
#  (+o users) : delfind <number>        - deleat a line (the list will show number, or dcc's '.find *' will show you the number)
#  (+o users) : finddel <number>        - deleat a line (the list will show number, or dcc's '.find *' will show you the number)
#  (+o users) : findstat                - current stats (resets on rehash/restart/start-up)
#  (+o users) : findstats               - current stats (resets on rehash/restart/start-up)
# PUB
#  (anyone)   : @find <*what*ever*>     - finds stuff du
#  (anyone)   : @search <*what*ever*>   - finds stuff du
# MSG
#  (anyone)   : addfind <product name> [keywords] [description] <where it can be found at>
#                                       - adds an entrie
#  (anyone)   : findadd <product name> [keywords] [description] <where it can be found at>
#                                       - adds an entrie
#  (+o users) : dllist                  - download the list
#  (+o users) : delfind <number>        - deleat a line (the list will show number, or dcc's '.find *' will show you the number)
#  (+o users) : finddel <number>        - deleat a line (the list will show number, or dcc's '.find *' will show you the number)
#
#########
#   Stuff You Need To Set (if you want to, it's set to default already, and default is 
#                                                                 what I use on my bot)
#
# This is protection so you don't get flooded off, when searching for a something really
# open, like *a*, this setting will only show the first (what ever # you put) (5 is default)
# and then say you need to limit your search, and stop...
set match_limit 6
#
# Set this to the maximum number of entries that will be able to exist in the database,
# if a new entrie is inputed, and the database is already at "what you set", then it will
# just over write the oldest entrie to make room (considering it was hard enought to 
# find and input 75 entries, I think 4000 is VERY sufficent ;) )
set databaselimit 4000
#
# Set this to what you want the data file to be named, default 'datafile'...
set datafile "datafile"
#
# [0 = no/1 = yes] Do you want to record the searches not found? (#1 this could be good
# if you wanna know what your find`r isn't finding, #2 this can use up alot of space if
# you don't check it ever so often and deleate it (deleation/viewing has to be done via 
# telnet or ftp to the shell) if I get any requests, I will update the script to allow 
# remote deletion of the file, like in '.delfind #'...) anyhow, I threw it in for me, if 
# you don't want it, just set it to 0
set notfoundlist 1
#
# Set this to what you want the not found data file to be named, default 'notfoundfile'
# if the above 'notfoundlist' is 0, then this variable should be left alone :)
set notfoundfile "notfoundfile"
#
# [0 = no/1 = yes] Do you want to display an onjoin msg telling that @find is available?
set onjoinmsg 1
#
# Set this to the channels you want it to on join msg to, if the above setting is turned
# off, then don't worry about it... example:
# set channels "#warez4free #channel2 #channel3"
# you can put as many channel in as you want, jut put a space inbetween them...
set channels "#warez4free #wareznorth"
#
#mc(flood) is used for flood protection, in the form x:y.  Any queries
#  beyond x in y seconds is considered a flood and ignored.
set mc(flood) 5:10
#
#mc(ignore) is used as a switch for ignoring flooders (1=on)
set mc(ignore) 1
#
#mc(ignore_time) is used to define the amount of time a flooder is 
#  ignored (minutes).  This is meaningless if bs(ignore) is 0.
set mc(ignore_time) 1
#
##############
### Do Not Edit Past This Part ###
set find_ver "1.1.0"
## This section out of Bass's bseen1.4.0.tcl ##
proc mc_flood_init {} {
 global mc mc_flood_array find_ver
 if {![string match *:* $mc(flood)]} {
  putlog "9,1+@find`r $find_ver: var mc(flood) not set correctly!" 
  return
 }
 set mc(flood_num) [lindex [split $mc(flood) :] 0] 
 set mc(flood_time) [lindex [split $mc(flood) :] 1] 
 set i [expr $mc(flood_num) - 1]
 while {$i >= 0} {
  set mc_flood_array($i) 0 
  incr i -1 
 }
 putlog "9,1 @find`r's flood protection, initalized (WoW, big word)..."
} 
proc mc_flood {nick uhost} {
 global mc mc_flood_array find_ver stat_flood
 if {$mc(flood_num) == 0} {
  return 0
 }
 set i [expr $mc(flood_num) - 1]
 while {$i >= 1} {
  set mc_flood_array($i) $mc_flood_array([expr $i - 1]) 
  incr i -1
 } 
 set mc_flood_array(0) [unixtime]
 if {[expr [unixtime] - $mc_flood_array([expr $mc(flood_num) - 1])] <= $mc(flood_time)} {
  putlog "9,1 @find`r's $find_ver: Flood detected from $nick."
  incr stat_flood 1
  if {$mc(ignore)} {
   newignore [maskhost *!*[string trimleft $uhost ~]] @find`r flood $mc(ignore_time)
  } 
  return 1
 } {
  return 0
 }
}
## End of the frood protection pulled from bseen1.4.0.tcl ((Bass you rule)) ##
bind dcc o|o findstat mc:find
bind dcc o|o findstats mc:find
proc mc:find {hand idx args} {
 global databaselimit notfoundlist stat_hits stat_found stat_not stat_notice stat_add stat_remove find_ver stat_flood number
 putdcc $idx "9,1Current stats for @find`r v $find_ver are as follows:"
 putdcc $idx "- Total @find hits = 0,012$stat_hits"
 putdcc $idx "- Hits found = 0,012$stat_found"
 if {$notfoundlist == 1 } {
  putdcc $idx "- Hits not found = 0,013$stat_not -=- Recorded!"
 } {
  putdcc $idx "- Hits not found = 0,013$stat_not"
 }
 if {[expr [expr $stat_hits - $stat_found] - $stat_not] == 0} {
  putdcc $idx "- Total mismatched = 0,012OK"
 } {
  putdcc $idx "- Total mismatched = 0,013[expr [expr $stat_hits - $stat_found]]"
 }
 putdcc $idx "- Times noticed for onjoin = 0,012$stat_notice"
 putdcc $idx "- Total erased = 0,012$stat_remove"
 putdcc $idx "- Total added = 0,012$stat_add"
 putdcc $idx "- # of ppl found flooding = 0,013$stat_flood"
 if {$number < 6} {
  putdcc $idx "- # of entries in database = 0,013$number/$databaselimit"
 } {
  putdcc $idx "- # of entries in database = 0,012$number/$databaselimit"
 }
 putdcc $idx "_____________________DONE_____________________"
}
proc find_filt {data} {
  regsub -all -- \\\\ $data \\\\\\\\ data ; regsub -all -- \\\[ $data \\\\\[ data ; regsub -all -- \\\] $data \\\\\] data
  regsub -all -- \\\} $data \\\\\} data ; regsub -all -- \\\{ $data \\\\\{ data ; regsub -all -- \\\" $data \\\\\" data ; return $data
}
if {$onjoinmsg == 1} { bind join -|- *!*@* mc:join }
proc mc:join {nick uhost hand chan} {
 global channels number find_ver botnick match_limit datafile stat_hits stat_found stat_not stat_notice stat_add stat_remove
 if {$nick == $botnick} { return 0 }
 foreach channels2 $channels {
  if {[string tolower $channels2] == [string tolower $chan]} {
   incr stat_notice 1
   putserv "NOTICE $nick :Welcome to $chan, We have a @find`r (v. $find_ver) available for your use"
   putserv "NOTICE $nick :just type '@find *what*ever*' in the channel, and I'll search for ya"
   if {$number == 1} {
    putserv "NOTICE $nick :-- I am currently tracking 1 entrie in my database, kinda low :("
   }
   if {$number <= 20 && $number != 1} {
    putserv "NOTICE $nick :-- I am currently tracking $number entries in my database, kinda low :("
   }
   if {$number > 20} {
    putserv "NOTICE $nick :-- I am currently tracking $number entries in my database"
   }
   putserv "NOTICE $nick :If you would like to add something, feel free, just type: /msg $botnick findadd <prog. name> \[description\] <where to get it at>"
  }
 }
}
bind dcc -|- find MC:find:dcc
bind dcc -|- search MC:find:dcc
proc MC:find:dcc {hand idx args} {
 global number find_ver botnick match_limit datafile stat_hits stat_found stat_not stat_notice stat_add stat_remove
 if {![file exists $datafile]} {
  putdcc $idx "The Search file hasn't been created yet, sorry..."
  return 0
 }
 set matches 0
 set match ""
 if {[catch {exec grep "" $datafile}]} {
  putdcc $idx "UNEXPECTED ERROR, TELL MC_8 AT ONCE! (error code 1)"
  return 0
 }
 set mc_list [split [exec grep "" $datafile] \n]
 set arg1 "*[string trimright [string trimleft [find_filt [string tolower [lindex $args 0]]] *] *]*"
 incr stat_hits 1
 foreach wind $mc_list {
  if {[string match $arg1 $wind]} {
   incr matches 1
   set match "$match $wind"
  }
 }
 if {$matches == 0} {
  putdcc $idx "I'm sorry, I did not find any matches for '$arg1', make your search shorter maby?"
#  putdcc $idx "--This script brought to you by #warez4free"
  putdcc $idx "--to add something, type: .addfind <program name> \[description or some keywords\] <WHERE TO GET IT AT>"
  unset mc_list
  notfoundlist "DCC: \[[date] [time]\] <$hand> $arg1"
  incr stat_not 1
  putcmdlog "#$hand# find $arg1"
  return 0
 }
 if {$matches == 1} {
  putdcc $idx "I found $matches match to your search for '$arg1'..."
 }
 if {$matches > 1} {
  putdcc $idx "I found $matches matches to your search for '$arg1'..."
 }
 set i 1
 foreach item $match {
  putdcc $idx "$i) $item"
  incr i
 }
 incr stat_found 1
# putdcc $idx "--This script brought to you by #warez4free"
 putdcc $idx "--to add something, type: .addfind <program name> \[description or some keywords\] <WHERE TO GET IT AT>"
 unset mc_list
 return 1
}
bind pub - @find MC:find:pub
bind pub - @search MC:find:pub
proc MC:find:pub {nick uhost hand chan args} {
 if {[mc_flood $nick $uhost]} {return 0}
 global number find_ver botnick match_limit datafile stat_hits stat_found stat_not stat_notice stat_add stat_remove
 if {![file exists $datafile]} {
  putserv "NOTICE $nick :The Search file hasn't been created yet, sorry..."
  return 0
 }
 set matches 0
 set match ""
 if {[catch {exec grep "" $datafile}]} {
  putserv "NOTICE $nick :UNEXPECTED ERROR, TELL MC_8 AT ONCE! (error code 1.2)"
  return 0
 }
 set mc_list [split [exec grep "" $datafile] \n]
 set arg1 "*[string trimright [string trimleft [find_filt [string tolower [lindex $args 0]]] *] *]*"
 incr stat_hits 1
 foreach wind $mc_list {
  if {[string match $arg1 $wind]} {
   incr matches 1
   set match "$match $wind"
  }
 }
 if {$matches == 0} {
  putserv "NOTICE $nick :I'm sorry, I did not find any matches for '$arg1', make your search shorter maby?"
#  if {"[string tolower $chan]" != "#warez4free"} {
#   putserv "NOTICE $nick :--This script brought to you by #warez4free"
#  }
  putserv "NOTICE $nick :--to add something, Type: /msg $botnick addfind <program name> \[description or some keywords\] <WHERE TO GET IT AT>"
  unset mc_list
  notfoundlist "$chan: \[[date] [time]\] <$nick> $arg1"
  incr stat_not 1
  return 0
 }
 if {$matches == 1} {
  putserv "NOTICE $nick :I found $matches match to your search for '$arg1'..."
 }
 if {$matches > 1} {
  putserv "NOTICE $nick :I found $matches matches to your search for '$arg1'..."
 }
 set i 1
 foreach item $match {
  putserv "NOTICE $nick :$i) $item"
  if {$i == $match_limit} {
   if {$i != $matches} {
    putserv "NOTICE $nick :To many matches, please make you search a lil more selective"
    putserv "NOTICE $nick : \[$i of $matches displayed\]"
#    if {"[string tolower $chan]" != "#warez4free"} {
#     putserv "NOTICE $nick :--This script brought to you by #warez4free"
#    }
    putserv "NOTICE $nick :--to add something, type: /msg $botnick addfind <program name> \[description or some keywords\] <WHERE TO GET IT AT>"
    incr stat_found 1
    return 2
   }
  }
  incr i
 }
 incr stat_found 1
# if {"[string tolower $chan]" != "#warez4free"} {
#  putserv "NOTICE $nick :--This script brought to you by #warez4free"
# }
 putserv "NOTICE $nick :--to add something, type: /msg $botnick addfind <program name> \[description or some keywords\] <WHERE TO GET IT AT>"
 unset mc_list
 return 2
}
bind dcc -|- addfind MC:addfind
bind dcc -|- findadd MC:addfind
proc MC:addfind {hand idx args} {
 global databaselimit number datafile stat_add stat_remove
 set arg1 "[concat [string tolower $args]]"
 if {[lindex [lindex $arg1 0] 1] == ""} {
  putdcc $idx "SYNTAX: .addfind <program name> \[description or some keywords\] <WHERE TO GET IT AT>"
  return 0
 }
 if {![split [catch {exec grep $arg1 $datafile}] \n]} {
  putdcc $idx "$arg1 already exists..."
  return 0
 }
 if {$number >= $databaselimit} {
  set row 0 
  set oldfind [getfind $datafile]
  if {[expr $row >= 0] && [expr $row < [llength $oldfind]]} {
   set newfinds [lreplace $oldfind $row $row]
   set fileio [open $datafile "w"]
   foreach item $newfinds {
    puts $fileio $item
   }
   flush $fileio
   close $fileio
   incr stat_remove 1
  }
  exec echo [string tolower $args] >> $datafile
  putdcc $idx "Added..."
  incr stat_add 1
 } {
  exec echo [string tolower $args] >> $datafile
  putdcc $idx "Added..."
  incr number 1
  incr stat_add 1
 }
}
bind msg - addfind MC:addfind:msg
bind msg - findadd MC:addfind:msg
proc MC:addfind:msg {nick uhost hand args} {
 global number databaselimit find_ver botnick match_limit datafile stat_hits stat_found stat_not stat_notice stat_add stat_remove
 if {[mc_flood $nick $uhost]} {return 0}
 set arg1 "[concat [string tolower $args]]"
 if {[lindex [lindex $arg1 0] 1] == ""} {
  puthelp "PRIVMSG $nick :SYNTAX: /msg $botnick addfind <program name> \[description\] <where to get it at>"
  return 0
 }
 if {![split [catch {exec grep $arg1 $datafile}] \n]} {
  puthelp "NOTICE $nick :$arg1 already exists..."
  return 0
 }
 if {$number >= $databaselimit} {
  set row 0 
  set oldfind [getfind $datafile]
  if {[expr $row >= 0] && [expr $row < [llength $oldfind]]} {
   set newfinds [lreplace $oldfind $row $row]
   set fileio [open $datafile "w"]
   foreach item $newfinds {
    puts $fileio $item
   }
   flush $fileio
   close $fileio
   incr stat_remove 1
  }
  exec echo [string tolower $args] >> $datafile
  puthelp "NOTICE $nick :Adding $args..."
  puthelp "NOTICE $nick :Done..."
  incr stat_add 1
 } {
  exec echo [string tolower $args] >> $datafile
  puthelp "NOTICE $nick :Adding $args..."
  puthelp "NOTICE $nick :Done..."
  incr number 1
  incr stat_add 1
 }
}
bind dcc o|o delfind MC:delfind
bind dcc o|o finddel MC:delfind
proc MC:delfind {hand idx arg} {
 global number find_ver botnick match_limit datafile stat_hits stat_found stat_not stat_notice stat_add stat_remove
 if {[lindex $arg 0] == ""} {
  putdcc $idx "SYNTAX: .delfind <number>"
  putdcc $idx "To find the number, just type: '.find *'  this will give you the total list"
  return 0
 }
 set row [expr $arg - 1]
 set oldfind [getfind $datafile]
 if {[expr $row >= 0] && [expr $row < [llength $oldfind]]} {
  set newfinds [lreplace $oldfind $row $row]
  set fileio [open $datafile "w"]
  foreach item $newfinds {
   puts $fileio $item
  }
  flush $fileio
  close $fileio
  putdcc $idx "Removed..."
  incr number -1
  incr stat_remove 1
 }
}
bind msg o|o finddel MC:delfind:msg
bind msg o|o delfind MC:delfind:msg
proc MC:delfind:msg {nick uhost hand arg} {
 global number find_ver botnick match_limit datafile stat_hits stat_found stat_not stat_notice stat_add stat_remove
 if {[mc_flood $nick $uhost]} {return 0}
 if {[lindex $arg 0] == ""} {
  puthelp "NOTICE $nick :SYNTAX: /msg $botnick delfind <number>"
  puthelp "NOTICE $nick :To find the number, you must be in dcc chat, and type: '.find *'  this will give you the total list"
  return 0
 }
 set row [expr $arg - 1]
 set oldfind [getfind $datafile]
 if {[expr $row >= 0] && [expr $row < [llength $oldfind]]} {
  set newfinds [lreplace $oldfind $row $row]
  set fileio [open $datafile "w"]
  foreach item $newfinds {
   puts $fileio $item
  }
  flush $fileio
  close $fileio
  puthelp "NOTICE $nick :Done..."
  incr number -1
  incr stat_remove 1
 }
}
proc getfind {file} {
 set finds ""
 set fileio [open $file "r"]
 while {![eof $fileio]} {
  set find [gets $fileio]
  if {$find != ""} {
   set finds [linsert $finds end $find]
  }
 }
 close $fileio
 return $finds
}
proc notfoundlist {arg1} {
 global notfoundlist notfoundfile
 if {$notfoundlist == 1} {
  exec echo [string tolower $arg1] >> $notfoundfile
 }
}
bind msg o|o dllist mc:dllist:msg
proc mc:dllist:msg {nick uhost hand arg} {
 global datafile
 if {[file exists $datafile.bak]} { 
  exec rm -r $datafile.bak
 }
 set mc_list [split [exec grep "" $datafile] \n]
 set i 1
 foreach wind $mc_list {
  exec echo "$i) $wind " >> $datafile.bak
  incr i 1
 }
 set output [dccsend $datafile.bak $nick]
 if {$output == 0} {
  puthelp "NOTICE $nick :Sending $datafile.bak to you"
  return 1
 }
 if {$output == 1} {
  puthelp "NOTICE $nick :dcc table is full (too many connections)"
  return 2
 }
 if {$output == 2} {
  puthelp "NOTICE $nick :can't open a socket for the transfer"
  return 3
 }
 if {$output == 3} {
  puthelp "NOTICE $nick :file doesn't exist <Tell MC_8 he has a bug :P>"
  return 4
 }
 if {$output == 4} {
  puthelp "NOTICE $nick :$datafile.bak was queued for later transfer"
  return 5
 }
}
bind dcc o|o dllist mc:dllist
proc mc:dllist {hand idx arg} {
 global datafile 
 if {[file exists $datafile.bak]} { 
  exec rm -r $datafile.bak
 }
 set mc_list [split [exec grep "" $datafile] \n]
 set i 1
 foreach wind $mc_list {
  exec echo "$i) $wind" >> $datafile.bak
  incr i 1
 }
 set arg1 [lindex $arg 0]
 if {$arg1 == ""} {
  putdcc $idx "Send to who? syntax: .dllist <nick>"
  return 0
 }
 set output [dccsend $datafile.bak $arg1]
 if {$output == 0} {
  putdcc $idx "Sending $datafile.bak to '$arg1'"
  return 1
 }
 if {$output == 1} {
  putdcc $idx "dcc table is full (too many connections)"
  return 2
 }
 if {$output == 2} {
  putdcc $idx "can't open a socket for the transfer"
  return 3
 }
 if {$output == 3} {
  putdcc $idx "file doesn't exist <Tell MC_8 he has a bug :P>"
  return 4
 }
 if {$output == 4} {
  putdcc $idx "$datafile.bak was queued for later transfer"
  return 5
 }
}
putlog "***==-==***"
if {[catch {exec grep "" $datafile}]} {
 putlog "9,1ERROR loading datafile, Please e`mail gregory@worldinter.net at once! (error code e1)"
 putlog "***==-==***"
 return 0
} {
 set number 0
 set mc_list [split [exec grep "" $datafile] \n]
 foreach dummie $mc_list {
  incr number 1
 }
 putlog "9,1 @find`r data-base loaded..."
 putlog "9,1 --currently tracking $number/$databaselimit entries in the database"
 set stat_hits 0
 set stat_found 0
 set stat_not 0
 set stat_notice 0
 set stat_add 0
 set stat_remove 0
 set stat_flood 0
 putlog "9,1 @find`r's stats reset..."
 mc_flood_init
 unset mc_list
 putlog "9,1Warez @find`r $find_ver loaded, by MC_8"
 putlog "***==-==***"
}