Files
jellybit/openspec/changes/archive/2026-07-18-telegram-metabase-match/tasks.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

43 lines
2.7 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.
## 1. Ядро: общий билдер URL
- [x] 1.1 `internal/worker/review.go`: добавить экспортируемую
`func ProviderURL(provider, id, mediaType string) string` (канонический URL;
пустой id / неизвестный провайдер → пусто) и метод
`func (rd *ReviewData) MatchURL() string` (приоритет URL выбранного кандидата
при совпадении provider+id с эффективными, иначе `ProviderURL` по
`rd.Provider`/`rd.ProviderID`/`rd.Plan.Type`).
- [x] 1.2 Перенести тесты `providerURL`/`matchURL` в `internal/worker`
(из `internal/httpapi/providerurl_test.go`), поправив на новые имена/сигнатуры.
## 2. httpapi: делегирование
- [x] 2.1 `internal/httpapi/review.go`/`download.go`: удалить локальные
`providerURL`/`matchURL`; `view.MatchURL = rd.MatchURL()`; `sourceMatchURL`
зовёт `worker.ProviderURL(src.Provider, src.ProviderID, src.Type)`.
`parseProviderURL`/`parseManualSource` остаются в httpapi.
## 3. tgbot: показ матча
- [x] 3.1 `internal/tgbot/render.go`: `escHref` — экранирование URL для значения
атрибута `href` (поверх `esc` заменяет `"``&quot;`).
- [x] 3.2 `baseLine` принимает `*worker.ReviewData`, использует эффективные
`rd.Provider`/`rd.ProviderID` и `rd.MatchURL()`: при непустом URL —
`<a href="...">provider id ↗</a>` (provider/id через `esc`, URL через `escHref`),
иначе текст `provider id`; при отсутствии матча — пусто.
- [x] 3.3 `reviewCard` зовёт `baseLine(rd)`, при пустом результате показывает
«База: нет матча» (сохранение поведения); `renderDone` добавляет строку
«База: …» только при непустом `baseLine(rd)` (без матча — опускает).
## 4. Тесты
- [x] 4.1 `internal/tgbot`: карточка ревью с матчем содержит `<a href=...↗`;
провайдер/id экранированы; матч без URL — текстом; `renderDone` содержит строку
матча при матче и опускает её без матча; карточка ревью без матча — «нет матча».
- [x] 4.2 `internal/tgbot`: id с `"` — кавычка в `href` экранируется (`&quot;`),
атрибут остаётся целым.
## 5. Спека и проверки
- [x] 5.1 `openspec validate --strict telegram-metabase-match`.
- [x] 5.2 `task test` и `task lint` — зелёные.