mTwitch.GroupChat.mrc

By SReject on Aug 27, 2015

version: 0000.0000.0006

Moved to GitHub

I've moved this project to github in hopes of alleviating some of the headaches caused by maintaining 5+ pages for what is essentially the same project. I also hope the move will motivate others to get involved and contribute to the codebase

About

This is an mTwitch module that, currently, implement's Twitch Chat's Whisper interface to more closely conform to the IRC standard. It makes use of mIRC sockets to connect to a group chat server directly after you connect to a normal Twitch Chat server. Once connected to the group chat server you can make use of mIRC's built query functionality to handle said whispers(/msg username, on text, on open, etc)

Plans

Eventually, Group Chats will be added but as of current I do not have a standing invite to such a room and thus cannot code/test against it; if you wish to create one, feel free to message me here and we will arrange something

Code

on *:START:{
  if (!$mTwitch.has.Core) {
    echo $color(info) -a [mTwitch->GroupChat] mTwitch.Core.mrc is required
    .unload -rs $qt($script)
  }
}
on $*:PARSELINE:out:/^PASS (oauth\x3A[a-zA-Z\d]{30,32})$/:{
  if ($mTwitch.isServer && !$mTwitch.isServer().isGroup) {
    connect $cid $me $regml(1)
  }
}
on $*:PARSELINE:out:/^PRIVMSG (?!=jtv|#)(\S+) :(.*)$/i:{
  if (!$mTwitch.isServer || $mTwitch.isServer().isGroup) {
    return
  }
  if ($sock(mTwitch.groupChatConnection $+ $cid) && $hget(mTwitch.groupChatConnection $+ $cid, loggedIn)) {
    buffer $+(mTwitch.groupChatConnection $+ $cid) PRIVMSG jtv :/w $regml(1) $regml(2)
  }
  halt
}
on *:DISCONNECT:{
  if ($mTwitch.isServer && $sock(mTwitch.GroupChatConnection $+ $cid)) {
    cleanup mTwitch.groupChatConnection $+ $cid
  }
}
on *:SOCKOPEN:mTwitch.groupChatConnection*:{
  tokenize 32 $sock($sockname).mark
  if ($0 !== 3) {
    cleanup $sockname
  }
  elseif ($sockerr) {
    scid $1
    echo $color(info) -a [mTwitch->GroupChat] Connection to Twitch Group-Chat server failed to open; retrying...
    cleanup %sock
    .timer 1 0 connect $1-
  }
  else {
    buffer $sockname PASS $3
    buffer $sockname NICK $2
    buffer $sockname USER $2 ? * :Twitch User
    buffer $sockname CAP REQ :twitch.tv/commands twitch.tv/tags twitch.tv/membership
  }
}
on *:SOCKWRITE:mTwitch.groupChatConnection*:{
  tokenize 32 $sock($sockname).mark
  if (!$0) {
    cleanup $sockname
  }
  elseif ($sockerr) {
    scid $1
    echo $color(info) -a [mTwitch->GroupChat] Connection to Twitch Group-Chat server failed; attempting to reconnect...
    cleanup $sockname
    .timer 1 0 connect $1-
  }
  elseif ($hget($sockname, sendbuffer, &buffer) && $calc(16384 - $sock($sockname).sq) > 0) {
    var %bytes = $v1
    if (%bytes >= $bvar(&buffer, 0)) {
      sockwrite $sockname &buffer
      hdel $sockname sendbuffer
    }
    else {
      sockwrite %bytes $sockname &buffer
      bcopy -c &buffer 1 &buffer $calc(%bytes + 1) -1
      hadd -mb $sockname sendbuffer &buffer
    }
  }
}
on *:SOCKREAD:mTwitch.groupChatConnection*:{
  tokenize 32 $sock($sockname).mark
  if (!$0) {
    cleanup $sockname
  }
  elseif ($sockerr) {
    scid $1
    echo $color(info) -a [mTwitch->GroupChat] Connection to Twitch Group-Chat server failed; attempting to reconnect...
    cleanup $sockname
    .timer 1 0 connect $1-
  }
  else {
    scid $1
    var %t
    sockread %t
    while ($sockbr) {
      parse $regsubex(%t, /(?:^[\r\n\s]+)|(?:[\r\n\s]+$)/i, )
      sockread %t
    }
  }
}
on *:SOCKCLOSE:mTwitch.groupChatConnection*:{
  tokenize 32 $sock($sockname).mark
  if (!$0) {
    cleanup $sockname
  }
  else {
    scid $1
    cleanup $sockname
    echo $color(info) -a [mTwitch->GroupChat] Connection to Twitch Group-Chat server lost; attempting to reconnect...
    .timer 1 0 connect $1-
  }
}

alias -l connect {
  var %sock = mTwitch.groupChatConnection $+ $1
  cleanup %sock
  sockopen %sock $$hfind(mTwitch.chatServerList, group, 1, w).data 443
  sockmark %sock $1-
}
alias -l buffer {
  if ($0 < 2 || !$sock($1)) { 
    return 
  }
  elseif (!$sock($1).sq) {
    sockwrite -n $1-
  }
  else {
    bunset &queue
    bunset &buffer
    bset -t &queue 1 $2- $+ $crlf
    noop $hget($1, sendbuffer, &buffer)
    bcopy -c &buffer $calc($bvar(&buffer, 0) +1) &queue 1 -1
    hadd -mb $1 sendbuffer &buffer
  }
}
alias -l cleanup {
  if ($sock($1)) sockclose $1
  if ($hget($1)) hfree $1
  if ($timer($1)) $+(.timer, $1) off
}
alias -l parse {
  var %sock = $sockname
  if ($regex($1-, /^PING (:.*)$/)) {
    buffer %sock PONG $regml(1)
    return
  }
  if (!$hget(%sock, loggedIn)) {
    if ($regex($1-, /^:(?:tmi|irc)\.twitch\.tv NOTICE \S+ :Error logging in$/)) {
      cleanup $sockname
      echo $color(info) -a [mTwitch->GroupChat] Invalid oauth token; stopping Twitch Group-Chat connection attempts.
      halt
    }
    elseif ($regex($1-, /^:(?:tmi|irc)\.twitch\.tv (\d\d\d) \S+ :\S*$/i)) {
      hadd -m $sockname loggedIn $true
    }
    else {
      return
    }
  }
  if ($regex($1-, /^:(?:[^\.!@]*\.)?(?:tmi|irc)\.twitch\.tv CAP /i)) {
    return
  }
  elseif ($regex($1-, /^:(?:[^\.!@]*\.)?(?:tmi|irc)\.twitch\.tv (\d\d\d) /i)) {
    var %tok = $regml(1)
    if (%tok isnum 1-5 || %tok == 372 || %tok == 375 || %tok == 376) {
      return
    }
    .parseline -iqptu0 :tmi.twitch.tv $2-
  }
  elseif ($regex($1-, /^(@\S+ [^!@\s]+![^@\s]+@\S+) WHISPER \S+ (:.*)$/i)) {
    .parseline -iqptu0 $regml(1) PRIVMSG $me $regml(2)
  }
  elseif ($regex($1-, /^:?(?:[^\.!@]*\.)?(?:tmi|irc)\.twitch\.tv /i)) {
    .parseline -iqptu0 $iif(:* iswm $1, :tmi.twitch.tv, tmi.twitch.tv) $2-
  }
  else {
    .parseline -iqptu0 $1-
  }
}
alias mTwitch.has.GroupChat return 0000.0000.0007

Updates

v0.0.0007: Versioning consolidation between working version and released version
v0.0.0006: Revert 0.0.0002 change: removed -n switch from /parseline commands; was adding an extra line delimiters(r\n) to messages
v0.0.0005: Fixed channels being assumed as whispers for purposes of sending messages
v0.0.0004: Fixed sent whispers having a colon prefixed to them
v0.0.0003: Fixed typo in /buffer alias causing "/hadd: invalid parameters" error
v0.0.0002: Added -n switch to /parseline

Comments

Sign in to comment.
SchmantFREDO   -  Dec 21, 2015

first of all, nice work all works fine. i want to implement my bot games into whisper so the chat is clear from game. I got it working read out query, read out spamquerys, but my problem is when i set variables and msg them back.
example: set %einsatz $2
msg $nick bla bla %einsatz WORD bla bla
then i get back WORD Unknown command
any solution here?

SReject  -  Dec 21, 2015

I would need to see what $2 and its usage

SchmantFREDO  -  Dec 21, 2015

thanks for the fast reply, sent u a msg with the full code i use

Sign in to comment

dariux1x   -  Nov 05, 2015

Doesnt work anymore :/ I think twitch did something

SReject  -  Nov 05, 2015

attempt to whisper me on twitch (using a web browser is fine)

My twitch name is SReject

Sign in to comment

SReject   -  Oct 22, 2015

v0.0.0002 - v0.0.0006 Update Notes:

v0.0.0006: Revert 0.0.0002 change: removed -n switch from /parseline commands; was adding an extra line delimiter(\r\n) to messages
v0.0.0005: Fixed channels being assumed as whispers for purposes of sending messages
v0.0.0004: Fixed sent whispers having a colon prefixed to them
v0.0.0003: Fixed typo in /buffer alias causing "/hadd: invalid parameters" error
v0.0.0002: Added -n switch to /parseline

If you notice bugs or inconsistancies please post them as a reply to this thread

 Respond  
DreadfullyDespized   -  Oct 01, 2015

Awesome work. Only thing that isn't ideal is that once a Whisper chat is started it then maintains in the alternate window instead of the main chatroom. From a streamer perspective it would be nice to see the whispers to you in the main chat.

Do you mean the groups that can be created within a stream? I believe any twitch streamer can create a room/group channel to chat in.

SReject  -  Oct 01, 2015

"once a Whisper chat is started it then maintains in the alternate window instead of the main chatroom" whispers/private messages do not have a chatroom association in the context of IRC.

With that said, this is simply an avenue of getting whispers to work on mIRC; from here you can use stuff like on open or on text to display the whisper where ever you like as though it was received straight from the IRC server.

"Do you mean groups that can be created within a stream" - Yes and no. That's a part of group chatting but there's also chats that sit outside the context of a streamer's chat that i'd like to support aswell.

Paper0rPlastic  -  Oct 07, 2015

Every so often I get an error in the status window:

/hadd: insufficient parameters (line 121, mTwitch.GroupChat.mrc)

Doesn't happen with every whisper.

SReject  -  Oct 21, 2015

This should be fixed now

Paper0rPlastic  -  Oct 22, 2015

Can confirm, no more errors. :) This project you are doing is a great help. Thank you for your efforts.

Sign in to comment

Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.