diff --git a/IDEA.MD b/IDEA.MD
index f28bc36..5fc5a81 100644
--- a/IDEA.MD
+++ b/IDEA.MD
@@ -24,7 +24,7 @@ Telegram-бот, который по запросу пользователя г
- **Подписка** — при входе показывает активный период и остаток дней; inline-кнопка продления сразу открывает Stars-инвойс (`/balance`, `/subscribe`).
- **Помощь** — справка и навигация по её разделам (`/help`).
-`/start` показывает ровно одно welcome-сообщение без автоматического вызова помощи. При входе в любой режим показывается короткий onboarding. Главное меню содержит только четыре пользовательских режима; внутри каждого режима клавиатура состоит из кнопки «Главное меню». Команды `/training`, `/generate`, `/subscription`, `/help` доступны из любого режима; профильные действия — только в своём режиме.
+`/start` показывает ровно одно welcome-сообщение без автоматического вызова помощи. При входе в любой режим показывается короткий onboarding. Главное меню содержит только четыре пользовательских режима; внутри каждого режима клавиатура состоит из кнопки «Главное меню». В справке `/help` кнопки разделов расположены последовательно, переносятся целиком по мере заполнения строки; отдельной кнопки «В меню» нет, из раздела доступны остальные разделы. Команды `/training`, `/generate`, `/subscription`, `/help` доступны из любого режима; профильные действия — только в своём режиме.
## Первая версия
- Принимать запрос обычным сообщением.
@@ -104,9 +104,9 @@ Telegram-бот, который по запросу пользователя г
- [x] Исправлен баг: `_send_idea` была потеряна в коммите про подписку — `/idea` падал с `NameError`
- [x] Реальная оплата Stars: `sendInvoice` (XTR) → `pre_checkout_query` → `successful_payment`; подписка активируется только после оплаты, `telegram_payment_charge_id` защищает от двойного начисления
- [x] В `DEPLOY_ENV=development` после обычного сообщения об инвойсе отдельным сообщением доступна кнопка «🧪 Оплатил (dev)»; callback ограничен пользователем инвойса, а все dev-ветви fail-closed выключены вне development
-- Версия разработки: `0.1.0+59`
+- Версия разработки: `0.1.0+60`
- [x] Статус долгой операции стримится живым драфтом `sendMessageDraft` в приватном чате и каждые 3–8 сек меняет случайную фразу из пула операции (`activity_phrases.py`); в группах и топиках работает прежний `edit_text`
-- [x] Справка бота (`/help`) описывает `/balance` и `/subscribe`
+- [x] Справка `/help`: кнопки разделов идут последовательно и переносятся на новую строку целиком; отдельной кнопки «В меню» нет, из раздела доступны остальные разделы
- [x] Проект Gitea «Social Post Writer Bot Roadmap» с задачами (выполненные — в «Готово», будущие — в Backlog)
- [x] Ротационный файл лога `/app/data/bot.log` (5 MiB × 3 архива) на persistent volume
- [x] Кнопка «✍️ Придумать пост» и `/post`: самостоятельный пост по обученному профилю, гейт по `users.is_trained`
diff --git a/README.md b/README.md
index e14e127..37696ba 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ Telegram-бот для генерации постов для соцсетей.
- [Деплой и конфигурация](#деплой-и-конфигурация)
- [Тесты](#тесты)
-Версия разработки: `0.1.0+59`.
+Версия разработки: `0.1.0+60`.
---
@@ -60,6 +60,12 @@ onboarding. В «Подписке» сразу отображаются тип
1. Отправляет ровно одно `WELCOME_RICH_HTML` с примерами и описанием режимов.
2. Показывает клавиатуру главного меню; справка открывается отдельно кнопкой или командой `/help`.
+### Справка (`/help`)
+
+Меню разделов и страницы справки используют последовательную раскладку inline-кнопок: кнопки
+идут друг за другом, а на следующую строку переносятся целиком, когда не помещаются. Из раздела
+можно перейти в любой другой; отдельной кнопки «В меню» нет, текущий раздел отключён.
+
### Поддержка (`support.py`)
Отдельного FSM-режима нет: обращение — расширение режима «Помощь». Пользователь нажимает
@@ -347,7 +353,7 @@ SUBSCRIPTION_PRICE_STARS = 100
- **Coolify:** проект `Social Post Writer Bot`, окружение `development`, приложение `social-post-writer-bot-development` (`d32u5zcq2g4odmdpq9hw91yn`) на `spb-easy-dale`.
- **Деплой:** `bash /root/.hermes/scripts/gitea_deploy.sh dev` (POST `/api/v1/deploy?uuid=...&force=false`).
- **Окружение:** `DEPLOY_ENV` включает dev-функции только при точном значении `development`; production, пустое и неизвестное значение отключают их. `BOT_ENV` отдельно выбирает Telegram Bot API и не используется для включения dev-поведения.
-- **VERSION:** файл `VERSION` (`0.1.0+59`). При `DEPLOY_ENV=development` и изменении версии бот шлёт уведомление о версии в `DEV_CHAT_ID`.
+- **VERSION:** файл `VERSION` (`0.1.0+60`). При `DEPLOY_ENV=development` и изменении версии бот шлёт уведомление о версии в `DEV_CHAT_ID`.
- **Переменные Coolify:** `BOT_TOKEN`, `APINEX_API_KEY`, `APINEX_STT_MODEL`, `APINEX_INTENT_CLASSIFIER_MODEL`, `APINEX_INJECTION_CLASSIFIER_MODEL`, `APINEX_POST_WRITER_MODEL`, `APINEX_IMAGE_TONE_MODEL`, `APINEX_RESPONSE_REPAIR_MODEL` (optional; default uses the standard model), `BOT_DB_PATH`, `RAW_UPDATES_DB_PATH` (optional; default `/app/data/bot_updates.sqlite3`), `DEPLOY_ENV`, `DEV_CHAT_ID`, `BOT_LOG_PATH` (optional; default `/app/data/bot.log`), `ACTIVITY_MIN_SECONDS` / `ACTIVITY_MAX_SECONDS` (optional; default 3 / 8 — границы паузы между сменами фраз в драфте), `ACTIVITY_MAX_ROTATIONS` (optional; default 12 — предохранитель от бесконечной ротации),
`SUPPORT_GROUP_ID` (id супергруппы с темами для обращений; без неё поддержка выключена),
`SUPPORT_NOTE_PREFIX` (optional; default `//` — префикс заметки, которая не уходит пользователю),
diff --git a/VERSION b/VERSION
index a2bea9e..2d5d1a2 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.0+59
\ No newline at end of file
+0.1.0+60
\ No newline at end of file
diff --git a/help_message.py b/help_message.py
index 1c19db1..c36aeeb 100644
--- a/help_message.py
+++ b/help_message.py
@@ -64,11 +64,11 @@ HELP_SECTIONS: dict[str, tuple[str, str]] = {
}
HELP_SECTION_ORDER: tuple[str, ...] = tuple(HELP_SECTIONS)
-HELP_MENU_BUTTON = "⌂ В меню"
+HELP_BUTTON_ROW_WIDTH = 24
def _menu_buttons(current: str | None = None) -> str:
- rows = []
+ buttons: list[tuple[str, str]] = []
for section in HELP_SECTION_ORDER:
title = HELP_SECTIONS[section][0]
if section == current:
@@ -78,18 +78,26 @@ def _menu_buttons(current: str | None = None) -> str:
f'