Botxona

6 стандартных правил — каким должен быть код бота

Botxona автоматически проверяет каждого загруженного бота по 6 стандартам (где смотреть результат). Эти правила — не формальность: они нужны, чтобы ваш бот мог засыпать и просыпаться, чтобы работали резервные копии и аналитика. Ниже по каждому: что, зачем, как проверяется и готовый код исправления.

1. Токен только из BOT_TOKEN

Что: токен бота не должен быть прописан в коде в открытом виде — только читаться из переменной окружения BOT_TOKEN.

Зачем: если токен зашит в код, для его смены придётся заново загружать код; кроме того, если вы поделитесь кодом с кем-то, токен тоже утечёт.

Как проверяется: система ищет в коде строки, похожие на настоящий токен вида число:буквы-символы. Если находит — 🔴 (fail).

Исправление:

import os
BOT_TOKEN = os.getenv("BOT_TOKEN")
token := os.Getenv("BOT_TOKEN")
const token = process.env.BOT_TOKEN

Типичная ошибка: вписать токен в код для удобства во время тестов и забыть его там. Перед загрузкой проверьте поиском (Ctrl+F).

2. Подключение к Telegram API — автоматически

Что: для этого правила ничего делать не нужно. Как бы бот ни подключался к Telegram (даже напрямую к api.telegram.org с настройками библиотеки по умолчанию), запросы автоматически проходят через прокси платформы.

Зачем: аналитика Botxona (DAU, ошибки, время ответа), сон/пробуждение и тестовый запуск опираются именно на запросы, прошедшие через этот прокси, — без изменений в коде. Кроме того, прокси обеспечивает слой изоляции и безопасности.

Как проверяется: проверка всегда 🟢 — «Автоматически: как бы бот ни подключался к Telegram, запросы проходят через платформу».

Код: настроек библиотеки по умолчанию достаточно, специальный адрес API не нужен:

from aiogram import Bot
bot = Bot(token=BOT_TOKEN)
import { Bot } from "grammy"
const bot = new Bot(process.env.BOT_TOKEN)
b, err := bot.New(os.Getenv("BOT_TOKEN"))

Примечание: платформа также передаёт переменную TELEGRAM_API_URL — если ваш код уже её использует (например, через apiRoot, base_url, WithServerURL), всё продолжит работать. Но это необязательно: в новом коде настраивать её не нужно.

3. Библиотеки с точными версиями

Что: в requirements.txt для Python, в package.json для Node.js и в go.mod (+ go.sum) для Go все библиотеки должны быть указаны с точной версией (например aiogram==3.13.1, а не просто aiogram).

Зачем: библиотека без версии со временем обновится и может сломать код — сегодня бот работает, а завтра перестаёт из-за несовместимых версий.

Исправление:

aiogram==3.13.1
python-dotenv==1.0.1
{
  "dependencies": {
    "grammy": "^1.30.0"
  }
}
module mening-botim

go 1.27

require github.com/go-telegram/bot v1.27.0

В Go в архив нужно добавить и go.sum (если его нет — предупреждение, сборка сама запускает go mod tidy).

Типичная ошибка: запустить pip freeze > requirements.txt не в виртуальном окружении проекта, а в глобальном Python и добавить десятки ненужных библиотек.

4. Явная точка входа

Что: система должна знать, какой файл запускать. Стандартные кандидаты для Python: main.py, bot.py, app.py. Для Node.js — скрипт "start" или поле main в package.json. Для Go — пакет main в корне проекта (main.go) или ровно одна папка cmd/<имя>/.

Зачем: без явной точки входа системе приходится угадывать, какой файл запускать, — если кандидатов несколько, может быть выбран не тот.

Исправление — для ясности добавьте botxona.yaml:

runtime: python
entry: main.py
runtime: node
start: node src/index.js
runtime: go
entry: ./cmd/bot

Подробная схема: botxona.yaml.

5. Постоянные данные только в DATA_DIR

Что: все файлы, которые сохраняет бот (база SQLite, выгрузки Excel, изображения и т. д.), должны находиться в папке, на которую указывает переменная окружения DATA_DIR.

Зачем: при перезапуске контейнера бота (повторный деплой, рестарт) файловая система за пределами DATA_DIR очищается — сохраняется только DATA_DIR, и только она ежедневно попадает в резервную копию (Данные и резервные копии).

Исправление:

import os
DATA_DIR = os.getenv("DATA_DIR", "./data")
os.makedirs(DATA_DIR, exist_ok=True)
db_path = os.path.join(DATA_DIR, "bot.sqlite3")
const DATA_DIR = process.env.DATA_DIR || "./data"
const dbPath = require("path").join(DATA_DIR, "bot.sqlite3")
dataDir := os.Getenv("DATA_DIR")
if dataDir == "" {
    dataDir = "./data"
}
os.MkdirAll(dataDir, 0o755)
dbPath := filepath.Join(dataDir, "bot.sqlite3")

Если в Go нужен SQLite, используйте modernc.org/sqlite без cgo: бот собирается в статический бинарник с CGO_ENABLED=0, поэтому github.com/mattn/go-sqlite3 не работает.

Типичная ошибка: писать в текущую папку (./) или в сам проект (., а не ./data) — во время сборки это работает, но в продакшн-контейнере файловая система разрешает запись только в DATA_DIR.

6. Настройки в .env.example

Что: все переменные окружения, которые ожидает ваш бот (ADMIN_IDS, CHANNEL_ID и т. д.), должны быть перечислены в файле .env.example с комментарием, но без значений.

Зачем: на основе этого списка панель Botxona показывает вам форму для ввода настроек — без .env.example переменные придётся добавлять вручную.

Исправление:

# Telegram ID админов, через запятую
ADMIN_IDS=

# ID канала (для отслеживания роста канала)
CHANNEL_ID=

Переменные, которые платформа задаёт сама, — BOT_TOKEN, TELEGRAM_API_URL, DATA_DIR, TZ, PORT — добавлять в .env.example не нужно: они передаются автоматически (Переменные окружения).

Следующий шаг

Загрузите код и посмотрите результат: Как читать результат проверки. Если не уверены в формате, промпт «Стандартизация» из библиотеки промптов автоматически адаптирует существующий код.