mIRC Home    About    Download    Register    News    Help

Topic Options
#241309 - 06/04/13 04:29 AM Sockets breaking loop
p4rad0xon Offline
Nutrimatic drinks dispenser

Registered: 05/04/13
Posts: 5
Loc: Germany
Hello there!

I have a question regarding sockets and their proper use. i wrote a script over the last few days including the following part:

Code:
alias -l dict {

  set %dict.term $$1-
  set %dict.url /?s= $+ $replace($$1-,$chr(32),+)
  sockopen dict www.dict.cc 80
; ------------------------
  timerdict.autoreset 1 2 dictautoreset
; ------------------------
}
; ------------------------
alias -l dictautoreset {
  msg %dict.recipient 4***Error 14 No Match for <14 %dict.term >14. Please visit7 www.dict.cc $+ %dict.url 14for more information. 
  unset %dict.*
  sockclose dict
}
; ------------------------
on *:SOCKOPEN:dict:{
  sockwrite -nt $sockname GET %dict.url HTTP/1.1
  sockwrite -nt $sockname HOST: www.dict.cc
  sockwrite -n $sockname
}


on *:SOCKREAD:dict: {
  if ($sockerr > 0) { echo -a Error while reading from $sockname $+ . | echo -a Error # $+ $sockerr occurred. | return }
  sockread %dict.read
  while ($sockbr) {
    if ($regex(%dict.read,var c.Arr = new Array)) {
      if ($mid(%dict.read,6,1) == 1) {
; ------------------------
        timerdict.autoreset off
; ------------------------
        set %dict.text.eng %dict.read
      }
      if ($mid(%dict.read,6,1) == 2) {
        set %dict.valid.result 1
        set %dict.text.deu %dict.read   
        dict.form
        halt
      }
    }
    sockread %dict.read 
  }
}
on *:SOCKCLOSE:dict: { msg %dict.recipient 4***Error14 - No match, please visit7 www.dict.cc $+ %dict.url 14for more information | unset %dict.* }


alias -l dict.form {
  Set %dict.char.remove 1
  msg %dict.recipient <14 %dict.term > 7Dict.cc14 Translation 12English - 3Deutsch 
  while (%dict.char.remove <= %dictresultcount) {
    Set %dict.word.eng.out $remove($remove($mid(%dict.text.eng,$pos(%dict.text.eng," $+ $chr(44) $+ ",%dict.char.remove),$calc($pos(%dict.text.eng," $+ $chr(44) $+ ",$calc(%dict.char.remove + 1)) - $pos(%dict.text.eng," $+ $chr(44) $+ ",%dict.char.remove)))," $+ $chr(44) $+ "),",\)
    Set %dict.word.deu.out $remove($remove($mid(%dict.text.deu,$pos(%dict.text.deu," $+ $chr(44) $+ ",%dict.char.remove),$calc($pos(%dict.text.deu," $+ $chr(44) $+ ",$calc(%dict.char.remove + 1)) - $pos(%dict.text.deu," $+ $chr(44) $+ ",%dict.char.remove)))," $+ $chr(44) $+ "),",\)
    if (%dict.word.eng.out) { msg %dict.recipient 12 %dict.word.eng.out -3 %dict.word.deu.out }
    inc %dict.char.remove
  }
  msg %dict.recipient 14for more information visit7 www.dict.cc $+ %dict.url 
  unset %dict.*
  sockclose dict
}


The script works without any proplem as long as the timer won't be interrupted for some reason and even if,
the socket will be closed automatically after approximately 30 sec which will reset all %dict. vars as well.

But i want to use some %dict. vars for a different Trigger to initiate onetime events.
If it happens now, that one of these %dict. vars is accidentally set in the 30 sec or even in the 2 sec until the timer runs out,
the Var will be reset together with all other %dict. Vars and the script won't be executed properly.
And sometimes the reading process takes to to long and an error occurs even if there was a match.

To get to the point, i want to replace the timer with a comparison in the SOCKREAD Trigger, so the process to reset the %dict. Vars is faster in general and to make the funktion more resistant against various errors.

I tried already to find a solution by using different Socket parameter like &sock(dict).rq and compare them,
but everything i tried (and i tried a lot) didn't work.

Sadly it's not possible to add another boolean comparison like this:

Code:
if ($regex(%dict.read,re) {
  unset %dict.*
  sockclose dict
  halt
}


I'm running out of options and have absolutely no clue how to fix this issue, so i thought maybe anyone here has a solution to offer and can give me a nudge in the right direction.

Any help is greatly appreciated!
_________________________
'Sup?

Top
#241311 - 06/04/13 07:07 AM Re: Sockets breaking loop [Re: p4rad0xon]
Loki12583 Offline
Hoopy frood

Registered: 22/01/04
Posts: 1244
Append $rand or $ticks to the socket name, you can then create dynamically named variables (or create a hash table) using $sockname. That will stop different calls from interfering with one another.

If you're concerned about operations taking too long and the socket closing, fetch all the information from the socket and write it to a file before acting on it.

Top
#241312 - 06/04/13 07:49 AM Re: Sockets breaking loop [Re: Loki12583]
p4rad0xon Offline
Nutrimatic drinks dispenser

Registered: 05/04/13
Posts: 5
Loc: Germany
That will work. Thank you.
_________________________
'Sup?

Top
#241315 - 07/04/13 05:58 AM Re: Sockets breaking loop [Re: p4rad0xon]
p4rad0xon Offline
Nutrimatic drinks dispenser

Registered: 05/04/13
Posts: 5
Loc: Germany
Ok i changed the code and using $ticks and hash tables helped to make the script running smoother, but i still can't find a way around using a timer to run dict.form before the socket is automatically closed.

Code:
on *:SOCKREAD:dict.*: {
  if ($sockerr > 0) { echo -a Error while reading from $sockname $+ . | echo -a Error # $+ $sockerr occurred. | return }
  sockread % [ $+ $sockname ]
  while ($sockbr) {
    hadd -m $sockname $+ .text $hget($sockname,count) % [ $+ $sockname ]
    hinc $sockname count   
    sockread % [ $+ $sockname ] 
  }
  timer $+ $sockname -m 1 100 dict.form $sockname
}


It's not a big deal, because the Script runs good enough the way it is,but everytime a timer is activated a message appears in the status window.

And in the end it looks like this:

* Timer dict.45327359 activated
-
* Timer dict.45327359 activated
-
* Timer dict.45327359 activated
-
*...
-
* Timer dict.45327359 halted


Which is pretty annoying to be honest, so i was wondering if there is maybe a possibility to start a timer without getting a notice or even better to run dict.form entirely without a timer.


Click to reveal.. (Full code)
Code:
alias dict {
  set %temp $ticks
  hadd -m dict. $+ %temp chan  $$1
  hadd dict. $+ %temp term  $$2-
  hadd dict. $+ %temp count 1
  hadd dict. $+ %temp url /?s= $+ $replace($$2-,$chr(32),+)
  sockopen dict. $+ %temp www.dict.cc 80
  unset %temp
}

on *:SOCKOPEN:dict.*:{
  sockwrite -nt $sockname GET $hget($sockname,url) HTTP/1.1
  sockwrite -nt $sockname HOST: www.dict.cc
  sockwrite -n $sockname
}


on *:SOCKREAD:dict.*: {
  if ($sockerr > 0) { echo -a Error while reading from $sockname $+ . | echo -a Error # $+ $sockerr occurred. | return }
  sockread % [ $+ $sockname ]
  while ($sockbr) {
    hadd -m $sockname $+ .text $hget($sockname,count) % [ $+ $sockname ]
    hinc $sockname count   
    sockread % [ $+ $sockname ] 
  }
  timer $+ $sockname -m 1 100 dict.form $sockname
}
on *:SOCKCLOSE:dict.*: { msg $hget($sockname,chan) 4***Error Socket wasn't closed properly | hfree -s $sockname }


alias -l dict.form {
  hadd $1 charremove 1
  msg $hget($1,chan) <14 $hget($1,term) > 7Dict.cc14 Translation 12English - 3Deutsch 
  while ($hget($1,charremove) <= %dictresultcount) {
    hadd $1 countreset $hget($1,count)
    while ($hget($1,countreset)) {
      if ($regex($hget($1 $+ .text,$hget($1,countreset)),var c.Arr = new Array)) {
        hadd $1 match 1
        if ($mid($hget($1 $+ .text,$hget($1,countreset)),6,1) == 1) { hadd $1 lang eng }
        else { hadd $1 lang deu }
        hadd $1 $hget($1,lang) $remove($remove($mid($hget($1 $+ .text,$hget($1,countreset)),$pos($hget($1 $+ .text,$hget($1,countreset))," $+ $chr(44) $+ ",$hget($1,charremove)),$calc($pos($hget($1 $+ .text,$hget($1,countreset))," $+ $chr(44) $+ ",$calc($hget($1,charremove) + 1)) - $pos($hget($1 $+ .text,$hget($1,countreset))," $+ $chr(44) $+ ",$hget($1,charremove))))," $+ $chr(44) $+ "),",\)
      }
      hdec $1 countreset
    }
    if ($hget($1,match) == $null) { msg $hget($1,chan) 12no match! | hadd $1 match 1 }
    if ($hget($1,eng)) && ($hget($1,deu)) { msg $hget($1,chan) 12 $hget($1,eng) -3 $hget($1,deu) }
    hinc $1 charremove

  } 
  msg $hget($1,chan) 14for more information visit7 www.dict.cc $+ $hget($1,url) 
  hfree -w $1*
  sockclose $1
}


EDIT: o.O Nevermind a single . fixed the proplem, but anyway if anyone has an idea how to run dict.form without a timer, i would be glad if he/she shares it with me.
TIA


Edited by p4rad0xon (07/04/13 06:38 AM)
_________________________
'Sup?

Top
#241317 - 07/04/13 10:47 AM Re: Sockets breaking loop [Re: p4rad0xon]
JohnEricNO Offline
Pikka bird

Registered: 20/12/11
Posts: 11
To suppress the status messages from commands, place a period in front of the command.

example:

.timer $+ $sockname -m 1 100 dict.form $sockname

instead of:

timer $+ $sockname -m 1 100 dict.form $sockname

Top
#241318 - 07/04/13 03:04 PM Re: Sockets breaking loop [Re: p4rad0xon]
Loki12583 Offline
Hoopy frood

Registered: 22/01/04
Posts: 1244
Why are you using a timer to begin with, what's wrong with just calling the alias in the sockclose?

Top
#241320 - 07/04/13 04:49 PM Re: Sockets breaking loop [Re: Loki12583]
p4rad0xon Offline
Nutrimatic drinks dispenser

Registered: 05/04/13
Posts: 5
Loc: Germany
Because the SOCKCLOSE trigger takes 30+ sec to trigger which is way to long.

i tried already to fix this by adding a line in SOCKREAD like

Code:
if ($sockbr == $null) { dict.form $sockname }


or

Code:
if ($sock($sockname).rq == $null) { dict.form $sockname }


and a lot more like this, but none of these lines worked

and i tried to add something like this

Code:
if ($regex(% [ $+ $sockname ],"text that appears in the last recived string from dict.cc")) { dict.form $sockname }


this would be probably the most clear version but sadly it's not possible because

Code:
$regex(% [ $+ $sockname ],var c.Arr = new Array)


returns $true , if there was a match, in the last 2 recived strings from dict.cc and there is no more string coming afterwards

the timer makes the script working but it's sometimes responsible for an error that i recive "no match" when it takes to long to call data from dict.cc so i want to replace it with something better.

Of course i could increase the <interval> of the timer, so this happens less often and it probably won't hurt much when i change it to 1 sec instead of 100 ms. But this timer really bothers me laugh


Edited by p4rad0xon (07/04/13 05:59 PM)
_________________________
'Sup?

Top
#241321 - 07/04/13 05:48 PM Re: Sockets breaking loop [Re: p4rad0xon]
Deega Offline
Vogon poet

Registered: 30/10/12
Posts: 164
I think it's a bit over complicated. IMHO there's no need for timer, so many variables or a hash table.
The below script uses 3 local vars and sets just 5 global variables plus 1 queue variable for each extra request recieved while the script is busy.

Assumes that /dict is passed the #channel/nick plus the search term (/dict #chan words to search)

Code:
alias dict {
  if ($sock(dict)) { set -e $+(%,dictq.,$ticks,.,$r(1,999)) $1 $$2- | return }
  ; The above line sets a queue if the script is already busy
  set -e %dict.term $+(<14,$$2-,>14)
  set -e %dict.chan $1
  set -e %dict.url /?s= $+ $replace($2-,$chr(32),+)
  sockopen dict www.dict.cc 80
}
on *:SOCKOPEN:dict:{
  if ($sockerr) {
    echo -a 4***Error:14 DICT Socket error: [Error $sock($sockname).wserr occurred]
    dict.nogo Socket error 
    return
  }
  sockwrite -nt $sockname GET %dict.url HTTP/1.1
  sockwrite -nt $sockname HOST: www.dict.cc
  sockwrite -n $sockname
}
on *:SOCKREAD:dict:{
  var %read
  sockread %read
  if (*no translations found* iswm %read) {
    sockclose dict
    dict.nogo No match
  }
  elseif (& c?Arr ? new Array* iswm %read) {
    if ($mid(%read,6,1) == 1) {
      tokenize 34 %read
      set -e %dict.text.eng $left($3-,-2)
    }
    elseif ($mid(%read,6,1) == 2) {
      tokenize 34 %read
      set -e %dict.text.deu $left($3-,-2)
      dict.form
    }
  }
}
on *:SOCKCLOSE:dict:{ dict.nogo No result }
alias -l dict.nogo {
  msg %dict.chan 4***Error14 %dict.term $([,$1,]) -- please visit7 www.dict.cc $+ %dict.url
  dict.new
}
alias -l dict.form {
  sockclose dict
  msg %dict.chan %dict.term 7Dict.cc14 Translation 12English - 3Deutsch
  var %i = 1,%x = $numtok(%dict.text.eng,44)
  while (%i !> %x) {
    msg %dict.chan %dict.term $+([,%i of %x,]) 12 $gettok(%dict.text.eng,%i,44) -3 $gettok(%dict.text.deu,%i,44)
    inc %i
    if (%i > 3) { break }
  }
  msg %dict.chan 14for more $iif(%x > 3,matches,information) visit7 www.dict.cc $+ %dict.url 
  dict.new
}
; Now process the next queued search (if there is any)
alias -l dict.new {
  unset %dict.*
  if ($var(%dictq.*,1) && $v1 != $var(%dictq.*,1).value) {
    unset $v1
    dict $v2
  }
}


I limited it to sending 3 matches so you don't (so easily) flood yourself off. wink
Already that's 5 lines sent (with your header & footer lines) so if you want more results, or if this script gets heavy usage it would be better to change it to sending the results via /play.
This limiting is done in the dict.form alias, the line- if (%i > 3) { break } -and in the /msg line that is 2 lines below that, where it says- $iif(%x > 3,matches,information)

Top
#241323 - 07/04/13 07:35 PM Re: Sockets breaking loop [Re: Deega]
p4rad0xon Offline
Nutrimatic drinks dispenser

Registered: 05/04/13
Posts: 5
Loc: Germany
Thank you very much for your effort and especially for this tiny piece of code
Code:
if (*no translations found* iswm %read)
i was tring for so long and haven't thought of the most obvious solution :facepalm:
_________________________
'Sup?

Top