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.

A few more Questions:

Help for those learning Tcl or writing their own scripts.
Post Reply
N
Nimos
Halfop
Posts: 80
Joined: Sun Apr 20, 2008 9:58 am

A few more Questions:

Post by Nimos »

1. On a "PUBM" bind, the last var is the whole message. How can I get only the word after the trigger?

2. How to use the "Global" variable set comman?

3. Whats the difference between putserv, puthelp & putquick? and which is best to use?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

1. First off, do you really need pubm binding? At first it almost sounds like a simple pub binding would do.
If you do go with pubm, you'll have to use various string manipulation techniques to accomplish what you ask for. One of the simplest, assuming you've got a fixed length trigger, is using "string range". Other options might be converting the string to a list (using split), and then use commands such as lindex or lrange and join to select the desired part.

2. global varname
Links the local variable named varname to the globalspace one with the same name.

3. The difference is in which queue the command is placed within.
puthelp has the lowest priority, and will only be sent when the other queues are empty. This is the preferred queue for anything not essential for protecting your channel, as it won't block kicks, modes, etc with non-critical commands.
putserv has higher priority than puthelp, but lower than putquick. This queue should be used for important things, such as opping members.
putquick has the highest priority, and should only be used for critical commands, such as kicking/banning people trying to take control of your channel, etc.

A common misconception is that putquick/putserv is faster than puthelp. This is not the case. They all use the same punishment calculator and throttling. puthelp will only be delayed if there is important stuff in the putserv and putquick queues.
  • If you are writing a script that outputs some kind of text to the channel, you should always strife to use puthelp - no public chatter is more important than keeping your channel safe. And using puthelp won't hurt performance if your eggie is not used for channel security.
  • If you are interacting with nickser/chanserv/etc, or pushing modes with your script, considder using the putserv command, as these would most likely be more important than simple chatter.
  • If your script is protecting your channel from floodnets or spammers, use putserv or putquick depending on the urgency of the action. Kicking TO-botnets would probably be more important than removing a spammer, but removing a virus-spreading spammer may be more important than removing a single floodbot.
NML_375
N
Nimos
Halfop
Posts: 80
Joined: Sun Apr 20, 2008 9:58 am

Post by Nimos »

thanks for your answer

i need a pubm binding because of a wildcard...imho pub binds dont support wildcards, right?

can you explain 1. more, if possible by giving an example?
im not really expierienced in tcl...
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

If you need wildcards, you indeed need the pubm binding.
string range <string> <start> <end> selects a substring of <string> defined by the ranges <start> and <end>.
Provided that the trigger is fixed-length, you could do something like this:

Code: Select all

bind pubm - "% myword *" myproc
proc myproc {nick host hand chan text} {
 set t [string range $text 6 end]
}
This specific case could, however, easily be replaced with a pub-binding.

If, however, you've got something a bit more complex, you'll most likely end up with using split, lrange, and join:

Code: Select all

bind pubm - "% %word *" myproc
proc myproc {nick host hand chan text} {
 set t [join [lrange [split $text " "] 1 end] " "]
}
NML_375
N
Nimos
Halfop
Posts: 80
Joined: Sun Apr 20, 2008 9:58 am

Post by Nimos »

works! thanks you!

now i need 2 more:

1. I have an !kick bind, but it is not working at ppl with [ ] in the name....how to fix it?

2. is there a way to put all users in a specified channel into a variable?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

1. Most likely you screwed up somewhere in the code. Without seing the code I could only make fairly educated guesses as to the error. My first guess would be that you use lindex or lrange on a string, which is a huge nono. Second guess would be that you use utimers improperly.

2. Yup:

Code: Select all

set myvar [chanlist <channel>] #store a list of channel-members for <channel>
NML_375
N
Nimos
Halfop
Posts: 80
Joined: Sun Apr 20, 2008 9:58 am

Post by Nimos »

yes, i used lrange in the wildcard bind...

but why does it work with people without [ ] in their names?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Because you are using it on a string, you should only use it on lists - ever!

lrange expects the first argument to be a valid tcl list-structure. These may look similar to strings at a first glance, however, they are not. Especially in the case where there's characters such as {[]} (among others), special formatting is done to preserve the structure of the list. If you attempt to use a malformatted list, you'll end up with garbled data and unexpected results.

If you need to use lrange to extract a substring from a string, you must use it like this (I'll explain why after the example):

Code: Select all

#Lets first store our string in a variable, not necessary, but helps keep the example easy-readable
set mystring "This is an example string containing odd characters such as {}"
#Now store a substring in newvar
set newvar [join [lrange [split $mystring " "] 2 3] " "]
So, what did we do here?
First, we stored the string in mystring, so we have something to work with. Next, using split, we converted it into a list having space as the separator.
Once we have a list, it is safe to pass it to lrange, where we use index 2 and 3 as start- and end-values. This will, however, return a new list, which is not what we really wanted.
In order to get a string, we thus use join to convert the new list back into a string, once again using a space as the separator; and store it in newvar.

If mystring would have contained a proper list from the beginning, we should not have split'd it in the first place. In the same manner, if we intended to use the result with a command expecting a list (such as foreach), we would not join it into a string.

The bottom line is, always keep track of whether the data you are processing is a string or a list; and use the proper commands for it (converting between them when necessary). A good rule of thumb, if the data is coming from a human, consider it a string.
NML_375
N
Nimos
Halfop
Posts: 80
Joined: Sun Apr 20, 2008 9:58 am

Post by Nimos »

but whats the difference between this one, and the example above?

the only one I see is "2 3" instead of "2 end"...
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Could you post the code?
NML_375
N
Nimos
Halfop
Posts: 80
Joined: Sun Apr 20, 2008 9:58 am

Post by Nimos »

ok

Code: Select all

pind pubm Q "*</002Nimos/002> bot *" servercmd

proc servercmd {nick host chan text} {

set com [lrange [split $text " " ] 3 end]
set targ [lrange [split $com " "] 1 end]
# I know I can set $com better with "3 4" instead of "3 end" now, but when i wrote the script I just used the code u gave me in reply 4 of this thread...

if {$chan == "#mychan"} {
            if {$com == "kick $targ"} {
                     putkick $chan $targ "Requested by Nimos"
                     puthelp "privmsg $chan :!say $targ was kicked from IRC!"
            } elseif {
            #Followed by a couple of other cmd's.....
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

The thing here, is that lrange returns a list, not a string.

Code: Select all

set com [lrange [split $text " " ] 3 end]
Here com is set to be a list, consisting of the 4th to last "words" in text.

Code: Select all

set targ [lrange [split $com " "] 1 end]
Here you assume com to be a string (which it is not, it's a list!), and try to split it into a new list. You then extract the 2nd to the last list item, and store it as a list in targ.

Code: Select all

...
            if {$com == "kick $targ"} {
Now you compare the list in com to a string consisting of the word "kick" followed by the list in targ (which basically becomes a very awkward string with psuedo-list properties).

First off, you really, really need to understand the difference between a string and a list. A list has a very delicate structure, whereas a string has pretty much none. Trying to manipulate a list as if it was a string (like "kick $targ") will most likely break the structure of the list. Assuming a string to have list-like structure is just as bad. Also, treating a list as if it was a string (such as [split $com " "]) will produce extra characters such as {} whenever there are non-simple list elements within the list. If you need to convert a list into a string, use the join-command as I illustrated in an earlier post.

All that said, what you wish to accomplish could be done alot simpler;

1st, convert text to a list, and store it in a new variable (I'll use tlist in this example). Use split for this

2nd, extract the 4th list element from tlist, and store it in a new variable (such as cmd). Since we're only interested in one single list element, we'll use lindex rather than lrange. Lindex returns the contents of the list-item, rather than a sublist, meaning we do not have to use join here.

3rd, extract teh 5th list element fromtlist, and store it in a new variable (such as target). Do this in the exact same manner as with cmd.

4th, test the string in cmd against "kick", to see if we should kick or not. I'd suggest using string equal for this, as it allows non-case sensitive matching.

5th, if the above test matches, do the kick using putkick using target as the kick-target.[/code]
NML_375
N
Nimos
Halfop
Posts: 80
Joined: Sun Apr 20, 2008 9:58 am

Post by Nimos »

thanks for your explanations!

everything works fine now!
m
metroid
Owner
Posts: 771
Joined: Wed Jun 16, 2004 2:46 am

Post by metroid »

I didn't read nml375's wall of text but you seem to be missing the handle var which is required for pubm binds.

I'd be suprised if your script worked as expected.
Post Reply