Files
jellybit/openspec/changes/archive/2026-07-18-telegram-metabase-match/proposal.md
T
avandClaude Opus 4.8 10a6348d39 tgbot: показывать запись матча метабазы (провайдер+id+ссылка)
В карточке подтверждения и уведомлении о готовности бот теперь показывает
запись матча метабазы — провайдер, id и кликабельную ссылку на страницу
записи, — как веб-страница /download/{id} и экран ревью. Так ошибочную
привязку видно и из Telegram.

Билдер URL записи (providerURL/matchURL) вынесен из internal/httpapi в ядро
internal/worker (worker.ProviderURL + метод (*ReviewData).MatchURL()), чтобы
оба транспорта строили ссылку одинаково; httpapi делегирует туда. baseLine
переведён на эффективные provider/id (с учётом ручных правок), URL в href
экранируется escHref (сверх esc закрывает кавычку — иначе изготовленный id
разорвал бы атрибут и Telegram отклонил бы сообщение). При отсутствии матча
карточка ревью показывает «нет матча», уведомление о готовности строку
опускает.

Capability notifications: ADDED «Показ записи матча метабазы» + MODIFIED
требования об экранировании (id матча и URL, контекст href).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-18 15:41:28 +03:00

59 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## Why
Веб уже показывает, с какой именно записью метабазы сматчилась загрузка:
страница `/download/{id}` и экран ревью выводят provider, id и — если URL
строится — ссылку на страницу записи (`internal/httpapi`: `matchURL`/
`providerURL`, шаблон `download_main.html`). В Telegram матч показан беднее:
карточка ревью (`internal/tgbot/render.go`, `baseLine`) выводит только
`provider id` из **сырого** распознавания и **без ссылки**, а уведомление о
готовности матч не показывает вовсе. Из-за этого ошибочную привязку (не тот
фильм/сезон) из бота не видно — приходится открывать веб.
## What Changes
- **Карточка подтверждения (review)** в боте показывает матч со **ссылкой** на
запись метабазы (когда URL строится) — как веб: `provider id ↗`. Без URL —
тем же текстом, что и раньше.
- **Уведомление о готовности** (`renderDone`) показывает строку матча (provider,
id, ссылка) — чтобы ошибочную привязку было видно и в финальном пинге.
- **Provider/id берутся эффективные** (`ReviewData.Provider`/`ProviderID`, с
учётом ручных правок), консистентно с веб-страницей и экраном ревью, а не из
сырого распознавания.
- **Единый билдер URL:** канонический `providerURL` и выбор ссылки матча
`matchURL` переезжают из `internal/httpapi` в ядро `internal/worker`
(`worker.ProviderURL` + метод `(*ReviewData).MatchURL()`), чтобы оба
транспорта (веб и Telegram) строили ссылку одинаково. httpapi делегирует туда.
- **Экранирование:** provider, id и URL — недоверенные, экранируются перед
вставкой в HTML-сообщение (инвариант «выход LLM недоверенный»); ссылка
рисуется только при непустом URL. URL — в контексте атрибута `href`: помимо
`<`/`>`/`&` экранируется и кавычка (иначе изготовленный id разорвёт атрибут и
Telegram отклонит сообщение).
## Capabilities
### New Capabilities
Нет.
### Modified Capabilities
- `notifications`: добавляется требование к **содержанию** уведомлений/
подтверждений — показ записи матча метабазы (provider, id, ссылка) в карточке
ревью и уведомлении о готовности, эффективным провайдером, с экранированием.
Условия и события доставки (падение, review, готовность, рассинхрон) без
изменений.
## Impact
- **Спеки:** дельта `notifications` — ADDED «Показ записи матча метабазы» +
MODIFIED «Экранирование внешнего текста» (в перечень добавлены id матча и URL,
экранирование учитывает контекст `href`/кавычку).
- **Код:** `internal/worker/review.go` (новые `ProviderURL` + метод `MatchURL`),
`internal/httpapi/review.go`/`download.go` (делегируют в worker; локальные
`providerURL`/`matchURL` удаляются, `sourceMatchURL` зовёт `worker.ProviderURL`),
`internal/tgbot/render.go` (`baseLine` по `ReviewData` со ссылкой; строка матча
в `renderDone`).
- **Тесты:** тесты `providerURL`/`matchURL` переезжают в `internal/worker`;
`internal/tgbot` — проверка ссылки и экранирования в строке матча.
- **Миграции БД:** нет (данные матча уже в БД).