all repos — telegram-bot-api @ a36ca539258ee740dc581ead09abafb622517621

Golang bindings for the Telegram Bot API

Add to and update docs.
Syfaro syfaro@huefox.com
Wed, 10 Mar 2021 16:36:15 -0500
commit

a36ca539258ee740dc581ead09abafb622517621

parent

5be25266b56e4097ab270fd83ccbec87f80d4eb8

M docs/SUMMARY.mddocs/SUMMARY.md

@@ -1,15 +1,17 @@

# Summary - [Getting Started](./getting-started/README.md) - * [Library Structure](./getting-started/library-structure.md) - * [Files](./getting-started/files.md) + - [Library Structure](./getting-started/library-structure.md) + - [Files](./getting-started/files.md) + - [Important Notes](./getting-started/important-notes.md) - [Examples](./examples/README.md) - * [Command Handling](./examples/command-handling.md) - * [Keyboard](./examples/keyboard.md) -- [Change Log]() + - [Command Handling](./examples/command-handling.md) + - [Keyboard](./examples/keyboard.md) + - [Inline Keyboard](./examples/inline-keyboard.md) +- [Change Log](./changelog.md) # Contributing - [Internals](./internals/README.md) - * [Adding Endpoints](./internals/adding-endpoints.md) - * [Uploading Files](./internals/uploading-files.md) + - [Adding Endpoints](./internals/adding-endpoints.md) + - [Uploading Files](./internals/uploading-files.md)
A docs/changelog.md

@@ -0,0 +1,19 @@

+# Change Log + +## v5 + +**Work In Progress** + +- Remove all methods that return `(APIResponse, error)`. + - Use the `Request` method instead. + - For more information, see [Library Structure][library-structure]. +- Remove all `New*Upload` and `New*Share` methods, replace with `New*`. + - Use different [file types][files] to specify if upload or share. +- Rename `UploadFile` to `UploadFiles`, accept `[]RequestFile` instead of a + single fieldname and file. +- Fix methods returning `APIResponse` and errors to always use pointers. +- Update user IDs to `int64` because of Bot API changes. +- Add missing Bot API features. + +[library-structure]: ./getting-started/library-structure.md#methods +[files]: ./getting-started/files.md
M docs/examples/command-handling.mddocs/examples/command-handling.md

@@ -6,55 +6,55 @@ ```go

package main import ( - "log" - "os" + "log" + "os" - "github.com/go-telegram-bot-api/telegram-bot-api" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) func main() { - bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN")) - if err != nil { - log.Panic(err) - } + bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN")) + if err != nil { + log.Panic(err) + } - bot.Debug = true + bot.Debug = true - log.Printf("Authorized on account %s", bot.Self.UserName) + log.Printf("Authorized on account %s", bot.Self.UserName) - u := tgbotapi.NewUpdate(0) - u.Timeout = 60 + u := tgbotapi.NewUpdate(0) + u.Timeout = 60 - updates := bot.GetUpdatesChan(u) + updates := bot.GetUpdatesChan(u) - for update := range updates { - if update.Message == nil { // ignore any non-Message updates - continue - } + for update := range updates { + if update.Message == nil { // ignore any non-Message updates + continue + } - if !update.Message.IsCommand() { // ignore any non-command Messages - continue - } + if !update.Message.IsCommand() { // ignore any non-command Messages + continue + } - // Create a new MessageConfig. We don't have text yet, - // so we leave it empty. - msg := tgbotapi.NewMessage(update.Message.Chat.ID, "") + // Create a new MessageConfig. We don't have text yet, + // so we leave it empty. + msg := tgbotapi.NewMessage(update.Message.Chat.ID, "") - // Extract the command from the Message. - switch update.Message.Command() { - case "help": - msg.Text = "I understand /sayhi and /status." - case "sayhi": - msg.Text = "Hi :)" - case "status": - msg.Text = "I'm ok." - default: - msg.Text = "I don't know that command" - } + // Extract the command from the Message. + switch update.Message.Command() { + case "help": + msg.Text = "I understand /sayhi and /status." + case "sayhi": + msg.Text = "Hi :)" + case "status": + msg.Text = "I'm ok." + default: + msg.Text = "I don't know that command" + } - if _, err := bot.Send(msg); err != nil { - log.Panic(err) - } - } + if _, err := bot.Send(msg); err != nil { + log.Panic(err) + } + } } ```
A docs/examples/inline-keyboard.md

@@ -0,0 +1,80 @@

+# Inline Keyboard + +This bot waits for you to send it the message "open" before sending you an +inline keyboard containing a URL and some numbers. When a number is clicked, it +sends you a message with your selected number. + +```go +package main + +import ( + "log" + "os" + + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" +) + +var numericKeyboard = tgbotapi.NewInlineKeyboardMarkup( + tgbotapi.NewInlineKeyboardRow( + tgbotapi.NewInlineKeyboardButtonURL("1.com", "http://1.com"), + tgbotapi.NewInlineKeyboardButtonData("2", "2"), + tgbotapi.NewInlineKeyboardButtonData("3", "3"), + ), + tgbotapi.NewInlineKeyboardRow( + tgbotapi.NewInlineKeyboardButtonData("4", "4"), + tgbotapi.NewInlineKeyboardButtonData("5", "5"), + tgbotapi.NewInlineKeyboardButtonData("6", "6"), + ), +) + +func main() { + bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN")) + if err != nil { + log.Panic(err) + } + + bot.Debug = true + + log.Printf("Authorized on account %s", bot.Self.UserName) + + u := tgbotapi.NewUpdate(0) + u.Timeout = 60 + + updates := bot.GetUpdatesChan(u) + + // Loop through each update. + for update := range updates { + // Check if we've gotten a message update. + if update.Message != nil { + // Construct a new message from the given chat ID and containing + // the text that we received. + msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text) + + // If the message was open, add a copy of our numeric keyboard. + switch update.Message.Text { + case "open": + msg.ReplyMarkup = numericKeyboard + + } + + // Send the message. + if _, err = bot.Send(msg); err != nil { + panic(err) + } + } else if update.CallbackQuery != nil { + // Respond to the callback query, telling Telegram to show the user + // a message with the data received. + callback := tgbotapi.NewCallback(update.CallbackQuery.ID, update.CallbackQuery.Data) + if _, err := bot.Request(callback); err != nil { + panic(err) + } + + // And finally, send a message containing the data received. + msg := tgbotapi.NewMessage(update.CallbackQuery.Message.Chat.ID, update.CallbackQuery.Data) + if _, err := bot.Send(msg); err != nil { + panic(err) + } + } + } +} +```
M docs/examples/keyboard.mddocs/examples/keyboard.md

@@ -7,57 +7,57 @@ ```go

package main import ( - "log" - "os" + "log" + "os" - "github.com/go-telegram-bot-api/telegram-bot-api" + tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) var numericKeyboard = tgbotapi.NewReplyKeyboard( - tgbotapi.NewKeyboardButtonRow( - tgbotapi.NewKeyboardButton("1"), - tgbotapi.NewKeyboardButton("2"), - tgbotapi.NewKeyboardButton("3"), - ), - tgbotapi.NewKeyboardButtonRow( - tgbotapi.NewKeyboardButton("4"), - tgbotapi.NewKeyboardButton("5"), - tgbotapi.NewKeyboardButton("6"), - ), + tgbotapi.NewKeyboardButtonRow( + tgbotapi.NewKeyboardButton("1"), + tgbotapi.NewKeyboardButton("2"), + tgbotapi.NewKeyboardButton("3"), + ), + tgbotapi.NewKeyboardButtonRow( + tgbotapi.NewKeyboardButton("4"), + tgbotapi.NewKeyboardButton("5"), + tgbotapi.NewKeyboardButton("6"), + ), ) func main() { - bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN")) - if err != nil { - log.Panic(err) - } + bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN")) + if err != nil { + log.Panic(err) + } - bot.Debug = true + bot.Debug = true - log.Printf("Authorized on account %s", bot.Self.UserName) + log.Printf("Authorized on account %s", bot.Self.UserName) - u := tgbotapi.NewUpdate(0) - u.Timeout = 60 + u := tgbotapi.NewUpdate(0) + u.Timeout = 60 - updates := bot.GetUpdatesChan(u) + updates := bot.GetUpdatesChan(u) - for update := range updates { - if update.Message == nil { // ignore non-Message updates - continue - } + for update := range updates { + if update.Message == nil { // ignore non-Message updates + continue + } - msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text) + msg := tgbotapi.NewMessage(update.Message.Chat.ID, update.Message.Text) - switch update.Message.Text { - case "open": - msg.ReplyMarkup = numericKeyboard - case "close": - msg.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true) - } + switch update.Message.Text { + case "open": + msg.ReplyMarkup = numericKeyboard + case "close": + msg.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true) + } - if _, err := bot.Send(msg); err != nil { - log.Panic(err) - } - } + if _, err := bot.Send(msg); err != nil { + log.Panic(err) + } + } } ```
M docs/getting-started/files.mddocs/getting-started/files.md

@@ -3,13 +3,13 @@

Telegram supports specifying files in many different formats. In order to accommodate them all, there are multiple structs and type aliases required. -| Type | Description | -| ---- | ----------- | -| `string` | Used as a local path to a file | -| `FileID` | Existing file ID on Telegram's servers | -| `FileURL` | URL to file, must be served with expected MIME type | -| `FileReader` | Use an `io.Reader` to provide a file. Lazily read to save memory. | -| `FileBytes` | `[]byte` containing file data. Prefer to use `FileReader` to save memory. | +| Type | Description | +| ------------ | ------------------------------------------------------------------------- | +| `string` | Used as a local path to a file | +| `FileID` | Existing file ID on Telegram's servers | +| `FileURL` | URL to file, must be served with expected MIME type | +| `FileReader` | Use an `io.Reader` to provide a file. Lazily read to save memory. | +| `FileBytes` | `[]byte` containing file data. Prefer to use `FileReader` to save memory. | ## `string`
A docs/getting-started/important-notes.md

@@ -0,0 +1,46 @@

+# Important Notes + +The Telegram Bot API has a few potentially unanticipated behaviors. Here are a +few of them. If any behavior was surprising to you, please feel free to open a +pull request! + +## Callback Queries + +- Every callback query must be answered, even if there is nothing to display to + the user. Failure to do so will show a loading icon on the keyboard until the + operation times out. + +## ChatMemberUpdated + +- In order to receive `chat_member` and updates, you must explicitly add it to + your `allowed_updates` when getting updates or setting your webhook. + +## Entities use UTF16 + +- When extracting text entities using offsets and lengths, characters can appear + to be in incorrect positions. This is because Telegram uses UTF16 lengths + while Golang uses UTF8. It's possible to convert between the two, see + [issue #231][issue-231] for more details. + +[issue-231]: https://github.com/go-telegram-bot-api/telegram-bot-api/issues/231 + +## GetUpdatesChan + +- This method is very basic and likely unsuitable for production use. Consider + creating your own implementation instead, as it's very simple to replicate. +- This method only allows your bot to process one update at a time. You can + spawn goroutines to handle updates concurrently or switch to webhooks instead. + Webhooks are suggested for high traffic bots. + +## Nil Updates + +- At most one of the fields in an `Update` will be set to a non-nil value. When + evaluating updates, you must make sure you check that the field is not nil + before trying to access any of it's fields. + +## User and Chat ID size + +- These types require up to 52 significant bits to store correctly, making a + 64-bit integer type required in most languages. They are already `int64` types + in this library, but make sure you use correct types when saving them to a + database or passing them to another language.