Files
tiennm99bot/cmd/server/command_menu.go
T
tiennm99 fe552f43e4 feat(menu): sort Telegram command suggestions by name
The command menu was in module load order, which split related commands across modules. Sorting by name keeps /thoitiet next to /thoitiethomnay. The weather module also lists /thoitiet first so /help matches.
2026-10-08 17:10:42 +07:00

57 lines
1.5 KiB
Go

package main
import (
"context"
"errors"
"slices"
"strings"
"time"
"github.com/go-telegram/bot"
"github.com/go-telegram/bot/models"
"github.com/tiennm99/tiennm99bot/internal/modules"
)
const commandMenuTimeout = 8 * time.Second
// botCommandMenu builds the Telegram command menu from the loaded public
// commands, sorted by name so related commands such as /thoitiet and
// /thoitiethomnay sit together whatever their module order.
func botCommandMenu(reg *modules.Registry) []models.BotCommand {
if reg == nil {
return nil
}
var out []models.BotCommand
for _, mod := range reg.Modules {
for _, cmd := range mod.Commands {
if cmd.Visibility != modules.VisibilityPublic {
continue
}
out = append(out, models.BotCommand{
Command: cmd.Name,
Description: cmd.TelegramMenuDescription(),
})
}
}
slices.SortFunc(out, func(a, b models.BotCommand) int { return strings.Compare(a.Command, b.Command) })
return out
}
// registerCommandMenu publishes the menu to Telegram. It is best-effort at
// startup: callers should log failures and keep the bot running.
func registerCommandMenu(ctx context.Context, b *bot.Bot, reg *modules.Registry) (int, error) {
cmds := botCommandMenu(reg)
menuCtx, cancel := context.WithTimeout(ctx, commandMenuTimeout)
defer cancel()
ok, err := b.SetMyCommands(menuCtx, &bot.SetMyCommandsParams{Commands: cmds})
if err != nil {
return len(cmds), err
}
if !ok {
return len(cmds), errors.New("telegram setMyCommands returned false")
}
return len(cmds), nil
}