Ответы
Answer
msg.Answer — то, что нужно почти всегда:
return msg.Answer("🌤 <b>Ясно</b>, 22°C")Он редактирует ваше собственное сообщение, если команду вызвали вы, и отвечает, если кто-то другой. Это юзербот-конвенция: ваша .weather превращается в результат, а не добавляет второе сообщение.
Reply и Edit
Когда нужно конкретное поведение:
return msg.Reply("новое сообщение в чате")
return msg.Edit("заменить текст этого сообщения")Форматирование
Текст разбирается как Telegram HTML:
msg.Answer("<b>жирный</b> <i>курсив</i> <code>моноширинный</code>")
msg.Answer("<a href=\"https://goroku.dev\">ссылка</a>")
msg.Answer("<blockquote>цитата</blockquote>")Поддерживаются: b, strong, i, em, u, s, del, code, pre, a, blockquote, tg-spoiler и tg-emoji для премиум-эмодзи.
Экранируйте всё, что пришло от пользователя
Подстановка пользовательского текста прямо в HTML ломает сообщение, если в нём есть < или &.
import "goroku/goroku/utils"
return msg.Answer("Вы написали: <code>" + utils.EscapeHTML(input) + "</code>")Опции
msg.Answer("без превью", goroku.WithNoWebpage(true))
msg.Answer("в тему форума", goroku.WithReplyTo(topicID))| Опция | Действие |
|---|---|
WithNoWebpage(bool) | Убрать превью ссылки |
WithReplyTo(int64) | Ответить на сообщение или отправить в тему форума |
WithInvertMedia(bool) | Превью над текстом |
WithWebPageMedia(url, optional, forceLarge) | Задать конкретное превью |
Длинный вывод
Telegram ограничивает сообщение примерно 4096 символами. Длинный результат отправляйте файлом:
import (
"bytes"
"goroku/goroku"
)
func (m *Mod) DumpCmd(msg *goroku.Message) error {
report := m.buildLongReport()
if len(report) < 3500 {
return msg.Answer("<pre>" + report + "</pre>")
}
_, err := m.Client.SendFile(
goroku.ChatRefID(msg.ChatID),
bytes.NewReader([]byte(report)),
"📄 Полный отчёт",
)
return err
}Прогресс долгой работы
Ответьте сразу, потом редактируйте по ходу:
func (m *Mod) SlowCmd(msg *goroku.Message) error {
if err := msg.Answer("⏳ <b>Работаю…</b>"); err != nil {
return err
}
result, err := m.doSlowThing(msg.Context())
if err != nil {
return err
}
return msg.Answer(result)
}Автоответ
Если обработчик изменил msg.Text и ни разу не вызвал Answer, диспетчер сам отправит новый текст. Явный вызов понятнее, но именно поэтому некоторые встроенные модули заканчиваются присваиванием в msg.Text.