Commit Graph
17 Commits
Author SHA1 Message Date
lukaszraczylo d666cda3b1 feat(genapi): derive discriminators and decode RichText alternates
The generator gated all union decoder emission behind knownDiscriminators, a
hand-curated map of 13 entries. Any sealed union absent from that map received
no decoder, so decoding must fail. Bot API v10 added RichBlock and RichText,
which were absent. Roughly 8.6 percent of Telegram updates failed with HTTP 400.

The generator now derives discriminators from the specification instead of a
fixed list. A gate check fails the build when a union resolves no discriminator.
Eleven unions gain decoders that never had one: BotCommandScope, InputMedia,
InputPaidMedia, InputPollMedia, InputPollOptionMedia, InputProfilePhoto,
InputRichBlock, InputStoryContent, PassportElementError, RichBlock and RichText.

RichText can also appear as a bare string or an array of RichText. The scraper
now extracts these alternate shapes into the intermediate representation. The
emitter adds RichTextPlain and RichTextSequence. The decoder dispatches on the
first JSON byte before it reads any discriminator.

Unions without alternates must regenerate byte for byte. The golden test proves
this.

Claude-Session: https://claude.ai/code/session_01Fu2wXqGUrfVBi5aLafKk8U
2026-09-15 10:59:48 +01:00
lukaszraczylo fa84f08b25 ci(regen): stop the weekly no-op update PR
The Telegram page ends with a "page generated in NN.NNms" comment that
changes on every fetch. Change detection saw it, so the run dispatched after
the codegen fix opened and merged a PR whose only content was that comment.
With the merge step in place, that becomes a pointless release every week.

Strip the comment on capture, and gate change detection on the generated
surface instead of testdata/html/, because the snapshot file name and the
latest.html symlink change every run by design. A fresh fetch now matches the
committed snapshot byte for byte while the API is unchanged.
2026-09-15 10:55:38 +01:00
54790f3e5b chore(api): regenerate from Telegram Bot API v10.3 (#18)
Co-authored-by: lukaszraczylo <[email protected]>
2026-09-14 06:40:10 +00:00
ab5f2c5700 chore(api): regenerate from Telegram Bot API v10.3 (#17)
Co-authored-by: lukaszraczylo <[email protected]>
2026-09-07 06:39:21 +00:00
926d51881d chore(api): regenerate from Telegram Bot API v10.3 (#16)
Co-authored-by: lukaszraczylo <[email protected]>
2026-08-31 06:39:17 +00:00
4511c823a3 chore(api): regenerate from Telegram Bot API v10.2 (#15)
Co-authored-by: lukaszraczylo <[email protected]>
2026-08-24 06:21:30 +00:00
7c5aca3bf8 chore(api): regenerate from Telegram Bot API v10.2 (#14)
Co-authored-by: lukaszraczylo <[email protected]>
2026-08-17 06:19:14 +00:00
4e6382ceeb chore(api): regenerate from Telegram Bot API v10.2 (#13)
Co-authored-by: lukaszraczylo <[email protected]>
2026-08-10 07:52:19 +00:00
b6881461fd chore(api): regenerate from Telegram Bot API v10.2 (#12)
Co-authored-by: lukaszraczylo <[email protected]>
2026-08-03 09:57:22 +00:00
6612c24dfc chore(api): regenerate from Telegram Bot API v10.2 (#11)
Co-authored-by: lukaszraczylo <[email protected]>
2026-07-27 10:02:19 +00:00
3620f8ce1e chore(api): regenerate from Telegram Bot API v10.2 (#10)
Co-authored-by: lukaszraczylo <[email protected]>
2026-07-21 21:56:30 +00:00
lukaszraczylo 9c363f470a chore(api): regenerate from Telegram Bot API v10.2
Snapshot taken 2026-07-21. Notable shape change: ReplyParameters.MessageID
becomes optional (*int64) because Bot API 10.2 allows a reply to target
ephemeral_message_id instead. This breaks callers that set MessageID by value,
so examples/echo passes the address now.

New surface includes the ephemeral message methods, sendRichMessage with
InputRichMessageMedia, and the Community service messages.
2026-07-21 22:52:20 +01:00
lukaszraczylo 140ea13bde fix(genapi): scope method-param enums per method, dedupe case-colliding enum consts
Bot API update added RichBlockListItem.type values (a/A/i/I/1) that
Pascal-case to identical const idents, and answerGuestQuery's non-enum
'result' param picked up answerChatJoinRequestQuery's Result enum via
the shared parent="" enum-plan key.

- key method params as method:<name> in the enum plan byField map
- enumDecl.ConstName resolves case collisions with Lower/Upper prefix
- regenerate api/ from 2026-06-11 snapshot
2026-06-12 00:03:45 +01:00
0731f10907 chore(api): regenerate from Telegram Bot API v10.0 (#7)
Co-authored-by: lukaszraczylo <[email protected]>
2026-06-01 13:15:45 +01:00
f5250197b7 chore(api): regenerate from Telegram Bot API v10.0 (#3)
Co-authored-by: lukaszraczylo <[email protected]>
2026-05-20 23:15:44 +01:00
lukaszraczylo 3c04d7b0b1 feat(api): typed enums for all string-enum fields
The Telegram docs describe many string fields and parameters with
phrases like "can be ..., or ...", "must be one of ...", or "always X",
yet the generated Go API surface used raw `string` for every one of
them. Callers had to write magic strings or `string(api.ChatTypePrivate)`
to satisfy the field type. This change makes those fields typed Go
string enums emitted from the IR, so the IDE autocompletes valid values
and breaking-value drift surfaces at compile time.

Pipeline changes:

- internal/spec/ir.go: Field gains EnumValues []string. Empty for non-
  enum fields; otherwise the wire-level values in doc order, deduped.

- cmd/scrape/enums.go: extractEnumValues recognises the curly-quoted
  patterns Telegram uses ("can be either", "currently can be", "one
  of", "must be", "always X") and rejects free-text quoted refs (e.g.
  "Can be available only for X") via a tight gap check between the
  trigger phrase and the first quoted value. parse_mode parameters
  get the canonical Markdown / MarkdownV2 / HTML triple injected
  because Telegram links to a separate formatting-options section
  instead of listing values inline.

- cmd/genapi/enums.go: planEnums groups fields by sorted value-tuple,
  picks a canonical Go enum name (most-common candidate, parent-
  prefixed beats plain, shortest beats longer, alphabetical for
  determinism), resolves cross-group name collisions by parent prefix.

- cmd/genapi/emitter.go + templates: goField rewrites the field type
  to the planned enum name; multipartFieldEntry casts typed enum
  values back to string when composing the wire map; enums.tmpl now
  iterates the planned enums instead of hardcoding four hand-curated
  ones; sentinelForField produces typed-constant test fixtures.

- api/enums.gen.go: regenerated from the live IR. 66 enum types, 155
  constants. ParseMode, ChatType, MessageEntityType, ChatMember /
  MessageOrigin / PaidMedia / Background / StoryAreaType / Reaction /
  TransactionPartner / PassportElement variant Status & Type fields
  are now typed.

- api/enums.go: hand-coded UpdateType (used by transport.LongPoller).
  The Telegram docs do not enumerate Update payload kinds inline, so
  the codegen pipeline cannot synthesise this enum.

- api/types.gen.go, api/methods.gen.go, api/methods_gen_test.go: 137
  field declarations rewritten string -> typed enum.

- dispatch/, examples/: dropped every string(api.<Const>) cast. The
  HasEntity filter now takes api.MessageEntityType; ChatType filter
  compares typed values directly. ChatMember discriminator filter
  casts variant.Status (typed per variant) to string for comparison.

- internal/spec/api.json, testdata/golden/*: regenerated and
  refreshed. make regen-from-fixture is byte-deterministic across
  runs.

Renames (no compat shims; v1 pre-public):
- EntityX  -> MessageEntityTypeX  (e.g. EntityBotCommand -> MessageEntityTypeBotCommand)
- EntityStrike -> MessageEntityTypeStrikethrough (full wire name)
2026-05-09 17:55:34 +01:00
lukaszraczylo ac7cae8fa7 Initial release of go-telegram
A fully-generated, strongly-typed Go client for the Telegram Bot API.

* 176 methods + 301 types generated from Bot API v10.0
* 1408 auto-generated tests (8 scenarios per method)
* Typed unions throughout — no 'any' in the public surface
* Pluggable HTTP transport and JSON codec (default goccy/go-json)
* Built-in retry middleware honouring Telegram's retry_after
* Generic dispatcher with filters and conversation handlers
* Self-verifying codegen pipeline (regen → audit → emit → run tests)
* 14 example bots covering common patterns
2026-05-09 13:09:27 +01:00