mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-28 11:16:37 +08:00
107 lines
3.1 KiB
Go
107 lines
3.1 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
)
|
|
|
|
func (s *ScraperService) prepareScrapedArtworkURL(ctx context.Context, mediaID, field, current, candidate string) (string, string) {
|
|
current = strings.TrimSpace(current)
|
|
candidate = strings.TrimSpace(candidate)
|
|
if candidate == "" {
|
|
return current, ""
|
|
}
|
|
if candidate == current {
|
|
return candidate, ""
|
|
}
|
|
if s == nil || s.images == nil || !isHTTPish(candidate) {
|
|
return candidate, ""
|
|
}
|
|
originalSource := metaTubeOriginalArtworkURL(candidate)
|
|
timeout := 15 * time.Second
|
|
if originalSource != "" {
|
|
// MetaTube face processing can become very slow under a batch scrape.
|
|
// Fail over quickly so the same source can be processed locally.
|
|
timeout = 8 * time.Second
|
|
}
|
|
fetchCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), timeout)
|
|
err := s.images.PrefetchCardVariant(fetchCtx, candidate)
|
|
cancel()
|
|
if err != nil {
|
|
if originalSource != "" {
|
|
fallbackCtx, fallbackCancel := context.WithTimeout(context.WithoutCancel(ctx), 15*time.Second)
|
|
fallbackErr := s.images.PrefetchRemote(fallbackCtx, originalSource)
|
|
fallbackCancel()
|
|
if fallbackErr == nil {
|
|
s.log.Warn("MetaTube artwork processing failed; using local face-aware crop",
|
|
zap.String("media_id", mediaID),
|
|
zap.String("field", field),
|
|
zap.String("candidate", redactSensitiveURL(candidate)),
|
|
zap.String("source", redactSensitiveURL(originalSource)),
|
|
zap.Error(redactSensitiveError(err)))
|
|
if current != "" && isHTTPish(current) {
|
|
return originalSource, current
|
|
}
|
|
return originalSource, ""
|
|
}
|
|
}
|
|
if current != "" {
|
|
s.log.Warn("scrape artwork prefetch failed; keeping existing artwork",
|
|
zap.String("media_id", mediaID),
|
|
zap.String("field", field),
|
|
zap.String("candidate", redactSensitiveURL(candidate)),
|
|
zap.String("existing", redactSensitiveURL(current)),
|
|
zap.Error(redactSensitiveError(err)))
|
|
return current, ""
|
|
}
|
|
s.log.Warn("scrape artwork prefetch failed; keeping new artwork URL for retry",
|
|
zap.String("media_id", mediaID),
|
|
zap.String("field", field),
|
|
zap.String("candidate", redactSensitiveURL(candidate)),
|
|
zap.Error(redactSensitiveError(err)))
|
|
return candidate, ""
|
|
}
|
|
if current != "" && isHTTPish(current) {
|
|
return candidate, current
|
|
}
|
|
return candidate, ""
|
|
}
|
|
|
|
func metaTubeOriginalArtworkURL(raw string) string {
|
|
parsed, err := url.Parse(strings.TrimSpace(raw))
|
|
if err != nil || !strings.Contains(parsed.Path, "/v1/images/primary/") {
|
|
return ""
|
|
}
|
|
source := strings.TrimSpace(parsed.Query().Get("url"))
|
|
if !isHTTPish(source) {
|
|
return ""
|
|
}
|
|
return source
|
|
}
|
|
|
|
func (s *ScraperService) removeCachedScrapedArtwork(urls ...string) {
|
|
if s == nil || s.images == nil {
|
|
return
|
|
}
|
|
seen := map[string]struct{}{}
|
|
for _, raw := range urls {
|
|
raw = strings.TrimSpace(raw)
|
|
if raw == "" {
|
|
continue
|
|
}
|
|
if _, ok := seen[raw]; ok {
|
|
continue
|
|
}
|
|
seen[raw] = struct{}{}
|
|
if err := s.images.RemoveCached(raw); err != nil {
|
|
s.log.Debug("remove old scraped artwork cache failed",
|
|
zap.String("url", redactSensitiveURL(raw)),
|
|
zap.Error(redactSensitiveError(err)))
|
|
}
|
|
}
|
|
}
|