mIRC Home    About    Download    Register    News    Help

Print Thread
Joined: Dec 2014
Posts: 40
Feyl0rd Offline OP
Ameglian cow
OP Offline
Ameglian cow
Joined: Dec 2014
Posts: 40
Okay! So I've spent the past four hours trying to wrap my head around SOCKOPEN and SOCKCLOSE and I attempted to reverse engineer and follow guides on using RAW EVENTS to get what I want done. But all to no end.

All I want is to have a command "!spell*" that then opens up
Code:
http://paizo.com/pathfinderRPG/prd/spells/colorSpray
for example
with !spell colorspray and then display the description the page offers. I've given up.

Joined: Dec 2008
Posts: 1,515
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2008
Posts: 1,515
Try use this code:

Code:
ON *:TEXT:!spell *:#: { .msg $chan http://paizo.com/pathfinderRPG/prd/spells/ $+ $$2 }


Need Online mIRC help or an mIRC Scripting Freelancer? -> https://irc.chathub.org <-
Joined: Dec 2014
Posts: 40
Feyl0rd Offline OP
Ameglian cow
OP Offline
Ameglian cow
Joined: Dec 2014
Posts: 40
This might work for some spells but I definitely plan on working up a sockopen raw event for spells that might be spelt differently or ones with spaces or hyphens. But thank you. I thought right over this quick fix.

Edit:
I also want it to actually message the chat with the content rather than just the link. Which is precisely why I need to work on it to be a sockopen and sockclose raw event.

Last edited by Feyl0rd; 25/02/16 07:31 PM.
Joined: Nov 2013
Posts: 22
Ameglian cow
Offline
Ameglian cow
Joined: Nov 2013
Posts: 22
be forewarned when you start scraping content off webpages, you're gonna have to deal with handling the content as it exists in <HTML> form. in your case this might not be much of an issue the page you linked seems pretty straightforward.

here is a rough idea of a working example that has lots of notes so you can figure out what's going on. note that the user needs to have the proper case (e.g. colorSpray, chillTouch) with the search query.. or else the server will throw an error. this is by no means rock solid code but you can get some ideas about how the sockets are working with it.

Code:
on *:text:!spell*:#: {
  getpaizocontent $chan $2
}

alias noHTML return $regsubex($1, /<[^>]+(?:>|$)|^[^<>]+>/g, $null)

alias getpaizocontent { 

  ;; get content from "http://paizo.com/pathfinderRPG/prd/spells/"
  ;
  ; usage:  /getpaizocontent $chan <searchquery>
  ;
  ; input:  $1 %paizochan
  ;         $2 %paizomark
  ;
  ; output: null => .msg $chan <result>

  ; let %paizochan be the room your nick is listening for !spell
  set %paizochan $1

  ; let %paizomark be the spell name in: !spell <spellname>
  set %paizomark $2

  ; close the <paizo> socket if it is already open
  sockclose paizo

  ; open a <paizo> socket
  sockopen paizo paizo.com 80

}

on *:sockopen:paizo: {

  ; write to the socket your HTTP header request...
  sockwrite -nt $sockname GET /pathfinderRPG/prd/spells/ $+ %paizomark $+ .html HTTP/1.1
  sockwrite -nt $sockname Connection: keep-alive
  sockwrite -nt $sockname Host: paizo.com
  sockwrite $sockname $crlf 
}

on *:sockread:paizo: {
  var %read

  ; let %startfind be the line of html right before your content starts
  var %startfind class="stat-block-title"><b>

  ; let %endfind be the line of html where your content ends
  ; ..caution: this mIRCscript will break if this html changes..
  var %endfind <div class = "footer">

  sockread %read

  ; there was a weird quirk in the HTML of the paizo site resulting in
  ; a blank newline with the text '368' ... not really sure why this is
  ; happening. resolved with the below commands:

  if ( $len(%read) < 10 ) && ( %paizofound = 1 ) {
    unset %paizofound
    unset %paizochan
    unset %paizomark
    sockclose paizo
    halt
  }

  ; typically if you wanted to close the socket you would listen for
  ; a string which would terminate your socket.. as shown below:

  if ( %endfind isin %read ) {
    sockclose paizo
    unset %paizofound
    unset %paizochan
    unset %paizomark
    halt
  }

  ; %paizofound is defined underneath this - the %startfind was found on
  ; the previous line, so start dumping the contents of the page to your channel..
  ; defined initially as %paizochan

  if ( %paizofound = 1 ) {
    msg %paizochan $noHTML(%read)
  }

  ; %startfind was found so set %paizofound to 1

  if ( %startfind isin %read ) {
    set %paizofound 1
  }
}

Joined: Dec 2015
Posts: 148
Vogon poet
Offline
Vogon poet
Joined: Dec 2015
Posts: 148
Just because I'm bored, here's an alternative that can make future socket exploration a bit easier.

Code:
alias mysocket {
  if (www.?*.??* iswm $2) tokenize 32 $1 http:// $+ $2
  if (http://?*.??* iswm $2) || (https://?*.??* iswm $2) {
    var %e = $iif($gettok($2,1,47) == https:,-e),%a $gettok($2,2,47),%p $iif($gettok(%a,2,58) isnum 60-65535,$v1,$iif(%e,443,80)),%a $gettok(%a,1,58),%s $sha1($2,0) $+ .mysocket
    .remove %s
    sockclose %s
    hfree -w %s
    hmake %s
    hadd %s command $1
    hadd %s full $2
    hadd %s port %p
    hadd %s host %a
    hadd %s path $iif($gettok($2,3-,47),/ $+ $v1 $+ $iif($right($2,1) == /,/),/)
    hadd %s r 0
    sockopen %e %s %a %p
    .timermysocket.check -io 1 120 mysocket.check
    if ($isid) return %s
  }
  else $iif($isid,return,echo -a Invalid input, us as: /mysocket <command> <link>)
}

on *:start:noop $findfile($scriptdir,????????????????????????????????????????.mysocket,0,0,.remove $qt($1-))

alias -l mysocket.check {
  var %x = 1
  while ($hget(%x) != $null) { if (*.mysocket iswm $v1) hfree -w $v1 | else inc %x }
  while ($sock(*.mysocket,1)) sockclose $v1
}

on *:sockopen:*.mysocket: {
  tokenize 32 $sockname
  if ($sockerr) mysocket.e $1 open $v1 $sock($1).wsmsg
  else {
    sockwrite -tn $1 GET $hget($1,path) HTTP/1.1
    sockwrite -tn $1 Host: $hget($1,host)
    sockwrite -tn $1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:44.0) Gecko/20100101 Firefox/44.0
    sockwrite -tn $1 Accept: text/html
    sockwrite -tn $1 Connection: close
    sockwrite -t $1 $crlf
  }
}

on *:sockread:*.mysocket: {
  tokenize 32 $sockname
  if ($sockerr) mysocket.e $1 read 
  elseif ($hget($1,r)) mysocket.r $1
  else {
    sockread -f %c.t
    while ($sockbr > 2) { hadd $1 %c.t | sockread -f %c.t }
    if ($sockbr) { hadd $1 r $calc($sock($1).rcvd +$iif($hget($1,Content-Length:) <= 2097152,$v1,$v2)) | if ($sock($1).rq) mysocket.r $1 }
  }
}

on *:sockclose:*.mysocket:mysocket.d $sockname done

alias -l mysocket.r {
  sockread $sock($1).rq &b
  bwrite $1 -1 &b
  if ($sock($1).rcvd >= $hget($1,r)) mysocket.d $1 done
}

alias -l mysocket.e {
  $hget($1,command) $1 error $2 $sockerr $sock($1).wsmsg
  .remove $1
  hfree -w $1
  sockclose $1
}

alias -l mysocket.d {
  if ($hget($1,Transfer-Encoding:) == chunked) {
    var %y = 1
    bread $1 0 $file($1).size &f
    while ($bfind(&f,%y,$crlf).text) {
      var %v = $v1,%h $bvar(&f,%y,$calc(%v -%y)).text,%r $base(%h,16,10),%y $calc(%v +4+%r)
      if (%r == 0) break
      else bcopy &mysocket $calc(1+$bvar(&mysocket,0)) &f $calc(2+%v) %r
    }
  }
  else bread $1 0 $file($1).size &mysocket
  $hget($1,command) $1 done
  .remove $1
  hfree -w $1
  sockclose $1
}

All you need to do is to give the link and command you want it to execute after it has all the data.

In your case it would be: /mysocket mysocketdone http://paizo.com/pathfinderRPG/prd/spells/colorSpray

"mysocketdone" is the custom alias that you need to create:
Code:
alias mysocketdone {

  ;Let's catch the errors here, first one checks for generic errors that happen sometimes and second one checks if it received any data.
  if ($2 == error) echo -a An error occurred with $qt($1) socket during $qt($3) process: $4-
  elseif (!$bvar(&mysocket,0)) echo -a No data received!
  else {

    ;%s = where the desired content starts, %e = where it ends.
    var %s = $bfind(&mysocket,1,<div class = "body">),%e $bfind(&mysocket,%s,<div class = "footer">)

    ;Just to be sure it picked the right spots, let's check %e's value is higher than %s'.
    if (%e > %s) {

      ;$bvar(&mysocket,%s,$calc(%e -%s)).text gives you everything between "<div class = "body">" and "<div class = "footer">", so let's make it easy and set it to its own binary variable: &mydata
      bcopy &mydata 1 &mysocket %s $calc(%e -%s)

      ;%start is where the "A vivid cone of clashing colors..." line starts and %end is where it stops.
      var %start = $bfind(&mydata,1,<p>),%end $bfind(&mydata,%start,</p>)

      ;Pukes out the whole line, and thanks to funfare's $nohtml, you don't need to deal with the included HTML code.
      echo -a $nohtml($bvar(&mydata,%start,$calc(%end -%start)).text)
    }
    else echo -a Something went wrong!
  }
}

alias noHTML return $regsubex($1,/<[^>]+(?:>|$)|^[^<>]+>/g,$null)



Just to explain a bit more:

Basically all you need to do with it, is to give it a link and a command. It will execute the command when it's done or when it encounters an error. If everything goes right, it will do the following: "<your command> <socket name> done"

If it encounters an error, it will do: "<your command> <socket name> error <the event where it happened (open/read)> <error code> <error message>"

Your custom alias should always start a bit like this (use this to test new links/sites/whatever):
Code:
alias mysockettest {
  if ($2 == error) echo -a An error occurred with $qt($1) socket during $qt($3) process: $4-
  elseif (!$bvar(&mysocket,0)) echo -a No data received!
  else {
    echo -a &mysocket contains the whole page/file: $bvar(&mysocket,0) characters (mysocket.txt)
    .remove mysocket.txt
    bwrite mysocket.txt 0 -1 &mysocket
    echo -a $1 hash table contains all the relevant information, like the header: $hget($1,0).item items (mysocket.ini)
    .remove mysocket.ini
    hsave -i $1 mysocket.ini mysocket
    echo -a $1 file contains the whole page/file: $bytes($file($1).size).suf (it will be deleted when this alias finishes.)
    echo -a $1 is the socket's name: $sock($1) (it will be closed when this alias finishes.)
  }
}

It will create a "<sha1 hash of the link>.mysocket" socket, hash table and a file. The hash table contains relevant information, like the header. The file will contain the whole page/file. All three of these are destroyed after your custom command finishes.

The best thing is, you don't have to deal with any of the above, all the data will be in &mysocket binary variable. Just use $bvar and $bfind and do whatever you want, or just do whatever you want with the hash table/file/socket.

If you use the command as an identifier ($mysocket(command,link)), it will either return the name (valid input) or $null (invalid input). This can be handy if you use it in a text event and you want it to spam some information to the channel/whatever. You can store the channel/user name in the hash table and retrieve when it executes your command.


As an example the original request:
Code:
on *:text:!spell *:#:if ($mysocket(myspell,http://paizo.com/pathfinderRPG/prd/spells/ $+ $replacex($2-,$chr(32),% $+ 20))) hadd $v1 channel #

alias myspell {
  if ($2 == error) msg $hget($1,channel) An error occurred with $qt($1) socket during $qt($3) process: $4-
  elseif (!$bvar(&mysocket,0)) msg $hget($1,channel) No data received!
  else {
    var %s = $bfind(&mysocket,1,<div class = "body">),%e $bfind(&mysocket,%s,<div class = "footer">)
    if (%e > %s) {
      bcopy &mydata 1 &mysocket %s $calc(%e -%s)
      var %start = $bfind(&mydata,1,<p>),%end $bfind(&mydata,%start,</p>)
      if ($nohtml($bvar(&mydata,%start,$calc(%end -%start)).text)) msg $hget($1,channel) $v1
      else msg $hget($1,channel) Something went wrong!
    }
    else msg $hget($1,channel) Something went wrong!
  }
}

alias noHTML return $regsubex($1,/<[^>]+(?:>|$)|^[^<>]+>/g,$null)

Just to be safe: you also need the first code thing.

Last edited by Dazuz; 03/03/16 09:29 AM.
Joined: Dec 2014
Posts: 40
Feyl0rd Offline OP
Ameglian cow
OP Offline
Ameglian cow
Joined: Dec 2014
Posts: 40
Thank you for your reply! I will now begin digesting this and another comment on the thread now.

Joined: Dec 2014
Posts: 40
Feyl0rd Offline OP
Ameglian cow
OP Offline
Ameglian cow
Joined: Dec 2014
Posts: 40
Holy wall of text bat-man!
Thanks for posting! I will begin the process of reading yours and others posts. Thank you!


Link Copied to Clipboard