Skip to content

[4.41/TG3b] Telegram outbound media groups: multi-file and multi-attachment sendMediaGroup #278

Description

@patrick-chinchill

Summary

Split out of #227 (size): the outbound half of the Telegram media-group work. post_message still raises "Telegram adapter supports a single file upload per message" / "single attachment upload per message"; upstream sends 2–10 files or attachments as one sendMediaGroup.

The inbound half (polling acknowledgement and checkpoint, incoming albums) lands in the #227 PR.

Upstream change

  • 8d7ccdb1 feat(telegram): support multiple file and attachment uploads (#605) — chat@4.34.0. Multiple files or attachments go out via sendMediaGroup. It requires 2–10 items and rejects an inline keyboard. Photos and videos may mix; documents and audio only group with their own type. The caption goes on the first item, uploads use attach://media{i} multipart parts, and the call returns the last sent message and caches all of them.

Scope

  • post_message: remove the single-file and single-attachment errors (keep "mixing file uploads and attachments" and "Attachment upload payload is empty"). One file / attachment keeps send_document / send_attachment; 2+ go to new _send_document_media_group / _send_attachment_media_group.
  • _validate_media_group_length (2–10, "Telegram media groups support 2-10 files") and _validate_attachment_media_group_types (file → document, audio → audio, else visual; more than one category raises). Reject reply_markup ("Telegram media groups do not support inline keyboards").
  • ATTACHMENT_MEDIA_GROUP_TYPES (audio/file→document/image→photo/video) and TELEGRAM_MEDIA_GROUP_MIN = 2 (TELEGRAM_MEDIA_GROUP_MAX = 10 already exists after [4.41/TG3] Telegram polling & media: await handlers before advancing offset, media groups, multi-file uploads #227).
  • aiohttp.FormData (lazy import) with chat_id, message_thread_id, a media JSON string of InputMedia items and media{i} file parts for binary payloads (URL-only attachments pass the URL as media). Caption + parse_mode on item 0 only, video width/height when integral, same MarkdownV2 → plain fallback as send_document (FormData rebuilt per attempt).
  • Parse and cache every returned message; return the last.

Out of scope

Tests

Port from packages/adapter-telegram/src/index.test.ts (not fidelity-mapped, see #78) into tests/test_telegram_api.py, replacing test_rejects_multiple_attachments:

  • "posts multiple files as a Telegram media group"
  • "posts and normalizes mixed image and video attachments as a Telegram media group"
  • "rejects incompatible Telegram media group attachment types"
  • "rejects Telegram media groups with more than 10 files"

("rejects mixed file uploads and attachments" and "rejects attachments without upload data" are already ported.) Python-specific: inline keyboard rejection and the MarkdownV2 → plain retry on sendMediaGroup.

Acceptance criteria

Metadata

  • Effort: S–M (~450 LOC including tests)
  • Consumer impact: low (Telegram only)
  • Suggested branch: sync/4.41-tg3b

Part of #184. Split from #227.

Activity

  1. patrick-chinchill commented on Oct 1, 2026

    @patrick-chinchill
    CollaboratorAuthor

    Coordination note from #228 (PR #299): Telegram native replies landed without outbound media groups. When #278 adds sendDocumentMediaGroup / sendAttachmentMediaGroup, thread the reply_parameters built at the top of post_message into the sendMediaGroup multipart body (via _append_reply_parameters, as upstream d5ebec12 does) and port the upstream test "threads a media group to its target" from describe("reply").

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions