Added unidentified actors and actor count filters.
This commit is contained in:
+62
-23
@@ -24,7 +24,7 @@ import { curateMedia } from './media.js';
|
||||
import redis from './redis.js';
|
||||
import { curateRevision } from './revisions.js';
|
||||
import { curateStash } from './stashes.js';
|
||||
import { syncActors, syncScenes, syncStashes } from './sync.js';
|
||||
import { syncActors, syncManticoreScenes, syncScenes, syncStashes } from './sync.js';
|
||||
|
||||
const logger = initLogger();
|
||||
const mj = new MerkleJson();
|
||||
@@ -235,15 +235,17 @@ export function sortActorsByGender(actors, context = {}) {
|
||||
return actors;
|
||||
}
|
||||
|
||||
const alphaActors = actors.sort((actorA, actorB) => actorA.name.localeCompare(actorB.name, 'en'));
|
||||
const genderActors = ['transsexual', 'female', undefined, null, 'male'].flatMap((gender) => alphaActors.filter((actor) => actor.gender === gender));
|
||||
|
||||
const alphaActors = actors.toSorted((actorA, actorB) => actorA.name?.localeCompare(actorB.name, 'en'));
|
||||
const titleSlug = slugify(context.title);
|
||||
|
||||
const titleActors = titleSlug
|
||||
? genderActors.sort((actorA, actorB) => {
|
||||
const actorASlug = actorA.slug.split('-')[0];
|
||||
const actorBSlug = actorB.slug.split('-')[0];
|
||||
? alphaActors.sort((actorA, actorB) => {
|
||||
const actorASlug = actorA.slug?.split('-')[0];
|
||||
const actorBSlug = actorB.slug?.split('-')[0];
|
||||
|
||||
if (!actorASlug || !actorBSlug) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (titleSlug.includes(actorASlug) && !titleSlug.includes(actorBSlug)) {
|
||||
return -1;
|
||||
@@ -257,7 +259,10 @@ export function sortActorsByGender(actors, context = {}) {
|
||||
})
|
||||
: alphaActors;
|
||||
|
||||
return titleActors;
|
||||
const genderActors = ['transsexual', 'female', undefined, null, 'male'].flatMap((gender) => titleActors.filter((actor) => actor.gender === gender));
|
||||
const identifiedActors = genderActors.toSorted((actorA, actorB) => !!actorA.isUnknown - !!actorB.isUnknown);
|
||||
|
||||
return identifiedActors;
|
||||
}
|
||||
|
||||
export async function fetchActorsById(actorIds, options = {}, reqUser) {
|
||||
@@ -465,22 +470,21 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
||||
builder.select('if(date_of_birth, floor((now() - date_of_birth) / 31556952), 0) as age');
|
||||
}
|
||||
|
||||
// range filters
|
||||
['age', 'height'].forEach((attribute) => {
|
||||
if (filters[attribute]) {
|
||||
builder
|
||||
.where(attribute, '>=', filters[attribute][0])
|
||||
.where(attribute, '<=', filters[attribute][1]);
|
||||
// range filters, either end may be open, weight is a reserved keyword in manticore
|
||||
Object.entries({ age: 'age', height: 'height', weight: 'mass' }).forEach(([attribute, column]) => {
|
||||
if (typeof filters[attribute]?.min === 'number') {
|
||||
builder.where(column, '>=', filters[attribute].min);
|
||||
}
|
||||
|
||||
if (typeof filters[attribute]?.max === 'number') {
|
||||
builder.where(column, '<=', filters[attribute].max);
|
||||
|
||||
if (typeof filters[attribute].min !== 'number') {
|
||||
builder.where(column, '>', 0); // unknown values are stored as 0, an open lower bound should not match them
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (filters.weight) {
|
||||
// weight is a reserved keyword in manticore
|
||||
builder
|
||||
.where('mass', '>=', filters.weight[0])
|
||||
.where('mass', '<=', filters.weight[1]);
|
||||
}
|
||||
|
||||
if (filters.dateOfBirth && filters.dobType === 'dateOfBirth') {
|
||||
builder.where('date_of_birth', Math.floor(filters.dateOfBirth.getTime() / 1000));
|
||||
}
|
||||
@@ -497,7 +501,8 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
||||
}
|
||||
|
||||
if (filters.cup) {
|
||||
builder.select(`regex(actors.cup, '^[${filters.cup[0]}-${filters.cup[1]}]') as cup_in_range`);
|
||||
// cup range is validated to single letters by the query parser
|
||||
builder.select(`regex(actors.cup, '^[${filters.cup.min || 'A'}-${filters.cup.max || 'Z'}]') as cup_in_range`);
|
||||
builder.where('cup_in_range', 1);
|
||||
}
|
||||
|
||||
@@ -1195,6 +1200,36 @@ async function fetchMainProfile(actorId, wasCreated = false) {
|
||||
return fetchMainProfile(actorId, true);
|
||||
}
|
||||
|
||||
async function fetchActorGenders(actorIds) {
|
||||
const actors = await knex('actors')
|
||||
.select('id', 'gender')
|
||||
.whereIn('id', actorIds);
|
||||
|
||||
return Object.fromEntries(actors.map((actor) => [actor.id, actor.gender]));
|
||||
}
|
||||
|
||||
// scene search documents count actors per gender, so scenes need a resync when an actor's gender changes
|
||||
// syncs the search documents directly, the materialized views don't depend on actor genders
|
||||
async function syncGenderChangedScenes(actorIds, gendersBefore) {
|
||||
const gendersAfter = await fetchActorGenders(actorIds);
|
||||
const changedActorIds = actorIds.filter((actorId) => gendersAfter[actorId] !== gendersBefore[actorId]);
|
||||
|
||||
if (changedActorIds.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const sceneIds = await knex('releases_actors')
|
||||
.distinct('release_id')
|
||||
.whereIn('actor_id', changedActorIds)
|
||||
.pluck('release_id');
|
||||
|
||||
logger.info(`Gender changed for ${changedActorIds.length} actors, resyncing ${sceneIds.length} scenes`);
|
||||
|
||||
if (sceneIds.length > 0) { // without IDs, all scenes are synced
|
||||
await syncManticoreScenes(sceneIds);
|
||||
}
|
||||
}
|
||||
|
||||
async function applyActorRevision(revisionIds, reqUser) {
|
||||
const revisions = await knex('actors_revisions')
|
||||
.whereIn('id', revisionIds)
|
||||
@@ -1276,6 +1311,7 @@ async function applyActorRevision(revisionIds, reqUser) {
|
||||
}, Promise.resolve());
|
||||
|
||||
const actorIds = Array.from(new Set(revisions.map((revision) => revision.actor_id)));
|
||||
const gendersBefore = await fetchActorGenders(actorIds);
|
||||
|
||||
await interpolateProfiles(actorIds, {
|
||||
knex,
|
||||
@@ -1285,7 +1321,10 @@ async function applyActorRevision(revisionIds, reqUser) {
|
||||
omit,
|
||||
}, { refreshView: false });
|
||||
|
||||
await syncActors(actorIds);
|
||||
await Promise.all([
|
||||
syncActors(actorIds),
|
||||
syncGenderChangedScenes(actorIds, gendersBefore),
|
||||
]);
|
||||
}
|
||||
|
||||
export async function reviewActorRevision(revisionId, isApproved, { feedback }, reqUser) {
|
||||
|
||||
Reference in New Issue
Block a user