Tutorial: an echo bot
This ties together bot auth, updates and sending messages into a complete, runnable program — a bot that replies with whatever you send it.
It is the bot-echo example,
annotated.
The full program
// Binary bot-echo implements a basic echo bot.
package main
import (
"context"
"go.uber.org/zap"
"github.com/gotd/log/logzap"
"github.com/gotd/td/examples"
"github.com/gotd/td/telegram"
"github.com/gotd/td/telegram/message"
"github.com/gotd/td/tg"
)
func main() {
// examples.Run sets up a logger and context; see Environment helpers.
examples.Run(func(ctx context.Context, log *zap.Logger) error {
// 1. The dispatcher routes incoming updates to handlers.
dispatcher := tg.NewUpdateDispatcher()
opts := telegram.Options{
Logger: logzap.New(log),
UpdateHandler: dispatcher,
}
// 2. BotFromEnvironment builds the client, runs it, and signs in
// with BOT_TOKEN from the environment.
return telegram.BotFromEnvironment(ctx, opts, func(ctx context.Context, client *telegram.Client) error {
// 3. Raw API client and a message sender built on top of it.
api := tg.NewClient(client)
sender := message.NewSender(api)
// 4. Reply to every incoming text message.
dispatcher.OnNewMessage(func(ctx context.Context, e tg.Entities, u *tg.UpdateNewMessage) error {
m, ok := u.Message.(*tg.Message)
if !ok || m.Out {
return nil // not a plain message, or our own — ignore
}
_, err := sender.Reply(e, u).Text(ctx, m.Message)
return err
})
return nil
}, telegram.RunUntilCanceled) // 5. Block until cancelled.
})
}
Walking through it
- Dispatcher —
tg.NewUpdateDispatcher()is both the thing you register handlers on and theUpdateHandlerthe client delivers updates to. BotFromEnvironment— readsAPP_ID,APP_HASH,BOT_TOKENand the session path, then handles connect + auth so the inner function starts already signed in.- Sender —
message.NewSenderwraps the raw API with the message builder. - Handler —
OnNewMessagefires for each message. We skip anything that isn't a*tg.Messageand skip our own outgoing messages (m.Out), thensender.Reply(e, u)targets the originating chat and.Text(ctx, m.Message)echoes the text back. RunUntilCanceled— keeps the client connected so updates keep flowing until you stop the process.
Run it
export APP_ID=1234567
export APP_HASH=abcdef0123456789abcdef0123456789
export BOT_TOKEN=12345:your-bot-token
export SESSION_FILE=~/session.echo.json
go run .
Message your bot and it replies with the same text.
Next steps
- Reply with formatting → Styled text and HTML
- Send files back → Uploading files
- Save media users send you → the
save-mediaexample and Downloading files - Never miss a message after downtime → Update recovery