mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-07 05:46:38 +08:00
refactor: split modules and harden scraping workflows
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/model"
|
||||
)
|
||||
|
||||
func (s *ScannerService) enrichCloudMetadataFromExternalIDs(ctx context.Context, lib *model.Library, path string, meta *LocalMetadata) *LocalMetadata {
|
||||
if s == nil || s.scraper == nil || meta == nil || !cloudMetadataNeedsExternalEnrich(meta) {
|
||||
return meta
|
||||
}
|
||||
localPoster, localBackdrop := cloudLocalArtworkURLs(meta)
|
||||
media := &model.Media{
|
||||
LibraryID: "",
|
||||
Title: firstNonEmpty(meta.Title, pathBaseSlash(path)),
|
||||
Path: path,
|
||||
Year: meta.Year,
|
||||
TMDbID: meta.TMDbID,
|
||||
BangumiID: meta.BangumiID,
|
||||
DoubanID: meta.DoubanID,
|
||||
TheTVDBID: meta.TheTVDBID,
|
||||
SeasonNum: meta.SeasonNum,
|
||||
EpisodeNum: meta.EpisodeNum,
|
||||
PosterURL: meta.PosterURL,
|
||||
BackdropURL: meta.BackdropURL,
|
||||
}
|
||||
if lib != nil {
|
||||
media.LibraryID = lib.ID
|
||||
}
|
||||
enrichCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
match := s.scraper.matchFromMediaExternalIDs(enrichCtx, media, lib)
|
||||
if match == nil {
|
||||
return meta
|
||||
}
|
||||
s.scraper.applyFanartArtwork(enrichCtx, match)
|
||||
mergeLocalMetadataIntoMatch(match, meta)
|
||||
|
||||
enriched := cloneLocalMetadata(meta)
|
||||
if enriched == nil {
|
||||
enriched = &LocalMetadata{}
|
||||
}
|
||||
mergeMatchIntoLocalMetadata(enriched, match)
|
||||
if localPoster != "" {
|
||||
enriched.PosterURL = localPoster
|
||||
enriched.HasArtwork = true
|
||||
}
|
||||
if localBackdrop != "" {
|
||||
enriched.BackdropURL = localBackdrop
|
||||
enriched.HasArtwork = true
|
||||
}
|
||||
enriched.PathHint = false
|
||||
enriched.HasNFO = true
|
||||
if enriched.PosterURL != "" || enriched.BackdropURL != "" {
|
||||
enriched.HasArtwork = true
|
||||
}
|
||||
s.prefetchRemoteArtworkFromScan(ctx, enriched.PosterURL)
|
||||
s.prefetchRemoteArtworkFromScan(ctx, enriched.BackdropURL)
|
||||
return enriched
|
||||
}
|
||||
|
||||
func cloudMetadataNeedsExternalEnrich(meta *LocalMetadata) bool {
|
||||
if meta == nil {
|
||||
return false
|
||||
}
|
||||
hasExternalID := meta.TMDbID > 0 || meta.BangumiID > 0 || strings.TrimSpace(meta.DoubanID) != "" || strings.TrimSpace(meta.TheTVDBID) != ""
|
||||
if !hasExternalID {
|
||||
return false
|
||||
}
|
||||
return meta.PosterURL == "" || meta.BackdropURL == "" || meta.Overview == "" || meta.Title == ""
|
||||
}
|
||||
|
||||
func cloudLocalArtworkURLs(meta *LocalMetadata) (poster, backdrop string) {
|
||||
if meta == nil || !meta.HasArtwork {
|
||||
return "", ""
|
||||
}
|
||||
if _, _, ok := ParseCloudArtworkURL(meta.PosterURL); ok {
|
||||
poster = meta.PosterURL
|
||||
}
|
||||
if _, _, ok := ParseCloudArtworkURL(meta.BackdropURL); ok {
|
||||
backdrop = meta.BackdropURL
|
||||
}
|
||||
return poster, backdrop
|
||||
}
|
||||
|
||||
func mergeMatchIntoLocalMetadata(meta *LocalMetadata, match *Match) {
|
||||
if meta == nil || match == nil {
|
||||
return
|
||||
}
|
||||
if match.Title != "" {
|
||||
meta.Title = match.Title
|
||||
}
|
||||
if match.OriginalName != "" {
|
||||
meta.OriginalName = match.OriginalName
|
||||
}
|
||||
if match.Year > 0 {
|
||||
meta.Year = match.Year
|
||||
}
|
||||
if match.Overview != "" {
|
||||
meta.Overview = match.Overview
|
||||
}
|
||||
if match.Rating > 0 {
|
||||
meta.Rating = match.Rating
|
||||
}
|
||||
if match.PosterURL != "" {
|
||||
meta.PosterURL = match.PosterURL
|
||||
}
|
||||
if match.BackdropURL != "" {
|
||||
meta.BackdropURL = match.BackdropURL
|
||||
}
|
||||
if match.TMDbID > 0 {
|
||||
meta.TMDbID = match.TMDbID
|
||||
}
|
||||
if match.BangumiID > 0 {
|
||||
meta.BangumiID = match.BangumiID
|
||||
}
|
||||
if match.DoubanID != "" {
|
||||
meta.DoubanID = match.DoubanID
|
||||
}
|
||||
if match.TheTVDBID != "" {
|
||||
meta.TheTVDBID = match.TheTVDBID
|
||||
}
|
||||
if len(match.Genres) > 0 {
|
||||
meta.Genres = strings.Join(match.Genres, ",")
|
||||
}
|
||||
if len(match.Countries) > 0 {
|
||||
meta.Countries = strings.Join(match.Countries, ",")
|
||||
}
|
||||
if len(match.Languages) > 0 {
|
||||
meta.Languages = strings.Join(match.Languages, ",")
|
||||
}
|
||||
if match.NSFW {
|
||||
meta.NSFW = true
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ScannerService) prefetchRemoteArtworkFromScan(ctx context.Context, raw string) {
|
||||
if s == nil || s.imageProxy == nil || !isHTTPish(raw) {
|
||||
return
|
||||
}
|
||||
fetchCtx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 15*time.Second)
|
||||
err := s.imageProxy.PrefetchRemote(fetchCtx, raw)
|
||||
cancel()
|
||||
if err != nil && s.log != nil {
|
||||
s.log.Debug("scan remote artwork prefetch failed", zap.String("url", raw), zap.Error(err))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user