stage 02 system status screen

This commit is contained in:
2026-04-13 21:47:59 +03:00
parent 7565aa485e
commit 9acf1b10e3
5 changed files with 174 additions and 15 deletions

View File

@@ -0,0 +1,91 @@
from __future__ import annotations
import platform
from dataclasses import dataclass
from src.core.constants import APP_NAME, APP_VERSION
from src.core.config import load_settings
@dataclass(slots=True)
class ComponentStatus:
name: str
state: str
details: str
@dataclass(slots=True)
class SystemSnapshot:
app_name: str
app_version: str
app_env: str
python_version: str
os_name: str
timezone_name: str
components: list[ComponentStatus]
def get_system_snapshot() -> SystemSnapshot:
settings = load_settings()
components = [
ComponentStatus(
name="Бот",
state="🟢 работает",
details="Процесс бота запущен и обрабатывает команды.",
),
ComponentStatus(
name="Telegram",
state="🟢 OK",
details="Polling активен, базовая маршрутизация подключена.",
),
ComponentStatus(
name="Биржа",
state="🟡 не подключена",
details="Интеграция с биржей будет добавлена на следующем этапе.",
),
ComponentStatus(
name="База данных",
state="🟡 не подключена",
details="Слой хранения пока только подготовлен структурно.",
),
]
return SystemSnapshot(
app_name=APP_NAME,
app_version=APP_VERSION,
app_env=settings.app_env,
python_version=platform.python_version(),
os_name=f"{platform.system()} {platform.release()}",
timezone_name=settings.tz,
components=components,
)
def build_system_text() -> str:
snapshot = get_system_snapshot()
component_lines = []
for component in snapshot.components:
component_lines.append(
f"{component.state} <b>{component.name}</b>\n"
f"{component.details}"
)
components_block = "\n\n".join(component_lines)
return (
"<b>⚙️ Система</b>\n\n"
"<b>Статус компонентов</b>\n"
f"{components_block}\n\n"
"<b>Окружение</b>\n"
f"- приложение: {snapshot.app_name} {snapshot.app_version}\n"
f"- env: {snapshot.app_env}\n"
f"- python: {snapshot.python_version}\n"
f"- os: {snapshot.os_name}\n"
f"- timezone: {snapshot.timezone_name}\n\n"
"<b>Справка</b>\n"
"/start — стартовый экран\n"
"/menu — показать меню\n"
"/help — открыть системную справку"
)

View File

@@ -1,9 +1,12 @@
from __future__ import annotations
from aiogram import F, Router from aiogram import F, Router
from aiogram.filters import Command from aiogram.filters import Command
from aiogram.types import Message from aiogram.types import Message
from src.core.system_status import build_system_text
from src.telegram.keyboards.reply import build_main_menu_keyboard from src.telegram.keyboards.reply import build_main_menu_keyboard
from src.telegram.menus import MAIN_MENU_TEXT, SYSTEM_TEXT from src.telegram.menus import MAIN_MENU_TEXT
router = Router(name="start") router = Router(name="start")
@@ -11,19 +14,31 @@ router = Router(name="start")
@router.message(Command("start")) @router.message(Command("start"))
async def cmd_start(message: Message) -> None: async def cmd_start(message: Message) -> None:
await message.answer(MAIN_MENU_TEXT, reply_markup=build_main_menu_keyboard()) await message.answer(
MAIN_MENU_TEXT,
reply_markup=build_main_menu_keyboard(),
)
@router.message(Command("menu")) @router.message(Command("menu"))
async def cmd_menu(message: Message) -> None: async def cmd_menu(message: Message) -> None:
await message.answer(MAIN_MENU_TEXT, reply_markup=build_main_menu_keyboard()) await message.answer(
MAIN_MENU_TEXT,
reply_markup=build_main_menu_keyboard(),
)
@router.message(Command("help")) @router.message(Command("help"))
async def cmd_help(message: Message) -> None: async def cmd_help(message: Message) -> None:
await message.answer(SYSTEM_TEXT, reply_markup=build_main_menu_keyboard()) await message.answer(
build_system_text(),
reply_markup=build_main_menu_keyboard(),
)
@router.message(F.text == "Меню") @router.message(F.text == "Меню")
async def menu_shortcut(message: Message) -> None: async def menu_shortcut(message: Message) -> None:
await message.answer(MAIN_MENU_TEXT, reply_markup=build_main_menu_keyboard()) await message.answer(
MAIN_MENU_TEXT,
reply_markup=build_main_menu_keyboard(),
)

View File

@@ -1,10 +1,9 @@
import platform from __future__ import annotations
from aiogram import F, Router from aiogram import F, Router
from aiogram.types import Message from aiogram.types import Message
from src.core.constants import APP_NAME, APP_VERSION from src.core.system_status import build_system_text
from src.telegram.menus import SYSTEM_TEXT
router = Router(name="system") router = Router(name="system")
@@ -12,10 +11,4 @@ router = Router(name="system")
@router.message(F.text.in_({"⚙️ Система", "⚙ Система"})) @router.message(F.text.in_({"⚙️ Система", "⚙ Система"}))
async def open_system(message: Message) -> None: async def open_system(message: Message) -> None:
runtime_info = ( await message.answer(build_system_text())
"\n\n<b>Runtime</b>\n"
f"- app: {APP_NAME} {APP_VERSION}\n"
f"- python: {platform.python_version()}\n"
f"- os: {platform.system()} {platform.release()}"
)
await message.answer(SYSTEM_TEXT + runtime_info)

View File

@@ -0,0 +1,14 @@
# 0004 — System Screen
## Решение
Сделать `Система` отдельным системным экраном, который показывает не только справку, но и снимок состояния приложения.
## Причины
- это удобно для диагностики
- это удобно для локальной разработки
- это удобно для проверки на Synology
- это закладывает основу для health checks
## Последствия
- справка больше не живет отдельно от системного экрана
- системный экран становится точкой входа для технического контроля проекта

View File

@@ -0,0 +1,46 @@
# Stage 02 — System
## Цель
Сделать раздел `⚙️ Система` реальным центром контроля приложения, а не просто статическим экраном.
## Что добавляется
- сервис `system_status`, который собирает снимок состояния приложения
- единый текст системы, который используется и кнопкой `⚙️ Система`, и командой `/help`
- отображение:
- статуса бота
- статуса Telegram-слоя
- статуса интеграции с биржей
- статуса слоя хранения
- текущего окружения
## Что должен увидеть пользователь
Экран вида:
- Бот: работает
- Telegram: OK
- Биржа: не подключена
- База данных: не подключена
- env / python / os / timezone
## Почему это важно
На следующих этапах сюда будут добавляться:
- ping биржи
- статус WebSocket
- статус БД
- статус Redis
- последние ошибки
- health checks
## Как проверить
1. Запустить бота локально
2. Открыть Telegram
3. Нажать `⚙️ Система`
4. Проверить команду `/help`
5. Убедиться, что экран одинаково полезен из кнопки и из команды
## Commit message
Рекомендуемый commit:
```bash
git commit -m "stage 02 system status screen"
```