watch: add pagination with inline navigation buttons

parent a9ada14f
from telegrinder import InlineKeyboard, InlineButton
def watch_nav_kb(maintainer: str, acl: str, offset: int, total: int, per_page: int = 10):
kb = InlineKeyboard()
nav_buttons = []
if offset > 0:
nav_buttons.append(InlineButton(
text="← Назад",
callback_data=f"watch/{maintainer}/{acl}/{offset - per_page}",
))
if offset + per_page < total:
nav_buttons.append(InlineButton(
text="Вперёд →",
callback_data=f"watch/{maintainer}/{acl}/{offset + per_page}",
))
if nav_buttons:
for btn in nav_buttons:
kb.add(btn)
kb.row()
kb.add(InlineButton(
"Полный список",
url=f"https://packages.altlinux.org/ru/sisyphus/maintainers/{maintainer}/watch",
))
return kb.get_markup()
def watch_more_kb(maintainer: str):
kb = InlineKeyboard()
kb.add(
......
from telegrinder import Dispatch, Message
from telegrinder.rules import Command, Argument, Text, IsPrivate
from telegrinder import Dispatch, Message, CallbackQuery
from telegrinder.rules import Command, Argument, Text, IsPrivate, CallbackDataMarkup
from telegrinder.tools.formatting import HTMLFormatter
from altrepo import altrepo
from config import TASK_URL
from database.models import User
from data.keyboards import watch_keyboards
from services.utils import _bold, resolve_maintainer
from services.watch import watch as watch_service
from services.watch import watch
PER_PAGE = 10
dp = Dispatch()
async def fetch_watch_packages(maintainer: str, acl: str):
watch_data = await altrepo.parser.packages.watch_by_maintainer(maintainer, acl)
if not watch_data:
return []
packages = {}
for package in watch_data:
name = package.pkg_name
if name not in packages or "src.rpm" in packages[name].url:
packages[name] = package
return list(packages.values())
async def format_watch_entry(package):
crossed = False
updated_in_task_message = ""
for status in ["DONE", "EPERM"]:
try:
data = await altrepo.api.task.progress.find_tasks(
input=[package.pkg_name, "sisyphus",
package.new_version, status]
)
task_id = data.tasks[0].task_id
updated_in_task_message = (
f" (<a href='{TASK_URL}{task_id}'>{task_id}/{status}</a>)"
)
crossed = True
break
except:
crossed = False
continue
prefix = "<s>" if crossed else ""
suffix = "</s>" if crossed else ""
return HTMLFormatter(
f"{prefix}"
f"{package.pkg_name}: {package.old_version} -> "
f"<a href='{package.url.replace('.git/', '/')}'>{package.new_version}</a>"
f"{suffix}"
f"{updated_in_task_message}\n"
)
async def format_watch_page(packages, offset: int, total: int):
message = _bold("Отслеживание:\n\n")
for package in packages:
message += await format_watch_entry(package)
message += f"\nПакеты {offset + 1}–{offset + len(packages)} из {total}"
return message
@dp.message(
Command("watch",
Argument("maintainer", optional=True),
......@@ -17,6 +75,42 @@ dp = Dispatch()
async def watch_handler(
m: Message, user: User | None, maintainer: str | None = None, acl: str | None = None
) -> None:
await watch(
user, m.chat_id, maintainer, acl
resolved = await resolve_maintainer(maintainer, user, m.chat_id)
if not resolved:
return
nickname = resolved.nickname
acl = acl or "by-acl"
packages = await fetch_watch_packages(nickname, acl)
if not packages:
await m.answer("Нет устаревших пакетов.")
return
total = len(packages)
page = packages[:PER_PAGE]
await m.answer(
await format_watch_page(page, 0, total),
reply_markup=watch_keyboards.watch_nav_kb(nickname, acl, 0, total, PER_PAGE),
)
@dp.callback_query(CallbackDataMarkup("watch/<maintainer>/<acl>/<offset:int>"))
async def watch_page_handler(
cb: CallbackQuery, maintainer: str, acl: str, offset: int,
) -> None:
packages = await fetch_watch_packages(maintainer, acl)
if not packages:
await cb.answer("Нет устаревших пакетов.")
return
total = len(packages)
page = packages[offset:offset + PER_PAGE]
await cb.edit_text(
await format_watch_page(page, offset, total),
reply_markup=watch_keyboards.watch_nav_kb(maintainer, acl, offset, total, PER_PAGE),
)
await cb.answer()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment