Локальный Discord-бот для уведомлений о старте стрима на Twitch. Работает через slash-команды Discord и polling Twitch Helix API, поэтому его можно запускать дома или на арендованном VPS без публичного webhook.
/twitch-subscribe streamer:<логин>- подписать текущий Discord-канал на Twitch-канал./twitch-subscribe streamer:<логин> discord_channel:<канал>- подписать выбранный канал./twitch-subscribe streamer:<логин> category:<категории>- получать уведомления только если стрим запущен в одной из категорий через запятую./twitch-subscribe streamer:<логин> exclude_category:<категории>- получать уведомления по всем категориям, кроме указанных через запятую./twitch-unsubscribe streamer:<логин>- удалить подписку./twitch-edit streamer:<логин>- редактировать существующую подписку в текущем канале./twitch-edit streamer:<логин> category:<категории>- заменить список разрешенных категорий./twitch-edit streamer:<логин> exclude_category:<категории>- заменить список исключенных категорий./twitch-edit streamer:<логин> clear_filters:true- убрать фильтры категорий./twitch-edit streamer:<логин> new_discord_channel:<канал>- перенести подписку в другой канал./twitch-edit streamer:<логин> notification_mode:<text|embed|both>- задать стиль уведомления для подписки./twitch-edit streamer:<логин> notify_category_changes:false- отключить уведомления при смене категории для подписки./twitch-list- показать подписки сервера./twitch-help- показать список команд./twitch-message show- показать шаблон уведомления./twitch-message set template:<текст>- задать свой текст./twitch-message reset- вернуть стандартный текст./twitch-message set template:<текст> streamer:<логин>- задать шаблон только для подписки в текущем канале./twitch-message show streamer:<логин>- показать шаблон конкретной подписки./twitch-message reset streamer:<логин>- сбросить шаблон конкретной подписки к серверному./twitch-language show- показать язык сервера./twitch-language set language:<ru|en>- выбрать язык ответов бота./twitch-stats- показать мини-статистику уведомлений сервера./twitch-test streamer:<логин>- отправить тестовое уведомление в текущий канал./twitch-test streamer:<логин> ping:true- отправить тест с реальным@everyone/@here./twitch-style show- показать стиль уведомлений сервера./twitch-style set notification_mode:<text|embed|both>- выбрать стиль уведомлений./twitch-style category_changes enabled:false- отключить уведомления при смене категории на сервере.
Поддерживаемые плейсхолдеры в шаблоне:
{streamer} {title} {game} {url} {viewers} {started_at} {channel}
Для переноса строки в slash-команде используйте \n:
@everyone {streamer} вышел в эфир!\nНазвание: {title}\nКатегория: {game}\n{url}
Пример:
{streamer} вышел в эфир!
{title}
Категория: {game}
{url}
Пример подписки только на Beat Saber и Synth Riders:
/twitch-subscribe streamer:somechannel category:Beat Saber, Synth Riders discord_channel:#streams
Если стример запустит Minecraft или другую категорию, уведомление по такой подписке отправлено не будет.
Пример двух каналов для одного стримера:
/twitch-subscribe streamer:somechannel category:Beat Saber discord_channel:#beat-saber
/twitch-subscribe streamer:somechannel exclude_category:Beat Saber, Synth Riders discord_channel:#other-streams
По умолчанию шаблон задается на весь сервер:
/twitch-message set template:@everyone {streamer} в эфире: {title} {url}
Можно задать отдельный шаблон для конкретной подписки в текущем канале:
/twitch-message set streamer:somechannel template:@BeatSaberPing {streamer} играет в {game}: {url}
Если подписка находится в другом канале, добавьте discord_channel.
Бот поддерживает ответы на русском и английском:
/twitch-language set language:en
/twitch-language set language:ru
Команда /twitch-help показывает справку на выбранном языке.
/twitch-stats показывает, сколько уведомлений бот отправил на сервере, топ стримеров и топ категорий. Статистика начинает копиться после версии с этой командой.
По умолчанию бот отправляет обычный текстовый шаблон. Можно включить embed-карточку:
/twitch-style set notification_mode:embed
Или два сообщения сразу: сначала текстовый шаблон, потом embed-карточка с названием стрима, категорией, зрителями и превью:
/twitch-style set notification_mode:both
Для одной конкретной подписки:
/twitch-edit streamer:somechannel notification_mode:both
Embed-карточка показывает стримера крупным заголовком, кликабельное название стрима, категорию, зрителей, превью и кнопку Смотреть на Twitch.
Уведомления при смене категории можно отключить на весь сервер:
/twitch-style category_changes enabled:false
Или только на одну подписку:
/twitch-edit streamer:somechannel notify_category_changes:false
Бот не отправляет одно и то же уведомление повторно после рестарта. Если стример завершил стрим и перезапустил его в той же категории в течение 10 минут, уведомление не отправится повторно.
Если категория изменилась во время стрима или новый стрим запущен уже в другой категории, бот отправит новое уведомление в подходящие подписки.
Команда отправляет пример уведомления без ожидания реального стрима:
/twitch-test streamer:somechannel
Если в выбранном канале есть подписка на этого стримера, бот использует шаблон этой подписки. Если личного шаблона нет, используется серверный шаблон.
По умолчанию @everyone и @here в тесте не пингуют людей. Для проверки реального пинга:
/twitch-test streamer:somechannel ping:true
- Установите Node.js 20 или новее.
- Создайте Discord-приложение и бота в Discord Developer Portal.
- Пригласите бота на сервер со scopes
botиapplications.commands; из прав минимум нужныSend MessagesиView Channels. - Создайте Twitch-приложение в Twitch Developer Console и получите
Client IDиClient Secret. - Установите зависимости:
npm install- Создайте
.envна основе.env.example. - Зарегистрируйте slash-команды:
npm run deploy-commandsВо время разработки укажите DISCORD_GUILD_ID, чтобы команды появились на одном сервере почти сразу. Без него команды регистрируются глобально и могут появляться дольше.
- Запустите бота:
npm start- Создайте
.envна основе.env.example. - Соберите и запустите контейнер:
docker compose up -d --build- Зарегистрируйте slash-команды (один раз после первого запуска или при изменении команд):
docker compose run --rm notiffio npm run deploy-commands- Просмотр логов:
docker compose logs -f notiffiodocker-compose.yml монтирует локальную папку ./data в контейнер (/app/data), поэтому подписки и статистика сохраняются между перезапусками.
Сервис теперь публикует runtime-статус в data/bot-data.json (поля runtime.lastPollStartedAt, runtime.lastPollSucceededAt, runtime.lastPollFailedAt, runtime.lastPollError).
В Docker-образ добавлен HEALTHCHECK, который проверяет:
- что был хотя бы один успешный polling Twitch;
- что с момента последнего успешного polling прошло не больше порога
HEALTHCHECK_MAX_POLL_LAG_SECONDS; - что последняя попытка polling не завершилась ошибкой после последнего успеха.
Проверка статуса:
docker inspect --format='{{.State.Health.Status}}' notiffio
docker inspect --format='{{json .State.Health.Log}}' notiffio | jqПо умолчанию в compose установлен порог HEALTHCHECK_MAX_POLL_LAG_SECONDS=240 (4 минуты).
В репозитории добавлен workflow .github/workflows/docker-image.yml, который:
- собирает multi-arch образ (
linux/amd64,linux/arm64); - публикует образ в GitHub Container Registry:
ghcr.io/<owner>/bee-notiffio; - на push в ветки обновляет branch-теги и тег
devдля default-ветки; - на PR собирает и (для PR из этого же репозитория) публикует
pr-<номер>теги; - на push тега формата
vX.Y.Zпубликует версии (X.Y.Z,X.Y,X) иlatest.
Пример запуска из GHCR:
docker run -d --name notiffio --restart unless-stopped --env-file .env -v $(pwd)/data:/app/data ghcr.io/<owner>/bee-notiffio:latestБот регулярно опрашивает Twitch Get Streams по всем подписанным логинам. Если канал стал live и этот stream id еще не был отправлен, бот пишет уведомление в подписанный Discord-канал. Когда стрим заканчивается, состояние сбрасывается, и следующий запуск стрима снова отправит уведомление.
Данные хранятся в JSON-файле data/bot-data.json, путь можно поменять через DATA_FILE.
Минимальный вариант через pm2:
npm install
npm run deploy-commands
npm install -g pm2
pm2 start src/bot.js --name notiffio-local
pm2 saveДля systemd лучше запускать npm start из папки проекта и хранить .env рядом с проектом или в environment-файле сервиса.
- Discord Application Commands: https://docs.discord.com/developers/docs/interactions/slash-commands
- Twitch Client Credentials Flow: https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/
- Twitch Get Streams API: https://dev.twitch.tv/docs/api/reference/#get-streams