mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-02 20:26:36 +08:00
Fix local adult metadata and watch history removal
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ExternalMediaResult is a metadata candidate from an online catalog. It is
|
||||
// intentionally separate from model.Media because the item may not exist in
|
||||
// the local library yet.
|
||||
type ExternalMediaResult struct {
|
||||
Source string `json:"source"`
|
||||
MediaType string `json:"media_type,omitempty"`
|
||||
Title string `json:"title"`
|
||||
Overview string `json:"overview,omitempty"`
|
||||
PosterURL string `json:"poster_url,omitempty"`
|
||||
BackdropURL string `json:"backdrop_url,omitempty"`
|
||||
Year int `json:"year,omitempty"`
|
||||
Rating float32 `json:"rating,omitempty"`
|
||||
TMDbID int `json:"tmdb_id,omitempty"`
|
||||
BangumiID int `json:"bangumi_id,omitempty"`
|
||||
DoubanID string `json:"douban_id,omitempty"`
|
||||
SubscribeKeyword string `json:"subscribe_keyword"`
|
||||
}
|
||||
|
||||
// SearchExternalMedia fans out one normalized search intent to TMDb, Douban
|
||||
// and Bangumi. This mirrors MoviePilot's separation of "metadata discovery"
|
||||
// from later tracker searching/downloading, but keeps our Go service small.
|
||||
func SearchExternalMedia(ctx context.Context, query string, year int, mediaType string, tmdb *TMDbProvider, douban *DoubanProvider, bangumi *BangumiProvider) []ExternalMediaResult {
|
||||
query = strings.TrimSpace(query)
|
||||
if query == "" {
|
||||
return []ExternalMediaResult{}
|
||||
}
|
||||
|
||||
results := make([]ExternalMediaResult, 0, 6)
|
||||
addMatch := func(source, typ string, m *Match) {
|
||||
if m == nil || strings.TrimSpace(m.Title) == "" {
|
||||
return
|
||||
}
|
||||
results = append(results, ExternalMediaResult{
|
||||
Source: source,
|
||||
MediaType: typ,
|
||||
Title: m.Title,
|
||||
Overview: m.Overview,
|
||||
PosterURL: m.PosterURL,
|
||||
BackdropURL: m.BackdropURL,
|
||||
Year: m.Year,
|
||||
Rating: m.Rating,
|
||||
TMDbID: m.TMDbID,
|
||||
BangumiID: m.BangumiID,
|
||||
SubscribeKeyword: buildSubscribeKeyword(m.Title, m.Year),
|
||||
})
|
||||
}
|
||||
|
||||
if tmdb != nil {
|
||||
if mediaType == "" || mediaType == "movie" {
|
||||
if m, err := tmdb.SearchMovie(ctx, query, year); err == nil {
|
||||
addMatch("tmdb", "movie", m)
|
||||
}
|
||||
}
|
||||
if mediaType == "" || mediaType == "tv" || mediaType == "anime" {
|
||||
if m, err := tmdb.SearchTV(ctx, query, year); err == nil {
|
||||
addMatch("tmdb", "tv", m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if bangumi != nil && (mediaType == "" || mediaType == "anime") {
|
||||
if m, err := bangumi.Search(ctx, query); err == nil {
|
||||
addMatch("bangumi", "anime", m)
|
||||
}
|
||||
}
|
||||
|
||||
if douban != nil {
|
||||
if m, err := douban.Search(ctx, query); err == nil && m != nil {
|
||||
yearValue, _ := strconv.Atoi(m.Year)
|
||||
typ := normalizeDoubanType(m.Type, mediaType)
|
||||
results = append(results, ExternalMediaResult{
|
||||
Source: "douban",
|
||||
MediaType: typ,
|
||||
Title: m.Title,
|
||||
PosterURL: m.Img,
|
||||
Year: yearValue,
|
||||
Rating: m.Rating,
|
||||
DoubanID: m.DoubanID,
|
||||
SubscribeKeyword: buildSubscribeKeyword(m.Title, yearValue),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return dedupeExternalMedia(results)
|
||||
}
|
||||
|
||||
func buildSubscribeKeyword(title string, year int) string {
|
||||
title = strings.TrimSpace(title)
|
||||
if year > 0 {
|
||||
return fmt.Sprintf("%s %d", title, year)
|
||||
}
|
||||
return title
|
||||
}
|
||||
|
||||
func normalizeDoubanType(doubanType, fallback string) string {
|
||||
doubanType = strings.ToLower(strings.TrimSpace(doubanType))
|
||||
switch doubanType {
|
||||
case "movie":
|
||||
return "movie"
|
||||
case "tv", "tvshow", "drama":
|
||||
return "tv"
|
||||
}
|
||||
if fallback != "" {
|
||||
return fallback
|
||||
}
|
||||
return "movie"
|
||||
}
|
||||
|
||||
func dedupeExternalMedia(in []ExternalMediaResult) []ExternalMediaResult {
|
||||
seen := map[string]struct{}{}
|
||||
out := make([]ExternalMediaResult, 0, len(in))
|
||||
for _, item := range in {
|
||||
key := item.Source + ":" + strings.ToLower(item.Title)
|
||||
if item.TMDbID > 0 {
|
||||
key = fmt.Sprintf("tmdb:%d:%s", item.TMDbID, item.MediaType)
|
||||
} else if item.BangumiID > 0 {
|
||||
key = fmt.Sprintf("bangumi:%d", item.BangumiID)
|
||||
} else if item.DoubanID != "" {
|
||||
key = "douban:" + item.DoubanID
|
||||
}
|
||||
if _, ok := seen[key]; ok {
|
||||
continue
|
||||
}
|
||||
seen[key] = struct{}{}
|
||||
out = append(out, item)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user