Skip to content

Latest commit

 

History

History
128 lines (84 loc) · 8.05 KB

README.md

File metadata and controls

128 lines (84 loc) · 8.05 KB

Deko Voice Bot

Telegram-бот для отправки реплик deko через inline-режим. Пользователи могут искать реплики, добавлять их в избранное, смотреть или отключать личную аналитику и поддерживать бота через Telegram Stars. Администратор управляет каталогом, статистикой и резервными копиями прямо в Telegram.

Боевой бот: https://t.me/dekoquotes_bot

Устройство проекта

Проверки надёжности и порядок восстановления: Operations checklist.

Это одно Node.js-приложение на TypeScript:

  • grammY обрабатывает polling при локальной разработке и webhook в production;
  • PostgreSQL и Drizzle ORM хранят каталог, пользователей, избранное и платежи;
  • Fluent содержит весь пользовательский текст;
  • FFmpeg конвертирует присланные MP3 в OGG/Opus;
  • pg_dump и pg_restore создают и восстанавливают зашифрованные копии базы.

Сессии меню и диалогов хранятся в памяти до 24 часов и сбрасываются при перезапуске. Приложение рассчитано на одну реплику процесса.

Основные каталоги:

drizzle/       схема, запросы и миграции PostgreSQL
locales/       Fluent-локализация
scripts/       аварийные локальные инструменты
src/backup/    создание, проверка и восстановление копий
src/bot/       Telegram-команды, меню и диалоги
src/main.ts    основной процесс бота
src/backup-cron.ts  короткоживущий процесс ежедневного бэкапа

Локальный запуск

Требуются Node.js 24, pnpm, PostgreSQL, FFmpeg и PostgreSQL client tools.

pnpm install
cp .env.example .env
pnpm db:migrate
pnpm dev

Для локальной разработки обычно используются BOT_MODE=polling и отдельный тестовый Telegram-бот. В production используется BOT_MODE=webhook.

Переменные окружения

Обязательные для основного процесса:

  • BOT_TOKEN — токен Telegram-бота;
  • BOT_MODE — polling или webhook;
  • DATABASE_URL — строка подключения PostgreSQL;
  • BACKUP_ENCRYPTION_KEY — 32 байта в base64;
  • для webhook также BOT_WEBHOOK и BOT_WEBHOOK_SECRET.

ADMIN_IDS — JSON-массив Telegram ID администраторов. Остальные настройки и значения по умолчанию перечислены в .env.example.

Ключ для резервных копий создаётся так:

openssl rand -base64 32

Храните его отдельно от самих копий: без ключа восстановление невозможно.

Railway

Основной сервис собирается из корневого Dockerfile. Миграции запускаются Railway pre-deploy command:

pnpm db:migrate

Стандартная команда запуска контейнера — node ./dist/main.mjs.

Для ежедневного бэкапа создайте второй Railway Cron service из того же репозитория и Dockerfile:

  • cron schedule: 0 21 * * * — это 00:00 по Минску (UTC+3);
  • start command: node ./dist/backup-cron.mjs;
  • переменные: BOT_TOKEN, DATABASE_URL, BACKUP_ENCRYPTION_KEY, BACKUP_CHAT_ID и настройки логов.

BACKUP_CHAT_ID должен указывать на закрытый канал, куда бот может отправлять документы. Если переменная отсутствует, cron пишет в лог, что бэкап отключён, и завершается с кодом 0. При ошибке выполняются три попытки, после чего бот старается отправить в канал текстовое уведомление и завершает процесс с ненулевым кодом.

Резервное копирование и восстановление

Команда /export создаёт зашифрованный файл .dump.enc и отправляет его администратору. /import принимает такой файл, проверяет формат и схему, просит подтверждение, отправляет аварийную копию текущей базы и только затем восстанавливает данные. Во время restore новые обращения к базе временно блокируются.

Если восстановление или проверка базы завершились ошибкой, бот сохраняет блокировку до проверки и восстановления через инструменты PostgreSQL. Перезапуск снимает эту блокировку: выполняйте его только после проверки базы. Порядок действий и тестовое восстановление описаны в Operations checklist.

Старые plaintext-дампы можно зашифровать или расшифровать локально:

pnpm backup:crypto encrypt backup.dump backup.dump.enc
pnpm backup:crypto decrypt backup.dump.enc backup.dump

Первый деплой после удаления API-сервиса

Миграция 0018_analytics_enabled переименовывает и инвертирует поле аналитики, а 0017_simplify_runtime удаляет старые runtime-таблицы. Старый процесс не должен работать одновременно с этими миграциями.

Безопасный порядок для этого единственного перехода:

  1. Выполнить /maintenance и /export на старой версии.
  2. Остановить старый bot deployment, чтобы он больше не обращался к базе.
  3. Развернуть новую версию с Railway pre-deploy command pnpm db:migrate.
  4. Проверить /voices, inline-отправку, /mydata, /export и затем выключить /maintenance.
  5. После успешной проверки удалить старые Railway API и Redis services.

Обычные последующие деплои снова используют стандартный pre-deploy без этой ручной остановки.

Управление репликами

/voices открывает единое меню: добавление реплики, список с пагинацией и действия над выбранной репликой. Можно изменить название, ID, файл или удалить запись. Добавление идёт по шагам: название → ID → MP3. /newvoices сохранена как скрытая команда-алиас и не публикуется через /setcommands.

FFmpeg проверяется только при запуске добавления или замены файла. pg_dump и pg_restore вызываются только командами и cron-задачей, которым они нужны.

Проверки

pnpm typecheck
pnpm lint
pnpm test
pnpm build

Лицензия

MIT — см. LICENSE.