Fixed actor merge failing if scene has multiple source actors assigned, merging stashed actors.
This commit is contained in:
@@ -598,9 +598,11 @@ export async function mergeActors(targetActorId, sourceActorIds, reqUser) {
|
|||||||
|
|
||||||
const trx = await knex.transaction();
|
const trx = await knex.transaction();
|
||||||
|
|
||||||
let mergedProfiles;
|
let mergedProfiles = [];
|
||||||
let mergedSceneActors;
|
let mergedSceneActors = [];
|
||||||
let existingSceneActors;
|
let existingSceneActors = [];
|
||||||
|
let duplicateSourceActors = [];
|
||||||
|
let mergedActorStashes = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [existingProfiles] = await Promise.all([
|
const [existingProfiles] = await Promise.all([
|
||||||
@@ -614,36 +616,83 @@ export async function mergeActors(targetActorId, sourceActorIds, reqUser) {
|
|||||||
trx('actors_avatars')
|
trx('actors_avatars')
|
||||||
.update('actor_id', targetActorId)
|
.update('actor_id', targetActorId)
|
||||||
.whereIn('actor_id', sourceActorIds),
|
.whereIn('actor_id', sourceActorIds),
|
||||||
trx('stashes_actors')
|
|
||||||
.update('actor_id', targetActorId)
|
|
||||||
.whereIn('actor_id', sourceActorIds)
|
|
||||||
.returning('id'),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
existingSceneActors = await trx('releases_actors')
|
// assign source actor profiles to target actor, unless a profile for that entity is already present
|
||||||
.where('actor_id', targetActorId);
|
|
||||||
|
|
||||||
mergedProfiles = await trx('actors_profiles')
|
mergedProfiles = await trx('actors_profiles')
|
||||||
.update('actor_id', targetActorId)
|
.update('actor_id', targetActorId)
|
||||||
.whereIn('actor_id', sourceActorIds)
|
.whereIn('actor_id', sourceActorIds)
|
||||||
.whereNotIn('entity_id', existingProfiles.map((profile) => profile.entity_id))
|
.whereNotIn('entity_id', existingProfiles.map((profile) => profile.entity_id))
|
||||||
.returning('id');
|
.returning('id');
|
||||||
|
|
||||||
|
// find releases that have more than one source actor assigned
|
||||||
|
duplicateSourceActors = await trx('releases_actors')
|
||||||
|
.select('release_id', knex.raw('array_agg(actor_id) as actor_ids'))
|
||||||
|
.whereIn('actor_id', sourceActorIds)
|
||||||
|
.groupBy('release_id')
|
||||||
|
.having(trx.raw('COUNT(DISTINCT actor_id) > 1'));
|
||||||
|
|
||||||
|
if (duplicateSourceActors.length > 0) {
|
||||||
|
// some scenes have multiple source actors assigned, which will cause a conflict after merging; we will need to remove all but one
|
||||||
|
await trx('releases_actors')
|
||||||
|
.whereIn('release_id', duplicateSourceActors.map((sceneActor) => sceneActor.release_id))
|
||||||
|
.whereIn('actor_id', duplicateSourceActors.flatMap((sceneActor) => sceneActor.actor_ids.slice(1)))
|
||||||
|
.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// find scenes that already have target actor assigned
|
||||||
|
existingSceneActors = await trx('releases_actors')
|
||||||
|
.where('actor_id', targetActorId);
|
||||||
|
|
||||||
|
// delete release source actors for scenes that already have the target actor assigned
|
||||||
|
await trx('releases_actors')
|
||||||
|
.whereIn('release_id', existingSceneActors.map((sceneActor) => sceneActor.release_id))
|
||||||
|
.whereIn('actor_id', sourceActorIds)
|
||||||
|
.delete();
|
||||||
|
|
||||||
|
// alias release source actors to target actors
|
||||||
mergedSceneActors = await trx('releases_actors')
|
mergedSceneActors = await trx('releases_actors')
|
||||||
.update({
|
.update({
|
||||||
actor_id: targetActorId,
|
actor_id: targetActorId,
|
||||||
alias_id: knex.raw('actor_id'),
|
alias_id: knex.raw('actor_id'),
|
||||||
})
|
})
|
||||||
.whereIn('actor_id', sourceActorIds)
|
.whereIn('actor_id', sourceActorIds)
|
||||||
.whereNotIn('release_id', existingSceneActors.map((sceneActor) => sceneActor.release_id)) // can't update entry if target actor already exists alongside source actor
|
|
||||||
.returning('release_id');
|
.returning('release_id');
|
||||||
|
|
||||||
// delete aliased actors for scenes that already had both source/aliased and target actor assigned
|
const [targetActorStashes, sourceActorStashes] = await Promise.all([
|
||||||
const releases = await trx('releases_actors')
|
trx('stashes_actors')
|
||||||
.whereIn('release_id', existingSceneActors.map((sceneActor) => sceneActor.release_id))
|
.where('actor_id', targetActorId),
|
||||||
|
trx('stashes_actors')
|
||||||
|
.whereIn('actor_id', sourceActorIds),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// remove source actors from stashes that already contain target actor
|
||||||
|
await trx('stashes_actors')
|
||||||
|
.whereIn('stash_id', targetActorStashes.map((stash) => stash.stash_id))
|
||||||
.whereIn('actor_id', sourceActorIds)
|
.whereIn('actor_id', sourceActorIds)
|
||||||
.delete();
|
.delete();
|
||||||
|
|
||||||
|
// find stashes that have more than one source actor assigned
|
||||||
|
const duplicateStashActors = await trx('stashes_actors')
|
||||||
|
.select('stash_id', knex.raw('array_agg(actor_id order by created_at) as actor_ids'))
|
||||||
|
.whereIn('actor_id', sourceActorStashes.map((actorStash) => actorStash.actor_id))
|
||||||
|
.groupBy('stash_id')
|
||||||
|
.having(trx.raw('COUNT(DISTINCT actor_id) > 1'));
|
||||||
|
|
||||||
|
if (duplicateStashActors.length > 0) {
|
||||||
|
// some stashes have multiple source actors assigned, which will cause a conflict after merging; we will need to remove all but one
|
||||||
|
await trx('stashes_actors')
|
||||||
|
.whereIn('stash_id', duplicateStashActors.map((actorStash) => actorStash.stash_id))
|
||||||
|
.whereIn('actor_id', duplicateStashActors.flatMap((actorStash) => actorStash.actor_ids.slice(1)))
|
||||||
|
.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we update an existing entry instead of creating a new one, so the original stash date is preserved
|
||||||
|
mergedActorStashes = await trx('stashes_actors')
|
||||||
|
.update('actor_id', targetActorId)
|
||||||
|
.whereIn('actor_id', sourceActorIds)
|
||||||
|
.returning('stash_id');
|
||||||
|
|
||||||
await trx.commit();
|
await trx.commit();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await trx.rollback();
|
await trx.rollback();
|
||||||
@@ -660,7 +709,11 @@ export async function mergeActors(targetActorId, sourceActorIds, reqUser) {
|
|||||||
}, { refreshView: false });
|
}, { refreshView: false });
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
syncScenes([...mergedSceneActors.map((sceneActor) => sceneActor.release_id), ...existingSceneActors.map((sceneActor) => sceneActor.release_id)]),
|
syncScenes([
|
||||||
|
...mergedSceneActors.map((sceneActor) => sceneActor.release_id),
|
||||||
|
...existingSceneActors.map((sceneActor) => sceneActor.release_id),
|
||||||
|
...duplicateSourceActors.map((sceneActor) => sceneActor.release_id),
|
||||||
|
]),
|
||||||
syncActors([targetActorId, ...sourceActorIds]),
|
syncActors([targetActorId, ...sourceActorIds]),
|
||||||
syncStashes('actor', [targetActorId, ...sourceActorIds]),
|
syncStashes('actor', [targetActorId, ...sourceActorIds]),
|
||||||
]);
|
]);
|
||||||
@@ -668,6 +721,7 @@ export async function mergeActors(targetActorId, sourceActorIds, reqUser) {
|
|||||||
return {
|
return {
|
||||||
scenes: mergedSceneActors.length,
|
scenes: mergedSceneActors.length,
|
||||||
profiles: mergedProfiles.length,
|
profiles: mergedProfiles.length,
|
||||||
|
stashes: mergedActorStashes.length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user