Skip to content
← Back to projects

Twitch Chat Bot

A custom TypeScript bot for a Twitch channel with commands, moderation, viewer engagement features, and stream analytics.

Custom command system
TypeScriptNode.jsWebSocketMongoDBtmi.js
TypeScript
Language
WebSocket
Protocol
MongoDB
Database
24/7
Uptime

The Problem

Every Twitch channel beyond a certain size needs a bot. The popular options — Nightbot, StreamElements, Moobot — handle the basics, but they are black boxes. You cannot customize the behavior beyond their configuration UI, you cannot integrate with your own systems, and you cannot collect the specific data you want. For our channel, we wanted a bot that does exactly what we need and nothing we do not.

The specific gaps: custom command logic that goes beyond simple text responses, moderation rules tuned to our community's tone, viewer engagement features that the off-the-shelf bots do not offer, and stream analytics that feed into our own database rather than being locked in someone else's dashboard.

The Approach

The bot connects to Twitch IRC via WebSocket using tmi.js and stays connected 24/7 — not just during streams. Chat activity between streams (raiders, lurkers, returning viewers) is valuable data. The connection handler manages reconnection with exponential backoff, handles Twitch's rate limits (20 messages per 30 seconds for non-mod bots), and logs connection health metrics.

The command system is modular. Each command is a self-contained module with its own handler, cooldown configuration, permission level, and usage tracking. Adding a new command means creating a new file — no touching the core bot logic. Commands range from simple (viewer stats, uptime) to complex (interactive polls, point systems, game integration).

Twitch IRC is deceptively simple. The protocol is standard IRC, but Twitch layers on custom tags (badges, emotes, subscription tier), rate limiting that varies by moderator status, and reconnection requirements that standard IRC libraries do not handle well. tmi.js abstracts most of this, but understanding the underlying protocol matters when you are debugging why your bot silently stopped receiving messages at 2 AM.

Technical Decisions

TypeScript over Python for the bot. The Twitch ecosystem is JavaScript-native — tmi.js is the most battle-tested IRC library, and most Twitch API wrappers are Node.js first. TypeScript adds the type safety that a long-running process needs. When the bot runs 24/7, a runtime type error at 3 AM that crashes the process is not acceptable. Strict TypeScript catches most of those at compile time.

MongoDB for chat and analytics storage. Chat messages, command usage, viewer activity, and stream metadata all go into MongoDB. The schema-flexible nature fits well — chat messages have variable metadata (some have emotes, some have bits, some are subscriptions), and we do not want to migrate a SQL schema every time Twitch adds a new event type. Aggregation pipelines handle the analytics queries for viewer trends, peak activity times, and command popularity.

Modular command architecture. Every command registers itself with the command handler, declaring its trigger, aliases, cooldown, required permission level, and handler function. The handler validates input, executes the logic, and returns a response. This pattern means commands are independently testable and deployable — we can hot-reload a single command module without restarting the entire bot.

Event-driven architecture for non-command features. Subscriptions, raids, follows, and bit donations trigger event handlers independently of the command system. Each event type has its own handler chain — a new subscription might trigger a thank-you message, update the subscriber database, increment a stream counter, and log the event for analytics, all as separate handlers on the same event. Adding new behavior to an existing event does not require modifying existing handlers.

What We Learned

Long-running processes have different failure modes than request-response servers. Memory leaks that are invisible in a web server that restarts daily become critical in a bot that runs for weeks. We added heap monitoring that alerts when memory usage trends upward over time, and periodic garbage collection logging to catch leaks early.

The other lesson was about community-specific moderation. Generic moderation rules (link filtering, caps lock detection, banned words) are table stakes. The interesting moderation problems are contextual — the same message might be fine during a casual stream and inappropriate during a competitive one. Stream state awareness (what game is being played, whether the streamer is in a tournament) feeds into moderation decisions, which is something no off-the-shelf bot handles.


Need a custom bot or automation? Let's talk.

Want Something Like This Built?

I build custom software, AI pipelines, and automation systems. Book a free 15-minute call to talk about your project.