Compare commits

...
10 Commits
7 changed files with 38 additions and 12 deletions

No files matched your search

+14
View File
@@ -1,5 +1,19 @@
# Changelog
## [3.21.0](https://github.com/Masutayunikon/FanKarr/compare/v3.20.3...v3.21.0) (2026-06-28)
### Features
* **settings:** ajout de englishDirectory qui permet d'avoir Season XX au lieu de Saison X ([6f1e0dc](https://github.com/Masutayunikon/FanKarr/commit/6f1e0dc844e8f97b0966b223d558c09ab498ddc9))
## [3.20.3](https://github.com/Masutayunikon/FanKarr/compare/v3.20.2...v3.20.3) (2026-06-26)
### Bug Fixes
* **serie:** ajout du label de saisons avec les episodes ([63146fd](https://github.com/Masutayunikon/FanKarr/commit/63146fdc27d98acb70cf86c7890ea1236388d717))
## [3.20.2](https://github.com/Masutayunikon/FanKarr/compare/v3.20.1...v3.20.2) (2026-06-26)
+5 -4
View File
@@ -35,12 +35,12 @@ export interface OrgEntry {
type Organized = Record<string, Record<string, OrgEntry>>
// ─── Settings ─────────────────────────────────────────────────
function readSettings(): { mediaPath: string; completePath: string; organizeMode: string; nfoSupport: boolean } {
function readSettings(): { mediaPath: string; completePath: string; organizeMode: string; nfoSupport: boolean, englishDirectory: boolean } {
try {
const p = path.join(DATA_DIR, 'settings.json')
if (!fs.existsSync(p)) return { mediaPath: '', completePath: '', organizeMode: 'hardlink', nfoSupport: false }
if (!fs.existsSync(p)) return { mediaPath: '', completePath: '', organizeMode: 'hardlink', nfoSupport: false, englishDirectory: false }
return JSON.parse(fs.readFileSync(p, 'utf-8'))
} catch { return { mediaPath: '', completePath: '', organizeMode: 'hardlink', nfoSupport: false } }
} catch { return { mediaPath: '', completePath: '', organizeMode: 'hardlink', nfoSupport: false , englishDirectory: false } }
}
// ─── Organized log ────────────────────────────────────────────
@@ -302,7 +302,8 @@ function swapExtension(filename: string, ext: string): string {
}
function seasonFolder(n: number): string {
return n === 0 ? 'Specials' : `Saison ${n}`
const { englishDirectory } = readSettings()
return n === 0 ? 'Specials' : (englishDirectory ? `Season ${String(n).padStart(2, '0')}` : `Saison ${n}`)
}
/**
+2 -1
View File
@@ -10,7 +10,7 @@ router.get('/settings', requireAuth, (_req, res) => {
})
router.post('/settings', requireAuth, (req, res) => {
const { mediaPath, completePath, organizeMode, category, nfoSupport, autoImport, devMode, deleteTorrentOnMove, autoUnimportMissing, requestAutoDownloadUsers } = req.body
const { mediaPath, completePath, organizeMode, category, nfoSupport, autoImport, devMode, deleteTorrentOnMove, autoUnimportMissing, requestAutoDownloadUsers, englishDirectory } = req.body
const patch: Record<string, any> = {}
if (mediaPath !== undefined) patch.mediaPath = mediaPath
if (completePath !== undefined) patch.completePath = completePath
@@ -22,6 +22,7 @@ router.post('/settings', requireAuth, (req, res) => {
if (deleteTorrentOnMove !== undefined) patch.deleteTorrentOnMove = deleteTorrentOnMove
if (autoUnimportMissing !== undefined) patch.autoUnimportMissing = autoUnimportMissing
if (requestAutoDownloadUsers !== undefined) patch.requestAutoDownloadUsers = requestAutoDownloadUsers
if (englishDirectory !== undefined) patch.englishDirectory = englishDirectory
const updated = writeSettings(patch)
logger.info('api', 'Paramètres mis à jour')
res.json(updated)
+2
View File
@@ -16,6 +16,7 @@ export interface Settings {
requestAutoDownloadUsers: 'all' | string[] // IDs users autorisés au dl auto sur approbation ; [] = désactivé
jellyfinUrl : string // URL du serveur Jellyfin (ex: http://jellyfin:8096)
jellyfinAdminToken : string // Token admin Jellyfin pour la sync
englishDirectory : boolean // Si true, les dossiers de séries sont en anglais (ex: "Season 1" au lieu de "Saison 1")
}
const defaults: Settings = {
@@ -30,6 +31,7 @@ const defaults: Settings = {
requestAutoDownloadUsers: [],
jellyfinUrl : '',
jellyfinAdminToken : '',
englishDirectory : false,
}
export function readSettings(): Settings {
+8 -6
View File
@@ -618,19 +618,21 @@ function _parseEpChap(plot: string | null | undefined): {
const seasonMatch = text.match(/saison\s+(\d+)/i)
const season = epMatch?.[3] ?? seasonMatch?.[1] ?? null
const chapMatch = text.match(
/chapitres?\s+(\d+)(?:\s+[àa]\s+(\d+))?/i
)
const episodes = epMatch
? (epMatch[2] ? `Ép. ${epMatch[1]}–${epMatch[2]}` : `Ép. ${epMatch[1]}`)
? `${season ? `S${season} · ` : ''}${
epMatch[2]
? `Ép. ${epMatch[1]}–${epMatch[2]}`
: `Ép. ${epMatch[1]}`
}`
: null
const season = epMatch?.[3]
? Number(epMatch[3])
: seasonMatch
? Number(seasonMatch[1])
: null
const chapters = chapMatch
? (chapMatch[2] ? `Ch. ${chapMatch[1]}–${chapMatch[2]}` : `Ch. ${chapMatch[1]}`)
@@ -103,6 +103,11 @@
label="Désimporter si fichier manquant"
description="Si un fichier importé n'est plus trouvé sur le disque lors du scan, il est automatiquement retiré de la bibliothèque."
/>
<SettingsToggle
v-model="form.englishDirectory"
label="Utilise 'Season' au lieu de 'Saison' dans les dossiers"
description="Si activé, les dossiers de saisons seront nommés 'Season 01' au lieu de 'Saison 01'."
/>
</div>
<!-- Plex -->
@@ -215,6 +220,7 @@ const form = ref({
autoImport : true,
deleteTorrentOnMove : false,
autoUnimportMissing : false,
englishDirectory : false,
})
const picker = ref<{ open: boolean; field: 'completePath' | 'mediaPath'; currentPath: string }>({
+1 -1
View File
@@ -1 +1 @@
3.20.2
3.21.0