Skip to content

Repository files navigation

Логотип TNVED_BOT

TNVED_BOT

CI Python 3.12 License: MIT Coverage 87%

Telegram-бот, который подбирает 10-значный код ТН ВЭД ЕАЭС по текстовому описанию товара или по фотографии. Работает локально на Windows, обращается к ИИ через CLI claude -p.

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

⚠️ Бот носит справочный характер. Окончательное решение о классификации принимает декларант; для официальной позиции — предварительное решение ФТС.

Что умеет

Возможность Как работает
Код по описанию Два обращения к ИИ: перевод запроса на язык справочника, затем выбор из кандидатов
Код по фотографии Модель описывает товар, вы подтверждаете описание, дальше обычный пайплайн
Уточняющие вопросы Кнопками, до 3 раундов; при неуверенности бот спрашивает, а не гадает
Пошлина и НДС У основного кода и у каждой альтернативы; ставка — из локального справочника
Разрешительные документы Перечень и техрегламенты по коду, с разделением обязательных и условных
Маркировка «Честный знак» Локальная таблица товарных групп; ответ даётся всегда, в том числе отрицательный
Ставка ниже рядом Соседние коды той же позиции с меньшей пошлиной — как повод перепроверить классификацию
Обучение на ошибках 👎 → присылаете верный код → бот учитывает его при похожих запросах
Управление доступом Whitelist в БД + приглашения ссылкой в один клик
Рассылка /broadcast с предпросмотром и подтверждением
Автозапуск Задача планировщика при входе в систему, без консольного окна
Автоудаление фото 48 часов, включая догоняющую очистку после простоя компьютера

Откуда берутся пошлина и документы

Ставка пошлины — из загруженного справочника ТН ВЭД. НДС, перечень разрешительных документов, техрегламенты и обезличенные примеры деклараций — со страницы кода на ifcg.ru; ответ кешируется в БД на 30 дней, поэтому за одним и тем же кодом бот ходит в сеть не чаще раза в месяц. Это единственный выход бота в интернет помимо Telegram, и он отключается одной переменной REFERENCE_ENABLED=false — без него бот работает как раньше, только без справки.

alta.ru отдаёт в HTML лишь пошлину и НДС, остальное подгружает скриптами, поэтому используется как ссылка «проверить код», а не как источник данных.

Перечни маркировки правятся в src/tnved_bot/customs/marking.csv — обычным текстом, без изменения кода. Они утверждаются постановлениями и меняются несколько раз в год, поэтому бот говорит «вероятно, проверьте по перечню», а не «маркировка нужна».

Требования

  • Windows 10/11, Python 3.12 (проверено на 3.12.10)
  • Claude Code CLI в PATH и авторизованный (claude --version)
  • Токен бота от @BotFather
  • Файл справочника ТН ВЭД ЕАЭС (XLSX или CSV) — см. ниже

Установка

cd c:\Claude\TNVED_BOT

py -3.12 -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
pip install -e .

Copy-Item .env.example .env
# заполнить BOT_TOKEN и ADMIN_USER_IDS

ADMIN_USER_IDS — числовые Telegram ID администраторов через запятую, без пробелов. Свой ID можно узнать, написав боту: он вернёт его в сообщении об отказе в доступе.

Загрузка справочника

Скачайте актуальную выгрузку и импортируйте:

Invoke-WebRequest -Uri 'https://www.tws.by/tws/tnved/download/excel' `
  -OutFile "data\nomenclature\tnved_$(Get-Date -Format 'yyyy-MM-dd').xlsx"

python scripts\import_nomenclature.py "data\nomenclature\tnved_$(Get-Date -Format 'yyyy-MM-dd').xlsx"

Импорт атомарен: пока новая версия не записана целиком, активной остаётся прежняя. Откат — --rollback, список версий — --list. Разбор источника и его ограничения: docs/research/nomenclature-sources.md.

До загрузки справочника бот стартует, но на запросы отвечает «справочник не загружен».

Запуск

python -m tnved_bot          # вручную, Ctrl+C для остановки

Автозапуск при включении компьютера

powershell -ExecutionPolicy Bypass -File scripts\install_autostart.ps1

Создаёт задачу TNVED_BOT: запуск при входе в систему, без ограничения времени работы. Окно не появляется вовсе: задача вызывает wscript.exe с scripts\run_hidden.vbs, а тот запускает надзорный скрипт с невидимым окном. Через powershell -WindowStyle Hidden консоль всё равно создавалась и мелькала при входе в систему.

Перезапуск после падения делает надзорный цикл в scripts\run_bot.ps1 — проверено, что встроенный механизм планировщика в этом сценарии не срабатывает.

Start-ScheduledTask -TaskName TNVED_BOT                  # запустить сейчас
powershell -File scripts\stop_bot.ps1                    # остановить
powershell -File scripts\uninstall_autostart.ps1         # убрать автозапуск
python scripts\smoke_check.py                            # проверить состояние

Команды бота

Команда Что делает
/start Приветствие и краткая инструкция
/start <код> Активировать приглашение
/help Как описывать товар, чтобы код был точным
/code <10 цифр> Официальное наименование кода из справочника
/cancel Прервать текущие уточнения
/forget Немедленно удалить свои фото и диалоги
/version Версия бота и справочника

Под ответом — кнопки 👍 / 👎. «Неверно» не уходит в пустоту: бот спросит верный код и учтёт его при похожих запросах.

Команды видны в меню Telegram (кнопка слева от поля ввода) — бот публикует их при старте. Администраторам показывается расширенный набор, обычным пользователям — только их шесть команд.

Панель администратора

/admin открывает панель на кнопках:

🛠 Панель администратора

Пользователей с доступом: 3
Невостребованных приглашений: 1
Запросов за сутки: 12

[ 👥 Пользователи ]  [ 🎟 Приглашения ]
[ ➕ Новое приглашение ]
[ 📊 Статистика ]  [ 🩺 Состояние ]
[ 📝 Исправления ]  [ 📣 Рассылка ]
  • Пользователи — список с заметками и датой последнего визита; кнопка напротив каждого отзывает доступ (с подтверждением). Администратора из .env отозвать нельзя — это аварийный вход.
  • Приглашения — невостребованные коды с сроком действия; лишние отзываются кнопкой. Выданный и забытый код остаётся открытой дверью до истечения суток.
  • Новое приглашение — код в один клик и готовое сообщение со ссылкой для пересылки.
  • Исправления — что пользователи поправили после 👎 и какие коды бот запомнил.
  • Рассылка — сообщение всем пользователям: предпросмотр, подтверждение, отчёт о доставке. Есть готовый текст об обновлении.

Те же действия доступны командами, когда ID уже известен:

Команда Что делает
/admin Панель на кнопках
/users Список пользователей с заметками
/adduser <id> [заметка] Выдать доступ без перезапуска
/deluser <id> Отозвать доступ, закрыть активные диалоги
/invite [заметка] Приглашение ссылкой на 24 часа
/broadcast Рассылка всем пользователям
/corrections Исправления, присланные пользователями
/health Справочник, claude, диск, очередь
/stats Статистика за сутки
/reload_db Сведения об активной версии справочника

Как пригласить человека

Спрашивать у него Telegram ID неудобно — он обычно не знает, где его взять. Нажмите ➕ Новое приглашение в панели (или /invite Петров). Бот пришлёт два сообщения: код со сроком действия — вам, и готовое приглашение — для пересылки:

Приглашение в бота подбора кодов ТН ВЭД ЕАЭС.

👉 Открыть бота и войти

Нажмите ссылку, затем кнопку «Запустить» — код подставится сам.

Ссылка вида https://t.me/<бот>?start=TNVED-7K2M-9XQP подставляет код за человека: вводить его руками больше не нужно. Приглашение одноразовое, живёт 24 часа, после активации человек появляется в списке пользователей.

Если код неверный

Нажмите 👎 под ответом — бот попросит прислать верный код. Пара «запрос → код» сохраняется и при похожем запросе попадает и в подсказку модели, и в список кандидатов. Код проверяется по справочнику до сохранения: исправление с несуществующим кодом бот не примет. Не знаете верный код — просто напишите новый запрос, ничего делать не нужно.

Приватность

  • Доступ только по whitelist: администраторы из .env, остальные — в таблице allowed_users.
  • Наружу уходит только код ТН ВЭД — за справкой о пошлине и документах. Текст запроса, описание товара и фотографии не покидают компьютер.
  • Фотографии хранятся локально не более 48 часов, затем файлы удаляются с диска.
  • При сохранении фото пересохраняется в JPEG — это уничтожает EXIF, включая геолокацию съёмки.
  • Фото не передаются никуда, кроме локального процесса claude.
  • Полные тексты запросов в журнал не пишутся — только SHA-256.
  • /forget удаляет данные пользователя немедленно, не дожидаясь TTL.

Разработка

pytest -q                                   # все тесты
pytest tests\test_sanitize.py -v            # защита от инъекций
ruff check src tests scripts
ruff format src tests scripts
mypy src
pytest -q --cov --cov-report=term-missing   # покрытие: 87 %, порог CI — 70 %

Те же четыре проверки на каждый push и pull request гоняет GitHub Actions на windows-latest — на той платформе, для которой бот написан. Секреты CI не нужны: тесты не ходят в сеть и не читают .env.

Диагностика

Симптом Причина и решение
Бот не отвечает python scripts\smoke_check.py; смотреть logs\bot.log
«Справочник не загружен» Выполнить scripts\import_nomenclature.py
«ИИ временно недоступен» Проверить claude --version и авторизацию Claude Code
Ответ идёт 15–20 секунд Нормально: два обращения к ИИ. Норматив ТЗ — до 60 с
Бот отвечает дважды Запущено два экземпляра: scripts\stop_bot.ps1, затем один запуск
Не стартует после перезагрузки Get-ScheduledTask -TaskName TNVED_BOT; смотреть logs\stdout.log
«Диалог уже закрыт» Сессия истекла (30 мин) — отправьте запрос заново
Скрипт .ps1 падает на разборе Файл сохранён без BOM: PowerShell 5.1 читает .ps1 как ANSI
«Справка недоступна» в ответе Нет сети или изменилась вёрстка источника; код и ставка из справочника показываются всё равно
Ставки устарели REFERENCE_TTL_DAYS или сброс кеша: DELETE FROM code_reference

Лицензия

MIT — © 2026 Alex Korytchenko (@AlexKorWeb).

Справочник ТН ВЭД ЕАЭС в репозиторий не входит: он загружается отдельно, из официального источника, скриптом scripts/import_nomenclature.py. Перечни маркировки в src/tnved_bot/customs/marking.csv носят справочный характер и не заменяют действующие постановления.

About

Telegram-бот подбора кодов ТН ВЭД ЕАЭС по описанию или фото. ИИ выбирает только из локального официального справочника — выдуманный код не может попасть в ответ. Python 3.12, aiogram 3, SQLite FTS5, claude -p

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages