Skip to content

Commit

Permalink
add support for basic shared chat ignorance
Browse files Browse the repository at this point in the history
  • Loading branch information
BarryCarlyon committed Sep 18, 2024
1 parent 6f638f8 commit 3836cc0
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 116 deletions.
5 changes: 4 additions & 1 deletion chat/eventbased/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ I'm not one for libraries too much but I'll shunt the parse logic into a includa

- [Chat Guide](https://dev.twitch.tv/docs/irc/guide)


## General Notes/Usage

- All IRC commands are emitted as `EVENTNAME` and `eventname`, so you can listen on `PRIVMSG` or `privmsg`
- Any `PRIVMSG` that are cheers will also riase a `cheer` avent in addition to `PRIVMSG`
- All `USERNOTICE`s are also sent as `usernotice_tagName` so `usernotice_resub` for example

- All Tags exist as their `hypen-name` and `hypen_name` so JS objects can destructure magically

# Notes

The eventbased_space version is likely more performant this version is just super legacy.
271 changes: 165 additions & 106 deletions chat/eventbased/chat_template.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class ChatBot extends EventEmitter {
constructor(opts) {
super();

opts = opts || {};
this.sharedChatPrefix = opts.sharedChatPrefix || true;

this.reconnect = true;
this.ws = null;
this.pinger = {
Expand Down Expand Up @@ -116,6 +119,7 @@ class ChatBot extends EventEmitter {
if (message[x].length == 0) {
return;
}
console.log(message[x]);

let payload = {
tags: {},
Expand Down Expand Up @@ -236,120 +240,175 @@ class ChatBot extends EventEmitter {
payload.message = actionCheck[1];
}

// https://tools.ietf.org/html/rfc1459
// commands the template needs to reply
switch (payload.command) {
case 'PING':
// Twitch sent a "R U STILL THERE?"
this.ws.send('PONG :' + payload.message);
case 'PONG':
this.pinger.gotPong();
break;
}
this._relay(payload);
}
}
_relay(message) {
this.emit('raw_parsed', message);
// determine what we want to emit
// and/or if we have an auto task to do

// auto tasks

// https://tools.ietf.org/html/rfc1459
// commands the template needs to reply
switch (message.command) {
case 'PING':
// Twitch sent a "R U STILL THERE?"
this.ws.send('PONG :' + message.params[1]);
case 'PONG':
this.pinger.gotPong();
break;
}

switch (payload.command) {
case '001':
case '002':
case '003':
case '004':
// do nothing
break;
case 'CAP':
this.emit('CAP ACK', payload.raw);
break;
case '372':
case '375':
case '376':
// motd
this.emit('MOTD', payload.raw);
break;
case '353':
case '366':
// names
break;

case 'PING':
case 'PONG':

case 'JOIN':
// You joined a room
case 'PART':
// as the result of a PART command
// you left a room

case 'GLOBALUSERSTATE':
// You connected to the server
// here is some info about the user
case 'USERSTATE':
// Often sent when you send a PRIVMSG to a room
case 'ROOMSTATE':
// You joined a room here is the intial state (followers only etc)
// The Room state was changed, on change only sends what changed, not the whole settings blob

case 'WHISPER':
// you received a whisper, good luck replying!
case 'PRIVMSG':
// heres where the magic happens

if (payload.hasOwnProperty('tags')) {
if (payload.tags.hasOwnProperty('bits')) {
// it's a cheer message
// but it's also a privmsg
this.emit(
'cheer',
payload
);
}
// regular sutff :tm:
//console.debug(message.command);

switch (message.command) {
case '001':
case '002':
case '003':
case '004':
// startup
case '353':
case '366':
// names

// above list of things
// we "ignore" and don't emit
// but we switch on them to stop
// the no process
break;

case 'CAP':
this.emit('CAP', message.raw);
break;
case '372':
case '375':
case '376':
// motd
this.emit('MOTD', message.raw);
break;

case 'PING':
case 'PONG':

case 'JOIN':
// You joined a room
case 'PART':
// generally as the result of a PART command
// you left a room

case 'GLOBALUSERSTATE':
// You connected to the server
// here is some info about the user you are logged in as
case 'USERSTATE':
// Often sent when in response to sending a PRIVMSG to a room
// but not every time
case 'ROOMSTATE':
// You joined a room here is the intial state (followers only etc)
// The Room state was changed, on change only sends what changed, not the whole settings blob

case 'WHISPER':
// you received a whisper, good luck replying!
case 'PRIVMSG':
// heres where the magic happens

if (message.hasOwnProperty('tags')) {
if (message.tags.hasOwnProperty('bits')) {
// it's a cheer message
// but it's also a privmsg
this._roomMatch(
'cheer',
message
);
}
}

case 'USERNOTICE':
// see https://dev.twitch.tv/docs/irc/tags#usernotice-twitch-tags
// An "Twitch event" occured, like a subscription or raid

if (payload.hasOwnProperty('tags')) {
if (payload.tags.hasOwnProperty('msg-id')) {
this.emit(
`usernotice_${payload.tags['msg-id']}`,
payload
);
}
case 'USERNOTICE':
// see https://dev.twitch.tv/docs/irc/tags#usernotice-twitch-tags
// An "Twitch event" occured, like a subscription or raid

if (message.hasOwnProperty('tags')) {
if (message.tags.hasOwnProperty('msg-id')) {
this._roomMatch(
message.tags['msg-id'],
message
);

this._roomMatch(
`usernotice_${message.tags['msg-id']}`,
message
);
}
}

case 'NOTICE':
// General notices about Twitch/rooms you are in
// https://dev.twitch.tv/docs/irc/commands#notice-twitch-commands

// moderationy stuff
case 'CLEARCHAT':
// A users message is to be removed
// as the result of a ban or timeout
case 'CLEARMSG':
// a single users message was deleted
case 'HOSTTARGET':
// the room you are in, is now hosting someone or has ended the host

this.emit(
payload.command,
payload
);
this.emit(
payload.command.toLowerCase(),
payload
);
break;

case 'RECONNECT':
// The server you are connected to is restarted
// you should restart the bot and reconnect

// close the socket and let the close handler grab it
this.ws.close();
break;
case 'NOTICE':
// General notices about Twitch/rooms you are in
// https://dev.twitch.tv/docs/irc/commands#notice-twitch-commands

// moderationy stuff
case 'CLEARCHAT':
// A users message is to be removed
// as the result of a ban or timeout
case 'CLEARMSG':
// a single users message was deleted

// default emit all events using the command name
this._roomMatch(
message.command,
message
);
this._roomMatch(
message.command.toLowerCase(),
message
);
break;

// service stuff
case 'RECONNECT':
// The server you are connected to is restarted
// you should restart the bot and reconnect

// close the socket and let the close handler grab it
this.ws.close();
break;

default:
console.log('No Process', message.command, message);
}
}

default:
console.log('No Process', payload.command, payload);
_roomMatch = function(event, message) {
/*
if the channel is in shared chat mode
and the message recieved is from the other channel
prepend shared_ to the event name
so you would have
privmsg
shared_privmsg
for example
*/
if (this.sharedChatPrefix) {
if (message.hasOwnProperty('tags')) {
if (message.tags.hasOwnProperty('source-room-id')) {
// the room connected to is in shared chat mode
let room_id = message.tags['room-id'];
let source_room_id = message.tags['source-room-id'];
if (room_id != source_room_id) {
event = `shared_${event}`;
}
}
}
}

this.emit(
event,
message
)
}

login = function(username, user_token, rooms) {
Expand Down
17 changes: 9 additions & 8 deletions chat/eventbased/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion chat/eventbased/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
"author": "",
"license": "ISC",
"dependencies": {
"ws": "^8.5.0"
"ws": "^8.18.0"
}
}

0 comments on commit 3836cc0

Please sign in to comment.