feat(whatsapp): reuse shared dispatcher for text commands
This commit is contained in:
parent
9350e9d4c4
commit
414877da9d
4 changed files with 107 additions and 0 deletions
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/sipeed/picoclaw/pkg/bus"
|
||||
"github.com/sipeed/picoclaw/pkg/channels"
|
||||
"github.com/sipeed/picoclaw/pkg/commands"
|
||||
"github.com/sipeed/picoclaw/pkg/config"
|
||||
"github.com/sipeed/picoclaw/pkg/identity"
|
||||
"github.com/sipeed/picoclaw/pkg/logger"
|
||||
|
|
@ -22,6 +23,7 @@ type WhatsAppChannel struct {
|
|||
conn *websocket.Conn
|
||||
config config.WhatsAppConfig
|
||||
url string
|
||||
dispatcher commands.Dispatching
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
mu sync.Mutex
|
||||
|
|
@ -42,6 +44,7 @@ func NewWhatsAppChannel(cfg config.WhatsAppConfig, bus *bus.MessageBus) (*WhatsA
|
|||
BaseChannel: base,
|
||||
config: cfg,
|
||||
url: cfg.BridgeURL,
|
||||
dispatcher: commands.NewDispatcher(commands.NewRegistry(commands.BuiltinDefinitions(nil))),
|
||||
connected: false,
|
||||
}, nil
|
||||
}
|
||||
|
|
@ -248,5 +251,34 @@ func (c *WhatsAppChannel) handleIncomingMessage(msg map[string]any) {
|
|||
return
|
||||
}
|
||||
|
||||
if c.tryHandleCommand(c.ctx, content, chatID, senderID, messageID) {
|
||||
return
|
||||
}
|
||||
|
||||
c.HandleMessage(c.ctx, peer, messageID, senderID, chatID, content, mediaPaths, metadata, sender)
|
||||
}
|
||||
|
||||
func (c *WhatsAppChannel) tryHandleCommand(
|
||||
ctx context.Context,
|
||||
text, chatID, senderID, messageID string,
|
||||
) bool {
|
||||
if c.dispatcher == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
res := c.dispatcher.Dispatch(ctx, commands.Request{
|
||||
Channel: "whatsapp",
|
||||
ChatID: chatID,
|
||||
SenderID: senderID,
|
||||
Text: text,
|
||||
MessageID: messageID,
|
||||
})
|
||||
if res.Err != nil {
|
||||
logger.WarnCF("whatsapp", "Command execution failed", map[string]any{
|
||||
"command": res.Command,
|
||||
"error": res.Err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return res.Matched
|
||||
}
|
||||
|
|
|
|||
22
pkg/channels/whatsapp/whatsapp_command_test.go
Normal file
22
pkg/channels/whatsapp/whatsapp_command_test.go
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
package whatsapp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/commands"
|
||||
)
|
||||
|
||||
func TestTryHandleCommand_UsesDispatcher(t *testing.T) {
|
||||
ch := &WhatsAppChannel{}
|
||||
called := false
|
||||
ch.dispatcher = commands.DispatchFunc(func(context.Context, commands.Request) commands.Result {
|
||||
called = true
|
||||
return commands.Result{Matched: true}
|
||||
})
|
||||
|
||||
handled := ch.tryHandleCommand(context.Background(), "/help", "chat1", "user1", "mid1")
|
||||
if !handled || !called {
|
||||
t.Fatalf("handled=%v called=%v", handled, called)
|
||||
}
|
||||
}
|
||||
24
pkg/channels/whatsapp_native/whatsapp_command_test.go
Normal file
24
pkg/channels/whatsapp_native/whatsapp_command_test.go
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
//go:build whatsapp_native
|
||||
|
||||
package whatsapp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/sipeed/picoclaw/pkg/commands"
|
||||
)
|
||||
|
||||
func TestTryHandleCommand_UsesDispatcher(t *testing.T) {
|
||||
ch := &WhatsAppNativeChannel{}
|
||||
called := false
|
||||
ch.dispatcher = commands.DispatchFunc(func(context.Context, commands.Request) commands.Result {
|
||||
called = true
|
||||
return commands.Result{Matched: true}
|
||||
})
|
||||
|
||||
handled := ch.tryHandleCommand(context.Background(), "/help", "chat1", "user1", "mid1")
|
||||
if !handled || !called {
|
||||
t.Fatalf("handled=%v called=%v", handled, called)
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ import (
|
|||
|
||||
"github.com/sipeed/picoclaw/pkg/bus"
|
||||
"github.com/sipeed/picoclaw/pkg/channels"
|
||||
"github.com/sipeed/picoclaw/pkg/commands"
|
||||
"github.com/sipeed/picoclaw/pkg/config"
|
||||
"github.com/sipeed/picoclaw/pkg/identity"
|
||||
"github.com/sipeed/picoclaw/pkg/logger"
|
||||
|
|
@ -55,6 +56,7 @@ type WhatsAppNativeChannel struct {
|
|||
mu sync.Mutex
|
||||
runCtx context.Context
|
||||
runCancel context.CancelFunc
|
||||
dispatcher commands.Dispatching
|
||||
reconnectMu sync.Mutex
|
||||
reconnecting bool
|
||||
stopping atomic.Bool // set once Stop begins; prevents new wg.Add calls
|
||||
|
|
@ -76,6 +78,7 @@ func NewWhatsAppNativeChannel(
|
|||
BaseChannel: base,
|
||||
config: cfg,
|
||||
storePath: storePath,
|
||||
dispatcher: commands.NewDispatcher(commands.NewRegistry(commands.BuiltinDefinitions(nil))),
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
|
@ -387,6 +390,9 @@ func (c *WhatsAppNativeChannel) handleIncoming(evt *events.Message) {
|
|||
if !c.IsAllowedSender(sender) {
|
||||
return
|
||||
}
|
||||
if c.tryHandleCommand(c.runCtx, content, chatID, senderID, messageID) {
|
||||
return
|
||||
}
|
||||
|
||||
logger.DebugCF(
|
||||
"whatsapp",
|
||||
|
|
@ -396,6 +402,29 @@ func (c *WhatsAppNativeChannel) handleIncoming(evt *events.Message) {
|
|||
c.HandleMessage(c.runCtx, peer, messageID, senderID, chatID, content, mediaPaths, metadata, sender)
|
||||
}
|
||||
|
||||
func (c *WhatsAppNativeChannel) tryHandleCommand(
|
||||
ctx context.Context,
|
||||
text, chatID, senderID, messageID string,
|
||||
) bool {
|
||||
if c.dispatcher == nil {
|
||||
return false
|
||||
}
|
||||
res := c.dispatcher.Dispatch(ctx, commands.Request{
|
||||
Channel: "whatsapp_native",
|
||||
ChatID: chatID,
|
||||
SenderID: senderID,
|
||||
Text: text,
|
||||
MessageID: messageID,
|
||||
})
|
||||
if res.Err != nil {
|
||||
logger.WarnCF("whatsapp", "Command execution failed", map[string]any{
|
||||
"command": res.Command,
|
||||
"error": res.Err.Error(),
|
||||
})
|
||||
}
|
||||
return res.Matched
|
||||
}
|
||||
|
||||
func (c *WhatsAppNativeChannel) Send(ctx context.Context, msg bus.OutboundMessage) error {
|
||||
if !c.IsRunning() {
|
||||
return channels.ErrNotRunning
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue