Files
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

2.7 KiB
Raw Permalink Blame History

1. Ядро: общий билдер URL

  • 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).
  • 1.2 Перенести тесты providerURL/matchURL в internal/worker (из internal/httpapi/providerurl_test.go), поправив на новые имена/сигнатуры.

2. httpapi: делегирование

  • 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: показ матча

  • 3.1 internal/tgbot/render.go: escHref — экранирование URL для значения атрибута href (поверх esc заменяет "&quot;).
  • 3.2 baseLine принимает *worker.ReviewData, использует эффективные rd.Provider/rd.ProviderID и rd.MatchURL(): при непустом URL — <a href="...">provider id ↗</a> (provider/id через esc, URL через escHref), иначе текст provider id; при отсутствии матча — пусто.
  • 3.3 reviewCard зовёт baseLine(rd), при пустом результате показывает «База: нет матча» (сохранение поведения); renderDone добавляет строку «База: …» только при непустом baseLine(rd) (без матча — опускает).

4. Тесты

  • 4.1 internal/tgbot: карточка ревью с матчем содержит <a href=...↗; провайдер/id экранированы; матч без URL — текстом; renderDone содержит строку матча при матче и опускает её без матча; карточка ревью без матча — «нет матча».
  • 4.2 internal/tgbot: id с " — кавычка в href экранируется (&quot;), атрибут остаётся целым.

5. Спека и проверки

  • 5.1 openspec validate --strict telegram-metabase-match.
  • 5.2 task test и task lint — зелёные.