TMDB Entegrasyonu
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user