question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

better way to parse message and emotes?

See original GitHub issue

I was just curious, does anyone have a better method of parsing the message with the emotes array? Here’s how I do it, wondering how everyone else does it.

function parseMessage(message, emotes) {
    var emoteArray = _.chain(emotes)
        .map(function(emote, index) {
            var charIndex = _.map(emote, function(chars) {
                var indexes = chars.split("-");

                return {
                    url: "http://static-cdn.jtvnw.net/emoticons/v1/" + index + "/1.0",
                    startIndex: parseInt(indexes[0]),
                    endIndex: parseInt(indexes[1]) + 1
                };
            });

            return charIndex;
        })
        .flatten()
        .sortBy(function(item) {
            return -1 * item.startIndex;
        })
        .value();

    if(emoteArray.length === 0) {
        return message;
    }

    var newMessage = message;

    _.each(emoteArray, function(emote) {
        var emoteName = newMessage.substring(emote.startIndex, emote.endIndex);

        var leftPart = newMessage.substring(0, emote.startIndex);
        var middlePart = makeImage(emoteName, emote.url);
        var rightPart = newMessage.substring(emote.endIndex);

        newMessage = leftPart + middlePart + rightPart;
    });

    return newMessage;
}


function makeImage(name, url) {
    return _s.sprintf("<img alt='%1$s' title='%1$s' src='%2$s' />", name, url);
}

It works by splitting the emote positions into a flattened array with every instance of said emote. Then I work backwards for every emote and string replace the position into an anchor tag (makeImage method).

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:26 (24 by maintainers)

github_iconTop GitHub Comments

2reactions
AlcaDesigncommented, Nov 18, 2016

This is the ugly code that I had used in the previous version for a stream chat.

stream chat

    function formatEmotes(text, emotes) {
        var splitText = text.split('');
        for(var i in emotes) {
            var e = emotes[i];
            for(var j in e) {
                var mote = e[j];
                if(typeof mote == 'string') {
                    mote = mote.split('-');
                    mote = [parseInt(mote[0]), parseInt(mote[1])];
                    var length =  mote[1] - mote[0],
                        empty = Array.apply(null, new Array(length + 1)).map(function() { return '' });
                    splitText = splitText.slice(0, mote[0]).concat(empty).concat(splitText.slice(mote[1] + 1, splitText.length));
                    splitText.splice(mote[0], 1, '<img class="emoticon" src="http://static-cdn.jtvnw.net/emoticons/v1/' + i + '/3.0">');
                }
            }
        }
        return splitText.join('');
    }

It essentially splits the text into individual characters and then sets all characters that are part of the emote into an empty character '' and changes the first index into an <img> tag. Doing it this way means going through each emote altering the indexes as given in one array, going through each emote however many times it needs to. Finally it joins it all together and returns it.

Rough example:

var message = 'OpieOP haha Kappa lel',
    emotes = {356:['0-5'],25:['12-16']};
    messageWithEmotes = formatEmotes(message, emotes);

messageWithEmotes comes out as:

<img class="emoticon" src="http://static-cdn.jtvnw.net/emoticons/v1/356/3.0"> haha <img class="emoticon" src="http://static-cdn.jtvnw.net/emoticons/v1/25/3.0"> lel
0reactions
Kequccommented, Aug 4, 2018

I wrote a solution before finding this thread that is maybe helpful for some people.

My project relied on having an array of characters that were written to the screen like a typewriter. So it seemed like a good idea to break it up into text strings one character long, and emote ids represented as numbers. Then while typing, it was able to discern “ok this is a character, this is an emote” as it goes.

This finds all indexes of the given emote code, inside of a string. It’s basically indexOf but returns all indexes.

function indexesOf (text, code) {
    const result = [];
    let index = -1;

    while (true) {
        index = text.indexOf(code, index + 1);
        if (index === -1) break;
        result.push(index);
    }

    return result;
}

The structure of my emotes is built somewhere else in my code, based on the user and the channel. It’s a plain object where keys are an available emote code and values are the emote id. For example it could look like this:

const emotes = {
    PartyHat: 965738,
    EarthDay: 959018,
    TombRaid: 864205,
    PopCorn: 724216
};

I use the following function to build an array where emote codes exist at the indexes they were found in the string. I use this array while breaking the text up into characters later.

function findEmotes (text, emotes) {
    const found = [];

    for (const code of Object.keys(emotes)) {
        for (const index of indexesOf(text, code)) {
            found[index] = code;
        }
    }

    return found;
}

Then finally I break the string down into characters and emotes.

export function getCharArray (text) {
    const emotes = getEmotes();
    const found = findEmotes(text, emotes);
    const charArray = [];

    for (let i = 0; i < text.length; i++) {
        if (found[i]) {
            // this is an emote
            const id = emotes[found[i]];
            charArray.push(id);
            i += (found[i].length - 1);
        } else {
            // this is text
            charArray.push(text[i]);
        }
    }

    return charArray;
}

For me it’s exactly what I needed because then my typewriter effect just needs to go through every item in the charArray, check whether it is a number, and if so insert a emote. Otherwise just insert the text.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How can I parse the emotes out of a Twitch IRC response into ...
I would like to parse an IRC message from Twitch to a list of dictionaries, accounting for emotes. Here is a sample of...
Read more >
Parsing Twitch Emotes (JS) - Reddit
Currently i am making a Twitch site that counts the number of emotes sent in a user specified channel, and ranks them by...
Read more >
Example Message Parser - Twitch Developers
The following example shows a simple parser that the example bot uses to parse Twitch IRC messages. The example parses many but not...
Read more >
Simple TMI Emote Parse - npm
Bring back emotes in chat messages coming from TMI.js (Twitch). Latest version: 1.1.1, last published: a year ago.
Read more >
Emote | npm.io
Emote Packages ; @mkody/twitch-emoticons. Gets Twitch, BTTV and FFZ emotes as well as parsing text to emotes! betterbttvemoji ; twitch-chat-cli. CLI for reading ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found