calc.tcl
June 20th, 2007
No comments
#### calc.tcl v1.0.1 ###########################################################
################################################################################
## Written by: ##
## KuNgFo0 (http://www.eggfaq.com/). ##
## ##
## Modified by: ##
## Brian Schmidt aka. brianMan. ##
################################################################################
#### Readme / Help #############################################################
################################################################################
## This script is ripped from KuNgFoO's ib.tcl v3.19 (infobot) script. ##
## ##
## Script that can calculate just about anything ;) ##
## ##
## Usage: ##
## To have the .calc[ulate] commands available on a channel you need to set ##
## the channel flag +calculator from the console/partyline . ##
## ``.chanset #channel +calculator´´ ##
## ##
## Channel Commands (available only if channel is +convert): ##
## .calc[ulate] ##
## Example: ##
## ``.calc 15*20+3´´ ##
################################################################################
#### Changelog #################################################################
################################################################################
## v1.0.1 ##
## * Minor code cleanup ##
## ##
## v1.0.0 ##
## + Initial release. ##
## * Changed the default trigger ``botname, calc[ulate]´´ to ``.calc[ulate]´´ ##
## + Added the possibility to control which channels could use the commands ##
## with the channel flag ``+/-calculator´´ ##
################################################################################
bind pub - .calc pub_calc
bind pub - .calculate pub_calc
bind msg - calc msg_calc
bind msg - calculate msg_calc
setudef flag calculator
# You shouldn't change these, however you may add additional variables
# These are used via %varname in the 'calculate' command
# Example: Mybot, calculate %pi / 2
set calc_const(pi) 3.14159265358979323846 ; # PI
set calc_const(e) 2.7182818284590452354 ; # E
set calc_const(n) 6.0221367e23 ; # Avogadro's number [1/mol]
set calc_const(R) 8.314510 ; # Universal gas constant [J/(mol*K)]
set calc_const(k) 1.380658e-23 ; # Boltzmann's constant [J/K]
set calc_const(G) 6.67259e-11 ; # Universal gravitational constant [N*m^2/kg^2]
set calc_const(h) 6.62606891e-34 ; # Planck's constant [J*s]
set calc_const(c) 2.99792458e8 ; # Speed of light [m/s]
# No more editing required
proc xrange {xr xr1 xr2} {
return [join [lrange [split $xr] $xr1 $xr2]]
}
proc xindex {xr xr1} {
return [join [lrange [split $xr] $xr1 $xr1]]
}
proc calc_fixdata {arg output} {
global botnick
if {[string index $output 0] != "#"} {
regsub -all -nocase {$output's} $arg "your" arg
}
regsub -all -nocase {$botnick's} $arg "my" arg
return $arg
}
proc calc_msg {targets arg} {
foreach target $targets { puthelp "PRIVMSG $target :[calc_fixdata $arg $target]" }
}
proc calc_fixtopic {arg} {
regsub -all {[\\\{\}\[\]\"]} $arg {} arg ; # Bad characters
regsub -all {(\s)+} $arg {\1} arg ; # Double whitespace
regsub -all {^\s*|\s*$} $arg {} arg ; # Whitespace at ends
return $arg
}
# Begin 'calc' code
proc calc_fixexpr {exp} {
global calc_const
set exp [calc_fixtopic $exp]
foreach i [array names calc_const] {
regsub -all "\%$i" $exp $calc_const($i) exp
}
return $exp
}
# End 'calc' code
# Begin Public binds code
proc msg_calc {nick uhost hand arg} {
global botnick
pub_calc $nick $uhost $hand "" $arg
}
proc pub_calc {nick uhost hand chan arg} {
global botnick calc_flag
if {(![isbotnick $nick]) && (![matchattr $hand +b])} {
if {(![string match "$chan" ""]) && (![channel get $chan calculator])} {
return 0 ; # If command comes from a channel, and that channel doesn't have +calculator then ignore
}
set isuser [expr {[matchattr $hand - $chan] || [matchattr $hand -]}] ; # Note that $chan might be "", so we must handle both cases
if {([validchan $chan]) && ($isuser)} {
set output1 $chan ; # The bot sends the text to the channel for users
} else {
set output1 $nick ; # Non-users get privmsg'd
}
if {[set i [string last ">" $arg]] == -1} {
set output2 $output1 ; # By default, output2 (~stdout~) goes to output1 (~stderr~)
} else {
# Output has been redirected
if {(!$isuser) || ([set output2 [string trim [string range $arg [expr $i + 1] end] " "]] == "")} {
set output2 $output1 ; # Error (User doesn't have access, or output was ""), so we go back to the default
}
set arg [string trim [string range $arg 0 [expr $i - 1]] " "]
}
set remainder [xrange $arg 0 end]
if {$remainder == ""} {
calc_msg $output1 "error parsing sentence"
} elseif {[catch {expr [calc_fixexpr $remainder]} output]} {
calc_msg $output1 "error calculating '$remainder' ($output)"
} else {
calc_msg $output2 "$remainder = $output"
}
}
}
# End Public binds code
# Init stuff
if {[catch {package require Tcl 8.2} error]} {
putlog "error TCL v8.2 or higher is required to run this script"
return 0
}
putlog "*** LOADED: calc.tcl"
################################################################################
## Written by: ##
## KuNgFo0 (http://www.eggfaq.com/). ##
## ##
## Modified by: ##
## Brian Schmidt aka. brianMan. ##
################################################################################
#### Readme / Help #############################################################
################################################################################
## This script is ripped from KuNgFoO's ib.tcl v3.19 (infobot) script. ##
## ##
## Script that can calculate just about anything ;) ##
## ##
## Usage: ##
## To have the .calc[ulate] commands available on a channel you need to set ##
## the channel flag +calculator from the console/partyline . ##
## ``.chanset #channel +calculator´´ ##
## ##
## Channel Commands (available only if channel is +convert): ##
## .calc[ulate] ##
## Example: ##
## ``.calc 15*20+3´´ ##
################################################################################
#### Changelog #################################################################
################################################################################
## v1.0.1 ##
## * Minor code cleanup ##
## ##
## v1.0.0 ##
## + Initial release. ##
## * Changed the default trigger ``botname, calc[ulate]´´ to ``.calc[ulate]´´ ##
## + Added the possibility to control which channels could use the commands ##
## with the channel flag ``+/-calculator´´ ##
################################################################################
bind pub - .calc pub_calc
bind pub - .calculate pub_calc
bind msg - calc msg_calc
bind msg - calculate msg_calc
setudef flag calculator
# You shouldn't change these, however you may add additional variables
# These are used via %varname in the 'calculate' command
# Example: Mybot, calculate %pi / 2
set calc_const(pi) 3.14159265358979323846 ; # PI
set calc_const(e) 2.7182818284590452354 ; # E
set calc_const(n) 6.0221367e23 ; # Avogadro's number [1/mol]
set calc_const(R) 8.314510 ; # Universal gas constant [J/(mol*K)]
set calc_const(k) 1.380658e-23 ; # Boltzmann's constant [J/K]
set calc_const(G) 6.67259e-11 ; # Universal gravitational constant [N*m^2/kg^2]
set calc_const(h) 6.62606891e-34 ; # Planck's constant [J*s]
set calc_const(c) 2.99792458e8 ; # Speed of light [m/s]
# No more editing required
proc xrange {xr xr1 xr2} {
return [join [lrange [split $xr] $xr1 $xr2]]
}
proc xindex {xr xr1} {
return [join [lrange [split $xr] $xr1 $xr1]]
}
proc calc_fixdata {arg output} {
global botnick
if {[string index $output 0] != "#"} {
regsub -all -nocase {$output's} $arg "your" arg
}
regsub -all -nocase {$botnick's} $arg "my" arg
return $arg
}
proc calc_msg {targets arg} {
foreach target $targets { puthelp "PRIVMSG $target :[calc_fixdata $arg $target]" }
}
proc calc_fixtopic {arg} {
regsub -all {[\\\{\}\[\]\"]} $arg {} arg ; # Bad characters
regsub -all {(\s)+} $arg {\1} arg ; # Double whitespace
regsub -all {^\s*|\s*$} $arg {} arg ; # Whitespace at ends
return $arg
}
# Begin 'calc' code
proc calc_fixexpr {exp} {
global calc_const
set exp [calc_fixtopic $exp]
foreach i [array names calc_const] {
regsub -all "\%$i" $exp $calc_const($i) exp
}
return $exp
}
# End 'calc' code
# Begin Public binds code
proc msg_calc {nick uhost hand arg} {
global botnick
pub_calc $nick $uhost $hand "" $arg
}
proc pub_calc {nick uhost hand chan arg} {
global botnick calc_flag
if {(![isbotnick $nick]) && (![matchattr $hand +b])} {
if {(![string match "$chan" ""]) && (![channel get $chan calculator])} {
return 0 ; # If command comes from a channel, and that channel doesn't have +calculator then ignore
}
set isuser [expr {[matchattr $hand - $chan] || [matchattr $hand -]}] ; # Note that $chan might be "", so we must handle both cases
if {([validchan $chan]) && ($isuser)} {
set output1 $chan ; # The bot sends the text to the channel for users
} else {
set output1 $nick ; # Non-users get privmsg'd
}
if {[set i [string last ">" $arg]] == -1} {
set output2 $output1 ; # By default, output2 (~stdout~) goes to output1 (~stderr~)
} else {
# Output has been redirected
if {(!$isuser) || ([set output2 [string trim [string range $arg [expr $i + 1] end] " "]] == "")} {
set output2 $output1 ; # Error (User doesn't have access, or output was ""), so we go back to the default
}
set arg [string trim [string range $arg 0 [expr $i - 1]] " "]
}
set remainder [xrange $arg 0 end]
if {$remainder == ""} {
calc_msg $output1 "error parsing sentence"
} elseif {[catch {expr [calc_fixexpr $remainder]} output]} {
calc_msg $output1 "error calculating '$remainder' ($output)"
} else {
calc_msg $output2 "$remainder = $output"
}
}
}
# End Public binds code
# Init stuff
if {[catch {package require Tcl 8.2} error]} {
putlog "error TCL v8.2 or higher is required to run this script"
return 0
}
putlog "*** LOADED: calc.tcl"