Files
StatusServerBot/main.py

158 lines
4.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
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"""
<b>🖥️ Состояние сервера</b>
<b>OS:</b> {system_info.system} {system_info.release}
<b>Uptime:</b> {boot_time}
<b>CPU:</b>
├ Ядер: {physical_cores} (логических: {logical_cores})
├ Загрузка: {cpu_percent}%
{load_str}<b>RAM:</b>
Всего: {memory.total / 1024 ** 3:.2f} GB
├ Используется: {memory.used / 1024 ** 3:.2f} GB
└ Свободно: {memory.available / 1024 ** 3:.2f} GB
<b>Диск ({root_path}):</b>
Всего: {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())