- #discord
- #bots
- #api-integration
- #twitch
- #automation
BotFire
A Discord bot for Il Bonfire, my streaming community: viewers suggest games through an IGDB-powered search, and I run my Twitch schedule from Discord with automatic Google Calendar sync.
- Role
- Solo developer and the community’s streamer: design, code and day-to-day running.
- Outcome
- In daily use on Il Bonfire since 2025. /prossima-live and /suggerisci-gioco are the most-used commands, and the schedule reaches Google Calendar more reliably than Twitch’s own sync.
- Year
- 2025
- Status
- in progress
- Stack
- Discord.js v14
- Node.js
- Twitch API
- IGDB API
- Google Calendar API
- Firestore
- Components V2
comandi-bot

BotFireAPP
Ciao viandante! Sono BotFire. Prova un comando qui sotto: suggerisci un gioco, guarda la prossima live o il programma del mese.
Try a command
A recreation of BotFire with sample data. The bot speaks Italian, like its community.
The start
A community and a creator, both underserved
I stream on Twitch, and Il Bonfire is my community's Discord server, the meeting point for my followers, the viandanti. Two chores kept eating my time: game suggestions scattered across the chat with no official way to collect them, and keeping my Twitch schedule in step with Google Calendar, which Twitch's own sync does in a half-broken way. No off-the-shelf bot did either the way I wanted, and I'd rather build a tool that fits than bend my workflow around a generic one.
The goal
One bot, two audiences
BotFire had to be a community hub for the viandanti and a private control panel for me. For the community: an official, well-made way to suggest games, smart enough to understand sagas and whether a game runs on PC, plus an easy way to see when the next stream is. For me: create, view and remove Twitch schedule entries instantly from Discord, with Google Calendar following along reliably.
The adventure
Four services behind one Discord bot
I started on September 16, 2025, and had the first complete version in about a month. BotFire runs on Discord.js v14 with ES modules and uses Discord's newest Components V2 for embed-free, interactive messages. Behind it sit four services: IGDB for the game database, Twitch's Helix API for the schedule, Google Calendar for the sync, and Firestore for the suggestions and votes. An in-memory cache with expiry and least-recently-used eviction keeps it fast without hammering any of them.
VideoSuggesting a game with /suggerisci-gioco0:00 / 0:00From search to saved suggestion. The difficulties
Sagas, calendars, limits and time zones
Finding every official, canonical game in a series took IGDB queries far more involved than a search: filtering out remasters, ports and spin-offs, then checking PC availability game by game. Keeping two calendars consistent meant linking every event to its Twitch segment and never letting a calendar failure block Twitch. Discord caps a message at about 40 components, so a busy month had to be split across messages. And every date had to survive time zones and daylight saving time on its way to two different APIs.
The end
In daily use, and still growing
BotFire is part of how I run my channel every day.
/prossima-liveand/suggerisci-giocoare the community's most-used commands, and the schedule reaches Google Calendar more reliably than Twitch's own sync. Not everyone uses its full potential, since some people are wary of Discord bots even when they're friendly, but the core features are part of the server's routine. It's an ongoing project: I keep adding tools, fixing and upgrading the existing ones, and I update this page whenever it changes significantly.
- To the first full version
- ~1 month
- To the first full version
- Services integrated
- 4
- Services integrated
- Permission levels
- 5
- Permission levels
- In use on Il Bonfire
- Daily
- In use on Il Bonfire
What's next
A friendlier schedule
I'd make the schedule even easier to use, within what Discord Components allow. Discord's forms are still limited, and I hope they get more powerful.
Calendar to Twitch
The infrastructure for syncing from Google Calendar back to Twitch exists; the logic to create Twitch segments from calendar events is the next step.
Game suggestions that understand sagas
IGDB-powered search with covers, saga detection, a PC check and no duplicates.
Twitch schedule from Discord
Create, view and remove streams instantly, in an interface with month navigation and per-stream actions.
Google Calendar sync
Every scheduled stream lands in Google Calendar, recurring ones included, more reliably than Twitch's own sync.
Community commands
The next stream, the suggested games with their votes, and the server's information, for everyone.
Five permission levels
Everyone, Member, Moderator, Admin and Owner, detected from roles and adjustable with a command.
Components V2 interface
Embed-free messages with buttons, modals and select menus, built on Discord's newest display components.
Game suggestions
/suggerisci-gioco searches IGDB as you type and understands that a game might be part of a bigger saga.
Saga detection
When a game belongs to a franchise, BotFire switches to the whole collection and lists every main entry.
PC check
I stream from a PC, so standalone games are checked for a PC release, and sagas get a PC compatibility percentage.
No duplicates
The same person can't suggest the same game or saga twice.
Search as you type
Live IGDB search with covers and metadata, from the third character.
Votes
Every suggestion counts as a vote, so the most wanted games and sagas rise to the top.
Smart filtering
Remasters, ports and spin-offs are left out, so a saga shows its canonical games only.
Suggestions and their votes can be browsed by game or by saga, with a leaderboard of the most active suggesters.
The Twitch schedule
The schedule commands are mine: they turn Discord into the place where I plan my streams.
Instant changes
Add, view and remove schedule entries straight from Discord, with no trip to Twitch's dashboard.
Google Calendar, automatically
Viewers can add streams to their own calendars, with reminders and notifications.
Categories with box art
Autocomplete over Twitch's game categories, with thumbnails.
Recurring streams
A weekly show is one entry, mirrored as a proper recurring event in the calendar.
Time zones
Full time zone support, daylight saving time included.
Fast navigation
Month by month, with smart caching and the next and previous months loaded in advance.
For the viandanti, /prossima-live shows when the next stream is and what it's about. The message deletes itself after 15 seconds, with a 20-second cooldown so it can't flood the chat.
Who can do what
Five levels, from the widest to the narrowest. The suggestion and next-stream commands are open to everyone; schedule management is owner-only by default, and /permission-set can change any of it.
Everyone
All users, including those with no role.Member
Users with any role beyond @everyone.Moderator
Users with moderation roles or permissions.Admin
Users with admin roles, and the server owner.Owner
Only the bot's owner.
Architecture
BotFire sits between Discord and three external services. Twitch is the source of truth for the schedule, Google Calendar follows it, and Firestore stands on its own for the game suggestions.
Twitch API (Helix)
Master
The schedule lives here. App-level tokens read public data; a user token authorizes schedule changes.
Google Calendar API
Follower
Synchronized from Twitch, through a service account. Each event stores its Twitch segment ID.
Firebase Firestore
Independent
Game suggestions, votes and user data, through service account credentials.
IGDB API
Game database
Search, collections and platforms, authenticated with the same Twitch OAuth2 credentials.
Every schedule action follows the same path: Discord command, validation, Twitch API, Google Calendar API, reply. A calendar failure is logged and never blocks Twitch.
Under the hood: game suggestions
Search
From the third character, up to 50 IGDB matches are fetched and the 25 shortest titles shown, as the most relevant.Details
The chosen game is fetched in full, including its collections.Saga
If it belongs to one, a multiquery fetches the saga's games and memberships in parallel.PC check
PC availability per game, and a percentage for the saga.Confirm and save
A confirmation, a duplicate check, then Firestore.
The saga multiquery
One request to IGDB's multiquery endpoint runs two queries side by side. The first fetches every game in the collection with its cover, release dates, platforms and parent game. The second fetches the collection's memberships, so the bot can keep only main games (membership type.id === 1) and drop spin-offs. Games are sorted by release date, using parent_game.first_release_date when there is one. The originally suggested game gets a marker in the list, PC games a check and the others a warning.
The filters keep only:
- Main games (
game_type = 0) that aren't remakes, remasters or ports. - DLCs (
game_type = 4) on PC only, and expansions (game_type = 8, 9) and standalone expansions (game_type = 10), filtered the same way. - Released games (
game_status = 0or none) that have a release year. - Modern platforms: PC, PlayStation 3, 4 and 5, Xbox 360, One and Series X|S, and Switch.
PC compatibility
A standalone game is checked for a release on PC (Microsoft Windows); without one, the confirmation turns gold (0xFFD700) with a warning. For a saga, each game is checked for platform 6 (PC), and below 75% compatibility the community gets a warning.
Storage and duplicates
Each suggestion is a Firestore document whose ID encodes the type, the target and the user:
{type}_{targetId}_{userId}
0_1942_123456789 a standalone game
1_123_123456789 a collectionSo the same user can't suggest the same thing twice, all suggestions for a game are one query away, and so are all suggestions by a user. Each document also stores the target's name, the user's name, a timestamp and audit fields (createdAt, updatedAt, createdBy, updatedBy).
Authentication
Twitch OAuth2
Client credentials flow; the token is cached in memory and refreshed when it expires, after an hour.
Performance
Caching
Firestore queries cached for 5 minutes with LRU eviction, at most 1,000 entries; the multiquery saves round trips.
Errors
Resilience
IGDB, autocomplete, Firestore and timeout errors are all handled, logged with context, and explained to users in Italian.
Under the hood: the schedule
Adding a stream
Form
A modal asks for title (140 characters, Twitch's limit), date, time, duration and whether it repeats.Validation
Formats, real dates, in the future but within a year, 30 minutes to 23 hours, category and time zone.Time zone
Local time becomes an ISO 8601 string with the right offset for that date.Confirmation
A summary with Confirm and Cancel, which expires after 30 seconds.Twitch
POST /helix/schedule/segment; overlapping streams get a clear error.Calendar
The event is created and linked to its Twitch segment.
Time zones are where schedules usually break. The input is read as local time in the chosen zone, and the offset is computed for that specific date with Intl.DateTimeFormat, so daylight saving time is always right:
19/09/2025 19:00, Europe/Rome → 2025-09-19T19:00:00+02:00The calendar event gets the title, a description, start and end times with the time zone, and a link to the channel. It stores twitchSegmentId and broadcasterId in its extended properties, and a recurring stream becomes an RRULE, such as RRULE:FREQ=WEEKLY;BYDAY=FR for every Friday.
Viewing the schedule
/schedule is built from Components V2: previous and next month, a refresh that clears the cache, and a close button. Each stream shows its game's box art, title (with a marker for recurring ones), date and relative time, duration and category, plus a menu to remove it or copy its ID.
Component budget
Discord limits
A message holds 5 action rows and about 40 components. A stream costs about 8, so the month is split: the first message keeps 34 for navigation, follow-ups get the full 40.
Caching
TTL
User info for 10 minutes, schedules for 1 minute, categories for 1 hour.
Prefetching
Speed
The months before and after the one on screen load in the background, so navigation feels instant.
Removing a stream
/schedule-remove cleans the calendar first: it looks for the event by twitchSegmentId, or, as a fallback, fetches the segment from Twitch and searches the calendar by time and title. Then it calls DELETE /helix/schedule/segment. If Twitch no longer has the segment but the calendar was cleaned, it still reports success; if the calendar fails, Twitch deletion goes ahead. Nothing blocks, everything is logged.
Keeping two calendars in step
Each calendar event stores its Twitch segment ID in extendedProperties.private.twitchSegmentId. To find an event, the bot first searches by that ID, which is fast and exact and returns the master event of a recurring series. If that fails, it searches within 60 minutes of the stream's time and matches by title. A recurring series keeps the ID on its master event, its instances inherit it, and removing the stream removes the whole series.
/schedule-sync repairs anything that drifted:
- Twitch to Calendar creates the events that are missing, without duplicates, and reports the counts. For the first setup, after calendar problems, or for streams created outside the bot.
- Calendar to Twitch is planned: the infrastructure exists, the logic to create Twitch segments from calendar events is still to come.
- Full sync runs both and reports on everything.
Operations aren't atomic across the two services, by design: Twitch is the master, the calendar follows, and a manual sync can always repair an inconsistency.
The stack
Discord.js
14.14.1
Slash commands, autocomplete and Components V2.
Node.js
16.9+ with ES modules
The runtime, with modern import and export.
Twitch API
Helix, OAuth2
Schedule management, with app and user tokens.
IGDB API
Twitch OAuth2
Game search, collections and platforms.
Google Calendar API
Service account
Event CRUD and RRULE recurrence.
Firebase Firestore
NoSQL
Votes and persistence, with caching and audit fields.
Challenges
Problem
Canonical games in a saga
Fetching every official game in a series meant excluding remasters, ports and non-canonical entries, across thousands of IGDB records.
Solution
A multiquery with membership filtering (type.id === 1 for main games), game_type filters and platform checks, sorted by release date and scored for PC compatibility.
Problem
A reliable calendar sync
Twitch's own calendar sync is unreliable, so consistency between Twitch and Google Calendar was on me.
Solution
Two-way linking through extended properties, fallback matching by time and title, non-blocking sync, and manual sync commands for repairs.
Problem
Discord's component limit
A message holds about 40 components, and a busy month needs many more.
Solution
A component budget per message, automatic splitting into follow-ups, and a first message reserved for navigation.
Problem
Time zones and DST
Every stream crosses two APIs, and an hour off is a missed stream.
Solution
Intl.DateTimeFormat computes the offset for the specific date, and every API call uses ISO 8601 with the offset.
Skills I gained
Discord.js v14 and Components V2
Modern Discord bots
Embed-free messages, interactive components, modals, slash commands, autocomplete and Discord's interaction model.
IGDB
Complex game queries
Multiquery syntax, collections, platform filters and the logic to tell canonical games from the rest.
Twitch Helix
Schedule management
App and user OAuth2, schedule segment CRUD, category search, time zones and rate limits.
Google Calendar
Synchronization
Service accounts, event CRUD, RRULE recurrence, extended properties for linking, and DST-aware time zones.
Firestore
NoSQL and caching
Document CRUD, query design, custom IDs, audit fields, and in-memory caching with TTL and LRU eviction.
Integration architecture
Multi-service sync
Master and follower patterns, two-way linking, error handling across services and keeping data consistent.
Why did you create BotFire?
Several reasons. I prefer custom solutions that fit my needs; I wanted an official, well-made way for people to suggest games; I needed better Twitch schedule management than the official, half-broken sync; and I wanted the community to have easy access to stream information. It's both a community hub and a tool that makes my life as a creator easier.
What makes the game suggestions special?
They use complex IGDB queries to find every official, canonical game in a series. The bot detects sagas, filters out remasters and ports, checks PC compatibility, prevents duplicates and stores everything in Firestore with vote tracking. It even works out what share of a whole saga is playable on PC.
How does the Twitch schedule management work?
Instant create, view and remove operations from Discord. Adding a stream creates the segment on Twitch and syncs it to Google Calendar automatically. The interface uses Components V2, with month navigation, category thumbnails and an action menu for each stream, and it's more reliable than Twitch's own calendar sync.
Why Components V2 instead of embeds?
Better UX and more practical patterns. They look better, feel like modern Discord, and handle interactive pieces like navigation buttons, action menus and dynamic content much more flexibly.
What did you learn building it?
I discovered IGDB and its well-maintained API, learned Twitch's Helix API for schedules and Firebase Firestore for persistence, and went deep on Discord.js v14 with Components V2, the Google Calendar API and multi-service synchronization.
Is the code public?
No. BotFire is fitted to my community's server and my own workflow, with integrations and features built around my specific needs.
What's your favourite feature?
The one I use most is the Twitch schedule: it's directly connected to Twitch and its form is comfortable to use. Instant changes plus the Google Calendar sync make managing my streams much easier than Twitch's own tools.
How long did it take to build?
About a month for the first version. Since then, maintenance means building new tools and fixing, updating and upgrading the existing ones, and I update this page whenever a lot changes.
What would you improve with more time?
I'd make the schedule even friendlier, but Discord Components can only go so far, and Discord's forms aren't very powerful yet. I hope they will be. There's always room to improve the integration architecture and the error handling too.
Does the community use every feature?
Only some people use its full potential: many aren't comfortable with Discord bots and are afraid of messing something up, even though it's friendly and robust. The most popular commands, /prossima-live and /suggerisci-gioco, are used all the time.
Need something like this?
Tell me what it should do, where it runs and when you need it.
More work

- #discord
- #bots
- #api-integration
LegitBot
A Discord bot that announced every diamond donation to the LEGIT clan, with an updated leaderboard.

- #bots
- #telegram
- #api-integration
Tik2Insta
A Telegram bot that turned a TikTok link into an Instagram post, crediting the original creator.

- #web
- #discord
- #bots
Arise Crossover Tools
Live dungeon and event timers for Arise Crossover, fed by a Discord bot that reads the official announcements.