IRCv3 two messages in one line?

I’ve been having an issue where my client receives two chat messages jammed in to one line, for example as follows:

@color=#000000;display-name=user1;emotes=;mod=0;subscriber=0;turbo=0;user-id=00000000;user-type= :user1!user1@user1.tmi.twitch.tv PRIVMSG #channel :chat message.@color=#FFFFFF;display-name=user2;emotes=;mod=0;subscriber=0;turbo=0;user-id=00000001;user-type= :user2!user2@user2.tmi.twitch.tv PRIVMSG #channel :another chat message.

It is extremely rare to happen but I can’t seem to figure out if it’s a Twitch anomaly or I’m doing something wrong, but, from what I can tell it appears to be sent to me this way since my code is pretty basic:

client.on('data', function(data) {
   if(data.indexOf('PRIVMSG') >= 0) {
      console.log('raw msg: ' + data);
   }
});

Any ideas?

What is client or how is it reading the data?

IRC messages are separate by \r\n so if your client isn’t using that a delimiter than it will cause issues.

Also, do have an example of an actual message that was received this way?

Here’s an example of a message. It happens approx. every 1 in 500+ messages:

@color=#00FF7F;display-name=Baddimes;emotes=;mod=0;subscriber=0;turbo=0;user-id=70822083;user=type= :baddimes!baddimes@baddimes.tmi.twitch.tv PRIVMSG #sodapoppin :lvl18 win bro@color=#FF0000;display-name=MikeAnderson1k;emotes=88:7-14;mod=0;subscriber=0;turbo=0;user-id=32285244;user-type= :mikeanderson1k!mikeanderson1k@mikeanderson1k.tmi.twitch.tv PRIVMSG #sodapoppin :lvl 18 PogChamp

So it is possible for Twitch to send two messages in one like that or? Because monitoring

test = data.match('\r\n').length;

In every message I’m always only getting one occurance/match (even in the double’d up messages) at the end which I typically just remove with

data = data.replace('\r\n', '');

Sounds like your collector/reader is derping.

Can you post your full code?

Here ya go. This is my stripped down code that still has the same issue with doubled up messages:

var net = require('net');

var client = new net.Socket();
client.setEncoding('utf-8');
client.setNoDelay(true);
client.connect(6667, 'irc.twitch.tv', function() {
	console.log('Connected');
	client.write('PASS pass\r\n');
	client.write('NICK nick\r\n');
	client.write('CAP REQ :twitch.tv/tags\r\n');
	client.write('CAP REQ :twitch.tv/commands\r\n');
	client.write('JOIN #SomeBusyTwitchChannel\r\n');
});

client.on('data', function(data) {
	if(data.indexOf('PRIVMSG') >= 0 && data.match(/PRIVMSG/g).length > 1) {
		console.log(data.match(/PRIVMSG/g).length +  ' found! ' + data);
	}
	
	if(data.indexOf('PING') >= 0) {
		client.write('PONG tmi.twitch.tv\r\n');
	}
});

client.on('close', function() {
	console.log('Connection closed');
	client.destroy();
});

client.on('error', function() {
	console.log('Connection error');
});

client.on('end', function() {
	console.log('Connection end');
});

client.on('timeout', function() {
	console.log('Connection timeout');
});

client.on('drain', function() {
	console.log('Connection drain');
});

client.on('lookup', function() {
	console.log('Connection lookup');
});

Apologies for lack of links. Am on mobile

Since you are appearing to be on nodejs. Instead of using net look at either tmi.js. Or my own fork of node-irc on GitHub. Tmi.js will save you a huge chunk of implementation work

In regards to your code: You do not split the incoming data at all?
As far as I know, twitchs websocket servers always send full messages (no chunking), so a simple data.split("\r\n") should do the trick - after that, iterate over the split parts. Additionally, I suggest using a proper IRC message parser (like the npm package irc-message) instead of things like indexOf, you will be glad you did.

Barry suggested you use tmi.js or similar, for a beginner that is not a bad idea.

If Twitch isn’t chunking the messages and there’s nothing in my code doing it I guess it’s something wrong with the net module or? Either way, that’s exactly what I ended up doing the other day and it works fine:

if(data.indexOf('PRIVMSG') >= 0) {
	lines = data.split('\r\n');

	if (lines[lines.length-1] === '')
		lines.pop();

	for (var i = 0; i < lines.length; i++) {
		individual line stuff...

Although I’m not a beginner, sometimes I do code like one lol. I don’t mind writing stuff myself (as a challenge/for learning purposes) I just don’t remember having this issue with the base TWITCHCLIENT or without CAP REQ tags.

Twitch batches messages that get sent (nearly) at the same time, which is why you have to split them manually. There is nothing wrong with the net module :wink:

If that code works fine, all is well.

EDIT: I dont know exactly how net handles this, but there is a chance that long messages will arrive in parts (chunks, usually 512 bytes or something). In this case, you will have to keep a buffer of received data and split off only complete lines including \r\n. This is default handling, and if you look into the popular IRC packages, all do that.
My own code looks like this: https://gist.github.com/CBenni/4538837f6c0d5b272985

I anticipate that net is reading till size of buffer.

Instead of reading to line delimiter. Or (assumed) max buffer length.

So instead or reinventing the wheel. At least use a pre existing IRC library

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.