mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
Fix the limitation on the number of tables in cards caused by Feishu (#1736)
* Fix the limitation on the number of tables in cards caused by Feishu * Only match the error code 11310
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
@@ -129,6 +130,7 @@ func (c *FeishuChannel) Stop(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// Send sends a message using Interactive Card format for markdown rendering.
|
||||
// Falls back to plain text message if card sending fails (e.g., table limit exceeded).
|
||||
func (c *FeishuChannel) Send(ctx context.Context, msg bus.OutboundMessage) error {
|
||||
if !c.IsRunning() {
|
||||
return channels.ErrNotRunning
|
||||
@@ -141,9 +143,38 @@ func (c *FeishuChannel) Send(ctx context.Context, msg bus.OutboundMessage) error
|
||||
// Build interactive card with markdown content
|
||||
cardContent, err := buildMarkdownCard(msg.Content)
|
||||
if err != nil {
|
||||
return fmt.Errorf("feishu send: card build failed: %w", err)
|
||||
// If card build fails, fall back to plain text
|
||||
return c.sendText(ctx, msg.ChatID, msg.Content)
|
||||
}
|
||||
return c.sendCard(ctx, msg.ChatID, cardContent)
|
||||
|
||||
// First attempt: try sending as interactive card
|
||||
err = c.sendCard(ctx, msg.ChatID, cardContent)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if error is due to card table limit (error code 11310)
|
||||
// See: https://open.feishu.cn/document/server-docs/im-api/message-content-description/create_json
|
||||
errMsg := err.Error()
|
||||
isCardLimitError := strings.Contains(errMsg, "11310")
|
||||
|
||||
if isCardLimitError {
|
||||
logger.WarnCF("feishu", "Card send failed (table limit), falling back to text message", map[string]any{
|
||||
"chat_id": msg.ChatID,
|
||||
"error": errMsg,
|
||||
})
|
||||
|
||||
// Second attempt: fall back to plain text message
|
||||
textErr := c.sendText(ctx, msg.ChatID, msg.Content)
|
||||
if textErr == nil {
|
||||
return nil
|
||||
}
|
||||
// If text also fails, return the text error
|
||||
return textErr
|
||||
}
|
||||
|
||||
// For other errors, return the original card error
|
||||
return err
|
||||
}
|
||||
|
||||
// EditMessage implements channels.MessageEditor.
|
||||
@@ -738,6 +769,35 @@ func (c *FeishuChannel) sendCard(ctx context.Context, chatID, cardContent string
|
||||
return nil
|
||||
}
|
||||
|
||||
// sendText sends a plain text message to a chat (fallback when card fails).
|
||||
func (c *FeishuChannel) sendText(ctx context.Context, chatID, text string) error {
|
||||
content, _ := json.Marshal(map[string]string{"text": text})
|
||||
|
||||
req := larkim.NewCreateMessageReqBuilder().
|
||||
ReceiveIdType(larkim.ReceiveIdTypeChatId).
|
||||
Body(larkim.NewCreateMessageReqBodyBuilder().
|
||||
ReceiveId(chatID).
|
||||
MsgType(larkim.MsgTypeText).
|
||||
Content(string(content)).
|
||||
Build()).
|
||||
Build()
|
||||
|
||||
resp, err := c.client.Im.V1.Message.Create(ctx, req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("feishu send text: %w", channels.ErrTemporary)
|
||||
}
|
||||
|
||||
if !resp.Success() {
|
||||
return fmt.Errorf("feishu text api error (code=%d msg=%s): %w", resp.Code, resp.Msg, channels.ErrTemporary)
|
||||
}
|
||||
|
||||
logger.DebugCF("feishu", "Feishu text message sent (fallback)", map[string]any{
|
||||
"chat_id": chatID,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// sendImage uploads an image and sends it as a message.
|
||||
func (c *FeishuChannel) sendImage(ctx context.Context, chatID string, file *os.File) error {
|
||||
// Upload image to get image_key
|
||||
|
||||
Reference in New Issue
Block a user