mIRC Homepage
Posted By: square_wave Twitch bot to use dictionary - 21/01/15 06:31 AM
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.
Posted By: Sakana Re: Twitch bot to use dictionary - 21/01/15 04:05 PM
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 
  }
}

Posted By: Sakana Re: Twitch bot to use dictionary - 21/01/15 10:09 PM
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 
  }
}
Posted By: paper0rplastic Re: Twitch bot to use dictionary - 21/01/15 10:49 PM
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
Posted By: Sakana Re: Twitch bot to use dictionary - 21/01/15 11:07 PM
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 
  }
}

Posted By: paper0rplastic Re: Twitch bot to use dictionary - 21/01/15 11:45 PM
Perfect! Thanks. smile
Posted By: square_wave Re: Twitch bot to use dictionary - 28/01/15 06:20 AM
Thank You. I will spend more time reverse enginnering what you did, but this is awesome! cool
Posted By: square_wave Re: Twitch bot to use dictionary - 06/02/15 04:27 AM
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
Posted By: Sakana Re: Twitch bot to use dictionary - 06/02/15 11:05 AM
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
Posted By: paper0rplastic Re: Twitch bot to use dictionary - 07/02/15 12:19 AM
Found another "bug" with this script. If you try to get the definition of "zombie" you will see it. wink
Posted By: Sakana Re: Twitch bot to use dictionary - 07/02/15 08:56 AM
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 
  }
}
Posted By: paper0rplastic Re: Twitch bot to use dictionary - 07/02/15 07:20 PM
Thank you again Sakana laugh
Posted By: Blas Re: Twitch bot to use dictionary - 23/11/15 07:03 PM
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 
  }
}
Posted By: Eric Re: Twitch bot to use dictionary - 15/03/16 08:50 PM
I'm trying to run your script, but all it returns is "word not found" what do I do to fix that?
Posted By: Dazuz Re: Twitch bot to use dictionary - 15/03/16 11:54 PM
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
}
Posted By: thewizard_123 Re: Twitch bot to use dictionary - 20/03/16 12:49 AM
How do I connect that into a channel? do i have to set it onto a channel and how?
Posted By: TUSK3N Re: Twitch bot to use dictionary - 20/03/16 02:44 PM
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!
Posted By: Dazuz Re: Twitch bot to use dictionary - 20/03/16 03:41 PM
mIRC itself has split option in options (IRC --> Messages --> Split long channel/query messages).
© mIRC Discussion Forums