Add to and update docs.
parent
5be25266b5
commit
a36ca53925
|
@ -1,15 +1,17 @@
|
||||||
# Summary
|
# Summary
|
||||||
|
|
||||||
- [Getting Started](./getting-started/README.md)
|
- [Getting Started](./getting-started/README.md)
|
||||||
* [Library Structure](./getting-started/library-structure.md)
|
- [Library Structure](./getting-started/library-structure.md)
|
||||||
* [Files](./getting-started/files.md)
|
- [Files](./getting-started/files.md)
|
||||||
|
- [Important Notes](./getting-started/important-notes.md)
|
||||||
- [Examples](./examples/README.md)
|
- [Examples](./examples/README.md)
|
||||||
* [Command Handling](./examples/command-handling.md)
|
- [Command Handling](./examples/command-handling.md)
|
||||||
* [Keyboard](./examples/keyboard.md)
|
- [Keyboard](./examples/keyboard.md)
|
||||||
- [Change Log]()
|
- [Inline Keyboard](./examples/inline-keyboard.md)
|
||||||
|
- [Change Log](./changelog.md)
|
||||||
|
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
- [Internals](./internals/README.md)
|
- [Internals](./internals/README.md)
|
||||||
* [Adding Endpoints](./internals/adding-endpoints.md)
|
- [Adding Endpoints](./internals/adding-endpoints.md)
|
||||||
* [Uploading Files](./internals/uploading-files.md)
|
- [Uploading Files](./internals/uploading-files.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
|
|
@ -6,55 +6,55 @@ This is a simple example of changing behavior based on a provided command.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN"))
|
bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
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 := tgbotapi.NewUpdate(0)
|
||||||
u.Timeout = 60
|
u.Timeout = 60
|
||||||
|
|
||||||
updates := bot.GetUpdatesChan(u)
|
updates := bot.GetUpdatesChan(u)
|
||||||
|
|
||||||
for update := range updates {
|
for update := range updates {
|
||||||
if update.Message == nil { // ignore any non-Message updates
|
if update.Message == nil { // ignore any non-Message updates
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !update.Message.IsCommand() { // ignore any non-command Messages
|
if !update.Message.IsCommand() { // ignore any non-command Messages
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new MessageConfig. We don't have text yet,
|
// Create a new MessageConfig. We don't have text yet,
|
||||||
// so we leave it empty.
|
// so we leave it empty.
|
||||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "")
|
msg := tgbotapi.NewMessage(update.Message.Chat.ID, "")
|
||||||
|
|
||||||
// Extract the command from the Message.
|
// Extract the command from the Message.
|
||||||
switch update.Message.Command() {
|
switch update.Message.Command() {
|
||||||
case "help":
|
case "help":
|
||||||
msg.Text = "I understand /sayhi and /status."
|
msg.Text = "I understand /sayhi and /status."
|
||||||
case "sayhi":
|
case "sayhi":
|
||||||
msg.Text = "Hi :)"
|
msg.Text = "Hi :)"
|
||||||
case "status":
|
case "status":
|
||||||
msg.Text = "I'm ok."
|
msg.Text = "I'm ok."
|
||||||
default:
|
default:
|
||||||
msg.Text = "I don't know that command"
|
msg.Text = "I don't know that command"
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := bot.Send(msg); err != nil {
|
if _, err := bot.Send(msg); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
|
@ -7,57 +7,57 @@ when you send "close" message.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"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(
|
var numericKeyboard = tgbotapi.NewReplyKeyboard(
|
||||||
tgbotapi.NewKeyboardButtonRow(
|
tgbotapi.NewKeyboardButtonRow(
|
||||||
tgbotapi.NewKeyboardButton("1"),
|
tgbotapi.NewKeyboardButton("1"),
|
||||||
tgbotapi.NewKeyboardButton("2"),
|
tgbotapi.NewKeyboardButton("2"),
|
||||||
tgbotapi.NewKeyboardButton("3"),
|
tgbotapi.NewKeyboardButton("3"),
|
||||||
),
|
),
|
||||||
tgbotapi.NewKeyboardButtonRow(
|
tgbotapi.NewKeyboardButtonRow(
|
||||||
tgbotapi.NewKeyboardButton("4"),
|
tgbotapi.NewKeyboardButton("4"),
|
||||||
tgbotapi.NewKeyboardButton("5"),
|
tgbotapi.NewKeyboardButton("5"),
|
||||||
tgbotapi.NewKeyboardButton("6"),
|
tgbotapi.NewKeyboardButton("6"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN"))
|
bot, err := tgbotapi.NewBotAPI(os.Getenv("TELEGRAM_APITOKEN"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
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 := tgbotapi.NewUpdate(0)
|
||||||
u.Timeout = 60
|
u.Timeout = 60
|
||||||
|
|
||||||
updates := bot.GetUpdatesChan(u)
|
updates := bot.GetUpdatesChan(u)
|
||||||
|
|
||||||
for update := range updates {
|
for update := range updates {
|
||||||
if update.Message == nil { // ignore non-Message updates
|
if update.Message == nil { // ignore non-Message updates
|
||||||
continue
|
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 {
|
switch update.Message.Text {
|
||||||
case "open":
|
case "open":
|
||||||
msg.ReplyMarkup = numericKeyboard
|
msg.ReplyMarkup = numericKeyboard
|
||||||
case "close":
|
case "close":
|
||||||
msg.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true)
|
msg.ReplyMarkup = tgbotapi.NewRemoveKeyboard(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := bot.Send(msg); err != nil {
|
if _, err := bot.Send(msg); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
Telegram supports specifying files in many different formats. In order to
|
Telegram supports specifying files in many different formats. In order to
|
||||||
accommodate them all, there are multiple structs and type aliases required.
|
accommodate them all, there are multiple structs and type aliases required.
|
||||||
|
|
||||||
| Type | Description |
|
| Type | Description |
|
||||||
| ---- | ----------- |
|
| ------------ | ------------------------------------------------------------------------- |
|
||||||
| `string` | Used as a local path to a file |
|
| `string` | Used as a local path to a file |
|
||||||
| `FileID` | Existing file ID on Telegram's servers |
|
| `FileID` | Existing file ID on Telegram's servers |
|
||||||
| `FileURL` | URL to file, must be served with expected MIME type |
|
| `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. |
|
| `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. |
|
| `FileBytes` | `[]byte` containing file data. Prefer to use `FileReader` to save memory. |
|
||||||
|
|
||||||
## `string`
|
## `string`
|
||||||
|
|
||||||
|
|
|
@ -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.
|
Loading…
Reference in New Issue