forked from DebaucheryLibrarian/traxxx
Added stash transfer tool.
This commit is contained in:
parent
f7708e0740
commit
56534800d8
|
@ -10,7 +10,8 @@ config/*
|
||||||
!config/default.js
|
!config/default.js
|
||||||
assets/js/config/
|
assets/js/config/
|
||||||
!assets/js/config/default.js
|
!assets/js/config/default.js
|
||||||
export*
|
/export*
|
||||||
|
/stashes*
|
||||||
*.heapprofile
|
*.heapprofile
|
||||||
*.heapsnapshot
|
*.heapsnapshot
|
||||||
.vscode
|
.vscode
|
||||||
|
|
|
@ -67,21 +67,21 @@
|
||||||
v-show="(!stash || stash.primary) && favorited"
|
v-show="(!stash || stash.primary) && favorited"
|
||||||
icon="heart7"
|
icon="heart7"
|
||||||
class="stash stashed"
|
class="stash stashed"
|
||||||
@click.prevent.native="unstashActor"
|
@click.stop.native="unstashActor"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
v-show="(!stash || stash.primary) && favorited === false"
|
v-show="(!stash || stash.primary) && favorited === false"
|
||||||
icon="heart8"
|
icon="heart8"
|
||||||
class="stash unstashed"
|
class="stash unstashed"
|
||||||
@click.prevent.native="stashActor"
|
@click.stop.native="stashActor"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Icon
|
<Icon
|
||||||
v-show="stash && !stash.primary"
|
v-show="stash && !stash.primary"
|
||||||
icon="cross2"
|
icon="cross2"
|
||||||
class="stash unstash"
|
class="stash unstash"
|
||||||
@click.prevent.native="unstashActor"
|
@click.stop.native="unstashActor"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span class="details">
|
<span class="details">
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<RouterLink
|
<RouterLink
|
||||||
v-if="me && favorites"
|
v-if="me && favorites"
|
||||||
:to="{ name: 'stash', params: { stashId: favorites.id, range: 'scenes', pageNumber: 1 } }"
|
:to="{ name: 'stash', params: { stashId: favorites.id, stashSlug: favorites.slug, username: me.username, range: 'scenes', pageNumber: 1 } }"
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
><Icon icon="heart7" />Favorites</RouterLink>
|
><Icon icon="heart7" />Favorites</RouterLink>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
exports.up = async (knex) => {
|
||||||
|
await knex.schema.alterTable('stashes', (table) => {
|
||||||
|
table.unique(['user_id', 'slug']);
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.raw(`
|
||||||
|
CREATE UNIQUE INDEX unique_primary ON stashes (user_id, "primary") WHERE ("primary" = TRUE);
|
||||||
|
`);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = async (knex) => {
|
||||||
|
await knex.schema.alterTable('stashes', (table) => {
|
||||||
|
table.dropUnique(['user_id', 'slug']);
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.raw(`
|
||||||
|
DROP INDEX unique_primary;
|
||||||
|
`);
|
||||||
|
};
|
|
@ -0,0 +1,133 @@
|
||||||
|
const fs = require('fs');
|
||||||
|
const knex = require('../knex');
|
||||||
|
const args = require('../argv');
|
||||||
|
|
||||||
|
async function getStashId(stash, user) {
|
||||||
|
const existingStash = await knex('stashes')
|
||||||
|
.select('id')
|
||||||
|
.where('user_id', user.id)
|
||||||
|
.where((builder) => {
|
||||||
|
builder
|
||||||
|
.where('slug', stash.slug)
|
||||||
|
.orWhere('primary', stash.primary);
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (existingStash) {
|
||||||
|
return existingStash.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [stashId] = await knex('stashes')
|
||||||
|
.insert({
|
||||||
|
user_id: user.id,
|
||||||
|
name: stash.name,
|
||||||
|
slug: stash.slug,
|
||||||
|
public: stash.public,
|
||||||
|
created_at: stash.createdAt,
|
||||||
|
})
|
||||||
|
.returning('id');
|
||||||
|
|
||||||
|
return stashId;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function importReleases(type, stash, user, filename) {
|
||||||
|
const curatedType = type === 'release' ? 'scene' : type;
|
||||||
|
|
||||||
|
await stash[`${curatedType}s`].reduce(async (chain, scene) => {
|
||||||
|
await chain;
|
||||||
|
|
||||||
|
const release = await knex(`${type}s`)
|
||||||
|
.select(`${type}s.id`, 'entities.id as entity_id', 'entities.name as entity_name')
|
||||||
|
.leftJoin('entities', 'entities.id', `${type}s.entity_id`)
|
||||||
|
.where(`${type}s.entry_id`, scene.entryId)
|
||||||
|
.where('entities.slug', scene.entitySlug)
|
||||||
|
.where('entities.type', scene.entityType)
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (!release) {
|
||||||
|
throw new Error(`${curatedType.slice(0, 1).toUpperCase}${curatedType.slice(1)} ${scene.title} in ${scene.entityType} ${scene.entitySlug} does not exist`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await knex(`stashes_${curatedType}s`)
|
||||||
|
.insert({
|
||||||
|
stash_id: stash.id,
|
||||||
|
[`${curatedType}_id`]: release.id,
|
||||||
|
comment: `import ${filename}`,
|
||||||
|
created_at: scene.createdAt,
|
||||||
|
})
|
||||||
|
.onConflict(['stash_id', `${curatedType}_id`])
|
||||||
|
.ignore();
|
||||||
|
|
||||||
|
console.log(`Imported ${stash.username} stash ${release.entity_name} ${curatedType} "${scene.title}"`);
|
||||||
|
}, Promise.resolve());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function importActors(stash, user, filename) {
|
||||||
|
await stash.actors.reduce(async (chain, actor) => {
|
||||||
|
await chain;
|
||||||
|
|
||||||
|
const actorEntry = await knex('actors')
|
||||||
|
.select('actors.*')
|
||||||
|
.leftJoin('entities', 'entities.id', 'actors.entity_id')
|
||||||
|
.where('actors.slug', actor.slug)
|
||||||
|
.where((builder) => {
|
||||||
|
if (actor.entitySlug) {
|
||||||
|
builder
|
||||||
|
.where('entities.slug', actor.entitySlug)
|
||||||
|
.where('entities.type', actor.entityType);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (!actorEntry) {
|
||||||
|
throw new Error(`Actor ${actor.slug} in ${user.username} stash ${stash.name} does not exist`);
|
||||||
|
}
|
||||||
|
|
||||||
|
await knex('stashes_actors')
|
||||||
|
.insert({
|
||||||
|
stash_id: stash.id,
|
||||||
|
actor_id: actorEntry.id,
|
||||||
|
comment: `import ${filename}`,
|
||||||
|
created_at: actor.createdAt,
|
||||||
|
})
|
||||||
|
.onConflict(['stash_id', 'actor_id'])
|
||||||
|
.ignore();
|
||||||
|
|
||||||
|
console.log(`Imported ${stash.username} stash actor "${actorEntry.name}"`);
|
||||||
|
}, Promise.resolve());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function load() {
|
||||||
|
const filename = process.argv[2];
|
||||||
|
const file = await fs.promises.readFile(filename, 'utf8');
|
||||||
|
|
||||||
|
const stashes = file.split('\n')
|
||||||
|
.filter(Boolean)
|
||||||
|
.map((data) => JSON.parse(data))
|
||||||
|
.filter((stash) => !args.username || stash.username === args.username);
|
||||||
|
|
||||||
|
await stashes.reduce(async (stashChain, stash, index) => {
|
||||||
|
await stashChain;
|
||||||
|
|
||||||
|
const user = await knex('users')
|
||||||
|
.select('id')
|
||||||
|
.where('username', stash.username)
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw new Error(`No user '${stash.username}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const stashId = await getStashId(stash, user);
|
||||||
|
|
||||||
|
await importReleases('release', { ...stash, id: stashId }, user, filename);
|
||||||
|
await importReleases('movie', { ...stash, id: stashId }, user, filename);
|
||||||
|
await importActors({ ...stash, id: stashId }, user, filename);
|
||||||
|
|
||||||
|
console.log(`Imported ${index + 1}/${stashes.length} stash ${stash.name} from ${stash.username}`);
|
||||||
|
}, Promise.resolve());
|
||||||
|
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
load();
|
|
@ -0,0 +1,84 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// const config = require('config');
|
||||||
|
// const util = require('util');
|
||||||
|
// const path = require('path');
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const moment = require('moment');
|
||||||
|
|
||||||
|
const knex = require('../knex');
|
||||||
|
|
||||||
|
async function save() {
|
||||||
|
const stashes = await knex('stashes')
|
||||||
|
.select('stashes.*', 'users.username')
|
||||||
|
.leftJoin('users', 'users.id', 'stashes.user_id');
|
||||||
|
|
||||||
|
const filename = `stashes-${moment().format('YYYY-MM-DD_hh_mm')}.json`;
|
||||||
|
let savedStashes = 0;
|
||||||
|
|
||||||
|
await stashes.reduce(async (chain, stash) => {
|
||||||
|
await chain;
|
||||||
|
|
||||||
|
const scenes = await knex('stashes_scenes')
|
||||||
|
.select('releases.title', 'releases.created_at', 'releases.entry_id', 'entities.slug as entity_slug', 'entities.type as entity_type')
|
||||||
|
.leftJoin('releases', 'releases.id', 'stashes_scenes.scene_id')
|
||||||
|
.leftJoin('entities', 'entities.id', 'releases.entity_id')
|
||||||
|
.where('stashes_scenes.stash_id', stash.id);
|
||||||
|
|
||||||
|
const movies = await knex('stashes_movies')
|
||||||
|
.select('movies.title', 'movies.created_at', 'movies.entry_id', 'entities.slug as entity_slug', 'entities.type as entity_type')
|
||||||
|
.leftJoin('movies', 'movies.id', 'stashes_movies.movie_id')
|
||||||
|
.leftJoin('entities', 'entities.id', 'movies.entity_id')
|
||||||
|
.where('stashes_movies.stash_id', stash.id);
|
||||||
|
|
||||||
|
const actors = await knex('stashes_actors')
|
||||||
|
.select('actors.slug', 'actors.created_at', 'entities.slug as entity_slug', 'entities.type as entity_type')
|
||||||
|
.leftJoin('actors', 'actors.id', 'stashes_actors.actor_id')
|
||||||
|
.leftJoin('entities', 'entities.id', 'actors.entity_id')
|
||||||
|
.where('stashes_actors.stash_id', stash.id);
|
||||||
|
|
||||||
|
console.log('scenes', scenes);
|
||||||
|
console.log('movies', movies);
|
||||||
|
console.log('actors', actors);
|
||||||
|
|
||||||
|
const curatedStash = JSON.stringify({
|
||||||
|
username: stash.username,
|
||||||
|
name: stash.name,
|
||||||
|
slug: stash.slug,
|
||||||
|
public: stash.public,
|
||||||
|
primary: stash.primary,
|
||||||
|
createdAt: stash.created_at,
|
||||||
|
scenes: scenes.map((scene) => ({
|
||||||
|
title: scene.title,
|
||||||
|
entryId: scene.entry_id,
|
||||||
|
entitySlug: scene.entity_slug,
|
||||||
|
entityType: scene.entity_type,
|
||||||
|
createdAt: scene.created_at,
|
||||||
|
})),
|
||||||
|
movies: movies.map((movie) => ({
|
||||||
|
title: movie.title,
|
||||||
|
entryId: movie.entry_id,
|
||||||
|
entitySlug: movie.entity_slug,
|
||||||
|
entityType: movie.entity_type,
|
||||||
|
createdAt: movie.created_at,
|
||||||
|
})),
|
||||||
|
actors: actors.map((actor) => ({
|
||||||
|
slug: actor.slug,
|
||||||
|
entitySlug: actor.entity_slug,
|
||||||
|
entityType: actor.entity_type,
|
||||||
|
createdAt: actor.created_at,
|
||||||
|
})),
|
||||||
|
});
|
||||||
|
|
||||||
|
await fs.promises.appendFile(filename, `${curatedStash}\n`);
|
||||||
|
|
||||||
|
savedStashes += 1;
|
||||||
|
}, Promise.resolve([]));
|
||||||
|
|
||||||
|
console.log(`Saved ${savedStashes} stashes`);
|
||||||
|
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
save();
|
Loading…
Reference in New Issue