|
1 | 1 | # botapi |
2 | 2 |
|
3 | | -The telegram-bot-api, but in go. WIP. |
4 | | -* [API Reference](https://core.telegram.org/bots/api) |
5 | | -* [Reference implementation](https://github.com/tdlib/telegram-bot-api) |
6 | | -* [Generated OpenAPI v3 Schema](./_oas/openapi.json) |
7 | | - |
8 | | -## Features |
9 | | -* Parsing of API documentation with defaults, format, enum and constraints inference |
10 | | -* OpenAPI v3 specification generation |
11 | | -* Server and Client generation based on OpenAPI v3 specification |
12 | | - |
13 | | -## Roadmap |
14 | | -- [x] Parse definition |
15 | | -- [x] Generate OpenAPI v3 Specification |
16 | | -- [x] Generate client and server from OpenAPi v3 using [ogen](https://github.com/ogen-go/ogen) |
17 | | -- [x] Infer enums |
18 | | -- [ ] Infer defaults |
19 | | -- [ ] Use rich text for documentation |
20 | | -- [ ] More links to documentation |
21 | | -- [ ] Support Emoji |
| 3 | +A Telegram Bot API library for Go, implemented directly over **MTProto** using |
| 4 | +[`gotd/td`](https://github.com/gotd/td) — not over HTTP to `api.telegram.org`. |
| 5 | + |
| 6 | +It exposes the familiar [Bot API](https://core.telegram.org/bots/api) surface |
| 7 | +(types, methods, updates) but speaks MTProto on a persistent connection. That |
| 8 | +sidesteps the Bot API server's rate limits, removes the `getUpdates`/webhook |
| 9 | +round trip, and keeps the raw `gotd/td` client one method call away |
| 10 | +(`Bot.Raw()`) for anything not yet covered. |
| 11 | + |
| 12 | +> **Status: under active reconstruction.** The repo is being rebuilt from a |
| 13 | +> codegen-first OpenAPI/ogen project into a hand-written library. The `Bot` |
| 14 | +> client skeleton compiles and connects today; the typed Bot API surface |
| 15 | +> (methods, types, handler framework) is being filled in. See |
| 16 | +> [`docs/roadmap.md`](./docs/roadmap.md) for what's done and what's next. |
| 17 | +
|
| 18 | +## Why MTProto instead of HTTP |
| 19 | + |
| 20 | +| | HTTP Bot API client (e.g. telego) | botapi | |
| 21 | +| --- | --- | --- | |
| 22 | +| Transport | HTTPS to `api.telegram.org` | MTProto via `gotd/td` | |
| 23 | +| Updates | `getUpdates` long-poll / webhook | persistent connection, no polling | |
| 24 | +| Rate limits | Bot API server limits | MTProto limits only | |
| 25 | +| Escape hatch | none | raw `*tg.Client` via `Bot.Raw()` | |
| 26 | + |
| 27 | +## Design goals |
| 28 | + |
| 29 | +In priority order (see [`docs/architecture.md`](./docs/architecture.md)): |
| 30 | + |
| 31 | +1. **Zero-reflection performance** — fully typed request/response building, no |
| 32 | + `reflect` in the hot path; allocation-tested like `gotd/td`. |
| 33 | +2. **Type-safe unions & enums** — `ChatID`, `InputFile`, `ChatMember`, |
| 34 | + `ReplyMarkup`, parse modes, etc. as sealed interfaces and typed constants, |
| 35 | + not stringly-typed structs. |
| 36 | +3. **First-class context & structured errors** — context-first API; typed |
| 37 | + errors (flood-wait, retry-after, network vs API vs not-implemented); |
| 38 | + proactive rate limiting. |
| 39 | +4. **A great handler framework** — composable middleware, router and predicates |
| 40 | + over a native MTProto update stream. |
| 41 | + |
| 42 | +## Usage |
| 43 | + |
| 44 | +> The high-level typed methods are still being built. Today you get the `Bot` |
| 45 | +> lifecycle plus the raw `gotd/td` client and message sender. |
| 46 | +
|
| 47 | +```go |
| 48 | +package main |
| 49 | + |
| 50 | +import ( |
| 51 | + "context" |
| 52 | + |
| 53 | + "github.com/gotd/botapi" |
| 54 | + "github.com/gotd/botapi/storage" |
| 55 | + "github.com/gotd/td/tg" |
| 56 | + "go.etcd.io/bbolt" |
| 57 | + "go.uber.org/zap" |
| 58 | +) |
| 59 | + |
| 60 | +func main() { |
| 61 | + ctx := context.Background() |
| 62 | + |
| 63 | + db, err := bbolt.Open("bot.bbolt", 0o600, nil) |
| 64 | + if err != nil { |
| 65 | + panic(err) |
| 66 | + } |
| 67 | + defer db.Close() |
| 68 | + |
| 69 | + // Bots still need an MTProto app identity (https://my.telegram.org). |
| 70 | + // This is NOT the bot token. |
| 71 | + bot, err := botapi.New("<bot-token>", botapi.Options{ |
| 72 | + AppID: 123456, |
| 73 | + AppHash: "<app-hash>", |
| 74 | + Logger: zap.NewExample(), |
| 75 | + Storage: storage.NewBBoltStorage(db), |
| 76 | + }) |
| 77 | + if err != nil { |
| 78 | + panic(err) |
| 79 | + } |
| 80 | + |
| 81 | + // Register raw MTProto update handlers on the dispatcher (the typed |
| 82 | + // handler framework is built on top of this in a later phase). |
| 83 | + bot.Dispatcher().OnNewMessage(func(ctx context.Context, e tg.Entities, u *tg.UpdateNewMessage) error { |
| 84 | + // ... use bot.Sender() to reply ... |
| 85 | + return nil |
| 86 | + }) |
| 87 | + |
| 88 | + // Connects, authorizes as a bot, and serves updates until ctx is cancelled. |
| 89 | + if err := bot.Run(ctx); err != nil { |
| 90 | + panic(err) |
| 91 | + } |
| 92 | +} |
| 93 | +``` |
| 94 | + |
| 95 | +`Options.Storage` is optional — leave it nil to keep session, peers and update |
| 96 | +state in memory (nothing survives a restart). `storage.BBoltStorage` persists |
| 97 | +all of it to a single bbolt file. |
| 98 | + |
| 99 | +## Package layout |
| 100 | + |
| 101 | +- `botapi` (root) — the public library: the `Bot` client, options, and the |
| 102 | + hand-written Bot API surface as it lands. |
| 103 | +- `storage` — bbolt-backed session/peer/update-state storage. |
| 104 | +- `internal/botdoc` — fetches and extracts the published Bot API docs; kept as a |
| 105 | + reference oracle and a conformance check against API-version drift. |
| 106 | +- `_seed/` — the previous codegen-era translation layer, preserved |
| 107 | + (non-compiled) as reference to re-point onto the hand-written types. |
| 108 | + |
| 109 | +## Acknowledgements |
| 110 | + |
| 111 | +- [Bot API reference](https://core.telegram.org/bots/api) — the spec. |
| 112 | +- [`gotd/td`](https://github.com/gotd/td) — the MTProto engine. |
| 113 | +- [reference Bot API server](https://github.com/tdlib/telegram-bot-api). |
0 commit comments