95 lines
3.7 KiB
Markdown
95 lines
3.7 KiB
Markdown
# 🐛 Исправление ошибки "Can't parse entities"
|
||
|
||
## Проблема
|
||
|
||
Бот получал ошибки при отправке длинных HTML-сообщений:
|
||
|
||
```
|
||
telegram.error.BadRequest: Can't parse entities: unexpected end tag at byte offset 1381
|
||
telegram.error.BadRequest: Message is too long
|
||
```
|
||
|
||
## Причина
|
||
|
||
1. **`send_long_message_html`** получал текст с HTML-тегами от Qwen
|
||
2. Пытался конвертировать его из Markdown → HTML (двойная конвертация)
|
||
3. При разбивке на части HTML-теги разрывались (`<b>` в одной части, `</b>` в другой)
|
||
4. Telegram отклонял сообщения с битыми тегами
|
||
|
||
## Решение
|
||
|
||
### 1. Улучшена обработка ошибок в `send_long_message`
|
||
|
||
**Файл:** `bot/utils/formatters.py`
|
||
|
||
Добавлен fallback для битых HTML-тегов:
|
||
|
||
```python
|
||
except Exception as e:
|
||
logger.warning(f"Ошибка HTML (parse_mode={actual_parse_mode}): {e}")
|
||
|
||
# Проверяем это ошибка парсинга HTML — пробуем экранировать
|
||
if "parse" in str(e).lower() or "tag" in str(e).lower():
|
||
import html as html_lib
|
||
safe_part = html_lib.escape(part)
|
||
try:
|
||
await send_method(safe_part, parse_mode=None)
|
||
except Exception as e2:
|
||
# Последняя попытка — обрезать до безопасного размера
|
||
safe_part = safe_part[:4000] + "... (обрезано)"
|
||
await send_method(safe_part, parse_mode=None)
|
||
```
|
||
|
||
### 2. Улучшена обработка в `send_long_message_html`
|
||
|
||
Добавлен многоуровневый fallback:
|
||
|
||
```python
|
||
try:
|
||
return await send_long_message(update, html_text, parse_mode=ParseMode.HTML, ...)
|
||
except Exception as e:
|
||
logger.warning(f"Ошибка отправки HTML: {e}")
|
||
|
||
# Если HTML не работает — экранируем и отправляем как plain text
|
||
escaped_text = html_lib.escape(html_text)
|
||
|
||
try:
|
||
return await send_long_message(update, escaped_text, parse_mode=None, ...)
|
||
except Exception as e2:
|
||
# Последний fallback — обрезаем до безопасного размера
|
||
safe_text = escaped_text[:4000] + "... (обрезано)"
|
||
return await send_long_message(update, safe_text, parse_mode=None, ...)
|
||
```
|
||
|
||
## Уровни защиты
|
||
|
||
| Уровень | Действие | Когда |
|
||
|---------|----------|-------|
|
||
| 1 | Отправка HTML | Нормальная работа |
|
||
| 2 | Экранирование HTML | Битые теги |
|
||
| 3 | Обрезка до 4000 символов | Слишком длинное сообщение |
|
||
|
||
## Тестирование
|
||
|
||
Проверьте отправку длинных сообщений:
|
||
|
||
```bash
|
||
# Отправьте боту запрос который вернёт длинный ответ
|
||
"Напиши подробное руководство по Python asyncio"
|
||
```
|
||
|
||
**Ожидаемое поведение:**
|
||
- Короткие сообщения отправляются в HTML
|
||
- Длинные сообщения разбиваются на части
|
||
- При ошибках HTML — экранируются и отправляются как текст
|
||
- Сообщения >4000 символов обрезаются с уведомлением
|
||
|
||
## Файлы изменены
|
||
|
||
- `bot/utils/formatters.py` — улучшена обработка ошибок HTML
|
||
|
||
---
|
||
|
||
**Дата исправления:** 2026-03-09
|
||
**Версия бота:** 0.9.0
|