# 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.
# 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."