Documentation
¶
Index ¶
- Constants
- Variables
- func AllowedUpdateTypes() []string
- func BuildRichPhotoMedia(uploads []RichPhotoUpload) ([]InputRichMessageMedia, []RichMessageAttachment, error)
- func IsSafeSplitPosition(pos int, blocks []CodeBlock) bool
- func SplitMessageSmart(text string, limit int) []string
- func ValidateRichMessageRequest(req SendRichMessageRequest) error
- type APIError
- type APIResponse
- type Animation
- type Audio
- type BotAPI
- type BotCommand
- type Chat
- type Client
- func (c *Client) EditMessageText(ctx context.Context, req EditMessageTextRequest) (*Message, error)
- func (c *Client) GetFile(ctx context.Context, req GetFileRequest) (*File, error)
- func (c *Client) GetUpdates(ctx context.Context, req GetUpdatesRequest) ([]Update, error)
- func (c *Client) SendChatAction(ctx context.Context, req SendChatActionRequest) error
- func (c *Client) SendDocument(ctx context.Context, req SendDocumentRequest) (*Message, error)
- func (c *Client) SendMediaGroup(ctx context.Context, req SendMediaGroupRequest) ([]Message, error)
- func (c *Client) SendMediaGroupDocuments(ctx context.Context, req SendMediaGroupDocumentsRequest) ([]Message, error)
- func (c *Client) SendMessage(ctx context.Context, req SendMessageRequest) (*Message, error)
- func (c *Client) SendPhoto(ctx context.Context, req SendPhotoRequest) (*Message, error)
- func (c *Client) SendRichMessage(ctx context.Context, req SendRichMessageRequest) (*Message, error)
- func (c *Client) SendRichMessageDraft(ctx context.Context, req SendRichMessageDraftRequest) error
- func (c *Client) SetMessageReaction(ctx context.Context, req SetMessageReactionRequest) error
- func (c *Client) SetMyCommands(ctx context.Context, req SetMyCommandsRequest) error
- func (c *Client) SetWebhook(ctx context.Context, req SetWebhookRequest) error
- type CodeBlock
- type DirectMessagesTopic
- type Document
- type EditMessageTextRequest
- type ExtendedClient
- type File
- type FileDownloader
- type GetFileRequest
- type GetUpdatesRequest
- type HTTPFileDownloader
- func (d *HTTPFileDownloader) DownloadFile(ctx context.Context, fileID string) ([]byte, error)
- func (d *HTTPFileDownloader) DownloadFileAsBase64(ctx context.Context, fileID string) (string, error)
- func (d *HTTPFileDownloader) DownloadFileWithLimit(ctx context.Context, fileID string, maxBytes int64) ([]byte, error)
- type InputMediaDocument
- type InputMediaPhoto
- type InputRichMessage
- type InputRichMessageMedia
- type InputRichMessagePhoto
- type Location
- type MediaType
- type Message
- type MessageEntity
- type MessageEntityProjection
- type MessageEntityProjectionError
- type MessageEntityType
- type MessageOrigin
- type MessageReactionUpdated
- type NormalizedRichMessage
- type PhotoSize
- type ReactionType
- type ReplyParameters
- type ResponseParameters
- type RichBlock
- type RichBlockCaption
- type RichBlockListItem
- type RichBlockTableCell
- type RichBlockType
- type RichDisposition
- type RichMediaKind
- type RichMediaOccurrence
- type RichMessage
- type RichMessageAttachment
- type RichPhotoUpload
- type RichProjectionLimits
- type RichProjectionStats
- type RichText
- type RichTextKind
- type RichValidationError
- type SendChatActionRequest
- type SendDocumentRequest
- type SendMediaGroupDocumentsRequest
- type SendMediaGroupRequest
- type SendMessageRequest
- type SendPhotoRequest
- type SendRichMessageDraftRequest
- type SendRichMessageRequest
- type SetMessageReactionRequest
- type SetMyCommandsRequest
- type SetWebhookRequest
- type Update
- type User
- type Video
- type VideoNote
- type VideoQuality
- type Voice
Constants ¶
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.
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.
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.
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 ¶
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.
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 ¶
IsSafeSplitPosition checks if a byte position is safe for splitting (not inside a protected block)
func SplitMessageSmart ¶
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.
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 ¶
type BotCommand ¶
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.
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:
- 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.
- 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 ¶
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
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 ¶
GetFile returns a File object with a file_path that can be used to download the file.
func (*Client) GetUpdates ¶
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
SendDocument uploads a file (preserving original bytes — no recompression) and returns the resulting message.
func (*Client) SendMediaGroup ¶ added in v0.8.0
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 ¶
SendMessage sends a text message.
func (*Client) SendPhoto ¶ added in v0.8.0
SendPhoto uploads a photo via multipart and returns the resulting message.
func (*Client) SendRichMessage ¶ added in v0.11.0
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 ¶
CodeBlock represents a protected byte range [Start, End) that must not be split (code blocks, tables).
func FindCodeBlocks ¶
FindCodeBlocks finds all code blocks in the text and returns their positions
func FindProtectedBlocks ¶ added in v0.10.1
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 ¶
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
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.
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
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
func (e *MessageEntityProjectionError) Error() string
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 ¶
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
UnmarshalJSON implements the tagged RichBlock union without retaining raw JSON for unknown variants.
type RichBlockCaption ¶ added in v0.11.0
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" 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
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
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
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.
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.