display_name: слоистое разрешение полей + сохранение режиссёра из контекста
Единый источник полей отображаемого имени и один рендер полного ярлыка на всех путях (старт и «Обновить имя»/авто-перелив). Раньше старт давал полный «Название (режиссёр, год). Сезон N» но выбрасывал структуру, а перелив по распознаванию — усечённый «Title (Year)». - Слоистое разрешение скаляров имени: override → recognition(+match) → новый базовый слой «контекст» (download.parsed_context, JSON naming.Fields). - naming: публичные Fields/Label/Derive, вынесен единый рендер; удалён FormatTitleYear. Сводка сезонов вынесена в recognize.SeasonSummary. - Режиссёр из метабазы (решение A2): TMDB/TVDB credits через опциональный metadata.DirectorProvider; авто-матч кладёт в plan.Director, ручной выбор кандидата тянет credits и пиннит ovrDirector. Метабаза бьёт контекст. - refreshDisplayNameLocked строит полный ярлык из эффективных полей; инфо-панель ревью показывает загруженного режиссёра. - Миграция 0011_parsed_context + ER-схема. Всё косметика: на пути/раскладку не влияет, приём/вывод имени не валятся (best-effort). Закрывает беклог-задачу «Кнопка „Обновить имя“: полный формат ярлыка». OpenSpec: archive/2026-07-11-field-resolution-display-name (ingest, recognition, metadata-match, review). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package recognize
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
@@ -143,10 +144,44 @@ func (r *Recognizer) buildMatch(ctx context.Context, p metadata.Provider, c meta
|
||||
ProviderID: pid,
|
||||
Title: c.Title,
|
||||
Year: c.Year,
|
||||
Director: directorOf(ctx, r.log, p, mt, c.ID),
|
||||
SeasonEpisodeCounts: counts,
|
||||
}
|
||||
}
|
||||
|
||||
// directorOf тянет режиссёра из провайдера по нативному id, если он умеет
|
||||
// (DirectorProvider). Best-effort: ошибка/неподдержка → пусто, распознавание не
|
||||
// валится. Режиссёр — недоверенное косметическое поле.
|
||||
func directorOf(ctx context.Context, log *slog.Logger, p metadata.Provider, mt metadata.MediaType, id string) string {
|
||||
dp, ok := p.(metadata.DirectorProvider)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
d, err := dp.Director(ctx, mt, id)
|
||||
if err != nil {
|
||||
logctx.FromOr(ctx, log).Debug("metadata director skipped", "provider", p.Name(), "id", id)
|
||||
return ""
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// Director тянет режиссёра выбранного источника по (provider, id) — точка входа
|
||||
// для ручного выбора кандидата в ревью (см. worker). Ищет провайдера поиска по
|
||||
// имени; best-effort — нет провайдера/не умеет/ошибка → пусто. mt — тип из плана.
|
||||
func (r *Recognizer) Director(ctx context.Context, mt MediaType, provider, providerID string) string {
|
||||
metaType := metadata.Movie
|
||||
if mt == MediaSeries {
|
||||
metaType = metadata.Series
|
||||
}
|
||||
for _, p := range r.providers {
|
||||
if p.Name() != provider {
|
||||
continue
|
||||
}
|
||||
return directorOf(ctx, r.log, p, metaType, providerID)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// CandidateTag — провайдер и id для тега папки Jellyfin: внешний (из
|
||||
// TagProvider/TagID, напр. TVMaze → tvdb/imdb), если есть, иначе сам провайдер
|
||||
// поиска. Используется и в матче, и при сохранении кандидатов.
|
||||
|
||||
Reference in New Issue
Block a user