A Node.js program was written to communicate with Twitch’s IRC servers and OBS. Custom functionality was added as needed. The main motivation for this was to support a new Twitch feature called Channel Points with an easily customisable interface. At the point of release, there were no bots that were offering this automation (but quickly, programmers flooded the market). An example of normal operation would be that a Twitch viewer redeems a channel point reward, which triggers OBS to hide/unhide scenes.

The full code can be found at: https://github.com/Urgableh/Twitch-Channel-Point-Redemption-Bot. A few examples have been shown below:


Required npm packages:

const fs = require('fs');
const util = require('util');
const tmi = require('tmi.js');
const OBSWebSocket = require('obs-websocket-js');
const PubSubClient = require('twitch-pubsub-client').default;
const request = require("request");
const TwitchClient = require('twitch').default;

Synchronous external file reads:

// Reads a file in the same directory
function readData() {
  var text1 = fs.readFileSync('data.csv', 'utf8');
  processData(text1, obsData);
  var text2 = fs.readFileSync('credentials.csv', 'utf8');
  processData(text2, credentialsData);
}

Asynchronous monitoring of channel points events from Twitch:

// Redemption request monitoring using pubsub client
const runRedemption = async () => {
  const twitchClient = TwitchClient.withCredentials(clientId, accessToken, undefined, {clientSecret, refreshToken, onRefresh: async (t) => {}});
  const pubSubClient = new PubSubClient();
  await pubSubClient.registerUserListener(twitchClient);
  var temp = false; // Temporary variable to make sure the queue doesn't restart on every redemption

  pubSubClient.onRedemption(channelId, (message) => {
    if ( q.length == 0 ) {  // If the queue has no items in it
      temp = true;
    }
    else {
      temp = false;
    }
    console.log("Redemption received");
    var redeemed = inRedemption(channelId, message); // Match data.csv to the redemption
    q.push(function (run) { // Add OBS manipulation item into queue
      results.push(runningQueue(redeemed[0], redeemed[1], redeemed[2], redeemed[3]))
      run();
    })
    q.push(function (run) { // Add console logging item into queue
      results.push(console.log("Redemption complete"));
      run();
    })
    if (temp){  // If the queue has no items in it when redemption was received, start the queue.
      q.start();
    }
  })
}

OBS websocket API to change scenes:

// Function to enable the OBS source visibility
function activateSource(commandName, sourceName, sceneName){
    obs.send('GetSceneList')
    .then(data => {
        obs.send('SetSceneItemRender', {
        source: sourceName,
        render: true,           // Enable visibility
        "scene-name": sceneName
      })
    })
    .catch(err => {
      console.log(err);
    });
    console.log(`* Executed ${commandName} command`);
}