Skip to main content

Your first client

A gotd program almost always follows the same shape:

  1. Create a client with telegram.NewClient.
  2. Call client.Run, passing a callback.
  3. Do all your work inside that callback.
  4. Return from the callback to disconnect cleanly.
package main

import (
"context"
"fmt"

"github.com/gotd/td/telegram"
)

func main() {
client := telegram.NewClient(appID, appHash, telegram.Options{})

if err := client.Run(context.Background(), func(ctx context.Context) error {
// The client is connected only while this function runs.
// ctx is cancelled when the connection drops or Run returns.
api := client.API()

// help.getNearestDC works without authentication — a good connectivity check.
dc, err := api.HelpGetNearestDC(ctx)
if err != nil {
return err
}
fmt.Printf("connected, nearest DC: %d\n", dc.NearestDC)
return nil
}); err != nil {
panic(err)
}
}

The Run lifecycle​

Run connects, performs the MTProto handshake, runs your callback, and then tears the connection down. A few rules follow from this:

  • The client is only usable inside the callback. client.API(), client.Auth(), client.Self() and friends must be called while Run has not returned.
  • ctx governs the connection. If the context is cancelled, the callback's ctx is cancelled too. Use it for every API call so requests are cancelled gracefully.
  • Returning ends the session. Return nil for a clean shutdown, or an error to propagate it out of Run.

If you authenticate inside the callback, the session lives only for that run unless you persist it — see Sessions and storage. Without a stored session you must re-authenticate every time.

What about long-running bots?​

A bot or userbot needs to stay connected and process updates indefinitely. For that you block inside the callback until the context is cancelled. gotd ships a helper, telegram.RunUntilCanceled, and the BotFromEnvironment wrapper that wires this up for you. See Handling updates and the Echo bot tutorial.

Configuring the client​

telegram.Options controls almost everything. The fields you will reach for most often:

FieldPurpose
SessionStoragePersist auth between runs — see Sessions
UpdateHandlerReceive incoming updates — see Handling updates
LoggerA github.com/gotd/log-compatible logger (e.g. via logzap)
MiddlewaresIntercept every RPC — see Middleware
NoUpdatesDisable update subscription for one-shot scripts
DeviceDevice/app info reported to Telegram
ResolverCustomize how datacenters are reached — see Transports

All fields have sensible defaults; an empty telegram.Options{} is valid.