The Interactive & Immersive HQ

Parsing Twitch Chat Commands in TouchDesigner

Twitch is blowing up as a platform and more and more clients are wanting to shift their projects into some form of interactive live stream. If you’ve read our past posts, we’ve talked about how to get Twitch chat into TouchDesigner using WebSockets, but if you’re just getting started on your TouchDesigner Python journey, then one of the main lines that parses your commands might feel like a total mystery. In this post, we’re going to break down the main Python trick behind all of this parsing so you feel confident taking these workflows into your own hands!

The tricky line

The first thing you should do is use the link below to download our Twitch Chat receiver that is a free download in our previous blog post about this:

Once you’ve got it all setup (there are instructions inside!), you’ll notice that the Python code in the WebSocket DAT callbacks is pretty straight forward until you hit this line:

command_list = {user_message.strip("!") for user_message in user_message.split() if user_message.startswith("!")}

Woof, that’s quite a line. In this particular example, it’s a dictionary comprehension, but you’ve probably seen something similar called a list comprehension, which is the same thing except with [ ] around it instead of { }. It doesn’t really matter that much for this use case which is used, but let’s unwrap this complicated looking situation.

List / Dictionary Comprehensions

Plain and simple: a comprehension is a for loop inside of a box. The boxes are usually lists or dictionaries. What do I mean by inside of a box? Take this example: you want to fill a list with numbers from 1-100. If you did this without comprehensions, it would look like this:

# make an empty list to dump values into
my_list = []

# start a for loop to go through 100 values
for i in range(100):
    # add each value to the list
    my_list.append(i)

Not complicated, but quite a bit long for something so simple. If we walk through these steps verbally, we make an empty list, run a for loop through 100 numbers, then add them to the list. The list in this case is the box! Our for loop serves no purpose other than dumping items into our box. Comprehensions, and specifically list comprehensions, allow us to compress this down to 1 line:

my_list = [i for i in range(100)]

Wow! What’s a difference! So what’s going on? Simple!

  1. We make a variable called my_list, which is a list because we make [ ]
  2. Inside of it, we have our for loop just like we did previously: for i in range(100)
  3. Then, we have an extra i at the beginning, which basically takes every iteration of i as we go through our for loop and adds it to the new list

That’s it! Nothing to be intimidated by here. It’s really just a regular for loop on the second half. And the first part ( i ) is the variable you’d be working with inside the for loop anyways, except it automatically drops it into the list.

Type don’t matter

In the above example, we worked with a list comprehension because the end result is a list. In our Twitch chat component, it’s a dictionary comprehension since it ends up in a dictionary with { }. At the end of the day, most of the meat of the comprehension is the same, so you don’t need to worry about learning a completely different syntax between lists and dictionaries. Let’s keep going!

But then…

Let’s be real, that example was not intimidating. The intimidating part is when you start seeing all kinds of extra business in the comprehension. Let’s add a few interesting things to our example above to make it a bit more complex. Before we were taking every number from 1 to 100. What if we only wanted add even numbers? The good news is we can just extend our for loop with a small if statement right on the end!

my_list = [i for i in range(100) if i % 2 == 0]

All we did here was add a quick if statement on the end. If you haven’t seen the modulo symbol before ( % ), it is a division operation that returns the remainder from the division instead of giving you the actual answer. This is useful here because we can divide i by 2, and if there are 0 remainder from the division, we know we have an even number. You can imagine this as a short form of this:

my_list = []

for i in range(100):
    if i % 2 == 0:
        my_list.append(i)

In the one line version, you can imagine it does the for loop first, then the if statement after it, then i will get given to you if it passes the if statement passes.

Working on i

If we keep building on this, what if we then have all our even numbers, and we want to multiply them by 10? Simple!

my_list = [i * 10 for i in range(100) if i % 2 == 0]

Similar to above, here’s how this reads out:

  1. We start reading with our for statement to grab every number from 1 to 100
  2. We pass the value as we’re going through the loop to the if statement which checks to see if it’s even
  3. If it is, that value gets passed out as the i at the beginning and then we multiply it by 10 before adding it to the list

Nothing to complicated to explain, but it does start to look a bit more complicated! If you saw that at the beginning of the post, you might be pretty confused, but now that we’ve broken it down, and made a few examples, you should feel more comfortable to approach an expression like that.

Get Our 7 Core TouchDesigner Templates, FREE

We’re making our 7 core project file templates available – for free.

These templates shed light into the most useful and sometimes obtuse features of TouchDesigner.

They’re designed to be immediately applicable for the complete TouchDesigner beginner, while also providing inspiration for the advanced user.

Bringing it back to Twitch

We took a bit of a detour away from Twitch itself to talk about comprehensions and now we’re back at this line:

command_list = {user_message.strip("!") for user_message in user_message.split() if user_message.startswith("!")}

Let’s break it down using our new found knowledge. We’re making a dictionary (honestly would probably be better as a list in hindsight!) and trying to fill it with all the commands inside of the current message. It seems popular on Twitch to build commands around symbols. Here I’m assuming we’re using ! for the commands, so they would look like !hello or !command. Now that command could be anywhere inside of the message. It could be a message of just “!jump” but it could be something like “I wish this would !jump.” Let’s read through this now in our steps:

  1. First our for loop splits the user message string, and since there’s no arguments in the .split() it’s going to make the split every time it sees a space. This means a message like “hello there 123” will turn into a list like [‘hello’, ‘there’, ‘123’]. This list is what we’re iterating over.
  2. Then we have an if statement that takes each item in our list and checks to see if it begins with an ! symbol. This is the if user_message.startswith(“!”). If the word starts with !, we’re assuming it’s a command and we then send it to the first part of the comprehension.
  3. Once a value has passed our check to see if it’s a command word with an !, right before writing it into our dictionary (or list), we use .strip(“!”) to remove the ! and then we write the command word into the list.

Boom! With that single line, we take full sentences of incoming messages and parse them out to find command words, then we add them to a list of commands found inside of that chat message. After that you can do whatever you like with that list of commands! In our example, we run a for loop on the list of the commands and click some buttons and write to some FIFO DATs, but you could do anything because the hard part is over!

Wrap up

Even though Python is one of the more friendly languages to learn and read, it still has it’s fair share of weird tricks and strange statements. Comprehensions can be difficult for new users to get into but they really aren’t that tricky. Once you’ve done a few examples and see the order of operations that happens inside the comprehension statement, they’ll quickly become more and more comfortable and you’ll be able to manipulate the ones you see out in the wild even more easily. Enjoy!