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