Простенький бот для выявления статуса сервера
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