Messages

Sending messages

The single most-used method in the library. SendMessage takes a destination, a body, and an optional bag of switches that controls everything from parse mode to flood-priority.

The basics

_, err := client.SendMessage("me", "hello, saved messages")
_, err := client.SendMessage("me", "hello, saved messages")

That call goes to your own "Saved Messages" chat — useful for development. To message someone else by username:

_, err := client.SendMessage("@durov", "ping")
_, err := client.SendMessage("@durov", "ping")

The return value is a *NewMessage: the sent message wrapped in gogram's update helper, the same type you get inside an incoming handler. You can chain operations on it — .Edit(...), .Delete(), .React(...), .Pin()— without re-fetching.

Peer ids

The peerID any parameter accepts any of:

  • An int64 chat or user id (123456, -1001234 for channels).
  • A username string ("@durov" or "durov", the @ is optional).
  • The literal string "me" for Saved Messages.
  • A phone number ("+15551234567") when you have the contact saved.
  • A t.me link ("https://t.me/durov").
  • An already-resolved InputPeer if you have one.

gogram resolves what you pass and caches the resulting InputPeer. After the first send to a username, subsequent sends are free of the contacts.resolveUsername round-trip.

SendOptions

The third argument is a pointer to SendOptions. Common fields:

ParseMode string
"Markdown" or "HTML". Defaults to whatever you set on the client.
ReplyID int32
Message id of what this reply targets.
TopicID int32
Forum topic id, for forum-enabled supergroups.
Silent bool
Deliver without notification sound.
NoForwards bool
Disable forwarding and saving on the recipient side.
LinkPreview bool
Generate a preview for URLs in the body. Default is whatever Telegram's server picks.
InvertMedia bool
Show media below the caption instead of above.
ReplyMarkup ReplyMarkup
Inline or reply keyboard. See Inline keyboards.
SendAs any
Post as a channel or linked group; takes any peer id form.
ScheduleDate int32
Unix timestamp; the message stays in the schedule queue until then.
NoForwards / Silent / Spoiler / TTL / Effect
Various flags that map directly onto fields of the underlying TL messages.sendMessage.
client.SendMessage(peerID, "*important*", &telegram.SendOptions{
	ParseMode:   "Markdown",
	ReplyID:     42,
	Silent:      true,
	NoForwards:  true,
	LinkPreview: false,
})
client.SendMessage(peerID, "*important*", &telegram.SendOptions{
	ParseMode:   "Markdown",
	ReplyID:     42,
	Silent:      true,
	NoForwards:  true,
	LinkPreview: false,
})

Replies and threads

client.On("message:*", func(m *telegram.NewMessage) error {
	_, err := m.Reply("got it")
	return err
})
client.On("message:*", func(m *telegram.NewMessage) error {
	_, err := m.Reply("got it")
	return err
})

NewMessage.Reply sets ReplyID automatically. To reply across threads in a supergroup or to a discussion-linked channel post, also set TopicID. For forum supergroups, every topic has an id you get from incoming messages or from channels.getForumTopics.

Silent and protected sends

Silent: truesends without notification sound — good for chatty bots posting status updates at 3am. NoForwards: true sets the protected flag on the message; the recipient cannot forward or save it. Both flags are independent and stack with everything else.

Scheduling

Telegram natively schedules messages on the server. The client submits the message, the server queues it for the requested time, the recipient sees it at that exact moment even if your bot is offline.

import "time"

client.ScheduleMessage(peerID, "morning standup in 5", time.Now().Add(5*time.Minute))
import "time"

client.ScheduleMessage(peerID, "morning standup in 5", time.Now().Add(5*time.Minute))

For repeating schedules, set ScheduleRepeatPeriod on SendOptions instead.

Sending as a channel

In a discussion group linked to a channel, users with the appropriate permission can post as the channel rather than as themselves. Bots in admin position can do the same:

client.SendMessage(peerID, "shipped", &telegram.SendOptions{
	SendAs: "@my_channel",
})
client.SendMessage(peerID, "shipped", &telegram.SendOptions{
	SendAs: "@my_channel",
})

Bots and group privacy

Streaming partial messages

For LLM-style typewriter effects, StreamMessage sends an initial message and then edits it repeatedly. Telegram debounces the edits server-side so you do not need to rate-limit yourself.

client.StreamMessage(peerID, func(update func(string)) {
	update("Working")
	update("Working.")
	update("Working..")
	update("Done")
})
client.StreamMessage(peerID, func(update func(string)) {
	update("Working")
	update("Working.")
	update("Working..")
	update("Done")
})