mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-13 13:17:28 +08:00
feishu inbound: download image/file media keys to local temp files for service pipeline
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -164,7 +165,7 @@ func (c *FeishuChannel) Send(ctx context.Context, msg bus.OutboundMessage) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *FeishuChannel) handleMessageReceive(_ context.Context, event *larkim.P2MessageReceiveV1) error {
|
||||
func (c *FeishuChannel) handleMessageReceive(ctx context.Context, event *larkim.P2MessageReceiveV1) error {
|
||||
if event == nil || event.Event == nil || event.Event.Message == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -223,10 +224,94 @@ func (c *FeishuChannel) handleMessageReceive(_ context.Context, event *larkim.P2
|
||||
logger.FieldPreview: truncateString(content, 80),
|
||||
})
|
||||
|
||||
c.HandleMessage(senderID, chatID, content, mediaPaths, metadata)
|
||||
resolvedMedia := c.resolveInboundMedia(ctx, mediaPaths)
|
||||
c.HandleMessage(senderID, chatID, content, resolvedMedia, metadata)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *FeishuChannel) resolveInboundMedia(ctx context.Context, mediaRefs []string) []string {
|
||||
if len(mediaRefs) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := make([]string, 0, len(mediaRefs))
|
||||
for _, ref := range mediaRefs {
|
||||
ref = strings.TrimSpace(ref)
|
||||
if strings.HasPrefix(ref, "feishu:image:") {
|
||||
key := strings.TrimPrefix(ref, "feishu:image:")
|
||||
if path, err := c.downloadFeishuMediaByKey(ctx, "image", key); err == nil {
|
||||
out = append(out, path)
|
||||
} else {
|
||||
logger.WarnCF("feishu", "download inbound image failed", map[string]interface{}{logger.FieldError: err.Error(), "image_key": key})
|
||||
out = append(out, ref)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(ref, "feishu:file:") {
|
||||
key := strings.TrimPrefix(ref, "feishu:file:")
|
||||
if path, err := c.downloadFeishuMediaByKey(ctx, "file", key); err == nil {
|
||||
out = append(out, path)
|
||||
} else {
|
||||
logger.WarnCF("feishu", "download inbound file failed", map[string]interface{}{logger.FieldError: err.Error(), "file_key": key})
|
||||
out = append(out, ref)
|
||||
}
|
||||
continue
|
||||
}
|
||||
out = append(out, ref)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (c *FeishuChannel) downloadFeishuMediaByKey(ctx context.Context, kind, key string) (string, error) {
|
||||
tok, err := c.getTenantAccessToken(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var u string
|
||||
switch kind {
|
||||
case "image":
|
||||
u = "https://open.feishu.cn/open-apis/im/v1/images/" + key
|
||||
case "file":
|
||||
u = "https://open.feishu.cn/open-apis/im/v1/files/" + key + "/download"
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported media kind: %s", kind)
|
||||
}
|
||||
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, u, nil)
|
||||
req.Header.Set("Authorization", "Bearer "+tok)
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
b, _ := io.ReadAll(io.LimitReader(resp.Body, 512))
|
||||
return "", fmt.Errorf("download status=%d body=%s", resp.StatusCode, string(b))
|
||||
}
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
ext := ""
|
||||
if ct := strings.TrimSpace(resp.Header.Get("Content-Type")); ct != "" {
|
||||
if exts, _ := mime.ExtensionsByType(ct); len(exts) > 0 {
|
||||
ext = exts[0]
|
||||
}
|
||||
}
|
||||
if ext == "" {
|
||||
if kind == "image" {
|
||||
ext = ".jpg"
|
||||
} else {
|
||||
ext = ".bin"
|
||||
}
|
||||
}
|
||||
dir := filepath.Join(os.TempDir(), "clawgo_feishu_media")
|
||||
_ = os.MkdirAll(dir, 0755)
|
||||
path := filepath.Join(dir, fmt.Sprintf("%s_%d%s", kind, time.Now().UnixNano(), ext))
|
||||
if err := os.WriteFile(path, b, 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
|
||||
func (c *FeishuChannel) isAllowedChat(chatID, chatType string) bool {
|
||||
chatID = strings.TrimSpace(chatID)
|
||||
chatType = strings.ToLower(strings.TrimSpace(chatType))
|
||||
|
||||
Reference in New Issue
Block a user