Files
telegram-shop/README.md

334 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Telegram Shop Bot
Телеграм-бот для организации онлайн-продаж через Telegram с поддержкой криптовалют, WireGuard VPN и Tor-прокси для доступа к админ-панели через onion-адрес.
## Возможности
- Каталог товаров с категориями и фильтрацией по локациям
- Покупки с оплатой криптовалютами (BTC, ETH, LTC, USDT, USDC)
- Управление криптокошельками (создание, пополнение, баланс)
- История транзакций и покупок
- SaaS-система с автоматическим расчётом комиссий
- **Мультиязычность (i18n)** — английский, испанский, немецкий с переключением в боте
- Админ-панель на порту 3001 с вкладкой локализации
- Tor-прокси с двумя onion-сервисами (SSH + админка)
- WireGuard VPN для безопасных транзакций
## Быстрый старт (одна команда)
### Требования
- Любое устройство с Docker: x86_64 (PC, сервер) или ARM64 (Orange Pi, Raspberry Pi)
- 512 МБ RAM минимум (Orange Pi Zero 2 поддерживается)
### Установка
```bash
git clone <repo-url> && cd telegram-shop
bash install.sh
```
Скрипт автоматически:
1. Определит архитектуру (x86_64 / ARM64 / ARMv7)
2. Установит Docker если не установлен
3. Создаст `.env` из шаблона
4. Проверит обязательные переменные
5. Соберёт Docker-образ под текущую архитектуру
6. Запустит контейнер и проверит health-check
### Ручная установка
```bash
# 1. Клонировать
git clone <repo-url> && cd telegram-shop
# 2. Создать .env из шаблона
cp .env.example .env
nano .env # заполнить BOT_TOKEN, ADMIN_IDS, ENCRYPTION_KEY
# 3. Собрать и запустить
docker compose up -d --build
# 4. Проверить статус
docker compose ps
curl http://localhost:3001/health
```
## Настройка .env
Скопируйте `.env.example` в `.env` и заполните:
| Переменная | Обязательно | Описание |
|---|---|---|
| `BOT_TOKEN` | ✅ | Токен Telegram бота (@BotFather) |
| `ADMIN_IDS` | ✅ | ID администраторов через запятую |
| `ENCRYPTION_KEY` | ✅ | Ключ шифрования (32 байта hex) |
| `ADMIN_SECRET` | ✅ | Секрет для админ-панели |
| `ADMIN_PORT` | — | Порт админ-панели (по умолчанию 3001) |
| `ADMIN_URL` | — | Полный URL админ-панели (для фото товаров) |
| `SUPER_ADMIN_IDS` | — | ID супер-админов |
| `SUPPORT_LINK` | — | Ссылка на поддержку |
| `DEFAULT_LANGUAGE` | — | Язык по умолчанию (`en`, `es`, `de`; по умолчанию `en`) |
| `SSH_HOST_IP` | — | Куда Tor перенаправляет SSH (по умолчанию host.docker.internal) |
| `SHOP_CONTAINER` | — | Имя контейнера магазина (по умолчанию telegram_shop_prod) |
| `WG_ENABLED` | — | `true` / `false` (по умолчанию `false`) |
| `WG_PRIVATE_KEY` | — | Приватный ключ WireGuard |
| `WG_PUBLIC_KEY` | — | Публичный ключ WireGuard |
| `WG_PRESHARED_KEY` | — | Pre-shared ключ WireGuard |
| `WG_ENDPOINT` | — | Адрес сервера WireGuard |
| `WG_ADDRESS` | — | Адрес интерфейса WireGuard |
| `WG_DNS` | — | DNS для WireGuard |
Генерация ключа шифрования:
```bash
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```
## Tor Proxy
Проект включает Tor-прокси для доступа к SSH и админ-панели через onion-адреса.
### Архитектура
```
Internet → Tor Network → tor-proxy контейнер
├── Onion #1 :22 → хост SSH
└── Onion #2 :80 → telegram_shop_prod:3001
(через Docker сеть tor_proxy_net)
```
### Файлы Tor-прокси
| Файл | Назначение |
|---|---|
| `tor-proxy/Dockerfile` | Alpine + Tor образ |
| `tor-proxy/entrypoint.sh` | Генерация torrc из env vars, валидация, запись onion-адресов |
| `tor-proxy/get-onions.sh` | Скрипт чтения onion-адресов и обновления .env |
| `tor-proxy/hosts/` | Директория для onion-hosts.txt (bind mount) |
### После запуска
Onion-адреса автоматически сохраняются в `tor-proxy/hosts/onion-hosts.txt`. Обновить `.env`:
```bash
./tor-proxy/get-onions.sh
```
Вывод:
```
============================================================
Onion services
============================================================
SSH : xxxxx.onion (port 22 -> host SSH)
Admin : yyyyy.onion (port 80 -> telegram_shop_prod:3001)
============================================================
Usage:
SSH : torify ssh user@xxxxx.onion
Admin : open http://yyyyy.onion in Tor Browser
```
### Переменные Tor
| Переменная | По умолчанию | Описание |
|---|---|---|
| `SSH_HOST_IP` | `host.docker.internal` | Куда Tor перенаправляет SSH |
| `SHOP_CONTAINER` | `telegram_shop_prod` | Контейнер магазина |
| `ADMIN_PORT` | `3001` | Порт админки |
## Поддерживаемые устройства
| Устройство | Архитектура | RAM | Статус |
|---|---|---|---|
| PC / Сервер | x86_64 | ≥ 512 МБ | ✅ |
| Orange Pi Zero 2 | ARM64 (H616) | 512 МБ | ✅ |
| Raspberry Pi 4 | ARM64 | ≥ 1 ГБ | ✅ |
| Raspberry Pi 3 | ARM64 | 1 ГБ | ✅ |
| Raspberry Pi 2 | ARMv7 | 1 ГБ | ✅ |
Docker автоматически собирает нативные модули (`better-sqlite3`, `tiny-secp256k1`) под архитектуру хоста.
## Архитектура Docker
```
┌──────────────────────────────────────────────────────────┐
│ docker-compose │
│ │
│ ┌────────────────────────┐ ┌─────────────────────────┐ │
│ │ telegram_shop_prod │ │ tor-proxy │ │
│ │ (node:22-alpine) │ │ (alpine:3.18 + tor) │ │
│ │ │ │ │ │
│ │ Port 3001 │◄─┤ HiddenService :80 │ │
│ │ Bot + Admin Panel │ │ HiddenService :22 → SSH│ │
│ │ │ │ │ │
│ │ Net: default │ │ Net: default + proxy_net │ │
│ │ + tor_proxy_net │ │ │ │
│ └────────────────────────┘ └─────────────────────────┘ │
│ │ │ │
│ Volumes: Volumes: │
│ db/, uploads/, .env tor_data, hosts/ │
└──────────────────────────────────────────────────────────┘
```
### Сети Docker
| Сеть | Назначение |
|---|---|
| `default` | Внутренняя связь между контейнерами |
| `tor_proxy_net` | Связь tor-proxy ↔ telegram_shop_prod |
## Команды управления
```bash
# Запуск
docker compose up -d
# Пересборка после изменений
docker compose up -d --build
# Логи
docker compose logs -f
# Логи конкретного сервиса
docker compose logs -f tor-proxy
docker compose logs -f telegram_shop_prod
# Стоп
docker compose down
# Рестарт
docker compose restart
# Статус
docker compose ps
# Health-check
curl http://localhost:3001/health
# Onion-адреса
docker exec tor-proxy cat /var/lib/tor/ssh/hostname
docker exec tor-proxy cat /var/lib/tor/admin/hostname
# Обновить .env с onion-адресами
./tor-proxy/get-onions.sh
```
## WireGuard
WireGuard по умолчанию отключен (`WG_ENABLED=false`). Для включения:
1. Установите `WG_ENABLED=true` в `.env`
2. Заполните ключи WireGuard в `.env`
3. Перезапустите: `docker compose restart`
Контейнер требует `NET_ADMIN` и `sysctl net.ipv4.conf.all.src_valid_mark=1` для WireGuard. Эти привилегии заданы в `docker-compose.yml`.
## Мультиязычность (i18n)
Бот поддерживает 3 языка: **🇬🇧 English**, **🇪🇸 Español**, **🇩🇪 Deutsch**.
### Как это работает
- **`/start`** — всегда показывает выбор языка с флагами
- **`/language`** — команда для смены языка в любой момент
- **Профиль** — кнопка «🌐 Change Language» рядом с «Set Location»
- Выбранный язык сохраняется в БД (`users.language`) и используется во всех сообщениях
- Интерполяция: `t('key', { param: value })``{{param}}` в строках
- Fallback: запрошенный язык → English → ключ
### Структура i18n
```
src/i18n/
├── index.js # tForUser(), tForLang(), LANGUAGE_NAMES, AVAILABLE_LANGUAGES
└── locales/
├── en.json # 201 ключ, английский
├── es.json # 201 ключ, испанский
└── de.json # 201 ключ, немецкий
```
### Админ-панель локализации
Вкладка «Локализация» в админ-панели (`/locales`) позволяет просматривать и редактировать все ключи перевода в таблице с сохранением в JSON-файлы.
### Добавление нового языка
1. Создать `src/i18n/locales/<code>.json` по шаблону `en.json`
2. Добавить код в `AVAILABLE_LANGUAGES` и `LANGUAGE_NAMES` в `src/i18n/index.js`
3. Язык автоматически появится в выборе при `/start` и `/language`
## Безопасность
- `.env` монтируется только для чтения (`:ro`)
- Порт 3001 доступен из LAN и через Tor onion
- Onion-адреса сохраняются в volume (персистентность при перезапуске)
- Tor hidden services с валидацией env vars
- Нативные модули компилируются в builder-стейдже
- `devDependencies` не попадают в production-образ
- Тестовые файлы исключены из Docker-образа (`.dockerignore`)
- `node_modules` хоста не попадают в образ (`.dockerignore`)
## Устойчивость к ошибкам
- Бот не крашит контейнер при невалидном `BOT_TOKEN`: 5 попыток с задержкой 5с, затем бот отключается, админка продолжает работать
- Комиссионные кошельки не обязательны для старта: при отсутствии логируется предупреждение
- При потере связи с Telegram API: polling ошибки логируются, процесс продолжает работать
## Структура проекта
```
├── src/
│ ├── admin/ # Админ-панель (Express)
│ │ ├── routes/ # Роуты админ-панели (вкл. /locales для i18n)
│ │ ├── views/ # Шаблоны HTML
│ │ ├── public/ # Статические файлы (CSS)
│ │ ├── auth.js # Авторизация
│ │ └── server.js # Express-сервер
│ ├── config/ # Конфигурация (БД, крипто)
│ ├── context/ # Контекст и состояния бота
│ ├── handlers/ # Обработчики команд
│ │ ├── adminHandlers/ # Обработчики админа
│ │ └── userHandlers/ # Обработчики пользователя
│ ├── i18n/ # Интернационализация
│ │ ├── index.js # tForUser(), tForLang(), LANGUAGE_NAMES
│ │ └── locales/ # en.json, es.json, de.json (201 ключ)
│ ├── middleware/ # Промежуточные обработчики
│ ├── migrations/ # Миграции БД
│ ├── models/ # Модели данных
│ ├── router/ # Роутинг Express
│ ├── services/ # Бизнес-логика
│ ├── utils/ # Утилиты (логирование, валидация, ошибки)
│ └── index.js # Точка входа
├── tor-proxy/ # Tor прокси для SSH и админки
│ ├── Dockerfile # Alpine + Tor образ
│ ├── entrypoint.sh # Генерация torrc, валидация env vars
│ ├── get-onions.sh # Скрипт обновления .env с onion-адресами
│ └── hosts/ # Директория для onion-hosts.txt
├── wg/ # WireGuard конфигурация
│ └── start.sh # Скрипт запуска контейнера
├── db/ # SQLite база данных (volume)
├── uploads/ # Загруженные фото (volume)
├── Dockerfile # Multi-stage сборка магазина
├── docker-compose.yml # Конфигурация обоих контейнеров
├── install.sh # Установщик (POSIX sh)
├── .dockerignore # Исключения из образа
├── .env.example # Шаблон переменных
└── package.json
```
## Разработка
```bash
# Установка зависимостей
npm install
# Запуск в режиме разработки
npm run dev
# Тесты
npm test
```
## Лицензия
MIT