telegram

package
v0.165.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2026 License: MIT Imports: 52 Imported by: 297

Documentation

Overview

Package telegram implements Telegram client.

Index

Examples

Constants

View Source
const (
	AddrProduction = "149.154.167.50:443"
	AddrTest       = "149.154.167.40:443"
)

Available MTProto default server addresses.

See https://my.telegram.org/apps.

View Source
const (
	TestAppID   = constant.TestAppID
	TestAppHash = constant.TestAppHash
)

Test-only credentials. Can be used with AddrTest and TestAuth to test authentication.

Reference:

View Source
const ErrFloodWait = tgerr.ErrFloodWait

ErrFloodWait is error type of "FLOOD_WAIT" error.

View Source
const Port = 443

Port is default port used by telegram.

Variables

View Source
var (
	// ErrAlreadyStarted is returned by Start and Run if the client was
	// already started by Start or Run: a Client is single-use, and Start and
	// Run are mutually exclusive. It is also returned by Close and Shutdown
	// of a client driven by Run.
	ErrAlreadyStarted = errors.New("client already started")
	// ErrClientClosed is returned by Start and Run after Close, Shutdown or
	// Stop of a client that was never started, and by Start canceled by them.
	ErrClientClosed = errors.New("client already closed")
)
View Source
var AsFloodWait = tgerr.AsFloodWait

AsFloodWait returns wait duration and true boolean if err is the "FLOOD_WAIT" error.

Client should wait for that duration before issuing new requests with same method.

Functions

func AuthKeyDropError

func AuthKeyDropError(u *tg.UpdateServiceNotification) error

AuthKeyDropError returns the error that is reported via OnAuthLost when the server sends an AUTH_KEY_DROP_* service notification: a *tgerr.Error with code 401, the notification type as Type and its text as Message.

func BotFromEnvironment added in v0.19.0

func BotFromEnvironment(
	ctx context.Context,
	opts Options,
	setup func(ctx context.Context, client *Client) error,
	cb func(ctx context.Context, client *Client) error,
) error

BotFromEnvironment creates bot client using ClientFromEnvironment connects to server and authenticates it.

Variables: BOT_TOKEN — token from BotFather.

func IsAccountBanned

func IsAccountBanned(err error) bool

IsAccountBanned reports whether err means that the account is banned by Telegram: USER_DEACTIVATED_BAN for a signed in account, PHONE_NUMBER_BANNED when signing in.

func IsAuthLost

func IsAuthLost(err error) bool

IsAuthLost reports whether err means that the authorization of the session is lost: the auth key is unregistered, the session is revoked or expired, the user is deactivated, or the key is used by another connection (AUTH_KEY_DUPLICATED).

SESSION_PASSWORD_NEEDED and other "not authorized yet" errors are not included.

Errors made from AUTH_KEY_DROP_* service notifications (see AuthKeyDropError) are included.

func IsFrozen

func IsFrozen(err error) bool

IsFrozen reports whether err means that the request was refused because the account is frozen: FROZEN_METHOD_INVALID (code 420, not a flood wait) or FROZEN_PARTICIPANT_MISSING.

func RunUntilCanceled added in v0.26.0

func RunUntilCanceled(ctx context.Context, client *Client) error

RunUntilCanceled is client callback which locks until client context is canceled.

func TDesktopResolver added in v0.156.0

func TDesktopResolver() dcs.Resolver

TDesktopResolver returns a DC resolver that connects the same way as Telegram Desktop: every direct connection is wrapped in Obfuscated2 and uses the abridged transport codec.

Use it together with DeviceTDesktopWindows to be indistinguishable from Telegram Desktop both on the transport layer and in initConnection:

client := telegram.NewClient(appID, appHash, telegram.Options{
	Device:   telegram.DeviceTDesktopWindows(),
	Resolver: telegram.TDesktopResolver(),
})

func TestClient added in v0.19.0

func TestClient(ctx context.Context, opts Options, cb func(ctx context.Context, client *Client) error) error

TestClient creates and authenticates user telegram.Client using Telegram test server.

func TimezoneParams added in v0.156.0

func TimezoneParams(loc *time.Location) tg.JSONValueClass

TimezoneParams builds the initConnection params value with the tz_offset field, matching what the official clients (e.g. Telegram Desktop) send.

The offset is the timezone offset of loc in seconds, rounded to the nearest 15 minutes (900 seconds) and clamped to the [-12h, +14h] range, exactly like Telegram Desktop's prepareInitParams.

Types

type AuthLostError

type AuthLostError struct {
	// Err is the RPC error that revealed the lost authorization, e.g.
	// AUTH_KEY_UNREGISTERED or SESSION_REVOKED.
	Err error
	// Reason is the error returned by Options.OnAuthLost.
	Reason error
}

AuthLostError is returned by Client.Run when the authorization of a client is lost (e.g. the session was terminated from another device) and Options.OnAuthLost returned an error.

Use errors.As to match it.

func (*AuthLostError) Error

func (e *AuthLostError) Error() string

Error implements error.

func (*AuthLostError) Kind

func (e *AuthLostError) Kind() AuthLostKind

Kind returns why authorization is lost.

func (*AuthLostError) Unwrap

func (e *AuthLostError) Unwrap() []error

Unwrap returns both underlying errors.

type AuthLostKind

type AuthLostKind int

AuthLostKind is why authorization is lost, see AuthLostKindOf.

const (
	// AuthLostUnknown is an error that is not one of IsAuthLost errors.
	AuthLostUnknown AuthLostKind = iota
	// AuthLostBanned means that the account is banned by Telegram
	// (USER_DEACTIVATED_BAN).
	AuthLostBanned
	// AuthLostDeleted means that the account is deleted (USER_DEACTIVATED).
	AuthLostDeleted
	// AuthLostRevoked means that the session was terminated, e.g. from
	// another device (SESSION_REVOKED), or the server asked to drop the key
	// (AUTH_KEY_DROP_* service notification).
	AuthLostRevoked
	// AuthLostUnregistered means that the server doesn't know the auth key
	// as an authorized one (AUTH_KEY_UNREGISTERED). It is what a terminated
	// session usually returns, but also what the keys of a deleted or banned
	// account return once they are dropped.
	AuthLostUnregistered
	// AuthLostExpired means that the session expired (SESSION_EXPIRED).
	AuthLostExpired
	// AuthLostKeyInvalid means that the auth key is invalid or used by
	// another connection (AUTH_KEY_INVALID, AUTH_KEY_DUPLICATED).
	AuthLostKeyInvalid
)

func AuthLostKindOf

func AuthLostKindOf(err error) AuthLostKind

AuthLostKindOf classifies an error of IsAuthLost.

func (AuthLostKind) String

func (k AuthLostKind) String() string

String implements fmt.Stringer. Values are used in logs and metrics.

type AuthTransferHandler added in v0.96.0

type AuthTransferHandler func(ctx context.Context, client *Client, fn func(context.Context) error) error

AuthTransferHandler is a function that is called during authorization transfer.

The fn callback should be serialized by user id via external locking. You can call Client.Self to acquire current user id.

The fn callback must return fn error if any.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client represents a MTProto client to Telegram.

Example (Mtproxy)
package main

import (
	"context"
	"encoding/hex"
	"fmt"
	"os"
	"os/signal"

	"github.com/go-faster/errors"

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

func connectViaMTProxy(ctx context.Context) error {
	secret, err := hex.DecodeString(os.Getenv("SECRET"))
	if err != nil {
		return errors.Wrap(err, "parse secret")
	}

	resolver, err := dcs.MTProxy(
		os.Getenv("PROXY_ADDR"),
		secret,
		dcs.MTProxyOptions{},
	)
	if err != nil {
		return errors.Wrap(err, "create MTProxy resolver")
	}

	client, err := telegram.ClientFromEnvironment(telegram.Options{
		Resolver: resolver,
	})
	if err != nil {
		return errors.Wrap(err, "create client")
	}

	return client.Run(ctx, func(ctx context.Context) error {
		cfg, err := tg.NewClient(client).HelpGetConfig(ctx)
		if err != nil {
			return errors.Wrap(err, "get config")
		}

		fmt.Println("This DC: ", cfg.ThisDC)
		return nil
	})
}

func main() {
	ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
	defer cancel()

	if err := connectViaMTProxy(ctx); err != nil {
		_, _ = fmt.Fprintf(os.Stderr, "%+v\n", err)
		os.Exit(1)
	}
}

func ClientFromEnvironment added in v0.19.0

func ClientFromEnvironment(opts Options) (*Client, error)

ClientFromEnvironment creates client using OptionsFromEnvironment but does not connect to server.

Variables:

APP_ID:   app_id of Telegram app.
APP_HASH: app_hash of Telegram app.

func Connect

func Connect(ctx context.Context, appID int, appHash string, opt Options, so ...StartOption) (*Client, error)

Connect creates a new client with NewClient and starts it with Start.

The ctx bounds the startup only, see Start. Call Close on the returned client to stop it. On error the client is fully stopped and nil is returned.

func NewClient added in v0.9.0

func NewClient(appID int, appHash string, opt Options) *Client

NewClient creates new unstarted client.

func (*Client) API added in v0.43.0

func (c *Client) API() *tg.Client

API returns *tg.Client for calling raw MTProto methods.

func (*Client) Auth added in v0.43.0

func (c *Client) Auth() *auth.Client

Auth returns auth client.

Example (Bot)
package main

import (
	"context"
	"os"

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

func main() {
	ctx := context.Background()
	client := telegram.NewClient(telegram.TestAppID, telegram.TestAppHash, telegram.Options{})
	if err := client.Run(ctx, func(ctx context.Context) error {
		// Checking auth status.
		status, err := client.Auth().Status(ctx)
		if err != nil {
			return err
		}
		// Can be already authenticated if we have valid session in
		// session storage.
		if !status.Authorized {
			// Otherwise, perform bot authentication.
			if _, err := client.Auth().Bot(ctx, os.Getenv("BOT_TOKEN")); err != nil {
				return err
			}
		}

		// All good, manually authenticated.
		return nil
	}); err != nil {
		panic(err)
	}
}
Example (CodeOnly)
package main

import (
	"bufio"
	"context"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"

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

func main() {
	check := func(err error) {
		if err != nil {
			panic(err)
		}
	}

	var (
		appIDString = os.Getenv("APP_ID")
		appHash     = os.Getenv("APP_HASH")
		phone       = os.Getenv("PHONE")
	)
	if appIDString == "" || appHash == "" || phone == "" {
		log.Fatal("PHONE, APP_ID or APP_HASH is not set")
	}

	appID, err := strconv.Atoi(appIDString)
	check(err)

	ctx := context.Background()
	client := telegram.NewClient(appID, appHash, telegram.Options{})
	codeAsk := func(ctx context.Context, sentCode *tg.AuthSentCode) (string, error) {
		fmt.Print("code:")
		code, err := bufio.NewReader(os.Stdin).ReadString('\n')
		if err != nil {
			return "", err
		}
		code = strings.ReplaceAll(code, "\n", "")
		return code, nil
	}

	check(client.Run(ctx, func(ctx context.Context) error {
		return auth.NewFlow(
			auth.CodeOnly(phone, auth.CodeAuthenticatorFunc(codeAsk)),
			auth.SendCodeOptions{},
		).Run(ctx, client.Auth())
	}))
}
Example (Password)
package main

import (
	"bufio"
	"context"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"

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

func main() {
	check := func(err error) {
		if err != nil {
			panic(err)
		}
	}

	var (
		appIDString = os.Getenv("APP_ID")
		appHash     = os.Getenv("APP_HASH")
		phone       = os.Getenv("PHONE")
		pass        = os.Getenv("PASSWORD")
	)
	if appIDString == "" || appHash == "" || phone == "" || pass == "" {
		log.Fatal("PHONE, PASSWORD, APP_ID or APP_HASH is not set")
	}

	appID, err := strconv.Atoi(appIDString)
	check(err)

	ctx := context.Background()
	client := telegram.NewClient(appID, appHash, telegram.Options{})
	codeAsk := func(ctx context.Context, sentCode *tg.AuthSentCode) (string, error) {
		fmt.Print("code:")
		code, err := bufio.NewReader(os.Stdin).ReadString('\n')
		if err != nil {
			return "", err
		}
		code = strings.ReplaceAll(code, "\n", "")
		return code, nil
	}

	check(client.Run(ctx, func(ctx context.Context) error {
		return auth.NewFlow(
			auth.Constant(phone, pass, auth.CodeAuthenticatorFunc(codeAsk)),
			auth.SendCodeOptions{},
		).Run(ctx, client.Auth())
	}))
}
Example (Test)
package main

import (
	"context"

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

func main() {
	// Example of using test server.
	const dcID = 2

	ctx := context.Background()
	client := telegram.NewClient(telegram.TestAppID, telegram.TestAppHash, telegram.Options{
		DC:     dcID,
		DCList: dcs.Test(),
	})
	if err := client.Run(ctx, func(ctx context.Context) error {
		return client.Auth().Test(ctx, dcID)
	}); err != nil {
		panic(err)
	}
}

func (*Client) CDN added in v0.142.0

func (c *Client) CDN(ctx context.Context, dc int, max int64) (CloseInvoker, error)

CDN creates new multi-connection invoker to given CDN DC ID. It connects to CDN DCs.

func (*Client) CDNProvider

func (c *Client) CDNProvider() downloader.CDNProvider

CDNProvider returns downloader.CDNProvider that serves CDN redirects using cached CDN pools of the client.

Wrap any downloader.Client with it via downloader.WithCDNProvider to enable CDN downloads through it.

func (*Client) Close

func (c *Client) Close() error

Close is Shutdown without a deadline: it stops the client started by Start and waits until all of its background work is finished.

It returns the error that stopped the client before Close was called, e.g. *AuthLostError (the same as Wait), or nil if Close stopped it or if Start failed.

Close is idempotent and safe to call concurrently, also before Start (then the client can not be started anymore). Never call Close from update handlers, OnAuthLost or other callbacks running inside the client, it would deadlock: use Stop there. Close returns ErrAlreadyStarted for a client driven by Run.

func (*Client) Config added in v0.26.0

func (c *Client) Config() tg.Config

Config returns current config.

func (*Client) DC added in v0.22.0

func (c *Client) DC(ctx context.Context, dc int, max int64) (CloseInvoker, error)

DC creates new multi-connection invoker to given DC.

func (*Client) Done

func (c *Client) Done() <-chan struct{}

Done returns a channel that is closed when the client stops for any reason: Stop or Close, a fatal error, the end of the lifetime context, a failed Start or the return of Run. Use Wait to get the reason.

func (*Client) Download added in v0.142.0

func (c *Client) Download(location tg.InputFileLocationClass) *downloader.Builder

Download creates Builder for plain file downloads.

func (*Client) DownloadScheduler

func (c *Client) DownloadScheduler(dc int) *downloader.Scheduler

DownloadScheduler returns the download Scheduler of given DC, created on first use with Options.DownloadScheduler, or nil if it is not set.

Each DC has its own window: a flood wait of one DC doesn't shrink the window of another one.

func (*Client) DownloadVia

func (c *Client) DownloadVia(invoker tg.Invoker, location tg.InputFileLocationClass) *downloader.Builder

DownloadVia creates Builder for plain file downloads, sending requests to master DC through given invoker, e.g. a pool from Client.Pool, Client.DC or Client.MediaOnly.

Unlike passing tg.NewClient(invoker) to downloader directly, CDN redirects are served through CDN pools of the client (if CDN is allowed). No Scheduler is set, as the DC of invoker is unknown: use Builder.WithScheduler(c.DownloadScheduler(dc)).

func (*Client) DownloadWeb added in v0.142.0

func (c *Client) DownloadWeb(location tg.InputWebFileLocationClass) *downloader.Builder

DownloadWeb creates Builder for web file downloads.

func (*Client) DownloadWebVia

func (c *Client) DownloadWebVia(invoker tg.Invoker, location tg.InputWebFileLocationClass) *downloader.Builder

DownloadWebVia creates Builder for web file downloads through given invoker.

func (*Client) Downloader added in v0.142.0

func (c *Client) Downloader() *downloader.Downloader

Downloader returns file downloader configured for current client: CDN policy from Options.AllowCDN, metrics from Options.MeterProvider and logs from Options.Logger (named "downloader").

Each call returns a new copy, so its With* methods don't affect other downloads; instruments are shared and created once.

It has no Scheduler: use Downloader.WithScheduler with Client.DownloadScheduler of the DC the downloads go to.

func (*Client) FileDC

func (c *Client) FileDC(ctx context.Context, dc int) (tg.Invoker, error)

FileDC returns invoker for file requests (e.g. upload.getFile) to given DC.

Unlike Client.DC, the pool is created once per DC (concurrent callers share creation), cached and closed when Run returns, so callers can call FileDC for every request. Its size is Options.FilePoolSize.

The invoker:

  • is wrapped with Options.Middlewares (flood wait, rate limit, metrics);
  • uses the primary session for the home DC, without authorization transfer;
  • follows FILE_MIGRATE_X errors to FileDC(X).

Must be called while client is running, otherwise an error is returned.

If a request fails as unauthorized, the cached pool of that DC is dropped and the request is retried once on a new pool with authorization transfer.

func (*Client) FreezeState

func (c *Client) FreezeState(ctx context.Context) (FreezeState, error)

FreezeState fetches app config and returns the freeze state of the account.

func (*Client) Invoke added in v0.43.0

func (c *Client) Invoke(ctx context.Context, input bin.Encoder, output bin.Decoder) error

Invoke invokes raw MTProto RPC method. It sends input and decodes result into output.

func (*Client) InvokeRawJSON added in v0.135.0

func (c *Client) InvokeRawJSON(ctx context.Context, jsonRequest string) (jsonResponse string, err error)

InvokeRawJSON invokes MTProto method using pure TDLib JSON format. It accepts JSON with @type field in TDLib format (e.g., "sendMessage") and returns JSON response in TDLib format.

The JSON structure, keys and values exactly match TDLib standard JSON. For example, use "sendMessage" not "messages.sendMessage" in @type field.

func (*Client) LogOut

func (c *Client) LogOut(ctx context.Context) (*tg.AuthLoggedOut, error)

LogOut logs the client out the way Telegram Desktop and TDLib do:

  1. auth.logOut on the home DC. A 401 error counts as success: the authorization is gone either way.
  2. auth.logOut on every other DC the client imported the authorization to (pools of *_MIGRATE redirects and of FileDC), best effort; then those pools are closed and their sessions forgotten.
  3. The stored session is wiped, so the next client started with the same storage creates a new auth key and starts unauthorized.

Like TDLib, LogOut is irrevocable: the local steps run even if auth.logOut fails, and its error is returned after them. Lost authorization is not reported to OnAuthLost while and after logging out, and the client stops saving its session until it is authorized again.

The client keeps running, unauthorized, on its current auth key; sign in again or stop it. The auth keys are not destroyed on the server (destroy_auth_key).

The result carries auth.loggedOut.future_auth_token, if the server sent one: pass it to a later sign-in (auth.sendCode logout_tokens) to skip the code.

func (*Client) MediaOnly added in v0.30.0

func (c *Client) MediaOnly(ctx context.Context, dc int, max int64) (CloseInvoker, error)

MediaOnly creates new multi-connection invoker to given DC ID. It connects to MediaOnly DCs.

func (*Client) MigrateTo added in v0.52.0

func (c *Client) MigrateTo(ctx context.Context, dcID int) error

MigrateTo forces client to migrate to another DC.

func (*Client) Ping

func (c *Client) Ping(ctx context.Context) error

Ping sends low level ping request to Telegram server.

func (*Client) Pool added in v0.22.0

func (c *Client) Pool(max int64) (CloseInvoker, error)

Pool creates new multi-connection invoker to current DC.

func (*Client) QR added in v0.52.0

func (c *Client) QR() qrlogin.QR

QR returns QR login helper.

func (*Client) RandInt64

func (c *Client) RandInt64() (int64, error)

RandInt64 returns new random int64 from random source.

Useful helper for places in API where random int is required.

func (*Client) Run added in v0.18.0

func (c *Client) Run(ctx context.Context, f func(ctx context.Context) error) (err error)

Run starts client session and blocks until connection close. The f callback is called on successful session initialization and Run will return on f() result.

Context of callback will be canceled if fatal error is detected. The ctx is used for background operations like updates handling or pools.

Run is single-use: create a new Client to run again. See Start, Close and Wait for the classic approach without explicit callback; Run and Start are mutually exclusive on one Client (ErrAlreadyStarted). Done and Wait report the result of Run once it returned.

func (*Client) Self added in v0.11.0

func (c *Client) Self(ctx context.Context) (*tg.User, error)

Self returns current user.

You can use tg.User.Bot to check whether current user is bot.

func (*Client) SelfID

func (c *Client) SelfID() (id int64, bot bool, ok bool)

SelfID returns the ID of the authorized user or bot and whether it is a bot, without a request: ok is false if it is not known yet. It is known after a successful Self call (including the one Run makes on connect) and is restored from the stored session.

func (*Client) SendMessage deprecated

func (c *Client) SendMessage(ctx context.Context, req *tg.MessagesSendMessageRequest) error

SendMessage sends message to peer.

Deprecated: use helpers like message.NewSender.

func (*Client) ServerTimeOffset

func (c *Client) ServerTimeOffset() time.Duration

ServerTimeOffset returns the server time minus local time observed by the client, to be passed as Options.ServerTimeOffset on the next start. It is zero until the first connection to the server.

func (*Client) Shutdown

func (c *Client) Shutdown(ctx context.Context) error

Shutdown stops the client started by Start, like Stop, and waits until all of its background work (connections, pools, update handlers and OnAuthLost callbacks) is finished or ctx is done, like http.Server.Shutdown.

It returns the error that stopped the client before Shutdown was called, e.g. *AuthLostError (the same as Wait), or nil if Shutdown stopped it or if Start failed, as Start already returned the error. If ctx is done first, it returns the wrapped ctx.Err(), and the client keeps stopping in background.

Do not call Shutdown or Close from update handlers, OnAuthLost or other callbacks running inside the client: the client waits for them to return, so the call blocks until ctx is done. Use Stop there.

Shutdown returns ErrAlreadyStarted for a client driven by Run.

func (*Client) Start

func (c *Client) Start(ctx context.Context, opts ...StartOption) error

Start connects the client in the background and blocks until it is ready for requests, which is the moment Run would call its callback, or until it fails.

The ctx bounds the startup only, like in net.Dialer.DialContext: once Start returned, the client runs until Stop or Close, a fatal error (e.g. *AuthLostError or a permanent connection error) or the end of the context passed via WithLifetime. Note that the client reconnects indefinitely on transient errors, so use ctx with a deadline to bound the startup.

Start returns the wrapped ctx.Err() if ctx is done before the client is ready, or the error that stopped the client before it got ready, e.g. *ConfigError. On error the client is fully stopped: no goroutines are left behind, and Close returns nil at once.

The client is valid for requests, e.g. via API, between a successful Start and Close, as inside the Run callback. Use Done or Wait to learn that it stopped, and Close to release resources:

if err := client.Start(ctx); err != nil {
	return err
}
defer func() { _ = client.Close() }()

Start and Run are mutually exclusive, and a Client can be started once: create a new Client to start again. Start supersedes the github.com/gotd/contrib/bg package.

Example

Bot without Run: Start, use the client, then Wait until it stops.

package main

import (
	"context"
	"fmt"
	"os"
	"os/signal"
	"time"

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

func main() {
	if err := func() error {
		ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
		defer stop()

		client, err := telegram.ClientFromEnvironment(telegram.Options{})
		if err != nil {
			return err
		}

		// Bound the startup: the client reconnects until ready otherwise.
		startCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
		defer cancel()
		// Stop the client on interrupt. Without WithLifetime it runs until
		// Close or a fatal error: startCtx bounds the startup only.
		if err := client.Start(startCtx, telegram.WithLifetime(ctx)); err != nil {
			return err
		}
		defer func() { _ = client.Close() }()

		if _, err := client.Auth().Bot(ctx, os.Getenv("BOT_TOKEN")); err != nil {
			return err
		}
		sender := message.NewSender(client.API())
		if _, err := sender.Resolve("@durov").Text(ctx, "Hello!"); err != nil {
			return err
		}

		// Block until interrupt or a fatal error, e.g. *telegram.AuthLostError.
		return client.Wait(context.Background())
	}(); err != nil {
		fmt.Println(err)
	}
}

func (*Client) Stop

func (c *Client) Stop()

Stop stops the client started by Start without waiting for it: use Done, Wait or Close to wait. Unlike Close and Shutdown, Stop is safe to call from update handlers, OnAuthLost and other callbacks running inside the client.

Stop is idempotent and safe to call concurrently, also before Start (then the client can not be started anymore). Stop does nothing for a client driven by Run: cancel the Run context or return from its callback instead.

func (*Client) Wait

func (c *Client) Wait(ctx context.Context) error

Wait blocks until the client stops or ctx is done.

It returns the error that stopped the client, e.g. *AuthLostError, a permanent connection error, the error returned by a failed Start or by Run, nil if it was stopped by Stop or Close or by the end of the lifetime context, or the wrapped ctx.Err() if ctx is done first.

Unlike Close, Wait does not stop the client, so it is the blocking "run until disconnected" call of the Start style:

return client.Wait(ctx)

type CloseInvoker added in v0.26.0

type CloseInvoker interface {
	tg.Invoker
	Close() error
}

CloseInvoker is a closeable tg.Invoker.

type ConfigError

type ConfigError struct {
	// Err is the RPC error returned to initConnection.
	Err *tgerr.Error
}

ConfigError is returned by Client.Run when the server rejects the connection setup (initConnection) with an error that reconnecting cannot fix, e.g. API_ID_INVALID, API_ID_PUBLISHED_FLOOD or CONNECTION_API_ID_INVALID: the client is misconfigured.

Use errors.As to match it.

func (*ConfigError) Error

func (e *ConfigError) Error() string

Error implements error.

func (*ConfigError) Unwrap

func (e *ConfigError) Unwrap() error

Unwrap returns the RPC error.

type ConnDeadEvent

type ConnDeadEvent struct {
	// DC is the ID of the DC of the connection.
	DC int
	// Kind is the kind of the connection.
	Kind ConnKind
	// Err is the reason.
	Err error
}

ConnDeadEvent describes a dead connection.

See Options.OnConnDead.

type ConnKind

type ConnKind int

ConnKind is the kind of client connection.

const (
	// ConnKindPrimary is the primary connection of Client.Run.
	ConnKindPrimary ConnKind = iota
	// ConnKindData is a connection of a pool: Client.Pool, Client.DC,
	// Client.MediaOnly, Client.FileDC, or a FILE_MIGRATE connection.
	ConnKindData
	// ConnKindCDN is a connection to a CDN DC.
	ConnKindCDN
)

func (ConnKind) String

func (k ConnKind) String() string

String implements fmt.Stringer.

type ConnectionState added in v0.151.0

type ConnectionState int

ConnectionState represents the state of the primary connection.

See Options.OnConnectionState.

const (
	// ConnectionStateConnecting means that client is establishing the primary
	// connection (initial connect or reconnect after failure).
	ConnectionStateConnecting ConnectionState = iota
	// ConnectionStateReady means that the primary connection is initialized
	// and ready to send requests.
	ConnectionStateReady
	// ConnectionStateDisconnected means that the primary connection is dead.
	// Client will reconnect automatically, transitioning to
	// ConnectionStateConnecting.
	ConnectionStateDisconnected
)

func (ConnectionState) String added in v0.151.0

func (s ConnectionState) String() string

String implements fmt.Stringer.

type ConnectionStateEvent

type ConnectionStateEvent struct {
	// DC is the ID of the DC of the primary connection.
	DC int
	// State is the new state.
	State ConnectionState
}

ConnectionStateEvent describes a state change of the primary connection.

See Options.OnConnectionStateEvent.

type DeviceConfig added in v0.21.0

type DeviceConfig = manager.DeviceConfig

DeviceConfig is config which send when Telegram connection session created.

func DeviceTDesktopWindows added in v0.156.0

func DeviceTDesktopWindows() DeviceConfig

DeviceTDesktopWindows returns a DeviceConfig that emulates a Telegram Desktop (Windows build) installation on initConnection, making the connection parameters indistinguishable from Telegram Desktop from the server's perspective.

Combine it with TDesktopResolver to also match Telegram Desktop on the transport layer.

type Error

type Error = tgerr.Error

Error represents RPC error returned to request.

type FileSessionStorage

type FileSessionStorage = session.FileStorage

FileSessionStorage is alias of mtproto.FileSessionStorage.

type FreezeState

type FreezeState struct {
	// Since is when the account was frozen, zero if it is not.
	Since time.Time
	// Until is when the account will be deleted unless the appeal succeeds.
	Until time.Time
	// AppealURL is a t.me link to the bot to appeal with.
	AppealURL string
}

FreezeState is the freeze state of the account, from app config.

A frozen account is signed in and can read, but most methods fail with FROZEN_METHOD_INVALID until Until or a successful appeal.

See https://core.telegram.org/api/config#freeze-since-date.

func FreezeStateFrom

func FreezeStateFrom(cfg tg.JSONValueClass) FreezeState

FreezeStateFrom returns the freeze state from help.getAppConfig result.

func (FreezeState) Frozen

func (s FreezeState) Frozen() bool

Frozen reports whether the account is frozen.

type InvokeFunc added in v0.43.0

type InvokeFunc func(ctx context.Context, input bin.Encoder, output bin.Decoder) error

InvokeFunc implements tg.Invoker as function.

func (InvokeFunc) Invoke added in v0.43.0

func (i InvokeFunc) Invoke(ctx context.Context, input bin.Encoder, output bin.Decoder) error

Invoke implements tg.Invoker.

type Middleware added in v0.43.0

type Middleware interface {
	Handle(next tg.Invoker) InvokeFunc
}

Middleware returns new InvokeFunc for next invoker.

Example
invoker := InvokeFunc(func(ctx context.Context, input bin.Encoder, output bin.Decoder) error {
	fmt.Println("invoke")
	return nil
})
printMiddleware := func(message string) Middleware {
	return MiddlewareFunc(func(next tg.Invoker) InvokeFunc {
		return func(ctx context.Context, input bin.Encoder, output bin.Decoder) error {
			fmt.Println(message, "(start)")
			err := next.Invoke(ctx, input, output)
			fmt.Println(message, "(end)")
			return err
		}
	})
}

// Testing composed invoker.
_ = chainMiddlewares(invoker,
	printMiddleware("first"),
	printMiddleware("second"),
).Invoke(context.Background(), nil, nil)
Output:
first (start)
second (start)
invoke
second (end)
first (end)

type MiddlewareFunc added in v0.43.0

type MiddlewareFunc func(next tg.Invoker) InvokeFunc

MiddlewareFunc implements Middleware as function.

func (MiddlewareFunc) Handle added in v0.43.0

func (m MiddlewareFunc) Handle(next tg.Invoker) InvokeFunc

Handle implements Middleware.

type Options

type Options struct {
	// PublicKeys of telegram.
	//
	// If not provided, embedded public keys will be used.
	PublicKeys []PublicKey

	// DC ID to connect.
	//
	// If not provided, 2 will be used by default.
	DC int

	// DCList is initial list of addresses to connect.
	DCList dcs.List

	// Resolver to use.
	Resolver dcs.Resolver

	// NoUpdates enables no updates mode.
	//
	// Enabled by default if no UpdateHandler is provided.
	NoUpdates bool

	// AllowCDN enables downloader CDN redirect flow for clients that support
	// downloader integration.
	//
	// If false, downloader will stay on the master DC path (legacy behavior).
	// If true and server does not return redirect, requests still go through the
	// same master path (no extra CDN round-trips).
	// Default is false.
	AllowCDN bool
	// DownloadScheduler enables adaptive limits of in-flight part requests
	// shared by downloads of the client: one downloader.Scheduler per DC,
	// created with these options, see Client.DownloadScheduler.
	//
	// Client.Download and DownloadWeb use the Scheduler of the home DC.
	// DownloadVia and DownloadWebVia use none, as the DC of the invoker is
	// unknown: pass Builder.WithScheduler(client.DownloadScheduler(dc)).
	// Builder.WithScheduler overrides it for one download. Default is nil (no
	// shared limit).
	DownloadScheduler *downloader.SchedulerOptions
	// ReconnectionBackoff configures and returns reconnection backoff object.
	ReconnectionBackoff func() backoff.BackOff
	// OnDead will be called on connection dead.
	//
	// It is called for all connections: primary, pools and CDN, without
	// telling them apart. Prefer OnConnDead in new code.
	OnDead func(error)
	// OnConnDead is called on connection dead with the DC ID and the kind of
	// the connection, e.g. for metrics. Preferred over OnDead, which is kept
	// for compatibility; if both are set, OnDead is called first.
	//
	// Called from the connection lifecycle, so the callback must not block.
	OnConnDead func(ConnDeadEvent)
	// OnConnectionState is called when the primary connection state changes:
	// on every (re)connect start, on successful initialization and on
	// connection loss. Connection death details are reported via OnDead.
	//
	// Called synchronously from connection lifecycle, so the callback must
	// not block.
	OnConnectionState func(ConnectionState)
	// OnConnectionStateEvent is OnConnectionState with the DC ID of the
	// primary connection the state is about, which changes on migration.
	// Preferred over OnConnectionState, which is kept for compatibility; if
	// both are set, OnConnectionState is called first. Same constraints.
	OnConnectionStateEvent func(ConnectionStateEvent)
	// MigrationTimeout configures migration timeout.
	MigrationTimeout time.Duration
	// FilePoolSize is the max number of connections of each pool returned by
	// Client.FileDC. Defaults to 4.
	FilePoolSize int64

	// Random is random source. Defaults to crypto.
	Random io.Reader
	// Logger is the structured logger. No logs by default.
	//
	// Use github.com/gotd/log/logzap to bridge a *zap.Logger:
	//
	//	import (
	//		"go.uber.org/zap"
	//		"github.com/gotd/log/logzap"
	//	)
	//
	//	zapLog, _ := zap.NewProduction()
	//	opts := telegram.Options{
	//		Logger: logzap.New(zapLog),
	//	}
	Logger log.Logger
	// SessionStorage will be used to load and save session data.
	// NB: Very sensitive data, save with care.
	SessionStorage SessionStorage
	// UpdateHandler will be called on received update.
	UpdateHandler UpdateHandler
	// Middlewares list allows wrapping tg.Invoker. Can be useful for metrics,
	// tracing, etc. Note that order is important, see ExampleMiddleware.
	//
	// Middlewares are called in order from first to last.
	Middlewares []Middleware

	// AckBatchSize is limit of MTProto ACK buffer size.
	AckBatchSize int
	// AckInterval is maximum time to buffer MTProto ACK.
	AckInterval time.Duration
	// RetryInterval is duration between send retries.
	RetryInterval time.Duration
	// MaxRetries is limit of send retries.
	MaxRetries int
	// ExchangeTimeout is timeout of every key exchange request.
	ExchangeTimeout time.Duration
	// DialTimeout is timeout of creating connection.
	DialTimeout time.Duration
	// PingInterval is duration between pings (ping_delay_disconnect) of a
	// connection. Zero (default) pings like Telegram Desktop, every 30–45
	// seconds with disconnect_delay 60; see mtproto.Options.
	PingInterval time.Duration
	// PingTimeout is the timeout of ping response, after which the connection
	// is considered dead. Defaults to 15 seconds, see mtproto.Options.
	PingTimeout time.Duration
	// RequestTimeout returns response deadline for a request on the primary
	// connection, zero to wait as long as the request context allows
	// (optional).
	//
	// If the deadline passes while the request context is still alive (e.g.
	// the request was acknowledged but never answered by a half-dead
	// connection), the client reconnects and sends the request once more on
	// the new connection, like Telegram Desktop does. Return zero for
	// requests that must not be sent twice.
	RequestTimeout func(input bin.Encoder) time.Duration
	// EnablePFS enables Perfect Forward Secrecy with temporary auth keys.
	EnablePFS bool
	// TempKeyTTL controls temporary key lifetime in seconds.
	// Default: 86400 (24h).
	// The value is clamped in mtproto layer to keep protocol-safe bounds.
	TempKeyTTL int

	// CompressThreshold is a threshold in bytes to determine that message
	// is large enough to be compressed using GZIP.
	// If < 0, compression will be disabled.
	// If == 0, default value will be used.
	CompressThreshold int

	// Device is device config.
	// Will be sent with session creation request.
	Device DeviceConfig

	// Layer is the schema layer to request via invokeWithLayer.
	//
	// If not provided, tg.Layer will be used, i.e. the layer of the schema
	// this package is generated from. Override it only if the server must be
	// asked for an older layer; requests are still encoded using tg.Layer
	// schema, so a mismatch may cause decoding errors.
	Layer int

	MessageID mtproto.MessageIDSource
	Clock     clock.Clock
	// ServerTimeOffset is the initial server time minus local time, e.g.
	// Client.ServerTimeOffset of a previous run. It is corrected from the
	// first message of the server; message ids and the msg_id time check use
	// server time, so a skewed local clock doesn't break the connection.
	ServerTimeOffset time.Duration

	// OpenTelemetry.
	TracerProvider trace.TracerProvider
	// MeterProvider is used for client metrics (gotd.client.*): connection
	// states, dead connections, reconnects, migrations, lost authorization,
	// request timeouts, cached DC pools and Invoke durations. No metrics by
	// default; the global provider is not used.
	//
	// It is also used by Client.Downloader and Client.Download* (gotd.downloader.*)
	// and by schedulers of Options.DownloadScheduler, with attribute dc. The
	// updates manager (telegram/updates) is configured separately: set
	// updates.Config.MeterProvider too.
	MeterProvider metric.MeterProvider

	// WireTracer observes plaintext MTProto messages and lifecycle events of
	// every connection of the client: primary, other DCs, media and CDN
	// connections. Nil (default) disables wire tracing.
	//
	// See mtproto.WireTracer.
	WireTracer mtproto.WireTracer

	// OnTransfer is called during authorization transfer.
	// See [AuthTransferHandler] for details.
	OnTransfer AuthTransferHandler

	// OnSelfError is called when client receives error calling Self() on connect.
	// Return error to stop reconnection.
	//
	// NB: this method is called immediately after connection, so it's not expected to be
	// non-nil error on first connection before auth, so it's safe to return nil until
	// first successful auth.
	OnSelfError func(ctx context.Context, err error) error

	// OnSelfSuccess is called when client get self calling Self() on connect.
	OnSelfSuccess func(self *tg.User)

	// OnAuthLost is called when a request of an authorized client fails
	// with an error meaning that the authorization is lost (see IsAuthLost),
	// e.g. the session was terminated from another device. Called once until
	// the client is authorized again.
	//
	// The client counts as authorized after any successful request that
	// requires authorization (anything but auth.*, help.*, langpack.* and the
	// 2FA/login email account.* methods), including Self() on connect, or
	// after a sign in that returned a complete authorization. So a session
	// restored from storage is covered after its first such request, also
	// with NoUpdates.
	//
	// ctx is the context of Run, not of the failed request, so the callback
	// can make requests, e.g. to sign in again. The callback runs on its own
	// goroutine, so the failed request returns at once, and Run waits for it
	// before returning.
	//
	// Return non-nil error to stop Run with *AuthLostError, so that one
	// account of many can be stopped and reported. Return nil to keep
	// running, e.g. to sign in again.
	//
	// If the connect-time Self() of an authorized client reveals the lost
	// authorization (e.g. on reconnect), OnAuthLost is called first. If it
	// returns nil, OnSelfError is called too, as for any Self() error; if
	// it stops Run, OnSelfError is not called. Before the client is
	// authorized, such errors are reported via OnSelfError only.
	OnAuthLost func(ctx context.Context, err error) error

	// OnFrozen is called when a request fails because the account is frozen
	// (see IsFrozen) and app config confirms it. The account stays signed in
	// and can read, but most methods fail until state.Until or a successful
	// appeal via state.AppealURL.
	//
	// The freeze state is checked at most once an hour, on its own
	// goroutine; ctx is the context of Run. Use Client.FreezeState to check
	// it at any time, e.g. at start.
	OnFrozen func(ctx context.Context, state FreezeState)
}

Options of Client.

Example (ConnectionState)
package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"strconv"

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

func main() {
	appID, err := strconv.Atoi(os.Getenv("APP_ID"))
	if err != nil {
		log.Fatal("APP_ID not set or invalid")
	}
	appHash := os.Getenv("APP_HASH")

	client := telegram.NewClient(appID, appHash, telegram.Options{
		OnConnectionState: func(state telegram.ConnectionState) {
			// Called on primary connection state change: connecting, ready,
			// disconnected. Callback must not block.
			fmt.Println("connection state:", state)
		},
	})
	if err := client.Run(context.Background(), func(ctx context.Context) error {
		// Connection state transitions are reported while client is running,
		// including automatic reconnects.
		return nil
	}); err != nil {
		log.Fatal(err)
	}
}

func OptionsFromEnvironment added in v0.19.0

func OptionsFromEnvironment(opts Options) (Options, error)

OptionsFromEnvironment fills unfilled field in opts parameter using environment variables.

Variables:

SESSION_FILE:        path to session file
SESSION_DIR:         path to session directory, if SESSION_FILE is not set
ALL_PROXY, NO_PROXY: see https://pkg.go.dev/golang.org/x/net/proxy#FromEnvironment

type PublicKey added in v0.50.0

type PublicKey = exchange.PublicKey

PublicKey is a Telegram server public key.

type SessionStorage

type SessionStorage = session.Storage

SessionStorage is alias of mtproto.SessionStorage.

type StartOption

type StartOption interface {
	// contains filtered or unexported methods
}

StartOption configures Client.Start.

func WithLifetime

func WithLifetime(ctx context.Context) StartOption

WithLifetime sets the parent context of the client started by Start: when ctx is done, the client stops as if Stop was called, and Wait and Close return nil.

By default the lifetime is context.WithoutCancel of the ctx passed to Start, so values like loggers and trace spans are kept, but the cancellation and deadline of the startup ctx do not stop the started client.

type UpdateHandler

type UpdateHandler interface {
	Handle(ctx context.Context, u tg.UpdatesClass) error
}

UpdateHandler will be called on received updates from Telegram.

type UpdateHandlerFunc added in v0.39.0

type UpdateHandlerFunc func(ctx context.Context, u tg.UpdatesClass) error

UpdateHandlerFunc type is an adapter to allow the use of ordinary function as update handler.

UpdateHandlerFunc(f) is an UpdateHandler that calls f.

func (UpdateHandlerFunc) Handle added in v0.39.0

Handle calls f(ctx, u)

Directories

Path Synopsis
Package auth provides authentication on top of tg.Client.
Package auth provides authentication on top of tg.Client.
qrlogin
Package qrlogin provides QR login flow implementation.
Package qrlogin provides QR login flow implementation.
srpguard
Package srpguard provides memguard-backed 2FA password handling for telegram/auth, keeping the plaintext password in locked, swap-protected memory that is wiped after the SRP answer is computed.
Package srpguard provides memguard-backed 2FA password handling for telegram/auth, keeping the plaintext password in locked, swap-protected memory that is wiped after the SRP answer is computed.
Package bot is a batteries-included bootstrap for Telegram bots on top of telegram.Client.
Package bot is a batteries-included bootstrap for Telegram bots on top of telegram.Client.
Package calls implements Telegram 1:1 phone calls (the tgcalls "v2" protocol) on top of the gotd/td MTProto client.
Package calls implements Telegram 1:1 phone calls (the tgcalls "v2" protocol) on top of the gotd/td MTProto client.
Package dcs contains Telegram DCs list and some helpers.
Package dcs contains Telegram DCs list and some helpers.
Package deeplink contains deeplink parsing helpers.
Package deeplink contains deeplink parsing helpers.
Package downloader contains downloading files helpers.
Package downloader contains downloading files helpers.
fileref
Package fileref contains helpers to refresh file references of file locations for downloader.Builder.WithRefresh.
Package fileref contains helpers to refresh file references of file locations for downloader.Builder.WithRefresh.
internal
e2etest
Package e2etest contains some helpers to make external E2E tests using Telegram test server.
Package e2etest contains some helpers to make external E2E tests using Telegram test server.
manager
Package manager contains connection management utilities.
Package manager contains connection management utilities.
upconv
Package upconv contains updates conversion helpers.
Package upconv contains updates conversion helpers.
version
Package version contains gotd module version getter.
Package version contains gotd module version getter.
Package message contains some useful utilities for creating Telegram messages.
Package message contains some useful utilities for creating Telegram messages.
entity
Package entity contains message formatting and styling helpers.
Package entity contains message formatting and styling helpers.
html
Package html contains HTML styling options.
Package html contains HTML styling options.
inline
Package inline contains inline query results builder.
Package inline contains inline query results builder.
internal/mkrun
Package mkrun contains some helpers for generation scripts.
Package mkrun contains some helpers for generation scripts.
internal/mktyping command
Binary mktyping generates TypingActionBuilder.
Binary mktyping generates TypingActionBuilder.
markdown
Package markdown contains Markdown (CommonMark) styling options.
Package markdown contains Markdown (CommonMark) styling options.
markup
Package markup contain bots inline markup builder.
Package markup contain bots inline markup builder.
peer
Package peer conatains some peer resolving and extracting helpers.
Package peer conatains some peer resolving and extracting helpers.
rich
Package rich builds Telegram rich messages.
Package rich builds Telegram rich messages.
styling
Package styling contains styling options for Telegram messages.
Package styling contains styling options for Telegram messages.
unpack
Package unpack contains some updates result unpacking helpers.
Package unpack contains some updates result unpacking helpers.
widget
Package widget contains helpers for Telegram HTML widget messages.
Package widget contains helpers for Telegram HTML widget messages.
Package peers contains helpers to work with Telegram peers.
Package peers contains helpers to work with Telegram peers.
members
Package members defines interfaces for working with chat/channel members.
Package members defines interfaces for working with chat/channel members.
Package query contains generic pagination helpers.
Package query contains generic pagination helpers.
cached
Package cached contains cached query helpers.
Package cached contains cached query helpers.
channels/participants
Package participants contains channel participants iteration helper.
Package participants contains channel participants iteration helper.
contacts/blocked
Package blocked contains blocked contacts iteration helper.
Package blocked contains blocked contacts iteration helper.
dialogs
Package dialogs contains dialog iteration helper.
Package dialogs contains dialog iteration helper.
hasher
Package hasher contains Telegram pagination hash implementation.
Package hasher contains Telegram pagination hash implementation.
internal/genutil
Package genutil is a utility package for query helpers codegeneration.
Package genutil is a utility package for query helpers codegeneration.
messages
Package messages contains message iteration helper.
Package messages contains message iteration helper.
messages/stickers/featured
Package featured contains featured stickers iteration helper.
Package featured contains featured stickers iteration helper.
photos
Package photos contains photos iteration helper.
Package photos contains photos iteration helper.
stories
Package stories contains helpers to iterate over stories.
Package stories contains helpers to iterate over stories.
Package takeout provides a wrapper for Telegram takeout sessions.
Package takeout provides a wrapper for Telegram takeout sessions.
Package thumbnail implements expanding of stripped telegram thumbnails.
Package thumbnail implements expanding of stripped telegram thumbnails.
Package tljson contains some helpers to work with JSONValue class.
Package tljson contains some helpers to work with JSONValue class.
Package updates provides a Telegram's internalState synchronization manager.
Package updates provides a Telegram's internalState synchronization manager.
hook
Package hook contains telegram update hook middleware.
Package hook contains telegram update hook middleware.
internal/e2e
Package e2e contains end-to-end updates processing test.
Package e2e contains end-to-end updates processing test.
Package uploader contains uploading files helpers.
Package uploader contains uploading files helpers.
source
Package source contains remote source interface and implementations for uploader.
Package source contains remote source interface and implementations for uploader.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL