Bugfix and Docs
This commit is contained in:
@@ -21,6 +21,8 @@ function parseJsonSafe(raw, fallback = null) {
|
||||
const PROCESS_LOG_TAIL_MAX_BYTES = 1024 * 1024;
|
||||
const processLogStreams = new Map();
|
||||
const PROFILE_PATH_SUFFIXES = ['bluray', 'dvd', 'other'];
|
||||
const RAW_INCOMPLETE_PREFIX = 'Incomplete_';
|
||||
const RAW_RIP_COMPLETE_PREFIX = 'Rip_Complete_';
|
||||
|
||||
function inspectDirectory(dirPath) {
|
||||
if (!dirPath) {
|
||||
@@ -430,9 +432,29 @@ function normalizeComparablePath(inputPath) {
|
||||
return resolveSafe(String(inputPath || '')).replace(/[\\/]+$/, '');
|
||||
}
|
||||
|
||||
function stripRawFolderStatePrefix(folderName) {
|
||||
const rawName = String(folderName || '').trim();
|
||||
if (!rawName) {
|
||||
return '';
|
||||
}
|
||||
return rawName
|
||||
.replace(new RegExp(`^${RAW_INCOMPLETE_PREFIX}`, 'i'), '')
|
||||
.replace(new RegExp(`^${RAW_RIP_COMPLETE_PREFIX}`, 'i'), '')
|
||||
.trim();
|
||||
}
|
||||
|
||||
function applyRawFolderPrefix(folderName, prefix = '') {
|
||||
const normalized = stripRawFolderStatePrefix(folderName);
|
||||
if (!normalized) {
|
||||
return normalized;
|
||||
}
|
||||
const safePrefix = String(prefix || '').trim();
|
||||
return safePrefix ? `${safePrefix}${normalized}` : normalized;
|
||||
}
|
||||
|
||||
function parseRawFolderMetadata(folderName) {
|
||||
const rawName = String(folderName || '').trim();
|
||||
const normalizedRawName = rawName.replace(/^Incomplete_/i, '').trim();
|
||||
const normalizedRawName = stripRawFolderStatePrefix(rawName);
|
||||
const folderJobIdMatch = normalizedRawName.match(/-\s*RAW\s*-\s*job-(\d+)\s*$/i);
|
||||
const folderJobId = folderJobIdMatch ? Number(folderJobIdMatch[1]) : null;
|
||||
let working = normalizedRawName.replace(/\s*-\s*RAW\s*-\s*job-\d+\s*$/i, '').trim();
|
||||
@@ -1053,6 +1075,7 @@ class HistoryService {
|
||||
detectedTitle: effectiveTitle
|
||||
});
|
||||
|
||||
const renameSteps = [];
|
||||
let finalRawPath = absRawPath;
|
||||
const renamedRawPath = buildRawPathForJobId(absRawPath, created.id);
|
||||
const shouldRenameRawFolder = normalizeComparablePath(renamedRawPath) !== absRawPath;
|
||||
@@ -1067,6 +1090,7 @@ class HistoryService {
|
||||
try {
|
||||
fs.renameSync(absRawPath, renamedRawPath);
|
||||
finalRawPath = normalizeComparablePath(renamedRawPath);
|
||||
renameSteps.push({ from: absRawPath, to: finalRawPath });
|
||||
} catch (error) {
|
||||
await db.run('DELETE FROM jobs WHERE id = ?', [created.id]);
|
||||
const wrapped = new Error(`RAW-Ordner konnte nicht auf neue Job-ID umbenannt werden: ${error.message}`);
|
||||
@@ -1075,6 +1099,30 @@ class HistoryService {
|
||||
}
|
||||
}
|
||||
|
||||
const ripCompleteFolderName = applyRawFolderPrefix(path.basename(finalRawPath), RAW_RIP_COMPLETE_PREFIX);
|
||||
const ripCompleteRawPath = path.join(path.dirname(finalRawPath), ripCompleteFolderName);
|
||||
const shouldMarkRipComplete = normalizeComparablePath(ripCompleteRawPath) !== normalizeComparablePath(finalRawPath);
|
||||
if (shouldMarkRipComplete) {
|
||||
if (fs.existsSync(ripCompleteRawPath)) {
|
||||
await db.run('DELETE FROM jobs WHERE id = ?', [created.id]);
|
||||
const error = new Error(`RAW-Ordner für Rip_Complete-Zustand existiert bereits: ${ripCompleteRawPath}`);
|
||||
error.statusCode = 409;
|
||||
throw error;
|
||||
}
|
||||
|
||||
try {
|
||||
const previousRawPath = finalRawPath;
|
||||
fs.renameSync(previousRawPath, ripCompleteRawPath);
|
||||
finalRawPath = normalizeComparablePath(ripCompleteRawPath);
|
||||
renameSteps.push({ from: previousRawPath, to: finalRawPath });
|
||||
} catch (error) {
|
||||
await db.run('DELETE FROM jobs WHERE id = ?', [created.id]);
|
||||
const wrapped = new Error(`RAW-Ordner konnte nicht als Rip_Complete markiert werden: ${error.message}`);
|
||||
wrapped.statusCode = 500;
|
||||
throw wrapped;
|
||||
}
|
||||
}
|
||||
|
||||
await this.updateJob(created.id, {
|
||||
status: 'FINISHED',
|
||||
last_state: 'FINISHED',
|
||||
@@ -1105,8 +1153,8 @@ class HistoryService {
|
||||
await this.appendLog(
|
||||
created.id,
|
||||
'SYSTEM',
|
||||
shouldRenameRawFolder
|
||||
? `Historieneintrag aus RAW erstellt. Ordner umbenannt: ${absRawPath} -> ${finalRawPath}`
|
||||
renameSteps.length > 0
|
||||
? `Historieneintrag aus RAW erstellt. Ordner umbenannt: ${renameSteps.map((step) => `${step.from} -> ${step.to}`).join(' | ')}`
|
||||
: `Historieneintrag aus bestehendem RAW-Ordner erstellt: ${finalRawPath}`
|
||||
);
|
||||
if (metadata.imdbId) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -716,7 +716,16 @@ class SettingsService {
|
||||
options?.mediaProfile || deviceInfo?.mediaProfile || null
|
||||
);
|
||||
const cmd = map.makemkv_command;
|
||||
const args = ['-r', 'info', this.resolveSourceArg(map, deviceInfo), ...splitArgs(map.makemkv_analyze_extra_args)];
|
||||
const extraArgs = splitArgs(map.makemkv_analyze_extra_args);
|
||||
const hasExplicitMinLength = extraArgs.some((arg) => /^--minlength(?:=|$)/i.test(String(arg || '').trim()));
|
||||
const minLengthMinutes = Number(map.makemkv_min_length_minutes || 0);
|
||||
const minLengthSeconds = Number.isFinite(minLengthMinutes) && minLengthMinutes > 0
|
||||
? Math.round(minLengthMinutes * 60)
|
||||
: 0;
|
||||
const minLengthArgs = (!hasExplicitMinLength && minLengthSeconds > 0)
|
||||
? [`--minlength=${minLengthSeconds}`]
|
||||
: [];
|
||||
const args = ['-r', ...minLengthArgs, ...extraArgs, 'info', this.resolveSourceArg(map, deviceInfo)];
|
||||
logger.debug('cli:makemkv:analyze', { cmd, args, deviceInfo });
|
||||
return { cmd, args };
|
||||
}
|
||||
@@ -726,7 +735,16 @@ class SettingsService {
|
||||
const map = this.resolveEffectiveToolSettings(rawMap, options?.mediaProfile || null);
|
||||
const cmd = map.makemkv_command;
|
||||
const sourceArg = `file:${sourcePath}`;
|
||||
const args = ['-r', 'info', sourceArg, ...splitArgs(map.makemkv_analyze_extra_args)];
|
||||
const extraArgs = splitArgs(map.makemkv_analyze_extra_args);
|
||||
const hasExplicitMinLength = extraArgs.some((arg) => /^--minlength(?:=|$)/i.test(String(arg || '').trim()));
|
||||
const minLengthMinutes = Number(map.makemkv_min_length_minutes || 0);
|
||||
const minLengthSeconds = Number.isFinite(minLengthMinutes) && minLengthMinutes > 0
|
||||
? Math.round(minLengthMinutes * 60)
|
||||
: 0;
|
||||
const minLengthArgs = (!hasExplicitMinLength && minLengthSeconds > 0)
|
||||
? [`--minlength=${minLengthSeconds}`]
|
||||
: [];
|
||||
const args = ['-r', ...minLengthArgs, ...extraArgs, 'info', sourceArg];
|
||||
const titleIdRaw = Number(options?.titleId);
|
||||
// "makemkvcon info" supports only <source>; title filtering is done in app parser.
|
||||
logger.debug('cli:makemkv:analyze:path', {
|
||||
|
||||
Reference in New Issue
Block a user