| View previous topic :: View next topic |
| Author |
Message |
gasak Halfop
Joined: 09 Aug 2010 Posts: 45
|
Posted: Tue Jun 05, 2012 1:13 am Post subject: [SOLVED]variable inside the proc |
|
|
Hi,
I don't understand yet much about list operation in TCL. I just starting learning TCL tho' I have question about calling variable inside the proc.
For example i have this list
| Code: | | set advert(words) "*http:* *www.* *.com*" |
And i want to call that list inside the proc to match the kick reason.
| Code: | foreach word $advert(words) {
if {[string match -nocase [lindex $advert(words)] $txt] } {return 0}
} |
So i need it for my kick reason
| Code: | | putserv "KICK $chan $nick :spam match from $word not allowed! |
But i got confused on the list operation command. It detects the whole advert(words) list. I still have no idea what list operation to use. Is it an lrange, lindex, or other. Please teach me. My code are so massy
Thank you _________________ Learning Knows No Boundaries!!
Last edited by gasak on Wed Jun 06, 2012 9:34 pm; edited 1 time in total |
|
| Back to top |
|
 |
nml375 Revered One
Joined: 04 Aug 2006 Posts: 2857
|
Posted: Tue Jun 05, 2012 12:32 pm Post subject: |
|
|
When using foreach-loops to iterate though lists, you specify an iterator-variable (in your code it's word), which will be updated with the next element in the list upon each iteration of the list. Thus, you should not use lindex on the list to extract the item.
| Code: | foreach word $advert(words) {
if {[string match -nocase $word $txt]} {...
|
_________________ NML_375, idling at #eggdrop@IrcNET |
|
| Back to top |
|
 |
caesar Mint Rubber

Joined: 14 Oct 2001 Posts: 3741 Location: Mint Factory
|
Posted: Tue Jun 05, 2012 1:50 pm Post subject: |
|
|
Also, in order to go to the next element in the list if a statement is false use continue not return . Example:
| Code: |
foreach word $advert(words) {
if {![string match -nocase $word $txt]} continue
|
that means if the current element that is taken from the $advert(words) doesn't match the $txt then it will continue with the next element. In order to stop the iteration use break instead of continue. _________________ Once the game is over, the king and the pawn go back in the same box. |
|
| Back to top |
|
 |
gasak Halfop
Joined: 09 Aug 2010 Posts: 45
|
Posted: Tue Jun 05, 2012 11:42 pm Post subject: |
|
|
I tried but doesn't work..
Ok here's the full code:
| Code: | set advban(time) "30"
set advban(chans) "#chan"
set advban(words) "*http*//* *http:* *www.* *.htm* *ftp*//* *www.*.co* */server*.*.*"
set advban(exempts) ""
bind pubm - "*" advban
proc advban {nick host hand chan txt} {
global advban
set advban(chans) [string tolower $advban(chans)]
set chan [string tolower $chan]
if {([string length [string trim $advban(chans)]] != 0) && ([lsearch -exact [split $advban(chans)] $chan] == -1)} {return 0}
foreach exempt $advban(exempts) {
if {[lsearch $txt $exempt]} {return 0}
}
foreach word $advban(words) {
if {![string match -nocase $word $txt]} {continue}
}
if {![validuser $nick] && ![isop $nick $chan]} {
set ban *!*@[lindex [split $host @] 1]
putquick "MODE $chan +b $ban"
putquick "KICK $chan $nick :Spam match from ($word) is not allowed here"
timer $advban(time) {putquick "MODE $chan -b $ban"}
}
} |
I got 2 errors there. the $word on kick msg doesnt work and the timer also doesnt work. It says wrong $chan for the timer part.
Please help. Thanks. _________________ Learning Knows No Boundaries!! |
|
| Back to top |
|
 |
caesar Mint Rubber

Joined: 14 Oct 2001 Posts: 3741 Location: Mint Factory
|
Posted: Wed Jun 06, 2012 12:21 am Post subject: |
|
|
| Code: |
foreach element $list {
if {whatever $element check you wish returns true} {
do this action
} else {
do this second action as the if statement returned false
}
}
|
In your case you should check each spoken word by the user and compare it with each element you have in the blackilst, but before that check if the word is not in the except list like this:
| Code: |
set found 0
foreach word [split $txt] {
if {[lsearch -nocase $advban(exempts) $word] != -1} break
foreach element [split $advban(words)] {
if {![string match -nocase $word $element]} continue
set found 1
set badword $word
break
}
}
if {$found} {
do whatever you wish as there has been a match with one of the words in the blacklist and that word has been stored in $badword variable
}
|
_________________ Once the game is over, the king and the pawn go back in the same box. |
|
| Back to top |
|
 |
gasak Halfop
Joined: 09 Aug 2010 Posts: 45
|
Posted: Wed Jun 06, 2012 12:29 am Post subject: |
|
|
ok thanks caesar.. i'll give it a try now.. _________________ Learning Knows No Boundaries!! |
|
| Back to top |
|
 |
gasak Halfop
Joined: 09 Aug 2010 Posts: 45
|
Posted: Wed Jun 06, 2012 12:42 am Post subject: |
|
|
caesar, i got this error:
| Quote: | | Tcl error [advban]: bad option "-nocase": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start |
_________________ Learning Knows No Boundaries!! |
|
| Back to top |
|
 |
caesar Mint Rubber

Joined: 14 Oct 2001 Posts: 3741 Location: Mint Factory
|
Posted: Wed Jun 06, 2012 4:34 am Post subject: |
|
|
That's cos you have an outdated TCL library version. Anyway, replace:
| Code: |
if {[lsearch -nocase $advban(exempts) $word] != -1} break
|
with:
| Code: |
if {[lsearch -equal $advban(exempts) [string tolower $word]] != -1} break
|
Btw, you should move the:
| Code: |
if {![validuser $nick] && ![isop $nick $chan]} {
|
after the global advban as it makes more sense to be there if you wish to skip a user if it's known to the bot AND is a channel operator. _________________ Once the game is over, the king and the pawn go back in the same box. |
|
| Back to top |
|
 |
gasak Halfop
Joined: 09 Aug 2010 Posts: 45
|
Posted: Wed Jun 06, 2012 8:09 am Post subject: |
|
|
The same error caesar
| Quote: | | Tcl error [spamban]: bad option "-equal": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start |
Is it correct the placement of my code?
| Code: | proc advban {nick host hand chan txt} {
global advban
if {![validuser $nick] && ![isop $nick $chan]} {
set advban(chans) [string tolower $advban(chans)]
set chan [string tolower $chan]
if {([string length [string trim $advban(chans)]] != 0) && ([lsearch -exact [split $advban(chans)] $chan] == -1)} {return 0}
foreach exempt $advban(exempts) {
if {[lsearch $txt $exempt]} {return 0}
}
set found 0
foreach word [split $txt] {
if {[lsearch -equal $advban(exempts) [string tolower $word]] != -1} break
foreach element [split $advban(words)] {
if {![string match -nocase $word $element]} continue
set found 1
set badword $word
break
}
}
if {$found} {
set ban *!*@[lindex [split $host @] 1]
putquick "MODE $chan +b $ban"
putquick "KICK $chan $nick :Spam match from ($word) is not allowed here"
timer $advban(time) {putquick "MODE $chan -b $ban"}
}
} |
anyway, should i remove this code?
| Code: | foreach exempt $advban(exempts) {
if {[lsearch $txt $exempt]} {return 0}
} |
Since you already called it inside.
Thanks. _________________ Learning Knows No Boundaries!! |
|
| Back to top |
|
 |
caesar Mint Rubber

Joined: 14 Oct 2001 Posts: 3741 Location: Mint Factory
|
Posted: Wed Jun 06, 2012 8:29 am Post subject: |
|
|
Something like this:
| Code: |
set advban(time) "30"
set advban(chans) "#chan"
set advban(words) "*http*//* *http:* *www.* *.htm* *ftp*//* *www.*.co* */server*.*.*"
set advban(exempts) ""
bind pubm - "*" advban
proc advban {nick host hand chan txt} {
global advban
if !{[string length $advban(chans)]} return
if {[lsearch -exact $advban(chans) $chan] == -1} return
if {[validuser $nick] && [isop $nick $chan]} return
set found 0
foreach word [split $txt] {
set word [string tolower $word]
if {[lsearch -equal $advban(exempts) $word] != -1} break
foreach element [split $advban(words)] {
if {![string match -nocase $word $element]} continue
set found 1
set badword $word
break
}
}
if {$found} {
set ban *!*@[lindex [split $host @] 1]
putquick "MODE $chan +b $ban"
putquick "KICK $chan $nick :Spam match from ($badword) is not allowed here"
timer $advban(time) [list "pusmode $chan -b $ban"]
}
}
|
Haven't tested so let me know if you get any issues.
Edit: fixed typo. _________________ Once the game is over, the king and the pawn go back in the same box.
Last edited by caesar on Wed Jun 06, 2012 10:15 am; edited 1 time in total |
|
| Back to top |
|
 |
gasak Halfop
Joined: 09 Aug 2010 Posts: 45
|
Posted: Wed Jun 06, 2012 9:30 am Post subject: |
|
|
Hi caesar,
I just tested it but it doesn't work at all. Nothings happen when the badwords trigger said on channel. _________________ Learning Knows No Boundaries!! |
|
| Back to top |
|
 |
caesar Mint Rubber

Joined: 14 Oct 2001 Posts: 3741 Location: Mint Factory
|
Posted: Wed Jun 06, 2012 10:15 am Post subject: |
|
|
Oh sorry, forgot a ! in:
| Code: |
if {[string length $advban(chans)]} return
|
that should be:
| Code: |
if {![string length $advban(chans)]} return
|
_________________ Once the game is over, the king and the pawn go back in the same box. |
|
| Back to top |
|
 |
nml375 Revered One
Joined: 04 Aug 2006 Posts: 2857
|
Posted: Wed Jun 06, 2012 1:17 pm Post subject: |
|
|
I'd suggest something along these lines;
Iterate through each badword-pattern, and get a list of matching words from the spoken text.
Since you'd like to use wildcards in your exempts-list, we'll have to iterate through this list for each match, and see if it should be exempted. If it should be exempted, move on to the next match; else, ban the user and be done with it.
Further, instead of manually adding the ban, kicking the user, and setting up a timer to finally remove it, why not just use the newchanban command with a custom expire-time?
The above converted to code:
| Code: | set advban(time) "30"
set advban(chans) [list "#chan"]
set advban(words) [list "*http*//*" "*http:*" "*www.*" "*.htm*" "*ftp*//*" "*www.*.co*" "*/server*.*.*"]
set advban(exempts) [list]
bind pubm - "*" advban
proc advban {nick host hand chan txt} {
global advban
set advban(chans) [string tolower $advban(chans)]
set chan [string tolower $chan]
set items [split [string tolower $txt]]
if {[validuser $hand] || [isop $nick $chan] || ([llength $advban(chans)] > 0 && [lsearch -exact $advban(chans) $chan] == -1)} {
return 0
}
foreach pattern $advban(words) {
foreach match [lsearch -all -inline $items [string tolower $pattern]] {
set exempt 0
foreach exception $advban(exempts) {
if {[string match -nocase $exception $match]} {
set exempt 1
break
}
}
if {$exempt} {
continue
} else {
newchanban $chan "*!*@[lindex [split $host "@"] 1]" "advban.tcl" "Spam match from ($match) is not allowed here" $advban(time)
return 1
}
}
}
}
|
Or, if we skip the wildcard matching of exempts:
| Code: | set advban(time) "30"
set advban(chans) [list "#chan"]
set advban(words) [list "*http*//*" "*http:*" "*www.*" "*.htm*" "*ftp*//*" "*www.*.co*" "*/server*.*.*"]
set advban(exempts) [list "*example.com*"]
bind pubm - "*" advban
proc advban {nick host hand chan txt} {
global advban
set advban(chans) [string tolower $advban(chans)]
set chan [string tolower $chan]
set items [split [string tolower $txt]]
if {[validuser $hand] || [isop $nick $chan] || ([llength $advban(chans)] > 0 && [lsearch -exact $advban(chans) $chan] == -1)} {
return 0
}
foreach pattern $advban(words) {
foreach match [lsearch -all -inline $items $pattern] {
if {[lsearch -exact $advban(exempts) $match]} {
continue
} else {
newchanban $chan "*!*@[lindex [split $host "@"] 1]" "advban.tcl" "Spam match from ($match) is not allowed here" $advban(time)
return 1
}
}
}
} |
_________________ NML_375, idling at #eggdrop@IrcNET |
|
| Back to top |
|
 |
gasak Halfop
Joined: 09 Aug 2010 Posts: 45
|
Posted: Wed Jun 06, 2012 9:32 pm Post subject: |
|
|
Thanks a lot nml375. It works great  _________________ Learning Knows No Boundaries!! |
|
| Back to top |
|
 |
|