Paginate update list output

This commit is contained in:
2026-02-07 23:05:36 +03:00
parent 6a4f29bd4b
commit a3a942ecb7
3 changed files with 73 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
from aiogram import F from aiogram import F
from aiogram.types import Message from aiogram.types import Message, CallbackQuery
from app import dp from app import dp
from auth import is_admin_msg from auth import is_admin_msg
from keyboards import system_kb from keyboards import system_kb
@@ -9,6 +9,8 @@ from services.http_checks import get_url_checks, check_url
import asyncio import asyncio
from services.queue import enqueue from services.queue import enqueue
from services.updates import list_updates, apply_updates from services.updates import list_updates, apply_updates
from state import UPDATES_CACHE
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
@dp.message(F.text == "💽 Disks") @dp.message(F.text == "💽 Disks")
@@ -60,8 +62,13 @@ async def updates_list(msg: Message):
return return
async def job(): async def job():
text = await list_updates() title, lines = await list_updates()
await msg.answer(text, reply_markup=system_kb, parse_mode="Markdown") UPDATES_CACHE[msg.from_user.id] = {
"title": title,
"lines": lines,
"page_size": 20,
}
await send_updates_page(msg, 0)
pos = await enqueue("pkg-updates", job) pos = await enqueue("pkg-updates", job)
await msg.answer(f"🕓 Updates queued (#{pos})", reply_markup=system_kb) await msg.answer(f"🕓 Updates queued (#{pos})", reply_markup=system_kb)
@@ -78,3 +85,48 @@ async def updates_apply(msg: Message):
pos = await enqueue("pkg-upgrade", job) pos = await enqueue("pkg-upgrade", job)
await msg.answer(f"🕓 Upgrade queued (#{pos})", reply_markup=system_kb) await msg.answer(f"🕓 Upgrade queued (#{pos})", reply_markup=system_kb)
def _updates_kb(page: int, total_pages: int) -> InlineKeyboardMarkup:
buttons = []
if total_pages > 1:
row = []
if page > 0:
row.append(InlineKeyboardButton(text="⬅️ Prev", callback_data=f"updpage:{page-1}"))
if page < total_pages - 1:
row.append(InlineKeyboardButton(text="Next ➡️", callback_data=f"updpage:{page+1}"))
if row:
buttons.append(row)
return InlineKeyboardMarkup(inline_keyboard=buttons)
async def send_updates_page(msg: Message, page: int):
data = UPDATES_CACHE.get(msg.from_user.id)
if not data:
await msg.answer("⚠️ Updates cache empty", reply_markup=system_kb)
return
lines = data["lines"]
page_size = data["page_size"]
total_pages = max(1, (len(lines) + page_size - 1) // page_size)
page = max(0, min(page, total_pages - 1))
start = page * page_size
end = start + page_size
body = "\n".join(lines[start:end])
text = f"{data['title']} (page {page+1}/{total_pages})\n```{body}```"
await msg.answer(text, reply_markup=_updates_kb(page, total_pages), parse_mode="Markdown")
@dp.callback_query(F.data.startswith("updpage:"))
async def updates_page(cb: CallbackQuery):
if cb.from_user.id not in UPDATES_CACHE:
await cb.answer("No cached updates")
return
try:
page = int(cb.data.split(":", 1)[1])
except ValueError:
await cb.answer("Bad page")
return
await cb.answer()
await send_updates_page(cb.message, page)

View File

@@ -14,16 +14,16 @@ def detect_pkg_manager() -> str | None:
return None return None
async def list_updates() -> str: async def list_updates() -> tuple[str, list[str]]:
pm = detect_pkg_manager() pm = detect_pkg_manager()
if not pm: if not pm:
return "⚠️ No supported package manager found" return "⚠️ Updates", ["No supported package manager found"]
if pm == "apt": if pm == "apt":
await run_cmd(["sudo", "apt", "update"], timeout=300) await run_cmd(["sudo", "apt", "update"], timeout=300)
rc, out = await run_cmd(["apt", "list", "--upgradable"], timeout=120) rc, out = await run_cmd(["apt", "list", "--upgradable"], timeout=120)
if rc != 0: if rc != 0:
return f"❌ apt list failed\n```{out}```" return "Updates (apt)", [f"apt list failed: {out}"]
lines = [] lines = []
for line in out.splitlines(): for line in out.splitlines():
@@ -47,26 +47,32 @@ async def list_updates() -> str:
else: else:
lines.append(f"{name}: -> {new_ver}") lines.append(f"{name}: -> {new_ver}")
body = "\n".join(lines) if lines else "No updates" if not lines:
return f"📦 Updates (apt)\n```{body}```" lines = ["No updates"]
return "📦 Updates (apt)", lines
if pm == "dnf": if pm == "dnf":
rc, out = await run_cmd(["sudo", "dnf", "check-update"], timeout=300) rc, out = await run_cmd(["sudo", "dnf", "check-update"], timeout=300)
if rc in (0, 100): if rc in (0, 100):
return f"📦 Updates (dnf)\n```{out}```" lines = out.splitlines() or ["No updates"]
return f"❌ dnf check-update failed\n```{out}```" return "📦 Updates (dnf)", lines
return "❌ Updates (dnf)", [f"dnf check-update failed: {out}"]
if pm == "yum": if pm == "yum":
rc, out = await run_cmd(["sudo", "yum", "check-update"], timeout=300) rc, out = await run_cmd(["sudo", "yum", "check-update"], timeout=300)
if rc in (0, 100): if rc in (0, 100):
return f"📦 Updates (yum)\n```{out}```" lines = out.splitlines() or ["No updates"]
return f"❌ yum check-update failed\n```{out}```" return "📦 Updates (yum)", lines
return "❌ Updates (yum)", [f"yum check-update failed: {out}"]
if pm == "pacman": if pm == "pacman":
rc, out = await run_cmd(["pacman", "-Qu"], timeout=120) rc, out = await run_cmd(["pacman", "-Qu"], timeout=120)
return f"📦 Updates (pacman)\n```{out}```" if rc == 0 else f"❌ pacman -Qu failed\n```{out}```" if rc == 0:
lines = out.splitlines() or ["No updates"]
return "📦 Updates (pacman)", lines
return "❌ Updates (pacman)", [f"pacman -Qu failed: {out}"]
return "⚠️ Unsupported package manager" return "⚠️ Updates", ["Unsupported package manager"]
async def apply_updates() -> str: async def apply_updates() -> str:

View File

@@ -2,3 +2,4 @@ from typing import Dict
DOCKER_MAP: Dict[str, str] = {} DOCKER_MAP: Dict[str, str] = {}
LOG_FILTER_PENDING: Dict[int, dict] = {} LOG_FILTER_PENDING: Dict[int, dict] = {}
UPDATES_CACHE: Dict[int, dict] = {}