telegram

package
v0.11.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2026 License: MIT Imports: 25 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MessageEntityProjectionMaxEntities         = 4_096
	MessageEntityProjectionMaxSourceCharacters = 32_768
	MessageEntityProjectionMaxNestingDepth     = RichMessageMaxNestingDepth
	MessageEntityProjectionMaxMetadataBytes    = 64 << 10
	MessageEntityProjectionMaxOutputCharacters = 1_048_576
)

Internal safety budgets for projecting ordinary Telegram message entities. Telegram doesn't publish an entity-count limit, so the count is deliberately generous while still bounding overlap validation. The output allowance is shared in spirit with rich-message projection and comfortably exceeds the maximum ordinary message size.

View Source
const (
	RichMessageMaxCharacters   = 32_768
	RichMessageMaxBlocks       = 500
	RichMessageMaxNestingDepth = 16
	RichMessageMaxMedia        = 50
	RichMessageMaxTableColumns = 20
)

Telegram Bot API 10.2 limits for received rich messages. The decoder is deliberately tolerant; these limits are enforced by ProjectRichMessage so an unknown discriminator doesn't make encoding/json discard the whole Update.

View Source
const (
	RichProjectionMaxTextNodes        = 65_536
	RichProjectionMaxOutputCharacters = 1_048_576
)

Internal safety budgets bound valid-but-adversarial entity arrays and the transport-neutral Markdown result. They are deliberately above Telegram's source-text ceiling and don't redefine any Bot API content limit.

View Source
const (

	// MaxRichMessageMedia is Telegram's current InputRichMessage.media limit.
	// Keeping it at the wire boundary prevents callers from building a request
	// that Telegram can only reject after all local files have been uploaded.
	MaxRichMessageMedia = 50
)

Variables

View Source
var ErrFileDownloadTooLarge = errors.New("telegram file exceeds download limit")

ErrFileDownloadTooLarge is returned when Telegram advertises or sends more than the active caller/per-file limit. Callers can use errors.Is to distinguish a permanent size rejection from a transient download failure.

View Source
var ErrMessageNotModified = errors.New("telegram: message is not modified")

ErrMessageNotModified is returned by EditMessageText when Telegram rejects an edit because the new text and entities are identical to the current message. Callers should treat this as a successful no-op.

Functions

func AllowedUpdateTypes added in v0.11.0

func AllowedUpdateTypes() []string

AllowedUpdateTypes is the single subscription source for both webhook and long polling. Keep it aligned with fields actually decoded and handled by Update; subscribing to an update kind and then silently acknowledging it is data loss.

func BuildRichPhotoMedia added in v0.11.0

func BuildRichPhotoMedia(uploads []RichPhotoUpload) ([]InputRichMessageMedia, []RichMessageAttachment, error)

BuildRichPhotoMedia converts trusted local photos into the two parallel arrays required by sendRichMessage. Identifiers are stable by input order, ASCII-only and intentionally independent from filenames supplied by tools. The returned media IDs can be referenced as tg://photo?id=<ID> by the rich HTML compositor.

func IsSafeSplitPosition

func IsSafeSplitPosition(pos int, blocks []CodeBlock) bool

IsSafeSplitPosition checks if a byte position is safe for splitting (not inside a protected block)

func SplitMessageSmart

func SplitMessageSmart(text string, limit int) []string

SplitMessageSmart splits a long message into chunks of at most limit RUNES. It preserves markdown structure: code blocks and tables are never cut at safe-point selection; oversized tables are split between rows with the header repeated in every piece.

func ValidateRichMessageRequest added in v0.11.0

func ValidateRichMessageRequest(req SendRichMessageRequest) error

ValidateRichMessageRequest checks the complete Rich Message media graph without serializing a multipart body or issuing a network request. It is intended for callers that must finish preflight before recording a non-idempotent delivery attempt.

Types

type APIError added in v0.11.0

type APIError struct {
	Code        int                 `json:"error_code"`
	Description string              `json:"description"`
	Parameters  *ResponseParameters `json:"parameters,omitempty"`
}

APIError is a structured failure returned by the Telegram API. Callers treat 4xx responses as confirmed request rejections; 5xx remains an unknown send outcome because the server may have accepted a non-idempotent request before failing. Network and response-decoding failures are returned as other error types and are unknown as well.

func (*APIError) Error added in v0.11.0

func (e *APIError) Error() string

type APIResponse

type APIResponse struct {
	Ok          bool                `json:"ok"`
	Result      json.RawMessage     `json:"result,omitempty"`
	Description string              `json:"description,omitempty"`
	ErrorCode   int                 `json:"error_code,omitempty"`
	Parameters  *ResponseParameters `json:"parameters,omitempty"`
}

APIResponse represents a response from the Telegram API.

type Animation added in v0.11.0

type Animation struct {
	FileID       string     `json:"file_id"`
	FileUniqueID string     `json:"file_unique_id"`
	Width        int        `json:"width"`
	Height       int        `json:"height"`
	Duration     int        `json:"duration"`
	Thumbnail    *PhotoSize `json:"thumbnail,omitempty"`
	FileName     string     `json:"file_name,omitempty"`
	MimeType     string     `json:"mime_type,omitempty"`
	FileSize     int64      `json:"file_size,omitempty"`
}

Animation represents an animation file (GIF or silent MPEG-4 video). FileSize is int64 because Bot API file sizes may exceed 2^31.

type Audio added in v0.6.0

type Audio struct {
	FileID       string     `json:"file_id"`
	FileUniqueID string     `json:"file_unique_id"`
	Duration     int        `json:"duration"`
	Performers   string     `json:"performer,omitempty"`
	Title        string     `json:"title,omitempty"`
	FileName     string     `json:"file_name,omitempty"`
	MimeType     string     `json:"mime_type,omitempty"`
	FileSize     int64      `json:"file_size,omitempty"`
	Thumbnail    *PhotoSize `json:"thumbnail,omitempty"`
}

Audio represents an audio file (MP3, etc.).

type BotAPI

type BotAPI interface {
	SendMessage(ctx context.Context, req SendMessageRequest) (*Message, error)
	SendRichMessage(ctx context.Context, req SendRichMessageRequest) (*Message, error)
	SendRichMessageDraft(ctx context.Context, req SendRichMessageDraftRequest) error
	EditMessageText(ctx context.Context, req EditMessageTextRequest) (*Message, error)
	SendPhoto(ctx context.Context, req SendPhotoRequest) (*Message, error)
	SendDocument(ctx context.Context, req SendDocumentRequest) (*Message, error)
	SendMediaGroup(ctx context.Context, req SendMediaGroupRequest) ([]Message, error)
	SendMediaGroupDocuments(ctx context.Context, req SendMediaGroupDocumentsRequest) ([]Message, error)
	SetMyCommands(ctx context.Context, req SetMyCommandsRequest) error
	SetWebhook(ctx context.Context, req SetWebhookRequest) error
	SendChatAction(ctx context.Context, req SendChatActionRequest) error
	GetFile(ctx context.Context, req GetFileRequest) (*File, error)
	SetMessageReaction(ctx context.Context, req SetMessageReactionRequest) error
	GetUpdates(ctx context.Context, req GetUpdatesRequest) ([]Update, error)
	GetToken() string
}

BotAPI defines the interface for the Telegram Bot API methods we use. This allows for easier mocking in tests.

func NewExtendedClient

func NewExtendedClient(token, proxyURL string) (BotAPI, error)

type BotCommand

type BotCommand struct {
	Command     string `json:"command"`
	Description string `json:"description"`
}

BotCommand represents a bot command.

type Chat

type Chat struct {
	ID       int64  `json:"id"`
	Type     string `json:"type"`
	Title    string `json:"title,omitempty"`
	Username string `json:"username,omitempty"`
}

Chat represents a chat.

func (*Chat) Format

func (c *Chat) Format() string

Format formats chat information for display.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a client for the Telegram Bot API.

ARCHITECTURAL DECISION: Two separate HTTP clients

Problem: Using a single HTTP client for all requests caused sporadic "context deadline exceeded (Client.Timeout exceeded while awaiting headers)" errors for sendMessage, sendChatAction, and getUpdates.

Cause: Long polling (getUpdates with Timeout=25s) held connections from the shared pool for long periods. Under high load or network delays, other requests could not get a free connection and timed out.

Solution:

  1. httpClient - for short API calls (sendMessage, sendChatAction, etc.) with a bounded timeout. Idempotent operations may retry; persistent message sends are one-shot because their outcome can become ambiguous.
  2. longPollingClient - for getUpdates with no timeout (controlled via context), isolated connection pool

Additionally, HTTP/2 is disabled (ForceAttemptHTTP2=false), since multiplexing requests over a single connection aggravated the resource contention problem.

func NewClient

func NewClient(token, proxyURL string) (*Client, error)

NewClient creates a new Telegram API client.

Creates two isolated HTTP clients with different settings:

  • httpClient: 30s timeout for sendMessage/sendChatAction (retry policy is selected per method)
  • longPollingClient: no timeout (controlled via context), for getUpdates

func (*Client) EditMessageText added in v0.9.0

func (c *Client) EditMessageText(ctx context.Context, req EditMessageTextRequest) (*Message, error)

EditMessageText edits the text of a message. Used by the streaming sink to progressively reveal the bot's reply.

Special-case error: when Telegram rejects the edit because the new text equals the existing one (HTTP 400 "message is not modified"), this method returns the typed sentinel ErrMessageNotModified so callers can ignore it without string-matching API descriptions.

func (*Client) GetFile

func (c *Client) GetFile(ctx context.Context, req GetFileRequest) (*File, error)

GetFile returns a File object with a file_path that can be used to download the file.

func (*Client) GetUpdates

func (c *Client) GetUpdates(ctx context.Context, req GetUpdatesRequest) ([]Update, error)

GetUpdates receives incoming updates using long polling.

IMPORTANT: Uses the dedicated longPollingClient with Timeout=0.

Long polling works like this: Telegram keeps the connection open for up to req.Timeout seconds, waiting for new messages. If messages arrive earlier, it returns them immediately. If not, it returns an empty array on timeout.

Why a separate client: - httpClient has a 15s timeout, which is less than the typical req.Timeout (25s) - Using a shared connection pool created contention with short requests - An isolated transport guarantees long polling does not affect sendMessage

Timeout is controlled via context: req.Timeout + 10 seconds for network delays.

Metrics: records request duration, long polling status, and number of updates.

func (*Client) SendChatAction

func (c *Client) SendChatAction(ctx context.Context, req SendChatActionRequest) error

SendChatAction tells the user that something is happening on the bot's side.

func (*Client) SendDocument added in v0.8.0

func (c *Client) SendDocument(ctx context.Context, req SendDocumentRequest) (*Message, error)

SendDocument uploads a file (preserving original bytes — no recompression) and returns the resulting message.

func (*Client) SendMediaGroup added in v0.8.0

func (c *Client) SendMediaGroup(ctx context.Context, req SendMediaGroupRequest) ([]Message, error)

SendMediaGroup uploads 2–10 photos as an album and returns the resulting messages (one per photo). For a single photo, use SendPhoto instead.

func (*Client) SendMediaGroupDocuments added in v0.8.0

func (c *Client) SendMediaGroupDocuments(ctx context.Context, req SendMediaGroupDocumentsRequest) ([]Message, error)

SendMediaGroupDocuments uploads 2–10 documents as a grouped album. Unlike SendMediaGroup (photos), Telegram does not recompress documents.

func (*Client) SendMessage

func (c *Client) SendMessage(ctx context.Context, req SendMessageRequest) (*Message, error)

SendMessage sends a text message.

func (*Client) SendPhoto added in v0.8.0

func (c *Client) SendPhoto(ctx context.Context, req SendPhotoRequest) (*Message, error)

SendPhoto uploads a photo via multipart and returns the resulting message.

func (*Client) SendRichMessage added in v0.11.0

func (c *Client) SendRichMessage(ctx context.Context, req SendRichMessageRequest) (*Message, error)

SendRichMessage sends an HTML rich message.

func (*Client) SendRichMessageDraft added in v0.11.0

func (c *Client) SendRichMessageDraft(ctx context.Context, req SendRichMessageDraftRequest) error

SendRichMessageDraft streams an ephemeral rich snapshot. Repeating a call with the same non-zero draft ID updates that draft instead of creating a persistent message, so transient transport failures may be retried safely.

func (*Client) SetMessageReaction

func (c *Client) SetMessageReaction(ctx context.Context, req SetMessageReactionRequest) error

SetMessageReaction sets a reaction on a message.

func (*Client) SetMyCommands

func (c *Client) SetMyCommands(ctx context.Context, req SetMyCommandsRequest) error

SetMyCommands changes the list of the bot's commands.

func (*Client) SetWebhook

func (c *Client) SetWebhook(ctx context.Context, req SetWebhookRequest) error

SetWebhook specifies a URL and receives incoming updates via an outgoing webhook.

type CodeBlock

type CodeBlock struct {
	Start int
	End   int
}

CodeBlock represents a protected byte range [Start, End) that must not be split (code blocks, tables).

func FindCodeBlocks

func FindCodeBlocks(text string) []CodeBlock

FindCodeBlocks finds all code blocks in the text and returns their positions

func FindProtectedBlocks added in v0.10.1

func FindProtectedBlocks(text string) []CodeBlock

FindProtectedBlocks returns every byte range that must not be split: code blocks plus markdown tables. Table ranges overlapping a code block are dropped — pipe-prefixed lines inside a fence are already protected.

type DirectMessagesTopic added in v0.11.0

type DirectMessagesTopic struct {
	TopicID int64 `json:"topic_id"`
}

DirectMessagesTopic is kept minimal because v1 only needs to detect this context and keep outbound rich delivery on the legacy path until its routing identifiers are carried by SendRichMessageRequest.

type Document

type Document struct {
	FileID       string `json:"file_id"`
	FileUniqueID string `json:"file_unique_id"`
	FileName     string `json:"file_name,omitempty"`
	MimeType     string `json:"mime_type,omitempty"`
	FileSize     int64  `json:"file_size,omitempty"`
}

Document represents a general file (as opposed to photos, voice messages and audio files).

type EditMessageTextRequest added in v0.9.0

type EditMessageTextRequest struct {
	ChatID    int64  `json:"chat_id"`
	MessageID int    `json:"message_id"`
	Text      string `json:"text"`
	ParseMode string `json:"parse_mode,omitempty"`
}

EditMessageTextRequest represents the parameters for the editMessageText method. MessageThreadID is not editable (Telegram derives it from MessageID), so it is omitted here. Used by the streaming sink to update an in-flight reply.

type ExtendedClient

type ExtendedClient struct {
	*Client
}

Wrapper for telegram.Client to implement BotAPI interface

func (*ExtendedClient) GetToken

func (c *ExtendedClient) GetToken() string

type File

type File struct {
	FileID       string `json:"file_id"`
	FileUniqueID string `json:"file_unique_id"`
	FileSize     int64  `json:"file_size,omitempty"`
	FilePath     string `json:"file_path,omitempty"`
}

File represents a file ready to be downloaded.

type FileDownloader

type FileDownloader interface {
	DownloadFile(ctx context.Context, fileID string) ([]byte, error)
	// DownloadFileWithLimit applies a caller-provided byte ceiling before the
	// response is buffered. It is used by aggregate-budget schedulers, where the
	// ordinary per-file ceiling is too coarse to bound concurrent allocations.
	DownloadFileWithLimit(ctx context.Context, fileID string, maxBytes int64) ([]byte, error)
	DownloadFileAsBase64(ctx context.Context, fileID string) (string, error)
}

FileDownloader defines an interface for downloading files from Telegram.

type GetFileRequest

type GetFileRequest struct {
	FileID string `json:"file_id"`
}

GetFileRequest represents the parameters for the getFile method.

type GetUpdatesRequest

type GetUpdatesRequest struct {
	Offset         int      `json:"offset,omitempty"`
	Limit          int      `json:"limit,omitempty"`
	Timeout        int      `json:"timeout,omitempty"`
	AllowedUpdates []string `json:"allowed_updates,omitempty"`
}

GetUpdatesRequest represents the parameters for the getUpdates method.

type HTTPFileDownloader

type HTTPFileDownloader struct {
	// contains filtered or unexported fields
}

HTTPFileDownloader is a concrete implementation of FileDownloader using HTTP.

func NewHTTPFileDownloader

func NewHTTPFileDownloader(api BotAPI, fileBaseURL, proxyURL string) (*HTTPFileDownloader, error)

NewHTTPFileDownloader creates a new HTTPFileDownloader.

HTTP client configured with: - 60s timeout for large file downloads - DisableKeepAlives to avoid connection pool issues - Reasonable timeouts for dial/TLS/headers - Proxy support (uses proxyURL if provided, otherwise falls back to environment)

func (*HTTPFileDownloader) DownloadFile

func (d *HTTPFileDownloader) DownloadFile(ctx context.Context, fileID string) ([]byte, error)

DownloadFile downloads a file from Telegram.

func (*HTTPFileDownloader) DownloadFileAsBase64

func (d *HTTPFileDownloader) DownloadFileAsBase64(ctx context.Context, fileID string) (string, error)

DownloadFileAsBase64 downloads a file and encodes it as a Base64 string.

func (*HTTPFileDownloader) DownloadFileWithLimit added in v0.11.0

func (d *HTTPFileDownloader) DownloadFileWithLimit(ctx context.Context, fileID string, maxBytes int64) ([]byte, error)

DownloadFileWithLimit downloads a file while enforcing the caller's byte reservation before buffering the body. The global Telegram limit remains an upper bound even if a larger value is supplied.

type InputMediaDocument added in v0.8.0

type InputMediaDocument struct {
	Data      []byte
	Filename  string
	Caption   string
	ParseMode string
}

InputMediaDocument is one entry of a document-type sendMediaGroup.

type InputMediaPhoto added in v0.8.0

type InputMediaPhoto struct {
	// Data holds the raw image bytes; the corresponding media JSON entry will
	// reference "attach://photo_<index>".
	Data     []byte
	Filename string // e.g. "generated_1.png"
	Caption  string // optional; only the first item's caption is shown on the group
	// ParseMode applies to Caption; uses "HTML" by default when empty.
	ParseMode string
}

InputMediaPhoto is one entry of a sendMediaGroup request.

type InputRichMessage added in v0.11.0

type InputRichMessage struct {
	HTML                string                  `json:"html,omitempty"`
	Media               []InputRichMessageMedia `json:"media,omitempty"`
	SkipEntityDetection bool                    `json:"skip_entity_detection,omitempty"`
}

InputRichMessage contains the HTML representation accepted by Telegram's sendRichMessage method. Media entries bind tg://photo?id=<ID> references in HTML to Telegram InputMedia objects. Local uploads additionally require a matching RichMessageAttachment on SendRichMessageRequest.

type InputRichMessageMedia added in v0.11.0

type InputRichMessageMedia struct {
	ID    string                `json:"id"`
	Media InputRichMessagePhoto `json:"media"`
}

InputRichMessageMedia is the official InputRichMessageMedia envelope. ID is referenced by rich HTML as tg://photo?id=<ID>; Media describes the actual Telegram photo source.

type InputRichMessagePhoto added in v0.11.0

type InputRichMessagePhoto struct {
	Media string `json:"media"`
}

InputRichMessagePhoto is the photo-only subset of Telegram's InputMedia union used by outgoing rich messages. The wire type is always "photo", so callers cannot accidentally construct a mismatched media discriminator.

func (InputRichMessagePhoto) MarshalJSON added in v0.11.0

func (p InputRichMessagePhoto) MarshalJSON() ([]byte, error)

type Location added in v0.11.0

type Location struct {
	Latitude             float64 `json:"latitude"`
	Longitude            float64 `json:"longitude"`
	HorizontalAccuracy   float64 `json:"horizontal_accuracy,omitempty"`
	LivePeriod           int     `json:"live_period,omitempty"`
	Heading              int     `json:"heading,omitempty"`
	ProximityAlertRadius int     `json:"proximity_alert_radius,omitempty"`
}

Location represents a point on the map. Live-location-only fields are kept so a future Bot API response can be projected without silently losing them.

type MediaType added in v0.8.0

type MediaType string

MediaType distinguishes media-group entry types. Telegram forbids mixing types within a single group.

const (
	MediaTypePhoto    MediaType = "photo"
	MediaTypeDocument MediaType = "document"
)

type Message

type Message struct {
	MessageID            int                  `json:"message_id"`
	MessageThreadID      int                  `json:"message_thread_id,omitempty"`
	BusinessConnectionID string               `json:"business_connection_id,omitempty"`
	DirectMessagesTopic  *DirectMessagesTopic `json:"direct_messages_topic,omitempty"`
	From                 *User                `json:"from,omitempty"`
	Chat                 *Chat                `json:"chat"`
	Date                 int                  `json:"date"`
	Text                 string               `json:"text,omitempty"`
	Entities             []MessageEntity      `json:"entities,omitempty"`
	Caption              string               `json:"caption,omitempty"`
	CaptionEntities      []MessageEntity      `json:"caption_entities,omitempty"`
	Photo                []PhotoSize          `json:"photo,omitempty"`
	Document             *Document            `json:"document,omitempty"`
	Voice                *Voice               `json:"voice,omitempty"`
	Audio                *Audio               `json:"audio,omitempty"`
	VideoNote            *VideoNote           `json:"video_note,omitempty"`
	RichMessage          *RichMessage         `json:"rich_message,omitempty"`
	ForwardOrigin        *MessageOrigin       `json:"forward_origin,omitempty"`
}

Message represents a message.

func (*Message) BuildContent

func (m *Message) BuildContent(translator *i18n.Translator, lang string) string

BuildContent constructs the full text content for a message, including prefixes for user, time, and forwarding.

func (*Message) BuildPrefix added in v0.2.0

func (m *Message) BuildPrefix(translator *i18n.Translator, lang string) string

BuildPrefix constructs the prefix for a message (user info or forwarding info).

type MessageEntity added in v0.11.0

type MessageEntity struct {
	Type           MessageEntityType `json:"type"`
	Offset         int               `json:"offset"`
	Length         int               `json:"length"`
	URL            string            `json:"url,omitempty"`
	User           *User             `json:"user,omitempty"`
	Language       string            `json:"language,omitempty"`
	CustomEmojiID  string            `json:"custom_emoji_id,omitempty"`
	UnixTime       int64             `json:"unix_time,omitempty"`
	DateTimeFormat string            `json:"date_time_format,omitempty"`
}

MessageEntity represents one special entity in Message.Text or Message.Caption. Offset and Length are measured in UTF-16 code units, not UTF-8 bytes or Unicode code points.

type MessageEntityProjection added in v0.11.0

type MessageEntityProjection struct {
	Markdown    string
	Partial     bool
	EntityCount int
}

MessageEntityProjection is the transport-neutral Markdown representation of ordinary Telegram text plus MessageEntity ranges. Partial is set when visible content was preserved but optional metadata, an unknown future entity type, or a delimiter-conflicting presentation wrapper could not be represented.

func ProjectMessageEntities added in v0.11.0

func ProjectMessageEntities(text string, entities []MessageEntity) (MessageEntityProjection, error)

ProjectMessageEntities validates Telegram's UTF-16 ranges and official nesting rules, then projects the selected Message.Text or Message.Caption to canonical Markdown. It never returns a partial Markdown value alongside an error, allowing callers to apply an atomic plain-text fallback.

type MessageEntityProjectionError added in v0.11.0

type MessageEntityProjectionError struct {
	Field       string
	EntityIndex int
	Reason      string
	Limit       int
	Actual      int
}

MessageEntityProjectionError describes a content-free validation or safety failure. EntityIndex is -1 when the error applies to the whole projection. Callers should atomically fall back to their original plain-text path.

func (*MessageEntityProjectionError) Error added in v0.11.0

type MessageEntityType added in v0.11.0

type MessageEntityType string

MessageEntityType identifies one of Telegram's special entities in ordinary message text or a media caption. It is a string so newer Bot API entity types remain decodable and can degrade to visible text.

const (
	MessageEntityTypeMention              MessageEntityType = "mention"
	MessageEntityTypeHashtag              MessageEntityType = "hashtag"
	MessageEntityTypeCashtag              MessageEntityType = "cashtag"
	MessageEntityTypeBotCommand           MessageEntityType = "bot_command"
	MessageEntityTypeURL                  MessageEntityType = "url"
	MessageEntityTypeEmail                MessageEntityType = "email"
	MessageEntityTypePhoneNumber          MessageEntityType = "phone_number"
	MessageEntityTypeBold                 MessageEntityType = "bold"
	MessageEntityTypeItalic               MessageEntityType = "italic"
	MessageEntityTypeUnderline            MessageEntityType = "underline"
	MessageEntityTypeStrikethrough        MessageEntityType = "strikethrough"
	MessageEntityTypeSpoiler              MessageEntityType = "spoiler"
	MessageEntityTypeBlockquote           MessageEntityType = "blockquote"
	MessageEntityTypeExpandableBlockquote MessageEntityType = "expandable_blockquote"
	MessageEntityTypeCode                 MessageEntityType = "code"
	MessageEntityTypePre                  MessageEntityType = "pre"
	MessageEntityTypeTextLink             MessageEntityType = "text_link"
	MessageEntityTypeTextMention          MessageEntityType = "text_mention"
	MessageEntityTypeCustomEmoji          MessageEntityType = "custom_emoji"
	MessageEntityTypeDateTime             MessageEntityType = "date_time"
)

Telegram Bot API 10.2 MessageEntity types.

type MessageOrigin

type MessageOrigin struct {
	Type            string `json:"type"`
	Date            int    `json:"date"`
	SenderUser      *User  `json:"sender_user,omitempty"`
	SenderUserName  string `json:"sender_user_name,omitempty"`
	SenderChat      *Chat  `json:"sender_chat,omitempty"`
	AuthorSignature string `json:"author_signature,omitempty"`
}

MessageOrigin represents the origin of a message.

func (*MessageOrigin) Format

func (mo *MessageOrigin) Format(forwardedBy *User, translator *i18n.Translator, lang string) string

Format formats the forward origin information for display.

type MessageReactionUpdated added in v0.10.2

type MessageReactionUpdated struct {
	Chat        *Chat          `json:"chat"`
	MessageID   int            `json:"message_id"`
	User        *User          `json:"user,omitempty"`
	Date        int            `json:"date"`
	OldReaction []ReactionType `json:"old_reaction"`
	NewReaction []ReactionType `json:"new_reaction"`
}

MessageReactionUpdated represents a change of a reaction on a message performed by a user. Delivered only when "message_reaction" is in the getUpdates allowed_updates list; never for reactions set by bots.

type NormalizedRichMessage added in v0.11.0

type NormalizedRichMessage struct {
	Markdown       string
	Media          []RichMediaOccurrence
	UnknownKinds   []string
	Disposition    RichDisposition
	HasVisibleText bool
	IsRTL          bool
	Stats          RichProjectionStats
}

NormalizedRichMessage is a content-preserving, transport-neutral semantic projection. Markdown contains stable media/unsupported markers but never raw unknown JSON.

func ProjectRichMessage added in v0.11.0

func ProjectRichMessage(message *RichMessage) (NormalizedRichMessage, error)

ProjectRichMessage projects with Telegram's official limits.

func ProjectRichMessageWithLimits added in v0.11.0

func ProjectRichMessageWithLimits(message *RichMessage, limits RichProjectionLimits) (NormalizedRichMessage, error)

ProjectRichMessageWithLimits exists for exact boundary and fuzz tests. A production caller should normally use ProjectRichMessage.

type PhotoSize

type PhotoSize struct {
	FileID       string `json:"file_id"`
	FileUniqueID string `json:"file_unique_id"`
	Width        int    `json:"width"`
	Height       int    `json:"height"`
	FileSize     int64  `json:"file_size,omitempty"`
}

PhotoSize represents one size of a photo or a file / sticker thumbnail.

type ReactionType

type ReactionType struct {
	Type  string `json:"type"`
	Emoji string `json:"emoji,omitempty"`
}

ReactionType represents a reaction type.

type ReplyParameters added in v0.11.0

type ReplyParameters struct {
	MessageID int `json:"message_id"`
}

ReplyParameters identifies the message being replied to.

type ResponseParameters added in v0.11.0

type ResponseParameters struct {
	RetryAfter int `json:"retry_after,omitempty"`
}

ResponseParameters contains additional information about a failed Telegram API request. RetryAfter is populated for rate-limit responses.

type RichBlock added in v0.11.0

type RichBlock struct {
	Type RichBlockType

	Text       *RichText
	Size       int
	Language   string
	Expression string
	Name       string

	Items   []RichBlockListItem
	Blocks  []RichBlock
	Credit  *RichText
	Caption *RichBlockCaption

	Cells      [][]RichBlockTableCell
	IsBordered bool
	IsStriped  bool

	Summary *RichText
	IsOpen  bool

	Location *Location
	Zoom     int
	Width    int
	Height   int

	Animation  *Animation
	Audio      *Audio
	Photo      []PhotoSize
	Video      *Video
	VoiceNote  *Voice
	HasSpoiler bool

	Unknown   bool
	Malformed bool
}

RichBlock contains fields for all Bot API 10.2 received block variants. Unknown blocks retain only safe, documented human-readable shapes; arbitrary fields and raw JSON never leave the decoder.

func (*RichBlock) UnmarshalJSON added in v0.11.0

func (b *RichBlock) UnmarshalJSON(data []byte) error

UnmarshalJSON implements the tagged RichBlock union without retaining raw JSON for unknown variants.

type RichBlockCaption added in v0.11.0

type RichBlockCaption struct {
	Text   *RichText
	Credit *RichText

	Malformed bool
}

RichBlockCaption is used by media, map, collage and slideshow blocks.

type RichBlockListItem added in v0.11.0

type RichBlockListItem struct {
	Label       string
	Blocks      []RichBlock
	HasCheckbox bool
	IsChecked   bool
	Value       *int
	Type        string

	Malformed bool
}

RichBlockListItem is one received list item. Value is a pointer because zero is distinct from an omitted value in the Bot API schema.

type RichBlockTableCell added in v0.11.0

type RichBlockTableCell struct {
	Text     *RichText
	IsHeader bool
	Colspan  int
	Rowspan  int
	Align    string
	VAlign   string

	Malformed bool
}

RichBlockTableCell is one cell in a received rich table.

type RichBlockType added in v0.11.0

type RichBlockType string

RichBlockType identifies one member of Telegram's RichBlock union.

const (
	RichBlockParagraph              RichBlockType = "paragraph"
	RichBlockHeading                RichBlockType = "heading"
	RichBlockPreformatted           RichBlockType = "pre"
	RichBlockFooter                 RichBlockType = "footer"
	RichBlockDivider                RichBlockType = "divider"
	RichBlockMathematicalExpression RichBlockType = "mathematical_expression"
	RichBlockAnchor                 RichBlockType = "anchor"
	RichBlockList                   RichBlockType = "list"
	RichBlockBlockquote             RichBlockType = "blockquote"
	RichBlockPullquote              RichBlockType = "pullquote"
	RichBlockCollage                RichBlockType = "collage"
	RichBlockSlideshow              RichBlockType = "slideshow"
	RichBlockTable                  RichBlockType = "table"
	RichBlockDetails                RichBlockType = "details"
	RichBlockMap                    RichBlockType = "map"
	RichBlockAnimation              RichBlockType = "animation"
	RichBlockAudio                  RichBlockType = "audio"
	RichBlockPhoto                  RichBlockType = "photo"
	RichBlockVideo                  RichBlockType = "video"
	RichBlockVoiceNote              RichBlockType = "voice_note"
	RichBlockThinking               RichBlockType = "thinking"
)

type RichDisposition added in v0.11.0

type RichDisposition string

RichDisposition describes how completely a received rich message was understood. Partial and unsupported projections are still deterministic and never contain raw unknown JSON.

const (
	RichDispositionAccepted    RichDisposition = "accepted"
	RichDispositionPartial     RichDisposition = "partial"
	RichDispositionUnsupported RichDisposition = "unsupported"
	RichDispositionInvalid     RichDisposition = "invalid"
)

type RichMediaKind added in v0.11.0

type RichMediaKind string

RichMediaKind identifies downloadable media blocks.

const (
	RichMediaPhoto     RichMediaKind = "photo"
	RichMediaVideo     RichMediaKind = "video"
	RichMediaAnimation RichMediaKind = "animation"
	RichMediaAudio     RichMediaKind = "audio"
	RichMediaVoice     RichMediaKind = "voice"
)

type RichMediaOccurrence added in v0.11.0

type RichMediaOccurrence struct {
	Ordinal   int
	Marker    string
	Kind      RichMediaKind
	BlockPath string

	Caption string
	Credit  string

	ContainerPath    string
	ContainerCaption string
	ContainerCredit  string

	HasSpoiler bool
	Photo      []PhotoSize
	Video      *Video
	Animation  *Animation
	Audio      *Audio
	Voice      *Voice
}

RichMediaOccurrence preserves every media occurrence, even when multiple occurrences refer to the same Telegram file. Downstream code may coalesce downloads by a non-empty file_unique_id without losing order or captions.

type RichMessage added in v0.11.0

type RichMessage struct {
	Blocks []RichBlock `json:"-"`
	IsRTL  bool        `json:"-"`

	Malformed bool `json:"-"`
}

RichMessage is Telegram's canonical received rich-message representation.

func (*RichMessage) UnmarshalJSON added in v0.11.0

func (m *RichMessage) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes each block through the tolerant union decoder.

type RichMessageAttachment added in v0.11.0

type RichMessageAttachment struct {
	ID          string `json:"-"`
	Filename    string `json:"-"`
	ContentType string `json:"-"`
	Data        []byte `json:"-"`
}

RichMessageAttachment is a local file uploaded with sendRichMessage. ID is the multipart field identifier used by an InputRichMessagePhoto source of the form attach://<ID>. Attachments are transport-local and never serialized into the rich_message JSON object.

type RichPhotoUpload added in v0.11.0

type RichPhotoUpload struct {
	Filename string
	MIME     string
	Data     []byte
}

RichPhotoUpload is one trusted local photo to bind into an outgoing Rich Message. BuildRichPhotoMedia assigns the Telegram-visible and multipart identifiers; callers only provide file metadata and bytes.

type RichProjectionLimits added in v0.11.0

type RichProjectionLimits struct {
	Characters       int
	Blocks           int
	NestingDepth     int
	Media            int
	TableColumns     int
	RichTextNodes    int
	OutputCharacters int
	UnknownKinds     int
}

RichProjectionLimits controls the bounded semantic traversal. The defaults are Telegram's official limits plus a bounded diagnostics allowance.

func DefaultRichProjectionLimits added in v0.11.0

func DefaultRichProjectionLimits() RichProjectionLimits

DefaultRichProjectionLimits returns Telegram Bot API 10.2 limits.

type RichProjectionStats added in v0.11.0

type RichProjectionStats struct {
	Characters       int
	Blocks           int
	MaxDepth         int
	Media            int
	MaxTableColumns  int
	RichTextNodes    int
	OutputCharacters int
	Unknown          int
}

RichProjectionStats contains the semantic counts used for validation and low-cardinality observability.

type RichText added in v0.11.0

type RichText struct {
	Kind     RichTextKind
	Value    string
	Children []RichText
	Text     *RichText

	UnixTime       int64
	DateTimeFormat string
	User           *User

	CustomEmojiID   string
	AlternativeText string
	Expression      string
	URL             string
	EmailAddress    string
	PhoneNumber     string
	BankCardNumber  string
	Username        string
	Hashtag         string
	Cashtag         string
	BotCommand      string
	Name            string
	AnchorName      string
	ReferenceName   string

	Unknown   bool
	Malformed bool
}

RichText is a lossless representation of all documented RichText variants, except that unknown raw JSON is intentionally discarded. For an unknown object, Type and a recursively decoded human-readable text field are retained for bounded semantic salvage.

func (*RichText) UnmarshalJSON added in v0.11.0

func (t *RichText) UnmarshalJSON(data []byte) error

UnmarshalJSON implements the string/array/tagged-object RichText union.

type RichTextKind added in v0.11.0

type RichTextKind string

RichTextKind identifies one member of Telegram's recursive RichText union. Plain and array are internal tags for the two untagged JSON alternatives.

const (
	RichTextPlain                  RichTextKind = "plain"
	RichTextArray                  RichTextKind = "array"
	RichTextBold                   RichTextKind = "bold"
	RichTextItalic                 RichTextKind = "italic"
	RichTextUnderline              RichTextKind = "underline"
	RichTextStrikethrough          RichTextKind = "strikethrough"
	RichTextSpoiler                RichTextKind = "spoiler"
	RichTextDateTime               RichTextKind = "date_time"
	RichTextTextMention            RichTextKind = "text_mention"
	RichTextSubscript              RichTextKind = "subscript"
	RichTextSuperscript            RichTextKind = "superscript"
	RichTextMarked                 RichTextKind = "marked"
	RichTextCode                   RichTextKind = "code"
	RichTextCustomEmoji            RichTextKind = "custom_emoji"
	RichTextMathematicalExpression RichTextKind = "mathematical_expression"
	RichTextURL                    RichTextKind = "url"
	RichTextEmailAddress           RichTextKind = "email_address"
	RichTextPhoneNumber            RichTextKind = "phone_number"
	RichTextBankCardNumber         RichTextKind = "bank_card_number"
	RichTextMention                RichTextKind = "mention"
	RichTextHashtag                RichTextKind = "hashtag"
	RichTextCashtag                RichTextKind = "cashtag"
	RichTextBotCommand             RichTextKind = "bot_command"
	RichTextAnchor                 RichTextKind = "anchor"
	RichTextAnchorLink             RichTextKind = "anchor_link"
	RichTextReference              RichTextKind = "reference"
	RichTextReferenceLink          RichTextKind = "reference_link"
)

type RichValidationError added in v0.11.0

type RichValidationError struct {
	Field  string
	Limit  int
	Actual int
}

RichValidationError is returned when an official structural limit or an internal traversal/output safety budget is exceeded. Field is stable and safe for metrics; no message content is kept.

func (*RichValidationError) Error added in v0.11.0

func (e *RichValidationError) Error() string

type SendChatActionRequest

type SendChatActionRequest struct {
	ChatID          int64  `json:"chat_id"`
	MessageThreadID *int   `json:"message_thread_id,omitempty"`
	Action          string `json:"action"`
}

SendChatActionRequest represents the parameters for the sendChatAction method. See the SendMessageRequest comment for why MessageThreadID uses *int.

type SendDocumentRequest added in v0.8.0

type SendDocumentRequest struct {
	ChatID           int64
	MessageThreadID  *int
	Data             []byte
	Filename         string
	Caption          string
	ParseMode        string
	ReplyToMessageID int
}

SendDocumentRequest represents the parameters for sendDocument. Use this for images whose full resolution must be preserved (2K / 4K) — unlike sendPhoto, Telegram does not recompress documents.

type SendMediaGroupDocumentsRequest added in v0.8.0

type SendMediaGroupDocumentsRequest struct {
	ChatID           int64
	MessageThreadID  *int
	Media            []InputMediaDocument
	ReplyToMessageID int
}

SendMediaGroupDocumentsRequest sends 2–10 documents as a single album. Telegram groups them visually while preserving full file resolution (no recompression), which SendMediaGroup with photos does not do.

type SendMediaGroupRequest added in v0.8.0

type SendMediaGroupRequest struct {
	ChatID           int64
	MessageThreadID  *int
	Media            []InputMediaPhoto
	ReplyToMessageID int
}

SendMediaGroupRequest represents the parameters for sendMediaGroup. Media slice must have 2–10 entries; 1 item should use SendPhoto instead.

type SendMessageRequest

type SendMessageRequest struct {
	ChatID           int64  `json:"chat_id"`
	MessageThreadID  *int   `json:"message_thread_id,omitempty"`
	Text             string `json:"text"`
	ParseMode        string `json:"parse_mode,omitempty"`
	ReplyToMessageID int    `json:"reply_to_message_id,omitempty"`
}

SendMessageRequest represents the parameters for the sendMessage method.

IMPORTANT: MessageThreadID uses *int instead of int so that omitempty works correctly for the zero value. The Telegram API interprets message_thread_id: 0 as an attempt to send to a topic with ID=0, which causes a "Bad Request: invalid topic identifier specified" error in regular chats (non-forums). With a pointer, nil is not serialized into JSON at all.

type SendPhotoRequest added in v0.8.0

type SendPhotoRequest struct {
	ChatID           int64
	MessageThreadID  *int
	PhotoData        []byte
	PhotoFilename    string // e.g. "generated.png"
	Caption          string // optional, ≤1024 UTF-16 chars
	ParseMode        string // "HTML" or "MarkdownV2" or ""
	ReplyToMessageID int
}

SendPhotoRequest represents the parameters for sendPhoto. PhotoData holds the raw image bytes to upload; PhotoFilename is used as the multipart field filename (Telegram uses it for the stored photo name).

NOTE: Telegram ALWAYS downscales and recompresses photos sent via sendPhoto (target ~1280 px on the long side). For originals > ~2 MB or higher than 2K resolution, use SendDocument instead to preserve quality.

type SendRichMessageDraftRequest added in v0.11.0

type SendRichMessageDraftRequest struct {
	ChatID          int64            `json:"chat_id"`
	MessageThreadID *int             `json:"message_thread_id,omitempty"`
	DraftID         int64            `json:"draft_id"`
	RichMessage     InputRichMessage `json:"rich_message"`
}

SendRichMessageDraftRequest represents the parameters for sendRichMessageDraft. DraftID is the stable, positive int32 identifier used to animate subsequent snapshots of the same ephemeral draft.

type SendRichMessageRequest added in v0.11.0

type SendRichMessageRequest struct {
	ChatID          int64                   `json:"chat_id"`
	MessageThreadID *int                    `json:"message_thread_id,omitempty"`
	RichMessage     InputRichMessage        `json:"rich_message"`
	ReplyParameters *ReplyParameters        `json:"reply_parameters,omitempty"`
	Attachments     []RichMessageAttachment `json:"-"`
}

SendRichMessageRequest represents the parameters for sendRichMessage. Optional integer fields use pointers so a missing value is omitted instead of being serialized as an invalid zero identifier.

type SetMessageReactionRequest

type SetMessageReactionRequest struct {
	ChatID    int64          `json:"chat_id"`
	MessageID int            `json:"message_id"`
	Reaction  []ReactionType `json:"reaction,omitempty"`
	IsBig     bool           `json:"is_big,omitempty"`
}

SetMessageReactionRequest represents the parameters for the setMessageReaction method.

type SetMyCommandsRequest

type SetMyCommandsRequest struct {
	Commands []BotCommand `json:"commands"`
}

SetMyCommandsRequest represents the parameters for the setMyCommands method.

type SetWebhookRequest

type SetWebhookRequest struct {
	URL            string   `json:"url"`
	SecretToken    string   `json:"secret_token,omitempty"`
	AllowedUpdates []string `json:"allowed_updates,omitempty"`
}

SetWebhookRequest represents the parameters for the setWebhook method.

type Update

type Update struct {
	UpdateID        int                     `json:"update_id"`
	Message         *Message                `json:"message,omitempty"`
	MessageReaction *MessageReactionUpdated `json:"message_reaction,omitempty"`
}

Update represents an incoming update.

type User

type User struct {
	ID        int64  `json:"id"`
	IsBot     bool   `json:"is_bot"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name,omitempty"`
	Username  string `json:"username,omitempty"`
}

User represents a Telegram user or bot.

func (*User) Format

func (u *User) Format() string

Format formats user information for display, including their username if available.

type Video added in v0.11.0

type Video struct {
	FileID         string         `json:"file_id"`
	FileUniqueID   string         `json:"file_unique_id"`
	Width          int            `json:"width"`
	Height         int            `json:"height"`
	Duration       int            `json:"duration"`
	Thumbnail      *PhotoSize     `json:"thumbnail,omitempty"`
	Cover          []PhotoSize    `json:"cover,omitempty"`
	StartTimestamp int            `json:"start_timestamp,omitempty"`
	Qualities      []VideoQuality `json:"qualities,omitempty"`
	FileName       string         `json:"file_name,omitempty"`
	MimeType       string         `json:"mime_type,omitempty"`
	FileSize       int64          `json:"file_size,omitempty"`
}

Video represents a video file received from Telegram.

type VideoNote added in v0.6.0

type VideoNote struct {
	FileID       string     `json:"file_id"`
	FileUniqueID string     `json:"file_unique_id"`
	Length       int        `json:"length"`   // Video width and height (diameter of the video message)
	Duration     int        `json:"duration"` // Duration of the video in seconds
	Thumbnail    *PhotoSize `json:"thumbnail,omitempty"`
	FileSize     int64      `json:"file_size,omitempty"`
}

VideoNote represents a video message (video circle).

type VideoQuality added in v0.11.0

type VideoQuality struct {
	FileID       string `json:"file_id"`
	FileUniqueID string `json:"file_unique_id"`
	Width        int    `json:"width"`
	Height       int    `json:"height"`
	Codec        string `json:"codec"`
	FileSize     int64  `json:"file_size,omitempty"`
}

VideoQuality represents one downloadable encoding of a video.

type Voice

type Voice struct {
	FileID       string `json:"file_id"`
	FileUniqueID string `json:"file_unique_id"`
	Duration     int    `json:"duration"`
	MimeType     string `json:"mime_type,omitempty"`
	FileSize     int64  `json:"file_size,omitempty"`
}

Voice represents a voice note.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL