Починены краши MarkdownV2: экранирование точек в очках, fallback на plain text

- Очки теперь через _md_escape (4.0 → 4\.0)
- Каждая пара в две строки (белые сверху, чёрные снизу)
- Защита: при ошибке MarkdownV2 парсинга — plain text
- Экранрованы точки в статусных сообщениях
This commit is contained in:
Roman Vrubel 2026-06-14 21:01:10 +00:00
parent 566daf5bb4
commit a17e21c983

View file

@ -72,8 +72,11 @@ def format_pairings(pairings_data: dict, tournament_name: str) -> str:
lines.append( lines.append(
f'{board}\\. {_md_escape(white.name)} ' f'{board}\\. {_md_escape(white.name)} '
f'\\({white.points:.1f}\\) — ' f'\\({_md_escape(f"{white.points:.1f}")}\\)'
f'{_md_escape(black.name)} \\({black.points:.1f}\\)' )
lines.append(
f' {_md_escape(black.name)} '
f'\\({_md_escape(f"{black.points:.1f}")}\\)'
) )
board += 1 board += 1
@ -121,7 +124,7 @@ async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE):
return return
if tournament['current_round'] >= tournament['num_rounds']: if tournament['current_round'] >= tournament['num_rounds']:
await msg.edit_text('🏁 Турнир уже завершён. Жеребьёвки не будет.', await msg.edit_text('🏁 Турнир уже завершён\\. Жеребьёвки не будет\\.',
parse_mode=ParseMode.MARKDOWN_V2) parse_mode=ParseMode.MARKDOWN_V2)
record_request(user.id, url, tournament.get('name', ''), True) record_request(user.id, url, tournament.get('name', ''), True)
return return
@ -178,6 +181,7 @@ async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE):
output = format_pairings(result, tournament['name']) output = format_pairings(result, tournament['name'])
# Telegram has 4096 char limit # Telegram has 4096 char limit
try:
if len(output) > 4000: if len(output) > 4000:
chunks = _chunk_output(output, 3800) chunks = _chunk_output(output, 3800)
await calc_msg.edit_text(chunks[0], parse_mode=ParseMode.MARKDOWN_V2, await calc_msg.edit_text(chunks[0], parse_mode=ParseMode.MARKDOWN_V2,
@ -188,6 +192,16 @@ async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE):
else: else:
await calc_msg.edit_text(output, parse_mode=ParseMode.MARKDOWN_V2, await calc_msg.edit_text(output, parse_mode=ParseMode.MARKDOWN_V2,
disable_web_page_preview=True) disable_web_page_preview=True)
except Exception:
# MarkdownV2 parse failed — fall back to plain text
plain = output.replace('*', '').replace('_', '').replace('\\', '')
if len(plain) > 4000:
chunks = _chunk_output(plain, 3800)
await calc_msg.edit_text(chunks[0])
for chunk in chunks[1:]:
await update.message.reply_text(chunk)
else:
await calc_msg.edit_text(plain)
record_request(user.id, url, tournament.get('name', ''), True) record_request(user.id, url, tournament.get('name', ''), True)