Чтение ввода
Каждый обработчик получает *goroku.Message. Эти хелперы покрывают почти весь разбор аргументов.
Args
Всё после слова команды, с обрезанными пробелами по краям:
// .say привет всем
msg.Args() // "привет всем"
// .say
msg.Args() // ""Внутренние пробелы сохраняются — .say a b даёт "a b" — так что это безопасно для текста, который вы собираетесь отдать дословно.
ArgsList и Arg
Разбиение по пробелам:
// .ban 42 спам тут
msg.ArgsList() // []string{"42", "спам", "тут"}
msg.Arg(0) // "42"
msg.Arg(1) // "спам"
msg.Arg(9) // "" — без паникиArg не выходит за границы. Проверять длину заранее не нужно:
func (m *Mod) BanCmd(msg *goroku.Message) error {
id := msg.Arg(0)
if id == "" {
return msg.Answer(m.T("no_id", "❌ <b>Кого?</b>"))
}
reason := msg.Arg(1) // "" если не указана — и это нормально
return m.ban(id, reason)
}ArgsOrReply
Паттерн, который нужен большинству команд: взять напечатанные аргументы, а если их нет — текст сообщения, на которое ответили.
func (m *HTML) HTMLCmd(msg *goroku.Message) error {
code := msg.ArgsOrReply()
if code == "" {
return msg.Answer(m.T("no_args", "❌ <b>Пришлите текст или ответьте на сообщение</b>"))
}
return msg.Answer(code)
}Теперь работают оба варианта:
.html <b>привет</b> → отрисует напечатанную разметку
.html (в ответ) → отрисует сообщение, на которое ответилиПустой результат означает, что нет ни того ни другого — считайте это «делать нечего».
Сообщение, на которое ответили
Для всего, кроме текста, получите его целиком:
reply, err := msg.GetReplyMessage()
if err != nil || reply == nil {
return msg.Answer(m.T("reply_needed", "❌ <b>Ответьте на сообщение</b>"))
}
if reply.Media != nil {
// обработать вложение
}Чтобы требовать ответ, лучше объявить это декларативно — диспетчер отфильтрует до запуска обработчика:
"mycmd": { OnlyReply: true },Поля Message
| Поле | Тип | Смысл |
|---|---|---|
ID | int64 | ID сообщения |
ChatID | int64 | Где отправлено |
SenderID | int64 | Кто отправил |
Text | string | Текст с применённым форматированием |
RawText | string | Текст как напечатан |
Out | bool | Отправлено вами |
IsPrivate, IsGroup, IsChannel | bool | Тип чата |
Media | tg.MessageMediaClass | Вложение, nil если нет |
ReplyToMsgID | int64 | 0, если это не ответ |
IsForwarded | bool | Переслано откуда-то |
Отмена
msg.Context() отменяется при завершении бота. Передавайте его во всё долгое:
req, err := http.NewRequestWithContext(msg.Context(), http.MethodGet, url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)Обработчики, которые его игнорируют, работать не перестанут — завершение просто их дождётся.