TMDB Entegrasyonu

This commit is contained in:
2025-10-27 06:05:34 +03:00
parent 1760441ce7
commit 66ac562bcd
9 changed files with 2292 additions and 136 deletions

View File

@@ -1,98 +1,176 @@
const LOWERCASE_WORDS = new Set(["di", "da", "de", "of", "and", "the", "la"]);
const IGNORED_TOKENS = new Set(
[
"hdrip",
"hdr",
"webrip",
"webdl",
"dl",
"web-dl",
"blu",
"bluray",
"bdrip",
"dvdrip",
"remux",
"multi",
"audio",
"aac",
"ac3",
"ddp",
"dts",
"xvid",
"x264",
"x265",
"x266",
"h264",
"h265",
"hevc",
"hdr10",
"hdr10plus",
"amzn",
"nf",
"netflix",
"disney",
"imax",
"atmos",
"dubbed",
"dublado",
"ita",
"eng",
"turkce",
"multi-audio",
"eazy",
"tbmovies",
"tbm",
"bone"
].map((t) => t.toLowerCase())
);
const QUALITY_PATTERNS = [
/^\d{3,4}p$/,
/^s\d{1,2}e\d{1,2}$/i,
/^(ac3|aac\d*|ddp\d*|dts|dubbed|dual|multi|hc)$/i,
/^(x|h)?26[45]$/i
];
export function extractTitleAndYear(rawName) {
if (!rawName) return { title: "", year: null };
const withoutExt = rawName.replace(/\.[^/.]+$/, "");
const normalized = withoutExt
.replace(/[\[\]\(\)\-]/g, " ")
.replace(/[._]/g, " ");
const tokens = normalized
.split(/\s+/)
.map((token) => token.trim())
.filter(Boolean);
if (!tokens.length) {
return { title: withoutExt.trim(), year: null };
}
const yearIndex = tokens.findIndex((token) => /^(19|20)\d{2}$/.test(token));
if (yearIndex > 0) {
const yearToken = tokens[yearIndex];
const candidateTokens = tokens.slice(0, yearIndex);
const filteredTitleTokens = candidateTokens.filter((token) => {
const lower = token.toLowerCase();
if (IGNORED_TOKENS.has(lower)) return false;
if (/^\d{3,4}p$/.test(lower)) return false;
if (/^(ac3|aac\d*|ddp\d*|dts|dubbed|dual|multi|hc)$/i.test(lower))
return false;
if (/^(x|h)?26[45]$/i.test(lower)) return false;
if (lower.includes("hdrip") || lower.includes("web-dl")) return false;
if (lower.includes("multi-audio")) return false;
return true;
});
const titleTokens = filteredTitleTokens.length
? filteredTitleTokens
: candidateTokens;
const title = titleTokens.join(" ").replace(/\s+/g, " ").trim();
return {
title: title || withoutExt.trim(),
year: Number(yearToken)
};
}
let year = null;
const filtered = [];
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];
const lower = token.toLowerCase();
if (!year && /^(19|20)\d{2}$/.test(lower)) {
year = Number(lower);
continue;
}
if (QUALITY_PATTERNS.some((pattern) => pattern.test(token))) continue;
if (lower === "web" && tokens[i + 1]?.toLowerCase() === "dl") {
i += 1;
continue;
}
if (IGNORED_TOKENS.has(lower)) continue;
if (lower.includes("multi-audio")) continue;
filtered.push(token);
}
const title = filtered.join(" ").replace(/\s+/g, " ").trim();
return {
title: title || withoutExt.trim(),
year
};
}
function titleCase(value) {
if (!value) return "";
return value
.split(" ")
.filter(Boolean)
.map((segment, index) => {
const lower = segment.toLowerCase();
if (index !== 0 && LOWERCASE_WORDS.has(lower)) {
return lower;
}
return lower.charAt(0).toUpperCase() + lower.slice(1);
})
.join(" ");
}
/**
* Dosya adını temizler ve sadeleştirir.
* Örnek:
* The.Astronaut.2025.1080p.WEBRip.x265-KONTRAST
* → "The Astronaut (2025)"
* 1761244874124/Gen.V.S02E08.Cavallo.di.Troia.ITA.ENG.1080p.AMZN.WEB-DL.DDP5.1.H.264-MeM.GP.mkv
* → "Gen V S02E08 Cavallo Di Troia"
* Dosya adını temizleyip başlık/yıl bilgisi çıkarır.
* Örn: The.Astronaut.2025.1080p.WEBRip → "The Astronaut (2025)"
*/
export function cleanFileName(fullPath) {
if (!fullPath) return "";
// 1⃣ Klasör yolunu kaldır
let name = fullPath.split("/").pop();
const baseName = fullPath.split("/").pop() || "";
const withoutExt = baseName.replace(/\.[^.]+$/, "");
// 2⃣ Uzantıyı kaldır
name = name.replace(/\.[^.]+$/, "");
const episodeMatch = withoutExt.match(/(S\d{1,2}E\d{1,2})/i);
const { title, year } = extractTitleAndYear(withoutExt);
// 3⃣ Noktaları ve alt tireleri boşluğa çevir
name = name.replace(/[._]+/g, " ");
let result = titleCase(title);
// 4⃣ Gereksiz etiketleri kaldır
const trashWords = [
"1080p",
"720p",
"2160p",
"4k",
"bluray",
"web[- ]?dl",
"webrip",
"hdrip",
"x264",
"x265",
"hevc",
"aac",
"h264",
"h265",
"ddp5",
"dvdrip",
"brrip",
"remux",
"multi",
"sub",
"subs",
"turkce",
"ita",
"eng",
"dublado",
"dubbed",
"extended",
"unrated",
"repack",
"proper",
"kontrast",
"yify",
"ettv",
"rarbg",
"hdtv",
"amzn",
"nf",
"netflix",
"mem",
"gp"
];
const trashRegex = new RegExp(`\\b(${trashWords.join("|")})\\b`, "gi");
name = name.replace(trashRegex, " ");
// 5⃣ Parantez veya köşeli parantez içindekileri kaldır
name = name.replace(/[\[\(].*?[\]\)]/g, " ");
// 6⃣ Fazla tireleri ve sayıları temizle
name = name
.replace(/[-]+/g, " ")
.replace(/\b\d{3,4}\b/g, " ") // tek başına 1080, 2025 gibi
.replace(/\s{2,}/g, " ")
.trim();
// 7⃣ Dizi formatını (S02E08) koru
const episodeMatch = name.match(/(S\d{1,2}E\d{1,2})/i);
if (episodeMatch) {
const epTag = episodeMatch[0].toUpperCase();
// örnek: Gen V S02E08 Cavallo di Troia
name = name.replace(episodeMatch[0], epTag);
const tag = episodeMatch[0].toUpperCase();
result = result
? `${result} ${tag}`
: tag;
} else if (year) {
result = result ? `${result} (${year})` : `${withoutExt} (${year})`;
}
// 8⃣ Baş harfleri büyüt (küçük kelimeleri koruyarak)
name = name
.split(" ")
.filter((w) => w.length > 0)
.map((w) => {
if (["di", "da", "de", "of", "and", "the"].includes(w.toLowerCase()))
return w.toLowerCase();
return w[0].toUpperCase() + w.slice(1).toLowerCase();
})
.join(" ")
.trim();
if (!result) {
result = withoutExt.replace(/[._]+/g, " ");
}
return name;
return result.trim();
}