Enhance show management: add OriginalName property to ShowSummaryDto, update ListShowsQueryHandler to include OriginalName, and improve upload functionality by allowing auto-detection of shows based on file names. Update translations for better user guidance on show detection.

This commit is contained in:
Leonid Pershin
2026-07-25 18:54:43 +03:00
parent 8718e8b6bf
commit 9cefc6a198
7 changed files with 113 additions and 31 deletions
@@ -0,0 +1,42 @@
/**
* Сопоставление файла с шоу по названию: имя релиза (напр. «The.Simpsons.S33E01.WEBDL…») содержит
* оригинальное (или отображаемое) название шоу. Нормализуем обе строки до слов через пробел и ищем
* название как цельную последовательность слов; при нескольких совпадениях берём самое длинное
* («Star Trek Discovery» важнее «Star Trek»).
*/
export type ShowNameRef = { id: string; name: string; originalName?: string | null }
/** Приводит строку к «словам через пробел»: буквы/цифры сохраняем, всё прочее — разделитель. */
function normalize(value: string): string {
return value
.toLowerCase()
.replace(/[^\p{L}\p{N}]+/gu, ' ')
.trim()
.replace(/\s+/g, ' ')
}
/** Минимальная длина названия-кандидата (в символах после нормализации) — отсекает шум. */
const MIN_CANDIDATE_LENGTH = 2
/**
* Возвращает id наиболее подходящего шоу для имени файла или undefined, если совпадений нет.
* Совпадением считается вхождение названия шоу как цельной последовательности слов в имя файла.
*/
export function matchShowByName(fileName: string, shows: readonly ShowNameRef[]): string | undefined {
const haystack = ` ${normalize(fileName)} `
let best: { id: string; length: number } | undefined
for (const show of shows) {
for (const candidate of [show.originalName, show.name]) {
if (!candidate) continue
const norm = normalize(candidate)
if (norm.length < MIN_CANDIDATE_LENGTH) continue
if (haystack.includes(` ${norm} `) && norm.length > (best?.length ?? 0)) {
best = { id: show.id, length: norm.length }
}
}
}
return best?.id
}