Yes, it was a typo... I did specify $whom at the beginning I thought?
Not within that proc. You have to remember that variables that get declared within a proc will only exist within the single invocation of that proc, and only inside it. You can access global variables using full namespace addressing or the global or upvar command. But I believe this is beyond the context of this script.
You do set whom within kick_user, but not within kickban (unless that's another typo).
I'm confused about what the right thing to do there is...
List are delicate data structures in tcl, that allow you to store multiple data entities (strings, other lists, numbers, etc) in a single "string". lindex is a command used to retrieve one specific item from the list, thus you must supply a valid list. In the case of selecting a single word from a user command, you'd usually use split to convert the string into a list, and then lindex to select the desired item (word). You could also use lrange in a similar manner to retrieve a subset of items - such as second word to the last word. lrange however returns a new list, not a string.
For simple strings, you usually get away with being sloppy, since tcl uses whitespaces to separate list elements. In some cases, however, tcl needs to escape the content of a list item to keep a valid list tructure, and this is where things may go bad. Say there's a { in the beginning of a word; this happens to be one of the characters used to "contain" or escape a complex item into a list. If you don't use proper coding, you'll see your script breaking here...
A quick rule of thumb, only use commands (such as lindex, lrange, etc) that expect list inputs, with actual lists. A string is only a list if it was generated by some command that returns a list (such as split and list). If you are uncertain, don't assume a string to be a valid list - check it's source, and if needed, consult manual pages for the source commands. In the case of data coming from a human user, never assume it to be a valid list.
Perhaps a few examples:
Code: Select all
proc kick_user {nick host hand chan text} {
set whom [lindex $text 0]
## Bad: $text originates from a user, and is thus a string, not a list. Should be:
proc kick_user {nick host hand chan text} {
set whom [lindex [split $text] 0]
puthelp "Kick $chan $whom :[lrange [split $text] 1 end]"
## Bad: $text is a string, but properly split into a list. However, lrange returns a new list, not a string.
## This may result in characters such as {} being injected into the string here and there. Use join to concatenate the list items into a single string.
##Should be:
puthelp "Kick $chan $whom :[join [lrange [split $text] 1 end]]"
Also, a hint:
Since you use the same list operations in multiple places of the same proc (in a fashion that would yield the very same result each time), consider doing this once in the begining of the proc, and save the result in variables. Usually makes the code alot easier to read - $reason makes alot more sense then [join [lrange [split $text] 1 end]] in the middle of a kick command.
Usually don't like posting complete fixes here, but just to give you an idea I've taken the liberty to tidy up your script alittle:
Code: Select all
bind pub f !kb kickban
proc kickban {nick host hand chan text} {
set list [split $text]
set whom [lindex $list 0]
set reason [join [lrange $list 1 end]]
if {$hand != "handle"} {
puthelp "PRIVMSG $chan :$nick: You don't have permission to use that command."
} elseif {$whom == ""} {
putserv "PRIVMSG $chan :$hand: You must specify a nick to kick."
} elseif {![onchan $whom $chan]} {
putserv "PRIVSMG $chan :$whom is not on $chan."
} else {
putserv "MODE $chan +b [maskhost "$whom![getchanhost $whom $chan]"]"
if {$reason == ""} {
puthelp "Kick $chan $whom :Requested by $hand"
} else {
puthelp "Kick $chan $whom :$reason"
}
}
}
bind pub f !kick kick_user
proc kick_user {nick host hand chan text} {
set list [split $text]
set whom [lindex $list 0]
set reason [join [lrange $list 1 end]]
if {$hand != "handle"} {
puthelp "PRIVMSG $chan :$nick: You don't have permission to use that command."
} elseif {$whom == ""} {
putserv "PRIVMSG $chan :$hand: You must specify a nick to kick."
} elseif {![onchan $whom $chan]} {
putserv "PRIVMSG $chan :$whom is not on $chan."
} elseif {$reason == ""} {
putserv "PRIVMSG $chan :You must specify a kick reason."
} else {
puthelp "Kick $chan $whom :$reason"
}
}