2022-04-26 00:02:51 +08:00
# Golang Telegram Bot
2023-01-19 16:36:36 +08:00
[](https://goreportcard.com/report/github.com/go-telegram/bot) [](https://codecov.io/gh/go-telegram/bot)
2023-01-19 16:33:37 +08:00
2023-01-26 15:20:27 +08:00
✅ Present in the list of libraries https://core.telegram.org/bots/samples#go
2023-01-19 16:33:37 +08:00
2022-05-02 17:20:48 +08:00
> [Telegram Group](https://t.me/gotelegrambotui)
2025-01-10 16:11:35 +08:00
> Supports Bot API version: [8.2](https://core.telegram.org/bots/api#january-1-2025) from January 1, 2025
2022-05-02 22:19:52 +08:00
2022-04-26 00:02:51 +08:00
It's a Go zero-dependencies telegram bot framework
2022-04-30 00:04:38 +08:00
A simple example `echo-bot` :
2022-04-26 00:02:51 +08:00
```go
package main
import (
"context"
"os"
"os/signal"
"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
)
// Send any text message to the bot after the bot has been started
func main() {
2022-05-03 00:39:04 +08:00
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
2022-04-26 00:02:51 +08:00
opts := []bot.Option{
bot.WithDefaultHandler(handler),
}
2022-10-14 18:48:02 +08:00
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER", opts...)
if err != nil {
panic(err)
}
2022-04-26 00:02:51 +08:00
2022-05-06 17:47:43 +08:00
b.Start(ctx)
2022-04-26 00:02:51 +08:00
}
func handler(ctx context.Context, b *bot.Bot, update *models.Update) {
2022-05-06 17:47:43 +08:00
b.SendMessage(ctx, & bot.SendMessageParams{
2022-04-30 00:04:38 +08:00
ChatID: update.Message.Chat.ID,
2022-04-26 00:02:51 +08:00
Text: update.Message.Text,
})
}
```
2022-04-30 00:04:38 +08:00
You can find more examples in the [examples ](examples ) folder.
2022-04-26 00:02:51 +08:00
2024-06-25 15:36:46 +08:00
To run the examples, set the `EXAMPLE_TELEGRAM_BOT_TOKEN` environment variable to your bot token.
2022-04-26 00:02:51 +08:00
## Getting started
Go version: **1.18**
Install the dependencies:
```bash
go get -u github.com/go-telegram/bot
```
Initialize and run the bot:
```go
2022-10-14 18:48:02 +08:00
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER")
2022-04-26 00:02:51 +08:00
2022-05-06 17:47:43 +08:00
b.Start(context.TODO())
2022-04-26 00:02:51 +08:00
```
2022-10-14 18:48:02 +08:00
On create bot will call the `getMe` method (with 5 sec timeout). And returns error on fail.
If you want to change this timeout, use option `bot.WithCheckInitTimeout`
2024-06-25 15:36:46 +08:00
You can define a default handler for the bot:
2022-05-02 01:44:13 +08:00
```go
2022-10-14 18:48:02 +08:00
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER", bot.WithDefaultHandler(handler))
2022-05-02 01:44:13 +08:00
func handler(ctx context.Context, b *bot.Bot, update *models.Update) {
// this handler will be called for all updates
}
```
2022-05-03 00:39:04 +08:00
## Webhooks
2024-06-25 15:36:46 +08:00
If you want to use webhooks, instead of using `bot.Start` , you should use the `bot.StartWebhook` method to start the bot.
Also, you should use `bot.WebhookHandler()` method as HTTP handler for your server.
2022-05-03 00:39:04 +08:00
```go
func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
opts := []bot.Option{
bot.WithDefaultHandler(handler),
2024-06-28 17:13:43 +08:00
bot.WithWebhookSecretToken(os.Getenv("EXAMPLE_TELEGRAM_WEBHOOK_SECRET_TOKEN"))
2022-05-03 00:39:04 +08:00
}
2022-10-14 18:48:02 +08:00
b, _ := bot.New(os.Getenv("EXAMPLE_TELEGRAM_BOT_TOKEN"), opts...)
2022-05-03 00:39:04 +08:00
// call methods.SetWebhook if needed
2024-09-16 16:16:36 +08:00
2022-05-06 17:47:43 +08:00
go b.StartWebhook(ctx)
2022-05-03 00:39:04 +08:00
http.ListenAndServe(":2000", b.WebhookHandler())
// call methods.DeleteWebhook if needed
}
func handler(ctx context.Context, b *bot.Bot, update *models.Update) {
2022-05-06 17:47:43 +08:00
b.SendMessage(ctx, & bot.SendMessageParams{
2022-05-03 00:39:04 +08:00
ChatID: update.Message.Chat.ID,
Text: update.Message.Text,
})
}
```
[Demo in examples ](examples/echo_with_webhook/main.go )
2023-04-05 17:58:39 +08:00
Also, you can manually process updates with `bot.ProcessUpdate` method.
```go
update := models.Update{}
json.NewDecoder(req.Body).Decode(& update)
b.ProcessUpdate(ctx, & update)
```
2022-05-03 00:39:04 +08:00
## Middlewares
You can use middlewares with `WithMiddlewares(middlewares ...Middleware)` option.
See an example in [examples ](examples/middleware/main.go )
2022-04-26 00:02:51 +08:00
## Available methods
All available methods are listed in the [Telegram Bot API documentation ](https://core.telegram.org/bots/api )
2022-05-06 17:47:43 +08:00
You can use all these methods as bot funcs. All methods have name like in official documentation, but with capital first letter.
2022-04-26 00:02:51 +08:00
2022-05-06 17:47:43 +08:00
`bot.SendMessage` , `bot.GetMe` , `bot.SendPhoto` , etc
2022-04-26 00:02:51 +08:00
2022-05-06 17:47:43 +08:00
All methods have signature `(ctx context.Context, params <PARAMS>) (<response>, error)` .
2022-05-02 22:19:52 +08:00
Except `GetMe` , `Close` and `Logout` which are have not params
2022-05-02 22:06:36 +08:00
`<PARAMS>` is a struct with fields that corresponds to Telegram Bot API parameters.
All Params structs have name like for corresponded methods, but with `Params` suffix.
`SendMessageParams` for `SendMessage` method etc.
You should pass params by pointer
```go
2022-05-06 17:47:43 +08:00
bot.SendMessage(ctx, & bot.SendMessageParams{...})
2022-05-02 22:06:36 +08:00
```
2022-04-26 00:02:51 +08:00
## Options
You can use options to customize the bot.
2022-05-02 01:44:13 +08:00
```go
2022-10-14 18:48:02 +08:00
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER", opts...)
2022-05-02 01:44:13 +08:00
```
2023-04-13 16:45:09 +08:00
### Options list (see [options.go](options.go) for more details)
- `WithCheckInitTimeout(timeout time.Duration)` - timeout for check init bot
- `WithMiddlewares(middlewares ...Middleware)` - add middlewares
- `WithMessageTextHandler(pattern string, matchType MatchType, handler HandlerFunc)` - add handler for Message.Text field
- `WithCallbackQueryDataHandler(pattern string, matchType MatchType, handler HandlerFunc)` - add handler for CallbackQuery.Data field
2024-12-23 16:04:26 +08:00
- `WithPhotoCaptionHandler` - add handler for Message.Caption field
2023-04-13 16:45:09 +08:00
- `WithDefaultHandler(handler HandlerFunc)` - add default handler
- `WithDebug()` - enable debug mode
- `WithErrorsHandler(handler ErrorsHandler)` - add errors handler
- `WithDebugHandler(handler DebugHandler)` - add debug handler
- `WithHTTPClient(pollTimeout time.Duration, client HttpClient)` - set custom http client
- `WithServerURL(serverURL string)` - set server url
2023-05-16 15:38:28 +08:00
- `WithSkipGetMe()` - skip call GetMe on bot init
2024-03-05 00:06:02 +08:00
- `WithAllowedUpdates(params AllowedUpdates)` - set [allowed_updates ](https://core.telegram.org/bots/api#getupdates ) for getUpdates method
2024-04-02 22:23:32 +08:00
- `WithUpdatesChannelCap(cap int)` - set updates channel capacity, by default 1024
2024-06-28 17:13:43 +08:00
- `WithWebhookSecretToken(webhookSecretToken string)` - set X-Telegram-Bot-Api-Secret-Token header sent from telegram servers to confirm validity of update
2024-09-16 16:16:36 +08:00
- `WithWorkers` - set the number of workers that are processing the Updates channel, by default 1
2024-08-22 16:45:37 +08:00
- `UseTestEnvironment()` - use test environment
2024-10-17 18:54:50 +08:00
- `WithNotAsyncHandlers()` - allows to run handlers in the main goroutine
2025-01-13 15:59:56 +08:00
- `WithInitialOffset(offset int64)` - allows to set initial offset for getUpdates method
2022-04-26 00:02:51 +08:00
## Message.Text and CallbackQuery.Data handlers
2024-12-23 16:04:26 +08:00
For your convenience, you can use `Message.Text` , `CallbackQuery.Data` and `Message.Caption` handlers.
2022-04-26 00:02:51 +08:00
An example:
```go
2022-10-14 18:48:02 +08:00
b, err := bot.New("YOUR_BOT_TOKEN_FROM_BOTFATHER")
2022-04-26 00:02:51 +08:00
b.RegisterHandler(bot.HandlerTypeMessageText, "/start", bot.MatchTypeExact, myStartHandler)
2022-05-06 17:47:43 +08:00
b.Start(context.TODO())
2022-04-26 00:02:51 +08:00
```
2022-05-02 22:06:36 +08:00
> also you can use bot init options `WithMessageTextHandler` and `WithCallbackQueryDataHandler`
2022-05-02 01:44:13 +08:00
2022-04-26 00:02:51 +08:00
In this example, the handler will be called when the user sends `/start` message. All other messages will be handled by the default handler.
Handler Types:
- `HandlerTypeMessageText` - for Update.Message.Text field
- `HandlerTypeCallbackQueryData` - for Update.CallbackQuery.Data field
2024-12-23 16:04:26 +08:00
- `HandlerTypePhotoCaption` - for Update.Message.Caption field
2022-04-26 00:02:51 +08:00
2022-04-30 00:04:38 +08:00
RegisterHandler returns a handler ID string. You can use it to remove the handler later.
```
b.UnregisterHandler(handlerID)
```
2022-04-26 00:02:51 +08:00
Match Types:
2024-09-16 16:16:36 +08:00
- `MatchTypeExact`
- `MatchTypePrefix`
2022-04-26 00:02:51 +08:00
- `MatchTypeContains`
2022-12-28 15:43:04 +08:00
You can use `RegisterHandlerRegexp` to match by regular expression.
2022-04-30 00:04:38 +08:00
```go
re := regexp.MustCompile(`^/start`)
b.RegisterHandlerRegexp(bot.HandlerTypeMessageText, re, myStartHandler)
```
2022-12-28 15:43:04 +08:00
If you want to use custom handler, use `RegisterHandlerMatchFunc`
```go
matchFunc := func(update *models.Update) bool {
// your checks
return true
}
b.RegisterHandlerMatchFunc(bot.HandlerTypeMessageText, matchFunc, myHandler)
```
2022-04-30 00:04:38 +08:00
## InputFile
For some methods, like `SendPhoto` , `SendAudio` etc, you can send file by file path or file contents.
2024-06-25 15:36:46 +08:00
To send a file by URL or FileID, you can use `&models.InputFileString{Data: string}` :
2022-04-30 00:04:38 +08:00
```go
2024-09-16 16:16:36 +08:00
// file id of uploaded image
2022-04-30 00:04:38 +08:00
inputFileData := "AgACAgIAAxkDAAIBOWJimnCJHQJiJ4P3aasQCPNyo6mlAALDuzEbcD0YSxzjB-vmkZ6BAQADAgADbQADJAQ"
// or URL image path
// inputFileData := "https://example.com/image.png"
2022-05-06 17:47:43 +08:00
params := & bot.SendPhotoParams{
2022-04-30 00:04:38 +08:00
ChatID: chatID,
Photo: & models.InputFileString{Data: inputFileData},
}
2022-05-06 17:47:43 +08:00
bot.SendPhoto(ctx, params)
2022-04-30 00:04:38 +08:00
```
2022-05-03 00:39:04 +08:00
[Demo in examples ](examples/send_photo/main.go )
2022-04-30 00:04:38 +08:00
2024-06-25 15:36:46 +08:00
To send an image file by its contents, you can use `&models.InputFileUpload{Filename: string, Data: io.Reader}` :
2022-04-30 00:04:38 +08:00
```go
fileContent, _ := os.ReadFile("/path/to/image.png")
2022-05-06 17:47:43 +08:00
params := & bot.SendPhotoParams{
2022-04-30 00:04:38 +08:00
ChatID: chatID,
Photo: & models.InputFileUpload{Filename: "image.png", Data: bytes.NewReader(fileContent)},
}
2022-05-06 17:47:43 +08:00
bot.SendPhoto(ctx, params)
2022-04-30 00:04:38 +08:00
```
2022-05-03 00:39:04 +08:00
[Demo in examples ](examples/send_photo_upload/main.go )
2022-04-30 00:04:38 +08:00
## InputMedia
For methods like `SendMediaGroup` or `EditMessageMedia` you can send media by file path or file contents.
[Official documentation InputMedia ](https://core.telegram.org/bots/api#inputmedia )
> field `media`: File to send. Pass a file_id to send a file that exists on the Telegram servers (recommended), pass an HTTP URL for Telegram to get a file from the Internet, or pass “attach://<file_attach_name>” to upload a new one using multipart/form-data under <file_attach_name> name.
If you want to use `attach://` format, you should to define `MediaAttachment` field with file content reader.
```go
2024-06-25 15:36:46 +08:00
fileContent, _ := os.ReadFile("/path/to/image.png")
2022-04-30 00:04:38 +08:00
media1 := & models.InputMediaPhoto{
Media: "https://telegram.org/img/t_logo.png",
}
media2 := & models.InputMediaPhoto{
2024-09-16 16:16:36 +08:00
Media: "attach://image.png",
2022-04-30 00:04:38 +08:00
Caption: "2",
2024-06-25 15:36:46 +08:00
MediaAttachment: bytes.NewReader(fileContent),
2022-04-30 00:04:38 +08:00
}
2022-05-06 17:47:43 +08:00
params := & bot.SendMediaGroupParams{
2022-04-30 00:04:38 +08:00
ChatID: update.Message.Chat.ID,
Media: []models.InputMedia{
media1,
media2,
},
}
2022-05-06 17:47:43 +08:00
bot.SendMediaGroup(ctx, params)
2022-04-30 00:04:38 +08:00
```
2022-05-03 00:39:04 +08:00
[Demo in examples ](examples/send_media_group/main.go )
2022-04-30 00:04:38 +08:00
2023-01-19 16:42:39 +08:00
## Helpers
### `EscapeMarkdown(s string) string`
2024-09-16 16:16:36 +08:00
Escape special symbols for Telegram MarkdownV2 syntax
2023-01-19 16:42:39 +08:00
### `EscapeMarkdownUnescaped(s string) string`
2024-09-16 16:16:36 +08:00
Escape only unescaped special symbols for Telegram MarkdownV2 syntax
2023-01-19 16:42:39 +08:00
### `RandomString(n int) string`
Returns fast random a-zA-Z string with n length
2023-04-10 15:43:31 +08:00
### `True() bool`, `False() bool`
2024-06-25 15:36:46 +08:00
Allows you to define `*bool` values for params, which require `*bool` , like `SendPollParams`
2023-04-10 15:43:31 +08:00
```go
p := & bot.SendPollParams{
ChatID: chatID,
Question: "Question",
Options: []string{"Option 1", "Option 2"},
IsAnonymous: bot.False(),
}
2024-06-25 15:36:46 +08:00
b.SendPoll(ctx, p)
2023-04-10 15:43:31 +08:00
```
2025-01-10 15:36:46 +08:00
### `ValidateWebappRequest(values url.Values, token string) (user *WebAppUser, ok bool)`
2024-07-25 20:30:52 +08:00
Validate request from Telegram Webapp
https://core.telegram.org/bots/webapps#validating-data-received-via-the-mini-app
```go
// get url values from request
values := req.URL.Query()
user, ok := bot.ValidateWebappRequest(values, os.Getenv("TELEGRAM_BOT_TOKEN"))
if !ok {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
```
2023-12-07 15:54:53 +08:00
### `FileDownloadLink(f *models.File) string`
2024-03-11 16:24:04 +08:00
Return file download link after call method `GetFile`
2023-12-07 15:54:53 +08:00
2024-07-18 22:37:31 +08:00
See [documentation ](https://core.telegram.org/bots/api#getfile )
2023-12-07 15:54:53 +08:00
2024-03-11 16:24:04 +08:00
## Errors
2024-04-03 15:45:48 +08:00
This library includes error handling. It provides the following error types:
2024-03-11 16:24:04 +08:00
2024-04-03 15:45:48 +08:00
- **ErrorForbidden (403):** This error occurs when the bot has no access to the action, such as when the user has blocked the bot.
- **ErrorBadRequest (400):** This error indicates a bad request made to the bot's API.
- **ErrorUnauthorized (401):** This error occurs when the bot's access is unauthorized for the requested action.
- **TooManyRequestsError: (429)** This error indicates that the bot has received too many requests within a short period. It includes a RetryAfter value indicating when to retry the request.
- **ErrorNotFound (404):** This error indicates that the requested resource was not found.
- **ErrorConflict (409):** This error indicates a conflict occurred during the request.
Usage:
2024-03-11 16:24:04 +08:00
```go
_, err := b.SendMessage(...)
2024-04-03 15:45:48 +08:00
if errors.Is(err, mybot.ErrorForbidden) {
// Handle the ErrorForbidden (403) case here
}
if errors.Is(err, mybot.ErrorBadRequest) {
// Handle the ErrorBadRequest (400) case here
}
if errors.Is(err, mybot.ErrorUnauthorized) {
// Handle the ErrorUnauthorized (401) case here
}
if mybot.IsTooManyRequestsError(err) {
// Handle the TooManyRequestsError (429) case here
fmt.Println("Received TooManyRequestsError with retry_after:", err.(*mybot.TooManyRequestsError).RetryAfter)
}
if errors.Is(err, mybot.ErrorNotFound) {
// Handle the ErrorNotFound (404) case here
}
if errors.Is(err, mybot.ErrorConflict) {
// Handle the ErrorConflict (409) case here
2024-03-11 16:24:04 +08:00
}
```
2025-01-10 17:00:32 +08:00
## Other
- `bot.ID() int64` - returns bot ID. Bot ID is a unique identifier for the bot, obtained from the token as first part before `:` . Example: `110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw` - bot ID is `110201543` . If the bot token is invalid, the bot ID will be 0.
- `bot.Token() string` - returns bot token
- `bot.SetToken()` - set new bot token
2025-01-10 21:21:29 +08:00
## MiniApp misc
Check the repo [go-telegram/miniapp ](https://github.com/go-telegram/miniapp ) for Telegram MiniApp example.
Repo [go-telegram/miniapp-types ](https://github.com/go-telegram/miniapp-types ) contains TypeScript types definitions for Telegram MiniApp object.
2022-04-30 00:04:38 +08:00
## UI Components
2022-04-26 00:02:51 +08:00
In the repo https://github.com/go-telegram/ui you can find a some UI elements for your bot.
- datepicker
- inline_keyboard
- slider
- paginator
and more...
2022-04-30 00:04:38 +08:00
Please, check the repo for more information and live demo.