HH-502: cover non-widget message sender events (#113)

Co-authored-by: Rogee <rogee@ipao.vip>
This commit is contained in:
Rogee
2026-08-23 07:40:38 +08:00
committed by GitHub
co-authored by rogee
parent eaf6edef66
commit dac8c5e068
3 changed files with 113 additions and 21 deletions
+9 -5
View File
@@ -77,7 +77,7 @@ func (s *MessageService) dispatchMessageEvent(ctx context.Context, eventType cha
}
event.Data["message"] = message
if eventType == channel.EventMessageCreated || eventType == channel.EventMessageUpdated || eventType == channel.EventMessageDeleted {
s.addWebWidgetEventContext(ctx, event, message)
s.addMessageEventContext(ctx, event, message)
}
applogger.L().Infof("dispatching event %s for message %d", eventType, message.ID)
if err := s.dispatcher.Dispatch(ctx, event); err != nil {
@@ -85,13 +85,17 @@ func (s *MessageService) dispatchMessageEvent(ctx context.Context, eventType cha
}
}
func (s *MessageService) addWebWidgetEventContext(ctx context.Context, event *channel.ChannelEvent, message *model.Message) {
func (s *MessageService) addMessageEventContext(ctx context.Context, event *channel.ChannelEvent, message *model.Message) {
var inbox model.Inbox
if err := s.repo.DB().WithContext(ctx).First(&inbox, message.InboxID).Error; err != nil || inbox.ChannelType != string(channel.ChannelWebWidget) {
if err := s.repo.DB().WithContext(ctx).First(&inbox, message.InboxID).Error; err != nil {
return
}
event.Channel = channel.ChannelWebWidget
event.Data["inbox"] = &inbox
isWebWidget := strings.EqualFold(strings.TrimSpace(inbox.ChannelType), string(channel.ChannelWebWidget)) ||
strings.EqualFold(strings.TrimSpace(inbox.ChannelType), string(model.InboxChannelTypeWebWidget))
if isWebWidget {
event.Channel = channel.ChannelWebWidget
}
var conversation model.Conversation
if err := s.repo.DB().WithContext(ctx).First(&conversation, message.ConversationID).Error; err != nil {
@@ -123,7 +127,7 @@ func (s *MessageService) addWebWidgetEventContext(ctx context.Context, event *ch
}
}
}
if message.Private || message.MessageType == string(model.MessageTypeActivity) || conversation.ContactInboxID == nil {
if !isWebWidget || message.Private || message.MessageType == string(model.MessageTypeActivity) || conversation.ContactInboxID == nil {
return
}
var contactInbox model.ContactInbox
@@ -140,7 +140,41 @@ func TestMessageService_WebWidgetReplyCarriesRealtimeContext(t *testing.T) {
assert.IsType(t, &model.User{}, created.Data["sender"])
}
func TestMessageService_WebWidgetReplyResolvesAutomatedSenders(t *testing.T) {
func TestMessageService_APIReplyCarriesRealtimeContext(t *testing.T) {
db, _, dispatcher, svc := setupMessageServiceWithDefaultLLM(t)
account := createTestAccount(t, db)
agent := createTestUser(t, db, account.ID)
inbox := createTestInbox(t, db, account.ID, string(channel.ChannelAPI))
contact := createTestContact(t, db, account.ID)
conversation := createTestConversation(t, db, account.ID, inbox.ID, contact.ID)
listener := &messageEventListener{}
dispatcher.Register(listener)
_, err := svc.Create(context.Background(), account.ID, agent.ID, CreateMessageRequest{
ConversationID: conversation.ID,
Content: "agent reply",
ContentType: "text",
MessageType: "outgoing",
})
require.NoError(t, err)
var created *channel.ChannelEvent
for _, event := range listener.events {
if event.Type == channel.EventMessageCreated {
created = event
break
}
}
require.NotNil(t, created)
assert.Equal(t, channel.ChannelAPI, created.Channel)
assert.NotContains(t, created.Data, "widget_token")
assert.IsType(t, &model.Inbox{}, created.Data["inbox"])
assert.IsType(t, &model.Conversation{}, created.Data["conversation"])
assert.IsType(t, &model.Contact{}, created.Data["contact"])
assert.IsType(t, &model.User{}, created.Data["sender"])
}
func TestMessageService_MessageEventContextResolvesAutomatedSenders(t *testing.T) {
db, _, _, svc := setupMessageServiceWithDefaultLLM(t)
require.NoError(t, db.AutoMigrate(&model.AgentBot{}, &model.CaptainAssistant{}))
account := createTestAccount(t, db)
@@ -169,16 +203,25 @@ func TestMessageService_WebWidgetReplyResolvesAutomatedSenders(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
event := channel.NewChannelEvent(channel.EventMessageCreated, channel.ChannelWebWidget, account.ID, inbox.ID)
message := &model.Message{ConversationID: conversation.ID, InboxID: inbox.ID, SenderID: &tt.senderID, SenderType: tt.senderType}
svc.addWebWidgetEventContext(context.Background(), event, message)
for _, channelType := range []channel.ChannelType{channel.ChannelWebWidget, channel.ChannelAPI} {
t.Run(string(channelType), func(t *testing.T) {
require.NoError(t, db.Model(inbox).Update("channel_type", string(channelType)).Error)
event := channel.NewChannelEvent(channel.EventMessageCreated, channelType, account.ID, inbox.ID)
message := &model.Message{ConversationID: conversation.ID, InboxID: inbox.ID, SenderID: &tt.senderID, SenderType: tt.senderType}
svc.addMessageEventContext(context.Background(), event, message)
assert.Equal(t, "visitor-token", event.Data["widget_token"])
assert.IsType(t, &model.Contact{}, event.Data["contact"])
if tt.expected == nil {
assert.NotContains(t, event.Data, "sender")
} else {
assert.IsType(t, tt.expected, event.Data["sender"])
assert.IsType(t, &model.Contact{}, event.Data["contact"])
if channelType == channel.ChannelWebWidget {
assert.Equal(t, "visitor-token", event.Data["widget_token"])
} else {
assert.NotContains(t, event.Data, "widget_token")
}
if tt.expected == nil {
assert.NotContains(t, event.Data, "sender")
} else {
assert.IsType(t, tt.expected, event.Data["sender"])
}
})
}
})
}