feat(asset): add AssetID to ContentChunk and update image handling in HTML content
This commit is contained in:
@@ -3,13 +3,11 @@ package utils
|
||||
import (
|
||||
"bytes"
|
||||
"cs-agent/internal/models"
|
||||
"cs-agent/internal/pkg/config"
|
||||
"cs-agent/internal/pkg/enums"
|
||||
"cs-agent/internal/repositories"
|
||||
"cs-agent/internal/services/storage"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/microcosm-cc/bluemonday"
|
||||
@@ -335,7 +333,6 @@ func normalizeHTMLImageAsset(node *html.Node) (*models.Asset, error) {
|
||||
assetID := strings.TrimSpace(findHTMLAttr(node, "data-asset-id"))
|
||||
provider := enums.AssetProvider(strings.TrimSpace(findHTMLAttr(node, "data-provider")))
|
||||
storageKey := strings.TrimSpace(findHTMLAttr(node, "data-storage-key"))
|
||||
src := strings.TrimSpace(findHTMLAttr(node, "src"))
|
||||
|
||||
hasAssetID := assetID != ""
|
||||
hasProvider := provider != ""
|
||||
@@ -353,94 +350,5 @@ func normalizeHTMLImageAsset(node *html.Node) (*models.Asset, error) {
|
||||
}
|
||||
return asset, nil
|
||||
}
|
||||
if src == "" {
|
||||
return nil, fmt.Errorf("html message image is missing asset metadata")
|
||||
}
|
||||
asset := findAssetByMessageImageURL(src)
|
||||
if asset == nil {
|
||||
return nil, fmt.Errorf("html message image must reference an uploaded asset")
|
||||
}
|
||||
return asset, nil
|
||||
}
|
||||
|
||||
func findAssetByMessageImageURL(rawURL string) *models.Asset {
|
||||
storageKey, err := resolveStorageKeyFromMessageImageURL(rawURL)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return repositories.AssetRepository.GetByStorageKey(sqls.DB(), storageKey)
|
||||
}
|
||||
|
||||
func FindAssetByMessageImageURL(rawURL string) *models.Asset {
|
||||
return findAssetByMessageImageURL(rawURL)
|
||||
}
|
||||
|
||||
func resolveStorageKeyFromMessageImageURL(rawURL string) (string, error) {
|
||||
cfg := config.Current().Storage
|
||||
candidates := make([]string, 0, 3)
|
||||
if baseURL := strings.TrimSpace(cfg.Local.BaseURL); baseURL != "" {
|
||||
candidates = append(candidates, baseURL)
|
||||
}
|
||||
if baseURL := strings.TrimSpace(cfg.OSS.BaseURL); baseURL != "" {
|
||||
candidates = append(candidates, baseURL)
|
||||
}
|
||||
if ossBucketBaseURL := buildOSSBucketBaseURL(cfg.OSS); ossBucketBaseURL != "" {
|
||||
candidates = append(candidates, ossBucketBaseURL)
|
||||
}
|
||||
for _, baseURL := range candidates {
|
||||
if storageKey, err := resolveStorageKeyFromAssetURL(baseURL, rawURL); err == nil && storageKey != "" {
|
||||
return storageKey, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("image url does not match any storage base url")
|
||||
}
|
||||
|
||||
func buildOSSBucketBaseURL(cfg config.OSSStorageConfig) string {
|
||||
endpoint := strings.TrimSpace(cfg.Endpoint)
|
||||
bucket := strings.TrimSpace(cfg.Bucket)
|
||||
if endpoint == "" || bucket == "" {
|
||||
return ""
|
||||
}
|
||||
if !strings.Contains(endpoint, "://") {
|
||||
endpoint = "https://" + endpoint
|
||||
}
|
||||
u, err := url.Parse(endpoint)
|
||||
if err != nil || strings.TrimSpace(u.Host) == "" {
|
||||
return ""
|
||||
}
|
||||
scheme := strings.TrimSpace(u.Scheme)
|
||||
if scheme == "" {
|
||||
scheme = "https"
|
||||
}
|
||||
return fmt.Sprintf("%s://%s.%s", scheme, bucket, u.Host)
|
||||
}
|
||||
|
||||
func resolveStorageKeyFromAssetURL(baseURL, rawURL string) (string, error) {
|
||||
baseURL = strings.TrimRight(strings.TrimSpace(baseURL), "/")
|
||||
rawURL = strings.TrimSpace(rawURL)
|
||||
if baseURL == "" || rawURL == "" {
|
||||
return "", fmt.Errorf("invalid image url")
|
||||
}
|
||||
if strings.HasPrefix(rawURL, baseURL+"/") {
|
||||
return strings.TrimLeft(strings.TrimPrefix(rawURL, baseURL), "/"), nil
|
||||
}
|
||||
|
||||
baseParsed, baseErr := url.Parse(baseURL)
|
||||
rawParsed, rawErr := url.Parse(rawURL)
|
||||
if baseErr != nil || rawErr != nil {
|
||||
return "", fmt.Errorf("invalid image url")
|
||||
}
|
||||
if !strings.EqualFold(baseParsed.Host, rawParsed.Host) {
|
||||
return "", fmt.Errorf("image url host mismatch")
|
||||
}
|
||||
basePath := strings.TrimRight(baseParsed.Path, "/")
|
||||
rawPath := strings.TrimLeft(rawParsed.Path, "/")
|
||||
if basePath == "" {
|
||||
return rawPath, nil
|
||||
}
|
||||
basePath = strings.TrimLeft(basePath, "/")
|
||||
if !strings.HasPrefix(rawPath, basePath+"/") {
|
||||
return "", fmt.Errorf("image url path mismatch")
|
||||
}
|
||||
return strings.TrimLeft(strings.TrimPrefix(rawPath, basePath), "/"), nil
|
||||
return nil, fmt.Errorf("html message image must include asset metadata")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user