yao/agent/robot/events/integrations/dingtalk/stream.go
Max 33efd3e890 Add Feishu and DingTalk integration support in robot lifecycle</message>
<message>
- Introduce Feishu and DingTalk adapters in the robot lifecycle for enhanced integration capabilities.
- Update the integration dispatcher to include new adapters for handling events from Feishu and DingTalk.
- Modify the configuration structure to support settings for both Feishu and DingTalk integrations.
- Enhance the integration parsing logic to recognize and process configurations for Feishu and DingTalk.
2026-03-02 07:36:34 +08:00

98 lines
2.4 KiB
Go

package dingtalk
import (
"context"
"strings"
"time"
dingstream "github.com/open-dingtalk/dingtalk-stream-sdk-go/chatbot"
dingclient "github.com/open-dingtalk/dingtalk-stream-sdk-go/client"
dtapi "github.com/yaoapp/yao/integrations/dingtalk"
)
const reconnectDelay = 5 * time.Second
// streamLoop starts the DingTalk Stream client for a single bot.
// It automatically reconnects on failure.
func (a *Adapter) streamLoop(ctx context.Context, entry *botEntry) {
log.Info("dingtalk streamLoop started robot=%s client=%s", entry.robotID, entry.clientID)
for {
select {
case <-ctx.Done():
log.Info("dingtalk streamLoop stopped robot=%s", entry.robotID)
return
case <-a.stopCh:
return
default:
}
err := a.runStreamClient(ctx, entry)
if err != nil {
log.Error("dingtalk stream disconnected robot=%s: %v, reconnecting in %s", entry.robotID, err, reconnectDelay)
}
select {
case <-ctx.Done():
return
case <-a.stopCh:
return
case <-time.After(reconnectDelay):
}
}
}
func (a *Adapter) runStreamClient(ctx context.Context, entry *botEntry) error {
cli := dingclient.NewStreamClient(
dingclient.WithAppCredential(dingclient.NewAppCredentialConfig(entry.clientID, entry.bot.ClientSecret())),
)
cli.RegisterChatBotCallbackRouter(func(c context.Context, data *dingstream.BotCallbackDataModel) ([]byte, error) {
return a.onBotCallback(c, entry, data)
})
errCh := make(chan error, 1)
go func() {
errCh <- cli.Start(ctx)
}()
select {
case <-ctx.Done():
return ctx.Err()
case <-a.stopCh:
return nil
case err := <-errCh:
return err
}
}
func (a *Adapter) onBotCallback(ctx context.Context, entry *botEntry, data *dingstream.BotCallbackDataModel) ([]byte, error) {
if data == nil {
return nil, nil
}
cm := &dtapi.ConvertedMessage{
MessageID: data.MsgId,
ConversationID: data.ConversationId,
ConversationType: data.ConversationType,
SenderID: data.SenderId,
SenderNick: data.SenderNick,
SenderStaffID: data.SenderStaffId,
ChatbotUserID: data.ChatbotUserId,
IsInAtList: data.IsInAtList,
SessionWebhook: data.SessionWebhook,
}
switch data.Msgtype {
case "text":
cm.Text = strings.TrimSpace(data.Text.Content)
}
if cm.HasMedia() {
groups := []string{"dingtalk", entry.robotID}
dtapi.ResolveMedia(ctx, cm, groups)
}
a.handleMessages(ctx, entry, []*dtapi.ConvertedMessage{cm})
return nil, nil
}