Skip to content

feat(telegram): render Markdown tables as native Rich Messages (opt-in) - #47

Open
hongmono wants to merge 1 commit into
kstost:mainfrom
cloiworks:feat/telegram-rich-message-tables
Open

feat(telegram): render Markdown tables as native Rich Messages (opt-in)#47
hongmono wants to merge 1 commit into
kstost:mainfrom
cloiworks:feat/telegram-rich-message-tables

Conversation

@hongmono

Copy link
Copy Markdown

요약

Telegram이 2026-06-11 Bot API 10.1에서 도입한 Rich Messages(sendRichMessage)를 사용해, 마크다운 표를 네이티브 표로 렌더링합니다.

현재는 모든 응답이 markdown_to_telegram_html() → 구식 sendMessage(HTML)로 나가는데, 이 변환에는 표 처리가 없어 표가 파이프(|) 텍스트로 노출됩니다(시스템 프롬프트도 이 때문에 표를 금지). 신규 API라 리스크를 고려해 per-chat opt-in(기본 OFF) 으로 설계했습니다.

데모

/richmessages on 전후 비교 — 위: OFF(파이프 텍스트), 아래: ON(네이티브 표):

screenshot_demo

변경 사항

src/services/telegram.rs 한 파일, +271/-1. 기존 로직 수정 없이 순수 추가 + 분기.

헬퍼 3개

  • contains_markdown_table() — GFM 표(헤더행 + |---| 구분행) 감지. 코드펜스 내부 제외로 오탐 방지.
  • send_rich_markdown() — teloxide 0.13에 없는 sendRichMessage를 reqwest로 직접 호출. api_base_url(프록시) 존중, 토큰 리댁션, 30s 타임아웃, ok:true만 성공 처리.
  • finalize_as_rich_table() — 롤링 placeholder를 삭제 후 Rich Message로 교체. 실패 시 기존 HTML 경로로 폴백.

설정 · 명령어

  • BotSettings.rich_messages: HashMap<String, bool> (기본 OFF) + bot_settings.json 영속화.
  • /richmessages (on/off/status/토글) — 기존 /fast 패턴과 동일. BotCommand·라우팅·/help 포함.

연동

  • 스트리밍 최종 전송 3경로(handle_text_message·execute_schedule·process_bot_message)에 분기 추가: 표 포함 + 단일 메시지(last_confirmed_len == 0) + opt-in ON일 때만 Rich 전송.
  • 시스템 프롬프트가 설정에 연동되어, ON일 때만 AI에게 표 사용을 허용.

설계 원칙

알려진 범위 (1차)

  • 단일 메시지로 끝나는 응답의 표만 Rich 처리. 4096자 초과로 분할되는 응답은 기존 경로 유지(표는 텍스트). 후속 확장 가능.
  • 스트리밍 중에는 표가 텍스트로 보이다가 완료 시 Rich 표로 교체.

테스트

  • cargo build 통과, 신규 경고 0.
  • 실제 봇 검증:
    • OFF(기본): 표 요청 → 파이프 텍스트(기존 동작 유지) ✅
    • /richmessages on → 설정 저장 확인 ✅ / ON: 표 요청 → 네이티브 표 ✅
    • 코드블록 내 | → 표로 오탐 안 됨 ✅
    • 표 없는 일반 응답 → 회귀 없음 ✅
SCR-20260617-jtbc

Use Telegram Bot API 10.1 sendRichMessage to render Markdown tables
natively instead of leaking pipe characters through the legacy
sendMessage HTML path.

- contains_markdown_table / send_rich_markdown / finalize_as_rich_table
- per-chat opt-in setting rich_messages (default OFF) + /richmessages command
- gate 3 streaming finalize paths; system prompt follows the setting
- always falls back to the existing HTML path on failure (regression-free)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant