Add updateExisting option to importers & UI
Introduce an updateExisting flag across importers and the Importer UI to control whether existing items should be updated or only new items imported. Changes: added updateExisting to XBVR, StashAPP, Playnite, and Jellyfin config types; added checkboxes in ImporterView (enabled by default) to toggle the behavior; import logic now skips existing items when updateExisting is false and logs/skips appropriately (XBVR, StashAPP, Playnite, Jellyfin). Also: minor Playnite env parsing tweak for port (undefined when not provided) and small logging/cleanup in the Jellyfin album handling.
This commit is contained in:
+21
-10
@@ -21,6 +21,7 @@ export interface JellyfinImportOptions {
|
||||
importCast?: boolean;
|
||||
limit?: number;
|
||||
libraryMappings?: LibraryMapping[];
|
||||
updateExisting?: boolean; // If true, update existing items; if false, only import new items
|
||||
}
|
||||
|
||||
export interface ImportProgress {
|
||||
@@ -830,6 +831,12 @@ export async function importFromJellyfin(
|
||||
const existing = existingMedia.get(movie.Name);
|
||||
const isUpdate = existing !== undefined;
|
||||
|
||||
// Skip if updateExisting is false and item already exists
|
||||
if (!options.updateExisting && isUpdate) {
|
||||
logCallback(`⊘ Skipped movie: ${movie.Name} (already exists, updateExisting is false)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const mediaData = await convertJellyfinMovieToMedia(movie, config, libraryIdToName, options.libraryMappings);
|
||||
|
||||
@@ -908,6 +915,12 @@ export async function importFromJellyfin(
|
||||
const existing = existingMedia.get(show.Name);
|
||||
const isUpdate = existing !== undefined;
|
||||
|
||||
// Skip if updateExisting is false and item already exists
|
||||
if (!options.updateExisting && isUpdate) {
|
||||
logCallback(`⊘ Skipped series: ${show.Name} (already exists, updateExisting is false)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const mediaData = await convertJellyfinSeriesToMedia(show, config, libraryIdToName, options.libraryMappings);
|
||||
|
||||
@@ -986,6 +999,12 @@ export async function importFromJellyfin(
|
||||
const existing = existingMedia.get(album.Name);
|
||||
const isUpdate = existing !== undefined;
|
||||
|
||||
// Skip if updateExisting is false and item already exists
|
||||
if (!options.updateExisting && isUpdate) {
|
||||
logCallback(`⊘ Skipped album: ${album.Name} (already exists, updateExisting is false)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const mediaData = await convertJellyfinAlbumToMedia(album, config, libraryIdToName, options.libraryMappings);
|
||||
|
||||
@@ -1009,24 +1028,16 @@ export async function importFromJellyfin(
|
||||
body: JSON.stringify(mediaData)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (response.ok) {
|
||||
musicImported++;
|
||||
logCallback(`✓ ${isUpdate ? 'Updated' : 'Imported'} album: ${album.Name}`);
|
||||
} else {
|
||||
const error = await response.text();
|
||||
progress.errors.push(`Failed to ${isUpdate ? 'update' : 'import'} album ${album.Name}: ${error}`);
|
||||
logCallback(`✗ Failed to ${isUpdate ? 'update' : 'import'} album: ${album.Name}`);
|
||||
}
|
||||
} catch (error) {
|
||||
progress.errors.push(`Error processing album ${album.Name}: ${error}`);
|
||||
logCallback(`✗ Error processing album: ${album.Name}`);
|
||||
logCallback(`✗ Error processing album ${album.Name}: ${error}`);
|
||||
}
|
||||
|
||||
progressCallback({
|
||||
musicImported,
|
||||
errors: progress.errors
|
||||
});
|
||||
}
|
||||
|
||||
logCallback(`Processed ${musicImported}/${albums.length} albums`);
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface PlayniteConfig {
|
||||
ip: string;
|
||||
apiToken: string;
|
||||
port?: number;
|
||||
updateExisting?: boolean;
|
||||
}
|
||||
|
||||
export interface ImportProgress {
|
||||
@@ -194,6 +195,15 @@ export async function importFromPlaynite(
|
||||
const existingGame = existingMedia.get(game.name);
|
||||
const isUpdate = existingGame !== undefined;
|
||||
|
||||
// Skip if updateExisting is false and item already exists
|
||||
if (!config.updateExisting && isUpdate) {
|
||||
logCallback(`⊘ Skipped game: ${game.name} (already exists, updateExisting is false)`);
|
||||
progressCallback({
|
||||
current: i + 1
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// Parse release date
|
||||
let year = new Date().getFullYear();
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface StashAPPConfig {
|
||||
url: string;
|
||||
apiKey?: string;
|
||||
blacklist?: ['/AI/', 'temp', 'backup'];
|
||||
updateExisting?: boolean;
|
||||
}
|
||||
|
||||
export interface ImportProgress {
|
||||
@@ -645,11 +646,14 @@ export async function importFromStashAPP(
|
||||
|
||||
// Check for duplicate
|
||||
if (existingTitles.has(scene.title)) {
|
||||
logCallback(`⊘ Skipped duplicate: ${scene.title}`);
|
||||
progressCallback({
|
||||
current: uniquePerformers.length + i + 1
|
||||
});
|
||||
continue;
|
||||
if (!config.updateExisting) {
|
||||
logCallback(`⊘ Skipped duplicate: ${scene.title} (updateExisting is false)`);
|
||||
progressCallback({
|
||||
current: uniquePerformers.length + i + 1
|
||||
});
|
||||
continue;
|
||||
}
|
||||
logCallback(`→ Updating existing: ${scene.title}`);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -6,6 +6,7 @@ import { SOURCE_CATEGORY_MAPPING } from '@/types';
|
||||
export interface XBVRConfig {
|
||||
url: string;
|
||||
apiKey?: string;
|
||||
updateExisting?: boolean;
|
||||
}
|
||||
|
||||
export interface ImportProgress {
|
||||
@@ -258,11 +259,14 @@ export async function importFromXBVR(
|
||||
|
||||
// Check for duplicate
|
||||
if (existingTitles.has(video.title)) {
|
||||
logCallback(`⊘ Skipped duplicate: ${video.title}`);
|
||||
progressCallback({
|
||||
current: uniqueActors.length + i + 1
|
||||
});
|
||||
continue;
|
||||
if (!config.updateExisting) {
|
||||
logCallback(`⊘ Skipped duplicate: ${video.title} (updateExisting is false)`);
|
||||
progressCallback({
|
||||
current: uniqueActors.length + i + 1
|
||||
});
|
||||
continue;
|
||||
}
|
||||
logCallback(`→ Updating existing: ${video.title}`);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user