114 lines
3.3 KiB
Python
114 lines
3.3 KiB
Python
from aiogram import F
|
|
from aiogram.types import Message
|
|
from app import dp
|
|
from auth import is_admin_msg
|
|
from keyboards import docker_kb, docker_inline_kb
|
|
from services.docker import container_uptime, docker_cmd
|
|
from state import DOCKER_MAP, LOG_FILTER_PENDING
|
|
import time
|
|
|
|
|
|
async def cmd_docker_status(msg: Message):
|
|
try:
|
|
if not DOCKER_MAP:
|
|
await msg.answer(
|
|
"⚠️ DOCKER_MAP пуст.\n"
|
|
"Контейнеры не обнаружены.",
|
|
reply_markup=docker_kb,
|
|
)
|
|
return
|
|
|
|
lines = ["🐳 Docker containers\n"]
|
|
|
|
for alias, real in DOCKER_MAP.items():
|
|
rc, raw = await docker_cmd(
|
|
["inspect", "-f", "{{.State.Status}}|{{.State.StartedAt}}", real],
|
|
timeout=10,
|
|
)
|
|
|
|
if rc != 0:
|
|
lines.append(f"🔴 {alias}: inspect error")
|
|
continue
|
|
|
|
raw = raw.strip()
|
|
if "|" not in raw:
|
|
lines.append(f"🟡 {alias}: invalid inspect output")
|
|
continue
|
|
|
|
status, started = raw.split("|", 1)
|
|
up = container_uptime(started)
|
|
|
|
icon = "🟢" if status == "running" else "🔴"
|
|
lines.append(f"{icon} {alias}: {status} ({up})")
|
|
|
|
await msg.answer("\n".join(lines), reply_markup=docker_kb)
|
|
|
|
except Exception as e:
|
|
# ⬅️ КРИТИЧЕСКИ ВАЖНО
|
|
await msg.answer(
|
|
"❌ Docker status crashed:\n"
|
|
f"```{type(e).__name__}: {e}```",
|
|
reply_markup=docker_kb,
|
|
parse_mode="Markdown",
|
|
)
|
|
|
|
|
|
@dp.message(F.text == "🔄 Restart")
|
|
async def dr(msg: Message):
|
|
if is_admin_msg(msg):
|
|
await msg.answer(
|
|
"🔄 Выберите контейнер для рестарта:",
|
|
reply_markup=docker_inline_kb("restart")
|
|
)
|
|
|
|
|
|
@dp.message(F.text == "📜 Logs")
|
|
async def dl(msg: Message):
|
|
if is_admin_msg(msg):
|
|
await msg.answer(
|
|
"📜 Выберите контейнер для логов:",
|
|
reply_markup=docker_inline_kb("logs")
|
|
)
|
|
|
|
|
|
@dp.message(F.text == "🐳 Status")
|
|
async def ds(msg: Message):
|
|
if is_admin_msg(msg):
|
|
await cmd_docker_status(msg)
|
|
|
|
|
|
@dp.message(F.text)
|
|
async def log_filter_input(msg: Message):
|
|
if not is_admin_msg(msg):
|
|
return
|
|
|
|
pending = LOG_FILTER_PENDING.pop(msg.from_user.id, None)
|
|
if not pending:
|
|
return
|
|
|
|
alias = pending["alias"]
|
|
real = DOCKER_MAP.get(alias)
|
|
if not real:
|
|
await msg.answer("⚠️ Container not found", reply_markup=docker_kb)
|
|
return
|
|
|
|
needle = (msg.text or "").strip()
|
|
if not needle:
|
|
await msg.answer("⚠️ Empty filter text", reply_markup=docker_kb)
|
|
return
|
|
|
|
since_ts = str(int(time.time() - int(pending.get("since_sec", 1800))))
|
|
rc, out = await docker_cmd(["logs", "--since", since_ts, "--tail", "400", real])
|
|
if rc != 0:
|
|
await msg.answer(out, reply_markup=docker_kb)
|
|
return
|
|
|
|
lines = [line for line in out.splitlines() if needle.lower() in line.lower()]
|
|
filtered = "\n".join(lines) if lines else "(no matches)"
|
|
|
|
await msg.answer(
|
|
f"📜 **Logs filter: {alias}**\n```{filtered}```",
|
|
parse_mode="Markdown",
|
|
reply_markup=docker_kb,
|
|
)
|