0.9.1-1 Metadata Assign
This commit is contained in:
4
backend/package-lock.json
generated
4
backend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "ripster-backend",
|
"name": "ripster-backend",
|
||||||
"version": "0.9.1",
|
"version": "0.9.1-1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ripster-backend",
|
"name": "ripster-backend",
|
||||||
"version": "0.9.1",
|
"version": "0.9.1-1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.4.7",
|
"dotenv": "^16.4.7",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ripster-backend",
|
"name": "ripster-backend",
|
||||||
"version": "0.9.1",
|
"version": "0.9.1-1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "commonjs",
|
"type": "commonjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -91,6 +91,12 @@ router.post(
|
|||||||
});
|
});
|
||||||
|
|
||||||
const job = await historyService.assignOmdbMetadata(id, payload);
|
const job = await historyService.assignOmdbMetadata(id, payload);
|
||||||
|
|
||||||
|
// Rename raw/output folders to reflect new metadata (best-effort, non-blocking)
|
||||||
|
pipelineService.renameJobFolders(id).catch((err) => {
|
||||||
|
logger.warn('post:job:omdb:assign:rename-failed', { id, error: err.message });
|
||||||
|
});
|
||||||
|
|
||||||
res.json({ job });
|
res.json({ job });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -110,6 +116,12 @@ router.post(
|
|||||||
});
|
});
|
||||||
|
|
||||||
const job = await historyService.assignCdMetadata(id, payload);
|
const job = await historyService.assignCdMetadata(id, payload);
|
||||||
|
|
||||||
|
// Rename raw/output folders to reflect new metadata (best-effort, non-blocking)
|
||||||
|
pipelineService.renameJobFolders(id).catch((err) => {
|
||||||
|
logger.warn('post:job:cd:assign:rename-failed', { id, error: err.message });
|
||||||
|
});
|
||||||
|
|
||||||
res.json({ job });
|
res.json({ job });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1662,11 +1662,10 @@ class HistoryService {
|
|||||||
const imdbIdInput = String(payload.imdbId || '').trim().toLowerCase();
|
const imdbIdInput = String(payload.imdbId || '').trim().toLowerCase();
|
||||||
let omdb = null;
|
let omdb = null;
|
||||||
if (imdbIdInput) {
|
if (imdbIdInput) {
|
||||||
omdb = await omdbService.fetchByImdbId(imdbIdInput);
|
try {
|
||||||
if (!omdb) {
|
omdb = await omdbService.fetchByImdbId(imdbIdInput);
|
||||||
const error = new Error(`OMDb Eintrag für ${imdbIdInput} nicht gefunden.`);
|
} catch (omdbErr) {
|
||||||
error.statusCode = 404;
|
logger.warn('assignOmdbMetadata:fetch-failed', { jobId, imdbId: imdbIdInput, message: omdbErr.message });
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1685,7 +1684,7 @@ class HistoryService {
|
|||||||
const year = Number.isFinite(Number(omdb?.year))
|
const year = Number.isFinite(Number(omdb?.year))
|
||||||
? Number(omdb.year)
|
? Number(omdb.year)
|
||||||
: (manualYear !== null ? manualYear : (job.year ?? null));
|
: (manualYear !== null ? manualYear : (job.year ?? null));
|
||||||
const imdbId = omdb?.imdbId || (imdbIdInput || job.imdb_id || null);
|
const imdbId = omdb?.imdbId || imdbIdInput || job.imdb_id || null;
|
||||||
const posterUrl = omdb?.poster || manualPoster || job.poster_url || null;
|
const posterUrl = omdb?.poster || manualPoster || job.poster_url || null;
|
||||||
const selectedFromOmdb = omdb ? 1 : Number(payload.fromOmdb ? 1 : 0);
|
const selectedFromOmdb = omdb ? 1 : Number(payload.fromOmdb ? 1 : 0);
|
||||||
|
|
||||||
|
|||||||
@@ -10766,6 +10766,91 @@ class PipelineService extends EventEmitter {
|
|||||||
return historyService.getJobById(jobId);
|
return historyService.getJobById(jobId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async renameJobFolders(jobId) {
|
||||||
|
const job = await historyService.getJobById(jobId);
|
||||||
|
if (!job) {
|
||||||
|
return { renamed: [] };
|
||||||
|
}
|
||||||
|
|
||||||
|
const renamed = [];
|
||||||
|
const mediaProfile = this.resolveMediaProfileForJob(job);
|
||||||
|
const isCd = mediaProfile === 'cd';
|
||||||
|
const settings = await settingsService.getEffectiveSettingsMap(mediaProfile);
|
||||||
|
|
||||||
|
// Rename raw folder
|
||||||
|
const currentRawPath = job.raw_path ? path.resolve(job.raw_path) : null;
|
||||||
|
if (currentRawPath && fs.existsSync(currentRawPath)) {
|
||||||
|
const rawBaseDir = path.dirname(currentRawPath);
|
||||||
|
const newMetadataBase = buildRawMetadataBase({
|
||||||
|
title: job.title || job.detected_title || null,
|
||||||
|
year: job.year || null
|
||||||
|
}, jobId);
|
||||||
|
const currentState = resolveRawFolderStateFromPath(currentRawPath);
|
||||||
|
const newRawDirName = buildRawDirName(newMetadataBase, jobId, { state: currentState });
|
||||||
|
const newRawPath = path.join(rawBaseDir, newRawDirName);
|
||||||
|
|
||||||
|
if (normalizeComparablePath(currentRawPath) !== normalizeComparablePath(newRawPath) && !fs.existsSync(newRawPath)) {
|
||||||
|
try {
|
||||||
|
fs.renameSync(currentRawPath, newRawPath);
|
||||||
|
await historyService.updateJob(jobId, { raw_path: newRawPath });
|
||||||
|
renamed.push({ type: 'raw', from: currentRawPath, to: newRawPath });
|
||||||
|
logger.info('rename-job-folders:raw', { jobId, from: currentRawPath, to: newRawPath });
|
||||||
|
} catch (err) {
|
||||||
|
logger.warn('rename-job-folders:raw-failed', { jobId, error: err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename output file (film) or output directory (CD)
|
||||||
|
const currentOutputPath = job.output_path ? path.resolve(job.output_path) : null;
|
||||||
|
if (currentOutputPath && fs.existsSync(currentOutputPath)) {
|
||||||
|
try {
|
||||||
|
if (isCd) {
|
||||||
|
const cdInfo = this.safeParseJson(job.makemkv_info_json) || {};
|
||||||
|
const selectedMeta = cdInfo.selectedMetadata && typeof cdInfo.selectedMetadata === 'object'
|
||||||
|
? cdInfo.selectedMetadata
|
||||||
|
: {};
|
||||||
|
const cdMeta = {
|
||||||
|
artist: String(selectedMeta.artist || '').trim() || String(job.title || '').trim() || null,
|
||||||
|
album: String(job.title || selectedMeta.title || '').trim() || null,
|
||||||
|
year: job.year || selectedMeta.year || null
|
||||||
|
};
|
||||||
|
const cdOutputBaseDir = String(settings.movie_dir || '').trim();
|
||||||
|
const cdOutputTemplate = String(settings.cd_output_template || cdRipService.DEFAULT_CD_OUTPUT_TEMPLATE).trim();
|
||||||
|
if (cdOutputBaseDir) {
|
||||||
|
const newCdOutputDir = cdRipService.buildOutputDir(cdMeta, cdOutputBaseDir, cdOutputTemplate);
|
||||||
|
if (normalizeComparablePath(currentOutputPath) !== normalizeComparablePath(newCdOutputDir) && !fs.existsSync(newCdOutputDir)) {
|
||||||
|
fs.mkdirSync(path.dirname(newCdOutputDir), { recursive: true });
|
||||||
|
fs.renameSync(currentOutputPath, newCdOutputDir);
|
||||||
|
await historyService.updateJob(jobId, { output_path: newCdOutputDir });
|
||||||
|
renamed.push({ type: 'output', from: currentOutputPath, to: newCdOutputDir });
|
||||||
|
logger.info('rename-job-folders:cd-output', { jobId, from: currentOutputPath, to: newCdOutputDir });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const newOutputPath = buildFinalOutputPathFromJob(settings, job, jobId);
|
||||||
|
if (normalizeComparablePath(currentOutputPath) !== normalizeComparablePath(newOutputPath) && !fs.existsSync(newOutputPath)) {
|
||||||
|
fs.mkdirSync(path.dirname(newOutputPath), { recursive: true });
|
||||||
|
moveFileWithFallback(currentOutputPath, newOutputPath);
|
||||||
|
try {
|
||||||
|
const oldParentDir = path.dirname(currentOutputPath);
|
||||||
|
if (fs.readdirSync(oldParentDir).length === 0) {
|
||||||
|
fs.rmdirSync(oldParentDir);
|
||||||
|
}
|
||||||
|
} catch (_ignoreErr) {}
|
||||||
|
await historyService.updateJob(jobId, { output_path: newOutputPath });
|
||||||
|
renamed.push({ type: 'output', from: currentOutputPath, to: newOutputPath });
|
||||||
|
logger.info('rename-job-folders:film-output', { jobId, from: currentOutputPath, to: newOutputPath });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
logger.warn('rename-job-folders:output-failed', { jobId, isCd, error: err.message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { renamed };
|
||||||
|
}
|
||||||
|
|
||||||
async startCdRip(jobId, ripConfig) {
|
async startCdRip(jobId, ripConfig) {
|
||||||
this.ensureNotBusy('startCdRip', jobId);
|
this.ensureNotBusy('startCdRip', jobId);
|
||||||
this.cancelRequestedByJob.delete(Number(jobId));
|
this.cancelRequestedByJob.delete(Number(jobId));
|
||||||
|
|||||||
4
frontend/package-lock.json
generated
4
frontend/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "ripster-frontend",
|
"name": "ripster-frontend",
|
||||||
"version": "0.9.1",
|
"version": "0.9.1-1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ripster-frontend",
|
"name": "ripster-frontend",
|
||||||
"version": "0.9.1",
|
"version": "0.9.1-1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"primeicons": "^7.0.0",
|
"primeicons": "^7.0.0",
|
||||||
"primereact": "^10.9.2",
|
"primereact": "^10.9.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ripster-frontend",
|
"name": "ripster-frontend",
|
||||||
"version": "0.9.1",
|
"version": "0.9.1-1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "ripster",
|
"name": "ripster",
|
||||||
"version": "0.9.1",
|
"version": "0.9.1-1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ripster",
|
"name": "ripster",
|
||||||
"version": "0.9.1",
|
"version": "0.9.1-1",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "^9.1.2"
|
"concurrently": "^9.1.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "ripster",
|
"name": "ripster",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.9.1",
|
"version": "0.9.1-1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "concurrently \"npm run dev --prefix backend\" \"npm run dev --prefix frontend\"",
|
"dev": "concurrently \"npm run dev --prefix backend\" \"npm run dev --prefix frontend\"",
|
||||||
"dev:backend": "npm run dev --prefix backend",
|
"dev:backend": "npm run dev --prefix backend",
|
||||||
|
|||||||
Reference in New Issue
Block a user