telega/media_group
Media Group Builder module for creating and sending groups of photos, videos, documents, and audio files.
This module provides a fluent builder API for constructing media groups (albums) that can be sent via the Telegram Bot API. Media groups allow you to send multiple media files as a single message, appearing as an album in the Telegram client.
Features
- Builder Pattern: Chain method calls to construct complex media groups
- Type Safety: Validates media compatibility at compile time
- Flexible Input: Supports URLs, file IDs, local files, and raw bytes
- Rich Formatting: Add captions with HTML/Markdown formatting
- Validation: Ensures media groups meet Telegram’s requirements
Telegram API Constraints
- Media groups must contain 2-10 items
- Documents and audio files can only be grouped with media of the same type
- Photos and videos can be mixed in the same group
- Only the first media item’s caption is prominently displayed
Examples
Simple Photo Album
let album = media_group.new()
|> media_group.add_photo_url("https://example.com/photo1.jpg", None)
|> media_group.add_photo_url_with_caption(
"https://example.com/photo2.jpg",
"Beautiful sunset"
)
|> media_group.validate_and_build()
Mixed Media (Photos + Videos)
let mixed = media_group.new()
|> media_group.add_photo_url("https://example.com/photo.jpg", None)
|> media_group.add_video_url_with_caption(
"https://example.com/video.mp4",
"Amazing video"
)
|> media_group.validate_and_build()
Document Group
let docs = media_group.new()
|> media_group.add_document(file.Url("https://example.com/doc1.pdf"), None)
|> media_group.add_document_with_caption(
file.Url("https://example.com/doc2.pdf"),
"Important document"
)
|> media_group.validate_and_build()
Error Handling
The validate_and_build function returns a Result with possible errors:
InvalidMediaCount: Less than 2 or more than 10 itemsIncompatibleMediaTypes: Mixing incompatible media typesEmptyMediaGroup: No media items added
See Also
Types
Media options for animations
pub type AnimationOptions {
AnimationOptions(
caption: option.Option(String),
parse_mode: option.Option(String),
caption_entities: option.Option(List(types.MessageEntity)),
show_caption_above_media: option.Option(Bool),
has_spoiler: option.Option(Bool),
thumbnail: option.Option(String),
width: option.Option(Int),
height: option.Option(Int),
duration: option.Option(Int),
)
}
Constructors
-
AnimationOptions( caption: option.Option(String), parse_mode: option.Option(String), caption_entities: option.Option(List(types.MessageEntity)), show_caption_above_media: option.Option(Bool), has_spoiler: option.Option(Bool), thumbnail: option.Option(String), width: option.Option(Int), height: option.Option(Int), duration: option.Option(Int), )
Media options for audio files
pub type AudioOptions {
AudioOptions(
caption: option.Option(String),
parse_mode: option.Option(String),
caption_entities: option.Option(List(types.MessageEntity)),
duration: option.Option(Int),
performer: option.Option(String),
title: option.Option(String),
thumbnail: option.Option(String),
)
}
Constructors
-
AudioOptions( caption: option.Option(String), parse_mode: option.Option(String), caption_entities: option.Option(List(types.MessageEntity)), duration: option.Option(Int), performer: option.Option(String), title: option.Option(String), thumbnail: option.Option(String), )
Media options for documents
pub type DocumentOptions {
DocumentOptions(
caption: option.Option(String),
parse_mode: option.Option(String),
caption_entities: option.Option(List(types.MessageEntity)),
disable_content_type_detection: option.Option(Bool),
thumbnail: option.Option(String),
)
}
Constructors
-
DocumentOptions( caption: option.Option(String), parse_mode: option.Option(String), caption_entities: option.Option(List(types.MessageEntity)), disable_content_type_detection: option.Option(Bool), thumbnail: option.Option(String), )
A builder for creating media groups
pub type MediaGroupBuilder {
MediaGroupBuilder(media: List(types.InputMedia))
}
Constructors
-
MediaGroupBuilder(media: List(types.InputMedia))
Media group validation errors
pub type MediaGroupError {
InvalidMediaCount(count: Int)
IncompatibleMediaTypes
EmptyMediaGroup
}
Constructors
-
InvalidMediaCount(count: Int)Media group must contain 2-10 items
-
IncompatibleMediaTypesMedia types cannot be mixed (except photo and video)
-
EmptyMediaGroupMedia group is empty
Media options for photos
pub type PhotoOptions {
PhotoOptions(
caption: option.Option(String),
parse_mode: option.Option(String),
caption_entities: option.Option(List(types.MessageEntity)),
show_caption_above_media: option.Option(Bool),
has_spoiler: option.Option(Bool),
)
}
Constructors
-
PhotoOptions( caption: option.Option(String), parse_mode: option.Option(String), caption_entities: option.Option(List(types.MessageEntity)), show_caption_above_media: option.Option(Bool), has_spoiler: option.Option(Bool), )
Media options for videos
pub type VideoOptions {
VideoOptions(
caption: option.Option(String),
parse_mode: option.Option(String),
caption_entities: option.Option(List(types.MessageEntity)),
show_caption_above_media: option.Option(Bool),
has_spoiler: option.Option(Bool),
thumbnail: option.Option(String),
width: option.Option(Int),
height: option.Option(Int),
duration: option.Option(Int),
supports_streaming: option.Option(Bool),
)
}
Constructors
-
VideoOptions( caption: option.Option(String), parse_mode: option.Option(String), caption_entities: option.Option(List(types.MessageEntity)), show_caption_above_media: option.Option(Bool), has_spoiler: option.Option(Bool), thumbnail: option.Option(String), width: option.Option(Int), height: option.Option(Int), duration: option.Option(Int), supports_streaming: option.Option(Bool), )
Values
pub fn add_animation(
builder: MediaGroupBuilder,
media: file.MediaInput,
options: option.Option(AnimationOptions),
) -> MediaGroupBuilder
Adds an animation to the media group
pub fn add_audio(
builder: MediaGroupBuilder,
media: file.MediaInput,
options: option.Option(AudioOptions),
) -> MediaGroupBuilder
Adds an audio file to the media group
pub fn add_audio_with_caption(
builder: MediaGroupBuilder,
media: file.MediaInput,
caption: String,
) -> MediaGroupBuilder
Add an audio file with caption (convenience function)
pub fn add_document(
builder: MediaGroupBuilder,
media: file.MediaInput,
options: option.Option(DocumentOptions),
) -> MediaGroupBuilder
Adds a document to the media group
pub fn add_document_file(
builder: MediaGroupBuilder,
path: String,
options: option.Option(DocumentOptions),
) -> MediaGroupBuilder
Add a document from a file path
pub fn add_document_with_caption(
builder: MediaGroupBuilder,
media: file.MediaInput,
caption: String,
) -> MediaGroupBuilder
Add a document with caption (convenience function)
pub fn add_photo(
builder: MediaGroupBuilder,
media: file.MediaInput,
options: option.Option(PhotoOptions),
) -> MediaGroupBuilder
Adds a photo to the media group with optional formatting options.
Parameters
media: The photo to add (URL, file ID, local file, or bytes)options: Optional formatting settings (caption, parse mode, spoiler, etc.)
Example
media_group.new()
|> media_group.add_photo(
file.Url("https://example.com/photo.jpg"),
Some(PhotoOptions(
caption: Some("Beautiful landscape"),
parse_mode: Some("HTML"),
has_spoiler: Some(False),
..default_photo_options()
))
)
pub fn add_photo_file(
builder: MediaGroupBuilder,
path: String,
options: option.Option(PhotoOptions),
) -> MediaGroupBuilder
Add a photo from a file path
pub fn add_photo_url(
builder: MediaGroupBuilder,
url: String,
options: option.Option(PhotoOptions),
) -> MediaGroupBuilder
Convenience function to add a photo from a URL.
This is a shorthand for add_photo(builder, file.Url(url), options).
pub fn add_photo_url_with_caption(
builder: MediaGroupBuilder,
url: String,
caption: String,
) -> MediaGroupBuilder
Convenience function to add a photo from URL with a caption.
Combines URL input and caption setting in a single call.
pub fn add_photo_with_caption(
builder: MediaGroupBuilder,
media: file.MediaInput,
caption: String,
) -> MediaGroupBuilder
Convenience function to add a photo with just a caption.
Use this when you only need to set a caption without other formatting options.
pub fn add_video(
builder: MediaGroupBuilder,
media: file.MediaInput,
options: option.Option(VideoOptions),
) -> MediaGroupBuilder
Adds a video to the media group with optional formatting options.
Videos can be mixed with photos in the same media group.
Parameters
media: The video to add (URL, file ID, local file, or bytes)options: Optional video settings (caption, dimensions, duration, etc.)
pub fn add_video_file(
builder: MediaGroupBuilder,
path: String,
options: option.Option(VideoOptions),
) -> MediaGroupBuilder
Add a video from a file path
pub fn add_video_url(
builder: MediaGroupBuilder,
url: String,
options: option.Option(VideoOptions),
) -> MediaGroupBuilder
Add a video from a URL
pub fn add_video_url_with_caption(
builder: MediaGroupBuilder,
url: String,
caption: String,
) -> MediaGroupBuilder
Add a video URL with caption (convenience function)
pub fn add_video_with_caption(
builder: MediaGroupBuilder,
media: file.MediaInput,
caption: String,
) -> MediaGroupBuilder
Add a video with caption (convenience function)
pub fn build(
builder: MediaGroupBuilder,
) -> List(types.InputMedia)
Builds the media group and returns the list of InputMedia
pub fn count(builder: MediaGroupBuilder) -> Int
Gets the count of media items in the builder.
Useful for checking if you’re within the 2-10 item limit.
pub fn default_animation_options() -> AnimationOptions
Helper function to create default animation options
pub fn default_audio_options() -> AudioOptions
Helper function to create default audio options
pub fn default_document_options() -> DocumentOptions
Helper function to create default document options
pub fn default_photo_options() -> PhotoOptions
Helper function to create default photo options
pub fn default_video_options() -> VideoOptions
Helper function to create default video options
pub fn first(
builder: MediaGroupBuilder,
) -> option.Option(types.InputMedia)
Gets the first media item if it exists
pub fn from_photo_urls(urls: List(String)) -> MediaGroupBuilder
Creates a media group from a list of photo URLs.
Convenient helper for quickly creating a photo album from URLs.
pub fn from_photos_with_captions(
photos: List(#(String, String)),
) -> MediaGroupBuilder
Creates a media group from a list of photo URLs with captions
pub fn from_video_urls(urls: List(String)) -> MediaGroupBuilder
Creates a media group from a list of video URLs
pub fn last(
builder: MediaGroupBuilder,
) -> option.Option(types.InputMedia)
Gets the last media item if it exists
pub fn new() -> MediaGroupBuilder
Creates a new empty media group builder.
This is the starting point for building a media group. Chain other methods
to add media items, then call validate_and_build() to get the final result.
pub fn photo_with_caption(
media: file.MediaInput,
caption: String,
) -> types.InputMedia
Creates a standalone photo InputMedia with a caption.
Useful when you need to create a single photo for direct use without the builder pattern.
pub fn requires_multipart(builder: MediaGroupBuilder) -> Bool
Checks if any media in the group requires multipart upload
pub fn validate_and_build(
builder: MediaGroupBuilder,
) -> Result(List(types.InputMedia), MediaGroupError)
Validates and builds the final media group.
This function checks that the media group meets Telegram’s requirements:
- Contains 2-10 items
- Uses compatible media types
- Is not empty
pub fn video_with_caption(
media: file.MediaInput,
caption: String,
) -> types.InputMedia
Creates a video with caption