This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

Did you know facts

Requests for complete scripts or modifications/fixes for scripts you didn't write. Response not guaranteed, and no thread bumping!
Post Reply
V
ViciousPiranha
Voice
Posts: 36
Joined: Mon Dec 17, 2012 5:21 am

Did you know facts

Post by ViciousPiranha »

hey I am looking for a 'did you know' fact script.

You can add a fact via public message with:

!addfact <subject> <the-fact-here>


and you can display facts in two ways

either:

!fact

triggers a random fact from any subject

or

!fact <subject>

would pick a random fact from that subject

help please?

thanks you
User avatar
SpiKe^^
Owner
Posts: 831
Joined: Fri May 12, 2006 10:20 pm
Location: Tennessee, USA
Contact:

JustTheFacts.tcl Version 1.0 by SpiKe^^

Post by SpiKe^^ »

Try this highly modified version of a script I wrote a while ago...

Code: Select all

# JustTheFacts.tcl  Version 1.0  by SpiKe^^ (21 Dec 2012) #

# author:  SpiKe^^ #
# e-mail:  spike<at>mytclscripts<dot>com #
# webpage: http://mytclscripts.com/ #

# This file is Copyrighted under the GNU Public License. #
# http://www.gnu.org/copyleft/gpl.html #

########### General Text File Settings ###########

# Set the full route & file name of the file to edit #
# Note: The !addfact & !addline commands will make this file if needed.
set jtFact(file) {/usr/home/spike/eggdrop/scripts/jtf.txt}

########### Public 'Facts' Commands Settings ###########

# Set listen channel(s) & access flags for the 'add subject|fact' command #
set jtFact(fachan) {#yourchannel #anotherchannel}
set jtFact(faflags) {o|o}

# Set the public trigger for the 'add subject|fact' command #
# used to add a subject|fact line at the end of the text file: 
#    example:  !addfact Animal facts|Cats can't taste sweets
set jtFact(factadd) {!addfact}

# Set the case to use when saving/displaying all 'subject' text #
# this is so all instances of the same subject, will be in the same case.
# this will also affect the output text of the !fact & !subjects commands.
# 1 = lower case: all subject text is in lower case
# 2 = sentence case: only the first letter of the first word is upper case
# 3 = title case: the first letter of every word is upper case
# 4 = upper case: all subject text is in upper case
set jtFact(docase) "2"

###########
# Set listen channel(s) & access flags for the !fact & !subjects commands #
set jtFact(frchan) {#yourchannel #anotherchannel}
set jtFact(frflags) {-|-}

# Set the public trigger for the 'read a fact' command #
# to read a random fact from all the facts in the database: 
#    example:  !fact
# to read a random fact from the subject: animal facts : 
#    example:  !fact animal facts
set jtFact(rndfact) {!fact}

# Set the text to use when doing 'read a fact' to the channel #
# these codes can be used in this setting:
#    %subject  = the subject from the database line
#    %fact     = the fact text from the database line
# Example: if the database line was:  Animal facts|Cats can't taste sweets
# -> set jtFact(facttxt) {%subject: Did you know, %fact ?}
# says this to channel:  Animal facts: Did you know, Cats can't taste sweets ?
set jtFact(facttxt) {Did you know, %fact ?}

# Set the public trigger for the 'list existing subjects' command #
# used to list all fact subjects currently defined in the text file: 
#    example:  !subjects
set jtFact(subjcts) {!subjects}

########### Timed Public Read Setting ###########

# Set the channel(s) for the timed public read fact #
set jtFact(tchan) {#yourchannel #anotherchannel}

# Set number of minutes between each timed public read fact #
# Set this to "0" to disable all timed public read facts
# Note: file errors will be sent to the first channel in jtFact(tchan)
set jtFact(timed) "10"

# show file line number before each timed public read fact? (0=no | 1=yes) #
set jtFact(tnum) "0"

# do timed public read facts in file order or random order ? #
# 1 = read the next fact in order from the file
# 2 = read the facts in random order from the file
set jtFact(trand) "2"

########### Public 'Line' Commands Settings ###########
## settings for: !addline !readline !delline & !editline ##
## Note: Use these commands for file administration/maintenance ##

# Set the listen channel(s) for all public Line commands #
set jtFact(lchan) {#yourchannel #anotherchannel}

# Set the access flags to use the public Line commands #
set jtFact(lflags) {o|o}

# Set the public trigger for the add line command #
# to add a line at the end of the file: 
#    example:  !addline end The text to add at file end.
#    example:  !addline The text to add at file end.
# to add a line at a specific line position in the file:
#    example:  !addline 4 The text to add at file line 4.
#    note: this will renumber the original line 4 & all lines after it!
set jtFact(add) {!addline}

# Set the public trigger for the read line command #
# to read a specific line (by line number) from the text file
#    example:  !readline 4
#    note: use to check for correct line before doing !editline or !delline
set jtFact(read) {!readline}

# Set the public trigger for the delete line command #
# to delete a specific line (by line number) from the text file
#    example:  !delline 4
#    note: this will renumber all lines after line 4!
set jtFact(del) {!delline}

# Set the public trigger for the edit line command #
# to edit a specific line (by line number) in the text file
#    example:  !editline 4 New text to replace file line 4.
set jtFact(edit) {!editline}

########### Public 'ReadFile' Command Settings ###########
## settings for the public !readfile command ##

# Set the listen channel(s) for the public !readfile command #
set jtFact(rchan) {#yourchannel #anotherchannel}

# Set the access flags to use the public read file command #
set jtFact(rflags) {o|o}

# Set the default number of lines to show for a read file command #
set jtFact(rfdef) "20"

# Set the public trigger for the read file command #
# to read 'default number of lines' from the beginning of the text file
#    example:  !readfile
# to read 'default number of lines' beginning with line 21
#    example:  !readfile 21
# to read file lines 1 through 10
#    example:  !readfile 1-10
set jtFact(readf) {!readfile}


################ End Settings ################


bind pub $jtFact(faflags) $jtFact(factadd) jtfProcFAdd
bind pub $jtFact(frflags) $jtFact(rndfact) jtfProcFact
bind pub $jtFact(frflags) $jtFact(subjcts) jtfProcSubj
bind pub $jtFact(lflags) $jtFact(add) jtfProcAdd
bind pub $jtFact(lflags) $jtFact(del) jtfProcDel
bind pub $jtFact(lflags) $jtFact(read) jtfProcRead
bind pub $jtFact(lflags) $jtFact(edit) jtfProcEdit
bind pub $jtFact(rflags) $jtFact(readf) jtfProcReadF

set jtFact(fachan) [split [string tolower [string trim $jtFact(fachan)]]]
set jtFact(frchan) [split [string tolower [string trim $jtFact(frchan)]]]
set jtFact(lchan) [split [string tolower [string trim $jtFact(lchan)]]]
set jtFact(rchan) [split [string tolower [string trim $jtFact(rchan)]]]
set jtFact(tchan) [split [string tolower [string trim $jtFact(tchan)]]]

if {$jtFact(tnum) ne "1"} {  set jtFact(tnum) 0  }
if {$jtFact(trand) ne "2"} {  set jtFact(trand) 1  }

if {$jtFact(timed)>"0" && ![info exists jtFact(tnxread)]} {
  if {$jtFact(timed)>"3"} {  timer 3 [list jtfProcTimed]
  } else {  timer $jtFact(timed) [list jtfProcTimed]  }
  set jtFact(tnxread) 1
}

if {![info exists jtFact(rls)]} {  set jtFact(rls) [list]  }

proc jtfDoCase {tx} {  set tx [regsub -all -- {\s{2,}} $tx { }]
  if {$::jtFact(docase) eq "4"} {  return [string toupper $tx]  }
  set tx [string tolower $tx]
  if {$::jtFact(docase) eq "1"} {  return $tx  }
  if {$::jtFact(docase) eq "3"} {  set tx [split $tx]  ;  set new ""
    foreach x $tx {  append new "[string toupper $x 0 0] "  }
    return [string trim $new]
  }
  return [string toupper $tx 0 0]
}

proc jtfCleanF {tx} {  set tx [string trim $tx]
  if {![string match ?*|*? $tx]} {  return 1  }
  set tx [split $tx |]
  lappend tls [jtfDoCase [string trim [lindex $tx 0]]]
  lappend tls [string trim [join [lrange $tx 1 end] |]]
  return $tls
}

proc jtfProcSubj {nk uh hn ch tx} {
  jtfProcFact $nk $uh $hn $ch $tx subj  ;  return
}

proc jtfProcFact {nk uh hn ch tx {do fact} } {  set ch [string tolower $ch]
  if {$uh eq "Timed"} {
    if {[lsearch -exact $::jtFact(tchan) $ch]=="-1"} {  return  }
  } else {
    if {[lsearch -exact $::jtFact(frchan) $ch]=="-1"} {  return  }
  }
  set tf $::jtFact(file)  ;  set tx [string trim $tx]
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Text file does not exist: $tf"  ;  return
  }
  set tid [open $tf]  ;  set lines [read -nonewline $tid]  ;  close $tid
  set lines [split $lines \n]  ;  set llen [llength $lines]
  if {$llen=="0"} { puthelp "PRIVMSG $ch :Text file is empty: $tf" ; return }
  if {$do ne "subj" && [llength $::jtFact(rls)]>"0"} {
    if {$llen>"1"} {  set rmax [expr {$llen/2}]
      if {$llen>"4" && [string match {*[13579]} $llen]} {  incr rmax  }
      if {$rmax>"50"} {  set rmax 50  }
      if {[llength $::jtFact(rls)]>$rmax} {
        set ::jtFact(rls) [lreplace $::jtFact(rls) $rmax end]
      }
    } else {  set ::jtFact(rls) [list]  }
  }
  if {$uh eq "Timed" || ($do eq "fact" && $tx eq "")} {
    if {[llength $::jtFact(rls)]>"0"} {  set tid -1  ;  set tls ""
      foreach ln $lines {  incr tid
        if {[lsearch -exact $::jtFact(rls) $tid]=="-1"} { lappend tls $tid }
      }
      set lidx [lindex $tls [rand [llength $tls]]]
      set ::jtFact(rls) [linsert $::jtFact(rls) 0 $lidx]
    } else { set lidx [rand [llength $lines]] ; lappend ::jtFact(rls) $lidx }
    set lin [split [lindex $lines $lidx] |]  ;  set pre ""
    if {$::jtFact(tnum)!="0" && $uh eq "Timed"} { set pre "\[[incr lidx]\] " }
    lappend map %subject [string trim [lindex $lin 0]] %fact
    lappend map [string trim [join [lrange $lin 1 end] |]]
    set say [string map $map $::jtFact(facttxt)]
    if {$uh eq "Timed" && [llength $::jtFact(tchan)]>"1"} {
      foreach ch $::jtFact(tchan) {  puthelp "PRIVMSG $ch :$pre$say"  }
    } else {  puthelp "PRIVMSG $ch :$pre$say"  }
  } else {  set tmp ""
    foreach lin $lines {  set sj [lindex [split $lin |] 0]
      if {$do eq "subj"} {
        if {[info exists count($sj)]} {  incr count($sj)
        } else {  set count($sj) 1  ;  lappend tmp $sj  }
      } else {
        if {[string match -nocase $tx $sj]} {  lappend tmp $lin  }
      }
    }
    if {$do eq "subj"} {  set tx ""  ;  set tmp [lsort -dictionary $tmp]
      foreach sj $tmp {  append tx " $sj ($count($sj)),"  }
      set tx [string trimright $tx ,]
      puthelp "PRIVMSG $ch :Subject list & number of facts in each: $tx."
    } else {
      if {[llength $tmp]=="0"} {  set say "For a list of valid subjects,"
        puthelp "PRIVMSG $ch :Subject does not exist: $tx"
        puthelp "PRIVMSG $ch :$say use: $::jtFact(subjcts)"  ;  return
      }
      set lin [lindex $tmp [rand [llength $tmp]]]
      if {[set lidx [lsearch -exact $lines $lin]]!="-1"} {
        if {[set tidx [lsearch -exact $::jtFact(rls) $lidx]]!="-1"} {
          set ::jtFact(rls) [lreplace $::jtFact(rls) $tidx $tidx]
        }
        set ::jtFact(rls) [linsert $::jtFact(rls) 0 $lidx]
      }
      set lin [split $lin |]
      lappend map %subject [string trim [lindex $lin 0]] %fact
      lappend map [string trim [join [lrange $lin 1 end] |]]
      puthelp "PRIVMSG $ch :[string map $map $::jtFact(facttxt)]"
    }
  }
  return
}

proc jtfProcFAdd {nk uh hn ch tx} {  set ch [string tolower $ch]
  if {[lsearch -exact $::jtFact(fachan) $ch]=="-1"} {  return  }
  set tx [string trim $tx]
  if {![string match ?*|*? $tx]} {  set add $::jtFact(factadd)
    puthelp "PRIVMSG $ch :Correct syntax is: $add <subject>|<the fact text>"
    puthelp "PRIVMSG $ch :Example: $add Animal facts|Cats can't taste sweets"
    return
  }
  set tf $::jtFact(file)
  if {![file exists $tf]} {  set nofile 1  }
  set tls [split $tx |]  ;  set subj [jtfDoCase [string trim [lindex $tls 0]]]
  set tx $subj|[string trim [join [lrange $tls 1 end] |]]
  set id [open $tf a]  ;  puts $id $tx  ;  close $id
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Unable to find or make text file: $tf"
  } elseif {[info exists nofile]} {
    puthelp "PRIVMSG $ch :Added first fact to the database: $tx"
  } else {  puthelp "PRIVMSG $ch :Added new fact to the database: $tx"  }
  return
}

proc jtfProcAdd {nk uh hn ch tx} {  set ch [string tolower $ch]
  if {[lsearch -exact $::jtFact(lchan) $ch]=="-1"} {  return  }
  set tx [split [string trim $tx]]
  if {[lindex $tx 0] eq "end" || [string is digit -strict [lindex $tx 0]]} {
    set addat [lindex $tx 0] ; set tx [string trim [join [lrange $tx 1 end]]]
  } else {  set addat end  ;  set tx [join $tx]  }
  if {![string match ?*|*? $tx] || $addat eq "0"} {  set add $::jtFact(add)
    set x "<subject>|<the fact text>"  ;  set y "Subject|Fact to add"
    puthelp "PRIVMSG $ch :Correct syntax is: $add \[position\] $x"
    puthelp "PRIVMSG $ch :Example: $add end $y at end of the file"
    puthelp "PRIVMSG $ch :Example: $add 4 $y at file line 4"
    puthelp "PRIVMSG $ch :Example: $add $y at end of the file"
    return
  }
  set tf $::jtFact(file)  ;  set tx [join [jtfCleanF $tx] |]
  if {![file exists $tf]} {  set addat end  ;  set nofile 1  }
  if {$addat ne "end"} {  set tx "$addat $tx"
    jtfProcEdit $nk $uh $hn $ch $tx add  ;  return
  }
  set id [open $tf a]  ;  puts $id $tx  ;  close $id
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Unable to find or make text file: $tf"
  } elseif {[info exists nofile]} {
    puthelp "PRIVMSG $ch :Added line to new text file: $tx"
  } else {  puthelp "PRIVMSG $ch :Added line at end of text file: $tx"  }
  return
}

proc jtfProcReadF {nk uh hn ch tx} {
  jtfProcRead $nk $uh $hn $ch $tx file  ;  return
}

proc jtfProcTimed {} {
  if {$::jtFact(timed)=="0"} {  unset ::jtFact(tnxread)  ;  return  }
  timer $::jtFact(timed) [list jtfProcTimed]
  set chan [lindex $::jtFact(tchan) 0]
  if {$::jtFact(trand)=="1"} {
    jtfProcRead $::botnick Timed Line $chan $::jtFact(tnxread)
  } else {  jtfProcFact $::botnick Timed Line $chan 0  }
  return
}

proc jtfProcRead {nk uh hn ch tx {do line} } {  set ch [string tolower $ch]
  if {$do eq "file"} {
    if {[lsearch -exact $::jtFact(rchan) $ch]=="-1"} {  return  }
  } elseif {$uh eq "Timed"} {
    if {[lsearch -exact $::jtFact(tchan) $ch]=="-1"} {  return  }
  } else {
    if {[lsearch -exact $::jtFact(lchan) $ch]=="-1"} {  return  }
  }
  set tf $::jtFact(file)
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Text file does not exist: $tf"  ;  return
  }
  set tx [lindex [split [string trim $tx]] 0]
  if {$do eq "line" && (![string is digit -strict $tx] || $tx=="0")} {
    puthelp "PRIVMSG $ch :Correct syntax is: $::jtFact(read) <line#>"
    puthelp "PRIVMSG $ch :Example: $::jtFact(read) 4"  ;  return
  } elseif {$do eq "file"} {  set rdef $::jtFact(rfdef)
    if {$tx ne ""} {
      if {![string match *-* $tx]} {
        if {![string is digit -strict $tx] || $tx=="0"} {  set begin err
        } else {  set begin $tx  ;  set end [expr {$tx+$rdef-1}]  }
      } elseif {$tx eq "-" || [string match *-*-* $tx]} {  set begin err
      } else {   foreach {x y} [split $tx -] { break }
        set dx [string is digit -strict $x];set dy [string is digit -strict $y]
        if {$dx=="1" && $dy=="1"} {
          if {$x>"0" && $y>=$x} {  set begin $x  ;  set end $y
          } else {  set begin err  }
        } elseif {$dx=="0" && $dy=="0"} {  set begin err
        } elseif {$x eq ""} {
          if {$y<"1"} {  set begin err
          } else {  set begin [expr {$y-$rdef+1}]  ;  set end $y
            if {$begin<"1"} {  set begin 1  }
          }
        } elseif {$y eq "" || $y eq "end"} {
          if {$x<"1"} {  set begin err
          } elseif {$y eq "end"} {  set begin $x  ;  set end $y
          } else {  set begin $x  ;  set end [expr {$x+$rdef-1}]  }
        } else {  set begin err  }
      }
    } else {  set begin 1  ;  set end $rdef  }
    set readf $::jtFact(readf)
    if {$begin eq "err"} {  set x "PRIVMSG $ch :Example,"
      puthelp "PRIVMSG $ch :Correct syntax is: $readf \[linenumber(s)\]"
      puthelp "$x read lines 1 to $rdef: $readf"
      puthelp "$x read lines 21 to [expr {20+$rdef}]: $readf 21"
      puthelp "$x read lines 41 to 58: $readf 41-58"
      puthelp "$x read lines 59 to end of file: $readf 59-end"
      return
    }
  }
  set tid [open $tf]  ;  set lnum 0
  while {![eof $tid]} {  set line [gets $tid]
    if {$line ne ""} {  incr lnum
      if {$uh eq "Timed" && $lnum=="1"} {  set ln1 $line  }
      if {$do eq "file"} {
        if {$lnum>=$begin && ($end eq "end" || $lnum<=$end)} {
          puthelp "PRIVMSG $ch :\[$lnum\] $line"
        }
      } elseif {$lnum==$tx} {
        if {$uh ne "Timed"} {  puthelp "PRIVMSG $ch :\[$lnum\] $line"  }
        break
      }
    }
  }
  close $tid
  if {$lnum=="0"} {
    if {[info exists ::jtFact(tnxread)]} {  set ::jtFact(tnxread) 1  }
    puthelp "PRIVMSG $ch :Text file is empty: $tf" ;  return
  }
  if {$lnum>"1"} {  set tl lines  ;  set is are
  } else {  set tl line  ;  set is is  }
  set fc "$lnum $tl in the file"
  if {$do eq "file"} {
    if {$begin>$lnum} {
      puthelp "PRIVMSG $ch :File line $begin doesn't exist ($fc)"
    } elseif {$end eq "end" || $lnum<=$end} {
      puthelp "PRIVMSG $ch :- End of File -"
    } else {  puthelp "PRIVMSG $ch :- There $is $fc -"
      if {$tx eq ""} {
        puthelp "PRIVMSG $ch :For more 'read file' options use: $readf help"
      }
    }
  } elseif {$uh eq "Timed"} {  set pre ""
    if {$lnum==$tx} {  incr ::jtFact(tnxread)
    } else {  set line $ln1  ;  set lnum 1  ;  set ::jtFact(tnxread) 2  }
    if {$::jtFact(tnum)!="0"} {  set pre "\[$lnum\] "  }
    set lin [split $line |]
    lappend map %subject [string trim [lindex $lin 0]] %fact
    lappend map [string trim [join [lrange $lin 1 end] |]]
    set line [string map $map $::jtFact(facttxt)]
    foreach ch $::jtFact(tchan) {  puthelp "PRIVMSG $ch :$pre$line"  }
  } elseif {$do eq "line" && $tx>$lnum} {
    puthelp "PRIVMSG $ch :File line $tx doesn't exist ($fc)"
  }
  return
}

proc jtfProcDel {nk uh hn ch tx} {
  jtfProcEdit $nk $uh $hn $ch $tx del  ;  return
}

proc jtfProcEdit {nk uh hn ch tx {do edit} } {  set ch [string tolower $ch]
  if {[lsearch -exact $::jtFact(lchan) $ch]=="-1"} {  return  }
  set tf $::jtFact(file)
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Text file does not exist: $tf"  ;  return
  }
  set tx [split [string trim $tx]]
  set find [lindex $tx 0]  ;  set tx [string trim [join [lrange $tx 1 end]]]
  set isdig [string is digit -strict $find]
  if {$do eq "edit"} {
    if {$isdig=="0" || $find=="0" || ![string match ?*|*? $tx]} {
      set edit $::jtFact(edit)
      set x "<subject>|<new fact text>"  ;  set y "Subject|New fact to"
      puthelp "PRIVMSG $ch :Correct syntax is: $edit <line#> $x"
      puthelp "PRIVMSG $ch :Example: $edit 4 $y replace file line 4"
      return
    }
  } elseif {$do eq "del" && ($isdig=="0" || $find=="0")} {
    puthelp "PRIVMSG $ch :Correct syntax is: $::jtFact(del) <line#>"
    puthelp "PRIVMSG $ch :Example: $::jtFact(del) 4"  ;  return
  }
  set new [file dirname $tf]/newfile.tmp  ;  set nid [open $new w]
  set tid [open $tf]  ;  set lnum 0
  while {![eof $tid]} {  set line [gets $tid]
    if {$line ne ""} {  incr lnum
      if {$lnum==$find} {
        if {$do eq "edit"} {
          puthelp "PRIVMSG $ch :Replaced line $lnum fact: $line"
          set tx [join [jtfCleanF $tx] |]
          puthelp "PRIVMSG $ch :with the new fact line: $tx"
          puts $nid $tx
        } elseif {$do eq "del"} {
          puthelp "PRIVMSG $ch :Deleted line $lnum fact: $line"
        } elseif {$do eq "add"} {
          puthelp "PRIVMSG $ch :Added new line $lnum fact: $tx"
          puts $nid $tx  ;  puts $nid $line
        }
      } else {  puts $nid $line  }
    }
  }
  close $tid
  if {$find>$lnum} {
    if {$do eq "add"} {  incr lnum
      puthelp "PRIVMSG $ch :Added new line $lnum fact: $tx"
      puts $nid $tx  ;  close $nid  ;  file rename -force $new $tf
    } else {
      if {$lnum>"0"} {  set tl line
        if {$lnum>"1"} {  set tl lines  }
        puthelp "PRIVMSG $ch :File line $find doesn't exist ($lnum $tl in the file)"
      } else {  puthelp "PRIVMSG $ch :Text file is empty: $tf"  }
      close $nid  ;  file delete $new
    }
  } else {  close $nid  ;  file rename -force $new $tf  }
  return
}

putlog "JustTheFacts.tcl Ver. 1.0 by SpiKe^^ loaded."

The script is mostly tested and seems to work fine.
Let me know how it works out for you.
Last edited by SpiKe^^ on Wed Dec 26, 2012 9:00 pm, edited 3 times in total.
SpiKe^^

Get BogusTrivia 2.06.4.7 at www.mytclscripts.com
or visit the New Tcl Acrhive at www.tclarchive.org
.
V
ViciousPiranha
Voice
Posts: 36
Joined: Mon Dec 17, 2012 5:21 am

Post by ViciousPiranha »

yes!! thanks!
User avatar
SpiKe^^
Owner
Posts: 831
Joined: Fri May 12, 2006 10:20 pm
Location: Tennessee, USA
Contact:

Post by SpiKe^^ »

Added a function to check the text file on hash or start, for file errors that might hang the script.

Code: Select all

# JustTheFacts.tcl  Version 1.1  by SpiKe^^ (26 Dec 2012) #

# author:  SpiKe^^ #
# e-mail:  spike<at>mytclscripts<dot>com #
# webpage: http://mytclscripts.com/ #

# This file is Copyrighted under the GNU Public License. #
# http://www.gnu.org/copyleft/gpl.html #

########### General Text File Settings ###########

# Set the full route & file name of the file to edit #
# Note: The !addfact & !addline commands will make this file if needed.
set jtFact(file) {/usr/home/spike/eggdrop/scripts/jtf.txt}

########### Public 'Facts' Commands Settings ###########

# Set listen channel(s) & access flags for the 'add subject|fact' command #
set jtFact(fachan) {#yourchannel #anotherchannel}
set jtFact(faflags) {o|o}

# Set the public trigger for the 'add subject|fact' command #
# used to add a subject|fact line at the end of the text file: 
#    example:  !addfact Animal facts|Cats can't taste sweets
set jtFact(factadd) {!addfact}

# Set the case to use when saving/displaying all 'subject' text #
# this is so all instances of the same subject, will be in the same case.
# this will also affect the output text of the !fact & !subjects commands.
# 1 = lower case: all subject text is in lower case
# 2 = sentence case: only the first letter of the first word is upper case
# 3 = title case: the first letter of every word is upper case
# 4 = upper case: all subject text is in upper case
set jtFact(docase) "2"

###########
# Set listen channel(s) & access flags for the !fact & !subjects commands #
set jtFact(frchan) {#yourchannel #anotherchannel}
set jtFact(frflags) {-|-}

# Set the public trigger for the 'read a fact' command #
# to read a random fact from all the facts in the database: 
#    example:  !fact
# to read a random fact from the subject: animal facts : 
#    example:  !fact animal facts
set jtFact(rndfact) {!fact}

# Set the text to use when doing 'read a fact' to the channel #
# these codes can be used in this setting:
#    %subject  = the subject from the database line
#    %fact     = the fact text from the database line
# Example: if the database line was:  Animal facts|Cats can't taste sweets
# -> set jtFact(facttxt) {%subject: Did you know, %fact ?}
# says this to channel:  Animal facts: Did you know, Cats can't taste sweets ?
set jtFact(facttxt) {Did you know, %fact ?}

# Set the public trigger for the 'list existing subjects' command #
# used to list all fact subjects currently defined in the text file: 
#    example:  !subjects
set jtFact(subjcts) {!subjects}

########### Timed Public Read Setting ###########

# Set the channel(s) for the timed public read fact #
set jtFact(tchan) {#yourchannel #anotherchannel}

# Set number of minutes between each timed public read fact #
# Set this to "0" to disable all timed public read facts
# Note: file errors will be sent to the first channel in jtFact(tchan)
set jtFact(timed) "10"

# show file line number before each timed public read fact? (0=no | 1=yes) #
set jtFact(tnum) "0"

# do timed public read facts in file order or random order ? #
# 1 = read the next fact in order from the file
# 2 = read the facts in random order from the file
set jtFact(trand) "2"

########### Public 'Line' Commands Settings ###########
## settings for: !addline !readline !delline & !editline ##
## Note: Use these commands for file administration/maintenance ##

# Set the listen channel(s) for all public Line commands #
set jtFact(lchan) {#yourchannel #anotherchannel}

# Set the access flags to use the public Line commands #
set jtFact(lflags) {o|o}

# Set the public trigger for the add line command #
# to add a line at the end of the file: 
#    example:  !addline end The text to add at file end.
#    example:  !addline The text to add at file end.
# to add a line at a specific line position in the file:
#    example:  !addline 4 The text to add at file line 4.
#    note: this will renumber the original line 4 & all lines after it!
set jtFact(add) {!addline}

# Set the public trigger for the read line command #
# to read a specific line (by line number) from the text file
#    example:  !readline 4
#    note: use to check for correct line before doing !editline or !delline
set jtFact(read) {!readline}

# Set the public trigger for the delete line command #
# to delete a specific line (by line number) from the text file
#    example:  !delline 4
#    note: this will renumber all lines after line 4!
set jtFact(del) {!delline}

# Set the public trigger for the edit line command #
# to edit a specific line (by line number) in the text file
#    example:  !editline 4 New text to replace file line 4.
set jtFact(edit) {!editline}

########### Public 'ReadFile' Command Settings ###########
## settings for the public !readfile command ##

# Set the listen channel(s) for the public !readfile command #
set jtFact(rchan) {#yourchannel #anotherchannel}

# Set the access flags to use the public read file command #
set jtFact(rflags) {o|o}

# Set the default number of lines to show for a read file command #
set jtFact(rfdef) "20"

# Set the public trigger for the read file command #
# to read 'default number of lines' from the beginning of the text file
#    example:  !readfile
# to read 'default number of lines' beginning with line 21
#    example:  !readfile 21
# to read file lines 1 through 10
#    example:  !readfile 1-10
set jtFact(readf) {!readfile}


################ End Settings ################


bind pub $jtFact(faflags) $jtFact(factadd) jtfProcFAdd
bind pub $jtFact(frflags) $jtFact(rndfact) jtfProcFact
bind pub $jtFact(frflags) $jtFact(subjcts) jtfProcSubj
bind pub $jtFact(lflags) $jtFact(add) jtfProcAdd
bind pub $jtFact(lflags) $jtFact(del) jtfProcDel
bind pub $jtFact(lflags) $jtFact(read) jtfProcRead
bind pub $jtFact(lflags) $jtFact(edit) jtfProcEdit
bind pub $jtFact(rflags) $jtFact(readf) jtfProcReadF

set jtFact(fachan) [split [string tolower [string trim $jtFact(fachan)]]]
set jtFact(frchan) [split [string tolower [string trim $jtFact(frchan)]]]
set jtFact(lchan) [split [string tolower [string trim $jtFact(lchan)]]]
set jtFact(rchan) [split [string tolower [string trim $jtFact(rchan)]]]
set jtFact(tchan) [split [string tolower [string trim $jtFact(tchan)]]]

if {$jtFact(tnum) ne "1"} {  set jtFact(tnum) 0  }
if {$jtFact(trand) ne "2"} {  set jtFact(trand) 1  }

if {$jtFact(timed)>"0" && ![info exists jtFact(tnxread)]} {
  if {$jtFact(timed)>"3"} {  timer 3 [list jtfProcTimed]
  } else {  timer $jtFact(timed) [list jtfProcTimed]  }
  set jtFact(tnxread) 1
}

if {![info exists jtFact(rls)]} {  set jtFact(rls) [list]  }

proc jtfDoCase {tx} {  set tx [regsub -all -- {\s{2,}} $tx { }]
  if {$::jtFact(docase) eq "4"} {  return [string toupper $tx]  }
  set tx [string tolower $tx]
  if {$::jtFact(docase) eq "1"} {  return $tx  }
  if {$::jtFact(docase) eq "3"} {  set tx [split $tx]  ;  set new ""
    foreach x $tx {  append new "[string toupper $x 0 0] "  }
    return [string trim $new]
  }
  return [string toupper $tx 0 0]
}

proc jtfCleanF {tx} {  set tx [string trim $tx]
  if {![string match ?*|*? $tx]} {  return 1  }
  set tx [split $tx |]
  lappend tls [jtfDoCase [string trim [lindex $tx 0]]]
  lappend tls [string trim [join [lrange $tx 1 end] |]]
  return $tls
}

proc jtfProcSubj {nk uh hn ch tx} {
  jtfProcFact $nk $uh $hn $ch $tx subj  ;  return
}

proc jtfProcFact {nk uh hn ch tx {do fact} } {  set ch [string tolower $ch]
  if {$uh eq "Timed"} {
    if {[lsearch -exact $::jtFact(tchan) $ch]=="-1"} {  return  }
  } else {
    if {[lsearch -exact $::jtFact(frchan) $ch]=="-1"} {  return  }
  }
  set tf $::jtFact(file)  ;  set tx [string trim $tx]
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Text file does not exist: $tf"  ;  return
  }
  set tid [open $tf]  ;  set lines [read -nonewline $tid]  ;  close $tid
  set lines [split $lines \n]  ;  set llen [llength $lines]
  if {$llen=="0"} { puthelp "PRIVMSG $ch :Text file is empty: $tf" ; return }
  if {$do ne "subj" && [llength $::jtFact(rls)]>"0"} {
    if {$llen>"1"} {  set rmax [expr {$llen/2}]
      if {$llen>"4" && [string match {*[13579]} $llen]} {  incr rmax  }
      if {$rmax>"50"} {  set rmax 50  }
      if {[llength $::jtFact(rls)]>$rmax} {
        set ::jtFact(rls) [lreplace $::jtFact(rls) $rmax end]
      }
    } else {  set ::jtFact(rls) [list]  }
  }
  if {$uh eq "Timed" || ($do eq "fact" && $tx eq "")} {
    if {[llength $::jtFact(rls)]>"0"} {  set tid -1  ;  set tls ""
      foreach ln $lines {  incr tid
        if {[lsearch -exact $::jtFact(rls) $tid]=="-1"} { lappend tls $tid }
      }
      set lidx [lindex $tls [rand [llength $tls]]]
      set ::jtFact(rls) [linsert $::jtFact(rls) 0 $lidx]
    } else { set lidx [rand [llength $lines]] ; lappend ::jtFact(rls) $lidx }
    set lin [split [lindex $lines $lidx] |]  ;  set pre ""
    if {$::jtFact(tnum)!="0" && $uh eq "Timed"} { set pre "\[[incr lidx]\] " }
    lappend map %subject [string trim [lindex $lin 0]] %fact
    lappend map [string trim [join [lrange $lin 1 end] |]]
    set say [string map $map $::jtFact(facttxt)]
    if {$uh eq "Timed" && [llength $::jtFact(tchan)]>"1"} {
      foreach ch $::jtFact(tchan) {  puthelp "PRIVMSG $ch :$pre$say"  }
    } else {  puthelp "PRIVMSG $ch :$pre$say"  }
  } else {  set tmp ""
    foreach lin $lines {  set sj [lindex [split $lin |] 0]
      if {$do eq "subj"} {
        if {[info exists count($sj)]} {  incr count($sj)
        } else {  set count($sj) 1  ;  lappend tmp $sj  }
      } else {
        if {[string match -nocase $tx $sj]} {  lappend tmp $lin  }
      }
    }
    if {$do eq "subj"} {  set tx ""  ;  set tmp [lsort -dictionary $tmp]
      foreach sj $tmp {  append tx " $sj ($count($sj)),"  }
      set tx [string trimright $tx ,]
      puthelp "PRIVMSG $ch :Subject list & number of facts in each: $tx."
    } else {
      if {[llength $tmp]=="0"} {  set say "For a list of valid subjects,"
        puthelp "PRIVMSG $ch :Subject does not exist: $tx"
        puthelp "PRIVMSG $ch :$say use: $::jtFact(subjcts)"  ;  return
      }
      set lin [lindex $tmp [rand [llength $tmp]]]
      if {[set lidx [lsearch -exact $lines $lin]]!="-1"} {
        if {[set tidx [lsearch -exact $::jtFact(rls) $lidx]]!="-1"} {
          set ::jtFact(rls) [lreplace $::jtFact(rls) $tidx $tidx]
        }
        set ::jtFact(rls) [linsert $::jtFact(rls) 0 $lidx]
      }
      set lin [split $lin |]
      lappend map %subject [string trim [lindex $lin 0]] %fact
      lappend map [string trim [join [lrange $lin 1 end] |]]
      puthelp "PRIVMSG $ch :[string map $map $::jtFact(facttxt)]"
    }
  }
  return
}

proc jtfProcFAdd {nk uh hn ch tx} {  set ch [string tolower $ch]
  if {[lsearch -exact $::jtFact(fachan) $ch]=="-1"} {  return  }
  set tx [string trim $tx]
  if {![string match ?*|*? $tx]} {  set add $::jtFact(factadd)
    puthelp "PRIVMSG $ch :Correct syntax is: $add <subject>|<the fact text>"
    puthelp "PRIVMSG $ch :Example: $add Animal facts|Cats can't taste sweets"
    return
  }
  set tf $::jtFact(file)
  if {![file exists $tf]} {  set nofile 1  }
  set tls [split $tx |]  ;  set subj [jtfDoCase [string trim [lindex $tls 0]]]
  set tx $subj|[string trim [join [lrange $tls 1 end] |]]
  set id [open $tf a]  ;  puts $id $tx  ;  close $id
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Unable to find or make text file: $tf"
  } elseif {[info exists nofile]} {
    puthelp "PRIVMSG $ch :Added first fact to the database: $tx"
  } else {  puthelp "PRIVMSG $ch :Added new fact to the database: $tx"  }
  return
}

proc jtfProcAdd {nk uh hn ch tx} {  set ch [string tolower $ch]
  if {[lsearch -exact $::jtFact(lchan) $ch]=="-1"} {  return  }
  set tx [split [string trim $tx]]
  if {[lindex $tx 0] eq "end" || [string is digit -strict [lindex $tx 0]]} {
    set addat [lindex $tx 0] ; set tx [string trim [join [lrange $tx 1 end]]]
  } else {  set addat end  ;  set tx [join $tx]  }
  if {![string match ?*|*? $tx] || $addat eq "0"} {  set add $::jtFact(add)
    set x "<subject>|<the fact text>"  ;  set y "Subject|Fact to add"
    puthelp "PRIVMSG $ch :Correct syntax is: $add \[position\] $x"
    puthelp "PRIVMSG $ch :Example: $add end $y at end of the file"
    puthelp "PRIVMSG $ch :Example: $add 4 $y at file line 4"
    puthelp "PRIVMSG $ch :Example: $add $y at end of the file"
    return
  }
  set tf $::jtFact(file)  ;  set tx [join [jtfCleanF $tx] |]
  if {![file exists $tf]} {  set addat end  ;  set nofile 1  }
  if {$addat ne "end"} {  set tx "$addat $tx"
    jtfProcEdit $nk $uh $hn $ch $tx add  ;  return
  }
  set id [open $tf a]  ;  puts $id $tx  ;  close $id
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Unable to find or make text file: $tf"
  } elseif {[info exists nofile]} {
    puthelp "PRIVMSG $ch :Added line to new text file: $tx"
  } else {  puthelp "PRIVMSG $ch :Added line at end of text file: $tx"  }
  return
}

proc jtfProcReadF {nk uh hn ch tx} {
  jtfProcRead $nk $uh $hn $ch $tx file  ;  return
}

proc jtfProcTimed {} {
  if {$::jtFact(timed)=="0"} {  unset ::jtFact(tnxread)  ;  return  }
  timer $::jtFact(timed) [list jtfProcTimed]
  set chan [lindex $::jtFact(tchan) 0]
  if {$::jtFact(trand)=="1"} {
    jtfProcRead $::botnick Timed Line $chan $::jtFact(tnxread)
  } else {  jtfProcFact $::botnick Timed Line $chan 0  }
  return
}

proc jtfProcRead {nk uh hn ch tx {do line} } {  set ch [string tolower $ch]
  if {$do eq "file"} {
    if {[lsearch -exact $::jtFact(rchan) $ch]=="-1"} {  return  }
  } elseif {$uh eq "Timed"} {
    if {[lsearch -exact $::jtFact(tchan) $ch]=="-1"} {  return  }
  } else {
    if {[lsearch -exact $::jtFact(lchan) $ch]=="-1"} {  return  }
  }
  set tf $::jtFact(file)
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Text file does not exist: $tf"  ;  return
  }
  set tx [lindex [split [string trim $tx]] 0]
  if {$do eq "line" && (![string is digit -strict $tx] || $tx=="0")} {
    puthelp "PRIVMSG $ch :Correct syntax is: $::jtFact(read) <line#>"
    puthelp "PRIVMSG $ch :Example: $::jtFact(read) 4"  ;  return
  } elseif {$do eq "file"} {  set rdef $::jtFact(rfdef)
    if {$tx ne ""} {
      if {![string match *-* $tx]} {
        if {![string is digit -strict $tx] || $tx=="0"} {  set begin err
        } else {  set begin $tx  ;  set end [expr {$tx+$rdef-1}]  }
      } elseif {$tx eq "-" || [string match *-*-* $tx]} {  set begin err
      } else {   foreach {x y} [split $tx -] { break }
        set dx [string is digit -strict $x];set dy [string is digit -strict $y]
        if {$dx=="1" && $dy=="1"} {
          if {$x>"0" && $y>=$x} {  set begin $x  ;  set end $y
          } else {  set begin err  }
        } elseif {$dx=="0" && $dy=="0"} {  set begin err
        } elseif {$x eq ""} {
          if {$y<"1"} {  set begin err
          } else {  set begin [expr {$y-$rdef+1}]  ;  set end $y
            if {$begin<"1"} {  set begin 1  }
          }
        } elseif {$y eq "" || $y eq "end"} {
          if {$x<"1"} {  set begin err
          } elseif {$y eq "end"} {  set begin $x  ;  set end $y
          } else {  set begin $x  ;  set end [expr {$x+$rdef-1}]  }
        } else {  set begin err  }
      }
    } else {  set begin 1  ;  set end $rdef  }
    set readf $::jtFact(readf)
    if {$begin eq "err"} {  set x "PRIVMSG $ch :Example,"
      puthelp "PRIVMSG $ch :Correct syntax is: $readf \[linenumber(s)\]"
      puthelp "$x read lines 1 to $rdef: $readf"
      puthelp "$x read lines 21 to [expr {20+$rdef}]: $readf 21"
      puthelp "$x read lines 41 to 58: $readf 41-58"
      puthelp "$x read lines 59 to end of file: $readf 59-end"
      return
    }
  }
  set tid [open $tf]  ;  set lnum 0
  while {![eof $tid]} {  set line [gets $tid]
    if {$line ne ""} {  incr lnum
      if {$uh eq "Timed" && $lnum=="1"} {  set ln1 $line  }
      if {$do eq "file"} {
        if {$lnum>=$begin && ($end eq "end" || $lnum<=$end)} {
          puthelp "PRIVMSG $ch :\[$lnum\] $line"
        }
      } elseif {$lnum==$tx} {
        if {$uh ne "Timed"} {  puthelp "PRIVMSG $ch :\[$lnum\] $line"  }
        break
      }
    }
  }
  close $tid
  if {$lnum=="0"} {
    if {[info exists ::jtFact(tnxread)]} {  set ::jtFact(tnxread) 1  }
    puthelp "PRIVMSG $ch :Text file is empty: $tf" ;  return
  }
  if {$lnum>"1"} {  set tl lines  ;  set is are
  } else {  set tl line  ;  set is is  }
  set fc "$lnum $tl in the file"
  if {$do eq "file"} {
    if {$begin>$lnum} {
      puthelp "PRIVMSG $ch :File line $begin doesn't exist ($fc)"
    } elseif {$end eq "end" || $lnum<=$end} {
      puthelp "PRIVMSG $ch :- End of File -"
    } else {  puthelp "PRIVMSG $ch :- There $is $fc -"
      if {$tx eq ""} {
        puthelp "PRIVMSG $ch :For more 'read file' options use: $readf help"
      }
    }
  } elseif {$uh eq "Timed"} {  set pre ""
    if {$lnum==$tx} {  incr ::jtFact(tnxread)
    } else {  set line $ln1  ;  set lnum 1  ;  set ::jtFact(tnxread) 2  }
    if {$::jtFact(tnum)!="0"} {  set pre "\[$lnum\] "  }
    set lin [split $line |]
    lappend map %subject [string trim [lindex $lin 0]] %fact
    lappend map [string trim [join [lrange $lin 1 end] |]]
    set line [string map $map $::jtFact(facttxt)]
    foreach ch $::jtFact(tchan) {  puthelp "PRIVMSG $ch :$pre$line"  }
  } elseif {$do eq "line" && $tx>$lnum} {
    puthelp "PRIVMSG $ch :File line $tx doesn't exist ($fc)"
  }
  return
}

proc jtfProcDel {nk uh hn ch tx} {
  jtfProcEdit $nk $uh $hn $ch $tx del  ;  return
}

proc jtfProcEdit {nk uh hn ch tx {do edit} } {  set ch [string tolower $ch]
  if {[lsearch -exact $::jtFact(lchan) $ch]=="-1"} {  return  }
  set tf $::jtFact(file)
  if {![file exists $tf]} {
    puthelp "PRIVMSG $ch :Text file does not exist: $tf"  ;  return
  }
  set tx [split [string trim $tx]]
  set find [lindex $tx 0]  ;  set tx [string trim [join [lrange $tx 1 end]]]
  set isdig [string is digit -strict $find]
  if {$do eq "edit"} {
    if {$isdig=="0" || $find=="0" || ![string match ?*|*? $tx]} {
      set edit $::jtFact(edit)
      set x "<subject>|<new fact text>"  ;  set y "Subject|New fact to"
      puthelp "PRIVMSG $ch :Correct syntax is: $edit <line#> $x"
      puthelp "PRIVMSG $ch :Example: $edit 4 $y replace file line 4"
      return
    }
  } elseif {$do eq "del" && ($isdig=="0" || $find=="0")} {
    puthelp "PRIVMSG $ch :Correct syntax is: $::jtFact(del) <line#>"
    puthelp "PRIVMSG $ch :Example: $::jtFact(del) 4"  ;  return
  }
  set new [file dirname $tf]/newfile.tmp  ;  set nid [open $new w]
  set tid [open $tf]  ;  set lnum 0
  while {![eof $tid]} {  set line [gets $tid]
    if {$line ne ""} {  incr lnum
      if {$lnum==$find} {
        if {$do eq "edit"} {
          puthelp "PRIVMSG $ch :Replaced line $lnum fact: $line"
          set tx [join [jtfCleanF $tx] |]
          puthelp "PRIVMSG $ch :with the new fact line: $tx"
          puts $nid $tx
        } elseif {$do eq "del"} {
          puthelp "PRIVMSG $ch :Deleted line $lnum fact: $line"
        } elseif {$do eq "add"} {
          puthelp "PRIVMSG $ch :Added new line $lnum fact: $tx"
          puts $nid $tx  ;  puts $nid $line
        }
      } else {  puts $nid $line  }
    }
  }
  close $tid
  if {$find>$lnum} {
    if {$do eq "add"} {  incr lnum
      puthelp "PRIVMSG $ch :Added new line $lnum fact: $tx"
      puts $nid $tx  ;  close $nid  ;  file rename -force $new $tf
    } else {
      if {$lnum>"0"} {  set tl line
        if {$lnum>"1"} {  set tl lines  }
        puthelp "PRIVMSG $ch :File line $find doesn't exist ($lnum $tl in the file)"
      } else {  puthelp "PRIVMSG $ch :Text file is empty: $tf"  }
      close $nid  ;  file delete $new
    }
  } else {  close $nid  ;  file rename -force $new $tf  }
  return
}

proc jtfFixFile {} {  set tf $::jtFact(file)
  if {![file exists $tf]} {  return  }
  putlog "JustTheFacts: Found existing fact file. Inspecting file..."
  set new [file dirname $tf]/newfile.tmp  ;  set nid [open $new w]
  set tid [open $tf]  ;  set lnum 0  ;  set cnum 0  ;  set enum 0
  while {![eof $tid]} {  set line [gets $tid]
    if {$line ne ""} {
      if {![string match ?*|*? $line]} {  incr enum
        if {![info exists efile]} {
          set efile [file dirname $tf]/BadFacts.txt ; set eid [open $efile a]
        }
        puts $eid $line  ;  continue
      }
      incr lnum  ;  puts $nid [set cln [join [jtfCleanF $line] |]]
      if {$cln ne $line} {  incr cnum  }
    }
  }
  close $nid  ;  close $tid  ;  file rename -force $new $tf
  if {[info exists efile]} {  close $eid  ;  set word line  ;  set wd2 it
    if {$enum>"1"} {  set word lines  ;  set wd2 them  }
    putlog "Removed $enum bad fact $word & saved $wd2 to file: $efile"
  }
  if {$cnum>"0"} {  set word line
    if {$cnum>"1"} {  set word lines  }
    putlog "Repaired $cnum fact $word for subject case and/or extra spaces."
  }
  set word line  ;  set wd2 is
  if {$lnum>"1"} {  set word lines  ;  set wd2 are  }
  putlog "There $wd2 $lnum fact $word in the file."
}
jtfFixFile

putlog "JustTheFacts.tcl Ver. 1.1 by SpiKe^^ loaded."

SpiKe^^

Get BogusTrivia 2.06.4.7 at www.mytclscripts.com
or visit the New Tcl Acrhive at www.tclarchive.org
.
Post Reply