Files
avandClaude Opus 4.8 f75d6b1f91 tgbot: выбор кандидата метабазы inline-кнопками в карточке ревью
Когда для распознавания сохранены кандидаты метабазы, карточка подтверждения
бота показывает кнопку «🗂 База (N)». По ней двухшагово (как delete/dismiss)
разворачивается список кандидатов inline-кнопками; выбор пиннит источник через
worker.ChooseCandidate (ручной матч, без авто-раскладки) и обновляет карточку.
Веб остаётся точкой точных правок (ручной ввод id/URL, «без базы»).

Безопасность границы: id кандидата из callback_data валидируется как ULID
(ident.Parse) до доменного вызова, как в вебе. Текст inline-кнопок Telegram не
парсится как HTML — название кандидата в подписи не экранируется.

SDD: change telegram-vybor-nahodok — дельта notifications (ADDED «Выбор
кандидата метабазы из карточки подтверждения бота») + review (MODIFIED
«Разделение труда транспортов»: быстрый выбор кандидата — Telegram-действие).
Влито в specs, change заархивирован. Миграций БД нет (кандидаты уже в БД).

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

40 lines
2.3 KiB
Markdown
Raw Permalink 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. Интерфейс транспорта
- [x] 1.1 `internal/tgbot/bot.go`: добавить в интерфейс `Reviewer` метод
`ChooseCandidate(ctx context.Context, id, candidateID string) error`.
- [x] 1.2 `internal/tgbot/bot_test.go`: дополнить `fakeReviewer` методом
`ChooseCandidate` (запоминает выбор для проверки).
## 2. Клавиатуры (render.go)
- [x] 2.1 `reviewKeyboard`: когда `len(rd.Candidates) > 0`, добавить кнопку
«🗂 База (N)» с callback `sources:<id>`.
- [x] 2.2 Новая `candidatesKeyboard(rd)`: по кнопке на кандидата (дедуп по
`provider:provider_id`, потолок), текст `provider · Title (Year)`, у `Chosen`
префикс «✓ », callback `pick:<id>:<candidateID>`; нижняя кнопка «← Назад» с
callback `srcback:<id>`.
## 3. Обработка callback (bot.go)
- [x] 3.1 `handleCallback`: ветки `sources` (answer + `editMarkup`
списком кандидатов, перечитав `ReviewData`; домен не трогаем) и `srcback`
(answer «Отменено» + `refreshCard`).
- [x] 3.2 Ветка `pick`: валидировать `val` (id кандидата) через `ident.Parse`
(невалидный → answer «Кнопка устарела…», состояние не меняем), затем
`reviewer.ChooseCandidate(ctx, id, candidateID)`; успех → answer «Источник
выбран» + `refreshCard`; ошибка — общая ветка ошибки.
## 4. Тесты
- [x] 4.1 `internal/tgbot`: карточка ревью с кандидатами содержит кнопку
`sources:<id>`; без кандидатов — не содержит.
- [x] 4.2 `sources` разворачивает клавиатуру с кнопками `pick:<id>:<candID>` и
«← Назад»; выбранный кандидат помечен «✓ ».
- [x] 4.3 `pick` с валидным id зовёт `ChooseCandidate` с этим id и обновляет
карточку; `pick` с невалидным id — не зовёт домен.
## 5. Спека и проверки
- [x] 5.1 `openspec validate --strict telegram-vybor-nahodok`.
- [x] 5.2 `task test` и `task lint` — зелёные.