Note: This site is currently "Under construction". I'm migrating to a new version of my site building software. Lots of things are in a state of disrepair as a result (for example, footnote links aren't working). It's all part of the process of building in public. Most things should still be readable though.

Twitch Chat Single Message Bot With TMI.js

#+PREFACE

This seems to work, but I still consider it suspect since I can't tell from the early work why sometimes the process would quit properly and sometimes it wouldn't. The sleep timer seems to take care of it but it feels like if some part of the network communication takes to long it might not close.

#+POST

I'm playing around with an idea for a single Twitch bot that acts as a single place for folks to receive EventSub notifications from Twitch and then forward them on to chat so everybody doesn't have to setup their own public server to receive the webhooks.

I don't want to stay connected to all the different chat channels all the time. The goal is to login, forward the message and then close the connection.

After a fair amount of banging around, this is what I ended up with:

Code

#!/usr/bin/env node

  const tmi = require('tmi.js')
  const { execSync } = require('child_process')

  const botname = 'thebotofalan'
  const channelName = 'theidofalan'

  const oauth_token = execSync(
    'security find-generic-password -w -a alan -s alan--twitch--oauth'
  )
  .toString()
  .trim()

  function sleep(milliseconds) {
    const date = Date.now()
    let currentDate = null
    do {
      currentDate = Date.now()
    } while (currentDate - date < milliseconds)
  }

  let client = new tmi.Client({
    options: { 
      debug: true,
    },
    identity: {
      username: botname,
      password: oauth_token,
    },
    channels: [channelName],
  })

  client.connect()

  client.on('join', (channel, username, self) => {
    if (username === botname) {
        client.say(channelName, `this is the message`)
        sleep(9000)
        client.disconnect()
    }
  })

You'll need to install tmi.js with:

Code

npm i tmi.js

You'll also need to setup a Twitch App with an OAuth token that has the proper scopes for getting to chat (currently `chat:read` and `chat:edit`). The first steps of the related [[https://twurple.js.org/docs/examples/chat/basic-bot.html][twurple]] bot guide shows how to do that

#+NOTES

- I store my passwords and credentials in the macOS built-in Keychain Access app. The `security` call from `execSync` is accessing it here

- There's probably a better way to do the sleep

- I'm not sure if the sleep in the `join` event before the `.disconnect()` is necessary. There seemed to be timing issues at some points figuring this out so I'm leaving it in regardless

- The 9sec. (9000ms) sleep is to give some time to connect if it fails to connect the first time which I've seen before.