Skip to content

Commit f796743

Browse files
ernadoclaude
andcommitted
fix(examples/rich): use only constructors allowed in bot rich messages
The showcase used Instant-View-page-only page blocks (Title, Subtitle, Header, Subheader, Kicker, AuthorDate, Cover, RelatedArticles) and the auto-link inline styles (AutoURL/AutoEmail/AutoPhone). The Bot API server rejects these in a bot-sent rich message with RICH_VALIDATE_CTOR_NOT_ALLOWED. Per telegram-bot-api td/td/telegram/WebPageBlock.cpp (blocks whose get_input_page_block logs an error are invalid input) and Client.cpp's richText switch, drop the disallowed constructors and keep only the allowed ones. Document the allowlist in the example doc comment and CHANGELOG. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 91ebc37 commit f796743

2 files changed

Lines changed: 24 additions & 30 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ messages follow [Conventional Commits](https://www.conventionalcommits.org/).
2020
- **Rich messages** (Bot API 10.1) — `SendRichMessage`/`SendRichHTML`/
2121
`SendRichMarkdown` send structured page-block content built with
2222
`github.com/gotd/td/telegram/message/rich`. The `examples/rich` bot showcases
23-
every page-block and rich-text constructor.
23+
the page-block and rich-text constructors valid in a bot-sent message.
24+
(Instant-View-page-only blocks — Title, Subtitle, Header, Subheader, Kicker,
25+
AuthorDate, Cover, RelatedArticles — and the auto-link inline styles are
26+
rejected by the server with `RICH_VALIDATE_CTOR_NOT_ALLOWED`.)
2427
- **Background sends**`Bot.Background()` / `Context.Background()` expose a
2528
run-lifetime context for proactive sends to any chat from timers, queues or
2629
goroutines, instead of the per-update handler context. Plus `Bot.Logger()`.

examples/rich/main.go

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
// Command rich is a showcase of Telegram rich messages (Bot API 10.1) built with
22
// github.com/gotd/td/telegram/message/rich. Each command sends a rich message
3-
// exercising a category of the rich-text and page-block constructors:
3+
// exercising a category of the allowed rich-text and page-block constructors:
44
//
5-
// /headings titles, headers, headings 1-6, kicker, author/date, footer
6-
// /text every inline text style (bold, italic, spoiler, math, links, …)
5+
// /headings headings 1-6 and a footer
6+
// /text every allowed inline text style (bold, italic, spoiler, math, …)
77
// /lists bullet, checklist and ordered lists (incl. block items)
8-
// /blocks paragraph, preformatted, quotes, details, math, divider, anchor
8+
// /blocks paragraph, anchor, code, quotes, math, details, thinking, divider
99
// /table a table with header and data cells
1010
// /map a map block
11-
// /media photo/audio/image/custom-emoji/cover/collage/slideshow/related
12-
// (the media-by-id blocks need real ids — see the env vars below)
11+
// /media photo/audio/image/custom-emoji/collage/slideshow (need real ids)
12+
//
13+
// Not every page block is valid in a bot-sent rich message. Per the official Bot
14+
// API server (telegram-bot-api, td/td/telegram/WebPageBlock.cpp), these are
15+
// Instant-View-page-only and the server rejects them with
16+
// RICH_VALIDATE_CTOR_NOT_ALLOWED, so they are intentionally not used here:
17+
// Title, Subtitle, Header, Subheader, Kicker, AuthorDate, Cover,
18+
// RelatedArticles — and the inline auto-link styles (AutoURL/AutoEmail/
19+
// AutoPhone). Video is omitted too.
1320
//
1421
// Run it with an MTProto app identity (https://my.telegram.org) and a BotFather
1522
// token. To exercise /media's media-by-id blocks, also set any of PHOTO_ID,
@@ -55,7 +62,7 @@ func main() {
5562

5663
bot.OnCommand("start", "List the rich-message demos", func(c *botapi.Context) error {
5764
return send(c,
58-
rich.Title(rich.Plain("Rich message showcase")),
65+
rich.Heading1(rich.Plain("Rich message showcase")),
5966
rich.Paragraph(rich.Plain("Try these commands to see the page-block constructors:")),
6067
rich.List(
6168
rich.ListItem(rich.Fixed(rich.Plain("/headings"))),
@@ -69,14 +76,8 @@ func main() {
6976
)
7077
})
7178

72-
bot.OnCommand("headings", "Titles and headings", func(c *botapi.Context) error {
79+
bot.OnCommand("headings", "Headings and a footer", func(c *botapi.Context) error {
7380
return send(c,
74-
rich.Kicker(rich.Plain("KICKER")),
75-
rich.Title(rich.Plain("The Title")),
76-
rich.Subtitle(rich.Plain("The subtitle")),
77-
rich.AuthorDate(rich.Plain("by Ada"), int(time.Now().Unix())),
78-
rich.Header(rich.Plain("A header")),
79-
rich.Subheader(rich.Plain("A subheader")),
8081
rich.Heading1(rich.Plain("Heading 1")),
8182
rich.Heading2(rich.Plain("Heading 2")),
8283
rich.Heading3(rich.Plain("Heading 3")),
@@ -88,7 +89,7 @@ func main() {
8889
)
8990
})
9091

91-
bot.OnCommand("text", "Every inline text style", func(c *botapi.Context) error {
92+
bot.OnCommand("text", "Every allowed inline text style", func(c *botapi.Context) error {
9293
return send(c,
9394
rich.Paragraph(rich.Concat(
9495
rich.Bold(rich.Plain("bold")), sp(), rich.Italic(rich.Plain("italic")), sp(),
@@ -115,12 +116,6 @@ func main() {
115116
rich.URL(rich.Plain("gotd/td"), "https://github.com/gotd/td", 0), sp(),
116117
rich.AnchorLink(rich.Plain("jump to anchor"), "more"),
117118
)),
118-
rich.Paragraph(rich.Concat(
119-
rich.Plain("auto-detected: "),
120-
rich.AutoURL(rich.Plain("https://telegram.org")), sp(),
121-
rich.AutoEmail(rich.Plain("team@telegram.org")), sp(),
122-
rich.AutoPhone(rich.Plain("+15550100")),
123-
)),
124119
rich.Paragraph(rich.Concat(
125120
rich.Plain("date: "),
126121
rich.Date(rich.Plain("now"), int(time.Now().Unix()), rich.DateFlags{LongDate: true, ShortTime: true}),
@@ -131,7 +126,7 @@ func main() {
131126

132127
bot.OnCommand("lists", "Bullet, checklist and ordered lists", func(c *botapi.Context) error {
133128
return send(c,
134-
rich.Header(rich.Plain("Unordered")),
129+
rich.Heading3(rich.Plain("Unordered")),
135130
rich.List(
136131
rich.ListItem(rich.Plain("a plain item")),
137132
rich.CheckListItem(true, rich.Plain("a checked item")),
@@ -141,7 +136,7 @@ func main() {
141136
rich.Preformatted(rich.Plain("nested := true"), "go"),
142137
),
143138
),
144-
rich.Header(rich.Plain("Ordered")),
139+
rich.Heading3(rich.Plain("Ordered")),
145140
rich.OrderedList(
146141
rich.OrderedListItem("1.", rich.Plain("first")),
147142
rich.OrderedListItem("2.", rich.Plain("second")),
@@ -150,7 +145,7 @@ func main() {
150145
)
151146
})
152147

153-
bot.OnCommand("blocks", "Paragraphs, quotes, code, details, math", func(c *botapi.Context) error {
148+
bot.OnCommand("blocks", "Anchor, code, quotes, math, details, divider", func(c *botapi.Context) error {
154149
return send(c,
155150
rich.AnchorBlock("more"),
156151
rich.Paragraph(rich.Concat(
@@ -213,7 +208,6 @@ func mediaBlocks() []tg.PageBlockClass {
213208
if id := envID("PHOTO_ID"); id != 0 {
214209
blocks = append(blocks,
215210
rich.Photo(id, caption("A photo")),
216-
rich.Cover(rich.Photo(id, caption("A cover"))),
217211
rich.Collage(caption("A collage"),
218212
rich.Photo(id, emptyCaption()), rich.Photo(id, emptyCaption())),
219213
rich.Slideshow(caption("A slideshow"),
@@ -234,11 +228,8 @@ func mediaBlocks() []tg.PageBlockClass {
234228
)))
235229
}
236230

231+
// A map always renders, so /media works even without any media ids.
237232
blocks = append(blocks,
238-
rich.RelatedArticles(rich.Plain("Related articles"),
239-
tg.PageRelatedArticle{URL: "https://telegram.org", Title: "Telegram", Author: "Telegram"},
240-
),
241-
// A map always renders, so /media works even without any media ids.
242233
rich.Map(&tg.InputGeoPoint{Lat: 55.7539, Long: 37.6208}, 15, 600, 400, caption("Red Square")),
243234
)
244235
return blocks

0 commit comments

Comments
 (0)