This commit is contained in:
truewhile
2026-09-08 23:11:57 +08:00
parent 8225b4e319
commit 4239474100
5 changed files with 71 additions and 21 deletions
@@ -96,8 +96,9 @@ func TestAdultProviderRouting(t *testing.T) {
if len(candidates) != 1 {
t.Fatalf("expected 1 candidate, got %d", len(candidates))
}
if candidates[0].PosterURL != "https://example.com/poster.jpg" ||
candidates[0].BackdropURL != "https://example.com/backdrop.jpg" {
wantPoster := mtServer.URL + "/v1/images/primary/javdb/999?auto=false&pos=-1&quality=90&ratio=0.6666666666666666"
wantBackdrop := mtServer.URL + "/v1/images/backdrop/javdb/999?quality=90"
if candidates[0].PosterURL != wantPoster || candidates[0].BackdropURL != wantBackdrop {
t.Fatalf("candidate artwork was not enriched: %#v", candidates[0])
}
+2 -1
View File
@@ -137,10 +137,11 @@ func (s *ScraperService) manualRequestMatch(ctx context.Context, req ManualScrap
if match != nil {
// Older search responses used the portrait poster as a backdrop
// fallback. Do not let that placeholder replace a real preview
// image fetched from the selected MetaTube provider.
// image or processed primary image fetched from MetaTube.
if strings.TrimSpace(match.BackdropURL) != "" &&
strings.TrimSpace(req.BackdropURL) == strings.TrimSpace(req.PosterURL) {
req.BackdropURL = ""
req.PosterURL = ""
}
return mergeManualRequestIntoMatch(match, req), nil
}
+6 -4
View File
@@ -93,11 +93,13 @@ func TestManualAdultMatchUsesSelectedMetaTubeDetailsAndRealBackdrop(t *testing.T
if detailCalls.Load() != 1 {
t.Fatalf("selected MetaTube detail calls = %d, want 1", detailCalls.Load())
}
if match.PosterURL != "https://example.com/search-cover.jpg" {
t.Fatalf("selected poster = %q", match.PosterURL)
wantPoster := upstream.URL + "/v1/images/primary/AVE/94600?auto=false&pos=-1&quality=90&ratio=0.6666666666666666"
if match.PosterURL != wantPoster {
t.Fatalf("selected poster = %q, want %q", match.PosterURL, wantPoster)
}
if match.BackdropURL != "https://example.com/backdrop.jpg" {
t.Fatalf("backdrop = %q, want detail preview", match.BackdropURL)
wantBackdrop := upstream.URL + "/v1/images/backdrop/AVE/94600?quality=90"
if match.BackdropURL != wantBackdrop {
t.Fatalf("backdrop = %q, want %q", match.BackdropURL, wantBackdrop)
}
}
+49 -10
View File
@@ -83,7 +83,7 @@ func (p *MetaTubeProvider) Search(ctx context.Context, cfg MetaTubeConfig, query
matches := make([]*Match, 0, len(results))
for _, res := range results {
match := p.convertSearchResultToMatch(query, &res)
match := p.convertSearchResultToMatch(cfg, query, &res)
if match != nil {
matches = append(matches, match)
}
@@ -134,7 +134,7 @@ func (p *MetaTubeProvider) GetMovie(ctx context.Context, cfg MetaTubeConfig, pro
return nil, fmt.Errorf("decode metatube movie response failed: %w", directErr)
}
return p.convertMovieInfoToMatch(&movie), nil
return p.convertMovieInfoToMatch(cfg, &movie), nil
}
// SearchAndGetBestMatch 执行搜索并拉取首个最佳结果的完整电影详情。
@@ -276,7 +276,7 @@ func (p *MetaTubeProvider) applyAuthHeader(req *http.Request, token string) {
req.Header.Set("User-Agent", "MeBox/1.0 (MetaTube Client)")
}
func (p *MetaTubeProvider) convertSearchResultToMatch(query string, res *MetaTubeSearchResult) *Match {
func (p *MetaTubeProvider) convertSearchResultToMatch(cfg MetaTubeConfig, query string, res *MetaTubeSearchResult) *Match {
if res == nil {
return nil
}
@@ -300,14 +300,20 @@ func (p *MetaTubeProvider) convertSearchResultToMatch(query string, res *MetaTub
}
}
posterURL := firstNonEmpty(res.BigCoverURL, res.CoverURL, res.BigThumbURL, res.ThumbURL)
posterURL, backdropURL := metaTubeArtworkURLs(cfg, res.Provider, res.ID)
if posterURL == "" {
posterURL = firstNonEmpty(res.BigThumbURL, res.ThumbURL, res.BigCoverURL, res.CoverURL)
}
if backdropURL == "" {
backdropURL = firstNonEmpty(res.BigCoverURL, res.CoverURL, posterURL)
}
return &Match{
MediaType: "adult",
Title: formattedTitle,
OriginalName: code,
PosterURL: posterURL,
BackdropURL: posterURL,
BackdropURL: backdropURL,
Year: year,
ReleaseDate: cleanDateString(res.ReleaseDate),
Rating: res.Score,
@@ -318,7 +324,7 @@ func (p *MetaTubeProvider) convertSearchResultToMatch(query string, res *MetaTub
}
}
func (p *MetaTubeProvider) convertMovieInfoToMatch(movie *MetaTubeMovieInfo) *Match {
func (p *MetaTubeProvider) convertMovieInfoToMatch(cfg MetaTubeConfig, movie *MetaTubeMovieInfo) *Match {
if movie == nil {
return nil
}
@@ -336,10 +342,16 @@ func (p *MetaTubeProvider) convertMovieInfoToMatch(movie *MetaTubeMovieInfo) *Ma
year := parseYearFromDate(movie.ReleaseDate)
posterURL := firstNonEmpty(movie.BigCoverURL, movie.CoverURL, movie.BigThumbURL, movie.ThumbURL)
backdropURL := posterURL
if len(movie.PreviewImages) > 0 && movie.PreviewImages[0] != "" {
backdropURL = movie.PreviewImages[0]
posterURL, backdropURL := metaTubeArtworkURLs(cfg, movie.Provider, movie.ID)
if posterURL == "" {
posterURL = firstNonEmpty(movie.BigThumbURL, movie.ThumbURL, movie.BigCoverURL, movie.CoverURL)
}
if backdropURL == "" {
if len(movie.PreviewImages) > 0 && movie.PreviewImages[0] != "" {
backdropURL = movie.PreviewImages[0]
} else {
backdropURL = firstNonEmpty(movie.BigCoverURL, movie.CoverURL, posterURL)
}
}
genres := make([]string, 0, len(movie.Genres)+len(movie.Actors)+4)
@@ -385,6 +397,33 @@ func (p *MetaTubeProvider) convertMovieInfoToMatch(movie *MetaTubeMovieInfo) *Ma
}
}
func metaTubeArtworkURLs(cfg MetaTubeConfig, provider, id string) (string, string) {
serverURL := strings.TrimRight(strings.TrimSpace(cfg.ServerURL), "/")
provider = strings.TrimSpace(provider)
id = strings.TrimSpace(id)
if serverURL == "" || provider == "" || id == "" {
return "", ""
}
imageURL := func(kind string, primary bool) string {
base := fmt.Sprintf("%s/v1/images/%s/%s/%s", serverURL, kind, url.PathEscape(provider), url.PathEscape(id))
values := url.Values{}
values.Set("quality", "90")
if primary {
values.Set("pos", "-1")
values.Set("auto", "false")
if cfg.CropCover {
values.Set("ratio", strconv.FormatFloat(2.0/3.0, 'f', -1, 64))
} else {
values.Set("ratio", "-1")
}
}
return base + "?" + values.Encode()
}
return imageURL("primary", true), imageURL("backdrop", false)
}
func parseYearFromDate(dateStr string) int {
dateStr = strings.TrimSpace(dateStr)
if len(dateStr) >= 4 {
+11 -4
View File
@@ -74,6 +74,12 @@ func TestMetaTubeProviderSearch(t *testing.T) {
if len(m.Genres) != 1 || m.Genres[0] != "相沢みなみ" {
t.Errorf("unexpected genres: %v", m.Genres)
}
if want := server.URL + "/v1/images/primary/javdb/123456?auto=false&pos=-1&quality=90&ratio=-1"; m.PosterURL != want {
t.Errorf("poster URL = %q, want %q", m.PosterURL, want)
}
if want := server.URL + "/v1/images/backdrop/javdb/123456?quality=90"; m.BackdropURL != want {
t.Errorf("backdrop URL = %q, want %q", m.BackdropURL, want)
}
}
func TestMetaTubeProviderGetMovie(t *testing.T) {
@@ -112,6 +118,7 @@ func TestMetaTubeProviderGetMovie(t *testing.T) {
provider := NewMetaTubeProvider(zap.NewNop())
cfg := MetaTubeConfig{
ServerURL: server.URL,
CropCover: true,
}
match, err := provider.GetMovie(context.Background(), cfg, "javdb", "123456")
@@ -124,11 +131,11 @@ func TestMetaTubeProviderGetMovie(t *testing.T) {
if match.Overview != "超绝美少女相沢みなみ出道作品!" {
t.Errorf("unexpected overview: %s", match.Overview)
}
if match.PosterURL != "https://example.com/big_cover.jpg" {
t.Errorf("unexpected poster URL: %s", match.PosterURL)
if want := server.URL + "/v1/images/primary/javdb/123456?auto=false&pos=-1&quality=90&ratio=0.6666666666666666"; match.PosterURL != want {
t.Errorf("poster URL = %q, want %q", match.PosterURL, want)
}
if match.BackdropURL != "https://example.com/preview1.jpg" {
t.Errorf("unexpected backdrop URL: %s", match.BackdropURL)
if want := server.URL + "/v1/images/backdrop/javdb/123456?quality=90"; match.BackdropURL != want {
t.Errorf("backdrop URL = %q, want %q", match.BackdropURL, want)
}
if match.Year != 2018 {
t.Errorf("expected year 2018, got %d", match.Year)