Простенький бот для выявления статуса сервера
This commit is contained in:
157
main.py
Normal file
157
main.py
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
"""
|
||||||
|
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())
|
||||||
Reference in New Issue
Block a user