Skip to main content

Sending messages

Sending a message with the raw API means building random IDs, resolving the peer into an InputPeer, and assembling a request. The message package does all of that behind a fluent builder.

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

sender := message.NewSender(client.API())

// Send to a username, resolving it automatically.
if _, err := sender.Resolve("@durov").Text(ctx, "Hello from gotd!"); err != nil {
return err
}

Choosing a target

A Sender produces a request builder per destination:

MethodTarget
sender.Self()Saved Messages (yourself)
sender.Resolve("@name")Username, phone, t.me link or deeplink
sender.To(inputPeer)A peer you already have as tg.InputPeerClass
sender.Reply(entities, upd)Reply within an update handler

Resolve accepts usernames (@durov), t.me/durov links, tg: deeplinks and phone numbers — see Peers and resolution.

Beyond plain text

The builder returned for a target exposes the full range of message types:

b := sender.Resolve("@channel")

b.Text(ctx, "plain text")
b.Textf(ctx, "formatted %d", 42)
b.StyledText(ctx, styling.Bold("bold"), styling.Plain(" and normal"))
b.Photo(ctx, inputFile)
b.Media(ctx, document) // any uploaded media, see Uploading files
b.Dice(ctx) // 🎲
b.Poll(ctx, /* options */)

For formatted text see Styled text and HTML; for sending files see Uploading files.

Message options

Options chain before the terminal call:

sender.Resolve("@channel").
Silent(). // no notification
NoWebpage(). // no link preview
Reply(replyMsgID). // reply to a message
Text(ctx, "quiet reply without preview")

Other options include Schedule(time.Time), NoForwards(), Markup(...) for inline keyboards (see Styled text and HTML) and SendAs(peer).

Replying to updates

Inside an update handler you usually want to reply in the same chat. sender.Reply takes the update's entities and the update itself and figures out the peer for you — this is the heart of the Echo bot:

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
}
_, err := sender.Reply(e, u).Text(ctx, m.Message)
return err
})