RichBuilder
A fluent builder for structured rich messages — headings, paragraphs, quotes, tables, dividers, and media in one document. The output is an InputRichMessage you pass to TL methods that accept one.
What it is
Plain SendMessageships a single text body with entity styling. RichBuilder produces a layered document — multiple blocks, embedded media, tables — that renders as an Instant-View-style card. It is the right tool when message structure is determined at runtime and string templating starts to fight you.
Build a *RichBuilder with telegram.NewRichMessage() and chain methods.
Text via Markdown or HTML
The simplest entry point: hand the builder a chunk of Markdown or HTML and let it parse the entity layer for you.
msg := telegram.NewRichMessage().
Markdown("**Build:** passing\nSee [logs](https://ci.example.com/run/4321)")
raw := msg.Build()
// raw is an InputRichMessage you can pass to a TL method that accepts one.msg := telegram.NewRichMessage().
Markdown("**Build:** passing\nSee [logs](https://ci.example.com/run/4321)")
raw := msg.Build()
// raw is an InputRichMessage you can pass to a TL method that accepts one.msg := telegram.NewRichMessage().
HTML("<b>Build:</b> passing<br/>See <a href=\"https://ci.example.com/run/4321\">logs</a>")msg := telegram.NewRichMessage().
HTML("<b>Build:</b> passing<br/>See <a href=\"https://ci.example.com/run/4321\">logs</a>")Each call appends to the document. Mixing Markdown and HTMLon the same builder works — both end up as parsed entity lists.
Block-level content
For structured documents, the typed block API is clearer than ad-hoc Markdown:
msg := telegram.NewRichMessage().
Heading("Quarterly report").
Paragraph("Revenue is up 14 % quarter-over-quarter.").
Divider().
Paragraph("Margins remain pressured by infra costs.").
Quote("Profit is opinion. Cash is fact.")msg := telegram.NewRichMessage().
Heading("Quarterly report").
Paragraph("Revenue is up 14 % quarter-over-quarter.").
Divider().
Paragraph("Margins remain pressured by infra costs.").
Quote("Profit is opinion. Cash is fact.")Heading(text)— section heading.Paragraph(text)— a normal text block.Quote(text)— pulled quote.Divider()— visual separator.Latex(s)— inline math.AddBlock(block)/Blocks(blocks...)— drop in a hand-builtPageBlock.
Adding media
msg := telegram.NewRichMessage().
Heading("Latest release").
Paragraph("Cut yesterday, available everywhere now.").
AddPhoto("./cover.jpg").
AddDocument("./release-notes.pdf")msg := telegram.NewRichMessage().
Heading("Latest release").
Paragraph("Cut yesterday, available everywhere now.").
AddPhoto("./cover.jpg").
AddDocument("./release-notes.pdf")AddPhoto, AddDocument, AddVideo, AddAudiotake any source — file path, byte slice, reader, URL — and upload it as part of the message build step.
For previously-uploaded media, AttachPhoto and AttachDocument take an existing InputPhoto or InputDocument and skip the upload.
Photo-only multi-image layouts use SlideshowPhotos(photos...) or CollagePhotos(photos...).
Tables and details
rows := [][]any{
{"Service", "p50", "p99"},
{"api", "12ms", "85ms"},
{"worker", "8ms", "32ms"},
}
msg := telegram.NewRichMessage().
Heading("Latency by service").
Table(rows, &telegram.TableOptions{
Bordered: true,
HasHeader: true,
})rows := [][]any{
{"Service", "p50", "p99"},
{"api", "12ms", "85ms"},
{"worker", "8ms", "32ms"},
}
msg := telegram.NewRichMessage().
Heading("Latency by service").
Table(rows, &telegram.TableOptions{
Bordered: true,
HasHeader: true,
})Table(rows, opts) takes a 2D slice of values (strings, ints, or pre-built rich-text fragments). Options control borders, header row, alignment.
Details(title, blocks...) creates a collapsed/expandable section:
msg := telegram.NewRichMessage().
Paragraph("The release went out at 14:32 UTC.").
Details("Show change log",
&telegram.PageBlockParagraph{
Text: &telegram.TextPlain{Text: "Fixed flaky DC reconnect timer."},
},
)msg := telegram.NewRichMessage().
Paragraph("The release went out at 14:32 UTC.").
Details("Show change log",
&telegram.PageBlockParagraph{
Text: &telegram.TextPlain{Text: "Fixed flaky DC reconnect timer."},
},
)Builder flags
msg := telegram.NewRichMessage().
RTL(). // right-to-left layout hint
NoAutoLink(). // do not auto-detect URLs in plain text
Paragraph("…")msg := telegram.NewRichMessage().
RTL(). // right-to-left layout hint
NoAutoLink(). // do not auto-detect URLs in plain text
Paragraph("…")- RTL()
- Mark the message as right-to-left for layout purposes.
- NoAutoLink()
- Disable auto-detection of URLs and mentions inside plain text blocks.
Building and using
Build() resolves any pending media uploads and returns an InputRichMessage. Pass it to the matching TL method — the high-level wrapper helpers for "send a rich message" vary across gogram releases, so check the source for the current entry point in your version.
