165 lines
6.3 KiB
Python
165 lines
6.3 KiB
Python
from aiogram import F
|
||
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
||
from app import dp, ADMIN_ID
|
||
from auth import is_admin_msg
|
||
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"
|
||
"🧪 */selftest* — health + restic snapshot probe.\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"
|
||
"Шорткаты: `/alerts_list`, `/alerts_recent`, `/alerts_mute_load` (60м).\n"
|
||
"Категории: load, disk, smart, ssl, docker, test.\n"
|
||
"Quiet hours: `alerts.quiet_hours` для не‑критичных.\n"
|
||
"Авто-мьют: `alerts.auto_mute` со слотами времени.\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, History.\n"
|
||
"History — хвост `/var/log/backup-auto.log`.\n"
|
||
"Fail → кнопка Retry (backup/check).\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"
|
||
"Команды: `/docker_status`, `/docker_health <alias>`.\n\n"
|
||
"🖥 **System**\n"
|
||
"Info: Disks/Security/Metrics/Hardware/SMART/OpenWrt.\n"
|
||
"Ops: Updates/Upgrade/Reboot.\n"
|
||
"Logs: Audit/Incidents/Security/Integrations/Processes.\n"
|
||
"OpenWrt: `/openwrt`, `/openwrt_wan`, `/openwrt_clients`, `/openwrt_leases`.",
|
||
),
|
||
(
|
||
"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"
|
||
"Incidents: `/incidents_summary`, `/incidents_diff [hours]`.\n"
|
||
"Export: `/incidents_export [hours] [csv|json]`, `/export_all [hours]` (zip).\n"
|
||
"Alerts log/heatmap: `/alerts_log [hours]`, `/alerts_heatmap [hours] [cat]`.\n"
|
||
"Backup SLA: `/backup_sla`; Docker restarts: `/docker_restarts [hours]`.\n"
|
||
"Disk snapshot: `/disk_snapshot`.\n"
|
||
"Queue: `/queue_history`, `/queue_sla`.\n"
|
||
"Self-test history: `/selftest_history`.\n"
|
||
"OpenWrt leases diff: `/openwrt_leases_diff`.\n"
|
||
"BotFather list: `/botfather_list`.\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", "/help"}))
|
||
async def help_cmd(msg: Message):
|
||
if not is_admin_msg(msg):
|
||
return
|
||
idx = 0
|
||
await msg.answer(
|
||
_help_text(idx),
|
||
reply_markup=_help_kb(idx),
|
||
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()
|
||
|
||
|
||
BOTFATHER_LIST = """\
|
||
help - Show help pages
|
||
status_short - Compact host status
|
||
health_short - Compact health report
|
||
selftest - Health + restic snapshot probe
|
||
alerts - Manage alerts
|
||
alerts_list - List active mutes
|
||
alerts_recent - Show recent incidents (24h)
|
||
alerts_mute_load - Mute load alerts for 60m
|
||
alerts_log - Show suppressed alerts
|
||
alerts_heatmap - Hourly incidents heatmap
|
||
backup_run - Run backup (queued)
|
||
backup_history - Show backup log tail
|
||
queue_history - Show queue recent jobs
|
||
queue_sla - Queue SLA stats
|
||
docker_status - Docker summary
|
||
docker_health - Docker inspect/health by alias
|
||
docker_health_summary - Docker health summary (problems only)
|
||
openwrt - Full OpenWrt status
|
||
openwrt_wan - OpenWrt WAN only
|
||
openwrt_clients - OpenWrt wifi clients
|
||
openwrt_leases - OpenWrt DHCP leases
|
||
openwrt_fast - OpenWrt quick WAN view
|
||
openwrt_leases_diff - OpenWrt DHCP diff
|
||
incidents_summary - Incidents counters (24h/7d)
|
||
incidents_export - Export incidents (hours fmt)
|
||
incidents_diff - Show incidents since last check
|
||
export_all - Zip with incidents/queue/selftest
|
||
backup_sla - Backup SLA check
|
||
docker_restarts - Docker restart history
|
||
selftest_history - Self-test history
|
||
disk_snapshot - Disk usage snapshot
|
||
config_check - Validate config
|
||
"""
|
||
|
||
|
||
@dp.message(F.text == "/botfather_list")
|
||
async def botfather_list(msg: Message):
|
||
if not is_admin_msg(msg):
|
||
return
|
||
await msg.answer(f"Commands for BotFather:\n```\n{BOTFATHER_LIST}\n```", parse_mode="Markdown")
|