""" Telegram-бот для отображения состояния системы. Функциональность: - команда /start отправляет информацию о сервере - отображаются CPU, RAM, диск, uptime и load average - токен загружается из переменной окружения BOT_TOKEN или .env Зависимости: pip install aiogram psutil python-dotenv """ from __future__ import annotations import asyncio import os from datetime import datetime from platform import uname, system from typing import Final import psutil from aiogram import Bot, Dispatcher from aiogram.client.default import DefaultBotProperties from aiogram.filters import CommandStart from aiogram.types import Message from dotenv import load_dotenv # --------------------------------------------------------------------- # Загрузка переменных окружения # --------------------------------------------------------------------- load_dotenv() BOT_TOKEN: Final[str | None] = os.getenv("BOT_TOKEN") if BOT_TOKEN is None: raise RuntimeError( "Переменная окружения BOT_TOKEN не найдена.\n" "Создайте файл .env и добавьте:\n" "BOT_TOKEN=your_telegram_token" ) # --------------------------------------------------------------------- # Инициализация Telegram-бота # --------------------------------------------------------------------- bot: Bot = Bot( token=BOT_TOKEN, default=DefaultBotProperties(parse_mode="HTML"), ) dp: Dispatcher = Dispatcher() # --------------------------------------------------------------------- # Системная информация # --------------------------------------------------------------------- def get_system_info() -> str: """ Собирает информацию о состоянии системы. Возвращает: str: форматированная строка с информацией о системе """ # Информация о системе system_info = uname() # Время загрузки системы boot_time_timestamp: float = psutil.boot_time() boot_time: str = datetime.fromtimestamp( boot_time_timestamp ).strftime("%Y-%m-%d %H:%M:%S") # Память memory = psutil.virtual_memory() # CPU cpu_percent: float = psutil.cpu_percent(interval=1) physical_cores: int | None = psutil.cpu_count(logical=False) logical_cores: int | None = psutil.cpu_count(logical=True) # Определяем корневой диск root_path: str = "C:\\" if system() == "Windows" else "/" disk = psutil.disk_usage(root_path) # Load average (только UNIX) load_str: str = "" if hasattr(os, "getloadavg"): load_avg = os.getloadavg() load_str = ( f"└ Load average: " f"{load_avg[0]:.2f}, {load_avg[1]:.2f}, {load_avg[2]:.2f}\n" ) # Формирование сообщения info: str = f""" 🖥️ Состояние сервера OS: {system_info.system} {system_info.release} Uptime: {boot_time} CPU: ├ Ядер: {physical_cores} (логических: {logical_cores}) ├ Загрузка: {cpu_percent}% {load_str}RAM: ├ Всего: {memory.total / 1024 ** 3:.2f} GB ├ Используется: {memory.used / 1024 ** 3:.2f} GB └ Свободно: {memory.available / 1024 ** 3:.2f} GB Диск ({root_path}): ├ Всего: {disk.total / 1024 ** 3:.2f} GB ├ Используется: {disk.used / 1024 ** 3:.2f} GB └ Свободно: {disk.free / 1024 ** 3:.2f} GB """.strip() return info # --------------------------------------------------------------------- # Обработчики # --------------------------------------------------------------------- @dp.message(CommandStart()) async def start_handler(message: Message) -> None: """ Обработчик команды /start. Отправляет пользователю текущее состояние системы. """ system_info: str = get_system_info() await message.answer(system_info) # --------------------------------------------------------------------- # Основной запуск # --------------------------------------------------------------------- async def main() -> None: """ Основная функция запуска бота. Запускает polling и корректно завершает соединение. """ try: await dp.start_polling(bot) finally: await bot.session.close() if __name__ == "__main__": asyncio.run(main())