mIRC Home    About    Download    Register    News    Help

Print Thread
S
square_wave
square_wave
S
Hello All,
I have a twitch bot that does all sorts of fun stuff, but I am having trouble getting the bot to reference a url and pull info from that url.

What I would like the bot to do is when someone types, !dic Science, It would reference dictionary.com and pull of the first definition of Science and post that in the chat.

ex...

me: !dic Science
bot: 1. this is the definition of Science
me: thanks bot!!!

I am new to programming with mIRC, but I must keep trying to learn. If there is a better way to do this example, feel free to suggest.

S
Sakana
Sakana
S
I wrote this. Could probably be improved on, but it's a start.

Edit: improved it

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

on *:text:!dic*:#: { 
  if ($1 == !dic) {
    set %channel #
    $iif($2,dic $2-,msg # Specify a word to look up)
  } 
}

alias dic {
  sockclose dic
  set %dic.word $1-
  set %dic.counter 0
  sockopen dic dictionary.reference.com 80
}

on *:SOCKOPEN:dic:{
  if $sockerr { return }
  sockwrite -n $sockname GET /browse/ $+ %dic.word $+ ?s=t HTTP/1.1
  sockwrite -n $sockname Host: dictionary.reference.com
  sockwrite -n $sockname $crlf
}

on *:SOCKREAD:dic:{
  if $sockerr { return }
  var %data  
  sockread %data  
  if ($regex(%data,<span class="def-number">1.</span>) == 1) { set %dic.target 1 }
  if (%dic.target == 1) { inc %dic.counter }
  if (%dic.counter == 3 ) { 
    msg %channel $+($upper($left($noHTML(%data),1)),$mid($noHTML(%data),2)) 
    unset %dic.*
    sockclose dic
  }
  elseif (<div class="cl-left">Copyright isin %data) { 
    msg %channel Word not found
    unset %dic.*
    sockclose dic 
  }
}


Last edited by Sakana; 21/01/15 09:38 PM.
S
Sakana
Sakana
S
This version also gives the word class

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

on *:text:!dic*:#: { 
  if ($1 == !dic) {
    set %channel #
    $iif($2,dic $2-,msg # Specify a word to look up)
  } 
}

alias dic {
  sockclose dic
  set %dic.word $1-
  set %dic.counter 0
  sockopen dic dictionary.reference.com 80
}

on *:SOCKOPEN:dic:{
  if $sockerr { return }
  sockwrite -n $sockname GET /browse/ $+ %dic.word $+ ?s=t HTTP/1.1
  sockwrite -n $sockname Host: dictionary.reference.com
  sockwrite -n $sockname $crlf
}

on *:SOCKREAD:dic:{
  if $sockerr { return }
  var %data  
  sockread %data  
  if ($regex(%data,<span class="dbox-pg">(.*?)</span>)) { set %dic.class $regml(1) }
  if ($regex(%data,<span class="def-number">1.</span>) == 1) { set %dic.target 1 }
  if (%dic.target == 1) { inc %dic.counter }
  if (%dic.counter == 3 ) { 
    msg %channel $+($upper($left(%dic.class,1)),$mid(%dic.class,2)) - $+($upper($left($noHTML(%data),1)),$mid($noHTML(%data),2)) 
    unset %dic.*
    sockclose dic
  }
  elseif (<div class="cl-left">Copyright isin %data) { 
    msg %channel Word not found
    unset %dic.*
    sockclose dic 
  }
}

P
paper0rplastic
paper0rplastic
P
This doesn't seem to work correctly if what you want to look up has a space in it. I try to get the definition for "bloody mary" and I get the definition for "bloody" Other than that, it works great smile

S
Sakana
Sakana
S
Oops, fixed ^^

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

on *:text:!dic*:#: { 
  if ($1 == !dic) {
    set %channel #
    $iif($2,dic $2-,msg # Specify a word to look up)
  } 
}

alias dic {
  sockclose dic
  set %dic.word $replace($1-,$chr(32),$chr(37) $+ 20)
  set %dic.counter 0
  sockopen dic dictionary.reference.com 80
}

on *:SOCKOPEN:dic:{
  if $sockerr { return }
  sockwrite -n $sockname GET /browse/ $+ %dic.word $+ ?s=t HTTP/1.1
  sockwrite -n $sockname Host: dictionary.reference.com
  sockwrite -n $sockname $crlf
}

on *:SOCKREAD:dic:{ 
  if $sockerr { return }
  var %data  
  sockread %data  
  if ($regex(%data,<span class="dbox-pg">(.*?)</span>)) { set %dic.class $regml(1) }
  if ($regex(%data,<span class="def-number">1.</span>) == 1) { set %dic.target 1 }
  if (%dic.target == 1) { inc %dic.counter }
  if (%dic.counter == 3 ) { 
    msg %channel $+($upper($left(%dic.class,1)),$mid(%dic.class,2)) - $+($upper($left($noHTML(%data),1)),$mid($noHTML(%data),2)) 
    unset %dic.*
    sockclose dic
  }
  elseif (<div class="cl-left">Copyright isin %data) || (HTTP/1.1 301 Moved Permanently isin %data) { 
    msg %channel Word not found
    unset %dic.*
    sockclose dic 
  }
}


Last edited by Sakana; 21/01/15 11:39 PM.
P
paper0rplastic
paper0rplastic
P
Perfect! Thanks. smile

S
square_wave
square_wave
S
Thank You. I will spend more time reverse enginnering what you did, but this is awesome! cool

S
square_wave
square_wave
S
Would y'all be willing to help out do the same thing but for an urban dictionary function?

I am trying to learn this, but it's slow going.

This would be about the same idea:

me: !urbdic Science
bot: 1. this is the ghetto definition of science
me: hahaha, lol, ROFL!


or at the least, can you tell me what to look for to make the changes to the other script for an !urbdic function?

Thank You smile

S
Sakana
Sakana
S
The urban dictionary page didn't work well with sockets when I tried, but they have an API:
http://api.urbandictionary.com/v0/define?term=example

All you need is a JSON parser for mIRC

P
paper0rplastic
paper0rplastic
P
Found another "bug" with this script. If you try to get the definition of "zombie" you will see it. wink

S
Sakana
Sakana
S
Try this wink

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

on *:text:!dic*:#: { 
    if ($1 == !dic) {
    set %channel #
    $iif($2,dic $2-,msg # Specify a word to look up)
  } 
}

alias dic {
  sockclose dic
  set %dic.word $replace($1-,$chr(32),$chr(37) $+ 20)    
  set %dic.counter 0
  sockopen dic dictionary.reference.com 80
}

on *:SOCKOPEN:dic:{
  if $sockerr { return }
  sockwrite -n $sockname GET /browse/ $+ %dic.word $+ ?s=t HTTP/1.1
  sockwrite -n $sockname Host: dictionary.reference.com
  sockwrite -n $sockname $crlf
}

on *:SOCKREAD:dic:{ 
  :nextread
  if $sockerr { return }
  var %data  
  sockread %data  
  if ($regex(%data,<span class="dbox-pg">(.*?)</span>)) { set %dic.class $regml(1) }
  if ($regex(%data,<span class="def-number">1.</span>)) { set %dic.target 1 }
  if (%dic.target == 1) { inc %dic.counter }
  if (%dic.counter >= 3 ) { 
    if (!$noHTML(%data)) goto nextread
    msg %channel $+($upper($left(%dic.class,1)),$mid(%dic.class,2)) - $+($upper($left($noHTML(%data),1)),$mid($noHTML(%data),2)) 
    unset %dic.*
    sockclose dic
  }
  elseif (<div class="cl-left">Copyright isin %data) || (HTTP/1.1 301 Moved Permanently isin %data) { 
    msg %channel Word not found
    unset %dic.*
    sockclose dic 
  }
}

Last edited by Sakana; 07/02/15 11:54 AM.
P
paper0rplastic
paper0rplastic
P
Thank you again Sakana laugh

B
Blas
Blas
B
This script is exactly what I was looking for. Thanks! I just have a quick fix though, as I'm assuming the dictionary website may have changed a bit since the last script update here. Queries with two or more words no longer work with the current script, at least not for me. "%20" was changing the URL to a "-" so I just changed the script to use that, and now it works again.

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

on *:text:!dic*:#: { 
    if ($1 == !dic) {
    set %channel #
    $iif($2,dic $2-,msg # Specify a word to look up)
  } 
}

alias dic {
  sockclose dic
  set %dic.word $replace($1-,$chr(32),-)    
  set %dic.counter 0
  sockopen dic dictionary.reference.com 80
}

on *:SOCKOPEN:dic:{
  if $sockerr { return }
  sockwrite -n $sockname GET /browse/ $+ %dic.word $+ ?s=t HTTP/1.1
  sockwrite -n $sockname Host: dictionary.reference.com
  sockwrite -n $sockname $crlf
}

on *:SOCKREAD:dic:{ 
  :nextread
  if $sockerr { return }
  var %data  
  sockread %data  
  if ($regex(%data,<span class="dbox-pg">(.*?)</span>)) { set %dic.class $regml(1) }
  if ($regex(%data,<span class="def-number">1.</span>)) { set %dic.target 1 }
  if (%dic.target == 1) { inc %dic.counter }
  if (%dic.counter >= 3 ) { 
    if (!$noHTML(%data)) goto nextread
    msg %channel $+($upper($left(%dic.class,1)),$mid(%dic.class,2)) - $+($upper($left($noHTML(%data),1)),$mid($noHTML(%data),2)) 
    unset %dic.*
    sockclose dic
  }
  elseif (<div class="cl-left">Copyright isin %data) || (HTTP/1.1 301 Moved Permanently isin %data) { 
    msg %channel Word not found
    unset %dic.*
    sockclose dic 
  }
}

E
Eric
Eric
E
I'm trying to run your script, but all it returns is "word not found" what do I do to fix that?

Joined: Dec 2015
Posts: 147
D
Vogon poet
Offline
Vogon poet
D
Joined: Dec 2015
Posts: 147
Here's another version that should work.
Code:
on *:text:!dictionary *:#: {
  if ($mysocket(dictionary,http://www.dictionary.com/browse/ $+ $replacex($2-,$chr(32),% $+ 20) $+ ?s=t)) {
    hadd $v1 channel #
    hadd $v1 word $2-
  }
}

alias -l dictionary {
  if ($2 == error) msg $hget($1,channel) An error occurred, please try again.
  else {
    if ($bfind(&mysocket,1,<span class="def-number">1.</span>)) && ($bfind(&mysocket,$v1,<div class="def-content">)) {
      var %s = $v1 + 28
      if ($bfind(&mysocket,%s,</div>)) msg $hget($1,channel) $upper($hget($1,word)) $+ : $regsubex($bvar(&mysocket,%s,$calc($v1 -%s)).text, /<[^>]+(?:>|$)|^[^<>]+>/g,$null)
      else msg $hget($1,channel) No word found.
    }
    else msg $hget($1,channel) No word found.
  }
}

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
    mysocket.k %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. $+ %s -io 1 60 mysocket.t %s
    if ($isid) return %s
  }
  else $iif($isid,return,echo -a Invalid input, us as: /mysocket <command> <link>)
}

alias -l mysocket.t $hget($1,command) $1 error open Connection timeout | mysocket.k $1

alias -l mysocket.k hfree -w $1 | sockclose $1 | .timermysocket. $+ $1 off | .remove $1 | unset %c.t

on *:sockopen:*.mysocket: {
  tokenize 32 $sockname
  if ($sockerr) mysocket.e $1 open
  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/45.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

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

alias -l mysocket.e $hget($1,command) $1 error $2 $sockerr $sock($1).wsmsg | mysocket.k $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 $iif($bvar(&mysocket,0),done,error read No data received.)
  mysocket.k $1
}

T
thewizard_123
thewizard_123
T
How do I connect that into a channel? do i have to set it onto a channel and how?

T
TUSK3N
TUSK3N
T
Dazuz, your script works fine but in twitch chat the message is sometime to long is it possible to set a limit to a text message and send 2 messages instead of 1? Other than that it works fine!

Joined: Dec 2015
Posts: 147
D
Vogon poet
Offline
Vogon poet
D
Joined: Dec 2015
Posts: 147
mIRC itself has split option in options (IRC --> Messages --> Split long channel/query messages).


Link Copied to Clipboard