Limit task lists and clamp message length
All checks were successful
publish-images / build (push) Successful in 6s

This commit is contained in:
dan
2026-01-06 10:09:20 +03:00
parent cfbaa7cb90
commit 79bb14f05c
3 changed files with 36 additions and 4 deletions

View File

@@ -39,6 +39,15 @@ docker run -d --name boinc-telegram-bot \
- `/start` или `/status` — сводный дашборд. - `/start` или `/status` — сводный дашборд.
- Кнопки: «Обновить», «Активные», «Очередь», «Готовы к отправке». - Кнопки: «Обновить», «Активные», «Очередь», «Готовы к отправке».
## CI/CD
- Gitea Actions (`.gitea/workflows/publish-images.yml`) собирает образ на пуше в `main` и пушит в `cr.danosito.com/dan/boinc-report-bot` с тегами `latest` и `${{ gitea.sha }}`. Используются `vars.REGISTRY_USER` и `vars.REGISTRY_PASSWORD`.
## Деплой через docker compose
- Пример compose в `deploy/docker-compose.yml` (host network для доступа к локальному BOINC).
- Создайте `.env` рядом с compose с `TELEGRAM_TOKEN` и, при необходимости, `BOINC_PASSWORD`.
- Для обхода блокировок Telegram указаны прокси-переменные (`HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`) на локальный http-proxy `http://127.0.0.1:10809` (контейнер `xray`). Если прокси другой, скорректируйте значения или перенесите их в `.env`.
- Запуск: `docker compose -f deploy/docker-compose.yml up -d`.
## Что под капотом ## Что под капотом
- Python + `python-telegram-bot`. - Python + `python-telegram-bot`.
- Получение статуса через `boinccmd --get_tasks` (RPC на BOINC). - Получение статуса через `boinccmd --get_tasks` (RPC на BOINC).

View File

@@ -41,14 +41,33 @@ def build_keyboard() -> InlineKeyboardMarkup:
async def render_view(view: View, client: BoincClient) -> str: async def render_view(view: View, client: BoincClient) -> str:
MAX_ITEMS = 20
snapshot = await client.fetch_snapshot() snapshot = await client.fetch_snapshot()
if view == "dashboard": if view == "dashboard":
return format_dashboard(snapshot) return format_dashboard(snapshot)
if view == "active": if view == "active":
return format_tasks_section("Активные задачи", snapshot.active) extra = len(snapshot.active) - MAX_ITEMS
text = format_tasks_section("Активные задачи", snapshot.active[:MAX_ITEMS])
if extra > 0:
text += f"\n... и еще {extra} задач(и)"
return text
if view == "queued": if view == "queued":
return format_tasks_section("Ожидают запуска", snapshot.queued) extra = len(snapshot.queued) - MAX_ITEMS
return format_tasks_section("Готовы к отправке", snapshot.completed) text = format_tasks_section("Ожидают запуска", snapshot.queued[:MAX_ITEMS])
if extra > 0:
text += f"\n... и еще {extra} задач(и)"
return text
extra = len(snapshot.completed) - MAX_ITEMS
text = format_tasks_section("Готовы к отправке", snapshot.completed[:MAX_ITEMS])
if extra > 0:
text += f"\n... и еще {extra} задач(и)"
return text
def clamp_message(text: str, limit: int = 3900) -> str:
if len(text) <= limit:
return text
return text[: limit - 80] + "\n...сообщение укорочено, отфильтруйте список"
async def start_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: async def start_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
@@ -63,7 +82,7 @@ async def callback_handler(update: Update, context: ContextTypes.DEFAULT_TYPE) -
client: BoincClient = context.bot_data["boinc_client"] client: BoincClient = context.bot_data["boinc_client"]
view: View = query.data if query.data in {"dashboard", "active", "queued", "completed"} else "dashboard" view: View = query.data if query.data in {"dashboard", "active", "queued", "completed"} else "dashboard"
try: try:
text = await render_view(view, client) text = clamp_message(await render_view(view, client))
except Exception as exc: # broad catch to show meaningful message in chat except Exception as exc: # broad catch to show meaningful message in chat
logger.exception("Error rendering view %s", view) logger.exception("Error rendering view %s", view)
text = f"Не удалось получить данные: {exc}" text = f"Не удалось получить данные: {exc}"

View File

@@ -8,4 +8,8 @@ services:
environment: environment:
- BOINC_HOST=127.0.0.1 - BOINC_HOST=127.0.0.1
- BOINC_PORT=31416 - BOINC_PORT=31416
- HTTP_PROXY=http://127.0.0.1:10809
- HTTPS_PROXY=http://127.0.0.1:10809
- ALL_PROXY=http://127.0.0.1:10809
- NO_PROXY=localhost,127.0.0.1
command: ["python", "-m", "bot.main"] command: ["python", "-m", "bot.main"]