Compare commits
25 Commits
e6919a4283
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 35ffc2b0f7 | |||
| 383844dda8 | |||
| 77fb6595a2 | |||
| aa3adbe634 | |||
| 59a700c2f3 | |||
| 18f5a6f476 | |||
| 63a178ca57 | |||
| 0ae949a616 | |||
| edc9720623 | |||
| bbc3fbb0a5 | |||
| 1fc468efac | |||
| 143c415797 | |||
| e79a4d48e1 | |||
| 343325440e | |||
| 5c018892d3 | |||
| be61293cbe | |||
| e493194ce1 | |||
| b61631c33c | |||
| fa65da75bc | |||
| a4468f18dc | |||
| fea28b71ba | |||
| 884ad891f3 | |||
| 058161f798 | |||
| aa68748817 | |||
| 928857596f |
@@ -19,6 +19,9 @@
|
|||||||
|
|
||||||
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0,interactive-widget=resizes-content" />
|
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0,interactive-widget=resizes-content" />
|
||||||
|
|
||||||
|
<!-- RTA restricted to adults label -->
|
||||||
|
<meta name="RATING" content="RTA-5042-1996-1400-1577-RTA" />
|
||||||
|
|
||||||
<title>traxxx - Consent</title>
|
<title>traxxx - Consent</title>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
@@ -156,6 +159,12 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.rta {
|
||||||
|
position: fixed;
|
||||||
|
bottom: .5rem;
|
||||||
|
right: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
@media(max-width: 800px) {
|
@media(max-width: 800px) {
|
||||||
.heading {
|
.heading {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
@@ -219,5 +228,12 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<img
|
||||||
|
src="/img/rta.gif"
|
||||||
|
alt="RTA Restricted To Adults"
|
||||||
|
title="RTA Restricted To Adults"
|
||||||
|
class="rta"
|
||||||
|
>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
2
common
2
common
Submodule common updated: ec4b15ce33...e4d6ff6ad1
@@ -105,7 +105,7 @@
|
|||||||
class="bio-item residence"
|
class="bio-item residence"
|
||||||
:class="{ hideable: !!actor.origin }"
|
:class="{ hideable: !!actor.origin }"
|
||||||
>
|
>
|
||||||
<dfn class="bio-label"><Icon icon="location" />Lives in</dfn>
|
<dfn class="bio-label"><Icon icon="location" />{{ actor.dateOfDeath ? 'Lived' : 'Lives' }} in</dfn>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
<span
|
<span
|
||||||
@@ -312,10 +312,10 @@
|
|||||||
<a
|
<a
|
||||||
v-for="social in socials"
|
v-for="social in socials"
|
||||||
:key="`social-${social.id}`"
|
:key="`social-${social.id}`"
|
||||||
|
v-tooltip="social.platform ? `${social.platform} ${env.socials.prefix[social.platform] || env.socials.prefix.default}${social.handle}` : social.url"
|
||||||
:href="getSocialUrl(social)"
|
:href="getSocialUrl(social)"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
:title="social.platform || social.url"
|
|
||||||
class="social ellipsis"
|
class="social ellipsis"
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
@@ -339,7 +339,9 @@
|
|||||||
:class="`icon-social icon-${social.platform} icon-generic`"
|
:class="`icon-social icon-${social.platform} icon-generic`"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!--
|
||||||
<template v-if="social.platform">{{ env.socials.prefix[social.platform] || env.socials.prefix.default }}</template>{{ social.handle }}
|
<template v-if="social.platform">{{ env.socials.prefix[social.platform] || env.socials.prefix.default }}</template>{{ social.handle }}
|
||||||
|
-->
|
||||||
</a>
|
</a>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -498,7 +500,7 @@ function getSocialUrl(social) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const socials = props.actor.socials.map((social) => ({
|
const socials = props.actor.socials.slice(0, 10).map((social) => ({
|
||||||
...social,
|
...social,
|
||||||
handle: social.url
|
handle: social.url
|
||||||
? new URL(social.url).hostname
|
? new URL(social.url).hostname
|
||||||
@@ -735,19 +737,23 @@ const socials = props.actor.socials.map((social) => ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
.socials {
|
.socials {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
/*
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
|
||||||
grid-gap: 0 0;
|
grid-gap: 0 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
*/
|
||||||
gap: .25rem;
|
gap: .25rem;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.social {
|
.social {
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
height: 2rem;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: .1rem .5rem;
|
justify-content: center;
|
||||||
|
padding: .75rem .75rem;
|
||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
@@ -755,10 +761,6 @@ const socials = props.actor.socials.map((social) => ({
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
background: var(--highlight-weak-40);
|
background: var(--highlight-weak-40);
|
||||||
|
|
||||||
.icon {
|
|
||||||
margin-right: .5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-generic {
|
.icon-generic {
|
||||||
fill: var(--highlight);
|
fill: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
<span
|
<span
|
||||||
v-if="actor.ageAtDeath"
|
v-if="actor.ageAtDeath"
|
||||||
:title="`Passed ${formatDate(actor.ageAtDeath, 'MMMM d, yyyy')}`"
|
:title="`Passed ${formatDate(actor.dateOfDeath, 'MMMM d, yyyy')}`"
|
||||||
class="age age-death"
|
class="age age-death"
|
||||||
>{{ actor.ageAtDeath }}</span>
|
>{{ actor.ageAtDeath }}</span>
|
||||||
|
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ const expanded = ref(new Set());
|
|||||||
|
|
||||||
const mappedKeys = {
|
const mappedKeys = {
|
||||||
actors: actorsById,
|
actors: actorsById,
|
||||||
tags: tagsById,
|
// tags: tagsById,
|
||||||
movies: moviesById,
|
movies: moviesById,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -292,6 +292,16 @@ const curatedRevisions = computed(() => revisions.value.map((revision) => {
|
|||||||
}))];
|
}))];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === 'tags') {
|
||||||
|
return [key, value.map((tag) => ({
|
||||||
|
id: tag.id,
|
||||||
|
name: tag.actorId
|
||||||
|
? `${actorsById.value[tag.actorId]?.name}: ${tagsById.value[tag.id]?.name}`
|
||||||
|
: tagsById.value[tag.id]?.name,
|
||||||
|
modified: revision.deltas.some((delta) => delta.key === key && !delta.value.some((deltaTag) => deltaTag.id === tag.id && (!Object.hasOwn(tag, 'actorId') || deltaTag.actorId === tag.actorId))),
|
||||||
|
}))];
|
||||||
|
}
|
||||||
|
|
||||||
if (key === 'socials') {
|
if (key === 'socials') {
|
||||||
// new socials don't have IDs yet, so we need to compare the values
|
// new socials don't have IDs yet, so we need to compare the values
|
||||||
return [key, value.map((item) => ({
|
return [key, value.map((item) => ({
|
||||||
@@ -323,6 +333,19 @@ const curatedRevisions = computed(() => revisions.value.map((revision) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (delta.key === 'tags') {
|
||||||
|
return {
|
||||||
|
...delta,
|
||||||
|
value: delta.value.map((tag) => ({
|
||||||
|
id: tag.id,
|
||||||
|
name: tag.actorId
|
||||||
|
? `${actorsById.value[tag.actorId]?.name}: ${tagsById.value[tag.id]?.name}`
|
||||||
|
: tagsById.value[tag.id]?.name,
|
||||||
|
modified: !revision.base[delta.key].some((baseTag) => baseTag.id === tag.id && (!Object.hasOwn(baseTag, 'actorId') || baseTag.actorId === tag.actorId)),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (delta.key === 'socials') {
|
if (delta.key === 'socials') {
|
||||||
// new socials don't have IDs yet, so we need to compare the values
|
// new socials don't have IDs yet, so we need to compare the values
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -12,25 +12,25 @@
|
|||||||
<Icon icon="search" />
|
<Icon icon="search" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<!--
|
<template v-if="isActorTagsAvailable">
|
||||||
<div
|
<div
|
||||||
v-show="showActorTags"
|
v-show="showActorTags"
|
||||||
v-tooltip="'Tags relevant to the selected actors'"
|
v-tooltip="'Tags relevant to the selected actors'"
|
||||||
class="filter-sort order noselect"
|
class="filter-sort order noselect"
|
||||||
@click="showActorTags = false"
|
@click="showActorTags = false"
|
||||||
>
|
>
|
||||||
<Icon icon="user-tags" />
|
<Icon icon="user-tags" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-show="!showActorTags"
|
v-show="!showActorTags"
|
||||||
v-tooltip="'All tags'"
|
v-tooltip="'All tags'"
|
||||||
class="filter-sort order noselect"
|
class="filter-sort order noselect"
|
||||||
@click="showActorTags = true"
|
@click="showActorTags = true"
|
||||||
>
|
>
|
||||||
<Icon icon="price-tags" />
|
<Icon icon="price-tags" />
|
||||||
</div>
|
</div>
|
||||||
-->
|
</template>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-show="order === 'priority'"
|
v-show="order === 'priority'"
|
||||||
@@ -142,13 +142,17 @@ const props = defineProps({
|
|||||||
const emit = defineEmits(['update']);
|
const emit = defineEmits(['update']);
|
||||||
|
|
||||||
const { pageProps } = inject('pageContext');
|
const { pageProps } = inject('pageContext');
|
||||||
// const { tag: pageTag, actor: pageActor } = pageProps;
|
|
||||||
const { tag: pageTag } = pageProps;
|
const {
|
||||||
|
tag: pageTag,
|
||||||
|
actor: pageActor,
|
||||||
|
stash: pageStash,
|
||||||
|
} = pageProps;
|
||||||
|
|
||||||
const search = ref('');
|
const search = ref('');
|
||||||
const searchRegexp = computed(() => new RegExp(search.value, 'i'));
|
const searchRegexp = computed(() => new RegExp(search.value, 'i'));
|
||||||
const order = ref('priority');
|
const order = ref('priority');
|
||||||
// const showActorTags = ref(true);
|
const showActorTags = ref(!!pageActor);
|
||||||
|
|
||||||
const priorityTags = [
|
const priorityTags = [
|
||||||
'anal',
|
'anal',
|
||||||
@@ -173,13 +177,13 @@ const priorityTags = [
|
|||||||
'lesbian',
|
'lesbian',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const isActorTagsAvailable = computed(() => props.actorTags && (props.filters.actors.length > 0 || pageActor) && !pageStash);
|
||||||
|
|
||||||
const groupedTags = computed(() => {
|
const groupedTags = computed(() => {
|
||||||
/*
|
// can't show actor tags inside stash, because both require a join, and manticore currently only supports one
|
||||||
const tags = showActorTags.value && props.actorTags && (props.filters.actors.length > 0 || pageActor)
|
const tags = showActorTags.value && isActorTagsAvailable.value
|
||||||
? props.actorTags
|
? props.actorTags
|
||||||
: props.tags;
|
: props.tags;
|
||||||
*/
|
|
||||||
const tags = props.tags;
|
|
||||||
|
|
||||||
const selected = tags.filter((tag) => props.filters.tags.includes(tag.slug));
|
const selected = tags.filter((tag) => props.filters.tags.includes(tag.slug));
|
||||||
const filtered = tags.filter((tag) => !props.filters.tags.includes(tag.slug)
|
const filtered = tags.filter((tag) => !props.filters.tags.includes(tag.slug)
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "traxxx-web",
|
"name": "traxxx-web",
|
||||||
"version": "0.48.0",
|
"version": "0.49.7",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"version": "0.48.0",
|
"version": "0.49.7",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@brillout/json-serializer": "^0.5.8",
|
"@brillout/json-serializer": "^0.5.8",
|
||||||
"@dicebear/collection": "^7.0.5",
|
"@dicebear/collection": "^7.0.5",
|
||||||
|
|||||||
@@ -92,7 +92,7 @@
|
|||||||
"overrides": {
|
"overrides": {
|
||||||
"vite": "$vite"
|
"vite": "$vite"
|
||||||
},
|
},
|
||||||
"version": "0.48.0",
|
"version": "0.49.7",
|
||||||
"imports": {
|
"imports": {
|
||||||
"#/*": "./*.js"
|
"#/*": "./*.js"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,19 +57,23 @@ export async function onBeforeRender(pageContext) {
|
|||||||
fetchReleases(pageContext, entityId),
|
fetchReleases(pageContext, entityId),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const entityIds = entity.isIndependent || !entity.parent
|
||||||
|
? [entity.id]
|
||||||
|
: [entity.id, entity.parent.id];
|
||||||
|
|
||||||
const campaigns = await getRandomCampaigns([
|
const campaigns = await getRandomCampaigns([
|
||||||
{
|
{
|
||||||
entityIds: [entity.id, entity.parent?.id].filter(Boolean),
|
entityIds,
|
||||||
minRatio: 3,
|
minRatio: 3,
|
||||||
allowRandomFallback: false,
|
allowRandomFallback: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
entityIds: [entity.id, entity.parent?.id].filter(Boolean),
|
entityIds,
|
||||||
minRatio: 3,
|
minRatio: 3,
|
||||||
allowRandomFallback: false,
|
allowRandomFallback: false,
|
||||||
},
|
},
|
||||||
pageContext.routeParams.domain === 'scenes' ? {
|
pageContext.routeParams.domain === 'scenes' ? {
|
||||||
entityIds: [entity.id, entity.parent?.id].filter(Boolean),
|
entityIds,
|
||||||
minRatio: 0.75,
|
minRatio: 0.75,
|
||||||
maxRatio: 1.25,
|
maxRatio: 1.25,
|
||||||
allowRandomFallback: false,
|
allowRandomFallback: false,
|
||||||
|
|||||||
BIN
public/img/rta.gif
Normal file
BIN
public/img/rta.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
@@ -70,6 +70,9 @@ async function onRenderHtml(pageContext) {
|
|||||||
|
|
||||||
<meta name="description" content="Keep track of new porn releases and re-discover classics from your favorite porn stars and sites" />
|
<meta name="description" content="Keep track of new porn releases and re-discover classics from your favorite porn stars and sites" />
|
||||||
|
|
||||||
|
<!-- RTA restricted to adults label -->
|
||||||
|
<meta name="RATING" content="RTA-5042-1996-1400-1577-RTA" />
|
||||||
|
|
||||||
${config.analytics.enabled ? dangerouslySkipEscape(`<script src="${config.analytics.address}" data-website-id="${config.analytics.siteId}" data-exclude-hash="true" async></script>`) : ''}
|
${config.analytics.enabled ? dangerouslySkipEscape(`<script src="${config.analytics.address}" data-website-id="${config.analytics.siteId}" data-exclude-hash="true" async></script>`) : ''}
|
||||||
|
|
||||||
<title>${title}</title>
|
<title>${title}</title>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ const keyMap = {
|
|||||||
isCircumcised: 'circumcised',
|
isCircumcised: 'circumcised',
|
||||||
};
|
};
|
||||||
|
|
||||||
const socialsOrder = ['onlyfans', 'twitter', 'fansly', 'loyalfans', 'manyvids', 'pornhub', 'linktree', null];
|
const socialsOrder = ['onlyfans', 'fansly', 'twitter', 'instagram', 'loyalfans', 'manyvids', 'pornhub', 'linktree', null];
|
||||||
|
|
||||||
export function curateActor(actor, context = {}) {
|
export function curateActor(actor, context = {}) {
|
||||||
return {
|
return {
|
||||||
@@ -80,6 +80,8 @@ export function curateActor(actor, context = {}) {
|
|||||||
ageThen: context.sceneDate && actor.date_of_birth && actor.date_of_birth.getFullYear() > 1
|
ageThen: context.sceneDate && actor.date_of_birth && actor.date_of_birth.getFullYear() > 1
|
||||||
? differenceInYears(context.sceneDate, actor.date_of_birth)
|
? differenceInYears(context.sceneDate, actor.date_of_birth)
|
||||||
: null,
|
: null,
|
||||||
|
dateOfBirth: actor.date_of_birth,
|
||||||
|
dateOfDeath: actor.date_of_death,
|
||||||
bust: actor.bust,
|
bust: actor.bust,
|
||||||
cup: actor.cup,
|
cup: actor.cup,
|
||||||
waist: actor.waist,
|
waist: actor.waist,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ function getWatchUrl(scene) {
|
|||||||
return new URL(scene.url).href;
|
return new URL(scene.url).href;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene.channel && (scene.channel.isIndependent || scene.channel.type === 'network')) {
|
if (scene.channel && (scene.channel.isIndependent || scene.channel.type === 'network' || !scene.network)) {
|
||||||
return new URL(scene.channel.url).href;
|
return new URL(scene.channel.url).href;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ function curateScene(rawScene, assets, reqUser, context) {
|
|||||||
slug: assets.channel.slug,
|
slug: assets.channel.slug,
|
||||||
name: censor(assets.channel.name, context.restriction),
|
name: censor(assets.channel.name, context.restriction),
|
||||||
type: assets.channel.type,
|
type: assets.channel.type,
|
||||||
|
url: assets.channel.url,
|
||||||
isIndependent: assets.channel.independent,
|
isIndependent: assets.channel.independent,
|
||||||
hasLogo: assets.channel.has_logo,
|
hasLogo: assets.channel.has_logo,
|
||||||
},
|
},
|
||||||
@@ -52,6 +53,7 @@ function curateScene(rawScene, assets, reqUser, context) {
|
|||||||
id: assets.channel.network_id,
|
id: assets.channel.network_id,
|
||||||
slug: assets.channel.network_slug,
|
slug: assets.channel.network_slug,
|
||||||
name: censor(assets.channel.network_name, context.restriction),
|
name: censor(assets.channel.network_name, context.restriction),
|
||||||
|
url: assets.network_url,
|
||||||
type: assets.channel.network_type,
|
type: assets.channel.network_type,
|
||||||
hasLogo: assets.channel.network_has_logo,
|
hasLogo: assets.channel.network_has_logo,
|
||||||
} : null,
|
} : null,
|
||||||
@@ -179,6 +181,7 @@ export async function fetchScenesById(sceneIds, { reqUser, ...context } = {}) {
|
|||||||
'networks.slug as network_slug',
|
'networks.slug as network_slug',
|
||||||
'networks.name as network_name',
|
'networks.name as network_name',
|
||||||
'networks.type as network_type',
|
'networks.type as network_type',
|
||||||
|
'networks.url as network_url',
|
||||||
'networks.has_logo as network_has_logo',
|
'networks.has_logo as network_has_logo',
|
||||||
knex.raw('row_to_json(affiliates) as affiliate'),
|
knex.raw('row_to_json(affiliates) as affiliate'),
|
||||||
)
|
)
|
||||||
@@ -402,10 +405,11 @@ function curateOptions(options) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function curateFacet(results, field, count = 'count(distinct id)') {
|
// function curateFacet(results, field, count = 'count(distinct id)') {
|
||||||
|
function curateFacet(results, field) {
|
||||||
return results
|
return results
|
||||||
.find((result) => result.columns[0][field] && result.columns[1][count])
|
.find((result) => result.columns[0][field] && (result.columns[1]['count(distinct id)'] || result.columns[1]['count(*)']))
|
||||||
?.data.map((row) => ({ key: row[field], doc_count: row[count] }))
|
?.data.map((row) => ({ key: row[field], doc_count: row['count(distinct id)'] || row['count(*)'] }))
|
||||||
.filter((row) => !!row.key)
|
.filter((row) => !!row.key)
|
||||||
|| [];
|
|| [];
|
||||||
}
|
}
|
||||||
@@ -432,6 +436,7 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
|||||||
:yearsFacet:
|
:yearsFacet:
|
||||||
:actorsFacet:
|
:actorsFacet:
|
||||||
:tagsFacet:
|
:tagsFacet:
|
||||||
|
:actorTagsFacet:
|
||||||
:channelsFacet:
|
:channelsFacet:
|
||||||
:studiosFacet:;
|
:studiosFacet:;
|
||||||
show meta;
|
show meta;
|
||||||
@@ -465,15 +470,14 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
|||||||
weight() as _score
|
weight() as _score
|
||||||
`));
|
`));
|
||||||
|
|
||||||
/*
|
// manticore only supports one joined table, so we can't use it inside stashes
|
||||||
// manticore only supports one joined table, so we can't use it inside stashes; probably not needed anyway (stashes only need global tags?)
|
|
||||||
builder
|
builder
|
||||||
.leftJoin('scenes_tags', 'scenes_tags.scene_id', 'scenes_.id')
|
.leftJoin('scenes_tags', 'scenes_tags.scene_id', 'scenes_.id')
|
||||||
.groupBy('scenes.id');
|
.groupBy('scenes.id');
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters.query) {
|
if (filters.query) {
|
||||||
|
// we exclude title because we have a curated title_filtered field for more effective results
|
||||||
builder.whereRaw('match(\'@!title :query:\', scenes)', { query: escape(filters.query) });
|
builder.whereRaw('match(\'@!title :query:\', scenes)', { query: escape(filters.query) });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,16 +578,14 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
|||||||
.offset((options.page - 1) * options.limit),
|
.offset((options.page - 1) * options.limit),
|
||||||
// option threads=1 fixes actors, but drastically slows down performance, wait for fix
|
// option threads=1 fixes actors, but drastically slows down performance, wait for fix
|
||||||
yearsFacet: options.aggregateYears ? knex.raw('facet effective_year as years_facet order by effective_year desc limit ?', [aggSize]) : null,
|
yearsFacet: options.aggregateYears ? knex.raw('facet effective_year as years_facet order by effective_year desc limit ?', [aggSize]) : null,
|
||||||
actorsFacet: options.aggregateActors ? knex.raw('facet scenes.actor_ids as actors_facet distinct id order by count(distinct id) desc limit ?', [aggSize]) : null,
|
actorsFacet: options.aggregateActors ? knex.raw('facet scenes.actor_ids as actors_facet distinct id order by count(*) desc limit ?', [aggSize]) : null,
|
||||||
// don't facet tags associated to other actors, actor ID 0 means global
|
// don't facet tags associated to other actors, actor ID 0 means global
|
||||||
tagsFacet: options.aggregateTags ? knex.raw('facet scenes.tag_ids as tags_facet order by count(distinct id) desc limit ?', [aggSize]) : null,
|
tagsFacet: options.aggregateTags ? knex.raw('facet scenes.tag_ids as tags_facet distinct id order by count(*) desc limit ?', [aggSize]) : null,
|
||||||
/*
|
|
||||||
actorTagsFacet: options.aggregateTags && !filters.stashId // eslint-disable-line no-nested-ternary
|
actorTagsFacet: options.aggregateTags && !filters.stashId // eslint-disable-line no-nested-ternary
|
||||||
? knex.raw(`facet IF(IN(scenes_tags.actor_id, ${[0, ...filters?.actorIds || []]}), scenes_tags.tag_id, 0) as actor_tags_facet distinct id order by count(distinct id) desc limit ?`, [aggSize])
|
? knex.raw(`facet IF(IN(scenes_tags.actor_id, ${[0, ...filters?.actorIds || []]}), scenes_tags.tag_id, 0) as actor_tags_facet distinct id order by count(*) desc limit ?`, [aggSize])
|
||||||
: null,
|
: null,
|
||||||
*/
|
channelsFacet: options.aggregateChannels ? knex.raw('facet scenes.channel_id as channels_facet distinct id order by count(*) desc limit ?', [aggSize]) : null,
|
||||||
channelsFacet: options.aggregateChannels ? knex.raw('facet scenes.channel_id as channels_facet distinct id order by count(distinct id) desc limit ?', [aggSize]) : null,
|
studiosFacet: options.aggregateChannels ? knex.raw('facet scenes.studio_id as studios_facet distinct id order by count(*) desc limit ?', [aggSize]) : null,
|
||||||
studiosFacet: options.aggregateChannels ? knex.raw('facet scenes.studio_id as studios_facet distinct id order by count(distinct id) desc limit ?', [aggSize]) : null,
|
|
||||||
maxMatches: config.database.manticore.maxMatches,
|
maxMatches: config.database.manticore.maxMatches,
|
||||||
maxQueryTime: config.database.manticore.maxQueryTime,
|
maxQueryTime: config.database.manticore.maxQueryTime,
|
||||||
}).toString();
|
}).toString();
|
||||||
@@ -601,9 +603,7 @@ async function queryManticoreSql(filters, options, _reqUser) {
|
|||||||
|
|
||||||
const results = await utilsApi.sql(curatedSqlQuery);
|
const results = await utilsApi.sql(curatedSqlQuery);
|
||||||
|
|
||||||
// console.log(util.inspect(results, null, Infinity));
|
const years = curateFacet(results, 'years_facet');
|
||||||
|
|
||||||
const years = curateFacet(results, 'years_facet', 'count(*)');
|
|
||||||
const actorIds = curateFacet(results, 'actors_facet');
|
const actorIds = curateFacet(results, 'actors_facet');
|
||||||
const tagIds = curateFacet(results, 'tags_facet');
|
const tagIds = curateFacet(results, 'tags_facet');
|
||||||
const actorTagIds = curateFacet(results, 'actor_tags_facet');
|
const actorTagIds = curateFacet(results, 'actor_tags_facet');
|
||||||
@@ -729,8 +729,14 @@ export async function fetchSceneRevisions(revisionId, filters = {}, reqUser) {
|
|||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset((page - 1) * limit);
|
.offset((page - 1) * limit);
|
||||||
|
|
||||||
const actorIds = Array.from(new Set(revisions.flatMap((revision) => [...revision.base.actors, ...(revision.deltas.find((delta) => delta.key === 'actors')?.value || [])])));
|
const actorIds = Array.from(new Set(revisions.flatMap((revision) => [
|
||||||
const tagIds = Array.from(new Set(revisions.flatMap((revision) => [...revision.base.tags, ...(revision.deltas.find((delta) => delta.key === 'tags')?.value || [])])));
|
...revision.base.actors,
|
||||||
|
...(revision.deltas.find((delta) => delta.key === 'actors')?.value || []),
|
||||||
|
...revision.base.tags.map((tag) => tag.actorId),
|
||||||
|
...revision.deltas.find((delta) => delta.key === 'tags')?.value.map((tag) => tag.actorId) || [],
|
||||||
|
].filter(Boolean))));
|
||||||
|
|
||||||
|
const tagIds = Array.from(new Set(revisions.flatMap((revision) => [...revision.base.tags, ...(revision.deltas.find((delta) => delta.key === 'tags')?.value || [])].map((tag) => tag.id))));
|
||||||
const movieIds = Array.from(new Set(revisions.flatMap((revision) => [...revision.base.movies, ...(revision.deltas.find((delta) => delta.key === 'movies')?.value || [])])));
|
const movieIds = Array.from(new Set(revisions.flatMap((revision) => [...revision.base.movies, ...(revision.deltas.find((delta) => delta.key === 'movies')?.value || [])])));
|
||||||
|
|
||||||
const [actors, tags, movies] = await Promise.all([
|
const [actors, tags, movies] = await Promise.all([
|
||||||
@@ -926,6 +932,10 @@ export async function reviewSceneRevision(revisionId, isApproved, { feedback },
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function createSceneRevision(sceneId, { edits, comment, apply }, reqUser) {
|
export async function createSceneRevision(sceneId, { edits, comment, apply }, reqUser) {
|
||||||
|
if (!reqUser) {
|
||||||
|
throw new HttpError('Must be authenticated to create scene revision', 401);
|
||||||
|
}
|
||||||
|
|
||||||
const [
|
const [
|
||||||
[scene],
|
[scene],
|
||||||
openRevisions,
|
openRevisions,
|
||||||
@@ -967,6 +977,13 @@ export async function createSceneRevision(sceneId, { edits, comment, apply }, re
|
|||||||
return [key, values.id];
|
return [key, values.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === 'tags') {
|
||||||
|
return [key, values.map((tag) => ({
|
||||||
|
id: tag.id,
|
||||||
|
actorId: tag.actorId,
|
||||||
|
}))];
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(values)) {
|
if (Array.isArray(values)) {
|
||||||
return [key, values.map((value) => value?.hash || value?.id || value)];
|
return [key, values.map((value) => value?.hash || value?.id || value)];
|
||||||
}
|
}
|
||||||
@@ -983,6 +1000,16 @@ export async function createSceneRevision(sceneId, { edits, comment, apply }, re
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key === 'tags') {
|
||||||
|
return {
|
||||||
|
key,
|
||||||
|
value: value.map((tag) => ({
|
||||||
|
id: tag.id,
|
||||||
|
actorId: tag.actorId,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
const valueSet = new Set(value);
|
const valueSet = new Set(value);
|
||||||
const baseSet = new Set(baseScene[key]);
|
const baseSet = new Set(baseScene[key]);
|
||||||
|
|||||||
80
src/tools/scene_tag_revision_fix.js
Normal file
80
src/tools/scene_tag_revision_fix.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import { MerkleJson } from 'merkle-json';
|
||||||
|
|
||||||
|
import knex from '../knex.js';
|
||||||
|
|
||||||
|
const mj = new MerkleJson();
|
||||||
|
|
||||||
|
function curateTag(tag) {
|
||||||
|
if (Object.hasOwn(tag, 'actorId')) {
|
||||||
|
return {
|
||||||
|
id: tag.id,
|
||||||
|
actorId: tag.actorId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof tag === 'number') {
|
||||||
|
return {
|
||||||
|
id: tag,
|
||||||
|
// can't restore actorId, don't set to null to hint at missing data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`Unrecognized tag delta: ${JSON.stringify(tag)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function init() {
|
||||||
|
const revisions = await knex('scenes_revisions');
|
||||||
|
|
||||||
|
// console.log(revisions);
|
||||||
|
|
||||||
|
const fixedRevisions = revisions.map((revision) => {
|
||||||
|
if (revision.base.tags.length === 0 && !revision.deltas.some((delta) => delta.key === 'tags')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newDeltas = revision.deltas.map((delta) => {
|
||||||
|
if (delta.key !== 'tags') {
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...delta,
|
||||||
|
value: delta.value.map((tag) => curateTag(tag)),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const newBase = {
|
||||||
|
...revision.base,
|
||||||
|
tags: revision.base.tags.map((tag) => curateTag(tag)),
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...revision,
|
||||||
|
deltas: newDeltas,
|
||||||
|
base: newBase,
|
||||||
|
};
|
||||||
|
}).filter(Boolean);
|
||||||
|
|
||||||
|
const entries = fixedRevisions.map((revision) => ({
|
||||||
|
id: revision.id,
|
||||||
|
base: JSON.stringify(revision.base),
|
||||||
|
deltas: JSON.stringify(revision.deltas),
|
||||||
|
hash: mj.hash({
|
||||||
|
base: revision.base,
|
||||||
|
deltas: revision.deltas,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.log(entries);
|
||||||
|
|
||||||
|
await knex('scenes_revisions')
|
||||||
|
.insert(entries)
|
||||||
|
.onConflict('id')
|
||||||
|
.merge(['base', 'deltas', 'hash']);
|
||||||
|
|
||||||
|
console.log(`Fixed ${entries.length} revisions`);
|
||||||
|
|
||||||
|
await knex.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
@@ -2,14 +2,14 @@ export default function consentHandler(req, res, next) {
|
|||||||
const redirect = req.headers.referer && new URL(req.headers.referer).searchParams.get('redirect');
|
const redirect = req.headers.referer && new URL(req.headers.referer).searchParams.get('redirect');
|
||||||
|
|
||||||
if (Object.hasOwn(req.query, 'lgbt')) {
|
if (Object.hasOwn(req.query, 'lgbt')) {
|
||||||
const lgbtFilters = (req.tagFilter || []).filter((tag) => !['gay', 'bisexual', 'transsexual'].includes(tag));
|
const lgbtFilters = Array.from(new Set([...(req.tagFilter || []).filter((tag) => !['gay', 'bisexual', 'transsexual'].includes(tag)), 'extreme-insertion']));
|
||||||
|
|
||||||
req.tagFilter = lgbtFilters; // eslint-disable-line no-param-reassign
|
req.tagFilter = lgbtFilters; // eslint-disable-line no-param-reassign
|
||||||
res.cookie('tags', JSON.stringify(lgbtFilters));
|
res.cookie('tags', JSON.stringify(lgbtFilters));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Object.hasOwn(req.query, 'straight')) {
|
if (Object.hasOwn(req.query, 'straight')) {
|
||||||
const straightFilters = Array.from(new Set([...(req.tagFilter || []), 'gay', 'bisexual', 'transsexual']));
|
const straightFilters = Array.from(new Set([...(req.tagFilter || []), 'gay', 'bisexual', 'transsexual', 'extreme-insertion']));
|
||||||
|
|
||||||
req.tagFilter = straightFilters; // eslint-disable-line no-param-reassign
|
req.tagFilter = straightFilters; // eslint-disable-line no-param-reassign
|
||||||
res.cookie('tags', JSON.stringify(straightFilters));
|
res.cookie('tags', JSON.stringify(straightFilters));
|
||||||
|
|||||||
2
static
2
static
Submodule static updated: d9fd99c504...d77e9faeb9
Reference in New Issue
Block a user