Files
traxxx-web/src/web/actors.js

235 lines
5.0 KiB
JavaScript

import { stringify } from '@brillout/json-serializer/stringify';
import { Router } from 'express';
import omit from 'object.omit';
import {
createActor,
createActorRevision,
fetchActorRevisions,
fetchActors,
fetchActorsById,
mergeActors,
reviewActorRevision,
} from '../actors.js';
import { fetchStashByUsernameAndSlug } from '../stashes.js';
export function curateActorsQuery(query) {
return {
query: query.q,
gender: query.gender,
age: query.age?.split(',').map((age) => Number(age)),
dateOfBirth: query.dob && new Date(query.dob),
dobType: ({ dob: 'dateOfBirth', bd: 'birthday' })[query.dobt] || 'birthday',
cup: query.cup?.split(','),
country: query.c,
naturalBoobs: query.nb,
height: query.height?.split(',').map((height) => Number(height)),
weight: query.weight?.split(',').map((weight) => Number(weight)),
requireAvatar: query.avatar,
stashId: Number(query.stashId) || null,
isGlobal: Object.hasOwn(query, 'global'),
includeAliased: Object.hasOwn(query, 'alias'),
};
}
export async function fetchActorsApi(req, res) {
const {
actors,
countries,
limit,
total,
} = await fetchActors(curateActorsQuery(req.query), {
page: Number(req.query.page) || 1,
limit: Number(req.query.limit) || 120,
order: req.query.order?.split('.') || ['likes', 'desc'],
}, req.user);
res.send(stringify({
actors,
countries,
limit,
total,
}));
}
export const actorsSchema = `
extend type Query {
actors(
query: String
stash: String
limit: Int! = 30
page: Int! = 1
order: [String!]
): ActorsResult
actor(
id: Int!
): Actor
actorsById(
ids: [Int!]!
): [Actor]
}
type Country {
alpha2: String
name: String
}
type Location {
country: Country
city: String
state: String
}
type ActorsResult {
nodes: [Actor!]!
total: Int
}
type Actor {
id: Int!
name: String
slug: String
allowGlobalMatch: Boolean
gender: String
dateOfBirth: Date
dateOfDeath: Date
age: Int
ageFromBirth: Int
ageThen: Int
origin: Location
residence: Location
ethnicity: String
height: Int
bust: String
hip: Int
waist: Int
naturalBoobs: Boolean
naturalButt: Boolean
penisLength: Int
penisGirth: Int
isCircumcised: Boolean
eyes: String
hairColor: String
hasTattoos: Boolean
tattoos: String
hasPiercings: Boolean
piercings: String
agency: String
entity: Entity
aliases: [Actor!]!
scenes: Int
likes: Int
stashes: [Stash!]!
}
`;
function curateGraphqlActor(actor) {
return {
...actor,
age: actor.ageFromBirth,
height: actor.height?.metric,
weight: actor.weight?.metric,
};
}
function getOrder(query) {
if (query.order) {
return query.order;
}
if (query.query) {
return ['results', 'desc'];
}
if (query.stash) {
return ['stashed', 'desc'];
}
return ['likes', 'desc'];
}
export async function fetchActorsGraphql(query, req) {
const stash = query.stash && req.user
? await fetchStashByUsernameAndSlug(req.user.id, query.stash, req.user)
: null;
const {
actors,
total,
} = await fetchActors({
query: query.query,
stashId: stash?.id,
}, {
limit: query.limit,
page: query.page,
order: getOrder(query),
aggregateCountries: false,
}, req.user);
return {
nodes: actors.map((actor) => curateGraphqlActor(actor)),
total,
};
}
export async function fetchActorsByIdGraphql(query, _req, _info) {
const actors = await fetchActorsById([].concat(query.id, query.ids).filter(Boolean));
const curatedActors = actors.map((actor) => curateGraphqlActor(actor));
if (query.ids) {
return curatedActors;
}
return curatedActors[0];
}
export async function createActorApi(req, res) {
const actor = await createActor(req.body.actor, omit(req.body, ['actor']), req.user);
res.send(stringify({ actor }));
}
export async function mergeActorsApi(req, res) {
const result = await mergeActors(
Number(req.params.targetActorId),
req.params.sourceActorIds.split(',').map((actorId) => Number(actorId)),
req.body.comment,
req.user,
);
res.send(stringify(result));
}
async function fetchActorRevisionsApi(req, res) {
const revisions = await fetchActorRevisions(Number(req.params.revisionId) || null, req.query, req.user);
res.send(stringify(revisions));
}
async function createActorRevisionApi(req, res) {
await createActorRevision(Number(req.body.actorId), req.body, req.user);
res.status(204).send();
}
async function reviewActorRevisionApi(req, res) {
await reviewActorRevision(Number(req.params.revisionId), req.body.isApproved, req.body, req.user);
res.status(204).send();
}
export const actorsRouter = Router();
actorsRouter.get('/api/actors', fetchActorsApi);
actorsRouter.post('/api/actors', createActorApi);
actorsRouter.post('/api/actors/:targetActorId/merge/:sourceActorIds', mergeActorsApi);
actorsRouter.get('/api/revisions/actors', fetchActorRevisionsApi);
actorsRouter.get('/api/revisions/actors/:revisionId', fetchActorRevisionsApi);
actorsRouter.post('/api/revisions/actors', createActorRevisionApi);
actorsRouter.post('/api/revisions/actors/:revisionId/reviews', reviewActorRevisionApi);