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.

Does utimer/timer have to be a proc or can it be like an if?

Help for those learning Tcl or writing their own scripts.
Post Reply
N
Nara
Halfop
Posts: 40
Joined: Sun Jul 23, 2006 11:12 pm

Does utimer/timer have to be a proc or can it be like an if?

Post by Nara »

Alright - just a quick q, no script. See topic.

~Nara
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

(u)timer takes two arguments, the time to delay, and <tcl-command>
That is, anything in <tcl-command> will be executed by the tcl-interpreter once the delay has passed. You'll have to remember that this will be run in globalspace, and not the namespace occupied by the proc that called it (if any).
Also, keep in mind the ways the tcl-interpreter operates, especially the variable- and command substitutions.
The two snippets below look quite similar, yet behave quite differently (both assumed to be run in globalspace)

Code: Select all

timer 10 [list puthelp "PRIVMSG #mychannel :I'm $botnick"]
timer 10 [list puthelp {PRIVMSG #mychannel :I'm $botnick}]
NML_375
User avatar
rosc2112
Revered One
Posts: 1454
Joined: Sun Feb 19, 2006 8:36 pm
Location: Northeast Pennsylvania

Post by rosc2112 »

Yes, it can be run from an if test within the global space, as nml said, of a script (eg, outside of a proc)
N
Nara
Halfop
Posts: 40
Joined: Sun Jul 23, 2006 11:12 pm

Post by Nara »

Alright, here's what I'm doing:

I'm doing a warning script within my ads/kicks, and this is the script I plan on using. Will this work or will it need mods?

Code: Select all

bind pub - * battle:mainchan

proc battle:warnnick {nick host hand chan text} {
	putserv "NOTICE $nick :You almost stepped on a landmine there Mr. Rock star. check out @rockrules and @advertising"
}


proc battle:mainchan {nick host hand chan text} {
        global text1 text2 mainchan
	set chan [string tolower $chan]
	if {[string equal $chan $mainchan]} {
		set text [stripcodes bcruag $text]
			if {[string match -nocase "text1" $text] || [string match -nocase "text2" $text} {
				return 0
			} elseif {[string match -nocase "#" $text] || [string match -nocase "www" $text] || [string match -nocase ".com" $text] || [string match -nocase ".net" $text] || [string match -nocase ".org" $text] || [string match -nocase "http" $text]} {
				battle:warnnick nick host hand chan text
				if {$nick.warned == 1} {
					putserv "PRIVMSG Chanserv :$mainchan addtimedban $nick 3m Ads"
					set $nick.warned 0
				} else {
					set $nick.warned 1
					timer 60 if {$nick.warned == 1} {set $nick.warned 0}
				}
			} else {
				return 0
			}
	}
}
~Nara
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

It will need some modifications..
First of all, (u)timer take two arguments, of which one is the delay..

Code: Select all

timer 60 if {$nick.warned == 1} {set $nick.warned 0}
has 4 arguments == 2 too many...
Would have to be changed into something like this:

Code: Select all

timer 60 [list if {$nick.warned == 1} {set $nick.warned 0}]
However, this will only work as expected if $nick.warned is a variable in globalspace, as this code snippet is not run within the environment of of the proc... Also, since the code includes a variable controlled by users, there's the risk of code injection (changing nick to foo[die]bar might get ugly if proper encapsulations are not in place)..

There's a few more things to considder, that I'll get to alittle later this evening

edit:
The main problem with your code above is the $nick.warned variable. You mix using it as a proc-local variable and a globalspace variable, without using "global" or any other means of accessing globalspace variables from proc's..
Since you wish to use dynamic variable names, this gets alittle messier..
Also due to the same reason, you really should test wether the variable actually exists before you try to use it (even in if-conditionals)

Finally, using a dot "." in your variable name will cause problems with conditional statements, considder using a different separator-char or named arrays (also solves the problem with dynamic variable names)
NML_375
User avatar
rosc2112
Revered One
Posts: 1454
Joined: Sun Feb 19, 2006 8:36 pm
Location: Northeast Pennsylvania

Post by rosc2112 »

Ohh my..is that the entire script? Cos..it's wrong in a lot of places..Starting with:

bind pub - * battle:mainchan

if you want a trigger to work on any possible input, you need to use pubm, which accepts wildcards, bind pub does not.

Where are the text1 and text2 global vars defined? They're not in the script as posted..

"string match" needs wildcards like

string match -nocase "*.com*" $text

unless you anticipate an exact match (just .com in the $text var)

text input from users should be split, [split $text] to make it safe, many functions will choke on tcl-special chars, otherwise. Read: http://www.peterre.com/characters.html

And actually, instead of using string match so much, and since you'd be wise to [split $text] you'd prolly be better off using lsearch to compare lists, like for your channel check:

in the global space:
set mychans "#mychan #chan2 #etc"

then within the pub (or pubm)q proc:

Code: Select all

proc whatever {nick uhost hand chan text} {
global mychans
if {[lsearch -exact $mychans $chan]} {
          #this is a matching channel
          # do stuff
} else {
           # this is not a match
           # return
}
Using [split] creates a list, on which you can use lsearch, lindex, lrange, lreplace, etc.

As for the timer, I'd make a seperate proc to run the test in. You'd need to set a global var to pass to the other proc as well, so within your
proc battle:mainchan, make nickwarned a global var, add it to the list of global vars at the beginning of the proc, then have it set by the proc. Also within the proc battle:mainchan you set your timer:

timer 60 [list someproc $nick]

Then when your timer runs the seperate proc for testing, you add that nickwarned var as a global there too:

Code: Select all

proc someproc {nick}
    global nickwarned
     if {$nick.warned == 1} {set $nick.warned 0}
}
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

You need to create not a variable, but an array. A global array. For example:

Code: Select all

proc bla {nick uhost hand chan} {
 global warned
 # ...etc
 set warned($nick) 0
 timer 60 [list blo $nick]
}

proc blo nick {
 global warned
 if {$warned($nick) == 1} { set warned($nick) 0 }
}
m
metroid
Owner
Posts: 771
Joined: Wed Jun 16, 2004 2:46 am

Post by metroid »

I think you mean

Code: Select all

set warned($nick) 1
in the first proc ;)
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

I noticed it, but didn't edit it. After all, it's just an example :P
N
Nara
Halfop
Posts: 40
Joined: Sun Jul 23, 2006 11:12 pm

Post by Nara »

Alright - here's what I'm trying to do, so help me out here.

This is an anti-ad script. I already fixed the wildcard and the bind [mistakes from coding all of this in under 2 minutes].

It needs to have a warning system, hence the $nick.warned stuff. I need a good way to store all nicks that are warned and then permit me to run them all through hourly. [probably with a bind time for hourly if it can be put into a protocol?]
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

Store them in an array (as I showed you above).
N
Nara
Halfop
Posts: 40
Joined: Sun Jul 23, 2006 11:12 pm

Post by Nara »

Sir_Fz wrote:Store them in an array (as I showed you above).
Then where does the list of nicks to check come from? [I never got much experience in lists and while loops, so if you could help, I'd most appreciate.]

~Nara
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

"array names" is your friend here; returns a list of all the keys in a speciffic array.
Something like this I suppose:

Code: Select all

proc test_nicks {} {
 global warned
 foreach nick [array names warned] {
  if {$warned($nick) == 1} {
   #evil spammer
  }
 }
}
Modify to suit your needs
NML_375
Post Reply