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.

Script works in shell but not as a proc

Help for those learning Tcl or writing their own scripts.
Post Reply
C
Coixi
Voice
Posts: 6
Joined: Sun Nov 12, 2006 4:34 am

Script works in shell but not as a proc

Post by Coixi »

Hello, i've a simple double-foreach script which works nicely when it's runned in shell but when i put it inside proc { }, it won't work anymore.

Here's the script:

Code: Select all

set channels "#chan1 #chan2 #chan3"

set messages "msg1 msg2 msg3"

foreach message $messages {

        foreach channel $channels {

                after 10000 {
                puts "PRIVMSG $message $channel ([clock format [clock seconds] -format %H:%M:%S])"
                set ::pleasewait 1
                }

        vwait ::pleasewait

        }
}
When i start my eggdrop ( v1.6.18 ) it will output this after modules have been loaded:

Code: Select all

PRIVMSG msg1 #chan1 (11:55:44)
PRIVMSG msg1 #chan2 (11:55:54)
PRIVMSG msg1 #chan3 (11:56:04)
PRIVMSG msg2 #chan1 (11:56:14)
PRIVMSG msg2 #chan2 (11:56:24)
PRIVMSG msg2 #chan3 (11:56:34)
PRIVMSG msg3 #chan1 (11:56:44)
PRIVMSG msg3 #chan2 (11:56:54)
PRIVMSG msg3 #chan3 (11:57:04)
After this userfile will be loaded and bot starts normally. The script work as i want it to work but when i want eggdrop to send those messages to channels (make it proc {}), it won't work anymore.

I'm trying it with this code:

Code: Select all

set channels "#chan1 #chan2 #chan3"

set messages "msg1 msg2 msg3"

proc sendmsg {} {
global channels messages

foreach message $messages {

        foreach channel $channels {

                after 10000 {
                puts "PRIVMSG $message $channel ([clock format [clock seconds] -format %H:%M:%S])"
                set ::pleasewait 1
                }

        vwait ::pleasewait

        }
}

}

::sendmsg
But when i start my eggdrop, i'm getting these errors after module loading:

Code: Select all

can't read "message": no such variable
    while executing
"puts "PRIVMSG $message $channel ([clock format [clock seconds] -format %H:%M:%S])""
    ("after" script)
[12:41] Tcl error in file 'coixi.conf':
[12:41] can't wait for variable "::pleasewait":  would wait forever
    while executing
"vwait ::pleasewait"
    (procedure "::sendmsg" line 13)
    invoked from within
"::sendmsg"
    (file "scripts/sendmsg.tcl" line 24)
    invoked from within
"source scripts/sendmsg.tcl"
    (file "coixi.conf" line 1343)
[12:41] * CONFIG FILE NOT LOADED (NOT FOUND, OR ERROR)
I've Googled, i've been going thru these forums and tried those variables with and without global, with/without $ and with :: but i cannot get it work. Also that can't wait for variable "::pleasewait": would wait forever part is bothering me.

If someone could solve or help with this problem, i'd be happyhappyhappy :)
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

Because the variable message is in the proc while the after executes outside the proc; the variable cannot be found. Instead, use the [utimer] eggdrop command.
C
Coixi
Voice
Posts: 6
Joined: Sun Nov 12, 2006 4:34 am

Post by Coixi »

Well, i did that but now the script sends the last message of $messages array to last channel in $channels array.

Could you place the utimer in there in a way that it works like with after? Like this:

Code: Select all

PRIVMSG msg1 #chan1 (11:55:44) 
PRIVMSG msg1 #chan2 (11:55:54) 
PRIVMSG msg1 #chan3 (11:56:04) 
PRIVMSG msg2 #chan1 (11:56:14) 
PRIVMSG msg2 #chan2 (11:56:24) 
PRIVMSG msg2 #chan3 (11:56:34) 
PRIVMSG msg3 #chan1 (11:56:44) 
PRIVMSG msg3 #chan2 (11:56:54) 
PRIVMSG msg3 #chan3 (11:57:04)
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

Code: Select all

set messages {"msg1" "msg2" "msg3"}
set channels {#chan1 #chan2 #chan3}

proc sendmsg {} {
 global messages channels
 set i 0
 foreach message $messages {
  foreach chan $channels {
   utimer [expr {10*[incr i]}] [list puthelp "PRIVMSG $chan :$message"]
  }
 }
}

sendmsg
C
Coixi
Voice
Posts: 6
Joined: Sun Nov 12, 2006 4:34 am

Post by Coixi »

Works like a charm, thanks.

Is utimer/timer best way to keep this whole proc running?

Or would you suggest something else. I want this to run in a loop, when everything is foreached -> it starts again. But i don't know any good way to do so.
User avatar
rosc2112
Revered One
Posts: 1454
Joined: Sun Feb 19, 2006 8:36 pm
Location: Northeast Pennsylvania

Post by rosc2112 »

This format is incorrect for eggdrop (although it may work for tclsh):
puts "PRIVMSG $message $channel ([clock format [clock seconds] -format %H:%M:%S])"

in eggdrop, you'd need to use:

puthelp "PRIVMSG $channel :$message etc"

Note the format of privmsg, the space and the colon are required in the format for irc, refer you to the rfc:

http://www.irchelp.org/irchelp/rfc/chapter4.html
Read section: 4.4.1 Private messages
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

Coixi wrote:Works like a charm, thanks.

Is utimer/timer best way to keep this whole proc running?

Or would you suggest something else. I want this to run in a loop, when everything is foreached -> it starts again. But i don't know any good way to do so.
Call the proc again after the last msg, like this:

Code: Select all

set messages {"msg1" "msg2" "msg3"}
set channels {#chan1 #chan2 #chan3}

proc sendmsg {} {
 global messages channels
 set i 0
 foreach message $messages {
  foreach chan $channels {
   utimer [set t [expr {10*[incr i]}]] [list puthelp "PRIVMSG $chan :$message"]
  }
 }
 utimer $t sendmsg
}

sendmsg
Notice how the delay-time is stored in $t, the proc will restart when the last message is sent.
C
Coixi
Voice
Posts: 6
Joined: Sun Nov 12, 2006 4:34 am

Post by Coixi »

Heya,

How do i make sure that those timers won't become duplicate when i .rehash. I've seen a very simple script for that but after two hours of hardcore googling i haven't found it.

It was a if {} with some info_exists stuff but i just cannot find it.
User avatar
rosc2112
Revered One
Posts: 1454
Joined: Sun Feb 19, 2006 8:36 pm
Location: Northeast Pennsylvania

Post by rosc2112 »

Code: Select all

if {![string match "*name_of_timer*" [timers]]} {timer 5 name_of_timer}
the 5 is the number of minutes as an example..
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

Sir_Fz wrote:Because the variable message is in the proc while the after executes outside the proc; the variable cannot be found. Instead, use the [utimer] eggdrop command.
there is nothing wrong with using [after] in eggdrop scripts; [utimer] was devised before [after] appeared in Tcl (circa 8.0)

of course, [vwait] usage in eggdrop is a no-no as it blocks
connection, sharing, dcc problems? click <here>
before asking for scripting help, read <this>
use

Code: Select all

 tag when posting logs, code
User avatar
Sir_Fz
Revered One
Posts: 3794
Joined: Sun Apr 27, 2003 3:10 pm
Location: Lebanon
Contact:

Post by Sir_Fz »

Didn't say he can't use [after], simply in his case using [utimer] is better since he won't have to worry about changing environments.
User avatar
demond
Revered One
Posts: 3073
Joined: Sat Jun 12, 2004 9:58 am
Location: San Francisco, CA
Contact:

Post by demond »

Sir_Fz wrote:Didn't say he can't use [after], simply in his case using [utimer] is better since he won't have to worry about changing environments.
actually it's the other way around - [after] is preferable in this case as it allows you to "kill timer" simply by using [after cancel] and there is no need to enumerate timers first and only then do the match & kill
connection, sharing, dcc problems? click <here>
before asking for scripting help, read <this>
use

Code: Select all

 tag when posting logs, code
Post Reply