feat(weixin): add workspace file handling and MIME type detection
- Implemented support for reading files from workspace URIs in the Weixin reply process, enhancing attachment management. - Introduced a new `mimeFromExt` function to determine content types based on file extensions, improving file handling capabilities. - Updated the `sendMediaFromURL` method to accommodate workspace file retrieval, ensuring robust error handling and logging for file operations.
This commit is contained in:
parent
f230f1e90c
commit
4376ac9dad
1 changed files with 64 additions and 1 deletions
|
|
@ -5,12 +5,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
agentcontext "github.com/yaoapp/yao/agent/context"
|
agentcontext "github.com/yaoapp/yao/agent/context"
|
||||||
events "github.com/yaoapp/yao/agent/robot/events"
|
events "github.com/yaoapp/yao/agent/robot/events"
|
||||||
"github.com/yaoapp/yao/attachment"
|
"github.com/yaoapp/yao/attachment"
|
||||||
weixinapi "github.com/yaoapp/yao/integrations/weixin"
|
weixinapi "github.com/yaoapp/yao/integrations/weixin"
|
||||||
|
"github.com/yaoapp/yao/workspace"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *Adapter) Reply(ctx context.Context, msg *agentcontext.Message, metadata *events.MessageMetadata) error {
|
func (a *Adapter) Reply(ctx context.Context, msg *agentcontext.Message, metadata *events.MessageMetadata) error {
|
||||||
|
|
@ -168,7 +170,37 @@ func (a *Adapter) sendMediaFromURL(ctx context.Context, entry *botEntry, toUserI
|
||||||
var plaintext []byte
|
var plaintext []byte
|
||||||
var contentType string
|
var contentType string
|
||||||
|
|
||||||
if isWrapper(fileURL) {
|
if strings.HasPrefix(fileURL, "workspace://") {
|
||||||
|
rest := strings.TrimPrefix(fileURL, "workspace://")
|
||||||
|
slashIdx := strings.Index(rest, "/")
|
||||||
|
if slashIdx < 0 {
|
||||||
|
return fmt.Errorf("invalid workspace URL: %s", fileURL)
|
||||||
|
}
|
||||||
|
wsID := rest[:slashIdx]
|
||||||
|
filePath := rest[slashIdx+1:]
|
||||||
|
|
||||||
|
wsm := workspace.M()
|
||||||
|
if wsm == nil {
|
||||||
|
return fmt.Errorf("workspace manager not initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
wsFS, err := wsm.FS(ctx, wsID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("open workspace %s: %w", wsID, err)
|
||||||
|
}
|
||||||
|
defer wsFS.Close()
|
||||||
|
|
||||||
|
plaintext, err = wsFS.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("read workspace file %s/%s: %w", wsID, filePath, err)
|
||||||
|
}
|
||||||
|
contentType = mimeFromExt(filepath.Ext(filePath))
|
||||||
|
if fileName == "" {
|
||||||
|
fileName = filepath.Base(filePath)
|
||||||
|
}
|
||||||
|
log.Info("weixin sendMedia: workspace read bytes=%d contentType=%q fileName=%q", len(plaintext), contentType, fileName)
|
||||||
|
|
||||||
|
} else if isWrapper(fileURL) {
|
||||||
managerName, fileID, err := parseWrapper(fileURL)
|
managerName, fileID, err := parseWrapper(fileURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -291,6 +323,37 @@ func toContentParts(content interface{}) ([]agentcontext.ContentPart, bool) {
|
||||||
return parts, ok
|
return parts, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mimeFromExt(ext string) string {
|
||||||
|
switch strings.ToLower(ext) {
|
||||||
|
case ".pdf":
|
||||||
|
return "application/pdf"
|
||||||
|
case ".html", ".htm":
|
||||||
|
return "text/html"
|
||||||
|
case ".png":
|
||||||
|
return "image/png"
|
||||||
|
case ".jpg", ".jpeg":
|
||||||
|
return "image/jpeg"
|
||||||
|
case ".gif":
|
||||||
|
return "image/gif"
|
||||||
|
case ".webp":
|
||||||
|
return "image/webp"
|
||||||
|
case ".md":
|
||||||
|
return "text/markdown"
|
||||||
|
case ".txt":
|
||||||
|
return "text/plain"
|
||||||
|
case ".csv":
|
||||||
|
return "text/csv"
|
||||||
|
case ".json":
|
||||||
|
return "application/json"
|
||||||
|
case ".xlsx":
|
||||||
|
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||||
|
case ".pptx":
|
||||||
|
return "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
||||||
|
default:
|
||||||
|
return "application/octet-stream"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Adapter) resolveByAccountID(accountID string) *botEntry {
|
func (a *Adapter) resolveByAccountID(accountID string) *botEntry {
|
||||||
if accountID == "" {
|
if accountID == "" {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue