diff --git a/pkg/channels/telegram/telegram.go b/pkg/channels/telegram/telegram.go index 0e1949ab6..7d19e0e7c 100644 --- a/pkg/channels/telegram/telegram.go +++ b/pkg/channels/telegram/telegram.go @@ -44,6 +44,7 @@ type TelegramChannel struct { bot *telego.Bot bh *telegohandler.BotHandler commands TelegramCommander + dispatcher commands.Dispatching config *config.Config chatIDs map[string]int64 ctx context.Context @@ -94,6 +95,7 @@ func NewTelegramChannel(cfg *config.Config, bus *bus.MessageBus) (*TelegramChann return &TelegramChannel{ BaseChannel: base, commands: NewTelegramCommands(bot, cfg), + dispatcher: commands.NewDispatcher(commands.NewRegistry(commands.BuiltinDefinitions(cfg))), bot: bot, config: cfg, chatIDs: make(map[string]int64), @@ -121,22 +123,9 @@ func (c *TelegramChannel) Start(ctx context.Context) error { c.bh = 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.Show(ctx, message) - }, th.CommandEqual("show")) - - bh.HandleMessage(func(ctx *th.Context, message telego.Message) error { - return c.commands.List(ctx, message) - }, th.CommandEqual("list")) - - bh.HandleMessage(func(ctx *th.Context, message telego.Message) error { + if c.dispatchCommand(ctx, message) { + return nil + } return c.handleMessage(ctx, &message) }, th.AnyMessage()) diff --git a/pkg/channels/telegram/telegram_dispatch.go b/pkg/channels/telegram/telegram_dispatch.go new file mode 100644 index 000000000..5c6014bd8 --- /dev/null +++ b/pkg/channels/telegram/telegram_dispatch.go @@ -0,0 +1,66 @@ +package telegram + +import ( + "context" + "strconv" + + "github.com/mymmrac/telego" + + "github.com/sipeed/picoclaw/pkg/commands" + "github.com/sipeed/picoclaw/pkg/logger" +) + +func (c *TelegramChannel) dispatchCommand(ctx context.Context, message telego.Message) bool { + if c.dispatcher == nil { + return false + } + + senderID := "" + if message.From != nil { + senderID = strconv.FormatInt(message.From.ID, 10) + } + + res := c.dispatcher.Dispatch(ctx, commands.Request{ + Channel: "telegram", + ChatID: strconv.FormatInt(message.Chat.ID, 10), + SenderID: senderID, + Text: message.Text, + MessageID: strconv.Itoa(message.MessageID), + }) + if !res.Matched { + return false + } + + switch res.Command { + case "help": + if err := c.commands.Help(ctx, message); err != nil { + logger.ErrorCF("telegram", "Command execution failed", map[string]any{ + "command": "help", + "error": err.Error(), + }) + } + case "start": + if err := c.commands.Start(ctx, message); err != nil { + logger.ErrorCF("telegram", "Command execution failed", map[string]any{ + "command": "start", + "error": err.Error(), + }) + } + case "show": + if err := c.commands.Show(ctx, message); err != nil { + logger.ErrorCF("telegram", "Command execution failed", map[string]any{ + "command": "show", + "error": err.Error(), + }) + } + case "list": + if err := c.commands.List(ctx, message); err != nil { + logger.ErrorCF("telegram", "Command execution failed", map[string]any{ + "command": "list", + "error": err.Error(), + }) + } + } + + return true +} diff --git a/pkg/channels/telegram/telegram_dispatch_test.go b/pkg/channels/telegram/telegram_dispatch_test.go new file mode 100644 index 000000000..1e187f5ac --- /dev/null +++ b/pkg/channels/telegram/telegram_dispatch_test.go @@ -0,0 +1,32 @@ +package telegram + +import ( + "context" + "testing" + + "github.com/mymmrac/telego" + + "github.com/sipeed/picoclaw/pkg/commands" +) + +func TestDispatchCommand_UsesDispatcher(t *testing.T) { + ch := &TelegramChannel{} + called := false + ch.dispatcher = commands.DispatchFunc(func(context.Context, commands.Request) commands.Result { + called = true + return commands.Result{Matched: true, Command: "noop"} + }) + + msg := telego.Message{ + Text: "/help", + MessageID: 7, + Chat: telego.Chat{ + ID: 123, + }, + } + + handled := ch.dispatchCommand(context.Background(), msg) + if !handled || !called { + t.Fatalf("handled=%v called=%v", handled, called) + } +} diff --git a/pkg/commands/dispatcher.go b/pkg/commands/dispatcher.go index 21a5a587f..4c419bb3b 100644 --- a/pkg/commands/dispatcher.go +++ b/pkg/commands/dispatcher.go @@ -25,6 +25,16 @@ type Dispatcher struct { reg *Registry } +type Dispatching interface { + Dispatch(ctx context.Context, req Request) Result +} + +type DispatchFunc func(ctx context.Context, req Request) Result + +func (f DispatchFunc) Dispatch(ctx context.Context, req Request) Result { + return f(ctx, req) +} + func NewDispatcher(reg *Registry) *Dispatcher { return &Dispatcher{reg: reg} }