Add an user interface to your Streamlabs Chatbot script using UI_Config.json

Share on:

Overview

Make your scripts look professional and easy to use with an user interface capable of customizing your script to meet your users requirements.

All the streamers who have used scripts before always check the configuration interface just after installing a script, so it makes sense to make your script as customizable as possible. Commands, cooldowns, messages, live only and script specific customizations!

In this post I will show you how to add an user interface to your script. The script we will create will be a dice roll script where the sides of the diCe can be customizable along the command, live only and output message.

Download

You can download the script to follow along from here (direct download) or here (support the blog).

Prerequisites

If you don't know how to make a Streamlabs Chatbot script make sure to check out how to create your first Streamlabs Chatbot script.

You also need to understand JSON (JavaScript Object Notation) to edit the user interface file, you can learn about JSON at these W3Schools' pages: JSON - Introduction and JSON Syntax.

Related to JSON, the JSON file will be converted to a Python Dictionary, you can learn more about python dictionaries here.

Adding an user interface to your script

1. Folder and files

We will create the next folder structure for our dice rolling script. The name will be Dice Roll.

1%APPDATA%\Streamlabs\Streamlabs Chatbot\Services\Scripts\
2└── DiceRoll\
3    ├── DiceRoll_StreamlabsSystem.py
4    ├── UI_Config.json
5    └── README.txt

2. Initialize the script

Before we start editing our user interface we need to make our script appear in the scripts list, so we initialize it with the required variables and functions:

DiceRoll_StreamlabsSystem.py

 1ScriptName = "Dice Roll"
 2Description = "Adds a command to roll a customizable die"
 3Creator = "LuisSanchezDev"
 4Version = "1.0.0"
 5Website = "https://luissanchez-dev.github.io/"
 6
 7def Init():
 8  pass
 9
10def Execute(data):
11  pass
12
13def Tick():
14  pass

Save the file, reload the scripts and make sure it shows up in the scripts list. There is no need to enable it yet.

3. Add controls to the user interface

Before editing the UI_Config.json file to add our controls, we need to define what controls we need and what information they hold, for example:

Configuration Type Value
Live only checkbox False
Roll command text !roll
Number of dice faces numberbox 6
Roll message text $user throws a $sides-sided dice: $value

The words starting with a dollar sign ($) are placeholders where we will put our own data.

Now that we know what information we need to customize the script we will edit the UI_Config.json file. Since it is a json file we enclose everything in curly brackets {}.

The first thing we need to specify is the filename where all the customized information will be stored.

UI_Config.json

1{
2  "output_file": "config.json",
3}

Next step is to specify all the controls we want. Each control is a json object with key-value pairs specific to each control type. The most common keys are:

Key name Description
"type" Specify the control type like checkbox, numberbox, textbox, etc.
"label" The name shown next to the control input.
"value" Control default value, this value is shown the first time the user opens the configuration interface.
"tooltip" Text shown when leaving the mouse over the control, useful for extra description.
"group" Specify the control group to keep your configuration interface clean and tidy.

The entire controls list can be found in the Streamlabs Chatbot wiki. In this case we are only using a checkbox, 2 textboxes and a numberbox which only need the keys specified before.

UI_Config.json

 1{
 2  "output_file": "config.json",
 3  "live_only": {
 4    "type": "checkbox",
 5    "label": "Live only",
 6    "value": false,
 7    "tooltip": "Check this option to limit the usage of this command to only live mode",
 8    "group": "General"
 9  },
10  "command": {
11    "type": "textbox",
12    "label": "Roll command",
13    "value": "!roll",
14    "tooltip": "Command to roll a dice",
15    "group": "General"
16  },
17  "faces": {
18    "type": "numberbox",
19    "label": "Number of dice faces",
20    "value": 6,
21    "tooltip": "Specify the amount of faces for the dice",
22    "group": "General"
23  },
24  "message": {
25    "type": "textbox",
26    "label": "Roll message",
27    "value": "$user throws a $sides-sided dice: $value",
28    "tooltip": "Shown when an user uses the command",
29    "group": "General"
30  },
31}

Save the file and go to the scripts list, click on the Dice Roll script name and you can now see your user interface.

script user interface

Now with the user interface ready lets go and edit the script!

4. Reading the configuration file

When the user clicks on the SAVE SETTINGS button, Streamlabs Chatbot will create a file with the same name as the "output_file" value in the UI_Config.json file. If the user hasn't clicked the button, this file will not exist so we will set a default configuration.

Importing required modules

Streamlabs Chatbot saves the json configuration file with UTF8 BOM encoding and since the Python version that is loaded is 2.7.13 we need to use the codecs module to open it. Also the starting path is where the Streamlabs Chatbot.exe is, so we need the os module to work with paths.

Add the following code to the beginning of your script file.

DiceRoll_StreamlabsSystem.py

1import os
2import json
3import codecs
4
5ScriptName = "Dice Roll"
6[...]

Global variables

Now we need some global variables to save important stuff such as the script directory path and the loaded settings so we can use them anywhere on the script.

You can see that I also added the path to the config file to my global variables, it makes it easier to read the code when loading the configuration.

DiceRoll_StreamlabsSystem.py

 1[...]
 2Website = "https://luissanchez-dev.github.io/"
 3
 4# Global variables
 5global PATH, CONFIG_FILE, SETTINGS
 6PATH = os.path.dirname(os.path.realpath(__file__))
 7CONFIG_FILE = os.path.join(PATH, "config.json")
 8SETTINGS = {}
 9
10def Init():
11[...]

Loading the configuration

We will load the configuration in the Init function to have everything ready before the script starts, since the config file is saved with the UTF8 BOM encoding we will use codecs.open since you can't specify a encoding in the default open function.

If we get an error while trying to open the config file that means there is no config file, so we can enclose the file opening code in a try/except block to load a default configuration.

DiceRoll_StreamlabsSystem.py

 1[...]
 2
 3def Init():
 4  global PATH, CONFIG_FILE, SETTINGS
 5  try:
 6    # Open config file with UTF8 BOM encoding
 7    with codecs.open(CONFIG_FILE, encoding="utf-8-sig", mode='r') as file:
 8      SETTINGS = json.load(file, encoding="utf-8-sig")
 9  except:
10    # Error loading the file, set default configuration
11    SETTINGS = {
12      "live_only": False,
13      "command": "!roll",
14      "faces": 6,
15      "message": "$user throws a $sides-sided dice: $value"
16    }
17    
18    # Prevent dice faces being less than 2
19    if SETTINGS["faces"] < 2:
20      SETTINGS["faces"] = 2
21
22[...]

As you can see, we used the same keys as the UI_Config.json file, loading the configuration file gives you the same dictionary with the user settings.

After loading the configuration you should take the opportunity to clean the input data, in this case we just make sure the number of faces is no less than 2 so when the user rolls the dice they get one of two numbers at least.

Now the SETTINGS object has all the configuration, we can now use it wherever we want, like for example in the Execute function.

5. Creating the command

With all the configuration handy we now write our command, as always only allow chat messages, then check if the streamer is live and if the command should work as per the script configuration.

I like to put all the conditions that should prevent further execution at the beginning of the code block.

To check if the streamer is live we use the IsLive function from the Parent object.

DiceRoll_StreamlabsSystem.py

 1[...]
 2
 3def Execute(data):
 4  global SETTINGS
 5  if not data.IsChatMessage():
 6    return
 7  
 8  if SETTINGS["live_only"]:
 9    if not Parent.IsLive():
10      return
11[...]

Is time to check if the command the user sent is the command we want to react to,but wait! Last time we hardcoded the command in the script, now we must take the value from the loaded configuration.

The command is now saved in our SETTINGS variable, we can access it using the "command" key as follows:

DiceRoll_StreamlabsSystem.py

 1[...]
 2
 3def Execute(data):
 4  global SETTINGS
 5  if not data.IsChatMessage():
 6    return
 7  
 8  if SETTINGS["live_only"]:
 9    if not Parent.IsLive():
10      return
11  
12  command = data.GetParam(0)
13  if command == SETTINGS["command"]:
14    # The command was used
15[...]

Now that we are filtering only the command we want is time to code the command logic.

We will use the function GetRandom from the Parent object to throw the dice and get a random number. You can see all the Parent functions at the Parent object wiki.

NOTE: The GetRandom function takes two arguments, the minimum and the maximum value. The maximum value is never reached so make sure to add +1 to the max value you want to get randomly.

DiceRoll_StreamlabsSystem.py

1[...]
2
3  command = data.GetParam(0)
4  if command == SETTINGS["command"]:
5    # The command was used
6    dice_value = Parent.GetRandom(1, SETTINGS["faces"] + 1)
7[...]

With the random dice value ready we just have to prepare our output message and send it. Remember we need to replace these words in the output message:

$user throws a $sides-sided dice: $value

  • $user: Replace with the username stored in data.UserName.
  • $sides: Dice number of faces, this is in the SETTINGS["faces"] configuration.
  • $value: The dice value, we just got it in dice_value.

Every string has a replace function we can use tu replace words in them, also don't forget to convert the numbers to strings:

DiceRoll_StreamlabsSystem.py

 1[...]
 2
 3  command = data.GetParam(0)
 4  if command == SETTINGS["command"]:
 5    # The command was used
 6    dice_value = Parent.GetRandom(1, SETTINGS["faces"] + 1)
 7    
 8    output_msg = SETTINGS["message"].replace("$user", data.UserName)
 9    output_msg = output_msg.replace("$sides", str(SETTINGS["faces"]))
10    output_msg = output_msg.replace("$value", str(dice_value))
11    Parent.SendStreamMessage(output_msg)
12
13[...]

If you try your script right now it will work but when the user saves a new configuration they will need to reload all the scripts. To tackle this, Streamlabs Chatbot has an optional function you can use called ReloadSettings, this function gets called when the user saves new settings.

This is why you should initialize everything in the Init function, you just have to call it inside the ReloadSettings function to avoid reloading all scripts:

DiceRoll_StreamlabsSystem.py

1[...]
2
3def Tick():
4  pass
5
6def ReloadSettings(jsonData):
7  Init()

Save, reload the scripts, enable Dice Roll and test the !roll command!

chat picture with script test

Now change the configuration and try again! I'm using the !throw command with a 20 sided dice and the $user summons a D$sides dice and rolls $value$ message.

custom configuration chat picture with script test

6. Add a README button

Your script is working! But what if you have a more complex script? Or you want to leave your contact information so that people can give you suggestions or report issues? You need a README.

First edit your README with all the info you want to give the user:

README.txt

 1Dice Roll made by Luis Sanchez
 2  Found any bugs or want to give a suggestion?
 3    * Email: my.email@email.com
 4    * Discord: myname#0123
 5    * Phone: 555-0123
 6
 7Description
 8This script allows you and your viewers to roll a dice with customizable settings!
 9
10Features
11* Anyone can roll a dice!
12* 6 sided dice? 20 sides? 100? Set your own dice sides!
13* Customizable message

Now add a button as the first control in your UI_Config.json, this button will show our README.txt.

UI_Config.json

 1{
 2    "output_file": "config.json",
 3    "readme": {
 4        "type": "button",
 5        "label": "Open README",
 6        "tooltip": "Click here to open the README for features list, usage and contact information",
 7        "function": "open_readme",
 8        "wsevent": "",
 9        "group": "General"
10    },
11    "live_only": {
12[...]

The function value in the button control is the name of the function you want this button to run.

Let's add an open_readme function to our script!

DiceRoll_StreamlabsSystem.py

1[...]
2
3def ReloadSettings(jsonData):
4  Init()
5
6def open_readme():
7  global PATH
8  readme_path = os.path.join(PATH, "README.txt")
9  os.startfile(readme_path)

As you can see, we use os.startfile to open the README.txt file. If you have your script on Github you can replace the file path with an url and it will open it.

To test the button you have to follow these steps:

  1. Save all files
  2. Reload the scripts
  3. Click on the Dice Roll script to show the user interface
  4. Click the OPEN README button

You have to do it this way because everytime you click on the script name, the user interface gets reloaded. Also the script that is currently running doesn't have the function defined so it will just throw an error. But even if you have the function defined and the user interface open and reload the scripts the button will stop working because it was linked to the function from the previously loaded script!

Extra. Common error

When using dictionaries there is an error with a non-descriptive error message, I modified a line so you can take a look at it:

non descriptive error message

Cool story bro! What is the problem? Well... the problem is that you tried to access a key in the dictionary that doesn't exists!

This is how the line #50 looks, you can see that we tried to access the messsage key instead of the message key!

DiceRoll_StreamlabsSystem.py

1    output_msg = SETTINGS["messsage"].replace("$user", data.UserName)

So when you see an error message like this one, make sure you are using the correct key.

Conclusion

It wasn't that difficult right? Create your UI_Config.json file, paste the controls you want and read the values from the script! With this information now your scripts will look professional and will be easy to use.

If you start creating a lot of sscripts I recommend to fill the settings first inside the script and when you finish the script, create your UI_Config.json file. Remember to make your script super easy to use and always add a README button for instructions on how to use your script.