Limit task lists and clamp message length
All checks were successful
publish-images / build (push) Successful in 6s
All checks were successful
publish-images / build (push) Successful in 6s
This commit is contained in:
@@ -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).
|
||||||
|
|||||||
27
bot/main.py
27
bot/main.py
@@ -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}"
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
Reference in New Issue
Block a user