8000
Skip to content

Support telegram rich messages as a hint part - #333

Draft
bomzheg wants to merge 2 commits into
masterfrom
claude/telegram-rich-messages-ogwk6c
Draft

Support telegram rich messages as a hint part#333
bomzheg wants to merge 2 commits into
masterfrom
claude/telegram-rich-messages-ogwk6c

Conversation

@bomzheg
@bomzheg bomzheg commented Aug 6, 2026
Copy link
Copy Markdown
Owner

Closes #295.

Bot API 10.1 added rich messages — a message built from blocks: headings, lists, tables, quotes, embedded media. A hint written that way says much more than a single run of text, so the scenario now carries a hint part for it.

What changed

Domain (core)

  • HintType.rich and hints.RichHint: the markup itself (text), the language it is written in (RichFormat.html / RichFormat.markdown), the is_rtl / skip_entity_detection flags telegram accepts, and media — the files the markup embeds, each bound to the id the markup refers to ('<img src="pic">').
  • get_guids() returns those file guids, so embedded files are packed into the scenario zip, validated on upload and copied with the game like any other hint file — no separate plumbing.
  • Search looks inside a rich hint's markup, and the hint renders as 📰 in the bot's hint listings.

Bot (tgbot)

  • RichHintLinkView / RichHintContentView build an InputRichMessage, and HintSender sends it through sendRichMessage — by file_id, and by content when a file was never uploaded to telegram.
  • Embedded media becomes InputMediaPhoto / Video / Animation / Audio by the stored file's content type; anything else is rejected with UnsupportedFileFormat rather than sent as something it isn't.
  • "Can this be sent as a link?" moved onto the link view itself. A rich message has many files, and any one of them missing a file_id has to send the whole message by content — the old sentinel on HintSender could only ask about a single file_id attribute.

API — no code change: hints are exposed as the core dataclasses and scenarios load straight into them, so type: "rich" round-trips through PUT /games/my/{id}/scenario as it stands. There is an integration test pinning that down.

Dependency — aiogram 3.26 → 3.30 for send_rich_message (Bot API 9.5 → 10.2). ChatMemberRestricted gained a required field in between, hence the one-line test fixture change; lock.txt is pinned to match.

Tests

  • tests/unit/test_rich_hint_view.py — html vs markdown, the flags, media by file_id and by content, the fallback when a file_id is missing, unsupported media types.
  • tests/unit/serialization — the all_types scenario fixture now carries a rich hint, so deserialization and hint rendering cover it.
  • tests/integration/bot_full/test_hint_sender.py — the four sendRichMessage paths.
  • tests/integration/api_full/test_game_edit.py — markup, format and embedded media survive the scenario API round trip.

Unit tests, ruff and mypy pass locally; the integration suite needs docker, so it runs in CI.

Not in this change

  • Composing a rich hint in the bot. Telegram gives an incoming rich message as its parsed blocks, and turning those back into markup is a converter of its own — an author assembles a rich hint in the web constructor instead (see the companion UI PR, and the note added to the author docs). A rich message that arrives with a plain-text body still parses as a text hint, as before.
  • Renewing the file_id after sending by content. The returned message's blocks carry no link back to our media ids, so a rich hint is re-uploaded rather than re-linked. Renewal is best-effort for every hint type; nothing breaks.

Generated by Claude Code

@bomzheg
bomzheg marked this pull request as ready for review August 7, 2026 17:02
@bomzheg
bomzheg marked this pull request as draft August 10, 2026 21:05
claude added 2 commits August 20, 2026 22:21
Bot API 10.1 added rich messages - a message built from blocks: headings,
lists, tables, quotes, embedded media. A hint written that way says much
more than the plain text hints authors have today, so the scenario now
carries a hint part for it.

- ``RichHint`` holds the markup itself plus the language it is written in
  (Rich HTML or Rich Markdown) and the files embedded into it, each bound
  to the id the markup refers to;
- the files live under their usual guids, so they are packed into the
  scenario zip and validated like any other hint file;
- both hint views build ``InputRichMessage``, so a rich hint goes out
  through ``sendRichMessage`` by file_id, and by content when a file was
  never uploaded to telegram;
- the "can this be sent as a link" question moved onto the link view
  itself - a rich message has many files, and any one of them missing a
  file_id sends the whole message by content.

aiogram is bumped to 3.30 for the new method; ``ChatMemberRestricted``
gained a required field in the meantime, hence the test fixture change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HR7ByNGirgnXDGjqvKtXr7
The author docs list what a hint part can be, and the glossary names every
concept the code has, so both learn about the new one - including the part
authors need to know: a rich hint is assembled on the site, not in the bot.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HR7ByNGirgnXDGjqvKtXr7
@bomzheg
bomzheg force-pushed the claude/telegram-rich-messages-ogwk6c branch from 09ad882 to ff6568d Compare August 20, 2026 19:22
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.

support rich message

2 participants

0