Compare commits

...
4 Commits
2 changed files with 39 additions and 20 deletions

No files matched your search

+7
View File
@@ -1,5 +1,12 @@
# Changelog
## [1.12.0](https://github.com/Masutayunikon/FanKarr/compare/v1.11.10...v1.12.0) (2026-03-21)
### Features
* now rename episodes with original_filename from api ([9bdb21a](https://github.com/Masutayunikon/FanKarr/commit/9bdb21a673ebb9871548aea6691bafbd049554ce))
## [1.11.10](https://github.com/Masutayunikon/FanKarr/compare/v1.11.9...v1.11.10) (2026-03-21)
+32 -20
View File
@@ -15,10 +15,16 @@ import fs from 'fs'
import fsp from 'fs/promises'
import path from 'path'
import { parentPort } from 'worker_threads'
import { DATA_DIR } from './config.js'
const TORRENTS_PATH = path.join(DATA_DIR, 'torrent_final.json')
const ORGANIZED_PATH = path.join(DATA_DIR, 'organized.json')
// Base directory : binaire Bun ou cwd (Docker/dev)
const _isBunBinary = typeof (globalThis as any).Bun !== 'undefined'
&& path.dirname((process as any).execPath) !== process.cwd()
const BASE_DIR = _isBunBinary
? path.dirname((process as any).execPath)
: process.cwd()
const TORRENTS_PATH = path.join(BASE_DIR, 'data', 'torrent_final.json')
const ORGANIZED_PATH = path.join(BASE_DIR, 'data', 'organized.json')
// ─── Utils log ────────────────────────────────────────────────
// Le worker tourne dans un thread séparé — il passe les logs au thread principal
@@ -33,7 +39,7 @@ function debug(msg: string) { parentPort?.postMessage({ type: 'log', level: 'deb
function readSettings(): { mediaPath: string; completePath: string; organizeMode: string; nfoSupport: boolean } {
try {
const p = path.join(DATA_DIR, 'settings.json')
const p = path.join(process.cwd(), 'data', 'settings.json')
if (!fs.existsSync(p)) return { mediaPath: '', completePath: '', organizeMode: 'hardlink', nfoSupport: false }
return JSON.parse(fs.readFileSync(p, 'utf-8'))
} catch { return { mediaPath: '', completePath: '', organizeMode: 'hardlink', nfoSupport: false } }
@@ -283,29 +289,35 @@ async function organizeTorrent(hash: string, name: string, savePath: string) {
return { ...result, total: 1, done: 1 }
}
// ── Map filename → original_filename (depuis l'API) ────────
const filenameToOriginal = new Map<string, string>()
for (const ep of torrent.resolved_episodes ?? []) {
if (ep.filename && ep.original_filename && ep.filename !== ep.original_filename) {
filenameToOriginal.set(ep.filename, ep.original_filename)
}
}
// ── Map filename → season ─────────────────────────────────
// Priorité : season_number dans torrent_files (packs multi-saisons)
// Fallback : resolved_episodes matchés par episode_number (torrents individuels)
const filenameSeasonMap = new Map<string, number>()
// Index resolved_episodes par episode_number pour lookup rapide
const filenameToSeason = new Map<string, number>()
const epByNum = new Map<number, number>() // ep_number → season_number
for (const ep of torrent.resolved_episodes ?? []) {
if (ep.filename && ep.season_number !== undefined)
filenameToSeason.set(ep.filename, ep.season_number)
if (ep.episode_number !== undefined && ep.season_number !== undefined)
epByNum.set(Number(ep.episode_number), ep.season_number)
}
for (const tf of torrentFiles) {
const sn = tf.season_number != null ? Number(tf.season_number) : null
const sn: number | null = tf.season_number != null ? Number(tf.season_number) : null
const tfNum = tf.num !== undefined ? Number(tf.num) : undefined
if (sn !== null) {
filenameSeasonMap.set(tf.filename, sn)
} else {
const fromResolved = filenameToSeason.get(tf.filename)
if (fromResolved !== undefined) {
filenameSeasonMap.set(tf.filename, fromResolved)
} else if (torrent.season_number !== undefined) {
filenameSeasonMap.set(tf.filename, torrent.season_number)
}
} else if (tfNum !== undefined && epByNum.has(tfNum)) {
filenameSeasonMap.set(tf.filename, epByNum.get(tfNum)!)
} else if (torrent.season_number !== undefined) {
filenameSeasonMap.set(tf.filename, torrent.season_number)
}
}
@@ -316,8 +328,7 @@ async function organizeTorrent(hash: string, name: string, savePath: string) {
const filePath: string[] = tf.path
// Skip les fichiers dans des dossiers bonus/musique/images
const tfMeta = torrentFiles.find((tf: any) => tf.filename === filename)
if (isInExcludedFolder(filePath) && tfMeta?.season_number == null) {
if (isInExcludedFolder(filePath)) {
log(`[organize] skip bonus: ${filename}`)
result.skipped++
continue
@@ -347,9 +358,10 @@ async function organizeTorrent(hash: string, name: string, savePath: string) {
continue
}
const seasonNum = filenameSeasonMap.get(filename) ?? 1
const destDir = path.join(mediaPath, serieTitle, seasonFolder(seasonNum))
const dest = path.join(destDir, filename)
const seasonNum = filenameSeasonMap.get(filename) ?? 1
const destFilename = filenameToOriginal.get(filename) ?? filename
const destDir = path.join(mediaPath, serieTitle, seasonFolder(seasonNum))
const dest = path.join(destDir, destFilename)
if (fs.existsSync(dest)) {
markOrganized(hash, filename)