mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-11 03:13:24 +00:00
* fix: resolve Zalo group name to real chat ID, notify origin on failed forward Two related root causes behind "forward message to group by name" silently failing while the agent reports success: 1. No tool let the agent resolve a group's display name (e.g. "Ban Dieu Hanh") to the chat ID the message tool actually requires. sessions_list only exposes session keys (numeric group IDs), never human-readable names, so the agent had no reliable way to turn a name into a real target and ended up passing the display name itself as `target`. Adds zalo_list_groups, wrapping the already-used (dashboard picker) protocol.FetchGroups behind the same optional-interface pattern as list_group_members/GroupMemberProvider (GroupListProvider on channels.Manager, gated to zalo_personal via RequiredChannelTypes). 2. When the resulting send fails downstream (e.g. Zalo rejects a bad chat_id), dispatchOutbound only ever retried/notified media failures on the same (already-broken) destination, and dropped text-only failures entirely — even though message.go's own postCrossTargetNotice comment states forwards must never announce a fake delivery. Because the bus publish is fire-and-forget, the tool had already returned "sent" and announced success to the origin chat before the real send was even attempted. message.go now tags cross-target forwards with origin channel/chat in OutboundMessage.Metadata; dispatchOutbound uses it to notify the ORIGIN chat with the real failure instead of silently dropping it or retrying against the same invalid target. * test: cover forward-origin metadata tagging and dispatch failure notice Extracts dispatchOutbound's error branch into handleSendFailure so it can be unit tested without driving the consumer loop/goroutine, and adds coverage for: forward failures notifying the origin chat (not the broken destination), pre-existing non-forward media/text-only behavior staying unchanged, message.go tagging cross-target group forwards with origin metadata alongside group_id, and the new zalo_list_groups tool/Manager delegator.
60 lines
1.6 KiB
Go
60 lines
1.6 KiB
Go
package channels
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/nextlevelbuilder/goclaw/internal/bus"
|
|
)
|
|
|
|
type groupListTestChannel struct {
|
|
*mockChannel
|
|
groups []GroupInfo
|
|
}
|
|
|
|
func (c *groupListTestChannel) ListGroups(_ context.Context) ([]GroupInfo, error) {
|
|
return c.groups, nil
|
|
}
|
|
|
|
func TestManagerListGroupsDelegatesToProvider(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
mgr := NewManager(bus.New())
|
|
ch := &groupListTestChannel{
|
|
mockChannel: newMockChannel("bunny-zalo-personal", TypeZaloPersonal),
|
|
groups: []GroupInfo{
|
|
{GroupID: "747300108647389888", Name: "Ban Điều Hành", TotalMember: 8},
|
|
},
|
|
}
|
|
mgr.RegisterChannel("bunny-zalo-personal", ch)
|
|
|
|
groups, err := mgr.ListGroups(context.Background(), "bunny-zalo-personal")
|
|
if err != nil {
|
|
t.Fatalf("ListGroups returned error: %v", err)
|
|
}
|
|
if len(groups) != 1 || groups[0].Name != "Ban Điều Hành" || groups[0].GroupID != "747300108647389888" {
|
|
t.Fatalf("unexpected groups: %#v", groups)
|
|
}
|
|
}
|
|
|
|
func TestManagerListGroupsUnsupportedChannel(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
mgr := NewManager(bus.New())
|
|
ch := newMockChannel("telegram-main", TypeTelegram) // does not implement GroupListProvider
|
|
mgr.RegisterChannel("telegram-main", ch)
|
|
|
|
if _, err := mgr.ListGroups(context.Background(), "telegram-main"); err == nil {
|
|
t.Fatal("expected error for channel without GroupListProvider support")
|
|
}
|
|
}
|
|
|
|
func TestManagerListGroupsUnknownChannel(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
mgr := NewManager(bus.New())
|
|
if _, err := mgr.ListGroups(context.Background(), "does-not-exist"); err == nil {
|
|
t.Fatal("expected error for unknown channel")
|
|
}
|
|
}
|