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>
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
## 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` заменяет `"` → `"`).
|
||||
- [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` экранируется (`"`),
|
||||
атрибут остаётся целым.
|
||||
|
||||
## 5. Спека и проверки
|
||||
|
||||
- [x] 5.1 `openspec validate --strict telegram-metabase-match`.
|
||||
- [x] 5.2 `task test` и `task lint` — зелёные.
|
||||
Reference in New Issue
Block a user