Files
qiweimanager-master/helper/after_sales_image.go

237 lines
5.7 KiB
Go

package main
import (
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
)
var afterSalesImageKeys = map[string]struct{}{
"file_path": {},
"filepath": {},
"file_name": {},
"filename": {},
"path": {},
"local_path": {},
"localpath": {},
"image_path": {},
"imagepath": {},
"thumb_path": {},
"thumbnail": {},
"url": {},
"image_url": {},
"file_id": {},
"fileid": {},
"aes_key": {},
"md5": {},
"content": {},
"message": {},
"text": {},
}
func extractAfterSalesImage(raw map[string]interface{}) (string, string) {
values := collectImageLikeStrings(raw)
for _, value := range values {
if isLocalImagePath(value) {
return value, ""
}
}
for _, value := range values {
if looksLikeImageRef(value) {
return "", value
}
}
return "", ""
}
func extractAfterSalesImageFromMessage(msg autoReplyMessage, raw map[string]interface{}) (string, string) {
for _, value := range []string{msg.MediaLocalPath, msg.MediaFileName} {
if isLocalImagePath(value) {
return normalizedLocalImagePath(value), ""
}
}
if path, _ := extractAfterSalesImage(raw); path != "" {
return normalizedLocalImagePath(path), ""
}
if shouldDownloadAfterSalesImage(msg, raw) {
if path, err := ensureAutoReplyMediaLocalPath(msg); err == nil && isLocalImagePath(path) {
return normalizedLocalImagePath(path), ""
}
}
if _, ref := extractAfterSalesImage(raw); ref != "" {
return "", ref
}
for _, value := range []string{msg.MediaURL, msg.MediaFileID} {
if looksLikeImageRef(value) {
return "", value
}
}
return "", ""
}
func shouldDownloadAfterSalesImage(msg autoReplyMessage, raw map[string]interface{}) bool {
switch strings.TrimSpace(msg.MediaKind) {
case "image", "emoji":
return true
}
if msg.RawType == 11042 {
return true
}
if strings.TrimSpace(msg.MediaURL) != "" || strings.TrimSpace(msg.MediaFileID) != "" {
return looksLikeImageMessage(raw)
}
return false
}
func normalizedLocalImagePath(value string) string {
value = strings.Trim(strings.TrimSpace(value), "\"'")
if value == "" {
return ""
}
if filepath.IsAbs(value) {
return value
}
candidate := resolveAutoReplyPath(value)
if _, err := os.Stat(candidate); err == nil {
return candidate
}
return value
}
func resolveAfterSalesImageRef(value string) string {
value = strings.TrimSpace(value)
if value == "" {
return ""
}
if isLocalImagePath(value) {
return normalizedLocalImagePath(value)
}
lower := strings.ToLower(value)
if !strings.HasPrefix(lower, "http://") && !strings.HasPrefix(lower, "https://") {
return ""
}
parsed, err := url.Parse(value)
if err != nil {
return ""
}
ext := strings.ToLower(filepath.Ext(parsed.Path))
switch ext {
case ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp":
default:
ext = ".jpg"
}
base := filepath.Base(parsed.Path)
if base == "." || base == string(filepath.Separator) || strings.TrimSpace(base) == "" {
base = "after_sales_image"
}
savePath := generateSavePath("after_sales_images", base, ext)
if savePath == "" {
return ""
}
if err := downloadPlainMedia(value, savePath); err != nil {
return ""
}
if isLocalImagePath(savePath) {
return savePath
}
return ""
}
func looksLikeImageMessage(raw map[string]interface{}) bool {
if raw == nil {
return false
}
if typeVal, ok := raw["type"]; ok {
switch intFromAny(typeVal) {
case 11042, 11044, 11045, 11046:
return true
}
}
values := collectImageLikeStrings(raw)
for _, value := range values {
if isLocalImagePath(value) || looksLikeImageRef(value) {
return true
}
}
return false
}
func collectImageLikeStrings(value interface{}) []string {
var result []string
var walk func(interface{}, string)
walk = func(item interface{}, key string) {
switch v := item.(type) {
case map[string]interface{}:
for k, child := range v {
walk(child, strings.ToLower(strings.TrimSpace(k)))
}
case []interface{}:
for _, child := range v {
walk(child, key)
}
case string:
text := strings.TrimSpace(v)
if text == "" {
return
}
if _, ok := afterSalesImageKeys[key]; ok || isLocalImagePath(text) || looksLikeImageRef(text) {
result = append(result, text)
}
case fmt.Stringer:
text := strings.TrimSpace(v.String())
if text != "" {
result = append(result, text)
}
}
}
walk(value, "")
return uniqueNonEmptyStrings(result)
}
func isLocalImagePath(value string) bool {
value = strings.Trim(strings.TrimSpace(value), "\"'")
if value == "" {
return false
}
if strings.HasPrefix(strings.ToLower(value), "http://") || strings.HasPrefix(strings.ToLower(value), "https://") {
return false
}
ext := strings.ToLower(filepath.Ext(value))
switch ext {
case ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp":
default:
return false
}
if filepath.IsAbs(value) {
if _, err := os.Stat(value); err == nil {
return true
}
return false
}
candidate := resolveAutoReplyPath(value)
if _, err := os.Stat(candidate); err == nil {
return true
}
return false
}
func looksLikeImageRef(value string) bool {
value = strings.TrimSpace(value)
if value == "" {
return false
}
lower := strings.ToLower(value)
if strings.HasPrefix(lower, "http://") || strings.HasPrefix(lower, "https://") {
if parsed, err := url.Parse(value); err == nil {
ext := strings.ToLower(filepath.Ext(parsed.Path))
return ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" || ext == ".bmp" || ext == ".webp" || strings.Contains(lower, "image")
}
return strings.Contains(lower, "image")
}
ext := strings.ToLower(filepath.Ext(value))
return ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".gif" || ext == ".bmp" || ext == ".webp" ||
strings.Contains(lower, "image") || strings.Contains(lower, "file_id") || strings.Contains(lower, "fileid")
}