feat(telegram): Init bot commands on start

This commit is contained in:
Artem Yadelskyi
2026-02-16 13:20:36 +02:00
parent 8d757fbb6f
commit bfb9d8f644
+65 -12
View File
@@ -7,14 +7,13 @@ import (
"net/url"
"os"
"regexp"
"slices"
"strings"
"sync"
"time"
th "github.com/mymmrac/telego/telegohandler"
"github.com/mymmrac/telego"
"github.com/mymmrac/telego/telegohandler"
th "github.com/mymmrac/telego/telegohandler"
tu "github.com/mymmrac/telego/telegoutil"
"github.com/sipeed/picoclaw/pkg/bus"
@@ -27,6 +26,7 @@ import (
type TelegramChannel struct {
*BaseChannel
bot *telego.Bot
botHandler *th.BotHandler
commands TelegramCommander
config *config.Config
chatIDs map[string]int64
@@ -87,6 +87,10 @@ func (c *TelegramChannel) SetTranscriber(transcriber *voice.GroqTranscriber) {
func (c *TelegramChannel) Start(ctx context.Context) error {
logger.InfoC("telegram", "Starting Telegram bot (polling mode)...")
if err := c.initBotCommands(ctx); err != nil {
return fmt.Errorf("failed to initialize bot commands: %w", err)
}
updates, err := c.bot.UpdatesViaLongPolling(ctx, &telego.GetUpdatesParams{
Timeout: 30,
})
@@ -94,18 +98,18 @@ func (c *TelegramChannel) Start(ctx context.Context) error {
return fmt.Errorf("failed to start long polling: %w", err)
}
bh, err := telegohandler.NewBotHandler(c.bot, updates)
bh, err := th.NewBotHandler(c.bot, updates)
if err != nil {
return fmt.Errorf("failed to create bot handler: %w", err)
}
c.botHandler = bh
bh.HandleMessage(func(ctx *th.Context, message telego.Message) error {
c.commands.Help(ctx, message)
return nil
}, th.CommandEqual("help"))
bh.HandleMessage(func(ctx *th.Context, message telego.Message) error {
return c.commands.Start(ctx, message)
}, th.CommandEqual("start"))
bh.HandleMessage(func(ctx *th.Context, message telego.Message) error {
return c.commands.Help(ctx, message)
}, th.CommandEqual("help"))
bh.HandleMessage(func(ctx *th.Context, message telego.Message) error {
return c.commands.Show(ctx, message)
@@ -124,11 +128,12 @@ func (c *TelegramChannel) Start(ctx context.Context) error {
"username": c.bot.Username(),
})
go bh.Start()
go func() {
<-ctx.Done()
bh.Stop()
if err = bh.Start(); err != nil {
logger.ErrorCF("telegram", "Bot handler failed", map[string]interface{}{
"error": err.Error(),
})
}
}()
return nil
@@ -136,6 +141,54 @@ func (c *TelegramChannel) Start(ctx context.Context) error {
func (c *TelegramChannel) Stop(ctx context.Context) error {
logger.InfoC("telegram", "Stopping Telegram bot...")
c.setRunning(false)
if c.botHandler != nil {
_ = c.botHandler.StopWithContext(ctx)
}
return nil
}
func (c *TelegramChannel) initBotCommands(ctx context.Context) error {
currentCommands, err := c.bot.GetMyCommands(ctx, &telego.GetMyCommandsParams{
Scope: tu.ScopeAllPrivateChats(),
})
if err != nil {
return fmt.Errorf("get commands: %w", err)
}
commands := []telego.BotCommand{
{
Command: "start",
Description: "Start the bot",
},
{
Command: "help",
Description: "Show a help message",
},
{
Command: "show",
Description: "Show the current configuration",
},
{
Command: "list",
Description: "List available options",
},
}
// Setting commands on each start will hit the rate limit very quickly, that's why we check if an update is needed
if !slices.Equal(currentCommands, commands) {
logger.InfoC("telegram", "Updating bot commands")
err = c.bot.SetMyCommands(ctx, &telego.SetMyCommandsParams{
Commands: commands,
Scope: tu.ScopeAllPrivateChats(),
})
if err != nil {
return fmt.Errorf("set commands: %w", err)
}
} else {
logger.InfoC("telegram", "Bot commands up to date")
}
return nil
}