Files
avandClaude Opus 4.8 4a58b0bda0 tgbot: download id моноширинным (code) для tap-to-copy
Включён HTML parse mode у всех исходящих сообщений бота (send + edit-путь
refreshCard), download id выводится моноширинным <code> — в клиентах Telegram
по нему работает tap-to-copy (скопировать id для /download/{id} или диагностики).
Префикс # / download_id= остаётся вне <code>, чтобы копировался чистый id.

Parse mode делает разметку значимой для всех текстов, поэтому добавлен
escape-хелпер и экранированы все внешние/недоверенные фрагменты: display name,
распознанное название, источник/контекст, целевой путь, причины, provider,
error_code/error_msg (инвариант «выход LLM недоверенный»). esc применяется
последним шагом, после усечения, чтобы обрез не разрубил HTML-сущность.

Capability notifications: два ADDED-требования (формат id + экранирование).
Беклог: задача закрыта, зонтичный telegram-revyu-uvedomleniy обновлён.

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

31 lines
2.2 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/render.go`: добавить хелпер `esc` (экранирование
внешнего текста для HTML parse mode Telegram) и `idCode` (обёртка download id в
`<code>` для tap-to-copy)
- [x] 1.2 `internal/tgbot/bot.go`: в `send()` выставить `ParseMode = HTML`; в
`refreshCard()` выставить `ParseMode = HTML` на edit-конфиге (оба варианта:
с клавиатурой и без)
- [x] 1.3 Заменить вывод download id на `idCode(id)` во всех сообщениях
(`bot.go`: pending/принято/дубль/refine/`opErr`; `render.go`: карточки, дефолтная
ветка `renderCard`, распознаю/раскладываю, done/failed, **`renderDesync`**)
- [x] 1.4 Экранировать все внешние фрагменты в `render.go` через `esc`: display
name / распознанное название, источник/контекст, путь плана, причины,
provider **и `provider_id`**, `error_code`, `error_msg`. Не забыть
**`renderDesync`** (внешний `displayTitle` уходит в `send` с HTML).
**Порядок:** `esc` применяем ПОСЛЕДНИМ шагом — над уже усечённым текстом
(после `shorten`/`tailPath`/`firstLine`), иначе обрез посреди сущности
`&lt;` даст битую разметку → Telegram 400 → сообщение не доставится.
## 2. Тесты
- [x] 2.1 `internal/tgbot/bot_test.go`: обновить ожидания текста под `<code>`-id
- [x] 2.2 Добавить тест: внешний фрагмент со спецсимволами (`<`/`>`/`&`) в
уведомлении экранируется (не ломает разметку) — покрыть desync/failed-путь и
кейс усечения длинного значения со спецсимволом у границы `shorten`
## 3. Спека
- [x] 3.1 Дельта `notifications` (два ADDED-требования); `openspec validate
--strict telegram-download-id-code`