Add multi-page inline help
This commit is contained in:
105
handlers/help.py
105
handlers/help.py
@@ -1,24 +1,105 @@
|
|||||||
from aiogram import F
|
from aiogram import F
|
||||||
from aiogram.types import Message
|
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
||||||
from app import dp
|
from app import dp, ADMIN_ID
|
||||||
from auth import is_admin_msg
|
from auth import is_admin_msg
|
||||||
from keyboards import menu_kb
|
from keyboards import menu_kb
|
||||||
|
|
||||||
|
|
||||||
|
HELP_PAGES = [
|
||||||
|
(
|
||||||
|
"Overview",
|
||||||
|
"ℹ️ **Help — Overview**\n\n"
|
||||||
|
"🩺 *Health* — быстрый health-check.\n"
|
||||||
|
"📊 *Статус* — общая загрузка.\n"
|
||||||
|
"📋 */status_short* — кратко (load/RAM/диски).\n"
|
||||||
|
"🩺 */health_short* — краткий health.\n"
|
||||||
|
"🔧 Разделы: Docker, Backup, Artifacts, System, OpenWrt.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Alerts",
|
||||||
|
"🚨 **Alerts & Mute**\n\n"
|
||||||
|
"Команды:\n"
|
||||||
|
"• `/alerts test <critical|warn|info>`\n"
|
||||||
|
"• `/alerts mute <cat> <minutes>` / `/alerts unmute <cat>` / `/alerts list`\n"
|
||||||
|
"• `/alerts recent [hours]`\n"
|
||||||
|
"Категории: load, disk, smart, ssl, docker, test.\n"
|
||||||
|
"Quiet hours: `alerts.quiet_hours` для не‑критичных.\n"
|
||||||
|
"Только красные load: `alerts.load_only_critical: true`.\n"
|
||||||
|
"Валидатор конфига: `/config_check`.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Backup",
|
||||||
|
"💾 **Backup (restic)**\n\n"
|
||||||
|
"Кнопки: Status, Last snapshot, Repo stats, Run backup, Queue, Restic check, Weekly report.\n"
|
||||||
|
"Run backup/Check учитывают `safety.dry_run`.\n"
|
||||||
|
"После бэкапа приходит TL;DR + путь к логу `/var/log/backup-auto.log`.\n"
|
||||||
|
"Queue → Details показывает отложенные задачи.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Docker & System",
|
||||||
|
"🐳 **Docker**\n"
|
||||||
|
"Status/Restart/Logs/Stats — клавиатура Docker.\n\n"
|
||||||
|
"🖥 **System**\n"
|
||||||
|
"Info: Disks/Security/Metrics/Hardware/SMART/OpenWrt.\n"
|
||||||
|
"Ops: Updates/Upgrade/Reboot.\n"
|
||||||
|
"Logs: Audit/Incidents/Security/Integrations/Processes.",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"Admin",
|
||||||
|
"🛠 **Admin & Deploy**\n\n"
|
||||||
|
"Config: `/config_check`, файл `config.yaml` (см. config.example.yaml).\n"
|
||||||
|
"Deploy: `deploy.sh` (ssh 10.10.10.10:1090 → git pull → systemctl restart tg-bot).\n"
|
||||||
|
"Безопасность: `safety.dry_run: true` блокирует опасные действия.\n"
|
||||||
|
"OpenWrt: кнопка в System → Info.",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _help_kb(idx: int) -> InlineKeyboardMarkup:
|
||||||
|
buttons = []
|
||||||
|
if idx > 0:
|
||||||
|
buttons.append(InlineKeyboardButton(text="◀️ Prev", callback_data=f"help:{idx-1}"))
|
||||||
|
buttons.append(InlineKeyboardButton(text=f"{idx+1}/{len(HELP_PAGES)}", callback_data="help:noop"))
|
||||||
|
if idx < len(HELP_PAGES) - 1:
|
||||||
|
buttons.append(InlineKeyboardButton(text="Next ▶️", callback_data=f"help:{idx+1}"))
|
||||||
|
return InlineKeyboardMarkup(inline_keyboard=[buttons])
|
||||||
|
|
||||||
|
|
||||||
|
def _help_text(idx: int) -> str:
|
||||||
|
_title, body = HELP_PAGES[idx]
|
||||||
|
return body
|
||||||
|
|
||||||
|
|
||||||
@dp.message(F.text.in_({"ℹ️ Help", "ℹ Help", "Help"}))
|
@dp.message(F.text.in_({"ℹ️ Help", "ℹ Help", "Help"}))
|
||||||
async def help_cmd(msg: Message):
|
async def help_cmd(msg: Message):
|
||||||
if not is_admin_msg(msg):
|
if not is_admin_msg(msg):
|
||||||
return
|
return
|
||||||
|
idx = 0
|
||||||
await msg.answer(
|
await msg.answer(
|
||||||
"ℹ️ **Help / Справка**\n\n"
|
_help_text(idx),
|
||||||
"🩺 Health — быстрый health-check сервера\n"
|
reply_markup=_help_kb(idx),
|
||||||
"📊 Статус — общая загрузка сервера\n"
|
|
||||||
"🐳 Docker — управление контейнерами\n"
|
|
||||||
"📦 Backup — restic бэкапы\n"
|
|
||||||
"🧉 Artifacts — критичные образы (Clonezilla, NAND)\n"
|
|
||||||
"⚙️ System — подменю: Info / Ops / Logs\n\n"
|
|
||||||
"Inline-кнопки используются для выбора контейнеров.",
|
|
||||||
reply_markup=menu_kb,
|
|
||||||
parse_mode="Markdown",
|
parse_mode="Markdown",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dp.callback_query(F.data.startswith("help:"))
|
||||||
|
async def help_cb(cb: CallbackQuery):
|
||||||
|
if cb.from_user.id != ADMIN_ID:
|
||||||
|
await cb.answer()
|
||||||
|
return
|
||||||
|
payload = cb.data.split(":", 1)[1]
|
||||||
|
if payload == "noop":
|
||||||
|
await cb.answer()
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
idx = int(payload)
|
||||||
|
except ValueError:
|
||||||
|
await cb.answer()
|
||||||
|
return
|
||||||
|
idx = max(0, min(idx, len(HELP_PAGES) - 1))
|
||||||
|
await cb.message.edit_text(
|
||||||
|
_help_text(idx),
|
||||||
|
reply_markup=_help_kb(idx),
|
||||||
|
parse_mode="Markdown",
|
||||||
|
)
|
||||||
|
await cb.answer()
|
||||||
|
|||||||
Reference in New Issue
Block a user