mIRC Homepage
Posted By: Borg8401 Help with sockread - 23/03/10 05:11 PM
Hey all, trying to figure something out.
I am trying to pull information from this page: here.

This is my code so far, which works:
Code:
on *:text:!player*:#: {
if ($sock(player)) .sockclose player
set %chan $chan
set %nick $nick
sockopen player herald.uthgard-server.net 80
}
on *:SOCKOPEN:player: {
sockwrite -nt $sockname GET /herald.php?view=stats&p1=player&p2=Player&p3=DESC&p5=Player&p6=Rotbart HTTP/1.1
sockwrite -nt $sockname Host: herald.uthgard-server.net
sockwrite -nt $sockname $crlf
}
on *:SOCKREAD:player: {
var %sockreader
sockread %sockreader
if (*<a class="charname"* iswm %sockreader ) {
set %name $nohtml($remove(%sockreader,Player))

var %sockreader
sockread %sockreader
if (*<a class="guild"* iswm %sockreader ) {
set %guild $nohtml($remove(%sockreader,Guild))

msg %chan %name < $+ %guild $+ >
unset %chan
unset %nick
unset %name %guild
sockclose player
}
}
}
}

Which outputs:
Rotbart Laeuseimschritt <Anguish>

However, I'm needing to get more information from it, and when I try this:
Code:
on *:text:!player*:#: {
if ($sock(player)) .sockclose player
set %chan $chan
set %nick $nick
sockopen player herald.uthgard-server.net 80
}
on *:SOCKOPEN:player: {
sockwrite -nt $sockname GET /herald.php?view=stats&p1=player&p2=Player&p3=DESC&p5=Player&p6=Rotbart HTTP/1.1
sockwrite -nt $sockname Host: herald.uthgard-server.net
sockwrite -nt $sockname $crlf
}
on *:SOCKREAD:player: {
var %sockreader
sockread %sockreader
if (*<a class="charname"* iswm %sockreader ) {
set %name $nohtml($remove(%sockreader,Player))

var %sockreader
sockread %sockreader
if (*<a class="guild"* iswm %sockreader ) {
set %guild $nohtml($remove(%sockreader,Guild))

var %sockreader
sockread %sockreader
if (*<a class="realmrank"* iswm %sockreader ) {
set %realmrank $nohtml($remove(%sockreader,Realmrank))

msg %chan %name < $+ %guild $+ > %realmrank
unset %chan
unset %nick
unset %name %guild %realmpoints
sockclose player
}
}
}
}
}

I get no response from the bot at all, I've tried renaming the %sockreader to %sockreader2, %sockreader3, etc for each sockread but nothing seems to help. I'm trying to get a total of 7 lines of information from that page.

Any help would be greatly appreciated
Posted By: Riamus2 Re: Help with sockread - 23/03/10 05:33 PM
You should only use one sockread. That section will loop until the entire page is read. Use IF statements to get all the information you need.

Code:
on *:text:!player*:#: {
  if ($sock(player)) .sockclose player
  set %chan $chan
  set %nick $nick
  sockopen player herald.uthgard-server.net 80
}
on *:SOCKOPEN:player: {
  sockwrite -nt $sockname GET /herald.php?view=stats&p1=player&p2=Player&p3=DESC&p5=Player&p6=Rotbart HTTP/1.1
  sockwrite -nt $sockname Host: herald.uthgard-server.net
  sockwrite -nt $sockname $crlf
}
on *:SOCKREAD:player: {
  var %sockreader
  sockread %sockreader
  if (*<a class="charname"* iswm %sockreader) {
    set %name $nohtml($remove(%sockreader,Player))
  }
  elseif (*<a class="guild"* iswm %sockreader) {
    set %guild $nohtml($remove(%sockreader,Guild))
  }
  elseif (*<a class="class2"* iswm %sockreader) {
    set %class $nohtml($remove(%sockreader,Class))
  }
  elseif (*<a class="race2"* iswm %sockreader) {
    set %race $nohtml($remove(%sockreader,Race))
  }
  if (</table>* iswm %sockreader) {
    msg %chan %name < $+ %guild $+ > %class %race
    unset %chan
    unset %nick
    unset %name %guild %class %race
    sockclose player
  }
}


There's just a quick example. It shows a couple extra pieces of information. Just repeat that format for anything else that you need. The main reason you ran into trouble is having the extra sockread's in there. Doing that will cause lines to be skipped.
Posted By: Borg8401 Re: Help with sockread - 23/03/10 05:44 PM
Wow, thanks for the quick reply... Works perfectly! Thank you for your time and help.
Posted By: Horstl Re: Help with sockread - 23/03/10 06:13 PM
Riamus2 beat me to it, but here's another approach (parsing all the data, no global variables) - maybe it's of use.
Code:
on *:TEXT:!player*:#: {
  if ($sock(player)) .sockclose player
  sockopen player herald.uthgard-server.net 80
  ; you can mark the socket instead of putting $chan and $nick into global variables
  sockmark player $chan $nick
}

on *:SOCKOPEN:player: {
  sockwrite -nt $sockname GET /herald.php?view=stats&p1=player&p2=Player&p3=DESC&p5=Player&p6=Rotbart HTTP/1.1
  sockwrite -nt $sockname Host: herald.uthgard-server.net
  sockwrite -nt $sockname $crlf
}

on *:SOCKREAD:player: {
  var %read

  ; goto-loop of sockread
  :read
  sockread %read

  ; if there was data left to read and the data matched " <tr class="TBLmid"><td>SOMETHING HERE</td><td> "
  ; then set a local variable named "%SOMETHING_HERE" (spaces replaced with underscores)
  ; which holds the data of $remove($nohtml(sockread),SOMETHING HERE)
  if ($sockbr) {
    if ($regex(read,%read,/\<tr class="TBLmid"><td>([^<]+)<\/td><td>/)) { set -l % $+ $replace($regml(read,1),$chr(32),_) $remove($nohtml(%read),$regml(read,1)) }
    goto read
  }

  ; this means you can now use EACH of
  ; %player %guild %class %race %level %realmrank %dragon_kills %legion_kills %kills %realmpoints %last_week _RPs

  ; convert sockmark back to local variables 
  var %chan = $gettok($sock($sockname).mark,1,32), %nick = $gettok($sock($sockname).mark,2,32)

  msg %chan %player < $+ %guild $+ > Rank: %realmrank Pts: %realmpoints
  sockclose $sockname
}

alias -l nohtml {
  var %x, %i = $regsub($1-,/(^[^<]*>|<[^>]*>|<[^>]*$)/g,$null,%x), %x = $remove(%x,&nbsp;,$chr(9))
  return %x
}
Posted By: Riamus2 Re: Help with sockread - 23/03/10 06:18 PM
Someday, I really need to learn regex. I like that approach, though it's not as easily adjusted when doing other socket scripts. It works great on this one since all the important lines use the same format. The only thing that may not (I can't test it here) is how race2 and class2 are used in the HTML... but you're removing Race and Class respectively. That would leave Race and Class in the %race2 and %class2 variables if I'm understanding the regex correctly. Maybe I'm not since I really don't know regex, but that seems to be the case?

EDIT: Nevermind. I realized that it wasn't looking at the URL section that included race2 and class2.
Posted By: Horstl Re: Help with sockread - 23/03/10 06:30 PM
The regex matches every collumn of the chart ( e.g. <tr class="TBLmid"><td>Race</td> ) and captures word with ([^<]+) aka "one or more chars being no "<"-char" to name the variables. The variable thus will be named "%Race". And yep - this approach will be of little use in other cases smile
Posted By: chacha Re: Help with sockread - 23/03/10 09:42 PM
hi
i think no need for goto loop and i prefer to add "wx" only to unset the global variable and replace the sockmark by set %wxchan # and %wxnick $nick
Code:
on *:sockread:player:{
  var %read | sockread %read
  if ($regex(read,%read,/\<tr class="TBLmid"><td>([^<]+)<\/td><td>/)) set -l %wx $+ $replace($regml(read,1),$chr(32),_) $remove($nohtml(%read),$regml(read,1))
}

then u use ON SOCKCLOSE event to send msg if exist result something like

Code:
on *:sockclose:player:{
  if %var here {
    msg %wxchan %wxplayer $+(<,%wxguild,>) Rank: %wxrealmrank Pts: %wxrealmpoints
    unset %wx*
  }
}


and for the alias nohtml u can use $regsubex

Code:
alias -l nohtml return $remove($regsubex($1-,/(^[^<]*>|<[^>]*>|<[^>]*$)/g,),&nbsp;,$chr(9))
Posted By: Tomao Re: Help with sockread - 24/03/10 07:15 AM
I think the $remove can be omitted:
Code:
alias -l nohtml return $regsubex($1-,/(^[^<]*>|<[^>]*>|<[^>]*$|\46nbsp\73|\t)/g,)
I haven't tested this but it should work to strip $chr(9) and
Code:
&nbsp;
too.
Posted By: Horstl Re: Help with sockread - 25/03/10 01:15 PM
(late reply)

- I used /sockmark especially to show that one may relay data to socket events with other means.
- Set -l sets local variables - they dont need any unset. That said, I usually try to avoid global variables wherever possible - especially if the data isn't required in further sessions. Global vars may persist (even with -e in case of a crash; if you forget adding an unload event etc). It depends on the situation and is a personal preference though (I like a clean vars section).
- You're right about $nohtml, I simpliy ripped the first alias I found from an existing thread, as (to my surprise) I didn't needed one in any script of mine so far.
- Of course you can trigger the output not after !$sockbr but on sockclose. However I don't see any advantage in this particular case... The $sockbr-loop is again a habbit of mine (but mandatory in some other socket situations).
- Yep, the OP could check first whether or not his variables actually hold [valid] data. However the script won't get stuck, issue invalid commands or the like without the check. And no output at all might cause more confusion than an output with missing values...
- Besides a small (and inconsequential) typo in the regex of my post, the expression could capture the data right away for a $regml(read,2) instead of using $nohtml and $remove on the whole line. That aside, the current construct can actually be improved with "$mid($nohtml(%read),$calc($len($regml(read,1)) +1))" instead of "$remove($nohtml(%read),$regml(read,1))": It won't strip "guild" out of a guild's name for example.
smile
Posted By: chacha Re: Help with sockread - 25/03/10 08:27 PM
about /set -l it's like /var i only copy paste and remove something but i didnt look at all :p
© mIRC Discussion Forums