Added actor stash.
This commit is contained in:
244
src/actors.js
244
src/actors.js
@@ -2,10 +2,11 @@ import config from 'config';
|
||||
import { differenceInYears } from 'date-fns';
|
||||
import { unit } from 'mathjs';
|
||||
|
||||
import knex from './knex.js';
|
||||
import { searchApi } from './manticore.js';
|
||||
import { knexOwner as knex, knexManticore } from './knex.js';
|
||||
import { utilsApi } from './manticore.js';
|
||||
import { HttpError } from './errors.js';
|
||||
import { fetchCountriesByAlpha2 } from './countries.js';
|
||||
import { curateStash } from './stashes.js';
|
||||
|
||||
export function curateActor(actor, context = {}) {
|
||||
return {
|
||||
@@ -58,6 +59,7 @@ export function curateActor(actor, context = {}) {
|
||||
createdAt: actor.created_at,
|
||||
updatedAt: actor.updated_at,
|
||||
likes: actor.stashed,
|
||||
stashes: context.stashes?.map((stash) => curateStash(stash)) || [],
|
||||
...context.append?.[actor.id],
|
||||
};
|
||||
}
|
||||
@@ -73,8 +75,8 @@ export function sortActorsByGender(actors) {
|
||||
return genderActors;
|
||||
}
|
||||
|
||||
export async function fetchActorsById(actorIds, options = {}) {
|
||||
const [actors] = await Promise.all([
|
||||
export async function fetchActorsById(actorIds, options = {}, reqUser) {
|
||||
const [actors, stashes] = await Promise.all([
|
||||
knex('actors')
|
||||
.select(
|
||||
'actors.*',
|
||||
@@ -93,10 +95,19 @@ export async function fetchActorsById(actorIds, options = {}) {
|
||||
builder.orderBy(...options.order);
|
||||
}
|
||||
}),
|
||||
reqUser
|
||||
? knex('stashes_actors')
|
||||
.leftJoin('stashes', 'stashes.id', 'stashes_actors.stash_id')
|
||||
.where('stashes.user_id', reqUser.id)
|
||||
.whereIn('stashes_actors.actor_id', actorIds)
|
||||
: [],
|
||||
]);
|
||||
|
||||
if (options.order) {
|
||||
return actors.map((actorEntry) => curateActor(actorEntry, { append: options.append }));
|
||||
return actors.map((actorEntry) => curateActor(actorEntry, {
|
||||
stashes: stashes.filter((stash) => stash.actor_id === actorEntry.id),
|
||||
append: options.append,
|
||||
}));
|
||||
}
|
||||
|
||||
const curatedActors = actorIds.map((actorId) => {
|
||||
@@ -107,7 +118,10 @@ export async function fetchActorsById(actorIds, options = {}) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return curateActor(actor, { append: options.append });
|
||||
return curateActor(actor, {
|
||||
stashes: stashes.filter((stash) => stash.actor_id === actor.id),
|
||||
append: options.append,
|
||||
});
|
||||
}).filter(Boolean);
|
||||
|
||||
return curatedActors;
|
||||
@@ -126,6 +140,30 @@ function curateOptions(options) {
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
const sortMap = {
|
||||
likes: 'stashed',
|
||||
scenes: 'scenes',
|
||||
relevance: '_score',
|
||||
};
|
||||
|
||||
function getSort(order) {
|
||||
if (order[0] === 'name') {
|
||||
return [{
|
||||
slug: order[1],
|
||||
}];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
[sortMap[order[0]]]: order[1],
|
||||
},
|
||||
{
|
||||
slug: 'asc', // sort by name where primary order is equal
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function buildQuery(filters) {
|
||||
const query = {
|
||||
bool: {
|
||||
@@ -230,31 +268,7 @@ function buildQuery(filters) {
|
||||
return { query, expressions };
|
||||
}
|
||||
|
||||
const sortMap = {
|
||||
likes: 'stashed',
|
||||
scenes: 'scenes',
|
||||
relevance: '_score',
|
||||
};
|
||||
|
||||
function getSort(order) {
|
||||
if (order[0] === 'name') {
|
||||
return [{
|
||||
slug: order[1],
|
||||
}];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
[sortMap[order[0]]]: order[1],
|
||||
},
|
||||
{
|
||||
slug: 'asc', // sort by name where primary order is equal
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export async function fetchActors(filters, rawOptions) {
|
||||
const options = curateOptions(rawOptions);
|
||||
async function queryManticoreJson(filters, options) {
|
||||
const { query, expressions } = buildQuery(filters);
|
||||
|
||||
const result = await searchApi.search({
|
||||
@@ -279,16 +293,176 @@ export async function fetchActors(filters, rawOptions) {
|
||||
},
|
||||
});
|
||||
|
||||
const actorIds = result.hits.hits.map((hit) => Number(hit._id));
|
||||
const actors = result.hits.hits.map((hit) => ({
|
||||
id: hit._id,
|
||||
...hit._source,
|
||||
_score: hit._score,
|
||||
}));
|
||||
|
||||
return {
|
||||
actors,
|
||||
total: result.hits.total,
|
||||
aggregations: result.aggregations && Object.fromEntries(Object.entries(result.aggregations).map(([key, { buckets }]) => [key, buckets])),
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
async function queryManticoreSql(filters, options, _reqUser) {
|
||||
const aggSize = config.database.manticore.maxAggregateSize;
|
||||
|
||||
const sqlQuery = knexManticore.raw(`
|
||||
:query:
|
||||
OPTION
|
||||
max_matches=:maxMatches:,
|
||||
max_query_time=:maxQueryTime:
|
||||
:countriesFacet:;
|
||||
show meta;
|
||||
`, {
|
||||
query: knexManticore(filters.stashId ? 'actors_stashed' : 'actors')
|
||||
.modify((builder) => {
|
||||
if (filters.stashId) {
|
||||
builder.select(knex.raw(`
|
||||
actors.id as id,
|
||||
actors.country as country,
|
||||
actors.scenes as scenes,
|
||||
actors.stashed as stashed,
|
||||
created_at as stashed_at
|
||||
`));
|
||||
// weight() as _score
|
||||
|
||||
builder
|
||||
.innerJoin('actors', 'actors.id', 'actors_stashed.actor_id')
|
||||
.where('stash_id', filters.stashId);
|
||||
} else {
|
||||
// builder.select(knex.raw('*, weight() as _score'));
|
||||
builder.select(knex.raw('*'));
|
||||
}
|
||||
|
||||
if (filters.query) {
|
||||
builder.whereRaw('match(\'@name :query:\', actors)', { query: filters.query });
|
||||
}
|
||||
|
||||
['gender', 'country'].forEach((attribute) => {
|
||||
if (filters[attribute]) {
|
||||
builder.where(attribute, filters[attribute]);
|
||||
}
|
||||
});
|
||||
|
||||
['age', 'height', 'weight'].forEach((attribute) => {
|
||||
if (filters[attribute]) {
|
||||
builder
|
||||
.where(attribute, '>=', filters[attribute][0])
|
||||
.where(attribute, '<=', filters[attribute][1]);
|
||||
}
|
||||
});
|
||||
|
||||
if (filters.dateOfBirth && filters.dobType === 'dateOfBirth') {
|
||||
builder.where('date_of_birth', Math.floor(filters.dateOfBirth.getTime() / 1000));
|
||||
}
|
||||
|
||||
if (filters.dateOfBirth && filters.dobType === 'birthday') {
|
||||
const month = filters.dateOfBirth.getMonth() + 1;
|
||||
const day = filters.dateOfBirth.getDate();
|
||||
|
||||
builder
|
||||
.where('month(date_of_birth)', month)
|
||||
.where('day(date_of_birth)', day);
|
||||
}
|
||||
|
||||
if (filters.cup) {
|
||||
builder.where(`regex(cup, '^[${filters.cup[0]}-${filters.cup[1]}]')`, 1);
|
||||
}
|
||||
|
||||
if (typeof filters.naturalBoobs === 'boolean') {
|
||||
builder.where('natural_boobs', filters.naturalBoobs ? 2 : 1); // manticore boolean does not support null, so 0 = null, 1 = false (enhanced), 2 = true (natural)
|
||||
}
|
||||
|
||||
if (filters.requireAvatar) {
|
||||
builder.where('has_avatar', 1);
|
||||
}
|
||||
|
||||
if (options.order?.[0] === 'name') {
|
||||
builder.orderBy('actors.slug', options.order[1]);
|
||||
} else if (options.order?.[0] === 'likes') {
|
||||
builder.orderBy([
|
||||
{ column: 'actors.stashed', order: options.order[1] },
|
||||
{ column: 'actors.slug', order: 'asc' },
|
||||
]);
|
||||
} else if (options.order?.[0] === 'scenes') {
|
||||
builder.orderBy([
|
||||
{ column: 'actors.scenes', order: options.order[1] },
|
||||
{ column: 'actors.slug', order: 'asc' },
|
||||
]);
|
||||
} else if (options.order?.[0] === 'stashed' && filters.stashId) {
|
||||
builder.orderBy([
|
||||
{ column: 'stashed_at', order: options.order[1] },
|
||||
{ column: 'actors.slug', order: 'asc' },
|
||||
]);
|
||||
} else if (options.order) {
|
||||
builder.orderBy([
|
||||
{ column: `actors.${options.order[0]}`, order: options.order[1] },
|
||||
{ column: 'actors.slug', order: 'asc' },
|
||||
]);
|
||||
} else {
|
||||
builder.orderBy('actors.slug', 'asc');
|
||||
}
|
||||
})
|
||||
.limit(options.limit)
|
||||
.offset((options.page - 1) * options.limit)
|
||||
.toString(),
|
||||
// option threads=1 fixes actors, but drastically slows down performance, wait for fix
|
||||
countriesFacet: options.aggregateActors ? knex.raw('facet actors.country order by count(*) desc limit 300', [aggSize]) : null,
|
||||
maxMatches: config.database.manticore.maxMatches,
|
||||
maxQueryTime: config.database.manticore.maxQueryTime,
|
||||
}).toString();
|
||||
|
||||
// manticore does not seem to accept table.column syntax if 'table' is primary (yet?), crude work-around
|
||||
const curatedSqlQuery = filters.stashId
|
||||
? sqlQuery
|
||||
: sqlQuery.replace(/actors\./g, '');
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.log(curatedSqlQuery);
|
||||
}
|
||||
|
||||
const results = await utilsApi.sql(curatedSqlQuery);
|
||||
|
||||
// console.log(results[0]);
|
||||
|
||||
const countries = results
|
||||
.find((result) => (result.columns[0].actor_ids || result.columns[0]['scenes.country']) && result.columns[1]['count(*)'])
|
||||
?.data.map((row) => ({ key: row.actor_ids || row['scenes.country'], doc_count: row['count(*)'] }))
|
||||
|| [];
|
||||
|
||||
const total = Number(results.at(-1).data.find((entry) => entry.Variable_name === 'total_found').Value);
|
||||
|
||||
return {
|
||||
actors: results[0].data,
|
||||
total,
|
||||
aggregations: {
|
||||
countries,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchActors(filters, rawOptions, reqUser) {
|
||||
const options = curateOptions(rawOptions);
|
||||
|
||||
console.log('filters', filters);
|
||||
console.log('options', options);
|
||||
|
||||
const result = await queryManticoreSql(filters, options, reqUser);
|
||||
|
||||
const actorIds = result.actors.map((actor) => Number(actor.id));
|
||||
const [actors, countries] = await Promise.all([
|
||||
fetchActorsById(actorIds),
|
||||
fetchCountriesByAlpha2(result.aggregations.countries.buckets.map((bucket) => bucket.key)),
|
||||
fetchActorsById(actorIds, {}, reqUser),
|
||||
fetchCountriesByAlpha2(result.aggregations.countries.map((bucket) => bucket.key)),
|
||||
]);
|
||||
|
||||
return {
|
||||
actors,
|
||||
countries,
|
||||
total: result.hits.total,
|
||||
total: result.total,
|
||||
limit: options.limit,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import config from 'config';
|
||||
import util from 'util'; /* eslint-disable-line no-unused-vars */
|
||||
|
||||
import { knexOwner as knex, knexManticore } from './knex.js';
|
||||
import { searchApi, utilsApi } from './manticore.js';
|
||||
import { utilsApi } from './manticore.js';
|
||||
import { HttpError } from './errors.js';
|
||||
import { fetchActorsById, curateActor, sortActorsByGender } from './actors.js';
|
||||
import { fetchTagsById } from './tags.js';
|
||||
@@ -55,7 +55,10 @@ function curateScene(rawScene, assets) {
|
||||
type: assets.channel.network_type,
|
||||
hasLogo: assets.channel.has_logo,
|
||||
} : null,
|
||||
actors: sortActorsByGender(assets.actors.map((actor) => curateActor(actor, { sceneDate: rawScene.effective_date }))),
|
||||
actors: sortActorsByGender(assets.actors.map((actor) => curateActor(actor, {
|
||||
sceneDate: rawScene.effective_date,
|
||||
stashes: assets.actorStashes,
|
||||
}))),
|
||||
directors: assets.directors.map((director) => ({
|
||||
id: director.id,
|
||||
slug: director.slug,
|
||||
@@ -74,7 +77,7 @@ function curateScene(rawScene, assets) {
|
||||
};
|
||||
}
|
||||
|
||||
export async function fetchScenesById(sceneIds, reqUser) {
|
||||
export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
|
||||
const [scenes, channels, actors, directors, tags, posters, photos, stashes] = await Promise.all([
|
||||
knex('releases').whereIn('releases.id', sceneIds),
|
||||
knex('releases')
|
||||
@@ -125,6 +128,13 @@ export async function fetchScenesById(sceneIds, reqUser) {
|
||||
: [],
|
||||
]);
|
||||
|
||||
const actorStashes = reqUser && context.actorStashes
|
||||
? await knex('stashes_actors')
|
||||
.leftJoin('stashes', 'stashes.id', 'stashes_actors.stash_id')
|
||||
.where('stashes.user_id', reqUser.id)
|
||||
.whereIn('stashes_actors.actor_id', actors.map((actor) => actor.id))
|
||||
: [];
|
||||
|
||||
return sceneIds.map((sceneId) => {
|
||||
const scene = scenes.find((sceneEntry) => sceneEntry.id === sceneId);
|
||||
|
||||
@@ -139,6 +149,7 @@ export async function fetchScenesById(sceneIds, reqUser) {
|
||||
const scenePoster = posters.find((poster) => poster.release_id === sceneId);
|
||||
const scenePhotos = photos.filter((photo) => photo.release_id === sceneId);
|
||||
const sceneStashes = stashes.filter((stash) => stash.scene_id === sceneId);
|
||||
const sceneActorStashes = sceneActors.map((actor) => actorStashes.find((stash) => stash.actor_id === actor.id)).filter(Boolean);
|
||||
|
||||
return curateScene(scene, {
|
||||
channel: sceneChannel,
|
||||
@@ -148,6 +159,7 @@ export async function fetchScenesById(sceneIds, reqUser) {
|
||||
poster: scenePoster,
|
||||
photos: scenePhotos,
|
||||
stashes: sceneStashes,
|
||||
actorStashes: sceneActorStashes,
|
||||
});
|
||||
}).filter(Boolean);
|
||||
}
|
||||
@@ -171,6 +183,7 @@ function curateOptions(options) {
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
function buildQuery(filters = {}, options) {
|
||||
const query = {
|
||||
bool: {
|
||||
@@ -215,23 +228,6 @@ function buildQuery(filters = {}, options) {
|
||||
}
|
||||
|
||||
if (filters.query) {
|
||||
/*
|
||||
query.bool.must.push({
|
||||
bool: {
|
||||
should: [
|
||||
{ match: { title_filtered: filters.query } },
|
||||
{ match: { actors: filters.query } },
|
||||
{ match: { tags: filters.query } },
|
||||
{ match: { channel_name: filters.query } },
|
||||
{ match: { network_name: filters.query } },
|
||||
{ match: { channel_slug: filters.query } },
|
||||
{ match: { network_slug: filters.query } },
|
||||
{ match: { meta: filters.query } }, // date
|
||||
],
|
||||
},
|
||||
});
|
||||
*/
|
||||
|
||||
query.bool.must.push({ match: { '!title': filters.query } }); // title_filtered is matched instead of title
|
||||
}
|
||||
|
||||
@@ -262,16 +258,6 @@ function buildQuery(filters = {}, options) {
|
||||
query.bool.must.push({ equals: { stash_id: filters.stashId } });
|
||||
}
|
||||
|
||||
/* tag filter
|
||||
must_not: [
|
||||
{
|
||||
in: {
|
||||
'any(tag_ids)': [101, 180, 32],
|
||||
},
|
||||
},
|
||||
],
|
||||
*/
|
||||
|
||||
return { query, sort };
|
||||
}
|
||||
|
||||
@@ -311,14 +297,6 @@ function buildAggregates(options) {
|
||||
return aggregates;
|
||||
}
|
||||
|
||||
function countAggregations(buckets) {
|
||||
if (!buckets) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Object.fromEntries(buckets.map((bucket) => [bucket.key, { count: bucket.doc_count }]));
|
||||
}
|
||||
|
||||
async function queryManticoreJson(filters, options, _reqUser) {
|
||||
const { query, sort } = buildQuery(filters, options);
|
||||
|
||||
@@ -357,24 +335,26 @@ async function queryManticoreJson(filters, options, _reqUser) {
|
||||
aggregations: result.aggregations && Object.fromEntries(Object.entries(result.aggregations).map(([key, { buckets }]) => [key, buckets])),
|
||||
};
|
||||
}
|
||||
*/
|
||||
|
||||
async function queryManticoreSql(filters, options, _reqUser) {
|
||||
const aggSize = config.database.manticore.maxAggregateSize;
|
||||
|
||||
const sqlQuery = knexManticore.raw(`
|
||||
:query:
|
||||
OPTION field_weights=(
|
||||
title_filtered=7,
|
||||
actors=10,
|
||||
tags=9,
|
||||
meta=6,
|
||||
channel_name=2,
|
||||
channel_slug=3,
|
||||
network_name=1,
|
||||
network_slug=1
|
||||
),
|
||||
max_matches=:maxMatches:,
|
||||
max_query_time=:maxQueryTime:
|
||||
OPTION
|
||||
field_weights=(
|
||||
title_filtered=7,
|
||||
actors=10,
|
||||
tags=9,
|
||||
meta=6,
|
||||
channel_name=2,
|
||||
channel_slug=3,
|
||||
network_name=1,
|
||||
network_slug=1
|
||||
),
|
||||
max_matches=:maxMatches:,
|
||||
max_query_time=:maxQueryTime:
|
||||
:actorsFacet:
|
||||
:tagsFacet:
|
||||
:channelsFacet:;
|
||||
@@ -391,6 +371,7 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
||||
scenes.channel_id as channel_id,
|
||||
scenes.network_id as network_id,
|
||||
scenes.effective_date as effective_date,
|
||||
scenes.stashed as stashed,
|
||||
scenes.created_at,
|
||||
created_at as stashed_at,
|
||||
weight() as _score
|
||||
@@ -481,7 +462,7 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
||||
|
||||
const results = await utilsApi.sql(curatedSqlQuery);
|
||||
|
||||
console.log(results[0]);
|
||||
// console.log(results[0]);
|
||||
|
||||
const actorIds = results
|
||||
.find((result) => (result.columns[0].actor_ids || result.columns[0]['scenes.actor_ids']) && result.columns[1]['count(*)'])
|
||||
@@ -511,6 +492,14 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
||||
};
|
||||
}
|
||||
|
||||
function countAggregations(buckets) {
|
||||
if (!buckets) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Object.fromEntries(buckets.map((bucket) => [bucket.key, { count: bucket.doc_count }]));
|
||||
}
|
||||
|
||||
export async function fetchScenes(filters, rawOptions, reqUser) {
|
||||
const options = curateOptions(rawOptions);
|
||||
|
||||
@@ -527,10 +516,6 @@ export async function fetchScenes(filters, rawOptions, reqUser) {
|
||||
const result = await queryManticoreSql(filters, options, reqUser);
|
||||
console.timeEnd('manticore sql');
|
||||
|
||||
console.time('manticore json');
|
||||
await queryManticoreJson(filters, options, reqUser);
|
||||
console.timeEnd('manticore json');
|
||||
|
||||
const actorCounts = options.aggregateActors && countAggregations(result.aggregations?.actorIds);
|
||||
const tagCounts = options.aggregateTags && countAggregations(result.aggregations?.tagIds);
|
||||
const channelCounts = options.aggregateChannels && countAggregations(result.aggregations?.channelIds);
|
||||
@@ -547,7 +532,7 @@ export async function fetchScenes(filters, rawOptions, reqUser) {
|
||||
|
||||
console.time('fetch full');
|
||||
const sceneIds = result.scenes.map((scene) => Number(scene.id));
|
||||
const scenes = await fetchScenesById(sceneIds, reqUser);
|
||||
const scenes = await fetchScenesById(sceneIds, { reqUser });
|
||||
console.timeEnd('fetch full');
|
||||
|
||||
return {
|
||||
|
||||
@@ -170,11 +170,25 @@ export async function refreshActorsView() {
|
||||
export async function stashActor(actorId, stashId, sessionUser) {
|
||||
const stash = await fetchStashById(stashId, sessionUser);
|
||||
|
||||
await knex('stashes_actors')
|
||||
const [stashed] = await knex('stashes_actors')
|
||||
.insert({
|
||||
stash_id: stash.id,
|
||||
actor_id: actorId,
|
||||
});
|
||||
})
|
||||
.returning(['id', 'created_at']);
|
||||
|
||||
await indexApi.replace({
|
||||
index: 'actors_stashed',
|
||||
id: stashed.id,
|
||||
doc: {
|
||||
actor_id: actorId,
|
||||
user_id: sessionUser.id,
|
||||
stash_id: stashId,
|
||||
created_at: Math.round(stashed.created_at.getTime() / 1000),
|
||||
},
|
||||
});
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) stashed actor ${actorId} to stash ${stash.id} (${stash.name})`);
|
||||
|
||||
refreshActorsView();
|
||||
|
||||
@@ -192,6 +206,25 @@ export async function unstashActor(actorId, stashId, sessionUser) {
|
||||
.where('stashes.user_id', sessionUser.id))
|
||||
.delete();
|
||||
|
||||
try {
|
||||
await indexApi.callDelete({
|
||||
index: 'actors_stashed',
|
||||
query: {
|
||||
bool: {
|
||||
must: [
|
||||
{ equals: { actor_id: actorId } },
|
||||
{ equals: { stash_id: stashId } },
|
||||
{ equals: { user_id: sessionUser.id } },
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) unstashed actor ${actorId} from stash ${stashId}`);
|
||||
|
||||
refreshActorsView();
|
||||
|
||||
return fetchStashes('actor', actorId, sessionUser);
|
||||
@@ -200,11 +233,26 @@ export async function unstashActor(actorId, stashId, sessionUser) {
|
||||
export async function stashScene(sceneId, stashId, sessionUser) {
|
||||
const stash = await fetchStashById(stashId, sessionUser);
|
||||
|
||||
await knex('stashes_scenes')
|
||||
const [stashed] = await knex('stashes_scenes')
|
||||
.insert({
|
||||
stash_id: stash.id,
|
||||
scene_id: sceneId,
|
||||
});
|
||||
})
|
||||
.returning(['id', 'created_at']);
|
||||
|
||||
await indexApi.replace({
|
||||
index: 'scenes_stashed',
|
||||
id: stashed.id,
|
||||
doc: {
|
||||
// ...doc.replace.doc,
|
||||
scene_id: sceneId,
|
||||
user_id: sessionUser.id,
|
||||
stash_id: stashId,
|
||||
created_at: Math.round(stashed.created_at.getTime() / 1000),
|
||||
},
|
||||
});
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) stashed scene ${sceneId} to stash ${stash.id} (${stash.name})`);
|
||||
|
||||
return fetchStashes('scene', sceneId, sessionUser);
|
||||
}
|
||||
@@ -225,7 +273,7 @@ export async function unstashScene(sceneId, stashId, sessionUser) {
|
||||
query: {
|
||||
bool: {
|
||||
must: [
|
||||
{ equals: { id: sceneId } },
|
||||
{ equals: { scene_id: sceneId } },
|
||||
{ equals: { stash_id: stashId } },
|
||||
{ equals: { user_id: sessionUser.id } },
|
||||
],
|
||||
@@ -233,6 +281,8 @@ export async function unstashScene(sceneId, stashId, sessionUser) {
|
||||
},
|
||||
});
|
||||
|
||||
logger.verbose(`${sessionUser.username} (${sessionUser.id}) unstashed scene ${sceneId} from stash ${stashId}`);
|
||||
|
||||
return fetchStashes('scene', sceneId, sessionUser);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import { format } from 'date-fns';
|
||||
import { faker } from '@faker-js/faker';
|
||||
|
||||
import { indexApi, utilsApi } from '../manticore.js';
|
||||
import { indexApi } from '../manticore.js';
|
||||
|
||||
import { knexOwner as knex } from '../knex.js';
|
||||
import slugify from '../utils/slugify.js';
|
||||
@@ -105,11 +105,11 @@ async function updateStashed(docs) {
|
||||
|
||||
const stashDoc = sceneStashes.map((stash) => ({
|
||||
replace: {
|
||||
index: 'movies_liked',
|
||||
index: 'scenes_stashed',
|
||||
id: stash.stashed_id,
|
||||
doc: {
|
||||
// ...doc.replace.doc,
|
||||
movie_id: doc.replace.id,
|
||||
scene_id: doc.replace.id,
|
||||
user_id: stash.user_id,
|
||||
},
|
||||
},
|
||||
@@ -127,35 +127,6 @@ async function updateStashed(docs) {
|
||||
}
|
||||
|
||||
async function init() {
|
||||
await utilsApi.sql('drop table if exists movies');
|
||||
await utilsApi.sql('drop table if exists movies_liked');
|
||||
|
||||
await utilsApi.sql(`create table movies (
|
||||
id int,
|
||||
title text,
|
||||
title_filtered text,
|
||||
channel_id int,
|
||||
channel_name text,
|
||||
channel_slug text,
|
||||
network_id int,
|
||||
network_name text,
|
||||
network_slug text,
|
||||
actor_ids multi,
|
||||
actors text,
|
||||
tag_ids multi,
|
||||
tags text,
|
||||
meta text,
|
||||
date timestamp,
|
||||
created_at timestamp,
|
||||
effective_date timestamp,
|
||||
liked int
|
||||
)`);
|
||||
|
||||
await utilsApi.sql(`create table movies_liked (
|
||||
movie_id int,
|
||||
user_id int
|
||||
)`);
|
||||
|
||||
const scenes = await fetchScenes();
|
||||
|
||||
const docs = scenes.map((scene) => {
|
||||
@@ -165,7 +136,7 @@ async function init() {
|
||||
|
||||
return {
|
||||
replace: {
|
||||
index: 'movies',
|
||||
index: 'scenes',
|
||||
id: scene.id,
|
||||
doc: {
|
||||
title: scene.title || undefined,
|
||||
|
||||
51
src/tools/sync-stashes.js
Normal file
51
src/tools/sync-stashes.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import { indexApi } from '../manticore.js';
|
||||
import { knexOwner as knex } from '../knex.js';
|
||||
import chunk from '../utils/chunk.js';
|
||||
|
||||
async function syncActorStashes() {
|
||||
const stashes = await knex('stashes_actors')
|
||||
.select(
|
||||
'stashes_actors.id as stashed_id',
|
||||
'stashes_actors.actor_id',
|
||||
'stashes.id as stash_id',
|
||||
'stashes.user_id as user_id',
|
||||
'stashes_actors.created_at as created_at',
|
||||
)
|
||||
.leftJoin('stashes', 'stashes.id', 'stashes_actors.stash_id');
|
||||
|
||||
if (stashes.length > 0) {
|
||||
console.log(stashes);
|
||||
}
|
||||
|
||||
await chunk(stashes, 1000).reduce(async (chain, stashChunk, index) => {
|
||||
await chain;
|
||||
|
||||
const stashDocs = stashChunk.map((stash) => ({
|
||||
replace: {
|
||||
index: 'actors_stashed',
|
||||
id: stash.stashed_id,
|
||||
doc: {
|
||||
actor_id: stash.actor_id,
|
||||
stash_id: stash.stash_id,
|
||||
user_id: stash.user_id,
|
||||
created_at: Math.round(stash.created_at.getTime() / 1000),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
console.log(stashDocs);
|
||||
|
||||
await indexApi.bulk(stashDocs.map((doc) => JSON.stringify(doc)).join('\n'));
|
||||
|
||||
console.log(`Synced ${index * 1000 + stashChunk.length}/${stashes.length} actor stashes`);
|
||||
}, Promise.resolve());
|
||||
}
|
||||
|
||||
async function init() {
|
||||
await syncActorStashes();
|
||||
console.log('Done!');
|
||||
|
||||
knex.destroy();
|
||||
}
|
||||
|
||||
init();
|
||||
@@ -13,6 +13,7 @@ export function curateActorsQuery(query) {
|
||||
height: query.height?.split(',').map((height) => Number(height)),
|
||||
weight: query.weight?.split(',').map((weight) => Number(weight)),
|
||||
requireAvatar: query.avatar,
|
||||
stashId: Number(query.stashId) || null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,7 +27,7 @@ export async function fetchActorsApi(req, res) {
|
||||
page: Number(req.query.page) || 1,
|
||||
limit: Number(req.query.limit) || 120,
|
||||
order: req.query.order?.split('.') || ['likes', 'desc'],
|
||||
});
|
||||
}, req.user);
|
||||
|
||||
res.send({
|
||||
actors,
|
||||
|
||||
@@ -11,7 +11,7 @@ export async function curateScenesQuery(query) {
|
||||
actorIds: [query.actorId, ...(query.actors?.split(',') || []).map((identifier) => parseActorIdentifier(identifier)?.id)].filter(Boolean),
|
||||
tagIds: await getIdsBySlug([query.tagSlug, ...(query.tags?.split(',') || [])], 'tags'),
|
||||
entityId: query.e ? await getIdsBySlug([query.e], 'entities').then(([id]) => id) : query.entityId,
|
||||
stashId: Number(query.stashId),
|
||||
stashId: Number(query.stashId) || null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -17,37 +17,37 @@ export async function createStashApi(req, res) {
|
||||
}
|
||||
|
||||
export async function updateStashApi(req, res) {
|
||||
const stash = await updateStash(req.params.stashId, req.body, req.session.user);
|
||||
const stash = await updateStash(Number(req.params.stashId), req.body, req.session.user);
|
||||
|
||||
res.send(stash);
|
||||
}
|
||||
|
||||
export async function removeStashApi(req, res) {
|
||||
await removeStash(req.params.stashId, req.session.user);
|
||||
await removeStash(Number(req.params.stashId), req.session.user);
|
||||
|
||||
res.status(204).send();
|
||||
}
|
||||
|
||||
export async function stashActorApi(req, res) {
|
||||
const stashes = await stashActor(req.body.actorId, req.params.stashId, req.user);
|
||||
const stashes = await stashActor(req.body.actorId, Number(req.params.stashId), req.user);
|
||||
|
||||
res.send(stashes);
|
||||
}
|
||||
|
||||
export async function stashSceneApi(req, res) {
|
||||
const stashes = await stashScene(req.body.sceneId, req.params.stashId, req.user);
|
||||
const stashes = await stashScene(req.body.sceneId, Number(req.params.stashId), req.user);
|
||||
|
||||
res.send(stashes);
|
||||
}
|
||||
|
||||
export async function stashMovieApi(req, res) {
|
||||
const stashes = await stashMovie(req.body.movieId, req.params.stashId, req.user);
|
||||
const stashes = await stashMovie(req.body.movieId, Number(req.params.stashId), req.user);
|
||||
|
||||
res.send(stashes);
|
||||
}
|
||||
|
||||
export async function unstashActorApi(req, res) {
|
||||
const stashes = await unstashActor(req.params.actorId, req.params.stashId, req.user);
|
||||
const stashes = await unstashActor(Number(req.params.actorId), Number(req.params.stashId), req.user);
|
||||
|
||||
res.send(stashes);
|
||||
}
|
||||
@@ -59,7 +59,7 @@ export async function unstashSceneApi(req, res) {
|
||||
}
|
||||
|
||||
export async function unstashMovieApi(req, res) {
|
||||
const stashes = await unstashMovie(req.params.movieId, req.params.stashId, req.user);
|
||||
const stashes = await unstashMovie(Number(req.params.movieId), Number(req.params.stashId), req.user);
|
||||
|
||||
res.send(stashes);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user