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.

I need help... cannot figure this out...

Help for those learning Tcl or writing their own scripts.
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

I need help... cannot figure this out...

Post by Luminous »

Okay, so a bit of code here... I can pastebin it, if preferred. I don't understand why these triggers don't work. I have several problems. Firstly, on !kb, I cannot get the kick reason to work. I want the kicker($hand) to be able to specify one if not, it will just say "Requested by $hand". It won't even do that last part. If I try to add a reason, my bot bans *!*@* for a moment, then unbans it without even kicking.

On !kick.. it works, but how do I scan if user is on $chan, and if not, say they aren't on $chan? My "if {"{[onchan]}..." } {" statement doesn't seem to work like I want... I would like !kb to do the same thing as well.

Code: Select all

bind pub f !kb kickban
proc kickban {nick host hand chan text} {
    if {"$hand" != "handle"} {
       puthelp "PRIVMSG $chan :$nick\: You don't have permission to use that command."
    } else {
       putserv "MODE $chan +b [maskhost [getchanhost [lindex [split $text] 0] $chan]]"
    if {"[lrange [split $text] 1 end]" == ""} {
        puthelp "Kick $chan [lindex [split $text] 0] :Requested by $hand"
    } else {
        puthelp "Kick $chan [lindex [split $text] 0] :[lrange [split $text] 1 end]"
    }
  }
}

bind pub f !kick kick_user
proc kick_user {nick host hand chan text} {
 set whom [lindex $text 0]
    if {"$hand" != "handle"} {
        puthelp "PRIVMSG $chan :$nick\: You don't have permission to use that command."
    } else {
    if {"$whom" == ""} {
        putserv "PRIVMSG $chan :$hand\: You must specify a nick to kick."
    } else {
     if {"{[onchan $whom $chan]}" == "0"} {
        putserv "PRIVMSG $chan :$whom is not on $chan."
    } else {
    if {"[lindex [split $text] 1 end]" == ""} {
        putserv "PRIVMSG $chan :You must specify a kick reason."
    } else {
        puthelp "Kick $chan $whom :[lrange [split $text] 1 end]"
   }
 }
  }
}
 }
So, what am I doing wrong here?

(edited)
Last edited by Luminous on Sat Feb 20, 2010 4:26 pm, edited 1 time in total.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Lets see...
You're a bit keen on using "" and {} all over, even when it's not needed, or where it even might prevent the expected desire. Most notably: {} prevents the substitution of variables, commands, and escape-sequences. Your {} are also unbalanced.

Good example from your code:

Code: Select all

   if {"{[onchan $chan $ whom]}" == "0"} {    
"if" is a command that takes a set of parameters; the conditional, what code to execute when true, and optionally what code to execute when not true. Since the blocks of code should only be executed when the proper condition is set, it's correct to enclose these using {}. Further, the conditional is evaluated by "if", and the result is tested for true/false - hence it should also be enclosed with {}. So far, so good..
Lets look closer at your actual conditional:

Code: Select all

   if {"{[onchan $chan $ whom]}" == "0"} {   =>
"{[onchan $chan $ whom]}" == "0"
Here, we have a string with a starting {, then a command substitution sequence [...] and then a }, which is then compared to "0". This is a proper string, so the command substitution would be done (we've got the "" there), however, that means the {} will be left untended at this level of execution. The result? "0" would be compared to either "{0}" or "{1}", thus always false (two strings that are not equal).

How would I write that line?

Code: Select all

 if {![onchan $chan $whom]} {
Also, I'm not sure if that's just a typo here, but you've got a space between the $ and whom, and the variable $whom is not defined at that point of the code, you'll have to assign it a value first, or use a different variable.

More, you've got improper list operations on a few locations. Don't use lindex on strings, only on lists. Use split to convert a string into a list. Use join to convert a list to a string (when needed).
lindex always returns the content of the list item, lrange returns a new list with the selected list items.
Be very careful when submitting multiple indexes with lindex - this works very differently than lrange.
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

nml375 wrote: Also, I'm not sure if that's just a typo here, but you've got a space between the $ and whom, and the variable $whom is not defined at that point of the code, you'll have to assign it a value first, or use a different variable.
Yes, it was a typo... Not sure why I added the $whom into !kb... must have gotten it mixed up with the other one...
More, you've got improper list operations on a few locations. Don't use lindex on strings, only on lists. Use split to convert a string into a list. Use join to convert a list to a string (when needed).
lindex always returns the content of the list item, lrange returns a new list with the selected list items.
Be very careful when submitting multiple indexes with lindex - this works very differently than lrange.
I'm confused about what the right thing to do there is... I've tried it with and without split, etc, but I get the same mess.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

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"
  }
}
Last edited by nml375 on Sun Feb 21, 2010 5:29 pm, edited 1 time in total.
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Oh, okay... that makes more sense now. :D I originally was trying to make variables like $kreason to use rather than the untidy lindex[...] stuff, but I was using the wrong list operators I see so that is why that wasn't working properly. I also completely forgot about "elseif". Thanks for taking the time to explain that. I've been trying to find decent examples but have been having trouble doing so.

Edit: the !kick part of that script works just as I wanted, but the !kb one still doesn't... perhaps I need to apply the ban another way? I know I can use newchanban, but I'd rather have the bans in the channel banlist. Also worth mentioning that I am looking to ban via *!user@*.domain. Type 0 mask on my network.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Whether or not you can add bans by simply issuing the MODE irc command, comes down to how you've set up your channel record, as well as user records. An eggdrop would rarely remove a ban placed by itself however.

I believe there was a post way back regarding a more flexible replacement for the maskhost command. Might be this one: http://forum.egghelp.org/viewtopic.php?t=8741
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Yeah, I have seen that thread.. but I am not sure what to do with that, how to use it, how to modify it to do what I need. At one point, I had my script banning the way I wanted, I've just always had kick reason issues.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

"Simply" add the proc posted by User in your script. Adjust the maskhostDefaultType setting, or add the desired type to the maskhost command as suggested.
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Oh, okay... I saw several scripts there and wasn't sure of which to use... Okay, so plugging that in is easy enough... so then on the putserv part, it should just then be: putserv "MODE $chan +b [maskhost $whom]"?, assuming I set the bantype properly?
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

yep, or [maskhost $whom 0] for type 0 regardless of the maskhostDefaultType setting
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Ah, okay.. yeah, that 0 is how I managed to do the ban before I believe. Well, I have it all plugged it but it still doesn't work... guess I'm either going to have to rethink this or simplify it somehow. I am thinking the onchan is maybe messing it up, but that works fine in !kick, so I don't get what the difference is, lol.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Could you elaborate "messing it up"?
IE what works, what does not work, what does not work as intended, what is the intended behaviour, what is the actual behavior, etc.
NML_375
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Maybe it's just not going past onchan?

What does work is the "You don't have permission" message if you are not $hand. The rest of it doesn't. I could try taking out onchan completely. Its really not necessary in this case... my $hand isn't going to use this command in silliness.
L
Luminous
Op
Posts: 146
Joined: Fri Feb 12, 2010 1:00 pm

Post by Luminous »

Well, so much for that theory... lol
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Do you get any error messages in your logs or dcc console?
NML_375
Post Reply