Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3eb64b175d | ||
|
|
25a8adc91d | ||
|
|
d533751ffb | ||
|
|
6f1e0dc844 | ||
|
|
894a7ed2b1 | ||
|
|
c87b7a4c7f | ||
|
|
a000e349c9 | ||
|
|
f23e3c04ec | ||
|
|
63146fdc27 | ||
|
|
7795598346 |
No files matched your search
@@ -1,5 +1,19 @@
|
|||||||
# Changelog
|
# 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)
|
## [3.20.2](https://github.com/Masutayunikon/FanKarr/compare/v3.20.1...v3.20.2) (2026-06-26)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ export interface OrgEntry {
|
|||||||
type Organized = Record<string, Record<string, OrgEntry>>
|
type Organized = Record<string, Record<string, OrgEntry>>
|
||||||
|
|
||||||
// ─── Settings ─────────────────────────────────────────────────
|
// ─── Settings ─────────────────────────────────────────────────
|
||||||
function readSettings(): { mediaPath: string; completePath: string; organizeMode: string; nfoSupport: boolean } {
|
function readSettings(): { mediaPath: string; completePath: string; organizeMode: string; nfoSupport: boolean, englishDirectory: boolean } {
|
||||||
try {
|
try {
|
||||||
const p = path.join(DATA_DIR, 'settings.json')
|
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'))
|
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 ────────────────────────────────────────────
|
// ─── Organized log ────────────────────────────────────────────
|
||||||
@@ -302,7 +302,8 @@ function swapExtension(filename: string, ext: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function seasonFolder(n: number): 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}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ router.get('/settings', requireAuth, (_req, res) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
router.post('/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> = {}
|
const patch: Record<string, any> = {}
|
||||||
if (mediaPath !== undefined) patch.mediaPath = mediaPath
|
if (mediaPath !== undefined) patch.mediaPath = mediaPath
|
||||||
if (completePath !== undefined) patch.completePath = completePath
|
if (completePath !== undefined) patch.completePath = completePath
|
||||||
@@ -22,6 +22,7 @@ router.post('/settings', requireAuth, (req, res) => {
|
|||||||
if (deleteTorrentOnMove !== undefined) patch.deleteTorrentOnMove = deleteTorrentOnMove
|
if (deleteTorrentOnMove !== undefined) patch.deleteTorrentOnMove = deleteTorrentOnMove
|
||||||
if (autoUnimportMissing !== undefined) patch.autoUnimportMissing = autoUnimportMissing
|
if (autoUnimportMissing !== undefined) patch.autoUnimportMissing = autoUnimportMissing
|
||||||
if (requestAutoDownloadUsers !== undefined) patch.requestAutoDownloadUsers = requestAutoDownloadUsers
|
if (requestAutoDownloadUsers !== undefined) patch.requestAutoDownloadUsers = requestAutoDownloadUsers
|
||||||
|
if (englishDirectory !== undefined) patch.englishDirectory = englishDirectory
|
||||||
const updated = writeSettings(patch)
|
const updated = writeSettings(patch)
|
||||||
logger.info('api', 'Paramètres mis à jour')
|
logger.info('api', 'Paramètres mis à jour')
|
||||||
res.json(updated)
|
res.json(updated)
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export interface Settings {
|
|||||||
requestAutoDownloadUsers: 'all' | string[] // IDs users autorisés au dl auto sur approbation ; [] = désactivé
|
requestAutoDownloadUsers: 'all' | string[] // IDs users autorisés au dl auto sur approbation ; [] = désactivé
|
||||||
jellyfinUrl : string // URL du serveur Jellyfin (ex: http://jellyfin:8096)
|
jellyfinUrl : string // URL du serveur Jellyfin (ex: http://jellyfin:8096)
|
||||||
jellyfinAdminToken : string // Token admin Jellyfin pour la sync
|
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 = {
|
const defaults: Settings = {
|
||||||
@@ -30,6 +31,7 @@ const defaults: Settings = {
|
|||||||
requestAutoDownloadUsers: [],
|
requestAutoDownloadUsers: [],
|
||||||
jellyfinUrl : '',
|
jellyfinUrl : '',
|
||||||
jellyfinAdminToken : '',
|
jellyfinAdminToken : '',
|
||||||
|
englishDirectory : false,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function readSettings(): Settings {
|
export function readSettings(): Settings {
|
||||||
|
|||||||
@@ -618,19 +618,21 @@ function _parseEpChap(plot: string | null | undefined): {
|
|||||||
|
|
||||||
const seasonMatch = text.match(/saison\s+(\d+)/i)
|
const seasonMatch = text.match(/saison\s+(\d+)/i)
|
||||||
|
|
||||||
|
const season = epMatch?.[3] ?? seasonMatch?.[1] ?? null
|
||||||
|
|
||||||
const chapMatch = text.match(
|
const chapMatch = text.match(
|
||||||
/chapitres?\s+(\d+)(?:\s+[àa]\s+(\d+))?/i
|
/chapitres?\s+(\d+)(?:\s+[àa]\s+(\d+))?/i
|
||||||
)
|
)
|
||||||
|
|
||||||
const episodes = epMatch
|
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
|
: null
|
||||||
|
|
||||||
const season = epMatch?.[3]
|
|
||||||
? Number(epMatch[3])
|
|
||||||
: seasonMatch
|
|
||||||
? Number(seasonMatch[1])
|
|
||||||
: null
|
|
||||||
|
|
||||||
const chapters = chapMatch
|
const chapters = chapMatch
|
||||||
? (chapMatch[2] ? `Ch. ${chapMatch[1]}–${chapMatch[2]}` : `Ch. ${chapMatch[1]}`)
|
? (chapMatch[2] ? `Ch. ${chapMatch[1]}–${chapMatch[2]}` : `Ch. ${chapMatch[1]}`)
|
||||||
|
|||||||
@@ -103,6 +103,11 @@
|
|||||||
label="Désimporter si fichier manquant"
|
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."
|
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>
|
</div>
|
||||||
|
|
||||||
<!-- Plex -->
|
<!-- Plex -->
|
||||||
@@ -215,6 +220,7 @@ const form = ref({
|
|||||||
autoImport : true,
|
autoImport : true,
|
||||||
deleteTorrentOnMove : false,
|
deleteTorrentOnMove : false,
|
||||||
autoUnimportMissing : false,
|
autoUnimportMissing : false,
|
||||||
|
englishDirectory : false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const picker = ref<{ open: boolean; field: 'completePath' | 'mediaPath'; currentPath: string }>({
|
const picker = ref<{ open: boolean; field: 'completePath' | 'mediaPath'; currentPath: string }>({
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
3.20.2
|
3.21.0
|
||||||
Reference in new issue
Block a user