Storing directors.
|
@ -68,6 +68,20 @@
|
|||
:tags="release.tags"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-if="release.directors"
|
||||
class="row"
|
||||
>
|
||||
<span class="row-label">Director</span>
|
||||
|
||||
<router-link
|
||||
v-for="director in release.directors"
|
||||
:key="`director-${director.id}`"
|
||||
class="link director"
|
||||
:to="`/director/${director.id}/${director.slug}`"
|
||||
>{{ director.name }}</router-link>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="release.movies && release.movies.length > 0"
|
||||
class="row"
|
||||
|
@ -423,6 +437,10 @@ export default {
|
|||
color: var(--link);
|
||||
text-decoration: none;
|
||||
|
||||
&.director:not(:last-child)::after {
|
||||
content: ', ';
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--primary);
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ function curateRelease(release) {
|
|||
if (release.trailer) curatedRelease.trailer = release.trailer.media;
|
||||
if (release.teaser) curatedRelease.teaser = release.teaser.media;
|
||||
if (release.actors) curatedRelease.actors = release.actors.filter(Boolean).map(actor => curateActor(actor.actor || actor, curatedRelease));
|
||||
if (release.directors) curatedRelease.directors = release.directors.filter(Boolean).map(director => curateActor(director.director || director, curatedRelease));
|
||||
if (release.movieTags && release.movieTags.length > 0) curatedRelease.tags = release.movieTags.filter(Boolean).map(({ tag }) => tag);
|
||||
if (release.movieActors && release.movieActors.length > 0) curatedRelease.actors = release.movieActors.filter(Boolean).map(({ actor }) => curateActor(actor, curatedRelease));
|
||||
|
||||
|
|
|
@ -82,6 +82,14 @@ const releaseActorsFragment = `
|
|||
}
|
||||
`;
|
||||
|
||||
const releaseDirectorFragment = `
|
||||
directors: releasesDirectors(orderBy: ACTOR_BY_DIRECTOR_ID__NAME_ASC) {
|
||||
director {
|
||||
${actorFields}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const releaseTagsFragment = `
|
||||
tags: releasesTags(orderBy: TAG_BY_TAG_ID__PRIORITY_DESC) {
|
||||
tag {
|
||||
|
@ -261,6 +269,7 @@ const releaseFragment = `
|
|||
comment
|
||||
url
|
||||
${releaseActorsFragment}
|
||||
${releaseDirectorFragment}
|
||||
${releaseTagsFragment}
|
||||
${releasePosterFragment}
|
||||
${releasePhotosFragment}
|
||||
|
|
|
@ -67,6 +67,23 @@ const routes = [
|
|||
component: Actor,
|
||||
name: 'actorRange',
|
||||
},
|
||||
{
|
||||
path: '/director/:actorId/:actorSlug',
|
||||
name: 'director',
|
||||
redirect: from => ({
|
||||
name: 'directorRange',
|
||||
params: {
|
||||
...from.params,
|
||||
range: 'latest',
|
||||
pageNumber: 1,
|
||||
},
|
||||
}),
|
||||
},
|
||||
{
|
||||
path: '/director/:actorId/:actorSlug',
|
||||
component: Actor,
|
||||
name: 'directorRange',
|
||||
},
|
||||
{
|
||||
path: '/channel/:entitySlug',
|
||||
redirect: from => ({
|
||||
|
|
|
@ -599,20 +599,6 @@ exports.up = knex => Promise.resolve()
|
|||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('directors', (table) => {
|
||||
table.increments('id', 12);
|
||||
|
||||
table.text('name');
|
||||
table.integer('alias_for', 12)
|
||||
.references('id')
|
||||
.inTable('directors');
|
||||
|
||||
table.text('slug', 32)
|
||||
.unique();
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('releases', (table) => {
|
||||
table.increments('id', 16);
|
||||
|
||||
|
@ -702,12 +688,21 @@ exports.up = knex => Promise.resolve()
|
|||
.inTable('releases')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.integer('director_id', 8)
|
||||
table.integer('director_id', 12)
|
||||
.notNullable()
|
||||
.references('id')
|
||||
.inTable('directors');
|
||||
.inTable('actors')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.integer('alias_id', 12)
|
||||
.references('id')
|
||||
.inTable('actors')
|
||||
.onDelete('cascade');
|
||||
|
||||
table.unique(['release_id', 'director_id']);
|
||||
|
||||
table.datetime('created_at')
|
||||
.defaultTo(knex.fn.now());
|
||||
}))
|
||||
.then(() => knex.schema.createTable('releases_posters', (table) => {
|
||||
table.integer('release_id', 16)
|
||||
|
@ -1236,7 +1231,6 @@ exports.down = (knex) => { // eslint-disable-line arrow-body-style
|
|||
DROP TABLE IF EXISTS chapters CASCADE;
|
||||
DROP TABLE IF EXISTS releases CASCADE;
|
||||
DROP TABLE IF EXISTS actors CASCADE;
|
||||
DROP TABLE IF EXISTS directors CASCADE;
|
||||
DROP TABLE IF EXISTS tags CASCADE;
|
||||
DROP TABLE IF EXISTS tags_groups CASCADE;
|
||||
DROP TABLE IF EXISTS social CASCADE;
|
||||
|
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 709 B |
Before Width: | Height: | Size: 640 B After Width: | Height: | Size: 640 B |
|
@ -2,18 +2,33 @@
|
|||
"name": "traxxx",
|
||||
"short_name": "traxxx",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/img/favicon/android-chrome-32x32.png",
|
||||
"sizes": "32x32",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/img/favicon/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/img/favicon/android-chrome-194x194.png",
|
||||
"sizes": "194x194",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/img/favicon/android-chrome-196x196.png",
|
||||
"sizes": "194x194",
|
||||
"type": "image/png"
|
||||
},
|
||||
{
|
||||
"src": "/img/favicon/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#ffffff",
|
||||
"theme_color": "#ff6c88",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
||||
|
|
After Width: | Height: | Size: 148 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 41 KiB |
|
@ -841,6 +841,7 @@ const tagPhotos = [
|
|||
['fake-cum', 3, 'Alexia Anders in "Thanksgiving Creampies" for Cum 4K'],
|
||||
['fake-cum', 0, 'Jynx Maze for Cumshot Surprise (Porn Pros)'],
|
||||
['fake-cum', 1, 'Ricki White for Fucked Up Facials'],
|
||||
['fake-cum', 4, 'Vina Sky in "Creaming Her Pipes" for Anal 4K'],
|
||||
['femdom', 1, 'Little Caprice in "Femdom" for Little Caprice Dreams'],
|
||||
['fingering', 2, 'Kylie Page and Hadley Viscara in "Busty Blonde Bombshells" for LesbianX'],
|
||||
['fingering', 0, 'Ashly Anderson in "Rough Love" for Hookup Hotshot'],
|
||||
|
|
|
@ -760,8 +760,6 @@ async function scrapeActors(argNames) {
|
|||
const actorNames = await getActorNames(argNames);
|
||||
const baseActors = toBaseActors(actorNames);
|
||||
|
||||
console.log(baseActors);
|
||||
|
||||
logger.info(`Scraping profiles for ${actorNames.length} actors`);
|
||||
|
||||
const sources = argv.profileSources || config.profiles || Object.keys(scrapers.actors);
|
||||
|
@ -898,13 +896,17 @@ async function getOrCreateActors(baseActors, batchId) {
|
|||
return existingActors;
|
||||
}
|
||||
|
||||
async function associateActors(releases, batchId) {
|
||||
async function associatePeople(releases, batchId, type = 'actor') {
|
||||
try {
|
||||
const baseActorsByReleaseId = releases.reduce((acc, release) => {
|
||||
if (release.actors) {
|
||||
if (type === 'actors' && release.actors) {
|
||||
acc[release.id] = toBaseActors(release.actors, release);
|
||||
}
|
||||
|
||||
if (type === 'directors' && release.director) {
|
||||
acc[release.id] = toBaseActors([release.director], release);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
|
@ -922,6 +924,11 @@ async function associateActors(releases, batchId) {
|
|||
const uniqueBaseActors = Object.values(baseActorsBySlug);
|
||||
const actors = await getOrCreateActors(uniqueBaseActors, batchId);
|
||||
|
||||
const personKey = ({
|
||||
actors: 'actor_id',
|
||||
directors: 'director_id',
|
||||
})[type];
|
||||
|
||||
const actorIdsByEntityIdEntryIdAndSlug = actors.reduce((acc, actor) => ({
|
||||
...acc,
|
||||
[actor.entity_id]: {
|
||||
|
@ -929,7 +936,7 @@ async function associateActors(releases, batchId) {
|
|||
[actor.entry_id]: {
|
||||
...acc[actor.entity_id]?.[actor.entry_id],
|
||||
[actor.slug]: {
|
||||
actor_id: actor.alias_for || actor.id,
|
||||
[personKey]: actor.alias_for || actor.id,
|
||||
alias_id: actor.alias_for ? actor.id : null,
|
||||
},
|
||||
},
|
||||
|
@ -944,15 +951,15 @@ async function associateActors(releases, batchId) {
|
|||
})))
|
||||
.flat();
|
||||
|
||||
const validReleaseActorAssociations = releaseActorAssociations.filter(association => association.release_id && association.actor_id);
|
||||
const validReleaseActorAssociations = releaseActorAssociations.filter(association => association.release_id && association[personKey]);
|
||||
|
||||
if (releaseActorAssociations.length > validReleaseActorAssociations.length) {
|
||||
const invalidReleaseActorAssociations = releaseActorAssociations.filter(association => !association.release_id || !association.actor_id);
|
||||
const invalidReleaseActorAssociations = releaseActorAssociations.filter(association => !association.release_id || !association[personKey]);
|
||||
|
||||
logger.error(invalidReleaseActorAssociations);
|
||||
}
|
||||
|
||||
await bulkInsert('releases_actors', validReleaseActorAssociations, false);
|
||||
await bulkInsert(`releases_${type}`, validReleaseActorAssociations, false);
|
||||
|
||||
logger.verbose(`Associated ${releaseActorAssociations.length} actors to ${releases.length} scenes`);
|
||||
|
||||
|
@ -964,6 +971,14 @@ async function associateActors(releases, batchId) {
|
|||
}
|
||||
}
|
||||
|
||||
async function associateActors(releases, batchId) {
|
||||
return associatePeople(releases, batchId, 'actors');
|
||||
}
|
||||
|
||||
async function associateDirectors(releases, batchId) {
|
||||
return associatePeople(releases, batchId, 'directors');
|
||||
}
|
||||
|
||||
async function fetchActor(actorId) {
|
||||
const actor = await knex('actors')
|
||||
.select(knex.raw(`
|
||||
|
@ -1081,6 +1096,7 @@ async function flushActors() {
|
|||
|
||||
module.exports = {
|
||||
associateActors,
|
||||
associateDirectors,
|
||||
deleteActors,
|
||||
fetchActor,
|
||||
flushActors,
|
||||
|
|
|
@ -9,7 +9,7 @@ const slugify = require('./utils/slugify');
|
|||
const bulkInsert = require('./utils/bulk-insert');
|
||||
const resolvePlace = require('./utils/resolve-place');
|
||||
const { formatDate } = require('./utils/qu');
|
||||
const { associateActors, scrapeActors, toBaseActors } = require('./actors');
|
||||
const { associateActors, associateDirectors, scrapeActors, toBaseActors } = require('./actors');
|
||||
const { associateReleaseTags } = require('./tags');
|
||||
const { curateEntity } = require('./entities');
|
||||
const { associateReleaseMedia } = require('./media');
|
||||
|
@ -229,6 +229,7 @@ async function updateReleasesSearch(releaseIds) {
|
|||
COALESCE(releases.shoot_id, '') || ' ' ||
|
||||
COALESCE(TO_CHAR(releases.date, 'YYYY YY MM FMMM FMmonth mon DD FMDD'), '') || ' ' ||
|
||||
STRING_AGG(COALESCE(actors.name, ''), ' ') || ' ' ||
|
||||
STRING_AGG(COALESCE(directors.name, ''), ' ') || ' ' ||
|
||||
STRING_AGG(COALESCE(tags.name, ''), ' ') || ' ' ||
|
||||
STRING_AGG(COALESCE(tags_aliases.name, ''), ' ')
|
||||
) as document
|
||||
|
@ -236,8 +237,10 @@ async function updateReleasesSearch(releaseIds) {
|
|||
LEFT JOIN entities ON releases.entity_id = entities.id
|
||||
LEFT JOIN entities AS parents ON parents.id = entities.parent_id
|
||||
LEFT JOIN releases_actors AS local_actors ON local_actors.release_id = releases.id
|
||||
LEFT JOIN releases_directors AS local_directors ON local_directors.release_id = releases.id
|
||||
LEFT JOIN releases_tags AS local_tags ON local_tags.release_id = releases.id
|
||||
LEFT JOIN actors ON local_actors.actor_id = actors.id
|
||||
LEFT JOIN actors AS directors ON local_directors.director_id = directors.id
|
||||
LEFT JOIN tags ON local_tags.tag_id = tags.id AND tags.priority >= 6
|
||||
LEFT JOIN tags as tags_aliases ON local_tags.tag_id = tags_aliases.alias_for AND tags_aliases.secondary = true
|
||||
${releaseIds ? 'WHERE releases.id = ANY(?)' : ''}
|
||||
|
@ -319,6 +322,7 @@ async function storeScenes(releases) {
|
|||
|
||||
const [actors] = await Promise.all([
|
||||
associateActors(releasesWithId, batchId),
|
||||
associateDirectors(releasesWithId, batchId),
|
||||
associateReleaseTags(releasesWithId),
|
||||
storeChapters(releasesWithId),
|
||||
]);
|
||||
|
|